fix: Fixes invalid professions. (#1882)

This commit is contained in:
Kamron Batman 2024-07-22 20:15:24 -07:00 committed by GitHub
parent e41d35d3d7
commit 0a07109cc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 133 additions and 131 deletions

View file

@ -745,6 +745,12 @@ public static class Utility
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T RandomList<T>(params T[] list) => list.RandomElement();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T RandomElement<T>(this ReadOnlySpan<T> list) => list.Length == 0 ? (T)default : list[Random(list.Length)];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T RandomElement<T>(this T[] list) => list.RandomElement(default);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T RandomElement<T>(this IList<T> list) => list.RandomElement(default);
@ -858,6 +864,10 @@ public static class Utility
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T RandomElement<T>(this T[] list, T valueIfZero) =>
list.Length == 0 ? valueIfZero : list[Random(list.Length)];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T RandomElement<T>(this IList<T> list, T valueIfZero) =>
list.Count == 0 ? valueIfZero : list[Random(list.Count)];

View file

@ -199,7 +199,7 @@ public static class CharacterCreation
private static void EventSink_CharacterCreated(CharacterCreatedEventArgs args)
{
if (!VerifyProfession(args.Profession))
if (!ProfessionInfo.GetProfession(args.Profession, out var profession))
{
args.Profession = 0;
}
@ -237,8 +237,6 @@ public static class CharacterCreation
if (newChar is PlayerMobile pm)
{
pm.Profession = args.Profession;
if (((Account)pm.Account).Young)
{
pm.Young = true;
@ -250,8 +248,9 @@ public static class CharacterCreation
}
}
SetStats(newChar, state, args.Stats, args.Profession);
SetSkills(newChar, args.Skills, args.Profession, args.ShirtHue, args.PantsHue);
SetStats(newChar, state, profession?.Stats ?? args.Stats);
SetSkills(newChar, profession?.Skills ?? args.Skills);
GiveProfessionItems(newChar, profession, args.ShirtHue, args.PantsHue);
if (race.ValidateHair(newChar, args.HairID))
{
@ -302,9 +301,6 @@ public static class CharacterCreation
new WelcomeTimer(newChar).Start();
}
public static bool VerifyProfession(int profession) =>
profession >= 0 && profession < ProfessionInfo.Professions.Length;
private static CityInfo GetStartLocation(CharacterCreatedEventArgs args)
{
var availableMaps = ExpansionInfo.CoreExpansion.MapSelectionFlags;
@ -325,81 +321,82 @@ public static class CharacterCreation
}
var flags = args.State?.Flags ?? ClientFlags.None;
var profession = ProfessionInfo.Professions[args.Profession];
switch (profession?.Name.ToLowerInvariant())
if (ProfessionInfo.GetProfession(args.Profession, out var profession))
{
case "necromancer":
{
if ((flags & ClientFlags.Malas) != 0 && availableMaps.Includes(MapSelectionFlags.Malas))
switch (profession.Name.ToLowerInvariant())
{
case "necromancer":
{
return new CityInfo("Umbra", "Mardoth's Tower", 2114, 1301, -50, Map.Malas);
if ((flags & ClientFlags.Malas) != 0 && availableMaps.Includes(MapSelectionFlags.Malas))
{
return new CityInfo("Umbra", "Mardoth's Tower", 2114, 1301, -50, Map.Malas);
}
/*
* 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.
*/
Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1062205));
return GetStartingCities()[0];
}
/*
* 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.
*/
Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1062205));
return GetStartingCities()[0];
}
case "paladin":
{
return GetStartingCities()[0];
}
case "samurai":
{
bool haotisAndTokunoAccessible =
(flags & ClientFlags.Tokuno) == ClientFlags.Tokuno &&
(flags & ClientFlags.Malas) == ClientFlags.Malas &&
availableMaps.Includes(MapSelectionFlags.Malas | MapSelectionFlags.Tokuno);
if (haotisAndTokunoAccessible)
case "paladin":
{
return new CityInfo("Samurai DE", "Haoti's Grounds", 368, 780, -1, Map.Malas);
return GetStartingCities()[0];
}
/*
* 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.
*/
Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1063487));
return GetStartingCities()[0];
}
case "ninja":
{
bool enimosAndTokunoAccessible =
(flags & ClientFlags.Tokuno) == ClientFlags.Tokuno &&
(flags & ClientFlags.Malas) == ClientFlags.Malas &&
availableMaps.Includes(MapSelectionFlags.Malas | MapSelectionFlags.Tokuno);
if (enimosAndTokunoAccessible)
case "samurai":
{
return new CityInfo("Ninja DE", "Enimo's Residence", 414, 823, -1, Map.Malas);
}
bool haotisAndTokunoAccessible =
(flags & ClientFlags.Tokuno) == ClientFlags.Tokuno &&
(flags & ClientFlags.Malas) == ClientFlags.Malas &&
availableMaps.Includes(MapSelectionFlags.Malas | MapSelectionFlags.Tokuno);
/*
* 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.
*/
Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1063487));
return GetStartingCities()[0];
}
if (haotisAndTokunoAccessible)
{
return new CityInfo("Samurai DE", "Haoti's Grounds", 368, 780, -1, Map.Malas);
}
/*
* 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.
*/
Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1063487));
return GetStartingCities()[0];
}
case "ninja":
{
bool enimosAndTokunoAccessible =
(flags & ClientFlags.Tokuno) == ClientFlags.Tokuno &&
(flags & ClientFlags.Malas) == ClientFlags.Malas &&
availableMaps.Includes(MapSelectionFlags.Malas | MapSelectionFlags.Tokuno);
if (enimosAndTokunoAccessible)
{
return new CityInfo("Ninja DE", "Enimo's Residence", 414, 823, -1, Map.Malas);
}
/*
* 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.
*/
Timer.StartTimer(BadStartMessageDelay, () => m.SendLocalizedMessage(1063487));
return GetStartingCities()[0];
}
}
}
return args.City;
}
private static void SetStats(Mobile m, NetState state, StatNameValue[] stats, int prof)
private static void SetStats(Mobile m, NetState state, StatNameValue[] stats)
{
var maxStats = state.NewCharacterCreation ? 90 : 80;
@ -407,11 +404,6 @@ public static class CharacterCreation
var dex = 0;
var intel = 0;
if (prof > 0)
{
stats = ProfessionInfo.Professions[prof]?.Stats ?? stats;
}
for (var i = 0; i < stats.Length; i++)
{
var (statType, value) = stats[i];
@ -480,20 +472,33 @@ public static class CharacterCreation
return total is 100 or 120;
}
private static void SetSkills(Mobile m, SkillNameValue[] skills, int prof, int shirtHue, int pantsHue)
private static void SetSkills(Mobile m, SkillNameValue[] skills)
{
ProfessionInfo profession = null;
if (prof > 0)
{
profession = ProfessionInfo.Professions[prof];
skills = ProfessionInfo.Professions[prof]?.Skills ?? skills;
}
else if (!ValidateSkills(m.Race.RaceFlag, skills)) // This does not check for skills that are not allowed by expansion
if (!ValidateSkills(m.Race.RaceFlag, skills))
{
return;
}
var addSkillItems = true;
for (var i = 0; i < skills.Length; ++i)
{
var (name, value) = skills[i];
if (value <= 0)
{
continue;
}
var skill = m.Skills[name];
if (skill != null)
{
skill.BaseFixedPoint = value * 10;
m.AddSkillItems(name);
}
}
}
private static void GiveProfessionItems(Mobile m, ProfessionInfo profession, int shirtHue, int pantsHue)
{
var elf = m.Race == Race.Elf;
var gargoyle = m.Race == Race.Gargoyle;
@ -547,10 +552,7 @@ public static class CharacterCreation
// animate dead, evil omen, pain spike, summon familiar, wraith form
m.PackItem(new NecromancerSpellbook(0x8981ul) { LootType = LootType.Blessed });
addSkillItems = false;
break;
return;
}
case "paladin":
{
@ -588,15 +590,10 @@ public static class CharacterCreation
}
m.PackItem(new BookOfChivalry { LootType = LootType.Blessed });
addSkillItems = false;
break;
return;
}
case "samurai":
{
addSkillItems = false;
if (elf)
{
EquipItem(m, new RavenHelm());
@ -628,13 +625,11 @@ public static class CharacterCreation
m.PackItem(new Bandage(50));
m.PackItem(new BookOfBushido());
break;
return;
}
case "ninja":
{
addSkillItems = false;
int[] hues = [0x1A8, 0xEC, 0x99, 0x90, 0xB5, 0x336, 0x89];
ReadOnlySpan<int> hues = [0x1A8, 0xEC, 0x99, 0x90, 0xB5, 0x336, 0x89];
// TODO: Verify that's ALL the hues for that above.
if (elf)
@ -668,7 +663,8 @@ public static class CharacterCreation
m.PackItem(new SmokeBomb());
m.PackItem(new SmokeBomb());
m.PackItem(new BookOfNinjitsu());
break;
return;
}
case "swordsman":
case "fencer":
@ -706,34 +702,14 @@ public static class CharacterCreation
}
}
if (addSkillItems)
m.AddShirt(shirtHue);
m.AddPants(pantsHue);
m.AddShoes();
// All elves get a wild staff
if (elf)
{
m.AddShirt(shirtHue);
m.AddPants(pantsHue);
m.AddShoes();
// All elves get a wild staff
if (elf)
{
EquipItem(m, new WildStaff());
}
}
for (var i = 0; i < skills.Length; ++i)
{
var (name, value) = skills[i];
if (value <= 0)
{
continue;
}
var skill = m.Skills[name];
if (skill != null)
{
skill.BaseFixedPoint = value * 10;
m.AddSkillItems(name);
}
EquipItem(m, new WildStaff());
}
}

View file

@ -1,12 +1,28 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
namespace Server;
public class ProfessionInfo
{
public static ProfessionInfo[] Professions { get; }
private static readonly ProfessionInfo[] _professions;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool VerifyProfession(int profIndex) =>
profIndex >= 0 && profIndex < _professions.Length;
public static bool GetProfession(int profIndex, out ProfessionInfo profession)
{
if (!VerifyProfession(profIndex))
{
profession = null;
return false;
}
return (profession = _professions[profIndex - 1]) != null;
}
private static bool TryGetSkillName(string name, out SkillName skillName)
{
@ -177,11 +193,11 @@ public class ProfessionInfo
}
}
Professions = new ProfessionInfo[1 + maxProf];
_professions = new ProfessionInfo[maxProf];
foreach (var p in profs)
{
Professions[p.ID] = p;
_professions[p.ID - 1] = p;
}
profs.Clear();

View file

@ -3178,7 +3178,7 @@ namespace Server.Mobiles
}
}
if (!CharacterCreation.VerifyProfession(Profession))
if (!ProfessionInfo.VerifyProfession(Profession))
{
Profession = 0;
}