mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-11 07:04:16 +00:00
Move encounter matching logic to iencounterable
generator logic is now clean
This commit is contained in:
parent
3481780e06
commit
2d75e93ef0
14 changed files with 703 additions and 733 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public enum EncounterMatchRating
|
||||
{
|
||||
None,
|
||||
Match,
|
||||
Deferred,
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue