diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs
index 0063b0e85..7d84d5fd0 100644
--- a/PKHeX/Legality/Checks.cs
+++ b/PKHeX/Legality/Checks.cs
@@ -166,7 +166,7 @@ private void verifyECPIDWurmple()
}
// Check if Wurmple was the origin (only Egg and Wild Encounter)
- bool wasWurmple = pkm.WasEgg || (Type == typeof (EncounterSlot[]) && ((EncounterSlot[])EncounterMatch).Any(slot => slot.Species == 265));
+ bool wasWurmple = pkm.WasEgg || (Type == typeof (EncounterSlot[]) && ((EncounterSlot[])EncounterMatch).All(slot => slot.Species == 265));
if (!wasWurmple)
return;
diff --git a/PKHeX/Legality/RNG/MethodFinder.cs b/PKHeX/Legality/RNG/MethodFinder.cs
index 8ed37005f..0622dcd77 100644
--- a/PKHeX/Legality/RNG/MethodFinder.cs
+++ b/PKHeX/Legality/RNG/MethodFinder.cs
@@ -38,6 +38,8 @@ public static PIDIV Analyze(PKM pk)
return pidiv;
// Special cases
+ if (getLCRNGRoamerMatch(top, bot, IVs, out pidiv))
+ return pidiv;
if (getChannelMatch(top, bot, IVs, out pidiv))
return pidiv;
if (getMG4Match(pid, IVs, out pidiv))
@@ -61,6 +63,8 @@ public static PIDIV Analyze(PKM pk)
private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
{
var reg = getSeedsFromPID(RNG.LCRNG, top, bot);
+ var iv1 = getIVChunk(IVs, 0);
+ var iv2 = getIVChunk(IVs, 3);
foreach (var seed in reg)
{
// A and B are already used by PID
@@ -68,25 +72,39 @@ private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidi
// 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)) // ABCD
+ var ivC = C >> 16 & 0x7FFF;
+ if (iv1 == ivC)
{
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1};
- return true;
+ var D = RNG.LCRNG.Next(C);
+ var ivD = D >> 16 & 0x7FFF;
+ if (iv2 == ivD) // ABCD
+ {
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1};
+ return true;
+ }
+
+ var E = RNG.LCRNG.Next(D);
+ var ivE = E >> 16 & 0x7FFF;
+ if (iv2 == ivE) // ABCE
+ {
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4};
+ return true;
+ }
}
-
- var E = RNG.LCRNG.Next(D);
- if (getIVs(D >> 16, E >> 16).SequenceEqual(IVs)) // ABDE
+ else
{
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2};
- return true;
- }
+ var D = RNG.LCRNG.Next(C);
+ var ivD = D >> 16 & 0x7FFF;
+ if (iv1 != ivD)
+ continue;
- if (getIVs(C >> 16, E >> 16).SequenceEqual(IVs)) // ABCE
- {
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4};
- return true;
+ var E = RNG.LCRNG.Next(D);
+ var ivE = E >> 16 & 0x7FFF;
+ if (iv2 == ivE) // ABDE
+ {
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2};
+ return true;
+ }
}
}
pidiv = null;
@@ -96,6 +114,8 @@ private static bool getLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out 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!
+ var iv1 = getIVChunk(IVs, 0);
+ var iv2 = getIVChunk(IVs, 3);
foreach (var seed in reg)
{
// A and B are already used by PID
@@ -103,30 +123,67 @@ private static bool getLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV
// 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
+ var ivC = C >> 16 & 0x7FFF;
+ if (iv1 == ivC)
{
- pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Unown };
- return true;
- }
+ var D = RNG.LCRNG.Next(C);
+ var ivD = D >> 16 & 0x7FFF;
+ if (iv2 == ivD) // 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;
+ var E = RNG.LCRNG.Next(D);
+ var ivE = E >> 16 & 0x7FFF;
+ if (iv2 == ivE) // BACE
+ {
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4_Unown};
+ return true;
+ }
}
+ else
+ {
+ var D = RNG.LCRNG.Next(C);
+ var ivD = D >> 16 & 0x7FFF;
+ if (iv1 != ivD)
+ continue;
- if (getIVs(C >> 16, E >> 16).SequenceEqual(IVs)) // BACE
- {
- pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4_Unown };
- return true;
+ var E = RNG.LCRNG.Next(D);
+ var ivE = E >> 16 & 0x7FFF;
+ if (iv2 != ivE) // BADE
+ {
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2_Unown};
+ return true;
+ }
}
}
pidiv = null;
return false;
}
+ private static bool getLCRNGRoamerMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
+ {
+ var iv2 = getIVChunk(IVs, 3);
+ if (iv2 != 0 || IVs[2] != 0)
+ {
+ pidiv = null;
+ return false;
+ }
+ var iv1 = getIVChunk(IVs, 0);
+ var reg = getSeedsFromPID(RNG.LCRNG, top, bot);
+ foreach (var seed in reg)
+ {
+ // Only the first two IVs are kept
+ var ivC = RNG.LCRNG.Advance(seed, 3) >> 16 & 0x03FF;
+ if (iv1 != ivC)
+ continue;
+
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Roamer};
+ 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);
@@ -280,8 +337,8 @@ private static bool getBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
var B = seed;
var A = RNG.LCRNG.Prev(B);
- var PID = A & 0xFFFF0000 | (B >> 16);
- bool isShiny = (pk.TID ^ pk.SID ^ (PID >> 16) ^ (PID & 0xFFFF)) < 8;
+ var PID = A & 0xFFFF0000 | B >> 16;
+ bool isShiny = (pk.TID ^ pk.SID ^ PID >> 16 ^ PID & 0xFFFF) < 8;
bool forceShiny = false;
if (PID != pid)
{
@@ -306,12 +363,12 @@ private static bool getBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
continue;
forceShiny = true;
}
- if (!forceShiny && ((PID + 8) & 0xFFFFFFF8) != pid)
+ if (!forceShiny && (PID + 8 & 0xFFFFFFF8) != pid)
continue;
}
var s = RNG.LCRNG.Prev(A);
- // Check for Restricted generation pattern
+ // Check for prior Restricted seed
var sn = s;
for (int i = 0; i < 3; i++, sn = RNG.LCRNG.Prev(sn))
{
@@ -321,7 +378,7 @@ private static bool getBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
pidiv = new PIDIV {OriginSeed = sn, RNG = RNG.LCRNG, Type = type};
return true;
}
-
+ // no restricted seed found, thus unrestricted
var t = forceShiny ? PIDType.BACD_U_S : isShiny ? PIDType.BACD_U_A : PIDType.BACD_U;
pidiv = new PIDIV {OriginSeed = s, RNG = RNG.LCRNG, Type = t};
return true;
diff --git a/PKHeX/Legality/RNG/PIDType.cs b/PKHeX/Legality/RNG/PIDType.cs
index d7e199d05..1aeaf4483 100644
--- a/PKHeX/Legality/RNG/PIDType.cs
+++ b/PKHeX/Legality/RNG/PIDType.cs
@@ -17,6 +17,8 @@ public enum PIDType
Method_2_Unown,
/// Method H4_Unown (FRLG)
Method_4_Unown,
+ /// Method 1 Roamer (Gen3)
+ Method_1_Roamer,
///
/// Event Reversed Order PID restricted to 16bit Origin Seed
diff --git a/PKHeX/Legality/Tables4.cs b/PKHeX/Legality/Tables4.cs
index 413b7a727..1572cf7e6 100644
--- a/PKHeX/Legality/Tables4.cs
+++ b/PKHeX/Legality/Tables4.cs
@@ -723,7 +723,7 @@ public static partial class Legal
new EncounterStatic { Species = 143, Level = 50, Location = 159, }, //Snorlax @ Route 11
new EncounterStatic { Species = 143, Level = 50, Location = 160, }, //Snorlax @ Route 12
new EncounterStatic { Species = 185, Level = 20, Location = 184, }, //Sudowoodo @ Route 36, Encounter does not have type
- new EncounterStaticTyped { Species = 172, Level = 30, Location = 214, Gender = 1, Form = 1, Moves = new[]{344,270,207,220}, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, //Spiky-eared Pichu @ Ilex forest
+ new EncounterStaticTyped { Species = 172, Level = 30, Location = 214, Gender = 1, Form = 1, Moves = new[]{344,270,207,220}, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Shiny = false }, //Spiky-eared Pichu @ Ilex forest
//Stationary Lengerdary
new EncounterStaticTyped { Species = 144, Level = 50, Location = 203, TypeEncounter = EncounterType.Cave_HallOfOrigin }, //Articuno @ Seafoam Islands
new EncounterStatic { Species = 145, Level = 50, Location = 158, }, //Zapdos @ Route 10