Move encounter matching logic to iencounterable

generator logic is now clean
This commit is contained in:
Kurt 2018-12-27 01:00:08 -08:00
parent 3481780e06
commit 2d75e93ef0
14 changed files with 703 additions and 733 deletions

View file

@ -1,4 +1,5 @@
using System;
using System.Linq;
namespace PKHeX.Core
{
@ -238,5 +239,131 @@ namespace PKHeX.Core
default: return PIDType.None;
}
}
public bool IsMatch(PKM pkm, int lvl)
{
if (Nature != Nature.Random && pkm.Nature != (int)Nature)
return false;
if (pkm.WasEgg != EggEncounter && pkm.Egg_Location == 0 && pkm.Format > 3 && pkm.GenNumber > 3 && !pkm.IsEgg)
return false;
if (this is EncounterStaticPID p && p.PID != pkm.PID)
return false;
if (pkm.Gen3 && EggLocation != 0) // Gen3 Egg
{
if (pkm.Format == 3 && pkm.IsEgg && EggLocation != pkm.Met_Location)
return false;
}
else if (pkm.VC || (pkm.GenNumber <= 2 && EggLocation != 0)) // Gen2 Egg
{
if (pkm.Format <= 2)
{
if (pkm.IsEgg)
{
if (pkm.Met_Location != 0 && pkm.Met_Level != 0)
return false;
}
else
{
switch (pkm.Met_Level)
{
case 0 when pkm.Met_Location != 0:
return false;
case 1 when pkm.Met_Location == 0:
return false;
default:
if (pkm.Met_Location == 0 && pkm.Met_Level != 0)
return false;
break;
}
}
if (pkm.Met_Level == 1)
lvl = 5; // met @ 1, hatch @ 5.
}
}
else if (EggLocation != pkm.Egg_Location)
{
if (pkm.IsEgg) // unhatched
{
if (EggLocation != pkm.Met_Location)
return false;
if (pkm.Egg_Location != 0)
return false;
}
else if (pkm.Gen4)
{
if (pkm.Egg_Location != 2002) // Link Trade
{
// check Pt/HGSS data
if (pkm.Format <= 4)
return false; // must match
if (EggLocation >= 3000 || EggLocation <= 2010) // non-Pt/HGSS egg gift
return false;
// transferring 4->5 clears pt/hgss location value and keeps Faraway Place
if (pkm.Egg_Location != 3002) // Faraway Place
return false;
}
}
else
{
if (pkm.Egg_Location != 30002) // Link Trade
return false;
}
}
else if (EggLocation != 0 && pkm.Gen4)
{
// Check the inverse scenario for 4->5 eggs
if (EggLocation < 3000 && EggLocation > 2010) // Pt/HGSS egg gift
{
if (pkm.Format > 4)
return false; // locations match when it shouldn't
}
}
if (pkm.HasOriginalMetLocation)
{
if (!EggEncounter && Location != 0 && Location != pkm.Met_Location)
return false;
if (Level != lvl)
{
if (!(pkm.Format == 3 && EggEncounter && lvl == 0))
return false;
}
}
else if (Level > lvl)
{
return false;
}
if (Gender != -1 && Gender != pkm.Gender)
return false;
if (Form != pkm.AltForm && !SkipFormCheck && !Legal.IsFormChangeable(pkm, Species))
return false;
if (EggLocation == 60002 && Relearn.Length == 0 && pkm.RelearnMoves.Any(z => z != 0)) // gen7 eevee edge case
return false;
if (IVs != null && (Generation > 2 || pkm.Format <= 2)) // 1,2->7 regenerates IVs, only check if original IVs still exist
{
for (int i = 0; i < 6; i++)
{
if (IVs[i] != -1 && IVs[i] != pkm.IVs[i])
return false;
}
}
if (pkm is IContestStats s && s.IsContestBelow(this))
return false;
// Defer to EC/PID check
// if (e.Shiny != null && e.Shiny != pkm.IsShiny)
// continue;
// Defer ball check to later
// if (e.Gift && pkm.Ball != 4) // PokéBall
// continue;
return true;
}
}
}

View file

@ -200,5 +200,132 @@ namespace PKHeX.Core
pk.OT_TextVar = 40;
pk.OT_Feeling = 5;
}
public bool IsMatch(PKM pkm, int lvl)
{
if (IVs != null)
{
for (int i = 0; i < 6; i++)
{
if (IVs[i] != -1 && IVs[i] != pkm.GetIV(i))
return false;
}
}
if (this is EncounterTradePID p)
{
if (p.PID != pkm.EncryptionConstant)
return false;
if (Nature != Nature.Random && (int)Nature != pkm.Nature) // gen5 BW only
return false;
}
else
{
if (!Shiny.IsValid(pkm))
return false;
if (Nature != Nature.Random && (int)Nature != pkm.Nature)
return false;
if (Gender != -1 && Gender != pkm.Gender)
return false;
}
if (TID != pkm.TID)
return false;
if (SID != pkm.SID)
return false;
if (pkm.HasOriginalMetLocation)
{
var loc = Location > 0 ? Location : DefaultMetLocation[Generation - 1];
if (loc != pkm.Met_Location)
return false;
if (pkm.Format < 5)
{
if (Level > lvl)
return false;
}
else if (Level != lvl)
{
return false;
}
}
else if (Level > lvl)
{
return false;
}
if (CurrentLevel != -1 && CurrentLevel > pkm.CurrentLevel)
return false;
if (Form != pkm.AltForm && !Legal.IsFormChangeable(pkm, pkm.Species))
return false;
if (OTGender != -1 && OTGender != pkm.OT_Gender)
return false;
if (EggLocation != pkm.Egg_Location)
return false;
// if (z.Ability == 4 ^ pkm.AbilityNumber == 4) // defer to Ability
// countinue;
if (!Version.Contains((GameVersion)pkm.Version))
return false;
if (pkm is IContestStats s && s.IsContestBelow(this))
return false;
return true;
}
public bool IsMatchVC1(PKM pkm)
{
if (Level > pkm.CurrentLevel) // minimum required level
return false;
if (pkm.Format != 1 || !pkm.Gen1_NotTradeback)
return true;
// Even if the in game trade uses the tables with source pokemon allowing generation 2 games, the traded pokemon could be a non-tradeback pokemon
var rate = (pkm as PK1)?.Catch_Rate;
if (this is EncounterTradeCatchRate r)
{
if (rate != r.Catch_Rate)
return false;
}
else
{
if (Version == GameVersion.YW && rate != PersonalTable.Y[Species].CatchRate)
return false;
if (Version != GameVersion.YW && rate != PersonalTable.RB[Species].CatchRate)
return false;
}
return true;
}
public bool IsMatchVC2(PKM pkm)
{
if (Level > pkm.CurrentLevel) // minimum required level
return false;
if (TID != pkm.TID)
return false;
if (Gender >= 0 && Gender != pkm.Gender && pkm.Format <= 2)
return false;
if (IVs?.SequenceEqual(pkm.IVs) == false && pkm.Format <= 2)
return false;
if (pkm.Met_Location != 0 && pkm.Format == 2 && pkm.Met_Location != 126)
return false;
return IsValidTradeOT12(pkm);
}
private bool IsValidTradeOT12(PKM pkm)
{
var OT = pkm.OT_Name;
if (pkm.Japanese)
return TrainerNames[(int)LanguageID.Japanese] == OT;
if (pkm.Korean)
return TrainerNames[(int)LanguageID.Korean] == OT;
const int start = (int)LanguageID.English;
const int end = (int)LanguageID.Italian;
var index = Array.FindIndex(TrainerNames, start, end - start, w => w == OT);
return index >= 0;
}
}
}

View file

@ -0,0 +1,9 @@
namespace PKHeX.Core
{
public enum EncounterMatchRating
{
None,
Match,
Deferred,
}
}

View file

@ -85,132 +85,15 @@ namespace PKHeX.Core
private static bool GetIsMatchStatic(PKM pkm, EncounterStatic e, int lvl)
{
if (e.Nature != Nature.Random && pkm.Nature != (int)e.Nature)
if (!e.IsMatch(pkm, lvl))
return false;
if (pkm.WasEgg != e.EggEncounter && pkm.Egg_Location == 0 && pkm.Format > 3 && pkm.GenNumber > 3 && !pkm.IsEgg)
return false;
if (e is EncounterStaticPID p && p.PID != pkm.PID)
return false;
if (pkm.Gen3 && e.EggLocation != 0) // Gen3 Egg
{
if (pkm.Format == 3 && pkm.IsEgg && e.EggLocation != pkm.Met_Location)
return false;
}
else if (pkm.VC || (pkm.GenNumber <= 2 && e.EggLocation != 0)) // Gen2 Egg
{
if (pkm.Format <= 2)
{
if (pkm.IsEgg)
{
if (pkm.Met_Location != 0 && pkm.Met_Level != 0)
return false;
}
else
{
switch (pkm.Met_Level)
{
case 0 when pkm.Met_Location != 0:
return false;
case 1 when pkm.Met_Location == 0:
return false;
default:
if (pkm.Met_Location == 0 && pkm.Met_Level != 0)
return false;
break;
}
}
if (pkm.Met_Level == 1)
lvl = 5; // met @ 1, hatch @ 5.
}
}
else if (e.EggLocation != pkm.Egg_Location)
{
if (pkm.IsEgg) // unhatched
{
if (e.EggLocation != pkm.Met_Location)
return false;
if (pkm.Egg_Location != 0)
return false;
}
else if (pkm.Gen4)
{
if (pkm.Egg_Location != 2002) // Link Trade
{
// check Pt/HGSS data
if (pkm.Format <= 4)
return false; // must match
if (e.EggLocation >= 3000 || e.EggLocation <= 2010) // non-Pt/HGSS egg gift
return false;
// transferring 4->5 clears pt/hgss location value and keeps Faraway Place
if (pkm.Egg_Location != 3002) // Faraway Place
return false;
}
}
else
{
if (pkm.Egg_Location != 30002) // Link Trade
return false;
}
}
else if (e.EggLocation != 0 && pkm.Gen4)
{
// Check the inverse scenario for 4->5 eggs
if (e.EggLocation < 3000 && e.EggLocation > 2010) // Pt/HGSS egg gift
{
if (pkm.Format > 4)
return false; // locations match when it shouldn't
}
}
if (pkm.HasOriginalMetLocation)
{
if (!e.EggEncounter && e.Location != 0 && e.Location != pkm.Met_Location)
return false;
if (e.Level != lvl)
{
if (!(pkm.Format == 3 && e.EggEncounter && lvl == 0))
return false;
}
}
else if (e.Level > lvl)
{
return false;
}
if (e.Gender != -1 && e.Gender != pkm.Gender)
return false;
if (e.Form != pkm.AltForm && !e.SkipFormCheck && !IsFormChangeable(pkm, e.Species))
return false;
if (e.EggLocation == 60002 && e.Relearn.Length == 0 && pkm.RelearnMoves.Any(z => z != 0)) // gen7 eevee edge case
return false;
if (e.IVs != null && (e.Generation > 2 || pkm.Format <= 2)) // 1,2->7 regenerates IVs, only check if original IVs still exist
{
for (int i = 0; i < 6; i++)
{
if (e.IVs[i] != -1 && e.IVs[i] != pkm.IVs[i])
return false;
}
}
if (pkm is IContestStats s && s.IsContestBelow(e))
return false;
// Defer to EC/PID check
// if (e.Shiny != null && e.Shiny != pkm.IsShiny)
// continue;
// Defer ball check to later
// if (e.Gift && pkm.Ball != 4) // PokéBall
// continue;
if (pkm is PK1 pk1 && pk1.Gen1_NotTradeback && !IsValidCatchRatePK1(e, pk1))
return false;
if (!ParseSettings.AllowGBCartEra && GameVersion.GBCartEraOnly.Contains(e.Version))
return false;
return true;
}

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using static PKHeX.Core.Legal;
@ -39,7 +38,7 @@ namespace PKHeX.Core
return Enumerable.Empty<EncounterTrade>();
var poss = GetPossibleNonVC(pkm, p, gameSource);
return poss.Where(z => IsEncounterTradeValid(pkm, z, lvl));
return poss.Where(z => z.IsMatch(pkm, lvl));
}
private static IEnumerable<EncounterTrade> GetPossibleNonVC(PKM pkm, IReadOnlyList<DexLevel> p, GameVersion gameSource = GameVersion.Any)
@ -86,138 +85,12 @@ namespace PKHeX.Core
{
var poss = GetPossibleVC(p, gameSource);
if (gameSource == GameVersion.RBY)
return poss.Where(z => GetIsValidTradeVC1(pkm, z));
return poss.Where(z => GetIsValidTradeVC2(pkm, z));
}
private static bool GetIsValidTradeVC1(PKM pkm, EncounterTrade z)
{
if (z.Level > pkm.CurrentLevel) // minimum required level
return false;
if (pkm.Format != 1 || !pkm.Gen1_NotTradeback)
return true;
// Even if the in game trade uses the tables with source pokemon allowing generation 2 games, the traded pokemon could be a non-tradeback pokemon
var rate = (pkm as PK1)?.Catch_Rate;
if (z is EncounterTradeCatchRate r)
{
if (rate != r.Catch_Rate)
return false;
}
else
{
if (z.Version == GameVersion.YW && rate != PersonalTable.Y[z.Species].CatchRate)
return false;
if (z.Version != GameVersion.YW && rate != PersonalTable.RB[z.Species].CatchRate)
return false;
}
return true;
}
private static bool GetIsValidTradeVC2(PKM pkm, EncounterTrade z)
{
if (z.Level > pkm.CurrentLevel) // minimum required level
return false;
if (z.TID != pkm.TID)
return false;
if (z.Gender >= 0 && z.Gender != pkm.Gender && pkm.Format <= 2)
return false;
if (z.IVs?.SequenceEqual(pkm.IVs) == false && pkm.Format <= 2)
return false;
if (pkm.Met_Location != 0 && pkm.Format == 2 && pkm.Met_Location != 126)
return false;
return IsValidTradeOT12(z, pkm);
}
private static bool IsValidTradeOT12(EncounterTrade z, PKM pkm)
{
var OT = pkm.OT_Name;
if (pkm.Japanese)
return z.TrainerNames[(int) LanguageID.Japanese] == OT;
if (pkm.Korean)
return z.TrainerNames[(int)LanguageID.Korean] == OT;
const int start = (int) LanguageID.English;
const int end = (int) LanguageID.Italian;
var index = Array.FindIndex(z.TrainerNames, start, end - start, w => w == OT);
return index >= 0;
return poss.Where(z => z.IsMatchVC1(pkm));
return poss.Where(z => z.IsMatchVC2(pkm));
}
private static bool GetIsFromGB(PKM pkm) => pkm.VC || pkm.Format <= 2;
private static bool IsEncounterTradeValid(PKM pkm, EncounterTrade z, int lvl)
{
if (z.IVs != null)
{
for (int i = 0; i < 6; i++)
{
if (z.IVs[i] != -1 && z.IVs[i] != pkm.IVs[i])
return false;
}
}
if (z is EncounterTradePID p)
{
if (p.PID != pkm.EncryptionConstant)
return false;
if (z.Nature != Nature.Random && (int)z.Nature != pkm.Nature) // gen5 BW only
return false;
}
else
{
if (!z.Shiny.IsValid(pkm))
return false;
if (z.Nature != Nature.Random && (int)z.Nature != pkm.Nature)
return false;
if (z.Gender != -1 && z.Gender != pkm.Gender)
return false;
}
if (z.TID != pkm.TID)
return false;
if (z.SID != pkm.SID)
return false;
if (pkm.HasOriginalMetLocation)
{
var loc = z.Location > 0 ? z.Location : EncounterTrade.DefaultMetLocation[z.Generation - 1];
if (loc != pkm.Met_Location)
return false;
if (pkm.Format < 5)
{
if (z.Level > lvl)
return false;
}
else if (z.Level != lvl)
{
return false;
}
}
else if (z.Level > lvl)
{
return false;
}
if (z.CurrentLevel != -1 && z.CurrentLevel > pkm.CurrentLevel)
return false;
if (z.Form != pkm.AltForm && !IsFormChangeable(pkm, pkm.Species))
return false;
if (z.OTGender != -1 && z.OTGender != pkm.OT_Gender)
return false;
if (z.EggLocation != pkm.Egg_Location)
return false;
// if (z.Ability == 4 ^ pkm.AbilityNumber == 4) // defer to Ability
// countinue;
if (!z.Version.Contains((GameVersion)pkm.Version))
return false;
if (pkm is IContestStats s && s.IsContestBelow(z))
return false;
return true;
}
private static int IsNotTrade(PKM pkm)
{
int lang = pkm.Language;

View file

@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using static PKHeX.Core.Legal;
using static PKHeX.Core.EncounterEvent;
namespace PKHeX.Core
@ -9,7 +8,7 @@ namespace PKHeX.Core
{
public static IEnumerable<MysteryGift> GetPossible(PKM pkm)
{
int maxSpecies = GetMaxSpeciesOrigin(pkm.Format);
int maxSpecies = Legal.GetMaxSpeciesOrigin(pkm.Format);
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxSpecies);
return GetPossible(pkm, vs);
}
@ -22,18 +21,14 @@ namespace PKHeX.Core
public static IEnumerable<MysteryGift> GetValidGifts(PKM pkm)
{
switch (pkm.GenNumber)
{
case 3: return GetMatchingWC3(pkm, MGDB_G3);
case 4: return GetMatchingPCD(pkm, MGDB_G4);
case 5: return GetMatchingPGF(pkm, MGDB_G5);
case 6: return GetMatchingWC6(pkm, MGDB_G6);
case 7:
return pkm.GG
? (IEnumerable<MysteryGift>) GetMatchingWB7(pkm, MGDB_G7GG)
: GetMatchingWC7(pkm, MGDB_G7);
default: return Enumerable.Empty<MysteryGift>();
}
int gen = pkm.GenNumber;
if (pkm.IsEgg && pkm.Format != gen) // transferred
return Enumerable.Empty<MysteryGift>();
if (gen == 4) // check for manaphy gift
return GetMatchingPCD(pkm, MGDB_G4);
var table = GetTable(pkm.GenNumber, pkm);
return GetMatchingGifts(pkm, table);
}
private static IEnumerable<MysteryGift> GetTable(int generation, PKM pkm)
@ -45,487 +40,49 @@ namespace PKHeX.Core
case 5: return MGDB_G5;
case 6: return MGDB_G6;
case 7:
return pkm.GG ? (IEnumerable<MysteryGift>) MGDB_G7GG : MGDB_G7;
if (pkm.GG)
return MGDB_G7GG;
return MGDB_G7;
default: return Enumerable.Empty<MysteryGift>();
}
}
private static IEnumerable<WC3> GetMatchingWC3(PKM pkm, IEnumerable<WC3> DB)
{
var validWC3 = new List<WC3>();
var vs = EvolutionChain.GetValidPreEvolutions(pkm, MaxSpeciesID_3);
var enumerable = DB.Where(wc => vs.Any(dl => dl.Species == wc.Species));
foreach (var wc in enumerable)
{
if (!GetIsMatchWC3(pkm, wc))
continue;
if (wc.Species == pkm.Species) // best match
yield return wc;
else
validWC3.Add(wc);
}
foreach (var z in validWC3)
yield return z;
}
private static IEnumerable<MysteryGift> GetMatchingPCD(PKM pkm, IEnumerable<PCD> DB)
{
if (pkm.IsEgg && pkm.Format != 4) // transferred
yield break;
if (IsRangerManaphy(pkm))
{
if (pkm.Language != (int)LanguageID.Korean) // never korean
yield return RangerManaphy;
yield return RangerManaphy;
yield break;
}
var deferred = new List<PCD>();
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
var enumerable = DB.Where(wc => vs.Any(dl => dl.Species == wc.Species));
foreach (var mg in enumerable)
{
var wc = mg.Gift.PK;
if (!GetIsMatchPCD(pkm, wc, vs))
continue;
foreach (var g in GetMatchingGifts(pkm, DB))
yield return g;
}
bool receivable = mg.CanBeReceivedBy(pkm.Version);
if (wc.Species == pkm.Species && receivable) // best match
private static IEnumerable<MysteryGift> GetMatchingGifts(PKM pkm, IEnumerable<MysteryGift> DB)
{
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
return GetMatchingGifts(pkm, DB, vs);
}
private static IEnumerable<MysteryGift> GetMatchingGifts(PKM pkm, IEnumerable<MysteryGift> DB, IReadOnlyList<DexLevel> vs)
{
var deferred = new List<MysteryGift>();
var gifts = DB.Where(wc => vs.Any(dl => dl.Species == wc.Species));
foreach (var mg in gifts)
{
var result = mg.IsMatch(pkm, vs);
if (result == EncounterMatchRating.None)
continue;
if (result == EncounterMatchRating.Match)
yield return mg;
else
else if (result == EncounterMatchRating.Deferred)
deferred.Add(mg);
}
foreach (var z in deferred)
yield return z;
}
private static IEnumerable<PGF> GetMatchingPGF(PKM pkm, IEnumerable<PGF> DB)
{
var deferred = new List<PGF>();
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
var enumerable = DB.Where(wc => vs.Any(dl => dl.Species == wc.Species));
foreach (var wc in enumerable)
{
if (!GetIsMatchPGF(pkm, wc, vs))
continue;
if (wc.Species == pkm.Species) // best match
yield return wc;
else
deferred.Add(wc);
}
foreach (var z in deferred)
yield return z;
}
private static IEnumerable<WC6> GetMatchingWC6(PKM pkm, IEnumerable<WC6> DB)
{
var deferred = new List<WC6>();
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
var enumerable = DB.Where(wc => vs.Any(dl => dl.Species == wc.Species));
foreach (var wc in enumerable)
{
if (!GetIsMatchWC6(pkm, wc, vs))
continue;
if (GetIsDeferredWC6(pkm, wc))
deferred.Add(wc);
else
yield return wc;
}
foreach (var z in deferred)
yield return z;
}
private static IEnumerable<WB7> GetMatchingWB7(PKM pkm, IEnumerable<WB7> DB)
{
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
var enumerable = DB.Where(wc => vs.Any(dl => dl.Species == wc.Species));
foreach (var wc in enumerable)
{
if (!GetIsMatchWB7(pkm, wc, vs))
continue;
if (wc.PIDType == 0 && pkm.PID != wc.PID)
continue;
yield return wc;
}
}
private static IEnumerable<WC7> GetMatchingWC7(PKM pkm, IEnumerable<WC7> DB)
{
var deferred = new List<WC7>();
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
var enumerable = DB.Where(wc => vs.Any(dl => dl.Species == wc.Species));
foreach (var wc in enumerable)
{
if (!GetIsMatchWC7(pkm, wc, vs))
continue;
if ((pkm.SID << 16 | pkm.TID) == 0x79F57B49) // Greninja WC has variant PID and can arrive @ 36 or 37
{
if (!pkm.IsShiny)
deferred.Add(wc);
continue;
}
if (wc.PIDType == 0 && pkm.PID != wc.PID)
continue;
if (GetIsDeferredWC7(pkm, wc))
deferred.Add(wc);
else
yield return wc;
}
foreach (var z in deferred)
yield return z;
}
private static bool GetIsValidOTMattleHoOh(string wc, string ot, bool ck3)
{
if (ck3 && ot.Length == 10)
return wc == ot;
return ot.Length == 7 && wc.StartsWith(ot);
}
private static bool GetIsMatchWC3(PKM pkm, WC3 wc)
{
// Gen3 Version MUST match.
if (wc.Version != 0 && !(wc.Version).Contains((GameVersion)pkm.Version))
return false;
bool hatchedEgg = wc.IsEgg && !pkm.IsEgg;
if (!hatchedEgg)
{
if (wc.SID != -1 && wc.SID != pkm.SID) return false;
if (wc.TID != -1 && wc.TID != pkm.TID) return false;
if (wc.OT_Gender < 3 && wc.OT_Gender != pkm.OT_Gender) return false;
var wcOT = wc.OT_Name;
if (wcOT != null)
{
if (wcOT.Length > 7) // Colosseum Mattle Ho-Oh
{
if (!GetIsValidOTMattleHoOh(wcOT, pkm.OT_Name, pkm is CK3))
return false;
}
else if (wcOT != pkm.OT_Name)
{
return false;
}
}
}
if (wc.Language != -1 && wc.Language != pkm.Language) return false;
if (wc.Ball != pkm.Ball) return false;
if (wc.Fateful != pkm.FatefulEncounter)
{
// XD Gifts only at level 20 get flagged after transfer
if (wc.Version == GameVersion.XD != pkm is XK3)
return false;
}
if (pkm.IsNative)
{
if (hatchedEgg)
return true; // defer egg specific checks to later.
if (wc.Met_Level != pkm.Met_Level)
return false;
if (wc.Location != pkm.Met_Location)
return false;
}
else
{
if (pkm.IsEgg)
return false;
if (wc.Level > pkm.Met_Level)
return false;
}
return true;
}
private static bool GetIsMatchPCD(PKM pkm, PK4 wc, IEnumerable<DexLevel> vs)
{
if (!wc.IsEgg)
{
if (wc.TID != pkm.TID) return false;
if (wc.SID != pkm.SID) return false;
if (wc.OT_Name != pkm.OT_Name) return false;
if (wc.OT_Gender != pkm.OT_Gender) return false;
if (wc.Language != 0 && wc.Language != pkm.Language) return false;
if (pkm.Format != 4) // transferred
{
// met location: deferred to general transfer check
if (wc.CurrentLevel > pkm.Met_Level) return false;
}
else
{
if (wc.Egg_Location + 3000 != pkm.Met_Location) return false;
if (wc.CurrentLevel != pkm.Met_Level) return false;
}
}
else // Egg
{
if (wc.Egg_Location + 3000 != pkm.Egg_Location && pkm.Egg_Location != 2002) // traded
return false;
if (wc.CurrentLevel != pkm.Met_Level)
return false;
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
if (wc.AltForm != pkm.AltForm && vs.All(dl => !IsFormChangeable(pkm, dl.Species)))
return false;
if (wc.Ball != pkm.Ball) return false;
if (wc.OT_Gender < 3 && wc.OT_Gender != pkm.OT_Gender) return false;
if (wc.PID == 1 && pkm.IsShiny) return false;
if (wc.Gender != 3 && wc.Gender != pkm.Gender) return false;
if (pkm is IContestStats s && s.IsContestBelow(wc))
return false;
return true;
}
private static bool GetIsMatchPGF(PKM pkm, PGF wc, IEnumerable<DexLevel> vs)
{
if (!wc.IsEgg)
{
if (wc.SID != pkm.SID) return false;
if (wc.TID != pkm.TID) return false;
if (wc.OT_Name != pkm.OT_Name) return false;
if (wc.OTGender < 3 && wc.OTGender != pkm.OT_Gender) return false;
if (wc.PID != 0 && pkm.PID != wc.PID) return false;
if (wc.PIDType == 0 && pkm.IsShiny) return false;
if (wc.PIDType == 2 && !pkm.IsShiny) return false;
if (wc.OriginGame != 0 && wc.OriginGame != pkm.Version) return false;
if (wc.Language != 0 && wc.Language != pkm.Language) return false;
if (wc.EggLocation != pkm.Egg_Location) return false;
if (wc.MetLocation != pkm.Met_Location) return false;
}
else
{
if (wc.EggLocation != pkm.Egg_Location) // traded
{
if (pkm.Egg_Location != 30003)
return false;
}
else if (wc.PIDType == 0 && pkm.IsShiny)
{
return false; // can't be traded away for unshiny
}
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
if (wc.Form != pkm.AltForm && vs.All(dl => !IsFormChangeable(pkm, dl.Species))) return false;
if (wc.Level != pkm.Met_Level) return false;
if (wc.Ball != pkm.Ball) return false;
if (wc.Nature != -1 && wc.Nature != pkm.Nature) return false;
if (wc.Gender != 2 && wc.Gender != pkm.Gender) return false;
if (pkm is IContestStats s && s.IsContestBelow(wc))
return false;
return true;
}
private static bool GetIsMatchWC6(PKM pkm, WC6 wc, IEnumerable<DexLevel> vs)
{
if (pkm.Egg_Location == 0) // Not Egg
{
if (wc.CardID != pkm.SID) return false;
if (wc.TID != pkm.TID) return false;
if (wc.OT_Name != pkm.OT_Name) return false;
if (wc.OTGender != pkm.OT_Gender) return false;
if (wc.PIDType == Shiny.FixedValue && pkm.PID != wc.PID) return false;
if (!wc.PIDType.IsValid(pkm)) return false;
if (wc.OriginGame != 0 && wc.OriginGame != pkm.Version) return false;
if (wc.EncryptionConstant != 0 && wc.EncryptionConstant != pkm.EncryptionConstant) return false;
if (wc.Language != 0 && wc.Language != pkm.Language) return false;
}
if (wc.Form != pkm.AltForm && vs.All(dl => !IsFormChangeable(pkm, dl.Species))) return false;
if (wc.IsEgg)
{
if (wc.EggLocation != pkm.Egg_Location) // traded
{
if (pkm.Egg_Location != 30002)
return false;
}
else if (wc.PIDType == 0 && pkm.IsShiny)
{
return false; // can't be traded away for unshiny
}
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
else
{
if (wc.EggLocation != pkm.Egg_Location) return false;
if (wc.MetLocation != pkm.Met_Location) return false;
}
if (wc.Level != pkm.Met_Level) return false;
if (wc.Ball != pkm.Ball) return false;
if (wc.OTGender < 3 && wc.OTGender != pkm.OT_Gender) return false;
if (wc.Nature != -1 && wc.Nature != pkm.Nature) return false;
if (wc.Gender != 3 && wc.Gender != pkm.Gender) return false;
if (pkm is IContestStats s && s.IsContestBelow(wc))
return false;
return true;
}
private static bool GetIsMatchWB7(PKM pkm, WB7 wc, IEnumerable<DexLevel> vs)
{
if (pkm.Egg_Location == 0) // Not Egg
{
if (wc.OTGender != 3)
{
if (wc.SID != pkm.SID) return false;
if (wc.TID != pkm.TID) return false;
if (wc.OTGender != pkm.OT_Gender) return false;
}
var OT = wc.GetOT(pkm.Language);
if (!string.IsNullOrEmpty(OT) && OT != pkm.OT_Name) return false;
if (wc.OriginGame != 0 && wc.OriginGame != pkm.Version) return false;
if (wc.EncryptionConstant != 0 && wc.EncryptionConstant != pkm.EncryptionConstant) return false;
}
if (wc.Form != pkm.AltForm && vs.All(dl => !IsFormChangeable(pkm, dl.Species)))
return false;
if (wc.IsEgg)
{
if (wc.EggLocation != pkm.Egg_Location) // traded
{
if (pkm.Egg_Location != 30002)
return false;
}
else if (wc.PIDType == 0 && pkm.IsShiny)
{
return false; // can't be traded away for unshiny
}
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
else
{
if (!wc.PIDType.IsValid(pkm)) return false;
if (wc.EggLocation != pkm.Egg_Location) return false;
if (wc.MetLocation != pkm.Met_Location) return false;
}
if (wc.MetLevel != pkm.Met_Level) return false;
if (wc.Ball != pkm.Ball) return false;
if (wc.OTGender < 3 && wc.OTGender != pkm.OT_Gender) return false;
if (wc.Nature != -1 && wc.Nature != pkm.Nature) return false;
if (wc.Gender != 3 && wc.Gender != pkm.Gender) return false;
if (pkm is IAwakened s && s.IsAwakeningBelow(wc))
return false;
return true;
}
private static bool GetIsMatchWC7(PKM pkm, WC7 wc, IEnumerable<DexLevel> vs)
{
if (pkm.Egg_Location == 0) // Not Egg
{
if (wc.OTGender != 3)
{
if (wc.SID != pkm.SID) return false;
if (wc.TID != pkm.TID) return false;
if (wc.OTGender != pkm.OT_Gender) return false;
}
if (!string.IsNullOrEmpty(wc.OT_Name) && wc.OT_Name != pkm.OT_Name) return false;
if (wc.OriginGame != 0 && wc.OriginGame != pkm.Version) return false;
if (wc.EncryptionConstant != 0 && wc.EncryptionConstant != pkm.EncryptionConstant) return false;
if (wc.Language != 0 && wc.Language != pkm.Language) return false;
}
if (wc.Form != pkm.AltForm && vs.All(dl => !IsFormChangeable(pkm, dl.Species)))
{
if (wc.Species == 744 && wc.Form == 1 && pkm.Species == 745 && pkm.AltForm == 2)
{
// Rockruff gift edge case; has altform 1 then evolves to altform 2
}
else
{
return false;
}
}
if (wc.IsEgg)
{
if (wc.EggLocation != pkm.Egg_Location) // traded
{
if (pkm.Egg_Location != 30002)
return false;
}
else if (wc.PIDType == 0 && pkm.IsShiny)
{
return false; // can't be traded away for unshiny
}
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
else
{
if (!wc.PIDType.IsValid(pkm)) return false;
if (wc.EggLocation != pkm.Egg_Location) return false;
if (wc.MetLocation != pkm.Met_Location) return false;
}
if (wc.MetLevel != pkm.Met_Level) return false;
if (wc.Ball != pkm.Ball) return false;
if (wc.OTGender < 3 && wc.OTGender != pkm.OT_Gender) return false;
if (wc.Nature != -1 && wc.Nature != pkm.Nature) return false;
if (wc.Gender != 3 && wc.Gender != pkm.Gender) return false;
if (pkm is IContestStats s && s.IsContestBelow(wc))
return false;
switch (wc.CardID)
{
case 2046: // Ash Greninja
return pkm.SM; // not USUM
}
return true;
}
private static bool GetIsDeferredWC6(PKM pkm, WC6 wc)
{
switch (wc.CardID)
{
case 0525 when wc.IV_HP == 0xFE: // Diancie was distributed with no IV enforcement & 3IVs
case 0504 when wc.RibbonClassic != ((IRibbonSetEvent4)pkm).RibbonClassic: // magmar with/without classic
return true;
}
if (wc.RestrictLanguage != 0 && wc.RestrictLanguage != pkm.Language)
return true;
if (!wc.CanBeReceivedByVersion(pkm.Version))
return true;
return wc.Species != pkm.Species;
}
private static bool GetIsDeferredWC7(PKM pkm, WC7 wc)
{
if (wc.RestrictLanguage != 0 && wc.RestrictLanguage != pkm.Language)
return true;
if (!wc.CanBeReceivedByVersion(pkm.Version))
return true;
return wc.Species != pkm.Species;
}
// Utility
private static readonly PGT RangerManaphy = new PGT {Data = {[0] = 7, [8] = 1}};
@ -538,6 +95,10 @@ namespace PKHeX.Core
return egg == linkegg || egg == ranger;
if (egg != ranger)
return false;
if (pkm.Language == (int)LanguageID.Korean) // never korean
return false;
var met = pkm.Met_Location;
return met == linkegg || met == 0;
}

View file

@ -80,9 +80,22 @@ namespace PKHeX.Core
public string Extension => GetType().Name.ToLower();
public string FileName => $"{CardHeader}.{Extension}";
public byte[] Data { get; set; }
public abstract PKM ConvertToPKM(ITrainerInfo SAV);
public abstract int Format { get; }
public abstract PKM ConvertToPKM(ITrainerInfo SAV);
protected abstract bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs);
protected abstract bool IsMatchDeferred(PKM pkm);
public EncounterMatchRating IsMatch(PKM pkm, IEnumerable<DexLevel> vs)
{
if (!IsMatchExact(pkm, vs))
return EncounterMatchRating.None;
if (IsMatchDeferred(pkm))
return EncounterMatchRating.Deferred;
return EncounterMatchRating.Match;
}
/// <summary>
/// Creates a deep copy of the <see cref="MysteryGift"/> object data.
/// </summary>

View file

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
{
@ -130,5 +132,58 @@ namespace PKHeX.Core
}
public bool CanBeReceivedBy(int pkmVersion) => (CardCompatibility >> pkmVersion & 1) == 1;
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)
{
var wc = Gift.PK;
if (!wc.IsEgg)
{
if (wc.TID != pkm.TID) return false;
if (wc.SID != pkm.SID) return false;
if (wc.OT_Name != pkm.OT_Name) return false;
if (wc.OT_Gender != pkm.OT_Gender) return false;
if (wc.Language != 0 && wc.Language != pkm.Language) return false;
if (pkm.Format != 4) // transferred
{
// met location: deferred to general transfer check
if (wc.CurrentLevel > pkm.Met_Level) return false;
}
else
{
if (wc.Egg_Location + 3000 != pkm.Met_Location) return false;
if (wc.CurrentLevel != pkm.Met_Level) return false;
}
}
else // Egg
{
if (wc.Egg_Location + 3000 != pkm.Egg_Location && pkm.Egg_Location != 2002) // traded
return false;
if (wc.CurrentLevel != pkm.Met_Level)
return false;
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
if (wc.AltForm != pkm.AltForm && vs.All(dl => !Legal.IsFormChangeable(pkm, dl.Species)))
return false;
if (wc.Ball != pkm.Ball) return false;
if (wc.OT_Gender < 3 && wc.OT_Gender != pkm.OT_Gender) return false;
if (wc.PID == 1 && pkm.IsShiny) return false;
if (wc.Gender != 3 && wc.Gender != pkm.Gender) return false;
if (pkm is IContestStats s && s.IsContestBelow(wc))
return false;
return true;
}
protected override bool IsMatchDeferred(PKM pkm)
{
if (!CanBeReceivedBy(pkm.Version))
return false;
return Species != pkm.Species;
}
}
}

View file

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PKHeX.Core
@ -311,5 +313,53 @@ namespace PKHeX.Core
pk.RefreshChecksum();
return pk;
}
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)
{
if (!IsEgg)
{
if (SID != pkm.SID) return false;
if (TID != pkm.TID) return false;
if (OT_Name != pkm.OT_Name) return false;
if (OTGender < 3 && OTGender != pkm.OT_Gender) return false;
if (PID != 0 && pkm.PID != PID) return false;
if (PIDType == 0 && pkm.IsShiny) return false;
if (PIDType == 2 && !pkm.IsShiny) return false;
if (OriginGame != 0 && OriginGame != pkm.Version) return false;
if (Language != 0 && Language != pkm.Language) return false;
if (EggLocation != pkm.Egg_Location) return false;
if (MetLocation != pkm.Met_Location) return false;
}
else
{
if (EggLocation != pkm.Egg_Location) // traded
{
if (pkm.Egg_Location != 30003)
return false;
}
else if (PIDType == 0 && pkm.IsShiny)
{
return false; // can't be traded away for unshiny
}
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
if (Form != pkm.AltForm && vs.All(dl => !Legal.IsFormChangeable(pkm, dl.Species))) return false;
if (Level != pkm.Met_Level) return false;
if (Ball != pkm.Ball) return false;
if (Nature != -1 && Nature != pkm.Nature) return false;
if (Gender != 2 && Gender != pkm.Gender) return false;
if (pkm is IContestStats s && s.IsContestBelow(this))
return false;
return true;
}
protected override bool IsMatchDeferred(PKM pkm) => false;
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@ -221,5 +222,8 @@ namespace PKHeX.Core
pk4.PID = RNG.ARNG.Next(pk4.PID);
return seed;
}
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs) => false;
protected override bool IsMatchDeferred(PKM pkm) => false;
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -456,5 +457,63 @@ namespace PKHeX.Core
pk.RefreshChecksum();
return pk;
}
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)
{
if (pkm.Egg_Location == 0) // Not Egg
{
if (OTGender != 3)
{
if (SID != pkm.SID) return false;
if (TID != pkm.TID) return false;
if (OTGender != pkm.OT_Gender) return false;
}
var OT = GetOT(pkm.Language);
if (!string.IsNullOrEmpty(OT) && OT != pkm.OT_Name) return false;
if (OriginGame != 0 && OriginGame != pkm.Version) return false;
if (EncryptionConstant != 0 && EncryptionConstant != pkm.EncryptionConstant) return false;
}
if (Form != pkm.AltForm && vs.All(dl => !Legal.IsFormChangeable(pkm, dl.Species)))
return false;
if (IsEgg)
{
if (EggLocation != pkm.Egg_Location) // traded
{
if (pkm.Egg_Location != 30002)
return false;
}
else if (PIDType == 0 && pkm.IsShiny)
{
return false; // can't be traded away for unshiny
}
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
else
{
if (!PIDType.IsValid(pkm)) return false;
if (EggLocation != pkm.Egg_Location) return false;
if (MetLocation != pkm.Met_Location) return false;
}
if (MetLevel != pkm.Met_Level) return false;
if (Ball != pkm.Ball) return false;
if (OTGender < 3 && OTGender != pkm.OT_Gender) return false;
if (Nature != -1 && Nature != pkm.Nature) return false;
if (Gender != 3 && Gender != pkm.Gender) return false;
if (pkm is IAwakened s && s.IsAwakeningBelow(this))
return false;
return true;
}
protected override bool IsMatchDeferred(PKM pkm)
{
return pkm.Species == Species;
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
namespace PKHeX.Core
{
@ -39,6 +40,13 @@ namespace PKHeX.Core
public override int Ball { get; set; } = 4;
public override bool IsShiny => Shiny == Shiny.Always;
public bool RibbonEarth { get; set; }
public bool RibbonNational { get; set; }
public bool RibbonCountry { get; set; }
public bool RibbonChampionBattle { get; set; }
public bool RibbonChampionRegional { get; set; }
public bool RibbonChampionNational { get; set; }
// Description
public override string CardTitle { get; set; } = "Generation 3 Event";
public override string CardHeader => CardTitle;
@ -204,11 +212,71 @@ namespace PKHeX.Core
}
}
public bool RibbonEarth { get; set; }
public bool RibbonNational { get; set; }
public bool RibbonCountry { get; set; }
public bool RibbonChampionBattle { get; set; }
public bool RibbonChampionRegional { get; set; }
public bool RibbonChampionNational { get; set; }
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)
{
// Gen3 Version MUST match.
if (Version != 0 && !(Version).Contains((GameVersion)pkm.Version))
return false;
bool hatchedEgg = IsEgg && !pkm.IsEgg;
if (!hatchedEgg)
{
if (SID != -1 && SID != pkm.SID) return false;
if (TID != -1 && TID != pkm.TID) return false;
if (OT_Gender < 3 && OT_Gender != pkm.OT_Gender) return false;
var wcOT = OT_Name;
if (wcOT != null)
{
if (wcOT.Length > 7) // Colosseum Mattle Ho-Oh
{
if (!GetIsValidOTMattleHoOh(wcOT, pkm.OT_Name, pkm is CK3))
return false;
}
else if (wcOT != pkm.OT_Name)
{
return false;
}
}
}
if (Language != -1 && Language != pkm.Language) return false;
if (Ball != pkm.Ball) return false;
if (Fateful != pkm.FatefulEncounter)
{
// XD Gifts only at level 20 get flagged after transfer
if (Version == GameVersion.XD != pkm is XK3)
return false;
}
if (pkm.IsNative)
{
if (hatchedEgg)
return true; // defer egg specific checks to later.
if (Met_Level != pkm.Met_Level)
return false;
if (Location != pkm.Met_Location)
return false;
}
else
{
if (pkm.IsEgg)
return false;
if (Level > pkm.Met_Level)
return false;
}
return true;
}
private static bool GetIsValidOTMattleHoOh(string wc, string ot, bool ck3)
{
if (ck3 && ot.Length == 10)
return wc == ot;
return ot.Length == 7 && wc.StartsWith(ot);
}
protected override bool IsMatchDeferred(PKM pkm)
{
return Species != pkm.Species;
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -451,5 +452,69 @@ namespace PKHeX.Core
pk.RefreshChecksum();
return pk;
}
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)
{
if (pkm.Egg_Location == 0) // Not Egg
{
if (CardID != pkm.SID) return false;
if (TID != pkm.TID) return false;
if (OT_Name != pkm.OT_Name) return false;
if (OTGender != pkm.OT_Gender) return false;
if (PIDType == Shiny.FixedValue && pkm.PID != PID) return false;
if (!PIDType.IsValid(pkm)) return false;
if (OriginGame != 0 && OriginGame != pkm.Version) return false;
if (EncryptionConstant != 0 && EncryptionConstant != pkm.EncryptionConstant) return false;
if (Language != 0 && Language != pkm.Language) return false;
}
if (Form != pkm.AltForm && vs.All(dl => !Legal.IsFormChangeable(pkm, dl.Species))) return false;
if (IsEgg)
{
if (EggLocation != pkm.Egg_Location) // traded
{
if (pkm.Egg_Location != 30002)
return false;
}
else if (PIDType == 0 && pkm.IsShiny)
{
return false; // can't be traded away for unshiny
}
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
else
{
if (EggLocation != pkm.Egg_Location) return false;
if (MetLocation != pkm.Met_Location) return false;
}
if (Level != pkm.Met_Level) return false;
if (Ball != pkm.Ball) return false;
if (OTGender < 3 && OTGender != pkm.OT_Gender) return false;
if (Nature != -1 && Nature != pkm.Nature) return false;
if (Gender != 3 && Gender != pkm.Gender) return false;
if (pkm is IContestStats s && s.IsContestBelow(this))
return false;
return true;
}
protected override bool IsMatchDeferred(PKM pkm)
{
switch (CardID)
{
case 0525 when IV_HP == 0xFE: // Diancie was distributed with no IV enforcement & 3IVs
case 0504 when RibbonClassic != ((IRibbonSetEvent4)pkm).RibbonClassic: // magmar with/without classic
return true;
}
if (RestrictLanguage != 0 && RestrictLanguage != pkm.Language)
return true;
if (!CanBeReceivedByVersion(pkm.Version))
return true;
return Species != pkm.Species;
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -487,5 +488,80 @@ namespace PKHeX.Core
{
return CardID == 2046 && (pkm.SID << 16 | pkm.TID) == 0x79F57B49;
}
protected override bool IsMatchExact(PKM pkm, IEnumerable<DexLevel> vs)
{
if (pkm.Egg_Location == 0) // Not Egg
{
if (OTGender != 3)
{
if (SID != pkm.SID) return false;
if (TID != pkm.TID) return false;
if (OTGender != pkm.OT_Gender) return false;
}
if (!string.IsNullOrEmpty(OT_Name) && OT_Name != pkm.OT_Name) return false;
if (OriginGame != 0 && OriginGame != pkm.Version) return false;
if (EncryptionConstant != 0 && EncryptionConstant != pkm.EncryptionConstant) return false;
if (Language != 0 && Language != pkm.Language) return false;
}
if (Form != pkm.AltForm && vs.All(dl => !Legal.IsFormChangeable(pkm, dl.Species)))
{
if (Species == 744 && Form == 1 && pkm.Species == 745 && pkm.AltForm == 2)
{
// Rockruff gift edge case; has altform 1 then evolves to altform 2
}
else
{
return false;
}
}
if (IsEgg)
{
if (EggLocation != pkm.Egg_Location) // traded
{
if (pkm.Egg_Location != 30002)
return false;
}
else if (PIDType == 0 && pkm.IsShiny)
{
return false; // can't be traded away for unshiny
}
if (pkm.IsEgg && !pkm.IsNative)
return false;
}
else
{
if (!PIDType.IsValid(pkm)) return false;
if (EggLocation != pkm.Egg_Location) return false;
if (MetLocation != pkm.Met_Location) return false;
}
if (MetLevel != pkm.Met_Level) return false;
if (Ball != pkm.Ball) return false;
if (OTGender < 3 && OTGender != pkm.OT_Gender) return false;
if (Nature != -1 && Nature != pkm.Nature) return false;
if (Gender != 3 && Gender != pkm.Gender) return false;
if (pkm is IContestStats s && s.IsContestBelow(this))
return false;
if (CardID == 2046) // Greninja WC has variant PID and can arrive @ 36 or 37
return pkm.SM; // not USUM
if (PIDType == 0 && pkm.PID != PID)
return false;
return true;
}
protected override bool IsMatchDeferred(PKM pkm)
{
if (RestrictLanguage != 0 && RestrictLanguage != pkm.Language)
return true;
if (!CanBeReceivedByVersion(pkm.Version))
return true;
return Species != pkm.Species;
}
}
}