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
This commit is contained in:
Kamron Batman 2023-11-25 23:31:54 -08:00 committed by GitHub
parent a93a363c5f
commit 674b8dca83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 122 additions and 97 deletions

View file

@ -1,5 +1,3 @@
using Server;
using System;
using Xunit;
namespace Server.Tests.Utility;

View file

@ -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<IPAddress, int> m_IPTable;
private static char[] m_ForbiddenChars = { '<', '>', ':', '"', '/', '\\', '|', '?', '*' };
@ -439,7 +412,7 @@ public static class AccountHandler
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)

View file

@ -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<CityInfo>();
}
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 @@ public static class CharacterCreation
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 @@ public static class CharacterCreation
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;
if (Core.ML && post6000Supported && availableMaps.Includes(MapSelectionFlags.Trammel))
{
return _newHavenInfo;
}
var useHaven = isYoung;
var flags = args.State?.Flags ?? ClientFlags.None;
var m = args.Mobile;
if (m.AccessLevel > AccessLevel.Player)
{
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 flags = args.State?.Flags ?? ClientFlags.None;
var profession = ProfessionInfo.Professions[args.Profession];
switch (profession?.Name.ToLowerInvariant())
@ -243,8 +345,6 @@ public static class CharacterCreation
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 @@ public static class CharacterCreation
*/
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 @@ public static class CharacterCreation
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 @@ public static class CharacterCreation
*/
Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1063487));
break;
return GetStartingCities(true)[0];
}
case "ninja":
{
@ -302,8 +395,6 @@ public static class CharacterCreation
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 @@ public static class CharacterCreation
* 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;
}