From 36d74b8d8569128b67b2c728ea6d92a08a3ea0bc Mon Sep 17 00:00:00 2001 From: Kaphotics Date: Tue, 22 Mar 2016 19:47:13 -0700 Subject: [PATCH] Refactoring & Fixes Add tracking for wild / link encounters Fixed sylveon ball check Added Demo link pkm Added Horde Hidden Ability checks --- Legality/Checks.cs | 117 +++++++---- Legality/Core.cs | 513 ++++++++++++++------------------------------- Legality/Data.cs | 33 +++ Legality/Tables.cs | 250 +++++++++++++++++++++- 4 files changed, 517 insertions(+), 396 deletions(-) diff --git a/Legality/Checks.cs b/Legality/Checks.cs index e2ac2bd85..cbbef8ab1 100644 --- a/Legality/Checks.cs +++ b/Legality/Checks.cs @@ -137,14 +137,13 @@ private LegalityCheck verifyID() } private LegalityCheck verifyEncounter() { - EncounterMatch = null; // Reset object if (!pk6.Gen6) return new LegalityCheck {Judgement = Severity.NotImplemented}; if (pk6.WasLink) { // Should NOT be Fateful, and should be in Database - return pk6.FatefulEncounter || Legal.getLinkMoves(pk6).Length == 0 + return pk6.FatefulEncounter || EncounterMatch == null ? new LegalityCheck(Severity.Invalid, "Not a valid Link gift.") : new LegalityCheck(Severity.Valid, "Valid Link gift."); } @@ -154,6 +153,8 @@ private LegalityCheck verifyEncounter() ? new LegalityCheck(Severity.Valid, $"Matches #{MatchedWC6.CardID.ToString("0000")} ({MatchedWC6.CardTitle})") : new LegalityCheck(Severity.Invalid, "Not a valid Wonder Card gift."); } + + EncounterMatch = null; // Reset object if (pk6.WasEgg) { // Check Hatch Locations @@ -180,8 +181,8 @@ private LegalityCheck verifyEncounter() return new LegalityCheck(Severity.Invalid, "Invalid location for hatched egg."); } - EncounterStatic z = Legal.getStaticEncounter(pk6); - if (z != null) + EncounterMatch = Legal.getValidStaticEncounter(pk6); + if (EncounterMatch != null) return new LegalityCheck(Severity.Valid, "Valid gift/static encounter."); if (Legal.getIsFossil(pk6)) @@ -205,19 +206,17 @@ private LegalityCheck verifyEncounter() return new LegalityCheck(Severity.Valid, "Valid friend safari encounter."); } - - if (Legal.getDexNavValid(pk6)) - return new LegalityCheck(Severity.Valid, "Valid (DexNav) encounter at location."); - if (Legal.getWildEncounterValid(pk6)) + + EncounterMatch = Legal.getValidWildEncounters(pk6); + if (EncounterMatch != null) { - return pk6.AbilityNumber != 4 - ? new LegalityCheck(Severity.Valid, "Valid encounter at location.") - : new LegalityCheck(Severity.Invalid, "Hidden ability on valid encounter."); + return ((EncounterSlot[]) EncounterMatch).Any(slot => !slot.DexNav) + ? new LegalityCheck(Severity.Valid, "Valid encounter at location.") + : new LegalityCheck(Severity.Valid, "Valid DexNav encounter at location."); } - EncounterTrade t = Legal.getIngameTrade(pk6); - if (t != null) + EncounterMatch = Legal.getValidIngameTrade(pk6); + if (EncounterMatch != null) { - EncounterMatch = t; // Check in individual methods return new LegalityCheck(Severity.Valid, "Valid ingame trade."); } return new LegalityCheck(Severity.Invalid, "Not a valid encounter."); @@ -245,12 +244,6 @@ private LegalityCheck verifyRibbons() pk6.RIB3_3, pk6.RIB3_4, pk6.RIB3_5, pk6.RIB3_6, pk6.RIB3_7, pk6.RIB4_0, pk6.RIB4_1, pk6.RIB4_2, pk6.RIB4_3, pk6.RIB4_4 }; - string[] EventRibName = - { - "Country", "National", "Earth", "World", "Classic", - "Premier", "Event", "Birthday", "Special", "Souvenir", - "Wishing", "Battle Champ", "Regional Champ", "National Champ", "World Champ" - }; if (MatchedWC6 != null) // Wonder Card { bool[] wc6rib = @@ -263,15 +256,20 @@ private LegalityCheck verifyRibbons() if (EventRib[i] ^ wc6rib[i]) // Mismatch (wc6rib[i] ? missingRibbons : invalidRibbons).Add(EventRibName[i]); } - else + else if (EncounterMatch?.GetType() == typeof(EncounterLink)) + { + // No Event Ribbons except Classic (unless otherwise specified, ie not for Demo) + for (int i = 0; i < EventRib.Length; i++) + if (i != 4 && EventRib[i]) + invalidRibbons.Add(EventRibName[i]); + + if (EventRib[4] ^ ((EncounterLink)EncounterMatch).Classic) + (EventRib[4] ? invalidRibbons : missingRibbons).Add(EventRibName[4]); + } + else // No ribbons { for (int i = 0; i < EventRib.Length; i++) - if (i == 4 && pk6.WasLink) - { - if (!EventRib[i]) // Classic - missingRibbons.Add(EventRibName[i]); - } - else if (EventRib[i]) + if (EventRib[i]) invalidRibbons.Add(EventRibName[i]); } @@ -307,11 +305,21 @@ private LegalityCheck verifyAbility() byte[] abilities = Legal.PersonalAO[index].Abilities; int abilval = Array.IndexOf(abilities, (byte)pk6.Ability); if (abilval < 0) - return new LegalityCheck(Severity.Invalid, "Ability is not valid for species/form"); + return new LegalityCheck(Severity.Invalid, "Ability is not valid for species/form."); - if (EncounterMatch != null && EncounterMatch.GetType() == typeof(EncounterTrade)) - if ((EncounterMatch as EncounterTrade).Ability == 4 ^ pk6.AbilityNumber == 4) - return new LegalityCheck(Severity.Invalid, "Hidden Ability mismatch for Ingame Trade"); + if (EncounterMatch != null) + { + Type etype = EncounterMatch.GetType(); + if (etype == typeof(EncounterStatic)) + if (pk6.AbilityNumber == 4 ^ ((EncounterStatic)EncounterMatch).Ability == 4) + return new LegalityCheck(Severity.Invalid, "Hidden Ability mismatch for static encounter."); + if (etype == typeof(EncounterTrade)) + if (pk6.AbilityNumber == 4 ^ ((EncounterTrade)EncounterMatch).Ability == 4) + return new LegalityCheck(Severity.Invalid, "Hidden Ability mismatch for ingame trade."); + if (etype == typeof(EncounterSlot[])) + if (pk6.AbilityNumber == 4 && ((EncounterSlot[])EncounterMatch).All(slot => slot.Type != SlotType.Horde)) + return new LegalityCheck(Severity.Invalid, "Hidden Ability on non-horde wild encounter."); + } return abilities[pk6.AbilityNumber >> 1] != pk6.Ability ? new LegalityCheck(Severity.Invalid, "Ability does not match ability number.") @@ -319,6 +327,9 @@ private LegalityCheck verifyAbility() } private LegalityCheck verifyBall() { + if (!Encounter.Valid) + return new LegalityCheck(Severity.Valid, "Skipped Ball check due to other check being invalid."); + if (MatchedWC6 != null) return pk6.Ball != MatchedWC6.Pokéball ? new LegalityCheck(Severity.Invalid, "Ball does not match specified Wonder Card Ball.") @@ -326,7 +337,7 @@ private LegalityCheck verifyBall() if (pk6.WasEgg) { - if (pk6.Species > 650) + if (pk6.Species > 650 && pk6.Species != 700) // Sylveon return !Legal.WildPokeballs.Contains(pk6.Ball) ? new LegalityCheck(Severity.Invalid, "Unobtainable ball for Kalos origin.") : new LegalityCheck(Severity.Valid, "Obtainable ball for Kalos origin."); @@ -350,23 +361,26 @@ private LegalityCheck verifyBall() ? new LegalityCheck(Severity.Invalid, "Incorrect ball on Link gift.") : new LegalityCheck(Severity.Valid, "Correct ball on Link gift."); } - if (EncounterMatch == null) - { - // Egg and Event already checked, if not a recognized Trade - // Wild Encounter - return !Legal.WildPokeballs.Contains(pk6.Ball) - ? new LegalityCheck(Severity.Invalid, "Unobtainable ball on captured encounter.") - : new LegalityCheck(Severity.Valid, "Obtainable ball on captured encounter."); - } - if (EncounterMatch.GetType() == typeof(EncounterTrade)) + Type etype = EncounterMatch?.GetType(); + if (etype == typeof(EncounterLink)) + return ((EncounterLink)EncounterMatch).Ball != pk6.Ball + ? new LegalityCheck(Severity.Invalid, "Incorrect ball on Link gift.") + : new LegalityCheck(Severity.Valid, "Correct ball on Link gift."); + + if (etype == typeof(EncounterTrade)) return pk6.Ball != 4 // Pokeball ? new LegalityCheck(Severity.Invalid, "Incorrect ball on ingame trade encounter.") : new LegalityCheck(Severity.Valid, "Correct ball on ingame trade encounter."); - return new LegalityCheck(Severity.Indeterminate, "Unable to verify Ball"); + return !Legal.WildPokeballs.Contains(pk6.Ball) + ? new LegalityCheck(Severity.Invalid, "Unobtainable ball on captured encounter.") + : new LegalityCheck(Severity.Valid, "Obtainable ball on captured encounter."); } private LegalityCheck verifyHandlerMemories() { + if (!Encounter.Valid) + return new LegalityCheck(Severity.Valid, "Skipped Memory check due to other check being invalid."); + if (MatchedWC6?.OT.Length > 0) // Has Event OT -- null propagation yields false if MatchedWC6=null { if (pk6.OT_Friendship != PKX.getBaseFriendship(pk6.Species)) @@ -464,12 +478,22 @@ private LegalityCheck[] verifyRelearn() { LegalityCheck[] res = new LegalityCheck[4]; MatchedWC6 = null; // Reset + EncounterMatch = null; + int[] Moves = pk6.RelearnMoves; if (!pk6.Gen6) goto noRelearn; if (pk6.WasLink) { - int[] moves = Legal.getLinkMoves(pk6); + EncounterMatch = Legal.getValidLinkGifts(pk6); + if (EncounterMatch == null) + { + for (int i = 0; i < 4; i++) + res[i] = new LegalityCheck(); + return res; + } + + int[] moves = ((EncounterLink)EncounterMatch).RelearnMoves; for (int i = 0; i < 4; i++) res[i] = moves[i] != Moves[i] ? new LegalityCheck(Severity.Invalid, $"Expected ID:{moves[i]}.") @@ -579,5 +603,12 @@ private LegalityCheck[] verifyRelearn() : new LegalityCheck(); return res; } + + private readonly string[] EventRibName = + { + "Country", "National", "Earth", "World", "Classic", + "Premier", "Event", "Birthday", "Special", "Souvenir", + "Wishing", "Battle Champ", "Regional Champ", "National Champ", "World Champ" + }; } } diff --git a/Legality/Core.cs b/Legality/Core.cs index 51fa2541e..c96032b15 100644 --- a/Legality/Core.cs +++ b/Legality/Core.cs @@ -5,73 +5,33 @@ namespace PKHeX { public static partial class Legal { + // PKHeX master Wonder Card Database internal static WC6[] WC6DB; // PKHeX master personal.dat internal static readonly PersonalInfo[] PersonalAO = PersonalInfo.getPersonalArray(Properties.Resources.personal_ao, PersonalInfo.SizeAO); - private static readonly PersonalInfo[] PersonalXY = PersonalInfo.getPersonalArray(Properties.Resources.personal_xy, PersonalInfo.SizeXY); private static readonly EggMoves[] EggMoveXY = EggMoves.getArray(Util.unpackMini(Properties.Resources.eggmove_xy, "xy")); private static readonly Learnset[] LevelUpXY = Learnset.getArray(Util.unpackMini(Properties.Resources.lvlmove_xy, "xy")); private static readonly EggMoves[] EggMoveAO = EggMoves.getArray(Util.unpackMini(Properties.Resources.eggmove_ao, "ao")); private static readonly Learnset[] LevelUpAO = Learnset.getArray(Util.unpackMini(Properties.Resources.lvlmove_ao, "ao")); private static readonly Evolutions[] Evolves = Evolutions.getArray(Util.unpackMini(Properties.Resources.evos_ao, "ao")); - private static readonly EncounterArea[] SlotsA = EncounterArea.getArray(Util.unpackMini(Properties.Resources.encounter_a, "ao")); - private static readonly EncounterArea[] SlotsO = EncounterArea.getArray(Util.unpackMini(Properties.Resources.encounter_o, "ao")); - #region XY Alt Slots - private static readonly EncounterArea[] SlotsXYAlt = + private static readonly EncounterArea[] SlotsA; + private static readonly EncounterArea[] SlotsO; + private static readonly EncounterArea[] SlotsX; + private static readonly EncounterArea[] SlotsY; + private static readonly EncounterArea[] DexNavA; + private static readonly EncounterArea[] DexNavO; + private static readonly EncounterStatic[] StaticX; + private static readonly EncounterStatic[] StaticY; + private static readonly EncounterStatic[] StaticA; + private static readonly EncounterStatic[] StaticO; + private static EncounterStatic[] getSpecial(GameVersion Game) { - new EncounterArea { - Location = 104, // Victory Road - Slots = new[] - { - // Drops - new EncounterSlot { Species = 075, LevelMin = 57, LevelMax = 57, Form = 0 }, // Graveler - new EncounterSlot { Species = 168, LevelMin = 58, LevelMax = 59, Form = 0 }, // Ariados - new EncounterSlot { Species = 714, LevelMin = 57, LevelMax = 59, Form = 0 }, // Noibat - - // Swoops - new EncounterSlot { Species = 022, LevelMin = 57, LevelMax = 59, Form = 0 }, // Fearow - new EncounterSlot { Species = 227, LevelMin = 57, LevelMax = 59, Form = 0 }, // Skarmory - new EncounterSlot { Species = 635, LevelMin = 59, LevelMax = 59, Form = 0 }, // Hydreigon - },}, - new EncounterArea { - Location = 34, // Route 6 - Slots = new[] - { - // Rustling Bush - new EncounterSlot { Species = 543, LevelMin = 10, LevelMax = 12, Form = 0 }, // Venipede - new EncounterSlot { Species = 531, LevelMin = 10, LevelMax = 12, Form = 0 }, // Audino - },}, - - new EncounterArea { Location = 88, // Route 18 - Slots = new[] - { - // Rustling Bush - new EncounterSlot { Species = 632, LevelMin = 44, LevelMax = 46, Form = 0 }, // Durant - new EncounterSlot { Species = 631, LevelMin = 45, LevelMax = 45, Form = 0 }, // Heatmor - },}, - - new EncounterArea { Location = 132, // Glittering Cave - Slots = new[] - { - // Drops - new EncounterSlot { Species = 527, LevelMin = 15, LevelMax = 17, Form = 0 }, // Woobat - new EncounterSlot { Species = 597, LevelMin = 15, LevelMax = 17, Form = 0 }, // Ferroseed - },}, - - new EncounterArea { Location = 56, // Reflection Cave - Slots = new[] - { - // Drops - new EncounterSlot { Species = 527, LevelMin = 21, LevelMax = 23, Form = 0 }, // Woobat - new EncounterSlot { Species = 597, LevelMin = 21, LevelMax = 23, Form = 0 }, // Ferroseed - },}, - }; - #endregion - private static readonly EncounterArea[] SlotsX = addXYAltTiles(EncounterArea.getArray(Util.unpackMini(Properties.Resources.encounter_x, "xy")), SlotsXYAlt); - private static readonly EncounterArea[] SlotsY = addXYAltTiles(EncounterArea.getArray(Util.unpackMini(Properties.Resources.encounter_y, "xy")), SlotsXYAlt); - private static readonly EncounterArea[] DexNavA = getDexNavSlots(SlotsA, 32); - private static readonly EncounterArea[] DexNavO = getDexNavSlots(SlotsO, 32); + if (Game == GameVersion.X || Game == GameVersion.Y) + return Encounter_XY.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray(); + // else if (Game == GameVersion.AS || Game == GameVersion.OR) + return Encounter_AO.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray(); + } private static EncounterArea[] addXYAltTiles(EncounterArea[] GameSlots, EncounterArea[] SpecialSlots) { foreach (EncounterArea g in GameSlots) @@ -87,17 +47,65 @@ private static EncounterArea[] getDexNavSlots(EncounterArea[] GameSlots, int sma EncounterArea[] eA = new EncounterArea[GameSlots.Length]; for (int i = 0; i < eA.Length; i++) { - eA[i] = new EncounterArea {Location = GameSlots[i].Location, Slots = GameSlots[i].Slots}; - eA[i].Slots = eA[i].Slots.Take(smashSlot).Concat(eA[i].Slots.Skip(smashSlot+5)).ToArray(); // Skip 5 Rock Smash slots. + eA[i] = new EncounterArea { Location = GameSlots[i].Location, Slots = GameSlots[i].Slots }; + eA[i].Slots = eA[i].Slots.Where(s => s.Type != SlotType.Rock_Smash).ToArray(); // Skip Rock Smash slots. + foreach (var slot in eA[i].Slots) + slot.DexNav = true; } return eA; } - internal static bool getDexNavValid(PK6 pk6) + static Legal() // Setup { - IEnumerable locs = getDexNavAreas(pk6); - return locs.Select(loc => getValidEncounterSlots(pk6, loc, DexNav: true)).Any(slots => slots.Any()); + StaticX = getSpecial(GameVersion.X); + StaticY = getSpecial(GameVersion.Y); + StaticA = getSpecial(GameVersion.AS); + StaticO = getSpecial(GameVersion.OR); + + var XSlots = EncounterArea.getArray(Util.unpackMini(Properties.Resources.encounter_x, "xy")); + var YSlots = EncounterArea.getArray(Util.unpackMini(Properties.Resources.encounter_y, "xy")); + + // Mark Horde Encounters + foreach (var area in XSlots) + { + int slotct = area.Slots.Length; + for (int i = slotct - 15; i < slotct; i++) + area.Slots[i].Type = SlotType.Horde; + } + foreach (var area in YSlots) + { + int slotct = area.Slots.Length; + for (int i = slotct - 15; i < slotct; i++) + area.Slots[i].Type = SlotType.Horde; + } + SlotsX = addXYAltTiles(XSlots, SlotsXYAlt); + SlotsY = addXYAltTiles(YSlots, SlotsXYAlt); + + SlotsA = EncounterArea.getArray(Util.unpackMini(Properties.Resources.encounter_a, "ao")); + SlotsO = EncounterArea.getArray(Util.unpackMini(Properties.Resources.encounter_o, "ao")); + + // Mark Rock Smash Encounters + foreach (var area in SlotsA) + { + for (int i = 32; i < 37; i++) + area.Slots[i].Type = SlotType.Rock_Smash; + int slotct = area.Slots.Length; + for (int i = slotct - 15; i < slotct; i++) + area.Slots[i].Type = SlotType.Horde; + } + foreach (var area in SlotsO) + { + for (int i = 32; i < 37; i++) + area.Slots[i].Type = SlotType.Rock_Smash; + int slotct = area.Slots.Length; + for (int i = slotct - 15; i < slotct; i++) + area.Slots[i].Type = SlotType.Horde; + } + + DexNavA = getDexNavSlots(SlotsA, 32); + DexNavO = getDexNavSlots(SlotsO, 32); } + internal static IEnumerable getValidMoves(PK6 pk6) { List r = new List {0}; @@ -140,23 +148,9 @@ internal static IEnumerable getValidRelearn(PK6 pk6, int skipOption) r.AddRange(getLVLMoves(species, 100, pk6.AltForm)); return r.Distinct(); } - internal static int[] getLinkMoves(PK6 pk6) + internal static EncounterLink getValidLinkGifts(PK6 pk6) { - if (pk6.Species == 251 && pk6.Met_Level == 10) // Celebi - return new[] {610, 0, 0, 0}; - if (pk6.Species == 154 && pk6.Met_Level == 50 && pk6.AbilityNumber == 4) // Meganium Hidden - return new[] {0, 0, 0, 0}; - if (pk6.Species == 157 && pk6.Met_Level == 50 && pk6.AbilityNumber == 4) // Typhlosion Hidden - return new[] {0, 0, 0, 0}; - if (pk6.Species == 160 && pk6.Met_Level == 50 && pk6.AbilityNumber == 4) // Feraligatr Hidden - return new[] {0, 0, 0, 0}; - if (pk6.Species == 377 && pk6.Met_Level == 50 && pk6.AbilityNumber == 4) // Regirock Hidden - return new[] {153, 8, 444, 359}; - if (pk6.Species == 378 && pk6.Met_Level == 50 && pk6.AbilityNumber == 4) // Regice Hidden - return new[] {85, 133, 58, 258}; - if (pk6.Species == 379 && pk6.Met_Level == 50 && pk6.AbilityNumber == 4) // Registeel Hidden - return new[] {442, 157, 356, 334}; - return new int[0]; + return LinkGifts.FirstOrDefault(g => g.Species == pk6.Species && g.Level == pk6.Met_Level); } internal static IEnumerable getValidWC6s(PK6 pk6) { @@ -205,16 +199,92 @@ internal static IEnumerable getValidWC6s(PK6 pk6) } return validWC6; } - internal static bool getWildEncounterValid(PK6 pk6) + internal static EncounterSlot[] getValidWildEncounters(PK6 pk6) { - var areas = getEncounterAreas(pk6); - bool slots = areas.Any(a => getValidEncounterSlots(pk6, a, DexNav: false).Any()); - if (slots) return true; + List s = new List(); - // Try DexNav -- quickly returns if not AO - areas = getDexNavAreas(pk6); - slots = areas.Any(a => getValidEncounterSlots(pk6, a, DexNav: true).Any()); - return slots; + foreach (var area in getEncounterAreas(pk6)) + s.AddRange(getValidEncounterSlots(pk6, area, DexNav: false)); + if (s.Any()) return s.ToArray(); + if (!pk6.AO) return null; + + // By default, no slots are currently stored. Continue! + foreach (var area in getDexNavAreas(pk6)) + s.AddRange(getValidEncounterSlots(pk6, area, DexNav: true)); + return s.Any() ? s.ToArray() : null; + } + internal static EncounterStatic getValidStaticEncounter(PK6 pk6) + { + // Get possible encounters + IEnumerable poss = getStaticEncounters(pk6); + // Back Check against pk6 + foreach (EncounterStatic e in poss) + { + if (e.Nature != Nature.Random && pk6.Nature != (int)e.Nature) + continue; + if (e.EggLocation != pk6.Egg_Location) + continue; + if (e.Location != 0 && e.Location != pk6.Met_Location) + continue; + if (e.Gender != -1 && e.Gender != pk6.Gender) + continue; + if (e.Level != pk6.Met_Level) + continue; + if (e.Shiny != null && e.Shiny != pk6.IsShiny) + continue; + if (e.Gift && pk6.Ball != 4) // PokéBall + continue; + + // Passes all checks, valid encounter + return e; + } + return null; + } + internal static EncounterTrade getValidIngameTrade(PK6 pk6) + { + int lang = pk6.Language; + if (lang == 0) + return null; + + // Get valid pre-evolutions + IEnumerable p = getValidPreEvolutions(pk6); + EncounterTrade z = null; + if (pk6.XY) + z = lang == 6 ? null : TradeGift_XY.FirstOrDefault(f => p.Any(r => r.Species == f.Species)); + if (pk6.AO) + z = lang == 6 ? null : TradeGift_AO.FirstOrDefault(f => p.Any(r => r.Species == f.Species)); + + if (z == null) + return null; + + for (int i = 0; i < 6; i++) + if (z.IVs[i] != -1 && z.IVs[i] != pk6.IVs[i]) + return null; + + if (z.Shiny ^ pk6.IsShiny) // Are PIDs static? + return null; + if (z.TID != pk6.TID) + return null; + if (z.SID != pk6.SID) + return null; + if (z.Location != pk6.Met_Location) + return null; + if (z.Level != pk6.Met_Level) + return null; + if (z.Nature != Nature.Random && ((int)z.Nature != pk6.Nature)) + return null; + if (z.Gender != pk6.Gender) + return null; + // if (z.Ability == 4 ^ pk6.AbilityNumber == 4) // defer to Ability + // return null; + + return z; + } + + internal static bool getDexNavValid(PK6 pk6) + { + IEnumerable locs = getDexNavAreas(pk6); + return locs.Select(loc => getValidEncounterSlots(pk6, loc, DexNav: true)).Any(slots => slots.Any()); } internal static bool getHasEvolved(PK6 pk6) { @@ -262,85 +332,7 @@ internal static IEnumerable getBaseEggMoves(PK6 pk6, int skipOption, int ga // if (gameSource == 1) // ORAS return LevelUpAO[species].getMoves(1); } - internal static EncounterStatic getStaticEncounter(PK6 pk6) - { - // Get possible encounters - IEnumerable poss = getStaticEncounters(pk6); - // Back Check against pk6 - foreach (EncounterStatic e in poss) - { - if (e.Nature != Nature.Random && pk6.Nature != (int)e.Nature) - continue; - if (e.EggLocation != pk6.Egg_Location) - continue; - if (e.Location != 0 && e.Location != pk6.Met_Location) - continue; - if (e.Ability == 4 && pk6.AbilityNumber != 4) // Hidden can't be changed by Ability Capsule - continue; - if (e.Ability != 4 && pk6.AbilityNumber == 4) // Shouldn't be Hidden - continue; - if (e.Gender != -1 && e.Gender != pk6.Gender) - continue; - if (e.Level != pk6.Met_Level) - continue; - if (e.Shiny != null && e.Shiny != pk6.IsShiny) - continue; - if (e.Gift && pk6.Ball != 4) // PokéBall - continue; - // Passes all checks, valid encounter - return e; - } - return null; - } - internal static EncounterTrade getIngameTrade(PK6 pk6) - { - int lang = pk6.Language; - if (lang == 0) - return null; - - // Get valid pre-evolutions - IEnumerable p = getValidPreEvolutions(pk6); - EncounterTrade z = null; - if (pk6.XY) - z = lang == 6 ? null : TradeGift_XY.FirstOrDefault(f => p.Any(r => r.Species == f.Species)); - if (pk6.AO) - z = lang == 6 ? null : TradeGift_AO.FirstOrDefault(f => p.Any(r => r.Species == f.Species)); - - if (z == null) - return null; - - for (int i = 0; i < 6; i++) - if (z.IVs[i] != -1 && z.IVs[i] != pk6.IVs[i]) - return null; - - if (z.Shiny ^ pk6.IsShiny) // Are PIDs static? - return null; - if (z.TID != pk6.TID) - return null; - if (z.SID != pk6.SID) - return null; - if (z.Location != pk6.Met_Location) - return null; - if (z.Level != pk6.Met_Level) - return null; - if (z.Nature != Nature.Random && ((int)z.Nature != pk6.Nature)) - return null; - if (z.Gender != pk6.Gender) - return null; - // if (z.Ability == 4 ^ pk6.AbilityNumber == 4) // defer to Ability - // return null; - - return z; - } - - private static IEnumerable getDexNavAreas(PK6 pk6) - { - bool alpha = pk6.Version == 26; - if (!alpha && pk6.Version != 27) - return new EncounterArea[0]; - return (alpha ? DexNavA : DexNavO).Where(l => l.Location == pk6.Met_Location); - } private static int getBaseSpecies(PK6 pk6, int skipOption = 0) { if (pk6.Species == 292) @@ -353,6 +345,13 @@ private static int getBaseSpecies(PK6 pk6, int skipOption = 0) default: return evos.Length <= 0 ? pk6.Species : evos.Last().Species; } } + private static IEnumerable getDexNavAreas(PK6 pk6) + { + bool alpha = pk6.Version == 26; + if (!alpha && pk6.Version != 27) + return new EncounterArea[0]; + return (alpha ? DexNavA : DexNavO).Where(l => l.Location == pk6.Met_Location); + } private static IEnumerable getLVLMoves(int species, int lvl, int formnum) { int ind_XY = PersonalXY[species].FormeIndex(species, formnum); @@ -487,191 +486,5 @@ private static IEnumerable getMachineMoves(int species, int formnum) moves.AddRange(TMHM_AO.Where((t, i) => pkAO.TMHM[i])); return moves; } - - #region Static Encounter/Gift Tables - private static readonly EncounterStatic[] Encounter_XY = - { - new EncounterStatic { Species = 650, Level = 5, Location = 10, Gift = true }, // Chespin - new EncounterStatic { Species = 653, Level = 5, Location = 10, Gift = true }, // Fennekin - new EncounterStatic { Species = 656, Level = 5, Location = 10, Gift = true }, // Froakie - - new EncounterStatic { Species = 1, Level = 10, Location = 22, Gift = true }, // Bulbasaur - new EncounterStatic { Species = 4, Level = 10, Location = 22, Gift = true }, // Charmander - new EncounterStatic { Species = 7, Level = 10, Location = 22, Gift = true }, // Squirtle - - new EncounterStatic { Species = 448, Level = 32, Location = 60, Ability = 1, Nature = Nature.Hasty, Gender = 0, IVs = new[] {6, 25, 16, 31, 25, 19}, Gift = true, Shiny = false }, // Lucario - new EncounterStatic { Species = 131, Level = 32, Location = 62, Nature = Nature.Docile, IVs = new[] {31, 20, 20, 20, 20, 20}, Gift = true }, // Lapras - - new EncounterStatic { Species = 143, Level = 15, Location = 38 }, // Snorlax - new EncounterStatic { Species = 568, Level = 35, Location = 142 }, // Trubbish - new EncounterStatic { Species = 569, Level = 36, Location = 142 }, // Garbodor - new EncounterStatic { Species = 569, Level = 37, Location = 142 }, // Garbodor - new EncounterStatic { Species = 569, Level = 38, Location = 142 }, // Garbodor - new EncounterStatic { Species = 479, Level = 38, Location = 142 }, // Rotom - - new EncounterStatic { Species = 716, Level = 50, Location = 138, Version = GameVersion.X, Shiny = false }, // Xerneas - new EncounterStatic { Species = 717, Level = 50, Location = 138, Version = GameVersion.Y, Shiny = false }, // Yveltal - new EncounterStatic { Species = 718, Level = 70, Location = 140, Shiny = false }, // Zygarde - - new EncounterStatic { Species = 150, Level = 70, Location = 168, Shiny = false }, // Mewtwo - - new EncounterStatic { Species = 144, Level = 70, Location = 146, Shiny = false }, // Articuno - new EncounterStatic { Species = 145, Level = 70, Location = 146, Shiny = false }, // Zapdos - new EncounterStatic { Species = 146, Level = 70, Location = 146, Shiny = false }, // Moltres - }; - private static readonly EncounterStatic[] Encounter_AO = - { - new EncounterStatic { Species = 252, Level = 5, Location = 204, Gift = true }, // Treeko - new EncounterStatic { Species = 255, Level = 5, Location = 204, Gift = true }, // Torchic - new EncounterStatic { Species = 258, Level = 5, Location = 204, Gift = true }, // Mudkip - - new EncounterStatic { Species = 152, Level = 5, Location = 204, Gift = true }, // Chikorita - new EncounterStatic { Species = 155, Level = 5, Location = 204, Gift = true }, // Cyndaquil - new EncounterStatic { Species = 158, Level = 5, Location = 204, Gift = true }, // Totodile - - new EncounterStatic { Species = 387, Level = 5, Location = 204, Gift = true }, // Turtwig - new EncounterStatic { Species = 390, Level = 5, Location = 204, Gift = true }, // Chimchar - new EncounterStatic { Species = 393, Level = 5, Location = 204, Gift = true }, // Piplup - - new EncounterStatic { Species = 495, Level = 5, Location = 204, Gift = true }, // Snivy - new EncounterStatic { Species = 498, Level = 5, Location = 204, Gift = true }, // Tepig - new EncounterStatic { Species = 501, Level = 5, Location = 204, Gift = true }, // Oshawott - - new EncounterStatic { Species = 25, Level = 20, Location = 186, Gender = 1, Ability = 4, Form = 1, IVs = new[] {-1, -1, -1, 31, -1, -1}, Contest = new[] {70,70,70,70,70,0}, Gift = true, Shiny = false }, // Pikachu - new EncounterStatic { Species = 25, Level = 20, Location = 186, Gender = 1, Ability = 4, Form = 3, IVs = new[] {-1, -1, -1, 31, -1, -1}, Contest = new[] {70,70,70,70,70,0}, Gift = true, Shiny = false }, // Pikachu - new EncounterStatic { Species = 360, Level = 1, EggLocation = 60004, Ability = 1, Gift = true }, // Wynaut - new EncounterStatic { Species = 175, Level = 1, EggLocation = 60004, Ability = 1, Gift = true }, // Togepi - new EncounterStatic { Species = 374, Level = 1, Location = 196, Ability = 1, IVs = new[] {-1, -1, 31, -1, -1, 31}, Gift = true }, // Beldum - - new EncounterStatic { Species = 351, Level = 30, Location = 240, Nature = Nature.Lax, Ability = 1, IVs = new[] {-1, -1, -1, -1, 31, -1}, Contest = new[] {0,100,0,0,0,0}, Gift = true }, // Castform - new EncounterStatic { Species = 319, Level = 40, Location = 318, Gender = 1, Ability = 1, Nature = Nature.Adamant, Gift = true }, // Sharpedo - new EncounterStatic { Species = 323, Level = 40, Location = 318, Gender = 1, Ability = 1, Nature = Nature.Quiet, Gift = true }, // Camerupt - - new EncounterStatic { Species = 380, Level = 30, Location = 320, Version = GameVersion.AS, Ability = 1, Gift = true }, // Latias - new EncounterStatic { Species = 381, Level = 30, Location = 320, Version = GameVersion.OR, Ability = 1, Gift = true }, // Latios - - new EncounterStatic { Species = 382, Level = 45, Location = 296, Version = GameVersion.AS, Shiny = false }, // Kyogre - new EncounterStatic { Species = 383, Level = 45, Location = 296, Version = GameVersion.OR, Shiny = false }, // Groudon - new EncounterStatic { Species = 384, Level = 70, Location = 316, Shiny = false }, // Rayquaza - new EncounterStatic { Species = 386, Level = 80, Location = 316, Shiny = false }, // Deoxys - - new EncounterStatic { Species = 377, Level = 40, Location = 278 }, // Regirock - new EncounterStatic { Species = 378, Level = 40, Location = 306 }, // Regice - new EncounterStatic { Species = 379, Level = 40, Location = 308 }, // Registeel - new EncounterStatic { Species = 486, Level = 50, Location = 306 }, // Regigigas - - new EncounterStatic { Species = 249, Level = 50, Location = 304, Version = GameVersion.AS }, // Lugia - new EncounterStatic { Species = 250, Level = 50, Location = 304, Version = GameVersion.OR }, // Ho-oh - - new EncounterStatic { Species = 483, Level = 50, Location = 348, Version = GameVersion.AS }, // Dialga - new EncounterStatic { Species = 484, Level = 50, Location = 348, Version = GameVersion.OR }, // Palia - - new EncounterStatic { Species = 644, Level = 50, Location = 340, Version = GameVersion.AS }, // Zekrom - new EncounterStatic { Species = 643, Level = 50, Location = 340, Version = GameVersion.OR }, // Reshiram - - new EncounterStatic { Species = 642, Level = 50, Location = 348, Version = GameVersion.AS }, // Thundurus - new EncounterStatic { Species = 641, Level = 50, Location = 348, Version = GameVersion.OR }, // Tornadus - - new EncounterStatic { Species = 485, Level = 50, Location = 312 }, // Heatran - new EncounterStatic { Species = 487, Level = 50, Location = 348 }, // Giratina - new EncounterStatic { Species = 488, Level = 50, Location = 344 }, // Cresselia - new EncounterStatic { Species = 645, Level = 50, Location = 348 }, // Landorus - new EncounterStatic { Species = 646, Level = 50, Location = 342 }, // Kyurem - - new EncounterStatic { Species = 243, Level = 50, Location = 334 }, // Raikou - new EncounterStatic { Species = 244, Level = 50, Location = 334 }, // Entei - new EncounterStatic { Species = 245, Level = 50, Location = 334 }, // Suicune - - new EncounterStatic { Species = 480, Level = 50, Location = 338 }, // Uxie - new EncounterStatic { Species = 481, Level = 50, Location = 338 }, // Mesprit - new EncounterStatic { Species = 482, Level = 50, Location = 338 }, // Azelf - - new EncounterStatic { Species = 638, Level = 50, Location = 336 }, // Cobalion - new EncounterStatic { Species = 639, Level = 50, Location = 336 }, // Terrakion - new EncounterStatic { Species = 640, Level = 50, Location = 336 }, // Virizion - - new EncounterStatic { Species = 352, Level = 30, Location = 240 }, // Kecleon @ Route 119 - new EncounterStatic { Species = 352, Level = 30, Location = 242 }, // Kecleon @ Route 120 - new EncounterStatic { Species = 352, Level = 40, Location = 176 }, // Kecleon @ Lavaridge - new EncounterStatic { Species = 352, Level = 45, Location = 196 }, // Kecleon @ Mossdeep City - - new EncounterStatic { Species = 381, Level = 30, Location = 320, Version = GameVersion.AS }, // Latios - new EncounterStatic { Species = 380, Level = 30, Location = 320, Version = GameVersion.OR }, // Latias - - new EncounterStatic { Species = 101, Level = 40, Location = 292, Version = GameVersion.AS }, // Electrode - new EncounterStatic { Species = 101, Level = 40, Location = 314, Version = GameVersion.OR }, // Electrode - - new EncounterStatic { Species = 100, Level = 20, Location = 302 }, // Voltorb @ Route 119 - new EncounterStatic { Species = 442, Level = 50, Location = 304 }, // Spiritomb @ Route 120 - - // Soaring in the Sky - new EncounterStatic { Species = 198, Level = 45, Location = 348 }, // Murkrow - new EncounterStatic { Species = 276, Level = 40, Location = 348 }, // Taillow - new EncounterStatic { Species = 278, Level = 40, Location = 348 }, // Wingull - new EncounterStatic { Species = 279, Level = 40, Location = 348 }, // Pelipper - new EncounterStatic { Species = 333, Level = 40, Location = 348 }, // Swablu - new EncounterStatic { Species = 425, Level = 45, Location = 348 }, // Drifloon - new EncounterStatic { Species = 628, Level = 45, Location = 348 }, // Braviary - }; - #endregion - private static readonly EncounterStatic[] StaticX = getSpecial(GameVersion.X); - private static readonly EncounterStatic[] StaticY = getSpecial(GameVersion.Y); - private static readonly EncounterStatic[] StaticA = getSpecial(GameVersion.AS); - private static readonly EncounterStatic[] StaticO = getSpecial(GameVersion.OR); - private static EncounterStatic[] getSpecial(GameVersion Game) - { - if (Game == GameVersion.X || Game == GameVersion.Y) - return Encounter_XY.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray(); - // else if (Game == GameVersion.AS || Game == GameVersion.OR) - return Encounter_AO.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray(); - } - private static readonly string[][] TradeXY = - { - new string[0], // 0 - None - Util.getStringList("tradexy", "ja"), // 1 - Util.getStringList("tradexy", "en"), // 2 - Util.getStringList("tradexy", "fr"), // 3 - Util.getStringList("tradexy", "it"), // 4 - Util.getStringList("tradexy", "de"), // 5 - new string[0], // 6 - None - Util.getStringList("tradexy", "es"), // 7 - Util.getStringList("tradexy", "ko"), // 8 - }; - private static readonly string[][] TradeAO = - { - new string[0], // 0 - None - Util.getStringList("tradeao", "ja"), // 1 - Util.getStringList("tradeao", "en"), // 2 - Util.getStringList("tradeao", "fr"), // 3 - Util.getStringList("tradeao", "it"), // 4 - Util.getStringList("tradeao", "de"), // 5 - new string[0], // 6 - None - Util.getStringList("tradeao", "es"), // 7 - Util.getStringList("tradeao", "ko"), // 8 - }; - - #region Trade Tables - private static readonly EncounterTrade[] TradeGift_XY = - { - new EncounterTrade { Species = 129, Level = 5, Ability = 1, Gender = 0, TID = 44285, Nature = Nature.Adamant, }, // Magikarp - new EncounterTrade { Species = 133, Level = 5, Ability = 1, Gender = 1, TID = 29294, Nature = Nature.Docile, }, // Eevee - - new EncounterTrade { Species = 83, Level = 10, Ability = 1, Gender = 0, TID = 00185, Nature = Nature.Jolly, IVs = new[] {-1, -1, -1, 31, -1, -1}, }, // Farfetch'd - new EncounterTrade { Species = 208, Level = 20, Ability = 1, Gender = 1, TID = 19250, Nature = Nature.Impish, IVs = new[] {-1, -1, 31, -1, -1, -1}, }, // Steelix - new EncounterTrade { Species = 625, Level = 50, Ability = 1, Gender = 0, TID = 03447, Nature = Nature.Adamant, IVs = new[] {-1, 31, -1, -1, -1, -1}, }, // Bisharp - - new EncounterTrade { Species = 656, Level = 5, Ability = 1, Gender = 0, TID = 00037, Nature = Nature.Jolly, IVs = new[] {20, 20, 20, 31, 20, 20}, }, // Froakie - new EncounterTrade { Species = 650, Level = 5, Ability = 1, Gender = 0, TID = 00037, Nature = Nature.Adamant, IVs = new[] {20, 31, 20, 20, 20, 20}, }, // Chespin - new EncounterTrade { Species = 653, Level = 5, Ability = 1, Gender = 0, TID = 00037, Nature = Nature.Modest, IVs = new[] {20, 20, 20, 20, 31, 20}, }, // Fennekin - - new EncounterTrade { Species = 280, Level = 5, Ability = 1, Gender = 1, TID = 37110, Nature = Nature.Modest, IVs = new[] {20, 20, 20, 31, 31, 20}, }, // Ralts - }; - private static readonly EncounterTrade[] TradeGift_AO = - { - new EncounterTrade { Species = 296, Level = 9, Ability = 2, Gender = 0, TID = 30724, Nature = Nature.Brave, IVs = new[] {-1, 31, -1, -1, -1, -1}, }, // Makuhita - new EncounterTrade { Species = 300, Level = 25, Ability = 1, Gender = 1, TID = 03239, Nature = Nature.Naughty, IVs = new[] {-1, -1, -1, 31, -1, -1}, }, // Skitty - new EncounterTrade { Species = 222, Level = 50, Ability = 4, Gender = 1, TID = 00325, Nature = Nature.Calm, IVs = new[] {31, -1, -1, -1, -1, 31}, }, // Corsola - }; - #endregion } } diff --git a/Legality/Data.cs b/Legality/Data.cs index 23a74f5b2..3cf4ab1fe 100644 --- a/Legality/Data.cs +++ b/Legality/Data.cs @@ -134,6 +134,25 @@ public class EncounterSlot public int Form; public int LevelMin; public int LevelMax; + public SlotType Type = SlotType.Any; + public bool DexNav = false; + } + + public enum SlotType + { + Any, + Grass, + Rough_Terrain, + Yellow_Flowers, + Purple_Flowers, + Red_Flowers, + Surf, + Old_Rod, + Good_Rod, + Super_Rod, + Rock_Smash, + Horde, + Special, } public class EncounterStatic { @@ -169,6 +188,20 @@ public class EncounterTrade public bool Shiny = false; public int Gender = -1; } + public class EncounterLink + { + public int Species; + public int Level; + public int Location = 30011; + public int Ability = 4; + public int Ball = 4; // Pokéball + public Nature Nature = Nature.Random; + public int[] IVs = { -1, -1, -1, -1, -1, -1 }; + public int FlawlessIVs = 0; + public bool Classic = true; + public bool Fateful = false; + public int[] RelearnMoves = new int[4]; + } public enum Nature { Random = -1, diff --git a/Legality/Tables.cs b/Legality/Tables.cs index bbab0ae68..4e1aafcbb 100644 --- a/Legality/Tables.cs +++ b/Legality/Tables.cs @@ -52,9 +52,7 @@ public static partial class Legal }; #endregion - - internal static readonly int[] Gen4EncounterTypes = {1, 2, 4, 5, 7, 9, 10, 12, 23, 24}; - + #region Games internal static readonly int[] Games_6xy = {24, 25}; @@ -346,6 +344,7 @@ public static partial class Legal #endregion // Legality + internal static readonly int[] Gen4EncounterTypes = { 1, 2, 4, 5, 7, 9, 10, 12, 23, 24 }; internal static readonly int Struggle = 165; internal static readonly int Chatter = 448; internal static readonly int[] InvalidSketch = {Struggle, Chatter}; @@ -437,5 +436,250 @@ public static partial class Legal 487, // Giratina 492, // Shaymin }; + + private static readonly string[][] TradeXY = + { + new string[0], // 0 - None + Util.getStringList("tradexy", "ja"), // 1 + Util.getStringList("tradexy", "en"), // 2 + Util.getStringList("tradexy", "fr"), // 3 + Util.getStringList("tradexy", "it"), // 4 + Util.getStringList("tradexy", "de"), // 5 + new string[0], // 6 - None + Util.getStringList("tradexy", "es"), // 7 + Util.getStringList("tradexy", "ko"), // 8 + }; + private static readonly string[][] TradeAO = + { + new string[0], // 0 - None + Util.getStringList("tradeao", "ja"), // 1 + Util.getStringList("tradeao", "en"), // 2 + Util.getStringList("tradeao", "fr"), // 3 + Util.getStringList("tradeao", "it"), // 4 + Util.getStringList("tradeao", "de"), // 5 + new string[0], // 6 - None + Util.getStringList("tradeao", "es"), // 7 + Util.getStringList("tradeao", "ko"), // 8 + }; + + #region XY Alt Slots + private static readonly EncounterArea[] SlotsXYAlt = + { + new EncounterArea { + Location = 104, // Victory Road + Slots = new[] + { + // Drops + new EncounterSlot { Species = 075, LevelMin = 57, LevelMax = 57, Form = 0 }, // Graveler + new EncounterSlot { Species = 168, LevelMin = 58, LevelMax = 59, Form = 0 }, // Ariados + new EncounterSlot { Species = 714, LevelMin = 57, LevelMax = 59, Form = 0 }, // Noibat + + // Swoops + new EncounterSlot { Species = 022, LevelMin = 57, LevelMax = 59, Form = 0 }, // Fearow + new EncounterSlot { Species = 227, LevelMin = 57, LevelMax = 59, Form = 0 }, // Skarmory + new EncounterSlot { Species = 635, LevelMin = 59, LevelMax = 59, Form = 0 }, // Hydreigon + },}, + new EncounterArea { + Location = 34, // Route 6 + Slots = new[] + { + // Rustling Bush + new EncounterSlot { Species = 543, LevelMin = 10, LevelMax = 12, Form = 0 }, // Venipede + new EncounterSlot { Species = 531, LevelMin = 10, LevelMax = 12, Form = 0 }, // Audino + },}, + + new EncounterArea { Location = 88, // Route 18 + Slots = new[] + { + // Rustling Bush + new EncounterSlot { Species = 632, LevelMin = 44, LevelMax = 46, Form = 0 }, // Durant + new EncounterSlot { Species = 631, LevelMin = 45, LevelMax = 45, Form = 0 }, // Heatmor + },}, + + new EncounterArea { Location = 132, // Glittering Cave + Slots = new[] + { + // Drops + new EncounterSlot { Species = 527, LevelMin = 15, LevelMax = 17, Form = 0 }, // Woobat + new EncounterSlot { Species = 597, LevelMin = 15, LevelMax = 17, Form = 0 }, // Ferroseed + },}, + + new EncounterArea { Location = 56, // Reflection Cave + Slots = new[] + { + // Drops + new EncounterSlot { Species = 527, LevelMin = 21, LevelMax = 23, Form = 0 }, // Woobat + new EncounterSlot { Species = 597, LevelMin = 21, LevelMax = 23, Form = 0 }, // Ferroseed + },}, + }; + #endregion + #region Static Encounter/Gift Tables + private static readonly EncounterStatic[] Encounter_XY = + { + new EncounterStatic { Species = 650, Level = 5, Location = 10, Gift = true }, // Chespin + new EncounterStatic { Species = 653, Level = 5, Location = 10, Gift = true }, // Fennekin + new EncounterStatic { Species = 656, Level = 5, Location = 10, Gift = true }, // Froakie + + new EncounterStatic { Species = 1, Level = 10, Location = 22, Gift = true }, // Bulbasaur + new EncounterStatic { Species = 4, Level = 10, Location = 22, Gift = true }, // Charmander + new EncounterStatic { Species = 7, Level = 10, Location = 22, Gift = true }, // Squirtle + + new EncounterStatic { Species = 448, Level = 32, Location = 60, Ability = 1, Nature = Nature.Hasty, Gender = 0, IVs = new[] {6, 25, 16, 31, 25, 19}, Gift = true, Shiny = false }, // Lucario + new EncounterStatic { Species = 131, Level = 32, Location = 62, Nature = Nature.Docile, IVs = new[] {31, 20, 20, 20, 20, 20}, Gift = true }, // Lapras + + new EncounterStatic { Species = 143, Level = 15, Location = 38 }, // Snorlax + new EncounterStatic { Species = 568, Level = 35, Location = 142 }, // Trubbish + new EncounterStatic { Species = 569, Level = 36, Location = 142 }, // Garbodor + new EncounterStatic { Species = 569, Level = 37, Location = 142 }, // Garbodor + new EncounterStatic { Species = 569, Level = 38, Location = 142 }, // Garbodor + new EncounterStatic { Species = 479, Level = 38, Location = 142 }, // Rotom + + new EncounterStatic { Species = 716, Level = 50, Location = 138, Version = GameVersion.X, Shiny = false }, // Xerneas + new EncounterStatic { Species = 717, Level = 50, Location = 138, Version = GameVersion.Y, Shiny = false }, // Yveltal + new EncounterStatic { Species = 718, Level = 70, Location = 140, Shiny = false }, // Zygarde + + new EncounterStatic { Species = 150, Level = 70, Location = 168, Shiny = false }, // Mewtwo + + new EncounterStatic { Species = 144, Level = 70, Location = 146, Shiny = false }, // Articuno + new EncounterStatic { Species = 145, Level = 70, Location = 146, Shiny = false }, // Zapdos + new EncounterStatic { Species = 146, Level = 70, Location = 146, Shiny = false }, // Moltres + }; + private static readonly EncounterStatic[] Encounter_AO = + { + new EncounterStatic { Species = 252, Level = 5, Location = 204, Gift = true }, // Treeko + new EncounterStatic { Species = 255, Level = 5, Location = 204, Gift = true }, // Torchic + new EncounterStatic { Species = 258, Level = 5, Location = 204, Gift = true }, // Mudkip + + new EncounterStatic { Species = 152, Level = 5, Location = 204, Gift = true }, // Chikorita + new EncounterStatic { Species = 155, Level = 5, Location = 204, Gift = true }, // Cyndaquil + new EncounterStatic { Species = 158, Level = 5, Location = 204, Gift = true }, // Totodile + + new EncounterStatic { Species = 387, Level = 5, Location = 204, Gift = true }, // Turtwig + new EncounterStatic { Species = 390, Level = 5, Location = 204, Gift = true }, // Chimchar + new EncounterStatic { Species = 393, Level = 5, Location = 204, Gift = true }, // Piplup + + new EncounterStatic { Species = 495, Level = 5, Location = 204, Gift = true }, // Snivy + new EncounterStatic { Species = 498, Level = 5, Location = 204, Gift = true }, // Tepig + new EncounterStatic { Species = 501, Level = 5, Location = 204, Gift = true }, // Oshawott + + new EncounterStatic { Species = 25, Level = 20, Location = 186, Gender = 1, Ability = 4, Form = 1, IVs = new[] {-1, -1, -1, 31, -1, -1}, Contest = new[] {70,70,70,70,70,0}, Gift = true, Shiny = false }, // Pikachu + new EncounterStatic { Species = 25, Level = 20, Location = 186, Gender = 1, Ability = 4, Form = 3, IVs = new[] {-1, -1, -1, 31, -1, -1}, Contest = new[] {70,70,70,70,70,0}, Gift = true, Shiny = false }, // Pikachu + new EncounterStatic { Species = 360, Level = 1, EggLocation = 60004, Ability = 1, Gift = true }, // Wynaut + new EncounterStatic { Species = 175, Level = 1, EggLocation = 60004, Ability = 1, Gift = true }, // Togepi + new EncounterStatic { Species = 374, Level = 1, Location = 196, Ability = 1, IVs = new[] {-1, -1, 31, -1, -1, 31}, Gift = true }, // Beldum + + new EncounterStatic { Species = 351, Level = 30, Location = 240, Nature = Nature.Lax, Ability = 1, IVs = new[] {-1, -1, -1, -1, 31, -1}, Contest = new[] {0,100,0,0,0,0}, Gift = true }, // Castform + new EncounterStatic { Species = 319, Level = 40, Location = 318, Gender = 1, Ability = 1, Nature = Nature.Adamant, Gift = true }, // Sharpedo + new EncounterStatic { Species = 323, Level = 40, Location = 318, Gender = 1, Ability = 1, Nature = Nature.Quiet, Gift = true }, // Camerupt + + new EncounterStatic { Species = 380, Level = 30, Location = 320, Version = GameVersion.AS, Ability = 1, Gift = true }, // Latias + new EncounterStatic { Species = 381, Level = 30, Location = 320, Version = GameVersion.OR, Ability = 1, Gift = true }, // Latios + + new EncounterStatic { Species = 382, Level = 45, Location = 296, Version = GameVersion.AS, Shiny = false }, // Kyogre + new EncounterStatic { Species = 383, Level = 45, Location = 296, Version = GameVersion.OR, Shiny = false }, // Groudon + new EncounterStatic { Species = 384, Level = 70, Location = 316, Shiny = false }, // Rayquaza + new EncounterStatic { Species = 386, Level = 80, Location = 316, Shiny = false }, // Deoxys + + new EncounterStatic { Species = 377, Level = 40, Location = 278 }, // Regirock + new EncounterStatic { Species = 378, Level = 40, Location = 306 }, // Regice + new EncounterStatic { Species = 379, Level = 40, Location = 308 }, // Registeel + new EncounterStatic { Species = 486, Level = 50, Location = 306 }, // Regigigas + + new EncounterStatic { Species = 249, Level = 50, Location = 304, Version = GameVersion.AS }, // Lugia + new EncounterStatic { Species = 250, Level = 50, Location = 304, Version = GameVersion.OR }, // Ho-oh + + new EncounterStatic { Species = 483, Level = 50, Location = 348, Version = GameVersion.AS }, // Dialga + new EncounterStatic { Species = 484, Level = 50, Location = 348, Version = GameVersion.OR }, // Palia + + new EncounterStatic { Species = 644, Level = 50, Location = 340, Version = GameVersion.AS }, // Zekrom + new EncounterStatic { Species = 643, Level = 50, Location = 340, Version = GameVersion.OR }, // Reshiram + + new EncounterStatic { Species = 642, Level = 50, Location = 348, Version = GameVersion.AS }, // Thundurus + new EncounterStatic { Species = 641, Level = 50, Location = 348, Version = GameVersion.OR }, // Tornadus + + new EncounterStatic { Species = 485, Level = 50, Location = 312 }, // Heatran + new EncounterStatic { Species = 487, Level = 50, Location = 348 }, // Giratina + new EncounterStatic { Species = 488, Level = 50, Location = 344 }, // Cresselia + new EncounterStatic { Species = 645, Level = 50, Location = 348 }, // Landorus + new EncounterStatic { Species = 646, Level = 50, Location = 342 }, // Kyurem + + new EncounterStatic { Species = 243, Level = 50, Location = 334 }, // Raikou + new EncounterStatic { Species = 244, Level = 50, Location = 334 }, // Entei + new EncounterStatic { Species = 245, Level = 50, Location = 334 }, // Suicune + + new EncounterStatic { Species = 480, Level = 50, Location = 338 }, // Uxie + new EncounterStatic { Species = 481, Level = 50, Location = 338 }, // Mesprit + new EncounterStatic { Species = 482, Level = 50, Location = 338 }, // Azelf + + new EncounterStatic { Species = 638, Level = 50, Location = 336 }, // Cobalion + new EncounterStatic { Species = 639, Level = 50, Location = 336 }, // Terrakion + new EncounterStatic { Species = 640, Level = 50, Location = 336 }, // Virizion + + new EncounterStatic { Species = 352, Level = 30, Location = 240 }, // Kecleon @ Route 119 + new EncounterStatic { Species = 352, Level = 30, Location = 242 }, // Kecleon @ Route 120 + new EncounterStatic { Species = 352, Level = 40, Location = 176 }, // Kecleon @ Lavaridge + new EncounterStatic { Species = 352, Level = 45, Location = 196 }, // Kecleon @ Mossdeep City + + new EncounterStatic { Species = 381, Level = 30, Location = 320, Version = GameVersion.AS }, // Latios + new EncounterStatic { Species = 380, Level = 30, Location = 320, Version = GameVersion.OR }, // Latias + + new EncounterStatic { Species = 101, Level = 40, Location = 292, Version = GameVersion.AS }, // Electrode + new EncounterStatic { Species = 101, Level = 40, Location = 314, Version = GameVersion.OR }, // Electrode + + new EncounterStatic { Species = 100, Level = 20, Location = 302 }, // Voltorb @ Route 119 + new EncounterStatic { Species = 442, Level = 50, Location = 304 }, // Spiritomb @ Route 120 + + // Soaring in the Sky + new EncounterStatic { Species = 198, Level = 45, Location = 348 }, // Murkrow + new EncounterStatic { Species = 276, Level = 40, Location = 348 }, // Taillow + new EncounterStatic { Species = 278, Level = 40, Location = 348 }, // Wingull + new EncounterStatic { Species = 279, Level = 40, Location = 348 }, // Pelipper + new EncounterStatic { Species = 333, Level = 40, Location = 348 }, // Swablu + new EncounterStatic { Species = 425, Level = 45, Location = 348 }, // Drifloon + new EncounterStatic { Species = 628, Level = 45, Location = 348 }, // Braviary + }; + #endregion + #region Trade Tables + private static readonly EncounterTrade[] TradeGift_XY = + { + new EncounterTrade { Species = 129, Level = 5, Ability = 1, Gender = 0, TID = 44285, Nature = Nature.Adamant, }, // Magikarp + new EncounterTrade { Species = 133, Level = 5, Ability = 1, Gender = 1, TID = 29294, Nature = Nature.Docile, }, // Eevee + + new EncounterTrade { Species = 83, Level = 10, Ability = 1, Gender = 0, TID = 00185, Nature = Nature.Jolly, IVs = new[] {-1, -1, -1, 31, -1, -1}, }, // Farfetch'd + new EncounterTrade { Species = 208, Level = 20, Ability = 1, Gender = 1, TID = 19250, Nature = Nature.Impish, IVs = new[] {-1, -1, 31, -1, -1, -1}, }, // Steelix + new EncounterTrade { Species = 625, Level = 50, Ability = 1, Gender = 0, TID = 03447, Nature = Nature.Adamant, IVs = new[] {-1, 31, -1, -1, -1, -1}, }, // Bisharp + + new EncounterTrade { Species = 656, Level = 5, Ability = 1, Gender = 0, TID = 00037, Nature = Nature.Jolly, IVs = new[] {20, 20, 20, 31, 20, 20}, }, // Froakie + new EncounterTrade { Species = 650, Level = 5, Ability = 1, Gender = 0, TID = 00037, Nature = Nature.Adamant, IVs = new[] {20, 31, 20, 20, 20, 20}, }, // Chespin + new EncounterTrade { Species = 653, Level = 5, Ability = 1, Gender = 0, TID = 00037, Nature = Nature.Modest, IVs = new[] {20, 20, 20, 20, 31, 20}, }, // Fennekin + + new EncounterTrade { Species = 280, Level = 5, Ability = 1, Gender = 1, TID = 37110, Nature = Nature.Modest, IVs = new[] {20, 20, 20, 31, 31, 20}, }, // Ralts + }; + private static readonly EncounterTrade[] TradeGift_AO = + { + new EncounterTrade { Species = 296, Level = 9, Ability = 2, Gender = 0, TID = 30724, Nature = Nature.Brave, IVs = new[] {-1, 31, -1, -1, -1, -1}, }, // Makuhita + new EncounterTrade { Species = 300, Level = 25, Ability = 1, Gender = 1, TID = 03239, Nature = Nature.Naughty, IVs = new[] {-1, -1, -1, 31, -1, -1}, }, // Skitty + new EncounterTrade { Species = 222, Level = 50, Ability = 4, Gender = 1, TID = 00325, Nature = Nature.Calm, IVs = new[] {31, -1, -1, -1, -1, 31}, }, // Corsola + }; + #endregion + #region Pokémon Link Gifts + + private static readonly EncounterLink[] LinkGifts = + { + new EncounterLink { Species = 154, Level = 50, Ability = 4 }, // Meganium + new EncounterLink { Species = 157, Level = 50, Ability = 4 }, // Typhlosion + new EncounterLink { Species = 160, Level = 50, Ability = 4 }, // Feraligatr + + new EncounterLink {Species = 251, Level = 10, RelearnMoves = new[] {610, 0, 0, 0}, Ball = 11 }, // Celebi + + new EncounterLink { Species = 377, Level = 50, RelearnMoves = new[] {153, 8, 444, 359 }, Ability = 4 }, // Regirock + new EncounterLink { Species = 378, Level = 50, RelearnMoves = new[] {85, 133, 58, 258 }, Ability = 4 }, // Regice + new EncounterLink { Species = 379, Level = 50, RelearnMoves = new[] {442, 157, 356, 334 }, Ability = 4 }, // Registeel + + new EncounterLink { Species = 208, Level = 40, Classic = false, Ability = 1 }, // Steelix + new EncounterLink { Species = 362, Level = 40, Classic = false, Ability = 1 }, // Glalie + }; + + #endregion } }