diff --git a/PKHeX.Core/Legality/Areas/EncounterArea7g.cs b/PKHeX.Core/Legality/Areas/EncounterArea7g.cs index 1f16d4dfb..46e9ab00d 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea7g.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea7g.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; -using static PKHeX.Core.Species; namespace PKHeX.Core { @@ -10,65 +10,66 @@ namespace PKHeX.Core /// public sealed class EncounterArea7g : EncounterArea { - private EncounterArea7g() : base(GameVersion.GO) { } + public int Species { get; } + public int Form { get; } - internal static EncounterArea7g[] GetArea(HashSet raid15) + private EncounterArea7g(int species, int form) : base(GameVersion.GO) { - var noForm = Enumerable.Range(1, 150).Concat(Enumerable.Range(808, 2)); // count : 152 - var forms = new[] - { - (byte)Rattata, - (byte)Raticate, - (byte)Raichu, - (byte)Sandshrew, - (byte)Sandslash, - (byte)Vulpix, - (byte)Ninetales, - (byte)Diglett, - (byte)Dugtrio, - (byte)Meowth, - (byte)Persian, - (byte)Geodude, - (byte)Graveler, - (byte)Golem, - (byte)Grimer, - (byte)Muk, - (byte)Exeggutor, - (byte)Marowak, - }; + Species = species; + Form = form; + Location = 50; + } - var area = new EncounterArea7g { Location = 50, Type = SlotType.GoPark }; - EncounterSlot7GO GetSlot(EncounterArea7g a, int species, int form) + internal static EncounterArea7g[] GetArea(byte[][] pickle) + { + var areas = new EncounterArea7g[pickle.Length]; + for (int i = 0; i < areas.Length; i++) + areas[i] = GetArea(pickle[i]); + return areas; + } + + private const int entrySize = 2; + + private static EncounterArea7g GetArea(byte[] data) + { + var sf = BitConverter.ToInt16(data, 0); + int species = sf & 0x7FF; + int form = sf >> 11; + + // Files are padded to be multiples of 4 bytes. The last entry might actually be padding. + // Since we aren't saving a count up-front, just check if the last entry is valid. + int count = (data.Length - 2) / entrySize; + if (data[data.Length - 1] == 0) // type of "None" is not valid + count--; + + var result = new EncounterSlot7GO[count]; + var area = new EncounterArea7g(species, form) {Slots = result}; + + for (int i = 0; i < result.Length; i++) { - var min = raid15.Contains(species | (form << 11)) ? 15 : 1; - return new EncounterSlot7GO(a, species, form, min, 40); + var offset = (i * entrySize) + 2; + var shiny = (Shiny)data[offset]; + var type = (PogoType)data[offset + 1]; + result[i] = new EncounterSlot7GO(area, species, form, shiny, type); } - var regular = noForm.Select(z => GetSlot(area, z, 0)); - var alolan = forms.Select(z => GetSlot(area, z, 1)); - var slots = regular.Concat(alolan).ToArray(); - - area.Slots = slots; - return new[] { area }; + return area; } public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) { - foreach (var slot in Slots) + bool exists = chain.Any(z => z.Species == Species && z.Form == Form); + if (!exists) + yield break; + + foreach (var s in Slots) { - foreach (var evo in chain) - { - if (slot.Species != evo.Species) - continue; - - if (!slot.IsLevelWithinRange(pkm.Met_Level)) - break; - if (slot.Form != evo.Form) - break; - - yield return slot; - break; - } + var slot = (EncounterSlot7GO)s; + if (!slot.IsLevelWithinRange(pkm.Met_Level)) + continue; + if (!slot.Shiny.IsValid(pkm)) + continue; + yield return slot; } } } diff --git a/PKHeX.Core/Legality/Areas/EncounterArea8g.cs b/PKHeX.Core/Legality/Areas/EncounterArea8g.cs index 9cd9fd2ac..cafa7fae0 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea8g.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea8g.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; namespace PKHeX.Core @@ -9,82 +10,72 @@ namespace PKHeX.Core /// public sealed class EncounterArea8g : EncounterArea { - private EncounterArea8g() : base(GameVersion.GO) { } + public int Species { get; } + public int Form { get; } - internal static EncounterArea8g[] GetArea(int maxSpecies, HashSet banlist, IEnumerable extras) + private EncounterArea8g(int species, int form) : base(GameVersion.GO) { - var area = new EncounterArea8g { Location = Locations.GO8, Type = SlotType.GoPark }; - var all = GetSlots(area, maxSpecies, banlist, extras); - area.Slots = all.ToArray(); - return new[] { area }; + Species = species; + Form = form; + Location = Locations.GO8; } - private static EncounterSlot8GO GetSlot(EncounterArea8g area, int species, int form, GameVersion baseOrigin) + internal static EncounterArea8g[] GetArea(byte[][] pickle) { - var min = EncountersGO.GetMinLevel(species, form); - return new EncounterSlot8GO(area, species, form, baseOrigin, min, 40); + var areas = new EncounterArea8g[pickle.Length]; + for (int i = 0; i < areas.Length; i++) + areas[i] = GetArea(pickle[i]); + return areas; } - private static IEnumerable GetSlots(EncounterArea8g area, int maxSpecies, HashSet banlist, IEnumerable extras) - { - // Gen7: GO transfers to LGPE cannot send Mew. - // Gen8: GO transfers to HOME can send Mew. Iterate from here. - // However, Mew transfers with LGPE base moves. Because everything <= 151 uses LGPE level-up table. Handle manually! - yield return GetSlot(area, (int)Species.Mew, 0, GameVersion.GG); - const int start = 1; - var speciesList = Enumerable.Range(start, maxSpecies - start + 1).Concat(extras); + private const int entrySize = (2 * sizeof(int)) + 2; - var pt7 = PersonalTable.USUM; + private static EncounterArea8g GetArea(byte[] data) + { + var sf = BitConverter.ToInt16(data, 0); + int species = sf & 0x7FF; + int form = sf >> 11; + + var group = GetGroup(species, form); + + var result = new EncounterSlot8GO[(data.Length - 2) / entrySize]; + var area = new EncounterArea8g(species, form) {Slots = result}; + for (int i = 0; i < result.Length; i++) + { + var offset = (i * entrySize) + 2; + result[i] = ReadSlot(data, offset, area, species, form, group); + } + + return area; + } + + private static EncounterSlot8GO ReadSlot(byte[] data, int offset, EncounterArea8g area, int species, int form, GameVersion group) + { + int start = BitConverter.ToInt32(data, offset); + int end = BitConverter.ToInt32(data, offset + 4); + var shiny = (Shiny)data[offset + 8]; + var type = (PogoType)data[offset + 9]; + return new EncounterSlot8GO(area, species, form, group, type, shiny, start, end); + } + + private static GameVersion GetGroup(int species, int form) + { var pt8 = PersonalTable.SWSH; var ptGG = PersonalTable.GG; - foreach (var specform in speciesList) + + var pi8 = (PersonalInfoSWSH)pt8[species]; + if (pi8.IsPresentInGame) { - var species = specform & 0x7FF; - if (banlist.Contains(species)) - continue; - - var pi8 = (PersonalInfoSWSH)pt8[species]; - if (pi8.IsPresentInGame) - { - for (int f = 0; f < pi8.FormeCount; f++) - { - var sf = species | (f << 11); - if (banlist.Contains(sf)) - continue; - if (IsDisallowedDuplicateForm(species, f)) - continue; - bool lgpe = (species <= 151 || species == 808 || species == 809) && (f == 0 || ptGG[species].HasForme(f)); - var game = lgpe ? GameVersion.GG : GameVersion.SWSH; - yield return GetSlot(area, species, f, game); - } - } - else if (species <= Legal.MaxSpeciesID_7_USUM) - { - var pi7 = pt7[species]; - for (int f = 0; f < pi7.FormeCount; f++) - { - var sf = species | (f << 11); - if (banlist.Contains(sf)) - continue; - if (IsDisallowedDuplicateForm(species, f)) - continue; - bool lgpe = species <= 151 && (f == 0 || ptGG[species].HasForme(f)); - var game = lgpe ? GameVersion.GG : GameVersion.USUM; - yield return GetSlot(area, species, f, game); - } - } + bool lgpe = (species <= 151 || species == 808 || species == 809) && (form == 0 || ptGG[species].HasForme(form)); + return lgpe ? GameVersion.GG : GameVersion.SWSH; + } + if (species <= Legal.MaxSpeciesID_7_USUM) + { + bool lgpe = species <= 151 && (form == 0 || ptGG[species].HasForme(form)); + return lgpe ? GameVersion.GG : GameVersion.USUM; } - } - private static bool IsDisallowedDuplicateForm(int species, int f) - { - if (AltFormInfo.IsBattleOnlyForm(species, f, 8)) - return true; - if (AltFormInfo.IsFusedForm(species, f, 8)) - return true; - if (species == (int) Species.Mothim) - return f != 0; // Reverts to Plant Cloak on transfer. - return false; + throw new ArgumentOutOfRangeException(nameof(species)); } public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) @@ -92,21 +83,21 @@ public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyLi if (pkm.TSV == 0) // HOME doesn't assign TSV=0 to accounts. yield break; - foreach (var slot in Slots) + bool exists = chain.Any(z => z.Species == Species && z.Form == Form); + if (!exists) + yield break; + + var ball = (Ball)pkm.Ball; + foreach (var s in Slots) { - foreach (var evo in chain) - { - if (slot.Species != evo.Species) - continue; - - if (!slot.IsLevelWithinRange(pkm.Met_Level)) - break; - if (slot.Form != evo.Form) - break; - - yield return slot; - break; - } + var slot = (EncounterSlot8GO)s; + if (!slot.IsLevelWithinRange(pkm.Met_Level)) + continue; + if (!slot.IsBallValid(ball)) + continue; + if (!slot.Shiny.IsValid(pkm)) + continue; + yield return slot; } } } diff --git a/PKHeX.Core/Legality/Encounters/Data/EncountersGO.cs b/PKHeX.Core/Legality/Encounters/Data/EncountersGO.cs index 4c482843c..756d26c63 100644 --- a/PKHeX.Core/Legality/Encounters/Data/EncountersGO.cs +++ b/PKHeX.Core/Legality/Encounters/Data/EncountersGO.cs @@ -1,799 +1,15 @@ -using System.Collections.Generic; -using static PKHeX.Core.Species; - -namespace PKHeX.Core +namespace PKHeX.Core { /// /// Encounter data from , which has multiple generations of origin. /// internal static class EncountersGO { - /// Clamp for generating encounters; no species allowed above this value except for those in . - private const int MaxSpeciesID_GO_HOME = Legal.MaxSpeciesID_5; + internal const int MAX_LEVEL = 40; - /// Species beyond that are available for capture and transferring. - private static readonly int[] ExtraSpecies = - { - (int)Meltan, - (int)Melmetal, + internal static readonly EncounterArea7g[] SlotsGO_GG = EncounterArea7g.GetArea(Get("go_lgpe", "go")); + internal static readonly EncounterArea8g[] SlotsGO = EncounterArea8g.GetArea(Get("go_home", "go")); - (int)Obstagoon, - (int)Perrserker, - (int)Sirfetchd, - (int)Runerigus, - }; - - /// When generating encounters, these species will be skipped. - private static readonly HashSet DisallowedSpecies = new HashSet - { - // Unreleased Galarian Forms and Galarian Evolutions - (int)Slowpoke + (1 << 11), (int)Slowbro + (2 << 11), (int)Slowking + (1 << 11), - (int)MrMime + (1 << 11), (int)MrRime, - (int)Articuno + (1 << 11), - (int)Zapdos + (1 << 11), - (int)Moltres + (1 << 11), - (int)Corsola + (1 << 11), (int)Cursola, - - // Unreleased Pokémon (Generations 6, 7, and 8 are all unavailable, with some exceptions) - (int)Kecleon, - (int)Phione, - (int)Manaphy, - (int)Shaymin, - (int)Arceus, - (int)Munna, (int)Musharna, - (int)Zorua, (int)Zoroark, - (int)Vanillite, (int)Vanillish, (int)Vanilluxe, - (int)Deerling, (int)Sawsbuck, // Spring - (int)Deerling + (1 << 11), (int)Sawsbuck + (1 << 11), // Summer - (int)Deerling + (3 << 11), (int)Sawsbuck + (3 << 11), // Winter - (int)Frillish, (int)Jellicent, - (int)Tynamo, (int)Eelektrik, (int)Eelektross, - (int)Mienfoo, (int)Mienshao, - (int)Druddigon, - (int)Larvesta, (int)Volcarona, - (int)Keldeo, - (int)Meloetta, - - // Cannot be transferred to HOME - (int)Spinda, - }; - - private static readonly HashSet UnavailableShiny = new HashSet - { - // Unreleased Shiny Galarian Forms and Galarian Evolutions - (int)Meowth + (2 << 11), (int)Perrserker, - (int)Ponyta + (1 << 11), (int)Rapidash + (1 << 11), - (int)Slowpoke + (1 << 11), (int)Slowbro + (2 << 11), (int)Slowking + (1 << 11), - (int)Farfetchd + (1 << 11), (int)Sirfetchd, - (int)Weezing + (1 << 11), - (int)MrMime + (1 << 11), (int)MrRime, - (int)Articuno + (1 << 11), - (int)Zapdos + (1 << 11), - (int)Moltres + (1 << 11), - (int)Corsola + (1 << 11), (int)Cursola, - (int)Zigzagoon + (1 << 11), (int)Linoone + (1 << 11), (int)Obstagoon, - (int)Darumaka + (1 << 11), (int)Darmanitan + (2 << 11), - (int)Yamask + (1 << 11), (int)Runerigus, - (int)Stunfisk + (1 << 11), - - // Unreleased Shiny Pokémon (Generations 6, 7, and 8 are all unavailable, with some exceptions) - (int)Spearow, (int)Fearow, - (int)Paras, (int)Parasect, - (int)Slowpoke, (int)Slowbro, (int)Slowking, - (int)Goldeen, (int)Seaking, - (int)Ditto, - (int)Mew, - (int)Hoothoot, (int)Noctowl, - (int)Spinarak, (int)Ariados, - (int)Hoppip, (int)Skiploom, (int)Jumpluff, - (int)Wooper, (int)Quagsire, - (int)Unown + (2 << 11), // B - (int)Unown + (3 << 11), // C - (int)Unown + (4 << 11), // D - (int)Unown + (5 << 11), // E - (int)Unown + (6 << 11), // F - (int)Unown + (8 << 11), // H - (int)Unown + (9 << 11), // I - (int)Unown + (10 << 11), // J - (int)Unown + (11 << 11), // K - (int)Unown + (13 << 11), // M - (int)Unown + (14 << 11), // N - (int)Unown + (16 << 11), // P - (int)Unown + (17 << 11), // Q - (int)Unown + (19 << 11), // S - (int)Unown + (22 << 11), // V - (int)Unown + (23 << 11), // W - (int)Unown + (24 << 11), // X - (int)Unown + (25 << 11), // Y - (int)Unown + (26 << 11), // Z - (int)Unown + (27 << 11), // ! - (int)Unown + (28 << 11), // ? - (int)Girafarig, - (int)Heracross, - (int)Slugma, (int)Magcargo, - (int)Corsola, - (int)Remoraid, (int)Octillery, - (int)Phanpy, (int)Donphan, - (int)Smeargle, - (int)Tyrogue, (int)Hitmonlee, (int)Hitmonchan, (int)Hitmontop, - (int)Miltank, - (int)Celebi, - (int)Surskit, (int)Masquerain, - (int)Shroomish, (int)Breloom, - (int)Whismur, (int)Loudred, (int)Exploud, - (int)Nosepass, (int)Probopass, - (int)Gulpin, (int)Swalot, - (int)Numel, (int)Camerupt, - (int)Torkoal, - (int)Cacnea, (int)Cacturne, - (int)Corphish, (int)Crawdaunt, - (int)Kecleon, - (int)Tropius, - (int)Spheal, (int)Sealeo, (int)Walrein, - (int)Relicanth, - (int)Jirachi, - (int)Starly, (int)Staravia, (int)Staraptor, - (int)Bidoof, (int)Bibarel, - (int)Cranidos, (int)Rampardos, - (int)Shieldon, (int)Bastiodon, - (int)Combee, (int)Vespiquen, - (int)Pachirisu, - (int)Buizel, (int)Floatzel, - (int)Cherubi, (int)Cherrim, - (int)Shellos, (int)Gastrodon, // West Sea - (int)Shellos + (1 << 11), (int)Gastrodon + (1 << 11), // East Sea - (int)Chingling, (int)Chimecho, - (int)Stunky, (int)Skuntank, - (int)Chatot, - (int)Munchlax, (int)Snorlax, - (int)Carnivine, - (int)Finneon, (int)Lumineon, - (int)Mantyke, (int)Mantine, - (int)Rotom, - (int)Uxie, - (int)Mesprit, - (int)Azelf, - (int)Dialga, - (int)Palkia, - (int)Regigigas, - (int)Phione, - (int)Manaphy, - (int)Shaymin, - (int)Arceus, - (int)Victini, - (int)Snivy, (int)Servine, (int)Serperior, - (int)Tepig, (int)Pignite, (int)Emboar, - (int)Oshawott, (int)Dewott, (int)Samurott, - (int)Purrloin, (int)Liepard, - (int)Pansage, (int)Simisage, - (int)Pansear, (int)Simisear, - (int)Panpour, (int)Simipour, - (int)Munna, (int)Musharna, - (int)Blitzle, (int)Zebstrika, - (int)Drilbur, (int)Excadrill, - (int)Audino, - (int)Tympole, (int)Palpitoad, (int)Seismitoad, - (int)Throh, - (int)Sawk, - (int)Sewaddle, (int)Swadloon, (int)Leavanny, - (int)Venipede, (int)Whirlipede, (int)Scolipede, - (int)Cottonee, (int)Whimsicott, - (int)Petilil, (int)Lilligant, - (int)Basculin, // Red-Striped - (int)Basculin + (1 << 11), // Blue-Striped - (int)Sandile, (int)Krokorok, (int)Krookodile, - (int)Darumaka, (int)Darmanitan, - (int)Maractus, - (int)Scraggy, (int)Scrafty, - (int)Sigilyph, - (int)Tirtouga, (int)Carracosta, - (int)Archen, (int)Archeops, - (int)Trubbish, (int)Garbodor, - (int)Zorua, (int)Zoroark, - (int)Gothita, (int)Gothorita, (int)Gothitelle, - (int)Solosis, (int)Duosion, (int)Reuniclus, - (int)Ducklett, (int)Swanna, - (int)Vanillite, (int)Vanillish, (int)Vanilluxe, - (int)Deerling, (int)Sawsbuck, // Spring - (int)Deerling + (1 << 11), (int)Sawsbuck + (1 << 11), // Summer - (int)Deerling + (2 << 11), (int)Sawsbuck + (2 << 11), // Autumn - (int)Deerling + (3 << 11), (int)Sawsbuck + (3 << 11), // Winter - (int)Emolga, - (int)Karrablast, (int)Escavalier, - (int)Foongus, (int)Amoonguss, - (int)Frillish, (int)Jellicent, - (int)Alomomola, - (int)Joltik, (int)Galvantula, - (int)Tynamo, (int)Eelektrik, (int)Eelektross, - (int)Elgyem, (int)Beheeyem, - (int)Litwick, (int)Lampent, (int)Chandelure, - (int)Axew, (int)Fraxure, (int)Haxorus, - (int)Cubchoo, (int)Beartic, - (int)Cryogonal, - (int)Shelmet, (int)Accelgor, - (int)Stunfisk, - (int)Mienfoo, (int)Mienshao, - (int)Druddigon, - (int)Golett, (int)Golurk, - (int)Pawniard, (int)Bisharp, - (int)Bouffalant, - (int)Rufflet, (int)Braviary, - (int)Vullaby, (int)Mandibuzz, - (int)Larvesta, (int)Volcarona, - (int)Tornadus, - (int)Thundurus, - (int)Reshiram, - (int)Zekrom, - (int)Landorus, - (int)Kyurem, - (int)Keldeo, - (int)Meloetta, - }; - - private static readonly HashSet Purified = new HashSet - { - // Purified Pokémon - (int)Bulbasaur, (int)Ivysaur, (int)Venusaur, - (int)Charmander, (int)Charmeleon, (int)Charizard, - (int)Squirtle, (int)Wartortle, (int)Blastoise, - (int)Weedle, (int)Kakuna, (int)Beedrill, - (int)Rattata, (int)Raticate, - (int)Ekans, (int)Arbok, - (int)Sandshrew, (int)Sandslash, - (int)NidoranF, (int)Nidorina, (int)Nidoqueen, - (int)NidoranM, (int)Nidorino, (int)Nidoking, - (int)Vulpix, (int)Ninetales, - (int)Zubat, (int)Golbat, (int)Crobat, - (int)Oddish, (int)Gloom, (int)Vileplume, (int)Bellossom, - (int)Venonat, (int)Venomoth, - (int)Diglett, (int)Dugtrio, - (int)Meowth, (int)Persian, - (int)Psyduck, (int)Golduck, - (int)Growlithe, (int)Arcanine, - (int)Poliwag, (int)Poliwhirl, (int)Poliwrath, (int)Politoed, - (int)Abra, (int)Kadabra, (int)Alakazam, - (int)Machop, (int)Machoke, (int)Machamp, - (int)Bellsprout, (int)Weepinbell, (int)Victreebel, - (int)Slowpoke, (int)Slowbro, (int)Slowking, - (int)Magnemite, (int)Magneton, (int)Magnezone, - (int)Grimer, (int)Muk, - (int)Shellder, (int)Cloyster, - (int)Drowzee, (int)Hypno, - (int)Exeggcute, (int)Exeggutor, - (int)Cubone, (int)Marowak, - (int)Hitmonlee, (int)Hitmonchan, - (int)Koffing, (int)Weezing, - (int)Scyther, (int)Scizor, - (int)Electabuzz, (int)Electivire, - (int)Magmar, (int)Magmortar, - (int)Pinsir, - (int)Magikarp, (int)Gyarados, - (int)Lapras, - (int)Porygon, (int)Porygon2, (int)PorygonZ, - (int)Omanyte, (int)Omastar, - (int)Aerodactyl, - (int)Snorlax, - (int)Articuno, - (int)Zapdos, - (int)Moltres, - (int)Dratini, (int)Dragonair, (int)Dragonite, - (int)Mewtwo, - (int)Mareep, (int)Flaaffy, (int)Ampharos, - (int)Hoppip, (int)Skiploom, (int)Jumpluff, - (int)Misdreavus, (int)Mismagius, - (int)Wobbuffet, - (int)Pineco, (int)Forretress, - (int)Gligar, (int)Gliscor, - (int)Shuckle, - (int)Sneasel, (int)Weavile, - (int)Teddiursa, (int)Ursaring, - (int)Delibird, - (int)Skarmory, - (int)Houndour, (int)Houndoom, - (int)Stantler, - (int)Raikou, - (int)Entei, - (int)Suicune, - (int)Larvitar, (int)Pupitar, (int)Tyranitar, - (int)Mudkip, (int)Marshtomp, (int)Swampert, - (int)Seedot, (int)Nuzleaf, (int)Shiftry, - (int)Ralts, (int)Kirlia, (int)Gardevoir, (int)Gallade, - (int)Sableye, - (int)Mawile, - (int)Carvanha, (int)Sharpedo, - (int)Trapinch, (int)Vibrava, (int)Flygon, - (int)Cacnea, (int)Cacturne, - (int)Shuppet, (int)Banette, - (int)Duskull, (int)Dusclops, (int)Dusknoir, - (int)Absol, - (int)Bagon, (int)Shelgon, (int)Salamence, - (int)Beldum, (int)Metang, (int)Metagross, - (int)Turtwig, (int)Grotle, (int)Torterra, - (int)Stunky, (int)Skuntank, - (int)Snover, (int)Abomasnow, - }; - - private static readonly HashSet PurifiedShiny = new HashSet - { - (int)Ekans, (int)Arbok, - (int)Meowth, (int)Persian, - (int)Growlithe, (int)Arcanine, - (int)Grimer, (int)Muk, - (int)Drowzee, (int)Hypno, - (int)Koffing, (int)Weezing, - (int)Scyther, (int)Scizor, - (int)Pinsir, - (int)Lapras, - (int)Omanyte, (int)Omastar, - (int)Pineco, (int)Forretress, - (int)Sneasel, (int)Weavile, - (int)Stantler, - (int)Mawile, - (int)Absol, - (int)Bagon, (int)Shelgon, (int)Salamence, - (int)Beldum, (int)Metang, (int)Metagross, - }; - - /// Premier Ball Legality - private static readonly HashSet AvailableAsRaids = new HashSet(Purified) - { - // Base Species (Raids) - (int)Bulbasaur, (int)Ivysaur, (int)Venusaur, - (int)Charmander, (int)Charmeleon, (int)Charizard, - (int)Squirtle, (int)Wartortle, (int)Blastoise, - (int)Caterpie, (int)Metapod, (int)Butterfree, - (int)Beedrill, - (int)Pidgeot, - (int)Fearow, - (int)Ekans, (int)Arbok, - (int)Pikachu, (int)Raichu, - (int)Sandshrew, (int)Sandslash, - (int)Nidoqueen, - (int)NidoranM, (int)Nidorino, (int)Nidoking, - (int)Clefairy, (int)Clefable, - (int)Vulpix, (int)Ninetales, - (int)Jigglypuff, (int)Wigglytuff, - (int)Zubat, (int)Golbat, (int)Crobat, - (int)Gloom, (int)Vileplume, (int)Bellossom, - (int)Venonat, (int)Venomoth, - (int)Meowth, (int)Persian, - (int)Psyduck, (int)Golduck, - (int)Mankey, (int)Primeape, - (int)Growlithe, (int)Arcanine, - (int)Poliwag, (int)Poliwhirl, (int)Poliwrath, (int)Politoed, - (int)Abra, (int)Kadabra, (int)Alakazam, - (int)Machop, (int)Machoke, (int)Machamp, - (int)Victreebel, - (int)Tentacruel, - (int)Geodude, (int)Graveler, (int)Golem, - (int)Ponyta, (int)Rapidash, - (int)Slowpoke, (int)Slowbro, (int)Slowking, - (int)Magnemite, (int)Magneton, (int)Magnezone, - (int)Seel, (int)Dewgong, - (int)Grimer, (int)Muk, - (int)Shellder, (int)Cloyster, - (int)Haunter, (int)Gengar, - (int)Onix, (int)Steelix, - (int)Drowzee, (int)Hypno, - (int)Krabby, (int)Kingler, - (int)Voltorb, (int)Electrode, - (int)Exeggutor, - (int)Cubone, (int)Marowak, - (int)Hitmonlee, (int)Hitmonchan, (int)Hitmontop, - (int)Lickitung, (int)Lickilicky, - (int)Koffing, (int)Weezing, - (int)Rhydon, (int)Rhyperior, - (int)Chansey, (int)Blissey, - (int)Tangela, (int)Tangrowth, - (int)Horsea, (int)Seadra, (int)Kingdra, - (int)Staryu, (int)Starmie, - (int)Scyther, (int)Scizor, - (int)Jynx, - (int)Electabuzz, (int)Electivire, - (int)Magmar, (int)Magmortar, - (int)Pinsir, - (int)Magikarp, (int)Gyarados, - (int)Lapras, - (int)Eevee, (int)Vaporeon, (int)Jolteon, (int)Flareon, (int)Espeon, (int)Umbreon, (int)Leafeon, (int)Glaceon, - (int)Porygon, (int)Porygon2, (int)PorygonZ, - (int)Omanyte, (int)Omastar, - (int)Kabuto, (int)Kabutops, - (int)Aerodactyl, - (int)Snorlax, - (int)Articuno, - (int)Zapdos, - (int)Moltres, - (int)Dratini, (int)Dragonair, (int)Dragonite, - (int)Mewtwo, - (int)Chikorita, (int)Bayleef, (int)Meganium, - (int)Cyndaquil, (int)Quilava, (int)Typhlosion, - (int)Totodile, (int)Croconaw, (int)Feraligatr, - (int)Sentret, (int)Furret, - (int)Noctowl, - (int)Lanturn, - (int)Togetic, (int)Togekiss, - (int)Mareep, (int)Flaaffy, (int)Ampharos, - (int)Azumarill, - (int)Sudowoodo, - (int)Aipom, (int)Ambipom, - (int)Sunkern, (int)Sunflora, - (int)Yanma, (int)Yanmega, - (int)Murkrow, (int)Honchkrow, - (int)Misdreavus, (int)Mismagius, - (int)Unown + (1 << 11), // A - (int)Unown + (12 << 11), // L - (int)Unown + (18 << 11), // R - (int)Unown + (20 << 11), // T - (int)Unown + (21 << 11), // U - (int)Wobbuffet, - (int)Girafarig, - (int)Pineco, (int)Forretress, - (int)Gligar, (int)Gliscor, - (int)Snubbull, (int)Granbull, - (int)Qwilfish, - (int)Shuckle, - (int)Sneasel, (int)Weavile, - (int)Ursaring, - (int)Magcargo, - (int)Swinub, (int)Piloswine, (int)Mamoswine, - (int)Octillery, - (int)Delibird, - (int)Mantine, - (int)Skarmory, - (int)Houndour, (int)Houndoom, - (int)Donphan, - (int)Miltank, - (int)Raikou, - (int)Entei, - (int)Suicune, - (int)Larvitar, (int)Pupitar, (int)Tyranitar, - (int)Lugia, - (int)HoOh, - (int)Treecko, (int)Grovyle, (int)Sceptile, - (int)Torchic, (int)Combusken, (int)Blaziken, - (int)Mudkip, (int)Marshtomp, (int)Swampert, - (int)Mightyena, - (int)Wurmple, (int)Silcoon, (int)Beautifly, (int)Cascoon, (int)Dustox, - (int)Lotad, (int)Lombre, (int)Ludicolo, - (int)Nuzleaf, (int)Shiftry, - (int)Swellow, - (int)Wingull, (int)Pelipper, - (int)Ralts, (int)Kirlia, (int)Gardevoir, (int)Gallade, - (int)Masquerain, - (int)Breloom, - (int)Slakoth, (int)Vigoroth, (int)Slaking, - (int)Ninjask, - (int)Makuhita, (int)Hariyama, - (int)Nosepass, (int)Probopass, - (int)Sableye, - (int)Mawile, - (int)Aron, (int)Lairon, (int)Aggron, - (int)Meditite, (int)Medicham, - (int)Manectric, - (int)Plusle, - (int)Minun, - (int)Roselia, (int)Roserade, - (int)Swalot, - (int)Carvanha, (int)Sharpedo, - (int)Wailmer, (int)Wailord, - (int)Spoink, (int)Grumpig, - (int)Trapinch, (int)Vibrava, (int)Flygon, - (int)Cacnea, (int)Cacturne, - (int)Swablu, (int)Altaria, - (int)Lunatone, - (int)Solrock, - (int)Whiscash, - (int)Crawdaunt, - (int)Baltoy, (int)Claydol, - (int)Lileep, (int)Cradily, - (int)Anorith, (int)Armaldo, - (int)Feebas, (int)Milotic, - (int)Shuppet, (int)Banette, - (int)Duskull, (int)Dusclops, (int)Dusknoir, - (int)Absol, - (int)Snorunt, (int)Glalie, (int)Froslass, - (int)Walrein, - (int)Clamperl, (int)Huntail, (int)Gorebyss, - (int)Luvdisc, - (int)Bagon, (int)Shelgon, (int)Salamence, - (int)Beldum, (int)Metang, (int)Metagross, - (int)Regirock, - (int)Regice, - (int)Registeel, - (int)Latias, - (int)Latios, - (int)Kyogre, - (int)Groudon, - (int)Rayquaza, - (int)Deoxys, - (int)Turtwig, (int)Grotle, (int)Torterra, - (int)Chimchar, (int)Monferno, (int)Infernape, - (int)Piplup, (int)Prinplup, (int)Empoleon, - (int)Staraptor, - (int)Bidoof, (int)Bibarel, - (int)Kricketot, (int)Kricketune, - (int)Shinx, (int)Luxio, (int)Luxray, - (int)Cranidos, (int)Rampardos, - (int)Shieldon, (int)Bastiodon, - (int)Burmy, (int)Wormadam, (int)Mothim, // Plant Cloak - (int)Burmy + (1 << 11), (int)Wormadam + (1 << 11), (int)Mothim + (1 << 11), // Sandy Cloak - (int)Burmy + (2 << 11), (int)Wormadam + (2 << 11), (int)Mothim + (2 << 11), // Trash Cloak - (int)Combee, (int)Vespiquen, - (int)Buizel, (int)Floatzel, - (int)Drifloon, (int)Drifblim, - (int)Buneary, (int)Lopunny, - (int)Skuntank, - (int)Bronzor, (int)Bronzong, - (int)Hippopotas, (int)Hippowdon, - (int)Gible, (int)Gabite, (int)Garchomp, - (int)Skorupi, (int)Drapion, - (int)Croagunk, (int)Toxicroak, - (int)Lumineon, - (int)Abomasnow, - (int)Uxie, - (int)Mesprit, - (int)Azelf, - (int)Dialga, - (int)Palkia, - (int)Heatran, - (int)Regigigas, - (int)Giratina, - (int)Cresselia, - (int)Darkrai, - (int)Snivy, (int)Servine, (int)Serperior, - (int)Tepig, (int)Pignite, (int)Emboar, - (int)Oshawott, (int)Dewott, (int)Samurott, - (int)Patrat, (int)Watchog, - (int)Lillipup, (int)Herdier, (int)Stoutland, - (int)Liepard, - (int)Pidove, (int)Tranquill, (int)Unfezant, - (int)Blitzle, (int)Zebstrika, - (int)Roggenrola, (int)Boldore, (int)Gigalith, - (int)Woobat, (int)Swoobat, - (int)Excadrill, - (int)Timburr, (int)Gurdurr, (int)Conkeldurr, - (int)Tympole, (int)Palpitoad, (int)Seismitoad, - (int)Venipede, (int)Whirlipede, (int)Scolipede, - (int)Cottonee, (int)Whimsicott, - (int)Petilil, (int)Lilligant, - (int)Darumaka, (int)Darmanitan, - (int)Dwebble, (int)Crustle, - (int)Yamask, (int)Cofagrigus, - (int)Trubbish, (int)Garbodor, - (int)Minccino, (int)Cinccino, - (int)Gothita, (int)Gothorita, (int)Gothitelle, - (int)Solosis, (int)Duosion, (int)Reuniclus, - (int)Amoonguss, - (int)Joltik, (int)Galvantula, - (int)Ferroseed, (int)Ferrothorn, - (int)Klink, (int)Klang, (int)Klinklang, - (int)Elgyem, (int)Beheeyem, - (int)Litwick, (int)Lampent, (int)Chandelure, - (int)Cubchoo, (int)Beartic, - (int)Cryogonal, - (int)Stunfisk, - (int)Golurk, - (int)Cobalion, - (int)Terrakion, - (int)Virizion, - (int)Tornadus, - (int)Thundurus, - (int)Landorus, - (int)Reshiram, - (int)Zekrom, - (int)Kyurem, - - // Alolan Forms (Raids) - (int)Raticate + (1 << 11), - (int)Raichu + (1 << 11), - (int)Vulpix + (1 << 11), (int)Ninetales + (1 << 11), - (int)Dugtrio + (1 << 11), - (int)Meowth + (1 << 11), (int)Persian + (1 << 11), - (int)Geodude + (1 << 11), (int)Graveler + (1 << 11), (int)Golem + (1 << 11), - (int)Grimer + (1 << 11), (int)Muk + (1 << 11), - (int)Exeggutor + (1 << 11), - (int)Marowak + (1 << 11), - - // Galarian Forms (Raids) - (int)Ponyta + (1 << 11), (int)Rapidash + (1 << 11), - (int)Weezing + (1 << 11), - (int)Stunfisk + (1 << 11), - }; - - private static readonly HashSet RequireLevelIV_Egg1_1 = new HashSet - { - // Egg - // Minimum Lvl: 1 - // Minimum GO IVs: 1/1/1 - // Minimum Core Series IVs: 3/3/3/3/3/0 - (int)Meowth + (2 << 11), (int)Perrserker, - (int)Ponyta + (1 << 11), (int)Rapidash + (1 << 11), - (int)Pichu, - (int)Cleffa, - (int)Igglybuff, - (int)Togepi, - (int)Tyrogue, - (int)Smoochum, - (int)Elekid, - (int)Magby, - (int)Zigzagoon + (1 << 11), (int)Linoone + (1 << 11), (int)Obstagoon, - (int)Azurill, - (int)Wynaut, - (int)Shinx, (int)Luxio, (int)Luxray, - (int)Budew, - (int)Chingling, - (int)Bonsly, - (int)Happiny, - (int)Munchlax, - (int)Riolu, (int)Lucario, - (int)Mantyke, - (int)Sandile, (int)Krokorok, (int)Krookodile, - (int)Darumaka, (int)Darmanitan, - (int)Darumaka + (1 << 11), (int)Darmanitan + (2 << 11), - (int)Klink, (int)Klang, (int)Klinklang, - (int)Pawniard, (int)Bisharp, - (int)Vullaby, (int)Mandibuzz, - }; - - private static readonly HashSet RequireLevelIV_EggShiny1_1 = new HashSet - { - // Shiny Baby Evolutions - // Minimum Lvl: 1 - // Minimum GO IVs: 1/1/1 - // Minimum Core Series IVs: 3/3/3/3/3/0 - // The following Species can only be Shiny if hatched from an Egg. - // They can be encountered in the wild, but if they are Shiny, they must abide by Egg requirements. - (int)Togetic, (int)Togekiss, - (int)Jynx, - (int)Electabuzz, (int)Electivire, - (int)Magmar, (int)Magmortar, - }; - - private static readonly HashSet RequireLevelIV_Raid15_1_LGPE = new HashSet - { - // Raid Battle / Field Research - // Minimum Lvl: 15 - // Minimum GO IVs: 1/1/1 - // Minimum Core Series IVs: 3/3/3/3/3/0 - // Pokémon from regular Raid Battles (Lv. 20) get moved down to Lv. 15 when Traded to low-level accounts. - (int)Raichu + (1 << 11), - (int)Articuno, - (int)Zapdos, - (int)Moltres, - (int)Mewtwo, - }; - - private static readonly HashSet RequireLevelIV_Raid15_1 = new HashSet(RequireLevelIV_Raid15_1_LGPE) - { - (int)Weezing + (1 << 11), - - (int)Raikou, - (int)Entei, - (int)Suicune, - (int)Lugia, - (int)HoOh, - (int)Shedinja, - (int)Spinda, - (int)Regirock, - (int)Regice, - (int)Registeel, - (int)Latias, - (int)Latios, - (int)Kyogre, - (int)Groudon, - (int)Rayquaza, - (int)Spiritomb, - (int)Dialga, - (int)Palkia, - (int)Heatran, - (int)Regigigas, - (int)Giratina, - (int)Cresselia, - (int)Victini, - (int)Yamask + (1 << 11), (int)Runerigus, - (int)Cobalion, - (int)Terrakion, - (int)Virizion, - (int)Tornadus, - (int)Thundurus, - (int)Reshiram, - (int)Zekrom, - (int)Landorus, - (int)Kyurem, - }; - - private static readonly HashSet RequireLevelIV_Field15_10 = new HashSet - { - // Field Research (Mythical) - // Minimum Lvl: 15 - // Minimum GO IVs: 10/10/10 - // Minimum Core Series IVs: 21/21/21/21/21/0 - (int)Mew, - (int)Celebi, - (int)Jirachi, - (int)Victini, - (int)Genesect, - }; - - private static readonly HashSet RequireLevelIV_Raid20_10 = new HashSet - { - // Raid Battle (Mythical) - // Minimum Lvl: 20 - // Minimum GO IVs: 10/10/10 - // Minimum Core Series IVs: 21/21/21/21/21/0 - (int)Deoxys, - (int)Darkrai, - }; - - internal static readonly EncounterArea7g[] SlotsGO_GG = EncounterArea7g.GetArea(RequireLevelIV_Raid15_1_LGPE); - internal static readonly EncounterArea8g[] SlotsGO = EncounterArea8g.GetArea(MaxSpeciesID_GO_HOME, DisallowedSpecies, ExtraSpecies); - - internal static bool IsBallValid(int species, int form, Ball ball) - { - if (ball == 0) - return false; - - var sf = species | (form << 11); - if (ball == Ball.Premier && AvailableAsRaids.Contains(sf)) - return true; - if (RequireLevelIV_Raid15_1.Contains(sf)) - return ball == Ball.Premier; - if (RequireLevelIV_Raid20_10.Contains(sf)) - return ball == Ball.Premier; - - if (RequireLevelIV_Field15_10.Contains(sf)) - return ball == Ball.Poke; - - if (RequireLevelIV_Egg1_1.Contains(sf) || RequireLevelIV_EggShiny1_1.Contains(sf)) - return ball == Ball.Poke; - - return Ball.Ultra <= ball && ball <= Ball.Poke; - } - - internal static int GetMinLevel(int species, int form) - { - var sf = species | (form << 11); - if (RequireLevelIV_Raid15_1.Contains(sf)) - return 15; - if (RequireLevelIV_Field15_10.Contains(sf)) - return 15; - if (RequireLevelIV_Raid20_10.Contains(sf)) - return 20; - return 1; - } - - internal static int GetMinIVs(int species, int form, Ball ball) - { - var sf = species | (form << 11); - if (ball == Ball.Premier) - { - if (RequireLevelIV_Raid15_1.Contains(sf)) - return 1; - if (RequireLevelIV_Field15_10.Contains(sf)) - return 10; - if (RequireLevelIV_Raid20_10.Contains(sf)) - return 10; - return 0; - } - - if (RequireLevelIV_Egg1_1.Contains(sf)) - return 1; - if (RequireLevelIV_EggShiny1_1.Contains(sf)) - return 1; - - return 0; - } - - public static bool IsShinyValid(int species, int form, Ball ball) - { - var sf = species | (form << 11); - if (ball == Ball.Premier) - { - if (PurifiedShiny.Contains(sf)) - return true; - } - - return !UnavailableShiny.Contains(sf); - } + private static byte[][] Get(string resource, string ident) => BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident); } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7GO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7GO.cs index 4f1680237..9b9b5bc4d 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7GO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7GO.cs @@ -1,17 +1,20 @@ namespace PKHeX.Core { - public sealed class EncounterSlot7GO : EncounterSlot + public sealed class EncounterSlot7GO : EncounterSlot, IPogoSlot { public override int Generation => 7; + public PogoType Type { get; } + public Shiny Shiny { get; } - public EncounterSlot7GO(EncounterArea7g area, int species, int form, int min, int max) : base(area) + public EncounterSlot7GO(EncounterArea7g area, int species, int form, Shiny shiny, PogoType type) : base(area) { Species = species; Form = form; - LevelMin = min; - LevelMax = max; - } + LevelMin = type.GetMinLevel(); + LevelMax = EncountersGO.MAX_LEVEL; - public void ClampMinRaid(int level) => LevelMin = level; + Shiny = shiny; + Type = type; + } } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8GO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8GO.cs index aa54a240e..68e7b251b 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8GO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8GO.cs @@ -1,17 +1,118 @@ namespace PKHeX.Core { - public sealed class EncounterSlot8GO : EncounterSlot + public sealed class EncounterSlot8GO : EncounterSlot, IPogoSlotTime { public override int Generation => 8; public GameVersion OriginGroup { get; } - public EncounterSlot8GO(EncounterArea8g area, int species, int form, GameVersion gameVersion, int min, int max) : base(area) + public PogoType Type { get; } + public Shiny Shiny { get; } + public int Start { get; } + public int End { get; } + + public override string LongName + { + get + { + var init = $"{Name} ({Type})"; + if (Start == 0 && End == 0) + return init; + return $"{init}: {GetDate(Start)}-{GetDate(End)}"; + } + } + + private static string GetDate(int time) + { + var d = time & 0xFF; + var m = (time >> 8) & 0xFF; + var y = time >> 16; + return $"{y:0000}.{m:00}.{d:00}"; + } + + public bool IsWithinStartEnd(int y, int m, int d) + { + var stamp = GetTimeStamp(y, m, d); + return IsWithinStartEnd(stamp); + } + + public bool IsWithinStartEnd(int stamp) + { + if (End == 0) + return stamp >= Start; + if (Start == 0) + return stamp <= Start; + return Start <= stamp && stamp <= End; + } + + public static int GetTimeStamp(int y, int m, int d) => (y << 16) | (m << 8) | d; + + public EncounterSlot8GO(EncounterArea8g area, int species, int form, GameVersion gameVersion, PogoType type, Shiny shiny, int start, int end) : base(area) { Species = species; Form = form; - LevelMin = min; - LevelMax = max; + LevelMin = type.GetMinLevel(); + LevelMax = 40; + Start = start; + End = end; + + Shiny = shiny; + Type = type; + OriginGroup = gameVersion; } + + public int GetMinIV() => Type.GetMinIV(); + public bool IsBallValid(Ball ball) => Type.IsBallValid(ball); + } + + public interface IPogoSlot + { + Shiny Shiny { get; } + PogoType Type { get; } + } + + public interface IPogoSlotTime : IPogoSlot + { + int Start { get; } + int End { get; } + } + + public enum PogoType : byte + { + None, // Don't use this. + + Wild, + Egg, + + /// requires level 15 and IV=1 + Raid15 = 10, + /// requires level 20 and IV=10 + Raid20, + + /// requires level 15 and IV=10 + Field15 = 20, + + Shadow = 30, + } + + public static class PogoTypeExtensions + { + public static int GetMinLevel(this PogoType t) => t switch + { + _ => 1, + }; + + public static int GetMinIV(this PogoType t) => t switch + { + _ => 1, + }; + + public static bool IsBallValid(this PogoType t, Ball b) => t switch + { + PogoType.Egg => b == Ball.Poke, + PogoType.Raid15 => b == Ball.Premier, + PogoType.Raid20 => b == Ball.Premier, + _ => b != Ball.Premier, + }; } } diff --git a/PKHeX.Core/Legality/Verifiers/BallVerifier.cs b/PKHeX.Core/Legality/Verifiers/BallVerifier.cs index ce704f358..4566ab2dd 100644 --- a/PKHeX.Core/Legality/Verifiers/BallVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/BallVerifier.cs @@ -87,7 +87,7 @@ private CheckResult VerifyBallWild(LegalityAnalysis data, EncounterSlot w) private CheckResult VerifyBallGOHOME(LegalityAnalysis data, EncounterSlot8GO enc) { - var valid = EncountersGO.IsBallValid(enc.Species, enc.Form, (Ball)data.pkm.Ball); + var valid = enc.IsBallValid((Ball)data.pkm.Ball); return GetResult(valid); } diff --git a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs index f197b7e10..fa11fbcb1 100644 --- a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs @@ -116,18 +116,10 @@ private void VerifyIVsGoTransfer(LegalityAnalysis data) } else if (data.EncounterMatch is EncounterSlot8GO g) { - var minIV = EncountersGO.GetMinIVs(g.Species, g.Form, (Ball) pkm.Ball); + var minIV = g.GetMinIV(); if (!IsGoIVSetValid(pkm, minIV)) data.AddLine(GetInvalid(LIVNotCorrect)); } - - if (!pkm.IsShiny) - return; - - var enc = data.EncounterMatch; - bool shinyValid = EncountersGO.IsShinyValid(enc.Species, enc.Form, (Ball)pkm.Ball); - if (!shinyValid) - data.AddLine(GetInvalid(LEncStaticPIDShiny, CheckIdentifier.PID)); } private static bool IsGoIVSetValid(PKM pkm) diff --git a/PKHeX.Core/PKHeX.Core.csproj b/PKHeX.Core/PKHeX.Core.csproj index 0ed5463b6..d625a9359 100644 --- a/PKHeX.Core/PKHeX.Core.csproj +++ b/PKHeX.Core/PKHeX.Core.csproj @@ -35,6 +35,8 @@ + + @@ -877,6 +879,8 @@ + + diff --git a/PKHeX.Core/Resources/byte/encounter_go_home.pkl b/PKHeX.Core/Resources/byte/encounter_go_home.pkl new file mode 100644 index 000000000..d41f31519 Binary files /dev/null and b/PKHeX.Core/Resources/byte/encounter_go_home.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_go_lgpe.pkl b/PKHeX.Core/Resources/byte/encounter_go_lgpe.pkl new file mode 100644 index 000000000..22ef77ac9 Binary files /dev/null and b/PKHeX.Core/Resources/byte/encounter_go_lgpe.pkl differ