diff --git a/PKHeX/Legality/RNG/MethodFinder.cs b/PKHeX/Legality/RNG/MethodFinder.cs index b2812da13..8ed37005f 100644 --- a/PKHeX/Legality/RNG/MethodFinder.cs +++ b/PKHeX/Legality/RNG/MethodFinder.cs @@ -32,6 +32,8 @@ public static PIDIV Analyze(PKM pk) PIDIV pidiv; if (getLCRNGMatch(top, bot, IVs, out pidiv)) return pidiv; + if (pk.Species == 201 && getLCRNGUnownMatch(top, bot, IVs, out pidiv)) // frlg only + return pidiv; if (getXDRNGMatch(top, bot, IVs, out pidiv)) return pidiv; @@ -90,6 +92,41 @@ private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidi pidiv = null; return false; } + private static bool getLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv) + { + // this is an exact copy of LCRNG 1,2,4 matching, except the PID has its halves switched (BACD, BADE, BACE) + var reg = getSeedsFromPID(RNG.LCRNG, bot, top); // reversed! + foreach (var seed in reg) + { + // A and B are already used by PID + var B = RNG.LCRNG.Advance(seed, 2); + + // Method 1/2/4 can use 3 different RNG frames + var C = RNG.LCRNG.Next(B); + var D = RNG.LCRNG.Next(C); + + if (getIVs(C >> 16, D >> 16).SequenceEqual(IVs)) // BACD + { + pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Unown }; + return true; + } + + var E = RNG.LCRNG.Next(D); + if (getIVs(D >> 16, E >> 16).SequenceEqual(IVs)) // BADE + { + pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2_Unown }; + return true; + } + + if (getIVs(C >> 16, E >> 16).SequenceEqual(IVs)) // BACE + { + pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4_Unown }; + return true; + } + } + pidiv = null; + return false; + } private static bool getXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv) { var xdc = getSeedsFromPID(RNG.XDRNG, bot, top); diff --git a/PKHeX/Legality/RNG/PIDType.cs b/PKHeX/Legality/RNG/PIDType.cs index b8c25ada7..d7e199d05 100644 --- a/PKHeX/Legality/RNG/PIDType.cs +++ b/PKHeX/Legality/RNG/PIDType.cs @@ -11,6 +11,12 @@ public enum PIDType Method_2, /// Method H4 Method_4, + /// Method H1_Unown (FRLG) + Method_1_Unown, + /// Method H2_Unown (FRLG) + Method_2_Unown, + /// Method H4_Unown (FRLG) + Method_4_Unown, /// /// Event Reversed Order PID restricted to 16bit Origin Seed diff --git a/Tests/PKHeX.Tests/PKM/PKMTests.cs b/Tests/PKHeX.Tests/PKM/PKMTests.cs index aeaefdc4c..01d0b81b5 100644 --- a/Tests/PKHeX.Tests/PKM/PKMTests.cs +++ b/Tests/PKHeX.Tests/PKM/PKMTests.cs @@ -254,6 +254,28 @@ public void PIDIVMatchingTest() Assert.AreEqual(true, MethodFinder.getPokeSpotSeeds(pkPS1, 1).Any(), "PokeSpot encounter info mismatch (Uncommon)"); var pkPS2 = new PK3 {PID = 0x9B667F3C}; // Surskit (Oasis) Assert.AreEqual(true, MethodFinder.getPokeSpotSeeds(pkPS2, 2).Any(), "PokeSpot encounter info mismatch (Rare)"); + + var pk1U = new PK3 + { + Species = 201, // Unown-C + PID = 0x815549A2, + IVs = new[] {02, 26, 30, 30, 11, 26} + }; + Assert.AreEqual(PIDType.Method_1_Unown, MethodFinder.Analyze(pk1U)?.Type, "Unable to match PID to Method 1 Unown spread"); + var pk2U = new PK3 + { + Species = 201, // Unown-M + PID = 0x8A7B5190, + IVs = new[] {14, 02, 21, 30, 29, 15} + }; + Assert.AreEqual(PIDType.Method_2_Unown, MethodFinder.Analyze(pk2U)?.Type, "Unable to match PID to Method 2 Unown spread"); + var pk4U = new PK3 + { + Species = 201, // Unown-C + PID = 0x5FA80D70, + IVs = new[] {02, 06, 03, 26, 04, 19} + }; + Assert.AreEqual(PIDType.Method_4_Unown, MethodFinder.Analyze(pk4U)?.Type, "Unable to match PID to Method 4 Unown spread"); } } }