Fix gen7 Eevee eggs checking and cleanup (#1028)

* Fix Eevee eggs in gen7 and cleanup

Needs to mark EncounterstaticMatch as null after verifyencounterstatic
failure
Egg moves were checked in parseMovesWasEggPreRelearn, so verifyeggmoves
function is unnecessay
No need to search friend safari for gen4 transfer
Simplify parsing special egg moves
Skip level-up moves when checking higher level moves

* Add PokePark Encounter

* Fix eggmoves and eventmoves conflict checking

* Add Egg Pokémon Present Eggs

Solve issue #987
Use special move to distinguish eventegg

* Fix Transferred gen3 egg Checking

Refactoring location in gen4transfer

* Fix species recognition of event eggs

include preevolutions checking

* Check encounter before egg for transferred pkm

Remove prerelearnencouner function.
The existence of RelearnMoves is checked in parseMovesSpecialMoveset
This commit is contained in:
wwwwwwzx 2017-04-06 17:41:25 -07:00 committed by Kurt
parent 1dc5831921
commit fc552fbfbe
5 changed files with 82 additions and 111 deletions

View file

@ -112,7 +112,6 @@ namespace PKHeX.Core
verifyNickname();
verifyDVs();
verifyG1OT();
AddLine(verifyEggMoves());
}
private void parsePK3(PKM pk)
{
@ -124,7 +123,6 @@ namespace PKHeX.Core
updateMoveLegality();
updateEncounterInfo();
updateChecks();
AddLine(verifyEggMoves());
}
private void parsePK4(PKM pk)
{
@ -137,7 +135,6 @@ namespace PKHeX.Core
updateMoveLegality();
updateEncounterInfo();
updateChecks();
AddLine(verifyEggMoves());
}
private void parsePK5(PKM pk)
{
@ -150,7 +147,6 @@ namespace PKHeX.Core
updateMoveLegality();
updateEncounterInfo();
updateChecks();
AddLine(verifyEggMoves());
}
private void parsePK6(PKM pk)
{
@ -234,8 +230,6 @@ namespace PKHeX.Core
verifyRegion();
verifyVersionEvolution();
}
if (pkm.GenNumber <= 5)
verifyEggMoves();
// SecondaryChecked = true;
}

View file

