From 007105b85242c46534ecfa3d5be66c3f9cfb5c17 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 13:26:33 +0100 Subject: [PATCH 1/9] Add optional paramter in functions getMoves and getValidmoves to not remove HM moves on transfer from gen 3 and 4 to next 4 and 5 --- PKHeX/Legality/Core.cs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 0f4809a4a..defc7365f 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -548,19 +548,19 @@ private static EncounterArea[] getTables2(GameVersion Version) } // Moves - internal static IEnumerable getValidMoves(PKM pkm, DexLevel[][] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true) + internal static IEnumerable getValidMoves(PKM pkm, DexLevel[][] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) { GameVersion version = (GameVersion)pkm.Version; if (!pkm.IsUntraded) version = GameVersion.Any; - return getValidMoves(pkm, version, evoChains, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder); + return getValidMoves(pkm, version, evoChains, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM: RemoveTransferHM); } - internal static IEnumerable getValidMoves(PKM pkm, DexLevel[] evoChain, int generation, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true) + internal static IEnumerable getValidMoves(PKM pkm, DexLevel[] evoChain, int generation, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) { GameVersion version = (GameVersion)pkm.Version; if (!pkm.IsUntraded) version = GameVersion.Any; - return getValidMoves(pkm, version, evoChain, generation, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder); + return getValidMoves(pkm, version, evoChain, generation, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM : RemoveTransferHM); } internal static IEnumerable getValidRelearn(PKM pkm, int skipOption) { @@ -2007,7 +2007,7 @@ private static IEnumerable getStatic(PKM pkm, IEnumerable dl = getValidPreEvolutions(pkm, lvl); return table.Where(e => dl.Any(d => d.Species == e.Species)); } - private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, IReadOnlyList vs, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true) + private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, IReadOnlyList vs, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true) { List r = new List { 0 }; if (Relearn && pkm.Format >= 6) @@ -2015,11 +2015,11 @@ private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, IRea for (int gen = pkm.GenNumber; gen <= pkm.Format; gen++) if (vs[gen].Any()) - r.AddRange(getValidMoves(pkm, Version, vs[gen], gen, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder)); + r.AddRange(getValidMoves(pkm, Version, vs[gen], gen, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM: RemoveTransferHM)); return r.Distinct().ToArray(); } - private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, DexLevel[] vs, int Generation, 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, int Generation, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true) { List r = new List { 0 }; if (!vs.Any()) @@ -2033,13 +2033,13 @@ private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, DexL { int formcount = pkm.PersonalInfo.FormeCount; for (int i = 0; i < formcount; i++) - r.AddRange(getMoves(pkm, species, vs.First().Level, i, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, Generation)); + r.AddRange(getMoves(pkm, species, vs.First().Level, i, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation)); if (Relearn) r.AddRange(pkm.RelearnMoves); return r.Distinct(); } foreach (DexLevel evo in vs) - r.AddRange(getMoves(pkm, evo.Species, evo.Level, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, Generation)); + r.AddRange(getMoves(pkm, evo.Species, evo.Level, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation)); if (pkm.Format <= 3) return r.Distinct(); @@ -2068,7 +2068,7 @@ private static IEnumerable getValidMoves(PKM pkm, GameVersion Version, DexL r.AddRange(pkm.RelearnMoves); return r.Distinct(); } - private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder) + private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder, bool RemoveTransferHM) { List r = new List { 0 }; int gen = pkm.GenNumber; @@ -2077,16 +2077,16 @@ private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form int max = pkm.Format < 3 ? 2 : 1; for (; gen <= max; gen++) if (pkm.InhabitedGeneration(gen, species)) - r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, MoveReminder, gen)); + r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, MoveReminder, RemoveTransferHM, gen)); gen = 7; } for (; gen <= pkm.Format; gen++) if (pkm.InhabitedGeneration(gen)) - r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, MoveReminder, gen)); + r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, MoveReminder, RemoveTransferHM, gen)); return r.Distinct(); } - private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder, int Generation) + private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder, bool RemoveTransferHM, int Generation) { List r = new List(); @@ -2163,12 +2163,12 @@ private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form { var pi_c = PersonalTable.E[index]; r.AddRange(TM_3.Where((t, m) => pi_c.TMHM[m])); - if (pkm.Format == 3) // HM moves must be removed for 3->4, only give if current format. + if (!RemoveTransferHM || pkm.Format == 3) // HM moves must be removed for 3->4, only give if current format. r.AddRange(HM_3.Where((t, m) => pi_c.TMHM[m+50])); } if (moveTutor) r.AddRange(getTutorMoves(pkm, species, form, specialTutors, Generation)); - if (pkm.Format > 3) //Remove HM + if (RemoveTransferHM && pkm.Format > 3) //Remove HM r = r.Except(HM_3).ToList(); break; } @@ -2188,7 +2188,7 @@ private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form var pi_hgss = PersonalTable.HGSS[index]; var pi_dppt = PersonalTable.Pt[index]; r.AddRange(TM_4.Where((t, m) => pi_hgss.TMHM[m])); - if (pkm.Format > 4) + if (RemoveTransferHM && pkm.Format > 4) { // The combination of both these moves is illegal, it should be checked that the pokemon only learn one // except if it can learn any of these moves in gen 5 or later @@ -2205,7 +2205,7 @@ private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form } if (moveTutor) r.AddRange(getTutorMoves(pkm, species, form, specialTutors, Generation)); - if (pkm.Format > 4) //Remove HM + if (RemoveTransferHM && pkm.Format > 4) //Remove HM r = r.Except(HM_4_RemovePokeTransfer).ToList(); break; } From 2fd67b98cab5a608a402b9d2185e189ef5e49a2d Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 13:27:42 +0100 Subject: [PATCH 2/9] Add getValidMovesAllGens to return the valid moves list from every valid generation from a pokemon instead of one list with all generations mixed, for crossgen legal analysis --- PKHeX/Legality/Core.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index defc7365f..942e15acc 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -548,6 +548,13 @@ private static EncounterArea[] getTables2(GameVersion Version) } // Moves + internal static int[][] getValidMovesAllGens(PKM pkm, DexLevel[][] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) + { + int[][] Moves = new int[evoChains.Length][]; + for (int i = 1; i < evoChains.Length; i++) + Moves[i] = getValidMoves(pkm, evoChains[i], i, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM).ToArray(); + return Moves; + } internal static IEnumerable getValidMoves(PKM pkm, DexLevel[][] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) { GameVersion version = (GameVersion)pkm.Version; From 82b200681eefd3e745807c266ef73b0f3b405cfc Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 16:41:45 +0100 Subject: [PATCH 3/9] Cross generation check moves --- PKHeX/Legality/Analysis.cs | 18 +++ PKHeX/Legality/CheckStrings.cs | 10 ++ PKHeX/Legality/Checks.cs | 196 ++++++++++++++++++++---- PKHeX/Legality/Core.cs | 22 +++ PKHeX/Resources/text/en/legality_en.txt | 11 +- 5 files changed, 228 insertions(+), 29 deletions(-) diff --git a/PKHeX/Legality/Analysis.cs b/PKHeX/Legality/Analysis.cs index bd6cbeb0d..49e4daa07 100644 --- a/PKHeX/Legality/Analysis.cs +++ b/PKHeX/Legality/Analysis.cs @@ -385,5 +385,23 @@ private static int getSuggestedTransferLocation(PKM pkm) return 30001; return -1; } + private static int[] getGenMovesCheckOrder(PKM pkm) + { + if (pkm.Format == 1) + return new [] { 1, 2 }; + else if (pkm.Format == 2) + return new [] { 2, 1 }; + else if (pkm.Format == 7 && pkm.VC1) + return new [] { 7, 1 }; + else if (pkm.Format == 7 && pkm.VC2) + return new [] { 7, 2, 1 }; + else + { + var order = new int[pkm.Format - pkm.GenNumber + 1]; + for (int i = 0; i < order.Length; i++) + order[i] = pkm.Format - i; + return order; + } + } } } diff --git a/PKHeX/Legality/CheckStrings.cs b/PKHeX/Legality/CheckStrings.cs index 761b8ae31..a6a4e9870 100644 --- a/PKHeX/Legality/CheckStrings.cs +++ b/PKHeX/Legality/CheckStrings.cs @@ -90,6 +90,10 @@ public static string[] getLocalization(string[] existingLines = null) public static string V174 { get; set; } = "Learned by Move Tutor."; public static string V175 { get; set; } = "Special Non-Relearn Move."; public static string V177 { get; set; } = "Learned by Level-up."; + public static string V330 { get; set; } = "Learned by Level-up in generation {0}."; + public static string V331 { get; set; } = "Learned by TM/HM in generation {0}."; + public static string V332 { get; set; } = "Learned by Move Tutor in generation {0}."; + public static string V333 { get; set; } = "Event Egg Move."; #endregion @@ -353,6 +357,12 @@ public static string[] getLocalization(string[] existingLines = null) public static string V327 {get; set;} = "Special ingame N's Sparkle flag should not be checked."; public static string V328 {get; set;} = "Version Specific evolution requires a trade to opposite version. A Handling Trainer is required."; + public static string V334 {get; set;} = "Non-tradeback egg move. Incompatible with generation 1 exclusive moves."; + public static string V335 {get; set;} = "Generation 1 exclusive move. Incompatible with Non-tradeback egg moves."; + public static string V336 {get; set;} = "Egg Move. Incompatible with event egg moves."; + public static string V337 {get; set;} = "Event Egg Move. Incompatible with normal egg moves."; + public static string V338 {get; set;} = "Defog and whirpool. One of the two moves should have been removed before transfered to generation 5."; + public static string V339 {get; set;} = "Generation {0} HM. Should have been removed before transfered to generation {1}."; #endregion } diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index abaa71c07..88cf3c1c2 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -2021,10 +2021,10 @@ private void verifyVersionEvolution() private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any) { - var validLevelMoves = Legal.getValidMoves(pkm, EvoChainsAllGens, Tutor: false, Machine: false).ToArray(); - var validTMHM = Legal.getValidMoves(pkm, EvoChainsAllGens, LVL: false, Tutor: false, MoveReminder: false).ToArray(); - var validTutor = Legal.getValidMoves(pkm, EvoChainsAllGens, LVL: false, Machine: false, MoveReminder: false).ToArray(); - + var validLevelMoves = Legal.getValidMovesAllGens(pkm, EvoChainsAllGens, Tutor: false, Machine: false, RemoveTransferHM:false); + var validTMHM = Legal.getValidMovesAllGens(pkm, EvoChainsAllGens, LVL: false, Tutor: false, MoveReminder: false, RemoveTransferHM: false); + var validTutor = Legal.getValidMovesAllGens(pkm, EvoChainsAllGens, LVL: false, Machine: false, MoveReminder: false, RemoveTransferHM: false); + Legal.RemoveFutureMoves(pkm, EvoChainsAllGens, ref validLevelMoves, ref validTMHM, ref validTutor); CheckResult[] res; int[] Moves = pkm.Moves; if (pkm.Species == 235) // Smeargle can have any move except a few @@ -2050,13 +2050,13 @@ private CheckResult[] parseMovesSketch(int[] Moves) : new CheckResult(CheckIdentifier.Move); return res; } - private CheckResult[] parseMovesGetGift(int[] Moves, int[] validLevelMoves, int[] validTMHM, int[] validTutor) + private CheckResult[] parseMovesGetGift(int[] Moves, int[][] validLevelMoves, int[][] validTMHM, int[][] validTutor) { int[] RelearnMoves = pkm.RelearnMoves; foreach (MysteryGift mg in EventGiftMatch) { int[] SpecialMoves = mg.Moves; - CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0]); + CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], new int[0]); if (res.Any(r => !r.Valid)) continue; @@ -2067,18 +2067,19 @@ private CheckResult[] parseMovesGetGift(int[] Moves, int[] validLevelMoves, int[ } // no Mystery Gifts matched - return parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, new int[0], new int[0]); + return parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, new int[0], new int[0], new int[0]); } - private CheckResult[] parseMovesRegular(int[] Moves, int[] validLevelMoves, int[] validTMHM, int[] validTutor, GameVersion game) + private CheckResult[] parseMovesRegular(int[] Moves, int[][] validLevelMoves, int[][] validTMHM, int[][] validTutor, GameVersion game) { int[] EggMoves = pkm.WasEgg ? Legal.getEggMoves(pkm, game).ToArray() : new int[0]; + int[] EventEggMoves = new int[0]; int[] RelearnMoves = pkm.RelearnMoves; int[] SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ?? (EncounterMatch as EncounterStatic)?.Moves ?? (EncounterMatch as EncounterTrade)?.Moves ?? new int[0]; - CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, EggMoves); + CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, EggMoves, EventEggMoves); if (pkm.GenNumber < 6) return res; @@ -2089,31 +2090,170 @@ private CheckResult[] parseMovesRegular(int[] Moves, int[] validLevelMoves, int[ return res; } - private static CheckResult[] parseMoves(int[] moves, int[] learn, int[] relearn, int[] tmhm, int[] tutor, int[] special, int[] egg) + private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[][] tmhm, int[][] tutor, int[] special, int[] egg, int[] eventegg) { CheckResult[] res = new CheckResult[4]; - for (int i = 0; i < 4; i++) + var Gen1MovesLearned = new List(); + var EggMovesLearned = new List(); + var EventEggMovesLearned = new List(); + // Check none moves and relearn moves before generation moves + for (int m = 0; m < 4; m++) { - if (moves[i] == 0) - res[i] = new CheckResult(Severity.Valid, V167, CheckIdentifier.Move); - else if (learn.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, V177, CheckIdentifier.Move); - else if (egg.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, V171, CheckIdentifier.Move) { Flag = true }; - else if (relearn.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, V172, CheckIdentifier.Move) { Flag = true }; - else if (tmhm.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, V173, CheckIdentifier.Move); - else if (tutor.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, V174, CheckIdentifier.Move); - else if (special.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, V175, CheckIdentifier.Move); - else - res[i] = new CheckResult(Severity.Invalid, V176, CheckIdentifier.Move); + if (moves[m] == 0) + res[m] = new CheckResult(Severity.Valid, V167, CheckIdentifier.Move); + else if (relearn.Contains(moves[m])) + res[m] = new CheckResult(Severity.Valid, V172, CheckIdentifier.Move) { Flag = true }; + } + + if (res.All(r => r.Valid)) + return res; + + bool MixedGen1NonTradebackGen2= false; + // Check moves going backwards, marking the move valid in the most current generation when it can be learned + int[] generations = getGenMovesCheckOrder(pkm); + for (int g = 0; g < generations.Length; g++) + { + var gen = generations[g]; + if (!pkm.InhabitedGeneration(gen)) + continue; + + IEnumerable HMLearned = new List(); + // Check if pokemon knows HM moves from generation 3 and 4 but are not valid yet, that means it cant learn the HMs in future generations + bool KnowDefogWhirlpool = false; + if (gen == 4 && pkm.Format > 4) + { + HMLearned = moves.Where((m,i) => !(res[i]?.Valid ?? false) && Legal.HM_4_RemovePokeTransfer.Any(l => l == m)).Select((m, i) => i); + // Defog and Whirlpool at the same time, also both can't be learned in future generations or else they will be valid + KnowDefogWhirlpool = moves.Where((m, i) => (m == 250 && m == 432) && !(res[i]?.Valid ?? false)).Count() == 2; + } + else if (gen == 3 && pkm.Format > 3) + HMLearned = moves.Where((m, i) => !(res[i]?.Valid ?? false) && Legal.HM_3.Any(l => l == m)).Select((m, i) => i); + + for (int m = 0; m < 4; m++) + { + if (res[m]?.Valid ?? false) + continue; + + if (learn[m].Contains(moves[m])) + { + res[m] = new CheckResult(Severity.Valid, (gen == pkm.Format)? V177 : String.Format(V330, gen), CheckIdentifier.Move); + if (gen == 1) Gen1MovesLearned.Add(m); + } + else if (tmhm[m].Contains(moves[m])) + { + res[m] = new CheckResult(Severity.Valid, (gen == pkm.Format) ? V173 : String.Format(V331, gen), CheckIdentifier.Move); + if (gen == 1) Gen1MovesLearned.Add(m); + } + else if (tutor[m].Contains(moves[m])) + { + res[m] = new CheckResult(Severity.Valid, (gen == pkm.Format) ? V173 : String.Format(V332, gen), CheckIdentifier.Move); + if (gen == 1) Gen1MovesLearned.Add(m); + } + else if (gen == pkm.GenNumber && special.Contains(moves[m])) + { + res[m] = new CheckResult(Severity.Valid, V175, CheckIdentifier.Move); + if (gen == 1) Gen1MovesLearned.Add(m); + } + } + + if (gen == generations.Length - 1) + { + // Check egg moves after all the generations and all the moves, every move that can be learned in another source should have preference + // the moves that can only be learned from egg moves should in the future check if the move combinations can be breed in gens 2 to 5 + for (int m = 0; m < 4; m++) + { + if (res[m]?.Valid ?? false) + continue; + if (egg.Contains(moves[m])) + { + if (Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) + { + // To learn exclusive generation 1 moves the pokemon was tradeback, but it can be trade to generation 1 + // without removing moves above MaxMoveID_1, egg moves above MaxMoveID_1 and gen 1 moves are incompatible + res[m] = new CheckResult(Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true }; + MixedGen1NonTradebackGen2 = true; + } + else + res[m] = new CheckResult(Severity.Valid, V171, CheckIdentifier.Move) { Flag = true }; + EggMovesLearned.Add(m); + } + if (eventegg.Contains(moves[m])) + { + if(!egg.Contains(moves[m])) + { + if (Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) + { + res[m] = new CheckResult(Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true }; + MixedGen1NonTradebackGen2 = true; + } + else + res[m] = new CheckResult(Severity.Valid, V33, CheckIdentifier.Move) { Flag = true }; + } + EventEggMovesLearned.Add(m); + } + } + + // A pokemon could have normal egg moves and regular egg moves only if all the event egg moves are also regular egg moves + if (!EggMovesLearned.All(e=> EventEggMovesLearned.Contains(e))) + { + for (int m = 0; m < 4; m++) + { + if (EventEggMovesLearned.Contains(m) && !EggMovesLearned.Contains(m)) + res[m] = new CheckResult(Severity.Invalid, V337, CheckIdentifier.Move); + else if (!EventEggMovesLearned.Contains(m) && EggMovesLearned.Contains(m)) + res[m] = new CheckResult(Severity.Invalid, V336, CheckIdentifier.Move); + } + } + + } + + if (3 <= gen && gen <= 4 && gen > pkm.Format) + { + // After all the moves from the generations 3 and 4, + // including egg moves if is the origin generation because some hidden moves are also special egg moves in gen 3 + // Check if the marked hidden moves that were invalid at the start are now marked as valid, that means + // the hidden move was learned in gen 3 or 4 but was not removed when transfer to 4 or 5 + if (KnowDefogWhirlpool) + KnowDefogWhirlpool = moves.Where((m,i) => (m == 250 && m == 432) && (res[i]?.Valid ?? false)).Count() == 2; + + if (KnowDefogWhirlpool) + { + KnowDefogWhirlpool = moves.Where((m, i) => (m == 250 && m == 432) && (res[i]?.Valid ?? false)).Count() == 2; + foreach (int index in moves.Where(m => (m == 250 && m == 432)).Select((move, index) => index)) + { + res[index] = new CheckResult(Severity.Invalid, V338, CheckIdentifier.Move); + } + } + + foreach (int hm in HMLearned.Where(l => res[l]?.Valid ?? false)) + { + res[hm] = new CheckResult(Severity.Invalid, string.Format(V339,gen,gen+1), CheckIdentifier.Move); + } + } + + // Mark the gen 1 exclusive moves as illegal because the pokemon also have Non tradeback egg moves. + if (MixedGen1NonTradebackGen2) + { + foreach (int m in Gen1MovesLearned) + { + res[m] = new CheckResult(Severity.Invalid, V335, CheckIdentifier.Move); + } + } + + if (res.All(r => r.Valid)) + return res; + } + + if (res.All(r => r.Valid)) + return res; + + for (int m = 0; m < 4; m++) + { + if (res[m] == null) + res[m] = new CheckResult(Severity.Invalid, V176, CheckIdentifier.Move); } return res; } - private CheckResult[] verifyRelearn() { RelearnBase = null; diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 942e15acc..7cd95e979 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -548,6 +548,28 @@ private static EncounterArea[] getTables2(GameVersion Version) } // Moves + internal static void RemoveFutureMoves(PKM pkm, DexLevel[][] evoChains, ref int[][] validLevelMoves, ref int[][] validTMHM, ref int[][] validTutor) + { + IEnumerable AllMoves = new List(); + if (pkm.Format > 3) + { + for (int i = evoChains.Length - 1; i > 0; i--) + { + validLevelMoves[i] = validLevelMoves[i].Except(AllMoves).ToArray(); + validTMHM[i] = validTMHM[i].Except(AllMoves).ToArray(); + validTutor[i] = validTutor[i].Except(AllMoves).ToArray(); + AllMoves = AllMoves.Concat(validLevelMoves[i]).Concat(validTMHM[i]).Concat(validTutor[i]); + } + } + else + { + int tradeback = (pkm.Format == 2) ? 1 : 2; + var formatmoves = validLevelMoves[pkm.Format].Concat(validTMHM[pkm.Format]).Concat(validTutor[pkm.Format]); + validLevelMoves[tradeback] = validLevelMoves[tradeback].Except(formatmoves).ToArray(); + validTMHM[tradeback] = validTMHM[tradeback].Except(formatmoves).ToArray(); + validTutor[tradeback] = validTutor[tradeback].Except(formatmoves).ToArray(); + } + } internal static int[][] getValidMovesAllGens(PKM pkm, DexLevel[][] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) { int[][] Moves = new int[evoChains.Length][]; diff --git a/PKHeX/Resources/text/en/legality_en.txt b/PKHeX/Resources/text/en/legality_en.txt index 74ac36425..d931a0c9c 100644 --- a/PKHeX/Resources/text/en/legality_en.txt +++ b/PKHeX/Resources/text/en/legality_en.txt @@ -15,6 +15,9 @@ V173 = Learned by TM/HM. V174 = Learned by Move Tutor. V175 = Special Non-Relearn Move. V177 = Learned by Level-up. +V330 = Learned by Level-up in generation {0}. +V332 = Learned by Move Tutor in generation {0}. +V333 = Event Egg Move. V203 = Genderless Pokémon should not have a gender. V201 = Encryption Constant is not set. V204 = Held item is unreleased. @@ -245,4 +248,10 @@ V324 = Special ingame Fateful Encounter flag missing. V325 = Fateful Encounter should not be checked. V326 = Special ingame N's Sparkle flag missing. V327 = Special ingame N's Sparkle flag should not be checked. -V328 = Version Specific evolution requires a trade to opposite version. A Handling Trainer is required. \ No newline at end of file +V328 = Version Specific evolution requires a trade to opposite version. A Handling Trainer is required. +V334 = Non-tradeback egg move. Incompatible with generation 1 exclusive moves. +V335 = Generation 1 exclusive move. Incompatible with Non-tradeback egg moves. +V336 = Egg Move. Incompatible with event egg moves. +V337 = Event Egg Move. Incompatible with normal egg moves. +V338 = Defog and whirpool. One of the two moves should have been removed before transfered to generation 5. +V339 = Generation {0} HM. Should have been removed before transfered to generation {1}. \ No newline at end of file From 8d4ad809491f30f9c295825b435eb77c6aa4734a Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 18:12:48 +0100 Subject: [PATCH 4/9] Gen 2 WasEgg fix --- 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 190857cb2..24127b689 100644 --- a/PKHeX/PKM/PKM.cs +++ b/PKHeX/PKM/PKM.cs @@ -422,7 +422,7 @@ public virtual bool WasEgg { get { - if (HasOriginalMetLocation) + if (Format > 2 && HasOriginalMetLocation) return Egg_Location > 0; return _WasEgg; } set { _WasEgg = value; } From 69d562685cbde787d3b42a0a66a2671c95dc81c6 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 18:14:57 +0100 Subject: [PATCH 5/9] Gen 2 get moves, returns crystal egg moves by default when origin can not be determined return gold/silver egg moves in the cases when origin can be proven is not from crystal --- PKHeX/Legality/Core.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 7cd95e979..b627c9db1 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -2339,15 +2339,13 @@ private static IEnumerable getEggMoves(PKM pkm, int species, int formnum, G { case 1: case 2: - switch (Version) - { - case GameVersion.GS: - return EggMovesGS[species].Moves; - case GameVersion.C: - return EggMovesC[species].Moves; - default: - return new List(); - } + if (pkm.Format != 2) + return EggMovesC[species].Moves; + if (pkm.HasOriginalMetLocation) + return EggMovesC[species].Moves; + if (pkm.Species > 151 && !FutureEvolutionsGen1.Contains(pkm.Species)) + return EggMovesGS[species].Moves; + return new List(); case 3: return EggMovesRS[species].Moves; case 4: From 81217799feef68fd71263c0fbe35d4b28c86cb33 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 18:19:38 +0100 Subject: [PATCH 6/9] Fix parseMoves and RemoveFutureMoves functions --- PKHeX/Legality/Checks.cs | 56 ++++++++++++++++++++++------------------ PKHeX/Legality/Core.cs | 19 +++++++------- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index 88cf3c1c2..f80922984 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -2096,6 +2096,7 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ var Gen1MovesLearned = new List(); var EggMovesLearned = new List(); var EventEggMovesLearned = new List(); + var IsGen2Pkm = pkm.Format == 2 || pkm.VC2; // Check none moves and relearn moves before generation moves for (int m = 0; m < 4; m++) { @@ -2105,7 +2106,7 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ res[m] = new CheckResult(Severity.Valid, V172, CheckIdentifier.Move) { Flag = true }; } - if (res.All(r => r.Valid)) + if (res.All(r => r != null)) return res; bool MixedGen1NonTradebackGen2= false; @@ -2117,34 +2118,35 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ if (!pkm.InhabitedGeneration(gen)) continue; - IEnumerable HMLearned = new List(); + var HMLearned = new int[0]; // Check if pokemon knows HM moves from generation 3 and 4 but are not valid yet, that means it cant learn the HMs in future generations bool KnowDefogWhirlpool = false; if (gen == 4 && pkm.Format > 4) { - HMLearned = moves.Where((m,i) => !(res[i]?.Valid ?? false) && Legal.HM_4_RemovePokeTransfer.Any(l => l == m)).Select((m, i) => i); + // Copy to array the hm found or else the list will be emptied when the legal status of moves changes in the current generation + HMLearned = moves.Where((m,i) => !(res[i]?.Valid ?? false) && Legal.HM_4_RemovePokeTransfer.Any(l => l == m)).Select((m, i) => i).ToArray(); // Defog and Whirlpool at the same time, also both can't be learned in future generations or else they will be valid - KnowDefogWhirlpool = moves.Where((m, i) => (m == 250 && m == 432) && !(res[i]?.Valid ?? false)).Count() == 2; + KnowDefogWhirlpool = moves.Where((m, i) => (m == 250 || m == 432) && !(res[i]?.Valid ?? false)).Count() == 2; } else if (gen == 3 && pkm.Format > 3) - HMLearned = moves.Where((m, i) => !(res[i]?.Valid ?? false) && Legal.HM_3.Any(l => l == m)).Select((m, i) => i); + HMLearned = moves.Select((m, i) => i).Where(i => !(res[i]?.Valid ?? false) && Legal.HM_3.Any(l => l == moves[i])).ToArray(); for (int m = 0; m < 4; m++) { if (res[m]?.Valid ?? false) continue; - if (learn[m].Contains(moves[m])) + if (learn[gen].Contains(moves[m])) { res[m] = new CheckResult(Severity.Valid, (gen == pkm.Format)? V177 : String.Format(V330, gen), CheckIdentifier.Move); if (gen == 1) Gen1MovesLearned.Add(m); } - else if (tmhm[m].Contains(moves[m])) + else if (tmhm[gen].Contains(moves[m])) { res[m] = new CheckResult(Severity.Valid, (gen == pkm.Format) ? V173 : String.Format(V331, gen), CheckIdentifier.Move); if (gen == 1) Gen1MovesLearned.Add(m); } - else if (tutor[m].Contains(moves[m])) + else if (tutor[gen].Contains(moves[m])) { res[m] = new CheckResult(Severity.Valid, (gen == pkm.Format) ? V173 : String.Format(V332, gen), CheckIdentifier.Move); if (gen == 1) Gen1MovesLearned.Add(m); @@ -2166,7 +2168,7 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ continue; if (egg.Contains(moves[m])) { - if (Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) + if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) { // To learn exclusive generation 1 moves the pokemon was tradeback, but it can be trade to generation 1 // without removing moves above MaxMoveID_1, egg moves above MaxMoveID_1 and gen 1 moves are incompatible @@ -2181,7 +2183,7 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ { if(!egg.Contains(moves[m])) { - if (Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) + if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) { res[m] = new CheckResult(Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true }; MixedGen1NonTradebackGen2 = true; @@ -2193,33 +2195,37 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ } } - // A pokemon could have normal egg moves and regular egg moves only if all the event egg moves are also regular egg moves - if (!EggMovesLearned.All(e=> EventEggMovesLearned.Contains(e))) + // A pokemon could have normal egg moves and regular egg moves + // Only if all regular egg moves are event egg moves or all event egg moves are regular egg moves + if (EggMovesLearned.Any() && EventEggMovesLearned.Any()) { - for (int m = 0; m < 4; m++) + // Moves that are egg moves or event egg moves but not both + var IncompatibleEggMoves = EggMovesLearned.Except(EventEggMovesLearned).Union(EventEggMovesLearned.Except(EggMovesLearned)); + if (IncompatibleEggMoves.Any()) { - if (EventEggMovesLearned.Contains(m) && !EggMovesLearned.Contains(m)) - res[m] = new CheckResult(Severity.Invalid, V337, CheckIdentifier.Move); - else if (!EventEggMovesLearned.Contains(m) && EggMovesLearned.Contains(m)) - res[m] = new CheckResult(Severity.Invalid, V336, CheckIdentifier.Move); + foreach(int m in IncompatibleEggMoves) + { + if (!EventEggMovesLearned.Contains(m) && !EggMovesLearned.Contains(m)) + res[m] = new CheckResult(Severity.Invalid, V337, CheckIdentifier.Move); + else if (!EventEggMovesLearned.Contains(m) && EggMovesLearned.Contains(m)) + res[m] = new CheckResult(Severity.Invalid, V336, CheckIdentifier.Move); + } } } - } - if (3 <= gen && gen <= 4 && gen > pkm.Format) + if (3 <= gen && gen <= 4 && pkm.Format > gen) { // After all the moves from the generations 3 and 4, // including egg moves if is the origin generation because some hidden moves are also special egg moves in gen 3 // Check if the marked hidden moves that were invalid at the start are now marked as valid, that means // the hidden move was learned in gen 3 or 4 but was not removed when transfer to 4 or 5 if (KnowDefogWhirlpool) - KnowDefogWhirlpool = moves.Where((m,i) => (m == 250 && m == 432) && (res[i]?.Valid ?? false)).Count() == 2; + KnowDefogWhirlpool = moves.Where((m,i) => (m == 250 || m == 432) && (res[i]?.Valid ?? false)).Count() == 2; if (KnowDefogWhirlpool) { - KnowDefogWhirlpool = moves.Where((m, i) => (m == 250 && m == 432) && (res[i]?.Valid ?? false)).Count() == 2; - foreach (int index in moves.Where(m => (m == 250 && m == 432)).Select((move, index) => index)) + foreach (int index in moves.Select((m, i) => i).Where(i => (moves[i] == 250 || moves[i] == 432))) { res[index] = new CheckResult(Severity.Invalid, V338, CheckIdentifier.Move); } @@ -2240,13 +2246,13 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ } } - if (res.All(r => r.Valid)) + if (res.All(r => r != null)) return res; } - if (res.All(r => r.Valid)) + if (res.All(r => r != null)) return res; - + for (int m = 0; m < 4; m++) { if (res[m] == null) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index b627c9db1..d1ac67590 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -550,15 +550,15 @@ private static EncounterArea[] getTables2(GameVersion Version) // Moves internal static void RemoveFutureMoves(PKM pkm, DexLevel[][] evoChains, ref int[][] validLevelMoves, ref int[][] validTMHM, ref int[][] validTutor) { - IEnumerable AllMoves = new List(); - if (pkm.Format > 3) + if (pkm.Format >= 3) { - for (int i = evoChains.Length - 1; i > 0; i--) + var FutureMoves = validLevelMoves[pkm.Format].Concat(validTMHM[pkm.Format]).Concat(validTutor[pkm.Format]); + for (int i = pkm.Format - 1; i >= pkm.GenNumber; i--) { - validLevelMoves[i] = validLevelMoves[i].Except(AllMoves).ToArray(); - validTMHM[i] = validTMHM[i].Except(AllMoves).ToArray(); - validTutor[i] = validTutor[i].Except(AllMoves).ToArray(); - AllMoves = AllMoves.Concat(validLevelMoves[i]).Concat(validTMHM[i]).Concat(validTutor[i]); + validLevelMoves[i] = validLevelMoves[i].Except(FutureMoves).ToArray(); + validTMHM[i] = validTMHM[i].Except(FutureMoves).ToArray(); + validTutor[i] = validTutor[i].Except(FutureMoves).ToArray(); + FutureMoves = FutureMoves.Concat(validLevelMoves[i]).Concat(validTMHM[i]).Concat(validTutor[i]); } } else @@ -574,7 +574,8 @@ internal static int[][] getValidMovesAllGens(PKM pkm, DexLevel[][] evoChains, bo { int[][] Moves = new int[evoChains.Length][]; for (int i = 1; i < evoChains.Length; i++) - Moves[i] = getValidMoves(pkm, evoChains[i], i, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM).ToArray(); + if (evoChains[i].Any()) + Moves[i] = getValidMoves(pkm, evoChains[i], i, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM).ToArray(); return Moves; } internal static IEnumerable getValidMoves(PKM pkm, DexLevel[][] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) @@ -589,7 +590,7 @@ internal static IEnumerable getValidMoves(PKM pkm, DexLevel[] evoChain, int GameVersion version = (GameVersion)pkm.Version; if (!pkm.IsUntraded) version = GameVersion.Any; - return getValidMoves(pkm, version, evoChain, generation, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM : RemoveTransferHM); + return getValidMoves(pkm, version, evoChain, generation, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM: RemoveTransferHM); } internal static IEnumerable getValidRelearn(PKM pkm, int skipOption) { From 5adb2dac22199abd11e1c95db1865d0c3c3bcb87 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 18:32:05 +0100 Subject: [PATCH 7/9] Adapted base egg moves to new parsemoves format --- PKHeX/Legality/Checks.cs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index 024aafc0b..5289627f0 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -2077,7 +2077,7 @@ private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any) else if (pkm.WasEgg && pkm.GenNumber < 6) res = verifyMovesEggPreRelearn(Moves, validLevelMoves, validTMHM, validTutor); else // Everything else - res = parseMovesRegular(Moves, validLevelMoves, validTMHM, validTutor, game); + res = parseMovesRegular(Moves, validLevelMoves, validTMHM, validTutor, new int[0], game); // Duplicate Moves Check verifyNoEmptyDuplicates(Moves, res); @@ -2086,7 +2086,7 @@ private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any) return res; } - private CheckResult[] verifyMovesEggPreRelearn(int[] Moves, int[] validLevelMoves, int[] validTMHM, int[] validTutor) + private CheckResult[] verifyMovesEggPreRelearn(int[] Moves, int[][] validLevelMoves, int[][] validTMHM, int[][] validTutor) { CheckResult[] res = new CheckResult[4]; @@ -2110,8 +2110,8 @@ private CheckResult[] verifyMovesEggPreRelearn(int[] Moves, int[] validLevelMove { for (int i = 0; i <= splitctr; i++) { - var lvlMoves = validLevelMoves.Concat(Legal.getBaseEggMoves(pkm, i, ver, 100)).ToArray(); - res = parseMovesRegular(Moves, lvlMoves, validTMHM, validTutor, ver); + var baseEggMoves = Legal.getBaseEggMoves(pkm, i, ver, 100).ToArray(); + res = parseMovesRegular(Moves, validLevelMoves, validTMHM, validTutor, baseEggMoves, ver); if (res.All(r => r.Valid)) // moves is satisfactory return res; } @@ -2133,7 +2133,7 @@ private CheckResult[] parseMovesGetGift(int[] Moves, int[][] validLevelMoves, in foreach (MysteryGift mg in EventGiftMatch) { int[] SpecialMoves = mg.Moves; - CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], new int[0]); + CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0]); if (res.Any(r => !r.Valid)) continue; @@ -2144,9 +2144,9 @@ private CheckResult[] parseMovesGetGift(int[] Moves, int[][] validLevelMoves, in } // no Mystery Gifts matched - return parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, new int[0], new int[0], new int[0]); + return parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, new int[0], new int[0], new int[0], new int[0]); } - private CheckResult[] parseMovesRegular(int[] Moves, int[][] validLevelMoves, int[][] validTMHM, int[][] validTutor, GameVersion game) + private CheckResult[] parseMovesRegular(int[] Moves, int[][] validLevelMoves, int[][] validTMHM, int[][] validTutor, int[] baseEggMoves, GameVersion game) { int[] EggMoves = pkm.WasEgg ? Legal.getEggMoves(pkm, game).ToArray() : new int[0]; int[] EventEggMoves = new int[0]; @@ -2156,7 +2156,7 @@ private CheckResult[] parseMovesRegular(int[] Moves, int[][] validLevelMoves, in (EncounterMatch as EncounterTrade)?.Moves ?? new int[0]; - CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, EggMoves, EventEggMoves); + CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, baseEggMoves, EggMoves, EventEggMoves); if (pkm.GenNumber < 6) return res; @@ -2167,7 +2167,7 @@ private CheckResult[] parseMovesRegular(int[] Moves, int[][] validLevelMoves, in return res; } - private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[][] tmhm, int[][] tutor, int[] special, int[] egg, int[] eventegg) + private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[][] tmhm, int[][] tutor, int[] special, int[] baseegg, int[] egg, int[] eventegg) { CheckResult[] res = new CheckResult[4]; var Gen1MovesLearned = new List(); @@ -2233,6 +2233,11 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ res[m] = new CheckResult(Severity.Valid, V175, CheckIdentifier.Move); if (gen == 1) Gen1MovesLearned.Add(m); } + else if (gen == pkm.GenNumber && baseegg.Contains(moves[m])) + { + res[m] = new CheckResult(Severity.Valid, V177, CheckIdentifier.Move); + if (gen == 1) Gen1MovesLearned.Add(m); + } } if (gen == generations.Length - 1) From f0b2294e3cfdd4bd813262f1bbe7dbffaac7e32c Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 19:02:33 +0100 Subject: [PATCH 8/9] Add pokemon box static encounters Fix gen 3 met egg location to allow 255 (pokemon box) and 253 (in game egg) --- PKHeX/Legality/Checks.cs | 8 ++++---- PKHeX/Legality/Core.cs | 23 ++++++++++++++++++++++- PKHeX/Legality/Tables3.cs | 24 +++++++++++++++++++++--- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index 5289627f0..cf2a3e392 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -521,8 +521,8 @@ private CheckResult verifyEncounterEgg3Native() return new CheckResult(Severity.Invalid, string.Format(V52, 0), CheckIdentifier.Encounter); if (pkm.IsEgg) { - var loc = pkm.FRLG ? 146 /* Four Island */ : 32; /* RSE: Route 117 */ - if (pkm.Met_Location != loc) + var loc = pkm.FRLG ? Legal.ValidEggMet_FRLG : Legal.ValidEggMet_RSE; + if (!loc.Contains(pkm.Met_Location)) return new CheckResult(Severity.Invalid, V55, CheckIdentifier.Encounter); } else @@ -2149,7 +2149,7 @@ private CheckResult[] parseMovesGetGift(int[] Moves, int[][] validLevelMoves, in private CheckResult[] parseMovesRegular(int[] Moves, int[][] validLevelMoves, int[][] validTMHM, int[][] validTutor, int[] baseEggMoves, GameVersion game) { int[] EggMoves = pkm.WasEgg ? Legal.getEggMoves(pkm, game).ToArray() : new int[0]; - int[] EventEggMoves = new int[0]; + int[] EventEggMoves = pkm.WasEgg ? Legal.getSpecialEggMoves(pkm, game).ToArray() : new int[0]; int[] RelearnMoves = pkm.RelearnMoves; int[] SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ?? (EncounterMatch as EncounterStatic)?.Moves ?? @@ -2240,7 +2240,7 @@ private CheckResult[] parseMoves(int[] moves, int[][] learn, int[] relearn, int[ } } - if (gen == generations.Length - 1) + if (gen == generations.Last()) { // Check egg moves after all the generations and all the moves, every move that can be learned in another source should have preference // the moves that can only be learned from egg moves should in the future check if the move combinations can be breed in gens 2 to 5 diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index a1bdaec23..ebb2cc059 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -715,7 +715,12 @@ internal static IEnumerable getBaseEggMoves(PKM pkm, int skipOption, GameVe internal static IEnumerable getEggMoves(PKM pkm, GameVersion Version) { return getEggMoves(pkm, getBaseSpecies(pkm), 0, Version); - } + } + + internal static IEnumerable getSpecialEggMoves(PKM pkm, GameVersion Version) + { + return getSpecialEggMoves(pkm, getBaseSpecies(pkm), 0, Version); + } // Encounter internal static EncounterLink getValidLinkGifts(PKM pkm) @@ -2394,6 +2399,22 @@ private static IEnumerable getMoves(PKM pkm, int species, int lvl, int form } return r; } + private static IEnumerable getSpecialEggMoves(PKM pkm, int species, int alform, GameVersion Version = GameVersion.Any) + { + if (!pkm.InhabitedGeneration(pkm.GenNumber, species)) + return new List(); + switch (pkm.GenNumber) + { + case 3: + { + var boxencounter = Encounter_Box.Where(e => e.Species == species).FirstOrDefault(); + if (boxencounter != null) + return boxencounter.Moves; + break; + } + } + return new List(); + } private static IEnumerable getEggMoves(PKM pkm, int species, int formnum, GameVersion Version = GameVersion.Any) { if (!pkm.InhabitedGeneration(pkm.GenNumber, species)) diff --git a/PKHeX/Legality/Tables3.cs b/PKHeX/Legality/Tables3.cs index 208e5683c..9379346fc 100644 --- a/PKHeX/Legality/Tables3.cs +++ b/PKHeX/Legality/Tables3.cs @@ -202,6 +202,13 @@ public static partial class Legal 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, }; + internal static readonly EncounterStatic[] Encounter_Box = + { + new EncounterStatic { Species = 333, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{206} }, // Swablu Egg with False Swipe + new EncounterStatic { Species = 263, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{245} }, // Zigzagoon Egg with Extreme Speed + new EncounterStatic { Species = 300, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{6} }, // Skitty Egg with Pay Day + new EncounterStatic { Species = 172, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{57} }, // Pichu Egg with Surf + }; internal static readonly EncounterStatic[] Encounter_RSE_Roam = { @@ -303,8 +310,8 @@ public static partial class Legal new EncounterStatic { Species = 386, Level = 30, Location = 187, Version = GameVersion.LG, Form = 2 }, // Deoxys @ Birth Island }; - internal static readonly EncounterStatic[] Encounter_RSE = Encounter_RSE_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_RSE)).Concat(Encounter_RSE_Regular).ToArray(); - internal static readonly EncounterStatic[] Encounter_FRLG = Encounter_FRLG_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_FRLG)).Concat(Encounter_FRLG_Stationary).ToArray(); + internal static readonly EncounterStatic[] Encounter_RSE = Encounter_RSE_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_RSE)).Concat(Encounter_RSE_Regular).Concat(Encounter_Box).ToArray(); + internal static readonly EncounterStatic[] Encounter_FRLG = Encounter_FRLG_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_FRLG)).Concat(Encounter_FRLG_Stationary).Concat(Encounter_Box).ToArray(); private static readonly int[] TradeContest_Cool = {30, 05, 05, 05, 05, 10}; private static readonly int[] TradeContest_Beauty = {05, 30, 05, 05, 05, 10}; @@ -480,7 +487,18 @@ public static partial class Legal },} }; #endregion - + internal static readonly int[] ValidEggMet_RSE = + { + 32, //Route 117 + 253, //Ingame egg gift + 255 // event/pokemon box + }; + internal static readonly int[] ValidEggMet_FRLG = + { + 146, //Four Island + 253, //Ingame egg gift + 255 // event/pokemon box + }; // 064 is an unused location for metor falls // 084 is Inside of a truck, no possible pokemon can be hatched there internal static readonly int[] ValidMet_RS = From b5a8a53320dc208e6e62b9b3bbcf96916aaaa23b Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 25 Mar 2017 19:49:34 +0100 Subject: [PATCH 9/9] Fix RemoveFutureMoves for VC and GB games --- PKHeX/Legality/Core.cs | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index ebb2cc059..f635ae086 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -574,21 +574,41 @@ internal static void RemoveFutureMoves(PKM pkm, DexLevel[][] evoChains, ref int[ if (pkm.Format >= 3) { var FutureMoves = validLevelMoves[pkm.Format].Concat(validTMHM[pkm.Format]).Concat(validTutor[pkm.Format]); - for (int i = pkm.Format - 1; i >= pkm.GenNumber; i--) + if(pkm.VC1) { - validLevelMoves[i] = validLevelMoves[i].Except(FutureMoves).ToArray(); - validTMHM[i] = validTMHM[i].Except(FutureMoves).ToArray(); - validTutor[i] = validTutor[i].Except(FutureMoves).ToArray(); - FutureMoves = FutureMoves.Concat(validLevelMoves[i]).Concat(validTMHM[i]).Concat(validTutor[i]); + validLevelMoves[1] = validLevelMoves[1].Except(FutureMoves).ToArray(); + validTMHM[1] = validTMHM[1].Except(FutureMoves).ToArray(); + validTutor[1] = validTutor[1].Except(FutureMoves).ToArray(); + } + else if (pkm.VC2) + { + for (int i = 2; i >= 1; i--) + { + validLevelMoves[i] = validLevelMoves[i]?.Except(FutureMoves).ToArray(); + validTMHM[i] = validTMHM[i]?.Except(FutureMoves).ToArray(); + validTutor[i] = validTutor[i]?.Except(FutureMoves).ToArray(); + if(validLevelMoves[i]!=null && validTMHM[i]!= null && validTutor[i]!= null) + FutureMoves = FutureMoves.Concat(validLevelMoves[i]).Concat(validTMHM[i]).Concat(validTutor[i]); + } + } + else + { + for (int i = pkm.Format - 1; i >= pkm.GenNumber; i--) + { + validLevelMoves[i] = validLevelMoves[i].Except(FutureMoves).ToArray(); + validTMHM[i] = validTMHM[i].Except(FutureMoves).ToArray(); + validTutor[i] = validTutor[i].Except(FutureMoves).ToArray(); + FutureMoves = FutureMoves.Concat(validLevelMoves[i]).Concat(validTMHM[i]).Concat(validTutor[i]); + } } } else { int tradeback = (pkm.Format == 2) ? 1 : 2; var formatmoves = validLevelMoves[pkm.Format].Concat(validTMHM[pkm.Format]).Concat(validTutor[pkm.Format]); - validLevelMoves[tradeback] = validLevelMoves[tradeback].Except(formatmoves).ToArray(); - validTMHM[tradeback] = validTMHM[tradeback].Except(formatmoves).ToArray(); - validTutor[tradeback] = validTutor[tradeback].Except(formatmoves).ToArray(); + validLevelMoves[tradeback] = validLevelMoves[tradeback]?.Except(formatmoves).ToArray(); + validTMHM[tradeback] = validTMHM[tradeback]?.Except(formatmoves).ToArray(); + validTutor[tradeback] = validTutor[tradeback]?.Except(formatmoves).ToArray(); } } internal static int[][] getValidMovesAllGens(PKM pkm, DexLevel[][] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true)