From 60cde3ec683923a7eef54e4a17a5a14d1eb39744 Mon Sep 17 00:00:00 2001 From: javierhimura Date: Fri, 14 Apr 2017 19:11:50 +0200 Subject: [PATCH] Split Breed Egg Moves improvements (#1058) * Added method getBaseEggSpecies to get the base species when the pokemon was an egg, is needed because for format 1 pokemon with egg origin every time getBaseSpecies is called is returning the gen 1 base species obtaining invalid eggmoves and base egg moves Also getBaseEggSpecies was using Evolves1 when format = 1 even when asking for a gen2 egg base species, returning Pikachu egg moves (empty list) instead of Pichu egg moves * Fix ability checking for generation 3 pokemon, likea de Seadra from Issue #1011 pkm.AbilityNumber have a value assuming PID match ability like a generation 4 pokemon but the validation should be ignored if is a generation 3 pokemon with only one ability in generation 3 Also changed the validation for ingame trades with fixed abilities to check only with generation 3 abilities in the case the species has two abilities generation 3, if only one was possible any PID should be valid with the generation 3 ability Encounter Trades Also the check for evolution was wrong, the most evolved species is the first in the evochain, not the last * Fix evoltuion chains for gen 3 pokemon in format 4 * Fix ability for generation 3 trades. Ability could not change if there were 2 abilities in generation 3, that means it is irrelevant if the pokemon evolved in gen 4-5, the ability number must match the encounter * Added missing skipOption to a call to getBaseEggSpecies * Functions to obtain moves excluvie to preevolutions, like moves that Azurill/Happiny could learn throught level up or TM but Marill/Chansey could not learn, icompatible with any Marill/Chansey egg moves Also add functions to return egg moves and base egg moves for both possible species for split breed eggs * Check both species from split breed egg at the same time to report moves incompatibilities * Reduced generation 4-5 was egg game check There is no need to check every possible generation game. For every egg species HGSS learnset tables y egg moves table contains all the moves from the same species in DP and Pt, without any move exclusive to that games except in legendaries, and they cant breed In generation 5 is the same with B2W2 except for Exxegutte, it have a exclusive level up move from B1W1, Psychic, but it can learn the move with TM, it wont count as an egg move * Check incompatible split breed moves in verify relearn egg * Fix generation 1 incompatibility moves check SolarBeam removed from Exeggcute/Exeggutor incompatiblity, Exeggutor could learn it with a TM in generation 1 Removed Vaporeon Mist and Eevee Take Down incompatiblity, Vaporeon could learn Take Down with a TM in generation 1 --- PKHeX/Legality/Checks.cs | 184 ++++++++++++------ PKHeX/Legality/Core.cs | 64 ++++++ PKHeX/Legality/LegalityCheckStrings.cs | 5 + PKHeX/Legality/Tables1.cs | 2 +- .../text/en/LegalityCheckStrings_en.txt | 7 +- .../text/zh/LegalityCheckStrings_zh.txt | 7 +- 6 files changed, 211 insertions(+), 58 deletions(-) diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index f868b9c34..3ed277836 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -2476,7 +2476,11 @@ private CheckResult[] parseMovesForEncounters(GameVersion game, List[] vali encounters = encounters.Distinct().ToList(); if (!encounters.Any()) // There isn't any valid encounter and wasnt an egg - return parseMoves(pkm.Moves, validLevelMoves, pkm.RelearnMoves, validTMHM, validTutor, new int[0], new int[0], new int[0], new int[0], new int[0]); + { + var empty = Legal.GetEmptyMovesList(EvoChainsAllGens); + var emptyegg = Legal.GetEmptyEggMovesList(); + return parseMoves(pkm.Moves, validLevelMoves, pkm.RelearnMoves, validTMHM, validTutor, new int[0], emptyegg, emptyegg, empty, new int[0], new int[0], false); + } // Iterate over encounters bool pre3DS = pkm.GenNumber < 6; @@ -2504,10 +2508,9 @@ private CheckResult[] parseMovesForSmeargle(int[] Moves, List[] validLevelM if (!pkm.IsEgg) return parseMovesSketch(Moves); // can only know sketch as egg - var empty = new List[EvoChainsAllGens.Length]; - for (int i = 0; i < empty.Length; i++) - empty[i] = new List(); - return parseMoves(pkm.Moves, validLevelMoves, new int[0], empty, empty, new int[0], new int[0], new int[0], new int[0], new int[0]); + var empty = Legal.GetEmptyMovesList(EvoChainsAllGens); + var emptyegg = Legal.GetEmptyEggMovesList(); + return parseMoves(pkm.Moves, validLevelMoves, new int[0], empty, empty, new int[0], emptyegg, emptyegg, empty, new int[0], new int[0], false); } private GameVersion[] getBaseMovesIsEggGames() { @@ -2632,29 +2635,31 @@ private CheckResult[] parseMovesWasEggPreRelearn(int[] Moves, List[] validL Games = getBaseMovesIsEggGames(); break; case 4: - Games = new[] { GameVersion.DP, GameVersion.Pt, GameVersion.HGSS }; + Games = new[] { GameVersion.HGSS }; break; case 5: - Games = new[] { GameVersion.BW, GameVersion.B2W2 }; + Games = new[] { GameVersion.B2W2 }; break; } int splitctr = Legal.SplitBreed.Contains(pkm.Species) ? 1 : 0; + var issplitbreed = Legal.SplitBreed.Contains(pkm.Species); foreach (var ver in Games) { var EventEggMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0]; - for (int i = 0; i <= splitctr; i++) - { - var BaseLvlMoves = 489 <= pkm.Species && pkm.Species <= 490 ? 1 : 100; - var LvlupEggMoves = Legal.getBaseEggMoves(pkm, i, ver, BaseLvlMoves)?.ToArray() ?? new int[0]; - var EggMoves = Legal.getEggMoves(pkm, i, ver).ToArray(); - bool volt = (gen > 3 || ver == GameVersion.E) && Legal.LightBall.Contains(pkm.Species); - var SpecialMoves = volt && EventEggMoves.Length == 0 ? new[] {344} : new int[0]; // Volt Tackle for bred Pichu line + var BaseLvlMoves = 489 <= pkm.Species && pkm.Species <= 490 ? 1 : 100; + var LvlupEggMoves = Legal.getBaseEggMoves(pkm, ver, BaseLvlMoves); + // Level up, TMHM or tutor moves exclusive to the incense egg species, like Azurill, incompatible with the non-incense species egg moves + var ExclusiveIncenseMoves = issplitbreed ? Legal.getExclusiveEvolutionMoves(pkm,Legal.getBaseEggSpecies(pkm,0), EvoChainsAllGens, ver) : null; + var EggMoves = Legal.getEggMoves(pkm, ver); + + bool volt = (gen > 3 || ver == GameVersion.E) && Legal.LightBall.Contains(pkm.Species); + var SpecialMoves = volt && EventEggMoves.Length == 0 ? new[] {344} : new int[0]; // Volt Tackle for bred Pichu line - res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, SpecialMoves, LvlupEggMoves, EggMoves, EventEggMoves, new int[0]); + res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, SpecialMoves, LvlupEggMoves, EggMoves, ExclusiveIncenseMoves,EventEggMoves, new int[0], issplitbreed); - if (res.All(r => r.Valid)) // moves is satisfactory - return res; - } + if (res.All(r => r.Valid)) // moves is satisfactory + return res; + } return res; } @@ -2671,8 +2676,6 @@ private CheckResult[] parseMoves3DS(GameVersion game, List[] validLevelMove { if (EncounterMatch is IMoveset) return parseMovesSpecialMoveset(Moves, validLevelMoves, validTMHM, validTutor); - if (pkm.WasEgg && Legal.SplitBreed.Contains(pkm.Species)) - return parseMovesRelearnSplitBreed(Moves, validLevelMoves, validTMHM, validTutor, game); // Everything else return parseMovesRelearn(Moves, validLevelMoves, validTMHM, validTutor, 0, game); @@ -2702,12 +2705,14 @@ private CheckResult[] parseMovesGen1(int[] Moves, List[] validLevelMoves, L return parseMovesSpecialMoveset(Moves, validLevelMoves, validTMHM, validTutor); var InitialMoves = new int[0]; int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0]; - foreach(GameVersion ver in games) + var empty = Legal.GetEmptyMovesList(EvoChainsAllGens); + var emptyegg = Legal.GetEmptyEggMovesList(); + foreach (GameVersion ver in games) { var VerInitialMoves = Legal.getInitialMovesGBEncounter(G1Encounter.Species, G1Encounter.LevelMin, ver).ToArray(); if (VerInitialMoves.SequenceEqual(InitialMoves)) return res; - res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0], VerInitialMoves); + res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, SpecialMoves, emptyegg, emptyegg, empty, new int[0], VerInitialMoves, false); if (res.All(r => r.Valid)) return res; InitialMoves = VerInitialMoves; @@ -2719,7 +2724,9 @@ private CheckResult[] parseMovesSpecialMoveset(int[] Moves, List[] validLev int[] RelearnMoves = pkm.GenNumber >= 6 ? pkm.RelearnMoves : new int[0]; var mg = EncounterMatch as IMoveset; int[] SpecialMoves = mg?.Moves ?? new int[0]; - CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0], new int[0]); + var empty = Legal.GetEmptyMovesList(EvoChainsAllGens); + var emptyegg = Legal.GetEmptyEggMovesList(); + CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, emptyegg, emptyegg, empty, new int[0], new int[0], false); if (res.Any(r => !r.Valid)) return res; @@ -2727,27 +2734,20 @@ private CheckResult[] parseMovesSpecialMoveset(int[] Moves, List[] validLev RelearnBase = (EncounterMatch as MysteryGift).RelearnMoves; return res; } - private CheckResult[] parseMovesRelearnSplitBreed(int[] Moves, List[] validLevelMoves, List[] validTMHM, List[] validTutor, GameVersion game) - { - CheckResult[] res = new CheckResult[4]; - int splitctr = Legal.SplitBreed.Contains(pkm.Species) ? 1 : 0; - - for (int i = 0; i <= splitctr; i++) - { - res = parseMovesRelearn(Moves, validLevelMoves, validTMHM, validTutor, i, game); - if (res.All(r => r.Valid)) // moves are satisfactory - break; - } - - return res; - } private CheckResult[] parseMovesRelearn(int[] Moves, List[] validLevelMoves, List[] validTMHM, List[] validTutor, int SkipOption, GameVersion game) { - int[] EggMoves = pkm.WasEgg && !pkm.WasGiftEgg && !pkm.WasEventEgg? Legal.getEggMoves(pkm, SkipOption, game).ToArray() : new int[0]; + var empty = Legal.GetEmptyMovesList(EvoChainsAllGens); + var emptyegg = Legal.GetEmptyEggMovesList(); + + var issplitbreed = pkm.WasEgg && Legal.SplitBreed.Contains(pkm.Species); + var EggMoves = pkm.WasEgg? Legal.getEggMoves(pkm, game): emptyegg; + // Level up, TMHM or tutor moves exclusive to the incense egg species, like Azurill, incompatible with the non-incense species egg moves + var ExclusiveIncenseMoves = issplitbreed ? Legal.getExclusiveEvolutionMoves(pkm, Legal.getBaseEggSpecies(pkm, 0), EvoChainsAllGens, game) : empty; + int[] RelearnMoves = pkm.RelearnMoves; int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0]; - CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], EggMoves, new int[0], new int[0]); + CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, emptyegg, EggMoves, ExclusiveIncenseMoves, new int[0], new int[0], issplitbreed); for (int i = 0; i < 4; i++) if ((pkm.IsEgg || res[i].Flag) && !RelearnMoves.Contains(Moves[i])) @@ -2755,7 +2755,7 @@ private CheckResult[] parseMovesRelearn(int[] Moves, List[] validLevelMoves return res; } - private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, List[] tmhm, List[] tutor, int[] special, int[] lvlupegg, int[] egg, int[] eventegg, int[] initialmoves) + private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, List[] tmhm, List[] tutor, int[] special, List[] lvlupegg, List[] egg, List[] IncenseExclusiveMoves, int[] eventegg, int[] initialmoves, bool issplitbreed) { CheckResult[] res = new CheckResult[4]; var Gen1MovesLearned = new List(); @@ -2764,6 +2764,15 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, var EventEggMovesLearned = new List(); var IsGen2Pkm = pkm.Format == 2 || pkm.VC2; var required = Legal.getRequiredMoveCount(pkm, moves, learn, tmhm, tutor, initialmoves); + var LvlupEggMovesSplitLearned = new List[egg.Length]; + var EggMovesSplitLearned = new List[egg.Length]; + var IncenseMovesLearned = new List(); + for (int i=0;i < egg.Length; i++ ) + { + LvlupEggMovesSplitLearned[i] = new List(); + EggMovesSplitLearned[i] = new List(); + } + // Check none moves and relearn moves before generation moves for (int m = 0; m < 4; m++) { @@ -2818,6 +2827,9 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, if (res[m] == null) continue; + if (res[m].Valid && issplitbreed && IncenseExclusiveMoves[gen].Contains(moves[m]) && !eventegg.Contains(moves[m]) && !special.Contains(moves[m])) + // Learned moves exclusive to the incense species, ignore if the move is also a special move or an event egg move + IncenseMovesLearned.Add(m); if (res[m].Valid && gen == 1) Gen1MovesLearned.Add(m); } @@ -2832,7 +2844,7 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, continue; if (moves[m] == 0) continue; - if (!lvlupegg.Contains(moves[m])) // Check if contains level-up egg moves from parents + if (!lvlupegg.Any(e => e.Contains(moves[m]))) // Check if contains level-up egg moves from parents continue; if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) @@ -2843,6 +2855,14 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, else res[m] = new CheckResult(Severity.Valid, V345, CheckIdentifier.Move); LvlupEggMovesLearned.Add(m); + if(issplitbreed) + { + // Only add to split breed lists learned moves that can be from one of the egg species, ignore common moves + if (lvlupegg[0].Contains(moves[m]) && !lvlupegg[1].Contains(moves[m])) + LvlupEggMovesSplitLearned[0].Add(m); + if (!lvlupegg[0].Contains(moves[m]) && lvlupegg[1].Contains(moves[m])) + LvlupEggMovesSplitLearned[1].Add(m); + } } // Check egg moves after all the generations and all the moves, every move that can't be learned in another source should have preference @@ -2854,7 +2874,7 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, if (moves[m] == 0) continue; - if (egg.Contains(moves[m])) + if (egg.Any(e => e.Contains(moves[m]))) { if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) { @@ -2866,11 +2886,19 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, else res[m] = new CheckResult(Severity.Valid, V171, CheckIdentifier.Move) { Flag = true }; EggMovesLearned.Add(m); + if (issplitbreed) + { + // Only add to split breed lists egg moves that can be from one of the egg species, ignore common moves + if (egg[0].Contains(moves[m]) && !egg[1].Contains(moves[m])) + EggMovesSplitLearned[0].Add(m); + if (!egg[0].Contains(moves[m]) && egg[1].Contains(moves[m])) + EggMovesSplitLearned[1].Add(m); + } } if (!eventegg.Contains(moves[m])) continue; - if (!egg.Contains(moves[m])) + if (!egg.Any(e => e.Contains(moves[m]))) { if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) { @@ -2903,6 +2931,36 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, } } } + // If there is no incompatibility with event egg check that there is no inherited move in gift eggs and event eggs + else if (RegularEggMovesLearned.Any() && (pkm.WasGiftEgg || pkm.WasEventEgg)) + { + foreach (int m in RegularEggMovesLearned) + { + if(EggMovesLearned.Contains(m)) + res[m] = new CheckResult(Severity.Invalid, pkm.WasGiftEgg ? V377 : V341, CheckIdentifier.Move); + else if (LvlupEggMovesLearned.Contains(m)) + res[m] = new CheckResult(Severity.Invalid, pkm.WasGiftEgg ? V378 : V347, CheckIdentifier.Move); + } + } + else if (issplitbreed) + { + // If there is no error in previous checks now check for incompatibility moves between split breed species + if ((EggMovesSplitLearned[0].Any() || IncenseMovesLearned.Any()) && EggMovesSplitLearned[1].Any()) + { + var species = specieslist; + var splitbreedspecies0 = species[Legal.getBaseEggSpecies(pkm, 0)]; + var splitbreedspecies1 = species[Legal.getBaseEggSpecies(pkm, 1)]; + foreach (int m in EggMovesSplitLearned[0]) + // Example: Azurill Egg move, incompatible with Marill egg moves + res[m] = new CheckResult(Severity.Invalid, string.Format(V375, splitbreedspecies0, splitbreedspecies1), CheckIdentifier.Move); + foreach (int m in EggMovesSplitLearned[1]) + // Example: Marill Egg move, incompatible with Azurill egg moves + res[m] = new CheckResult(Severity.Invalid, string.Format(V375, splitbreedspecies1, splitbreedspecies0), CheckIdentifier.Move); + foreach (int m in IncenseMovesLearned) + // Example: Azurill levelup/tmhm/tutor move, incompatible with Marill egg moves + res[m] = new CheckResult(Severity.Invalid, string.Format(V376, splitbreedspecies0, splitbreedspecies1), CheckIdentifier.Move); + } + } } if (3 <= gen && gen <= 4 && pkm.Format > gen) @@ -2961,9 +3019,9 @@ private CheckResult[] parseMoves(int[] moves, List[] learn, int[] relearn, private void ParseRedYellowIncompatibleMoves(int[] moves, ref CheckResult[] res) { var incompatible = new List(); - if (pkm.Species == 134 && moves.Contains(151) && pkm.CurrentLevel < 47) + if (pkm.Species == 134 && pkm.CurrentLevel < 47 && moves.Contains(151)) { - // Vaporeon in Yellow learn Mist and Acid Armor at level 42, Mist only if level up in day-care + // Vaporeon in Yellow learn Mist and Haze at level 42, Mist only if level up in day-care // Vaporeon in Red Blue learn Acid Armor at level 42 and level 47 in Yellow if (moves.Contains(54)) incompatible.Add(54); @@ -2972,7 +3030,7 @@ private void ParseRedYellowIncompatibleMoves(int[] moves, ref CheckResult[] res) if (incompatible.Any()) incompatible.Add(151); } - if (pkm.Species == 136 && moves.Contains(43) && moves.Contains(123) && pkm.CurrentLevel < 47) + if (pkm.Species == 136 && pkm.CurrentLevel < 47 && moves.Contains(43) && moves.Contains(123)) { // Flareon in Yellow learn Smog at level 42 // Flareon in Red Blue learn Leer at level 42 and level 47 in Yellow @@ -3004,7 +3062,7 @@ private void ParseEvolutionsIncompatibleMoves(int[] moves, List tmhm, ref C if (pkm.Species == 103 && moves.Contains(23) && moves.Any(m => Legal.G1Exeggcute_IncompatibleMoves.Contains(moves[m]))) { // Exeggutor learns stomp at level 28 - // Exeggcute learns Stun Spore at 32, PoisonPowder at 37, SolarBeam at 42 and Sleep Powder at 48 + // Exeggcute learns Stun Spore at 32, PoisonPowder at 37 and Sleep Powder at 48 incompatible_current.Add(23); incompatible_previous.AddRange(Legal.G1Exeggcute_IncompatibleMoves); previousspecies = species[103]; @@ -3028,12 +3086,6 @@ private void ParseEvolutionsIncompatibleMoves(int[] moves, List tmhm, ref C if (EeveeLevels.Any(ev => ev > EvoLevels[i])) incompatible_current.Add(ExclusiveMoves[1][i]); } - // Vaporeon Mist and Eevee Take Down, special case, they are learned at the same level, but Mist only in daycare - if (pkm.Species == 134 && moves.Contains(36) && moves.Contains(54)) - { - incompatible_current.Add(54); - incompatible_previous.Add(36); - } } for (int m = 0; m < 4; m++) @@ -3219,7 +3271,7 @@ private CheckResult[] verifyRelearnEgg() GameVersion ver = gameSource == -1 ? GameVersion.Any : Games[gameSource]; // Generate & Analyze compatibility - res = verifyRelearnEggBase(RelearnMoves, skipOption, ver); + res = verifyRelearnEggBase(RelearnMoves, skipOption, splitBreed, ver); if (res.All(r => r.Valid)) // egg is satisfactory break; } @@ -3227,7 +3279,7 @@ private CheckResult[] verifyRelearnEgg() verifyNoEmptyDuplicates(RelearnMoves, res); return res; } - private CheckResult[] verifyRelearnEggBase(int[] RelearnMoves, int skipOption, GameVersion ver) + private CheckResult[] verifyRelearnEggBase(int[] RelearnMoves, int skipOption, bool splitBreed, GameVersion ver) { CheckResult[] res = new CheckResult[4]; @@ -3241,6 +3293,12 @@ private CheckResult[] verifyRelearnEggBase(int[] RelearnMoves, int skipOption, G var inherited = RelearnMoves.Where(m => m != 0 && (!baseMoves.Contains(m) || inheritMoves.Contains(m))).ToList(); int inheritCt = inherited.Count; + + // Obtain alternate split breed species inherited move + var splitbreedinvalid = false; + var skipOption_alt = !splitBreed ? 0 : skipOption == 1 ? 0 : 1; + var inheritMoves_alt = splitBreed ? Legal.getValidRelearn(pkm, skipOption_alt).ToList() : new List(); + // Get required amount of base moves int unique = baseMoves.Concat(inherited).Distinct().Count(); int reqBase = inheritCt == 4 || baseCt + inheritCt > 4 ? 4 - inheritCt : baseCt; @@ -3276,10 +3334,26 @@ private CheckResult[] verifyRelearnEggBase(int[] RelearnMoves, int skipOption, G res[i] = new CheckResult(Severity.Valid, V167, CheckIdentifier.RelearnMove); else if (inheritMoves.Contains(RelearnMoves[i])) // inherited res[i] = new CheckResult(Severity.Valid, V172, CheckIdentifier.RelearnMove); + else if (inheritMoves_alt.Contains(RelearnMoves[i])) // inherited + splitbreedinvalid = true; else // not inheritable, flag res[i] = new CheckResult(Severity.Invalid, V182, CheckIdentifier.RelearnMove); } + if(splitbreedinvalid) + { + var species = specieslist; + var splitbreedspecies0 = species[Legal.getBaseEggSpecies(pkm, skipOption)]; + var splitbreedspecies1 = species[Legal.getBaseEggSpecies(pkm, skipOption_alt)]; + for (int i = reqBase; i < 4; i++) + { + if (inheritMoves.Contains(RelearnMoves[i]) && !inheritMoves_alt.Contains(RelearnMoves[i])) + res[i] = new CheckResult(Severity.Invalid, string.Format(V379, splitbreedspecies0, splitbreedspecies1), CheckIdentifier.RelearnMove); + if (!inheritMoves.Contains(RelearnMoves[i]) && inheritMoves_alt.Contains(RelearnMoves[i])) + res[i] = new CheckResult(Severity.Invalid, string.Format(V379, splitbreedspecies1, splitbreedspecies0), CheckIdentifier.RelearnMove); + } + } + RelearnBase = baseMoves.ToArray(); return res; } diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index cb2d509ff..5dce207ca 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -1047,6 +1047,56 @@ internal static IEnumerable getBaseEggMoves(PKM pkm, int skipOption, GameVe } return null; } + internal static List[] getExclusiveEvolutionMoves(PKM pkm, int Species,DexLevel[][] evoChains, GameVersion Version) + { + // Return moves that the pokemon could only learn throught the preevolution Species + List[] Moves = new List[evoChains.Length]; + for (int i = 1; i < evoChains.Length; i++) + if (evoChains[i].Any()) + Moves[i] = getExclusiveEvolutionMoves(pkm, Species, evoChains[i], i, Version).ToList(); + else + Moves[i] = new List(); + return Moves; + } + internal static IEnumerable getExclusiveEvolutionMoves(PKM pkm, int Species, DexLevel[] evoChain, int Generation, GameVersion Version) + { + var preevomoves = new List(); + var evomoves = new List(); + var index = Array.FindIndex(evoChain, e => e.Species == Species); + for(int i =0; i < evoChain.Length; i++) + { + var evo = evoChain[i]; + var moves = getMoves(pkm, evo.Species, 1, evo.Level, pkm.AltForm, moveTutor: true, Version: Version, LVL: true, specialTutors: true, Machine: true, MoveReminder: false, RemoveTransferHM: false, Generation: Generation); + if (i >= index) + // Moves from Species or any species bellow in the evolution phase + preevomoves.AddRange(moves); + else + // Moves in phase evolutions after the limit species, this moves should be removed + evomoves.AddRange(moves); + } + preevomoves.RemoveAll(x => evomoves.Contains(x)); + return preevomoves.Distinct().ToList(); + } + internal static List[] getBaseEggMoves(PKM pkm, GameVersion gameSource, int lvl) + { + if (SplitBreed.Contains(pkm.Species)) + return new[] + { + getBaseEggMoves(pkm, 0, gameSource,lvl).ToList(), + getBaseEggMoves(pkm, 1, gameSource,lvl).ToList(), + }; + return new[] { getBaseEggMoves(pkm, 0, gameSource, lvl).ToList(), }; + } + internal static List[] getEggMoves(PKM pkm, GameVersion Version) + { + if (SplitBreed.Contains(pkm.Species)) + return new[] + { + getEggMoves(pkm, getBaseEggSpecies(pkm, 0), 0, Version).ToList(), + getEggMoves(pkm, getBaseEggSpecies(pkm, 1), 0, Version).ToList() + }; + return new[] { getEggMoves(pkm, getBaseEggSpecies(pkm, 0), 0, Version).ToList() }; + } internal static IEnumerable getEggMoves(PKM pkm, int skipOption, GameVersion Version) { return getEggMoves(pkm, getBaseEggSpecies(pkm, skipOption), 0, Version); @@ -3381,5 +3431,19 @@ internal static IEnumerable getTutorMoves(PKM pkm, int species, int form, b } return moves.Distinct(); } + internal static List[] GetEmptyMovesList(DexLevel[][] EvoChainsAllGens) + { + var empty = new List[EvoChainsAllGens.Length]; + for (int i = 0; i < empty.Length; i++) + empty[i] = new List(); + return empty; + } + + internal static List[] GetEmptyEggMovesList() + { + var emptyegg = new List[1]; + emptyegg[0] = new List(); + return emptyegg; + } } } diff --git a/PKHeX/Legality/LegalityCheckStrings.cs b/PKHeX/Legality/LegalityCheckStrings.cs index 3a43f4d2f..42d630400 100644 --- a/PKHeX/Legality/LegalityCheckStrings.cs +++ b/PKHeX/Legality/LegalityCheckStrings.cs @@ -364,6 +364,11 @@ public static class LegalityCheckStrings public static string V371 {get; set;} = "American E-Reader Berry in Japanese savegame."; public static string V373 {get; set;} = "Ability does not match generation 3 species ability."; public static string V374 {get; set;} = "Invalid egg hatch cycles."; + public static string V375 {get; set;} = "{0} Egg Move. Incompatible with {1} egg moves."; + public static string V376 {get; set;} = "{0} Exclusive Move. Incompatible with {1} egg moves."; + public static string V377 {get; set;} = "Egg Move. Not expected in a gift egg."; + public static string V378 {get; set;} = "Inherited move learned by Level-up. Not expected in a gift egg."; + public static string V379 {get; set;} = "{0} Inherited Move. Incompatible with {1} inherited moves."; #endregion } diff --git a/PKHeX/Legality/Tables1.cs b/PKHeX/Legality/Tables1.cs index f23db0eb2..9eab37f8e 100644 --- a/PKHeX/Legality/Tables1.cs +++ b/PKHeX/Legality/Tables1.cs @@ -46,7 +46,7 @@ public static partial class Legal internal static readonly int[] G1WeedleMoves = new[] { 40, 81 }; internal static readonly int[] G1MetapodMoves = G1CaterpieMoves.Concat(new[] { 106 }).ToArray(); internal static readonly int[] G1KakunaMoves = G1WeedleMoves.Concat(new[] { 106 }).ToArray(); - internal static readonly int[] G1Exeggcute_IncompatibleMoves = new[] { 78, 77, 76, 79 }; + internal static readonly int[] G1Exeggcute_IncompatibleMoves = new[] { 78, 77, 79 }; internal static readonly int[] WildPokeBalls1 = {4}; diff --git a/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt b/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt index 9fd49a9f2..7cbb15e2f 100644 --- a/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt +++ b/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt @@ -303,4 +303,9 @@ V369 = Invalid E-Reader Berry. V370 = Japanese E-Reader Berry in international savegame. V371 = American E-Reader Berry in Japanese savegame. V373 = Ability does not match generation 3 species ability. -V374 = Invalid egg hatch cycles. \ No newline at end of file +V374 = Invalid egg hatch cycles. +V375 = {0} Egg Move. Incompatible with {1} egg moves. +V376 = {0} Exclusive Move. Incompatible with {1} egg moves. +V377 = Egg Move. Not expected in a gift egg. +V378 = Inherited move learned by Level-up. Not expected in a gift egg. +V379 = {0} Inherited Move. Incompatible with {1} inherited moves. \ No newline at end of file diff --git a/PKHeX/Resources/text/zh/LegalityCheckStrings_zh.txt b/PKHeX/Resources/text/zh/LegalityCheckStrings_zh.txt index 4fc122a43..87c205df9 100644 --- a/PKHeX/Resources/text/zh/LegalityCheckStrings_zh.txt +++ b/PKHeX/Resources/text/zh/LegalityCheckStrings_zh.txt @@ -303,4 +303,9 @@ V369 = Invalid E-Reader Berry. V370 = Japanese E-Reader Berry in international savegame. V371 = American E-Reader Berry in Japanese savegame. V373 = Ability does not match generation 3 species ability. -V374 = Invalid egg hatch cycles. \ No newline at end of file +V374 = Invalid egg hatch cycles. +V375 = {0} Egg Move. Incompatible with {1} egg moves. +V376 = {0} Exclusive Move. Incompatible with {1} egg moves. +V377 = Egg Move. Not expected in a gift egg. +V378 = Inherited move learned by Level-up. Not expected in a gift egg. +V379 = {0} Inherited Move. Incompatible with {1} inherited moves. \ No newline at end of file