Misc cleanup

Add PCD fixed PID check
improve PID matching for CXD pkm
hide no-pidiv match seed (00000000)
fix matching fateful for wild pokespot pkm
don't generate eggs for c/xd
This commit is contained in:
Kurt 2017-06-03 15:16:24 -07:00
parent aed6dffce4
commit 4201e10a0e
8 changed files with 121 additions and 111 deletions

View file

@ -352,7 +352,7 @@ namespace PKHeX.Core
lines.AddRange(br); lines.AddRange(br);
lines.Add(string.Format(V195, EncounterName)); lines.Add(string.Format(V195, EncounterName));
var pidiv = MethodFinder.Analyze(pkm); var pidiv = info.PIDIV ?? MethodFinder.Analyze(pkm);
if (pidiv != null) if (pidiv != null)
{ {
if (!pidiv.NoSeed) if (!pidiv.NoSeed)

View file

@ -78,15 +78,20 @@ namespace PKHeX.Core
if (pkm.GenNumber >= 6 && pkm.PID == pkm.EncryptionConstant) if (pkm.GenNumber >= 6 && pkm.PID == pkm.EncryptionConstant)
AddLine(Severity.Invalid, V208, CheckIdentifier.PID); // better to flag than 1:2^32 odds since RNG is not feasible to yield match AddLine(Severity.Invalid, V208, CheckIdentifier.PID); // better to flag than 1:2^32 odds since RNG is not feasible to yield match
if (EncounterMatch is EncounterStatic s) switch (EncounterMatch)
{ {
if (s.Shiny != null && (bool) s.Shiny ^ pkm.IsShiny) case EncounterStatic s:
AddLine(Severity.Invalid, V209, CheckIdentifier.Shiny); if (s.Shiny != null && (bool)s.Shiny ^ pkm.IsShiny)
} AddLine(Severity.Invalid, V209, CheckIdentifier.Shiny);
else if (EncounterMatch is EncounterSlot w) break;
{ case EncounterSlot w:
if (pkm.IsShiny && w.Type == SlotType.HiddenGrotto) if (pkm.IsShiny && w.Type == SlotType.HiddenGrotto)
AddLine(Severity.Invalid, V221, CheckIdentifier.Shiny); AddLine(Severity.Invalid, V221, CheckIdentifier.Shiny);
break;
case PCD d: // fixed PID
if (d.Gift.PK.PID != 1 && pkm.EncryptionConstant != d.Gift.PK.PID)
AddLine(Severity.Invalid, V410, CheckIdentifier.Shiny);
break;
} }
} }
private void verifyECPIDWurmple() private void verifyECPIDWurmple()
@ -150,9 +155,9 @@ namespace PKHeX.Core
if (pk.Length > (lang == 2 ? 10 : 5)) if (pk.Length > (lang == 2 ? 10 : 5))
AddLine(Severity.Invalid, V1, CheckIdentifier.Nickname); AddLine(Severity.Invalid, V1, CheckIdentifier.Nickname);
} }
else if (Type == typeof(MysteryGift)) else if (EncounterMatch is MysteryGift m)
{ {
if (pkm.IsNicknamed && (!(EncounterMatch as MysteryGift)?.IsEgg ?? false)) if (pkm.IsNicknamed && !m.IsEgg)
AddLine(Severity.Fishy, V0, CheckIdentifier.Nickname); AddLine(Severity.Fishy, V0, CheckIdentifier.Nickname);
} }
@ -803,26 +808,10 @@ namespace PKHeX.Core
private void verifyCXD() private void verifyCXD()
{ {
if (EncounterMatch is EncounterSlot w) // pokespot if (EncounterMatch is EncounterStatic)
{ verifyCXDStarterCorrelation(info.PIDIV);
// find origin info, if nothing returned then the PID is unobtainable
var slot = w.SlotNumber;
var pidiv = MethodFinder.getPokeSpotSeeds(pkm, slot);
if (!pidiv.Any())
AddLine(Severity.Invalid, V400, CheckIdentifier.PID);
}
else if (Type == typeof (EncounterStatic))
{
var pidiv = MethodFinder.Analyze(pkm);
if (pidiv == null || pidiv.Type != PIDType.CXD)
AddLine(Severity.Invalid, V400, CheckIdentifier.PID);
else // Starters have a correlation to the Trainer ID numbers
verifyCXDStarterCorrelation(pidiv);
}
else if (pkm.WasEgg) // can't obtain eggs in CXD else if (pkm.WasEgg) // can't obtain eggs in CXD
{
AddLine(Severity.Invalid, V80, CheckIdentifier.Encounter); // invalid encounter AddLine(Severity.Invalid, V80, CheckIdentifier.Encounter); // invalid encounter
}
if (pkm.OT_Gender == 1) if (pkm.OT_Gender == 1)
AddLine(Severity.Invalid, V407, CheckIdentifier.Trainer); AddLine(Severity.Invalid, V407, CheckIdentifier.Trainer);
@ -973,15 +962,19 @@ namespace PKHeX.Core
} }
private void verifyAbility5(int[] abilities) private void verifyAbility5(int[] abilities)
{ {
if (EncounterMatch is EncounterSlot w) switch (EncounterMatch)
{ {
// Hidden Abilities for Wild Encounters are only available at a Hidden Grotto case PGF g:
bool grotto = w.Type == SlotType.HiddenGrotto; verifyAbilityMG456(abilities, g.AbilityType);
if (pkm.AbilityNumber == 4 ^ grotto) break;
AddLine(Severity.Invalid, grotto ? V217 : V108, CheckIdentifier.Ability);
case EncounterSlot w:
// Hidden Abilities for Wild Encounters are only available at a Hidden Grotto
bool grotto = w.Type == SlotType.HiddenGrotto;
if (pkm.AbilityNumber == 4 ^ grotto)
AddLine(Severity.Invalid, grotto ? V217 : V108, CheckIdentifier.Ability);
break;
} }
else if (Type == typeof(MysteryGift))
verifyAbilityMG456(abilities, ((PGF)EncounterMatch).AbilityType);
} }
private void verifyAbility6(int[] abilities) private void verifyAbility6(int[] abilities)
{ {
@ -991,8 +984,8 @@ namespace PKHeX.Core
if (!valid) if (!valid)
AddLine(Severity.Invalid, V300, CheckIdentifier.Ability); AddLine(Severity.Invalid, V300, CheckIdentifier.Ability);
} }
else if (Type == typeof(MysteryGift)) else if (EncounterMatch is WC6 g)
verifyAbilityMG456(abilities, ((WC6)EncounterMatch).AbilityType); verifyAbilityMG456(abilities, g.AbilityType);
else if (Legal.Ban_NoHidden6.Contains(pkm.SpecForm) && pkm.AbilityNumber == 4) else if (Legal.Ban_NoHidden6.Contains(pkm.SpecForm) && pkm.AbilityNumber == 4)
AddLine(Severity.Invalid, V112, CheckIdentifier.Ability); AddLine(Severity.Invalid, V112, CheckIdentifier.Ability);
} }
@ -1001,12 +994,11 @@ namespace PKHeX.Core
if (EncounterMatch is EncounterSlot slot && pkm.AbilityNumber == 4) if (EncounterMatch is EncounterSlot slot && pkm.AbilityNumber == 4)
{ {
bool valid = slot.Type == SlotType.SOS; bool valid = slot.Type == SlotType.SOS;
if (!valid) if (!valid)
AddLine(Severity.Invalid, V111, CheckIdentifier.Ability); AddLine(Severity.Invalid, V111, CheckIdentifier.Ability);
} }
else if (Type == typeof(MysteryGift)) else if (EncounterMatch is WC7 g)
verifyAbilityMG456(abilities, ((WC7)EncounterMatch).AbilityType); verifyAbilityMG456(abilities, g.AbilityType);
else if (Legal.Ban_NoHidden7.Contains(pkm.SpecForm) && pkm.AbilityNumber == 4) else if (Legal.Ban_NoHidden7.Contains(pkm.SpecForm) && pkm.AbilityNumber == 4)
AddLine(Severity.Invalid, V112, CheckIdentifier.Ability); AddLine(Severity.Invalid, V112, CheckIdentifier.Ability);
} }
@ -1055,9 +1047,9 @@ namespace PKHeX.Core
verifyBallEquals(l.Ball); verifyBallEquals(l.Ball);
return; return;
} }
if (Type == typeof (EncounterTrade)) if (EncounterMatch is EncounterTrade t)
{ {
verifyBallEquals(4); // Pokeball verifyBallEquals(t.Ball); // Pokeball
return; return;
} }
@ -1576,15 +1568,15 @@ namespace PKHeX.Core
// Undocumented, uncommon, and insignificant -- don't bother. // Undocumented, uncommon, and insignificant -- don't bother.
return; return;
} }
if (MatchedType == typeof(WC6)) if (EncounterMatch is WC6 wc6)
{ {
WC6 g = EncounterMatch as WC6; var g = wc6;
verifyOTMemoryIs(new[] {g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling}); verifyOTMemoryIs(new[] {g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling});
return; return;
} }
if (MatchedType == typeof(WC7)) if (EncounterMatch is WC7 wc7)
{ {
WC7 g = EncounterMatch as WC7; var g = wc7;
verifyOTMemoryIs(new[] {g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling}); verifyOTMemoryIs(new[] {g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling});
return; return;
} }
@ -1989,75 +1981,82 @@ namespace PKHeX.Core
{ AddLine(Severity.Invalid, V374, CheckIdentifier.Misc); } { AddLine(Severity.Invalid, V374, CheckIdentifier.Misc); }
} }
if (Encounter.Valid) if (!Encounter.Valid)
return;
if (EncounterMatch is MysteryGift g)
{ {
if (EncounterMatch is MysteryGift g) bool fatefulValid = false;
if (g.Format == 3)
{ {
bool fatefulValid = false; // obedience flag in gen3 is the fateful flag; met location stores the fateful info until transfer
if (g.Format == 3) bool required = g.Species == 151 || g.Species == 386;
{ required |= pkm.Format != 3 && !g.IsEgg;
// obedience flag in gen3 is the fateful flag; met location stores the fateful info until transfer fatefulValid = !(required ^ pkm.FatefulEncounter);
bool required = g.Species == 151 || g.Species == 386;
required |= pkm.Format != 3 && !g.IsEgg;
fatefulValid = !(required ^ pkm.FatefulEncounter);
var g3 = (WC3) g; // shiny locked gifts var g3 = (WC3) g; // shiny locked gifts
if (g3.Shiny != null && g3.Shiny != pkm.IsShiny) if (g3.Shiny != null && g3.Shiny != pkm.IsShiny)
AddLine(Severity.Invalid, V409, CheckIdentifier.Fateful); AddLine(Severity.Invalid, V409, CheckIdentifier.Fateful);
}
else
{
if (pkm.FatefulEncounter)
fatefulValid = true;
}
if (fatefulValid)
AddLine(Severity.Valid, V321, CheckIdentifier.Fateful);
else
AddLine(Severity.Invalid, V322, CheckIdentifier.Fateful);
return;
} }
if (EncounterMatch is EncounterStatic s) else
{ {
var fateful = s.Fateful; if (pkm.FatefulEncounter)
var shadow = EncounterMatch is EncounterStaticShadow; fatefulValid = true;
if (shadow && !(pkm is XK3 || pkm is CK3))
fateful = true; // purification required for transfer
if (fateful)
{
if (pkm.FatefulEncounter)
AddLine(Severity.Valid, V323, CheckIdentifier.Fateful);
else
AddLine(Severity.Invalid, V324, CheckIdentifier.Fateful);
}
else if (pkm.FatefulEncounter && !shadow)
AddLine(Severity.Invalid, V325, CheckIdentifier.Fateful);
} }
else if (pkm.FatefulEncounter)
if (fatefulValid)
AddLine(Severity.Valid, V321, CheckIdentifier.Fateful);
else
AddLine(Severity.Invalid, V322, CheckIdentifier.Fateful);
return;
}
if (EncounterMatch is EncounterStatic s)
{
var fateful = s.Fateful;
var shadow = EncounterMatch is EncounterStaticShadow;
if (shadow && !(pkm is XK3 || pkm is CK3))
fateful = true; // purification required for transfer
if (fateful)
{
if (pkm.FatefulEncounter)
AddLine(Severity.Valid, V323, CheckIdentifier.Fateful);
else
AddLine(Severity.Invalid, V324, CheckIdentifier.Fateful);
}
else if (pkm.FatefulEncounter && !shadow)
AddLine(Severity.Invalid, V325, CheckIdentifier.Fateful); AddLine(Severity.Invalid, V325, CheckIdentifier.Fateful);
}
else if (EncounterMatch is EncounterSlot && pkm.Version == 15) // pokespot pkm
{
if (pkm.FatefulEncounter)
AddLine(Severity.Valid, V323, CheckIdentifier.Fateful);
else
AddLine(Severity.Invalid, V324, CheckIdentifier.Fateful);
}
else if (pkm.FatefulEncounter)
AddLine(Severity.Invalid, V325, CheckIdentifier.Fateful);
if (pkm.GenNumber == 5) if (pkm.GenNumber == 5)
{
var enc = EncounterMatch as EncounterStatic;
bool req = enc?.NSparkle ?? false;
if (pkm.Format == 5)
{ {
var enc = EncounterMatch as EncounterStatic; bool has = ((PK5)pkm).NPokémon;
bool req = enc?.NSparkle ?? false; if (req && !has)
if (pkm.Format == 5) AddLine(Severity.Invalid, V326, CheckIdentifier.Fateful);
{ if (!req && has)
bool has = ((PK5)pkm).NPokémon; AddLine(Severity.Invalid, V327, CheckIdentifier.Fateful);
if (req && !has) }
AddLine(Severity.Invalid, V326, CheckIdentifier.Fateful); if (req)
if (!req && has) {
AddLine(Severity.Invalid, V327, CheckIdentifier.Fateful); if (pkm.IVs.Any(iv => iv != 30))
} AddLine(Severity.Invalid, V218, CheckIdentifier.IVs);
if (req) if (pkm.OT_Name != "N" || pkm.TID != 00002 || pkm.SID != 00000)
{ AddLine(Severity.Invalid, V219, CheckIdentifier.Trainer);
if (pkm.IVs.Any(iv => iv != 30)) if (pkm.IsShiny)
AddLine(Severity.Invalid, V218, CheckIdentifier.IVs); AddLine(Severity.Invalid, V220, CheckIdentifier.Shiny);
if (pkm.OT_Name != "N" || pkm.TID != 00002 || pkm.SID != 00000)
AddLine(Severity.Invalid, V219, CheckIdentifier.Trainer);
if (pkm.IsShiny)
AddLine(Severity.Invalid, V220, CheckIdentifier.Shiny);
}
} }
} }
} }

