From f0e6e96435341cea88a1dcfa058a9584be9dcb7b Mon Sep 17 00:00:00 2001 From: javierhimura Date: Sat, 1 Apr 2017 18:45:13 +0200 Subject: [PATCH] parseMoves functions improvement (#1018) * Add egg locations and gits egg locations for gen 4 and 5 Add WasGiftEgg property and diferenciate from WasEventEgg * Separate parseMoves Pre Relearn and Post Relearn generations Separte parseMoves Pre Relearn egg-encounter for non-egg encounters, a gen3 pokemon can be both Post Relearn IsEgg pokemon should have all moves as relearn moves parseMovesSketch should not be used for Smeargle inside an egg WasGiftEgg should not have egg moves * Fix WasEgg and WasEventEgg functions for Manaphy * Add gen 5 trade egg location Check for generation 3 IsEgg if is a gift egg or an event egg that there is a valid encounter for the egg * Move parseMovesGetGift bellow WasEggPreRelearn. WasEggPreRelearn is already checking for gift encounters, some generation 3 pokemon could be both an egg or an event encounter * Check for gift egg without valid encounter in verifyEncounterEgg * Check WasEventEgg without encounter in verifyEncounterEgg --- PKHeX/Legality/Checks.cs | 109 ++++++++++++------ PKHeX/Legality/LegalityCheckStrings.cs | 2 + PKHeX/Legality/Tables4.cs | 8 ++ PKHeX/Legality/Tables5.cs | 4 + PKHeX/PKM/PK3.cs | 3 +- PKHeX/PKM/PK4.cs | 4 +- PKHeX/PKM/PK5.cs | 2 +- PKHeX/PKM/PK6.cs | 4 +- PKHeX/PKM/PK7.cs | 4 +- PKHeX/PKM/PKM.cs | 27 ++++- .../text/en/LegalityCheckStrings_en.txt | 2 + 11 files changed, 125 insertions(+), 44 deletions(-) diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index 75748d2eb..d6e63d48f 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -499,7 +499,10 @@ private CheckResult verifyEncounterEgg() // Check Species if (Legal.NoHatchFromEgg.Contains(pkm.Species) && EncounterMatch == null) return new CheckResult(Severity.Invalid, V50, CheckIdentifier.Encounter); - + if (pkm.WasGiftEgg && EncounterMatch == null) + return new CheckResult(Severity.Invalid, V359, CheckIdentifier.Encounter); + if (pkm.WasEventEgg && EncounterMatch == null) + return new CheckResult(Severity.Invalid, V360, CheckIdentifier.Encounter); switch (pkm.GenNumber) { case 1: @@ -2235,29 +2238,38 @@ private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any) 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; + CheckResult[] res = null; int[] Moves = pkm.Moves; - if (pkm.IsEgg && pkm.GenNumber < 6) - { - if(EventGiftMatch?.Count > 0) - res = verifyMovesEggPreRelearnEvent(Moves); - else - { - var SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ?? - (EncounterMatch as EncounterStatic)?.Moves ?? - (EncounterMatch as EncounterTrade)?.Moves; - var allowinherited = SpecialMoves == null; - res = verifyMovesIsEggPreRelearn(Moves, SpecialMoves ?? new int[0], allowinherited); - } - } - else if (pkm.Species == 235) // Smeargle can have any move except a few + if (!pkm.IsEgg && pkm.Species == 235) // Smeargle can have any move except a few res = parseMovesSketch(Moves); - else if (pkm.WasEgg && pkm.GenNumber < 6) - res = verifyMovesWasEggPreRelearn(Moves, validLevelMoves, validTMHM, validTutor); + else if (pkm.GenNumber < 6) + { + if (pkm.IsEgg) + { + if (EventGiftMatch?.Count > 0) + res = parseMovesIsEggPreRelearnEvent(Moves); + else + { + var SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ?? + (EncounterMatch as EncounterStatic)?.Moves ?? + (EncounterMatch as EncounterTrade)?.Moves; + var allowinherited = SpecialMoves == null && !pkm.WasGiftEgg && !pkm.WasEventEgg; + res = parseMovesIsEggPreRelearn(Moves, SpecialMoves ?? new int[0], allowinherited); + } + } + else if (pkm.WasEgg) + res = parseMovesWasEggPreRelearn(Moves, validLevelMoves, validTMHM, validTutor); + else if (EventGiftMatch?.Count > 1) // Multiple possible non-egg Mystery Gifts matched, get the best match too + res = parseMovesGetGift(Moves, validLevelMoves, validTMHM, validTutor); + else + res = parseMovesPreRelearnEncounter(Moves, validLevelMoves, validTMHM, validTutor, game); + } else if (EventGiftMatch?.Count > 1) // Multiple possible Mystery Gifts matched, get the best match too res = parseMovesGetGift(Moves, validLevelMoves, validTMHM, validTutor); + else if (pkm.WasEgg && Legal.SplitBreed.Contains(pkm.Species)) + res = parseMovesRelearnSplitBreed(Moves, validLevelMoves, validTMHM, validTutor, game); else // Everything else - res = parseMovesRegular(Moves, validLevelMoves, validTMHM, validTutor, new int[0], 0, game); + res = parseMovesRelearn(Moves, validLevelMoves, validTMHM, validTutor, 0, game); // Duplicate Moves Check verifyNoEmptyDuplicates(Moves, res); @@ -2326,7 +2338,7 @@ private GameVersion[] getBaseMovesIsEggGames() } return Games; } - private CheckResult[] verifyMovesIsEggPreRelearn(int[] Moves, int[] SpecialMoves, bool allowinherited) + private CheckResult[] parseMovesIsEggPreRelearn(int[] Moves, int[] SpecialMoves, bool allowinherited) { CheckResult[] res = new CheckResult[4]; var ValidSpecialMoves = SpecialMoves.Where(m => m != 0).ToList(); @@ -2364,17 +2376,19 @@ private CheckResult[] verifyMovesIsEggPreRelearn(int[] Moves, int[] SpecialMoves } return res; } - private CheckResult[] verifyMovesWasEggPreRelearn(int[] Moves, List[] validLevelMoves, List[] validTMHM, List[] validTutor) + private CheckResult[] parseMovesWasEggPreRelearn(int[] Moves, List[] validLevelMoves, List[] validTMHM, List[] validTutor) { CheckResult[] res = new CheckResult[4]; + // Gen 3 could have an egg origin and a non-egg origin, check first non-egg origin if (pkm.GenNumber == 3 && !pkm.HasOriginalMetLocation && EncounterMatch !=null) { res = EventGiftMatch?.Count > 1 ? parseMovesGetGift(Moves, validLevelMoves, validTMHM, validTutor) // Multiple possible Mystery Gifts matched, get the best match too - : parseMovesRegular(Moves, validLevelMoves, validTMHM, validTutor, new int[0], 0, GameVersion.Any); // Everything else + : parseMovesPreRelearnEncounter(Moves, validLevelMoves, validTMHM, validTutor, GameVersion.Any); // Everything else, non-egg encounters only if (res.All(r => r.Valid)) // moves are satisfactory return res; + // If non-egg encounter is not valid check egg-encounter with eggmoves and without special moves } // Some games can have different egg movepools. Have to check all situations. @@ -2398,22 +2412,26 @@ private CheckResult[] verifyMovesWasEggPreRelearn(int[] Moves, List[] valid int splitctr = Legal.SplitBreed.Contains(pkm.Species) ? 1 : 0; foreach (var ver in Games) { + var EventEggMoves = pkm.WasEgg && !pkm.WasGiftEgg ? Legal.getSpecialEggMoves(pkm, ver).ToArray() : new int[0]; for (int i = 0; i <= splitctr; i++) { var baseEggMoves = Legal.getBaseEggMoves(pkm, i, ver, 100)?.ToArray() ?? new int[0]; - res = parseMovesRegular(Moves, validLevelMoves, validTMHM, validTutor, baseEggMoves, i, ver); + var EggMoves = pkm.WasEgg && !pkm.WasGiftEgg ? Legal.getEggMoves(pkm, i, ver).ToArray() : new int[0]; + + res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, new int[0], baseEggMoves, EggMoves, EventEggMoves); + if (res.All(r => r.Valid)) // moves is satisfactory return res; } } return res; } - private CheckResult[] verifyMovesEggPreRelearnEvent(int[] Moves) + private CheckResult[] parseMovesIsEggPreRelearnEvent(int[] Moves) { foreach (MysteryGift mg in EventGiftMatch) { int[] SpecialMoves = mg.Moves; - CheckResult[] res = verifyMovesIsEggPreRelearn(Moves, SpecialMoves, false); + CheckResult[] res = parseMovesIsEggPreRelearn(Moves, SpecialMoves, false); if (res.Any(r => !r.Valid)) continue; @@ -2422,7 +2440,7 @@ private CheckResult[] verifyMovesEggPreRelearnEvent(int[] Moves) return res; } // no Mystery Gifts matched - return verifyMovesIsEggPreRelearn(Moves, new int[0], false); + return parseMovesIsEggPreRelearn(Moves, new int[0], false); } private CheckResult[] parseMovesSketch(int[] Moves) { @@ -2452,23 +2470,46 @@ private CheckResult[] parseMovesGetGift(int[] Moves, List[] validLevelMoves // no Mystery Gifts matched return parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, new int[0], new int[0], new int[0], new int[0]); } - private CheckResult[] parseMovesRegular(int[] Moves, List[] validLevelMoves, List[] validTMHM, List[] validTutor, int[] baseEggMoves, int SkipOption, GameVersion game) + private CheckResult[] parseMovesPreRelearnEncounter(int[] Moves, List[] validLevelMoves, List[] validTMHM, List[] validTutor, GameVersion game) { - int[] EggMoves = pkm.WasEgg ? Legal.getEggMoves(pkm, SkipOption, game).ToArray() : new int[0]; - int[] EventEggMoves = pkm.WasEgg ? Legal.getSpecialEggMoves(pkm, game).ToArray() : new int[0]; + int[] SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ?? + (EncounterMatch as EncounterStatic)?.Moves ?? + (EncounterMatch as EncounterTrade)?.Moves ?? + new int[0]; + + CheckResult[] res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0]); + + 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 is satisfactory + return res; + } + + return res; + } + private CheckResult[] parseMovesRelearn(int[] Moves, List[] validLevelMoves, List[] validTMHM, List[] validTutor, int SkipOption, GameVersion game) + { + int[] EggMoves = pkm.WasEgg && !pkm.WasGiftEgg? Legal.getEggMoves(pkm, SkipOption, game).ToArray() : new int[0]; + int[] EventEggMoves = pkm.WasEgg && !pkm.WasGiftEgg ? Legal.getSpecialEggMoves(pkm, game).ToArray() : 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, baseEggMoves, EggMoves, EventEggMoves); - - if (pkm.GenNumber < 6) - return res; + CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], EggMoves, EventEggMoves); for (int i = 0; i < 4; i++) - if (res[i].Flag && !RelearnMoves.Contains(Moves[i])) + if ((pkm.IsEgg || res[i].Flag) && !RelearnMoves.Contains(Moves[i])) res[i] = new CheckResult(Severity.Invalid, string.Format(V170, res[i].Comment), res[i].Identifier); return res; diff --git a/PKHeX/Legality/LegalityCheckStrings.cs b/PKHeX/Legality/LegalityCheckStrings.cs index e55c3c245..157a4d4c2 100644 --- a/PKHeX/Legality/LegalityCheckStrings.cs +++ b/PKHeX/Legality/LegalityCheckStrings.cs @@ -344,6 +344,8 @@ public static class LegalityCheckStrings public static string V354 {get; set;} = "Non Platinum Shaymin from Flower Paradise. Unreleased event."; public static string V357 {get; set;} = "Only one Ninjask move allowed."; public static string V358 {get; set;} = "Inherited move learned by Level-up. Incompatible with event egg moves."; + public static string V359 {get; set;} = "Unable to match an gift egg encounter from origin game."; + public static string V360 {get; set;} = "Unable to match an event egg encounter from origin game."; #endregion } diff --git a/PKHeX/Legality/Tables4.cs b/PKHeX/Legality/Tables4.cs index d7d81750b..820c72a02 100644 --- a/PKHeX/Legality/Tables4.cs +++ b/PKHeX/Legality/Tables4.cs @@ -1169,5 +1169,13 @@ public static partial class Legal 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 234, //233: Pokéwalker }; + internal static int[] GiftEggLocation4 = + { + 2009, 2010, 2011, 2013, 2014 + }; + internal static int[] EggLocations4 = + { + 2000, 2002, 2009, 2010, 2011, 2013, 2014 + }; } } diff --git a/PKHeX/Legality/Tables5.cs b/PKHeX/Legality/Tables5.cs index bd25d9174..d97aaaccf 100644 --- a/PKHeX/Legality/Tables5.cs +++ b/PKHeX/Legality/Tables5.cs @@ -878,5 +878,9 @@ public static partial class Legal 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 139, 140, //138 --- 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, }; + internal static int[] EggLocations5 = + { + 30002, 60002, 60003 + }; } } diff --git a/PKHeX/PKM/PK3.cs b/PKHeX/PKM/PK3.cs index 82424056b..f05dd9688 100644 --- a/PKHeX/PKM/PK3.cs +++ b/PKHeX/PKM/PK3.cs @@ -163,7 +163,8 @@ public PK3(byte[] decryptedData = null, string ident = null) public override bool WasEgg => Met_Level == 0; public override bool WasEvent => Met_Location == 255; // Fateful public override bool WasIngameTrade => Met_Location == 254; // Trade - public override bool WasEventEgg => Met_Location == 253; // Gift Egg + public override bool WasGiftEgg => IsEgg && Met_Location == 253; // Gift Egg, indistinguible from normal eggs after hatch + public override bool WasEventEgg => IsEgg && Met_Location == 255; // Event Egg, indistinguible from normal eggs after hatch public override byte[] Encrypt() { diff --git a/PKHeX/PKM/PK4.cs b/PKHeX/PKM/PK4.cs index d2afbe1dd..64b23e946 100644 --- a/PKHeX/PKM/PK4.cs +++ b/PKHeX/PKM/PK4.cs @@ -384,10 +384,10 @@ public override int Characteristic } } // Legality Extensions - public override bool WasEgg => GenNumber < 4 ? base.WasEgg : Egg_Location > 0; + public override bool WasEgg => GenNumber < 4 ? base.WasEgg : Species == 490 && Egg_Location == 3001 || Legal.EggLocations4.Contains(Egg_Location); public override bool WasEvent => Met_Location >= 3000 && Met_Location <= 3076 || FatefulEncounter; public override bool WasIngameTrade => Met_Location == 2001; // Trade - public override bool WasEventEgg => Met_Location == 2002; // Gift Egg + public override bool WasEventEgg => WasEgg && Species == 490; // Manaphy was the only generation 4 released event egg // Methods public override byte[] Encrypt() { diff --git a/PKHeX/PKM/PK5.cs b/PKHeX/PKM/PK5.cs index 3b928f2fb..444ab62df 100644 --- a/PKHeX/PKM/PK5.cs +++ b/PKHeX/PKM/PK5.cs @@ -301,7 +301,7 @@ public override int Characteristic } // Legality Extensions - public override bool WasEgg => GenNumber < 4 ? base.WasEgg : GenNumber == 4 ? Egg_Location > 0 : Legal.EggLocations.Contains(Egg_Location); + public override bool WasEgg => GenNumber < 5 ? base.WasEgg : Legal.EggLocations5.Contains(Egg_Location); // Methods public override byte[] Encrypt() diff --git a/PKHeX/PKM/PK6.cs b/PKHeX/PKM/PK6.cs index bee8a0071..98f9ce8ee 100644 --- a/PKHeX/PKM/PK6.cs +++ b/PKHeX/PKM/PK6.cs @@ -584,9 +584,9 @@ public void TradeMemory(bool Bank) // Legality Properties public override bool WasLink => Met_Location == 30011; - public override bool WasEgg => GenNumber < 4 ? base.WasEgg : GenNumber == 4 ? Egg_Location > 0 : Legal.EggLocations.Contains(Egg_Location); + public override bool WasEgg => GenNumber < 6 ? base.WasEgg : Legal.EggLocations.Contains(Egg_Location); public override bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter && Species != 386; - public override bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1; + public override bool WasEventEgg => GenNumber < 5 ? base.WasEventEgg : ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1; public override bool WasTradedEgg => Egg_Location == 30002 || GenNumber == 4 && Egg_Location == 2002; public override bool WasIngameTrade => Met_Location == 30001 || GenNumber == 4 && Egg_Location == 2001; diff --git a/PKHeX/PKM/PK7.cs b/PKHeX/PKM/PK7.cs index 9a576865f..b05676f07 100644 --- a/PKHeX/PKM/PK7.cs +++ b/PKHeX/PKM/PK7.cs @@ -621,9 +621,9 @@ public void TradeMemory(bool Bank) // Legality Properties public override bool WasLink => Met_Location == 30011; - public override bool WasEgg => GenNumber < 4 ? base.WasEgg : GenNumber == 4 ? Egg_Location > 0 : Legal.EggLocations.Contains(Egg_Location); + public override bool WasEgg => GenNumber < 6 ? base.WasEgg : Legal.EggLocations.Contains(Egg_Location); public override bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter && Species != 386; - public override bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1; + public override bool WasEventEgg => GenNumber < 5 ? base.WasEventEgg : ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1; public override bool WasTradedEgg => Egg_Location == 30002 || GenNumber == 4 && Egg_Location == 2002; public override bool WasIngameTrade => Met_Location == 30001 || GenNumber == 4 && Egg_Location == 2001; } diff --git a/PKHeX/PKM/PKM.cs b/PKHeX/PKM/PKM.cs index 821e6fbfb..e650f5918 100644 --- a/PKHeX/PKM/PKM.cs +++ b/PKHeX/PKM/PKM.cs @@ -423,12 +423,35 @@ public virtual bool WasEgg { get { - return Egg_Location > 0 || _WasEgg; + switch (GenNumber) + { + case 4: return Species == 490 && Egg_Location == 3001 || Legal.EggLocations4.Contains(Egg_Location); + case 5: return Legal.EggLocations5.Contains(Egg_Location); + case 6: + case 7: return Legal.EggLocations.Contains(Egg_Location); + } + // Gen 1/2 and pal park Gen 3 + return _WasEgg; } set { _WasEgg = value; } } + public virtual bool WasGiftEgg + { + get + { + if (!WasEgg) return false; + switch(GenNumber) + { + case 4: return Legal.GiftEggLocation4.Contains(Egg_Location); + case 5: return Egg_Location == 60003; + case 6: return Egg_Location == 60004; + case 7: return Egg_Location == 60002; + } + return false; + } + } public virtual bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter; - public virtual bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location > 0)) && Met_Level == 1; + public virtual bool WasEventEgg => GenNumber == 4 ? WasEgg && Species == 490 : ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location > 0)) && Met_Level == 1; public virtual bool WasTradedEgg => Egg_Location == 30002 || GenNumber == 4 && Egg_Location == 2002; public virtual bool WasIngameTrade => Met_Location == 30001 || GenNumber == 4 && Egg_Location == 2001; public virtual bool IsUntraded => Format >= 6 && string.IsNullOrWhiteSpace(HT_Name) && GenNumber == Format; diff --git a/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt b/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt index 5e52261fc..093fcf203 100644 --- a/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt +++ b/PKHeX/Resources/text/en/LegalityCheckStrings_en.txt @@ -279,4 +279,6 @@ V353 = Non japanese Mew from Faraway Island. Unreleased event. V354 = Non Platinum Shaymin from Flower Paradise. Unreleased event. V357 = Only one Ninjask move allowed. V358 = Inherited move learned by Level-up. Incompatible with event egg moves. +V359 = Unable to match an gift egg encounter from origin game.; +V360 = Unable to match an event egg encounter from origin game.; \ No newline at end of file