From 674b8dca8308fb39877f7b613e182b58eec8d4dd Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sat, 25 Nov 2023 23:31:54 -0800 Subject: [PATCH] fix: Fixes character starting cities. (#1615) ### Summary - Moves starting city info from AccountHandler to CharacterCreation - Simplifies the logic of determining the starting cities - Adds support for Trammel & Felucca for non-young accounts - Fixes fall through starting city for v6+ in UOR era. - All staff are force-sent to GA. Closes #1408 --- .../Tests/Utilities/TryParseTests.cs | 2 - .../UOContent/Accounting/AccountHandler.cs | 29 +-- Projects/UOContent/Misc/CharacterCreation.cs | 182 ++++++++++++------ 3 files changed, 119 insertions(+), 94 deletions(-) diff --git a/Projects/UOContent.Tests/Tests/Utilities/TryParseTests.cs b/Projects/UOContent.Tests/Tests/Utilities/TryParseTests.cs index ab1d7aa9ad..518146d271 100644 --- a/Projects/UOContent.Tests/Tests/Utilities/TryParseTests.cs +++ b/Projects/UOContent.Tests/Tests/Utilities/TryParseTests.cs @@ -1,5 +1,3 @@ -using Server; -using System; using Xunit; namespace Server.Tests.Utility; diff --git a/Projects/UOContent/Accounting/AccountHandler.cs b/Projects/UOContent/Accounting/AccountHandler.cs index e86a9af790..6986fda024 100644 --- a/Projects/UOContent/Accounting/AccountHandler.cs +++ b/Projects/UOContent/Accounting/AccountHandler.cs @@ -20,33 +20,6 @@ public static class AccountHandler private static TimeSpan DeleteDelay = TimeSpan.FromDays(7.0); private static bool PasswordCommandEnabled; - private static CityInfo[] OldHavenStartingCities = - { - new("Yew", "The Empath Abbey", 633, 858, 0), - new("Minoc", "The Barnacle", 2476, 413, 15), - new("Britain", "Sweet Dreams Inn", 1496, 1628, 10), - new("Moonglow", "The Scholars Inn", 4408, 1168, 0), - new("Trinsic", "The Traveler's Inn", 1845, 2745, 0), - new("Magincia", "The Great Horns Tavern", 3734, 2222, 20), - new("Jhelom", "The Mercenary Inn", 1374, 3826, 0), - new("Skara Brae", "The Falconer's Inn", 618, 2234, 0), - new("Vesper", "The Ironwood Inn", 2771, 976, 0), - new("Haven", "Buckler's Hideaway", 3667, 2625, 0) - }; - - private static CityInfo[] StartingCities = - { - new("New Haven", "New Haven Bank", 1150168, 3667, 2625, 0), - new("Yew", "The Empath Abbey", 1075072, 633, 858, 0), - new("Minoc", "The Barnacle", 1075073, 2476, 413, 15), - new("Britain", "The Wayfarer's Inn", 1075074, 1602, 1591, 20), - new("Moonglow", "The Scholars Inn", 1075075, 4408, 1168, 0), - new("Trinsic", "The Traveler's Inn", 1075076, 1845, 2745, 0), - new("Jhelom", "The Mercenary Inn", 1075078, 1374, 3826, 0), - new("Skara Brae", "The Falconer's Inn", 1075079, 618, 2234, 0), - new("Vesper", "The Ironwood Inn", 1075080, 2771, 976, 0) - }; - private static Dictionary m_IPTable; private static char[] m_ForbiddenChars = { '<', '>', ':', '"', '/', '\\', '|', '?', '*' }; @@ -439,7 +412,7 @@ public static void EventSink_GameLogin(GameLoginEventArgs e) logger.Information("Login: {NetState} Account '{Username}' at character list", e.State, un); e.State.Account = acct; e.Accepted = true; - e.CityInfo = TileMatrix.Pre6000ClientSupport ? OldHavenStartingCities : StartingCities; + e.CityInfo = CharacterCreation.GetStartingCities(acct); } if (!e.Accepted) diff --git a/Projects/UOContent/Misc/CharacterCreation.cs b/Projects/UOContent/Misc/CharacterCreation.cs index 1439a5fbcf..93a0ea2154 100644 --- a/Projects/UOContent/Misc/CharacterCreation.cs +++ b/Projects/UOContent/Misc/CharacterCreation.cs @@ -76,8 +76,111 @@ public static class CharacterCreation private static readonly TimeSpan BadStartMessageDelay = TimeSpan.FromSeconds(3.5); - private static readonly CityInfo _newHavenInfo = - new("New Haven", "The Bountiful Harvest Inn", 3503, 2574, 14, Map.Trammel); + public static readonly CityInfo[] NewHavenInn = + { + new("New Haven", "The Bountiful Harvest Inn", 3503, 2574, 14, Map.Trammel) + }; + + // TODO: Verify this location (v5.0.8.3 client) + public static readonly CityInfo[] OldHavenBank = + { + new("Haven", "Haven bank", 3677, 2513, -1, Map.Trammel) + }; + + // Map property is not supported (Pre v6 clients) + public static readonly CityInfo[] OldHavenStartingCities = + { + new("Yew", "The Empath Abbey", 633, 858, 0), + new("Minoc", "The Barnacle", 2476, 413, 15), + new("Britain", "Sweet Dreams Inn", 1496, 1628, 10), + new("Moonglow", "The Scholars Inn", 4408, 1168, 0), + new("Trinsic", "The Traveler's Inn", 1845, 2745, 0), + new("Magincia", "The Great Horns Tavern", 3734, 2222, 20), + new("Jhelom", "The Mercenary Inn", 1374, 3826, 0), + new("Skara Brae", "The Falconer's Inn", 618, 2234, 0), + new("Vesper", "The Ironwood Inn", 2771, 976, 0), + new("Occlo", "Buckler's Hideaway", 3667, 2625, 0) + }; + + // TODO: Move to JSON files + public static readonly CityInfo[] FeluccaStartingCities = + { + new("Yew", "The Empath Abbey", 633, 858, 0, Map.Felucca), + new("Minoc", "The Barnacle", 2476, 413, 15, Map.Felucca), + new("Britain", "Sweet Dreams Inn", 1496, 1628, 10, Map.Felucca), + // TODO: Add New Magincia + new("Moonglow", "The Scholars Inn", 4408, 1168, 0, Map.Felucca), + new("Trinsic", "The Traveler's Inn", 1845, 2745, 0, Map.Felucca), + new("Magincia", "The Great Horns Tavern", 3734, 2222, 20, Map.Felucca), + new("Jhelom", "The Mercenary Inn", 1374, 3826, 0, Map.Felucca), + new("Skara Brae", "The Falconer's Inn", 618, 2234, 0, Map.Felucca), + new("Vesper", "The Ironwood Inn", 2771, 976, 0, Map.Felucca), + }; + + // TODO: Move to JSON files + public static readonly CityInfo[] TrammelStartingCities = + { + new("New Haven", "New Haven Bank", 1150168, 3667, 2625, 0, Map.Trammel), + new("Yew", "The Empath Abbey", 1075072, 633, 858, 0, Map.Trammel), + new("Minoc", "The Barnacle", 1075073, 2476, 413, 15, Map.Trammel), + new("Britain", "The Wayfarer's Inn", 1075074, 1602, 1591, 20, Map.Trammel), + // TODO: Add New Magincia + new("Moonglow", "The Scholars Inn", 1075075, 4408, 1168, 0, Map.Trammel), + new("Trinsic", "The Traveler's Inn", 1075076, 1845, 2745, 0, Map.Trammel), + new("Jhelom", "The Mercenary Inn", 1075078, 1374, 3826, 0, Map.Trammel), + new("Skara Brae", "The Falconer's Inn", 1075079, 618, 2234, 0, Map.Trammel), + new("Vesper", "The Ironwood Inn", 1075080, 2771, 976, 0, Map.Trammel) + }; + + private static CityInfo[] _availableStartingCities; + + public static CityInfo[] GetStartingCities(Account acct) + { + if (acct.Young && ExpansionInfo.CoreExpansion.MapSelectionFlags.Includes(MapSelectionFlags.Trammel)) + { + return TileMatrix.Pre6000ClientSupport ? OldHavenBank : NewHavenInn; + } + + return _availableStartingCities ??= ConstructAvailableStartingCities(); + } + + private static CityInfo[] ConstructAvailableStartingCities() + { + if (!TileMatrix.Pre6000ClientSupport) + { + return OldHavenStartingCities; + } + + var availableMaps = ExpansionInfo.CoreExpansion.MapSelectionFlags; + var trammelAvailable = availableMaps.Includes(MapSelectionFlags.Trammel); + var feluccaAvailable = availableMaps.Includes(MapSelectionFlags.Felucca); + + var length = (trammelAvailable ? TrammelStartingCities.Length : 0) + + (feluccaAvailable ? FeluccaStartingCities.Length : 0); + + if (length == 0) + { + logger.Error("Both Felucca and Trammel are unavailable maps, therefore no starting cities are available."); + return Array.Empty(); + } + + var cities = new CityInfo[length]; + var index = 0; + if (trammelAvailable) + { + Array.Copy(TrammelStartingCities, 0, cities, index, TrammelStartingCities.Length); + index += TrammelStartingCities.Length; + } + + if (feluccaAvailable) + { + Array.Copy(FeluccaStartingCities, 0, cities, index, FeluccaStartingCities.Length); + } + + // TODO: Add Royal City for gargoyles + + return cities; + } public static void Initialize() { @@ -197,7 +300,7 @@ private static void EventSink_CharacterCreated(CharacterCreatedEventArgs args) newChar.BankBox.DropItem(ticket); } - var city = GetStartLocation(args, young); + var city = GetStartLocation(args); newChar.MoveToWorld(city.Location, city.Map); logger.Information( @@ -216,22 +319,21 @@ private static void EventSink_CharacterCreated(CharacterCreatedEventArgs args) public static bool VerifyProfession(int profession) => profession >= 0 && profession < ProfessionInfo.Professions.Length; - private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool isYoung) + private static CityInfo GetStartLocation(CharacterCreatedEventArgs args) { - // We don't get the actual client version until after character creation - var post6000Supported = !TileMatrix.Pre6000ClientSupport; var availableMaps = ExpansionInfo.CoreExpansion.MapSelectionFlags; + var m = args.Mobile; - if (Core.ML && post6000Supported && availableMaps.Includes(MapSelectionFlags.Trammel)) + if (m.AccessLevel > AccessLevel.Player) { - return _newHavenInfo; + var map = availableMaps.Includes(MapSelectionFlags.Felucca) ? Map.Felucca : Map.Trammel; + if (availableMaps.Includes(MapSelectionFlags.Felucca)) + { + return new CityInfo("Green Acres", "Green Acres", 5445, 1153, 0, map); + } } - var useHaven = isYoung; - var flags = args.State?.Flags ?? ClientFlags.None; - var m = args.Mobile; - var profession = ProfessionInfo.Professions[args.Profession]; switch (profession?.Name.ToLowerInvariant()) @@ -243,8 +345,6 @@ private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool is return new CityInfo("Umbra", "Mardoth's Tower", 2114, 1301, -50, Map.Malas); } - useHaven = true; - /* * Unfortunately you are playing on a *NON-Age-Of-Shadows* game * installation and cannot be transported to Malas. @@ -254,16 +354,11 @@ private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool is */ Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1062205)); - break; + return GetStartingCities(true)[0]; } case "paladin": { - if (availableMaps.Includes(MapSelectionFlags.Trammel) && post6000Supported) - { - return _newHavenInfo; - } - - break; + return GetStartingCities(true)[0]; } case "samurai": { @@ -277,8 +372,6 @@ private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool is return new CityInfo("Samurai DE", "Haoti's Grounds", 368, 780, -1, Map.Malas); } - useHaven = true; - /* * Unfortunately you are playing on a *NON-Samurai-Empire* game * installation and cannot be transported to Tokuno. @@ -288,7 +381,7 @@ private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool is */ Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1063487)); - break; + return GetStartingCities(true)[0]; } case "ninja": { @@ -302,8 +395,6 @@ private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool is return new CityInfo("Ninja DE", "Enimo's Residence", 414, 823, -1, Map.Malas); } - useHaven = true; - /* * Unfortunately you are playing on a *NON-Samurai-Empire* game * installation and cannot be transported to Tokuno. @@ -312,47 +403,10 @@ private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool is * Haven on the Trammel facet. */ Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1063487)); - - break; + return GetStartingCities(true)[0]; } } - if (post6000Supported && useHaven && availableMaps.Includes(MapSelectionFlags.Trammel)) - { - // New Haven is supported, so put them there... - // Note: if your server maps don't contain New Haven, this will place - // them in the wilderness of Ocllo - return _newHavenInfo; - } - - if (useHaven) - { - // New Haven is not available, so place them in Ocllo instead, if they're aiming for Haven - CityInfo oclloBank = new CityInfo("Ocllo", "Near the bank", 3677, 2513, -1, Map.Trammel); - if (availableMaps.Includes(MapSelectionFlags.Trammel)) - { - return oclloBank; - } - - if (availableMaps.Includes(MapSelectionFlags.Felucca)) - { - oclloBank.Map = Map.Felucca; - return oclloBank; - } - } - - // They're not trying to get to Haven, so use their city selection - // instead - adjusted according to available maps - if (args.City.Map == Map.Trammel && !availableMaps.Includes(MapSelectionFlags.Trammel)) - { - args.City.Map = Map.Felucca; - } - - if (args.City.Map == Map.Felucca && !availableMaps.Includes(MapSelectionFlags.Felucca)) - { - args.City.Map = Map.Trammel; - } - return args.City; }