View file

@ -50,7 +50,7 @@ namespace PKHeX.Core
{ {
if (encounter.PeekIsNext()) if (encounter.PeekIsNext())
continue; continue;
info.Parse.Add(new CheckResult(Severity.Invalid, "PID Type Mismatch", CheckIdentifier.PID)); info.Parse.Add(new CheckResult(Severity.Invalid, V411, CheckIdentifier.PID));
} }
// Encounter Passes // Encounter Passes

View file

@ -54,6 +54,8 @@ namespace PKHeX.Core
var deferred = new List<IEncounterable>(); var deferred = new List<IEncounterable>();
foreach (var z in GenerateRawEncounters3(pkm)) foreach (var z in GenerateRawEncounters3(pkm))
{ {
if (z is EncounterSlot w && pkm.Version == 15)
info.PIDIV = MethodFinder.getPokeSpotSeeds(pkm, w.SlotNumber).FirstOrDefault() ?? info.PIDIV;
if (info.PIDIV.Type.IsCompatible3(z, pkm)) if (info.PIDIV.Type.IsCompatible3(z, pkm))
yield return z; yield return z;
else else
@ -243,6 +245,9 @@ namespace PKHeX.Core
foreach (var z in getValidStaticEncounter(pkm)) foreach (var z in getValidStaticEncounter(pkm))
yield return z; yield return z;
if (pkm.Version == 15)
yield break; // no eggs in C/XD
foreach (var z in generateEggs(pkm)) foreach (var z in generateEggs(pkm))
yield return z; yield return z;
} }

