From 7f9803905d1dd95c2a661c935de09290e6f45f29 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Wed, 15 Feb 2017 19:53:25 +0100 Subject: [PATCH 01/24] Ignore .vs folder, is a folder where Visual Studio 2015 put all machine and user-specific files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2bd0a997b..b8fdb6e1e 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ local.properties *.suo *.user *.sln.docstates +*.vs # Build results From 7720e93600155b82cd92468741811bb673caafd2 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Wed, 15 Feb 2017 21:21:23 +0100 Subject: [PATCH 02/24] Included min level of evolutions in the Lineage of a Pokemon, used to check evolution legality and to check in what evolutionary forms any pokemon inhabited previous generations --- PKHeX/Legality/Structures/DexLevel.cs | 3 ++- PKHeX/Legality/Structures/EvolutionTree.cs | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/PKHeX/Legality/Structures/DexLevel.cs b/PKHeX/Legality/Structures/DexLevel.cs index cea495af3..4ff880449 100644 --- a/PKHeX/Legality/Structures/DexLevel.cs +++ b/PKHeX/Legality/Structures/DexLevel.cs @@ -4,12 +4,13 @@ { public int Species; public int Level; + public int MinLevel; public int Form = -1; public int Flag = -1; public DexLevel Copy(int lvl) { - return new DexLevel {Species = Species, Level = lvl, Form = Form, Flag = -1}; + return new DexLevel {Species = Species, Level = lvl, MinLevel = MinLevel, Form = Form, Flag = -1}; } public bool Matches(int species, int form) { diff --git a/PKHeX/Legality/Structures/EvolutionTree.cs b/PKHeX/Legality/Structures/EvolutionTree.cs index 1371a2525..cd3848602 100644 --- a/PKHeX/Legality/Structures/EvolutionTree.cs +++ b/PKHeX/Legality/Structures/EvolutionTree.cs @@ -153,7 +153,7 @@ namespace PKHeX.Core return Personal.getFormeIndex(evolvesToSpecies, evolvesToForm); } - public IEnumerable getValidPreEvolutions(PKM pkm, int lvl, bool skipChecks = false) + public IEnumerable getValidPreEvolutions(PKM pkm, int lvl,bool skipChecks = false) { int index = getIndex(pkm); int maxSpeciesOrigin = Legal.getMaxSpeciesOrigin(pkm); @@ -354,7 +354,7 @@ namespace PKHeX.Core return false; } } - + public DexLevel GetDexLevel(int species, int lvl) { @@ -416,6 +416,22 @@ namespace PKHeX.Core continue; oneValid = true; + if (evo.Level == 0 && !evo.RequiresLevelUp) //Evolutions like elemental stones + dl.Last().MinLevel = 1; + else if(evo.Level ==0) //Evolutions like frienship, picho -> pikachu, eeve -> umbreon, etc + { + dl.Last().MinLevel = 2; + if (dl.Count() > 1 && dl.First().MinLevel == 1) + dl.First().MinLevel = 2; + } + else + { + dl.Last().MinLevel = evo.Level; + if (dl.Count() > 1 && dl.First().MinLevel == 1) + dl.First().MinLevel = evo.Level; //Pokemon like Nidoqueen, its minimun level is Nidorina minimun level + if (dl.Count() > 1 && dl.First().MinLevel == 2) + dl.First().MinLevel = evo.Level + 1; //Pokemon like Crobat, its minimun level is Golbat minimun level + 1 + } int species = evo.Species; // Gen7 Personal Formes -- unmap the forme personal entry ID to the actual species ID since species are consecutive @@ -436,6 +452,8 @@ namespace PKHeX.Core if (dl.Any(d => d.Species <= maxSpeciesOrigin) && dl.Last().Species > maxSpeciesOrigin) dl.RemoveAt(dl.Count - 1); + //Last species is the wild/hatched species, the minimu is 1 because it has not evolved from previous species + dl.Last().MinLevel = 1; return dl; } } From c9af06e2a35b6f328571f75f57e72248aa821869 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Wed, 15 Feb 2017 22:01:39 +0100 Subject: [PATCH 03/24] Include RequiresLvlUp info in Lineage --- PKHeX/Legality/Structures/DexLevel.cs | 3 ++- PKHeX/Legality/Structures/EvolutionTree.cs | 18 +++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/PKHeX/Legality/Structures/DexLevel.cs b/PKHeX/Legality/Structures/DexLevel.cs index 4ff880449..cd3d1e475 100644 --- a/PKHeX/Legality/Structures/DexLevel.cs +++ b/PKHeX/Legality/Structures/DexLevel.cs @@ -5,12 +5,13 @@ public int Species; public int Level; public int MinLevel; + public bool RequiresLvlUp; public int Form = -1; public int Flag = -1; public DexLevel Copy(int lvl) { - return new DexLevel {Species = Species, Level = lvl, MinLevel = MinLevel, Form = Form, Flag = -1}; + return new DexLevel {Species = Species, Level = lvl, MinLevel = MinLevel, RequiresLvlUp = RequiresLvlUp, Form = Form, Flag = -1}; } public bool Matches(int species, int form) { diff --git a/PKHeX/Legality/Structures/EvolutionTree.cs b/PKHeX/Legality/Structures/EvolutionTree.cs index cd3848602..fd6b9376d 100644 --- a/PKHeX/Legality/Structures/EvolutionTree.cs +++ b/PKHeX/Legality/Structures/EvolutionTree.cs @@ -416,22 +416,25 @@ namespace PKHeX.Core continue; oneValid = true; - if (evo.Level == 0 && !evo.RequiresLevelUp) //Evolutions like elemental stones + if (evo.Level == 0 && !evo.RequiresLevelUp) //Evolutions like elemental stones, trade, etc + { dl.Last().MinLevel = 1; + } else if(evo.Level ==0) //Evolutions like frienship, picho -> pikachu, eeve -> umbreon, etc { dl.Last().MinLevel = 2; - if (dl.Count() > 1 && dl.First().MinLevel == 1) - dl.First().MinLevel = 2; + if (dl.Count() > 1 && !dl.First().RequiresLvlUp) + dl.First().MinLevel = 2; //Raichu from Pikachu would have minimun level 1, but with Pichu included Raichu minimun level is 2 } - else + else //level up evolutions { dl.Last().MinLevel = evo.Level; - if (dl.Count() > 1 && dl.First().MinLevel == 1) + if (dl.Count() > 1 && dl.First().MinLevel < evo.Level && !dl.First().RequiresLvlUp) dl.First().MinLevel = evo.Level; //Pokemon like Nidoqueen, its minimun level is Nidorina minimun level - if (dl.Count() > 1 && dl.First().MinLevel == 2) + if (dl.Count() > 1 && dl.First().MinLevel <= evo.Level && dl.First().RequiresLvlUp) dl.First().MinLevel = evo.Level + 1; //Pokemon like Crobat, its minimun level is Golbat minimun level + 1 } + dl.Last().RequiresLvlUp = evo.RequiresLevelUp; int species = evo.Species; // Gen7 Personal Formes -- unmap the forme personal entry ID to the actual species ID since species are consecutive @@ -452,8 +455,9 @@ namespace PKHeX.Core if (dl.Any(d => d.Species <= maxSpeciesOrigin) && dl.Last().Species > maxSpeciesOrigin) dl.RemoveAt(dl.Count - 1); - //Last species is the wild/hatched species, the minimu is 1 because it has not evolved from previous species + //Last species is the wild/hatched species, the minimun is 1 because it has not evolved from previous species dl.Last().MinLevel = 1; + dl.Last().RequiresLvlUp = false; return dl; } } From b1ecdde41d776941fe5e7c0c0fc2702be16b6bdd Mon Sep 17 00:00:00 2001 From: javierhimura Date: Wed, 15 Feb 2017 22:12:06 +0100 Subject: [PATCH 04/24] getEvolutionChain adapted to get evolution chains from previous generations Excluded future gen evolutions, both evolutions of species that does not exits in the generation expected in the chain, but also evolutions impossible because it requires a level above transfer level --- PKHeX/Legality/Core.cs | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 27fd13c3e..bb529e2e7 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -742,9 +742,13 @@ namespace PKHeX.Core } } internal static DexLevel[] getEvolutionChain(PKM pkm, object Encounter) + { + return getEvolutionChain(pkm, Encounter,pkm.Species, 100); + } + public static DexLevel[] getEvolutionChain(PKM pkm, object Encounter,int maxspec, int maxlevel) { int minspec; - var vs = getValidPreEvolutions(pkm).ToArray(); + DexLevel[] vs = getValidPreEvolutions(pkm).ToArray(); // Evolution chain is in reverse order (devolution) @@ -757,8 +761,29 @@ namespace PKHeX.Core else minspec = vs.Last().Species; - int index = Math.Max(0, Array.FindIndex(vs, p => p.Species == minspec)); - Array.Resize(ref vs, index + 1); + int minindex = Math.Max(0, Array.FindIndex(vs, p => p.Species == minspec)); + Array.Resize(ref vs, minindex + 1); + if(vs.Last().MinLevel > 1) //Last entry from vs is removed, turn next entry into the wild/hatched pokemon + { + vs.Last().MinLevel = 1; + vs.Last().RequiresLvlUp = false; + if (vs.First().MinLevel == 2 && !vs.First().RequiresLvlUp) + { + //Example Raichu in gen 2 or later, + //because Pichu requires level up minimun level of Raichu would be 2 + //but after removing Pichu because the origin species is Pikachu, Raichu min level should be 1 + vs.First().MinLevel = 1; + vs.First().RequiresLvlUp = false; + } + } + //Maxspec is used to remove future gen evolutions, to gather evolution chain of a pokemon in previous generations + int skip = Math.Max(0, Array.FindIndex(vs, p => p.Species == maxspec)); + //Maxlevel is also used for previous generations, it removes evolutions imposible before the transfer level + //For example a fire red charizard whose current level in XY is 50 but met level is 20, it couldnt be a Charizard in gen 3 and 4 games + vs = vs.Skip(skip).Where(e=>e.MinLevel <= maxlevel).ToArray(); + //Reduce the evolution chain levels to max level, because met level is the las one when the pokemon could be and learn moves in that generation + foreach (DexLevel d in vs) + d.Level = Math.Min(d.Level, maxlevel); return vs; } internal static string getEncounterTypeName(PKM pkm, object Encounter) From 4c04f4eee4e39b3ceb46a12ed43d61bfdc11685c Mon Sep 17 00:00:00 2001 From: javierhimura Date: Wed, 15 Feb 2017 23:10:20 +0100 Subject: [PATCH 05/24] Added function to calculate from a given pokemon evolution chain for all possible generations, every chain will contain only the evolution forms and maximun possible level when the pokemon could exits --- PKHeX/Legality/Analysis.cs | 2 ++ PKHeX/Legality/Core.cs | 59 +++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/PKHeX/Legality/Analysis.cs b/PKHeX/Legality/Analysis.cs index 394e08a16..ffe270071 100644 --- a/PKHeX/Legality/Analysis.cs +++ b/PKHeX/Legality/Analysis.cs @@ -8,6 +8,7 @@ namespace PKHeX.Core { private PKM pkm; private DexLevel[] EvoChain; + private DexLevel[][] EvoChainsAllGens; private readonly List Parse = new List(); private object EncounterMatch; @@ -143,6 +144,7 @@ namespace PKHeX.Core Encounter = verifyEncounter(); Parse.Add(Encounter); EvoChain = Legal.getEvolutionChain(pkm, EncounterMatch); + EvoChainsAllGens = Legal.getEvolutionChainsAllGens(pkm, EncounterMatch); } private void updateEncounterInfo() { diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index bb529e2e7..de3582856 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -741,11 +741,68 @@ namespace PKHeX.Core default: return evos.Length <= 0 ? pkm.Species : evos.Last().Species; } } + + internal static DexLevel[][] getEvolutionChainsAllGens(PKM pkm, object Encounter) + { + IEnumerable CompleteEvoChain = getEvolutionChain(pkm, Encounter); + DexLevel[][] GensEvoChains = new DexLevel[8][]; + for (int gen = 1; gen <= 7; gen++) + GensEvoChains[gen] = new DexLevel[0]; + + if(pkm.GenU || pkm.Species==0)//Illegal origin or empty pokemon, return only chain for current format + { + GensEvoChains[pkm.Format] = CompleteEvoChain.ToArray(); + return GensEvoChains; + } + + int currengenlevel = pkm.CurrentLevel; + int maxgen = (pkm.Format <= 2) ? 2 : pkm.Format; + int mingen = (pkm.Format <= 2) ? 1 : pkm.GenNumber; + //Iterate generations backwards because level will be decreased from current level in each generation + for (int gen = maxgen; gen >= mingen; gen--) + { + if ((pkm.Gen1 || pkm.VC1) && pkm.Format >2 && 2 <= gen && gen <= 6) + continue; + if ((pkm.Gen2 || pkm.VC2) && 3 <= gen && gen <= 6) + continue; + if (!pkm.HasOriginalMetLocation && pkm.Format >2 && gen <= 4 && currengenlevel > pkm.Met_Level) + //Met location was lost at this point but it also means the pokemon existed in generations 1 to 4 with maximun level met level + currengenlevel = pkm.Met_Level; + //Remove future gen evolutions after a few special considerations, + //it he pokemon origin is illegal like a "gen 3" Infernape the list will be emptied, it didnt existed in gen 3 in any evolution phase + while (CompleteEvoChain.Any() && CompleteEvoChain.First().Species > getMaxSpeciesOrigin(gen)) + { + //Eeve requieres to level one time to be Sylveon, it can be deduced in gen 5 and before it existed with maximun one level bellow current + if (CompleteEvoChain.First().Species == 700 && gen == 5) + currengenlevel--; + //This is a gen 3 pokemon in a gen 4 phase evolution that requieres level up and then transfered to gen 5,6 or 7 + //We can deduce that it existed in gen 4 until met level, + //but if current level is met level we can also deduce it existed in gen 3 until maximun met level -1 + if (gen == 3 && pkm.Format>4 && currengenlevel == pkm.CurrentLevel && CompleteEvoChain.First().RequiresLvlUp) + currengenlevel--; + CompleteEvoChain = CompleteEvoChain.Skip(1); + }; + //Alolan form evolutions, remove from gens 1-6 chains + if (gen < 7 && pkm.Format >= 7 && CompleteEvoChain.Any() && CompleteEvoChain.First().Form > 0 && EvolveToAlolanForms.Contains(CompleteEvoChain.First().Species)) + CompleteEvoChain = CompleteEvoChain.Skip(1); + + if(CompleteEvoChain.Any()) + { + GensEvoChains[gen] = getEvolutionChain(pkm, Encounter, CompleteEvoChain.First().Species, currengenlevel); + if (!pkm.HasOriginalMetLocation && gen >= pkm.GenNumber ) + //Remove previous evolutions bellow transfer level + //For example a gen3 charizar in format 7 with current level 36 and met level 36 + //chain level for charmander is 35, is bellow met level + GensEvoChains[gen] = GensEvoChains[gen].Where(e => e.Level >= currengenlevel).ToArray(); + } + } + return GensEvoChains; + } internal static DexLevel[] getEvolutionChain(PKM pkm, object Encounter) { return getEvolutionChain(pkm, Encounter,pkm.Species, 100); } - public static DexLevel[] getEvolutionChain(PKM pkm, object Encounter,int maxspec, int maxlevel) + internal static DexLevel[] getEvolutionChain(PKM pkm, object Encounter,int maxspec, int maxlevel) { int minspec; DexLevel[] vs = getValidPreEvolutions(pkm).ToArray(); From 3622733ecebb001ad057034429dbc91daddb3d34 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Wed, 15 Feb 2017 23:11:01 +0100 Subject: [PATCH 06/24] GenU returns should returns false for VC pokemon --- PKHeX/PKM/PKM.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/PKHeX/PKM/PKM.cs b/PKHeX/PKM/PKM.cs index 3299c6c67..076006eaf 100644 --- a/PKHeX/PKM/PKM.cs +++ b/PKHeX/PKM/PKM.cs @@ -277,7 +277,7 @@ namespace PKHeX.Core public bool Gen3 => Version >= 1 && Version <= 5 || Version == 15; public bool Gen2 => Version == (int)GameVersion.GSC; public bool Gen1 => Version == (int)GameVersion.RBY; - public bool GenU => !(Gen7 || Gen6 || Gen5 || Gen4 || Gen3 || Gen2 || Gen1); + public bool GenU => !(Gen7 || Gen6 || Gen5 || Gen4 || Gen3 || Gen2 || Gen1 || VC); public int GenNumber { get @@ -453,6 +453,9 @@ namespace PKHeX.Core if (species < 0) species = Species; + if (Format == 1 && Generation ==2 && Legal.MaxSpeciesID_2 >= species) + return true; + if (Format < Generation) return false; // Future @@ -466,8 +469,8 @@ namespace PKHeX.Core int gen = GenNumber; switch (Generation) { - case 1: return VC; - case 2: return VC; + case 1: return Format == 1 || VC1; + case 2: return Format <= 2 || VC2; case 3: return Gen3; case 4: return 3 <= gen && gen <= 4; case 5: return 3 <= gen && gen <= 5; From 8b645de431ab91d5ba4be7c70c659d35f6b4dc91 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Wed, 15 Feb 2017 23:33:59 +0100 Subject: [PATCH 07/24] Use the list of evolution chains from every generation to search valid moves from a given pokemon --- PKHeX/Legality/Analysis.cs | 2 +- PKHeX/Legality/Checks.cs | 17 +++++--- PKHeX/Legality/Core.cs | 89 ++++++++++++++++++++++++++++---------- 3 files changed, 77 insertions(+), 31 deletions(-) diff --git a/PKHeX/Legality/Analysis.cs b/PKHeX/Legality/Analysis.cs index ffe270071..6e3168e7e 100644 --- a/PKHeX/Legality/Analysis.cs +++ b/PKHeX/Legality/Analysis.cs @@ -259,7 +259,7 @@ namespace PKHeX.Core return null; if (!Parsed) return new int[4]; - return Legal.getValidMoves(pkm, EvoChain, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray(); // skip move 0 + return Legal.getValidMoves(pkm, EvoChainsAllGens, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray(); // skip move 0 } public EncounterStatic getSuggestedMetInfo() diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index d51396610..a96fe8d82 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -1433,8 +1433,11 @@ namespace PKHeX.Core resultPrefix = "HT "; break; } + int[] generations = new int[1] { pkm.Format }; + if (pkm.GenNumber == 6 && pkm.Format == 7) + generations = new int[2] { 6, 7 }; int matchingMoveMemory = Array.IndexOf(Legal.MoveSpecificMemories[0], m); - if (matchingMoveMemory != -1 && pkm.Species != 235 && !Legal.getCanLearnMachineMove(pkm, Legal.MoveSpecificMemories[1][matchingMoveMemory])) + if (matchingMoveMemory != -1 && pkm.Species != 235 && !Legal.getCanLearnMachineMove(pkm, Legal.MoveSpecificMemories[1][matchingMoveMemory], generations)) { return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot learn this move.", CheckIdentifier.Memory); } @@ -1444,14 +1447,14 @@ namespace PKHeX.Core } if (m == 21) // {0} saw {2} carrying {1} on its back. {4} that {3}. { - if (!Legal.getCanLearnMachineMove(new PK6 {Species = t, EXP = PKX.getEXP(100, t)}, 19)) + if (!Legal.getCanLearnMachineMove(new PK6 {Species = t, EXP = PKX.getEXP(100, t)}, 19, generations)) return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Argument Species cannot learn Fly.", CheckIdentifier.Memory); } - if ((m == 16 || m == 48) && (t == 0 || !Legal.getCanKnowMove(pkm, t, GameVersion.Any))) + if ((m == 16 || m == 48) && (t == 0 || !Legal.getCanKnowMove(pkm, t, generations, GameVersion.Any))) { return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot know this move.", CheckIdentifier.Memory); } - if (m == 49 && (t == 0 || !Legal.getCanRelearnMove(pkm, t, GameVersion.Any))) // {0} was able to remember {2} at {1}'s instruction. {4} that {3}. + if (m == 49 && (t == 0 || !Legal.getCanRelearnMove(pkm, t, generations, GameVersion.Any))) // {0} was able to remember {2} at {1}'s instruction. {4} that {3}. { return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot relearn this move.", CheckIdentifier.Memory); } @@ -1897,9 +1900,9 @@ namespace PKHeX.Core for (int i = 0; i < 4; i++) res[i] = new CheckResult(CheckIdentifier.Move); - var validMoves = Legal.getValidMoves(pkm, EvoChain, Tutor: false, Machine: false).ToArray(); - var validTMHM = Legal.getValidMoves(pkm, EvoChain, Tutor: false, MoveReminder: false).ToArray(); - var validTutor = Legal.getValidMoves(pkm, EvoChain, Machine: false, MoveReminder: false).ToArray(); + var validMoves = Legal.getValidMoves(pkm, EvoChainsAllGens, Tutor: false, Machine: false).ToArray(); + var validTMHM = Legal.getValidMoves(pkm, EvoChainsAllGens, Tutor: false, MoveReminder: false).ToArray(); + var validTutor = Legal.getValidMoves(pkm, EvoChainsAllGens, Machine: false, MoveReminder: false).ToArray(); if (pkm.Species == 235) // Smeargle { for (int i = 0; i < 4; i++) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index de3582856..27d5ca64a 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -192,12 +192,19 @@ namespace PKHeX.Core } // Moves - internal static IEnumerable getValidMoves(PKM pkm, IEnumerable evoChain, bool Tutor = true, bool Machine = true, bool MoveReminder = true) + internal static IEnumerable getValidMoves(PKM pkm, DexLevel[][] evoChains, bool Tutor = true, bool Machine = true, bool MoveReminder = true) { GameVersion version = (GameVersion)pkm.Version; if (!pkm.IsUntraded) version = GameVersion.Any; - return getValidMoves(pkm, version, evoChain, LVL: true, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder); + return getValidMoves(pkm, version, evoChains, LVL: true, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder); + } + internal static IEnumerable getValidMoves(PKM pkm, IEnumerable evoChain,int generation, bool Tutor = true, bool Machine = true, bool MoveReminder = true) + { + GameVersion version = (GameVersion)pkm.Version; + if (!pkm.IsUntraded) + version = GameVersion.Any; + return getValidMoves(pkm, version, evoChain, generation,LVL: true, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder); } internal static IEnumerable getValidRelearn(PKM pkm, int skipOption) { @@ -414,7 +421,7 @@ namespace PKHeX.Core default: return -1; } } - + internal static int getMaxSpeciesOrigin(PKM pkm) { if (pkm.Format == 1 || pkm.VC1) // Gen1 VC could not trade with gen 2 yet @@ -705,25 +712,52 @@ namespace PKHeX.Core return false; } - internal static bool getCanLearnMachineMove(PKM pkm, int move, GameVersion version = GameVersion.Any) + internal static bool getCanLearnMachineMove(PKM pkm, int move, int[] generations, GameVersion version = GameVersion.Any) { - return getValidMoves(pkm, version, getValidPreEvolutions(pkm), Machine: true).Contains(move); + foreach (int generation in generations) + if (getCanLearnMachineMove(pkm, generation, move, version)) + return true; + return false; } - internal static bool getCanRelearnMove(PKM pkm, int move, GameVersion version = GameVersion.Any) + internal static bool getCanRelearnMove(PKM pkm,int move, int[] generations, GameVersion version = GameVersion.Any) { - return getValidMoves(pkm, version, getValidPreEvolutions(pkm), LVL: true, Relearn: true).Contains(move); + foreach (int generation in generations) + if (getCanRelearnMove(pkm, move, generation, version)) + return true; + return false; } - internal static bool getCanLearnMove(PKM pkm, int move, GameVersion version = GameVersion.Any) + internal static bool getCanLearnMove(PKM pkm, int move, int[] generations, GameVersion version = GameVersion.Any) { - return getValidMoves(pkm, version, getValidPreEvolutions(pkm), Tutor: true, Machine: true).Contains(move); + foreach (int generation in generations) + if (getCanLearnMove(pkm, move, generation, version)) + return true; + return false; } - internal static bool getCanKnowMove(PKM pkm, int move, GameVersion version = GameVersion.Any) + internal static bool getCanKnowMove(PKM pkm, int move, int[] generations, GameVersion version = GameVersion.Any) + { + foreach (int generation in generations) + if (getCanKnowMove(pkm, move, generation, version)) + return true; + return false; + } + internal static bool getCanLearnMachineMove(PKM pkm,int move, int generation, GameVersion version = GameVersion.Any) + { + return getValidMoves(pkm, version, getValidPreEvolutions(pkm), generation, Machine: true).Contains(move); + } + internal static bool getCanRelearnMove(PKM pkm, int move, int generation, GameVersion version = GameVersion.Any) + { + return getValidMoves(pkm, version, getValidPreEvolutions(pkm), generation, LVL: true, Relearn: true).Contains(move); + } + internal static bool getCanLearnMove(PKM pkm,int move, int generation, GameVersion version = GameVersion.Any) + { + return getValidMoves(pkm, version, getValidPreEvolutions(pkm), generation, Tutor: true, Machine: true).Contains(move); + } + internal static bool getCanKnowMove(PKM pkm,int move, int generation, GameVersion version = GameVersion.Any) { if (pkm.Species == 235 && !InvalidSketch.Contains(move)) return true; - return getValidMoves(pkm, Version: version, vs: getValidPreEvolutions(pkm), LVL: true, Relearn: true, Tutor: true, Machine: true).Contains(move); + return getValidMoves(pkm, version,getValidPreEvolutions(pkm), generation, LVL: true, Relearn: true, Tutor: true, Machine: true).Contains(move); } - internal static int getBaseSpecies(PKM pkm, int skipOption = 0) { if (pkm.Species == 292) @@ -838,7 +872,7 @@ namespace PKHeX.Core //Maxlevel is also used for previous generations, it removes evolutions imposible before the transfer level //For example a fire red charizard whose current level in XY is 50 but met level is 20, it couldnt be a Charizard in gen 3 and 4 games vs = vs.Skip(skip).Where(e=>e.MinLevel <= maxlevel).ToArray(); - //Reduce the evolution chain levels to max level, because met level is the las one when the pokemon could be and learn moves in that generation + //Reduce the evolution chain levels to max level, because met level is the last one when the pokemon could be and learn moves in that generation foreach (DexLevel d in vs) d.Level = Math.Min(d.Level, maxlevel); return vs; @@ -1039,13 +1073,13 @@ namespace PKHeX.Core if (lvl == 1 && pkm.IsEgg) return new List { - new DexLevel { Species = pkm.Species, Level = 1 }, + new DexLevel { Species = pkm.Species, Level = 1, MinLevel = 1 }, }; - if (pkm.Species == 292 && pkm.Met_Level + 1 <= lvl && lvl >= 20) + if (pkm.Species == 292 && lvl >= 20 && (!pkm.HasOriginalMetLocation || pkm.Met_Level + 1 <= lvl)) return new List { - new DexLevel { Species = 292, Level = lvl }, - new DexLevel { Species = 290, Level = lvl-1 } + new DexLevel { Species = 292, Level = lvl, MinLevel =20 }, + new DexLevel { Species = 290, Level = lvl - 1, MinLevel = 1 } }; var et = getEvolutionTable(pkm); @@ -1056,11 +1090,22 @@ namespace PKHeX.Core IEnumerable dl = getValidPreEvolutions(pkm, lvl); return table.Where(e => dl.Any(d => d.Species == e.Species)); } - private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, IEnumerable vs, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true) + private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, DexLevel[][] vs, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true) { List r = new List { 0 }; + for(int gen =1;gen<=7;gen++) + { + if (vs[gen].Any()) + r.AddRange(getValidMoves(pkm, Version, vs[gen], gen, LVL, Tutor, Machine, MoveReminder)); + } + return r.Distinct().ToArray(); + } + private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, IEnumerable vs, int Generation, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true) + { + List r = new List { 0 }; + if (!vs.Any()) + return r; int species = pkm.Species; - int lvl = pkm.CurrentLevel; // Special Type Tutors Availability bool moveTutor = Tutor || MoveReminder; // Usually true, except when called for move suggestions (no tutored moves) @@ -1069,15 +1114,13 @@ namespace PKHeX.Core { int formcount = pkm.PersonalInfo.FormeCount; for (int i = 0; i < formcount; i++) - r.AddRange(getMoves(pkm, species, lvl, i, moveTutor, Version, LVL, Tutor, Machine, MoveReminder)); + r.AddRange(getMoves(pkm, species, vs.First().Level, i, moveTutor, Version, LVL, Tutor, Machine, Generation, MoveReminder)); if (Relearn) r.AddRange(pkm.RelearnMoves); return r.Distinct().ToArray(); } - r.AddRange(getMoves(pkm, species, lvl, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine, MoveReminder)); - foreach (DexLevel evo in vs) - r.AddRange(getMoves(pkm, evo.Species, evo.Level, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine, MoveReminder)); + r.AddRange(getMoves(pkm, evo.Species, evo.Level, evo.Form, moveTutor, Version, LVL, Tutor, Machine, Generation, MoveReminder)); if (pkm.Format <= 3) return r.Distinct().ToArray(); From fc14a2ec50a23db7253e0ef91ad748f7726a2191 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 00:05:13 +0100 Subject: [PATCH 08/24] Tweks in function InhabitedGeneration to take into account future gen evolutions and GB-GBC transfer --- PKHeX/Legality/Core.cs | 15 ++++++++++++++- PKHeX/Legality/Tables1.cs | 5 +++++ PKHeX/Legality/Tables2.cs | 5 +++++ PKHeX/Legality/Tables3.cs | 5 +++++ PKHeX/Legality/Tables4.cs | 5 +++++ PKHeX/Legality/Tables5.cs | 5 +++++ 6 files changed, 39 insertions(+), 1 deletion(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 27d5ca64a..41b87e527 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -421,7 +421,20 @@ namespace PKHeX.Core default: return -1; } } - + + internal static int[] getFutureGenEvolutions(int generation) + { + switch (generation) + { + case 1: return FutureEvolutionsGen1; + case 2: return FutureEvolutionsGen2; + case 3: return FutureEvolutionsGen3; + case 4: return FutureEvolutionsGen4; + case 5: return FutureEvolutionsGen5; + default: return new int[0]; + } + } + internal static int getMaxSpeciesOrigin(PKM pkm) { if (pkm.Format == 1 || pkm.VC1) // Gen1 VC could not trade with gen 2 yet diff --git a/PKHeX/Legality/Tables1.cs b/PKHeX/Legality/Tables1.cs index 5079716b6..9b52ab7e5 100644 --- a/PKHeX/Legality/Tables1.cs +++ b/PKHeX/Legality/Tables1.cs @@ -114,5 +114,10 @@ namespace PKHeX.Core new EncounterSlot1 {Species = 118, LevelMin = 10, LevelMax = 10, Type = SlotType.Good_Rod, Rate = -1, }, // Goldeen new EncounterSlot1 {Species = 060, LevelMin = 10, LevelMax = 10, Type = SlotType.Good_Rod, Rate = -1, }, // Poliwag }}; + + internal static readonly int[] FutureEvolutionsGen1 = + { + 169,182,186,196,197,199,208,212,230,233,242,462,463,464,465,466,467,470,471,474,700 + }; } } diff --git a/PKHeX/Legality/Tables2.cs b/PKHeX/Legality/Tables2.cs index 27a3a89c5..1c934f4dd 100644 --- a/PKHeX/Legality/Tables2.cs +++ b/PKHeX/Legality/Tables2.cs @@ -36,5 +36,10 @@ namespace PKHeX.Core 10, 00, 00, 00, 00 }; internal static readonly int[] WildPokeBalls2 = { 4 }; + + internal static readonly int[] FutureEvolutionsGen2 = + { + 424,429,430,461,462,463,464,465,466,467,468,469,470,471,472,473,474,700 + }; } } diff --git a/PKHeX/Legality/Tables3.cs b/PKHeX/Legality/Tables3.cs index a136845ca..34cbb69e2 100644 --- a/PKHeX/Legality/Tables3.cs +++ b/PKHeX/Legality/Tables3.cs @@ -82,5 +82,10 @@ namespace PKHeX.Core 590, 591, 592, 593 }; internal static readonly int[] WildPokeBalls3 = {1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12}; + + internal static readonly int[] FutureEvolutionsGen3 = + { + 407,424,429,430,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,700 + }; } } diff --git a/PKHeX/Legality/Tables4.cs b/PKHeX/Legality/Tables4.cs index 8dbfb116b..83f1a9f6f 100644 --- a/PKHeX/Legality/Tables4.cs +++ b/PKHeX/Legality/Tables4.cs @@ -130,5 +130,10 @@ namespace PKHeX.Core 17, 18, 19, 20, 21, 22, // Comp Ball not usable in wild }; + + internal static readonly int[] FutureEvolutionsGen4 = + { + 700 + }; } } diff --git a/PKHeX/Legality/Tables5.cs b/PKHeX/Legality/Tables5.cs index 7c1199c20..723d65860 100644 --- a/PKHeX/Legality/Tables5.cs +++ b/PKHeX/Legality/Tables5.cs @@ -89,5 +89,10 @@ namespace PKHeX.Core // HGSS balls not usable // Dream ball not usable in wild }; + + internal static readonly int[] FutureEvolutionsGen5 = + { + 700 + }; } } From 980ffac9d394d5e74e27fd481bcad862fd960d6e Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 00:47:44 +0100 Subject: [PATCH 09/24] Even with met location and met level lost after transfer pokemon from gen 3 to 4, 4 to 5 and 1 to 7 Met Level can still be used to filter some invalid encounter slots, those whose min level is greater that the met level of the pokemon Even without knowing the real met level, it can be greater than the transfer level For GB and GBC pokemon the same but with the current level instead. This will make illegal any level 7 glitch Articuno --- PKHeX/Legality/Core.cs | 49 +++++++++++++++++++++++++++++++-------- PKHeX/Legality/Tables3.cs | 7 ++++++ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 41b87e527..a09cf4cb0 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -294,6 +294,11 @@ namespace PKHeX.Core if (e.Level != pkm.Met_Level) continue; } + else + { + if (e.Level > pkm.Met_Level) + continue; + } if (e.Gender != -1 && e.Gender != pkm.Gender) continue; if (e.Form != pkm.AltForm && !FormChange.Contains(pkm.Species) && !e.SkipFormCheck) @@ -350,7 +355,9 @@ namespace PKHeX.Core return null; if (pkm.HasOriginalMetLocation && z.Location != pkm.Met_Location) return null; - if (z.Level != pkm.Met_Level) + if (pkm.HasOriginalMetLocation && z.Level != pkm.Met_Level) + return null; + if (!pkm.HasOriginalMetLocation && z.Level > pkm.Met_Level) return null; if (z.Nature != Nature.Random && (int)z.Nature != pkm.Nature) return null; @@ -421,7 +428,7 @@ namespace PKHeX.Core default: return -1; } } - + internal static int[] getFutureGenEvolutions(int generation) { switch (generation) @@ -1016,14 +1023,31 @@ namespace PKHeX.Core bool ignoreSlotLevel = ignoreLevel; IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && (ignoreSlotLevel || evo.Level >= slot.LevelMin - df))); - if (pkm.Format < 3 || pkm.VC) - return slots; // no met level or special encounter considerations - // Filter for Met Level - int lvl = pkm.Met_Level; + int lvl = (pkm.Format < 3) ? pkm.CurrentLevel : pkm.Met_Level; int gen = pkm.GenNumber; - bool ignoreMetLevel = ignoreLevel || gen <= 4 && pkm.Format != gen; - var encounterSlots = slots.Where(slot => ignoreMetLevel || slot.LevelMin - df <= lvl && lvl <= slot.LevelMax + (slot.AllowDexNav ? dn : df)).ToList(); + IEnumerable encounterSlots; + if(pkm.HasOriginalMetLocation) + encounterSlots = slots.Where(slot => ignoreLevel || slot.LevelMin - df <= lvl && lvl <= slot.LevelMax + (slot.AllowDexNav ? dn : df)).ToList(); + else + { + //See comments in getEvolutionChainsAllGens for more info in this sentence + if (gen == 3 && pkm.Format > 4 && lvl == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) + lvl--; + //Those encounters with level min greater that met level are not valid for this pokemon + encounterSlots = slots.Where(slot => ignoreLevel || slot.LevelMin <= lvl).ToList(); + } + + if(gen <= 2) + { + //For gen 1 and 2 return minimun level slot + //Minimun level is needed to check available moves, because there is no move reminder in gen 1, + //There are moves in the level up table that cant be legally obtained + EncounterSlot slotMin = encounterSlots.OrderBy(slot => slot.LevelMin).FirstOrDefault(); + if (slotMin != null) + slotdata.Add(slotMin); + return slotdata; + } // Pressure Slot EncounterSlot slotMax = encounterSlots.OrderByDescending(slot => slot.LevelMax).FirstOrDefault(); @@ -1036,7 +1060,7 @@ namespace PKHeX.Core slotdata.Add(slotMax); return slotdata; } - if (!DexNav) + if (gen == 6 || !DexNav) { // Filter for Form Specific slotdata.AddRange(WildForms.Contains(pkm.Species) @@ -1048,6 +1072,11 @@ namespace PKHeX.Core } List eslots = encounterSlots.Where(slot => !WildForms.Contains(pkm.Species) || slot.Form == pkm.AltForm).ToList(); + if(gen <=4) + { + slotdata.AddRange(eslots); + return slotdata; + } if (slotMax != null) eslots.Add(slotMax); foreach (EncounterSlot s in eslots) @@ -1092,7 +1121,7 @@ namespace PKHeX.Core return new List { new DexLevel { Species = 292, Level = lvl, MinLevel =20 }, - new DexLevel { Species = 290, Level = lvl - 1, MinLevel = 1 } + new DexLevel { Species = 290, Level = lvl-1, MinLevel = 1 } }; var et = getEvolutionTable(pkm); diff --git a/PKHeX/Legality/Tables3.cs b/PKHeX/Legality/Tables3.cs index 34cbb69e2..91ec69374 100644 --- a/PKHeX/Legality/Tables3.cs +++ b/PKHeX/Legality/Tables3.cs @@ -87,5 +87,12 @@ namespace PKHeX.Core { 407,424,429,430,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,700 }; + + internal static readonly int[] FutureEvolutionsGen3_LevelUp = new int[] + { + 424, 461, 462, 463, 465, 469, 470, 471, 472, 473, 476 + }; + // Ambipom Weavile Magnezone Lickilicky Tangrowth + // Yanmega Leafeon Glaceon Mamoswine Gliscor Probopass } } From b123218e2ca8400b17e39db2f75f9a6185d63952 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 00:56:54 +0100 Subject: [PATCH 10/24] Include the special moves in the filters of level moves and move reminder to avoid duplicates when executing getValidMoves multiple times Also filter those special moves by generation, to avoid return a gen 5 move when gen 4 is solicitied, even if that only could happen with illegal pokemons --- PKHeX/Legality/Core.cs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index a09cf4cb0..8df76ba8b 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -1166,21 +1166,22 @@ namespace PKHeX.Core if (pkm.Format <= 3) return r.Distinct().ToArray(); + if (LVL) + { + if (species == 479 && Generation >= 4) // Rotom + r.Add(RotomMoves[pkm.AltForm]); + if (species == 648 && Generation >= 5) // Meloetta + r.Add(547); // Relic Song - if (species == 479) // Rotom - r.Add(RotomMoves[pkm.AltForm]); - if (species == 648) // Meloetta - r.Add(547); // Relic Song + if (species == 25 && pkm.Format == 6 && Generation == 6) // Pikachu + r.Add(PikachuMoves[pkm.AltForm]); - if (species == 25 && pkm.Format == 6 && pkm.GenNumber == 6) // Pikachu - r.Add(PikachuMoves[pkm.AltForm]); - - if (species == 718 && pkm.GenNumber == 7) // Zygarde - r.AddRange(ZygardeMoves); - if ((species == 25 || species == 26) && pkm.Format == 7) // Pikachu/Raichu Tutor + if (species == 718 && Generation == 7) // Zygarde + r.AddRange(ZygardeMoves); + } + if ((species == 25 || species == 26) && Generation == 7 && moveTutor) // Pikachu/Raichu Tutor r.Add(344); // Volt Tackle - - if (Relearn) r.AddRange(pkm.RelearnMoves); + if (Relearn && Generation >= 6) r.AddRange(pkm.RelearnMoves); return r.Distinct().ToArray(); } private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder) From 2b8cc8ffd59e9fa1eed8f7409ef13782950d4036 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 01:04:48 +0100 Subject: [PATCH 11/24] Fixes --- PKHeX/Legality/Core.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 8df76ba8b..065118bfd 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -803,7 +803,7 @@ namespace PKHeX.Core for (int gen = 1; gen <= 7; gen++) GensEvoChains[gen] = new DexLevel[0]; - if(pkm.GenU || pkm.Species==0)//Illegal origin or empty pokemon, return only chain for current format + if((pkm.Format >2 && pkm.GenU) || pkm.Species==0)//Illegal origin or empty pokemon, return only chain for current format { GensEvoChains[pkm.Format] = CompleteEvoChain.ToArray(); return GensEvoChains; @@ -820,10 +820,10 @@ namespace PKHeX.Core if ((pkm.Gen2 || pkm.VC2) && 3 <= gen && gen <= 6) continue; if (!pkm.HasOriginalMetLocation && pkm.Format >2 && gen <= 4 && currengenlevel > pkm.Met_Level) - //Met location was lost at this point but it also means the pokemon existed in generations 1 to 4 with maximun level met level + //Met location was lost at this point but it also means the pokemon existed in generations 1 to 4 with maximun level equals to met level currengenlevel = pkm.Met_Level; //Remove future gen evolutions after a few special considerations, - //it he pokemon origin is illegal like a "gen 3" Infernape the list will be emptied, it didnt existed in gen 3 in any evolution phase + //it the pokemon origin is illegal like a "gen 3" Infernape the list will be emptied, it didnt existed in gen 3 in any evolution phase while (CompleteEvoChain.Any() && CompleteEvoChain.First().Species > getMaxSpeciesOrigin(gen)) { //Eeve requieres to level one time to be Sylveon, it can be deduced in gen 5 and before it existed with maximun one level bellow current @@ -832,7 +832,7 @@ namespace PKHeX.Core //This is a gen 3 pokemon in a gen 4 phase evolution that requieres level up and then transfered to gen 5,6 or 7 //We can deduce that it existed in gen 4 until met level, //but if current level is met level we can also deduce it existed in gen 3 until maximun met level -1 - if (gen == 3 && pkm.Format>4 && currengenlevel == pkm.CurrentLevel && CompleteEvoChain.First().RequiresLvlUp) + if (gen == 3 && pkm.Format>4 && currengenlevel == pkm.CurrentLevel && CompleteEvoChain.First().Species > MaxSpeciesID_3 && CompleteEvoChain.First().RequiresLvlUp) currengenlevel--; CompleteEvoChain = CompleteEvoChain.Skip(1); }; From dec2787aef398ffbdbd5219df2b983de758d87ef Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 01:23:13 +0100 Subject: [PATCH 12/24] Revert change in form parameter in getValidMoves --- PKHeX/Legality/Core.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 065118bfd..eccd9bdfa 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -1162,7 +1162,7 @@ namespace PKHeX.Core } foreach (DexLevel evo in vs) - r.AddRange(getMoves(pkm, evo.Species, evo.Level, evo.Form, moveTutor, Version, LVL, Tutor, Machine, Generation, MoveReminder)); + r.AddRange(getMoves(pkm, evo.Species, evo.Level, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine, Generation, MoveReminder)); if (pkm.Format <= 3) return r.Distinct().ToArray(); From 036449dfa0ba6d11aedf7474622527b3419e1b87 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 01:33:17 +0100 Subject: [PATCH 13/24] Check future gen evolutions in InhabitedGeneration Return true when format equals generation --- PKHeX/PKM/PKM.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/PKHeX/PKM/PKM.cs b/PKHeX/PKM/PKM.cs index 076006eaf..951bb7480 100644 --- a/PKHeX/PKM/PKM.cs +++ b/PKHeX/PKM/PKM.cs @@ -453,7 +453,11 @@ namespace PKHeX.Core if (species < 0) species = Species; - if (Format == 1 && Generation ==2 && Legal.MaxSpeciesID_2 >= species) + if (Format == 1 && Generation ==2 && (Legal.MaxSpeciesID_2 >= species || Legal.FutureEvolutionsGen2.Contains(species))) + return true; + + if (Format == Generation) + //Every pokemon even those with illegal data inhabit the generation of its current format return true; if (Format < Generation) @@ -463,7 +467,7 @@ namespace PKHeX.Core return false; // Sanity Check Species ID - if (Legal.getMaxSpeciesOrigin(GenNumber) < species) + if (Legal.getMaxSpeciesOrigin(GenNumber) < species && !Legal.getFutureGenEvolutions(GenNumber).Contains(species)) return false; int gen = GenNumber; From 26b9308890ead2a8409aebd5fd8f579a6c34f091 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 03:03:29 +0100 Subject: [PATCH 14/24] Fix in getValidEncounterSlots --- PKHeX/Legality/Core.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index eccd9bdfa..d24a479d7 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -1054,13 +1054,7 @@ namespace PKHeX.Core if (slotMax != null) slotMax = new EncounterSlot(slotMax) { Pressure = true, Form = pkm.AltForm }; - if (gen < 4) - { - if (slotMax != null) - slotdata.Add(slotMax); - return slotdata; - } - if (gen == 6 || !DexNav) + if (gen >= 6 && !DexNav) { // Filter for Form Specific slotdata.AddRange(WildForms.Contains(pkm.Species) @@ -1072,7 +1066,7 @@ namespace PKHeX.Core } List eslots = encounterSlots.Where(slot => !WildForms.Contains(pkm.Species) || slot.Form == pkm.AltForm).ToList(); - if(gen <=4) + if(gen <= 5) { slotdata.AddRange(eslots); return slotdata; From 98e11e233225bae34f112ac341eb23546b021e2b Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 10:33:31 +0100 Subject: [PATCH 15/24] Remove unnecesary use of linq --- PKHeX/Legality/Structures/EvolutionTree.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PKHeX/Legality/Structures/EvolutionTree.cs b/PKHeX/Legality/Structures/EvolutionTree.cs index fd6b9376d..53a705483 100644 --- a/PKHeX/Legality/Structures/EvolutionTree.cs +++ b/PKHeX/Legality/Structures/EvolutionTree.cs @@ -420,18 +420,18 @@ namespace PKHeX.Core { dl.Last().MinLevel = 1; } - else if(evo.Level ==0) //Evolutions like frienship, picho -> pikachu, eeve -> umbreon, etc + else if(evo.Level ==0) //Evolutions like frienship, pichu -> pikachu, eevee -> umbreon, etc { dl.Last().MinLevel = 2; - if (dl.Count() > 1 && !dl.First().RequiresLvlUp) + if (dl.Count > 1 && !dl.First().RequiresLvlUp) dl.First().MinLevel = 2; //Raichu from Pikachu would have minimun level 1, but with Pichu included Raichu minimun level is 2 } else //level up evolutions { dl.Last().MinLevel = evo.Level; - if (dl.Count() > 1 && dl.First().MinLevel < evo.Level && !dl.First().RequiresLvlUp) + if (dl.Count > 1 && dl.First().MinLevel < evo.Level && !dl.First().RequiresLvlUp) dl.First().MinLevel = evo.Level; //Pokemon like Nidoqueen, its minimun level is Nidorina minimun level - if (dl.Count() > 1 && dl.First().MinLevel <= evo.Level && dl.First().RequiresLvlUp) + if (dl.Count > 1 && dl.First().MinLevel <= evo.Level && dl.First().RequiresLvlUp) dl.First().MinLevel = evo.Level + 1; //Pokemon like Crobat, its minimun level is Golbat minimun level + 1 } dl.Last().RequiresLvlUp = evo.RequiresLevelUp; From 3a830ca682c2d82479a13b864d5858b15937800f Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 10:35:14 +0100 Subject: [PATCH 16/24] Check if pokemon is inside an egg in getEvolutionChainsAllGens Add special conditions for gen1 encounters and chains for spcies in gen2 future evolutions Use current level to filter encounter slot for pokemon in format 1 and 2 --- PKHeX/Legality/Checks.cs | 4 ++-- PKHeX/Legality/Core.cs | 42 ++++++++++++++++++++++++++++++++------- PKHeX/Legality/Tables1.cs | 6 ++++++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index a96fe8d82..3108cb8d6 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -526,9 +526,9 @@ namespace PKHeX.Core { // Since encounter matching is super weak due to limited stored data in the structure // Calculate all 3 at the same time and pick the best result (by species). - var s = Legal.getValidStaticEncounter(pkm); + var s = Legal.getValidStaticEncounter(pkm, gen1Encounter: true); var e = Legal.getValidWildEncounters(pkm); - var t = Legal.getValidIngameTrade(pkm); + var t = Legal.getValidIngameTrade(pkm, gen1Encounter: true); const byte invalid = 255; diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index d24a479d7..cc8cec415 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -276,10 +276,17 @@ namespace PKHeX.Core s.AddRange(getValidEncounterSlots(pkm, area, DexNav: pkm.AO)); return s.Any() ? s.ToArray() : null; } - internal static EncounterStatic getValidStaticEncounter(PKM pkm) + internal static EncounterStatic getValidStaticEncounter(PKM pkm, bool gen1Encounter = false) { // Get possible encounters IEnumerable poss = getStaticEncounters(pkm); + + int lvl = (pkm.Format < 3) ? pkm.CurrentLevel : pkm.Met_Level; + if (pkm.Gen3 && pkm.Format > 4 && lvl == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) + lvl--; + if (gen1Encounter && (pkm.Format == 2 || pkm.VC2) && lvl == pkm.CurrentLevel && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) + lvl--; + // Back Check against pkm foreach (EncounterStatic e in poss) { @@ -291,12 +298,12 @@ namespace PKHeX.Core { if (e.Location != 0 && e.Location != pkm.Met_Location) continue; - if (e.Level != pkm.Met_Level) + if (e.Level != lvl) continue; } else { - if (e.Level > pkm.Met_Level) + if (e.Level > lvl) continue; } if (e.Gender != -1 && e.Gender != pkm.Gender) @@ -317,7 +324,7 @@ namespace PKHeX.Core } return null; } - internal static EncounterTrade getValidIngameTrade(PKM pkm) + internal static EncounterTrade getValidIngameTrade(PKM pkm, bool gen1Encounter = false) { if (!pkm.WasIngameTrade) return null; @@ -325,6 +332,12 @@ namespace PKHeX.Core if (lang == 0 || lang == 6) return null; + int lvl = (pkm.Format < 3) ? pkm.CurrentLevel : pkm.Met_Level; + if (pkm.Gen3 && pkm.Format > 4 && lvl == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) + lvl--; + if (gen1Encounter && (pkm.Format == 2 || pkm.VC2) && lvl == pkm.CurrentLevel && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) + lvl--; + // Get valid pre-evolutions IEnumerable p = getValidPreEvolutions(pkm); @@ -355,9 +368,9 @@ namespace PKHeX.Core return null; if (pkm.HasOriginalMetLocation && z.Location != pkm.Met_Location) return null; - if (pkm.HasOriginalMetLocation && z.Level != pkm.Met_Level) + if (pkm.HasOriginalMetLocation && z.Level != lvl) return null; - if (!pkm.HasOriginalMetLocation && z.Level > pkm.Met_Level) + if (!pkm.HasOriginalMetLocation && z.Level > lvl) return null; if (z.Nature != Nature.Random && (int)z.Nature != pkm.Nature) return null; @@ -808,6 +821,15 @@ namespace PKHeX.Core GensEvoChains[pkm.Format] = CompleteEvoChain.ToArray(); return GensEvoChains; } + //If is egg skip the other checks and just return the evo chain for GenNumber, that will contains only the pokemon inside the egg + //Empty list returned if is an impossible egg (like a gen 3 infernape inside an egg) + if (pkm.IsEgg && getMaxSpeciesOrigin(pkm.GenNumber) > pkm.Species) + return GensEvoChains; + else if (pkm.IsEgg) + { + GensEvoChains[pkm.GenNumber] = CompleteEvoChain.ToArray(); + return GensEvoChains; + } int currengenlevel = pkm.CurrentLevel; int maxgen = (pkm.Format <= 2) ? 2 : pkm.Format; @@ -822,9 +844,10 @@ namespace PKHeX.Core if (!pkm.HasOriginalMetLocation && pkm.Format >2 && gen <= 4 && currengenlevel > pkm.Met_Level) //Met location was lost at this point but it also means the pokemon existed in generations 1 to 4 with maximun level equals to met level currengenlevel = pkm.Met_Level; + int maxspeciesgen = getMaxSpeciesOrigin(gen); //Remove future gen evolutions after a few special considerations, //it the pokemon origin is illegal like a "gen 3" Infernape the list will be emptied, it didnt existed in gen 3 in any evolution phase - while (CompleteEvoChain.Any() && CompleteEvoChain.First().Species > getMaxSpeciesOrigin(gen)) + while (CompleteEvoChain.Any() && CompleteEvoChain.First().Species > maxspeciesgen) { //Eeve requieres to level one time to be Sylveon, it can be deduced in gen 5 and before it existed with maximun one level bellow current if (CompleteEvoChain.First().Species == 700 && gen == 5) @@ -834,6 +857,9 @@ namespace PKHeX.Core //but if current level is met level we can also deduce it existed in gen 3 until maximun met level -1 if (gen == 3 && pkm.Format>4 && currengenlevel == pkm.CurrentLevel && CompleteEvoChain.First().Species > MaxSpeciesID_3 && CompleteEvoChain.First().RequiresLvlUp) currengenlevel--; + //The same condition for gen2 evolution of gen 1 pokemon, level of the pokemon in gen 1 games would be CurrentLevel -1 one level bellow gen 2 level + if (gen == 1 && (pkm.Format == 2 || pkm.VC2 ) && currengenlevel == pkm.CurrentLevel && CompleteEvoChain.First().Species > MaxSpeciesID_1 && CompleteEvoChain.First().RequiresLvlUp) + currengenlevel--; CompleteEvoChain = CompleteEvoChain.Skip(1); }; //Alolan form evolutions, remove from gens 1-6 chains @@ -1034,6 +1060,8 @@ namespace PKHeX.Core //See comments in getEvolutionChainsAllGens for more info in this sentence if (gen == 3 && pkm.Format > 4 && lvl == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) lvl--; + if (gen == 1 && ( pkm.Format == 2 || pkm.VC2 ) && lvl == pkm.CurrentLevel && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) + lvl--; //Those encounters with level min greater that met level are not valid for this pokemon encounterSlots = slots.Where(slot => ignoreLevel || slot.LevelMin <= lvl).ToList(); } diff --git a/PKHeX/Legality/Tables1.cs b/PKHeX/Legality/Tables1.cs index 9b52ab7e5..7770d500b 100644 --- a/PKHeX/Legality/Tables1.cs +++ b/PKHeX/Legality/Tables1.cs @@ -119,5 +119,11 @@ namespace PKHeX.Core { 169,182,186,196,197,199,208,212,230,233,242,462,463,464,465,466,467,470,471,474,700 }; + + internal static readonly int[] FutureEvolutionsGen1_Gen2LevelUp = new int[] + { + 169,196,197,242 + }; + //Crobat Espeon Umbreon Blissey } } From 85e25dad5cd91e8f026f8986b53fb4676ced3aa4 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 10:43:27 +0100 Subject: [PATCH 17/24] Fix for VC2 --- PKHeX/Legality/Core.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index cc8cec415..30d9bdffa 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -833,7 +833,7 @@ namespace PKHeX.Core int currengenlevel = pkm.CurrentLevel; int maxgen = (pkm.Format <= 2) ? 2 : pkm.Format; - int mingen = (pkm.Format <= 2) ? 1 : pkm.GenNumber; + int mingen = (pkm.VC2 || pkm.Format <= 2) ? 1 : pkm.GenNumber; //Iterate generations backwards because level will be decreased from current level in each generation for (int gen = maxgen; gen >= mingen; gen--) { From f0b4c83365b852af4e3d2e787a51e1412888d72c Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 11:59:07 +0100 Subject: [PATCH 18/24] Create a function to obtain the max and min possible level a given pokemon could have in a given generation --- PKHeX/Legality/Core.cs | 70 ++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 30d9bdffa..00d176fc5 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -281,11 +281,7 @@ namespace PKHeX.Core // Get possible encounters IEnumerable poss = getStaticEncounters(pkm); - int lvl = (pkm.Format < 3) ? pkm.CurrentLevel : pkm.Met_Level; - if (pkm.Gen3 && pkm.Format > 4 && lvl == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) - lvl--; - if (gen1Encounter && (pkm.Format == 2 || pkm.VC2) && lvl == pkm.CurrentLevel && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) - lvl--; + int lvl = (pkm.HasOriginalMetLocation) ? pkm.Met_Level : getMaxLevelGeneration(pkm); // Back Check against pkm foreach (EncounterStatic e in poss) @@ -332,11 +328,7 @@ namespace PKHeX.Core if (lang == 0 || lang == 6) return null; - int lvl = (pkm.Format < 3) ? pkm.CurrentLevel : pkm.Met_Level; - if (pkm.Gen3 && pkm.Format > 4 && lvl == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) - lvl--; - if (gen1Encounter && (pkm.Format == 2 || pkm.VC2) && lvl == pkm.CurrentLevel && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) - lvl--; + int lvl = (pkm.HasOriginalMetLocation) ? pkm.Met_Level : getMaxLevelGeneration(pkm); // Get valid pre-evolutions IEnumerable p = getValidPreEvolutions(pkm); @@ -808,7 +800,53 @@ namespace PKHeX.Core default: return evos.Length <= 0 ? pkm.Species : evos.Last().Species; } } + internal static int getMaxLevelGeneration(PKM pkm) + { + return getMaxLevelGeneration(pkm, pkm.GenNumber); + } + internal static int getMaxLevelGeneration(PKM pkm, int generation) + { + if (!pkm.InhabitedGeneration(generation)) + return 0; + if (pkm.Format <= 2) + { + if (generation == 1 && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) + return pkm.CurrentLevel - 1; + return pkm.CurrentLevel; + } + + if (pkm.Species == 700 && generation == 5) + return pkm.CurrentLevel - 1; + + if (pkm.Gen3 && pkm.Format > 4 && pkm.Met_Level == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) + return pkm.Met_Level - 1; + if (pkm.VC2 && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) + return pkm.Met_Level - 1; + + return pkm.CurrentLevel; + } + + internal static int getMinLevelGeneration(PKM pkm) + { + return getMinLevelGeneration(pkm, pkm.GenNumber); + } + internal static int getMinLevelGeneration(PKM pkm, int generation) + { + if (!pkm.InhabitedGeneration(generation)) + return 0; + + if (pkm.Format <= 2) + return 2; + + if(!pkm.HasOriginalMetLocation) + return pkm.Met_Level; + + if (pkm.GenNumber <= 3) + return 2; + + return 1; + } internal static DexLevel[][] getEvolutionChainsAllGens(PKM pkm, object Encounter) { IEnumerable CompleteEvoChain = getEvolutionChain(pkm, Encounter); @@ -1049,22 +1087,14 @@ namespace PKHeX.Core bool ignoreSlotLevel = ignoreLevel; IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && (ignoreSlotLevel || evo.Level >= slot.LevelMin - df))); - // Filter for Met Level - int lvl = (pkm.Format < 3) ? pkm.CurrentLevel : pkm.Met_Level; + int lvl = (pkm.HasOriginalMetLocation) ? pkm.Met_Level: getMaxLevelGeneration(pkm); int gen = pkm.GenNumber; IEnumerable encounterSlots; if(pkm.HasOriginalMetLocation) encounterSlots = slots.Where(slot => ignoreLevel || slot.LevelMin - df <= lvl && lvl <= slot.LevelMax + (slot.AllowDexNav ? dn : df)).ToList(); else - { - //See comments in getEvolutionChainsAllGens for more info in this sentence - if (gen == 3 && pkm.Format > 4 && lvl == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) - lvl--; - if (gen == 1 && ( pkm.Format == 2 || pkm.VC2 ) && lvl == pkm.CurrentLevel && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) - lvl--; //Those encounters with level min greater that met level are not valid for this pokemon encounterSlots = slots.Where(slot => ignoreLevel || slot.LevelMin <= lvl).ToList(); - } if(gen <= 2) { @@ -1233,6 +1263,8 @@ namespace PKHeX.Core { case 1: { + if (species > MaxSpeciesID_1)//Sanity check + return r; var pi_rb = (PersonalInfoG1)PersonalTable.RB[species]; var pi_y = (PersonalInfoG1)PersonalTable.Y[species]; if (LVL) From 801b4f97d9f291842708444f17376453f5845dc4 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 12:01:18 +0100 Subject: [PATCH 19/24] Do not decrease level for VC2 evolved pokemon in gen 1, they could have evolve in gen7 games --- PKHeX/Legality/Core.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 00d176fc5..22ae63ed1 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -821,8 +821,6 @@ namespace PKHeX.Core if (pkm.Gen3 && pkm.Format > 4 && pkm.Met_Level == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) return pkm.Met_Level - 1; - if (pkm.VC2 && FutureEvolutionsGen1_Gen2LevelUp.Contains(pkm.Species)) - return pkm.Met_Level - 1; return pkm.CurrentLevel; } @@ -896,7 +894,7 @@ namespace PKHeX.Core if (gen == 3 && pkm.Format>4 && currengenlevel == pkm.CurrentLevel && CompleteEvoChain.First().Species > MaxSpeciesID_3 && CompleteEvoChain.First().RequiresLvlUp) currengenlevel--; //The same condition for gen2 evolution of gen 1 pokemon, level of the pokemon in gen 1 games would be CurrentLevel -1 one level bellow gen 2 level - if (gen == 1 && (pkm.Format == 2 || pkm.VC2 ) && currengenlevel == pkm.CurrentLevel && CompleteEvoChain.First().Species > MaxSpeciesID_1 && CompleteEvoChain.First().RequiresLvlUp) + if (gen == 1 && pkm.Format == 2 && currengenlevel == pkm.CurrentLevel && CompleteEvoChain.First().Species > MaxSpeciesID_1 && CompleteEvoChain.First().RequiresLvlUp) currengenlevel--; CompleteEvoChain = CompleteEvoChain.Skip(1); }; From 4ccbce5f24a9a7a4cf89aaab4ab18f5f4f656efd Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 12:06:05 +0100 Subject: [PATCH 20/24] Fix VC2 --- PKHeX/PKM/PKM.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKHeX/PKM/PKM.cs b/PKHeX/PKM/PKM.cs index 951bb7480..32dd885ec 100644 --- a/PKHeX/PKM/PKM.cs +++ b/PKHeX/PKM/PKM.cs @@ -473,7 +473,7 @@ namespace PKHeX.Core int gen = GenNumber; switch (Generation) { - case 1: return Format == 1 || VC1; + case 1: return Format == 1 || VC; case 2: return Format <= 2 || VC2; case 3: return Gen3; case 4: return 3 <= gen && gen <= 4; From c9bdcdd46481373c22a674439cc7a2d3b4d3d995 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 12:13:06 +0100 Subject: [PATCH 21/24] Do not return encounters if maximun level for a generation is 0, is an illegal level encounter --- PKHeX/Legality/Core.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 22ae63ed1..86f384ac6 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -282,7 +282,8 @@ namespace PKHeX.Core IEnumerable poss = getStaticEncounters(pkm); int lvl = (pkm.HasOriginalMetLocation) ? pkm.Met_Level : getMaxLevelGeneration(pkm); - + if (lvl <= 0) + return null; ; // Back Check against pkm foreach (EncounterStatic e in poss) { @@ -329,7 +330,8 @@ namespace PKHeX.Core return null; int lvl = (pkm.HasOriginalMetLocation) ? pkm.Met_Level : getMaxLevelGeneration(pkm); - + if (lvl <= 0) + return lvl; // Get valid pre-evolutions IEnumerable p = getValidPreEvolutions(pkm); @@ -1086,6 +1088,8 @@ namespace PKHeX.Core IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && (ignoreSlotLevel || evo.Level >= slot.LevelMin - df))); int lvl = (pkm.HasOriginalMetLocation) ? pkm.Met_Level: getMaxLevelGeneration(pkm); + if (lvl <= 0) + return slotdata; int gen = pkm.GenNumber; IEnumerable encounterSlots; if(pkm.HasOriginalMetLocation) From 0b0dd21d93cef1e6ae1e01b4d2328c7de6fd5d4f Mon Sep 17 00:00:00 2001 From: javierhimura Date: Thu, 16 Feb 2017 12:14:10 +0100 Subject: [PATCH 22/24] Fix for the last commit --- PKHeX/Legality/Core.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 86f384ac6..c7c9865ad 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -331,7 +331,7 @@ namespace PKHeX.Core int lvl = (pkm.HasOriginalMetLocation) ? pkm.Met_Level : getMaxLevelGeneration(pkm); if (lvl <= 0) - return lvl; + return null; // Get valid pre-evolutions IEnumerable p = getValidPreEvolutions(pkm); From 56ccddce8d6f9a08b4ce4b7532c01d83237e1005 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Fri, 17 Feb 2017 14:56:50 +0100 Subject: [PATCH 23/24] getMaxLevelGeneration should return met level when met level data is lost --- PKHeX/Legality/Core.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index c7c9865ad..ab6255eb5 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -824,7 +824,10 @@ namespace PKHeX.Core if (pkm.Gen3 && pkm.Format > 4 && pkm.Met_Level == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) return pkm.Met_Level - 1; - return pkm.CurrentLevel; + if(!pkm.HasOriginalMetLocation)) + return pkm.Met_Level; + + return pkm.CurrentLevel; } internal static int getMinLevelGeneration(PKM pkm) From a1cca754d79d6c8d150209a89e9c6bdd48e6f28b Mon Sep 17 00:00:00 2001 From: javierhimura Date: Fri, 17 Feb 2017 16:16:39 +0100 Subject: [PATCH 24/24] getMaxLevelGeneration should return met level when pokemon does not HasOriginalMetLocation and is not one of the special cases already considered --- PKHeX/Legality/Core.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index ab6255eb5..21afca5e9 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -824,7 +824,7 @@ namespace PKHeX.Core if (pkm.Gen3 && pkm.Format > 4 && pkm.Met_Level == pkm.CurrentLevel && FutureEvolutionsGen3_LevelUp.Contains(pkm.Species)) return pkm.Met_Level - 1; - if(!pkm.HasOriginalMetLocation)) + if(!pkm.HasOriginalMetLocation) return pkm.Met_Level; return pkm.CurrentLevel;