diff --git a/PKHeX.Core/Legality/Localization/LegalityCheckLocalization.cs b/PKHeX.Core/Legality/Localization/LegalityCheckLocalization.cs index 844d7cb55..03374be9a 100644 --- a/PKHeX.Core/Legality/Localization/LegalityCheckLocalization.cs +++ b/PKHeX.Core/Legality/Localization/LegalityCheckLocalization.cs @@ -295,6 +295,7 @@ public sealed class LegalityCheckLocalization public string MoveEvoFCombination_0 { get; init; } = "Moves combinations is not compatible with {0} evolution."; public string MoveFExpectSingle_0 { get; init; } = "Expected: {0}"; public string MoveKeldeoMismatch { get; init; } = "Keldeo Move/Form mismatch."; + public string MovePPMatchesVirtualConsole { get; init; } = "Move PP exactly matches values from the 3DS Virtual Console transfer bug."; public string MovePPExpectHealed_01 { get; init; } = "Move {0} PP is below the amount expected ({1})."; public string MovePPTooHigh_01 { get; init; } = "Move {0} PP is above the amount allowed ({1})."; public string MovePPUpsTooHigh_01 { get; init; } = "Move {0} PP Ups is above the amount allowed ({1})."; diff --git a/PKHeX.Core/Legality/Localization/LegalityCheckResultCodeExtensions.cs b/PKHeX.Core/Legality/Localization/LegalityCheckResultCodeExtensions.cs index 3858d2ada..b68e867d5 100644 --- a/PKHeX.Core/Legality/Localization/LegalityCheckResultCodeExtensions.cs +++ b/PKHeX.Core/Legality/Localization/LegalityCheckResultCodeExtensions.cs @@ -173,6 +173,7 @@ public static class LegalityCheckResultCodeExtensions MarkValueUnusedBitsPresent => localization.MarkValueUnusedBitsPresent, // Moves + MovePPMatchesVirtualConsole => localization.MovePPMatchesVirtualConsole, MoveEvoFCombination_0 => localization.MoveEvoFCombination_0, MovePPExpectHealed_01 => localization.MovePPExpectHealed_01, MovePPTooHigh_01 => localization.MovePPTooHigh_01, diff --git a/PKHeX.Core/Legality/Structures/LegalityCheckResultCode.cs b/PKHeX.Core/Legality/Structures/LegalityCheckResultCode.cs index de2afd9c0..3518fa6a6 100644 --- a/PKHeX.Core/Legality/Structures/LegalityCheckResultCode.cs +++ b/PKHeX.Core/Legality/Structures/LegalityCheckResultCode.cs @@ -254,6 +254,7 @@ public enum LegalityCheckResultCode : ushort // Moves - General MoveKeldeoMismatch, MovesShouldMatchRelearnMoves, + MovePPMatchesVirtualConsole, // Moves - Shop & Alpha MoveShopAlphaMoveShouldBeOther, diff --git a/PKHeX.Core/Legality/Verifiers/MovePPVerifier.cs b/PKHeX.Core/Legality/Verifiers/MovePPVerifier.cs index faeda41c7..2a3393558 100644 --- a/PKHeX.Core/Legality/Verifiers/MovePPVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MovePPVerifier.cs @@ -67,12 +67,18 @@ private void VerifyEntity(LegalityAnalysis data) } } + // Sometimes the PP count will exceed (such as VC=>Bank); rather than flag it as invalid, add a tag indicating it is an untouched VC transfer. + // Gen7 3DS VC: Bad values are valid only if they never move it from the box. Could be more restrictive with disallowing other attributes, alas. + if (pk is PK7 { VC: true } pk7 && data.IsStoredSlot(StorageSlotType.Box) && IsVirtualConsoleUntouched(pk7, moves, pp)) + { + data.AddLine(GetValid(MovePPMatchesVirtualConsole)); + return; // Don't check further; we've verified all values match. + } + var allowedStates = GetPermittedStatePP(data, pk); for (int i = 0; i < pp.Length; i++) { - // Sometimes the PP count will exceed (such as VC=>Bank); just flag it as invalid so the user knows they need to heal them. - // Technically that case is legal (game bug) only if they never move it from the box, but we want to inform the user. var healed = pk.GetMovePP(moves[i], ups[i]); var value = pp[i]; if (value > healed) @@ -157,6 +163,30 @@ private static MoveHealState HasLeftBoxAfterAcquisition(PKM pk, IEncounterTempla return pk.MetLevel != current ? OnlyHealed : Any; return !enc.IsLevelWithinRange(current) ? OnlyHealed : Any; } + + private static bool IsVirtualConsoleUntouched(PK7 pk, ReadOnlySpan moves, ReadOnlySpan pp) + { + // Sanity check the language is a possible VC-transfer language. + var language = (LanguageID)pk.Language; + if (!VirtualConsolePP.IsSupportedLanguage(language)) + return false; + + // Pre-check to ensure the moves are only available from the game they were transferred from. + // Can't leave the box immediately after transfer (else PP would heal), but we don't prevent the Move Verifier from passing Gen3+ moves. + // Maybe in a future update we can add more strict interlocks. + if (pk.VC1) + { + if (!VirtualConsolePP.IsPossibleVC1(moves)) + return false; // GSC+ moves + } + else // VC2 + { + if (!VirtualConsolePP.IsPossibleVC2(moves)) + return false; // RSE+ moves + } + + return VirtualConsolePP.IsMatch(language, moves, pp); + } } [Flags] diff --git a/PKHeX.Core/Moves/VirtualConsolePP.cs b/PKHeX.Core/Moves/VirtualConsolePP.cs new file mode 100644 index 000000000..c758851e2 --- /dev/null +++ b/PKHeX.Core/Moves/VirtualConsolePP.cs @@ -0,0 +1,98 @@ +using System; +using static PKHeX.Core.LanguageID; + +namespace PKHeX.Core; + +/// +/// Transfers from Gen1/2=>Gen7 don't set PP correctly (ignoring PP Ups and bad range fetch). +/// This class contains the expected PP values for each move in each language, as well as methods to check if a given set of moves and PP values match the expected values. +/// +public static class VirtualConsolePP +{ + // Skip move IDs 0-109, no need to duplicate them since we have the valid table elsewhere. + private const byte MoveFirst = 110; // Withdraw + + private static ReadOnlySpan TableENG => [000, 000, 109, 000, 000, 165, 255, 000, 000, 017, 023, 047, 213, 201, 207, 232, 236, 037, 070, 205, 100, 118, 211, 238, 006, 016, 089, 086, 172, 032, 151, 000, 089, 000, 022, 000, 023, 000, 024, 000, 025, 000, 025, 000, 026, 000, 027, 000, 027, 000, 028, 000, 029, 000, 030, 000, 030, 000, 031, 000, 032, 000, 032, 000, 033, 000, 034, 000, 034, 000, 035, 000, 036, 000, 036, 000, 037, 000, 038, 000, 039, 000, 039, 000, 040, 000, 041, 000, 042, 000, 042, 000, 043, 000, 044, 000, 044, 000, 045, 000, 046, 000, 047, 000, 048, 000, 048, 000, 049, 000, 050, 000, 051, 000, 052, 000, 052, 000, 053, 000, 054, 000, 055, 000, 055, 000, 056, 000, 057, 000, 058, 000, 059, 000, 060, 000, 060, 000, 061, 000, 062, 000]; + private static ReadOnlySpan TableJPN => [000, 000, 123, 000, 000, 164, 255, 000, 000, 022, 030, 059, 224, 028, 037, 065, 069, 142, 180, 065, 015, 039, 147, 178, 206, 219, 032, 087, 082, 003, 045, 000, 105, 000, 023, 000, 024, 000, 024, 000, 025, 000, 026, 000, 027, 000, 028, 000, 029, 000, 030, 000, 031, 000, 031, 000, 032, 000, 033, 000, 034, 000, 035, 000, 036, 000, 037, 000, 038, 000, 039, 000, 039, 000, 040, 000, 041, 000, 042, 000, 043, 000, 044, 000, 045, 000, 046, 000, 046, 000, 047, 000, 048, 000, 049, 000, 050, 000, 051, 000, 052, 000, 053, 000, 054, 000, 055, 000, 055, 000, 056, 000, 057, 000, 058, 000, 059, 000, 060, 000, 061, 000, 062, 000, 063, 000, 064, 000, 065, 000, 066, 000, 067, 000, 068, 000, 069, 000, 070, 000, 062, 000]; + private static ReadOnlySpan TableSPA => [000, 000, 109, 000, 000, 161, 255, 000, 000, 017, 023, 048, 147, 147, 153, 179, 182, 242, 022, 161, 054, 072, 170, 197, 221, 232, 226, 231, 064, 219, 105, 000, 093, 000, 023, 000, 023, 000, 024, 000, 025, 000, 026, 000, 026, 000, 027, 000, 028, 000, 029, 000, 030, 000, 030, 000, 031, 000, 032, 000, 033, 000, 033, 000, 034, 000, 035, 000, 036, 000, 037, 000, 037, 000, 038, 000, 039, 000, 040, 000, 040, 000, 041, 000, 042, 000, 043, 000, 044, 000, 045, 000, 045, 000, 046, 000, 046, 000, 047, 000, 048, 000, 049, 000, 050, 000, 050, 000, 051, 000, 052, 000, 053, 000, 054, 000, 054, 000, 055, 000, 056, 000, 057, 000, 058, 000, 058, 000, 059, 000, 060, 000, 061, 000, 062, 000, 063, 000, 064, 000, 064, 000]; + private static ReadOnlySpan TableFRE => [000, 000, 113, 000, 000, 165, 255, 000, 000, 017, 023, 049, 173, 169, 176, 201, 204, 007, 042, 199, 093, 111, 206, 236, 003, 014, 054, 059, 154, 091, 016, 000, 092, 000, 023, 000, 023, 000, 024, 000, 025, 000, 026, 000, 026, 000, 027, 000, 028, 000, 029, 000, 029, 000, 030, 000, 031, 000, 031, 000, 032, 000, 033, 000, 034, 000, 034, 000, 035, 000, 036, 000, 036, 000, 037, 000, 038, 000, 039, 000, 039, 000, 040, 000, 041, 000, 042, 000, 043, 000, 043, 000, 044, 000, 045, 000, 046, 000, 046, 000, 047, 000, 048, 000, 049, 000, 050, 000, 050, 000, 051, 000, 052, 000, 053, 000, 054, 000, 054, 000, 055, 000, 056, 000, 057, 000, 058, 000, 058, 000, 059, 000, 060, 000, 061, 000, 062, 000, 063, 000, 063, 000]; + private static ReadOnlySpan TableDEU => [000, 000, 110, 000, 000, 166, 255, 000, 000, 017, 023, 049, 191, 177, 184, 208, 212, 022, 057, 207, 099, 118, 222, 251, 017, 028, 065, 065, 114, 036, 251, 000, 093, 000, 023, 000, 023, 000, 024, 000, 025, 000, 026, 000, 026, 000, 027, 000, 028, 000, 028, 000, 029, 000, 030, 000, 031, 000, 032, 000, 032, 000, 033, 000, 034, 000, 035, 000, 035, 000, 036, 000, 037, 000, 038, 000, 038, 000, 039, 000, 040, 000, 041, 000, 041, 000, 042, 000, 043, 000, 044, 000, 045, 000, 045, 000, 046, 000, 047, 000, 048, 000, 049, 000, 049, 000, 050, 000, 051, 000, 052, 000, 053, 000, 053, 000, 054, 000, 055, 000, 056, 000, 057, 000, 057, 000, 058, 000, 059, 000, 060, 000, 061, 000, 062, 000, 063, 000, 063, 000, 064, 000]; + private static ReadOnlySpan TableKOR => [000, 000, 082, 000, 000, 162, 255, 000, 000, 017, 022, 039, 237, 154, 160, 178, 180, 219, 239, 050, 186, 203, 253, 014, 029, 036, 039, 247, 228, 151, 138, 000, 056, 000, 022, 000, 023, 000, 023, 000, 024, 000, 024, 000, 024, 000, 025, 000, 025, 000, 025, 000, 026, 000, 026, 000, 027, 000, 027, 000, 027, 000, 028, 000, 028, 000, 028, 000, 029, 000, 029, 000, 030, 000, 030, 000, 030, 000, 031, 000, 031, 000, 031, 000, 032, 000, 032, 000, 033, 000, 033, 000, 033, 000, 034, 000, 034, 000, 034, 000, 035, 000, 035, 000, 036, 000, 036, 000, 036, 000, 037, 000, 037, 000, 038, 000, 038, 000, 038, 000, 039, 000, 039, 000, 040, 000, 040, 000, 040, 000, 041, 000, 041, 000, 041, 000, 042, 000, 042, 000, 043, 000]; + private static ReadOnlySpan TableITA => [000, 000, 109, 000, 000, 166, 255, 000, 000, 017, 023, 048, 185, 173, 180, 206, 209, 012, 046, 195, 090, 108, 197, 225, 248, 003, 074, 078, 163, 046, 202, 000, 093, 000, 022, 000, 023, 000, 024, 000, 025, 000, 025, 000, 026, 000, 027, 000, 028, 000, 029, 000, 029, 000, 030, 000, 031, 000, 032, 000, 032, 000, 033, 000, 034, 000, 035, 000, 035, 000, 036, 000, 037, 000, 037, 000, 038, 000, 039, 000, 040, 000, 041, 000, 041, 000, 042, 000, 043, 000, 044, 000, 045, 000, 045, 000, 046, 000, 047, 000, 048, 000, 048, 000, 049, 000, 050, 000, 051, 000, 052, 000, 052, 000, 053, 000, 054, 000, 055, 000, 056, 000, 057, 000, 057, 000, 058, 000, 059, 000, 060, 000, 061, 000, 062, 000, 062, 000, 063, 000, 064, 000]; + private static ReadOnlySpan TableZHS => [000, 000, 082, 000, 000, 162, 255, 000, 000, 017, 022, 038, 154, 068, 074, 092, 094, 126, 146, 198, 075, 092, 132, 147, 160, 167, 106, 051, 200, 227, 050, 000, 051, 000, 022, 000, 023, 000, 023, 000, 023, 000, 024, 000, 024, 000, 024, 000, 025, 000, 025, 000, 025, 000, 026, 000, 026, 000, 026, 000, 027, 000, 027, 000, 027, 000, 028, 000, 028, 000, 028, 000, 028, 000, 029, 000, 029, 000, 029, 000, 030, 000, 030, 000, 030, 000, 031, 000, 031, 000, 031, 000, 032, 000, 032, 000, 032, 000, 033, 000, 033, 000, 033, 000, 034, 000, 034, 000, 034, 000, 035, 000, 035, 000, 035, 000, 036, 000, 036, 000, 036, 000, 037, 000, 037, 000, 037, 000, 038, 000, 038, 000, 038, 000, 039, 000, 039, 000, 040, 000, 040, 000]; + private static ReadOnlySpan TableZHT => [000, 000, 082, 000, 000, 163, 255, 000, 000, 017, 022, 039, 151, 065, 072, 089, 091, 124, 143, 195, 073, 089, 130, 145, 158, 165, 107, 052, 199, 227, 060, 000, 051, 000, 022, 000, 023, 000, 023, 000, 023, 000, 024, 000, 024, 000, 024, 000, 025, 000, 025, 000, 025, 000, 026, 000, 026, 000, 026, 000, 027, 000, 027, 000, 027, 000, 028, 000, 028, 000, 028, 000, 028, 000, 029, 000, 029, 000, 029, 000, 030, 000, 030, 000, 030, 000, 031, 000, 031, 000, 031, 000, 032, 000, 032, 000, 032, 000, 033, 000, 033, 000, 033, 000, 034, 000, 034, 000, 034, 000, 035, 000, 035, 000, 035, 000, 036, 000, 036, 000, 036, 000, 037, 000, 037, 000, 037, 000, 038, 000, 038, 000, 038, 000, 039, 000, 039, 000, 040, 000, 040, 000]; + + /// + /// Sanity check the languages possible. + /// + /// Language ID to check. + /// True if the language is supported for VC PP table; false otherwise. + public static bool IsSupportedLanguage(LanguageID language) => language is (>= Japanese and <= ChineseT) and not UNUSED_6; + + public static ReadOnlySpan GetTable(LanguageID language) => language switch + { + English => TableENG, + Japanese => TableJPN, + Spanish => TableSPA, + French => TableFRE, + German => TableDEU, + Korean => TableKOR, + Italian => TableITA, + ChineseS => TableZHS, + ChineseT => TableZHT, + _ => throw new NotSupportedException($"Language {language} is not supported for VC PP table."), + }; + + /// + /// Fetches the expected PP for the given move from the VC PP table. Returns false if the move is not in the VC range. + /// + /// Move ID. + /// Glitched PP table for the Pokémon's language. + /// Output expected PP for the move. + /// if the move is in the VC range and the expected PP was fetched; otherwise. + public static bool IsGlitched(ushort move, ReadOnlySpan arr, out byte pp) + { + var index = move - MoveFirst; + if (index < 0) + { + pp = MoveInfo7.PP[move]; // fetch from the normal table for moves below the glitched range + return true; + } + if ((uint)index < arr.Length) + { + pp = arr[index]; // fetch from the glitched table for moves in the glitched range + return true; + } + pp = 0; // unexpected move, ignore. + return false; + } + + /// + /// Checks if all moves are possible from R/B/Y only. + /// + public static bool IsPossibleVC1(ReadOnlySpan moves) + => !moves.ContainsAnyExceptInRange(0, Legal.MaxMoveID_1); + + /// + /// Checks if all moves are possible from R/B/Y/G/S/C only. + /// + public static bool IsPossibleVC2(ReadOnlySpan moves) + => !moves.ContainsAnyExceptInRange(0, Legal.MaxMoveID_2); + + /// + /// Checks the moves against the table to see if all match their stored PP value. + /// + public static bool IsMatch(LanguageID language, ReadOnlySpan moves, ReadOnlySpan pp) + { + var arr = GetTable(language); + for (int i = 0; i < moves.Length; i++) + { + var move = moves[i]; + if (!IsGlitched(move, arr, out var expected)) + return false; + if (pp[i] != expected) + return false; + } + return true; + } +} diff --git a/PKHeX.Core/PKM/PK1.cs b/PKHeX.Core/PKM/PK1.cs index 199daeaa6..a4b692ae7 100644 --- a/PKHeX.Core/PKM/PK1.cs +++ b/PKHeX.Core/PKM/PK1.cs @@ -247,6 +247,7 @@ public PK7 ConvertToPK7() pk7.Nickname = StringConverter12Transporter.GetString(NicknameTrash, Japanese); } + // Don't replicate the bugged PP application method; heal the PP to correct values. pk7.HealPP(); pk7.RefreshChecksum(); return pk7; diff --git a/PKHeX.Core/PKM/PK2.cs b/PKHeX.Core/PKM/PK2.cs index 19ff7cd89..fe6fea5c5 100644 --- a/PKHeX.Core/PKM/PK2.cs +++ b/PKHeX.Core/PKM/PK2.cs @@ -219,6 +219,7 @@ public PK7 ConvertToPK7() pk7.FixMoves(); } + // Don't replicate the bugged PP application method; heal the PP to correct values. pk7.HealPP(); pk7.RefreshChecksum(); return pk7; diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index ccc984df7..d25062098 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -549,6 +549,26 @@ internal void SetTransferPID(bool isShiny) } } + /// + /// Resets the PP of moves to match Bank's initial values. + /// + public void SetVirtualConsoleTransferPP() + { + var language = (LanguageID)Language; + if (!VirtualConsolePP.IsSupportedLanguage(language)) + return; + + var arr = VirtualConsolePP.GetTable(language); + if (VirtualConsolePP.IsGlitched(Move1, arr, out var pp)) + Move1_PP = pp; + if (VirtualConsolePP.IsGlitched(Move2, arr, out pp)) + Move2_PP = pp; + if (VirtualConsolePP.IsGlitched(Move3, arr, out pp)) + Move3_PP = pp; + if (VirtualConsolePP.IsGlitched(Move4, arr, out pp)) + Move4_PP = pp; + } + public override string GetString(ReadOnlySpan data) => StringConverter7.GetString(data); public override int LoadString(ReadOnlySpan data, Span destBuffer) diff --git a/PKHeX.Core/Resources/localize/legality/legality_de.json b/PKHeX.Core/Resources/localize/legality/legality_de.json index a5234a0e6..de01faca5 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_de.json +++ b/PKHeX.Core/Resources/localize/legality/legality_de.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "Attacken-Kombination ist nicht mit der Entwicklung zu {0} kompatibel.", "MoveFExpectSingle_0": "Erwartet: {0}", "MoveKeldeoMismatch": "Keldeo: Attacke und Form stimmen nicht überein.", + "MovePPMatchesVirtualConsole": "Die AP der Attacken stimmen exakt mit den Werten des 3DS‑Virtual‑Console‑Transferfehlers überein.", "MovePPExpectHealed_01": "Die AP der Attacke {0} liegen unter dem erwarteten Wert ({1}).", "MovePPTooHigh_01": "Die AP der Attacke {0} liegen über dem erlaubten Wert ({1}).", "MovePPUpsTooHigh_01": "Die Anzahl der AP-Plus bei der Attacke {0} liegt über dem erlaubten Limit ({1}).", diff --git a/PKHeX.Core/Resources/localize/legality/legality_en.json b/PKHeX.Core/Resources/localize/legality/legality_en.json index ca935356e..cb95d66c8 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_en.json +++ b/PKHeX.Core/Resources/localize/legality/legality_en.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "Moves combinations is not compatible with {0} evolution.", "MoveFExpectSingle_0": "Expected: {0}", "MoveKeldeoMismatch": "Keldeo Move/Form mismatch.", + "MovePPMatchesVirtualConsole": "Move PP exactly matches values from the 3DS Virtual Console transfer bug.", "MovePPExpectHealed_01": "Move {0} PP is below the amount expected ({1}).", "MovePPTooHigh_01": "Move {0} PP is above the amount allowed ({1}).", "MovePPUpsTooHigh_01": "Move {0} PP Ups is above the amount allowed ({1}).", diff --git a/PKHeX.Core/Resources/localize/legality/legality_es-419.json b/PKHeX.Core/Resources/localize/legality/legality_es-419.json index 552479c5e..6d395fdac 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_es-419.json +++ b/PKHeX.Core/Resources/localize/legality/legality_es-419.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "Combinaciones de Movimientos no son compatibles con Movimientos de la evolución de {0}.", "MoveFExpectSingle_0": "Esperado: {0}", "MoveKeldeoMismatch": "Movimiento/Forma de Keldeo incorrecta.", + "MovePPMatchesVirtualConsole": "Los PP de los movimientos coinciden exactamente con los valores del error de transferencia de la Consola Virtual de 3DS.", "MovePPExpectHealed_01": "Los PP del movimiento {0} son inferiores a la cantidad esperada ({1}).", "MovePPTooHigh_01": "Los PP del movimiento {0} están por encima de los permitidos ({1}).", "MovePPUpsTooHigh_01": "Los Más PP del movimiento {0} superan la cantidad permitida ({1}).", diff --git a/PKHeX.Core/Resources/localize/legality/legality_es.json b/PKHeX.Core/Resources/localize/legality/legality_es.json index 13d4c3596..00d739b56 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_es.json +++ b/PKHeX.Core/Resources/localize/legality/legality_es.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "Combinaciones de Movimientos no son compatibles con Movimientos de la evolución de {0}.", "MoveFExpectSingle_0": "Esperado: {0}", "MoveKeldeoMismatch": "Movimiento/Forma de Keldeo incorrecta.", + "MovePPMatchesVirtualConsole": "Los PP de los movimientos coinciden exactamente con los valores del error de transferencia de la Consola Virtual de 3DS.", "MovePPExpectHealed_01": "Los PP del movimiento {0} son inferiores a la cantidad esperada ({1}).", "MovePPTooHigh_01": "Los PP del movimiento {0} están por encima de los permitidos ({1}).", "MovePPUpsTooHigh_01": "Los Más PP del movimiento {0} superan la cantidad permitida ({1}).", diff --git a/PKHeX.Core/Resources/localize/legality/legality_fr.json b/PKHeX.Core/Resources/localize/legality/legality_fr.json index 06849c8a2..7e721ea8a 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_fr.json +++ b/PKHeX.Core/Resources/localize/legality/legality_fr.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "Le moveset est incompatible avec l'évolution de {0}.", "MoveFExpectSingle_0": "Attendu : {0}", "MoveKeldeoMismatch": "Combinaison forme/capacité invalide chez Keldeo.", + "MovePPMatchesVirtualConsole": "Les PP des capacités correspondent exactement aux valeurs du bug de transfert sur la console virtuelle 3DS.", "MovePPExpectHealed_01": "Les PP de la capacité {0} sont inférieures à la quantité attendue ({1}).", "MovePPTooHigh_01": "Les PP de la capacité {0} sont supérieures à la quantité attendue ({1}).", "MovePPUpsTooHigh_01": "La quantité de PP Plus pour la capacité {0} est supérieure à la quantité attendue ({1}).", diff --git a/PKHeX.Core/Resources/localize/legality/legality_it.json b/PKHeX.Core/Resources/localize/legality/legality_it.json index 8dae98791..fdc9926ac 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_it.json +++ b/PKHeX.Core/Resources/localize/legality/legality_it.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "la combinazione di mosse non è compatibile con l'evoluzione di {0}.", "MoveFExpectSingle_0": "Previsto: {0}", "MoveKeldeoMismatch": "Mossa/Forma di Keldeo non corrispondente.", + "MovePPMatchesVirtualConsole": "I PP delle mosse corrispondono esattamente ai valori del bug di trasferimento della Virtual Console 3DS.", "MovePPExpectHealed_01": "I PP della mossa {0} sono inferiori alla quantità prevista ({1}).", "MovePPTooHigh_01": "I PP della mossa {0} sono oltre il massimo consentito ({1}).", "MovePPUpsTooHigh_01": "I PP Up della mossa {0} sono oltre il massimo consentito ({1}).", diff --git a/PKHeX.Core/Resources/localize/legality/legality_ja.json b/PKHeX.Core/Resources/localize/legality/legality_ja.json index 09dc6fb9f..df91f4af7 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_ja.json +++ b/PKHeX.Core/Resources/localize/legality/legality_ja.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "技の組み合わせは {0} 進化と両立できません。", "MoveFExpectSingle_0": "予想: {0}", "MoveKeldeoMismatch": "ケルディオの技/フォルムが一致しません。", + "MovePPMatchesVirtualConsole": "技のPPが3DSバーチャルコンソール転送バグの値と完全に一致しています。", "MovePPExpectHealed_01": "Move {0} PP is below the amount expected ({1}).", "MovePPTooHigh_01": "技 {0} のPPが上限を超えています ({1})。", "MovePPUpsTooHigh_01": "技 {0} のポイントアップ上限を超えています ({1})。", diff --git a/PKHeX.Core/Resources/localize/legality/legality_ko.json b/PKHeX.Core/Resources/localize/legality/legality_ko.json index c79a69ef6..33d8f17b8 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_ko.json +++ b/PKHeX.Core/Resources/localize/legality/legality_ko.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "기술 조합이 {0} 진화와 호환되지 않습니다.", "MoveFExpectSingle_0": "예상되는: {0}", "MoveKeldeoMismatch": "케르디오의 기술과 폼이 일치하지 않습니다.", + "MovePPMatchesVirtualConsole": "기술의 PP가 3DS 가상 콘솔 전송 버그의 값과 정확히 일치합니다.", "MovePPExpectHealed_01": "기술 {0}의 PP가 예상 수치({1})보다 낮습니다.", "MovePPTooHigh_01": "기술 {0}의 PP가 허용된 값보다 많습니다 ({1}).", "MovePPUpsTooHigh_01": "기술 {0}의 포인트업 횟수가 허용 수치({1})를 초과했습니다.", diff --git a/PKHeX.Core/Resources/localize/legality/legality_zh-hans.json b/PKHeX.Core/Resources/localize/legality/legality_zh-hans.json index 835096817..f90358312 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_zh-hans.json +++ b/PKHeX.Core/Resources/localize/legality/legality_zh-hans.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "招式组合与{0}进化型不兼容。", "MoveFExpectSingle_0": "预期: {0}", "MoveKeldeoMismatch": "凯路迪欧的招式与形态不匹配。", + "MovePPMatchesVirtualConsole": "招式的PP与3DS虚拟主机传输漏洞的数值完全一致。", "MovePPExpectHealed_01": "招式 {0} 的PP恢复量未达预期值 ({1})。", "MovePPTooHigh_01": "招式 {0} PP高于允许值 ({1})。", "MovePPUpsTooHigh_01": "招式 {0} PP上升高于允许值 ({1})。", diff --git a/PKHeX.Core/Resources/localize/legality/legality_zh-hant.json b/PKHeX.Core/Resources/localize/legality/legality_zh-hant.json index d5b0b78ae..559c50ebb 100644 --- a/PKHeX.Core/Resources/localize/legality/legality_zh-hant.json +++ b/PKHeX.Core/Resources/localize/legality/legality_zh-hant.json @@ -228,6 +228,7 @@ "MoveEvoFCombination_0": "招式組合與{0}進化型不相容。", "MoveFExpectSingle_0": "應該是該招式: {0}。", "MoveKeldeoMismatch": "凱路迪歐之現時招式與當前形態不匹配。", + "MovePPMatchesVirtualConsole": "招式的PP與3DS虛擬主機傳輸漏洞的數值完全一致。", "MovePPExpectHealed_01": "招式 {0} 的PP恢復量未達預期值 ({1})。", "MovePPTooHigh_01": "招式 {0} PP 高於允許值。 ({1})", "MovePPUpsTooHigh_01": "招式 {0} PP 高於允許值。 ({1})", diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs index 63979d071..ecad7435d 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs @@ -1424,6 +1424,9 @@ private static bool IsPossibleNotNicknamed(PKM pk, ReadOnlySpan current) private void UpdateNickname(object sender, EventArgs e) { + if (!FieldsLoaded) + return; + if (sender == Label_Species) { switch (ModifierKeys) diff --git a/PKHeX.WinForms/Resources/text/lang_de.txt b/PKHeX.WinForms/Resources/text/lang_de.txt index 455339108..13b5c186e 100644 --- a/PKHeX.WinForms/Resources/text/lang_de.txt +++ b/PKHeX.WinForms/Resources/text/lang_de.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=Hinterlege verschiedene Begegnungs Vo LocalizedDescription.ShowEncounterOpacityBackground=Deckkraft des Hintergrunds des Begegnungs Typen. LocalizedDescription.ShowEncounterOpacityStripe=Deckkraft der Begegnungs Typen Streifen Schicht. LocalizedDescription.ShowEncounterThicknessStripe=Anzahl der Pixel des farbigen Streifens der Begegnungs Typen. +LocalizedDescription.ShowExperienceBar=Beim Anzeigen einer Entität die Erfahrungsleiste anzeigen, um EXP und Level bearbeiten zu können. LocalizedDescription.ShowExperiencePercent=Zeige einen dünnen Streifen, der den Level-Up Fortschritt darstellt. LocalizedDescription.ShowGenderGen1=Zeigt bei Entitäten im Generation-1-Format das Geschlecht an, das sie beim Transfer in spätere Generationen erhalten würden. LocalizedDescription.ShowLegalBallsFirst=Zeige in der Ball Auswahl legale Bälle zuerst und illegale Bälle darunter an. diff --git a/PKHeX.WinForms/Resources/text/lang_en.txt b/PKHeX.WinForms/Resources/text/lang_en.txt index 6cacc152b..3918b1144 100644 --- a/PKHeX.WinForms/Resources/text/lang_en.txt +++ b/PKHeX.WinForms/Resources/text/lang_en.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=Show a background to differentiate th LocalizedDescription.ShowEncounterOpacityBackground=Opacity for the Encounter Type background layer. LocalizedDescription.ShowEncounterOpacityStripe=Opacity for the Encounter Type stripe layer. LocalizedDescription.ShowEncounterThicknessStripe=Amount of pixels thick to show when displaying the encounter type color stripe. +LocalizedDescription.ShowExperienceBar=When showing an entity, show the Experience Bar to allow editing of EXP and Level. LocalizedDescription.ShowExperiencePercent=Show a thin stripe to indicate the percent of level-up progress LocalizedDescription.ShowGenderGen1=When showing a Generation 1 format entity, show the gender it would have if transferred to other generations. LocalizedDescription.ShowLegalBallsFirst=When showing the list of balls to select, show the legal balls before the illegal balls rather than sorting by Ball ID. diff --git a/PKHeX.WinForms/Resources/text/lang_es-419.txt b/PKHeX.WinForms/Resources/text/lang_es-419.txt index e8d860c34..2b7b8ff90 100644 --- a/PKHeX.WinForms/Resources/text/lang_es-419.txt +++ b/PKHeX.WinForms/Resources/text/lang_es-419.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=Mostrar un fondo para diferenciar el LocalizedDescription.ShowEncounterOpacityBackground=Nivel de opacidad de la capa de fondo correspondiente al tipo de encuentro. LocalizedDescription.ShowEncounterOpacityStripe=Nivel de opacidad de la raya correspondiente al tipo de encuentro. LocalizedDescription.ShowEncounterThicknessStripe=Nivel de grosor (en píxeles) al mostrar la raya coloreada del tipo de encuentro. +LocalizedDescription.ShowExperienceBar=Al mostrar una entidad, mostrar la barra de experiencia para permitir editar el EXP y el nivel. LocalizedDescription.ShowExperiencePercent=Mostrar una raya fina para indicar el porcentaje de subida de nivel. LocalizedDescription.ShowGenderGen1=Al mostrar una entidad en el formato de la 1a generación, mostrar el sexo que tendría al ser transferido a otra generación. LocalizedDescription.ShowLegalBallsFirst=Al mostrar la lista de Pokébolas a seleccionar, ordenarlas por Pokébolas legales primero, en vez de ordenarlas por ID. diff --git a/PKHeX.WinForms/Resources/text/lang_es.txt b/PKHeX.WinForms/Resources/text/lang_es.txt index f35de7d13..d8af46419 100644 --- a/PKHeX.WinForms/Resources/text/lang_es.txt +++ b/PKHeX.WinForms/Resources/text/lang_es.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=Mostrar un fondo para diferenciar el LocalizedDescription.ShowEncounterOpacityBackground=Nivel de opacidad de la capa de fondo correspondiente al tipo de encuentro. LocalizedDescription.ShowEncounterOpacityStripe=Nivel de opacidad de la raya correspondiente al tipo de encuentro. LocalizedDescription.ShowEncounterThicknessStripe=Nivel de grosor (en píxeles) al mostrar la raya coloreada del tipo de encuentro. +LocalizedDescription.ShowExperienceBar=Al mostrar una entidad, mostrar la barra de experiencia para permitir editar el EXP y el nivel. LocalizedDescription.ShowExperiencePercent=Mostrar una raya fina para indicar el porcentaje de subida de nivel. LocalizedDescription.ShowGenderGen1=Al mostrar una entidad en el formato de la 1a generación, mostrar el sexo que tendría al ser transferido a otra generación. LocalizedDescription.ShowLegalBallsFirst=Al mostrar la lista de Poké Balls a seleccionar, ordenarlas por Poké Balls legales primero, en vez de ordenarlas por ID. diff --git a/PKHeX.WinForms/Resources/text/lang_fr.txt b/PKHeX.WinForms/Resources/text/lang_fr.txt index 81c0c2a0f..46aac9023 100644 --- a/PKHeX.WinForms/Resources/text/lang_fr.txt +++ b/PKHeX.WinForms/Resources/text/lang_fr.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=Afficher un arrière-plan pour diffé LocalizedDescription.ShowEncounterOpacityBackground=Opacité pour la couche d'arrière-plan du modèle de rencontre. LocalizedDescription.ShowEncounterOpacityStripe=Opacité pour la couche de rayure du modèle de rencontre. LocalizedDescription.ShowEncounterThicknessStripe=Épaisseur de pixels à montrer lors de l'affichage de la couleur de la rayure du modèle de rencontre. +LocalizedDescription.ShowExperienceBar=Lors de l’affichage d’une entité, afficher la barre d’expérience pour permettre l’édition de l’EXP et du niveau. LocalizedDescription.ShowExperiencePercent=Afficher une fine rayure pour indiquer le pourcentage de progression de niveau LocalizedDescription.ShowGenderGen1=Lorsqu'une entité au format génération 1 est montrée, afficher le sexe que l'entité aurait si elle devait être transférée vers d'autres générations. LocalizedDescription.ShowLegalBallsFirst=Lors de l'affichage de la liste des balls à choisir, montrer les balls légales avant celles illégales au lieu de simplement les trier par ID. diff --git a/PKHeX.WinForms/Resources/text/lang_it.txt b/PKHeX.WinForms/Resources/text/lang_it.txt index 89f29bd3e..d61dbddf8 100644 --- a/PKHeX.WinForms/Resources/text/lang_it.txt +++ b/PKHeX.WinForms/Resources/text/lang_it.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=Mostra uno sfondo per differenziare i LocalizedDescription.ShowEncounterOpacityBackground=Opacità per lo sfondo del Tipo di Incontro. LocalizedDescription.ShowEncounterOpacityStripe=Opacità per la barra del Tipo di Incontro. LocalizedDescription.ShowEncounterThicknessStripe=Spessore dei Pixel da mostrare per la barra del Tipo di Incontro. +LocalizedDescription.ShowExperienceBar=Quando si mostra un’entità, mostra la barra dell’esperienza per consentire la modifica di EXP e livello. LocalizedDescription.ShowExperiencePercent=Mostra una piccola barra per indicare la percentuale di progresso di Aumento Livello LocalizedDescription.ShowGenderGen1=Quando viene mostrata un'entità in formato Gen 1, mostra il sesso che avrebbe se venisse trasferita nelle altre generazioni. LocalizedDescription.ShowLegalBallsFirst= Quando viene mostrata la lista di Ball, mostra le Ball legali prima di quelle illegali, anziché andare per ordine di ID. diff --git a/PKHeX.WinForms/Resources/text/lang_ja.txt b/PKHeX.WinForms/Resources/text/lang_ja.txt index 05efa6a49..4388f95ea 100644 --- a/PKHeX.WinForms/Resources/text/lang_ja.txt +++ b/PKHeX.WinForms/Resources/text/lang_ja.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=PKMスロットで認識された出 LocalizedDescription.ShowEncounterOpacityBackground=出会いタイプ背景レイヤーの不透明度。 LocalizedDescription.ShowEncounterOpacityStripe=出会いタイプのストライプレイヤーの不透明度。 LocalizedDescription.ShowEncounterThicknessStripe=エンカウントタイプのカラーストライプを表示する時のピクセルの太さ。 +LocalizedDescription.ShowExperienceBar=個体を表示する際、EXPとレベルを編集できるように経験値バーを表示します。 LocalizedDescription.ShowExperiencePercent=次のレベルに必要な経験値のストライプを表示します。 LocalizedDescription.ShowGenderGen1=1世代のゲームを編集時、2世代の条件でポケモンの性別を表示するかどうか。 LocalizedDescription.ShowLegalBallsFirst=ボールを選択する時のリストはID順ではなく、正規が先で後から不正の順番にする。 diff --git a/PKHeX.WinForms/Resources/text/lang_ko.txt b/PKHeX.WinForms/Resources/text/lang_ko.txt index ee6c6348e..9e8d25566 100644 --- a/PKHeX.WinForms/Resources/text/lang_ko.txt +++ b/PKHeX.WinForms/Resources/text/lang_ko.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=포켓몬 슬롯에 인식된 인카 LocalizedDescription.ShowEncounterOpacityBackground=인카운터 유형 배경 레이어의 불투명도입니다. LocalizedDescription.ShowEncounterOpacityStripe=인카운터 유형 스트라이프 레이어의 불투명도입니다. LocalizedDescription.ShowEncounterThicknessStripe=인카운터 유형 색상 스트라이프를 표시할 때의 두께입니다. +LocalizedDescription.ShowExperienceBar=개체를 표시할 때 EXP와 레벨을 편집할 수 있도록 경험치 바를 표시합니다. LocalizedDescription.ShowExperiencePercent=레벨업 진행률을 나타내는 얇은 스트라이프를 표시합니다. LocalizedDescription.ShowGenderGen1=1세대 형식의 개체를 표시할 때, 다른 세대로 옮겼을 경우 갖게 될 성별을 표시합니다. LocalizedDescription.ShowLegalBallsFirst=선택 가능한 볼 목록을 표시할 때, 볼 ID 순서로 정렬하는 대신 합법적인 볼을 불법적인 볼보다 먼저 표시합니다. diff --git a/PKHeX.WinForms/Resources/text/lang_zh-Hans.txt b/PKHeX.WinForms/Resources/text/lang_zh-Hans.txt index b37ba715f..9d00aec0c 100644 --- a/PKHeX.WinForms/Resources/text/lang_zh-Hans.txt +++ b/PKHeX.WinForms/Resources/text/lang_zh-Hans.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=显示背景以区分PKM槽位的已 LocalizedDescription.ShowEncounterOpacityBackground=相遇方式指示背景层的透明度。 LocalizedDescription.ShowEncounterOpacityStripe=相遇方式指示条的透明度。 LocalizedDescription.ShowEncounterThicknessStripe=相遇方式指示条的画素高度。 +LocalizedDescription.ShowExperienceBar=显示个体时,显示经验条以便编辑EXP和等级。 LocalizedDescription.ShowExperiencePercent=显示一条细条纹来表示升级进度的百分比。 LocalizedDescription.ShowGenderGen1=当显示第1代格式的数据时,显示其在转移到其他代时会有的性别。 LocalizedDescription.ShowLegalBallsFirst=当显示要选择的球列表时,在非法球之前显示合法球,而不是按球ID排序。 diff --git a/PKHeX.WinForms/Resources/text/lang_zh-Hant.txt b/PKHeX.WinForms/Resources/text/lang_zh-Hant.txt index 3396d70a3..bdad47d62 100644 --- a/PKHeX.WinForms/Resources/text/lang_zh-Hant.txt +++ b/PKHeX.WinForms/Resources/text/lang_zh-Hant.txt @@ -380,6 +380,7 @@ LocalizedDescription.ShowEncounterColorPKM=顯示背景以區分 PKM 槽位的 LocalizedDescription.ShowEncounterOpacityBackground=遇見方式指示背景層之透明度。 LocalizedDescription.ShowEncounterOpacityStripe=遇見方式指示條之透明度。 LocalizedDescription.ShowEncounterThicknessStripe=遇見方式指示條之畫素高度。 +LocalizedDescription.ShowExperienceBar=顯示個體時,顯示經驗值條以便編輯EXP和等級。 LocalizedDescription.ShowExperiencePercent=顯示一條細條紋來表示升級進度的百分比。 LocalizedDescription.ShowGenderGen1=當顯示第1代格式的資料時,顯示其在轉移到其他世代時會有的性別。 LocalizedDescription.ShowLegalBallsFirst=當顯示要選擇的球列表時,在非法球之前顯示合法球,而不是按球ID排序。 diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9a.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9a.Designer.cs index 79a796c46..2a1648750 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9a.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9a.Designer.cs @@ -91,9 +91,9 @@ private void InitializeComponent() TC_Editor = new System.Windows.Forms.TabControl(); Tab_Overview = new System.Windows.Forms.TabPage(); tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - trainerID1 = new PKHeX.WinForms.Controls.TrainerID(); CAL_LastSavedTime = new System.Windows.Forms.DateTimePicker(); CAL_LastSavedDate = new System.Windows.Forms.DateTimePicker(); + trainerID1 = new PKHeX.WinForms.Controls.TrainerID(); L_LastSaved = new System.Windows.Forms.Label(); flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); CB_Gender = new PKHeX.WinForms.Controls.GenderToggle(); @@ -700,16 +700,6 @@ private void InitializeComponent() tableLayoutPanel1.Size = new System.Drawing.Size(593, 297); tableLayoutPanel1.TabIndex = 75; // - // trainerID1 - // - tableLayoutPanel1.SetColumnSpan(trainerID1, 2); - trainerID1.Dock = System.Windows.Forms.DockStyle.Fill; - trainerID1.Location = new System.Drawing.Point(88, 30); - trainerID1.Margin = new System.Windows.Forms.Padding(88, 0, 0, 0); - trainerID1.Name = "trainerID1"; - trainerID1.Size = new System.Drawing.Size(593, 25); - trainerID1.TabIndex = 74; - // // CAL_LastSavedTime // CAL_LastSavedTime.Anchor = System.Windows.Forms.AnchorStyles.Left; @@ -735,6 +725,16 @@ private void InitializeComponent() CAL_LastSavedDate.TabIndex = 55; CAL_LastSavedDate.Value = new System.DateTime(2000, 1, 1, 0, 0, 0, 0); // + // trainerID1 + // + tableLayoutPanel1.SetColumnSpan(trainerID1, 2); + trainerID1.Dock = System.Windows.Forms.DockStyle.Fill; + trainerID1.Location = new System.Drawing.Point(88, 30); + trainerID1.Margin = new System.Windows.Forms.Padding(88, 0, 0, 0); + trainerID1.Name = "trainerID1"; + trainerID1.Size = new System.Drawing.Size(593, 25); + trainerID1.TabIndex = 74; + // // L_LastSaved // L_LastSaved.Anchor = System.Windows.Forms.AnchorStyles.Right; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9a.resx b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9a.resx new file mode 100644 index 000000000..d683b26fb --- /dev/null +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9a.resx @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAACHSURBVDhPzZQhDsAgDEV3bBAcB8Up0ByD4ECB74KAtSxZ + ISD2k6fof6kp14UihIAVcLdnHJrliERK+cjGxxWaqPIPEWZLdGyjT5ExBkIIkFKCUgohxgjee9Ba86KZ + 5Jx5kXNu7L1ireVFjTqklCLg4rRolS3RsY2IaPfeumT3ByCSlnGIA3dvHLf7kzM4Ke4AAAAASUVORK5C + YII= + + + \ No newline at end of file diff --git a/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/144 ★ - Articuno - A4103D3BFB2D badPP.pk7 b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/144 ★ - Articuno - A4103D3BFB2D badPP.pk7 new file mode 100644 index 000000000..51da84f05 Binary files /dev/null and b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/144 ★ - Articuno - A4103D3BFB2D badPP.pk7 differ diff --git a/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/145 ★ - Zapdos - 018B4D16087D badPP.pk7 b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/145 ★ - Zapdos - 018B4D16087D badPP.pk7 new file mode 100644 index 000000000..158c92285 Binary files /dev/null and b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/145 ★ - Zapdos - 018B4D16087D badPP.pk7 differ diff --git a/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/251 ★ - Celebi - 6695A818ECEA badPP.pk7 b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/251 ★ - Celebi - 6695A818ECEA badPP.pk7 new file mode 100644 index 000000000..cf6f8613c Binary files /dev/null and b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/251 ★ - Celebi - 6695A818ECEA badPP.pk7 differ