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

View File

@@ -180,7 +180,7 @@ private void verifyECPID()
: 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 @@ private void verifyNicknameTrade()
else
AddLine(Severity.Valid, V11, CheckIdentifier.Nickname);
}
#endregion
private void verifyEVs()
{
var evs = pkm.EVs;
@@ -419,6 +419,7 @@ private void verifyDVs()
{
// todo
}
#region verifyOT
private void verifyOT()
{
if (EncounterType == typeof(EncounterTrade))
@@ -456,7 +457,7 @@ private void verifyG1OT()
AddLine(Severity.Invalid, V39, CheckIdentifier.Trainer);
}
}
#endregion
private void verifyHyperTraining()
{
if (pkm.Format < 7)
@@ -479,7 +480,7 @@ private void verifyHyperTraining()
}
}
}
#region verifyEncounter
private CheckResult verifyEncounterLink()
{
// Should NOT be Fateful, and should be in Database
@@ -788,6 +789,7 @@ private CheckResult verifyEncounter()
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 @@ private CheckResult verifyEncounterG3Transfer()
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 @@ private CheckResult verifyEncounterG4Transfer()
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 @@ private CheckResult verifyEncounterG4Transfer()
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 @@ private CheckResult verifyVCEncounter(int baseSpecies)
return new CheckResult(CheckIdentifier.Encounter);
}
#endregion
private void verifyLevel()
{
MysteryGift MatchedGift = EncounterMatch as MysteryGift;
@@ -1015,7 +1015,7 @@ private void verifyLevel()
else
AddLine(Severity.Valid, V88, CheckIdentifier.Level);
}
#region verifyMedals
private void verifyMedals()
{
if (pkm.Format < 6)
@@ -1059,7 +1059,7 @@ private void verifyMedalsEvent()
else if (DistCount > 0)
{ AddLine(Severity.Fishy, V94, CheckIdentifier.Training); }
}
#endregion
private void verifyRibbons()
{
if (!Encounter.Valid)
@@ -1330,7 +1330,7 @@ private void verifyAbility()
AddLine(Severity.Valid, V115, CheckIdentifier.Ability);
}
#region verifyBall
private void verifyBallEquals(params int[] balls)
{
int ball = pkm.Ball;
@@ -1641,7 +1641,7 @@ private void verifyBallEggGen7()
}
AddLine(Severity.Invalid, V125, CheckIdentifier.Ball);
}
#endregion
private CheckResult verifyHistory()
{
if (!Encounter.Valid)
@@ -2310,7 +2310,7 @@ private void verifyVersionEvolution()
break;
}
}
#region verifyMoves
private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any)
{
var validLevelMoves = Legal.getValidMovesAllGens(pkm, EvoChainsAllGens, Tutor: false, Machine: false, RemoveTransferHM:false);
@@ -2339,7 +2339,10 @@ private CheckResult[] parseMovesForEncounters(GameVersion game, List<int>[] vali
if (null != EncounterStaticMatch)
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 @@ private CheckResult[] parseMovesWasEggPreRelearn(int[] Moves, List<int>[] validL
{
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
return res;
}
// Some games can have different egg movepools. Have to check all situations.
@@ -2507,13 +2507,13 @@ private CheckResult[] parseMovesWasEggPreRelearn(int[] Moves, List<int>[] validL
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 @@ private CheckResult[] parseMovesWasEggPreRelearn(int[] Moves, List<int>[] validL
}
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 @@ private CheckResult[] parseMovesPre3DS(GameVersion game, List<int>[] validLevelM
{
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 @@ private CheckResult[] parseMovesSpecialMoveset(int[] Moves, List<int>[] validLev
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 @@ private CheckResult[] parseMovesRelearn(int[] Moves, List<int>[] validLevelMoves
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 @@ private CheckResult[] parseMoves(int[] moves, List<int>[] learn, int[] relearn,
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 @@ private CheckResult[] parseMoves(int[] moves, List<int>[] learn, int[] relearn,
}
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 @@ private CheckResult[] parseMoves(int[] moves, List<int>[] learn, int[] relearn,
// 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 @@ private CheckResult[] parseMoves(int[] moves, List<int>[] learn, int[] relearn,
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 @@ private void verifyNoEmptyDuplicates(int[] Moves, CheckResult[] res)
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 @@ internal static IEnumerable<int> getEggMoves(PKM pkm, int skipOption, GameVersio
{
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 @@ private static IEnumerable<int> getMoves(PKM pkm, int species, int lvl, int form
}
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 @@ public static partial class Legal
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 @@ public static partial class Legal
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};