diff --git a/PKHeX.Core/Game/Enums/Ball.cs b/PKHeX.Core/Game/Enums/Ball.cs index 80ca73afd..e369a55de 100644 --- a/PKHeX.Core/Game/Enums/Ball.cs +++ b/PKHeX.Core/Game/Enums/Ball.cs @@ -40,7 +40,7 @@ public enum Ball : byte Beast = 26, } - public static partial class Extensions + public static class BallExtensions { /// /// Checks if the is an Apricorn Ball (HG/SS) @@ -48,5 +48,23 @@ public static partial class Extensions /// Ball ID /// True if Apricorn, false if not. public static bool IsApricornBall(this Ball ball) => Ball.Fast <= ball && ball <= Ball.Moon; + + public static Ball GetRequiredBallValueWild(int gen, int loc) + { + return gen switch + { + // For Gen3 Safari Zones, we've already deferred partial match encounters. + 3 when Locations.IsSafariZoneLocation3(loc) => Ball.Safari, + + // For Gen4 Safari Zones and BCC, we've already deferred partial match encounters. + 4 when Locations.IsSafariZoneLocation4(loc) => Ball.Safari, + 4 when Locations.BugCatchingContest4 == loc => Ball.Sport, + + // Poké Pelago + 7 when loc == 30016 => Ball.Poke, + + _ => Ball.None, + }; + } } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/Areas/EncounterArea.cs b/PKHeX.Core/Legality/Areas/EncounterArea.cs index 7289b0d5a..fbb65d7ef 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea.cs @@ -6,71 +6,19 @@ namespace PKHeX.Core /// /// Represents an Area where can be encountered, which contains a Location ID and data. /// - public class EncounterArea + public abstract class EncounterArea { - public int Location; + public int Location { get; protected set; } + public SlotType Type { get; protected set; } = SlotType.Any; public EncounterSlot[] Slots = Array.Empty(); - /// - /// Gets the encounter areas for species with same level range and same slot type at same location - /// - /// List of species that exist in the Area. - /// Paired min and max levels of the encounter slots. - /// Location index of the encounter area. - /// Encounter slot type of the encounter area. - /// Encounter area with slots - public static TArea[] GetSimpleEncounterArea(int[] species, int[] lvls, int location, SlotType t) - where TArea : EncounterArea, new() - where TSlot : EncounterSlot, new() - { - if ((lvls.Length & 1) != 0) // levels data not paired; expect multiple of 2 - throw new ArgumentException(nameof(lvls)); - - var count = species.Length * (lvls.Length / 2); - var slots = new TSlot[count]; - int ctr = 0; - foreach (var s in species) - { - for (int i = 0; i < lvls.Length;) - { - slots[ctr++] = new TSlot - { - LevelMin = lvls[i++], - LevelMax = lvls[i++], - Species = s, - Type = t - }; - } - } - return new[] { new TArea { Location = location, Slots = slots } }; - } - /// /// Gets the slots contained in the area that match the provided data. /// /// Pokémon Data /// Evolution lineage /// Enumerable list of encounters - public virtual IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) - { - foreach (var slot 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 && !Legal.WildChangeFormAfter.Contains(slot.Species)) - break; - - yield return slot; - break; - } - } - } + public abstract IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain); /// /// Checks if the provided met location ID matches the parameters for the area. diff --git a/PKHeX.Core/Legality/Areas/EncounterArea1.cs b/PKHeX.Core/Legality/Areas/EncounterArea1.cs index f4f2024a9..d40873733 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea1.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea1.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; namespace PKHeX.Core { @@ -10,100 +8,35 @@ namespace PKHeX.Core /// public sealed class EncounterArea1 : EncounterArea { - private static EncounterSlot1[] ReadSlots1FishingYellow(byte[] data, ref int ofs, int count, SlotType t, int rate) - { - // Convert byte to actual number - byte[] levels = { 0xFF, 0x15, 0x67, 0x1D, 0x3B, 0x5C, 0x72, 0x16, 0x71, 0x18, 0x00, 0x6D, 0x80, }; - byte[] g1DexIDs = { 0x47, 0x6E, 0x18, 0x9B, 0x17, 0x4E, 0x8A, 0x5C, 0x5D, 0x9D, 0x9E, 0x1B, 0x85, 0x16, 0x58, 0x59, }; - int[] speciesIDs = { 060, 061, 072, 073, 090, 098, 099, 116, 117, 118, 119, 120, 129, 130, 147, 148, }; + public readonly int Rate; + public static EncounterArea1[] GetAreas(byte[][] input, GameVersion game) + { + var result = new EncounterArea1[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea1(input[i], game); + return result; + } + + private EncounterArea1(byte[] data, GameVersion game) + { + Location = data[0]; + // 1 byte unused + Type = (SlotType)data[2]; + Rate = data[3]; + + int count = (data.Length - 4) / 4; var slots = new EncounterSlot1[count]; - for (int slot = 0; slot < count; slot++) + for (int i = 0; i < slots.Length; i++) { - int species = speciesIDs[Array.IndexOf(g1DexIDs, data[ofs++])]; - int lvl = Array.IndexOf(levels, data[ofs++]) * 5; - slots[slot] = new EncounterSlot1(species, lvl, lvl, rate, t, slot); + int offset = 4 + (4 * i); + int species = data[offset + 0]; + int slotNum = data[offset + 1]; + int min = data[offset + 2]; + int max = data[offset + 3]; + slots[i] = new EncounterSlot1(this, species, min, max, slotNum, game); } - return slots; - } - - /// - /// Gets the encounter areas with information from Generation 1 Grass/Water data. - /// - /// Input raw data. - /// Count of areas in the binary. - /// Array of encounter areas. - public static EncounterArea1[] GetArray1GrassWater(byte[] data, int count) - { - EncounterArea1[] areas = new EncounterArea1[count]; - for (int i = 0; i < areas.Length; i++) - { - int ptr = BitConverter.ToInt16(data, i * 2); - var grass = GetSlots1GrassWater(data, ref ptr, SlotType.Grass); - var water = GetSlots1GrassWater(data, ref ptr, SlotType.Surf); - areas[i] = new EncounterArea1 - { - Location = i, - Slots = ArrayUtil.ConcatAll(grass, water), - }; - } - return areas.Where(area => area.Slots.Length != 0).ToArray(); - } - - /// - /// Gets the encounter areas with information from Pokémon Yellow (Generation 1) Fishing data. - /// - /// Input raw data. - /// Array of encounter areas. - public static EncounterArea1[] GetArray1FishingYellow(byte[] data) - { - const int size = 9; - int count = data.Length / size; - EncounterArea1[] areas = new EncounterArea1[count]; - for (int i = 0; i < count; i++) - { - int ofs = (i * size) + 1; - areas[i] = new EncounterArea1 - { - Location = data[(i * size) + 0], - Slots = ReadSlots1FishingYellow(data, ref ofs, 4, SlotType.Super_Rod, -1) - }; - } - return areas; - } - - /// - /// Gets the encounter areas with information from Generation 1 Fishing data. - /// - /// Input raw data. - /// Count of areas in the binary. - /// Array of encounter areas. - public static EncounterArea1[] GetArray1Fishing(byte[] data, int count) - { - EncounterArea1[] areas = new EncounterArea1[count]; - for (int i = 0; i < areas.Length; i++) - { - int loc = data[(i * 3) + 0]; - int ptr = BitConverter.ToInt16(data, (i * 3) + 1); - areas[i] = new EncounterArea1 - { - Location = loc, - Slots = GetSlots1Fishing(data, ptr) - }; - } - return areas; - } - - private static EncounterSlot1[] GetSlots1GrassWater(byte[] data, ref int ofs, SlotType t) - { - int rate = data[ofs++]; - return rate == 0 ? Array.Empty() : EncounterSlot1.ReadSlots(data, ref ofs, 10, t, rate); - } - - private static EncounterSlot1[] GetSlots1Fishing(byte[] data, int ofs) - { - int count = data[ofs++]; - return EncounterSlot1.ReadSlots(data, ref ofs, count, SlotType.Super_Rod, -1); + Slots = slots; } public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) @@ -116,7 +49,7 @@ public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyLi if (slot.Species != evo.Species) continue; - if (!slot.IsLevelWithinRange(evo.MinLevel, evo.Level)) + if (slot.LevelMin > evo.Level) break; if (slot.Form != evo.Form) break; diff --git a/PKHeX.Core/Legality/Areas/EncounterArea2.cs b/PKHeX.Core/Legality/Areas/EncounterArea2.cs index c330efe0d..e9505f252 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea2.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea2.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace PKHeX.Core { @@ -10,274 +9,68 @@ namespace PKHeX.Core /// public sealed class EncounterArea2 : EncounterArea { - /// - /// Gets the encounter areas with information from Generation 2 Grass/Water data. - /// - /// Input raw data. - /// Array of encounter areas. - public static EncounterArea2[] GetArray2GrassWater(byte[] data) + private static readonly byte[] BCC_SlotRates = { 20, 20, 10, 10, 05, 05, 10, 10, 05, 05 }; + private static readonly byte[] RatesGrass = { 30, 30, 20, 10, 5, 4, 1 }; + private static readonly byte[] RatesSurf = { 60, 30, 10 }; + + internal readonly EncounterTime Time; + public readonly int Rate; + public readonly IReadOnlyList Rates; + + public static EncounterArea2[] GetAreas(byte[][] input, GameVersion game) { - int ofs = 0; - var areas = new List(); - areas.AddRange(GetAreas2(data, ref ofs, SlotType.Grass, 3, 7)); // Johto Grass - areas.AddRange(GetAreas2(data, ref ofs, SlotType.Surf, 1, 3)); // Johto Water - areas.AddRange(GetAreas2(data, ref ofs, SlotType.Grass, 3, 7)); // Kanto Grass - areas.AddRange(GetAreas2(data, ref ofs, SlotType.Surf, 1, 3)); // Kanto Water - areas.AddRange(GetAreas2(data, ref ofs, SlotType.Swarm, 3, 7)); // Swarm - areas.AddRange(GetAreas2(data, ref ofs, SlotType.Special, 1, 3)); // Union Cave - return areas.ToArray(); + var result = new EncounterArea2[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea2(input[i], game); + return result; } - // Fishing Tables are not associated to a single map; a map picks a table to use. - // For all maps that use a table, create a new EncounterArea with reference to the table's slots. - private static readonly sbyte[] convMapIDtoFishLocationID = + private EncounterArea2(byte[] data, GameVersion game) { - -1, 1, -1, 0, 3, 3, 3, -1, 10, 3, 2, -1, -1, 2, 3, 0, - -1, -1, 3, -1, -1, -1, 3, -1, -1, -1, -1, 0, -1, -1, 0, 9, - 1, 0, 2, 2, -1, 3, 7, 3, -1, 3, 4, 8, 2, -1, 2, 1, - -1, 3, -1, -1, -1, -1, -1, 0, 2, 2, -1, -1, 3, 1, -1, -1, - -1, 2, -1, 2, -1, -1, -1, -1, -1, -1, 10, 10, -1, -1, -1, -1, - -1, 7, 0, 1, -1, 1, 1, 3, -1, -1, -1, 1, 1, 2, 3, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; + Location = data[0]; + Time = (EncounterTime)data[1]; + var type = Type = (SlotType)data[2]; + var rate = data[3]; - /// - /// Gets the encounter areas with information from Generation 2 Grass/Water data. - /// - /// Input raw data. - /// Array of encounter areas. - public static EncounterArea2[] GetArray2Fishing(byte[] data) - { - int ofs = 0; - var f = GetAreas2Fishing(data, ref ofs); - - var areas = new List(); - for (int i = 0; i < convMapIDtoFishLocationID.Length; i++) + if (type > SlotType.Surf) // Not Grass/Surf { - var loc = convMapIDtoFishLocationID[i]; - if (loc == -1) // no table for map - continue; - areas.Add(new EncounterArea2 { Location = i, Slots = f[loc].Slots }); + const int size = 5; + int count = (data.Length - 4) / size; + + var rates = new byte[count]; + for (int i = 0; i < rates.Length; i++) + rates[i] = data[4 + i]; + + Rates = rates; + Slots = ReadSlots(data, count, 4 + count, game); } - - // Some maps have two tables. Fortunately, there's only two. Add the second table. - areas.Add(new EncounterArea2 { Location = 0x1B, Slots = f[1].Slots }); // Olivine City (0: Harbor, 1: City) - areas.Add(new EncounterArea2 { Location = 0x2E, Slots = f[3].Slots }); // Silver Cave (2: Inside, 3: Outside) - return areas.ToArray(); - } - - public static EncounterArea2[] GetArray2Headbutt(byte[] data) - { - int ofs = 0; - return GetAreas2Headbutt(data, ref ofs).ToArray(); - } - - private static EncounterSlot2[] GetSlots2GrassWater(byte[] data, ref int ofs, SlotType t, int slotSets, int slotCount) - { - byte[] rates = new byte[slotSets]; - for (int i = 0; i < rates.Length; i++) - rates[i] = data[ofs++]; - - var slots = EncounterSlot2.ReadSlots(data, ref ofs, slotSets * slotCount, t, rates[0]); - if (slotSets <= 1) - return slots; - - for (int i = 0; i < slotCount; i++) + else { - slots[i].Time = EncounterTime.Morning; - } - for (int r = 1; r < slotSets; r++) - { - for (int i = 0; i < slotCount; i++) - { - int index = i + (r * slotCount); - slots[index].Rate = rates[r]; - slots[index].SlotNumber = i; - slots[index].Time = r == 1 ? EncounterTime.Day : EncounterTime.Night; - } - } + Rate = rate; - return slots; + const int size = 4; + int count = (data.Length - 4) / size; + Rates = type == SlotType.BugContest ? BCC_SlotRates : (type == SlotType.Grass) ? RatesGrass : RatesSurf; + Slots = ReadSlots(data, count, 4, game); + } } - private static EncounterSlot2[] GetSlots2Fishing(byte[] data, ref int ofs, SlotType t) + private EncounterSlot2[] ReadSlots(byte[] data, int count, int start, GameVersion game) { - // slot set ends with final slot having 0xFF 0x** 0x** - const int size = 3; - int end = ofs; // scan for count - while (data[end] != 0xFF) - end += size; - var count = ((end - ofs) / size) + 1; var slots = new EncounterSlot2[count]; for (int i = 0; i < slots.Length; i++) { - int rate = data[ofs++]; - int species = data[ofs++]; - int level = data[ofs++]; - var type = species == 0 ? SlotType.Special : t; // day/night specific; - slots[i] = new EncounterSlot2(species, level, level, rate, type, i); + int offset = start + (4 * i); + int species = data[offset + 0]; + int slotNum = data[offset + 1]; + int min = data[offset + 2]; + int max = data[offset + 3]; + slots[i] = new EncounterSlot2(this, species, min, max, slotNum, game); } + return slots; } - private static EncounterSlot2[] GetSlots2Headbutt(byte[] data, ref int ofs, SlotType t) - { - // slot set ends in 0xFF - var slots = new List(); - int tableCount = t == SlotType.Headbutt ? 2 : 1; - SlotType slottype = t; - int slot = 0; - while (tableCount != 0) - { - if (t == SlotType.Headbutt) - slottype = tableCount == 2 ? SlotType.Headbutt_Special : SlotType.Headbutt; - int rate = data[ofs++]; - if (rate == 0xFF) // end of table - { - tableCount--; - continue; - } - - int species = data[ofs++]; - int level = data[ofs++]; - - slots.Add(new EncounterSlot2(species, level, level, rate, slottype, slot++)); - } - return slots.ToArray(); - } - - private static IEnumerable GetAreas2(byte[] data, ref int ofs, SlotType t, int slotSets, int slotCount) - { - var areas = new List(); - while (data[ofs] != 0xFF) // end - { - var location = data[ofs++] << 8 | data[ofs++]; - var slots = GetSlots2GrassWater(data, ref ofs, t, slotSets, slotCount); - var area = new EncounterArea2 - { - Location = location, - Slots = slots, - }; - foreach (var slot in slots) - slot.Area = area; - areas.Add(area); - } - ofs++; - return areas; - } - - private static List GetAreas2Fishing(byte[] data, ref int ofs) - { - var areas = new List(); - while (ofs != 0x18C) - { - var old = GetSlots2Fishing(data, ref ofs, SlotType.Old_Rod); - var good = GetSlots2Fishing(data, ref ofs, SlotType.Good_Rod); - var super = GetSlots2Fishing(data, ref ofs, SlotType.Super_Rod); - areas.Add(new EncounterArea2 - { - Slots = ArrayUtil.ConcatAll(old, good, super), - }); - } - - // Read TimeFishGroups - var dl = new List(); - while (ofs < data.Length) - dl.Add(new SlotTemplate(data[ofs++], data[ofs++])); - - // Add TimeSlots - foreach (var area in areas) - { - var slots = area.Slots; - for (int i = 0; i < slots.Length; i++) - { - var slot = slots[i]; - if (slot.Type != SlotType.Special) - continue; - Array.Resize(ref slots, slots.Length + 1); - Array.Copy(slots, i, slots, i + 1, slots.Length - i - 1); // shift slots down - slots[i + 1] = slot.Clone(); // differentiate copied slot - - int index = slot.LevelMin * 2; - for (int j = 0; j < 2; j++) // load special slot info - { - var s = (EncounterSlot2)slots[i + j]; - s.Species = dl[index + j].Species; - s.LevelMin = s.LevelMax = dl[index + j].Level; - s.Type = slots[i - 1].Type; // special slots are never first in a set, so copy previous type - s.Time = j == 0 ? EncounterTime.Morning | EncounterTime.Day : EncounterTime.Night; - } - } - area.Slots = slots; - } - return areas; - } - - private readonly struct SlotTemplate - { - public readonly byte Species; - public readonly byte Level; - - public SlotTemplate(byte species, byte level) - { - Species = species; - Level = level; - } - } - - private static IEnumerable GetAreas2Headbutt(byte[] data, ref int ofs) - { - // Read Location Table - var head = new List(); - var headID = new List(); - while (data[ofs] != 0xFF) - { - head.Add(new EncounterArea2 - { - Location = (data[ofs++] << 8) | data[ofs++], - //Slots = null, // later - }); - headID.Add(data[ofs++]); - } - ofs++; - - var rock = new List(); - var rockID = new List(); - while (data[ofs] != 0xFF) - { - rock.Add(new EncounterArea2 - { - Location = (data[ofs++] << 8) | data[ofs++], - //Slots = null, // later - }); - rockID.Add(data[ofs++]); - } - ofs++; - ofs += 0x16; // jump over GetTreeMons - - // Read ptr table - int[] ptr = new int[data.Length == 0x109 ? 6 : 9]; // GS : C - for (int i = 0; i < ptr.Length; i++) - ptr[i] = data[ofs++] | (data[ofs++] << 8); - - int baseOffset = ptr.Min() - ofs; - - // Read Tables - for (int i = 0; i < head.Count; i++) - { - int o = ptr[headID[i]] - baseOffset; - head[i].Slots = GetSlots2Headbutt(data, ref o, SlotType.Headbutt); - } - for (int i = 0; i < rock.Count; i++) - { - int o = ptr[rockID[i]] - baseOffset; - rock[i].Slots = GetSlots2Headbutt(data, ref o, SlotType.Rock_Smash); - } - - return head.Concat(rock); - } - public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) { if (!(pkm is PK2 pk2) || pk2.CaughtData == 0) @@ -306,8 +99,7 @@ private IEnumerable GetSlotsSpecificLevelTime(IReadOnlyList GetSlotsFuzzy(IReadOnlyList chai if (slot.Species != (int) Species.Unown || evo.Form >= 26) // Don't yield !? forms break; } - if (!slot.IsLevelWithinRange(evo.MinLevel, evo.Level)) + if (slot.LevelMin > evo.Level) break; yield return slot; diff --git a/PKHeX.Core/Legality/Areas/EncounterArea3.cs b/PKHeX.Core/Legality/Areas/EncounterArea3.cs index 064fafd74..e89c0f148 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea3.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea3.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace PKHeX.Core { @@ -10,119 +9,96 @@ namespace PKHeX.Core /// public sealed class EncounterArea3 : EncounterArea { - private static IEnumerable GetSlots3(byte[] data, ref int ofs, int numslots, SlotType t) + public readonly int Rate; + + internal EncounterArea3() { } + + public static EncounterArea3[] GetAreas(byte[][] input, GameVersion game) { - var slots = new List(); - int Ratio = data[ofs]; - //1 byte padding - if (Ratio > 0) - ReadInSlots(data, ofs, numslots, t, slots); - ofs += 2 + (numslots * 4); - return slots; + var result = new EncounterArea3[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea3(input[i], game); + return result; } - private static void ReadInSlots(byte[] data, int ofs, int numslots, SlotType t, List slots) + public static EncounterArea3[] GetAreasSwarm(byte[][] input, GameVersion game) { - for (int i = 0; i < numslots; i++) - { - int o = ofs + (i * 4); - int species = BitConverter.ToInt16(data, o + 4); - if (species <= 0) - continue; + var result = new EncounterArea3[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea3(input[i], game, false); + return result; + } - slots.Add(new EncounterSlot3 - { - LevelMin = data[o + 2], - LevelMax = data[o + 3], - Species = species, - SlotNumber = i, - Type = t - }); + private EncounterArea3(byte[] data, GameVersion game) + { + Location = data[0] | (data[1] << 8); + Type = (SlotType)data[2]; + Rate = data[3]; + + Slots = ReadRegularSlots(data, game); + } + + private EncounterArea3(byte[] data, GameVersion game, bool _) + { + Location = data[0] | (data[1] << 8); + Type = SlotType.Swarm | SlotType.Grass; + Rate = data[3]; + + Slots = ReadSwarmSlots(data, game); + } + + private EncounterSlot3[] ReadRegularSlots(byte[] data, GameVersion game) + { + const int size = 10; + int count = (data.Length - 4) / size; + var slots = new EncounterSlot3[count]; + for (int i = 0; i < slots.Length; i++) + { + int offset = 4 + (size * i); + + int species = BitConverter.ToUInt16(data, offset + 0); + int form = data[offset + 2]; + int slotNum = data[offset + 3]; + int min = data[offset + 4]; + int max = data[offset + 5]; + + int mpi = data[offset + 6]; + int mpc = data[offset + 7]; + int sti = data[offset + 8]; + int stc = data[offset + 9]; + slots[i] = new EncounterSlot3(this, species, form, min, max, slotNum, mpi, mpc, sti, stc, game); } - } - private static IEnumerable GetSlots3Fishing(byte[] data, ref int ofs, int numslots) - { - var slots = new List(); - int Ratio = data[ofs]; - //1 byte padding - if (Ratio > 0) - ReadFishingSlots(data, ofs, numslots, slots); - ofs += 2 + (numslots * 4); return slots; } - private static void ReadFishingSlots(byte[] data, int ofs, int numslots, List slots) + private EncounterSlot3[] ReadSwarmSlots(byte[] data, GameVersion game) { - for (int i = 0; i < numslots; i++) + const int size = 14; + int count = (data.Length - 4) / size; + var slots = new EncounterSlot3[count]; + for (int i = 0; i < slots.Length; i++) { - int Species = BitConverter.ToInt16(data, ofs + 4 + (i * 4)); - if (Species <= 0) - continue; + int offset = 4 + (size * i); - var slot = new EncounterSlot3 + int species = BitConverter.ToUInt16(data, offset + 0); + // form always 0 + int slotNum = data[offset + 3]; + int min = data[offset + 4]; + int max = data[offset + 5]; + + int[] moves = { - LevelMin = data[ofs + 2 + (i * 4)], - LevelMax = data[ofs + 3 + (i * 4)], - Species = Species, + BitConverter.ToUInt16(data, offset + 6), + BitConverter.ToUInt16(data, offset + 8), + BitConverter.ToUInt16(data, offset + 10), + BitConverter.ToUInt16(data, offset + 12), }; - if (i < 2) - { - slot.Type = SlotType.Old_Rod; - slot.SlotNumber = i; // 0,1 - } - else if (i < 5) - { - slot.Type = SlotType.Good_Rod; - slot.SlotNumber = i - 2; // 0,1,2 - } - else - { - slot.Type = SlotType.Super_Rod; - slot.SlotNumber = i - 5; // 0,1,2,3,4 - } - slots.Add(slot); + slots[i] = new EncounterSlot3Swarm(this, species, min, max, slotNum, game, moves); } - } - private static EncounterArea3 GetArea3(byte[] data) - { - var HaveGrassSlots = data[1] == 1; - var HaveSurfSlots = data[2] == 1; - var HaveRockSmashSlots = data[3] == 1; - var HaveFishingSlots = data[4] == 1; - - int offset = 5; - var slots = new List(); - if (HaveGrassSlots) - slots.AddRange(GetSlots3(data, ref offset, 12, SlotType.Grass)); - if (HaveSurfSlots) - slots.AddRange(GetSlots3(data, ref offset, 5, SlotType.Surf)); - if (HaveRockSmashSlots) - slots.AddRange(GetSlots3(data, ref offset, 5, SlotType.Rock_Smash)); - if (HaveFishingSlots) - slots.AddRange(GetSlots3Fishing(data, ref offset, 10)); - - var area = new EncounterArea3 - { - Location = data[0], - Slots = slots.ToArray() - }; - foreach (var slot in area.Slots) - slot.Area = area; - - return area; - } - - /// - /// Gets the encounter areas with information from Generation 3 data. - /// - /// Raw data, one byte array per encounter area - /// Array of encounter areas. - public static EncounterArea3[] GetArray3(byte[][] entries) - { - return entries.Select(GetArea3).Where(Area => Area.Slots.Length != 0).ToArray(); + return slots; } public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) @@ -165,7 +141,7 @@ private IEnumerable GetSlotsFuzzy(IReadOnlyList chai if (slot.Form != evo.Form) break; - if (!slot.IsLevelWithinRange(evo.MinLevel, evo.Level)) + if (slot.LevelMin > evo.Level) break; yield return slot; diff --git a/PKHeX.Core/Legality/Areas/EncounterArea32.cs b/PKHeX.Core/Legality/Areas/EncounterArea32.cs deleted file mode 100644 index 16d4dbdc4..000000000 --- a/PKHeX.Core/Legality/Areas/EncounterArea32.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; - -namespace PKHeX.Core -{ - /// - /// - /// Base encounter class for manually repacked areas - /// - /// - /// Encounter Data is stored in the following format: (u16 Location, n*[u16 Species/Form, u8 Min, u8 Max]), hence the 32bit name - /// - public abstract class EncounterArea32 : EncounterArea - { - /// - /// Gets an array of areas from an array of raw area data - /// - /// Simplified raw format of an Area - /// Array of areas - public static A[] GetArray(byte[][] entries) - where A : EncounterArea32, new() - where S : EncounterSlot, new() - { - var data = new A[entries.Length]; - for (int i = 0; i < data.Length; i++) - { - var loc = data[i] = new A(); - loc.LoadSlots(entries[i]); - } - return data; - } - - private void LoadSlots(byte[] areaData) where S : EncounterSlot, new() - { - var count = (areaData.Length - 2) / 4; - Location = BitConverter.ToUInt16(areaData, 0); - Slots = new EncounterSlot[count]; - for (int i = 0; i < Slots.Length; i++) - { - int ofs = 2 + (i * 4); - ushort SpecForm = BitConverter.ToUInt16(areaData, ofs); - Slots[i] = new S - { - Species = SpecForm & 0x7FF, - Form = SpecForm >> 11, - LevelMin = areaData[ofs + 2], - LevelMax = areaData[ofs + 3], - }; - } - foreach (var slot in Slots) - slot.Area = this; - } - } -} \ No newline at end of file diff --git a/PKHeX.Core/Legality/Areas/EncounterArea3XD.cs b/PKHeX.Core/Legality/Areas/EncounterArea3XD.cs new file mode 100644 index 000000000..5928a76c2 --- /dev/null +++ b/PKHeX.Core/Legality/Areas/EncounterArea3XD.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; + +namespace PKHeX.Core +{ + /// + /// + /// encounter area + /// + public sealed class EncounterArea3XD : EncounterArea + { + public EncounterArea3XD(int loc, int s0, int l0, int s1, int l1, int s2, int l2) + { + Location = loc; + Type = SlotType.Grass; + Slots = new[] + { + new EncounterSlot3PokeSpot(this, s0, 10, l0, 0), + new EncounterSlot3PokeSpot(this, s1, 10, l1, 1), + new EncounterSlot3PokeSpot(this, s2, 10, l2, 2), + }; + } + + public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) + { + if (pkm.Format != 3) // Met Location and Met Level are changed on PK3->PK4 + return GetSlotsFuzzy(chain); + if (pkm.Met_Location != Location) + return Array.Empty(); + return GetSlotsMatching(chain, pkm.Met_Level); + } + + private IEnumerable GetSlotsMatching(IReadOnlyList chain, int lvl) + { + foreach (var slot in Slots) + { + foreach (var evo in chain) + { + if (slot.Species != evo.Species) + continue; + + if (slot.Form != evo.Form) + break; + if (!slot.IsLevelWithinRange(lvl)) + break; + + yield return slot; + break; + } + } + } + + private IEnumerable GetSlotsFuzzy(IReadOnlyList chain) + { + foreach (var slot in Slots) + { + foreach (var evo in chain) + { + if (slot.Species != evo.Species) + continue; + + if (slot.Form != evo.Form) + break; + if (slot.LevelMin > evo.Level) + break; + + yield return slot; + break; + } + } + } + } +} diff --git a/PKHeX.Core/Legality/Areas/EncounterArea4.cs b/PKHeX.Core/Legality/Areas/EncounterArea4.cs index c34d993c9..40b1ce76b 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea4.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea4.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace PKHeX.Core { @@ -8,57 +7,54 @@ namespace PKHeX.Core /// /// encounter area /// - public abstract class EncounterArea4 : EncounterArea + public sealed class EncounterArea4 : EncounterArea { - /// - /// Reads the GBA Pak Special slots, cloning data from the area's base encounter slots. - /// - /// - /// These special slots only contain the info of species id; the level is copied from the corresponding index. - /// - /// Encounter binary data - /// Offset to read from - /// DP/Pt slotSize = 4 bytes/entry, HG/SS slotSize = 2 bytes/entry - /// Slots from regular encounter table that end up replaced by in-game conditions - /// Slot indexes to replace with read species IDs - /// Slot type of the special encounter - protected static List GetSlots4GrassSlotReplace(byte[] data, int ofs, int slotSize, EncounterSlot[] ReplacedSlots, int[] slotnums, SlotType t = SlotType.Grass) - { - var slots = new List(); + public readonly EncounterType TypeEncounter; + public readonly int Rate; - int numslots = slotnums.Length; - for (int i = 0; i < numslots; i++) + public static EncounterArea4[] GetAreas(byte[][] input, GameVersion game) + { + var result = new EncounterArea4[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea4(input[i], game); + return result; + } + + private EncounterArea4(byte[] data, GameVersion game) + { + Location = data[0] | (data[1] << 8); + Type = (SlotType)data[2]; + Rate = data[3]; + TypeEncounter = (EncounterType) BitConverter.ToUInt16(data, 4); + + Slots = ReadRegularSlots(data, game); + } + + private EncounterSlot4[] ReadRegularSlots(byte[] data, GameVersion game) + { + const int size = 10; + int count = (data.Length - 6) / size; + var slots = new EncounterSlot4[count]; + for (int i = 0; i < slots.Length; i++) { - var baseSlot = ReplacedSlots[slotnums[i]]; - if (baseSlot.LevelMin <= 0) - continue; + int offset = 6 + (size * i); - int species = BitConverter.ToUInt16(data, ofs + (i / (4 / slotSize) * slotSize)); - if (species <= 0 || baseSlot.Species == species) // Empty or duplicate - continue; + int species = BitConverter.ToUInt16(data, offset + 0); + int form = data[offset + 2]; + int slotNum = data[offset + 3]; + int min = data[offset + 4]; + int max = data[offset + 5]; - var slot = (EncounterSlot4)baseSlot.Clone(); - slot.Species = species; - slot.Type = t; - slot.SlotNumber = i; - slots.Add(slot); + int mpi = data[offset + 6]; + int mpc = data[offset + 7]; + int sti = data[offset + 8]; + int stc = data[offset + 9]; + slots[i] = new EncounterSlot4(this, species, form, min, max, slotNum, mpi, mpc, sti, stc, game); } + return slots; } - protected static IEnumerable MarkStaticMagnetExtras(IEnumerable>> product) - { - var trackPermute = new List(); - foreach (var p in product) - MarkStaticMagnetPermute(p.SelectMany(z => z), trackPermute); - return trackPermute; - } - - protected static void MarkStaticMagnetPermute(IEnumerable grp, List trackPermute) - { - EncounterUtil.MarkEncountersStaticMagnetPullPermutation(grp, PersonalTable.HGSS, trackPermute); - } - public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) { if (pkm.Format != 4) // Met Location and Met Level are changed on PK4->PK5 @@ -77,7 +73,7 @@ private IEnumerable GetSlotsMatching(IReadOnlyList c if (slot.Species != evo.Species) continue; - if (slot.Form != evo.Form && !Legal.WildChangeFormAfter.Contains(slot.Species)) + if (slot.Form != evo.Form && !Legal.WildChangeFormAfter.Contains(slot.Species) && slot.Species != (int)Species.Unown) break; if (!slot.IsLevelWithinRange(lvl)) break; @@ -97,9 +93,9 @@ private IEnumerable GetSlotsFuzzy(IReadOnlyList chai if (slot.Species != evo.Species) continue; - if (slot.Form != evo.Form && !Legal.WildChangeFormAfter.Contains(slot.Species)) + if (slot.Form != evo.Form && !Legal.WildChangeFormAfter.Contains(slot.Species) && slot.Species != (int)Species.Unown) break; - if (!slot.IsLevelWithinRange(evo.MinLevel, evo.Level)) + if (slot.LevelMin > evo.Level) break; yield return slot; diff --git a/PKHeX.Core/Legality/Areas/EncounterArea4DPPt.cs b/PKHeX.Core/Legality/Areas/EncounterArea4DPPt.cs deleted file mode 100644 index 145a7df28..000000000 --- a/PKHeX.Core/Legality/Areas/EncounterArea4DPPt.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace PKHeX.Core -{ - /// - /// - /// encounter area - /// - public sealed class EncounterArea4DPPt : EncounterArea4 - { - /// - /// Gets the encounter areas with information from Generation 4 Diamond, Pearl and Platinum data. - /// - /// Raw data, one byte array per encounter area - /// Platinum flag (for Trophy Garden slot insertion) - /// Array of encounter areas. - public static EncounterArea4DPPt[] GetArray4DPPt(byte[][] entries, bool pt = false) - { - return entries.Select(z => GetArea4DPPt(z, pt)).Where(Area => Area.Slots.Length != 0).ToArray(); - } - - private static EncounterSlot4[] GetSlots4GrassDPPt(byte[] data, int ofs, int numslots, SlotType t) - { - var slots = new EncounterSlot4[numslots]; - - for (int i = 0; i < numslots; i++) - { - int o = ofs + (i * 8); - int level = data[o]; - int species = BitConverter.ToInt32(data, o + 4); - slots[i] = new EncounterSlot4 - { - LevelMax = level, - LevelMin = level, - Species = species, - SlotNumber = i, - Type = t - }; - } - return slots; - } - - private static IEnumerable GetSlots4WaterFishingDPPt(byte[] data, int ofs, int numslots, SlotType t) - { - var slots = new List(); - for (int i = 0; i < numslots; i++) - { - // max, min, unused, unused, [32bit species] - int Species = BitConverter.ToInt32(data, ofs + 4 + (i * 8)); - if (Species <= 0) - continue; - // Fishing and Surf slots without a species ID are not added - // DPPt does not have fishing or surf swarms, and does not have any Rock Smash encounters. - slots.Add(new EncounterSlot4 - { - LevelMax = data[ofs + 0 + (i * 8)], - LevelMin = data[ofs + 1 + (i * 8)], - Species = Species, - SlotNumber = i, - Type = t - }); - } - EncounterUtil.MarkEncountersStaticMagnetPull(slots, PersonalTable.HGSS); - return slots; - } - - private static EncounterArea4DPPt GetArea4DPPt(byte[] data, bool pt = false) - { - var Slots = new List(); - - int location = BitConverter.ToUInt16(data, 0x00); - var GrassRatio = BitConverter.ToInt32(data, 0x02); - if (GrassRatio > 0) - { - var GrassSlots = GetSlots4GrassDPPt(data, 0x06, 12, SlotType.Grass); - //Swarming slots replace slots 0 and 1 - var swarm = GetSlots4GrassSlotReplace(data, 0x66, 4, GrassSlots, Legal.Slot4_Swarm, SlotType.Swarm); - //Morning and Night slots replace slots 2 and 3 - var morning = GetSlots4GrassSlotReplace(data, 0x6E, 4, GrassSlots, Legal.Slot4_Time); // Morning - var night = GetSlots4GrassSlotReplace(data, 0x76, 4, GrassSlots, Legal.Slot4_Time); // Night - //Pokéradar slots replace slots 4,5,10 and 11 - //Pokéradar is marked with different slot type because it have different PID-IV generationn - var radar = GetSlots4GrassSlotReplace(data, 0x7E, 4, GrassSlots, Legal.Slot4_Radar, SlotType.Pokeradar); - - //24 bytes padding - - //Dual Slots replace slots 8 and 9 - var ruby = GetSlots4GrassSlotReplace(data, 0xA6, 4, GrassSlots, Legal.Slot4_Dual); // Ruby - var sapphire = GetSlots4GrassSlotReplace(data, 0xAE, 4, GrassSlots, Legal.Slot4_Dual); // Sapphire - var emerald = GetSlots4GrassSlotReplace(data, 0xB6, 4, GrassSlots, Legal.Slot4_Dual); // Emerald - var firered = GetSlots4GrassSlotReplace(data, 0xBE, 4, GrassSlots, Legal.Slot4_Dual); // FireRed - var leafgreen = GetSlots4GrassSlotReplace(data, 0xC6, 4, GrassSlots, Legal.Slot4_Dual); // LeafGreen - - Slots.AddRange(GrassSlots); - Slots.AddRange(swarm); - Slots.AddRange(morning); - Slots.AddRange(night); - Slots.AddRange(radar); - Slots.AddRange(ruby); - Slots.AddRange(sapphire); - Slots.AddRange(emerald); - Slots.AddRange(firered); - Slots.AddRange(leafgreen); - - // Permute Static-Magnet Pull combinations - // [None/Swarm]-[None/Morning/Night]-[None/Radar]-[None/R/S/E/F/L] [None/TrophyGarden] - // 2 * 3 * 2 * 6 = 72 different combinations of slots (more with trophy garden) - var regular = new List> { GrassSlots.Where(z => z.SlotNumber == 6 || z.SlotNumber == 7).ToList() }; // every other slot is in the product - var pair0 = new List> { GrassSlots.Where(z => Legal.Slot4_Swarm.Contains(z.SlotNumber)).ToList() }; - var pair1 = new List> { GrassSlots.Where(z => Legal.Slot4_Time.Contains(z.SlotNumber)).ToList() }; - var pair2 = new List> { GrassSlots.Where(z => Legal.Slot4_Radar.Contains(z.SlotNumber)).ToList() }; - var pair3 = new List> { GrassSlots.Where(z => Legal.Slot4_Dual.Contains(z.SlotNumber)).ToList() }; - if (swarm.Count != 0) pair0.Add(swarm); - if (morning.Count != 0) pair1.Add(morning); if (night.Count != 0) pair1.Add(night); - if (radar.Count != 0) pair2.Add(radar); - if (ruby.Count != 0) pair3.Add(ruby); if (sapphire.Count != 0) pair3.Add(sapphire); if (emerald.Count != 0) pair3.Add(emerald); - if (firered.Count != 0) pair3.Add(firered); if (leafgreen.Count != 0) pair3.Add(leafgreen); - if (location == 68) // Trophy Garden - { - // Occupy Slots 6 & 7 - var species = pt ? Encounters4.TrophyPt : Encounters4.TrophyDP; - var slots = new List(); - foreach (var s in species) - { - var slot = (EncounterSlot4)regular[0][0].Clone(); - slot.Species = s; - slots.Add(slot); - - slot = (EncounterSlot4)regular[0][1].Clone(); - slot.Species = s; - slots.Add(slot); - } - Slots.AddRange(slots); - // get all permutations of trophy inhabitants - var trophy = regular[0].Concat(slots).ToArray(); - for (int i = 0; i < trophy.Length; i++) - { - for (int j = i + 1; j < trophy.Length; j++) - regular.Add(new List { trophy[i], trophy[j] }); - } - } - - var set = new[] { regular, pair0, pair1, pair2, pair3 }; - var product = set.CartesianProduct(); - var extra = MarkStaticMagnetExtras(product); - Slots.AddRange(extra); - } - - var SurfRatio = BitConverter.ToInt32(data, 0xCE); - if (SurfRatio > 0) - Slots.AddRange(GetSlots4WaterFishingDPPt(data, 0xD2, 5, SlotType.Surf)); - - //44 bytes padding - - var OldRodRatio = BitConverter.ToInt32(data, 0x126); - if (OldRodRatio > 0) - Slots.AddRange(GetSlots4WaterFishingDPPt(data, 0x12A, 5, SlotType.Old_Rod)); - - var GoodRodRatio = BitConverter.ToInt32(data, 0x152); - if (GoodRodRatio > 0) - Slots.AddRange(GetSlots4WaterFishingDPPt(data, 0x156, 5, SlotType.Good_Rod)); - - var SuperRodRatio = BitConverter.ToInt32(data, 0x17E); - if (SuperRodRatio > 0) - Slots.AddRange(GetSlots4WaterFishingDPPt(data, 0x182, 5, SlotType.Super_Rod)); - - var Area4 = new EncounterArea4DPPt - { - Location = location, - Slots = Slots.ToArray() - }; - foreach (var slot in Area4.Slots) - slot.Area = Area4; - - return Area4; - } - - private EncounterArea4DPPt Clone(int location) => new EncounterArea4DPPt { Slots = Slots, Location = location}; - - public EncounterArea4DPPt[] Clone(int[] locations) - { - var Areas = new EncounterArea4DPPt[locations.Length]; - for (int i = 0; i < locations.Length; i++) - Areas[i] = Clone(locations[i]); - return Areas; - } - } - - public static class DPEncounterExtensions - { - public static IEnumerable> CartesianProduct(this IEnumerable> sequences) - { - IEnumerable> emptyProduct = new[] { Enumerable.Empty() }; - return sequences.Aggregate( - emptyProduct, - (accumulator, sequence) => - from accseq in accumulator - from item in sequence - select accseq.Concat(new[] { item })); - } - } -} \ No newline at end of file diff --git a/PKHeX.Core/Legality/Areas/EncounterArea4HGSS.cs b/PKHeX.Core/Legality/Areas/EncounterArea4HGSS.cs deleted file mode 100644 index 207b59f3f..000000000 --- a/PKHeX.Core/Legality/Areas/EncounterArea4HGSS.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace PKHeX.Core -{ - /// - /// - /// encounter area - /// - public sealed class EncounterArea4HGSS : EncounterArea4 - { - /// - /// Gets the encounter areas with information from Generation 4 Heart Gold and Soul Silver data. - /// - /// Raw data, one byte array per encounter area - /// Array of encounter areas. - public static EncounterArea4HGSS[] GetArray4HGSS(byte[][] entries) - { - return entries.Select(GetArea4HGSS).Where(Area => Area.Slots.Length != 0).ToArray(); - } - - /// - /// Gets the encounter areas with information from Generation 4 Heart Gold and Soul Silver Headbutt tree data. - /// - /// Raw data, one byte array per encounter area - /// Array of encounter areas. - public static EncounterArea4HGSS[] GetArray4HGSS_Headbutt(byte[][] entries) - { - return entries.Select(GetArea4HeadbuttHGSS).Where(Area => Area.Slots.Length != 0).ToArray(); - } - - private static EncounterSlot4[] GetSlots4GrassHGSS(byte[] data, int ofs, int numslots, SlotType t) - { - var slots = new EncounterSlot4[numslots * 3]; - // First 36 slots are morning, day and night grass slots - // The order is 12 level values, 12 morning species, 12 day species and 12 night species - for (int i = 0; i < numslots; i++) - { - int level = data[ofs + i]; - int species = BitConverter.ToUInt16(data, ofs + numslots + (i * 2)); - slots[i] = new EncounterSlot4 - { - LevelMin = level, - LevelMax = level, - Species = species, - SlotNumber = i, - Type = t - }; - slots[numslots + i] = (EncounterSlot4)slots[i].Clone(); - slots[numslots + i].Species = BitConverter.ToUInt16(data, ofs + (numslots * 3) + (i * 2)); - slots[numslots + i].Type = t; - slots[(numslots * 2) + i] = (EncounterSlot4)slots[i].Clone(); - slots[(numslots * 2) + i].Species = BitConverter.ToUInt16(data, ofs + (numslots * 5) + (i * 2)); - slots[(numslots * 2) + i].Type = t; - } - - return slots; - } - - private static IEnumerable GetSlots4WaterFishingHGSS(byte[] data, int ofs, int numslots, SlotType t) - { - var slots = new List(); - for (int i = 0; i < numslots; i++) - { - // min, max, [16bit species] - int Species = BitConverter.ToInt16(data, ofs + 2 + (i * 4)); - if (t == SlotType.Rock_Smash && Species <= 0) - continue; - // Fishing and surf Slots without a species ID are added too; these are needed for the swarm encounters. - // These empty slots will will be deleted after we add swarm slots. - - slots.Add(new EncounterSlot4 - { - LevelMin = data[ofs + 0 + (i * 4)], - LevelMax = data[ofs + 1 + (i * 4)], - Species = Species, - SlotNumber = i, - Type = t - }); - } - EncounterUtil.MarkEncountersStaticMagnetPull(slots, PersonalTable.HGSS); - return slots; - } - - private static EncounterArea4HGSS GetArea4HGSS(byte[] data) - { - var Slots = new List(); - - var GrassRatio = data[0x02]; - var SurfRatio = data[0x03]; - var RockSmashRatio = data[0x04]; - var OldRodRatio = data[0x05]; - var GoodRodRatio = data[0x06]; - var SuperRodRatio = data[0x07]; - // 2 bytes padding - - if (GrassRatio > 0) - { - // First 36 slots are morning, day and night grass slots - // The order is 12 level values, 12 morning species, 12 day species and 12 night species - var GrassSlots = GetSlots4GrassHGSS(data, 0x0A, 12, SlotType.Grass); - //Grass slots with species = 0 are added too, it is needed for the swarm encounters, it will be deleted after swarms are added - - // Hoenn Sound and Sinnoh Sound replace slots 4 and 5 - var hoenn = GetSlots4GrassSlotReplace(data, 0x5E, 2, GrassSlots, Legal.Slot4_Sound); // Hoenn - var sinnoh = GetSlots4GrassSlotReplace(data, 0x62, 2, GrassSlots, Legal.Slot4_Sound); // Sinnoh - - Slots.AddRange(GrassSlots); - Slots.AddRange(hoenn); - Slots.AddRange(sinnoh); - - // Static / Magnet Pull - var grass1 = GrassSlots.Take(12).ToList(); - var grass2 = GrassSlots.Skip(12).Take(12).ToList(); - var grass3 = GrassSlots.Skip(24).ToList(); - // Swarm slots do not displace electric/steel types, with exception of SoulSilver Mawile (which doesn't displace) -- handle separately - - foreach (var time in new[] { grass1, grass2, grass3 }) - { - // non radio - var regular = time.Where(z => !Legal.Slot4_Sound.Contains(z.SlotNumber)).ToList(); // every other slot is in the product - var radio = new List> { time.Where(z => Legal.Slot4_Sound.Contains(z.SlotNumber)).ToList() }; - if (hoenn.Count > 0) - radio.Add(hoenn); - if (sinnoh.Count > 0) - radio.Add(sinnoh); - - var extra = new List(); - foreach (var t in radio) - MarkStaticMagnetPermute(regular.Concat(t), extra); - Slots.AddRange(extra); - } - } - - if (SurfRatio > 0) - Slots.AddRange(GetSlots4WaterFishingHGSS(data, 0x66, 5, SlotType.Surf)); - - if (RockSmashRatio > 0) - Slots.AddRange(GetSlots4WaterFishingHGSS(data, 0x7A, 2, SlotType.Rock_Smash)); - - if (OldRodRatio > 0) - Slots.AddRange(GetSlots4WaterFishingHGSS(data, 0x82, 5, SlotType.Old_Rod)); - - if (GoodRodRatio > 0) - Slots.AddRange(GetSlots4WaterFishingHGSS(data, 0x96, 5, SlotType.Good_Rod)); - - if (SuperRodRatio > 0) - Slots.AddRange(GetSlots4WaterFishingHGSS(data, 0xAA, 5, SlotType.Super_Rod)); - - // Last 6 bytes only have species ID info - if (data[0xC2] == 120) // Location = 182, 127, 130, 132, 167, 188, 210 - Slots.AddRange(SlotsHGSS_Staryu); - - var Area4 = new EncounterArea4HGSS - { - Location = BitConverter.ToUInt16(data, 0x00), - Slots = Slots.ToArray() - }; - foreach (var slot in Area4.Slots) - slot.Area = Area4; - return Area4; - } - - private static readonly EncounterSlot4[] SlotsHGSS_Staryu = - { - new EncounterSlot4 { Species = 120, LevelMin = 20, LevelMax = 20, Type = SlotType.Good_Rod }, - new EncounterSlot4 { Species = 120, LevelMin = 40, LevelMax = 40, Type = SlotType.Super_Rod }, - }; - - private static EncounterArea4HGSS GetArea4HeadbuttHGSS(byte[] data) - { - if (data.Length < 78) - return new EncounterArea4HGSS(); // bad data - - //2 byte location ID (defer to end) - //4 bytes padding - var Slots = new List(); - - // 00-11 Normal trees - // 12-17 Special trees - for (int i = 0; i < 18; i++) - { - int Species = BitConverter.ToInt16(data, 6 + (i * 4)); - if (Species <= 0) - continue; - Slots.Add(new EncounterSlot4 - { - Species = Species, - LevelMin = data[8 + (i * 4)], - LevelMax = data[9 + (i * 4)], - Type = i <= 11 ? SlotType.Headbutt : SlotType.Headbutt_Special - }); - } - - var Area = new EncounterArea4HGSS - { - Location = BitConverter.ToUInt16(data, 0), - Slots = Slots.ToArray() - }; - foreach (var slot in Area.Slots) - slot.Area = Area; - return Area; - } - } -} \ No newline at end of file diff --git a/PKHeX.Core/Legality/Areas/EncounterArea5.cs b/PKHeX.Core/Legality/Areas/EncounterArea5.cs index 6d828c5d0..6b6395ba9 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea5.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea5.cs @@ -1,10 +1,68 @@ -namespace PKHeX.Core +using System; +using System.Collections.Generic; + +namespace PKHeX.Core { /// /// /// encounter area /// - public sealed class EncounterArea5 : EncounterArea32 + public sealed class EncounterArea5 : EncounterArea { + public static EncounterArea5[] GetAreas(byte[][] input, GameVersion game) + { + var result = new EncounterArea5[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea5(input[i], game); + return result; + } + + private EncounterArea5(byte[] data, GameVersion game) + { + Location = data[0] | (data[1] << 8); + Type = (SlotType)data[2]; + + Slots = ReadSlots(data, game); + } + + private EncounterSlot5[] ReadSlots(byte[] data, GameVersion game) + { + const int size = 4; + int count = (data.Length - 4) / size; + var slots = new EncounterSlot5[count]; + for (int i = 0; i < slots.Length; i++) + { + int offset = 4 + (size * i); + ushort SpecForm = BitConverter.ToUInt16(data, offset); + int species = SpecForm & 0x3FF; + int form = SpecForm >> 11; + int min = data[offset + 2]; + int max = data[offset + 3]; + slots[i] = new EncounterSlot5(this, species, form, min, max, game); + } + + return slots; + } + + public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) + { + foreach (var slot 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 && !Legal.WildChangeFormAfter.Contains(slot.Species)) + break; + + yield return slot; + break; + } + } + } } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs b/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs index 282ea710d..5841a7c90 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace PKHeX.Core { @@ -6,8 +7,43 @@ namespace PKHeX.Core /// /// encounter area /// - public sealed class EncounterArea6AO : EncounterArea32 + public sealed class EncounterArea6AO : EncounterArea { + public static EncounterArea6AO[] GetAreas(byte[][] input, GameVersion game) + { + var result = new EncounterArea6AO[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea6AO(input[i], game); + return result; + } + + private EncounterArea6AO(byte[] data, GameVersion game) + { + Location = data[0] | (data[1] << 8); + Type = (SlotType)data[2]; + + Slots = ReadSlots(data, game); + } + + private EncounterSlot6AO[] ReadSlots(byte[] data, GameVersion game) + { + const int size = 4; + int count = (data.Length - 4) / size; + var slots = new EncounterSlot6AO[count]; + for (int i = 0; i < slots.Length; i++) + { + int offset = 4 + (size * i); + ushort SpecForm = BitConverter.ToUInt16(data, offset); + int species = SpecForm & 0x3FF; + int form = SpecForm >> 11; + int min = data[offset + 2]; + int max = data[offset + 3]; + slots[i] = new EncounterSlot6AO(this, species, form, min, max, game); + } + + return slots; + } + private const int FluteBoostMin = 4; // White Flute decreases levels. private const int FluteBoostMax = 4; // Black Flute increases levels. private const int DexNavBoost = 30; // Maximum DexNav chain @@ -23,7 +59,7 @@ public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyLi if (slot.Species != evo.Species) continue; - var boostMax = slot.Type != SlotType.Rock_Smash ? DexNavBoost : FluteBoostMax; + var boostMax = Type != SlotType.Rock_Smash ? DexNavBoost : FluteBoostMax; const int boostMin = FluteBoostMin; if (!slot.IsLevelWithinRange(pkm.Met_Level, boostMin, boostMax)) break; @@ -41,14 +77,17 @@ public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyLi private static void MarkSlotDetails(PKM pkm, EncounterSlot6AO slot, EvoCriteria evo) { - bool nav = slot.AllowDexNav && (pkm.RelearnMove1 != 0 || pkm.AbilityNumber == 4); - slot.DexNav = nav; - if (slot.LevelMin > evo.MinLevel) slot.WhiteFlute = true; if (slot.LevelMax + 1 <= evo.MinLevel && evo.MinLevel <= slot.LevelMax + FluteBoostMax) slot.BlackFlute = true; - if (slot.LevelMax != evo.MinLevel && slot.AllowDexNav) + + if (!slot.CanDexNav) + return; + + if (slot.LevelMax != evo.MinLevel) + slot.DexNav = true; + if (pkm.RelearnMove1 != 0 || pkm.AbilityNumber == 4) slot.DexNav = true; } } diff --git a/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs b/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs index 7a7b553e2..708f20470 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace PKHeX.Core { @@ -6,8 +7,55 @@ namespace PKHeX.Core /// /// encounter area /// - public sealed class EncounterArea6XY : EncounterArea32 + public sealed class EncounterArea6XY : EncounterArea { + public static EncounterArea6XY[] GetAreas(byte[][] input, GameVersion game) + { + var result = new EncounterArea6XY[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea6XY(input[i], game); + return result; + } + + public EncounterArea6XY(ICollection species) + { + Location = 148; + Type = SlotType.FriendSafari; + + var slots = new EncounterSlot6XY[species.Count]; + int ctr = 0; + foreach (var s in species) + slots[ctr++] = new EncounterSlot6XY(this, s, 0, 30, 30, GameVersion.XY); + Slots = slots; + } + + private EncounterArea6XY(byte[] data, GameVersion game) + { + Location = data[0] | (data[1] << 8); + Type = (SlotType)data[2]; + + Slots = ReadSlots(data, game); + } + + private EncounterSlot6XY[] ReadSlots(byte[] data, GameVersion game) + { + const int size = 4; + int count = (data.Length - 4) / size; + var slots = new EncounterSlot6XY[count]; + for (int i = 0; i < slots.Length; i++) + { + int offset = 4 + (size * i); + ushort SpecForm = BitConverter.ToUInt16(data, offset); + int species = SpecForm & 0x3FF; + int form = SpecForm >> 11; + int min = data[offset + 2]; + int max = data[offset + 3]; + slots[i] = new EncounterSlot6XY(this, species, form, min, max, game); + } + + return slots; + } + private const int RandomForm = 31; private const int RandomFormVivillon = RandomForm - 1; diff --git a/PKHeX.Core/Legality/Areas/EncounterArea6XYFriendSafari.cs b/PKHeX.Core/Legality/Areas/EncounterArea6XYFriendSafari.cs deleted file mode 100644 index 29bef434a..000000000 --- a/PKHeX.Core/Legality/Areas/EncounterArea6XYFriendSafari.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace PKHeX.Core -{ - public class EncounterArea6XYFriendSafari : EncounterArea - { - public static bool WasFriendSafari(PKM pkm) - { - if (!pkm.XY) - return false; - if (pkm.Met_Location != 148) - return false; - if (pkm.Met_Level != 30) - return false; - if (pkm.Egg_Location != 0) - return false; - return true; - } - - public static ILookup GetArea() - { - var area = new EncounterArea6XYFriendSafari { Location = 148 }; - EncounterSlot6XY FriendSafariSlot(int d) - { - return new EncounterSlot6XY - { - Area = area, - Species = d, - LevelMin = 30, - LevelMax = 30, - Form = 0, - Type = SlotType.FriendSafari, - Version = GameVersion.XY, - }; - } - area.Slots = Legal.FriendSafari.Select(FriendSafariSlot).ToArray(); - return area.Slots.Cast().ToLookup(s => s.Species); - } - - public static IEnumerable GetValidSafariEncounters(PKM pkm) - { - var chain = EvolutionChain.GetValidPreEvolutions(pkm); - return GetValidSafariEncounters(chain); - } - - public static IEnumerable GetValidSafariEncounters(IReadOnlyList chain) - { - var valid = chain.Where(d => d.Level >= 30); - return valid.SelectMany(z => Encounters6.FriendSafari[z.Species]); - } - } -} \ No newline at end of file diff --git a/PKHeX.Core/Legality/Areas/EncounterArea7.cs b/PKHeX.Core/Legality/Areas/EncounterArea7.cs index 24654e5fa..99b2a96ca 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea7.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea7.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace PKHeX.Core { @@ -6,8 +7,43 @@ namespace PKHeX.Core /// /// encounter area /// - public sealed class EncounterArea7 : EncounterArea32 + public sealed class EncounterArea7 : EncounterArea { + public static EncounterArea7[] GetAreas(byte[][] input, GameVersion game) + { + var result = new EncounterArea7[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea7(input[i], game); + return result; + } + + private EncounterArea7(byte[] data, GameVersion game) + { + Location = data[0] | (data[1] << 8); + Type = (SlotType)data[2]; + + Slots = ReadSlots(data, game); + } + + private EncounterSlot7[] ReadSlots(byte[] data, GameVersion game) + { + const int size = 4; + int count = (data.Length - 4) / size; + var slots = new EncounterSlot7[count]; + for (int i = 0; i < slots.Length; i++) + { + int offset = 4 + (size * i); + ushort SpecForm = BitConverter.ToUInt16(data, offset); + int species = SpecForm & 0x3FF; + int form = SpecForm >> 11; + int min = data[offset + 2]; + int max = data[offset + 3]; + slots[i] = new EncounterSlot7(this, species, form, min, max, game); + } + + return slots; + } + public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) { foreach (var slot in Slots) diff --git a/PKHeX.Core/Legality/Areas/EncounterArea7b.cs b/PKHeX.Core/Legality/Areas/EncounterArea7b.cs index edfd0431d..aaabe4756 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea7b.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea7b.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace PKHeX.Core { @@ -6,8 +7,40 @@ namespace PKHeX.Core /// /// encounter area /// - public sealed class EncounterArea7b : EncounterArea32 + public sealed class EncounterArea7b : EncounterArea { + public static EncounterArea7b[] GetAreas(byte[][] input, GameVersion game) + { + var result = new EncounterArea7b[input.Length]; + for (int i = 0; i < input.Length; i++) + result[i] = new EncounterArea7b(input[i], game); + return result; + } + + private EncounterArea7b(byte[] data, GameVersion game) + { + Location = data[0] | (data[1] << 8); + Slots = ReadSlots(data, game); + } + + private EncounterSlot7b[] ReadSlots(byte[] data, GameVersion game) + { + const int size = 4; + int count = (data.Length - 2) / size; + var slots = new EncounterSlot7b[count]; + for (int i = 0; i < slots.Length; i++) + { + int offset = 2 + (size * i); + ushort SpecForm = BitConverter.ToUInt16(data, offset); + int species = SpecForm & 0x3FF; + int min = data[offset + 2]; + int max = data[offset + 3]; + slots[i] = new EncounterSlot7b(this, species, min, max, game); + } + + return slots; + } + private const int CatchComboBonus = 1; public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) diff --git a/PKHeX.Core/Legality/Areas/EncounterArea7g.cs b/PKHeX.Core/Legality/Areas/EncounterArea7g.cs index c2787fbc2..d9b450986 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea7g.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea7g.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace PKHeX.Core { @@ -6,8 +7,56 @@ namespace PKHeX.Core /// /// encounter area for /// - public sealed class EncounterArea7g : EncounterArea32 + public sealed class EncounterArea7g : EncounterArea { + internal static EncounterArea7g[] GetArea() + { + var area = new EncounterArea7g { Location = 50, Type = SlotType.GoPark }; + static EncounterSlot GetSlot(EncounterArea7g area, int species, int form) + { + return new EncounterSlot7GO(area, species, form, 1, 40, GameVersion.GO); + } + + var obtainable = Enumerable.Range(1, 150).Concat(Enumerable.Range(808, 2)); // count : 152 + var AlolanKanto = new byte[] + { + // Level 1+ + 019, // Rattata + 020, // Raticate + 027, // Sandshrew + 028, // Sandslash + 037, // Vulpix + 038, // Ninetales + 050, // Diglett + 051, // Dugtrio + 052, // Meowth + 053, // Persian + 074, // Geodude + 075, // Graveler + 076, // Golem + 088, // Grimer + 089, // Muk + 103, // Exeggutor + 105, // Marowak + + // Level 15+ + 026, // Raichu + }; + + var regular = obtainable.Select(z => GetSlot(area, z, 0)); + var alolan = AlolanKanto.Select(z => GetSlot(area, z, 1)); + var slots = regular.Concat(alolan).ToArray(); + + slots[slots.Length - 1].LevelMin = 15; // Raichu + slots[(int)Species.Mewtwo - 1].LevelMin = 15; + slots[(int)Species.Articuno - 1].LevelMin = 15; + slots[(int)Species.Zapdos - 1].LevelMin = 15; + slots[(int)Species.Moltres - 1].LevelMin = 15; + + area.Slots = slots; + return new[] { area }; + } + public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) { foreach (var slot in Slots) diff --git a/PKHeX.Core/Legality/Areas/EncounterArea8.cs b/PKHeX.Core/Legality/Areas/EncounterArea8.cs index addd31880..1c5c5221d 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea8.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea8.cs @@ -198,19 +198,20 @@ public abstract class EncounterAreaSH : EncounterArea /// Gets an array of areas from an array of raw area data /// /// Simplified raw format of an Area + /// Game of origin /// Array of areas - public static T[] GetArray(byte[][] entries) where T : EncounterAreaSH, new() + public static T[] GetArray(byte[][] entries, GameVersion game) where T : EncounterAreaSH, new() { T[] data = new T[entries.Length]; for (int i = 0; i < data.Length; i++) { var loc = data[i] = new T(); - loc.LoadSlots(entries[i]); + loc.LoadSlots(entries[i], game); } return data; } - private void LoadSlots(byte[] areaData) + private void LoadSlots(byte[] areaData, GameVersion game) { Location = areaData[0]; Slots = new EncounterSlot[areaData[1]]; @@ -228,11 +229,9 @@ private void LoadSlots(byte[] areaData) for (int i = 0; i < count; i++, ctr++, ofs += 2) { var specForm = BitConverter.ToUInt16(areaData, ofs); - Slots[ctr] = new EncounterSlot8(specForm, min, max, flags); + Slots[ctr] = new EncounterSlot8(this, specForm, min, max, flags, game); } } while (ctr != Slots.Length); - foreach (var slot in Slots) - slot.Area = this; } } @@ -271,7 +270,7 @@ public sealed class EncounterSlot8 : EncounterSlot public override string LongName => Weather == AreaWeather8.All ? wild : $"{wild} - {Weather.ToString().Replace("_", string.Empty)}"; public override int Generation => 8; - public EncounterSlot8(int specForm, int min, int max, AreaWeather8 weather) + public EncounterSlot8(EncounterAreaSH area, int specForm, int min, int max, AreaWeather8 weather, GameVersion game) : base(area) { Species = specForm & 0x7FF; Form = specForm >> 11; @@ -279,6 +278,7 @@ public EncounterSlot8(int specForm, int min, int max, AreaWeather8 weather) LevelMax = max; Weather = weather; + Version = game; } } } diff --git a/PKHeX.Core/Legality/Areas/EncounterAreaFake.cs b/PKHeX.Core/Legality/Areas/EncounterAreaFake.cs deleted file mode 100644 index ed64b9cb2..000000000 --- a/PKHeX.Core/Legality/Areas/EncounterAreaFake.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace PKHeX.Core -{ - /// - /// - /// Fake encounter area used to mock data - /// - public sealed class EncounterAreaFake : EncounterArea - { - public override IEnumerable GetMatchingSlots(PKM pkm, IReadOnlyList chain) => - Array.Empty(); - } -} \ No newline at end of file diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs index 1a2d6aab0..140fc94f7 100644 --- a/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs +++ b/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs @@ -19,152 +19,6 @@ internal static class EncounterUtil return source.Where(s => s.Version.Contains(game)).ToArray(); } - /// - /// Direct fetch for data; can also be used to fetch supplementary encounter streams. - /// - /// Unpacking identification ASCII characters (first two bytes of binary) - /// Resource name (will be prefixed with "encounter_" - /// Array of encounter areas - internal static A[] GetEncounterTables(string ident, string resource) - where A : EncounterArea32, new() - where S : EncounterSlot, new() - { - byte[] mini = Util.GetBinaryResource($"encounter_{resource}.pkl"); - return EncounterArea32.GetArray(BinLinker.Unpack(mini, ident)); - } - - /// - /// Direct fetch for data; can also be used to fetch supplementary encounter streams. - /// - /// Unpacking identification ASCII characters (first two bytes of binary) - /// Resource name (will be prefixed with "encounter_") - /// Array of encounter areas - internal static T[] GetEncounterTables8(string ident, string resource) where T : EncounterAreaSH, new() - { - byte[] mini = Util.GetBinaryResource($"encounter_{resource}.pkl"); - return EncounterAreaSH.GetArray(BinLinker.Unpack(mini, ident)); - } - - /// - /// Combines slot arrays with the same . - /// - /// Input encounter areas to combine - /// Combined Array of encounter areas. No duplicate location IDs will be present. - internal static T[] AddExtraTableSlots(params T[][] tables) where T : EncounterArea, new() - { - return tables.SelectMany(s => s).GroupBy(l => l.Location) - .Select(t => t.Count() == 1 - ? t.First() // only one table, just return the area - : new T { Location = t.Key, Slots = t.SelectMany(s => s.Slots).ToArray() }) - .ToArray(); - } - - /// - /// Marks Encounter Slots for party lead's ability slot influencing. - /// - /// Magnet Pull attracts Steel type slots, and Static attracts Electric - /// Encounter Area array for game - /// Personal data for use with a given species' type - internal static void MarkEncountersStaticMagnetPull(IEnumerable areas, PersonalTable t) - where T : EncounterSlot, IMagnetStatic - { - foreach (EncounterArea area in areas) - { - foreach (var grp in area.Slots.Cast().GroupBy(z => z.Type)) - MarkEncountersStaticMagnetPull(grp, t); - } - } - - internal static void MarkEncountersStaticMagnetPull(IEnumerable grp, PersonalTable t) - where T : EncounterSlot, IMagnetStatic - { - GetStaticMagnet(t, grp, out List s, out List m); - for (var i = 0; i < s.Count; i++) - { - var slot = s[i]; - slot.StaticIndex = i; - slot.StaticCount = s.Count; - } - for (var i = 0; i < m.Count; i++) - { - var slot = m[i]; - slot.MagnetPullIndex = i; - slot.MagnetPullCount = m.Count; - } - } - - internal static void MarkEncountersStaticMagnetPullPermutation(IEnumerable grp, PersonalTable t, List permuted) - where T : EncounterSlot, IMagnetStatic, INumberedSlot - { - GetStaticMagnet(t, grp, out List s, out List m); - - // Apply static/magnet values; if any permutation has a unique slot combination, add it to the slot list. - for (int i = 0; i < s.Count; i++) - { - var slot = s[i]; - if (slot.StaticIndex >= 0) // already has unique data - { - if (slot.IsMatchStatic(i, s.Count)) - continue; // same values, no permutation - if (permuted.Any(z => z.SlotNumber == slot.SlotNumber && z.IsMatchStatic(i, s.Count) && z.Species == slot.Species)) - continue; // same values, previously permuted - - s[i] = slot = (T)slot.Clone(); - permuted.Add(slot); - } - slot.StaticIndex = i; - slot.StaticCount = s.Count; - } - for (int i = 0; i < m.Count; i++) - { - var slot = m[i]; - if (slot.MagnetPullIndex >= 0) // already has unique data - { - if (slot.IsMatchStatic(i, m.Count)) - continue; // same values, no permutation - if (permuted.Any(z => z.SlotNumber == slot.SlotNumber && z.IsMatchMagnet(i, m.Count) && z.Species == slot.Species)) - continue; // same values, previously permuted - - m[i] = slot = (T)slot.Clone(); - permuted.Add(slot); - } - slot.MagnetPullIndex = i; - slot.MagnetPullCount = m.Count; - } - } - - private static void GetStaticMagnet(PersonalTable t, IEnumerable grp, out List s, out List m) - where T : EncounterSlot, IMagnetStatic - { - const int steel = (int)MoveType.Steel; - const int electric = (int)MoveType.Electric + 1; // offset by 1 in gen3/4 for the ??? type - s = new List(); - m = new List(); - foreach (T Slot in grp) - { - var p = t[Slot.Species]; - if (p.IsType(steel)) - m.Add(Slot); - if (p.IsType(electric)) - s.Add(Slot); - } - } - - /// - /// Sets the value, for use in determining split-generation origins. - /// - /// Only used for Gen 1 & 2, as data is not present. - /// In-game encounter data - /// Version ID to set - internal static void MarkEncountersVersion(IEnumerable areas, GameVersion game) - { - foreach (EncounterArea area in areas) - { - foreach (var Slot in area.Slots) - Slot.Version = game; - } - } - /// /// Sets the value. /// @@ -182,37 +36,8 @@ private static void MarkEncountersGeneration(int generation, IEnumerable - /// Groups areas by location id, raw data has areas with different slots but the same location id. - /// - /// Similar to , this method combines a single array. - /// Ingame encounter data - internal static void ReduceAreasSize(ref T[] Areas) where T : EncounterArea, new() - { - Areas = Areas.GroupBy(a => a.Location).Select(a => new T - { - Location = a.Key, - Slots = a.SelectMany(m => m.Slots).ToArray() - }).ToArray(); - } - internal static T[] ConcatAll(params IEnumerable[] arr) => arr.SelectMany(z => z).ToArray(); - internal static void MarkEncounterAreaArray(params T[][] areas) where T : EncounterArea - { - foreach (var area in areas) - MarkEncounterAreas(area); - } - - private static void MarkEncounterAreas(params T[] areas) where T : EncounterArea - { - foreach (var area in areas) - { - foreach (var slot in area.Slots) - slot.Area = area; - } - } - internal static EncounterStatic Clone(this EncounterStatic s, int location) { var result = s.Clone(); @@ -255,11 +80,5 @@ private static EncounterStatic5 DreamRadarClone(this EncounterStatic5 s, int lev } string[] getNames(int i, IEnumerable names) => names.Select(z => z.Length > i ? z[i] : string.Empty).ToArray(); } - - internal static void MarkEncounterGame(IEnumerable table, GameVersion version) where T: IVersion, IVersionSet - { - foreach (var t in table.Where(z => ((IVersion)z).Version == GameVersion.Any)) - ((IVersionSet)t).Version = version; - } } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs index 70c121d53..f98031937 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs @@ -1,5 +1,4 @@ -using System; -using static PKHeX.Core.EncounterUtil; +using static PKHeX.Core.EncounterUtil; using static PKHeX.Core.GameVersion; namespace PKHeX.Core @@ -9,13 +8,16 @@ namespace PKHeX.Core /// internal static class Encounters1 { - internal static readonly EncounterArea1[] SlotsRBY; - internal static readonly EncounterStatic1[] StaticRBY; + private static readonly EncounterArea1[] SlotsR = Get("red", "g1", RD); + private static readonly EncounterArea1[] SlotsB = Get("blue", "g1", BU); + private static readonly EncounterArea1[] SlotsY = Get("yellow", "g1", YW); + internal static readonly EncounterArea1[] SlotsRBY = ArrayUtil.ConcatAll(SlotsR, SlotsB, SlotsY); + + private static EncounterArea1[] Get(string name, string ident, GameVersion game) => + EncounterArea1.GetAreas(BinLinker.Unpack(Util.GetBinaryResource($"encounter_{name}.pkl"), ident), game); static Encounters1() { - StaticRBY = Encounter_RBY; - SlotsRBY = GetAreas(); MarkEncountersGeneration(1, StaticRBY, TradeGift_RBY_NoTradeback, TradeGift_RBY_Tradeback); var trades = ArrayUtil.ConcatAll(TradeGift_RBY_NoTradeback, TradeGift_RBY_Tradeback); @@ -23,34 +25,7 @@ static Encounters1() t.TrainerNames = StringConverter12.G1TradeOTName; } - private static EncounterArea1[] GetAreas() - { - var red_gw = EncounterArea1.GetArray1GrassWater(Util.GetBinaryResource("encounter_red.pkl"), 248); - var blu_gw = EncounterArea1.GetArray1GrassWater(Util.GetBinaryResource("encounter_blue.pkl"), 248); - var ylw_gw = EncounterArea1.GetArray1GrassWater(Util.GetBinaryResource("encounter_yellow.pkl"), 249); - var rb_fish = EncounterArea1.GetArray1Fishing(Util.GetBinaryResource("encounter_rb_f.pkl"), 33); - var ylw_fish = EncounterArea1.GetArray1FishingYellow(Util.GetBinaryResource("encounter_yellow_f.pkl")); - - MarkEncountersVersion(red_gw, RD); - MarkEncountersVersion(blu_gw, BU); - MarkEncountersVersion(ylw_gw, YW); - MarkEncountersVersion(rb_fish, RB); - MarkEncountersVersion(ylw_fish, YW); - - var table = AddExtraTableSlots(red_gw, blu_gw, ylw_gw, rb_fish, ylw_fish); - Array.Resize(ref table, table.Length + 1); - table[table.Length - 1] = FishOldGood_RBY; - - foreach (var arr in table) - { - foreach (var slot in arr.Slots) - slot.Area = arr; - } - - return table; - } - - private static readonly EncounterStatic1[] Encounter_RBY = + internal static readonly EncounterStatic1[] StaticRBY = { // GameVersion is RBY for Pokemon with the same catch rate and initial moves in all games // If there are any differences in moves or catch rate, they will be defined as different encounters (GameVersion) @@ -187,16 +162,5 @@ private static EncounterArea1[] GetAreas() new EncounterTrade1(051, 05, RBY), // Dugtrio - Trade Lickitung (GSC 5) new EncounterTrade1(047, 05, RBY), // Parasect - Trade Tangela (GSC 5) }); - - private static readonly EncounterArea1 FishOldGood_RBY = new EncounterArea1 - { - Location = -1, - Slots = new EncounterSlot[] - { - new EncounterSlot1(129, 05, 05, -1, SlotType.Old_Rod, 0) { Version = RBY }, // Magikarp - new EncounterSlot1(118, 10, 10, -1, SlotType.Good_Rod, 1) { Version = RBY }, // Goldeen - new EncounterSlot1(060, 10, 10, -1, SlotType.Good_Rod, 2) { Version = RBY }, // Poliwag - } - }; } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs index 4015936a9..88585262e 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs @@ -9,124 +9,28 @@ namespace PKHeX.Core /// internal static class Encounters2 { - internal static readonly EncounterArea2[] SlotsGSC, SlotsGS, SlotsC; - internal static readonly EncounterStatic2[] StaticGSC, StaticGS, StaticC; + private static readonly EncounterArea2[] SlotsG = Get("gold", "g2", GameVersion.GD); + private static readonly EncounterArea2[] SlotsS = Get("silver", "g2", GameVersion.SV); + internal static readonly EncounterArea2[] SlotsC = Get("crystal", "g2", GameVersion.C); + + internal static readonly EncounterArea2[] SlotsGS = ArrayUtil.ConcatAll(SlotsG, SlotsS); + internal static readonly EncounterArea2[] SlotsGSC = ArrayUtil.ConcatAll(SlotsGS, SlotsC); private static readonly TreesArea[] HeadbuttTreesC = TreesArea.GetArray(BinLinker.Unpack(Util.GetBinaryResource("trees_h_c.pkl"), "ch")); + private static EncounterArea2[] Get(string name, string ident, GameVersion game) => + EncounterArea2.GetAreas(BinLinker.Unpack(Util.GetBinaryResource($"encounter_{name}.pkl"), ident), game); static Encounters2() { - StaticGS = Encounter_GS; - StaticC = Encounter_C; - StaticGSC = Encounter_GSC; - SlotsGS = GetTables2(GameVersion.GS); - SlotsC = GetTables2(GameVersion.C); - SlotsGSC = GetTables2(GameVersion.GSC); - MarkEncounterAreaArray(SlotsGS, SlotsC, SlotsGSC, EncounterSafari_GSC, EncounterBCC_GSC); - ReduceAreasSize(ref SlotsGS); - ReduceAreasSize(ref SlotsC); - ReduceAreasSize(ref SlotsGSC); MarkEncountersGeneration(2, StaticGS, StaticC, StaticGSC, TradeGift_GSC); MarkEncounterTradeStrings(TradeGift_GSC, TradeGift_GSC_OTs); - SlotsGSC.SetVersion(GameVersion.GSC); - SlotsGS.SetVersion(GameVersion.GS); - SlotsC.SetVersion(GameVersion.C); StaticGSC.SetVersion(GameVersion.GSC); StaticGS.SetVersion(GameVersion.GS); StaticC.SetVersion(GameVersion.C); TradeGift_GSC.SetVersion(GameVersion.GSC); } - private static EncounterArea2[] GetTables2(GameVersion Version) - { - // Fishing - var f = EncounterArea2.GetArray2Fishing(Util.GetBinaryResource("encounter_gsc_f.pkl")); - - var Slots = Array.Empty(); - if (Version.Contains(GameVersion.GS)) - Slots = GetSlots_GS(f); - if (Version.Contains(GameVersion.C)) - Slots = AddExtraTableSlots(Slots, GetSlots_C(f)); - - return Slots; - } - - private static EncounterArea2[] GetSlots_GS(EncounterArea2[] f) - { - // Grass/Water - var g = EncounterArea2.GetArray2GrassWater(Util.GetBinaryResource("encounter_gold.pkl")); - var s = EncounterArea2.GetArray2GrassWater(Util.GetBinaryResource("encounter_silver.pkl")); - // Headbutt/Rock Smash - var h_g = EncounterArea2.GetArray2Headbutt(Util.GetBinaryResource("encounter_gold_h.pkl")); - var h_s = EncounterArea2.GetArray2Headbutt(Util.GetBinaryResource("encounter_silver_h.pkl")); - var safari_gs = EncounterSafari_GSC; - var bcc_gs = EncounterBCC_GSC; - - MarkEncountersVersion(bcc_gs, GameVersion.GS); - MarkEncountersVersion(f, GameVersion.GS); - MarkEncountersVersion(g, GameVersion.GD); - MarkEncountersVersion(s, GameVersion.SV); - MarkEncountersVersion(h_g, GameVersion.GD); - MarkEncountersVersion(h_s, GameVersion.SV); - MarkEncountersVersion(safari_gs, GameVersion.GS); - - return AddExtraTableSlots(g, s, h_g, h_s, f, bcc_gs, safari_gs); - } - - private static EncounterArea2[] GetSlots_C(EncounterArea2[] f) - { - // Grass/Water - var c = EncounterArea2.GetArray2GrassWater(Util.GetBinaryResource("encounter_crystal.pkl")); - // Headbutt/Rock Smash - var h_c = EncounterArea2.GetArray2Headbutt(Util.GetBinaryResource("encounter_crystal_h.pkl")); - var safari_c = EncounterSafari_GSC; - var bcc_c = EncounterBCC_GSC; - - MarkEncountersVersion(bcc_c, GameVersion.C); - MarkEncountersVersion(safari_c, GameVersion.C); - MarkEncountersVersion(f, GameVersion.C); - MarkEncountersVersion(c, GameVersion.C); - MarkEncountersVersion(h_c, GameVersion.C); - - var extra = AddExtraTableSlots(c, h_c, f, bcc_c, safari_c); - return extra; - } - - private static readonly EncounterArea2[] EncounterBCC_GSC = { new EncounterArea2 { - Location = 19, - Slots = new EncounterSlot[] - { - new EncounterSlot2(010, 07, 18, 20, SlotType.BugContest, 0), // Caterpie - new EncounterSlot2(013, 07, 18, 20, SlotType.BugContest, 1), // Weedle - new EncounterSlot2(011, 09, 18, 10, SlotType.BugContest, 2), // Metapod - new EncounterSlot2(014, 09, 18, 10, SlotType.BugContest, 3), // Kakuna - new EncounterSlot2(012, 12, 15, 05, SlotType.BugContest, 4), // Butterfree - new EncounterSlot2(015, 12, 15, 05, SlotType.BugContest, 5), // Beedrill - new EncounterSlot2(048, 10, 16, 10, SlotType.BugContest, 6), // Venonat - new EncounterSlot2(046, 10, 17, 10, SlotType.BugContest, 7), // Paras - new EncounterSlot2(123, 13, 14, 05, SlotType.BugContest, 8), // Scyther - new EncounterSlot2(127, 13, 14, 05, SlotType.BugContest, 9), // Pinsir - } - }}; - - private static readonly EncounterArea2[] EncounterSafari_GSC = { new EncounterArea2 { - Location = 81, - Slots = new EncounterSlot[] - { - new EncounterSlot2(129, 10, 10, 100, SlotType.Old_Rod_Safari, 0), // Magikarp - new EncounterSlot2(098, 10, 10, 100, SlotType.Old_Rod_Safari, 1), // Krabby - new EncounterSlot2(098, 20, 20, 100, SlotType.Good_Rod_Safari, 0), // Krabby - new EncounterSlot2(129, 20, 20, 100, SlotType.Good_Rod_Safari, 1), // Magikarp - new EncounterSlot2(222, 20, 20, 100, SlotType.Good_Rod_Safari, 2), // Corsola - new EncounterSlot2(120, 20, 20, 100, SlotType.Good_Rod_Safari, 3), // Staryu - new EncounterSlot2(098, 40, 40, 100, SlotType.Super_Rod_Safari, 0), // Krabby - new EncounterSlot2(222, 40, 40, 100, SlotType.Super_Rod_Safari, 1), // Corsola - new EncounterSlot2(120, 40, 40, 100, SlotType.Super_Rod_Safari, 2), // Staryu - new EncounterSlot2(121, 40, 40, 100, SlotType.Super_Rod_Safari, 3), // Kingler - } - }}; - private static readonly EncounterStatic2[] Encounter_GSC_Common = { new EncounterStatic2(152, 05) { Location = 001, Version = GameVersion.GSC }, // Chikorita @ New Bark Town @@ -267,9 +171,13 @@ internal static TreeEncounterAvailable GetGSCHeadbuttAvailability(EncounterSlot if (Area == null) // Failsafe, every area with headbutt encounters has a tree area return TreeEncounterAvailable.Impossible; - var table = Area.GetTrees(encounter.Type); + var table = Area.GetTrees(encounter.Area.Type); var trainerpivot = TID % 10; return table[trainerpivot]; } + + internal static readonly EncounterStatic2[] StaticGSC = Encounter_GSC; + internal static readonly EncounterStatic2[] StaticGS = Encounter_GS; + internal static readonly EncounterStatic2[] StaticC = Encounter_C; } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs index bb6cb62cd..b6b8278d3 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using static PKHeX.Core.EncounterUtil; +using static PKHeX.Core.EncounterUtil; using static PKHeX.Core.Encounters3Teams; namespace PKHeX.Core @@ -10,112 +8,30 @@ namespace PKHeX.Core /// internal static class Encounters3 { - internal static readonly EncounterArea3[] SlotsR, SlotsS, SlotsE; - internal static readonly EncounterArea3[] SlotsFR, SlotsLG; - internal static readonly EncounterStatic3[] StaticR, StaticS, StaticE; - internal static readonly EncounterStatic3[] StaticFR, StaticLG; - - private const int SafariLocation_RSE = 57; - private const int SafariLocation_FRLG = 136; + private static readonly EncounterArea3[] SlotsSwarmRSE = Get("rse_swarm", "rs", GameVersion.RSE); + internal static readonly EncounterArea3[] SlotsR = ArrayUtil.ConcatAll(Get("r", "ru", GameVersion.R), SlotsSwarmRSE); + internal static readonly EncounterArea3[] SlotsS = ArrayUtil.ConcatAll(Get("s", "sa", GameVersion.S), SlotsSwarmRSE); + internal static readonly EncounterArea3[] SlotsE = ArrayUtil.ConcatAll(Get("e", "em", GameVersion.E), SlotsSwarmRSE); + internal static readonly EncounterArea3[] SlotsFR = Get("fr", "fr", GameVersion.FR); + internal static readonly EncounterArea3[] SlotsLG = Get("lg", "lg", GameVersion.LG); + private static EncounterArea3[] Get(string resource, string ident, GameVersion game) + => EncounterArea3.GetAreas(BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident), game); static Encounters3() { - StaticR = GetEncounters(Encounter_RSE, GameVersion.R); - StaticS = GetEncounters(Encounter_RSE, GameVersion.S); - StaticE = GetEncounters(Encounter_RSE, GameVersion.E); - StaticFR = GetEncounters(Encounter_FRLG, GameVersion.FR); - StaticLG = GetEncounters(Encounter_FRLG, GameVersion.LG); - - static EncounterArea3[] get(string resource, string ident) - => EncounterArea3.GetArray3(BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident)); - - var R_Slots = get("r", "ru"); - var S_Slots = get("s", "sa"); - var E_Slots = get("e", "em"); - var FR_Slots = get("fr", "fr"); - var LG_Slots = get("lg", "lg"); - - MarkEncounterAreaArray(SlotsRSEAlt, SlotsFRLGUnown, SlotsXD); - - ReduceAreasSize(ref R_Slots); - ReduceAreasSize(ref S_Slots); - ReduceAreasSize(ref E_Slots); - MarkG3Slots_FRLG(ref FR_Slots); - MarkG3Slots_FRLG(ref LG_Slots); - - MarkG3SlotsSafariZones(ref R_Slots, SafariLocation_RSE); - MarkG3SlotsSafariZones(ref S_Slots, SafariLocation_RSE); - MarkG3SlotsSafariZones(ref E_Slots, SafariLocation_RSE); - MarkG3SlotsSafariZones(ref FR_Slots, SafariLocation_FRLG); - MarkG3SlotsSafariZones(ref LG_Slots, SafariLocation_FRLG); - - MarkEncountersStaticMagnetPull(E_Slots, PersonalTable.E); - - SlotsR = AddExtraTableSlots(R_Slots, SlotsRSEAlt); - SlotsS = AddExtraTableSlots(S_Slots, SlotsRSEAlt); - SlotsE = AddExtraTableSlots(E_Slots, SlotsRSEAlt); - SlotsFR = AddExtraTableSlots(FR_Slots, SlotsFRLGUnown); - SlotsLG = AddExtraTableSlots(LG_Slots, SlotsFRLGUnown); - MarkEncountersGeneration(3, StaticR, StaticS, StaticE, StaticFR, StaticLG, Encounter_CXD, TradeGift_RSE, TradeGift_FRLG); MarkEncounterTradeStrings(TradeGift_RSE, TradeRSE); MarkEncounterTradeStrings(TradeGift_FRLG, TradeFRLG); - SlotsRSEAlt.SetVersion(GameVersion.RSE); - SlotsFRLGUnown.SetVersion(GameVersion.FRLG); - SlotsR.SetVersion(GameVersion.R); - SlotsS.SetVersion(GameVersion.S); - SlotsE.SetVersion(GameVersion.E); - SlotsFR.SetVersion(GameVersion.FR); - SlotsLG.SetVersion(GameVersion.LG); Encounter_RSE.SetVersion(GameVersion.RSE); Encounter_FRLG.SetVersion(GameVersion.FRLG); TradeGift_RSE.SetVersion(GameVersion.RSE); TradeGift_FRLG.SetVersion(GameVersion.FRLG); Encounter_Colo.SetVersion(GameVersion.COLO); Encounter_XD.SetVersion(GameVersion.XD); - SlotsXD.SetVersion(GameVersion.XD); } - private static void MarkG3Slots_FRLG(ref EncounterArea3[] Areas) - { - // Remove slots for unown, those slots does not contains alt form info, it will be added manually in SlotsRFLGAlt - // Group areas by location id, the raw data have areas with different slots but the same location id - Areas = Areas.Where(a => a.Location < 188 || a.Location > 194).GroupBy(a => a.Location).Select(a => new EncounterArea3 - { - Location = a.First().Location, - Slots = a.SelectMany(m => m.Slots).ToArray() - }).ToArray(); - } - - private static void MarkG3SlotsSafariZones(ref EncounterArea3[] Areas, int location) - { - foreach (var Area in Areas.Where(a => a.Location == location)) - { - foreach (EncounterSlot Slot in Area.Slots) - Slot.Type |= SlotType.Safari; - } - } - - private static readonly int[] Roaming_MetLocation_FRLG = - { - //Route 1-25 encounter is possible either in grass or on water - 101,102,103,104,105,106,107,108,109,110, - 111,112,113,114,115,116,117,118,119,120, - 121,122,123,124,125 - }; - - private static readonly int[] Roaming_MetLocation_RSE = - { - //Roaming encounter is possible in tall grass and on water - //Route 101-138 - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, - }; - private static readonly EncounterStatic3[] Encounter_RSE_Roam = { new EncounterStatic3 { Species = 380, Level = 40, Version = GameVersion.S, Roaming = true }, // Latias @@ -230,8 +146,8 @@ private static void MarkG3SlotsSafariZones(ref EncounterArea3[] Areas, int locat new EncounterStatic3 { Species = 386, Level = 30, Location = 187, Version = GameVersion.LG, Form = 2, Fateful = true }, // Deoxys @ Birth Island }; - private static readonly EncounterStatic3[] Encounter_RSE = Encounter_RSE_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_RSE)).Concat(Encounter_RSE_Regular).ToArray(); - private static readonly EncounterStatic3[] Encounter_FRLG = Encounter_FRLG_Roam.SelectMany(e => e.Clone(Roaming_MetLocation_FRLG)).Concat(Encounter_FRLG_Stationary).ToArray(); + private static readonly EncounterStatic3[] Encounter_RSE = ArrayUtil.ConcatAll(Encounter_RSE_Roam, Encounter_RSE_Regular); + private static readonly EncounterStatic3[] Encounter_FRLG = ArrayUtil.ConcatAll(Encounter_FRLG_Roam, Encounter_FRLG_Stationary); private static readonly int[] TradeContest_Cool = { 30, 05, 05, 05, 05, 10 }; private static readonly int[] TradeContest_Beauty = { 05, 30, 05, 05, 05, 10 }; @@ -273,89 +189,6 @@ private static void MarkG3SlotsSafariZones(ref EncounterArea3[] Areas, int locat private static readonly string[][] TradeRSE = Util.GetLanguageStrings7(tradeRSE); private static readonly string[][] TradeFRLG = Util.GetLanguageStrings7(tradeFRLG); - private static readonly int[] MoveSwarmSurskit = { 145, 098 }; /* Bubble, Quick Attack */ - private static readonly int[] MoveSwarmSeedot = { 117, 106, 073 }; /* Bide, Harden, Leech Seed */ - private static readonly int[] MoveSwarmNuzleaf = { 106, 074, 267, 073 }; /* Harden, Growth, Nature Power, Leech Seed */ - private static readonly int[] MoveSwarmSeedotF = { 202, 218, 076, 073 }; /* Giga Drain, Frustration, Solar Beam, Leech Seed */ - private static readonly int[] MoveSwarmSkittyRS = { 045, 033 }; /* Growl, Tackle */ - private static readonly int[] MoveSwarmSkittyE = { 045, 033, 039, 213 }; /* Growl, Tackle, Tail Whip, Attract */ - - #region AltSlots - private static readonly EncounterArea3[] SlotsRSEAlt = - { - // Swarm can be passed from R/S<->E via mixing records - // Encounter Percent is a 50% call - new EncounterArea3 { - Location = 17, // Route 102 - Slots = new EncounterSlot[] - { - new EncounterSlot3Swarm(MoveSwarmSurskit) { Species = 283, LevelMin = 03, LevelMax = 03, Type = SlotType.Swarm }, - new EncounterSlot3Swarm(MoveSwarmSeedot) { Species = 273, LevelMin = 03, LevelMax = 03, Type = SlotType.Swarm }, - },}, - new EncounterArea3 { - Location = 29, // Route 114 - Slots = new EncounterSlot[] - { - new EncounterSlot3Swarm(MoveSwarmSurskit) { Species = 283, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm }, - new EncounterSlot3Swarm(MoveSwarmNuzleaf) { Species = 274, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm }, - },}, - new EncounterArea3 { - Location = 31, // Route 116 - Slots = new EncounterSlot[] - { - new EncounterSlot3Swarm(MoveSwarmSkittyRS) { Species = 300, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm }, - new EncounterSlot3Swarm(MoveSwarmSkittyE) { Species = 300, LevelMin = 08, LevelMax = 08, Type = SlotType.Swarm }, - },}, - new EncounterArea3 { - Location = 32, // Route 117 - Slots = new EncounterSlot[] - { - new EncounterSlot3Swarm(MoveSwarmSurskit) { Species = 283, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm }, - new EncounterSlot3Swarm(MoveSwarmNuzleaf) { Species = 273, LevelMin = 13, LevelMax = 13, Type = SlotType.Swarm }, // Has same moves as Nuzleaf - },}, - new EncounterArea3 { - Location = 35, // Route 120 - Slots = new EncounterSlot[] - { - new EncounterSlot3Swarm(MoveSwarmSurskit) { Species = 283, LevelMin = 28, LevelMax = 28, Type = SlotType.Swarm }, - new EncounterSlot3Swarm(MoveSwarmSeedotF) { Species = 273, LevelMin = 25, LevelMax = 25, Type = SlotType.Swarm }, - },}, - - // Feebas fishing spot - new EncounterArea3 { - Location = 34, // Route 119 - Slots = new[] - { - new EncounterSlot3 { Species = 349, LevelMin = 20, LevelMax = 25, Type = SlotType.Swarm } // Feebas with any Rod (50%) - },}, - }; - - private static readonly EncounterArea3[] SlotsFRLGUnown = - { - GetUnownArea(188, new[] { 00,00,00,00,00,00,00,00,00,00,00,27 }), // 188 = Monean Chamber - GetUnownArea(189, new[] { 02,02,02,03,03,03,07,07,07,20,20,14 }), // 189 = Liptoo Chamber - GetUnownArea(190, new[] { 13,13,13,13,18,18,18,18,08,08,04,04 }), // 190 = Weepth Chamber - GetUnownArea(191, new[] { 15,15,11,11,09,09,17,17,17,16,16,16 }), // 191 = Dilford Chamber - GetUnownArea(192, new[] { 24,24,19,19,06,06,06,05,05,05,10,10 }), // 192 = Scufib Chamber - GetUnownArea(193, new[] { 21,21,21,22,22,22,23,23,12,12,01,01 }), // 193 = Rixy Chamber - GetUnownArea(194, new[] { 25,25,25,25,25,25,25,25,25,25,25,26 }), // 194 = Viapois Chamber - }; - - private static EncounterArea3 GetUnownArea(int location, IReadOnlyList SlotForms) - { - return new EncounterArea3 - { - Location = location, - Slots = SlotForms.Select((_, i) => new EncounterSlot3 - { - Species = 201, LevelMin = 25, LevelMax = 25, Type = SlotType.Grass, - SlotNumber = i, - Form = SlotForms[i] - }).ToArray() - }; - } - #endregion - #region Colosseum private static readonly EncounterStatic3[] Encounter_Colo = { @@ -465,15 +298,6 @@ private static EncounterArea3 GetUnownArea(int location, IReadOnlyList Slot #region XD - private static readonly int[] MirorBXDLocations = - { - 090, // Rock - 091, // Oasis - 092, // Cave - 113, // Pyrite Town - 059, // Realgam Tower - }; - private static readonly EncounterStatic3[] Encounter_XD = new[] { new EncounterStatic3 { Fateful = true, Gift = true, Species = 133, Level = 10, Location = 000, Moves = new[] {044} }, // Eevee (Bite) @@ -597,44 +421,23 @@ private static EncounterArea3 GetUnownArea(int location, IReadOnlyList Slot new EncounterStaticShadow(Articuno) { Fateful = true, Species = 144, Level = 50, Gauge = 10000, Moves = new[] {326,215,114,058}, Location = 074, }, // Articuno: Grand Master Greevil @ Citadark Isle new EncounterStaticShadow(Zapdos) { Fateful = true, Species = 145, Level = 50, Gauge = 10000, Moves = new[] {326,226,319,085}, Location = 074, }, // Zapdos: Grand Master Greevil @ Citadark Isle new EncounterStaticShadow(Dragonite) { Fateful = true, Species = 149, Level = 55, Gauge = 09000, Moves = new[] {063,215,349,089}, Location = 162, }, // Dragonite: Wanderer Miror B. @ Gateon Port - }.SelectMany(CloneMirorB).ToArray(); + }; - internal static readonly EncounterArea3[] SlotsXD = + internal static readonly EncounterArea3XD[] SlotsXD = { - new EncounterArea3 { Location = 090, Slots = new[] // Rock - { - new EncounterSlot3PokeSpot(027, 10, 23, 0), // Sandshrew - new EncounterSlot3PokeSpot(207, 10, 20, 1), // Gligar - new EncounterSlot3PokeSpot(328, 10, 20, 2), // Trapinch - } - }, - new EncounterArea3 { Location = 091, Slots = new[] // Oasis - { - new EncounterSlot3PokeSpot(187, 10, 20, 0), // Hoppip - new EncounterSlot3PokeSpot(231, 10, 20, 1), // Phanpy - new EncounterSlot3PokeSpot(283, 10, 20, 2), // Surskit - } - }, - new EncounterArea3 { Location = 092, Slots = new[] // Cave - { - new EncounterSlot3PokeSpot(041, 10, 21, 0), // Zubat - new EncounterSlot3PokeSpot(304, 10, 21, 1), // Aron - new EncounterSlot3PokeSpot(194, 10, 21, 2), // Wooper - } - }, + new EncounterArea3XD(90, 027, 23, 207, 20, 328, 20), // Rock (Sandshrew, Gligar, Trapinch) + new EncounterArea3XD(91, 187, 20, 231, 20, 283, 20), // Oasis (Hoppip, Phanpy, Surskit) + new EncounterArea3XD(92, 041, 21, 304, 21, 194, 21), // Cave (Zubat, Aron, Wooper) }; internal static readonly EncounterStatic3[] Encounter_CXD = ArrayUtil.ConcatAll(Encounter_Colo, Encounter_XD); - private static IEnumerable CloneMirorB(EncounterStatic3 arg) - { - yield return arg; - if (!(arg is EncounterStaticShadow s)) - yield break; - foreach (int loc in MirorBXDLocations) - yield return (EncounterStatic3)s.Clone(loc); - } - #endregion + + internal static readonly EncounterStatic3[] StaticR = GetEncounters(Encounter_RSE, GameVersion.R); + internal static readonly EncounterStatic3[] StaticS = GetEncounters(Encounter_RSE, GameVersion.S); + internal static readonly EncounterStatic3[] StaticE = GetEncounters(Encounter_RSE, GameVersion.E); + internal static readonly EncounterStatic3[] StaticFR = GetEncounters(Encounter_FRLG, GameVersion.FR); + internal static readonly EncounterStatic3[] StaticLG = GetEncounters(Encounter_FRLG, GameVersion.LG); } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs index b99dd964d..a2ff7ee2e 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using static PKHeX.Core.EncounterUtil; +using static PKHeX.Core.GameVersion; namespace PKHeX.Core { @@ -10,69 +10,16 @@ namespace PKHeX.Core /// internal static class Encounters4 { - internal static readonly EncounterArea4DPPt[] SlotsD, SlotsP, SlotsPt; - internal static readonly EncounterArea4HGSS[] SlotsHG, SlotsSS; - internal static readonly EncounterStatic4[] StaticD, StaticP, StaticPt, StaticHG, StaticSS; + internal static readonly EncounterArea4[] SlotsD = EncounterArea4.GetAreas(Get("d", "da"), D); + internal static readonly EncounterArea4[] SlotsP = EncounterArea4.GetAreas(Get("p", "pe"), P); + internal static readonly EncounterArea4[] SlotsPt = EncounterArea4.GetAreas(Get("pt", "pt"), Pt); + internal static readonly EncounterArea4[] SlotsHG = EncounterArea4.GetAreas(Get("hg", "hg"), HG); + internal static readonly EncounterArea4[] SlotsSS = EncounterArea4.GetAreas(Get("ss", "ss"), SS); + private static byte[][] Get(string resource, string ident) => BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident); static Encounters4() { MarkG4PokeWalker(Encounter_PokeWalker); - StaticD = GetEncounters(Encounter_DPPt, GameVersion.D); - StaticP = GetEncounters(Encounter_DPPt, GameVersion.P); - StaticPt = GetEncounters(Encounter_DPPt, GameVersion.Pt); - var staticHGSS = Encounter_HGSS.Concat(Encounter_PokeWalker).ToArray(); - StaticHG = GetEncounters(staticHGSS, GameVersion.HG); - StaticSS = GetEncounters(staticHGSS, GameVersion.SS); - - static byte[][] get(string resource, string ident) - => BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident); - - var D_Slots = EncounterArea4DPPt.GetArray4DPPt(get("d", "da")); - var P_Slots = EncounterArea4DPPt.GetArray4DPPt(get("p", "pe")); - var Pt_Slots = EncounterArea4DPPt.GetArray4DPPt(get("pt", "pt"), true); - var HG_Slots = EncounterArea4HGSS.GetArray4HGSS(get("hg", "hg")); - var SS_Slots = EncounterArea4HGSS.GetArray4HGSS(get("ss", "ss")); - - var DP_Feebas = GetFeebasArea(D_Slots[10]); - var Pt_Feebas = GetFeebasArea(Pt_Slots[10]); - var HG_Headbutt_Slots = EncounterArea4HGSS.GetArray4HGSS_Headbutt(get("hb_hg", "hg")); - var SS_Headbutt_Slots = EncounterArea4HGSS.GetArray4HGSS_Headbutt(get("hb_ss", "ss")); - - var D_HoneyTrees_Slots = SlotsD_HoneyTree.Clone(HoneyTreesLocation); - var P_HoneyTrees_Slots = SlotsP_HoneyTree.Clone(HoneyTreesLocation); - var Pt_HoneyTrees_Slots = SlotsPt_HoneyTree.Clone(HoneyTreesLocation); - - MarkG4SwarmSlots(HG_Slots, SlotsHG_Swarm); - MarkG4SwarmSlots(SS_Slots, SlotsSS_Swarm); - - MarkEncounterTypeData(D_Slots, P_Slots, Pt_Slots, HG_Slots, SS_Slots); - - ReduceAreasSize(ref D_Slots); - ReduceAreasSize(ref P_Slots); - ReduceAreasSize(ref Pt_Slots); - ReduceAreasSize(ref HG_Slots); - ReduceAreasSize(ref SS_Slots); - ReduceAreasSize(ref HG_Headbutt_Slots); - ReduceAreasSize(ref SS_Headbutt_Slots); - - MarkG4SlotsGreatMarsh(D_Slots, 52); - MarkG4SlotsGreatMarsh(P_Slots, 52); - MarkG4SlotsGreatMarsh(Pt_Slots, 52); - - MarkEncounterAreaArray(D_HoneyTrees_Slots, P_HoneyTrees_Slots, Pt_HoneyTrees_Slots, DP_GreatMarshAlt, Pt_GreatMarshAlt, DPPt_Unown, DP_Feebas, Pt_Feebas); - MarkEncounterAreaArray(HG_Headbutt_Slots, SS_Headbutt_Slots, SlotsHGSSAlt); - - SlotsD = AddExtraTableSlots(D_Slots, D_HoneyTrees_Slots, DP_GreatMarshAlt, DPPt_Unown, DP_Feebas); - SlotsP = AddExtraTableSlots(P_Slots, P_HoneyTrees_Slots, DP_GreatMarshAlt, DPPt_Unown, DP_Feebas); - SlotsPt = AddExtraTableSlots(Pt_Slots, Pt_HoneyTrees_Slots, Pt_GreatMarshAlt, DPPt_Unown, Pt_Feebas); - SlotsHG = AddExtraTableSlots(HG_Slots, HG_Headbutt_Slots, SlotsHGSSAlt); - SlotsSS = AddExtraTableSlots(SS_Slots, SS_Headbutt_Slots, SlotsHGSSAlt); - - MarkDPPtEncounterTypeSlots(SlotsD); - MarkDPPtEncounterTypeSlots(SlotsP); - MarkDPPtEncounterTypeSlots(SlotsPt); - MarkHGSSEncounterTypeSlots(SlotsHG); - MarkHGSSEncounterTypeSlots(SlotsSS); MarkEncountersGeneration(4, StaticD, StaticP, StaticPt, StaticHG, StaticSS, TradeGift_DPPt, TradeGift_HGSS); @@ -82,74 +29,10 @@ static byte[][] get(string resource, string ident) foreach (var t in RanchGifts) t.TrainerNames = RanchOTNames; - DP_GreatMarshAlt.SetVersion(GameVersion.DP); - DPPt_Unown.SetVersion(GameVersion.DPPt); - DP_Feebas.SetVersion(GameVersion.DP); - SlotsHGSSAlt.SetVersion(GameVersion.HGSS); - SlotsD.SetVersion(GameVersion.D); - SlotsP.SetVersion(GameVersion.P); - SlotsPt.SetVersion(GameVersion.Pt); - SlotsHG.SetVersion(GameVersion.HG); - SlotsSS.SetVersion(GameVersion.SS); - Encounter_DPPt.SetVersion(GameVersion.DPPt); - Encounter_HGSS.SetVersion(GameVersion.HGSS); - TradeGift_DPPt.SetVersion(GameVersion.DPPt); - TradeGift_HGSS.SetVersion(GameVersion.HGSS); - } - - private static EncounterArea4DPPt[] GetFeebasArea(EncounterArea4DPPt template) - { - Debug.Assert(template.Location == 50); // Mt Coronet - Debug.Assert(template.Slots.Last().Species == (int)Species.Whiscash); - var slots = template.Slots.Where(z => z.Type.IsFishingRodType()).Select(z => z.Clone()).ToArray(); - Debug.Assert(slots[0].Species == (int)Species.Magikarp); - foreach (var s in slots) - { - s.Species = (int)Species.Feebas; - ((EncounterSlot4)s).TypeEncounter = EncounterType.Surfing_Fishing; - } - - var area = new EncounterArea4DPPt - { - Location = template.Location, - Slots = slots, - }; - return new[] {area}; - } - - private static void MarkEncounterTypeData(EncounterArea4[] D_Slots, EncounterArea4[] P_Slots, EncounterArea4[] Pt_Slots, EncounterArea4[] HG_Slots, EncounterArea4[] SS_Slots) - { - // Shellos & Gastrodon - MarkG4AltFormSlots(D_Slots, 422, 1, Shellos_EastSeaLocation_DP); - MarkG4AltFormSlots(D_Slots, 423, 1, Gastrodon_EastSeaLocation_DP); - MarkG4AltFormSlots(P_Slots, 422, 1, Shellos_EastSeaLocation_DP); - MarkG4AltFormSlots(P_Slots, 423, 1, Gastrodon_EastSeaLocation_DP); - MarkG4AltFormSlots(Pt_Slots, 422, 1, Shellos_EastSeaLocation_Pt); - MarkG4AltFormSlots(Pt_Slots, 423, 1, Gastrodon_EastSeaLocation_Pt); - - const int Route209 = 24; - MarkDPPtEncounterTypeSlots_MultipleTypes(D_Slots, Route209, EncounterType.Building_EnigmaStone, 1); - MarkDPPtEncounterTypeSlots_MultipleTypes(P_Slots, Route209, EncounterType.Building_EnigmaStone, 1); - MarkDPPtEncounterTypeSlots_MultipleTypes(Pt_Slots, Route209, EncounterType.Building_EnigmaStone, 1); - const int StarkMountain = 84; - MarkDPPtEncounterTypeSlots_MultipleTypes(D_Slots, StarkMountain, EncounterType.Cave_HallOfOrigin, 1); - MarkDPPtEncounterTypeSlots_MultipleTypes(P_Slots, StarkMountain, EncounterType.Cave_HallOfOrigin, 1); - MarkDPPtEncounterTypeSlots_MultipleTypes(Pt_Slots, StarkMountain, EncounterType.Cave_HallOfOrigin, 1); - const int MtCoronet = 50; - MarkDPPtEncounterTypeSlots_MultipleTypes(D_Slots, MtCoronet, EncounterType.Cave_HallOfOrigin, DPPt_MtCoronetExteriorEncounters); - MarkDPPtEncounterTypeSlots_MultipleTypes(P_Slots, MtCoronet, EncounterType.Cave_HallOfOrigin, DPPt_MtCoronetExteriorEncounters); - MarkDPPtEncounterTypeSlots_MultipleTypes(Pt_Slots, MtCoronet, EncounterType.Cave_HallOfOrigin, DPPt_MtCoronetExteriorEncounters); - const int RuinsOfAlph = 209; - MarkHGSSEncounterTypeSlots_MultipleTypes(HG_Slots, RuinsOfAlph, EncounterType.Cave_HallOfOrigin, 1); - MarkHGSSEncounterTypeSlots_MultipleTypes(SS_Slots, RuinsOfAlph, EncounterType.Cave_HallOfOrigin, 1); - MarkSpecific(HG_Slots, RuinsOfAlph, SlotType.Rock_Smash, EncounterType.DialgaPalkia); - MarkSpecific(SS_Slots, RuinsOfAlph, SlotType.Rock_Smash, EncounterType.DialgaPalkia); - const int MtSilver = 219; - MarkHGSSEncounterTypeSlots_MultipleTypes(HG_Slots, MtSilver, EncounterType.Cave_HallOfOrigin, HGSS_MtSilverCaveExteriorEncounters); - MarkHGSSEncounterTypeSlots_MultipleTypes(SS_Slots, MtSilver, EncounterType.Cave_HallOfOrigin, HGSS_MtSilverCaveExteriorEncounters); - const int Cianwood = 130; - MarkHGSSEncounterTypeSlots_MultipleTypes(HG_Slots, Cianwood, EncounterType.RockSmash); - MarkHGSSEncounterTypeSlots_MultipleTypes(SS_Slots, Cianwood, EncounterType.RockSmash); + Encounter_DPPt.SetVersion(DPPt); + Encounter_HGSS.SetVersion(HGSS); + TradeGift_DPPt.SetVersion(DPPt); + TradeGift_HGSS.SetVersion(HGSS); } private static void MarkG4PokeWalker(IEnumerable t) @@ -158,405 +41,10 @@ private static void MarkG4PokeWalker(IEnumerable t) { s.Location = 233; //Pokéwalker s.Gift = true; //Pokeball only - s.Version = GameVersion.HGSS; + s.Version = HGSS; } } - private static void MarkG4SlotsGreatMarsh(IEnumerable Areas, int location) - { - foreach (EncounterArea Area in Areas.Where(a => a.Location == location)) - { - foreach (EncounterSlot Slot in Area.Slots) - Slot.Type |= SlotType.Safari; - } - } - - private static void MarkG4SwarmSlots(IEnumerable Areas, T[] SwarmAreas) where T : EncounterArea - { - // Grass Swarm slots replace slots 0 and 1 from encounters data - // for surfing only replace slots 0 from encounters data - // for fishing replace one or several random slots from encounters data, but all slots have the same level, it's ok to only replace the first - // Species id are not included in encounter tables but levels can be copied from the encounter raw data - foreach (var Area in Areas) - { - var SwarmSlots = SwarmAreas.Where(a => a.Location == Area.Location).SelectMany(s => s.Slots); - var OutputSlots = new List(); - foreach (var SwarmSlot in SwarmSlots) - { - int slotsnum = SwarmSlot.Type == SlotType.Grass ? 2 : 1; - foreach (var swarmSlot in Area.Slots.Where(s => s.Type == SwarmSlot.Type).Take(slotsnum).Select(slot => (EncounterSlot4)slot.Clone())) - { - swarmSlot.Species = SwarmSlot.Species; - if (swarmSlot.Species == (int)Species.Mawile) // edge case, Mawile is only swarm subject to magnet pull (no other steel types in area) - { - swarmSlot.MagnetPullIndex = swarmSlot.SlotNumber; - swarmSlot.MagnetPullCount = 2; - } - OutputSlots.Add(swarmSlot); - } - } - Area.Slots = Area.Slots.Concat(OutputSlots).Where(a => a.Species > 0).ToArray(); - } - } - - // Gen 4 raw encounter data does not contains info for alt slots - // Shellos and Gastrodon East Sea form should be modified - private static void MarkG4AltFormSlots(IEnumerable Areas, int Species, int form, int[] Locations) - { - foreach (var Area in Areas.Where(a => Locations.Contains(a.Location))) - { - foreach (EncounterSlot Slot in Area.Slots.Where(s => s.Species == Species)) - Slot.Form = form; - } - } - - private static EncounterType GetEncounterTypeBySlotDPPt(SlotType Type, EncounterType GrassType) - { - switch (Type) - { - case SlotType.Pokeradar: - case SlotType.Pokeradar_Safari: - case SlotType.Swarm: - case SlotType.Grass: return GrassType; - case SlotType.Surf: - case SlotType.Old_Rod: - case SlotType.Good_Rod: - case SlotType.Super_Rod: - case SlotType.Surf_Safari: - case SlotType.Old_Rod_Safari: - case SlotType.Good_Rod_Safari: - case SlotType.Super_Rod_Safari: return EncounterType.Surfing_Fishing; - case SlotType.Grass_Safari: return EncounterType.MarshSafari; - case SlotType.HoneyTree: return EncounterType.None; - } - return EncounterType.None; - } - - private static EncounterType GetEncounterTypeBySlotHGSS(SlotType Type, EncounterType GrassType, EncounterType HeadbuttType) - { - switch (Type) - { - // HGSS Safari encounters have normal water/grass encounter type, not safari encounter type - case SlotType.Grass: - case SlotType.Grass_Safari: - case SlotType.BugContest: return GrassType; - - case SlotType.Surf: - case SlotType.Old_Rod: - case SlotType.Good_Rod: - case SlotType.Super_Rod: - case SlotType.Surf_Safari: - case SlotType.Old_Rod_Safari: - case SlotType.Good_Rod_Safari: - case SlotType.Super_Rod_Safari: return EncounterType.Surfing_Fishing; - - case SlotType.Rock_Smash: - if (GrassType == EncounterType.RockSmash) - return EncounterType.RockSmash | EncounterType.Building_EnigmaStone; - if (HeadbuttType == EncounterType.Building_EnigmaStone) - return HeadbuttType; - if (GrassType == EncounterType.Cave_HallOfOrigin) - return GrassType; - return EncounterType.None; - - case SlotType.Headbutt_Special: - case SlotType.Headbutt: return HeadbuttType | EncounterType.None; - // not sure on if "None" should always be allowed, but this is so uncommon it shouldn't matter (gen7 doesn't keep this value anyway). - } - return EncounterType.None; - } - - private static void MarkDPPtEncounterTypeSlots_MultipleTypes(EncounterArea4[] Areas, int Location, EncounterType NormalEncounterType, params int[] SpecialEncounterFiles) - { - var numfile = 0; - foreach (var Area in Areas.Where(x => x.Location == Location)) - { - numfile++; - var GrassType = SpecialEncounterFiles.Contains(numfile) ? EncounterType.TallGrass : NormalEncounterType; - foreach (EncounterSlot slot in Area.Slots) - { - ((EncounterSlot4)slot).TypeEncounter = GetEncounterTypeBySlotDPPt(slot.Type, GrassType); - } - } - } - - private static void MarkHGSSEncounterTypeSlots_MultipleTypes(EncounterArea4[] Areas, int Location, EncounterType NormalEncounterType, params int[] SpecialEncounterFile) - { - // Area with two different encounter type for grass encounters - // SpecialEncounterFile is taall grass encounter type, the other files have the normal encounter type for this location - var HeadbuttType = GetHeadbuttEncounterType(Location); - var numfile = 0; - foreach (var Area in Areas.Where(x => x.Location == Location)) - { - numfile++; - var GrassType = SpecialEncounterFile.Contains(numfile) ? EncounterType.TallGrass : NormalEncounterType; - foreach (EncounterSlot slot in Area.Slots) - { - ((EncounterSlot4)slot).TypeEncounter = GetEncounterTypeBySlotHGSS(slot.Type, GrassType, HeadbuttType); - } - } - } - - private static void MarkSpecific(EncounterArea4[] Areas, int Location, SlotType t, EncounterType val) - { - foreach (var Area in Areas.Where(x => x.Location == Location)) - { - foreach (var slot in Area.Slots.Where(s => s.Type == t)) - ((EncounterSlot4)slot).TypeEncounter = val; - } - } - - private static void MarkDPPtEncounterTypeSlots(EncounterArea4[] Areas) - { - foreach (var Area in Areas) - { - if (DPPt_MixInteriorExteriorLocations.Contains(Area.Location)) - continue; - var GrassType = GetGrassType(Area.Location); - - EncounterType GetGrassType(int location) - { - if (location == 70) // Old Chateau - return EncounterType.Building_EnigmaStone; - if (DPPt_CaveLocations.Contains(Area.Location)) - return EncounterType.Cave_HallOfOrigin; - return EncounterType.TallGrass; - } - foreach (EncounterSlot slot in Area.Slots) - { - if (((EncounterSlot4)slot).TypeEncounter == EncounterType.None) // not defined yet - ((EncounterSlot4)slot).TypeEncounter = GetEncounterTypeBySlotDPPt(slot.Type, GrassType); - } - } - } - - private static EncounterType GetHeadbuttEncounterType(int Location) - { - if (Location == 195 || Location == 196) // Route 47/48 - return EncounterType.DialgaPalkia | EncounterType.TallGrass; - - // Routes with trees adjacent to water tiles - var allowsurf = HGSS_SurfingHeadbutt_Locations.Contains(Location); - - // Cities - if (HGSS_CityLocations.Contains(Location)) - { - return allowsurf - ? EncounterType.Building_EnigmaStone | EncounterType.Surfing_Fishing - : EncounterType.Building_EnigmaStone; - } - - // Caves with no exterior zones - if (!HGSS_MixInteriorExteriorLocations.Contains(Location) && HGSS_CaveLocations.Contains(Location)) - { - return allowsurf - ? EncounterType.Cave_HallOfOrigin | EncounterType.Surfing_Fishing - : EncounterType.Cave_HallOfOrigin; - } - - // Routes and exterior areas - // Routes with trees adjacent to grass tiles - var allowgrass = HGSS_GrassHeadbutt_Locations.Contains(Location); - if (allowgrass) - { - return allowsurf - ? EncounterType.TallGrass | EncounterType.Surfing_Fishing - : EncounterType.TallGrass; - } - - return allowsurf - ? EncounterType.Surfing_Fishing - : EncounterType.None; - } - - private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas) - { - foreach (var Area in Areas) - { - if (HGSS_MixInteriorExteriorLocations.Contains(Area.Location)) - continue; - var GrassType = HGSS_CaveLocations.Contains(Area.Location) ? EncounterType.Cave_HallOfOrigin : EncounterType.TallGrass; - var HeadbuttType = GetHeadbuttEncounterType(Area.Location); - foreach (EncounterSlot slot in Area.Slots) - { - if (((EncounterSlot4)slot).TypeEncounter == EncounterType.None) // not defined yet - ((EncounterSlot4)slot).TypeEncounter = GetEncounterTypeBySlotHGSS(slot.Type, GrassType, HeadbuttType); - } - } - } - - #region Encounter Types - private static readonly HashSet DPPt_CaveLocations = new HashSet - { - 46, // Oreburgh Mine - 50, // Mt. Coronet - 53, // Solaceon Ruins - 54, // Sinnoh Victory Road - 57, // Ravaged Path - 59, // Oreburgh Gate - 62, // Turnback Cave - 64, // Snowpoint Temple - 65, // Wayward Cave - 66, // Ruin Maniac Cave - 67, // Maniac Tunnel - 66, // Ruin Maniac Cave - 69, // Iron Island - 84, // Stark Mountain - }; - - private static readonly HashSet DPPt_MixInteriorExteriorLocations = new HashSet - { - 24, // Route 209 (Lost Tower) - 50, // Mt Coronet - 84, // Stark Mountain - }; - - private static readonly int[] DPPt_MtCoronetExteriorEncounters = - { - 4, 5, 70 - }; - - /// - /// Locations with headbutt trees accessible from Cave tiles - /// - private static readonly HashSet HGSS_CaveLocations = new HashSet - { - 197, // DIGLETT's Cave - 198, // Mt. Moon - 199, // Cerulean Cave - 200, // Rock Tunnel - 201, // Power Plant - 203, // Seafoam Islands - 204, // Sprout Tower - 205, // Bell Tower - 206, // Burned Tower - 209, // Ruins of Alph - 210, // Union Cave - 211, // SLOWPOKE Well - 214, // Ilex Forest - 216, // Mt. Mortar - 217, // Ice Path - 218, // Whirl Islands - 219, // Mt. Silver Cave - 220, // Dark Cave - 221, // Kanto Victory Road - 223, // Tohjo Falls - 228, // Cliff Cave - 234, // Cliff Edge Gate - }; - - /// - /// Locations with headbutt trees accessible from city tiles - /// - private static readonly HashSet HGSS_CityLocations = new HashSet - { - 126, // New Bark Town - 127, // Cherrygrove City - 128, // Violet City - 129, // Azalea Town - 130, // Cianwood City - 131, // Goldenrod City - 132, // Olivine City - 133, // Ecruteak City - 134, // Mahogany Town - 136, // Blackthorn City - 138, // Pallet Town - 139, // Viridian City - 140, // Pewter City - 141, // Cerulean City - 142, // Lavender Town - 143, // Vermilion City - 144, // Celadon City - 145, // Fuchsia City - 146, // Cinnabar Island - 147, // Indigo Plateau - 148, // Saffron City - 227, // Safari Zone Gate - }; - - /// - /// Locations with headbutt trees accessible from water tiles - /// - private static readonly HashSet HGSS_SurfingHeadbutt_Locations = new HashSet - { - 126, // New Bark Town - 127, // Cherrygrove City - 128, // Violet City - 133, // Ecruteak City - 135, // Lake of Rage - 138, // Pallet Town - 139, // Viridian City - 160, // Route 12 - 169, // Route 21 - 170, // Route 22 - 174, // Route 26 - 175, // Route 27 - 176, // Route 28 - 178, // Route 30 - 179, // Route 31 - 180, // Route 32 - 182, // Route 34 - 183, // Route 35 - 190, // Route 42 - 191, // Route 43 - 192, // Route 44 - 214, // Ilex Forest - }; - - /// - /// Locations with headbutt trees accessible from tall grass tiles - /// - private static readonly HashSet HGSS_GrassHeadbutt_Locations = new HashSet - { - 137, // Mt. Silver - 149, // Route 1 - 150, // Route 2 - 151, // Route 3 - 152, // Route 4 - 153, // Route 5 - 154, // Route 6 - 155, // Route 7 - 159, // Route 11 - 161, // Route 13 - 163, // Route 15 - 164, // Route 16 - 169, // Route 21 - 170, // Route 22 - 174, // Route 26 - 175, // Route 27 - 176, // Route 28 - 177, // Route 29 - 178, // Route 30 - 179, // Route 31 - 180, // Route 32 - 181, // Route 33 - 182, // Route 34 - 183, // Route 35 - 184, // Route 36 - 185, // Route 37 - 186, // Route 38 - 187, // Route 39 - 191, // Route 43 - 192, // Route 44 - 194, // Route 46 - 195, // Route 47 - 196, // Route 48 - 219, // Mt. Silver Cave - 224, // Viridian Forest - }; - - private static readonly int[] HGSS_MtSilverCaveExteriorEncounters = - { - 2, 3 - }; - - private static readonly int[] HGSS_MixInteriorExteriorLocations = - { - 209, // Ruins of Alph - 219, // Mt. Silver Cave - }; - - #endregion #region Pokéwalker Encounter // all pkm are in Poke Ball and have a met location of "PokeWalker" private static readonly EncounterStatic4[] Encounter_PokeWalker = @@ -753,84 +241,84 @@ private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas) { new EncounterStaticTyped { Species = 481, Level = 50, Roaming = true, TypeEncounter = EncounterType.TallGrass }, // Mesprit new EncounterStaticTyped { Species = 488, Level = 50, Roaming = true, TypeEncounter = EncounterType.TallGrass }, // Cresselia - new EncounterStaticTyped { Species = 144, Level = 60, Roaming = true, TypeEncounter = EncounterType.TallGrass, Version = GameVersion.Pt }, // Articuno - new EncounterStaticTyped { Species = 145, Level = 60, Roaming = true, TypeEncounter = EncounterType.TallGrass, Version = GameVersion.Pt }, // Zapdos - new EncounterStaticTyped { Species = 146, Level = 60, Roaming = true, TypeEncounter = EncounterType.TallGrass, Version = GameVersion.Pt }, // Moltres + new EncounterStaticTyped { Species = 144, Level = 60, Roaming = true, TypeEncounter = EncounterType.TallGrass, Version = Pt }, // Articuno + new EncounterStaticTyped { Species = 145, Level = 60, Roaming = true, TypeEncounter = EncounterType.TallGrass, Version = Pt }, // Zapdos + new EncounterStaticTyped { Species = 146, Level = 60, Roaming = true, TypeEncounter = EncounterType.TallGrass, Version = Pt }, // Moltres }; private static readonly EncounterStaticTyped[] Encounter_DPPt_Roam_Surf = { new EncounterStaticTyped { Species = 481, Level = 50, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing }, // Mesprit new EncounterStaticTyped { Species = 488, Level = 50, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing }, // Cresselia - new EncounterStaticTyped { Species = 144, Level = 60, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, Version = GameVersion.Pt }, // Articuno - new EncounterStaticTyped { Species = 145, Level = 60, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, Version = GameVersion.Pt }, // Zapdos - new EncounterStaticTyped { Species = 146, Level = 60, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, Version = GameVersion.Pt }, // Moltres + new EncounterStaticTyped { Species = 144, Level = 60, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, Version = Pt }, // Articuno + new EncounterStaticTyped { Species = 145, Level = 60, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, Version = Pt }, // Zapdos + new EncounterStaticTyped { Species = 146, Level = 60, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, Version = Pt }, // Moltres }; private static readonly EncounterStatic4[] Encounter_DPPt_Regular = { // Starters - new EncounterStaticTyped { Gift = true, Species = 387, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Turtwig @ Lake Verity - new EncounterStaticTyped { Gift = true, Species = 390, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Chimchar - new EncounterStaticTyped { Gift = true, Species = 393, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Piplup - new EncounterStaticTyped { Gift = true, Species = 387, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Turtwig @ Route 201 - new EncounterStaticTyped { Gift = true, Species = 390, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Chimchar - new EncounterStaticTyped { Gift = true, Species = 393, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Piplup + new EncounterStaticTyped { Gift = true, Species = 387, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Turtwig @ Lake Verity + new EncounterStaticTyped { Gift = true, Species = 390, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Chimchar + new EncounterStaticTyped { Gift = true, Species = 393, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Piplup + new EncounterStaticTyped { Gift = true, Species = 387, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Turtwig @ Route 201 + new EncounterStaticTyped { Gift = true, Species = 390, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Chimchar + new EncounterStaticTyped { Gift = true, Species = 393, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Piplup // Fossil @ Mining Museum - new EncounterStaticTyped { Gift = true, Species = 138, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Omanyte - new EncounterStaticTyped { Gift = true, Species = 140, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Kabuto - new EncounterStaticTyped { Gift = true, Species = 142, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Aerodactyl - new EncounterStaticTyped { Gift = true, Species = 345, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Lileep - new EncounterStaticTyped { Gift = true, Species = 347, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP}, // Anorith - new EncounterStaticTyped { Gift = true, Species = 408, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Cranidos - new EncounterStaticTyped { Gift = true, Species = 410, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = GameVersion.DP }, // Shieldon - new EncounterStaticTyped { Gift = true, Species = 138, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Omanyte - new EncounterStaticTyped { Gift = true, Species = 140, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Kabuto - new EncounterStaticTyped { Gift = true, Species = 142, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Aerodactyl - new EncounterStaticTyped { Gift = true, Species = 345, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Lileep - new EncounterStaticTyped { Gift = true, Species = 347, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt}, // Anorith - new EncounterStaticTyped { Gift = true, Species = 408, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Cranidos - new EncounterStaticTyped { Gift = true, Species = 410, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.Pt }, // Shieldon + new EncounterStaticTyped { Gift = true, Species = 138, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Omanyte + new EncounterStaticTyped { Gift = true, Species = 140, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Kabuto + new EncounterStaticTyped { Gift = true, Species = 142, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Aerodactyl + new EncounterStaticTyped { Gift = true, Species = 345, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Lileep + new EncounterStaticTyped { Gift = true, Species = 347, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP}, // Anorith + new EncounterStaticTyped { Gift = true, Species = 408, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Cranidos + new EncounterStaticTyped { Gift = true, Species = 410, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, Version = DP }, // Shieldon + new EncounterStaticTyped { Gift = true, Species = 138, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Omanyte + new EncounterStaticTyped { Gift = true, Species = 140, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Kabuto + new EncounterStaticTyped { Gift = true, Species = 142, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Aerodactyl + new EncounterStaticTyped { Gift = true, Species = 345, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Lileep + new EncounterStaticTyped { Gift = true, Species = 347, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt}, // Anorith + new EncounterStaticTyped { Gift = true, Species = 408, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Cranidos + new EncounterStaticTyped { Gift = true, Species = 410, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = Pt }, // Shieldon // Gift - new EncounterStaticTyped { Gift = true, Species = 133, Level = 05, Location = 010, Version = GameVersion.DP, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, }, // Eevee @ Hearthome City - new EncounterStaticTyped { Gift = true, Species = 133, Level = 20, Location = 010, Version = GameVersion.Pt, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Eevee @ Hearthome City - new EncounterStaticTyped { Gift = true, Species = 137, Level = 25, Location = 012, Version = GameVersion.Pt, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Porygon @ Veilstone City - new EncounterStatic4 { Gift = true, Species = 175, Level = 01, EggLocation = 2011, Version = GameVersion.Pt,}, // Togepi Egg from Cynthia - new EncounterStatic4 { Gift = true, Species = 440, Level = 01, EggLocation = 2009, Version = GameVersion.DP,}, // Happiny Egg from Traveling Man + new EncounterStaticTyped { Gift = true, Species = 133, Level = 05, Location = 010, Version = DP, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, }, // Eevee @ Hearthome City + new EncounterStaticTyped { Gift = true, Species = 133, Level = 20, Location = 010, Version = Pt, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Eevee @ Hearthome City + new EncounterStaticTyped { Gift = true, Species = 137, Level = 25, Location = 012, Version = Pt, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Porygon @ Veilstone City + new EncounterStatic4 { Gift = true, Species = 175, Level = 01, EggLocation = 2011, Version = Pt,}, // Togepi Egg from Cynthia + new EncounterStatic4 { Gift = true, Species = 440, Level = 01, EggLocation = 2009, Version = DP,}, // Happiny Egg from Traveling Man new EncounterStatic4 { Gift = true, Species = 447, Level = 01, EggLocation = 2010, }, // Riolu Egg from Riley // Stationary - new EncounterStatic4 { Species = 425, Level = 22, Location = 47, Version = GameVersion.DP }, // Drifloon @ Valley Windworks - new EncounterStatic4 { Species = 425, Level = 15, Location = 47, Version = GameVersion.Pt }, // Drifloon @ Valley Windworks - new EncounterStaticTyped { Species = 479, Level = 15, Location = 70, Version = GameVersion.DP, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Rotom @ Old Chateau - new EncounterStaticTyped { Species = 479, Level = 20, Location = 70, Version = GameVersion.Pt, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Rotom @ Old Chateau + new EncounterStatic4 { Species = 425, Level = 22, Location = 47, Version = DP }, // Drifloon @ Valley Windworks + new EncounterStatic4 { Species = 425, Level = 15, Location = 47, Version = Pt }, // Drifloon @ Valley Windworks + new EncounterStaticTyped { Species = 479, Level = 15, Location = 70, Version = DP, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Rotom @ Old Chateau + new EncounterStaticTyped { Species = 479, Level = 20, Location = 70, Version = Pt, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Rotom @ Old Chateau new EncounterStatic4 { Species = 442, Level = 25, Location = 24 }, // Spiritomb @ Route 209 // Stationary Legendary - new EncounterStaticTyped { Species = 377, Level = 30, Location = 125, Version = GameVersion.Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Regirock @ Rock Peak Ruins - new EncounterStaticTyped { Species = 378, Level = 30, Location = 124, Version = GameVersion.Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Regice @ Iceberg Ruins - new EncounterStaticTyped { Species = 379, Level = 30, Location = 123, Version = GameVersion.Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Registeel @ Iron Ruins + new EncounterStaticTyped { Species = 377, Level = 30, Location = 125, Version = Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Regirock @ Rock Peak Ruins + new EncounterStaticTyped { Species = 378, Level = 30, Location = 124, Version = Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Regice @ Iceberg Ruins + new EncounterStaticTyped { Species = 379, Level = 30, Location = 123, Version = Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Registeel @ Iron Ruins new EncounterStaticTyped { Species = 480, Level = 50, Location = 089, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Uxie @ Acuity Cavern new EncounterStaticTyped { Species = 482, Level = 50, Location = 088, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Azelf @ Valor Cavern - new EncounterStaticTyped { Species = 483, Level = 47, Location = 051, Version = GameVersion.D, TypeEncounter = EncounterType.DialgaPalkia }, // Dialga @ Spear Pillar - new EncounterStaticTyped { Species = 484, Level = 47, Location = 051, Version = GameVersion.P, TypeEncounter = EncounterType.DialgaPalkia }, // Palkia @ Spear Pillar - new EncounterStaticTyped { Species = 483, Level = 70, Location = 051, Version = GameVersion.Pt, TypeEncounter = EncounterType.DialgaPalkia }, // Dialga @ Spear Pillar - new EncounterStaticTyped { Species = 484, Level = 70, Location = 051, Version = GameVersion.Pt, TypeEncounter = EncounterType.DialgaPalkia }, // Palkia @ Spear Pillar - new EncounterStaticTyped { Species = 485, Level = 70, Location = 084, Version = GameVersion.DP, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Heatran @ Stark Mountain - new EncounterStaticTyped { Species = 485, Level = 50, Location = 084, Version = GameVersion.Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Heatran @ Stark Mountain - new EncounterStaticTyped { Species = 486, Level = 70, Location = 064, Version = GameVersion.DP, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Regigigas @ Snowpoint Temple - new EncounterStaticTyped { Species = 486, Level = 01, Location = 064, Version = GameVersion.Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Regigigas @ Snowpoint Temple - new EncounterStaticTyped { Species = 487, Level = 70, Location = 062, Version = GameVersion.DP, Form = 0, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Giratina @ Turnback Cave - new EncounterStaticTyped { Species = 487, Level = 47, Location = 117, Version = GameVersion.Pt, Form = 1, TypeEncounter = EncounterType.DistortionWorld_Pt, HeldItem = 112 }, // Giratina @ Distortion World - new EncounterStaticTyped { Species = 487, Level = 47, Location = 062, Version = GameVersion.Pt, Form = 0, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Giratina @ Turnback Cave + new EncounterStaticTyped { Species = 483, Level = 47, Location = 051, Version = D, TypeEncounter = EncounterType.DialgaPalkia }, // Dialga @ Spear Pillar + new EncounterStaticTyped { Species = 484, Level = 47, Location = 051, Version = P, TypeEncounter = EncounterType.DialgaPalkia }, // Palkia @ Spear Pillar + new EncounterStaticTyped { Species = 483, Level = 70, Location = 051, Version = Pt, TypeEncounter = EncounterType.DialgaPalkia }, // Dialga @ Spear Pillar + new EncounterStaticTyped { Species = 484, Level = 70, Location = 051, Version = Pt, TypeEncounter = EncounterType.DialgaPalkia }, // Palkia @ Spear Pillar + new EncounterStaticTyped { Species = 485, Level = 70, Location = 084, Version = DP, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Heatran @ Stark Mountain + new EncounterStaticTyped { Species = 485, Level = 50, Location = 084, Version = Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Heatran @ Stark Mountain + new EncounterStaticTyped { Species = 486, Level = 70, Location = 064, Version = DP, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Regigigas @ Snowpoint Temple + new EncounterStaticTyped { Species = 486, Level = 01, Location = 064, Version = Pt, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Regigigas @ Snowpoint Temple + new EncounterStaticTyped { Species = 487, Level = 70, Location = 062, Version = DP, Form = 0, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Giratina @ Turnback Cave + new EncounterStaticTyped { Species = 487, Level = 47, Location = 117, Version = Pt, Form = 1, TypeEncounter = EncounterType.DistortionWorld_Pt, HeldItem = 112 }, // Giratina @ Distortion World + new EncounterStaticTyped { Species = 487, Level = 47, Location = 062, Version = Pt, Form = 0, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Giratina @ Turnback Cave // Event - new EncounterStaticTyped { Species = 491, Level = 40, Location = 079, Version = GameVersion.DP, TypeEncounter = EncounterType.TallGrass }, // Darkrai @ Newmoon Island (Unreleased in Diamond and Pearl) - new EncounterStaticTyped { Species = 491, Level = 50, Location = 079, Version = GameVersion.Pt, TypeEncounter = EncounterType.TallGrass }, // Darkrai @ Newmoon Island - new EncounterStatic4 { Species = 492, Form = 0, Level = 30, Location = 063, Version = GameVersion.Pt, Fateful = true }, // Shaymin @ Flower Paradise - new EncounterStatic4 { Species = 492, Form = 0, Level = 30, Location = 063, Version = GameVersion.DP, Fateful = false }, // Shaymin @ Flower Paradise (Unreleased in Diamond and Pearl) + new EncounterStaticTyped { Species = 491, Level = 40, Location = 079, Version = DP, TypeEncounter = EncounterType.TallGrass }, // Darkrai @ Newmoon Island (Unreleased in Diamond and Pearl) + new EncounterStaticTyped { Species = 491, Level = 50, Location = 079, Version = Pt, TypeEncounter = EncounterType.TallGrass }, // Darkrai @ Newmoon Island + new EncounterStatic4 { Species = 492, Form = 0, Level = 30, Location = 063, Version = Pt, Fateful = true }, // Shaymin @ Flower Paradise + new EncounterStatic4 { Species = 492, Form = 0, Level = 30, Location = 063, Version = DP, Fateful = false }, // Shaymin @ Flower Paradise (Unreleased in Diamond and Pearl) new EncounterStaticTyped { Species = 493, Form = 0, Level = 80, Location = 086, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Arceus @ Hall of Origin (Unreleased) }; @@ -887,14 +375,14 @@ private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas) private static readonly EncounterStaticTyped[] Encounter_HGSS_KantoRoam_Grass = { - new EncounterStaticTyped { Species = 380, Level = 35, Version = GameVersion.HG, Roaming = true, TypeEncounter = EncounterType.TallGrass, }, // Latias - new EncounterStaticTyped { Species = 381, Level = 35, Version = GameVersion.SS, Roaming = true, TypeEncounter = EncounterType.TallGrass, }, // Latios + new EncounterStaticTyped { Species = 380, Level = 35, Version = HG, Roaming = true, TypeEncounter = EncounterType.TallGrass, }, // Latias + new EncounterStaticTyped { Species = 381, Level = 35, Version = SS, Roaming = true, TypeEncounter = EncounterType.TallGrass, }, // Latios }; private static readonly EncounterStaticTyped[] Encounter_HGSS_KantoRoam_Surf = { - new EncounterStaticTyped { Species = 380, Level = 35, Version = GameVersion.HG, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, }, // Latias - new EncounterStaticTyped { Species = 381, Level = 35, Version = GameVersion.SS, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, }, // Latios + new EncounterStaticTyped { Species = 380, Level = 35, Version = HG, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, }, // Latias + new EncounterStaticTyped { Species = 381, Level = 35, Version = SS, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, }, // Latios }; internal static readonly EncounterStaticTyped SpikyEaredPichu = new EncounterStaticTyped // Spiky-Eared Pichu @ Ilex Forest @@ -933,6 +421,7 @@ private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas) new EncounterStaticTyped { Gift = true, Species = 410, Level = 20, Location = 140, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Shieldon // Gift + new EncounterStaticTyped { Gift = true, Species = 072, Level = 15, Location = 130, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Tentacool @ Cianwood City new EncounterStaticTyped { Gift = true, Species = 133, Level = 05, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Eevee @ Goldenrod City new EncounterStaticTyped { Gift = true, Species = 147, Level = 15, Location = 222, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Moves = new[] {245} }, // Dratini @ Dragon's Den (ExtremeSpeed) new EncounterStaticTyped { Gift = true, Species = 236, Level = 10, Location = 216, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Tyrogue @ Mt. Mortar @@ -948,8 +437,8 @@ private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas) // Goldenrod City Game Corner new EncounterStaticTyped { Gift = true, Species = 063, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Abra - new EncounterStaticTyped { Gift = true, Species = 023, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.HG }, // Ekans - new EncounterStaticTyped { Gift = true, Species = 027, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = GameVersion.SS }, // Sandshrew + new EncounterStaticTyped { Gift = true, Species = 023, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = HG }, // Ekans + new EncounterStaticTyped { Gift = true, Species = 027, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Version = SS }, // Sandshrew new EncounterStaticTyped { Gift = true, Species = 147, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Dratini // Team Rocket HQ Trap Floor @@ -973,14 +462,14 @@ private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas) new EncounterStaticTyped { Species = 150, Level = 70, Location = 199, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Mewtwo @ Cerulean Cave new EncounterStatic4 { Species = 245, Level = 40, Location = 173, }, // Suicune @ Route 25 new EncounterStaticTyped { Species = 245, Level = 40, Location = 206, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Suicune @ Burned Tower - new EncounterStaticTyped { Species = 249, Level = 45, Location = 218, Version = GameVersion.SS, TypeEncounter = EncounterType.Surfing_Fishing }, // Lugia @ Whirl Islands - new EncounterStaticTyped { Species = 249, Level = 70, Location = 218, Version = GameVersion.HG, TypeEncounter = EncounterType.Surfing_Fishing }, // Lugia @ Whirl Islands - new EncounterStaticTyped { Species = 250, Level = 45, Location = 205, Version = GameVersion.HG, TypeEncounter = EncounterType.Building_EnigmaStone }, // Ho-Oh @ Bell Tower - new EncounterStaticTyped { Species = 250, Level = 70, Location = 205, Version = GameVersion.SS, TypeEncounter = EncounterType.Building_EnigmaStone }, // Ho-Oh @ Bell Tower - new EncounterStaticTyped { Species = 380, Level = 40, Location = 140, Version = GameVersion.SS, TypeEncounter = EncounterType.Building_EnigmaStone }, // Latias @ Pewter City - new EncounterStaticTyped { Species = 381, Level = 40, Location = 140, Version = GameVersion.HG, TypeEncounter = EncounterType.Building_EnigmaStone }, // Latios @ Pewter City - new EncounterStaticTyped { Species = 382, Level = 50, Location = 232, Version = GameVersion.HG, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Kyogre @ Embedded Tower - new EncounterStaticTyped { Species = 383, Level = 50, Location = 232, Version = GameVersion.SS, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Groudon @ Embedded Tower + new EncounterStaticTyped { Species = 249, Level = 45, Location = 218, Version = SS, TypeEncounter = EncounterType.Surfing_Fishing }, // Lugia @ Whirl Islands + new EncounterStaticTyped { Species = 249, Level = 70, Location = 218, Version = HG, TypeEncounter = EncounterType.Surfing_Fishing }, // Lugia @ Whirl Islands + new EncounterStaticTyped { Species = 250, Level = 45, Location = 205, Version = HG, TypeEncounter = EncounterType.Building_EnigmaStone }, // Ho-Oh @ Bell Tower + new EncounterStaticTyped { Species = 250, Level = 70, Location = 205, Version = SS, TypeEncounter = EncounterType.Building_EnigmaStone }, // Ho-Oh @ Bell Tower + new EncounterStaticTyped { Species = 380, Level = 40, Location = 140, Version = SS, TypeEncounter = EncounterType.Building_EnigmaStone }, // Latias @ Pewter City + new EncounterStaticTyped { Species = 381, Level = 40, Location = 140, Version = HG, TypeEncounter = EncounterType.Building_EnigmaStone }, // Latios @ Pewter City + new EncounterStaticTyped { Species = 382, Level = 50, Location = 232, Version = HG, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Kyogre @ Embedded Tower + new EncounterStaticTyped { Species = 383, Level = 50, Location = 232, Version = SS, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Groudon @ Embedded Tower new EncounterStaticTyped { Species = 384, Level = 50, Location = 232, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Rayquaza @ Embedded Tower new EncounterStaticTyped { Species = 483, Level = 01, Location = 231, Gift = true, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Dialga @ Sinjoh Ruins new EncounterStaticTyped { Species = 484, Level = 01, Location = 231, Gift = true, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Palkia @ Sinjoh Ruins @@ -999,28 +488,28 @@ private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas) private static readonly EncounterTrade[] RanchGifts = { - new EncounterTrade4PID(323975838) { Species = 025, Level = 18, Moves = new[] {447,085,148,104}, TID = 1000, SID = 19840, OTGender = 1, Version = GameVersion.D, Location = 0068, Gender = 0, Ability = 1, CurrentLevel = 20, }, // Pikachu - new EncounterTrade4PID(323977664) { Species = 037, Level = 16, Moves = new[] {412,109,053,219}, TID = 1000, SID = 21150, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 0, Ability = 1, CurrentLevel = 30, }, // Vulpix - new EncounterTrade4PID(323975579) { Species = 077, Level = 13, Moves = new[] {036,033,039,052}, TID = 1000, SID = 01123, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 0, Ability = 2, CurrentLevel = 16, }, // Ponyta - new EncounterTrade4PID(323975564) { Species = 108, Level = 34, Moves = new[] {076,111,014,205}, TID = 1000, SID = 03050, OTGender = 1, Version = GameVersion.D, Location = 0077, Gender = 0, Ability = 1, CurrentLevel = 40, }, // Lickitung - new EncounterTrade4PID(323977579) { Species = 114, Level = 01, Moves = new[] {437,438,079,246}, TID = 1000, SID = 49497, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 1, Ability = 2, }, // Tangela - new EncounterTrade4PID(323977675) { Species = 133, Level = 16, Moves = new[] {363,270,098,247}, TID = 1000, SID = 47710, OTGender = 1, Version = GameVersion.D, Location = 0068, Gender = 0, Ability = 2, CurrentLevel = 30, }, // Eevee - new EncounterTrade4PID(323977588) { Species = 142, Level = 20, Moves = new[] {363,089,444,332}, TID = 1000, SID = 43066, OTGender = 1, Version = GameVersion.D, Location = 0094, Gender = 0, Ability = 1, CurrentLevel = 50, }, // Aerodactyl - new EncounterTrade4 { Species = 151, Level = 50, Moves = new[] {235,216,095,100}, TID = 1000, SID = 59228, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 2, Fateful = true, Ball = 0x10, }, // Mew - new EncounterTrade4PID(232975554) { Species = 193, Level = 22, Moves = new[] {318,095,246,138}, TID = 1000, SID = 42301, OTGender = 1, Version = GameVersion.D, Location = 0052, Gender = 0, Ability = 1, CurrentLevel = 45, Ball = 0x05, }, // Yanma - new EncounterTrade4PID(323975570) { Species = 241, Level = 16, Moves = new[] {208,215,360,359}, TID = 1000, SID = 02707, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 1, Ability = 1, CurrentLevel = 48, }, // Miltank - new EncounterTrade4PID(323975563) { Species = 285, Level = 22, Moves = new[] {402,147,206,078}, TID = 1000, SID = 02788, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 0, Ability = 2, CurrentLevel = 45, Ball = 0x05, }, // Shroomish - new EncounterTrade4PID(323975559) { Species = 320, Level = 30, Moves = new[] {156,323,133,058}, TID = 1000, SID = 27046, OTGender = 1, Version = GameVersion.D, Location = 0038, Gender = 0, Ability = 2, CurrentLevel = 45, }, // Wailmer - new EncounterTrade4PID(323977657) { Species = 360, Level = 01, Moves = new[] {204,150,227,000}, TID = 1000, SID = 01788, OTGender = 1, Version = GameVersion.D, Location = 0004, Gender = 0, Ability = 2, EggLocation = 2000, }, // Wynaut - new EncounterTrade4PID(323975563) { Species = 397, Level = 02, Moves = new[] {355,017,283,018}, TID = 1000, SID = 59298, OTGender = 1, Version = GameVersion.D, Location = 0016, Gender = 0, Ability = 2, CurrentLevel = 23, }, // Staravia - new EncounterTrade4PID(323970584) { Species = 415, Level = 05, Moves = new[] {230,016,000,000}, TID = 1000, SID = 54140, OTGender = 1, Version = GameVersion.D, Location = 0020, Gender = 1, Ability = 1, CurrentLevel = 20, }, // Combee - new EncounterTrade4PID(323977539) { Species = 417, Level = 09, Moves = new[] {447,045,351,098}, TID = 1000, SID = 18830, OTGender = 1, Version = GameVersion.D, Location = 0020, Gender = 1, Ability = 2, CurrentLevel = 10, }, // Pachirisu - new EncounterTrade4PID(323974107) { Species = 422, Level = 20, Moves = new[] {363,352,426,104}, TID = 1000, SID = 39272, OTGender = 1, Version = GameVersion.D, Location = 0028, Gender = 0, Ability = 2, CurrentLevel = 25, Form = 1 }, // Shellos - new EncounterTrade4PID(323977566) { Species = 427, Level = 10, Moves = new[] {204,193,409,098}, TID = 1000, SID = 31045, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 1, Ability = 1, CurrentLevel = 16, }, // Buneary - new EncounterTrade4PID(323975579) { Species = 453, Level = 22, Moves = new[] {310,207,426,389}, TID = 1000, SID = 41342, OTGender = 1, Version = GameVersion.D, Location = 0052, Gender = 0, Ability = 2, CurrentLevel = 31, Ball = 0x05, }, // Croagunk - new EncounterTrade4PID(323977566) { Species = 456, Level = 15, Moves = new[] {213,352,219,392}, TID = 1000, SID = 48348, OTGender = 1, Version = GameVersion.D, Location = 0020, Gender = 1, Ability = 1, CurrentLevel = 35, }, // Finneon - new EncounterTrade4PID(323975582) { Species = 459, Level = 32, Moves = new[] {452,420,275,059}, TID = 1000, SID = 23360, OTGender = 1, Version = GameVersion.D, Location = 0031, Gender = 0, Ability = 1, CurrentLevel = 41, }, // Snover - new EncounterTrade4 { Species = 489, Level = 01, Moves = new[] {447,240,156,057}, TID = 1000, SID = 09248, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 2, Fateful = true, CurrentLevel = 50, Ball = 0x10, EggLocation = 3000, }, // Phione + new EncounterTrade4PID(323975838) { Species = 025, Level = 18, Moves = new[] {447,085,148,104}, TID = 1000, SID = 19840, OTGender = 1, Version = D, Location = 0068, Gender = 0, Ability = 1, CurrentLevel = 20, }, // Pikachu + new EncounterTrade4PID(323977664) { Species = 037, Level = 16, Moves = new[] {412,109,053,219}, TID = 1000, SID = 21150, OTGender = 1, Version = D, Location = 3000, Gender = 0, Ability = 1, CurrentLevel = 30, }, // Vulpix + new EncounterTrade4PID(323975579) { Species = 077, Level = 13, Moves = new[] {036,033,039,052}, TID = 1000, SID = 01123, OTGender = 1, Version = D, Location = 3000, Gender = 0, Ability = 2, CurrentLevel = 16, }, // Ponyta + new EncounterTrade4PID(323975564) { Species = 108, Level = 34, Moves = new[] {076,111,014,205}, TID = 1000, SID = 03050, OTGender = 1, Version = D, Location = 0077, Gender = 0, Ability = 1, CurrentLevel = 40, }, // Lickitung + new EncounterTrade4PID(323977579) { Species = 114, Level = 01, Moves = new[] {437,438,079,246}, TID = 1000, SID = 49497, OTGender = 1, Version = D, Location = 3000, Gender = 1, Ability = 2, }, // Tangela + new EncounterTrade4PID(323977675) { Species = 133, Level = 16, Moves = new[] {363,270,098,247}, TID = 1000, SID = 47710, OTGender = 1, Version = D, Location = 0068, Gender = 0, Ability = 2, CurrentLevel = 30, }, // Eevee + new EncounterTrade4PID(323977588) { Species = 142, Level = 20, Moves = new[] {363,089,444,332}, TID = 1000, SID = 43066, OTGender = 1, Version = D, Location = 0094, Gender = 0, Ability = 1, CurrentLevel = 50, }, // Aerodactyl + new EncounterTrade4 { Species = 151, Level = 50, Moves = new[] {235,216,095,100}, TID = 1000, SID = 59228, OTGender = 1, Version = D, Location = 3000, Gender = 2, Fateful = true, Ball = 0x10, }, // Mew + new EncounterTrade4PID(232975554) { Species = 193, Level = 22, Moves = new[] {318,095,246,138}, TID = 1000, SID = 42301, OTGender = 1, Version = D, Location = 0052, Gender = 0, Ability = 1, CurrentLevel = 45, Ball = 0x05, }, // Yanma + new EncounterTrade4PID(323975570) { Species = 241, Level = 16, Moves = new[] {208,215,360,359}, TID = 1000, SID = 02707, OTGender = 1, Version = D, Location = 3000, Gender = 1, Ability = 1, CurrentLevel = 48, }, // Miltank + new EncounterTrade4PID(323975563) { Species = 285, Level = 22, Moves = new[] {402,147,206,078}, TID = 1000, SID = 02788, OTGender = 1, Version = D, Location = 3000, Gender = 0, Ability = 2, CurrentLevel = 45, Ball = 0x05, }, // Shroomish + new EncounterTrade4PID(323975559) { Species = 320, Level = 30, Moves = new[] {156,323,133,058}, TID = 1000, SID = 27046, OTGender = 1, Version = D, Location = 0038, Gender = 0, Ability = 2, CurrentLevel = 45, }, // Wailmer + new EncounterTrade4PID(323977657) { Species = 360, Level = 01, Moves = new[] {204,150,227,000}, TID = 1000, SID = 01788, OTGender = 1, Version = D, Location = 0004, Gender = 0, Ability = 2, EggLocation = 2000, }, // Wynaut + new EncounterTrade4PID(323975563) { Species = 397, Level = 02, Moves = new[] {355,017,283,018}, TID = 1000, SID = 59298, OTGender = 1, Version = D, Location = 0016, Gender = 0, Ability = 2, CurrentLevel = 23, }, // Staravia + new EncounterTrade4PID(323970584) { Species = 415, Level = 05, Moves = new[] {230,016,000,000}, TID = 1000, SID = 54140, OTGender = 1, Version = D, Location = 0020, Gender = 1, Ability = 1, CurrentLevel = 20, }, // Combee + new EncounterTrade4PID(323977539) { Species = 417, Level = 09, Moves = new[] {447,045,351,098}, TID = 1000, SID = 18830, OTGender = 1, Version = D, Location = 0020, Gender = 1, Ability = 2, CurrentLevel = 10, }, // Pachirisu + new EncounterTrade4PID(323974107) { Species = 422, Level = 20, Moves = new[] {363,352,426,104}, TID = 1000, SID = 39272, OTGender = 1, Version = D, Location = 0028, Gender = 0, Ability = 2, CurrentLevel = 25, Form = 1 }, // Shellos + new EncounterTrade4PID(323977566) { Species = 427, Level = 10, Moves = new[] {204,193,409,098}, TID = 1000, SID = 31045, OTGender = 1, Version = D, Location = 3000, Gender = 1, Ability = 1, CurrentLevel = 16, }, // Buneary + new EncounterTrade4PID(323975579) { Species = 453, Level = 22, Moves = new[] {310,207,426,389}, TID = 1000, SID = 41342, OTGender = 1, Version = D, Location = 0052, Gender = 0, Ability = 2, CurrentLevel = 31, Ball = 0x05, }, // Croagunk + new EncounterTrade4PID(323977566) { Species = 456, Level = 15, Moves = new[] {213,352,219,392}, TID = 1000, SID = 48348, OTGender = 1, Version = D, Location = 0020, Gender = 1, Ability = 1, CurrentLevel = 35, }, // Finneon + new EncounterTrade4PID(323975582) { Species = 459, Level = 32, Moves = new[] {452,420,275,059}, TID = 1000, SID = 23360, OTGender = 1, Version = D, Location = 0031, Gender = 0, Ability = 1, CurrentLevel = 41, }, // Snover + new EncounterTrade4 { Species = 489, Level = 01, Moves = new[] {447,240,156,057}, TID = 1000, SID = 09248, OTGender = 1, Version = D, Location = 3000, Gender = 2, Fateful = true, CurrentLevel = 50, Ball = 0x10, EggLocation = 3000, }, // Phione }; internal static readonly EncounterTrade[] TradeGift_DPPt = new [] @@ -1055,596 +544,10 @@ private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas) private static readonly string[][] TradeHGSS = Util.GetLanguageStrings8(tradeHGSS); #endregion - #region Alt Slots - - private static readonly EncounterArea4DPPt[] DPPt_Unown = - { - new EncounterArea4DPPt { - Location = 53, // Solaceon Ruins - Slots = Enumerable.Range(1, 27).Select(i => new EncounterSlot4 { Species = 201, LevelMin = 14, LevelMax = 30, Type = SlotType.Grass, Form = i }).ToArray() // B->?, Unown A is loaded from encounters raw file - }, - }; - - private static readonly EncounterArea4HGSS SlotsHGSS_BCC = - - new EncounterArea4HGSS - { - // Source http://bulbapedia.bulbagarden.net/wiki/Bug-Catching_Contest#Generation_IV - Location = 207, // National Park Catching Contest - Slots = new[] - { - // Bug Contest Pre-National Pokédex - new EncounterSlot4 { Species = 010, LevelMin = 07, LevelMax = 18, Type = SlotType.BugContest, SlotNumber = 0 }, // Caterpie - new EncounterSlot4 { Species = 013, LevelMin = 07, LevelMax = 18, Type = SlotType.BugContest, SlotNumber = 1 }, // Weedle - new EncounterSlot4 { Species = 011, LevelMin = 09, LevelMax = 18, Type = SlotType.BugContest, SlotNumber = 2 }, // Metapod - new EncounterSlot4 { Species = 014, LevelMin = 09, LevelMax = 18, Type = SlotType.BugContest, SlotNumber = 3 }, // Kakuna - new EncounterSlot4 { Species = 012, LevelMin = 12, LevelMax = 15, Type = SlotType.BugContest, SlotNumber = 4 }, // Butterfree - new EncounterSlot4 { Species = 015, LevelMin = 12, LevelMax = 15, Type = SlotType.BugContest, SlotNumber = 5 }, // Beedrill - new EncounterSlot4 { Species = 048, LevelMin = 10, LevelMax = 16, Type = SlotType.BugContest, SlotNumber = 6 }, // Venonat - new EncounterSlot4 { Species = 046, LevelMin = 10, LevelMax = 17, Type = SlotType.BugContest, SlotNumber = 7 }, // Paras - new EncounterSlot4 { Species = 123, LevelMin = 13, LevelMax = 14, Type = SlotType.BugContest, SlotNumber = 8 }, // Scyther - new EncounterSlot4 { Species = 127, LevelMin = 13, LevelMax = 14, Type = SlotType.BugContest, SlotNumber = 9 }, // Pinsir - // Bug Contest Tuesday Post-National Pokédex - new EncounterSlot4 { Species = 010, LevelMin = 24, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 0 }, // Caterpie - new EncounterSlot4 { Species = 013, LevelMin = 24, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 1 }, // Weedle - new EncounterSlot4 { Species = 011, LevelMin = 26, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 2 }, // Metapod - new EncounterSlot4 { Species = 014, LevelMin = 26, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 3 }, // Kakuna - new EncounterSlot4 { Species = 012, LevelMin = 27, LevelMax = 30, Type = SlotType.BugContest, SlotNumber = 4 }, // Butterfree - new EncounterSlot4 { Species = 015, LevelMin = 27, LevelMax = 30, Type = SlotType.BugContest, SlotNumber = 5 }, // Beedrill - new EncounterSlot4 { Species = 048, LevelMin = 25, LevelMax = 32, Type = SlotType.BugContest, SlotNumber = 6 }, // Venonat - new EncounterSlot4 { Species = 046, LevelMin = 27, LevelMax = 34, Type = SlotType.BugContest, SlotNumber = 7 }, // Paras - new EncounterSlot4 { Species = 123, LevelMin = 27, LevelMax = 28, Type = SlotType.BugContest, SlotNumber = 8 }, // Scyther - new EncounterSlot4 { Species = 127, LevelMin = 27, LevelMax = 28, Type = SlotType.BugContest, SlotNumber = 9 }, // Pinsir - - // Bug Contest Thursday and Saturday Post-National Pokédex - new EncounterSlot4 { Species = 265, LevelMin = 24, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 0 }, // Wurmple - new EncounterSlot4 { Species = 266, LevelMin = 24, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 1 }, // Silcoon (Thursday) - new EncounterSlot4 { Species = 268, LevelMin = 24, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 1 }, // Cascoon (Saturday) - new EncounterSlot4 { Species = 290, LevelMin = 26, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 2 }, // Nincada - new EncounterSlot4 { Species = 313, LevelMin = 26, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 3 }, // Volbeat (Thursday) - new EncounterSlot4 { Species = 314, LevelMin = 26, LevelMax = 36, Type = SlotType.BugContest, SlotNumber = 3 }, // Illumise (Saturday) - new EncounterSlot4 { Species = 401, LevelMin = 27, LevelMax = 30, Type = SlotType.BugContest, SlotNumber = 4 }, // Kricketot - new EncounterSlot4 { Species = 402, LevelMin = 27, LevelMax = 30, Type = SlotType.BugContest, SlotNumber = 5 }, // Kricketune - new EncounterSlot4 { Species = 269, LevelMin = 25, LevelMax = 32, Type = SlotType.BugContest, SlotNumber = 6 }, // Dustox (Thursday) - new EncounterSlot4 { Species = 267, LevelMin = 25, LevelMax = 32, Type = SlotType.BugContest, SlotNumber = 6 }, // Beautifly (Saturday) - new EncounterSlot4 { Species = 415, LevelMin = 27, LevelMax = 34, Type = SlotType.BugContest, SlotNumber = 7 }, // Combee - new EncounterSlot4 { Species = 123, LevelMin = 27, LevelMax = 28, Type = SlotType.BugContest, SlotNumber = 8 }, // Scyther - new EncounterSlot4 { Species = 127, LevelMin = 27, LevelMax = 28, Type = SlotType.BugContest, SlotNumber = 9 }, // Pinsir - } - }; - - private static readonly EncounterSlot[] SAFARIZONE_PEAK = - { - new EncounterSlot4 { Species = 022, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Fearow - new EncounterSlot4 { Species = 046, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Paras - new EncounterSlot4 { Species = 074, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Geodude - new EncounterSlot4 { Species = 075, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Graveler - new EncounterSlot4 { Species = 080, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Slowbro - new EncounterSlot4 { Species = 081, LevelMin = 15, LevelMax = 16, Type = SlotType.Grass_Safari }, // Magnemite - new EncounterSlot4 { Species = 082, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Magneton - new EncounterSlot4 { Species = 126, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Magmar - new EncounterSlot4 { Species = 126, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Magmar - new EncounterSlot4 { Species = 202, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Wobbuffet - new EncounterSlot4 { Species = 202, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Wobbuffet - new EncounterSlot4 { Species = 264, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Linoone - new EncounterSlot4 { Species = 288, LevelMin = 47, LevelMax = 47, Type = SlotType.Grass_Safari }, // Vigoroth - new EncounterSlot4 { Species = 305, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Lairon - new EncounterSlot4 { Species = 335, LevelMin = 43, LevelMax = 45, Type = SlotType.Grass_Safari }, // Zangoose - new EncounterSlot4 { Species = 363, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Spheal - new EncounterSlot4 { Species = 436, LevelMin = 45, LevelMax = 46, Type = SlotType.Grass_Safari }, // Bronzor - }; - - private static readonly EncounterSlot[] SAFARIZONE_DESERT = - { - new EncounterSlot4 { Species = 022, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Fearow - new EncounterSlot4 { Species = 022, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Fearow - new EncounterSlot4 { Species = 022, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Fearow - new EncounterSlot4 { Species = 027, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Sandshrew - new EncounterSlot4 { Species = 028, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Sandslash - new EncounterSlot4 { Species = 104, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Cubone - new EncounterSlot4 { Species = 105, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Marowak - new EncounterSlot4 { Species = 105, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Marowak - new EncounterSlot4 { Species = 270, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Lotad - new EncounterSlot4 { Species = 327, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Spinda - new EncounterSlot4 { Species = 328, LevelMin = 46, LevelMax = 47, Type = SlotType.Grass_Safari }, // Trapinch - new EncounterSlot4 { Species = 329, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Vibrava - new EncounterSlot4 { Species = 331, LevelMin = 35, LevelMax = 35, Type = SlotType.Grass_Safari }, // Cacnea - new EncounterSlot4 { Species = 332, LevelMin = 48, LevelMax = 48, Type = SlotType.Grass_Safari }, // Cacturne - new EncounterSlot4 { Species = 449, LevelMin = 43, LevelMax = 43, Type = SlotType.Grass_Safari }, // Hippopotas - new EncounterSlot4 { Species = 455, LevelMin = 48, LevelMax = 48, Type = SlotType.Grass_Safari }, // Carnivine - }; - - private static readonly EncounterSlot[] SAFARIZONE_PLAINS = - { - new EncounterSlot4 { Species = 019, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Rattata - new EncounterSlot4 { Species = 020, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Raticate - new EncounterSlot4 { Species = 063, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Abra - new EncounterSlot4 { Species = 077, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Ponyta - new EncounterSlot4 { Species = 203, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Girafarig - new EncounterSlot4 { Species = 203, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Girafarig - new EncounterSlot4 { Species = 229, LevelMin = 43, LevelMax = 44, Type = SlotType.Grass_Safari }, // Houndoom - new EncounterSlot4 { Species = 234, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Stantler - new EncounterSlot4 { Species = 234, LevelMin = 40, LevelMax = 41, Type = SlotType.Grass_Safari }, // Stantler - new EncounterSlot4 { Species = 235, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Smeargle - new EncounterSlot4 { Species = 235, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Smeargle - new EncounterSlot4 { Species = 263, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Zigzagoon - new EncounterSlot4 { Species = 270, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Lotad - new EncounterSlot4 { Species = 283, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Surskit - new EncounterSlot4 { Species = 310, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Manectric - new EncounterSlot4 { Species = 335, LevelMin = 43, LevelMax = 45, Type = SlotType.Grass_Safari }, // Zangoose - new EncounterSlot4 { Species = 403, LevelMin = 43, LevelMax = 44, Type = SlotType.Grass_Safari }, // Shinx - }; - - private static readonly EncounterSlot[] SAFARIZONE_MEADOW = - { - new EncounterSlot4 { Species = 020, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Raticate - new EncounterSlot4 { Species = 035, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Clefairy - new EncounterSlot4 { Species = 035, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Clefairy - new EncounterSlot4 { Species = 039, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Jigglypuff - new EncounterSlot4 { Species = 060, LevelMin = 12, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 060, LevelMin = 22, LevelMax = 24, Type = SlotType.Good_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 060, LevelMin = 35, LevelMax = 36, Type = SlotType.Super_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 061, LevelMin = 15, LevelMax = 16, Type = SlotType.Old_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 061, LevelMin = 24, LevelMax = 25, Type = SlotType.Good_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 061, LevelMin = 27, LevelMax = 27, Type = SlotType.Good_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 061, LevelMin = 35, LevelMax = 38, Type = SlotType.Super_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 074, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Geodude - new EncounterSlot4 { Species = 113, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Chansey - new EncounterSlot4 { Species = 129, LevelMin = 15, LevelMax = 17, Type = SlotType.Surf_Safari }, // Magikarp - new EncounterSlot4 { Species = 129, LevelMin = 12, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 129, LevelMin = 22, LevelMax = 24, Type = SlotType.Good_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 130, LevelMin = 28, LevelMax = 28, Type = SlotType.Good_Rod_Safari }, // Gyarados - new EncounterSlot4 { Species = 130, LevelMin = 42, LevelMax = 42, Type = SlotType.Super_Rod_Safari }, // Gyarados - new EncounterSlot4 { Species = 130, LevelMin = 45, LevelMax = 45, Type = SlotType.Super_Rod_Safari }, // Gyarados - new EncounterSlot4 { Species = 183, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Marill - new EncounterSlot4 { Species = 183, LevelMin = 16, LevelMax = 17, Type = SlotType.Surf_Safari }, // Marill - new EncounterSlot4 { Species = 187, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Hoppip - new EncounterSlot4 { Species = 188, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Skiploom - new EncounterSlot4 { Species = 188, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Skiploom - new EncounterSlot4 { Species = 188, LevelMin = 47, LevelMax = 47, Type = SlotType.Surf_Safari }, // Skiploom - new EncounterSlot4 { Species = 191, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Sunkern - new EncounterSlot4 { Species = 194, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Wooper - new EncounterSlot4 { Species = 194, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Wooper - new EncounterSlot4 { Species = 194, LevelMin = 15, LevelMax = 17, Type = SlotType.Surf_Safari }, // Wooper - new EncounterSlot4 { Species = 273, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Seedot - new EncounterSlot4 { Species = 274, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Nuzleaf - new EncounterSlot4 { Species = 274, LevelMin = 47, LevelMax = 48, Type = SlotType.Grass_Safari }, // Nuzleaf - new EncounterSlot4 { Species = 284, LevelMin = 42, LevelMax = 42, Type = SlotType.Surf_Safari }, // Masquerain - new EncounterSlot4 { Species = 284, LevelMin = 46, LevelMax = 46, Type = SlotType.Surf_Safari }, // Masquerain - new EncounterSlot4 { Species = 299, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Nosepass - new EncounterSlot4 { Species = 447, LevelMin = 45, LevelMax = 46, Type = SlotType.Grass_Safari }, // Riolu - }; - - private static readonly EncounterSlot[] SAFARIZONE_FOREST = - { - new EncounterSlot4 { Species = 016, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Pidgey - new EncounterSlot4 { Species = 069, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Bellsprout - new EncounterSlot4 { Species = 092, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Gastly - new EncounterSlot4 { Species = 093, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Haunter - new EncounterSlot4 { Species = 108, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Lickitung - new EncounterSlot4 { Species = 122, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Mr. Mime - new EncounterSlot4 { Species = 122, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Mr. Mime - new EncounterSlot4 { Species = 125, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Electabuzz - new EncounterSlot4 { Species = 200, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Misdreavus - new EncounterSlot4 { Species = 200, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Misdreavus - new EncounterSlot4 { Species = 283, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Surskit - new EncounterSlot4 { Species = 353, LevelMin = 46, LevelMax = 47, Type = SlotType.Grass_Safari }, // Shuppet - new EncounterSlot4 { Species = 374, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Beldum - new EncounterSlot4 { Species = 399, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Bidoof - new EncounterSlot4 { Species = 406, LevelMin = 47, LevelMax = 47, Type = SlotType.Grass_Safari }, // Budew - new EncounterSlot4 { Species = 437, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Bronzong - }; - - private static readonly EncounterSlot[] SAFARIZONE_SWAMP = - { - new EncounterSlot4 { Species = 039, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Jigglypuff - new EncounterSlot4 { Species = 046, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Paras - new EncounterSlot4 { Species = 047, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Parasect - new EncounterSlot4 { Species = 070, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Weepinbell - new EncounterSlot4 { Species = 096, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Drowzee - new EncounterSlot4 { Species = 097, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Hypno - new EncounterSlot4 { Species = 097, LevelMin = 37, LevelMax = 37, Type = SlotType.Grass_Safari }, // Hypno - new EncounterSlot4 { Species = 100, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Voltorb - new EncounterSlot4 { Species = 118, LevelMin = 15, LevelMax = 17, Type = SlotType.Surf_Safari }, // Goldeen - new EncounterSlot4 { Species = 118, LevelMin = 17, LevelMax = 17, Type = SlotType.Old_Rod_Safari }, // Goldeen - new EncounterSlot4 { Species = 118, LevelMin = 22, LevelMax = 24, Type = SlotType.Good_Rod_Safari }, // Goldeen - new EncounterSlot4 { Species = 118, LevelMin = 35, LevelMax = 37, Type = SlotType.Super_Rod_Safari }, // Goldeen - new EncounterSlot4 { Species = 119, LevelMin = 17, LevelMax = 17, Type = SlotType.Old_Rod_Safari }, // Seaking - new EncounterSlot4 { Species = 119, LevelMin = 24, LevelMax = 25, Type = SlotType.Good_Rod_Safari }, // Seaking - new EncounterSlot4 { Species = 119, LevelMin = 27, LevelMax = 27, Type = SlotType.Good_Rod_Safari }, // Seaking - new EncounterSlot4 { Species = 119, LevelMin = 35, LevelMax = 37, Type = SlotType.Super_Rod_Safari }, // Seaking - new EncounterSlot4 { Species = 119, LevelMin = 42, LevelMax = 42, Type = SlotType.Surf_Safari }, // Seaking - new EncounterSlot4 { Species = 129, LevelMin = 12, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 129, LevelMin = 22, LevelMax = 24, Type = SlotType.Good_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 129, LevelMin = 15, LevelMax = 17, Type = SlotType.Surf_Safari }, // Magikarp - new EncounterSlot4 { Species = 147, LevelMin = 36, LevelMax = 37, Type = SlotType.Super_Rod_Safari }, // Dratini - new EncounterSlot4 { Species = 147, LevelMin = 29, LevelMax = 29, Type = SlotType.Good_Rod_Safari }, // Dratini - new EncounterSlot4 { Species = 148, LevelMin = 42, LevelMax = 42, Type = SlotType.Super_Rod_Safari }, // Dragonair - new EncounterSlot4 { Species = 148, LevelMin = 45, LevelMax = 45, Type = SlotType.Super_Rod_Safari }, // Dragonair - new EncounterSlot4 { Species = 161, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Sentret - new EncounterSlot4 { Species = 162, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Furret - new EncounterSlot4 { Species = 198, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Murkrow - new EncounterSlot4 { Species = 198, LevelMin = 37, LevelMax = 37, Type = SlotType.Grass_Safari }, // Murkrow - new EncounterSlot4 { Species = 198, LevelMin = 47, LevelMax = 47, Type = SlotType.Surf_Safari }, // Murkrow - new EncounterSlot4 { Species = 355, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Duskull - new EncounterSlot4 { Species = 355, LevelMin = 48, LevelMax = 48, Type = SlotType.Surf_Safari }, // Duskull - new EncounterSlot4 { Species = 358, LevelMin = 46, LevelMax = 47, Type = SlotType.Grass_Safari }, // Chimecho - new EncounterSlot4 { Species = 371, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Bagon - new EncounterSlot4 { Species = 417, LevelMin = 47, LevelMax = 47, Type = SlotType.Grass_Safari }, // Pachirisu - new EncounterSlot4 { Species = 419, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Floatzel - }; - - private static readonly EncounterSlot[] SAFARIZONE_MARSHLAND = - { - new EncounterSlot4 { Species = 023, LevelMin = 15, LevelMax = 16, Type = SlotType.Grass_Safari }, // Ekans - new EncounterSlot4 { Species = 024, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Arbok - new EncounterSlot4 { Species = 043, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Oddish - new EncounterSlot4 { Species = 044, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Gloom - new EncounterSlot4 { Species = 044, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Gloom - new EncounterSlot4 { Species = 050, LevelMin = 43, LevelMax = 43, Type = SlotType.Grass_Safari }, // Diglett - new EncounterSlot4 { Species = 060, LevelMin = 12, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 060, LevelMin = 15, LevelMax = 17, Type = SlotType.Surf_Safari }, // Poliwag - new EncounterSlot4 { Species = 060, LevelMin = 16, LevelMax = 16, Type = SlotType.Old_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 060, LevelMin = 18, LevelMax = 18, Type = SlotType.Old_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 061, LevelMin = 22, LevelMax = 25, Type = SlotType.Good_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 061, LevelMin = 35, LevelMax = 38, Type = SlotType.Super_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 088, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Grimer - new EncounterSlot4 { Species = 088, LevelMin = 15, LevelMax = 17, Type = SlotType.Surf_Safari }, // Grimer - new EncounterSlot4 { Species = 089, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Muk - new EncounterSlot4 { Species = 089, LevelMin = 48, LevelMax = 48, Type = SlotType.Surf_Safari }, // Muk - new EncounterSlot4 { Species = 109, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Koffing - new EncounterSlot4 { Species = 110, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Weezing - new EncounterSlot4 { Species = 129, LevelMin = 12, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 129, LevelMin = 22, LevelMax = 24, Type = SlotType.Good_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 130, LevelMin = 36, LevelMax = 37, Type = SlotType.Super_Rod_Safari }, // Gyarados - new EncounterSlot4 { Species = 130, LevelMin = 26, LevelMax = 26, Type = SlotType.Good_Rod_Safari }, // Gyarados - new EncounterSlot4 { Species = 130, LevelMin = 29, LevelMax = 29, Type = SlotType.Good_Rod_Safari }, // Gyarados - new EncounterSlot4 { Species = 189, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Jumpluff - new EncounterSlot4 { Species = 189, LevelMin = 47, LevelMax = 47, Type = SlotType.Surf_Safari }, // Jumpluff - new EncounterSlot4 { Species = 194, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Wooper - new EncounterSlot4 { Species = 194, LevelMin = 15, LevelMax = 17, Type = SlotType.Surf_Safari }, // Wooper - new EncounterSlot4 { Species = 195, LevelMin = 43, LevelMax = 43, Type = SlotType.Surf_Safari }, // Quagsire - new EncounterSlot4 { Species = 213, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Shuckle - new EncounterSlot4 { Species = 315, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Roselia - new EncounterSlot4 { Species = 336, LevelMin = 47, LevelMax = 48, Type = SlotType.Grass_Safari }, // Seviper - new EncounterSlot4 { Species = 339, LevelMin = 42, LevelMax = 42, Type = SlotType.Super_Rod_Safari }, // Barboach - new EncounterSlot4 { Species = 339, LevelMin = 45, LevelMax = 45, Type = SlotType.Super_Rod_Safari }, // Barboach - new EncounterSlot4 { Species = 354, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Banette - new EncounterSlot4 { Species = 453, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Croagunk - new EncounterSlot4 { Species = 455, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Carnivine - }; - - private static readonly EncounterSlot[] SAFARIZONE_MOUNTAIN = - { - new EncounterSlot4 { Species = 019, LevelMin = 15, LevelMax = 16, Type = SlotType.Grass_Safari }, // Rattata - new EncounterSlot4 { Species = 020, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Raticate - new EncounterSlot4 { Species = 041, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Zubat - new EncounterSlot4 { Species = 042, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Golbat - new EncounterSlot4 { Species = 082, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Magneton - new EncounterSlot4 { Species = 082, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Magneton - new EncounterSlot4 { Species = 098, LevelMin = 43, LevelMax = 43, Type = SlotType.Grass_Safari }, // Krabby - new EncounterSlot4 { Species = 108, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Lickitung - new EncounterSlot4 { Species = 246, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Larvitar - new EncounterSlot4 { Species = 246, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Larvitar - new EncounterSlot4 { Species = 307, LevelMin = 43, LevelMax = 44, Type = SlotType.Grass_Safari }, // Meditite - new EncounterSlot4 { Species = 313, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Volbeat - new EncounterSlot4 { Species = 337, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Lunatone - new EncounterSlot4 { Species = 356, LevelMin = 45, LevelMax = 46, Type = SlotType.Grass_Safari }, // Dusclops - new EncounterSlot4 { Species = 364, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Sealeo - new EncounterSlot4 { Species = 375, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Metang - new EncounterSlot4 { Species = 433, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Chingling - }; - - private static readonly EncounterSlot[] SAFARIZONE_ROCKYBEACH = - { - new EncounterSlot4 { Species = 041, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Zubat - new EncounterSlot4 { Species = 060, LevelMin = 15, LevelMax = 16, Type = SlotType.Surf_Safari }, // Poliwag - new EncounterSlot4 { Species = 061, LevelMin = 16, LevelMax = 17, Type = SlotType.Surf_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 079, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Slowpoke - new EncounterSlot4 { Species = 080, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Slowbro - new EncounterSlot4 { Species = 080, LevelMin = 37, LevelMax = 37, Type = SlotType.Grass_Safari }, // Slowbro - new EncounterSlot4 { Species = 080, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Slowbro - new EncounterSlot4 { Species = 084, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Doduo - new EncounterSlot4 { Species = 085, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Dodrio - new EncounterSlot4 { Species = 098, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Krabby - new EncounterSlot4 { Species = 098, LevelMin = 13, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Krabby - new EncounterSlot4 { Species = 098, LevelMin = 22, LevelMax = 25, Type = SlotType.Good_Rod_Safari }, // Krabby - new EncounterSlot4 { Species = 098, LevelMin = 17, LevelMax = 17, Type = SlotType.Old_Rod_Safari }, // Krabby - new EncounterSlot4 { Species = 098, LevelMin = 18, LevelMax = 18, Type = SlotType.Old_Rod_Safari }, // Krabby - new EncounterSlot4 { Species = 099, LevelMin = 26, LevelMax = 27, Type = SlotType.Good_Rod_Safari }, // Kingler - new EncounterSlot4 { Species = 099, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Kingler - new EncounterSlot4 { Species = 099, LevelMin = 38, LevelMax = 39, Type = SlotType.Super_Rod_Safari }, // Kingler - new EncounterSlot4 { Species = 118, LevelMin = 13, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Goldeen - new EncounterSlot4 { Species = 118, LevelMin = 22, LevelMax = 23, Type = SlotType.Good_Rod_Safari }, // Goldeen - new EncounterSlot4 { Species = 118, LevelMin = 35, LevelMax = 38, Type = SlotType.Super_Rod_Safari }, // Goldeen - new EncounterSlot4 { Species = 119, LevelMin = 35, LevelMax = 38, Type = SlotType.Super_Rod_Safari }, // Seaking - new EncounterSlot4 { Species = 129, LevelMin = 12, LevelMax = 14, Type = SlotType.Old_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 129, LevelMin = 22, LevelMax = 23, Type = SlotType.Good_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 129, LevelMin = 15, LevelMax = 16, Type = SlotType.Surf_Safari }, // Magikarp - new EncounterSlot4 { Species = 131, LevelMin = 15, LevelMax = 16, Type = SlotType.Surf_Safari }, // Lapras - new EncounterSlot4 { Species = 131, LevelMin = 36, LevelMax = 37, Type = SlotType.Surf_Safari }, // Lapras - new EncounterSlot4 { Species = 131, LevelMin = 41, LevelMax = 42, Type = SlotType.Surf_Safari }, // Lapras - new EncounterSlot4 { Species = 131, LevelMin = 46, LevelMax = 47, Type = SlotType.Surf_Safari }, // Lapras - new EncounterSlot4 { Species = 179, LevelMin = 43, LevelMax = 43, Type = SlotType.Grass_Safari }, // Mareep - new EncounterSlot4 { Species = 304, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Aron - new EncounterSlot4 { Species = 309, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Electrike - new EncounterSlot4 { Species = 310, LevelMin = 37, LevelMax = 37, Type = SlotType.Grass_Safari }, // Manectric - new EncounterSlot4 { Species = 341, LevelMin = 46, LevelMax = 46, Type = SlotType.Super_Rod_Safari }, // Corphish - new EncounterSlot4 { Species = 341, LevelMin = 48, LevelMax = 48, Type = SlotType.Super_Rod_Safari }, // Corphish - new EncounterSlot4 { Species = 406, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Budew - new EncounterSlot4 { Species = 443, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Gible - }; - - private static readonly EncounterSlot[] SAFARIZONE_WASTELAND = - { - new EncounterSlot4 { Species = 022, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Fearow - new EncounterSlot4 { Species = 055, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Golduck - new EncounterSlot4 { Species = 066, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Machop - new EncounterSlot4 { Species = 067, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Machoke - new EncounterSlot4 { Species = 067, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Machoke - new EncounterSlot4 { Species = 069, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Bellsprout - new EncounterSlot4 { Species = 081, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Magnemite - new EncounterSlot4 { Species = 095, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Onix - new EncounterSlot4 { Species = 099, LevelMin = 48, LevelMax = 48, Type = SlotType.Grass_Safari }, // Kingler - new EncounterSlot4 { Species = 115, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Kangaskhan - new EncounterSlot4 { Species = 286, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Breloom - new EncounterSlot4 { Species = 308, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Medicham - new EncounterSlot4 { Species = 310, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Manectric - new EncounterSlot4 { Species = 314, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Illumise - new EncounterSlot4 { Species = 338, LevelMin = 45, LevelMax = 46, Type = SlotType.Grass_Safari }, // Solrock - new EncounterSlot4 { Species = 451, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Skorupi - }; - - private static readonly EncounterSlot[] SAFARIZONE_SAVANNAH = - { - new EncounterSlot4 { Species = 029, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Nidoran♀ - new EncounterSlot4 { Species = 030, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Nidorina - new EncounterSlot4 { Species = 032, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Nidoran♂ - new EncounterSlot4 { Species = 033, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Nidorino - new EncounterSlot4 { Species = 041, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Zubat - new EncounterSlot4 { Species = 042, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Golbat - new EncounterSlot4 { Species = 111, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Rhyhorn - new EncounterSlot4 { Species = 111, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Rhyhorn - new EncounterSlot4 { Species = 112, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Rhydon - new EncounterSlot4 { Species = 128, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Tauros - new EncounterSlot4 { Species = 128, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Tauros - new EncounterSlot4 { Species = 228, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Houndour - new EncounterSlot4 { Species = 263, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Zigzagoon - new EncounterSlot4 { Species = 285, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Shroomish - new EncounterSlot4 { Species = 298, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Azurill - new EncounterSlot4 { Species = 324, LevelMin = 46, LevelMax = 47, Type = SlotType.Grass_Safari }, // Torkoal - new EncounterSlot4 { Species = 332, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Cacturne - new EncounterSlot4 { Species = 404, LevelMin = 45, LevelMax = 46, Type = SlotType.Grass_Safari }, // Luxio - }; - - private static readonly EncounterSlot[] SAFARIZONE_WETLAND = - { - new EncounterSlot4 { Species = 021, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Spearow - new EncounterSlot4 { Species = 054, LevelMin = 15, LevelMax = 16, Type = SlotType.Grass_Safari }, // Psyduck - new EncounterSlot4 { Species = 054, LevelMin = 16, LevelMax = 17, Type = SlotType.Surf_Safari }, // Psyduck - new EncounterSlot4 { Species = 055, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Golduck - new EncounterSlot4 { Species = 055, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Golduck - new EncounterSlot4 { Species = 055, LevelMin = 37, LevelMax = 37, Type = SlotType.Surf_Safari }, // Golduck - new EncounterSlot4 { Species = 055, LevelMin = 45, LevelMax = 45, Type = SlotType.Surf_Safari }, // Golduck - new EncounterSlot4 { Species = 060, LevelMin = 12, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 060, LevelMin = 22, LevelMax = 24, Type = SlotType.Good_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 060, LevelMin = 35, LevelMax = 37, Type = SlotType.Super_Rod_Safari }, // Poliwag - new EncounterSlot4 { Species = 060, LevelMin = 15, LevelMax = 16, Type = SlotType.Surf_Safari }, // Poliwag - new EncounterSlot4 { Species = 061, LevelMin = 17, LevelMax = 18, Type = SlotType.Old_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 061, LevelMin = 23, LevelMax = 25, Type = SlotType.Good_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 061, LevelMin = 35, LevelMax = 37, Type = SlotType.Super_Rod_Safari }, // Poliwhirl - new EncounterSlot4 { Species = 083, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Farfetch'd - new EncounterSlot4 { Species = 083, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Farfetch'd - new EncounterSlot4 { Species = 084, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Doduo - new EncounterSlot4 { Species = 129, LevelMin = 12, LevelMax = 15, Type = SlotType.Old_Rod_Safari }, // Magikarp - new EncounterSlot4 { Species = 130, LevelMin = 44, LevelMax = 45, Type = SlotType.Super_Rod_Safari }, // Gyarados - new EncounterSlot4 { Species = 130, LevelMin = 47, LevelMax = 48, Type = SlotType.Super_Rod_Safari }, // Gyarados - new EncounterSlot4 { Species = 132, LevelMin = 17, LevelMax = 17, Type = SlotType.Grass_Safari }, // Ditto - new EncounterSlot4 { Species = 132, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Ditto - new EncounterSlot4 { Species = 161, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Sentret - new EncounterSlot4 { Species = 162, LevelMin = 37, LevelMax = 37, Type = SlotType.Grass_Safari }, // Furret - new EncounterSlot4 { Species = 194, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Wooper - new EncounterSlot4 { Species = 194, LevelMin = 15, LevelMax = 16, Type = SlotType.Surf_Safari }, // Wooper - new EncounterSlot4 { Species = 195, LevelMin = 16, LevelMax = 17, Type = SlotType.Grass_Safari }, // Quagsire - new EncounterSlot4 { Species = 195, LevelMin = 16, LevelMax = 17, Type = SlotType.Surf_Safari }, // Quagsire - new EncounterSlot4 { Species = 195, LevelMin = 37, LevelMax = 37, Type = SlotType.Surf_Safari }, // Quagsire - new EncounterSlot4 { Species = 271, LevelMin = 47, LevelMax = 47, Type = SlotType.Grass_Safari }, // Lombre - new EncounterSlot4 { Species = 283, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Surskit - new EncounterSlot4 { Species = 341, LevelMin = 26, LevelMax = 26, Type = SlotType.Good_Rod_Safari }, // Corphish - new EncounterSlot4 { Species = 341, LevelMin = 28, LevelMax = 28, Type = SlotType.Good_Rod_Safari }, // Corphish - new EncounterSlot4 { Species = 372, LevelMin = 46, LevelMax = 46, Type = SlotType.Grass_Safari }, // Shelgon - new EncounterSlot4 { Species = 417, LevelMin = 43, LevelMax = 43, Type = SlotType.Grass_Safari }, // Pachirisu - new EncounterSlot4 { Species = 418, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Buizel - }; - - private static readonly EncounterArea4HGSS SlotsHGSS_SafariZone = new EncounterArea4HGSS - { - // Source http://bulbapedia.bulbagarden.net/wiki/Johto_Safari_Zone#Pok.C3.A9mon - // Supplement http://www.psypokes.com/hgss/safari_areas.php - Location = 202, // Johto Safari Zone - Slots = ArrayUtil.ConcatAll( - SAFARIZONE_PEAK, - SAFARIZONE_DESERT, - SAFARIZONE_PLAINS, - SAFARIZONE_MEADOW, - SAFARIZONE_FOREST, - SAFARIZONE_SWAMP, - SAFARIZONE_MARSHLAND, - SAFARIZONE_MOUNTAIN, - SAFARIZONE_ROCKYBEACH, - SAFARIZONE_WASTELAND, - SAFARIZONE_SAVANNAH, - SAFARIZONE_WETLAND) - }; - - private static readonly EncounterArea4HGSS[] SlotsHGSSAlt = - { - SlotsHGSS_BCC, - new EncounterArea4HGSS { - Location = 209, // Ruins of Alph - Slots = Enumerable.Range(1, 25).Select((_, i) => new EncounterSlot4 { Species = 201, LevelMin = 5, LevelMax = 5, Type = SlotType.Grass, Form = i }).ToArray() // B->?, Unown A is loaded from encounters raw file - }, - SlotsHGSS_SafariZone, - //Some edge cases - new EncounterArea4HGSS - { - Location = 219, // Mt. Silver Cave 1F - Slots = new[]{new EncounterSlot4 { Species = 130, LevelMin = 20, LevelMax = 20, Type = SlotType.Good_Rod },}, // Gyarados at night - }, - }; - - private static readonly EncounterArea4DPPt SlotsPt_HoneyTree = new EncounterArea4DPPt - { - Slots = new[] - { - new EncounterSlot4 {Species = 190, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree}, // Aipom - new EncounterSlot4 {Species = 214, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree}, // Heracross - new EncounterSlot4 {Species = 265, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree}, // Wurmple - new EncounterSlot4 {Species = 412, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree, Form = 0}, // Burmy Plant Cloak - new EncounterSlot4 {Species = 415, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree}, // Combee - new EncounterSlot4 {Species = 420, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree}, // Cheruby - new EncounterSlot4 {Species = 446, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree}, // Munchlax - }, - }; - - private static readonly EncounterArea4DPPt SlotsD_HoneyTree = new EncounterArea4DPPt - { - Slots = SlotsPt_HoneyTree.Slots.Concat(new[] - { - new EncounterSlot4 {Species = 266, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree}, // Silcoon - }).ToArray() - }; - - private static readonly EncounterArea4DPPt SlotsP_HoneyTree = new EncounterArea4DPPt - { - Slots = SlotsPt_HoneyTree.Slots.Concat(new[] - { - new EncounterSlot4 {Species = 268, LevelMin = 5, LevelMax = 15, Type = SlotType.HoneyTree}, // Cascoon - }).ToArray() - }; - - internal static readonly int[] TrophyDP = { 035, 039, 052, 113, 133, 137, 173, 174, 183, 298, 311, 312, 351, 438, 439, 440 }; // Porygon - internal static readonly int[] TrophyPt = { 035, 039, 052, 113, 133, 132, 173, 174, 183, 298, 311, 312, 351, 438, 439, 440 }; // Ditto - - private static readonly int[] DP_GreatMarshAlt_Species = - { - // Daily changing Pokemon are not in the raw data http://bulbapedia.bulbagarden.net/wiki/Great_Marsh - 055, 315, 397, 451, 453, 455, - 183, 194, 195, 298, 399, 400, // Pre-National Pokédex - 046, 102, 115, 193, 285, 316, 452, 454 // Post-National Pokédex - }; - - private static readonly EncounterArea4DPPt[] DP_GreatMarshAlt = EncounterArea.GetSimpleEncounterArea(DP_GreatMarshAlt_Species, new[] { 22, 22, 24, 24, 26, 26 }, 52, SlotType.Grass_Safari); - - private static readonly int[] Pt_GreatMarshAlt_Species = - { - 114,193,195,357,451,453,455, - 194, // Pre-National Pokédex - 046,102,115,285,316,352,452,454 // Post-National Pokédex - }; - - private static readonly EncounterArea4DPPt[] Pt_GreatMarshAlt = EncounterArea.GetSimpleEncounterArea(Pt_GreatMarshAlt_Species, new[] { 27, 30 }, 52, SlotType.Grass_Safari); - - private static readonly int[] Shellos_EastSeaLocation_DP = - { - 28, // Route 213 - 39, // Route 224 - }; - - private static readonly int[] Shellos_EastSeaLocation_Pt = - { - 11, // Pastoria City - 27, // Route 212 - 28, // Route 213 - }; - - private static readonly int[] Gastrodon_EastSeaLocation_DP = - { - 37, // Route 222 - 39, // Route 224 - 45, // Route 230 - }; - - private static readonly int[] Gastrodon_EastSeaLocation_Pt = - { - 11, // Pastoria City - 27, // Route 212 - 28, // Route 213 - 39, // Route 224 - 45, // Route 230 - }; - - private static readonly int[] HoneyTreesLocation = - { - 20, // Route 205 - 21, // Route 206 - 22, // Route 207 - 23, // Route 208 - 24, // Route 209 - 25, // Route 210 - 26, // Route 211 - 27, // Route 212 - 28, // Route 213 - 29, // Route 214 - 30, // Route 215 - 33, // Route 218 - 36, // Route 221 - 37, // Route 222 - 47, // Valley Windworks - 48, // Eterna Forest - 49, // Fuego Ironworks - 58, // Floaroma Meadow - }; - - private static readonly EncounterArea4HGSS[] SlotsHGSS_Swarm = - { - new EncounterArea4HGSS {Location = 143, Slots = new[]{new EncounterSlot4 {Species = 278, Type = SlotType.Surf },},}, // Wingull @ Vermillion City - new EncounterArea4HGSS {Location = 149, Slots = new[]{new EncounterSlot4 {Species = 261, Type = SlotType.Grass },},}, // Poochyena @ Route 1 - new EncounterArea4HGSS {Location = 161, Slots = new[]{new EncounterSlot4 {Species = 113, Type = SlotType.Grass },},}, // Chansey @ Route 13 - new EncounterArea4HGSS {Location = 167, Slots = new[]{new EncounterSlot4 {Species = 366, Type = SlotType.Surf },},}, // Clamperl @ Route 19 - new EncounterArea4HGSS {Location = 173, Slots = new[]{new EncounterSlot4 {Species = 427, Type = SlotType.Grass },},}, // Buneary @ Route 25 - new EncounterArea4HGSS {Location = 175, Slots = new[]{new EncounterSlot4 {Species = 370, Type = SlotType.Surf },},}, // Luvdisc @ Route 27 - new EncounterArea4HGSS {Location = 182, Slots = new[]{new EncounterSlot4 {Species = 280, Type = SlotType.Grass },},}, // Ralts @ Route 34 - new EncounterArea4HGSS {Location = 183, Slots = new[]{new EncounterSlot4 {Species = 193, Type = SlotType.Grass },},}, // Yanma @ Route 35 - new EncounterArea4HGSS {Location = 186, Slots = new[]{new EncounterSlot4 {Species = 209, Type = SlotType.Grass },},}, // Snubbull @ Route 38 - new EncounterArea4HGSS {Location = 193, Slots = new[]{new EncounterSlot4 {Species = 333, Type = SlotType.Grass },},}, // Swablu @ Route 45 - new EncounterArea4HGSS {Location = 195, Slots = new[]{new EncounterSlot4 {Species = 132, Type = SlotType.Grass },},}, // Ditto @ Route 47 - new EncounterArea4HGSS {Location = 216, Slots = new[]{new EncounterSlot4 {Species = 183, Type = SlotType.Grass },},}, // Marill @ Mt. Mortar - new EncounterArea4HGSS {Location = 220, Slots = new[]{new EncounterSlot4 {Species = 206, Type = SlotType.Grass },},}, // Dunsparce @ Dark Cave - new EncounterArea4HGSS {Location = 224, Slots = new[]{new EncounterSlot4 {Species = 401, Type = SlotType.Grass },},}, // Kricketot @ Viridian Forest - - new EncounterArea4HGSS {Location = 128, Slots = new[]{ // Whiscash @ Violet City - new EncounterSlot4 {Species = 340, Type = SlotType.Old_Rod }, - new EncounterSlot4 {Species = 340, Type = SlotType.Good_Rod }, - new EncounterSlot4 {Species = 340, Type = SlotType.Super_Rod }, - },}, - new EncounterArea4HGSS {Location = 160, Slots = new[]{ // Relicanth @ Route 12 - new EncounterSlot4 {Species = 369, Type = SlotType.Old_Rod }, - new EncounterSlot4 {Species = 369, Type = SlotType.Good_Rod }, - new EncounterSlot4 {Species = 369, Type = SlotType.Super_Rod }, - },}, - new EncounterArea4HGSS {Location = 180, Slots = new[]{ // Qwilfish @ Route 32 - new EncounterSlot4 {Species = 211, Type = SlotType.Old_Rod }, - new EncounterSlot4 {Species = 211, Type = SlotType.Good_Rod }, - new EncounterSlot4 {Species = 211, Type = SlotType.Super_Rod }, - },}, - new EncounterArea4HGSS {Location = 192, Slots = new[]{ // Remoraid @ Route 44 - new EncounterSlot4 {Species = 223, Type = SlotType.Old_Rod }, - new EncounterSlot4 {Species = 223, Type = SlotType.Good_Rod }, - new EncounterSlot4 {Species = 223, Type = SlotType.Super_Rod }, - },}, - }; - - private static readonly EncounterArea4HGSS[] SlotsHG_Swarm = SlotsHGSS_Swarm.Concat(new[] { - new EncounterArea4HGSS {Location = 151, Slots = new[]{new EncounterSlot4 {Species = 343, Type = SlotType.Grass },},}, // Baltoy @ Route 3 - new EncounterArea4HGSS {Location = 157, Slots = new[]{new EncounterSlot4 {Species = 302, Type = SlotType.Grass },},}, // Sableye @ Route 9 - }).ToArray(); - - private static readonly EncounterArea4HGSS[] SlotsSS_Swarm = SlotsHGSS_Swarm.Concat(new[] { - new EncounterArea4HGSS {Location = 151, Slots = new[]{new EncounterSlot4 {Species = 316, Type = SlotType.Grass },},}, // Gulpin @ Route 3 - new EncounterArea4HGSS {Location = 157, Slots = new[]{new EncounterSlot4 {Species = 303, Type = SlotType.Grass },},}, // Mawile @ Route 9 - }).ToArray(); - - #endregion + internal static readonly EncounterStatic4[] StaticD = GetEncounters(Encounter_DPPt, D); + internal static readonly EncounterStatic4[] StaticP = GetEncounters(Encounter_DPPt, P); + internal static readonly EncounterStatic4[] StaticPt = GetEncounters(Encounter_DPPt, Pt); + internal static readonly EncounterStatic4[] StaticHG = GetEncounters(ArrayUtil.ConcatAll(Encounter_HGSS, Encounter_PokeWalker), HG); + internal static readonly EncounterStatic4[] StaticSS = GetEncounters(ArrayUtil.ConcatAll(Encounter_HGSS, Encounter_PokeWalker), SS); } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs index 906be5367..385b4e676 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs @@ -9,41 +9,14 @@ namespace PKHeX.Core /// public static class Encounters5 { - internal static readonly EncounterArea5[] SlotsB, SlotsW, SlotsB2, SlotsW2; - internal static readonly EncounterStatic5[] StaticB, StaticW, StaticB2, StaticW2; + internal static readonly EncounterArea5[] SlotsB = EncounterArea5.GetAreas(Get("b", "51"), GameVersion.B); + internal static readonly EncounterArea5[] SlotsW = EncounterArea5.GetAreas(Get("w", "51"), GameVersion.W); + internal static readonly EncounterArea5[] SlotsB2 = EncounterArea5.GetAreas(Get("b2", "52"), GameVersion.B2); + internal static readonly EncounterArea5[] SlotsW2 = EncounterArea5.GetAreas(Get("w2", "52"), GameVersion.W2); + private static byte[][] Get(string resource, string ident) => BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident); static Encounters5() { - MarkG5DreamWorld(ref BW_DreamWorld); - MarkG5DreamWorld(ref B2W2_DreamWorld); - var staticbw = Encounter_BW.Concat(BW_DreamWorld).ToArray(); - var staticb2w2 = Encounter_B2W2.Concat(B2W2_DreamWorld).ToArray(); - StaticB = GetEncounters(staticbw, GameVersion.B); - StaticW = GetEncounters(staticbw, GameVersion.W); - StaticB2 = GetEncounters(staticb2w2, GameVersion.B2); - StaticW2 = GetEncounters(staticb2w2, GameVersion.W2); - - var BSlots = GetEncounterTables("51", "b"); - var WSlots = GetEncounterTables("51", "w"); - var B2Slots = GetEncounterTables("52", "b2"); - var W2Slots = GetEncounterTables("52", "w2"); - MarkG5Slots(ref BSlots); - MarkG5Slots(ref WSlots); - MarkG5Slots(ref B2Slots); - MarkG5Slots(ref W2Slots); - MarkBWSwarmSlots(SlotsB_Swarm); - MarkBWSwarmSlots(SlotsW_Swarm); - MarkB2W2SwarmSlots(SlotsB2_Swarm); - MarkB2W2SwarmSlots(SlotsW2_Swarm); - MarkG5HiddenGrottoSlots(SlotsB2_HiddenGrotto); - MarkG5HiddenGrottoSlots(SlotsW2_HiddenGrotto); - MarkEncounterAreaArray(SlotsB_Swarm, SlotsW_Swarm, SlotsB2_Swarm, SlotsW2_Swarm, SlotsB2_HiddenGrotto, SlotsW2_HiddenGrotto, WhiteForestSlot); - - SlotsB = AddExtraTableSlots(BSlots, SlotsB_Swarm); - SlotsW = AddExtraTableSlots(WSlots, SlotsW_Swarm, WhiteForestSlot); - SlotsB2 = AddExtraTableSlots(B2Slots, SlotsB2_Swarm, SlotsB2_HiddenGrotto); - SlotsW2 = AddExtraTableSlots(W2Slots, SlotsW2_Swarm, SlotsW2_HiddenGrotto); - MarkEncountersGeneration(5, StaticB, StaticW, StaticB2, StaticW2, TradeGift_BW, TradeGift_B2W2); MarkEncounterTradeStrings(TradeGift_BW, TradeBW); @@ -53,52 +26,23 @@ static Encounters5() BW_DreamWorld.SetVersion(GameVersion.BW); B2W2_DreamWorld.SetVersion(GameVersion.B2W2); - SlotsB.SetVersion(GameVersion.B); - SlotsW.SetVersion(GameVersion.W); - SlotsB2.SetVersion(GameVersion.B2); - SlotsW2.SetVersion(GameVersion.W2); Encounter_BW.SetVersion(GameVersion.BW); Encounter_B2W2.SetVersion(GameVersion.B2W2); TradeGift_BW.SetVersion(GameVersion.BW); TradeGift_B2W2.SetVersion(GameVersion.B2W2); } - private static void MarkBWSwarmSlots(EncounterArea5[] Areas) - { - foreach (EncounterSlot s in Areas.SelectMany(area => area.Slots)) - { - s.LevelMin = 15; s.LevelMax = 55; s.Type = SlotType.Swarm; - } - } - - private static void MarkB2W2SwarmSlots(EncounterArea5[] Areas) - { - foreach (EncounterSlot s in Areas.SelectMany(area => area.Slots)) - { - s.LevelMin = 40; s.LevelMax = 55; s.Type = SlotType.Swarm; - } - } - - private static void MarkG5HiddenGrottoSlots(EncounterArea5[] Areas) - { - foreach (EncounterSlot s in Areas[0].Slots) //Only 1 area - s.Type = SlotType.HiddenGrotto; - } - - private static void MarkG5DreamWorld(ref EncounterStatic5[] t) + private static EncounterStatic5[] MarkG5DreamWorld(EncounterStatic5[] t) { + // Split encounters with multiple permitted special moves -- a pkm can only be obtained with 1 of the special moves! + var list = new List(); foreach (EncounterStatic5 s in t) { s.Location = 075; // Entree Forest var p = (PersonalInfoBW)PersonalTable.B2W2[s.Species]; s.Ability = p.HasHiddenAbility ? 4 : 1; s.Shiny = Shiny.Never; - } - // Split encounters with multiple permitted special moves -- a pkm can only be obtained with 1 of the special moves! - var list = new List(); - foreach (EncounterStatic5 s in t) - { if (s.Moves.Count <= 1) // no special moves { list.Add(s); @@ -113,40 +57,7 @@ private static void MarkG5DreamWorld(ref EncounterStatic5[] t) list.Add(clone); } } - t = list.ToArray(); - } - - private static void MarkG5Slots(ref EncounterArea5[] Areas) - { - foreach (var area in Areas) - { - int ctr = 0; - do - { - for (int i = 0; i < 12; i++) - area.Slots[ctr++].Type = SlotType.Grass; // Single - - for (int i = 0; i < 12; i++) - area.Slots[ctr++].Type = SlotType.Grass; // Double - - for (int i = 0; i < 12; i++) - area.Slots[ctr++].Type = SlotType.Grass; // Shaking - - for (int i = 0; i < 5; i++) // 5 - area.Slots[ctr++].Type = SlotType.Surf; // Surf - - for (int i = 0; i < 5; i++) // 5 - area.Slots[ctr++].Type = SlotType.Surf; // Surf Spot - - for (int i = 0; i < 5; i++) // 5 - area.Slots[ctr++].Type = SlotType.Super_Rod; // Fish - - for (int i = 0; i < 5; i++) // 5 - area.Slots[ctr++].Type = SlotType.Super_Rod; // Fish Spot - } while (ctr != area.Slots.Length); - area.Slots = area.Slots.Where(slot => slot.Species != 0).ToArray(); - } - ReduceAreasSize(ref Areas); + return list.ToArray(); } #region Dream Radar Tables @@ -360,7 +271,7 @@ private static void MarkG5Slots(ref EncounterArea5[] Areas) new EncounterStatic5 { Species = 376, Level = 45, Moves = new[]{038}, Gender = 2, }, // Metagross }; - public static readonly EncounterStatic5[] BW_DreamWorld = DreamWorld_Common.Concat(new[] + public static readonly EncounterStatic5[] BW_DreamWorld = MarkG5DreamWorld(DreamWorld_Common.Concat(new[] { // Pleasant Forest new EncounterStatic5 { Species = 029, Level = 10, Moves = new[]{010, 389, 162}, }, // Nidoran♀ @@ -459,9 +370,9 @@ private static void MarkG5Slots(ref EncounterArea5[] Areas) new EncounterStatic5 { Species = 242, Level = 10 }, // Blissey new EncounterStatic5 { Species = 448, Level = 10, Moves = new[]{418}, Gender = 0, }, // Lucario new EncounterStatic5 { Species = 189, Level = 27, Moves = new[]{206}, Gender = 0, }, // Jumpluff - }).ToArray(); + }).ToArray()); - public static readonly EncounterStatic5[] B2W2_DreamWorld = DreamWorld_Common.Concat(new[] + public static readonly EncounterStatic5[] B2W2_DreamWorld = MarkG5DreamWorld(DreamWorld_Common.Concat(new[] { // Pleasant Forest new EncounterStatic5 { Species = 535, Level = 10, Moves = new[]{496, 414, 352}, }, // Tympole @@ -523,7 +434,7 @@ private static void MarkG5Slots(ref EncounterArea5[] Areas) new EncounterStatic5 { Species = 390, Level = 10, Moves = new[]{252}, Gender = 0, }, // Chimchar new EncounterStatic5 { Species = 393, Level = 10, Moves = new[]{297}, Gender = 0, }, // Piplup new EncounterStatic5 { Species = 575, Level = 32, Moves = new[]{286}, Gender = 0, }, // Gothorita - }).ToArray(); + }).ToArray()); #endregion #region Static Encounter/Gift Tables @@ -750,233 +661,10 @@ private static void MarkG5Slots(ref EncounterArea5[] Areas) internal static readonly EncounterTrade[] TradeGift_B2W2 = TradeGift_B2W2_Regular.Concat(TradeGift_B2W2_YancyCurtis).ToArray(); #endregion - #region Alt Slots - // White forest white version only - - private static readonly int[] WhiteForest_GrassSpecies = - { - 016, 029, 032, 043, 063, 066, 069, 081, 092, 111, - 137, 175, 179, 187, 239, 240, 265, 270, 273, 280, - 287, 293, 298, 304, 328, 371, 396, 403, 406, 440, - }; - - private static readonly int[] WhiteForest_SurfSpecies = - { - 194, 270, 283, 341, - }; - - private static readonly EncounterArea5[] WhiteForestSlot = EncounterArea.GetSimpleEncounterArea(WhiteForest_GrassSpecies, new[] { 5, 5 }, 51, SlotType.Grass).Concat( - EncounterArea.GetSimpleEncounterArea(WhiteForest_SurfSpecies, new[] { 5, 5 }, 51, SlotType.Surf)).ToArray(); - - private static readonly EncounterArea5[] SlotsBW_Swarm = - { - // Level Range and Slot Type will be marked later - new EncounterArea5 { Location = 014, Slots = new[]{new EncounterSlot5 { Species = 083 }, }, }, // Farfetch'd @ Route 1 - new EncounterArea5 { Location = 015, Slots = new[]{new EncounterSlot5 { Species = 360 }, }, }, // Wynaut @ Route 2 - new EncounterArea5 { Location = 017, Slots = new[]{new EncounterSlot5 { Species = 449 }, }, }, // Hippopotas @ Route 4 - new EncounterArea5 { Location = 018, Slots = new[]{new EncounterSlot5 { Species = 235 }, }, }, // Smeargle @ Route 5 - new EncounterArea5 { Location = 020, Slots = new[]{new EncounterSlot5 { Species = 161 }, }, }, // Sentret @ Route 7 - new EncounterArea5 { Location = 021, Slots = new[]{new EncounterSlot5 { Species = 453 }, }, }, // Croagunk @ Route 8 - new EncounterArea5 { Location = 023, Slots = new[]{new EncounterSlot5 { Species = 236 }, }, }, // Tyrogue @ Route 10 - new EncounterArea5 { Location = 025, Slots = new[]{new EncounterSlot5 { Species = 084 }, }, }, // Doduo @ Route 12 - new EncounterArea5 { Location = 026, Slots = new[]{new EncounterSlot5 { Species = 353 }, }, }, // Shuppet @ Route 13 - new EncounterArea5 { Location = 027, Slots = new[]{new EncounterSlot5 { Species = 193 }, }, }, // Yanma @ Route 14 - new EncounterArea5 { Location = 028, Slots = new[]{new EncounterSlot5 { Species = 056 }, }, }, // Mankey @ Route 15 - new EncounterArea5 { Location = 029, Slots = new[]{new EncounterSlot5 { Species = 204 }, }, }, // Pineco @ Route 16 - new EncounterArea5 { Location = 031, Slots = new[]{new EncounterSlot5 { Species = 102 }, }, }, // Exeggcute @ Route 18 - }; - - private static readonly EncounterArea5[] SlotsB_Swarm = SlotsBW_Swarm.Concat(new[] { - new EncounterArea5 { Location = 016, Slots = new[]{new EncounterSlot5 { Species = 313 }, }, }, // Volbeat @ Route 3 - new EncounterArea5 { Location = 019, Slots = new[]{new EncounterSlot5 { Species = 311 }, }, }, // Plusle @ Route 6 - new EncounterArea5 { Location = 022, Slots = new[]{new EncounterSlot5 { Species = 228 }, }, }, // Houndour @ Route 9 - new EncounterArea5 { Location = 024, Slots = new[]{new EncounterSlot5 { Species = 285 }, }, }, // Shroomish @ Route 11 - }).ToArray(); - - private static readonly EncounterArea5[] SlotsW_Swarm = SlotsBW_Swarm.Concat(new[] { - new EncounterArea5 { Location = 016, Slots = new[]{new EncounterSlot5 { Species = 314 }, }, }, // Illumise @ Route 3 - new EncounterArea5 { Location = 019, Slots = new[]{new EncounterSlot5 { Species = 312 }, }, }, // Minun @ Route 6 - new EncounterArea5 { Location = 022, Slots = new[]{new EncounterSlot5 { Species = 261 }, }, }, // Poochyena @ Route 9 - new EncounterArea5 { Location = 024, Slots = new[]{new EncounterSlot5 { Species = 046 }, }, }, // Paras @ Route 11 - }).ToArray(); - - private static readonly EncounterArea5[] SlotsB2W2_Swarm = - { - // Level Range and Slot Type will be marked later - new EncounterArea5 { Location = 014, Slots = new[]{new EncounterSlot5 { Species = 083 }, }, }, // Farfetch'd @ Route 1 - new EncounterArea5 { Location = 018, Slots = new[]{new EncounterSlot5 { Species = 177 }, }, }, // Natu @ Route 5 - new EncounterArea5 { Location = 020, Slots = new[]{new EncounterSlot5 { Species = 162 }, }, }, // Furret @ Route 7 - new EncounterArea5 { Location = 021, Slots = new[]{new EncounterSlot5 { Species = 195 }, }, }, // Quagsire @ Route 8 - new EncounterArea5 { Location = 022, Slots = new[]{new EncounterSlot5 { Species = 317 }, }, }, // Swalot @ Route 9 - new EncounterArea5 { Location = 024, Slots = new[]{new EncounterSlot5 { Species = 284 }, }, }, // Masquerain @ Route 11 - new EncounterArea5 { Location = 025, Slots = new[]{new EncounterSlot5 { Species = 084 }, }, }, // Doduo @ Route 12 - new EncounterArea5 { Location = 026, Slots = new[]{new EncounterSlot5 { Species = 277 }, }, }, // Swellow @ Route 13 - new EncounterArea5 { Location = 028, Slots = new[]{new EncounterSlot5 { Species = 022 }, }, }, // Fearow @ Route 15 - new EncounterArea5 { Location = 029, Slots = new[]{new EncounterSlot5 { Species = 204 }, }, }, // Pineco @ Route 16 - new EncounterArea5 { Location = 031, Slots = new[]{new EncounterSlot5 { Species = 187 }, }, }, // Hoppip @ Route 18 - new EncounterArea5 { Location = 032, Slots = new[]{new EncounterSlot5 { Species = 097 }, }, }, // Hypno @ Dreamyard - new EncounterArea5 { Location = 034, Slots = new[]{new EncounterSlot5 { Species = 450 }, }, }, // Hippowdon @ Desert Resort - new EncounterArea5 { Location = 070, Slots = new[]{new EncounterSlot5 { Species = 079 }, }, }, // Slowpoke @ Abundant shrine - new EncounterArea5 { Location = 132, Slots = new[]{new EncounterSlot5 { Species = 332 }, }, }, // Cacturne @ Reaversal Mountian - }; - - private static readonly EncounterArea5[] SlotsB2_Swarm = SlotsB2W2_Swarm.Concat(new[] { - new EncounterArea5 { Location = 016, Slots = new[]{new EncounterSlot5 { Species = 313 }, }, }, // Volbeat @ Route 3 - new EncounterArea5 { Location = 019, Slots = new[]{new EncounterSlot5 { Species = 311 }, }, }, // Plusle @ Route 6 - new EncounterArea5 { Location = 125, Slots = new[]{new EncounterSlot5 { Species = 185 }, }, }, // Sudowoodo @ Route 20 - new EncounterArea5 { Location = 127, Slots = new[]{new EncounterSlot5 { Species = 168 }, }, }, // Ariados @ Route 22 - }).ToArray(); - - private static readonly EncounterArea5[] SlotsW2_Swarm = SlotsB2W2_Swarm.Concat(new[] { - new EncounterArea5 { Location = 016, Slots = new[]{new EncounterSlot5 { Species = 314 }, }, }, // Illumise @ Route 3 - new EncounterArea5 { Location = 019, Slots = new[]{new EncounterSlot5 { Species = 312 }, }, }, // Minun @ Route 6 - new EncounterArea5 { Location = 125, Slots = new[]{new EncounterSlot5 { Species = 122 }, }, }, // Mr. Mime @ Route 20 - new EncounterArea5 { Location = 127, Slots = new[]{new EncounterSlot5 { Species = 166 }, }, }, // Ledian @ Route 22 - }).ToArray(); - - private static readonly EncounterSlot[] SlotsB2W2_HiddenGrottoEncounterSlots = - { - // reference http://bulbapedia.bulbagarden.net/wiki/Hidden_Grotto - // Route 2 - new EncounterSlot5 { Species = 029, LevelMin = 55, LevelMax = 60, }, // Nidoran♀ - new EncounterSlot5 { Species = 032, LevelMin = 55, LevelMax = 60, }, // Nidoran♂ - new EncounterSlot5 { Species = 210, LevelMin = 55, LevelMax = 60, }, // Granbull - new EncounterSlot5 { Species = 505, LevelMin = 55, LevelMax = 60, }, // Watchog - - // Route 3 - new EncounterSlot5 { Species = 310, LevelMin = 55, LevelMax = 60, }, // Manectric @ Dark Grass - new EncounterSlot5 { Species = 417, LevelMin = 55, LevelMax = 60, }, // Pachirisu @ Dark Grass - new EncounterSlot5 { Species = 523, LevelMin = 55, LevelMax = 60, }, // Zebstrika @ Dark Grass - new EncounterSlot5 { Species = 048, LevelMin = 55, LevelMax = 60, }, // Venonat @ Pond - new EncounterSlot5 { Species = 271, LevelMin = 55, LevelMax = 60, }, // Lombre @ Pond - new EncounterSlot5 { Species = 400, LevelMin = 55, LevelMax = 60, }, // Bibarel @ Pond - - // Route 5 - new EncounterSlot5 { Species = 510, LevelMin = 20, LevelMax = 25, }, // Liepard - new EncounterSlot5 { Species = 572, LevelMin = 20, LevelMax = 25, }, // Minccino - new EncounterSlot5 { Species = 590, LevelMin = 20, LevelMax = 25, }, // Foongus - - // Route 6 - new EncounterSlot5 { Species = 206, LevelMin = 25, LevelMax = 30, }, // Dunsparce @ Near PKM Breeder - new EncounterSlot5 { Species = 299, LevelMin = 25, LevelMax = 30, }, // Nosepass @ Mistralton Cave - new EncounterSlot5 { Species = 527, LevelMin = 25, LevelMax = 30, }, // Woobat @ Both - new EncounterSlot5 { Species = 590, LevelMin = 25, LevelMax = 30, }, // Foongus @ Both - - // Route 7 - new EncounterSlot5 { Species = 335, LevelMin = 30, LevelMax = 35, }, // Zangoose - new EncounterSlot5 { Species = 336, LevelMin = 30, LevelMax = 35, }, // Seviper - new EncounterSlot5 { Species = 505, LevelMin = 30, LevelMax = 35, }, // Watchog - new EncounterSlot5 { Species = 613, LevelMin = 30, LevelMax = 35, }, // Cubchoo - - // Route 9 - new EncounterSlot5 { Species = 089, LevelMin = 35, LevelMax = 40, }, // Muk - new EncounterSlot5 { Species = 510, LevelMin = 35, LevelMax = 40, }, // Liepard - new EncounterSlot5 { Species = 569, LevelMin = 35, LevelMax = 40, }, // Garbodor - new EncounterSlot5 { Species = 626, LevelMin = 35, LevelMax = 40, }, // Bouffalant - - // Route 13 - new EncounterSlot5 { Species = 114, LevelMin = 35, LevelMax = 40, }, // Tangela @ Gaint Chasm - new EncounterSlot5 { Species = 363, LevelMin = 35, LevelMax = 40, }, // Spheal @ Stairs - new EncounterSlot5 { Species = 425, LevelMin = 35, LevelMax = 40, }, // Drifloon @ Stairs - new EncounterSlot5 { Species = 451, LevelMin = 35, LevelMax = 40, }, // Skorupi @ Gaint Chasm - new EncounterSlot5 { Species = 590, LevelMin = 35, LevelMax = 40, }, // Foongus @ Both - - // Route 18 - new EncounterSlot5 { Species = 099, LevelMin = 55, LevelMax = 60, }, // Kingler - new EncounterSlot5 { Species = 149, LevelMin = 55, LevelMax = 60, }, // Dragonite - new EncounterSlot5 { Species = 222, LevelMin = 55, LevelMax = 60, }, // Corsola - new EncounterSlot5 { Species = 441, LevelMin = 55, LevelMax = 60, }, // Chatot - - // Pinwheel Forest - new EncounterSlot5 { Species = 061, LevelMin = 55, LevelMax = 60, }, // Poliwhirl @ Outer - new EncounterSlot5 { Species = 198, LevelMin = 55, LevelMax = 60, }, // Murkrow @ Inner - new EncounterSlot5 { Species = 286, LevelMin = 55, LevelMax = 60, }, // Breloom @ Inner - new EncounterSlot5 { Species = 297, LevelMin = 55, LevelMax = 60, }, // Hariyama @ Outer - new EncounterSlot5 { Species = 308, LevelMin = 55, LevelMax = 60, }, // Medicham @ Outer - new EncounterSlot5 { Species = 371, LevelMin = 55, LevelMax = 60, }, // Bagon @ Outer - new EncounterSlot5 { Species = 591, LevelMin = 55, LevelMax = 60, }, // Amoonguss @ Inner - - // Giant Chasm - new EncounterSlot5 { Species = 035, LevelMin = 45, LevelMax = 50, }, // Clefairy - new EncounterSlot5 { Species = 132, LevelMin = 45, LevelMax = 50, }, // Ditto - new EncounterSlot5 { Species = 215, LevelMin = 45, LevelMax = 50, }, // Sneasel - new EncounterSlot5 { Species = 375, LevelMin = 45, LevelMax = 50, }, // Metang - - // Abundant Shrine - new EncounterSlot5 { Species = 037, LevelMin = 35, LevelMax = 40, }, // Vulpix @ Near Youngster - new EncounterSlot5 { Species = 055, LevelMin = 35, LevelMax = 40, }, // Golduck @ Shrine - new EncounterSlot5 { Species = 333, LevelMin = 35, LevelMax = 40, }, // Swablu @ Shrine - new EncounterSlot5 { Species = 436, LevelMin = 35, LevelMax = 40, }, // Bronzor @ Near Youngster - new EncounterSlot5 { Species = 591, LevelMin = 35, LevelMax = 40, }, // Amoonguss @ Both - - // Lostlorn Forest - new EncounterSlot5 { Species = 127, LevelMin = 20, LevelMax = 25, }, // Pinsir - new EncounterSlot5 { Species = 214, LevelMin = 20, LevelMax = 25, }, // Heracross - new EncounterSlot5 { Species = 415, LevelMin = 20, LevelMax = 25, }, // Combee - new EncounterSlot5 { Species = 542, LevelMin = 20, LevelMax = 25, }, // Leavanny - - // Route 22 - new EncounterSlot5 { Species = 279, LevelMin = 40, LevelMax = 45, }, // Pelipper - new EncounterSlot5 { Species = 591, LevelMin = 40, LevelMax = 45, }, // Amoonguss - new EncounterSlot5 { Species = 619, LevelMin = 40, LevelMax = 45, }, // Mienfoo - - // Route 23 - new EncounterSlot5 { Species = 055, LevelMin = 50, LevelMax = 55, }, // Golduck - new EncounterSlot5 { Species = 207, LevelMin = 50, LevelMax = 55, }, // Gligar - new EncounterSlot5 { Species = 335, LevelMin = 50, LevelMax = 55, }, // Zangoose - new EncounterSlot5 { Species = 336, LevelMin = 50, LevelMax = 55, }, // Seviper - new EncounterSlot5 { Species = 359, LevelMin = 50, LevelMax = 55, }, // Absol - - // Floccesy Ranch - new EncounterSlot5 { Species = 183, LevelMin = 10, LevelMax = 15, }, // Marill - new EncounterSlot5 { Species = 206, LevelMin = 10, LevelMax = 15, }, // Dunsparce - new EncounterSlot5 { Species = 507, LevelMin = 10, LevelMax = 15, }, // Herdier - - // Funfest Missions - // todo : check the level - new EncounterSlot5 { Species = 133, LevelMin = 15, LevelMax = 60, }, // Eevee - new EncounterSlot5 { Species = 134, LevelMin = 15, LevelMax = 60, }, // Vaporeon - new EncounterSlot5 { Species = 135, LevelMin = 15, LevelMax = 60, }, // Jolteon - new EncounterSlot5 { Species = 136, LevelMin = 15, LevelMax = 60, }, // Flareon - new EncounterSlot5 { Species = 196, LevelMin = 15, LevelMax = 60, }, // Espeon - new EncounterSlot5 { Species = 197, LevelMin = 15, LevelMax = 60, }, // Umbreon - new EncounterSlot5 { Species = 470, LevelMin = 15, LevelMax = 60, }, // Leafeon - new EncounterSlot5 { Species = 471, LevelMin = 15, LevelMax = 60, }, // Glaceon - - // Funfest Week 3 - // new EncounterSlot5 { Species = 060, LevelMin = 15, LevelMax = 60, }, // Poliwag - new EncounterSlot5 { Species = 113, LevelMin = 15, LevelMax = 60, }, // Chansey - new EncounterSlot5 { Species = 176, LevelMin = 15, LevelMax = 60, }, // Togetic - new EncounterSlot5 { Species = 082, LevelMin = 15, LevelMax = 60, }, // Magneton - new EncounterSlot5 { Species = 148, LevelMin = 15, LevelMax = 60, }, // Dragonair - new EncounterSlot5 { Species = 372, LevelMin = 15, LevelMax = 60, }, // Shelgon - }; - - private static readonly EncounterArea5[] SlotsB2_HiddenGrotto = - { - new EncounterArea5 - { - Location = 143, // Hidden Grotto - Slots = SlotsB2W2_HiddenGrottoEncounterSlots.Concat(new[]{ - new EncounterSlot5 { Species = 015, LevelMin = 55, LevelMax = 60 }, // Beedrill @ Pinwheel Forest - new EncounterSlot5 { Species = 434, LevelMin = 15, LevelMax = 60 }, // Stunky from Funfest Missions - }).ToArray(), - } - }; - - private static readonly EncounterArea5[] SlotsW2_HiddenGrotto = - { - new EncounterArea5 - { - Location = 143, // Hidden Grotto - Slots = SlotsB2W2_HiddenGrottoEncounterSlots.Concat(new[]{ - new EncounterSlot5 { Species = 012, LevelMin = 55, LevelMax = 60 }, // Butterfree @ Pinwheel Forest - new EncounterSlot5 { Species = 431, LevelMin = 15, LevelMax = 60 }, // Glameow from Funfest Missions - }).ToArray(), - } - }; - - #endregion + internal static readonly EncounterStatic5[] StaticB = GetEncounters(ArrayUtil.ConcatAll(Encounter_BW, BW_DreamWorld), GameVersion.B); + internal static readonly EncounterStatic5[] StaticW = GetEncounters(ArrayUtil.ConcatAll(Encounter_BW, BW_DreamWorld), GameVersion.W); + internal static readonly EncounterStatic5[] StaticB2 = GetEncounters(ArrayUtil.ConcatAll(Encounter_B2W2, B2W2_DreamWorld), GameVersion.B2); + internal static readonly EncounterStatic5[] StaticW2 = GetEncounters(ArrayUtil.ConcatAll(Encounter_B2W2, B2W2_DreamWorld), GameVersion.W2); } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs index 7853c1b50..ed9abc0a3 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs @@ -9,151 +9,32 @@ namespace PKHeX.Core /// internal static class Encounters6 { - internal static readonly EncounterArea6XY[] SlotsX, SlotsY; - internal static readonly EncounterArea6AO[] SlotsA, SlotsO; - internal static readonly EncounterStatic[] StaticX, StaticY, StaticA, StaticO; - internal static readonly ILookup FriendSafari; + private static readonly EncounterArea6XY FriendSafari = new EncounterArea6XY(Legal.FriendSafari); + internal static readonly EncounterArea6XY[] SlotsX = ArrayUtil.ConcatAll(EncounterArea6XY.GetAreas(Get("x", "xy"), GameVersion.X), new[] { FriendSafari }); + internal static readonly EncounterArea6XY[] SlotsY = ArrayUtil.ConcatAll(EncounterArea6XY.GetAreas(Get("y", "xy"), GameVersion.Y), new[] { FriendSafari }); + internal static readonly EncounterArea6AO[] SlotsA = EncounterArea6AO.GetAreas(Get("a", "ao"), GameVersion.AS); + internal static readonly EncounterArea6AO[] SlotsO = EncounterArea6AO.GetAreas(Get("o", "ao"), GameVersion.OR); + private static byte[][] Get(string resource, string ident) => BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident); + static Encounters6() { - StaticX = GetEncounters(Encounter_XY, GameVersion.X); - StaticY = GetEncounters(Encounter_XY, GameVersion.Y); - StaticA = GetEncounters(Encounter_AO, GameVersion.AS); - StaticO = GetEncounters(Encounter_AO, GameVersion.OR); - - var XSlots = GetEncounterTables("xy", "x"); - var YSlots = GetEncounterTables("xy", "y"); - MarkG6XYSlots(ref XSlots); - MarkG6XYSlots(ref YSlots); - MarkEncounterAreaArray(SlotsXYAlt); - SlotsX = AddExtraTableSlots(XSlots, SlotsXYAlt); - SlotsY = AddExtraTableSlots(YSlots, SlotsXYAlt); - - SlotsA = GetEncounterTables("ao", "a"); - SlotsO = GetEncounterTables("ao", "o"); - MarkG6AOSlots(ref SlotsA); - MarkG6AOSlots(ref SlotsO); - MarkEncountersGeneration(6, StaticX, StaticY, StaticA, StaticO, TradeGift_XY, TradeGift_AO); - FriendSafari = EncounterArea6XYFriendSafari.GetArea(); MarkEncounterTradeStrings(TradeGift_XY, TradeXY); MarkEncounterTradeStrings(TradeGift_AO, TradeAO); - SlotsXYAlt.SetVersion(GameVersion.XY); - SlotsX.SetVersion(GameVersion.X); - SlotsY.SetVersion(GameVersion.Y); - SlotsA.SetVersion(GameVersion.AS); - SlotsO.SetVersion(GameVersion.OR); Encounter_XY.SetVersion(GameVersion.XY); Encounter_AO.SetVersion(GameVersion.ORAS); TradeGift_XY.SetVersion(GameVersion.XY); TradeGift_AO.SetVersion(GameVersion.ORAS); } - private static void MarkG6XYSlots(ref EncounterArea6XY[] Areas) - { - foreach (var area in Areas) - { - int slotct = area.Slots.Length; - for (int i = slotct - 15; i < slotct; i++) - area.Slots[i].Type = SlotType.Horde; - } - ReduceAreasSize(ref Areas); - } - - private static void MarkG6AOSlots(ref EncounterArea6AO[] Areas) - { - foreach (var area in Areas) - { - 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; - - for (int i = 0; i < slotct; i++) - ((EncounterSlot6AO)area.Slots[i]).AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash; - } - ReduceAreasSize(ref Areas); - } - private const string tradeXY = "tradexy"; private const string tradeAO = "tradeao"; private static readonly string[][] TradeXY = Util.GetLanguageStrings8(tradeXY); private static readonly string[][] TradeAO = Util.GetLanguageStrings8(tradeAO); - #region XY Alt Slots - private static readonly EncounterArea6XY[] SlotsXYAlt = - { - new EncounterArea6XY { - Location = 104, // Victory Road - Slots = new[] - { - // Drops - new EncounterSlot6XY { Species = 075, LevelMin = 57, LevelMax = 57, Form = 0 }, // Graveler - new EncounterSlot6XY { Species = 168, LevelMin = 58, LevelMax = 59, Form = 0 }, // Ariados - new EncounterSlot6XY { Species = 714, LevelMin = 57, LevelMax = 59, Form = 0 }, // Noibat - - // Swoops - new EncounterSlot6XY { Species = 022, LevelMin = 57, LevelMax = 59, Form = 0 }, // Fearow - new EncounterSlot6XY { Species = 227, LevelMin = 57, LevelMax = 59, Form = 0 }, // Skarmory - new EncounterSlot6XY { Species = 635, LevelMin = 59, LevelMax = 59, Form = 0 }, // Hydreigon - },}, - new EncounterArea6XY { - Location = 34, // Route 6 - Slots = new[] - { - // Rustling Bush - new EncounterSlot6XY { Species = 543, LevelMin = 10, LevelMax = 12, Form = 0 }, // Venipede - new EncounterSlot6XY { Species = 531, LevelMin = 10, LevelMax = 12, Form = 0 }, // Audino - },}, - - new EncounterArea6XY { Location = 38, // Route 7 - Slots = new[] - { - // Berry Field - new EncounterSlot6XY { Species = 165, LevelMin = 14, LevelMax = 15, Form = 0 }, // Ledyba - new EncounterSlot6XY { Species = 313, LevelMin = 14, LevelMax = 15, Form = 0 }, // Volbeat - new EncounterSlot6XY { Species = 314, LevelMin = 14, LevelMax = 15, Form = 0 }, // Illumise - new EncounterSlot6XY { Species = 412, LevelMin = 14, LevelMax = 15, Form = 0 }, // Burmy - new EncounterSlot6XY { Species = 415, LevelMin = 14, LevelMax = 15, Form = 0 }, // Combee - new EncounterSlot6XY { Species = 665, LevelMin = 14, LevelMax = 15, Form = 30 }, // Spewpa - },}, - - new EncounterArea6XY { Location = 88, // Route 18 - Slots = new[] - { - // Rustling Bush - new EncounterSlot6XY { Species = 632, LevelMin = 44, LevelMax = 46, Form = 0 }, // Durant - new EncounterSlot6XY { Species = 631, LevelMin = 45, LevelMax = 45, Form = 0 }, // Heatmor - },}, - - new EncounterArea6XY { Location = 132, // Glittering Cave - Slots = new[] - { - // Drops - new EncounterSlot6XY { Species = 527, LevelMin = 15, LevelMax = 17, Form = 0 }, // Woobat - new EncounterSlot6XY { Species = 597, LevelMin = 15, LevelMax = 17, Form = 0 }, // Ferroseed - },}, - - new EncounterArea6XY { Location = 56, // Reflection Cave - Slots = new[] - { - // Drops - new EncounterSlot6XY { Species = 527, LevelMin = 21, LevelMax = 23, Form = 0 }, // Woobat - new EncounterSlot6XY { Species = 597, LevelMin = 21, LevelMax = 23, Form = 0 }, // Ferroseed - },}, - - new EncounterArea6XY { Location = 140, // Terminus Cave - Slots = new[] - { - // Drops - new EncounterSlot6XY { Species = 168, LevelMin = 44, LevelMax = 46, Form = 0 }, // Ariados - new EncounterSlot6XY { Species = 714, LevelMin = 44, LevelMax = 46, Form = 0 }, // Noibat - },}, - }; - #endregion #region Static Encounter/Gift Tables private static readonly EncounterStatic[] Encounter_XY = { @@ -362,5 +243,10 @@ private static IEnumerable PermuteCosplayPikachu() new EncounterTrade6(07,4,10,319) { Species = 222, Level = 50, Ability = 4, TID = 00325, IVs = new[] {31,-1,-1,-1,-1,31}, Gender = 1, Nature = Nature.Calm, }, // Corsola }; #endregion + + internal static readonly EncounterStatic[] StaticX = GetEncounters(Encounter_XY, GameVersion.X); + internal static readonly EncounterStatic[] StaticY = GetEncounters(Encounter_XY, GameVersion.Y); + internal static readonly EncounterStatic[] StaticA = GetEncounters(Encounter_AO, GameVersion.AS); + internal static readonly EncounterStatic[] StaticO = GetEncounters(Encounter_AO, GameVersion.OR); } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs index ce3506e2b..7a3b5b8c1 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs @@ -1,5 +1,4 @@ -using System.Linq; -using static PKHeX.Core.EncounterUtil; +using static PKHeX.Core.EncounterUtil; namespace PKHeX.Core { @@ -8,72 +7,25 @@ namespace PKHeX.Core /// internal static class Encounters7 { - internal static readonly EncounterArea7[] SlotsSN, SlotsMN, SlotsUS, SlotsUM; - internal static readonly EncounterStatic7[] StaticSN, StaticMN, StaticUS, StaticUM; + internal static readonly EncounterArea7[] SlotsSN = EncounterArea7.GetAreas(Get("sn", "sm"), GameVersion.SN); + internal static readonly EncounterArea7[] SlotsMN = EncounterArea7.GetAreas(Get("mn", "sm"), GameVersion.MN); + internal static readonly EncounterArea7[] SlotsUS = EncounterArea7.GetAreas(Get("us", "uu"), GameVersion.US); + internal static readonly EncounterArea7[] SlotsUM = EncounterArea7.GetAreas(Get("um", "uu"), GameVersion.UM); + private static byte[][] Get(string resource, string ident) => BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident); static Encounters7() { - StaticSN = GetEncounters(Encounter_SM, GameVersion.SN); - StaticMN = GetEncounters(Encounter_SM, GameVersion.MN); - StaticUS = GetEncounters(Encounter_USUM, GameVersion.US); - StaticUM = GetEncounters(Encounter_USUM, GameVersion.UM); - - var REG_SN = GetEncounterTables("sm", "sn"); - var REG_MN = GetEncounterTables("sm", "mn"); - var SOS_SN = GetEncounterTables("sm", "sn_sos"); - var SOS_MN = GetEncounterTables("sm", "mn_sos"); - MarkG7REGSlots(ref REG_SN); - MarkG7REGSlots(ref REG_MN); - MarkG7SMSlots(ref SOS_SN); - MarkG7SMSlots(ref SOS_MN); - int[] pelagoMin = { 1, 11, 21, 37, 49 }; - InitializePelagoSM(pelagoMin, out var p_sn, out var p_mn); - InitializePelagoUltra(pelagoMin, out var p_us, out var p_um); - SlotsSN = AddExtraTableSlots(REG_SN, SOS_SN, p_sn); - SlotsMN = AddExtraTableSlots(REG_MN, SOS_MN, p_mn); - - var REG_US = GetEncounterTables("uu", "us"); - var REG_UM = GetEncounterTables("uu", "um"); - var SOS_US = GetEncounterTables("uu", "us_sos"); - var SOS_UM = GetEncounterTables ("uu", "um_sos"); - MarkG7REGSlots(ref REG_US); - MarkG7REGSlots(ref REG_UM); - MarkG7SMSlots(ref SOS_US); - MarkG7SMSlots(ref SOS_UM); - SlotsUS = AddExtraTableSlots(REG_US, SOS_US, p_us); - SlotsUM = AddExtraTableSlots(REG_UM, SOS_UM, p_um); - - MarkEncounterAreaArray(SOS_SN, SOS_MN, SOS_US, SOS_UM, - p_sn, p_mn, - p_us, p_um); - MarkEncountersGeneration(7, StaticSN, StaticMN, StaticUS, StaticUM, TradeGift_SM, TradeGift_USUM); MarkEncounterTradeStrings(TradeGift_SM, TradeSM); MarkEncounterTradeStrings(TradeGift_USUM, TradeUSUM); - SlotsSN.SetVersion(GameVersion.SN); - SlotsMN.SetVersion(GameVersion.MN); - SlotsUS.SetVersion(GameVersion.US); - SlotsUM.SetVersion(GameVersion.UM); Encounter_SM.SetVersion(GameVersion.SM); Encounter_USUM.SetVersion(GameVersion.USUM); TradeGift_SM.SetVersion(GameVersion.SM); TradeGift_USUM.SetVersion(GameVersion.USUM); } - private static void MarkG7REGSlots(ref EncounterArea7[] Areas) - { - ReduceAreasSize(ref Areas); - } - - private static void MarkG7SMSlots(ref EncounterArea7[] Areas) - { - foreach (EncounterSlot s in Areas.SelectMany(area => area.Slots)) - s.Type = SlotType.SOS; - ReduceAreasSize(ref Areas); - } - private static readonly EncounterStatic7[] Encounter_SM = // @ a\1\5\5 { // Gifts - 0.bin @@ -408,53 +360,9 @@ private static void MarkG7SMSlots(ref EncounterArea7[] Areas) private static readonly string[][] TradeSM = Util.GetLanguageStrings10(tradeSM); private static readonly string[][] TradeUSUM = Util.GetLanguageStrings10(tradeUSUM); - private static void InitializePelagoSM(int[] minLevels, out EncounterArea7[] sn, out EncounterArea7[] mn) - { - int[][] speciesSM = - { - new[] {627/*SN*/, 021, 041, 090, 278, 731}, // 1-7 - new[] {064, 081, 092, 198, 426, 703}, // 11-17 - new[] {060, 120, 127, 661, 709, 771}, // 21-27 - new[] {227, 375, 707}, // 37-43 - new[] {123, 131, 429, 587}, // 49-55 - }; - sn = GetPelagoArea(speciesSM, minLevels); - speciesSM[0][0] = 629; // Rufflet -> Vullaby - mn = GetPelagoArea(speciesSM, minLevels); - } - - private static void InitializePelagoUltra(int[] minLevels, out EncounterArea7[] us, out EncounterArea7[] um) - { - int[][] speciesUU = - { - new[] {731, 278, 041, 742, 086}, // 1-7 - new[] {079, 120, 222, 122, 180, 124}, // 11-17 - new[] {127, 177, 764, 163, 771, 701}, // 21-27 - new[] {131, 354, 200, /* US */ 228}, // 37-43 - new[] {209, 667, 357, 430}, // 49-55 - }; - us = GetPelagoArea(speciesUU, minLevels); - speciesUU[3][3] = 309; // Houndour -> Electrike - um = GetPelagoArea(speciesUU, minLevels); - } - - private static EncounterArea7[] GetPelagoArea(int[][] species, int[] min) - { - // Species that appear at a lower level than the current table show up too. - var area = new EncounterArea7 - { - Location = 30016, - Slots = species.SelectMany((_, i) => - species.Take(1 + i).SelectMany(z => // grab current row & above - z.Select(s => new EncounterSlot7 // get slot data for each species - { - Species = s, - LevelMin = min[i], - LevelMax = min[i] + 6 - } - ))).ToArray(), - }; - return new[] {area}; - } + internal static readonly EncounterStatic7[] StaticSN = GetEncounters(Encounter_SM, GameVersion.SN); + internal static readonly EncounterStatic7[] StaticMN = GetEncounters(Encounter_SM, GameVersion.MN); + internal static readonly EncounterStatic7[] StaticUS = GetEncounters(Encounter_USUM, GameVersion.US); + internal static readonly EncounterStatic7[] StaticUM = GetEncounters(Encounter_USUM, GameVersion.UM); } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters7b.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters7b.cs index 79dff44ca..59387b82c 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters7b.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters7b.cs @@ -7,20 +7,15 @@ namespace PKHeX.Core { internal static class Encounters7b { - internal static readonly EncounterArea7b[] SlotsGP = GetEncounterTables("gg", "gp"); - internal static readonly EncounterArea7b[] SlotsGE = GetEncounterTables("gg", "ge"); - internal static readonly EncounterStatic[] StaticGP, StaticGE; - internal static readonly EncounterArea7g[] SlotsGO_GG = GetGoParkArea(); + internal static readonly EncounterArea7b[] SlotsGP = EncounterArea7b.GetAreas(Get("gp", "gg"), GameVersion.GP); + internal static readonly EncounterArea7b[] SlotsGE = EncounterArea7b.GetAreas(Get("ge", "gg"), GameVersion.GE); + internal static readonly EncounterArea7g[] SlotsGO_GG = EncounterArea7g.GetArea(); + private static byte[][] Get(string resource, string ident) => BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident); static Encounters7b() { - StaticGP = GetEncounters(Encounter_GG, GameVersion.GP); - StaticGE = GetEncounters(Encounter_GG, GameVersion.GE); - ManuallyAddRareSpawns(SlotsGP); ManuallyAddRareSpawns(SlotsGE); - SlotsGP.SetVersion(GameVersion.GP); - SlotsGE.SetVersion(GameVersion.GE); Encounter_GG.SetVersion(GameVersion.GG); TradeGift_GG.SetVersion(GameVersion.GG); MarkEncountersGeneration(7, StaticGP, StaticGE, TradeGift_GG); @@ -83,63 +78,7 @@ static Encounters7b() new EncounterTrade7b { Species = 074, Level = 16, Form = 1, TrainerNames = T8, TID7 = 551873, OTGender = 0, Shiny = Shiny.Random, IVs = new[] {31,31,-1,-1,-1,-1}, IsNicknamed = false }, // Geodude @ Vermilion City, AV rand [0-5) }; - private static EncounterArea7g[] GetGoParkArea() - { - var area = new EncounterArea7g { Location = 50 }; - EncounterSlot GetSlot(int species, int form) - { - return new EncounterSlot7GO - { - Area = area, - Species = species, - LevelMin = 1, - LevelMax = 40, - Form = form, - Type = SlotType.GoPark, - Version = GameVersion.GO, - }; - } - - var obtainable = Enumerable.Range(1, 150).Concat(Enumerable.Range(808, 2)); // count : 152 - var AlolanKanto = new byte[] - { - // Level 1+ - 019, // Rattata - 020, // Raticate - 027, // Sandshrew - 028, // Sandslash - 037, // Vulpix - 038, // Ninetales - 050, // Diglett - 051, // Dugtrio - 052, // Meowth - 053, // Persian - 074, // Geodude - 075, // Graveler - 076, // Golem - 088, // Grimer - 089, // Muk - 103, // Exeggutor - 105, // Marowak - - // Level 15+ - 026, // Raichu - }; - - var regular = obtainable.Select(z => GetSlot(z, 0)); - var alolan = AlolanKanto.Select(z => GetSlot(z, 1)); - var slots = regular.Concat(alolan).ToArray(); - - slots[slots.Length - 1].LevelMin = 15; // Raichu - slots[(int)Species.Mewtwo - 1].LevelMin = 15; - slots[(int)Species.Articuno - 1].LevelMin = 15; - slots[(int)Species.Zapdos - 1].LevelMin = 15; - slots[(int)Species.Moltres - 1].LevelMin = 15; - - area.Slots = slots; - return new[] {area}; - } - + private class RareSpawn { public readonly int Species; @@ -177,7 +116,7 @@ protected internal RareSpawn(int species, params byte[] locations) new RareSpawn(149, Sky), }; - private static void ManuallyAddRareSpawns(IEnumerable areas) + private static void ManuallyAddRareSpawns(IEnumerable areas) { foreach (var table in areas) { @@ -188,13 +127,7 @@ private static void ManuallyAddRareSpawns(IEnumerable areas) var slots = table.Slots; var first = slots[0]; var extra = species - .Select(z => new EncounterSlot7b - { - Area = table, - Species = z, - LevelMin = (z == 006 || z >= 144) ? 03 : first.LevelMin, - LevelMax = (z == 006 || z >= 144) ? 56 : first.LevelMax, - }).ToArray(); + .Select(z => new EncounterSlot7b(table, z, (z == 006 || z >= 144) ? 03 : first.LevelMin, (z == 006 || z >= 144) ? 56 : first.LevelMax, GameVersion.GG)).ToArray(); int count = slots.Length; Array.Resize(ref slots, count + extra.Length); @@ -202,5 +135,8 @@ private static void ManuallyAddRareSpawns(IEnumerable areas) table.Slots = slots; } } + + internal static readonly EncounterStatic[] StaticGP = GetEncounters(Encounter_GG, GameVersion.GP); + internal static readonly EncounterStatic[] StaticGE = GetEncounters(Encounter_GG, GameVersion.GE); } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters8.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters8.cs index daaa79706..b17842a84 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters8.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters8.cs @@ -15,19 +15,17 @@ namespace PKHeX.Core /// internal static class Encounters8 { - internal static readonly EncounterArea8[] SlotsSW_Symbol = GetEncounterTables8("sw", "sw_symbol"); - internal static readonly EncounterArea8[] SlotsSH_Symbol = GetEncounterTables8("sh", "sh_symbol"); - internal static readonly EncounterArea8[] SlotsSW_Hidden = GetEncounterTables8("sw", "sw_hidden"); - internal static readonly EncounterArea8[] SlotsSH_Hidden = GetEncounterTables8("sh", "sh_hidden"); - internal static readonly EncounterArea8[] SlotsSW, SlotsSH; - internal static readonly EncounterStatic[] StaticSW, StaticSH; + private static readonly EncounterArea8[] SlotsSW_Symbol = EncounterAreaSH.GetArray(Get("sw_symbol", "sw"), SW); + private static readonly EncounterArea8[] SlotsSH_Symbol = EncounterAreaSH.GetArray(Get("sh_symbol", "sh"), SH); + private static readonly EncounterArea8[] SlotsSW_Hidden = EncounterAreaSH.GetArray(Get("sw_hidden", "sw"), SW); + private static readonly EncounterArea8[] SlotsSH_Hidden = EncounterAreaSH.GetArray(Get("sh_hidden", "sh"), SH); + private static byte[][] Get(string resource, string ident) => BinLinker.Unpack(Util.GetBinaryResource($"encounter_{resource}.pkl"), ident); + + internal static readonly EncounterArea8[] SlotsSW = ArrayUtil.ConcatAll(SlotsSW_Symbol, SlotsSW_Hidden); + internal static readonly EncounterArea8[] SlotsSH = ArrayUtil.ConcatAll(SlotsSH_Symbol, SlotsSH_Hidden); static Encounters8() { - SlotsSW = ArrayUtil.ConcatAll(SlotsSW_Symbol, SlotsSW_Hidden); - SlotsSH = ArrayUtil.ConcatAll(SlotsSH_Symbol, SlotsSH_Hidden); - SlotsSW.SetVersion(SW); - SlotsSH.SetVersion(SH); foreach (var area in SlotsSW_Symbol) area.PermitCrossover = true; foreach (var area in SlotsSH_Symbol) @@ -46,12 +44,7 @@ static Encounters8() Crystal_SWSH.SetVersion(SWSH); MarkEncounterTradeStrings(TradeGift_SWSH, TradeSWSH); - StaticSW = GetEncounters(Encounter_SWSH, SW); - StaticSH = GetEncounters(Encounter_SWSH, SH); - // Include Nest Tables for both versions -- online play can share them across versions! In the IsMatch method we check if it's a valid share. - StaticSW = ArrayUtil.ConcatAll(Nest_Common, Nest_SW, Nest_SH, Dist_Common, Dist_SW, Dist_SH, GetEncounters(Crystal_SWSH, SW), StaticSW); - StaticSH = ArrayUtil.ConcatAll(Nest_Common, Nest_SW, Nest_SH, Dist_Common, Dist_SW, Dist_SH, GetEncounters(Crystal_SWSH, SH), StaticSH); MarkEncountersGeneration(8, StaticSW, StaticSH, TradeGift_SWSH); @@ -610,5 +603,8 @@ private static void CopyBerryTreeFromBridgeFieldToStony(IReadOnlyList 0; set { } } public override string ToString() => $"{(Species) Species} @ {LevelMin}-{LevelMax}"; - internal EncounterArea? Area { get; set; } - public int Location { get => Area?.Location ?? 0; set { } } + internal readonly EncounterArea Area; + public int Location { get => Area.Location; set { } } - public SlotType Type { get; set; } = SlotType.Any; + protected EncounterSlot(EncounterArea area) => Area = area; public EncounterSlot Clone() => (EncounterSlot)MemberwiseClone(); @@ -67,9 +67,9 @@ public virtual string LongName { get { - if (Type == SlotType.Any) + if (Area!.Type == SlotType.Any) return wild; - return $"{wild} {Type.ToString().Replace('_', ' ')}"; + return $"{wild} {Area!.Type.ToString().Replace('_', ' ')}"; } } @@ -93,7 +93,9 @@ protected virtual void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria pk.CurrentLevel = level; pk.Version = (int)version; pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation); - pk.Ball = (int)Type.GetBall(); + + var ball = BallExtensions.GetRequiredBallValueWild(Generation, Location); + pk.Ball = (int)(ball == Ball.None ? Ball.Poke : ball); pk.Language = lang; pk.OT_Friendship = pk.PersonalInfo.BaseFriendship; pk.AltForm = GetWildAltForm(pk, Form, sav); @@ -126,7 +128,7 @@ protected virtual void SetPINGA(PKM pk, EncounterCriteria criteria) int nature = (int)criteria.GetNature(Nature.Random); var ability = Util.Rand.Next(2); - if (Type == SlotType.HiddenGrotto) // don't force hidden for DexNav + if (Area!.Type == SlotType.HiddenGrotto) // don't force hidden for DexNav ability = 2; PIDGenerator.SetRandomWildPID(pk, pk.Format, nature, ability, gender); diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot1.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot1.cs index d31e2d8fc..4489dd00a 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot1.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot1.cs @@ -8,39 +8,13 @@ public sealed class EncounterSlot1 : EncounterSlot, INumberedSlot public override int Generation => 1; public int SlotNumber { get; set; } - public readonly int Rate; - - public EncounterSlot1(int species, int min, int max, int rate, SlotType type, int slot) + public EncounterSlot1(EncounterArea1 area, int species, int min, int max, int slot, GameVersion game) : base(area) { Species = species; LevelMin = min; LevelMax = max; - Rate = rate; - Type = type; SlotNumber = slot; - } - - /// - /// Deserializes Gen1 Encounter Slots from data. - /// - /// Byte array containing complete slot data table. - /// Offset to start reading from. - /// Amount of slots to read. - /// Type of encounter slot table. - /// Slot type encounter rate. - /// Array of encounter slots. - public static EncounterSlot1[] ReadSlots(byte[] data, ref int ofs, int count, SlotType type, int rate) - { - var bump = type == SlotType.Surf ? 4 : 0; - var slots = new EncounterSlot1[count]; - for (int slot = 0; slot < count; slot++) - { - int min = data[ofs++]; - int species = data[ofs++]; - int max = min + bump; - slots[slot] = new EncounterSlot1(species, min, max, rate, type, slot); - } - return slots; + Version = game; } protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs index dce36e182..ab529436a 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs @@ -11,40 +11,13 @@ public sealed class EncounterSlot2 : EncounterSlot, INumberedSlot public override int Generation => 2; public int SlotNumber { get; set; } - public int Rate; - internal EncounterTime Time; - - public EncounterSlot2(int species, int min, int max, int rate, SlotType type, int slot) + public EncounterSlot2(EncounterArea2 area, int species, int min, int max, int slot, GameVersion game) : base(area) { Species = species; LevelMin = min; LevelMax = max; - Rate = rate; - Type = type; SlotNumber = slot; - } - - /// - /// Deserializes Gen2 Encounter Slots from data. - /// - /// Byte array containing complete slot data table. - /// Offset to start reading from. - /// Amount of slots to read. - /// Type of encounter slot table. - /// Slot type encounter rate. - /// Array of encounter slots. - public static EncounterSlot2[] ReadSlots(byte[] data, ref int ofs, int count, SlotType type, int rate) - { - var bump = type == SlotType.Surf ? 4 : 0; - var slots = new EncounterSlot2[count]; - for (int slot = 0; slot < count; slot++) - { - int min = data[ofs++]; - int species = data[ofs++]; - int max = min + bump; - slots[slot] = new EncounterSlot2(species, min, max, rate, type, slot); - } - return slots; + Version = game; } protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) @@ -53,7 +26,7 @@ protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteri var pk2 = (PK2)pk; if (Version == GameVersion.C) - pk2.Met_TimeOfDay = Time.RandomValidTime(); + pk2.Met_TimeOfDay = ((EncounterArea2)Area!).Time.RandomValidTime(); } } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3.cs index 5d58dded2..760746f2f 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3.cs @@ -4,11 +4,27 @@ public class EncounterSlot3 : EncounterSlot, IMagnetStatic, INumberedSlot { public override int Generation => 3; - public int StaticIndex { get; set; } = -1; - public int MagnetPullIndex { get; set; } = -1; + public int StaticIndex { get; set; } + public int MagnetPullIndex { get; set; } public int StaticCount { get; set; } public int MagnetPullCount { get; set; } public int SlotNumber { get; set; } + + public EncounterSlot3(EncounterArea3 area, int species, int form, int min, int max, int slot, int mpi, int mpc, int sti, int stc, GameVersion game) : base(area) + { + Species = species; + Form = form; + LevelMin = min; + LevelMax = max; + SlotNumber = slot; + Version = game; + + MagnetPullIndex = mpi; + MagnetPullCount = mpc; + + StaticIndex = sti; + StaticCount = stc; + } } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs index ae453c1fe..2169325c2 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs @@ -6,12 +6,13 @@ public sealed class EncounterSlot3PokeSpot : EncounterSlot, INumberedSlot public int SlotNumber { get; set; } - public EncounterSlot3PokeSpot(int species, int min, int max, int slot) + public EncounterSlot3PokeSpot(EncounterArea3XD area, int species, int min, int max, int slot) : base(area) { Species = species; LevelMin = min; LevelMax = max; SlotNumber = slot; + Version = GameVersion.XD; } // PokeSpot encounters always have Fateful Encounter set. diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3Swarm.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3Swarm.cs index a3a9d23b8..77e672448 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3Swarm.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3Swarm.cs @@ -7,7 +7,8 @@ internal sealed class EncounterSlot3Swarm : EncounterSlot3, IMoveset public override int Generation => 3; public IReadOnlyList Moves { get; } - public EncounterSlot3Swarm(IReadOnlyList moves) => Moves = moves; + public EncounterSlot3Swarm(EncounterArea3 area, int species, int min, int max, int slot, GameVersion game, + IReadOnlyList moves) : base(area, species, 0, min, max, slot, 0, 0, 0, 0, game) => Moves = moves; protected override void SetEncounterMoves(PKM pk, GameVersion version, int level) { diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot4.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot4.cs index 1cb41923e..faf7c9069 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot4.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot4.cs @@ -3,15 +3,31 @@ namespace PKHeX.Core public sealed class EncounterSlot4 : EncounterSlot, IMagnetStatic, INumberedSlot { public override int Generation => 4; - public EncounterType TypeEncounter { get; set; } = EncounterType.None; + public EncounterType TypeEncounter => ((EncounterArea4)Area).TypeEncounter; - public int StaticIndex { get; set; } = -1; - public int MagnetPullIndex { get; set; } = -1; + public int StaticIndex { get; set; } + public int MagnetPullIndex { get; set; } public int StaticCount { get; set; } public int MagnetPullCount { get; set; } public int SlotNumber { get; set; } + public EncounterSlot4(EncounterArea4 area, int species, int form, int min, int max, int slot, int mpi, int mpc, int sti, int stc, GameVersion game) : base(area) + { + Species = species; + Form = form; + LevelMin = min; + LevelMax = max; + SlotNumber = slot; + Version = game; + + MagnetPullIndex = mpi; + MagnetPullCount = mpc; + + StaticIndex = sti; + StaticCount = stc; + } + protected override void SetFormatSpecificData(PKM pk) => ((PK4)pk).EncounterType = TypeEncounter.GetIndex(); } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot5.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot5.cs index c4e4b46ae..cbba78388 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot5.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot5.cs @@ -3,5 +3,14 @@ namespace PKHeX.Core public sealed class EncounterSlot5 : EncounterSlot { public override int Generation => 5; + + public EncounterSlot5(EncounterArea5 area, int species, int form, int min, int max, GameVersion game) : base(area) + { + Species = species; + Form = form; + LevelMin = min; + LevelMax = max; + Version = game; + } } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot6AO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot6AO.cs index 23c164b92..d91ae73ca 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot6AO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot6AO.cs @@ -4,18 +4,26 @@ public sealed class EncounterSlot6AO : EncounterSlot { public override int Generation => 6; + public EncounterSlot6AO(EncounterArea6AO area, int species, int form, int min, int max, GameVersion game) : base(area) + { + Species = species; + Form = form; + LevelMin = min; + LevelMax = max; + Version = game; + } + public bool Pressure { get; set; } - public bool AllowDexNav { get; set; } public bool DexNav { get; set; } public bool WhiteFlute { get; set; } public bool BlackFlute { get; set; } - private bool IsDexNav => AllowDexNav && DexNav; + public bool CanDexNav => Area.Type != SlotType.Rock_Smash; protected override void SetFormatSpecificData(PKM pk) { var pk6 = (PK6)pk; - if (IsDexNav) + if (CanDexNav) { var eggMoves = MoveEgg.GetEggMoves(pk, Species, Form, Version); if (eggMoves.Length > 0) diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot6XY.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot6XY.cs index fa10c9069..bb0ed56b6 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot6XY.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot6XY.cs @@ -5,6 +5,15 @@ public sealed class EncounterSlot6XY : EncounterSlot public override int Generation => 6; public bool Pressure { get; set; } + public EncounterSlot6XY(EncounterArea6XY area, int species, int form, int min, int max, GameVersion game) : base(area) + { + Species = species; + Form = form; + LevelMin = min; + LevelMax = max; + Version = game; + } + protected override void SetFormatSpecificData(PKM pk) { var pk6 = (PK6)pk; diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7.cs index 34695ddfe..bd93427b2 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7.cs @@ -2,6 +2,15 @@ namespace PKHeX.Core { public sealed class EncounterSlot7 : EncounterSlot { + public EncounterSlot7(EncounterArea7 area, int species, int form, int min, int max, GameVersion game) : base(area) + { + Species = species; + Form = form; + LevelMin = min; + LevelMax = max; + Version = game; + } + public override int Generation => 7; public bool Pressure { get; set; } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7GO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7GO.cs index 77ac65989..2a5c21213 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7GO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7GO.cs @@ -3,5 +3,14 @@ namespace PKHeX.Core public sealed class EncounterSlot7GO : EncounterSlot { public override int Generation => 7; + + public EncounterSlot7GO(EncounterArea7g area, int species, int form, int min, int max, GameVersion game) : base(area) + { + Species = species; + Form = form; + LevelMin = min; + LevelMax = max; + Version = game; + } } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7b.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7b.cs index 2f0540a51..2958f6a13 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7b.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot7b.cs @@ -3,5 +3,13 @@ namespace PKHeX.Core public sealed class EncounterSlot7b : EncounterSlot { public override int Generation => 7; + + public EncounterSlot7b(EncounterArea7b area, int species, int min, int max, GameVersion game) : base(area) + { + Species = species; + LevelMin = min; + LevelMax = max; + Version = game; + } } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic3.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic3.cs index 8248092e7..d2073af55 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic3.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic3.cs @@ -1,4 +1,7 @@ -namespace PKHeX.Core +using System; +using System.Linq; + +namespace PKHeX.Core { public class EncounterStatic3 : EncounterStatic { @@ -26,11 +29,39 @@ protected override bool IsMatchLocation(PKM pkm) { if (EggEncounter) return true; - if (Location == 0) - return true; - if (pkm.Format == 3) - return Location == pkm.Met_Location; - return true; // transfer location verified later + if (pkm.Format != 3) + return true; // transfer location verified later + + var met = pkm.Met_Location; + if (!Roaming) + return Location == met; + + var table = Version <= GameVersion.E ? Roaming_MetLocation_RSE : Roaming_MetLocation_FRLG; + return table.Contains(met); } + + protected override void SetMetData(PKM pk, int level, DateTime today) + { + pk.Met_Level = level; + pk.Met_Location = !Roaming ? Location : (Version <= GameVersion.E ? Roaming_MetLocation_RSE : Roaming_MetLocation_FRLG)[0]; + } + + private static readonly int[] Roaming_MetLocation_FRLG = + { + // Route 1-25 encounter is possible either in grass or on water + 101,102,103,104,105,106,107,108,109,110, + 111,112,113,114,115,116,117,118,119,120, + 121,122,123,124,125 + }; + + private static readonly int[] Roaming_MetLocation_RSE = + { + // Roaming encounter is possible in tall grass and on water + // Route 101-138 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, + }; } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStaticShadow.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStaticShadow.cs index 350e7db1c..71421700d 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStaticShadow.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStaticShadow.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace PKHeX.Core { @@ -24,5 +25,30 @@ public sealed class EncounterStaticShadow : EncounterStatic3 public EncounterStaticShadow(TeamLock[] locks) => Locks = locks; public EncounterStaticShadow() => Locks = Array.Empty(); + + private static readonly int[] MirorBXDLocations = + { + 090, // Rock + 091, // Oasis + 092, // Cave + 113, // Pyrite Town + 059, // Realgam Tower + }; + + protected override bool IsMatchLocation(PKM pkm) + { + if (pkm.Format != 3) + return true; // transfer location verified later + + var met = pkm.Met_Location; + if (Version == GameVersion.XD) + { + if (met == Location) + return true; + return MirorBXDLocations.Contains(met); + } + + return met == Location; + } } -} \ No newline at end of file +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs index f5b2291d9..7f5faf8ec 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs @@ -306,16 +306,10 @@ private static IEnumerable GenerateRawEncounters(PKM pkm) { yield return z; ++ctr; } if (ctr != 0) yield break; - if (EncounterArea6XYFriendSafari.WasFriendSafari(pkm)) - { - foreach (var z in EncounterArea6XYFriendSafari.GetValidSafariEncounters(pkm)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; - } - foreach (var z in GetValidWildEncounters(pkm, chain)) { yield return z; ++ctr; } if (ctr != 0) yield break; + foreach (var z in GetValidEncounterTrades(pkm, chain)) { yield return z; ++ctr; } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs index 0f0200c5b..6d4de1686 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs @@ -310,14 +310,11 @@ private static bool IsUnobtainable(this EncounterSlot slot, ITrainerID pk) switch (slot.Generation) { case 2: - if ((slot.Type & SlotType.Safari) != 0) // Safari Zone is unavailable in Gen 2. - return true; - - if ((slot.Type & SlotType.Headbutt) != 0) // Unreachable Headbutt Trees. + if (slot.Area.Type == SlotType.Headbutt) // Unreachable Headbutt Trees. return Encounters2.GetGSCHeadbuttAvailability(slot, pk.TID) != TreeEncounterAvailable.ValidTree; break; case 4: - if (slot.Location == 193 && slot.Type == SlotType.Surf) // Johto Route 45 surfing encounter. Unreachable Water tiles. + if (slot.Location == 193 && slot.Area.Type == SlotType.Surf) // Johto Route 45 surfing encounter. Unreachable Water tiles. return true; break; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterSlotGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterSlotGenerator.cs index 048edba32..0472b191d 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterSlotGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterSlotGenerator.cs @@ -24,7 +24,7 @@ public static IEnumerable GetPossible(PKM pkm, IReadOnlyList GetRawEncounterSlots(PKM pkm, IReadOnlyList chain, GameVersion gameSource) { - if (pkm.Egg_Location != 0) + if (pkm.Egg_Location != 0 || pkm.IsEgg) yield break; var possibleAreas = GetEncounterAreas(pkm, gameSource); @@ -61,39 +61,36 @@ public static IEnumerable GetValidWildEncounters(PKM pkm, IReadOn var s = GetRawEncounterSlots(pkm, chain, gameSource); - bool IsSafariBall = pkm.Ball == (int)Ball.Safari; - bool IsSportBall = pkm.Ball == (int)Ball.Sport; bool IsHidden = pkm.AbilityNumber == 4; // hidden Ability int species = pkm.Species; - return s.DeferByBoolean(slot => slot.IsDeferred(species, pkm, IsSafariBall, IsSportBall, IsHidden)); // non-deferred first + return s.DeferByBoolean(slot => slot.IsDeferred(species, pkm, IsHidden)); // non-deferred first } public static bool IsDeferred3(this EncounterSlot slot, int currentSpecies, PKM pkm, bool IsSafariBall) { return slot.IsDeferredWurmple(currentSpecies, pkm) - || slot.IsDeferredSafari(IsSafariBall); + || slot.IsDeferredSafari3(IsSafariBall); } public static bool IsDeferred4(this EncounterSlot slot, int currentSpecies, PKM pkm, bool IsSafariBall, bool IsSportBall) { return slot.IsDeferredWurmple(currentSpecies, pkm) - || slot.IsDeferredSafari(IsSafariBall) + || slot.IsDeferredSafari4(IsSafariBall) || slot.IsDeferredSport(IsSportBall); } - private static bool IsDeferred(this EncounterSlot slot, int currentSpecies, PKM pkm, bool IsSafariBall, bool IsSportBall, bool IsHidden) + private static bool IsDeferred(this EncounterSlot slot, int currentSpecies, PKM pkm, bool IsHidden) { return slot.IsDeferredWurmple(currentSpecies, pkm) - || slot.IsDeferredHiddenAbility(IsHidden) - || slot.IsDeferredSafari(IsSafariBall) - || slot.IsDeferredSport(IsSportBall); + || slot.IsDeferredHiddenAbility(IsHidden); } private static bool IsDeferredWurmple(this IEncounterable slot, int currentSpecies, PKM pkm) => slot.Species == (int)Species.Wurmple && currentSpecies != (int)Species.Wurmple && !WurmpleUtil.IsWurmpleEvoValid(pkm); - private static bool IsDeferredSafari(this EncounterSlot slot, bool IsSafariBall) => IsSafariBall != ((slot.Type & SlotType.Safari) != 0); - private static bool IsDeferredSport(this EncounterSlot slot, bool IsSportBall) => IsSportBall != ((slot.Type & SlotType.BugContest) != 0); - private static bool IsDeferredHiddenAbility(this EncounterSlot slot, bool IsHidden) => IsHidden != slot.IsHiddenAbilitySlot(); + private static bool IsDeferredSafari3(this ILocation slot, bool IsSafariBall) => IsSafariBall != Locations.IsSafariZoneLocation3(slot.Location); + private static bool IsDeferredSafari4(this ILocation slot, bool IsSafariBall) => IsSafariBall != Locations.IsSafariZoneLocation4(slot.Location); + private static bool IsDeferredSport(this ILocation slot, bool IsSportBall) => IsSportBall != (slot.Location == Locations.BugCatchingContest4); + private static bool IsDeferredHiddenAbility(this EncounterSlot slot, bool IsHidden) => IsHidden && !slot.IsHiddenAbilitySlot(); private static IEnumerable GetValidEncounterSlots(PKM pkm, EncounterArea loc, IReadOnlyList chain) { @@ -125,20 +122,13 @@ private static IEnumerable GetEncounterAreas(PKM pkm, GameVersion private static bool IsHiddenAbilitySlot(this EncounterSlot slot) { - return (slot is EncounterSlot6AO ao && ao.DexNav) || slot.Type == SlotType.FriendSafari || slot.Type == SlotType.Horde || slot.Type == SlotType.SOS; + return (slot is EncounterSlot6AO ao && ao.CanDexNav) || slot.Area.Type == SlotType.FriendSafari || slot.Area.Type == SlotType.Horde || slot.Area.Type == SlotType.SOS; } - internal static EncounterArea? GetCaptureLocation(PKM pkm) + internal static EncounterSlot? GetCaptureLocation(PKM pkm) { var chain = EvolutionChain.GetValidPreEvolutions(pkm, maxLevel: 100, skipChecks: true); - return (from area in GetEncounterSlots(pkm) - let slots = GetValidEncounterSlots(pkm, area, chain).ToArray() - where slots.Length != 0 - select new EncounterAreaFake - { - Location = area.Location, - Slots = slots, - }).OrderBy(area => area.Slots.Min(x => x.LevelMin)).FirstOrDefault(); + return GetPossible(pkm, chain).OrderBy(z => z.LevelMin).FirstOrDefault(); } private static IEnumerable GetEncounterTable(PKM pkm, GameVersion gameSource = GameVersion.Any) diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterLearn.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterLearn.cs index 87d3c116f..82e827ed7 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterLearn.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterLearn.cs @@ -138,21 +138,11 @@ private static IEnumerable GetSummaries(IEncounterable item) { switch (item) { - case EncounterSlot s: - var type = s.Type; - if (type == 0) - { - yield return new EncounterSummary(item); - break; - } - for (int i = 0; i < sizeof(SlotType) * 8; i++) - { - var flag = (SlotType)(1 << i); - if ((type & flag) != 0) - yield return new EncounterSummary(item, flag.ToString()); - } - + case EncounterSlot s when s.Area.Type != 0: + { + yield return new EncounterSummary(item, s.Area.Type.ToString()); break; + } default: yield return new EncounterSummary(item); diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs index f9abc76c6..d7d0d84d9 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs @@ -63,11 +63,9 @@ public static int GetSuggestedEncounterEggLocationEgg(PKM pkm, bool traded = fal } } - private static EncounterSuggestionData GetSuggestedEncounterWild(PKM pkm, EncounterArea area, int loc = -1) + private static EncounterSuggestionData GetSuggestedEncounterWild(PKM pkm, EncounterSlot first, int loc = -1) { - var slots = area.Slots.OrderBy(s => s.LevelMin); - var first = slots.First(); - var met = loc != -1 ? loc : area.Location; + var met = loc != -1 ? loc : first.Location; return new EncounterSuggestionData(pkm, first, met); } diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs index 0bc738e49..3880402f1 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs @@ -56,15 +56,6 @@ private static CheckResult VerifyEncounterG12(PKM pkm, LegalInfo info) // Gen2 Wild Encounters private static CheckResult VerifyWildEncounterGen2(PKM pkm, EncounterSlot2 encounter) { - switch (encounter.Type) - { - // Fishing in the beta gen 2 Safari Zone - case SlotType.Old_Rod_Safari: - case SlotType.Good_Rod_Safari: - case SlotType.Super_Rod_Safari: - return new CheckResult(Severity.Invalid, LG2InvalidTileSafari, CheckIdentifier.Encounter); - } - if (encounter.Version == GameVersion.C) return VerifyWildEncounterCrystal(pkm, encounter); @@ -73,10 +64,9 @@ private static CheckResult VerifyWildEncounterGen2(PKM pkm, EncounterSlot2 encou private static CheckResult VerifyWildEncounterCrystal(PKM pkm, EncounterSlot encounter) { - switch (encounter.Type) + switch (encounter.Area.Type) { case SlotType.Headbutt: - case SlotType.Headbutt_Special: return VerifyWildEncounterCrystalHeadbutt(pkm, encounter); case SlotType.Old_Rod: @@ -261,7 +251,7 @@ private static CheckResult VerifyEncounterWild(EncounterSlot slot) switch (slot.Generation) { case 4: - if (slot.Location == 193 && slot.Type == SlotType.Surf) // surfing in Johto Route 45 + if (slot.Location == 193 && slot.Area.Type == SlotType.Surf) // surfing in Johto Route 45 return new CheckResult(Severity.Invalid, LG4InvalidTileR45Surf, CheckIdentifier.Encounter); break; } diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/VerifyRelearnMoves.cs b/PKHeX.Core/Legality/Encounters/Verifiers/VerifyRelearnMoves.cs index a3a376b9a..10fa087dd 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/VerifyRelearnMoves.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/VerifyRelearnMoves.cs @@ -22,7 +22,7 @@ public static CheckResult[] VerifyRelearn(PKM pkm, LegalInfo info) { IRelearn s when s.Relearn.Count > 0 => VerifyRelearnSpecifiedMoveset(pkm, info, s.Relearn), EncounterEgg e => VerifyRelearnEggBase(pkm, info, e), - EncounterSlot6AO z when pkm.RelearnMove1 != 0 && z.DexNav => VerifyRelearnDexNav(pkm, info), + EncounterSlot6AO z when pkm.RelearnMove1 != 0 && z.CanDexNav => VerifyRelearnDexNav(pkm, info), _ => VerifyRelearnNone(pkm, info) }; } diff --git a/PKHeX.Core/Legality/Enums/SlotType.cs b/PKHeX.Core/Legality/Enums/SlotType.cs index 91f8c9d81..00eaf9ec2 100644 --- a/PKHeX.Core/Legality/Enums/SlotType.cs +++ b/PKHeX.Core/Legality/Enums/SlotType.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core /// /// Different from , this corresponds to the method that the may be encountered. [Flags] - public enum SlotType + public enum SlotType : byte { /// /// Default (un-assigned) encounter slot type. @@ -18,125 +18,77 @@ public enum SlotType /// /// Slot is encountered via Grass. /// - Grass = 1 << 00, + Grass = 1, /// /// Slot is encountered via Surfing. /// - Surf = 1 << 01, + Surf = 2, /// /// Slot is encountered via Old Rod (Fishing). /// - Old_Rod = 1 << 02, + Old_Rod = 3, /// /// Slot is encountered via Good Rod (Fishing). /// - Good_Rod = 1 << 03, + Good_Rod = 4, /// /// Slot is encountered via Super Rod (Fishing). /// - Super_Rod = 1 << 04, + Super_Rod = 5, /// /// Slot is encountered via Rock Smash. /// - Rock_Smash = 1 << 05, - - /// - /// Slot is encountered via a Horde. - /// - Horde = 1 << 06, - - /// - /// Slot is encountered via the Friend Safari. - /// - FriendSafari = 1 << 07, - - /// - /// Slot is encountered through special means. Used to signify special slots for Gen2, sometimes for later follow-up). - /// - Special = 1 << 08, - - /// - /// Slot is encountered via SOS signal. - /// - SOS = 1 << 09, - - /// - /// Slot is encountered in a Swarm. - /// - Swarm = 1 << 10, + Rock_Smash = 6, /// /// Slot is encountered via Headbutt. /// - Headbutt = 1 << 11, - - Headbutt_Special = Headbutt | Special, - - /// - /// Slot is encountered via the Poké Radar. - /// - Pokeradar = 1 << 12, + Headbutt = 7, /// /// Slot is encountered via a Honey Tree. /// - HoneyTree = 1 << 13, - - /// - /// Slot is encountered via a Hidden Grotto. - /// - HiddenGrotto = 1 << 14, + HoneyTree = 8, /// /// Slot is encountered via the Bug Catching Contest. /// - BugContest = 1 << 15, + BugContest = 9, - /// - /// Slot is encountered via the Go Park. - /// - GoPark = 1 << 16, + HiddenGrotto = 10, + GoPark = 11, + FriendSafari = 12, + Horde = 13, + // Pokeradar = 14, + SOS = 15, + // always used as a modifier to another slot type - /// - /// Slot is encountered in the Safari Zone. - /// - Safari = 1 << 30, // always used as a modifier to another slot type - - Grass_Safari = Grass | Safari, - Surf_Safari = Surf | Safari, - Old_Rod_Safari = Old_Rod | Safari, - Good_Rod_Safari = Good_Rod | Safari, - Super_Rod_Safari = Super_Rod | Safari, - Rock_Smash_Safari = Rock_Smash | Safari, - Pokeradar_Safari = Pokeradar | Safari, + Swarm = 1 << 7, } public static partial class Extensions { - internal static bool IsSafariType(this SlotType t) => (t & SlotType.Safari) != 0; - internal static bool IsFishingRodType(this SlotType t) { - return (t & SlotType.Old_Rod) != 0 || (t & SlotType.Good_Rod) != 0 || (t & SlotType.Super_Rod) != 0; + t &= (SlotType)0xF; + return t == SlotType.Old_Rod || t == SlotType.Good_Rod || t == SlotType.Super_Rod; } internal static bool IsSweetScentType(this SlotType t) { - return !(t.IsFishingRodType() || (t & SlotType.Rock_Smash) != 0); - } + return t switch + { + SlotType.Grass => true, + SlotType.Surf => true, + SlotType.BugContest => true, - public static Ball GetBall(this SlotType t) - { - if (t == SlotType.BugContest) - return Ball.Sport; - if (t.IsSafariType()) - return Ball.Safari; - return Ball.Poke; + _ => false, + }; } } } diff --git a/PKHeX.Core/Legality/RNG/Frame/Frame.cs b/PKHeX.Core/Legality/RNG/Frame/Frame.cs index e8450e71b..fcb4ffb32 100644 --- a/PKHeX.Core/Legality/RNG/Frame/Frame.cs +++ b/PKHeX.Core/Legality/RNG/Frame/Frame.cs @@ -78,7 +78,7 @@ public Frame(uint seed, FrameType type, LeadRequired lead) { // Static and Magnet Pull do a slot search rather than slot mapping 0-99. return Lead != LeadRequired.StaticMagnet - ? SlotRange.GetSlot(slot.Type, RandESV, FrameType) + ? SlotRange.GetSlot(slot.Area.Type, RandESV, FrameType) : SlotRange.GetSlotStaticMagnet(slot, RandESV); } diff --git a/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs b/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs index 3840ffb17..2d4fc11f8 100644 --- a/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs +++ b/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs @@ -32,15 +32,10 @@ private static int HSlot(SlotType type, uint rand) return type switch { SlotType.Old_Rod => CalcSlot(ESV, H_OldRod), - SlotType.Old_Rod_Safari => CalcSlot(ESV, H_OldRod), SlotType.Good_Rod => CalcSlot(ESV, H_GoodRod), - SlotType.Good_Rod_Safari => CalcSlot(ESV, H_GoodRod), SlotType.Super_Rod => CalcSlot(ESV, H_SuperRod), - SlotType.Super_Rod_Safari => CalcSlot(ESV, H_SuperRod), SlotType.Rock_Smash => CalcSlot(ESV, H_Surf), - SlotType.Rock_Smash_Safari => CalcSlot(ESV, H_Surf), SlotType.Surf => CalcSlot(ESV, H_Surf), - SlotType.Surf_Safari => CalcSlot(ESV, H_Surf), SlotType.Swarm => (ESV < 50 ? 0 : -1), _ => CalcSlot(ESV, H_Regular) }; @@ -60,15 +55,7 @@ private static int KSlot(SlotType type, uint rand) return CalcSlot(ESV, K_SuperRod); case SlotType.BugContest: return CalcSlot(ESV, K_BCC); - case SlotType.Grass_Safari: - case SlotType.Surf_Safari: - case SlotType.Old_Rod_Safari: - case SlotType.Good_Rod_Safari: - case SlotType.Super_Rod_Safari: - case SlotType.Rock_Smash_Safari: - return 0; // (int)(rand % 10); /* Block Slot Priority not implemented */ case SlotType.Headbutt: - case SlotType.Headbutt_Special: return CalcSlot(ESV, K_Headbutt); default: return CalcSlot(ESV, H_Regular); @@ -143,7 +130,7 @@ public static int GetLevel(EncounterSlot slot, LeadRequired lead, uint lvlrand) public static bool GetIsEncounterable(EncounterSlot slot, FrameType frameType, int rand, LeadRequired lead) #pragma warning restore IDE0060, RCS1163 // Unused parameter. { - if (slot.Type.IsSweetScentType()) + if (slot.Area.Type.IsSweetScentType()) return true; return true; // todo //return GetCanEncounter(slot, frameType, rand, lead); @@ -153,27 +140,28 @@ public static bool GetIsEncounterable(EncounterSlot slot, FrameType frameType, i public static bool GetCanEncounter(EncounterSlot slot, FrameType frameType, int rand, LeadRequired lead) { int proc = frameType == FrameType.MethodJ ? rand / 656 : rand % 100; - if ((slot.Type & SlotType.Rock_Smash) != 0) + var stype = slot.Area.Type; + if (stype == SlotType.Rock_Smash) return proc < 60; if (frameType == FrameType.MethodH) return true; // fishing encounters are disjointed by the hooked message. // fishing - if ((slot.Type & SlotType.Old_Rod) != 0) + if (stype == SlotType.Old_Rod) { if (proc < 25) return true; if (proc < 50) return lead == LeadRequired.None; } - else if ((slot.Type & SlotType.Good_Rod) != 0) + else if (stype == SlotType.Good_Rod) { if (proc < 50) return true; if (proc < 75 && lead == LeadRequired.None) return lead == LeadRequired.None; } - else if ((slot.Type & SlotType.Super_Rod) != 0) + else if (stype == SlotType.Super_Rod) { if (proc < 75) return true; diff --git a/PKHeX.Core/Legality/RNG/PIDGenerator.cs b/PKHeX.Core/Legality/RNG/PIDGenerator.cs index 8c90dd6dd..3a6e1e156 100644 --- a/PKHeX.Core/Legality/RNG/PIDGenerator.cs +++ b/PKHeX.Core/Legality/RNG/PIDGenerator.cs @@ -401,16 +401,7 @@ private static void SetRandomWildPID(PKM pk, int nature, int ability, int gender private static void SetRandomIVs(PKM pk) { - var rng = Util.Rand; - pk.IVs = new[] - { - rng.Next(32), - rng.Next(32), - rng.Next(32), - rng.Next(32), - rng.Next(32), - rng.Next(32), - }; + pk.IVs = pk.SetRandomIVs(); } } } diff --git a/PKHeX.Core/Legality/Tables/Locations.cs b/PKHeX.Core/Legality/Tables/Locations.cs index 49d4aae9d..51a306b69 100644 --- a/PKHeX.Core/Legality/Tables/Locations.cs +++ b/PKHeX.Core/Legality/Tables/Locations.cs @@ -71,6 +71,8 @@ public static class Locations /// Generation 4 -> Generation 5 Transfer Location (Crown Beast - Event activated in Gen 5) public const int Transfer4_CrownUsed = 30013; + public const int BugCatchingContest4 = 207; + public static int TradedEggLocationNPC(int gen) { return gen switch @@ -98,6 +100,11 @@ public static int TradedEggLocation(int gen) public static bool IsPtHGSSLocationEgg(int location) => 2010 < location && location < 3000; public static bool IsEventLocation5(int location) => 40000 < location && location < 50000; - public static bool IsSafariZoneLocation4(int loc) => loc == 52 || loc == 202; + private const int SafariLocation_RSE = 57; + private const int SafariLocation_FRLG = 136; + private const int SafariLocation_HGSS = 202; + private const int MarshLocation_DPPt = 52; + public static bool IsSafariZoneLocation3(int loc) => loc == SafariLocation_RSE || loc == SafariLocation_FRLG; + public static bool IsSafariZoneLocation4(int loc) => loc == MarshLocation_DPPt || loc == SafariLocation_HGSS; } } diff --git a/PKHeX.Core/Legality/Verifiers/AbilityVerifier.cs b/PKHeX.Core/Legality/Verifiers/AbilityVerifier.cs index 0aedef349..56156b4f5 100644 --- a/PKHeX.Core/Legality/Verifiers/AbilityVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/AbilityVerifier.cs @@ -37,11 +37,12 @@ private CheckResult VerifyAbility(LegalityAnalysis data) if (abilval < 0) return GetInvalid(LAbilityUnexpected); - if (data.EncounterMatch is MysteryGift g && g.Format >= 4) - return VerifyAbilityMG(data, abilities, g.AbilityType); + var enc = data.EncounterMatch; + if (enc is MysteryGift g && g.Format >= 4) + return VerifyAbilityMG(data, g, abilities); if (pkm.Format < 6) - return VerifyAbility345(data, abilities, abilval); + return VerifyAbility345(data, enc, abilities, abilval); // Check AbilityNumber is a single set bit var num = pkm.AbilityNumber; @@ -58,8 +59,8 @@ private CheckResult VerifyAbility(LegalityAnalysis data) private CheckResult VerifyAbility(LegalityAnalysis data, IReadOnlyList abilities, int abilnum) { - var EncounterMatch = data.EncounterMatch; - var eabil = GetEncounterFixedAbilityNumber(EncounterMatch); + var enc = data.EncounterMatch; + var eabil = GetEncounterFixedAbilityNumber(enc); if (eabil >= 0) { if ((data.pkm.AbilityNumber == 4) != (eabil == 4)) @@ -71,15 +72,15 @@ private CheckResult VerifyAbility(LegalityAnalysis data, IReadOnlyList abil var gen = data.Info.Generation; return gen switch { - 5 => VerifyAbility5(data, abilities), - 6 => VerifyAbility6(data), - 7 => VerifyAbility7(data), - 8 => VerifyAbility8(data), + 5 => VerifyAbility5(data, enc, abilities), + 6 => VerifyAbility6(data, enc), + 7 => VerifyAbility7(data, enc), + 8 => VerifyAbility8(data, enc), _ => CheckMatch(data.pkm, abilities, gen, AbilityState.CanMismatch) }; } - private CheckResult VerifyAbility345(LegalityAnalysis data, IReadOnlyList abilities, int abilnum) + private CheckResult VerifyAbility345(LegalityAnalysis data, IEncounterable enc, IReadOnlyList abilities, int abilnum) { var pkm = data.pkm; var state = AbilityState.MustMatch; @@ -98,7 +99,7 @@ private CheckResult VerifyAbility345(LegalityAnalysis data, IReadOnlyList a int gen = data.Info.Generation; if (gen == 5) - return VerifyAbility5(data, abilities); + return VerifyAbility5(data, enc, abilities); return CheckMatch(pkm, abilities, gen, state); } @@ -188,29 +189,30 @@ private AbilityState VerifyAbilityGen3Transfer(LegalityAnalysis data, IReadOnlyL return AbilityState.CanMismatch; } - private CheckResult VerifyAbilityMG(LegalityAnalysis data, IReadOnlyList abilities, int cardtype) + private CheckResult VerifyAbilityMG(LegalityAnalysis data, MysteryGift g, IReadOnlyList abilities) { - if (data.EncounterMatch is PCD d) + if (g is PCD d) return VerifyAbilityPCD(data, abilities, d); var pkm = data.pkm; - if (data.EncounterMatch is PGT) // Ranger Manaphy + if (g is PGT) // Ranger Manaphy return (pkm.Format >= 6 ? (pkm.AbilityNumber == 1) : (pkm.AbilityNumber < 4)) ? VALID : GetInvalid(LAbilityMismatchGift); - int abilNumber = pkm.AbilityNumber; - if (cardtype == 4) // 1/2/H + var cardType = g.AbilityType; + if (cardType == 4) // 1/2/H return VALID; - if (cardtype == 3) // 1/2 + int abilNumber = pkm.AbilityNumber; + if (cardType == 3) // 1/2 return abilNumber == 4 ? GetInvalid(LAbilityMismatchGift) : VALID; // Only remaining matches are fixed index abilities - int cardAbilIndex = 1 << cardtype; + int cardAbilIndex = 1 << cardType; if (abilNumber == cardAbilIndex) return VALID; // Can still match if the ability was changed via ability capsule... // However, it can't change to/from Hidden Abilities. - if (abilNumber == 4 || cardtype == 2) + if (abilNumber == 4 || cardType == 2) return GetInvalid(LAbilityHiddenFail); // Ability can be flipped 0/1 if Ability Capsule is available, is not Hidden Ability, and Abilities are different. @@ -243,14 +245,14 @@ private CheckResult VerifyAbilityPCD(LegalityAnalysis data, IReadOnlyList a return pkm.Ability == pcd.Gift.PK.Ability ? VALID : INVALID; } - private CheckResult VerifyAbility5(LegalityAnalysis data, IReadOnlyList abilities) + private CheckResult VerifyAbility5(LegalityAnalysis data, IEncounterable enc, IReadOnlyList abilities) { var pkm = data.pkm; - switch (data.EncounterMatch) + switch (enc) { case EncounterSlot w: // Hidden Abilities for Wild Encounters are only available at a Hidden Grotto - bool grotto = w.Type == SlotType.HiddenGrotto; + bool grotto = w.Area.Type == SlotType.HiddenGrotto; if (pkm.AbilityNumber == 4 ^ grotto) return GetInvalid(grotto ? LAbilityMismatchGrotto : LAbilityHiddenFail); break; @@ -265,17 +267,16 @@ private CheckResult VerifyAbility5(LegalityAnalysis data, IReadOnlyList abi return CheckMatch(data.pkm, abilities, 5, state); } - private CheckResult VerifyAbility6(LegalityAnalysis data) + private CheckResult VerifyAbility6(LegalityAnalysis data, IEncounterable enc) { var pkm = data.pkm; if (pkm.AbilityNumber != 4) return VALID; // hidden abilities - var EncounterMatch = data.EncounterMatch; - if (EncounterMatch is EncounterSlot slot) + if (enc is EncounterSlot slot) { - bool valid = (slot is EncounterSlot6AO ao && ao.DexNav) || slot.Type == SlotType.FriendSafari || slot.Type == SlotType.Horde; + bool valid = (slot is EncounterSlot6AO ao && ao.CanDexNav) || slot.Area.Type == SlotType.FriendSafari || slot.Area.Type == SlotType.Horde; if (!valid) return GetInvalid(LAbilityMismatchHordeSafari); } @@ -285,13 +286,12 @@ private CheckResult VerifyAbility6(LegalityAnalysis data) return VALID; } - private CheckResult VerifyAbility7(LegalityAnalysis data) + private CheckResult VerifyAbility7(LegalityAnalysis data, IEncounterable enc) { var pkm = data.pkm; - var EncounterMatch = data.EncounterMatch; - if (EncounterMatch is EncounterSlot slot && pkm.AbilityNumber == 4) + if (enc is EncounterSlot slot && pkm.AbilityNumber == 4) { - bool valid = slot.Type == SlotType.SOS; + bool valid = slot.Area.Type == SlotType.SOS; if (!valid) return GetInvalid(LAbilityMismatchSOS); } @@ -301,11 +301,10 @@ private CheckResult VerifyAbility7(LegalityAnalysis data) return VALID; } - private CheckResult VerifyAbility8(LegalityAnalysis data) + private CheckResult VerifyAbility8(LegalityAnalysis data, IEncounterable enc) { var pkm = data.pkm; - var EncounterMatch = data.EncounterMatch; - if (EncounterMatch is EncounterSlot && pkm.AbilityNumber == 4) + if (enc is EncounterSlot && pkm.AbilityNumber == 4) return GetInvalid(LAbilityHiddenUnavailable); if (Legal.Ban_NoHidden8.Contains(pkm.SpecForm) && pkm.AbilityNumber == 4) return GetInvalid(LAbilityHiddenUnavailable); diff --git a/PKHeX.Core/Legality/Verifiers/BallVerifier.cs b/PKHeX.Core/Legality/Verifiers/BallVerifier.cs index 88dc89038..f31a87dec 100644 --- a/PKHeX.Core/Legality/Verifiers/BallVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/BallVerifier.cs @@ -74,20 +74,30 @@ private CheckResult VerifyBallStatic(LegalityAnalysis data, EncounterStatic s) return VerifyBallEquals(data, Legal.GetWildBalls(data.Info.Generation, data.Info.Game)); } + private static Ball GetRequiredBallValue(int gen, int loc) + { + return gen switch + { + // For Gen3 Safari Zones, we've already deferred partial match encounters. + 3 when Locations.IsSafariZoneLocation3(loc) => Safari, + + // For Gen4 Safari Zones and BCC, we've already deferred partial match encounters. + 4 when Locations.IsSafariZoneLocation4(loc) => Safari, + 4 when Locations.BugCatchingContest4 == loc => Sport, + + // Poké Pelago + 7 when loc == 30016 => Poke, + + _ => None, + }; + } + private CheckResult VerifyBallWild(LegalityAnalysis data, EncounterSlot w) { - if (w.Location == 30016 && w.Generation == 7) // Poké Pelago - return VerifyBallEquals(data, (int)Poke); // Pokeball + var req = BallExtensions.GetRequiredBallValueWild(w.Generation, w.Location); + if (req != None) + return VerifyBallEquals(data, (int) req); - var Info = data.Info; - - // For gen3/4 Safari Zones and BCC getValidWildEncounters already filter to not return - // mixed possible encounters between safari, BCC and other encounters - // That means is the first encounter is not safari then there is no safari encounter in the array - if (3 <= Info.Generation && Info.Generation <= 4 && w.Type.IsSafariType()) - return VerifyBallEquals(data, (int)Safari); // Safari Ball - if (Info.Generation == 4 && w.Type == SlotType.BugContest) - return VerifyBallEquals(data, (int)Sport); // Sport Ball return VerifyBallEquals(data, Legal.GetWildBalls(data.Info.Generation, data.Info.Game)); } diff --git a/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs index fd3b28689..2fab2f4ab 100644 --- a/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs @@ -71,7 +71,7 @@ private void VerifyAwakenedValues(LegalityAnalysis data, IAwakened awakened) var EncounterMatch = data.EncounterMatch; if (!awakened.AwakeningAllValid()) data.AddLine(GetInvalid(LAwakenedCap)); - if (EncounterMatch is EncounterSlot s && s.Type == SlotType.GoPark && Enumerable.Range(0, 6).Select(awakened.GetAV).Any(z => z < 2)) + if (EncounterMatch is EncounterSlot s && s.Area.Type == SlotType.GoPark && Enumerable.Range(0, 6).Select(awakened.GetAV).Any(z => z < 2)) data.AddLine(GetInvalid(string.Format(LAwakenedShouldBeValue, 2))); // go park transfers have 2 AVs for all stats. else if (awakened.AwakeningSum() == 0 && !EncounterMatch.IsWithinRange(pkm)) data.AddLine(Get(LAwakenedEXPIncreased, Severity.Fishy)); diff --git a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs index 003fd23c2..7908a2cf8 100644 --- a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs @@ -42,7 +42,7 @@ private CheckResult VerifyForm(LegalityAnalysis data) if (!PersonalInfo.IsFormeWithinRange(form) && !FormConverter.IsValidOutOfBoundsForme(species, form, Info.Generation)) return GetInvalid(string.Format(LFormInvalidRange, count - 1, form)); - if (EncounterMatch is EncounterSlot w && w.Type == SlotType.FriendSafari) + if (EncounterMatch is EncounterSlot w && w.Area.Type == SlotType.FriendSafari) { VerifyFormFriendSafari(data); } diff --git a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs index 7721e5baf..aa3283c10 100644 --- a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs @@ -94,7 +94,7 @@ private void VerifyIVsGen6(LegalityAnalysis data, EncounterSlot w) var pkm = data.pkm; if (pkm.XY && PersonalTable.XY[data.EncounterMatch.Species].IsEggGroup(15)) // Undiscovered VerifyIVsFlawless(data, 3); - else if (w.Type == SlotType.FriendSafari) + else if (w.Area.Type == SlotType.FriendSafari) VerifyIVsFlawless(data, 2); } diff --git a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs index 2e076c651..d9e3cd963 100644 --- a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs @@ -57,9 +57,9 @@ private void VerifyShiny(LegalityAnalysis data) break; case EncounterSlot w: - if (pkm.IsShiny && w.Type == SlotType.HiddenGrotto) + if (pkm.IsShiny && w.Area.Type == SlotType.HiddenGrotto) data.AddLine(GetInvalid(LG5PIDShinyGrotto, CheckIdentifier.Shiny)); - if (Info.Generation == 5 && w.Type != SlotType.HiddenGrotto) + if (Info.Generation == 5 && w.Area.Type != SlotType.HiddenGrotto) VerifyG5PID_IDCorrelation(data); break; diff --git a/PKHeX.Core/PKHeX.Core.csproj b/PKHeX.Core/PKHeX.Core.csproj index 61d793743..133d8b82a 100644 --- a/PKHeX.Core/PKHeX.Core.csproj +++ b/PKHeX.Core/PKHeX.Core.csproj @@ -31,47 +31,36 @@ - - - - - + - - - - - - - @@ -856,47 +845,36 @@ - - - - - + - - - - - - - diff --git a/PKHeX.Core/Resources/byte/encounter_a.pkl b/PKHeX.Core/Resources/byte/encounter_a.pkl index f7b359e18..45ac6db12 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_a.pkl and b/PKHeX.Core/Resources/byte/encounter_a.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_b.pkl b/PKHeX.Core/Resources/byte/encounter_b.pkl index 439993865..736deac19 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_b.pkl and b/PKHeX.Core/Resources/byte/encounter_b.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_b2.pkl b/PKHeX.Core/Resources/byte/encounter_b2.pkl index bb9e1eeae..68dfca7a4 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_b2.pkl and b/PKHeX.Core/Resources/byte/encounter_b2.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_blue.pkl b/PKHeX.Core/Resources/byte/encounter_blue.pkl index 1ba7b481a..7950f31f6 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_blue.pkl and b/PKHeX.Core/Resources/byte/encounter_blue.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_crystal.pkl b/PKHeX.Core/Resources/byte/encounter_crystal.pkl index 6de85c4d2..e1289b5b1 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_crystal.pkl and b/PKHeX.Core/Resources/byte/encounter_crystal.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_crystal_h.pkl b/PKHeX.Core/Resources/byte/encounter_crystal_h.pkl deleted file mode 100644 index d1b42d922..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_crystal_h.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_d.pkl b/PKHeX.Core/Resources/byte/encounter_d.pkl index 89099af4e..b26ab102b 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_d.pkl and b/PKHeX.Core/Resources/byte/encounter_d.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_e.pkl b/PKHeX.Core/Resources/byte/encounter_e.pkl index b74e425c9..120b61ddd 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_e.pkl and b/PKHeX.Core/Resources/byte/encounter_e.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_fr.pkl b/PKHeX.Core/Resources/byte/encounter_fr.pkl index 0dcf716f7..b1c35379a 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_fr.pkl and b/PKHeX.Core/Resources/byte/encounter_fr.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_gold.pkl b/PKHeX.Core/Resources/byte/encounter_gold.pkl index c92b618ee..db98048c0 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_gold.pkl and b/PKHeX.Core/Resources/byte/encounter_gold.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_gold_h.pkl b/PKHeX.Core/Resources/byte/encounter_gold_h.pkl deleted file mode 100644 index ff6b561ea..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_gold_h.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_gsc_f.pkl b/PKHeX.Core/Resources/byte/encounter_gsc_f.pkl deleted file mode 100644 index 3254575a1..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_gsc_f.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_hb_hg.pkl b/PKHeX.Core/Resources/byte/encounter_hb_hg.pkl deleted file mode 100644 index 339ecbdc2..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_hb_hg.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_hb_ss.pkl b/PKHeX.Core/Resources/byte/encounter_hb_ss.pkl deleted file mode 100644 index 3d37db1b9..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_hb_ss.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_hg.pkl b/PKHeX.Core/Resources/byte/encounter_hg.pkl index c45893dcb..13614463f 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_hg.pkl and b/PKHeX.Core/Resources/byte/encounter_hg.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_lg.pkl b/PKHeX.Core/Resources/byte/encounter_lg.pkl index 8fc08f08e..883cc174e 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_lg.pkl and b/PKHeX.Core/Resources/byte/encounter_lg.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_mn.pkl b/PKHeX.Core/Resources/byte/encounter_mn.pkl index 4e872809c..7e12f1fc5 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_mn.pkl and b/PKHeX.Core/Resources/byte/encounter_mn.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_mn_sos.pkl b/PKHeX.Core/Resources/byte/encounter_mn_sos.pkl deleted file mode 100644 index c42706498..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_mn_sos.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_o.pkl b/PKHeX.Core/Resources/byte/encounter_o.pkl index ac34096cd..84a6d5bed 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_o.pkl and b/PKHeX.Core/Resources/byte/encounter_o.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_p.pkl b/PKHeX.Core/Resources/byte/encounter_p.pkl index eb0d7a4c8..bdccd4628 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_p.pkl and b/PKHeX.Core/Resources/byte/encounter_p.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_pt.pkl b/PKHeX.Core/Resources/byte/encounter_pt.pkl index dc4542abb..e37dc9e20 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_pt.pkl and b/PKHeX.Core/Resources/byte/encounter_pt.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_r.pkl b/PKHeX.Core/Resources/byte/encounter_r.pkl index 194e3c3a4..2e5d0f74c 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_r.pkl and b/PKHeX.Core/Resources/byte/encounter_r.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_rb_f.pkl b/PKHeX.Core/Resources/byte/encounter_rb_f.pkl deleted file mode 100644 index 01ffcb391..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_rb_f.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_red.pkl b/PKHeX.Core/Resources/byte/encounter_red.pkl index bf235971d..75313dd20 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_red.pkl and b/PKHeX.Core/Resources/byte/encounter_red.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_rse_swarm.pkl b/PKHeX.Core/Resources/byte/encounter_rse_swarm.pkl new file mode 100644 index 000000000..c161b4fff Binary files /dev/null and b/PKHeX.Core/Resources/byte/encounter_rse_swarm.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_s.pkl b/PKHeX.Core/Resources/byte/encounter_s.pkl index af14836bd..724172920 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_s.pkl and b/PKHeX.Core/Resources/byte/encounter_s.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_silver.pkl b/PKHeX.Core/Resources/byte/encounter_silver.pkl index b80de3d7f..8026b9835 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_silver.pkl and b/PKHeX.Core/Resources/byte/encounter_silver.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_silver_h.pkl b/PKHeX.Core/Resources/byte/encounter_silver_h.pkl deleted file mode 100644 index 07a7d561f..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_silver_h.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_sn.pkl b/PKHeX.Core/Resources/byte/encounter_sn.pkl index 67c2861c6..56ec38d87 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_sn.pkl and b/PKHeX.Core/Resources/byte/encounter_sn.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_sn_sos.pkl b/PKHeX.Core/Resources/byte/encounter_sn_sos.pkl deleted file mode 100644 index 4db4805d6..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_sn_sos.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_ss.pkl b/PKHeX.Core/Resources/byte/encounter_ss.pkl index 409df781d..cd44002eb 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_ss.pkl and b/PKHeX.Core/Resources/byte/encounter_ss.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_um.pkl b/PKHeX.Core/Resources/byte/encounter_um.pkl index 4b758a125..735957b2d 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_um.pkl and b/PKHeX.Core/Resources/byte/encounter_um.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_um_sos.pkl b/PKHeX.Core/Resources/byte/encounter_um_sos.pkl deleted file mode 100644 index c707614f7..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_um_sos.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_us.pkl b/PKHeX.Core/Resources/byte/encounter_us.pkl index 76fa962b6..ccf00b342 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_us.pkl and b/PKHeX.Core/Resources/byte/encounter_us.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_us_sos.pkl b/PKHeX.Core/Resources/byte/encounter_us_sos.pkl deleted file mode 100644 index cabd42081..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_us_sos.pkl and /dev/null differ diff --git a/PKHeX.Core/Resources/byte/encounter_w.pkl b/PKHeX.Core/Resources/byte/encounter_w.pkl index a8a61b5e8..c204d5604 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_w.pkl and b/PKHeX.Core/Resources/byte/encounter_w.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_w2.pkl b/PKHeX.Core/Resources/byte/encounter_w2.pkl index d1dff5da4..201744746 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_w2.pkl and b/PKHeX.Core/Resources/byte/encounter_w2.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_x.pkl b/PKHeX.Core/Resources/byte/encounter_x.pkl index 514be6e1d..92e1b7b0f 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_x.pkl and b/PKHeX.Core/Resources/byte/encounter_x.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_y.pkl b/PKHeX.Core/Resources/byte/encounter_y.pkl index 856d80fb9..c7308183c 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_y.pkl and b/PKHeX.Core/Resources/byte/encounter_y.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_yellow.pkl b/PKHeX.Core/Resources/byte/encounter_yellow.pkl index 16718e632..25051356c 100644 Binary files a/PKHeX.Core/Resources/byte/encounter_yellow.pkl and b/PKHeX.Core/Resources/byte/encounter_yellow.pkl differ diff --git a/PKHeX.Core/Resources/byte/encounter_yellow_f.pkl b/PKHeX.Core/Resources/byte/encounter_yellow_f.pkl deleted file mode 100644 index 7663fbb27..000000000 Binary files a/PKHeX.Core/Resources/byte/encounter_yellow_f.pkl and /dev/null differ