View file

@ -403,6 +403,8 @@ namespace PKHeX.Core
public static string V407 {get; set;} = "OT from Colosseum/XD cannot be female."; public static string V407 {get; set;} = "OT from Colosseum/XD cannot be female.";
public static string V408 {get; set;} = "Female OT from Generation 1/2 is invalid."; public static string V408 {get; set;} = "Female OT from Generation 1/2 is invalid.";
public static string V409 {get; set;} = "Mystery Gift shiny mismatch."; public static string V409 {get; set;} = "Mystery Gift shiny mismatch.";
public static string V410 {get; set;} = "Mystery Gift fixed PID mismatch.";
public static string V411 {get; set;} = "Encounter Type PID mismatch.";
#endregion #endregion
} }

View file

@ -55,7 +55,7 @@ namespace PKHeX.Core
if (getBACDMatch(pk, pid, IVs, out pidiv)) if (getBACDMatch(pk, pid, IVs, out pidiv))
return pidiv; return pidiv;
return new PIDIV {Type=PIDType.None}; // no match return new PIDIV {Type=PIDType.None, NoSeed=true}; // no match
} }
private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv) private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
@ -504,7 +504,7 @@ namespace PKHeX.Core
if ((s>>16)%3 != 0) // can't activate even if generous if ((s>>16)%3 != 0) // can't activate even if generous
continue; continue;
} }
yield return new PIDIV {OriginSeed = s, RNG = RNG.XDRNG, Type = PIDType.None}; yield return new PIDIV {OriginSeed = s, RNG = RNG.XDRNG, Type = PIDType.PokeSpot};
} }
} }
@ -517,10 +517,12 @@ namespace PKHeX.Core
case EncounterStaticShadow _: case EncounterStaticShadow _:
return val == PIDType.CXD; return val == PIDType.CXD;
case EncounterStatic s: case EncounterStatic s:
if (pkm.Version == 15)
return val == PIDType.CXD;
return s.Roaming ? val == PIDType.Method_1_Roamer : MethodH.Any(z => z == val); return s.Roaming ? val == PIDType.Method_1_Roamer : MethodH.Any(z => z == val);
case EncounterSlot w: case EncounterSlot w:
if (pkm.Version == 15) if (pkm.Version == 15)
return val == PIDType.CXD; return val == PIDType.PokeSpot;
return (w.Species == 201 ? MethodH_Unown : MethodH).Any(z => z == val); return (w.Species == 201 ? MethodH_Unown : MethodH).Any(z => z == val);
default: default:
return val == PIDType.None; return val == PIDType.None;

View file

@ -57,6 +57,7 @@
// XDRNG Based // XDRNG Based
CXD, CXD,
Channel, Channel,
PokeSpot,
// ARNG Based // ARNG Based
G4MGAntiShiny, G4MGAntiShiny,

View file

@ -23,6 +23,7 @@
public int OTGender = -1; public int OTGender = -1;
public bool EggEncounter => false; public bool EggEncounter => false;
public bool EvolveOnTrade = false; public bool EvolveOnTrade = false;
public int Ball = 4;
public string Name => "In-game Trade"; public string Name => "In-game Trade";