mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-26 22:10:21 +00:00
Revise EncounterArea and EncounterType for clarity (#3228)
EncounterArea now stores a more specific type'd array for encounter slots. Better iteration and less casting, as the nonspecific `Slots` fetch is rarely referenced. EncounterType renamed to GroundTile to reflect how it actually works in Gen4. Was previously an ambiguous field that was clarified a little; we can describe it a little better now. Keep the GUI the same to not scare the end users. Change Trash Byte properties to get/set a Span. Trash Byte legality checking easier on the garbage collector?
This commit is contained in:
parent
9cd617708d
commit
103aa9aa4b
63 changed files with 534 additions and 329 deletions
|
@ -104,7 +104,6 @@ namespace PKHeX.Core
|
|||
public int Met_Year => pkm.MetDate.GetValueOrDefault().Year;
|
||||
public int Met_Month => pkm.MetDate.GetValueOrDefault().Month;
|
||||
public int Met_Day => pkm.MetDate.GetValueOrDefault().Day;
|
||||
public int Encounter => pkm.EncounterType;
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ namespace PKHeX.Core
|
|||
public GameVersion Version { get; }
|
||||
public int Location { get; protected init; }
|
||||
public SlotType Type { get; protected init; } = SlotType.Any;
|
||||
public EncounterSlot[] Slots { get; protected init; } = Array.Empty<EncounterSlot>();
|
||||
protected abstract IReadOnlyList<EncounterSlot> Raw { get; }
|
||||
|
||||
protected EncounterArea(GameVersion game) => Version = game;
|
||||
|
||||
|
@ -29,5 +29,8 @@ namespace PKHeX.Core
|
|||
/// <param name="location">Met Location ID</param>
|
||||
/// <returns>True if possibly originated from this area, false otherwise.</returns>
|
||||
public virtual bool IsMatchLocation(int location) => Location == location;
|
||||
|
||||
public bool HasSpecies(int species) => Raw.Any(z => z.Species == species);
|
||||
public IEnumerable<EncounterSlot> GetSpecies(IReadOnlyList<DexLevel> chain) => Raw.Where(z => chain.Any(c => z.Species == c.Species));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ namespace PKHeX.Core
|
|||
public sealed record EncounterArea1 : EncounterArea
|
||||
{
|
||||
public readonly int Rate;
|
||||
public readonly EncounterSlot1[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea1[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,9 @@ namespace PKHeX.Core
|
|||
internal readonly EncounterTime Time;
|
||||
public readonly int Rate;
|
||||
public readonly IReadOnlyList<byte> Rates;
|
||||
public readonly EncounterSlot2[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea2[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
|
@ -86,7 +89,7 @@ namespace PKHeX.Core
|
|||
return GetSlotsSpecificLevelTime(chain, pk2.Met_TimeOfDay, pk2.Met_Level);
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsSpecificLevelTime(IReadOnlyList<EvoCriteria> chain, int time, int lvl)
|
||||
private IEnumerable<EncounterSlot2> GetSlotsSpecificLevelTime(IReadOnlyList<EvoCriteria> chain, int time, int lvl)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
|
@ -113,7 +116,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
||||
private IEnumerable<EncounterSlot2> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
|
|
|
@ -10,6 +10,9 @@ namespace PKHeX.Core
|
|||
public sealed record EncounterArea3 : EncounterArea
|
||||
{
|
||||
public readonly int Rate;
|
||||
public readonly EncounterSlot3[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea3[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
|
@ -108,7 +111,7 @@ namespace PKHeX.Core
|
|||
return GetSlotsMatching(chain, pkm.Met_Level);
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsMatching(IReadOnlyList<EvoCriteria> chain, int lvl)
|
||||
private IEnumerable<EncounterSlot3> GetSlotsMatching(IReadOnlyList<EvoCriteria> chain, int lvl)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
|
@ -128,7 +131,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
||||
private IEnumerable<EncounterSlot3> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,10 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed record EncounterArea3XD : EncounterArea
|
||||
{
|
||||
public readonly EncounterSlot3PokeSpot[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public EncounterArea3XD(int loc, int s0, int l0, int s1, int l1, int s2, int l2) : base(GameVersion.XD)
|
||||
{
|
||||
Location = loc;
|
||||
|
@ -26,11 +30,11 @@ namespace PKHeX.Core
|
|||
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 Array.Empty<EncounterSlot3PokeSpot>();
|
||||
return GetSlotsMatching(chain, pkm.Met_Level);
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsMatching(IReadOnlyList<EvoCriteria> chain, int lvl)
|
||||
private IEnumerable<EncounterSlot3PokeSpot> GetSlotsMatching(IReadOnlyList<EvoCriteria> chain, int lvl)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
|
@ -50,7 +54,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
||||
private IEnumerable<EncounterSlot3PokeSpot> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
|
|
|
@ -9,8 +9,11 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed record EncounterArea4 : EncounterArea
|
||||
{
|
||||
public readonly EncounterType TypeEncounter;
|
||||
public readonly int Rate;
|
||||
public readonly GroundTilePermission GroundTile;
|
||||
public readonly EncounterSlot4[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea4[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
|
@ -25,7 +28,8 @@ namespace PKHeX.Core
|
|||
Location = data[0] | (data[1] << 8);
|
||||
Type = (SlotType)data[2];
|
||||
Rate = data[3];
|
||||
TypeEncounter = (EncounterType) BitConverter.ToUInt16(data, 4);
|
||||
// although GroundTilePermission flags are 32bit, none have values > 16bit.
|
||||
GroundTile = (GroundTilePermission) BitConverter.ToUInt16(data, 4);
|
||||
|
||||
Slots = ReadRegularSlots(data);
|
||||
}
|
||||
|
@ -60,11 +64,11 @@ namespace PKHeX.Core
|
|||
if (pkm.Format != 4) // Met Location and Met Level are changed on PK4->PK5
|
||||
return GetSlotsFuzzy(chain);
|
||||
if (pkm.Met_Location != Location)
|
||||
return Array.Empty<EncounterSlot>();
|
||||
return Array.Empty<EncounterSlot4>();
|
||||
return GetSlotsMatching(chain, pkm.Met_Level);
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsMatching(IReadOnlyList<EvoCriteria> chain, int lvl)
|
||||
private IEnumerable<EncounterSlot4> GetSlotsMatching(IReadOnlyList<EvoCriteria> chain, int lvl)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
|
@ -84,7 +88,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<EncounterSlot> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
||||
private IEnumerable<EncounterSlot4> GetSlotsFuzzy(IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,10 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed record EncounterArea5 : EncounterArea
|
||||
{
|
||||
public readonly EncounterSlot5[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea5[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
var result = new EncounterArea5[input.Length];
|
||||
|
|
|
@ -9,6 +9,10 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed record EncounterArea6AO : EncounterArea
|
||||
{
|
||||
public readonly EncounterSlot6AO[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea6AO[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
var result = new EncounterArea6AO[input.Length];
|
||||
|
@ -68,12 +72,11 @@ namespace PKHeX.Core
|
|||
break;
|
||||
|
||||
// Track some metadata about how this slot was matched.
|
||||
var ao = (EncounterSlot6AO)slot;
|
||||
var clone = ao with
|
||||
var clone = slot with
|
||||
{
|
||||
WhiteFlute = evo.MinLevel < slot.LevelMin,
|
||||
BlackFlute = evo.MinLevel > slot.LevelMax && evo.MinLevel <= slot.LevelMax + FluteBoostMax,
|
||||
DexNav = ao.CanDexNav && (evo.MinLevel != slot.LevelMax || pkm.RelearnMove1 != 0 || pkm.AbilityNumber == 4),
|
||||
DexNav = slot.CanDexNav && (evo.MinLevel != slot.LevelMax || pkm.RelearnMove1 != 0 || pkm.AbilityNumber == 4),
|
||||
};
|
||||
yield return clone;
|
||||
break;
|
||||
|
|
|
@ -9,6 +9,10 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed record EncounterArea6XY : EncounterArea
|
||||
{
|
||||
public readonly EncounterSlot6XY[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea6XY[] GetAreas(byte[][] input, GameVersion game, EncounterArea6XY safari)
|
||||
{
|
||||
var result = new EncounterArea6XY[input.Length + 1];
|
||||
|
@ -124,7 +128,7 @@ namespace PKHeX.Core
|
|||
if (maxLevel != pkm.Met_Level)
|
||||
break;
|
||||
|
||||
yield return ((EncounterSlot6XY)slot).CreatePressureFormCopy(evo.Form);
|
||||
yield return slot.CreatePressureFormCopy(evo.Form);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed record EncounterArea7 : EncounterArea
|
||||
{
|
||||
public readonly EncounterSlot7[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea7[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
var result = new EncounterArea7[input.Length];
|
||||
|
|
|
@ -8,6 +8,10 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed record EncounterArea7b : EncounterArea
|
||||
{
|
||||
public readonly EncounterSlot7b[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea7b[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
var result = new EncounterArea7b[input.Length];
|
||||
|
|
|
@ -15,12 +15,16 @@ namespace PKHeX.Core
|
|||
public int Species { get; }
|
||||
/// <summary> Form of the Species </summary>
|
||||
public int Form { get; }
|
||||
public readonly EncounterSlot7GO[] Slots;
|
||||
|
||||
private EncounterArea7g(int species, int form) : base(GameVersion.GO)
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
private EncounterArea7g(int species, int form, EncounterSlot7GO[] slots) : base(GameVersion.GO)
|
||||
{
|
||||
Species = species;
|
||||
Form = form;
|
||||
Location = Locations.GO7;
|
||||
Slots = slots;
|
||||
}
|
||||
|
||||
internal static EncounterArea7g[] GetArea(byte[][] data)
|
||||
|
@ -40,7 +44,7 @@ namespace PKHeX.Core
|
|||
int form = sf >> 11;
|
||||
|
||||
var result = new EncounterSlot7GO[(data.Length - 2) / entrySize];
|
||||
var area = new EncounterArea7g(species, form) { Slots = result };
|
||||
var area = new EncounterArea7g(species, form, result);
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var offset = (i * entrySize) + 2;
|
||||
|
@ -72,11 +76,10 @@ namespace PKHeX.Core
|
|||
|
||||
var stamp = EncounterSlotGO.GetTimeStamp(pkm.Met_Year + 2000, pkm.Met_Month, pkm.Met_Day);
|
||||
var met = Math.Max(sf.MinLevel, pkm.Met_Level);
|
||||
EncounterSlot? deferredIV = null;
|
||||
EncounterSlot7GO? deferredIV = null;
|
||||
|
||||
foreach (var s in Slots)
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
var slot = (EncounterSlot7GO)s;
|
||||
if (!slot.IsLevelWithinRange(met))
|
||||
continue;
|
||||
//if (!slot.IsBallValid(ball)) -- can have any of the in-game balls due to re-capture
|
||||
|
|
|
@ -10,6 +10,9 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public sealed record EncounterArea8 : EncounterArea
|
||||
{
|
||||
public readonly EncounterSlot8[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
/// <summary>
|
||||
/// Slots from this area can cross over to another area, resulting in a different met location.
|
||||
/// </summary>
|
||||
|
@ -234,9 +237,9 @@ namespace PKHeX.Core
|
|||
Slots = ReadSlots(areaData, areaData[1]);
|
||||
}
|
||||
|
||||
private EncounterSlot[] ReadSlots(byte[] areaData, byte slotCount)
|
||||
private EncounterSlot8[] ReadSlots(byte[] areaData, byte slotCount)
|
||||
{
|
||||
var slots = new EncounterSlot[slotCount];
|
||||
var slots = new EncounterSlot8[slotCount];
|
||||
|
||||
int ctr = 0;
|
||||
int ofs = 2;
|
||||
|
|
|
@ -15,12 +15,16 @@ namespace PKHeX.Core
|
|||
public int Species { get; }
|
||||
/// <summary> Form of the Species </summary>
|
||||
public int Form { get; }
|
||||
public readonly EncounterSlot8GO[] Slots;
|
||||
|
||||
private EncounterArea8g(int species, int form) : base(GameVersion.GO)
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
private EncounterArea8g(int species, int form, EncounterSlot8GO[] slots) : base(GameVersion.GO)
|
||||
{
|
||||
Species = species;
|
||||
Form = form;
|
||||
Location = Locations.GO8;
|
||||
Slots = slots;
|
||||
}
|
||||
|
||||
internal static EncounterArea8g[] GetArea(byte[][] data)
|
||||
|
@ -42,7 +46,7 @@ namespace PKHeX.Core
|
|||
var group = GetGroup(species, form);
|
||||
|
||||
var result = new EncounterSlot8GO[(data.Length - 2) / entrySize];
|
||||
var area = new EncounterArea8g(species, form) {Slots = result};
|
||||
var area = new EncounterArea8g(species, form, result);
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var offset = (i * entrySize) + 2;
|
||||
|
@ -102,11 +106,10 @@ namespace PKHeX.Core
|
|||
|
||||
var ball = (Ball)pkm.Ball;
|
||||
var met = Math.Max(sf.MinLevel, pkm.Met_Level);
|
||||
EncounterSlot? deferredIV = null;
|
||||
EncounterSlot8GO? deferredIV = null;
|
||||
|
||||
foreach (var s in Slots)
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
var slot = (EncounterSlot8GO)s;
|
||||
if (!slot.IsLevelWithinRange(met))
|
||||
continue;
|
||||
if (!slot.IsBallValid(ball))
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using static PKHeX.Core.EncounterUtil;
|
||||
using static PKHeX.Core.GameVersion;
|
||||
using static PKHeX.Core.GroundTilePermission;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -198,33 +199,33 @@ namespace PKHeX.Core
|
|||
private static readonly EncounterStatic4[] Encounter_DPPt =
|
||||
{
|
||||
// Starters
|
||||
new(DP) { Gift = true, Species = 387, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Turtwig @ Lake Verity
|
||||
new(DP) { Gift = true, Species = 390, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Chimchar
|
||||
new(DP) { Gift = true, Species = 393, Level = 5, Location = 076, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Piplup
|
||||
new(Pt) { Gift = true, Species = 387, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Turtwig @ Route 201
|
||||
new(Pt) { Gift = true, Species = 390, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Chimchar
|
||||
new(Pt) { Gift = true, Species = 393, Level = 5, Location = 016, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Piplup
|
||||
new(DP) { Gift = true, Species = 387, Level = 5, Location = 076, GroundTile = Max_DP }, // Turtwig @ Lake Verity
|
||||
new(DP) { Gift = true, Species = 390, Level = 5, Location = 076, GroundTile = Max_DP }, // Chimchar
|
||||
new(DP) { Gift = true, Species = 393, Level = 5, Location = 076, GroundTile = Max_DP }, // Piplup
|
||||
new(Pt) { Gift = true, Species = 387, Level = 5, Location = 016, GroundTile = Max_Pt }, // Turtwig @ Route 201
|
||||
new(Pt) { Gift = true, Species = 390, Level = 5, Location = 016, GroundTile = Max_Pt }, // Chimchar
|
||||
new(Pt) { Gift = true, Species = 393, Level = 5, Location = 016, GroundTile = Max_Pt }, // Piplup
|
||||
|
||||
// Fossil @ Mining Museum
|
||||
new(DP) { Gift = true, Species = 138, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Omanyte
|
||||
new(DP) { Gift = true, Species = 140, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Kabuto
|
||||
new(DP) { Gift = true, Species = 142, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Aerodactyl
|
||||
new(DP) { Gift = true, Species = 345, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Lileep
|
||||
new(DP) { Gift = true, Species = 347, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Anorith
|
||||
new(DP) { Gift = true, Species = 408, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Cranidos
|
||||
new(DP) { Gift = true, Species = 410, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Shieldon
|
||||
new(Pt) { Gift = true, Species = 138, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Omanyte
|
||||
new(Pt) { Gift = true, Species = 140, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Kabuto
|
||||
new(Pt) { Gift = true, Species = 142, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Aerodactyl
|
||||
new(Pt) { Gift = true, Species = 345, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Lileep
|
||||
new(Pt) { Gift = true, Species = 347, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Anorith
|
||||
new(Pt) { Gift = true, Species = 408, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Cranidos
|
||||
new(Pt) { Gift = true, Species = 410, Level = 20, Location = 094, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Shieldon
|
||||
new(DP) { Gift = true, Species = 138, Level = 20, Location = 094, GroundTile = Max_DP }, // Omanyte
|
||||
new(DP) { Gift = true, Species = 140, Level = 20, Location = 094, GroundTile = Max_DP }, // Kabuto
|
||||
new(DP) { Gift = true, Species = 142, Level = 20, Location = 094, GroundTile = Max_DP }, // Aerodactyl
|
||||
new(DP) { Gift = true, Species = 345, Level = 20, Location = 094, GroundTile = Max_DP }, // Lileep
|
||||
new(DP) { Gift = true, Species = 347, Level = 20, Location = 094, GroundTile = Max_DP }, // Anorith
|
||||
new(DP) { Gift = true, Species = 408, Level = 20, Location = 094, GroundTile = Max_DP }, // Cranidos
|
||||
new(DP) { Gift = true, Species = 410, Level = 20, Location = 094, GroundTile = Max_DP }, // Shieldon
|
||||
new(Pt) { Gift = true, Species = 138, Level = 20, Location = 094, GroundTile = Max_Pt }, // Omanyte
|
||||
new(Pt) { Gift = true, Species = 140, Level = 20, Location = 094, GroundTile = Max_Pt }, // Kabuto
|
||||
new(Pt) { Gift = true, Species = 142, Level = 20, Location = 094, GroundTile = Max_Pt }, // Aerodactyl
|
||||
new(Pt) { Gift = true, Species = 345, Level = 20, Location = 094, GroundTile = Max_Pt }, // Lileep
|
||||
new(Pt) { Gift = true, Species = 347, Level = 20, Location = 094, GroundTile = Max_Pt }, // Anorith
|
||||
new(Pt) { Gift = true, Species = 408, Level = 20, Location = 094, GroundTile = Max_Pt }, // Cranidos
|
||||
new(Pt) { Gift = true, Species = 410, Level = 20, Location = 094, GroundTile = Max_Pt }, // Shieldon
|
||||
|
||||
// Gift
|
||||
new(DP) { Gift = true, Species = 133, Level = 05, Location = 010, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP, }, // Eevee @ Hearthome City
|
||||
new(Pt) { Gift = true, Species = 133, Level = 20, Location = 010, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Eevee @ Hearthome City
|
||||
new(Pt) { Gift = true, Species = 137, Level = 25, Location = 012, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Porygon @ Veilstone City
|
||||
new(DP) { Gift = true, Species = 133, Level = 05, Location = 010, GroundTile = Max_DP, }, // Eevee @ Hearthome City
|
||||
new(Pt) { Gift = true, Species = 133, Level = 20, Location = 010, GroundTile = Max_Pt, }, // Eevee @ Hearthome City
|
||||
new(Pt) { Gift = true, Species = 137, Level = 25, Location = 012, GroundTile = Max_Pt, }, // Porygon @ Veilstone City
|
||||
new(Pt) { Gift = true, Species = 175, Level = 01, EggLocation = 2011 }, // Togepi Egg from Cynthia
|
||||
new(DP) { Gift = true, Species = 440, Level = 01, EggLocation = 2009 }, // Happiny Egg from Traveling Man
|
||||
new(DPPt) { Gift = true, Species = 447, Level = 01, EggLocation = 2010, }, // Riolu Egg from Riley
|
||||
|
@ -232,95 +233,95 @@ namespace PKHeX.Core
|
|||
// Stationary
|
||||
new(DP) { Species = 425, Level = 22, Location = 47, }, // Drifloon @ Valley Windworks
|
||||
new(Pt) { Species = 425, Level = 15, Location = 47, }, // Drifloon @ Valley Windworks
|
||||
new(DP) { Species = 479, Level = 15, Location = 70, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Rotom @ Old Chateau
|
||||
new(Pt) { Species = 479, Level = 20, Location = 70, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Rotom @ Old Chateau
|
||||
new(DP) { Species = 479, Level = 15, Location = 70, GroundTile = Building, }, // Rotom @ Old Chateau
|
||||
new(Pt) { Species = 479, Level = 20, Location = 70, GroundTile = Building, }, // Rotom @ Old Chateau
|
||||
new(DPPt) { Species = 442, Level = 25, Location = 24 }, // Spiritomb @ Route 209
|
||||
|
||||
// Stationary Legendary
|
||||
new(Pt) { Species = 377, Level = 30, Location = 125, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Regirock @ Rock Peak Ruins
|
||||
new(Pt) { Species = 378, Level = 30, Location = 124, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Regice @ Iceberg Ruins
|
||||
new(Pt) { Species = 379, Level = 30, Location = 123, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Registeel @ Iron Ruins
|
||||
new(DPPt) { Species = 480, Level = 50, Location = 089, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Uxie @ Acuity Cavern
|
||||
new(DPPt) { Species = 482, Level = 50, Location = 088, TypeEncounter = EncounterType.Cave_HallOfOrigin, }, // Azelf @ Valor Cavern
|
||||
new(D ) { Species = 483, Level = 47, Location = 051, TypeEncounter = EncounterType.DialgaPalkia }, // Dialga @ Spear Pillar
|
||||
new( P) { Species = 484, Level = 47, Location = 051, TypeEncounter = EncounterType.DialgaPalkia }, // Palkia @ Spear Pillar
|
||||
new(Pt) { Species = 483, Level = 70, Location = 051, TypeEncounter = EncounterType.DialgaPalkia }, // Dialga @ Spear Pillar
|
||||
new(Pt) { Species = 484, Level = 70, Location = 051, TypeEncounter = EncounterType.DialgaPalkia }, // Palkia @ Spear Pillar
|
||||
new(DP) { Species = 485, Level = 70, Location = 084, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Heatran @ Stark Mountain
|
||||
new(Pt) { Species = 485, Level = 50, Location = 084, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Heatran @ Stark Mountain
|
||||
new(DP) { Species = 486, Level = 70, Location = 064, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Regigigas @ Snowpoint Temple
|
||||
new(Pt) { Species = 486, Level = 01, Location = 064, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Regigigas @ Snowpoint Temple
|
||||
new(DP) { Species = 487, Level = 70, Location = 062, TypeEncounter = EncounterType.Cave_HallOfOrigin, Form = 0, }, // Giratina @ Turnback Cave
|
||||
new(Pt) { Species = 487, Level = 47, Location = 062, TypeEncounter = EncounterType.Cave_HallOfOrigin, Form = 0, }, // Giratina @ Turnback Cave
|
||||
new(Pt) { Species = 487, Level = 47, Location = 117, TypeEncounter = EncounterType.DistortionWorld_Pt,Form = 1, HeldItem = 112 }, // Giratina @ Distortion World
|
||||
new(Pt) { Species = 377, Level = 30, Location = 125, GroundTile = Cave, }, // Regirock @ Rock Peak Ruins
|
||||
new(Pt) { Species = 378, Level = 30, Location = 124, GroundTile = Cave, }, // Regice @ Iceberg Ruins
|
||||
new(Pt) { Species = 379, Level = 30, Location = 123, GroundTile = Cave, }, // Registeel @ Iron Ruins
|
||||
new(DPPt) { Species = 480, Level = 50, Location = 089, GroundTile = Cave, }, // Uxie @ Acuity Cavern
|
||||
new(DPPt) { Species = 482, Level = 50, Location = 088, GroundTile = Cave, }, // Azelf @ Valor Cavern
|
||||
new(D ) { Species = 483, Level = 47, Location = 051, GroundTile = Rock }, // Dialga @ Spear Pillar
|
||||
new( P) { Species = 484, Level = 47, Location = 051, GroundTile = Rock }, // Palkia @ Spear Pillar
|
||||
new(Pt) { Species = 483, Level = 70, Location = 051, GroundTile = Rock }, // Dialga @ Spear Pillar
|
||||
new(Pt) { Species = 484, Level = 70, Location = 051, GroundTile = Rock }, // Palkia @ Spear Pillar
|
||||
new(DP) { Species = 485, Level = 70, Location = 084, GroundTile = Cave }, // Heatran @ Stark Mountain
|
||||
new(Pt) { Species = 485, Level = 50, Location = 084, GroundTile = Cave }, // Heatran @ Stark Mountain
|
||||
new(DP) { Species = 486, Level = 70, Location = 064, GroundTile = Cave }, // Regigigas @ Snowpoint Temple
|
||||
new(Pt) { Species = 486, Level = 01, Location = 064, GroundTile = Cave }, // Regigigas @ Snowpoint Temple
|
||||
new(DP) { Species = 487, Level = 70, Location = 062, GroundTile = Cave, Form = 0, }, // Giratina @ Turnback Cave
|
||||
new(Pt) { Species = 487, Level = 47, Location = 062, GroundTile = Cave, Form = 0, }, // Giratina @ Turnback Cave
|
||||
new(Pt) { Species = 487, Level = 47, Location = 117, GroundTile = Distortion,Form = 1, HeldItem = 112 }, // Giratina @ Distortion World
|
||||
|
||||
// Event
|
||||
new(DP) { Species = 491, Level = 40, Location = 079, TypeEncounter = EncounterType.TallGrass }, // Darkrai @ Newmoon Island (Unreleased in Diamond and Pearl)
|
||||
new(Pt) { Species = 491, Level = 50, Location = 079, TypeEncounter = EncounterType.TallGrass }, // Darkrai @ Newmoon Island
|
||||
new(DP) { Species = 491, Level = 40, Location = 079, GroundTile = Grass }, // Darkrai @ Newmoon Island (Unreleased in Diamond and Pearl)
|
||||
new(Pt) { Species = 491, Level = 50, Location = 079, GroundTile = Grass }, // Darkrai @ Newmoon Island
|
||||
new(Pt) { Species = 492, Form = 0, Level = 30, Location = 063, Fateful = true }, // Shaymin @ Flower Paradise
|
||||
new(DP) { Species = 492, Form = 0, Level = 30, Location = 063, Fateful = false }, // Shaymin @ Flower Paradise (Unreleased in Diamond and Pearl)
|
||||
new(DPPt) { Species = 493, Form = 0, Level = 80, Location = 086, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Arceus @ Hall of Origin (Unreleased)
|
||||
new(DPPt) { Species = 493, Form = 0, Level = 80, Location = 086, GroundTile = Cave }, // Arceus @ Hall of Origin (Unreleased)
|
||||
|
||||
// Roamers
|
||||
new(DPPt) { Roaming = true, Species = 481, Level = 50, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing }, // Mesprit
|
||||
new(DPPt) { Roaming = true, Species = 488, Level = 50, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing }, // Cresselia
|
||||
new(Pt) { Roaming = true, Species = 144, Level = 60, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing }, // Articuno
|
||||
new(Pt) { Roaming = true, Species = 145, Level = 60, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing }, // Zapdos
|
||||
new(Pt) { Roaming = true, Species = 146, Level = 60, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing }, // Moltres
|
||||
new(DPPt) { Roaming = true, Species = 481, Level = 50, GroundTile = Grass | Water }, // Mesprit
|
||||
new(DPPt) { Roaming = true, Species = 488, Level = 50, GroundTile = Grass | Water }, // Cresselia
|
||||
new(Pt) { Roaming = true, Species = 144, Level = 60, GroundTile = Grass | Water }, // Articuno
|
||||
new(Pt) { Roaming = true, Species = 145, Level = 60, GroundTile = Grass | Water }, // Zapdos
|
||||
new(Pt) { Roaming = true, Species = 146, Level = 60, GroundTile = Grass | Water }, // Moltres
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic4[] Encounter_HGSS =
|
||||
{
|
||||
// Starters
|
||||
new(HGSS) { Gift = true, Species = 001, Level = 05, Location = 138, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Bulbasaur @ Pallet Town
|
||||
new(HGSS) { Gift = true, Species = 004, Level = 05, Location = 138, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Charmander
|
||||
new(HGSS) { Gift = true, Species = 007, Level = 05, Location = 138, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Squirtle
|
||||
new(HGSS) { Gift = true, Species = 152, Level = 05, Location = 126, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Chikorita @ New Bark Town
|
||||
new(HGSS) { Gift = true, Species = 155, Level = 05, Location = 126, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Cyndaquil
|
||||
new(HGSS) { Gift = true, Species = 158, Level = 05, Location = 126, TypeEncounter = EncounterType.Starter_Fossil_Gift_DP }, // Totodile
|
||||
new(HGSS) { Gift = true, Species = 252, Level = 05, Location = 148, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Treecko @ Saffron City
|
||||
new(HGSS) { Gift = true, Species = 255, Level = 05, Location = 148, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Torchic
|
||||
new(HGSS) { Gift = true, Species = 258, Level = 05, Location = 148, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Mudkip
|
||||
new(HGSS) { Gift = true, Species = 001, Level = 05, Location = 138, GroundTile = Max_Pt }, // Bulbasaur @ Pallet Town
|
||||
new(HGSS) { Gift = true, Species = 004, Level = 05, Location = 138, GroundTile = Max_Pt }, // Charmander
|
||||
new(HGSS) { Gift = true, Species = 007, Level = 05, Location = 138, GroundTile = Max_Pt }, // Squirtle
|
||||
new(HGSS) { Gift = true, Species = 152, Level = 05, Location = 126, GroundTile = Max_DP }, // Chikorita @ New Bark Town
|
||||
new(HGSS) { Gift = true, Species = 155, Level = 05, Location = 126, GroundTile = Max_DP }, // Cyndaquil
|
||||
new(HGSS) { Gift = true, Species = 158, Level = 05, Location = 126, GroundTile = Max_DP }, // Totodile
|
||||
new(HGSS) { Gift = true, Species = 252, Level = 05, Location = 148, GroundTile = Max_Pt }, // Treecko @ Saffron City
|
||||
new(HGSS) { Gift = true, Species = 255, Level = 05, Location = 148, GroundTile = Max_Pt }, // Torchic
|
||||
new(HGSS) { Gift = true, Species = 258, Level = 05, Location = 148, GroundTile = Max_Pt }, // Mudkip
|
||||
|
||||
// Fossils @ Pewter City
|
||||
new(HGSS) { Gift = true, Species = 138, Level = 20, Location = 140, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Omanyte
|
||||
new(HGSS) { Gift = true, Species = 140, Level = 20, Location = 140, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Kabuto
|
||||
new(HGSS) { Gift = true, Species = 142, Level = 20, Location = 140, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Aerodactyl
|
||||
new(HGSS) { Gift = true, Species = 345, Level = 20, Location = 140, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Lileep
|
||||
new(HGSS) { Gift = true, Species = 347, Level = 20, Location = 140, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Anorith
|
||||
new(HGSS) { Gift = true, Species = 408, Level = 20, Location = 140, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Cranidos
|
||||
new(HGSS) { Gift = true, Species = 410, Level = 20, Location = 140, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Shieldon
|
||||
new(HGSS) { Gift = true, Species = 138, Level = 20, Location = 140, GroundTile = Max_Pt, }, // Omanyte
|
||||
new(HGSS) { Gift = true, Species = 140, Level = 20, Location = 140, GroundTile = Max_Pt, }, // Kabuto
|
||||
new(HGSS) { Gift = true, Species = 142, Level = 20, Location = 140, GroundTile = Max_Pt, }, // Aerodactyl
|
||||
new(HGSS) { Gift = true, Species = 345, Level = 20, Location = 140, GroundTile = Max_Pt, }, // Lileep
|
||||
new(HGSS) { Gift = true, Species = 347, Level = 20, Location = 140, GroundTile = Max_Pt, }, // Anorith
|
||||
new(HGSS) { Gift = true, Species = 408, Level = 20, Location = 140, GroundTile = Max_Pt, }, // Cranidos
|
||||
new(HGSS) { Gift = true, Species = 410, Level = 20, Location = 140, GroundTile = Max_Pt, }, // Shieldon
|
||||
|
||||
// Gift
|
||||
new(HGSS) { Gift = true, Species = 072, Level = 15, Location = 130, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Tentacool @ Cianwood City
|
||||
new(HGSS) { Gift = true, Species = 133, Level = 05, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Eevee @ Goldenrod City
|
||||
new(HGSS) { Gift = true, Species = 147, Level = 15, Location = 222, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Moves = new[] {245} }, // Dratini @ Dragon's Den (ExtremeSpeed)
|
||||
new(HGSS) { Gift = true, Species = 236, Level = 10, Location = 216, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, }, // Tyrogue @ Mt. Mortar
|
||||
new(HGSS) { Gift = true, Species = 072, Level = 15, Location = 130, GroundTile = Max_Pt }, // Tentacool @ Cianwood City
|
||||
new(HGSS) { Gift = true, Species = 133, Level = 05, Location = 131, GroundTile = Max_Pt }, // Eevee @ Goldenrod City
|
||||
new(HGSS) { Gift = true, Species = 147, Level = 15, Location = 222, GroundTile = Max_Pt, Moves = new[] {245} }, // Dratini @ Dragon's Den (ExtremeSpeed)
|
||||
new(HGSS) { Gift = true, Species = 236, Level = 10, Location = 216, GroundTile = Max_Pt, }, // Tyrogue @ Mt. Mortar
|
||||
new(HGSS) { Gift = true, Species = 175, Level = 01, EggLocation = 2013, Moves = new[] {326} }, // Togepi Egg from Mr. Pokemon (Extrasensory as Egg move)
|
||||
new(HGSS) { Gift = true, Species = 179, Level = 01, EggLocation = 2014, }, // Mareep Egg from Primo
|
||||
new(HGSS) { Gift = true, Species = 194, Level = 01, EggLocation = 2014, }, // Wooper Egg from Primo
|
||||
new(HGSS) { Gift = true, Species = 218, Level = 01, EggLocation = 2014, }, // Slugma Egg from Primo
|
||||
|
||||
// Celadon City Game Corner
|
||||
new(HGSS) { Gift = true, Species = 122, Level = 15, Location = 144, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Mr. Mime
|
||||
new(HGSS) { Gift = true, Species = 133, Level = 15, Location = 144, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Eevee
|
||||
new(HGSS) { Gift = true, Species = 137, Level = 15, Location = 144, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Porygon
|
||||
new(HGSS) { Gift = true, Species = 122, Level = 15, Location = 144, GroundTile = Max_Pt }, // Mr. Mime
|
||||
new(HGSS) { Gift = true, Species = 133, Level = 15, Location = 144, GroundTile = Max_Pt }, // Eevee
|
||||
new(HGSS) { Gift = true, Species = 137, Level = 15, Location = 144, GroundTile = Max_Pt }, // Porygon
|
||||
|
||||
// Goldenrod City Game Corner
|
||||
new(HGSS) { Gift = true, Species = 063, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Abra
|
||||
new(HG ) { Gift = true, Species = 023, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Ekans
|
||||
new( SS) { Gift = true, Species = 027, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Sandshrew
|
||||
new(HGSS) { Gift = true, Species = 147, Level = 15, Location = 131, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Dratini
|
||||
new(HGSS) { Gift = true, Species = 063, Level = 15, Location = 131, GroundTile = Max_Pt }, // Abra
|
||||
new(HG ) { Gift = true, Species = 023, Level = 15, Location = 131, GroundTile = Max_Pt }, // Ekans
|
||||
new( SS) { Gift = true, Species = 027, Level = 15, Location = 131, GroundTile = Max_Pt }, // Sandshrew
|
||||
new(HGSS) { Gift = true, Species = 147, Level = 15, Location = 131, GroundTile = Max_Pt }, // Dratini
|
||||
|
||||
// Team Rocket HQ Trap Floor
|
||||
new(HGSS) { Species = 100, Level = 23, Location = 213, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Voltorb
|
||||
new(HGSS) { Species = 074, Level = 21, Location = 213, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Geodude
|
||||
new(HGSS) { Species = 109, Level = 21, Location = 213, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Koffing
|
||||
new(HGSS) { Species = 100, Level = 23, Location = 213, GroundTile = Building, }, // Voltorb
|
||||
new(HGSS) { Species = 074, Level = 21, Location = 213, GroundTile = Building, }, // Geodude
|
||||
new(HGSS) { Species = 109, Level = 21, Location = 213, GroundTile = Building, }, // Koffing
|
||||
|
||||
// Stationary
|
||||
new(HGSS) { Species = 130, Level = 30, Location = 135, TypeEncounter = EncounterType.Surfing_Fishing, Shiny = Shiny.Always }, // Gyarados @ Lake of Rage
|
||||
new(HGSS) { Species = 131, Level = 20, Location = 210, TypeEncounter = EncounterType.Surfing_Fishing, }, // Lapras @ Union Cave Friday Only
|
||||
new(HGSS) { Species = 101, Level = 23, Location = 213, TypeEncounter = EncounterType.Building_EnigmaStone, }, // Electrode @ Team Rocket HQ
|
||||
new(HGSS) { Species = 130, Level = 30, Location = 135, GroundTile = Water, Shiny = Shiny.Always }, // Gyarados @ Lake of Rage
|
||||
new(HGSS) { Species = 131, Level = 20, Location = 210, GroundTile = Water, }, // Lapras @ Union Cave Friday Only
|
||||
new(HGSS) { Species = 101, Level = 23, Location = 213, GroundTile = Building, }, // Electrode @ Team Rocket HQ
|
||||
new(HGSS) { Species = 143, Level = 50, Location = 159, }, // Snorlax @ Route 11
|
||||
new(HGSS) { Species = 143, Level = 50, Location = 160, }, // Snorlax @ Route 12
|
||||
new(HGSS) { Species = 185, Level = 20, Location = 184, }, // Sudowoodo @ Route 36, Encounter does not have type
|
||||
|
@ -334,37 +335,37 @@ namespace PKHeX.Core
|
|||
Nature = Nature.Naughty,
|
||||
Location = 214,
|
||||
Moves = new[] { 344, 270, 207, 220 },
|
||||
TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio,
|
||||
GroundTile = Max_Pt,
|
||||
Shiny = Shiny.Never
|
||||
},
|
||||
|
||||
// Stationary Legendary
|
||||
new(HGSS) { Species = 144, Level = 50, Location = 203, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Articuno @ Seafoam Islands
|
||||
new(HGSS) { Species = 144, Level = 50, Location = 203, GroundTile = Cave }, // Articuno @ Seafoam Islands
|
||||
new(HGSS) { Species = 145, Level = 50, Location = 158, }, // Zapdos @ Route 10
|
||||
new(HGSS) { Species = 146, Level = 50, Location = 219, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Moltres @ Mt. Silver Cave
|
||||
new(HGSS) { Species = 150, Level = 70, Location = 199, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Mewtwo @ Cerulean Cave
|
||||
new(HGSS) { Species = 146, Level = 50, Location = 219, GroundTile = Cave }, // Moltres @ Mt. Silver Cave
|
||||
new(HGSS) { Species = 150, Level = 70, Location = 199, GroundTile = Cave }, // Mewtwo @ Cerulean Cave
|
||||
new(HGSS) { Species = 245, Level = 40, Location = 173, }, // Suicune @ Route 25
|
||||
new(HGSS) { Species = 245, Level = 40, Location = 206, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Suicune @ Burned Tower
|
||||
new( SS) { Species = 249, Level = 45, Location = 218, TypeEncounter = EncounterType.Surfing_Fishing }, // Lugia @ Whirl Islands
|
||||
new(HG ) { Species = 249, Level = 70, Location = 218, TypeEncounter = EncounterType.Surfing_Fishing }, // Lugia @ Whirl Islands
|
||||
new(HG ) { Species = 250, Level = 45, Location = 205, TypeEncounter = EncounterType.Building_EnigmaStone }, // Ho-Oh @ Bell Tower
|
||||
new( SS) { Species = 250, Level = 70, Location = 205, TypeEncounter = EncounterType.Building_EnigmaStone }, // Ho-Oh @ Bell Tower
|
||||
new( SS) { Species = 380, Level = 40, Location = 140, TypeEncounter = EncounterType.Building_EnigmaStone }, // Latias @ Pewter City
|
||||
new(HG ) { Species = 381, Level = 40, Location = 140, TypeEncounter = EncounterType.Building_EnigmaStone }, // Latios @ Pewter City
|
||||
new(HG ) { Species = 382, Level = 50, Location = 232, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Kyogre @ Embedded Tower
|
||||
new( SS) { Species = 383, Level = 50, Location = 232, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Groudon @ Embedded Tower
|
||||
new(HGSS) { Species = 384, Level = 50, Location = 232, TypeEncounter = EncounterType.Cave_HallOfOrigin }, // Rayquaza @ Embedded Tower
|
||||
new(HGSS) { Species = 483, Level = 01, Location = 231, Gift = true, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Dialga @ Sinjoh Ruins
|
||||
new(HGSS) { Species = 484, Level = 01, Location = 231, Gift = true, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, // Palkia @ Sinjoh Ruins
|
||||
new(HGSS) { Species = 487, Level = 01, Location = 231, Gift = true, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Form = 1, HeldItem = 112 }, // Giratina @ Sinjoh Ruins
|
||||
new(HGSS) { Species = 245, Level = 40, Location = 206, GroundTile = Cave }, // Suicune @ Burned Tower
|
||||
new( SS) { Species = 249, Level = 45, Location = 218, GroundTile = Water }, // Lugia @ Whirl Islands
|
||||
new(HG ) { Species = 249, Level = 70, Location = 218, GroundTile = Water }, // Lugia @ Whirl Islands
|
||||
new(HG ) { Species = 250, Level = 45, Location = 205, GroundTile = Building }, // Ho-Oh @ Bell Tower
|
||||
new( SS) { Species = 250, Level = 70, Location = 205, GroundTile = Building }, // Ho-Oh @ Bell Tower
|
||||
new( SS) { Species = 380, Level = 40, Location = 140, GroundTile = Building }, // Latias @ Pewter City
|
||||
new(HG ) { Species = 381, Level = 40, Location = 140, GroundTile = Building }, // Latios @ Pewter City
|
||||
new(HG ) { Species = 382, Level = 50, Location = 232, GroundTile = Cave }, // Kyogre @ Embedded Tower
|
||||
new( SS) { Species = 383, Level = 50, Location = 232, GroundTile = Cave }, // Groudon @ Embedded Tower
|
||||
new(HGSS) { Species = 384, Level = 50, Location = 232, GroundTile = Cave }, // Rayquaza @ Embedded Tower
|
||||
new(HGSS) { Species = 483, Level = 01, Location = 231, Gift = true, GroundTile = Max_Pt }, // Dialga @ Sinjoh Ruins
|
||||
new(HGSS) { Species = 484, Level = 01, Location = 231, Gift = true, GroundTile = Max_Pt }, // Palkia @ Sinjoh Ruins
|
||||
new(HGSS) { Species = 487, Level = 01, Location = 231, Gift = true, GroundTile = Max_Pt, Form = 1, HeldItem = 112 }, // Giratina @ Sinjoh Ruins
|
||||
|
||||
// Johto Roamers
|
||||
new(HGSS) { Roaming = true, Species = 243, Level = 40, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing, }, // Raikou
|
||||
new(HGSS) { Roaming = true, Species = 244, Level = 40, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing, }, // Entei
|
||||
new(HGSS) { Roaming = true, Species = 243, Level = 40, GroundTile = Grass | Water, }, // Raikou
|
||||
new(HGSS) { Roaming = true, Species = 244, Level = 40, GroundTile = Grass | Water, }, // Entei
|
||||
|
||||
// Kanto Roamers
|
||||
new(HG ) { Roaming = true, Species = 380, Level = 35, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing, }, // Latias
|
||||
new( SS) { Roaming = true, Species = 381, Level = 35, TypeEncounter = EncounterType.TallGrass | EncounterType.Surfing_Fishing, }, // Latios
|
||||
new(HG ) { Roaming = true, Species = 380, Level = 35, GroundTile = Grass | Water, }, // Latias
|
||||
new( SS) { Roaming = true, Species = 381, Level = 35, GroundTile = Grass | Water, }, // Latios
|
||||
};
|
||||
#endregion
|
||||
#region Trade Tables
|
||||
|
|
|
@ -4,10 +4,10 @@ namespace PKHeX.Core
|
|||
/// Encounter Slot found in <see cref="GameVersion.Gen4"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="EncounterSlot"/>
|
||||
public sealed record EncounterSlot4 : EncounterSlot, IMagnetStatic, INumberedSlot, IEncounterTypeTile
|
||||
public sealed record EncounterSlot4 : EncounterSlot, IMagnetStatic, INumberedSlot, IGroundTypeTile
|
||||
{
|
||||
public override int Generation => 4;
|
||||
public EncounterType TypeEncounter => ((EncounterArea4)Area).TypeEncounter;
|
||||
public GroundTilePermission GroundTile => ((EncounterArea4)Area).GroundTile;
|
||||
|
||||
public int StaticIndex { get; }
|
||||
public int MagnetPullIndex { get; }
|
||||
|
@ -27,7 +27,7 @@ namespace PKHeX.Core
|
|||
StaticCount = stc;
|
||||
}
|
||||
|
||||
protected override void SetFormatSpecificData(PKM pk) => ((PK4)pk).EncounterType = TypeEncounter.GetIndex();
|
||||
protected override void SetFormatSpecificData(PKM pk) => ((PK4)pk).GroundTile = GroundTile.GetIndex();
|
||||
|
||||
public override EncounterMatchRating GetMatchRating(PKM pkm)
|
||||
{
|
||||
|
|
|
@ -7,20 +7,20 @@ namespace PKHeX.Core
|
|||
/// <seealso cref="EncounterSlot4"/>
|
||||
/// <seealso cref="EncounterStatic4"/>
|
||||
/// </remarks>
|
||||
public interface IEncounterTypeTile
|
||||
public interface IGroundTypeTile
|
||||
{
|
||||
/// <summary>
|
||||
/// Tile Type the <see cref="IEncounterable"/> was obtained on.
|
||||
/// </summary>
|
||||
EncounterType TypeEncounter { get; }
|
||||
GroundTilePermission GroundTile { get; }
|
||||
}
|
||||
|
||||
public static class EncounterTypeTileExtensions
|
||||
public static class GroundTypeTileExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets if the resulting <see cref="PKM"/> will still have a value depending on the current <see cref="format"/>.
|
||||
/// </summary>
|
||||
/// <remarks>Generation 6 no longer stores this value.</remarks>
|
||||
public static bool HasTypeEncounter(this IEncounterTypeTile _, int format) => format is 4 or 5;
|
||||
/// <remarks>Generation 7 no longer stores this value.</remarks>
|
||||
public static bool HasGroundTile(this IGroundTypeTile _, int format) => format is (4 or 5 or 6);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.EncounterType;
|
||||
using static PKHeX.Core.GroundTilePermission;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -8,15 +8,15 @@ namespace PKHeX.Core
|
|||
/// Generation 4 Static Encounter
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="EncounterStatic"/>
|
||||
public sealed record EncounterStatic4 : EncounterStatic, IEncounterTypeTile
|
||||
public sealed record EncounterStatic4 : EncounterStatic, IGroundTypeTile
|
||||
{
|
||||
public override int Generation => 4;
|
||||
|
||||
/// <summary> Indicates if the encounter is a Roamer (variable met location) </summary>
|
||||
public bool Roaming { get; init; }
|
||||
|
||||
/// <summary> <see cref="PK4.EncounterType"/> values permitted for the encounter. </summary>
|
||||
public EncounterType TypeEncounter { get; init; } = None;
|
||||
/// <summary> <see cref="PK4.GroundTile"/> values permitted for the encounter. </summary>
|
||||
public GroundTilePermission GroundTile { get; init; } = None;
|
||||
|
||||
public EncounterStatic4(GameVersion game) : base(game) { }
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace PKHeX.Core
|
|||
if (pkm is not G4PKM pk4)
|
||||
return true;
|
||||
|
||||
var locs = GetRoamLocations(Species, pk4.EncounterType);
|
||||
var locs = GetRoamLocations(Species, pk4.GroundTile);
|
||||
return locs.Contains(pk4.Met_Location);
|
||||
}
|
||||
|
||||
|
@ -95,17 +95,17 @@ namespace PKHeX.Core
|
|||
protected override void SetMetData(PKM pk, int level, DateTime today)
|
||||
{
|
||||
var pk4 = (PK4)pk;
|
||||
var type = pk4.EncounterType = TypeEncounter.GetIndex();
|
||||
var type = pk4.GroundTile = GroundTile.GetIndex();
|
||||
pk.Met_Location = Roaming ? GetRoamLocations(Species, type)[0] : Location;
|
||||
pk.Met_Level = level;
|
||||
pk.MetDate = today;
|
||||
}
|
||||
|
||||
private static int[] GetRoamLocations(int species, int type) => species switch
|
||||
private static int[] GetRoamLocations(int species, GroundTileType type) => species switch
|
||||
{
|
||||
481 or 488 or 144 or 145 or 146 => 1 << type == (int)TallGrass ? Roaming_MetLocation_DPPt_Grass : Roaming_MetLocation_DPPt_Surf,
|
||||
243 or 244 => 1 << type == (int)TallGrass ? Roaming_MetLocation_HGSS_Johto_Grass : Roaming_MetLocation_HGSS_Johto_Surf,
|
||||
380 or 381 => 1 << type == (int)TallGrass ? Roaming_MetLocation_HGSS_Kanto_Grass : Roaming_MetLocation_HGSS_Kanto_Surf,
|
||||
481 or 488 or 144 or 145 or 146 => type == GroundTileType.Grass ? Roaming_MetLocation_DPPt_Grass : Roaming_MetLocation_DPPt_Surf,
|
||||
243 or 244 => type == GroundTileType.Grass ? Roaming_MetLocation_HGSS_Johto_Grass : Roaming_MetLocation_HGSS_Johto_Surf,
|
||||
380 or 381 => type == GroundTileType.Grass ? Roaming_MetLocation_HGSS_Kanto_Grass : Roaming_MetLocation_HGSS_Kanto_Surf,
|
||||
_ => throw new IndexOutOfRangeException(nameof(species)),
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
if (!info.PIDIV.Type.IsCompatible4(z, pkm))
|
||||
deferredPIDIV.Add(z);
|
||||
else if (pkm.Format <= 6 && !(z is IEncounterTypeTile t ? t.TypeEncounter.Contains(pkm.EncounterType) : pkm.EncounterType == 0))
|
||||
else if (pkm is IGroundTile e && !(z is IGroundTypeTile t ? t.GroundTile.Contains(e.GroundTile) : e.GroundTile == 0))
|
||||
deferredEType.Add(z);
|
||||
else
|
||||
yield return z;
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace PKHeX.Core
|
|||
public static IEnumerable<EncounterSlot> GetPossible(PKM pkm, IReadOnlyList<DexLevel> chain, GameVersion gameSource = Any)
|
||||
{
|
||||
var possibleAreas = GetAreasByGame(pkm, gameSource);
|
||||
return possibleAreas.SelectMany(area => area.Slots).Where(z => chain.Any(v => v.Species == z.Species));
|
||||
return possibleAreas.SelectMany(z => z.GetSpecies(chain));
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterArea> GetAreasByGame(PKM pkm, GameVersion gameSource) => gameSource switch
|
||||
|
|
|
@ -203,7 +203,7 @@ namespace PKHeX.Core
|
|||
public int LevelMax { get; }
|
||||
|
||||
public int GetSuggestedMetLevel(PKM pkm) => EncounterSuggestion.GetSuggestedMetLevel(pkm, LevelMin);
|
||||
public int GetSuggestedEncounterType() => Encounter is IEncounterTypeTile t ? t.TypeEncounter.GetIndex() : 0;
|
||||
public bool HasEncounterType(int format) => Encounter is IEncounterTypeTile t && t.HasTypeEncounter(format);
|
||||
public GroundTileType GetSuggestedGroundTile() => Encounter is IGroundTypeTile t ? t.GroundTile.GetIndex() : 0;
|
||||
public bool HasGroundTile(int format) => Encounter is IGroundTypeTile t && t.HasGroundTile(format);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Tile type the <see cref="PKM"/> was encountered from.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Used in Generation 4 games, this value is set depending on what type of overworld tile the player is standing on when the <see cref="PKM"/> is obtained.
|
||||
/// Some locations have multiple tile types, requiring multiple values possible.
|
||||
/// </remarks>
|
||||
[Flags]
|
||||
public enum EncounterType
|
||||
{
|
||||
Undefined = 0,
|
||||
None = 1 << 00,
|
||||
RockSmash = 1 << 01,
|
||||
TallGrass = 1 << 02,
|
||||
DialgaPalkia = 1 << 04,
|
||||
Cave_HallOfOrigin = 1 << 05,
|
||||
Surfing_Fishing = 1 << 07,
|
||||
Building_EnigmaStone = 1 << 09,
|
||||
MarshSafari = 1 << 10,
|
||||
Starter_Fossil_Gift_DP = 1 << 12,
|
||||
DistortionWorld_Pt = 1 << 23,
|
||||
Starter_Fossil_Gift_Pt_DPTrio = 1 << 24,
|
||||
}
|
||||
|
||||
public static class EncounterTypeExtension
|
||||
{
|
||||
public static bool Contains(this EncounterType g1, int g2) => (g1 & (EncounterType)(1 << g2)) != 0;
|
||||
|
||||
public static int GetIndex(this EncounterType g)
|
||||
{
|
||||
int val = (int) g;
|
||||
for (int i = 0; i < 8 * sizeof(EncounterType); i++)
|
||||
{
|
||||
val >>= 1;
|
||||
if (val == 0)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
68
PKHeX.Core/Legality/Enums/GroundTilePermission.cs
Normal file
68
PKHeX.Core/Legality/Enums/GroundTilePermission.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Permitted <see cref="GroundTileType"/> values an encounter can be acquired with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Some locations have multiple tile types that can proc an encounter, requiring multiple values possible.
|
||||
/// </remarks>
|
||||
[Flags]
|
||||
public enum GroundTilePermission
|
||||
{
|
||||
Undefined = 0,
|
||||
None = 1 << 00, // No animation for the tile
|
||||
Sand = 1 << 01, // Obtainable only via HG/SS
|
||||
Grass = 1 << 02,
|
||||
Puddle = 1 << 03, // No encounters from this tile type
|
||||
Rock = 1 << 04,
|
||||
Cave = 1 << 05,
|
||||
Snow = 1 << 06, // No encounters from this tile type
|
||||
Water = 1 << 07,
|
||||
Ice = 1 << 08, // No encounters from this tile type
|
||||
Building = 1 << 09,
|
||||
Marsh = 1 << 10,
|
||||
Bridge = 1 << 11, // No encounters from this tile type
|
||||
Max_DP = 1 << 12, // Unspecific, catch-all for DP undefined tiles.
|
||||
|
||||
// added tile types in Pt
|
||||
// no encounters from these tile types
|
||||
Elite4_1 = 1 << 12, // Elite Four Room #1
|
||||
Elite4_2 = 1 << 13, // Elite Four Room #2
|
||||
Elite4_3 = 1 << 14, // Elite Four Room #3
|
||||
Elite4_4 = 1 << 15, // Elite Four Room #4
|
||||
Elite4_M = 1 << 16, // Elite Four Champion Room
|
||||
DistortionSideways = 1 << 17, // Distortion World (Not Giratina)
|
||||
BattleTower = 1 << 18,
|
||||
BattleFactory = 1 << 19,
|
||||
BattleArcade = 1 << 20,
|
||||
BattleCastle = 1 << 21,
|
||||
BattleHall = 1 << 22,
|
||||
|
||||
Distortion = 1 << 23,
|
||||
Max_Pt = 1 << 24, // Unspecific, catch-all for Pt undefined tiles.
|
||||
}
|
||||
|
||||
public static class GroundTilePermissionExtensions
|
||||
{
|
||||
public static bool Contains(this GroundTilePermission g1, GroundTileType g2) => (g1 & (GroundTilePermission)(1 << (int)g2)) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Grabs the highest set bit from the tile value.
|
||||
/// </summary>
|
||||
/// <param name="g">Tile bit-permission value</param>
|
||||
/// <returns>Bit index</returns>
|
||||
public static GroundTileType GetIndex(this GroundTilePermission g)
|
||||
{
|
||||
int val = (int) g;
|
||||
for (byte i = 0; i < 8 * sizeof(GroundTilePermission); i++)
|
||||
{
|
||||
val >>= 1;
|
||||
if (val == 0)
|
||||
return (GroundTileType)i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ namespace PKHeX.Core
|
|||
/// Wild Encounter data <see cref="EncounterSlot"/> Type
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Different from <see cref="EncounterType"/>, this corresponds to the method that the <see cref="IEncounterable"/> may be encountered.</remarks>
|
||||
/// Different from <see cref="GroundTilePermission"/>, this corresponds to the method that the <see cref="IEncounterable"/> may be encountered.</remarks>
|
||||
[Flags]
|
||||
#pragma warning disable RCS1191 // Declare enum value as combination of names.
|
||||
public enum SlotType : byte
|
||||
|
|
|
@ -297,7 +297,7 @@ namespace PKHeX.Core
|
|||
|
||||
var format = pkm.Format;
|
||||
if (format is 4 or 5 or 6)
|
||||
Gen4EncounterType.Verify(this); // Gen 6->7 transfer deletes encounter type data
|
||||
Gen4GroundTile.Verify(this); // Gen 6->7 transfer deletes encounter type data
|
||||
|
||||
if (format < 6)
|
||||
return;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
public static readonly MedalVerifier Medal = new();
|
||||
public static readonly RibbonVerifier Ribbon = new();
|
||||
public static readonly ItemVerifier Item = new();
|
||||
public static readonly EncounterTypeVerifier Gen4EncounterType = new();
|
||||
public static readonly GroundTileVerifier Gen4GroundTile = new();
|
||||
public static readonly HyperTrainingVerifier HyperTraining = new();
|
||||
public static readonly GenderVerifier GenderValues = new();
|
||||
public static readonly PIDVerifier PIDEC = new();
|
||||
|
|
|
@ -878,9 +878,9 @@ namespace PKHeX.Core
|
|||
return true;
|
||||
if (val != ChainShiny)
|
||||
return false;
|
||||
// Chain shiny with poke radar is only possible in DPPt in tall grass, safari zone do not allow pokeradar
|
||||
// TypeEncounter TallGrass discard any cave or city
|
||||
return pkm.IsShiny && !pkm.HGSS && sl.TypeEncounter == EncounterType.TallGrass && !Locations.IsSafariZoneLocation4(sl.Location);
|
||||
// Chain shiny with poke radar is only possible in DPPt in grass, safari zone does not allow pokeradar
|
||||
// TypeEncounter Grass discard any cave or city
|
||||
return pkm.IsShiny && !pkm.HGSS && sl.GroundTile == GroundTilePermission.Grass && !Locations.IsSafariZoneLocation4(sl.Location);
|
||||
case PGT: // manaphy
|
||||
return IsG4ManaphyPIDValid(val, pkm);
|
||||
case PCD d when d.Gift.PK.PID != 1:
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
using static PKHeX.Core.LegalityCheckStrings;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies the <see cref="PK4.EncounterType"/>.
|
||||
/// </summary>
|
||||
public sealed class EncounterTypeVerifier : Verifier
|
||||
{
|
||||
protected override CheckIdentifier Identifier => CheckIdentifier.Encounter;
|
||||
|
||||
public override void Verify(LegalityAnalysis data)
|
||||
{
|
||||
var type = data.EncounterMatch is IEncounterTypeTile t ? t.TypeEncounter : EncounterType.None;
|
||||
var result = !type.Contains(data.pkm.EncounterType) ? GetInvalid(LEncTypeMismatch) : GetValid(LEncTypeMatch);
|
||||
data.AddLine(result);
|
||||
}
|
||||
}
|
||||
}
|
21
PKHeX.Core/Legality/Verifiers/GroundTileVerifier.cs
Normal file
21
PKHeX.Core/Legality/Verifiers/GroundTileVerifier.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
using static PKHeX.Core.LegalityCheckStrings;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies the <see cref="PK4.GroundTile"/>.
|
||||
/// </summary>
|
||||
public sealed class GroundTileVerifier : Verifier
|
||||
{
|
||||
protected override CheckIdentifier Identifier => CheckIdentifier.Encounter;
|
||||
|
||||
public override void Verify(LegalityAnalysis data)
|
||||
{
|
||||
if (data.pkm is not IGroundTile e)
|
||||
return;
|
||||
var type = data.EncounterMatch is IGroundTypeTile t ? t.GroundTile : GroundTilePermission.None;
|
||||
var result = !type.Contains(e.GroundTile) ? GetInvalid(LEncTypeMismatch) : GetValid(LEncTypeMatch);
|
||||
data.AddLine(result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -157,7 +157,7 @@ namespace PKHeX.Core
|
|||
|
||||
private static bool GetCanBeCaptured(int species, IEnumerable<EncounterArea> area, IEnumerable<EncounterStatic> statics)
|
||||
{
|
||||
if (area.Any(loc => loc.Slots.Any(slot => slot.Species == species)))
|
||||
if (area.Any(loc => loc.HasSpecies(species)))
|
||||
return true;
|
||||
if (statics.Any(enc => enc.Species == species && !enc.Gift))
|
||||
return true;
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace PKHeX.Core
|
|||
if (pkm.Format <= 7 && pkm.IsNicknamed) // can nickname afterwards
|
||||
{
|
||||
if (pkm.VC)
|
||||
VerifyG1NicknameWithinBounds(data, nickname);
|
||||
VerifyG1NicknameWithinBounds(data, nickname.AsSpan());
|
||||
else if (enc is MysteryGift {IsEgg: false})
|
||||
data.AddLine(Get(LEncGiftNicknamed, ParseSettings.NicknamedMysteryGift));
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private void VerifyG1NicknameWithinBounds(LegalityAnalysis data, string str)
|
||||
private void VerifyG1NicknameWithinBounds(LegalityAnalysis data, ReadOnlySpan<char> str)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
if (StringConverter12.GetIsG1English(str))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using static PKHeX.Core.LegalityCheckStrings;
|
||||
|
||||
namespace PKHeX.Core
|
||||
|
@ -118,7 +118,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
VerifyG1OTWithinBounds(data, tr);
|
||||
VerifyG1OTWithinBounds(data, tr.AsSpan());
|
||||
|
||||
if (pkm.OT_Gender == 1)
|
||||
{
|
||||
|
@ -127,7 +127,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private void VerifyG1OTWithinBounds(LegalityAnalysis data, string str)
|
||||
private void VerifyG1OTWithinBounds(LegalityAnalysis data, ReadOnlySpan<char> str)
|
||||
{
|
||||
if (StringConverter12.GetIsG1English(str))
|
||||
{
|
||||
|
@ -152,7 +152,12 @@ namespace PKHeX.Core
|
|||
|
||||
private static bool IsOTNameSuspicious(string name)
|
||||
{
|
||||
return SuspiciousOTNames.Any(name.StartsWith);
|
||||
foreach (var s in SuspiciousOTNames)
|
||||
{
|
||||
if (s.StartsWith(name, StringComparison.InvariantCultureIgnoreCase))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsOTIDSuspicious(int tid16, int sid16)
|
||||
|
@ -187,7 +192,13 @@ namespace PKHeX.Core
|
|||
return (uint)(c - '0') <= 9;
|
||||
}
|
||||
|
||||
return str.Count(IsNumber);
|
||||
int ctr = 0;
|
||||
foreach (var c in str)
|
||||
{
|
||||
if (IsNumber(c))
|
||||
++ctr;
|
||||
}
|
||||
return ctr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -331,7 +331,7 @@ namespace PKHeX.Core
|
|||
|
||||
public override int Met_Level { get => Data[0x84] >> 1; set => Data[0x84] = (byte)((Data[0x84] & 0x1) | value << 1); }
|
||||
public override int OT_Gender { get => Data[0x84] & 1; set => Data[0x84] = (byte)((Data[0x84] & ~0x1) | (value & 1)); }
|
||||
public override int EncounterType { get => Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
public override GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
// Unused 0x87
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace PKHeX.Core
|
|||
private static byte[] SetString(string value, int maxLength) => StringConverter3.SetBEString3(value, maxLength);
|
||||
|
||||
// Trash Bytes
|
||||
public override byte[] Nickname_Trash { get => GetData(0x2E, 20); set { if (value.Length == 20) value.CopyTo(Data, 0x2E); } }
|
||||
public override byte[] OT_Trash { get => GetData(0x18, 20); set { if (value.Length == 20) value.CopyTo(Data, 0x18); } }
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x2E, 20); set { if (value.Length == 20) value.CopyTo(Data.AsSpan(0x2E)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x18, 20); set { if (value.Length == 20) value.CopyTo(Data.AsSpan(0x18)); } }
|
||||
|
||||
// Future Attributes
|
||||
|
||||
|
|
|
@ -43,8 +43,8 @@ namespace PKHeX.Core
|
|||
private const string EggNameJapanese = "タマゴ";
|
||||
|
||||
// Trash Bytes
|
||||
public override byte[] Nickname_Trash { get => GetData(0x08, 10); set { if (value.Length == 10) value.CopyTo(Data, 0x08); } }
|
||||
public override byte[] OT_Trash { get => GetData(0x14, 7); set { if (value.Length == 7) value.CopyTo(Data, 0x14); } }
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x08, 10); set { if (value.Length == 10) value.CopyTo(Data.AsSpan(0x08)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x14, 7); set { if (value.Length == 7) value.CopyTo(Data.AsSpan(0x14)); } }
|
||||
|
||||
// At top for System.Reflection execution order hack
|
||||
|
||||
|
|
|
@ -310,8 +310,8 @@ namespace PKHeX.Core
|
|||
|
||||
public override int Met_Level { get => Data[0x84] & ~0x80; set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0x84] >> 7; set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | value << 7); }
|
||||
public override int EncounterType { get => Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
public int PokéathlonStat { get => Data[0x87]; set => Data[0x87] = (byte)value; }
|
||||
public override GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
public byte PokéathlonStat { get => Data[0x87]; set => Data[0x87] = value; }
|
||||
// Unused 0x87
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -4,7 +4,9 @@ using System.Collections.Generic;
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary> Generation 5 <see cref="PKM"/> format. </summary>
|
||||
public sealed class PK5 : PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IContestStats, IContestStatsMutable
|
||||
public sealed class PK5 : PKM,
|
||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4,
|
||||
IContestStats, IContestStatsMutable, IGroundTile
|
||||
{
|
||||
private static readonly ushort[] Unused =
|
||||
{
|
||||
|
@ -39,8 +41,8 @@ namespace PKHeX.Core
|
|||
private static byte[] SetString(string value, int maxLength) => StringConverter.SetString5(value, maxLength);
|
||||
|
||||
// Trash Bytes
|
||||
public override byte[] Nickname_Trash { get => GetData(0x48, 22); set { if (value.Length == 22) value.CopyTo(Data, 0x48); } }
|
||||
public override byte[] OT_Trash { get => GetData(0x68, 16); set { if (value.Length == 16) value.CopyTo(Data, 0x68); } }
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x48, 22); set { if (value.Length == 22) value.CopyTo(Data.AsSpan(0x48)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x68, 16); set { if (value.Length == 16) value.CopyTo(Data.AsSpan(0x68)); } }
|
||||
|
||||
// Future Attributes
|
||||
public override uint EncryptionConstant { get => PID; set { } }
|
||||
|
@ -242,7 +244,7 @@ namespace PKHeX.Core
|
|||
public override int Ball { get => Data[0x83]; set => Data[0x83] = (byte)value; }
|
||||
public override int Met_Level { get => Data[0x84] & ~0x80; set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0x84] >> 7; set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | value << 7); }
|
||||
public override int EncounterType { get => Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
public GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; }
|
||||
// 0x86 Unused
|
||||
public byte PokeStarFame { get => Data[0x87]; set => Data[0x87] = value; }
|
||||
public bool IsPokeStar { get => PokeStarFame > 250; set => PokeStarFame = value ? (byte)255 : (byte)0; }
|
||||
|
@ -394,7 +396,7 @@ namespace PKHeX.Core
|
|||
// OT Gender & Encounter Level
|
||||
Met_Level = Met_Level,
|
||||
OT_Gender = OT_Gender,
|
||||
EncounterType = EncounterType,
|
||||
GroundTile = GroundTile,
|
||||
|
||||
// Fill the Ribbon Counter Bytes
|
||||
RibbonCountMemoryContest = CountContestRibbons(),
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
/// <summary> Generation 6 <see cref="PKM"/> format. </summary>
|
||||
public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6,
|
||||
IContestStats, IContestStatsMutable, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection
|
||||
IContestStats, IContestStatsMutable, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection, IGroundTile
|
||||
{
|
||||
private static readonly ushort[] Unused =
|
||||
{
|
||||
|
@ -343,7 +343,7 @@ namespace PKHeX.Core
|
|||
public override int Ball { get => Data[0xDC]; set => Data[0xDC] = (byte)value; }
|
||||
public override int Met_Level { get => Data[0xDD] & ~0x80; set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0xDD] >> 7; set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); }
|
||||
public override int EncounterType { get => Data[0xDE]; set => Data[0xDE] = (byte)value; }
|
||||
public GroundTileType GroundTile { get => (GroundTileType)Data[0xDE]; set => Data[0xDE] = (byte)value; }
|
||||
public override int Version { get => Data[0xDF]; set => Data[0xDF] = (byte)value; }
|
||||
public int Country { get => Data[0xE0]; set => Data[0xE0] = (byte)value; }
|
||||
public int Region { get => Data[0xE1]; set => Data[0xE1] = (byte)value; }
|
||||
|
|
|
@ -66,9 +66,9 @@ namespace PKHeX.Core
|
|||
public override int SIZE_STORED => PokeCrypto.SIZE_8STORED;
|
||||
|
||||
// Trash Bytes
|
||||
public override byte[] Nickname_Trash { get => GetData(0x58, 24); set { if (value.Length == 24) value.CopyTo(Data, 0x58); } }
|
||||
public override byte[] HT_Trash { get => GetData(0xA8, 24); set { if (value.Length == 24) value.CopyTo(Data, 0xA8); } }
|
||||
public override byte[] OT_Trash { get => GetData(0xF8, 24); set { if (value.Length == 24) value.CopyTo(Data, 0xF8); } }
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x58, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x58)); } }
|
||||
public override Span<byte> HT_Trash { get => Data.AsSpan(0xA8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xA8)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0xF8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xF8)); } }
|
||||
|
||||
// Maximums
|
||||
public override int MaxIV => 31;
|
||||
|
|
|
@ -31,11 +31,9 @@ namespace PKHeX.Core
|
|||
public virtual bool Valid { get => ChecksumValid && Sanity == 0; set { if (!value) return; Sanity = 0; RefreshChecksum(); } }
|
||||
|
||||
// Trash Bytes
|
||||
public abstract byte[] Nickname_Trash { get; set; }
|
||||
public abstract byte[] OT_Trash { get; set; }
|
||||
public virtual byte[] HT_Trash { get => Array.Empty<byte>(); set { } }
|
||||
|
||||
protected byte[] GetData(int Offset, int Length) => Data.Slice(Offset, Length);
|
||||
public abstract Span<byte> Nickname_Trash { get; set; }
|
||||
public abstract Span<byte> OT_Trash { get; set; }
|
||||
public virtual Span<byte> HT_Trash { get => Span<byte>.Empty; set { } }
|
||||
|
||||
protected virtual ushort CalculateChecksum() => PokeCrypto.GetCHK(Data, SIZE_STORED);
|
||||
|
||||
|
@ -223,7 +221,6 @@ namespace PKHeX.Core
|
|||
public virtual int RelearnMove2 { get => 0; set { } }
|
||||
public virtual int RelearnMove3 { get => 0; set { } }
|
||||
public virtual int RelearnMove4 { get => 0; set { } }
|
||||
public virtual int EncounterType { get => 0; set { } }
|
||||
|
||||
// Exposed but not Present in all
|
||||
public abstract int CurrentHandler { get; set; }
|
||||
|
@ -293,7 +290,6 @@ namespace PKHeX.Core
|
|||
public bool LGPE => Version is (int)GP or (int)GE;
|
||||
public bool SWSH => Version is (int)SW or (int)SH;
|
||||
|
||||
protected internal bool PtHGSS => Pt || HGSS;
|
||||
public bool GO_LGPE => GO && Met_Location == Locations.GO7;
|
||||
public bool GO_HOME => GO && Met_Location == Locations.GO8;
|
||||
public bool VC => VC1 || VC2;
|
||||
|
|
|
@ -106,8 +106,8 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
public override byte[] Nickname_Trash { get => GetData(0x24, 12); set { if (value.Length == 12) value.CopyTo(Data, 0x24); } }
|
||||
public override byte[] OT_Trash { get => GetData(0x30, 12); set { if (value.Length == 12) value.CopyTo(Data, 0x30); } }
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x24, 12); set { if (value.Length == 12) value.CopyTo(Data.AsSpan(0x24)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x30, 12); set { if (value.Length == 12) value.CopyTo(Data.AsSpan(0x30)); } }
|
||||
#endregion
|
||||
|
||||
#region Party Attributes
|
||||
|
@ -186,24 +186,32 @@ namespace PKHeX.Core
|
|||
};
|
||||
}
|
||||
|
||||
private static bool IsJapanese(byte[] data)
|
||||
private static bool IsJapanese(ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (!StringConverter12.GetIsG1Japanese(data, 0x24, StringLength))
|
||||
if (!StringConverter12.GetIsG1Japanese(data.Slice(0x30, StringLength)))
|
||||
return false;
|
||||
if (!StringConverter12.GetIsG1Japanese(data, 0x30, StringLength))
|
||||
if (!StringConverter12.GetIsG1Japanese(data.Slice(0x24, StringLength)))
|
||||
return false;
|
||||
|
||||
for (int i = 6; i < 0xC; i++)
|
||||
{
|
||||
if (data[0x24 + i] is not (0 or StringConverter12.G1TerminatorCode))
|
||||
return false;
|
||||
if (data[0x30 + i] is not (0 or StringConverter12.G1TerminatorCode))
|
||||
return false;
|
||||
if (data[0x24 + i] is not (0 or StringConverter12.G1TerminatorCode))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsEnglish(byte[] data) => StringConverter12.GetIsG1English(data, 0x24, StringLength) && StringConverter12.GetIsG1English(data, 0x30, StringLength);
|
||||
private static bool IsEnglish(ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (!StringConverter12.GetIsG1English(data.Slice(0x30, StringLength)))
|
||||
return false;
|
||||
if (!StringConverter12.GetIsG1English(data.Slice(0x24, StringLength)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsPossible(bool japanese) => japanese ? IsJapanese(Data) : IsEnglish(Data);
|
||||
public void SwapLanguage() => IsEncodingJapanese ^= true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
namespace PKHeX.Core
|
||||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public abstract class G4PKM : PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IContestStats, IContestStatsMutable
|
||||
public abstract class G4PKM : PKM,
|
||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4,
|
||||
IContestStats, IContestStatsMutable, IGroundTile
|
||||
{
|
||||
protected G4PKM(byte[] data) : base(data) { }
|
||||
protected G4PKM(int size) : base(size) { }
|
||||
|
@ -20,6 +24,8 @@
|
|||
public sealed override int PSV => (int)((PID >> 16 ^ (PID & 0xFFFF)) >> 3);
|
||||
public sealed override int TSV => (TID ^ SID) >> 3;
|
||||
|
||||
protected bool PtHGSS => Pt || HGSS;
|
||||
|
||||
public sealed override int Characteristic
|
||||
{
|
||||
get
|
||||
|
@ -38,8 +44,8 @@
|
|||
}
|
||||
|
||||
// Trash Bytes
|
||||
public sealed override byte[] Nickname_Trash { get => GetData(0x48, 22); set { if (value.Length == 22) value.CopyTo(Data, 0x48); } }
|
||||
public sealed override byte[] OT_Trash { get => GetData(0x68, 16); set { if (value.Length == 16) value.CopyTo(Data, 0x68); } }
|
||||
public sealed override Span<byte> Nickname_Trash { get => Data.AsSpan(0x48, 22); set { if (value.Length == 22) value.CopyTo(Data.AsSpan(0x48)); } }
|
||||
public sealed override Span<byte> OT_Trash { get => Data.AsSpan(0x68, 16); set { if (value.Length == 16) value.CopyTo(Data.AsSpan(0x68)); } }
|
||||
|
||||
// Future Attributes
|
||||
public sealed override uint EncryptionConstant { get => PID; set { } }
|
||||
|
@ -158,6 +164,8 @@
|
|||
public abstract byte CNT_Tough { get; set; }
|
||||
public abstract byte CNT_Sheen { get; set; }
|
||||
|
||||
public abstract GroundTileType GroundTile { get; set; }
|
||||
|
||||
protected T ConvertTo<T>() where T : G4PKM, new()
|
||||
{
|
||||
var pk = new T
|
||||
|
@ -215,7 +223,7 @@
|
|||
PKRS_Days = PKRS_Days,
|
||||
PKRS_Strain = PKRS_Strain,
|
||||
Ball = Ball,
|
||||
EncounterType = EncounterType,
|
||||
GroundTile = GroundTile,
|
||||
FatefulEncounter = FatefulEncounter,
|
||||
|
||||
Met_Level = Met_Level,
|
||||
|
|
|
@ -11,9 +11,9 @@ namespace PKHeX.Core
|
|||
protected G6PKM(int size) : base(size) { }
|
||||
|
||||
// Trash Bytes
|
||||
public sealed override byte[] Nickname_Trash { get => GetData(0x40, 24); set { if (value.Length == 24) value.CopyTo(Data, 0x40); } }
|
||||
public sealed override byte[] HT_Trash { get => GetData(0x78, 24); set { if (value.Length == 24) value.CopyTo(Data, 0x78); } }
|
||||
public sealed override byte[] OT_Trash { get => GetData(0xB0, 24); set { if (value.Length == 24) value.CopyTo(Data, 0xB0); } }
|
||||
public sealed override Span<byte> Nickname_Trash { get => Data.AsSpan(0x40, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x40)); } }
|
||||
public sealed override Span<byte> HT_Trash { get => Data.AsSpan(0x78, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x78)); } }
|
||||
public sealed override Span<byte> OT_Trash { get => Data.AsSpan(0xB0, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xB0)); } }
|
||||
|
||||
protected sealed override ushort CalculateChecksum()
|
||||
{
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
|
|
@ -18,8 +18,8 @@ namespace PKHeX.Core
|
|||
internal readonly byte[] RawNickname;
|
||||
|
||||
// Trash Bytes
|
||||
public sealed override byte[] Nickname_Trash { get => RawNickname; set { if (value.Length == RawNickname.Length) value.CopyTo(RawNickname, 0); } }
|
||||
public sealed override byte[] OT_Trash { get => RawOT; set { if (value.Length == RawOT.Length) value.CopyTo(RawOT, 0); } }
|
||||
public sealed override Span<byte> Nickname_Trash { get => RawNickname; set { if (value.Length == RawNickname.Length) value.CopyTo(RawNickname); } }
|
||||
public sealed override Span<byte> OT_Trash { get => RawOT; set { if (value.Length == RawOT.Length) value.CopyTo(RawOT); } }
|
||||
|
||||
protected GBPKML(int size, bool jp = false) : base(size)
|
||||
{
|
||||
|
|
47
PKHeX.Core/PKM/Shared/GroundTileType.cs
Normal file
47
PKHeX.Core/PKM/Shared/GroundTileType.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Ground Tile Type the <see cref="PKM"/> was encountered from.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Used in Generation 4 games, this value is set depending on what type of overworld tile the player is standing on when the <see cref="PKM"/> is obtained.
|
||||
/// </remarks>
|
||||
public enum GroundTileType : byte
|
||||
{
|
||||
None = 00, // No animation for the tile
|
||||
Sand = 01, // Obtainable only via HG/SS
|
||||
Grass = 02,
|
||||
Puddle = 03, // No encounters from this tile type
|
||||
Rock = 04,
|
||||
Cave = 05,
|
||||
Snow = 06, // No encounters from this tile type
|
||||
Water = 07,
|
||||
Ice = 08, // No encounters from this tile type
|
||||
Building = 09,
|
||||
Marsh = 10,
|
||||
Bridge = 11, // No encounters from this tile type
|
||||
Max_DP = 12, // Unspecific, catch-all for DP undefined tiles.
|
||||
|
||||
// added tile types in Pt
|
||||
// no encounters from these tile types
|
||||
Elite4_1 = 12, // Elite Four Room #1
|
||||
Elite4_2 = 13, // Elite Four Room #2
|
||||
Elite4_3 = 14, // Elite Four Room #3
|
||||
Elite4_4 = 15, // Elite Four Room #4
|
||||
Elite4_M = 16, // Elite Four Champion Room
|
||||
DistortionSideways = 17, // Distortion World (Not Giratina)
|
||||
BattleTower = 18,
|
||||
BattleFactory = 19,
|
||||
BattleArcade = 20,
|
||||
BattleCastle = 21,
|
||||
BattleHall = 22,
|
||||
|
||||
Distortion = 23,
|
||||
Max_Pt = 24, // Unspecific, catch-all for Pt undefined tiles.
|
||||
}
|
||||
|
||||
public static class GroundTileTypeExtensions
|
||||
{
|
||||
public static bool IsObtainable(this GroundTileType type) => ((0b_1_10000000_00010110_10110111 >> (int) type) & 1) == 1;
|
||||
}
|
||||
}
|
13
PKHeX.Core/PKM/Shared/IGroundTile.cs
Normal file
13
PKHeX.Core/PKM/Shared/IGroundTile.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the Type of Encounter Tile the Pokémon was encountered on.
|
||||
/// </summary>
|
||||
public interface IGroundTile
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of Encounter Tile the Pokémon was encountered on.
|
||||
/// </summary>
|
||||
GroundTileType GroundTile { get; set; }
|
||||
}
|
||||
}
|
|
@ -149,9 +149,11 @@ namespace PKHeX.Core
|
|||
int pkOfs = GetOffsetPKMData(base_ofs, i);
|
||||
int otOfs = GetOffsetPKMOT(base_ofs, i);
|
||||
int nkOfs = GetOffsetPKMNickname(base_ofs, i);
|
||||
Array.Copy(Pokemon[i].Data, 0, Data, pkOfs, Entry_Size);
|
||||
Array.Copy(Pokemon[i].OT_Trash, 0, Data, otOfs, StringLength);
|
||||
Array.Copy(Pokemon[i].Nickname_Trash, 0, Data, nkOfs, StringLength);
|
||||
|
||||
var pk = Pokemon[i];
|
||||
Array.Copy(pk.Data, 0, Data, pkOfs, Entry_Size);
|
||||
pk.RawOT.CopyTo(Data, otOfs);
|
||||
pk.RawNickname.CopyTo(Data, nkOfs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PKHeX.Core
|
||||
|
@ -10,18 +9,25 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
public static class StringConverter12
|
||||
{
|
||||
public static bool GetIsG1Japanese(string str) => AllCharsInDictionary(str, U2RBY_J);
|
||||
public static bool GetIsG1English(string str) => AllCharsInDictionary(str, U2RBY_U);
|
||||
public static bool GetIsG1Japanese(byte[] data, int start, int length) => AllCharsInDictionary(data, start, length, RBY2U_J);
|
||||
public static bool GetIsG1English(byte[] data, int start, int length) => AllCharsInDictionary(data, start, length, RBY2U_U);
|
||||
public static bool GetIsG1Japanese(ReadOnlySpan<char> str) => AllCharsInDictionary(str, U2RBY_J);
|
||||
public static bool GetIsG1English(ReadOnlySpan<char> str) => AllCharsInDictionary(str, U2RBY_U);
|
||||
public static bool GetIsG1Japanese(ReadOnlySpan<byte> raw) => AllCharsInDictionary(raw, RBY2U_J);
|
||||
public static bool GetIsG1English(ReadOnlySpan<byte> raw) => AllCharsInDictionary(raw, RBY2U_U);
|
||||
|
||||
private static bool AllCharsInDictionary(IEnumerable<char> c, IReadOnlyDictionary<char, byte> d) => c.All(d.ContainsKey);
|
||||
|
||||
private static bool AllCharsInDictionary(IReadOnlyList<byte> data, int start, int length, IReadOnlyDictionary<byte, char> d)
|
||||
private static bool AllCharsInDictionary(ReadOnlySpan<char> c, IReadOnlyDictionary<char, byte> d)
|
||||
{
|
||||
for (int i = start; i < start + length; i++)
|
||||
foreach (var x in c)
|
||||
{
|
||||
if (!d.ContainsKey(x))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool AllCharsInDictionary(ReadOnlySpan<byte> data, IReadOnlyDictionary<byte, char> d)
|
||||
{
|
||||
foreach (var c in data)
|
||||
{
|
||||
var c = data[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
if (!d.ContainsKey(c))
|
||||
|
@ -54,7 +60,15 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
/// <param name="data">Raw string bytes</param>
|
||||
/// <returns>Indication if the data is from a definitely-german string</returns>
|
||||
public static bool IsG12German(IEnumerable<byte> data) => data.Any(z => z is >= 0xC0 and <= 0xC6);
|
||||
public static bool IsG12German(ReadOnlySpan<byte> data)
|
||||
{
|
||||
foreach (var b in data)
|
||||
{
|
||||
if (b is >= 0xC0 and <= 0xC6)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the input byte array is definitely of German origin (any ÄÖÜäöü)
|
||||
|
@ -71,14 +85,21 @@ namespace PKHeX.Core
|
|||
/// <param name="count"></param>
|
||||
/// <param name="jp">Data source is Japanese.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString1(byte[] data, int offset, int count, bool jp)
|
||||
public static string GetString1(byte[] data, int offset, int count, bool jp) => GetString1(data.AsSpan(offset, count), jp);
|
||||
|
||||
/// <summary>
|
||||
/// Converts Generation 1 encoded data into a string.
|
||||
/// </summary>
|
||||
/// <param name="data">Encoded data.</param>
|
||||
/// <param name="jp">Data source is Japanese.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString1(ReadOnlySpan<byte> data, bool jp)
|
||||
{
|
||||
var dict = jp ? RBY2U_J : RBY2U_U;
|
||||
|
||||
var s = new StringBuilder(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
var s = new StringBuilder(data.Length);
|
||||
foreach (var val in data)
|
||||
{
|
||||
var val = data[offset + i];
|
||||
if (!dict.TryGetValue(val, out var c)) // Take valid values
|
||||
break;
|
||||
if (c == G1Terminator) // Stop if Terminator
|
||||
|
@ -127,12 +148,12 @@ namespace PKHeX.Core
|
|||
/// <param name="key">Encoded character.</param>
|
||||
/// <param name="jp">Data source is Japanese.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetG1Char(byte key, bool jp)
|
||||
public static char GetG1Char(byte key, bool jp)
|
||||
{
|
||||
var dict = jp ? RBY2U_J : RBY2U_U;
|
||||
if (dict.TryGetValue(key, out var val))
|
||||
return val.ToString();
|
||||
return string.Empty;
|
||||
return val;
|
||||
return G1Terminator;
|
||||
}
|
||||
|
||||
#region Gen 1/2 Character Tables
|
||||
|
|
|
@ -15,7 +15,16 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Checks if any of the characters inside <see cref="str"/> are from the special Korean codepoint pages.
|
||||
/// </summary>
|
||||
public static bool GetIsG2Korean(string str) => str.All(z => U2GSC_KOR.Any(x => x.ContainsKey(z)));
|
||||
public static bool GetIsG2Korean(ReadOnlySpan<char> str)
|
||||
{
|
||||
var dict = U2GSC_KOR;
|
||||
foreach (var c in str)
|
||||
{
|
||||
if (!dict.Any(d => d.ContainsKey(c)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Generation 2 Korean encoded data into a string.
|
||||
|
|
|
@ -20,12 +20,19 @@ namespace PKHeX.Core
|
|||
/// <param name="count">Length of data to read.</param>
|
||||
/// <param name="jp">Value source is Japanese font.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString3(byte[] data, int offset, int count, bool jp)
|
||||
public static string GetString3(byte[] data, int offset, int count, bool jp) => GetString3(data.AsSpan(offset, count), jp);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Generation 3 encoded value array to string.
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array containing string data.</param>
|
||||
/// <param name="jp">Value source is Japanese font.</param>
|
||||
/// <returns>Decoded string.</returns>
|
||||
public static string GetString3(ReadOnlySpan<byte> data, bool jp)
|
||||
{
|
||||
var s = new StringBuilder(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
var s = new StringBuilder(data.Length);
|
||||
foreach (var val in data)
|
||||
{
|
||||
var val = data[offset + i];
|
||||
var c = GetG3Char(val, jp); // Convert to Unicode
|
||||
if (c == Terminator) // Stop if Terminator/Invalid
|
||||
break;
|
||||
|
|
|
@ -160,7 +160,8 @@ namespace PKHeX.Core
|
|||
if (pk.HeldItem > Legal.MaxItemID_6_AO)
|
||||
return true;
|
||||
|
||||
int et = pk.EncounterType;
|
||||
// Ground Tile property is replaced with Hyper Training PK6->PK7
|
||||
var et = pk.GroundTile;
|
||||
if (et != 0)
|
||||
{
|
||||
if (pk.CurrentLevel < 100) // can't be hyper trained
|
||||
|
@ -168,7 +169,7 @@ namespace PKHeX.Core
|
|||
|
||||
if (!pk.Gen4) // can't have encounter type
|
||||
return true;
|
||||
if (et > 24) // invalid gen4 EncounterType
|
||||
if (et > GroundTileType.Max_Pt) // invalid gen4 EncounterType
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace PKHeX.Core
|
|||
private static byte[] SetString(string value, int maxLength) => StringConverter3.SetBEString3(value, maxLength);
|
||||
|
||||
// Trash Bytes
|
||||
public override byte[] Nickname_Trash { get => GetData(0x4E, 20); set { if (value.Length == 20) value.CopyTo(Data, 0x4E); } }
|
||||
public override byte[] OT_Trash { get => GetData(0x38, 20); set { if (value.Length == 20) value.CopyTo(Data, 0x38); } }
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x4E, 20); set { if (value.Length == 20) value.CopyTo(Data.AsSpan(0x4E)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0x38, 20); set { if (value.Length == 20) value.CopyTo(Data.AsSpan(0x38)); } }
|
||||
|
||||
// Silly Attributes
|
||||
public override ushort Sanity { get => 0; set { } } // valid flag set in pkm structure.
|
||||
|
|
|
@ -240,7 +240,7 @@ namespace PKHeX.Core
|
|||
set => SetString(value, OTLength).CopyTo(Data, Offsets.OT);
|
||||
}
|
||||
|
||||
public byte[] OT_Trash { get => GetData(Offsets.OT, StringLength); set { if (value.Length == StringLength) SetData(value, Offsets.OT); } }
|
||||
public Span<byte> OT_Trash { get => Data.AsSpan(Offsets.OT, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.OT)); } }
|
||||
|
||||
public override int Gender
|
||||
{
|
||||
|
|
|
@ -321,10 +321,10 @@ namespace PKHeX.Core
|
|||
set => SetString(value, (Korean ? 2 : 1) * OTLength).CopyTo(Data, Offsets.Trainer1 + 2);
|
||||
}
|
||||
|
||||
public byte[] OT_Trash
|
||||
{
|
||||
get => GetData(Offsets.Trainer1 + 2, StringLength);
|
||||
set { if (value.Length == StringLength) SetData(value, Offsets.Trainer1 + 2); }
|
||||
public Span<byte> OT_Trash
|
||||
{
|
||||
get => Data.AsSpan(Offsets.Trainer1 + 2, StringLength);
|
||||
set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.Trainer1 + 2)); }
|
||||
}
|
||||
|
||||
public override int Gender
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace PKHeX.WinForms.Controls
|
|||
LoadMisc3(pk4);
|
||||
LoadMisc4(pk4);
|
||||
|
||||
CB_EncounterType.SelectedValue = pk4.Gen4 ? pk4.EncounterType : 0;
|
||||
CB_EncounterType.SelectedValue = pk4.Gen4 ? (int)pk4.GroundTile : 0;
|
||||
CB_EncounterType.Visible = Label_EncounterType.Visible = Entity.Gen4;
|
||||
|
||||
if (HaX)
|
||||
|
@ -40,7 +40,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SaveMisc3(pk4);
|
||||
SaveMisc4(pk4);
|
||||
|
||||
pk4.EncounterType = WinFormsUtil.GetIndex(CB_EncounterType);
|
||||
pk4.GroundTile = (GroundTileType)WinFormsUtil.GetIndex(CB_EncounterType);
|
||||
|
||||
// Minor properties
|
||||
pk4.ShinyLeaf = ShinyLeaf.GetValue();
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace PKHeX.WinForms.Controls
|
|||
LoadMisc2(pk5);
|
||||
LoadMisc3(pk5);
|
||||
LoadMisc4(pk5);
|
||||
CB_EncounterType.SelectedValue = pk5.Gen4 ? pk5.EncounterType : 0;
|
||||
CB_EncounterType.SelectedValue = pk5.Gen4 ? (int)pk5.GroundTile : 0;
|
||||
CB_EncounterType.Visible = Label_EncounterType.Visible = pk5.Gen4;
|
||||
CHK_NSparkle.Checked = pk5.NPokémon;
|
||||
|
||||
|
@ -39,7 +39,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SaveMisc3(pk5);
|
||||
SaveMisc4(pk5);
|
||||
|
||||
pk5.EncounterType = WinFormsUtil.GetIndex(CB_EncounterType);
|
||||
pk5.GroundTile = (GroundTileType)WinFormsUtil.GetIndex(CB_EncounterType);
|
||||
pk5.NPokémon = CHK_NSparkle.Checked;
|
||||
if (!HaX) // specify via extra 0x42 instead
|
||||
pk5.HiddenAbility = CB_Ability.SelectedIndex > 1; // not 0 or 1
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace PKHeX.WinForms.Controls
|
|||
LoadMisc4(pk6);
|
||||
LoadMisc6(pk6);
|
||||
|
||||
CB_EncounterType.SelectedValue = pk6.Gen4 ? pk6.EncounterType : 0;
|
||||
CB_EncounterType.SelectedValue = pk6.Gen4 ? (int)pk6.GroundTile : 0;
|
||||
CB_EncounterType.Visible = Label_EncounterType.Visible = pk6.Gen4;
|
||||
|
||||
LoadPartyStats(pk6);
|
||||
|
@ -35,7 +35,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SaveMisc6(pk6);
|
||||
CheckTransferPIDValid(pk6);
|
||||
|
||||
pk6.EncounterType = WinFormsUtil.GetIndex(CB_EncounterType);
|
||||
pk6.GroundTile = (GroundTileType)WinFormsUtil.GetIndex(CB_EncounterType);
|
||||
|
||||
// Toss in Party Stats
|
||||
SavePartyStats(pk6);
|
||||
|
|
|
@ -798,7 +798,7 @@ namespace PKHeX.WinForms.Controls
|
|||
|
||||
if (Entity.CurrentLevel >= minlvl && Entity.Met_Level == level && Entity.Met_Location == location)
|
||||
{
|
||||
if (!encounter.HasEncounterType(Entity.Format) || WinFormsUtil.GetIndex(CB_EncounterType) == encounter.GetSuggestedEncounterType())
|
||||
if (!encounter.HasGroundTile(Entity.Format) || WinFormsUtil.GetIndex(CB_EncounterType) == (int)encounter.GetSuggestedGroundTile())
|
||||
return false;
|
||||
}
|
||||
if (minlvl < level)
|
||||
|
@ -821,8 +821,8 @@ namespace PKHeX.WinForms.Controls
|
|||
TB_MetLevel.Text = encounter.GetSuggestedMetLevel(Entity).ToString();
|
||||
CB_MetLocation.SelectedValue = location;
|
||||
|
||||
if (encounter.HasEncounterType(Entity.Format))
|
||||
CB_EncounterType.SelectedValue = encounter.GetSuggestedEncounterType();
|
||||
if (encounter.HasGroundTile(Entity.Format))
|
||||
CB_EncounterType.SelectedValue = (int)encounter.GetSuggestedGroundTile();
|
||||
|
||||
if (Entity.Gen6 && Entity.WasEgg && ModifyPKM)
|
||||
Entity.SetHatchMemory6();
|
||||
|
@ -1200,7 +1200,7 @@ namespace PKHeX.WinForms.Controls
|
|||
}
|
||||
|
||||
// Visibility logic for Gen 4 encounter type; only show for Gen 4 Pokemon.
|
||||
if (Entity.Format >= 4)
|
||||
if (Entity is IGroundTile)
|
||||
{
|
||||
bool g4 = Entity.Gen4;
|
||||
CB_EncounterType.Visible = Label_EncounterType.Visible = g4 && Entity.Format < 7;
|
||||
|
|
|
@ -12,14 +12,14 @@ namespace PKHeX.WinForms
|
|||
|
||||
public TrashEditor(TextBoxBase TB_NN, SaveFile sav) : this(TB_NN, Array.Empty<byte>(), sav) { }
|
||||
|
||||
public TrashEditor(TextBoxBase TB_NN, byte[] raw, SaveFile sav)
|
||||
public TrashEditor(TextBoxBase TB_NN, Span<byte> raw, SaveFile sav)
|
||||
{
|
||||
InitializeComponent();
|
||||
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
|
||||
SAV = sav;
|
||||
|
||||
FinalString = TB_NN.Text;
|
||||
Raw = FinalBytes = raw;
|
||||
Raw = FinalBytes = raw.ToArray();
|
||||
|
||||
editing = true;
|
||||
if (raw.Length != 0)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using PKHeX.Core;
|
||||
using Xunit;
|
||||
|
@ -49,14 +49,22 @@ namespace PKHeX.Tests.PKM
|
|||
CheckStringGetSet(nameof(pkm.Nickname), name_nidoran, pkm.Nickname, byte_nidoran, pkm.Nickname_Trash);
|
||||
}
|
||||
|
||||
private static void CheckStringGetSet(string check, string instr, string outstr, byte[] indata, byte[] outdata)
|
||||
private static void CheckStringGetSet(string check, string instr, string outstr, ReadOnlySpan<byte> indata, ReadOnlySpan<byte> outdata)
|
||||
{
|
||||
instr.Should().BeEquivalentTo(outstr);
|
||||
|
||||
outdata = outdata[..indata.Length];
|
||||
|
||||
indata.SequenceEqual(outdata).Should()
|
||||
.BeTrue($"expected {check} to set properly, instead got {string.Join(", ", outdata.Select(z => $"{z:X2}"))}");
|
||||
.BeTrue($"expected {check} to set properly, instead got {Hex(outdata)}");
|
||||
}
|
||||
|
||||
private static string Hex(ReadOnlySpan<byte> outdata)
|
||||
{
|
||||
var sb = new System.Text.StringBuilder(outdata.Length);
|
||||
foreach (var b in outdata)
|
||||
sb.AppendFormat("{0:X2}, ", b);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
Loading…
Reference in a new issue