fix: Fixes invalid professions. (#1882)
This commit is contained in:
parent
e41d35d3d7
commit
0a07109cc1
4 changed files with 133 additions and 131 deletions
|
|
@ -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)];
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -3178,7 +3178,7 @@ namespace Server.Mobiles
|
|||
}
|
||||
}
|
||||
|
||||
if (!CharacterCreation.VerifyProfession(Profession))
|
||||
if (!ProfessionInfo.VerifyProfession(Profession))
|
||||
{
|
||||
Profession = 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue