using System; using System.Collections.Generic; using System.Linq; namespace PKHeX.Core { /// /// Logic related to the name of a . /// public static class SpeciesName { /// /// Species name lists indexed by the value. /// public static readonly IReadOnlyList> SpeciesLang = new[] { 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 }; /// /// to table for all values. /// public static readonly IReadOnlyList> SpeciesDict = Util.GetMultiDictionary(SpeciesLang); /// /// Gets a Pokémon's default name for the desired language ID. /// /// National Dex number of the Pokémon. Should be 0 if an egg. /// Language ID of the Pokémon /// The Species name if within expected range, else an empty string. /// Should only be used externally for message displays; for accurate in-game names use . public static string GetSpeciesName(int species, int language) { if ((uint)language >= SpeciesLang.Count) return string.Empty; var arr = SpeciesLang[language]; if ((uint)species >= arr.Count) return string.Empty; return arr[species]; } /// /// Gets a Pokémon's default name for the desired language ID and generation. /// /// National Dex number of the Pokémon. Should be 0 if an egg. /// Language ID of the Pokémon /// Generation specific formatting option /// Generation specific default species name public static string GetSpeciesNameGeneration(int species, int language, int generation) { if (generation >= 5) { // 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. if (generation == 7 && language == (int) LanguageID.ChineseS) { switch (species) { // Revised in DLC1 - Isle of Armor // https://cn.portal-pokemon.com/topics/event/200323190120_post_19.html case (int)Species.Porygon2: return "多边兽Ⅱ"; // Later changed to 多边兽2型 case (int)Species.PorygonZ: return "多边兽Z"; // Later changed to 多边兽乙型 case (int)Species.Mimikyu: return "谜拟Q"; // Later changed to 谜拟丘 // Revised in DLC2 - Crown Tundra // https://cn.portal-pokemon.com/topics/event/201020170000_post_21.html case (int)Species.Cofagrigus: return "死神棺"; // Later changed to 迭失棺 case (int)Species.Pangoro: return "流氓熊猫"; // Later changed to 霸道熊猫 case (int)Species.Nickit: return "偷儿狐"; // Later changed to 狡小狐 case (int)Species.Thievul: return "狐大盗"; // Later changed to 猾大狐 case (int)Species.Toxel: return "毒电婴"; // Later changed to 电音婴 case (int)Species.Runerigus: return "死神板"; // Later changed to 迭失板 } } return GetSpeciesName(species, language); } if (species == 0) { if (generation == 3) return "タマゴ"; // All Gen3 eggs are treated as JPN eggs. if (language == (int)LanguageID.French) return "Oeuf"; // Gen2 & Gen4 don't use Œuf like in future games } string nick = GetSpeciesName(species, language); if (generation == 2 && language == (int)LanguageID.Korean) return StringConverter2KOR.LocalizeKOR2(nick); if (generation != 4 || species != 0) // All caps GenIV and previous, except GenIV eggs. { nick = nick.ToUpper(); if (language == (int)LanguageID.French) nick = StringConverter4.StripDiacriticsFR4(nick); // strips accents on E and I } if (generation < 3) nick = nick.Replace(" ", string.Empty); return nick; } /// /// Checks if the input is not the species name for all languages. /// /// National Dex number of the Pokémon. Should be 0 if an egg. /// Current name /// Generation specific formatting option /// True if it does not match any language name, False if not nicknamed public static bool IsNicknamedAnyLanguage(int species, string nickname, int generation = PKX.Generation) { if (species == (int)Species.Farfetchd && string.Equals(nickname, "Farfetch'd", StringComparison.OrdinalIgnoreCase)) // stupid ’ return false; if (species == (int)Species.Sirfetchd && string.Equals(nickname, "Sirfetch'd", StringComparison.OrdinalIgnoreCase)) // stupid ’ return false; var langs = Language.GetAvailableGameLanguages(generation); return langs.All(language => IsNicknamed(species, nickname, language, generation)); } /// /// Checks if the input is not the species name. /// /// National Dex number of the Pokémon. Should be 0 if an egg. /// Current name /// Language ID of the Pokémon /// Generation specific formatting option /// True if it does not match the language name, False if not nicknamed (matches). public static bool IsNicknamed(int species, string nickname, int language, int generation = PKX.Generation) { return GetSpeciesNameGeneration(species, language, generation) != nickname; } /// /// Gets the Species name Language ID for the current name and generation. /// /// National Dex number of the Pokémon. Should be 0 if an egg. /// Language ID with a higher priority /// Current name /// Generation specific formatting option /// Language ID if it does not match any language name, -1 if no matches public static int GetSpeciesNameLanguage(int species, int priorityLanguage, string nickname, int generation = PKX.Generation) { var langs = Language.GetAvailableGameLanguages(generation); if (langs.Contains(priorityLanguage) && GetSpeciesNameGeneration(species, priorityLanguage, generation) == nickname) return priorityLanguage; return GetSpeciesNameLanguage(species, nickname, generation, langs); } /// /// Gets the Species name Language ID for the current name and generation. /// /// National Dex number of the Pokémon. Should be 0 if an egg. /// Current name /// Generation specific formatting option /// Language ID if it does not match any language name, -1 if no matches public static int GetSpeciesNameLanguage(int species, string nickname, int generation = PKX.Generation) { var langs = Language.GetAvailableGameLanguages(generation); return GetSpeciesNameLanguage(species, nickname, generation, langs); } private static int GetSpeciesNameLanguage(int species, string nickname, int generation, IReadOnlyList langs) { foreach (var lang in langs) { if (GetSpeciesNameGeneration(species, lang, generation) == nickname) return lang; } return -1; } /// /// Gets the Species ID for the specified and . /// /// Species Name /// Language the name is from /// Species ID /// Only use this for modern era name -> ID fetching. public static int GetSpeciesID(string speciesName, int language = (int)LanguageID.English) { return SpeciesDict[language].TryGetValue(speciesName, out var val) ? val : -1; } } }