SlotNumber/MagnetStatic int->byte

more size reductions
This commit is contained in:
Kurt 2022-03-06 22:47:03 -08:00
parent ba9d3c95af
commit 462ef70ffb
14 changed files with 100 additions and 114 deletions

View File

@ -29,26 +29,22 @@ private EncounterArea1(ReadOnlySpan<byte> data, GameVersion game) : base(game)
Type = (SlotType)data[2];
Rate = data[3];
int count = (data.Length - 4) / 4;
var next = data[4..];
int count = next.Length / 4;
var slots = new EncounterSlot1[count];
for (int i = 0; i < slots.Length; i++)
{
int offset = 4 + (4 * i);
var entry = data.Slice(offset, 4);
slots[i] = ReadSlot(entry);
const int size = 4;
var entry = data.Slice(i * size, size);
int max = entry[3];
int min = entry[2];
byte slotNum = entry[1];
int species = entry[0];
slots[i] = new EncounterSlot1(this, species, min, max, slotNum);
}
Slots = slots;
}
private EncounterSlot1 ReadSlot(ReadOnlySpan<byte> entry)
{
int species = entry[0];
int slotNum = entry[1];
int min = entry[2];
int max = entry[3];
return new EncounterSlot1(this, species, min, max, slotNum);
}
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
{
int rate = pkm is PK1 pk1 ? pk1.Catch_Rate : -1;

View File

@ -14,7 +14,7 @@ public sealed record EncounterArea2 : EncounterArea
private static readonly byte[] RatesSurf = { 60, 30, 10 };
internal readonly EncounterTime Time;
public readonly int Rate;
public readonly byte Rate;
public readonly IReadOnlyList<byte> Rates;
public readonly EncounterSlot2[] Slots;
@ -33,61 +33,49 @@ private EncounterArea2(ReadOnlySpan<byte> data, GameVersion game) : base(game)
Location = data[0];
Time = (EncounterTime)data[1];
var type = (Type = (SlotType)data[2]) & (SlotType)0xF;
var rate = data[3];
Rate = data[3];
var next = data[4..];
if (type is > SlotType.Surf and not SlotType.BugContest) // Not Grass/Surf
{
const int size = 5;
int count = (data.Length - 4) / size;
var rates = new byte[count];
for (int i = 0; i < rates.Length; i++)
rates[i] = data[4 + i];
Rates = rates;
Slots = ReadSlots(data, count, 4 + count);
int count = next.Length / size;
Rates = next[..count].ToArray();
Slots = ReadSlots(next[count..], count);
}
else
{
Rate = rate;
const int size = 4;
int count = (data.Length - 4) / size;
int count = next.Length / size;
Rates = type switch
{
SlotType.BugContest => BCC_SlotRates,
SlotType.Grass => RatesGrass,
_ => RatesSurf,
};
Slots = ReadSlots(data, count, 4);
Slots = ReadSlots(next, count);
}
}
private EncounterSlot2[] ReadSlots(ReadOnlySpan<byte> data, int count, int start)
private EncounterSlot2[] ReadSlots(ReadOnlySpan<byte> data, int count)
{
const int size = 4;
var slots = new EncounterSlot2[count];
for (int i = 0; i < slots.Length; i++)
{
int offset = start + (4 * i);
var entry = data.Slice(offset, 4);
slots[i] = ReadSlot(entry);
var entry = data.Slice(i * size, size);
int max = entry[3];
int min = entry[2];
byte slotNum = entry[1];
int species = entry[0];
slots[i] = new EncounterSlot2(this, species, min, max, slotNum);
}
return slots;
}
private EncounterSlot2 ReadSlot(ReadOnlySpan<byte> entry)
{
int species = entry[0];
int slotNum = entry[1];
int min = entry[2];
int max = entry[3];
return new EncounterSlot2(this, species, min, max, slotNum);
}
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
{
if (pkm is not ICaughtData2 pk2 || pk2.CaughtData == 0)
if (pkm is not ICaughtData2 {CaughtData: not 0} pk2)
return GetSlotsFuzzy(chain);
if (pk2.Met_Location != Location)

View File

@ -68,14 +68,14 @@ private EncounterSlot3 ReadRegularSlot(ReadOnlySpan<byte> entry)
{
int species = ReadUInt16LittleEndian(entry);
int form = entry[2];
int slotNum = entry[3];
byte slotNum = entry[3];
int min = entry[4];
int max = entry[5];
int mpi = entry[6];
int mpc = entry[7];
int sti = entry[8];
int stc = entry[9];
byte mpi = entry[6];
byte mpc = entry[7];
byte sti = entry[8];
byte stc = entry[9];
return new EncounterSlot3(this, species, form, min, max, slotNum, mpi, mpc, sti, stc);
}
@ -98,7 +98,7 @@ private EncounterSlot3Swarm ReadSwarmSlot(ReadOnlySpan<byte> entry)
{
int species = ReadUInt16LittleEndian(entry);
// form always 0
int slotNum = entry[3];
byte slotNum = entry[3];
int min = entry[4];
int max = entry[5];

View File

@ -54,13 +54,13 @@ private EncounterSlot4 ReadRegularSlot(ReadOnlySpan<byte> entry)
{
int species = ReadUInt16LittleEndian(entry);
int form = entry[2];
int slotNum = entry[3];
byte slotNum = entry[3];
int min = entry[4];
int max = entry[5];
int mpi = entry[6];
int mpc = entry[7];
int sti = entry[8];
int stc = entry[9];
byte mpi = entry[6];
byte mpc = entry[7];
byte sti = entry[8];
byte stc = entry[9];
return new EncounterSlot4(this, species, form, min, max, slotNum, mpi, mpc, sti, stc);
}

View File

@ -7,10 +7,10 @@
public sealed record EncounterSlot1 : EncounterSlot, INumberedSlot
{
public override int Generation => 1;
public int SlotNumber { get; }
public byte SlotNumber { get; }
public override Ball FixedBall => Ball.Poke;
public EncounterSlot1(EncounterArea1 area, int species, int min, int max, int slot) : base(area, species, 0, min, max)
public EncounterSlot1(EncounterArea1 area, int species, int min, int max, byte slot) : base(area, species, 0, min, max)
{
SlotNumber = slot;
}

View File

@ -12,10 +12,10 @@ namespace PKHeX.Core
public sealed record EncounterSlot2 : EncounterSlot, INumberedSlot
{
public override int Generation => 2;
public int SlotNumber { get; }
public byte SlotNumber { get; }
public override Ball FixedBall => Ball.Poke;
public EncounterSlot2(EncounterArea2 area, int species, int min, int max, int slot) : base(area, species, species == 201 ? FormRandom : 0, min, max)
public EncounterSlot2(EncounterArea2 area, int species, int min, int max, byte slot) : base(area, species, species == 201 ? FormRandom : 0, min, max)
{
SlotNumber = slot;
}

View File

@ -8,16 +8,16 @@ public record EncounterSlot3 : EncounterSlot, IMagnetStatic, INumberedSlot, ISlo
{
public sealed override int Generation => 3;
public int StaticIndex { get; }
public int MagnetPullIndex { get; }
public int StaticCount { get; }
public int MagnetPullCount { get; }
public byte StaticIndex { get; }
public byte MagnetPullIndex { get; }
public byte StaticCount { get; }
public byte MagnetPullCount { get; }
public SlotType Type => Area.Type;
public int SlotNumber { get; }
public byte SlotNumber { get; }
public override Ball FixedBall => Locations.IsSafariZoneLocation3(Location) ? Ball.Safari : Ball.None;
public EncounterSlot3(EncounterArea3 area, int species, int form, int min, int max, int slot, int mpi, int mpc, int sti, int stc) : base(area, species, form, min, max)
public EncounterSlot3(EncounterArea3 area, int species, int form, int min, int max, byte slot, byte mpi, byte mpc, byte sti, byte stc) : base(area, species, form, min, max)
{
SlotNumber = slot;

View File

@ -8,9 +8,9 @@ public sealed record EncounterSlot3PokeSpot : EncounterSlot, INumberedSlot
{
public override int Generation => 3;
public int SlotNumber { get; }
public byte SlotNumber { get; }
public EncounterSlot3PokeSpot(EncounterArea3XD area, int species, int min, int max, int slot) : base(area, species, 0, min, max)
public EncounterSlot3PokeSpot(EncounterArea3XD area, int species, int min, int max, byte slot) : base(area, species, 0, min, max)
{
SlotNumber = slot;
}

View File

@ -13,7 +13,7 @@ internal sealed record EncounterSlot3Swarm : EncounterSlot3, IMoveset
{
public IReadOnlyList<int> Moves { get; }
public EncounterSlot3Swarm(EncounterArea3 area, int species, int min, int max, int slot,
public EncounterSlot3Swarm(EncounterArea3 area, int species, int min, int max, byte slot,
IReadOnlyList<int> moves) : base(area, species, 0, min, max, slot, 0, 0, 0, 0) => Moves = moves;
protected override void SetEncounterMoves(PKM pk, GameVersion version, int level)

View File

@ -9,17 +9,17 @@ public sealed record EncounterSlot4 : EncounterSlot, IMagnetStatic, INumberedSlo
public override int Generation => 4;
public GroundTilePermission GroundTile => ((EncounterArea4)Area).GroundTile;
public int StaticIndex { get; }
public int MagnetPullIndex { get; }
public int StaticCount { get; }
public int MagnetPullCount { get; }
public byte StaticIndex { get; }
public byte MagnetPullIndex { get; }
public byte StaticCount { get; }
public byte MagnetPullCount { get; }
public SlotType Type => Area.Type;
public int SlotNumber { get; }
public byte SlotNumber { get; }
public override Ball FixedBall => GetRequiredBallValue();
public bool CanUseRadar => !GameVersion.HGSS.Contains(Version) && GroundTile.HasFlag(GroundTilePermission.Grass);
public EncounterSlot4(EncounterArea4 area, int species, int form, int min, int max, int slot, int mpi, int mpc, int sti, int stc) : base(area, species, form, min, max)
public EncounterSlot4(EncounterArea4 area, int species, int form, int min, int max, byte slot, byte mpi, byte mpc, byte sti, byte stc) : base(area, species, form, min, max)
{
SlotNumber = slot;

View File

@ -1,29 +1,32 @@
namespace PKHeX.Core
namespace PKHeX.Core;
/// <summary>
/// Contains information about the RNG restrictions for the slot, and any mutated RNG values.
/// </summary>
/// <remarks>
/// When encountering a Wild Pokémon with a lead that has an ability of <see cref="Ability.Static"/> or <see cref="Ability.MagnetPull"/>,
/// the game picks encounters from the <seealso cref="EncounterArea"/> that match the type.
/// The values in this interface change the <seealso cref="INumberedSlot"/> to allow different values for slot yielding.
/// </remarks>
public interface IMagnetStatic
{
/// <summary>
/// Contains information about the RNG restrictions for the slot, and any mutated RNG values.
/// </summary>
/// <remarks>
/// When encountering a Wild Pokémon with a lead that has an ability of <see cref="Ability.Static"/> or <see cref="Ability.MagnetPull"/>,
/// the game picks encounters from the <seealso cref="EncounterArea"/> that match the type.
/// The values in this interface change the <seealso cref="INumberedSlot"/> to allow different values for slot yielding.
/// </remarks>
public interface IMagnetStatic
{
/// <summary> <see cref="INumberedSlot.SlotNumber"/> if the lead is <see cref="Ability.Static"/> </summary>
int StaticIndex { get; }
/// <summary> <see cref="INumberedSlot.SlotNumber"/> if the lead is <see cref="Ability.MagnetPull"/> </summary>
int MagnetPullIndex { get; }
/// <summary> <see cref="INumberedSlot.SlotNumber"/> if the lead is <see cref="Ability.Static"/> </summary>
byte StaticIndex { get; }
/// <summary> <see cref="INumberedSlot.SlotNumber"/> if the lead is <see cref="Ability.MagnetPull"/> </summary>
byte MagnetPullIndex { get; }
/// <summary> Count of slots in the parent area that can be yielded by <see cref="Ability.Static"/> </summary>
int StaticCount { get; }
/// <summary> Count of slots in the parent area that can be yielded by <see cref="Ability.MagnetPull"/> </summary>
int MagnetPullCount { get; }
}
public static class MagnetStaticExtensions
{
public static bool IsMatchStatic(this IMagnetStatic slot, int index, int count) => index == slot.StaticIndex && count == slot.StaticCount;
public static bool IsMatchMagnet(this IMagnetStatic slot, int index, int count) => index == slot.MagnetPullIndex && count == slot.MagnetPullCount;
}
/// <summary> Count of slots in the parent area that can be yielded by <see cref="Ability.Static"/> </summary>
byte StaticCount { get; }
/// <summary> Count of slots in the parent area that can be yielded by <see cref="Ability.MagnetPull"/> </summary>
byte MagnetPullCount { get; }
}
public static class MagnetStaticExtensions
{
private const byte NotMagnetStaticSlot = byte.MaxValue;
public static bool IsStaticSlot(this IMagnetStatic slot) => slot.StaticCount != 0 && slot.StaticIndex != NotMagnetStaticSlot;
public static bool IsMagnetSlot(this IMagnetStatic slot) => slot.MagnetPullCount != 0 && slot.MagnetPullIndex != NotMagnetStaticSlot;
public static bool IsMatchStatic(this IMagnetStatic slot, int index, int count) => index == slot.StaticIndex && count == slot.StaticCount;
public static bool IsMatchMagnet(this IMagnetStatic slot, int index, int count) => index == slot.MagnetPullIndex && count == slot.MagnetPullCount;
}

View File

@ -1,16 +1,15 @@
namespace PKHeX.Core
namespace PKHeX.Core;
/// <summary>
/// <seealso cref="EncounterSlot"/> that contains information about what Index it is within the <seealso cref="EncounterArea"/>'s type-group of slots.
/// </summary>
/// <remarks>
/// Useful for checking legality (if the RNG can yield this slot).
/// </remarks>
public interface INumberedSlot
{
/// <summary>
/// <seealso cref="EncounterSlot"/> that contains information about what Index it is within the <seealso cref="EncounterArea"/>'s type-group of slots.
/// Number Index of the <seealso cref="EncounterSlot"/>.
/// </summary>
/// <remarks>
/// Useful for checking legality (if the RNG can yield this slot).
/// </remarks>
public interface INumberedSlot
{
/// <summary>
/// Number Index of the <seealso cref="EncounterSlot"/>.
/// </summary>
int SlotNumber { get; }
}
byte SlotNumber { get; }
}

View File

@ -6,7 +6,7 @@ namespace PKHeX.Core
/// Generation 2 Time of Encounter enum
/// </summary>
[Flags]
internal enum EncounterTime
internal enum EncounterTime : byte
{
Any = 0,
Morning = 1 << 1,
@ -29,4 +29,4 @@ internal static int RandomValidTime(this EncounterTime t1)
return val;
}
}
}
}

View File

@ -168,13 +168,13 @@ public static int GetLevel(EncounterSlot slot, LeadRequired lead, uint lvlrand)
/// <returns>Slot number from the slot data if the slot is selected on this frame, else an invalid slot value.</returns>
internal static int GetSlotStaticMagnet<T>(T slot, uint esv) where T : EncounterSlot, IMagnetStatic, INumberedSlot
{
if (slot.StaticCount > 0 && slot.StaticIndex >= 0)
if (slot.IsStaticSlot())
{
var index = esv % slot.StaticCount;
if (index == slot.StaticIndex)
return slot.SlotNumber;
}
if (slot.MagnetPullCount > 0 && slot.MagnetPullIndex >= 0)
if (slot.IsMagnetSlot())
{
var index = esv % slot.MagnetPullCount;
if (index == slot.MagnetPullIndex)