mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 06:34:19 +00:00
Offload EncounterSlot loading logic to reduce complexity (#2980)
* Rework gen1 slot loading Slot templates are precomputed from ROM data and just loaded straight in, with tight coupling to the encounter area (grouped by slot types). * Revise fuzzy met check for underleveled wild evos Example: Level 23 poliwhirl in RBY as a level 50 poliwhirl, will assume the chain is 25-50 for poliwhirl (as poliwag evolves at 25). Instead of revising the origin chain, just ignore the evo min level in the comparison. Previous commit fixed it for gen1. * Rework gen2-4 slot loading Gen4 not finished, Type Encounter data and some edge encounters not recognizing yet... * Add feebas slots for old/good encounters * Begin moving properties Great news! Gen5-7 need to be de-dumbed like Gen1-4. Then I can remove the bang (!) on the Area accessor and ensure that it's never null! * Split off XD pokespot slot encounter table type * Set area in constructor * Deduplicate g3 roaming encounters * Deduplicate xd encounter locations (rebattle) Only difference is met location; no need to create 500 extra encounter objects. A simple contains check is ok (rarely in gen3 format). * Make all slots have a readonly reference to their parent area * Minor clean * Remove "Safari" slot type flag Can be determined via other means (generation-location), allows us to reduce the size of SlotType member to a byte Output of slot binaries didn't preserve the Safari flag anyway. * Update SlotType.cs * Handle type encounters correctly * Merge safari area into regular xy area * Merge dexnav accessor logic * fix some logic so that tests pass again rearrange g5 dw init to be done outside of static constructor (initializer instead) PIDGenerator: friend safari slots now generate with required flawless IV count * Add cianwood tentacool gift encounter * Remove unnecessary abstractions Fake area just returned a slot; since Slots have a non-null reference to the area, we can just return the slot and use the API to grab a list of possible slots for the chain. Increase restrictiveness of location/type get-set operations * Minor tweaks, pass parameters DexNav observed state isn't necessary to use, only need to see if it's possible to dexnav. Now that we have metadata for slots, we can. * Remove unused legality tables
This commit is contained in:
parent
c1bc371d76
commit
6ee7a8724b
104 changed files with 1082 additions and 3827 deletions
|
@ -40,7 +40,7 @@ namespace PKHeX.Core
|
|||
Beast = 26,
|
||||
}
|
||||
|
||||
public static partial class Extensions
|
||||
public static class BallExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="ball"/> is an Apricorn Ball (HG/SS)
|
||||
|
@ -48,5 +48,23 @@ namespace PKHeX.Core
|
|||
/// <param name="ball">Ball ID</param>
|
||||
/// <returns>True if Apricorn, false if not.</returns>
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,71 +6,19 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Represents an Area where <see cref="PKM"/> can be encountered, which contains a Location ID and <see cref="EncounterSlot"/> data.
|
||||
/// </summary>
|
||||
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<EncounterSlot>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encounter areas for species with same level range and same slot type at same location
|
||||
/// </summary>
|
||||
/// <param name="species">List of species that exist in the Area.</param>
|
||||
/// <param name="lvls">Paired min and max levels of the encounter slots.</param>
|
||||
/// <param name="location">Location index of the encounter area.</param>
|
||||
/// <param name="t">Encounter slot type of the encounter area.</param>
|
||||
/// <returns>Encounter area with slots</returns>
|
||||
public static TArea[] GetSimpleEncounterArea<TArea, TSlot>(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 } };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the slots contained in the area that match the provided data.
|
||||
/// </summary>
|
||||
/// <param name="pkm">Pokémon Data</param>
|
||||
/// <param name="chain">Evolution lineage</param>
|
||||
/// <returns>Enumerable list of encounters</returns>
|
||||
public virtual IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> 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<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the provided met location ID matches the parameters for the area.
|
||||
|
|
|
@ -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
|
|||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot"/> information from Generation 1 Grass/Water data.
|
||||
/// </summary>
|
||||
/// <param name="data">Input raw data.</param>
|
||||
/// <param name="count">Count of areas in the binary.</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot"/> information from Pokémon Yellow (Generation 1) Fishing data.
|
||||
/// </summary>
|
||||
/// <param name="data">Input raw data.</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot"/> information from Generation 1 Fishing data.
|
||||
/// </summary>
|
||||
/// <param name="data">Input raw data.</param>
|
||||
/// <param name="count">Count of areas in the binary.</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
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>() : 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<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
|
@ -116,7 +49,7 @@ namespace PKHeX.Core
|
|||
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;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -10,274 +9,68 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed class EncounterArea2 : EncounterArea
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot2"/> information from Generation 2 Grass/Water data.
|
||||
/// </summary>
|
||||
/// <param name="data">Input raw data.</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
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<byte> Rates;
|
||||
|
||||
public static EncounterArea2[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
int ofs = 0;
|
||||
var areas = new List<EncounterArea2>();
|
||||
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];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot2"/> information from Generation 2 Grass/Water data.
|
||||
/// </summary>
|
||||
/// <param name="data">Input raw data.</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
public static EncounterArea2[] GetArray2Fishing(byte[] data)
|
||||
{
|
||||
int ofs = 0;
|
||||
var f = GetAreas2Fishing(data, ref ofs);
|
||||
|
||||
var areas = new List<EncounterArea2>();
|
||||
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<EncounterSlot2>();
|
||||
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<EncounterArea2> GetAreas2(byte[] data, ref int ofs, SlotType t, int slotSets, int slotCount)
|
||||
{
|
||||
var areas = new List<EncounterArea2>();
|
||||
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<EncounterArea2> GetAreas2Fishing(byte[] data, ref int ofs)
|
||||
{
|
||||
var areas = new List<EncounterArea2>();
|
||||
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<SlotTemplate>();
|
||||
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<EncounterArea2> GetAreas2Headbutt(byte[] data, ref int ofs)
|
||||
{
|
||||
// Read Location Table
|
||||
var head = new List<EncounterArea2>();
|
||||
var headID = new List<int>();
|
||||
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<EncounterArea2>();
|
||||
var rockID = new List<int>();
|
||||
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<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
if (!(pkm is PK2 pk2) || pk2.CaughtData == 0)
|
||||
|
@ -306,8 +99,7 @@ namespace PKHeX.Core
|
|||
if (!slot.IsLevelWithinRange(lvl))
|
||||
break;
|
||||
|
||||
var expect = ((EncounterSlot2)slot).Time;
|
||||
if (!expect.Contains(time))
|
||||
if (!Time.Contains(time))
|
||||
break;
|
||||
|
||||
yield return slot;
|
||||
|
@ -330,7 +122,7 @@ namespace PKHeX.Core
|
|||
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;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -10,119 +9,96 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed class EncounterArea3 : EncounterArea
|
||||
{
|
||||
private static IEnumerable<EncounterSlot> 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<EncounterSlot>();
|
||||
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<EncounterSlot> 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<EncounterSlot> GetSlots3Fishing(byte[] data, ref int ofs, int numslots)
|
||||
{
|
||||
var slots = new List<EncounterSlot>();
|
||||
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<EncounterSlot> 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<EncounterSlot>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot"/> information from Generation 3 data.
|
||||
/// </summary>
|
||||
/// <param name="entries">Raw data, one byte array per encounter area</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
public static EncounterArea3[] GetArray3(byte[][] entries)
|
||||
{
|
||||
return entries.Select(GetArea3).Where(Area => Area.Slots.Length != 0).ToArray();
|
||||
return slots;
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
|
@ -165,7 +141,7 @@ namespace PKHeX.Core
|
|||
|
||||
if (slot.Form != evo.Form)
|
||||
break;
|
||||
if (!slot.IsLevelWithinRange(evo.MinLevel, evo.Level))
|
||||
if (slot.LevelMin > evo.Level)
|
||||
break;
|
||||
|
||||
yield return slot;
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Base encounter class for manually repacked areas
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Encounter Data is stored in the following format: (u16 Location, n*[u16 Species/Form, u8 Min, u8 Max]), hence the 32bit name
|
||||
/// </remarks>
|
||||
public abstract class EncounterArea32 : EncounterArea
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an array of areas from an array of raw area data
|
||||
/// </summary>
|
||||
/// <param name="entries">Simplified raw format of an Area</param>
|
||||
/// <returns>Array of areas</returns>
|
||||
public static A[] GetArray<A, S>(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<S>(entries[i]);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private void LoadSlots<S>(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;
|
||||
}
|
||||
}
|
||||
}
|
73
PKHeX.Core/Legality/Areas/EncounterArea3XD.cs
Normal file
73
PKHeX.Core/Legality/Areas/EncounterArea3XD.cs
Normal file
|
@ -0,0 +1,73 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// <see cref="GameVersion.XD"/> encounter area
|
||||
/// </summary>
|
||||
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<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> 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<EncounterSlot>();
|
||||
return GetSlotsMatching(chain, pkm.Met_Level);
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsMatching(IReadOnlyList<EvoCriteria> 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<EncounterSlot> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -8,57 +7,54 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// <see cref="GameVersion.Gen4"/> encounter area
|
||||
/// </summary>
|
||||
public abstract class EncounterArea4 : EncounterArea
|
||||
public sealed class EncounterArea4 : EncounterArea
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads the GBA Pak Special slots, cloning <see cref="EncounterSlot"/> data from the area's base encounter slots.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These special slots only contain the info of species id; the level is copied from the corresponding <see cref="slotnums"/> index.
|
||||
/// </remarks>
|
||||
/// <param name="data">Encounter binary data</param>
|
||||
/// <param name="ofs">Offset to read from</param>
|
||||
/// <param name="slotSize">DP/Pt slotSize = 4 bytes/entry, HG/SS slotSize = 2 bytes/entry</param>
|
||||
/// <param name="ReplacedSlots">Slots from regular encounter table that end up replaced by in-game conditions</param>
|
||||
/// <param name="slotnums">Slot indexes to replace with read species IDs</param>
|
||||
/// <param name="t">Slot type of the special encounter</param>
|
||||
protected static List<EncounterSlot4> GetSlots4GrassSlotReplace(byte[] data, int ofs, int slotSize, EncounterSlot[] ReplacedSlots, int[] slotnums, SlotType t = SlotType.Grass)
|
||||
{
|
||||
var slots = new List<EncounterSlot4>();
|
||||
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<EncounterSlot4> MarkStaticMagnetExtras(IEnumerable<IEnumerable<List<EncounterSlot4>>> product)
|
||||
{
|
||||
var trackPermute = new List<EncounterSlot4>();
|
||||
foreach (var p in product)
|
||||
MarkStaticMagnetPermute(p.SelectMany(z => z), trackPermute);
|
||||
return trackPermute;
|
||||
}
|
||||
|
||||
protected static void MarkStaticMagnetPermute(IEnumerable<EncounterSlot4> grp, List<EncounterSlot4> trackPermute)
|
||||
{
|
||||
EncounterUtil.MarkEncountersStaticMagnetPullPermutation(grp, PersonalTable.HGSS, trackPermute);
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
if (pkm.Format != 4) // Met Location and Met Level are changed on PK4->PK5
|
||||
|
@ -77,7 +73,7 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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;
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// <see cref="GameVersion.DPPt"/> encounter area
|
||||
/// </summary>
|
||||
public sealed class EncounterArea4DPPt : EncounterArea4
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot"/> information from Generation 4 Diamond, Pearl and Platinum data.
|
||||
/// </summary>
|
||||
/// <param name="entries">Raw data, one byte array per encounter area</param>
|
||||
/// <param name="pt">Platinum flag (for Trophy Garden slot insertion)</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
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<EncounterSlot4> GetSlots4WaterFishingDPPt(byte[] data, int ofs, int numslots, SlotType t)
|
||||
{
|
||||
var slots = new List<EncounterSlot4>();
|
||||
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<EncounterSlot>();
|
||||
|
||||
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<List<EncounterSlot4>> { GrassSlots.Where(z => z.SlotNumber == 6 || z.SlotNumber == 7).ToList() }; // every other slot is in the product
|
||||
var pair0 = new List<List<EncounterSlot4>> { GrassSlots.Where(z => Legal.Slot4_Swarm.Contains(z.SlotNumber)).ToList() };
|
||||
var pair1 = new List<List<EncounterSlot4>> { GrassSlots.Where(z => Legal.Slot4_Time.Contains(z.SlotNumber)).ToList() };
|
||||
var pair2 = new List<List<EncounterSlot4>> { GrassSlots.Where(z => Legal.Slot4_Radar.Contains(z.SlotNumber)).ToList() };
|
||||
var pair3 = new List<List<EncounterSlot4>> { 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<EncounterSlot4>();
|
||||
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<EncounterSlot4> { 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<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
|
||||
{
|
||||
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
|
||||
return sequences.Aggregate(
|
||||
emptyProduct,
|
||||
(accumulator, sequence) =>
|
||||
from accseq in accumulator
|
||||
from item in sequence
|
||||
select accseq.Concat(new[] { item }));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,206 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// <see cref="GameVersion.HGSS"/> encounter area
|
||||
/// </summary>
|
||||
public sealed class EncounterArea4HGSS : EncounterArea4
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot"/> information from Generation 4 Heart Gold and Soul Silver data.
|
||||
/// </summary>
|
||||
/// <param name="entries">Raw data, one byte array per encounter area</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
public static EncounterArea4HGSS[] GetArray4HGSS(byte[][] entries)
|
||||
{
|
||||
return entries.Select(GetArea4HGSS).Where(Area => Area.Slots.Length != 0).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encounter areas with <see cref="EncounterSlot"/> information from Generation 4 Heart Gold and Soul Silver Headbutt tree data.
|
||||
/// </summary>
|
||||
/// <param name="entries">Raw data, one byte array per encounter area</param>
|
||||
/// <returns>Array of encounter areas.</returns>
|
||||
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<EncounterSlot4> GetSlots4WaterFishingHGSS(byte[] data, int ofs, int numslots, SlotType t)
|
||||
{
|
||||
var slots = new List<EncounterSlot4>();
|
||||
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<EncounterSlot4>();
|
||||
|
||||
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<List<EncounterSlot4>> { 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<EncounterSlot4>();
|
||||
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<EncounterSlot>();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,68 @@
|
|||
namespace PKHeX.Core
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// <see cref="GameVersion.Gen5"/> encounter area
|
||||
/// </summary>
|
||||
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<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -6,8 +7,43 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// <see cref="GameVersion.ORAS"/> encounter area
|
||||
/// </summary>
|
||||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -6,8 +7,55 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// <see cref="GameVersion.XY"/> encounter area
|
||||
/// </summary>
|
||||
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<int> 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;
|
||||
|
||||
|
|
|
@ -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<int, EncounterSlot6XY> 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<EncounterSlot6XY>().ToLookup(s => s.Species);
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterSlot> GetValidSafariEncounters(PKM pkm)
|
||||
{
|
||||
var chain = EvolutionChain.GetValidPreEvolutions(pkm);
|
||||
return GetValidSafariEncounters(chain);
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterSlot> GetValidSafariEncounters(IReadOnlyList<DexLevel> chain)
|
||||
{
|
||||
var valid = chain.Where(d => d.Level >= 30);
|
||||
return valid.SelectMany(z => Encounters6.FriendSafari[z.Species]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -6,8 +7,43 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// <see cref="GameVersion.Gen7"/> encounter area
|
||||
/// </summary>
|
||||
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<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -6,8 +7,40 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// <see cref="GameVersion.GG"/> encounter area
|
||||
/// </summary>
|
||||
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<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -6,8 +7,56 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// <see cref="GameVersion.GO"/> encounter area for <see cref="GameVersion.GG"/>
|
||||
/// </summary>
|
||||
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<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
|
|
|
@ -198,19 +198,20 @@ namespace PKHeX.Core
|
|||
/// Gets an array of areas from an array of raw area data
|
||||
/// </summary>
|
||||
/// <param name="entries">Simplified raw format of an Area</param>
|
||||
/// <param name="game">Game of origin</param>
|
||||
/// <returns>Array of areas</returns>
|
||||
public static T[] GetArray<T>(byte[][] entries) where T : EncounterAreaSH, new()
|
||||
public static T[] GetArray<T>(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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
LevelMax = max;
|
||||
|
||||
Weather = weather;
|
||||
Version = game;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Fake encounter area used to mock data
|
||||
/// </summary>
|
||||
public sealed class EncounterAreaFake : EncounterArea
|
||||
{
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain) =>
|
||||
Array.Empty<EncounterSlot>();
|
||||
}
|
||||
}
|
|
@ -19,152 +19,6 @@ namespace PKHeX.Core
|
|||
return source.Where(s => s.Version.Contains(game)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Direct fetch for <see cref="EncounterArea"/> data; can also be used to fetch supplementary encounter streams.
|
||||
/// </summary>
|
||||
/// <param name="ident">Unpacking identification ASCII characters (first two bytes of binary)</param>
|
||||
/// <param name="resource">Resource name (will be prefixed with "encounter_"</param>
|
||||
/// <returns>Array of encounter areas</returns>
|
||||
internal static A[] GetEncounterTables<A, S>(string ident, string resource)
|
||||
where A : EncounterArea32, new()
|
||||
where S : EncounterSlot, new()
|
||||
{
|
||||
byte[] mini = Util.GetBinaryResource($"encounter_{resource}.pkl");
|
||||
return EncounterArea32.GetArray<A, S>(BinLinker.Unpack(mini, ident));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Direct fetch for <see cref="EncounterArea"/> data; can also be used to fetch supplementary encounter streams.
|
||||
/// </summary>
|
||||
/// <param name="ident">Unpacking identification ASCII characters (first two bytes of binary)</param>
|
||||
/// <param name="resource">Resource name (will be prefixed with "encounter_")</param>
|
||||
/// <returns>Array of encounter areas</returns>
|
||||
internal static T[] GetEncounterTables8<T>(string ident, string resource) where T : EncounterAreaSH, new()
|
||||
{
|
||||
byte[] mini = Util.GetBinaryResource($"encounter_{resource}.pkl");
|
||||
return EncounterAreaSH.GetArray<T>(BinLinker.Unpack(mini, ident));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines <see cref="EncounterArea"/> slot arrays with the same <see cref="EncounterArea.Location"/>.
|
||||
/// </summary>
|
||||
/// <param name="tables">Input encounter areas to combine</param>
|
||||
/// <returns>Combined Array of encounter areas. No duplicate location IDs will be present.</returns>
|
||||
internal static T[] AddExtraTableSlots<T>(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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks Encounter Slots for party lead's ability slot influencing.
|
||||
/// </summary>
|
||||
/// <remarks>Magnet Pull attracts Steel type slots, and Static attracts Electric</remarks>
|
||||
/// <param name="areas">Encounter Area array for game</param>
|
||||
/// <param name="t">Personal data for use with a given species' type</param>
|
||||
internal static void MarkEncountersStaticMagnetPull<T>(IEnumerable<EncounterArea> areas, PersonalTable t)
|
||||
where T : EncounterSlot, IMagnetStatic
|
||||
{
|
||||
foreach (EncounterArea area in areas)
|
||||
{
|
||||
foreach (var grp in area.Slots.Cast<T>().GroupBy(z => z.Type))
|
||||
MarkEncountersStaticMagnetPull(grp, t);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void MarkEncountersStaticMagnetPull<T>(IEnumerable<T> grp, PersonalTable t)
|
||||
where T : EncounterSlot, IMagnetStatic
|
||||
{
|
||||
GetStaticMagnet(t, grp, out List<T> s, out List<T> 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<T>(IEnumerable<T> grp, PersonalTable t, List<T> permuted)
|
||||
where T : EncounterSlot, IMagnetStatic, INumberedSlot
|
||||
{
|
||||
GetStaticMagnet(t, grp, out List<T> s, out List<T> 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<T>(PersonalTable t, IEnumerable<T> grp, out List<T> s, out List<T> 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<T>();
|
||||
m = new List<T>();
|
||||
foreach (T Slot in grp)
|
||||
{
|
||||
var p = t[Slot.Species];
|
||||
if (p.IsType(steel))
|
||||
m.Add(Slot);
|
||||
if (p.IsType(electric))
|
||||
s.Add(Slot);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="EncounterSlot1.Version"/> value, for use in determining split-generation origins.
|
||||
/// </summary>
|
||||
/// <remarks>Only used for Gen 1 & 2, as <see cref="PKM.Version"/> data is not present.</remarks>
|
||||
/// <param name="areas">In-game encounter data</param>
|
||||
/// <param name="game">Version ID to set</param>
|
||||
internal static void MarkEncountersVersion(IEnumerable<EncounterArea> areas, GameVersion game)
|
||||
{
|
||||
foreach (EncounterArea area in areas)
|
||||
{
|
||||
foreach (var Slot in area.Slots)
|
||||
Slot.Version = game;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="IGenerationSet.Generation"/> value.
|
||||
/// </summary>
|
||||
|
@ -182,37 +36,8 @@ namespace PKHeX.Core
|
|||
enc.Generation = generation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Groups areas by location id, raw data has areas with different slots but the same location id.
|
||||
/// </summary>
|
||||
/// <remarks>Similar to <see cref="AddExtraTableSlots{T}"/>, this method combines a single array.</remarks>
|
||||
/// <param name="Areas">Ingame encounter data</param>
|
||||
internal static void ReduceAreasSize<T>(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<T>(params IEnumerable<T>[] arr) => arr.SelectMany(z => z).ToArray();
|
||||
|
||||
internal static void MarkEncounterAreaArray<T>(params T[][] areas) where T : EncounterArea
|
||||
{
|
||||
foreach (var area in areas)
|
||||
MarkEncounterAreas(area);
|
||||
}
|
||||
|
||||
private static void MarkEncounterAreas<T>(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 @@ namespace PKHeX.Core
|
|||
}
|
||||
string[] getNames(int i, IEnumerable<string[]> names) => names.Select(z => z.Length > i ? z[i] : string.Empty).ToArray();
|
||||
}
|
||||
|
||||
internal static void MarkEncounterGame<T>(IEnumerable<T> table, GameVersion version) where T: IVersion, IVersionSet
|
||||
{
|
||||
foreach (var t in table.Where(z => ((IVersion)z).Version == GameVersion.Any))
|
||||
((IVersionSet)t).Version = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|||
/// </summary>
|
||||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,124 +9,28 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
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<EncounterArea2>();
|
||||
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 @@ namespace PKHeX.Core
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|||
/// </summary>
|
||||
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<EncounterSlot3>(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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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<int> 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 @@ namespace PKHeX.Core
|
|||
|
||||
#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 @@ namespace PKHeX.Core
|
|||
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<EncounterStatic3> 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);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,41 +9,14 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
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<EncounterArea5, EncounterSlot5>("51", "b");
|
||||
var WSlots = GetEncounterTables<EncounterArea5, EncounterSlot5>("51", "w");
|
||||
var B2Slots = GetEncounterTables<EncounterArea5, EncounterSlot5>("52", "b2");
|
||||
var W2Slots = GetEncounterTables<EncounterArea5, EncounterSlot5>("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 @@ namespace PKHeX.Core
|
|||
|
||||
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<EncounterStatic5>();
|
||||
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<EncounterStatic5>();
|
||||
foreach (EncounterStatic5 s in t)
|
||||
{
|
||||
if (s.Moves.Count <= 1) // no special moves
|
||||
{
|
||||
list.Add(s);
|
||||
|
@ -113,40 +57,7 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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<EncounterArea5, EncounterSlot5>(WhiteForest_GrassSpecies, new[] { 5, 5 }, 51, SlotType.Grass).Concat(
|
||||
EncounterArea.GetSimpleEncounterArea<EncounterArea5, EncounterSlot5>(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,151 +9,32 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
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<int, EncounterSlot6XY> 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<EncounterArea6XY, EncounterSlot6XY>("xy", "x");
|
||||
var YSlots = GetEncounterTables<EncounterArea6XY, EncounterSlot6XY>("xy", "y");
|
||||
MarkG6XYSlots(ref XSlots);
|
||||
MarkG6XYSlots(ref YSlots);
|
||||
MarkEncounterAreaArray(SlotsXYAlt);
|
||||
SlotsX = AddExtraTableSlots(XSlots, SlotsXYAlt);
|
||||
SlotsY = AddExtraTableSlots(YSlots, SlotsXYAlt);
|
||||
|
||||
SlotsA = GetEncounterTables<EncounterArea6AO, EncounterSlot6AO>("ao", "a");
|
||||
SlotsO = GetEncounterTables<EncounterArea6AO, EncounterSlot6AO>("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 @@ namespace PKHeX.Core
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|||
/// </summary>
|
||||
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<EncounterArea7, EncounterSlot7>("sm", "sn");
|
||||
var REG_MN = GetEncounterTables<EncounterArea7, EncounterSlot7>("sm", "mn");
|
||||
var SOS_SN = GetEncounterTables<EncounterArea7, EncounterSlot7>("sm", "sn_sos");
|
||||
var SOS_MN = GetEncounterTables<EncounterArea7, EncounterSlot7>("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<EncounterArea7, EncounterSlot7>("uu", "us");
|
||||
var REG_UM = GetEncounterTables<EncounterArea7, EncounterSlot7>("uu", "um");
|
||||
var SOS_US = GetEncounterTables<EncounterArea7, EncounterSlot7>("uu", "us_sos");
|
||||
var SOS_UM = GetEncounterTables<EncounterArea7, EncounterSlot7> ("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 @@ namespace PKHeX.Core
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,20 +7,15 @@ namespace PKHeX.Core
|
|||
{
|
||||
internal static class Encounters7b
|
||||
{
|
||||
internal static readonly EncounterArea7b[] SlotsGP = GetEncounterTables<EncounterArea7b, EncounterSlot7b>("gg", "gp");
|
||||
internal static readonly EncounterArea7b[] SlotsGE = GetEncounterTables<EncounterArea7b, EncounterSlot7b>("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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
new RareSpawn(149, Sky),
|
||||
};
|
||||
|
||||
private static void ManuallyAddRareSpawns(IEnumerable<EncounterArea> areas)
|
||||
private static void ManuallyAddRareSpawns(IEnumerable<EncounterArea7b> areas)
|
||||
{
|
||||
foreach (var table in areas)
|
||||
{
|
||||
|
@ -188,13 +127,7 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
table.Slots = slots;
|
||||
}
|
||||
}
|
||||
|
||||
internal static readonly EncounterStatic[] StaticGP = GetEncounters(Encounter_GG, GameVersion.GP);
|
||||
internal static readonly EncounterStatic[] StaticGE = GetEncounters(Encounter_GG, GameVersion.GE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,19 +15,17 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
internal static class Encounters8
|
||||
{
|
||||
internal static readonly EncounterArea8[] SlotsSW_Symbol = GetEncounterTables8<EncounterArea8>("sw", "sw_symbol");
|
||||
internal static readonly EncounterArea8[] SlotsSH_Symbol = GetEncounterTables8<EncounterArea8>("sh", "sh_symbol");
|
||||
internal static readonly EncounterArea8[] SlotsSW_Hidden = GetEncounterTables8<EncounterArea8>("sw", "sw_hidden");
|
||||
internal static readonly EncounterArea8[] SlotsSH_Hidden = GetEncounterTables8<EncounterArea8>("sh", "sh_hidden");
|
||||
internal static readonly EncounterArea8[] SlotsSW, SlotsSH;
|
||||
internal static readonly EncounterStatic[] StaticSW, StaticSH;
|
||||
private static readonly EncounterArea8[] SlotsSW_Symbol = EncounterAreaSH.GetArray<EncounterArea8>(Get("sw_symbol", "sw"), SW);
|
||||
private static readonly EncounterArea8[] SlotsSH_Symbol = EncounterAreaSH.GetArray<EncounterArea8>(Get("sh_symbol", "sh"), SH);
|
||||
private static readonly EncounterArea8[] SlotsSW_Hidden = EncounterAreaSH.GetArray<EncounterArea8>(Get("sw_hidden", "sw"), SW);
|
||||
private static readonly EncounterArea8[] SlotsSH_Hidden = EncounterAreaSH.GetArray<EncounterArea8>(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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
};
|
||||
|
||||
internal static readonly EncounterTrade[] TradeGift_SWSH = TradeGift_Regular.Concat(TradeGift_R1).ToArray();
|
||||
|
||||
internal static readonly EncounterStatic[] StaticSW = ArrayUtil.ConcatAll(Nest_Common, Nest_SW, Nest_SH, Dist_Common, Dist_SW, Dist_SH, GetEncounters(Crystal_SWSH, SW), GetEncounters(Encounter_SWSH, SW));
|
||||
internal static readonly EncounterStatic[] StaticSH = ArrayUtil.ConcatAll(Nest_Common, Nest_SW, Nest_SH, Dist_Common, Dist_SW, Dist_SH, GetEncounters(Crystal_SWSH, SH), GetEncounters(Encounter_SWSH, SH));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@ namespace PKHeX.Core
|
|||
public int EggLocation { get => 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 @@ namespace PKHeX.Core
|
|||
{
|
||||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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);
|
||||
|
|
|
@ -8,39 +8,13 @@
|
|||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes Gen1 Encounter Slots from data.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing complete slot data table.</param>
|
||||
/// <param name="ofs">Offset to start reading from.</param>
|
||||
/// <param name="count">Amount of slots to read.</param>
|
||||
/// <param name="type">Type of encounter slot table.</param>
|
||||
/// <param name="rate">Slot type encounter rate.</param>
|
||||
/// <returns>Array of encounter slots.</returns>
|
||||
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)
|
||||
|
|
|
@ -11,40 +11,13 @@
|
|||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes Gen2 Encounter Slots from data.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing complete slot data table.</param>
|
||||
/// <param name="ofs">Offset to start reading from.</param>
|
||||
/// <param name="count">Amount of slots to read.</param>
|
||||
/// <param name="type">Type of encounter slot table.</param>
|
||||
/// <param name="rate">Slot type encounter rate.</param>
|
||||
/// <returns>Array of encounter slots.</returns>
|
||||
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 @@
|
|||
|
||||
var pk2 = (PK2)pk;
|
||||
if (Version == GameVersion.C)
|
||||
pk2.Met_TimeOfDay = Time.RandomValidTime();
|
||||
pk2.Met_TimeOfDay = ((EncounterArea2)Area!).Time.RandomValidTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,27 @@ namespace PKHeX.Core
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,13 @@ namespace PKHeX.Core
|
|||
|
||||
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.
|
||||
|
|
|
@ -7,7 +7,8 @@ namespace PKHeX.Core
|
|||
public override int Generation => 3;
|
||||
public IReadOnlyList<int> Moves { get; }
|
||||
|
||||
public EncounterSlot3Swarm(IReadOnlyList<int> moves) => Moves = moves;
|
||||
public EncounterSlot3Swarm(EncounterArea3 area, int species, int min, int max, int slot, GameVersion game,
|
||||
IReadOnlyList<int> 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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,18 +4,26 @@ namespace PKHeX.Core
|
|||
{
|
||||
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)
|
||||
|
|
|
@ -5,6 +5,15 @@ namespace PKHeX.Core
|
|||
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;
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
namespace PKHeX.Core
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public class EncounterStatic3 : EncounterStatic
|
||||
{
|
||||
|
@ -26,11 +29,39 @@
|
|||
{
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -24,5 +25,30 @@ namespace PKHeX.Core
|
|||
|
||||
public EncounterStaticShadow(TeamLock[] locks) => Locks = locks;
|
||||
public EncounterStaticShadow() => Locks = Array.Empty<TeamLock>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -306,16 +306,10 @@ namespace PKHeX.Core
|
|||
{ 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; }
|
||||
}
|
||||
|
|
|
@ -310,14 +310,11 @@ namespace PKHeX.Core
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace PKHeX.Core
|
|||
|
||||
private static IEnumerable<EncounterSlot> GetRawEncounterSlots(PKM pkm, IReadOnlyList<EvoCriteria> 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 @@ namespace PKHeX.Core
|
|||
|
||||
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<EncounterSlot> GetValidEncounterSlots(PKM pkm, EncounterArea loc, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
|
@ -125,20 +122,13 @@ namespace PKHeX.Core
|
|||
|
||||
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<EncounterArea> GetEncounterTable(PKM pkm, GameVersion gameSource = GameVersion.Any)
|
||||
|
|
|
@ -138,21 +138,11 @@ namespace PKHeX.Core
|
|||
{
|
||||
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);
|
||||
|
|
|
@ -63,11 +63,9 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,15 +56,6 @@ namespace PKHeX.Core
|
|||
// 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 @@ namespace PKHeX.Core
|
|||
|
||||
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 @@ namespace PKHeX.Core
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
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)
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core
|
|||
/// <remarks>
|
||||
/// Different from <see cref="EncounterType"/>, this corresponds to the method that the <see cref="IEncounterable"/> may be encountered.</remarks>
|
||||
[Flags]
|
||||
public enum SlotType
|
||||
public enum SlotType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Default (un-assigned) encounter slot type.
|
||||
|
@ -18,125 +18,77 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Slot is encountered via Grass.
|
||||
/// </summary>
|
||||
Grass = 1 << 00,
|
||||
Grass = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Surfing.
|
||||
/// </summary>
|
||||
Surf = 1 << 01,
|
||||
Surf = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Old Rod (Fishing).
|
||||
/// </summary>
|
||||
Old_Rod = 1 << 02,
|
||||
Old_Rod = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Good Rod (Fishing).
|
||||
/// </summary>
|
||||
Good_Rod = 1 << 03,
|
||||
Good_Rod = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Super Rod (Fishing).
|
||||
/// </summary>
|
||||
Super_Rod = 1 << 04,
|
||||
Super_Rod = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Rock Smash.
|
||||
/// </summary>
|
||||
Rock_Smash = 1 << 05,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via a Horde.
|
||||
/// </summary>
|
||||
Horde = 1 << 06,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via the Friend Safari.
|
||||
/// </summary>
|
||||
FriendSafari = 1 << 07,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered through special means. Used to signify special slots for Gen2, sometimes for later follow-up).
|
||||
/// </summary>
|
||||
Special = 1 << 08,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via SOS signal.
|
||||
/// </summary>
|
||||
SOS = 1 << 09,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered in a Swarm.
|
||||
/// </summary>
|
||||
Swarm = 1 << 10,
|
||||
Rock_Smash = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Headbutt.
|
||||
/// </summary>
|
||||
Headbutt = 1 << 11,
|
||||
|
||||
Headbutt_Special = Headbutt | Special,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via the Poké Radar.
|
||||
/// </summary>
|
||||
Pokeradar = 1 << 12,
|
||||
Headbutt = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via a Honey Tree.
|
||||
/// </summary>
|
||||
HoneyTree = 1 << 13,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via a Hidden Grotto.
|
||||
/// </summary>
|
||||
HiddenGrotto = 1 << 14,
|
||||
HoneyTree = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via the Bug Catching Contest.
|
||||
/// </summary>
|
||||
BugContest = 1 << 15,
|
||||
BugContest = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via the Go Park.
|
||||
/// </summary>
|
||||
GoPark = 1 << 16,
|
||||
HiddenGrotto = 10,
|
||||
GoPark = 11,
|
||||
FriendSafari = 12,
|
||||
Horde = 13,
|
||||
// Pokeradar = 14,
|
||||
SOS = 15,
|
||||
// always used as a modifier to another slot type
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered in the Safari Zone.
|
||||
/// </summary>
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,15 +32,10 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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;
|
||||
|
|
|
@ -401,16 +401,7 @@ namespace PKHeX.Core
|
|||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@
|
|||
/// <summary> Generation 4 -> Generation 5 Transfer Location (Crown Beast - Event activated in Gen 5) </summary>
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,11 +37,12 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
|
||||
private CheckResult VerifyAbility(LegalityAnalysis data, IReadOnlyList<int> 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 @@ namespace PKHeX.Core
|
|||
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<int> abilities, int abilnum)
|
||||
private CheckResult VerifyAbility345(LegalityAnalysis data, IEncounterable enc, IReadOnlyList<int> abilities, int abilnum)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
var state = AbilityState.MustMatch;
|
||||
|
@ -98,7 +99,7 @@ namespace PKHeX.Core
|
|||
|
||||
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 @@ namespace PKHeX.Core
|
|||
return AbilityState.CanMismatch;
|
||||
}
|
||||
|
||||
private CheckResult VerifyAbilityMG(LegalityAnalysis data, IReadOnlyList<int> abilities, int cardtype)
|
||||
private CheckResult VerifyAbilityMG(LegalityAnalysis data, MysteryGift g, IReadOnlyList<int> 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 @@ namespace PKHeX.Core
|
|||
return pkm.Ability == pcd.Gift.PK.Ability ? VALID : INVALID;
|
||||
}
|
||||
|
||||
private CheckResult VerifyAbility5(LegalityAnalysis data, IReadOnlyList<int> abilities)
|
||||
private CheckResult VerifyAbility5(LegalityAnalysis data, IEncounterable enc, IReadOnlyList<int> 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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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 @@ namespace PKHeX.Core
|
|||
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);
|
||||
|
|
|
@ -74,20 +74,30 @@ namespace PKHeX.Core
|
|||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace PKHeX.Core
|
|||
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));
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace PKHeX.Core
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace PKHeX.Core
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,9 +57,9 @@ namespace PKHeX.Core
|
|||
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;
|
||||
|
||||
|
|
|
@ -31,47 +31,36 @@
|
|||
<None Remove="Resources\byte\encounter_b2.pkl" />
|
||||
<None Remove="Resources\byte\encounter_blue.pkl" />
|
||||
<None Remove="Resources\byte\encounter_crystal.pkl" />
|
||||
<None Remove="Resources\byte\encounter_crystal_h.pkl" />
|
||||
<None Remove="Resources\byte\encounter_d.pkl" />
|
||||
<None Remove="Resources\byte\encounter_e.pkl" />
|
||||
<None Remove="Resources\byte\encounter_fr.pkl" />
|
||||
<None Remove="Resources\byte\encounter_ge.pkl" />
|
||||
<None Remove="Resources\byte\encounter_gold.pkl" />
|
||||
<None Remove="Resources\byte\encounter_gold_h.pkl" />
|
||||
<None Remove="Resources\byte\encounter_gp.pkl" />
|
||||
<None Remove="Resources\byte\encounter_gsc_f.pkl" />
|
||||
<None Remove="Resources\byte\encounter_hg.pkl" />
|
||||
<None Remove="Resources\byte\encounter_lg.pkl" />
|
||||
<None Remove="Resources\byte\encounter_mn.pkl" />
|
||||
<None Remove="Resources\byte\encounter_mn_sos.pkl" />
|
||||
<None Remove="Resources\byte\encounter_o.pkl" />
|
||||
<None Remove="Resources\byte\encounter_p.pkl" />
|
||||
<None Remove="Resources\byte\encounter_pt.pkl" />
|
||||
<None Remove="Resources\byte\encounter_r.pkl" />
|
||||
<None Remove="Resources\byte\encounter_rb_f.pkl" />
|
||||
<None Remove="Resources\byte\encounter_red.pkl" />
|
||||
<None Remove="Resources\byte\encounter_rse_swarm.pkl" />
|
||||
<None Remove="Resources\byte\encounter_s.pkl" />
|
||||
<None Remove="Resources\byte\encounter_sh_hidden.pkl" />
|
||||
<None Remove="Resources\byte\encounter_sh_symbol.pkl" />
|
||||
<None Remove="Resources\byte\encounter_silver.pkl" />
|
||||
<None Remove="Resources\byte\encounter_silver_h.pkl" />
|
||||
<None Remove="Resources\byte\encounter_sn.pkl" />
|
||||
<None Remove="Resources\byte\encounter_sn_sos.pkl" />
|
||||
<None Remove="Resources\byte\encounter_ss.pkl" />
|
||||
<None Remove="Resources\byte\encounter_sw_hidden.pkl" />
|
||||
<None Remove="Resources\byte\encounter_sw_symbol.pkl" />
|
||||
<None Remove="Resources\byte\encounter_us.pkl" />
|
||||
<None Remove="Resources\byte\encounter_us_sos.pkl" />
|
||||
<None Remove="Resources\byte\encounter_um.pkl" />
|
||||
<None Remove="Resources\byte\encounter_um_sos.pkl" />
|
||||
<None Remove="Resources\byte\encounter_w.pkl" />
|
||||
<None Remove="Resources\byte\encounter_w2.pkl" />
|
||||
<None Remove="Resources\byte\encounter_x.pkl" />
|
||||
<None Remove="Resources\byte\encounter_y.pkl" />
|
||||
<None Remove="Resources\byte\encounter_yellow.pkl" />
|
||||
<None Remove="Resources\byte\encounter_yellow_f.pkl" />
|
||||
<None Remove="Resources\byte\encounter_hb_hg.pkl" />
|
||||
<None Remove="Resources\byte\encounter_hb_ss.pkl" />
|
||||
<None Remove="Resources\byte\evos_ao.pkl" />
|
||||
<None Remove="Resources\byte\evos_g3.pkl" />
|
||||
<None Remove="Resources\byte\evos_g4.pkl" />
|
||||
|
@ -856,47 +845,36 @@
|
|||
<EmbeddedResource Include="Resources\byte\encounter_b2.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_blue.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_crystal.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_crystal_h.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_d.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_e.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_fr.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_ge.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_gold.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_gold_h.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_gsc_f.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_gp.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_hg.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_lg.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_mn.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_mn_sos.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_o.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_p.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_pt.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_r.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_rb_f.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_red.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_rse_swarm.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_s.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_sh_hidden.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_sh_symbol.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_silver.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_silver_h.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_sn.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_sn_sos.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_ss.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_sw_hidden.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_sw_symbol.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_us.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_us_sos.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_um.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_um_sos.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_w.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_w2.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_x.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_y.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_yellow.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_yellow_f.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_hb_hg.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\encounter_hb_ss.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\evos_ao.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\evos_g3.pkl" />
|
||||
<EmbeddedResource Include="Resources\byte\evos_g4.pkl" />
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
PKHeX.Core/Resources/byte/encounter_rse_swarm.pkl
Normal file
BIN
PKHeX.Core/Resources/byte/encounter_rse_swarm.pkl
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue