using System; using System.Collections.Generic; using System.Linq; using static PKHeX.Core.Species; namespace PKHeX.Core { /// /// Logic for parsing details for objects. /// public static class ShowdownParsing { private static readonly string[] genderForms = { "", "F", "" }; /// /// Gets the Form ID from the input . /// /// /// /// Species ID the form belongs to /// Format the form name should appear in /// Zero (base form) if no form matches the input string. public static int GetFormFromString(string name, GameStrings strings, int species, int format) { if (name.Length == 0) return 0; string[] formStrings = FormConverter.GetFormList(species, strings.Types, strings.forms, genderForms, format); return Math.Max(0, Array.FindIndex(formStrings, z => z.Contains(name))); } /// /// Converts a Form ID to string. /// /// /// /// /// /// public static string GetStringFromForm(int form, GameStrings strings, int species, int format) { if (form <= 0) return string.Empty; var forms = FormConverter.GetFormList(species, strings.Types, strings.forms, genderForms, format); return form >= forms.Length ? string.Empty : forms[form]; } private const string MiniorFormName = "Meteor"; /// /// Converts the PKHeX standard form name to Showdown's form name. /// /// Species ID /// PKHeX form name public static string GetShowdownFormName(int species, string form) { if (form.Length == 0) { return species switch { (int)Minior => MiniorFormName, _ => form }; } return species switch { (int)Basculin when form is "Blue" => "Blue-Striped", (int)Vivillon when form is "Poké Ball" => "Pokeball", (int)Zygarde => form.Replace("-C", string.Empty).Replace("50%", string.Empty), (int)Minior when form.StartsWith("M-") => MiniorFormName, (int)Minior => form.Replace("C-", string.Empty), (int)Necrozma when form is "Dusk" => $"{form}-Mane", (int)Necrozma when form is "Dawn" => $"{form}-Wings", (int)Polteageist or (int)Sinistea => form == "Antique" ? form : string.Empty, (int)Furfrou or (int)Greninja or (int)Rockruff => string.Empty, _ => Legal.Totem_USUM.Contains(species) && form == "Large" ? Legal.Totem_Alolan.Contains(species) && species != (int)Mimikyu ? "Alola-Totem" : "Totem" : form.Replace(' ', '-') }; } /// /// Converts the Showdown form name to PKHeX's form name. /// /// Species ID /// Showdown form name /// Showdown ability ID public static string SetShowdownFormName(int species, string form, int ability) { if (form.Length != 0) form = form.Replace(' ', '-'); // inconsistencies are great return species switch { (int)Basculin when form == "Blue-Striped" => "Blue", (int)Vivillon when form == "Pokeball" => "Poké Ball", (int)Necrozma when form == "Dusk-Mane" => "Dusk", (int)Necrozma when form == "Dawn-Wings" => "Dawn", (int)Toxtricity when form == "Low-Key" => "Low Key", (int)Darmanitan when form == "Galar-Zen" => "Galar Zen", (int)Minior when form != MiniorFormName => $"C-{form}", (int)Zygarde when form == "Complete" => form, (int)Zygarde when ability == 211 => $"{(string.IsNullOrWhiteSpace(form) ? "50%" : "10%")}-C", (int)Greninja when ability == 210 => "Ash", // Battle Bond (int)Rockruff when ability == 020 => "Dusk", // Rockruff-1 (int)Urshifu => form.Replace('-', ' '), _ => Legal.Totem_USUM.Contains(species) && form.EndsWith("Totem") ? "Large" : form, }; } /// /// Fetches data from the input . /// /// Raw lines containing numerous multi-line set data. /// objects until is consumed. public static IEnumerable GetShowdownSets(IEnumerable lines) { // exported sets always have >4 moves; new List will always require 1 resizing, allocate 2x to save 1 reallocation. // intro, nature, ability, (ivs, evs, shiny, level) 4*moves var setLines = new List(8); foreach (var line in lines) { if (!string.IsNullOrWhiteSpace(line)) { setLines.Add(line); continue; } if (setLines.Count == 0) continue; yield return new ShowdownSet(setLines); setLines.Clear(); } if (setLines.Count != 0) yield return new ShowdownSet(setLines); } /// /// Converts the data into an importable set format for Pokémon Showdown. /// /// PKM to convert to string /// Multi line set data public static string GetShowdownText(PKM pkm) { if (pkm.Species == 0) return string.Empty; return new ShowdownSet(pkm).Text; } /// /// Fetches ShowdownSet lines from the input data. /// /// Pokémon data to summarize. /// Consumable list of lines. public static IEnumerable GetShowdownSets(IEnumerable data) => data.Where(p => p.Species != 0).Select(GetShowdownText); /// /// Fetches ShowdownSet lines from the input data, and combines it into one string. /// /// Pokémon data to summarize. /// Splitter between each set. /// Single string containing all lines. public static string GetShowdownSets(IEnumerable data, string separator) => string.Join(separator, GetShowdownSets(data)); /// /// Gets a localized string preview of the provided . /// /// Pokémon data /// Language code /// Multi-line string public static string GetLocalizedPreviewText(PKM pk, string language) { var set = new ShowdownSet(pk); if (pk.Format <= 2) // Nature preview from IVs set.Nature = Experience.GetNatureVC(pk.EXP); return set.LocalizedText(language); } } }