Add PIDIV checking for encounters

Fixes HGSS egg moves, and improves encounter detail detection.
example: togepi from FRLG transferred up, old detection couldn't
differentiate the gift egg from a regular egg; however, PIDIVs can lend
a hand -- eggs don't have a PIDIV!

fixed shiny BACD spread detection (in regards to antishiny rerolls).
Shiny WISHMKR now detected correctly.
This commit is contained in:
Kurt
2017-06-03 00:12:05 -07:00
parent 03f42ee19c
commit 5823425f42
7 changed files with 90 additions and 34 deletions

View File

@@ -2716,15 +2716,13 @@ internal static int[] getEggMoves(PKM pkm, int species, int formnum, GameVersion
case 3:
return EggMovesRS[species].Moves;
case 4:
switch (Version)
switch (pkm.Version)
{
case GameVersion.DP:
case GameVersion.Pt:
return EggMovesDPPt[species].Moves;
case GameVersion.HGSS:
case (int)GameVersion.HG:
case (int)GameVersion.SS:
return EggMovesHGSS[species].Moves;
default:
return new int[0];
return EggMovesDPPt[species].Moves;
}
case 5:
return EggMovesBW[species].Moves;

View File

@@ -20,6 +20,7 @@ public static LegalInfo verifyEncounter(PKM pkm)
while (encounter.MoveNext())
{
var EncounterMatch = info.EncounterMatch = encounter.Current;
bool PIDMatch = info.PIDIVMatches;
var e = EncounterValidator(pkm, EncounterMatch);
if (!e.Valid && encounter.PeekIsNext())
@@ -43,9 +44,15 @@ public static LegalInfo verifyEncounter(PKM pkm)
var evo = VerifyEvolution.verifyEvolution(pkm, EncounterMatch);
if (!evo.Valid && encounter.PeekIsNext())
continue;
info.Parse.Add(evo);
if (!PIDMatch)
{
if (encounter.PeekIsNext())
continue;
info.Parse.Add(new CheckResult(Severity.Invalid, "PID Type Mismatch", CheckIdentifier.PID));
}
// Encounter Passes
break;
}

View File

@@ -50,19 +50,33 @@ private static IEnumerable<IEncounterable> getEncounters12(PKM pkm, LegalInfo in
}
private static IEnumerable<IEncounterable> getEncounters3(PKM pkm, LegalInfo info)
{
info.PIDIV = MethodFinder.Analyze(pkm);
var deferred = new List<IEncounterable>();
foreach (var z in GenerateRawEncounters3(pkm))
{
// todo: pidiv filtering
yield return z;
if (info.PIDIV.Type.IsCompatible3(z, pkm))
yield return z;
else
deferred.Add(z);
}
info.PIDIVMatches = false;
foreach (var z in deferred)
yield return z;
}
private static IEnumerable<IEncounterable> getEncounters4(PKM pkm, LegalInfo info)
{
info.PIDIV = MethodFinder.Analyze(pkm);
var deferred = new List<IEncounterable>();
foreach (var z in GenerateRawEncounters4(pkm))
{
// todo: pidiv filtering
yield return z;
if (info.PIDIV.Type.IsCompatible4(z))
yield return z;
else
deferred.Add(z);
}
info.PIDIVMatches = false;
foreach (var z in deferred)
yield return z;
}
private static IEnumerable<GBEncounterData> GenerateRawEncounters12(PKM pkm, GameVersion game)
{
@@ -157,7 +171,6 @@ private static IEnumerable<IEncounterable> GenerateRawEncounters(PKM pkm)
{
foreach (var z in generateEggs(pkm))
yield return z;
yield break;
}
foreach (var z in getValidStaticEncounter(pkm))
@@ -187,7 +200,6 @@ private static IEnumerable<IEncounterable> GenerateRawEncounters4(PKM pkm)
{
foreach (var z in generateEggs(pkm))
{ yield return z; ++ctr; }
if (ctr != 0) yield break;
}
bool safariSport = pkm.Ball == 0x05 || pkm.Ball == 0x18; // never static encounters
@@ -212,10 +224,8 @@ private static IEnumerable<IEncounterable> GenerateRawEncounters4(PKM pkm)
}
private static IEnumerable<IEncounterable> GenerateRawEncounters3(PKM pkm)
{
int ctr = 0;
foreach (var z in getValidGifts(pkm))
{ yield return z; ++ctr; }
if (ctr != 0) yield break;
yield return z;
bool safari = pkm.Ball == 0x05; // never static encounters
if (!safari)
@@ -288,12 +298,9 @@ private static IEnumerable<EncounterStatic> getMatchingStaticEncounters(PKM pkm,
{
if (e.Nature != Nature.Random && pkm.Nature != (int)e.Nature)
continue;
if (pkm.Gen3 && e.EggLocation != 0)
if (pkm.Gen3 && e.EggLocation != 0) // egg
{
// Hatched gen 3 gift egg can not be differentiated from normal eggs
if (!pkm.IsEgg || pkm.Format > 3)
continue;
if (e.EggLocation != pkm.Met_Location)
if (pkm.Format == 3 && e.EggLocation != pkm.Met_Location)
continue;
}
else if (e.EggLocation != pkm.Egg_Location)
@@ -770,8 +777,8 @@ private static IEnumerable<MysteryGift> getMatchingWC3(PKM pkm, IEnumerable<Myst
if (!wc.IsEgg)
{
if (wc.SID != -1 && wc.SID != pkm.SID) continue;
if (wc.TID != -1 && wc.TID != pkm.TID) continue;
if (wc.SID != pkm.SID) continue;
if (wc.TID != pkm.TID) continue;
if (wc.OT_Name != pkm.OT_Name) continue;
if (wc.OT_Gender < 3 && wc.OT_Gender != pkm.OT_Gender) continue;
if (wc.Language != 0 && wc.Language != pkm.Language) continue;

View File

@@ -39,6 +39,7 @@ public IEncounterable EncounterMatch
private DexLevel[][] _evochains;
private IEncounterable _match;
public PIDIV PIDIV;
public bool PIDIVMatches = true;
public LegalInfo(PKM pk)
{

View File

@@ -55,7 +55,7 @@ public static PIDIV Analyze(PKM pk)
if (getBACDMatch(pk, pid, IVs, out pidiv))
return pidiv;
return null; // no match
return new PIDIV {Type=PIDType.None}; // no match
}
private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
@@ -336,6 +336,7 @@ private static bool getBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
var PID = A & 0xFFFF0000 | B >> 16;
bool isShiny = (pk.TID ^ pk.SID ^ PID >> 16 ^ PID & 0xFFFF) < 8;
bool forceShiny = false;
bool antiShiny = false;
if (PID != pid)
{
if (!isShiny)
@@ -359,8 +360,12 @@ private static bool getBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
continue;
forceShiny = true;
}
if (!forceShiny && (PID + 8 & 0xFFFFFFF8) != pid)
continue;
if (!forceShiny)
{
if ((PID + 8 & 0xFFFFFFF8) != pid)
continue;
antiShiny = true;
}
}
var s = RNG.LCRNG.Prev(A);
@@ -370,12 +375,12 @@ private static bool getBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
{
if ((sn & 0xFFFF0000) != 0)
continue;
var type = forceShiny ? PIDType.BACD_R_S : isShiny ? PIDType.BACD_R_A : PIDType.BACD_R;
var type = forceShiny ? PIDType.BACD_R_S : antiShiny ? PIDType.BACD_R_A : PIDType.BACD_R;
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;
var t = forceShiny ? PIDType.BACD_U_S : antiShiny ? PIDType.BACD_U_A : PIDType.BACD_U;
pidiv = new PIDIV {OriginSeed = s, RNG = RNG.LCRNG, Type = t};
return true;
}
@@ -502,5 +507,40 @@ public static IEnumerable<PIDIV> getPokeSpotSeeds(PKM pkm, int slot)
yield return new PIDIV {OriginSeed = s, RNG = RNG.XDRNG, Type = PIDType.None};
}
}
public static bool IsCompatible3(this PIDType val, IEncounterable encounter, PKM pkm)
{
switch (encounter)
{
case WC3 g:
return val == g.Method;
case EncounterStaticShadow _:
return val == PIDType.CXD;
case EncounterStatic s:
return s.Roaming ? val == PIDType.Method_1_Roamer : MethodH.Any(z => z == val);
case EncounterSlot w:
if (pkm.Version == 15)
return val == PIDType.CXD;
return (w.Species == 201 ? MethodH_Unown : MethodH).Any(z => z == val);
default:
return val == PIDType.None;
}
}
public static bool IsCompatible4(this PIDType val, IEncounterable encounter)
{
switch (encounter)
{
case EncounterStatic s:
return s.Shiny == true ? val == PIDType.ChainShiny : val == PIDType.Method_1;
case EncounterSlot _:
return val == PIDType.Method_1;
default:
return val == PIDType.None;
}
}
private static readonly PIDType[] MethodH = { PIDType.Method_1, PIDType.Method_2, PIDType.Method_4 };
private static readonly PIDType[] MethodH_Unown = { PIDType.Method_1_Unown, PIDType.Method_2_Unown, PIDType.Method_4_Unown };
}
}

View File

@@ -283,15 +283,18 @@ public static partial class Legal
new WC3 { Species = 359, IsEgg = true, Level = 05, Version = (int)GameVersion.RS, Moves = new[]{273} }, // Absol with Wish
new WC3 { Species = 371, IsEgg = true, Level = 05, Version = (int)GameVersion.RS, Moves = new[]{334} }, // Bagon with Iron Defense
new WC3 { Species = 371, IsEgg = true, Level = 05, Version = (int)GameVersion.RS, Moves = new[]{273} }, // Bagon with Wish
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 30317, OT_Name = "RUBY" },
new WC3 { Species = 263, Level = 5, Version = (int)GameVersion.RS, Method = PIDType.BACD_R_S, TID = 30317, OT_Name = "SAPHIRE" },
};
internal static readonly MysteryGift[] Encounter_Event3_Common =
{
// Pokémon Box
new WC3 { Species = 333, IsEgg = true, Level = 05, /*Version = (int)GameVersion.RSBOX,*/ Moves = new[]{206} }, // Swablu Egg with False Swipe
new WC3 { Species = 263, IsEgg = true, Level = 05, /*Version = (int)GameVersion.RSBOX,*/ Moves = new[]{245} }, // Zigzagoon Egg with Extreme Speed
new WC3 { Species = 300, IsEgg = true, Level = 05, /*Version = (int)GameVersion.RSBOX,*/ Moves = new[]{006} }, // Skitty Egg with Pay Day
new WC3 { Species = 172, IsEgg = true, Level = 05, /*Version = (int)GameVersion.RSBOX,*/ Moves = new[]{057} }, // Pichu Egg with Surf
new WC3 { Species = 333, IsEgg = true, Level = 05, /*Version = (int)GameVersion.RSBOX,*/ Moves = new[]{206}, Method = PIDType.BACD_U }, // Swablu Egg with False Swipe
new WC3 { Species = 263, IsEgg = true, Level = 05, /*Version = (int)GameVersion.RSBOX,*/ Moves = new[]{245}, Method = PIDType.BACD_U }, // Zigzagoon Egg with Extreme Speed
new WC3 { Species = 300, IsEgg = true, Level = 05, /*Version = (int)GameVersion.RSBOX,*/ Moves = new[]{006}, Method = PIDType.BACD_U }, // Skitty Egg with Pay Day
new WC3 { Species = 172, IsEgg = true, Level = 05, /*Version = (int)GameVersion.RSBOX,*/ Moves = new[]{057}, Method = PIDType.BACD_U }, // Pichu Egg with Surf
// PokePark Eggs
new WC3 { Species = 054, IsEgg = true, Level = 05, Moves = new[]{300} }, // Psyduck with Mud Sport
new WC3 { Species = 172, IsEgg = true, Level = 05, Moves = new[]{266} }, // Pichu with Follow me

View File

@@ -13,8 +13,8 @@ public class WC3 : MysteryGift
public string OT_Name;
public int OT_Gender = 3;
public int TID = -1;
public int SID = -1;
public int TID;
public int SID;
public int Met_Location = 255;
public int Version;
public int Language;