diff --git a/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownParsing.cs b/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownParsing.cs index 2b654930d..625e4c977 100644 --- a/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownParsing.cs +++ b/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownParsing.cs @@ -75,7 +75,10 @@ public static string GetStringFromForm(byte form, GameStrings strings, ushort sp return string.Empty; var forms = FormConverter.GetFormList(species, strings.Types, strings.forms, genderForms, context); - return form >= forms.Length ? string.Empty : forms[form]; + var result = form >= forms.Length ? string.Empty : forms[form]; + + // Showdown uses a non-standard representation for some forms, and uses interstitial dashes instead of spaces. + return GetShowdownFormName(species, result); } private const string MiniorFormName = "Meteor"; @@ -116,13 +119,22 @@ public static string GetShowdownFormName(ushort species, string form) }; } + public static bool IsTotemForm(ReadOnlySpan formName) => + formName.Equals("Totem", StringComparison.OrdinalIgnoreCase) || + formName.Equals("Alola-Totem", StringComparison.OrdinalIgnoreCase) || + formName.Equals("Large", StringComparison.OrdinalIgnoreCase); + + + public static bool IsCosplayPikachu(ReadOnlySpan formName, ReadOnlySpan formNames) + => FormConverter.IsCosplayPikachu(formName, formNames); + /// /// Converts the Showdown form name to PKHeX's form name. /// /// Species ID /// Showdown form name /// Showdown ability ID - public static string SetShowdownFormName(ushort species, string form, int ability) + public static string GetFormNameFromShowdownFormName(ushort species, string form, int ability) { if (form.Length != 0) form = form.Replace(' ', '-'); // inconsistencies are great diff --git a/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownSet.cs b/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownSet.cs index 2a3de4913..6154fd06d 100644 --- a/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownSet.cs +++ b/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownSet.cs @@ -77,7 +77,8 @@ private void LoadLines(IEnumerable lines, BattleTemplateLocalization loc private void SanitizeResult(BattleTemplateLocalization localization) { - FormName = ShowdownParsing.SetShowdownFormName(Species, FormName, Ability); + ReviseContextIfPastGenForm(localization.Strings); + FormName = ShowdownParsing.GetFormNameFromShowdownFormName(Species, FormName, Ability); Form = ShowdownParsing.GetFormFromString(FormName, localization.Strings, Species, Context); // Handle edge case with fixed-gender forms. @@ -85,6 +86,17 @@ private void SanitizeResult(BattleTemplateLocalization localization) ReviseGenderedForms(); } + private void ReviseContextIfPastGenForm(GameStrings strings) + { + if (FormName.Length == 0) + return; // no form name + + if (FormInfo.HasTotemForm(Species) && ShowdownParsing.IsTotemForm(FormName)) + Context = EntityContext.Gen7; + else if (Species is (int)Pikachu && ShowdownParsing.IsCosplayPikachu(FormName, strings.forms)) + Context = EntityContext.Gen6; + } + private void ReviseGenderedForms() { if (Gender == 1) // Recognized with (F) @@ -115,7 +127,7 @@ private void ParseLines(SpanLineEnumerator lines, BattleTemplateLocalization loc bool first = true; foreach (var line in lines) { - ReadOnlySpan trim = line.Trim(); + var trim = line.Trim(); if (IsLengthOutOfRange(trim)) { // Try for other languages just in case. @@ -502,8 +514,7 @@ private void PushToken(BattleTemplateToken token, List result, in Battle { // Core case BattleTemplateToken.FirstLine: - var form = ShowdownParsing.GetShowdownFormName(Species, FormName); - result.Add(GetStringFirstLine(form, settings)); + result.Add(GetStringFirstLine(FormName, settings)); break; case BattleTemplateToken.Ability when (uint)Ability < strings.Ability.Count: result.Add(cfg.Push(BattleTemplateToken.Ability, strings.Ability[Ability])); diff --git a/PKHeX.Core/Legality/Tables/FormInfo.cs b/PKHeX.Core/Legality/Tables/FormInfo.cs index fe55c7eba..5d5e2bd89 100644 --- a/PKHeX.Core/Legality/Tables/FormInfo.cs +++ b/PKHeX.Core/Legality/Tables/FormInfo.cs @@ -24,6 +24,24 @@ public static bool IsBattleOnlyForm(ushort species, byte form, byte format) return false; } + /// + /// Checks if the form is a Mega form. + /// + /// Entity species + /// Entity form + public static bool IsMegaForm(ushort species, byte form) + { + if (BattleMegas.Contains(species)) + return IsBattleMegaForm(species, form); + return false; + } + + /// + /// Checks if the species has a Mega form. + /// + /// Entity species + public static bool HasMegaForm(ushort species) => BattleMegas.Contains(species); + private static bool IsBattleForm(ushort species, byte form) => species switch { // Only continue checking if the species is in the list of Battle Only forms. diff --git a/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs b/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs index 503f1b724..f7668e093 100644 --- a/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs +++ b/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs @@ -957,7 +957,7 @@ private static void SetAlcremieFormList(IReadOnlyList forms, Span result, [ConstantExpected] byte f, string baseName) + static void SetDecorations(Span result, [ConstantExpected] byte f, ReadOnlySpan baseName) { int start = f * AlcremieCountDecoration; var slice = result.Slice(start, AlcremieCountDecoration); @@ -973,4 +973,20 @@ static void SetDecorations(Span result, [ConstantExpected] byte f, strin (int)Alcremie => Enum.GetNames(), _ => EMPTY, }; + + /// + /// Compatibility check for past-generation form list for . + /// + /// Desired form name + /// List of all form names + /// true if the form name is a cosplay Pikachu form. + public static bool IsCosplayPikachu(ReadOnlySpan formName, ReadOnlySpan formNames) + { + for (int i = 729; i <= 734; i++) + { + if (formName.Equals(formNames[i], StringComparison.OrdinalIgnoreCase)) + return true; + } + return false; + } } diff --git a/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs b/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs index aa8810df3..f3ce18b48 100644 --- a/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs +++ b/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs @@ -12,11 +12,11 @@ public void SimulatorGetParse() { var settings = new BattleTemplateExportSettings(BattleTemplateConfig.CommunityStandard); - foreach (ReadOnlySpan setstr in Sets) + foreach (var setstr in Sets) { var set = new ShowdownSet(setstr).GetSetLines(settings); foreach (var line in set) - setstr.Contains(line, StringComparison.Ordinal).Should().BeTrue($"Line {line} should be in the set {setstr}"); + setstr.Contains(line, StringComparison.Ordinal).Should().BeTrue($"`{line}` should be in the set: {setstr}"); } } @@ -410,7 +410,7 @@ Adamant Nature SetMunchSnorLax, """ - Greninja @ Choice Specs + Greninja-Ash @ Choice Specs Ability: Battle Bond EVs: 252 SpA / 4 SpD / 252 Spe Timid Nature