Refactoring: Move Source (Legality) (#3560)
Rewrites a good amount of legality APIs pertaining to:
* Legal moves that can be learned
* Evolution chains & cross-generation paths
* Memory validation with forgotten moves
In generation 8, there are 3 separate contexts an entity can exist in: SW/SH, BD/SP, and LA. Not every entity can cross between them, and not every entity from generation 7 can exist in generation 8 (Gogoat, etc). By creating class models representing the restrictions to cross each boundary, we are able to better track and validate data.
The old implementation of validating moves was greedy: it would iterate for all generations and evolutions, and build a full list of every move that can be learned, storing it on the heap. Now, we check one game group at a time to see if the entity can learn a move that hasn't yet been validated. End result is an algorithm that requires 0 allocation, and a smaller/quicker search space.
The old implementation of storing move parses was inefficient; for each move that was parsed, a new object is created and adjusted depending on the parse. Now, move parse results are `struct` and store the move parse contiguously in memory. End result is faster parsing and 0 memory allocation.
* `PersonalTable` objects have been improved with new API methods to check if a species+form can exist in the game.
* `IEncounterTemplate` objects have been improved to indicate the `EntityContext` they originate in (similar to `Generation`).
* Some APIs have been extended to accept `Span<T>` instead of Array/IEnumerable
2022-08-03 23:15:27 +00:00
|
|
|
|
using System;
|
2022-01-03 05:35:59 +00:00
|
|
|
|
using System.Collections.Generic;
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
namespace PKHeX.Core;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Logic related to the name of a <see cref="Species"/>.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static class SpeciesName
|
2019-09-19 02:58:23 +00:00
|
|
|
|
{
|
Refactoring: Move Source (Legality) (#3560)
Rewrites a good amount of legality APIs pertaining to:
* Legal moves that can be learned
* Evolution chains & cross-generation paths
* Memory validation with forgotten moves
In generation 8, there are 3 separate contexts an entity can exist in: SW/SH, BD/SP, and LA. Not every entity can cross between them, and not every entity from generation 7 can exist in generation 8 (Gogoat, etc). By creating class models representing the restrictions to cross each boundary, we are able to better track and validate data.
The old implementation of validating moves was greedy: it would iterate for all generations and evolutions, and build a full list of every move that can be learned, storing it on the heap. Now, we check one game group at a time to see if the entity can learn a move that hasn't yet been validated. End result is an algorithm that requires 0 allocation, and a smaller/quicker search space.
The old implementation of storing move parses was inefficient; for each move that was parsed, a new object is created and adjusted depending on the parse. Now, move parse results are `struct` and store the move parse contiguously in memory. End result is faster parsing and 0 memory allocation.
* `PersonalTable` objects have been improved with new API methods to check if a species+form can exist in the game.
* `IEncounterTemplate` objects have been improved to indicate the `EntityContext` they originate in (similar to `Generation`).
* Some APIs have been extended to accept `Span<T>` instead of Array/IEnumerable
2022-08-03 23:15:27 +00:00
|
|
|
|
private const int LatestGeneration = PKX.Generation;
|
|
|
|
|
|
2019-09-19 02:58:23 +00:00
|
|
|
|
/// <summary>
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// Species name lists indexed by the <see cref="LanguageID"/> value.
|
2019-09-19 02:58:23 +00:00
|
|
|
|
/// </summary>
|
2022-06-18 18:04:24 +00:00
|
|
|
|
public static readonly IReadOnlyList<IReadOnlyList<string>> SpeciesLang = new[]
|
2019-09-19 02:58:23 +00:00
|
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
|
Util.GetSpeciesList("ja"), // 0 (unused, invalid)
|
|
|
|
|
Util.GetSpeciesList("ja"), // 1
|
|
|
|
|
Util.GetSpeciesList("en"), // 2
|
|
|
|
|
Util.GetSpeciesList("fr"), // 3
|
|
|
|
|
Util.GetSpeciesList("it"), // 4
|
|
|
|
|
Util.GetSpeciesList("de"), // 5
|
|
|
|
|
Util.GetSpeciesList("es"), // 6 (reserved for Gen3 KO?, unused)
|
|
|
|
|
Util.GetSpeciesList("es"), // 7
|
|
|
|
|
Util.GetSpeciesList("ko"), // 8
|
|
|
|
|
Util.GetSpeciesList("zh"), // 9 Simplified
|
|
|
|
|
Util.GetSpeciesList("zh2"), // 10 Traditional
|
|
|
|
|
};
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Egg name list indexed by the <see cref="LanguageID"/> value.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>Indexing matches <see cref="SpeciesLang"/>.</remarks>
|
|
|
|
|
private static readonly string[] EggNames =
|
|
|
|
|
{
|
|
|
|
|
"タマゴ",
|
|
|
|
|
"タマゴ",
|
|
|
|
|
"Egg",
|
|
|
|
|
"Œuf",
|
|
|
|
|
"Uovo",
|
|
|
|
|
"Ei",
|
|
|
|
|
"Huevo",
|
|
|
|
|
"Huevo",
|
|
|
|
|
"알",
|
|
|
|
|
"蛋",
|
|
|
|
|
"蛋",
|
|
|
|
|
};
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <see cref="PKM.Nickname"/> to <see cref="Species"/> table for all <see cref="LanguageID"/> values.
|
|
|
|
|
/// </summary>
|
2022-08-27 06:43:36 +00:00
|
|
|
|
public static readonly IReadOnlyList<Dictionary<string, int>> SpeciesDict = Util.GetMultiDictionary(SpeciesLang, 1);
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a Pokémon's default name for the desired language ID.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
|
|
|
|
|
/// <param name="language">Language ID of the Pokémon</param>
|
|
|
|
|
/// <returns>The Species name if within expected range, else an empty string.</returns>
|
|
|
|
|
/// <remarks>Should only be used externally for message displays; for accurate in-game names use <see cref="GetSpeciesNameGeneration"/>.</remarks>
|
2022-08-27 06:43:36 +00:00
|
|
|
|
public static string GetSpeciesName(ushort species, int language)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
|
|
|
|
if ((uint)language >= SpeciesLang.Count)
|
|
|
|
|
return string.Empty;
|
2021-05-11 01:41:01 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
if (species == 0)
|
|
|
|
|
return EggNames[language];
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
var arr = SpeciesLang[language];
|
2023-01-22 04:02:33 +00:00
|
|
|
|
if (species >= arr.Count)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
return string.Empty;
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
return arr[species];
|
|
|
|
|
}
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a Pokémon's default name for the desired language ID and generation.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
|
|
|
|
|
/// <param name="language">Language ID of the Pokémon</param>
|
|
|
|
|
/// <param name="generation">Generation specific formatting option</param>
|
|
|
|
|
/// <returns>Generation specific default species name</returns>
|
2022-08-27 06:43:36 +00:00
|
|
|
|
public static string GetSpeciesNameGeneration(ushort species, int language, int generation) => generation switch
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
Refactoring: Move Source (Legality) (#3560)
Rewrites a good amount of legality APIs pertaining to:
* Legal moves that can be learned
* Evolution chains & cross-generation paths
* Memory validation with forgotten moves
In generation 8, there are 3 separate contexts an entity can exist in: SW/SH, BD/SP, and LA. Not every entity can cross between them, and not every entity from generation 7 can exist in generation 8 (Gogoat, etc). By creating class models representing the restrictions to cross each boundary, we are able to better track and validate data.
The old implementation of validating moves was greedy: it would iterate for all generations and evolutions, and build a full list of every move that can be learned, storing it on the heap. Now, we check one game group at a time to see if the entity can learn a move that hasn't yet been validated. End result is an algorithm that requires 0 allocation, and a smaller/quicker search space.
The old implementation of storing move parses was inefficient; for each move that was parsed, a new object is created and adjusted depending on the parse. Now, move parse results are `struct` and store the move parse contiguously in memory. End result is faster parsing and 0 memory allocation.
* `PersonalTable` objects have been improved with new API methods to check if a species+form can exist in the game.
* `IEncounterTemplate` objects have been improved to indicate the `EntityContext` they originate in (similar to `Generation`).
* Some APIs have been extended to accept `Span<T>` instead of Array/IEnumerable
2022-08-03 23:15:27 +00:00
|
|
|
|
<= 4 => GetSpeciesName1234(species, language, generation),
|
|
|
|
|
7 when language == (int) LanguageID.ChineseS => GetSpeciesName7ZH(species, language),
|
|
|
|
|
_ => GetSpeciesName(species, language),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a Pokémon's egg name for the desired language ID and generation.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="language">Language ID of the Pokémon</param>
|
|
|
|
|
/// <param name="generation">Generation specific formatting option</param>
|
|
|
|
|
public static string GetEggName(int language, int generation = LatestGeneration) => generation switch
|
|
|
|
|
{
|
|
|
|
|
<= 4 => GetEggName1234(0, language, generation),
|
|
|
|
|
_ => (uint)language >= EggNames.Length ? string.Empty : EggNames[language],
|
|
|
|
|
};
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-08-27 06:43:36 +00:00
|
|
|
|
private static string GetSpeciesName1234(ushort species, int language, int generation)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
|
|
|
|
if (species == 0)
|
|
|
|
|
return GetEggName1234(species, language, generation);
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2023-01-22 04:02:33 +00:00
|
|
|
|
var nick = GetSpeciesName(species, language);
|
2022-06-18 18:04:24 +00:00
|
|
|
|
switch (language)
|
|
|
|
|
{
|
|
|
|
|
case (int)LanguageID.Korean:
|
2023-03-22 00:20:13 +00:00
|
|
|
|
if (generation == 2)
|
|
|
|
|
StringConverter2KOR.LocalizeKOR2(species, ref nick);
|
|
|
|
|
return nick; // No further processing
|
2022-06-18 18:04:24 +00:00
|
|
|
|
case (int)LanguageID.Japanese:
|
|
|
|
|
return nick; // No further processing
|
|
|
|
|
}
|
2022-01-03 05:35:59 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
Span<char> result = stackalloc char[nick.Length];
|
2023-01-22 04:02:33 +00:00
|
|
|
|
nick.CopyTo(result);
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
// All names are uppercase.
|
2023-03-22 00:20:13 +00:00
|
|
|
|
foreach (ref var c in result)
|
|
|
|
|
c = char.ToUpperInvariant(c);
|
2022-06-18 18:04:24 +00:00
|
|
|
|
if (language == (int)LanguageID.French)
|
|
|
|
|
StringConverter4Util.StripDiacriticsFR4(result); // strips accents on E and I
|
2022-01-08 04:34:35 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
// Gen1/2 species names do not have spaces.
|
|
|
|
|
if (generation >= 3)
|
2023-01-22 04:02:33 +00:00
|
|
|
|
return new string(result);
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
int indexSpace = result.IndexOf(' ');
|
|
|
|
|
if (indexSpace != -1)
|
2021-05-10 23:09:28 +00:00
|
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
|
// Shift down. Strings have at most 1 occurrence of a space.
|
|
|
|
|
result[(indexSpace+1)..].CopyTo(result[indexSpace..]);
|
|
|
|
|
result = result[..^1];
|
|
|
|
|
}
|
2023-01-22 04:02:33 +00:00
|
|
|
|
return new string(result);
|
2022-06-18 18:04:24 +00:00
|
|
|
|
}
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-08-27 06:43:36 +00:00
|
|
|
|
private static string GetEggName1234(ushort species, int language, int generation)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
|
|
|
|
if (generation == 3)
|
|
|
|
|
return "タマゴ"; // All Gen3 eggs are treated as JPN eggs.
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
// Gen2 & Gen4 don't use Œuf like in future games
|
|
|
|
|
if (language == (int)LanguageID.French)
|
|
|
|
|
return generation == 2 ? "OEUF" : "Oeuf";
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
var nick = GetSpeciesName(species, language);
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
// All Gen4 egg names are Title cased.
|
|
|
|
|
if (generation == 4)
|
|
|
|
|
return nick;
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
// Gen2: All Caps
|
|
|
|
|
return nick.ToUpperInvariant();
|
|
|
|
|
}
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the Generation 7 species name for Chinese games.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// Species Names for Chinese (Simplified) were revised during Generation 8 Crown Tundra DLC (#2).
|
|
|
|
|
/// For a Gen7 species name request, return the old species name (hardcoded... yay).
|
|
|
|
|
/// In an updated Gen8 game, the species nickname will automatically reset to the correct localization (on save/load ?), fixing existing entries.
|
|
|
|
|
/// We don't differentiate patch revisions, just generation; Gen8 will return the latest localization.
|
|
|
|
|
/// Gen8 did revise CHT species names, but only for Barraskewda, Urshifu, and Zarude. These species are new (Gen8); we can just use the latest.
|
|
|
|
|
/// </remarks>
|
2022-08-27 06:43:36 +00:00
|
|
|
|
private static string GetSpeciesName7ZH(ushort species, int language) => species switch
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
|
|
|
|
// Revised in DLC1 - Isle of Armor
|
|
|
|
|
// https://cn.portal-pokemon.com/topics/event/200323190120_post_19.html
|
|
|
|
|
(int)Species.Porygon2 => "多边兽Ⅱ", // Later changed to 多边兽2型
|
|
|
|
|
(int)Species.PorygonZ => "多边兽Z", // Later changed to 多边兽乙型
|
|
|
|
|
(int)Species.Mimikyu => "谜拟Q", // Later changed to 谜拟丘
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
// Revised in DLC2 - Crown Tundra
|
|
|
|
|
// https://cn.portal-pokemon.com/topics/event/201020170000_post_21.html
|
|
|
|
|
(int)Species.Cofagrigus => "死神棺", // Later changed to 迭失棺
|
|
|
|
|
(int)Species.Pangoro => "流氓熊猫", // Later changed to 霸道熊猫
|
|
|
|
|
//(int)Species.Nickit => "偷儿狐", // Later changed to 狡小狐
|
|
|
|
|
//(int)Species.Thievul => "狐大盗", // Later changed to 猾大狐
|
|
|
|
|
//(int)Species.Toxel => "毒电婴", // Later changed to 电音婴
|
|
|
|
|
//(int)Species.Runerigus => "死神板", // Later changed to 迭失板
|
2021-05-10 23:09:28 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
_ => GetSpeciesName(species, language),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks if the input <see cref="nickname"/> is not the species name for all languages.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
|
|
|
|
|
/// <param name="nickname">Current name</param>
|
|
|
|
|
/// <param name="generation">Generation specific formatting option</param>
|
|
|
|
|
/// <returns>True if it does not match any language name, False if not nicknamed</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
|
public static bool IsNicknamedAnyLanguage(ushort species, ReadOnlySpan<char> nickname, int generation = LatestGeneration)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
|
|
|
|
var langs = Language.GetAvailableGameLanguages(generation);
|
|
|
|
|
foreach (var language in langs)
|
2019-09-19 02:58:23 +00:00
|
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
|
if (!IsNicknamed(species, nickname, language, generation))
|
|
|
|
|
return false;
|
2020-08-29 17:40:41 +00:00
|
|
|
|
}
|
2022-06-18 18:04:24 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-08-29 17:40:41 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks if the input <see cref="nickname"/> is not the species name.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
|
|
|
|
|
/// <param name="nickname">Current name</param>
|
|
|
|
|
/// <param name="language">Language ID of the Pokémon</param>
|
|
|
|
|
/// <param name="generation">Generation specific formatting option</param>
|
|
|
|
|
/// <returns>True if it does not match the language name, False if not nicknamed (matches).</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
|
public static bool IsNicknamed(ushort species, ReadOnlySpan<char> nickname, int language, int generation = LatestGeneration)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
2023-01-22 04:02:33 +00:00
|
|
|
|
var expect = GetSpeciesNameGeneration(species, language, generation);
|
|
|
|
|
return !nickname.SequenceEqual(expect);
|
2022-06-18 18:04:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the Species name Language ID for the current name and generation.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
|
|
|
|
|
/// <param name="priorityLanguage">Language ID with a higher priority</param>
|
|
|
|
|
/// <param name="nickname">Current name</param>
|
|
|
|
|
/// <param name="generation">Generation specific formatting option</param>
|
|
|
|
|
/// <returns>Language ID if it does not match any language name, -1 if no matches</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
|
public static int GetSpeciesNameLanguage(ushort species, int priorityLanguage, ReadOnlySpan<char> nickname, int generation = LatestGeneration)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
|
|
|
|
var langs = Language.GetAvailableGameLanguages(generation);
|
|
|
|
|
var priorityIndex = langs.IndexOf((byte)priorityLanguage);
|
|
|
|
|
if (priorityIndex != -1)
|
2020-08-29 17:40:41 +00:00
|
|
|
|
{
|
2023-01-22 04:02:33 +00:00
|
|
|
|
var expect = GetSpeciesNameGeneration(species, priorityLanguage, generation);
|
|
|
|
|
if (nickname.SequenceEqual(expect))
|
2022-06-18 18:04:24 +00:00
|
|
|
|
return priorityLanguage;
|
2019-09-19 02:58:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
return GetSpeciesNameLanguage(species, nickname, generation, langs);
|
|
|
|
|
}
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the Species name Language ID for the current name and generation.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="species">National Dex number of the Pokémon. Should be 0 if an egg.</param>
|
|
|
|
|
/// <param name="nickname">Current name</param>
|
|
|
|
|
/// <param name="generation">Generation specific formatting option</param>
|
|
|
|
|
/// <returns>Language ID if it does not match any language name, -1 if no matches</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
|
public static int GetSpeciesNameLanguage(ushort species, ReadOnlySpan<char> nickname, int generation = LatestGeneration)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
|
|
|
|
var langs = Language.GetAvailableGameLanguages(generation);
|
|
|
|
|
return GetSpeciesNameLanguage(species, nickname, generation, langs);
|
|
|
|
|
}
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2023-01-22 04:02:33 +00:00
|
|
|
|
private static int GetSpeciesNameLanguage(ushort species, ReadOnlySpan<char> nickname, int generation, ReadOnlySpan<byte> langs)
|
2022-06-18 18:04:24 +00:00
|
|
|
|
{
|
|
|
|
|
foreach (var lang in langs)
|
2019-09-19 02:58:23 +00:00
|
|
|
|
{
|
2023-01-22 04:02:33 +00:00
|
|
|
|
var expect = GetSpeciesNameGeneration(species, lang, generation);
|
|
|
|
|
if (nickname.SequenceEqual(expect))
|
2022-06-18 18:04:24 +00:00
|
|
|
|
return lang;
|
2019-09-19 02:58:23 +00:00
|
|
|
|
}
|
2022-06-18 18:04:24 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the Species ID for the specified <see cref="speciesName"/> and <see cref="language"/>.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="speciesName">Species Name</param>
|
|
|
|
|
/// <param name="language">Language the name is from</param>
|
|
|
|
|
/// <returns>Species ID</returns>
|
|
|
|
|
/// <remarks>Only use this for modern era name -> ID fetching.</remarks>
|
|
|
|
|
public static int GetSpeciesID(string speciesName, int language = (int)LanguageID.English)
|
|
|
|
|
{
|
|
|
|
|
if (SpeciesDict[language].TryGetValue(speciesName, out var value))
|
|
|
|
|
return value;
|
2019-09-19 02:58:23 +00:00
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
|
// stupid ’, ignore language if we match these.
|
|
|
|
|
return speciesName switch
|
2019-09-19 02:58:23 +00:00
|
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
|
"Farfetch'd" => (int)Species.Farfetchd,
|
|
|
|
|
"Sirfetch'd" => (int)Species.Sirfetchd,
|
|
|
|
|
_ => -1,
|
|
|
|
|
};
|
2019-09-19 02:58:23 +00:00
|
|
|
|
}
|
2021-04-13 00:04:02 +00:00
|
|
|
|
}
|