@ -180,7 +180,7 @@ namespace PKHeX.Core
: V216, CheckIdentifier.ECPID);
}
}
#region verifyNickname
private void verifyNickname()
{
// If the Pokémon is not nicknamed, it should match one of the language strings.
@ -348,7 +348,7 @@ namespace PKHeX.Core
else
AddLine(Severity.Valid, V11, CheckIdentifier.Nickname);
}
#endregion
private void verifyEVs()
{
var evs = pkm.EVs;
@ -419,6 +419,7 @@ namespace PKHeX.Core
{
// todo
}
#region verifyOT
private void verifyOT()
{
if (EncounterType == typeof(EncounterTrade))
@ -456,7 +457,7 @@ namespace PKHeX.Core
AddLine(Severity.Invalid, V39, CheckIdentifier.Trainer);
}
}
#endregion
private void verifyHyperTraining()
{
if (pkm.Format < 7)
@ -479,7 +480,7 @@ namespace PKHeX.Core
}
}
}
#region verifyEncounter
private CheckResult verifyEncounterLink()
{
// Should NOT be Fateful, and should be in Database
@ -788,6 +789,7 @@ namespace PKHeX.Core
if (result != null)
return result;
EncounterStaticMatch = null; // Mark as no satisfying static result
EncounterMatch = null; // Reset Encounter Object, test for remaining encounters
}
@ -879,7 +881,7 @@ namespace PKHeX.Core
if (pkm.Format != 4 && pkm.Met_Location != 30001)
AddLine(Severity.Invalid, V61, CheckIdentifier.Encounter);
return G3Result ?? new CheckResult(Severity.Invalid, V80, CheckIdentifier.Encounter);
return G3Result ?? EggResult ?? new CheckResult(Severity.Invalid, V80, CheckIdentifier.Encounter);
}
private CheckResult verifyEncounterG4Transfer()
{
@ -900,15 +902,13 @@ namespace PKHeX.Core
if (result != null)
return result;
EncounterStaticMatch = null;
EncounterMatch = null; // Reset Encounter Object, test for remaining encounters
}
if (pkm.WasEgg) // Invalid transfer is already checked in encounter egg
return verifyEncounterEgg();
if (Gen4Result == null && null != (EncounterMatch = Legal.getValidFriendSafari(pkm)))
Gen4Result = verifyEncounterSafari();
if (Gen4Result == null && null != (EncounterMatch = Legal.getValidWildEncounters(pkm)))
Gen4Result = verifyEncounterWild();
@ -931,14 +931,14 @@ namespace PKHeX.Core
switch (pkm.Species)
{
case 251: // Celebi
if (pkm.Met_Location == 30010 || pkm.Met_Location == 30011) // unused || used
if (loc == 30010 || loc == 30011) // unused || used
return Gen4Result;
return new CheckResult(Severity.Invalid, V351, CheckIdentifier.Encounter);
case 243: // Raikou
case 244: // Entei
case 245: // Suicune
if (pkm.Met_Location == 30012 || pkm.Met_Location == 30013) // unused || used
if (loc == 30012 || loc == 30013) // unused || used
return Gen4Result;
return new CheckResult(Severity.Invalid, V351, CheckIdentifier.Encounter);
}
@ -981,7 +981,7 @@ namespace PKHeX.Core
return new CheckResult(CheckIdentifier.Encounter);
}
#endregion
private void verifyLevel()
{
MysteryGift MatchedGift = EncounterMatch as MysteryGift;
@ -1015,7 +1015,7 @@ namespace PKHeX.Core
else
AddLine(Severity.Valid, V88, CheckIdentifier.Level);
}
#region verifyMedals
private void verifyMedals()
{
if (pkm.Format < 6)
@ -1059,7 +1059,7 @@ namespace PKHeX.Core
else if (DistCount > 0)
{ AddLine(Severity.Fishy, V94, CheckIdentifier.Training); }
}
#endregion
private void verifyRibbons()
{
if (!Encounter.Valid)
@ -1330,7 +1330,7 @@ namespace PKHeX.Core
AddLine(Severity.Valid, V115, CheckIdentifier.Ability);
}
#region verifyBall
private void verifyBallEquals(params int[] balls)
{
int ball = pkm.Ball;
@ -1641,7 +1641,7 @@ namespace PKHeX.Core
}
AddLine(Severity.Invalid, V125, CheckIdentifier.Ball);
}
#endregion
private CheckResult verifyHistory()
{
if (!Encounter.Valid)
@ -2310,7 +2310,7 @@ namespace PKHeX.Core
break;
}
}
#region verifyMoves
private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any)
{
var validLevelMoves = Legal.getValidMovesAllGens(pkm, EvoChainsAllGens, Tutor: false, Machine: false, RemoveTransferHM:false);
@ -2340,6 +2340,9 @@ namespace PKHeX.Core
encounters.AddRange(EncounterStaticMatch);
encounters.Add(EncounterMatch); // can be null
if (pkm.Gen3 && pkm.WasEgg) //Can not distinguish event egg and normal egg after hatching, and not in the EncounterStaticMatch
encounters.AddRange(Legal.getG3SpecialEggEncounter(pkm));
// Iterate over encounters
bool pre3DS = pkm.GenNumber < 6;
CheckResult[] res = new CheckResult[4];
@ -2475,15 +2478,12 @@ namespace PKHeX.Core
{
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)
// Gen 1-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 = EncounterMatch is IMoveset
? parseMovesSpecialMoveset(Moves, validLevelMoves, validTMHM, validTutor)
: parseMovesPreRelearnEncounter(Moves, validLevelMoves, validTMHM, validTutor); // Everything else, non-egg encounters only
res = parseMovesSpecialMoveset(Moves, validLevelMoves, validTMHM, validTutor);
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.
@ -2507,13 +2507,13 @@ namespace PKHeX.Core
int splitctr = Legal.SplitBreed.Contains(pkm.Species) ? 1 : 0;
foreach (var ver in Games)
{
var EventEggMoves = !pkm.WasGiftEgg? Legal.getSpecialEggMoves(pkm, ver).ToArray() : new int[0];
var EventEggMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0];
for (int i = 0; i <= splitctr; i++)
{
var baseEggMoves = Legal.getBaseEggMoves(pkm, i, ver, 100)?.ToArray() ?? new int[0];
var EggMoves = pkm.WasGiftEgg ? (EncounterMatch as EncounterStatic)?.Moves ?? new int[0] : Legal.getEggMoves(pkm, i, ver).ToArray();
var LvlupEggMoves = Legal.getBaseEggMoves(pkm, i, ver, 100)?.ToArray() ?? new int[0];
var EggMoves = Legal.getEggMoves(pkm, i, ver).ToArray();
res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, new int[0], baseEggMoves, EggMoves, EventEggMoves);
res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, new int[0], LvlupEggMoves, EggMoves, EventEggMoves);
if (res.All(r => r.Valid)) // moves is satisfactory
return res;
@ -2521,11 +2521,6 @@ namespace PKHeX.Core
}
return res;
}
private CheckResult[] parseMovesIsEggPreRelearnEvent(int[] Moves)
{
int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0];
return parseMovesIsEggPreRelearn(Moves, SpecialMoves, false);
}
private CheckResult[] parseMovesSketch(int[] Moves)
{
CheckResult[] res = new CheckResult[4];
@ -2549,12 +2544,9 @@ namespace PKHeX.Core
{
if (pkm.IsEgg)
{
if (MatchIsMysteryGift)
return parseMovesIsEggPreRelearnEvent(Moves);
int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves;
var allowinherited = SpecialMoves == null && !pkm.WasGiftEgg && !pkm.WasEventEgg;
return parseMovesIsEggPreRelearn(Moves, SpecialMoves ?? new int[0], allowinherited);
int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0];
var allowinherited = SpecialMoves == null && !pkm.WasGiftEgg && !pkm.WasEventEgg && !MatchIsMysteryGift;
return parseMovesIsEggPreRelearn(Moves, SpecialMoves, allowinherited);
}
if (pkm.WasEgg)
return parseMovesWasEggPreRelearn(Moves, validLevelMoves, validTMHM, validTutor);
@ -2574,11 +2566,6 @@ namespace PKHeX.Core
RelearnBase = (EncounterMatch as MysteryGift).RelearnMoves;
return res;
}
private CheckResult[] parseMovesPreRelearnEncounter(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor)
{
int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0];
return parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0]);
}
private CheckResult[] parseMovesRelearnSplitBreed(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor, GameVersion game)
{
CheckResult[] res = new CheckResult[4];
@ -2607,12 +2594,12 @@ namespace PKHeX.Core
return res;
}
private CheckResult[] parseMoves(int[] moves, List<int>[] learn, int[] relearn, List<int>[] tmhm, List<int>[] tutor, int[] special, int[] baseegg, int[] egg, int[] eventegg)
private CheckResult[] parseMoves(int[] moves, List<int>[] learn, int[] relearn, List<int>[] tmhm, List<int>[] tutor, int[] special, int[] lvlupegg, int[] egg, int[] eventegg)
{
CheckResult[] res = new CheckResult[4];
var Gen1MovesLearned = new List<int>();
var EggMovesLearned = new List<int>();
var BaseEggMovesLearned = new List<int>();
var LvlupEggMovesLearned = new List<int>();
var EventEggMovesLearned = new List<int>();
var IsGen2Pkm = pkm.Format == 2 || pkm.VC2;
// Check none moves and relearn moves before generation moves
@ -2671,11 +2658,13 @@ namespace PKHeX.Core
if (gen == generations.Last())
{
// Check base egg moves after all the moves but just before egg moves to different it from normal level up moves
// Check higher-level moves after all the moves but just before egg moves to differentiate it from normal level up moves
// Also check if the base egg moves is a non tradeback move
for (int m = 0; m < 4; m++)
{
if (!baseegg.Contains(moves[m]))
if (res[m]?.Valid ?? false) // Skip valid move
continue;
if (!lvlupegg.Contains(moves[m])) // Check if contains level-up egg moves from parents
continue;
if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1)
@ -2685,7 +2674,7 @@ namespace PKHeX.Core
}
else
res[m] = new CheckResult(Severity.Valid, V345, CheckIdentifier.Move);
BaseEggMovesLearned.Add(m);
LvlupEggMovesLearned.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
@ -2725,7 +2714,7 @@ namespace PKHeX.Core
// 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
var RegularEggMovesLearned = EggMovesLearned.Union(BaseEggMovesLearned).ToList();
var RegularEggMovesLearned = EggMovesLearned.Union(LvlupEggMovesLearned).ToList();
if (RegularEggMovesLearned.Any() && EventEggMovesLearned.Any())
{
// Moves that are egg moves or event egg moves but not both
@ -2738,7 +2727,7 @@ namespace PKHeX.Core
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);
else if (!EventEggMovesLearned.Contains(m) && BaseEggMovesLearned.Contains(m))
else if (!EventEggMovesLearned.Contains(m) && LvlupEggMovesLearned.Contains(m))
res[m] = new CheckResult(Severity.Invalid, V358, CheckIdentifier.Move);
}
}
@ -3130,38 +3119,7 @@ namespace PKHeX.Core
res[i] = new CheckResult(Severity.Invalid, V168, res[i].Identifier);
}
}
private CheckResult verifyEggMoves()
{
if (!pkm.WasEgg || vMoves.All(m => m.Valid))
return new CheckResult(CheckIdentifier.Egg);
// todo: egg move breeding legality
switch (pkm.GenNumber)
{
case 1:
case 2:
// Check Both Egg Moves -- egg moves are initially checked with no game as the base.
foreach (var game in new[] {GameVersion.GS, GameVersion.C})
{
vMoves = verifyMoves(game);
if (vMoves.Any(m => !m.Valid))
continue;
// todo: check compatibility of parents (chain wise)
return new CheckResult(Severity.Valid, string.Format(V185, game), CheckIdentifier.Egg);
}
break;
case 3:
return new CheckResult(Severity.NotImplemented, V186, CheckIdentifier.Egg);
case 4:
return new CheckResult(Severity.NotImplemented, V186, CheckIdentifier.Egg);
}
return new CheckResult(CheckIdentifier.Egg);
}
#endregion
public static string[] movelist = Util.getMovesList("en");
private static readonly string[] EventRibName =
{

View file

@ -833,10 +833,21 @@ namespace PKHeX.Core
{
return getEggMoves(pkm, getBaseSpecies(pkm, skipOption), 0, Version);
}
internal static IEnumerable<int> getSpecialEggMoves(PKM pkm, GameVersion Version)
internal static IEnumerable<EncounterStatic> getG3SpecialEggEncounter(PKM pkm)
{
return getSpecialEggMoves(pkm, getBaseSpecies(pkm), 0, Version);
IEnumerable<DexLevel> dl = getValidPreEvolutions(pkm,MaxSpeciesID_3);
var table = EventEgg_G3.Where(e => dl.Any(d => d.Species == e.Species));
foreach (EncounterStatic e in table)
{
if (pkm.Moves.All(m => !e.Moves.Contains(m))) // No special move
continue;
if (e.Nature != Nature.Random && pkm.Nature != (int)e.Nature)
continue;
if (e.Gender != -1 && e.Gender != pkm.Gender)
continue;
yield return e;
}
}
// Encounter
@ -2639,22 +2650,6 @@ namespace PKHeX.Core
}
return r;
}
private static IEnumerable<int> getSpecialEggMoves(PKM pkm, int species, int alform, GameVersion Version = GameVersion.Any)
{
if (!pkm.InhabitedGeneration(pkm.GenNumber, species))
return new List<int>();
switch (pkm.GenNumber)
{
case 3:
{
var boxencounter = Encounter_Box.FirstOrDefault(e => e.Species == species);
if (boxencounter != null)
return boxencounter.Moves;
break;
}
}
return new List<int>();
}
private static IEnumerable<int> getEggMoves(PKM pkm, int species, int formnum, GameVersion Version = GameVersion.Any)
{
if (!pkm.InhabitedGeneration(pkm.GenNumber, species))

View file

@ -3,7 +3,7 @@
public class EncounterStatic : IEncounterable, IMoveset
{
public int Species { get; set; }
public int[] Moves { get; set; } = new int[4];
public int[] Moves { get; set; }
public int Level;
public int Location;

View file

@ -216,6 +216,30 @@ namespace PKHeX.Core
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[] EventEgg_G3 = Encounter_Box.Concat(new[]
{
// PokePark Eggs
new EncounterStatic { Species = 054, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{300} }, // Psyduck with Mud Sport
new EncounterStatic { Species = 172, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{266} }, // Pichu with Follow me
new EncounterStatic { Species = 174, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{321} }, // Igglybuff with Tickle
new EncounterStatic { Species = 222, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{300} }, // Corsola with Mud Sport
new EncounterStatic { Species = 276, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{294} }, // Taillow with Feather Dance
new EncounterStatic { Species = 283, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{300} }, // Surskit with Mud Sport
new EncounterStatic { Species = 293, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{298} }, // Whismur with Teeter Dance
new EncounterStatic { Species = 300, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{205} }, // Skitty with Rollout
new EncounterStatic { Species = 311, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{346} }, // Plusle with Water Sport
new EncounterStatic { Species = 312, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{300} }, // Minun with Mud Sport
new EncounterStatic { Species = 325, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{253} }, // Spoink with Uproar
new EncounterStatic { Species = 327, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{047} }, // Spinda with Sing
new EncounterStatic { Species = 331, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{227} }, // Cacnea with Encore
new EncounterStatic { Species = 341, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{346} }, // Corphish with Water Sport
new EncounterStatic { Species = 360, Level = 05, EggLocation = 255, Version = GameVersion.RSBOX, Moves = new[]{321} }, // Wynaut with Tickle
// Egg Pokémon Present Eggs
new EncounterStatic { Species = 043, Level = 05, EggLocation = 255, Version = GameVersion.FRLG, Moves = new[]{073} }, // Oddish with Leech Seed
new EncounterStatic { Species = 052, Level = 05, EggLocation = 255, Version = GameVersion.FRLG, Moves = new[]{080} }, // Meowth with Petal Dance
new EncounterStatic { Species = 060, Level = 05, EggLocation = 255, Version = GameVersion.FRLG, Moves = new[]{186} }, // Poliwag with Sweet Kiss
new EncounterStatic { Species = 069, Level = 05, EggLocation = 255, Version = GameVersion.FRLG, Moves = new[]{298} }, // Bellsprout with Teeter Dance
}).ToArray();
internal static readonly EncounterStatic[] Encounter_RSE_Roam =
{
@ -330,8 +354,8 @@ namespace PKHeX.Core
new EncounterStatic { Species = 386, Level = 30, Location = 187, Version = GameVersion.LG, Form = 2, Fateful = true }, // Deoxys @ Birth Island
};
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();
internal static readonly EncounterStatic[] Encounter_RSE = Encounter_RSE_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_RSE)).Concat(Encounter_RSE_Regular).Concat(EventEgg_G3).ToArray();
internal static readonly EncounterStatic[] Encounter_FRLG = Encounter_FRLG_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_FRLG)).Concat(Encounter_FRLG_Stationary).Concat(EventEgg_G3).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};