diff --git a/PKHeX.Core/Legality/Areas/EncounterArea1.cs b/PKHeX.Core/Legality/Areas/EncounterArea1.cs index b789ca0f9..a4ade4386 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea1.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea1.cs @@ -29,26 +29,22 @@ private EncounterArea1(ReadOnlySpan 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 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 GetMatchingSlots(PKM pkm, IReadOnlyList chain) { int rate = pkm is PK1 pk1 ? pk1.Catch_Rate : -1; diff --git a/PKHeX.Core/Legality/Areas/EncounterArea2.cs b/PKHeX.Core/Legality/Areas/EncounterArea2.cs index 0a70c4e0f..ad716ceba 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea2.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea2.cs @@ -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 Rates; public readonly EncounterSlot2[] Slots; @@ -33,61 +33,49 @@ private EncounterArea2(ReadOnlySpan 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 data, int count, int start) + private EncounterSlot2[] ReadSlots(ReadOnlySpan 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 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 GetMatchingSlots(PKM pkm, IReadOnlyList 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) diff --git a/PKHeX.Core/Legality/Areas/EncounterArea3.cs b/PKHeX.Core/Legality/Areas/EncounterArea3.cs index 55b6e01cb..68a40456d 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea3.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea3.cs @@ -68,14 +68,14 @@ private EncounterSlot3 ReadRegularSlot(ReadOnlySpan 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 entry) { int species = ReadUInt16LittleEndian(entry); // form always 0 - int slotNum = entry[3]; + byte slotNum = entry[3]; int min = entry[4]; int max = entry[5]; diff --git a/PKHeX.Core/Legality/Areas/EncounterArea4.cs b/PKHeX.Core/Legality/Areas/EncounterArea4.cs index fe578b972..9a451909f 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea4.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea4.cs @@ -54,13 +54,13 @@ private EncounterSlot4 ReadRegularSlot(ReadOnlySpan 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); } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot1.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot1.cs index 63cdd6c0a..be0985db9 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot1.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot1.cs @@ -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; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs index 63dc9db35..2badd7c22 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs @@ -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; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3.cs index 30b30a5e0..892ff89a8 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3.cs @@ -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; diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs index e78d9ac1e..266ccdbc1 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs @@ -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; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3Swarm.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3Swarm.cs index 4e995ca84..ac59c0a65 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3Swarm.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3Swarm.cs @@ -13,7 +13,7 @@ internal sealed record EncounterSlot3Swarm : EncounterSlot3, IMoveset { public IReadOnlyList 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 moves) : base(area, species, 0, min, max, slot, 0, 0, 0, 0) => Moves = moves; protected override void SetEncounterMoves(PKM pk, GameVersion version, int level) diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot4.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot4.cs index 492c32682..0470ec4fc 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot4.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot4.cs @@ -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; diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/IMagnetStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/IMagnetStatic.cs index 1fd3f5e80..079acab36 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/IMagnetStatic.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/IMagnetStatic.cs @@ -1,29 +1,32 @@ -namespace PKHeX.Core +namespace PKHeX.Core; + +/// +/// Contains information about the RNG restrictions for the slot, and any mutated RNG values. +/// +/// +/// When encountering a Wild Pokémon with a lead that has an ability of or , +/// the game picks encounters from the that match the type. +/// The values in this interface change the to allow different values for slot yielding. +/// +public interface IMagnetStatic { - /// - /// Contains information about the RNG restrictions for the slot, and any mutated RNG values. - /// - /// - /// When encountering a Wild Pokémon with a lead that has an ability of or , - /// the game picks encounters from the that match the type. - /// The values in this interface change the to allow different values for slot yielding. - /// - public interface IMagnetStatic - { - /// if the lead is - int StaticIndex { get; } - /// if the lead is - int MagnetPullIndex { get; } + /// if the lead is + byte StaticIndex { get; } + /// if the lead is + byte MagnetPullIndex { get; } - /// Count of slots in the parent area that can be yielded by - int StaticCount { get; } - /// Count of slots in the parent area that can be yielded by - 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; - } + /// Count of slots in the parent area that can be yielded by + byte StaticCount { get; } + /// Count of slots in the parent area that can be yielded by + 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; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/INumberedSlot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/INumberedSlot.cs index 8dbbc15bb..1ccea3db2 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/INumberedSlot.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/INumberedSlot.cs @@ -1,16 +1,15 @@ -namespace PKHeX.Core +namespace PKHeX.Core; + +/// +/// that contains information about what Index it is within the 's type-group of slots. +/// +/// +/// Useful for checking legality (if the RNG can yield this slot). +/// +public interface INumberedSlot { /// - /// that contains information about what Index it is within the 's type-group of slots. + /// Number Index of the . /// - /// - /// Useful for checking legality (if the RNG can yield this slot). - /// - public interface INumberedSlot - { - /// - /// Number Index of the . - /// - int SlotNumber { get; } - } + byte SlotNumber { get; } } diff --git a/PKHeX.Core/Legality/Enums/EncounterTime.cs b/PKHeX.Core/Legality/Enums/EncounterTime.cs index 591524464..ffa01f390 100644 --- a/PKHeX.Core/Legality/Enums/EncounterTime.cs +++ b/PKHeX.Core/Legality/Enums/EncounterTime.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core /// Generation 2 Time of Encounter enum /// [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; } } -} \ No newline at end of file +} diff --git a/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs b/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs index 0208e2793..46aa23d1a 100644 --- a/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs +++ b/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs @@ -168,13 +168,13 @@ public static int GetLevel(EncounterSlot slot, LeadRequired lead, uint lvlrand) /// Slot number from the slot data if the slot is selected on this frame, else an invalid slot value. internal static int GetSlotStaticMagnet(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)