diff --git a/PKHeX.Core/Editing/PKM/QR/QRPK7.cs b/PKHeX.Core/Editing/PKM/QR/QRPK7.cs
index 9e244fcbb..c58718055 100644
--- a/PKHeX.Core/Editing/PKM/QR/QRPK7.cs
+++ b/PKHeX.Core/Editing/PKM/QR/QRPK7.cs
@@ -6,9 +6,10 @@ namespace PKHeX.Core;
///
/// Generation 7 PGL QR Code encoded entities.
///
-public sealed class QRPK7(byte[] Data) : IEncounterInfo
+public sealed class QRPK7(Memory Raw) : IEncounterInfo
{
- private readonly byte[] Data = (byte[])Data.Clone();
+ public const int SIZE = 0x30;
+ private Span Data => Raw.Span;
public bool EggEncounter => false;
public byte LevelMin => Level;
@@ -16,10 +17,13 @@ public sealed class QRPK7(byte[] Data) : IEncounterInfo
public byte Generation => Version.GetGeneration();
public EntityContext Context => EntityContext.Gen7;
public bool IsShiny => false;
+ public ushort Location => 0;
+ public ushort EggLocation => 0;
+ public AbilityPermission Ability => (AbilityPermission)AbilityIndex;
+ public Ball FixedBall => (Ball)Ball;
+ public Shiny Shiny => Shiny.Never;
- public const int SIZE = 0x30;
-
- public uint EncryptionConstant => ReadUInt32LittleEndian(Data.AsSpan(0));
+ public uint EncryptionConstant => ReadUInt32LittleEndian(Data[..]);
public byte HyperTrainFlags => Data[4];
public byte Unk_5 => Data[5];
public byte Unk_6 => Data[6];
@@ -28,20 +32,20 @@ public sealed class QRPK7(byte[] Data) : IEncounterInfo
public byte Move2_PPUps => Data[9];
public byte Move3_PPUps => Data[0xA];
public byte Move4_PPUps => Data[0xB];
- public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0xC)); set => WriteUInt32LittleEndian(Data.AsSpan(0xC), value); }
+ public uint IV32 { get => ReadUInt32LittleEndian(Data.Slice(0xC)); set => WriteUInt32LittleEndian(Data.Slice(0xC), value); }
public int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | (uint)((value > 31 ? 31 : value) << 00); }
public int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | (uint)((value > 31 ? 31 : value) << 05); }
public int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | (uint)((value > 31 ? 31 : value) << 10); }
public int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 15)) | (uint)((value > 31 ? 31 : value) << 15); }
public int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 20)) | (uint)((value > 31 ? 31 : value) << 20); }
public int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 25)) | (uint)((value > 31 ? 31 : value) << 25); }
- public uint PID => ReadUInt32LittleEndian(Data.AsSpan(0x10));
- public ushort Species => ReadUInt16LittleEndian(Data.AsSpan(0x14));
- public ushort HeldItem => ReadUInt16LittleEndian(Data.AsSpan(0x16));
- public ushort Move1 => ReadUInt16LittleEndian(Data.AsSpan(0x18));
- public ushort Move2 => ReadUInt16LittleEndian(Data.AsSpan(0x1A));
- public ushort Move3 => ReadUInt16LittleEndian(Data.AsSpan(0x1C));
- public ushort Move4 => ReadUInt16LittleEndian(Data.AsSpan(0x1E));
+ public uint PID => ReadUInt32LittleEndian(Data.Slice(0x10));
+ public ushort Species => ReadUInt16LittleEndian(Data.Slice(0x14));
+ public ushort HeldItem => ReadUInt16LittleEndian(Data.Slice(0x16));
+ public ushort Move1 => ReadUInt16LittleEndian(Data.Slice(0x18));
+ public ushort Move2 => ReadUInt16LittleEndian(Data.Slice(0x1A));
+ public ushort Move3 => ReadUInt16LittleEndian(Data.Slice(0x1C));
+ public ushort Move4 => ReadUInt16LittleEndian(Data.Slice(0x1E));
public byte Unk_20 => Data[0x20];
public byte AbilityIndex => Data[0x21];
public Nature Nature => (Nature)Data[0x22];
diff --git a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs
index 05fc79aa9..4057f07d6 100644
--- a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs
+++ b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs
@@ -203,6 +203,11 @@ private static bool IsPlausibleSmeargleMoveset(EntityContext context, ReadOnlySp
public ushort Species => 0;
public byte Form => 0;
public bool IsShiny => false;
+ public ushort Location => 0;
+ public ushort EggLocation => 0;
+ public AbilityPermission Ability => 0;
+ public Ball FixedBall => 0;
+ public Shiny Shiny => 0;
}
private static ushort[] GetNeededMoves(PKM pk, ReadOnlySpan moves, GameVersion version, byte generation, EntityContext context)
diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs
index bb870c928..0b6c240f1 100644
--- a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs
+++ b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
namespace PKHeX.Core;
@@ -81,9 +80,9 @@ private static bool IsTrainerNameValid(PKM pk)
private int GetNicknameIndex(ReadOnlySpan nickname) => GetIndex(nickname, Nicknames);
- private static int GetIndex(ReadOnlySpan name, IReadOnlyList arr)
+ private static int GetIndex(ReadOnlySpan name, ReadOnlySpan arr)
{
- for (int i = 0; i < arr.Count; i++)
+ for (int i = 0; i < arr.Length; i++)
{
if (name.SequenceEqual(arr[i]))
return i;
diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterTemplate.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterTemplate.cs
index 57ba41b2d..17c7d84f6 100644
--- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterTemplate.cs
+++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterTemplate.cs
@@ -3,7 +3,7 @@ namespace PKHeX.Core;
///
/// Represents all details that an entity may be encountered with.
///
-public interface IEncounterTemplate : ISpeciesForm, IVersion, IGeneration, IShiny, ILevelRange
+public interface IEncounterTemplate : ISpeciesForm, IVersion, IGeneration, IShiny, ILevelRange, ILocation, IFixedAbilityNumber, IFixedBall, IShinyPotential
{
///
/// Original Context
@@ -27,6 +27,10 @@ public static bool IsWithinEncounterRange(this IEncounterTemplate encounter, PKM
return level == encounter.LevelMin;
if (encounter is MysteryGift g)
return level == g.Level;
- return level == pk.MetLevel;
+
+ var met = pk.MetLevel;
+ if (met != 0)
+ return level == met;
+ return encounter.IsLevelWithinRange(level);
}
}
diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterable.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterable.cs
index 253f1955e..b93979b88 100644
--- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterable.cs
+++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterable.cs
@@ -1,10 +1,10 @@
-namespace PKHeX.Core;
+namespace PKHeX.Core;
///
/// Common Encounter Properties base interface.
///
///
-public interface IEncounterable : IEncounterInfo, ILocation, IFixedAbilityNumber, IFixedBall, IShinyPotential
+public interface IEncounterable : IEncounterInfo
{
///
/// Short name to describe the encounter data, usually just indicating which of the main component encounter types the data is.
diff --git a/PKHeX.Core/Legality/Tables/MystryMew.cs b/PKHeX.Core/Legality/Tables/MystryMew.cs
index eead42e8a..4ea4da3b7 100644
--- a/PKHeX.Core/Legality/Tables/MystryMew.cs
+++ b/PKHeX.Core/Legality/Tables/MystryMew.cs
@@ -33,7 +33,6 @@ public static class MystryMew
0xFE9D,
];
- //private const int FramesPerMew = 5;
private const int MewPerRestrictedSeed = 5;
///
@@ -70,9 +69,9 @@ public static int GetSeedIndex(uint seed)
var seeds = Seeds;
if (seed <= ushort.MaxValue)
return seeds.BinarySearch((ushort)seed);
- for (int i = 0; i < 5; i++)
+ for (int i = 0; i < MewPerRestrictedSeed; i++)
{
- seed = LCRNG.Prev5(seed);
+ seed = LCRNG.Prev5(seed); // BACD{?}
if (seed <= ushort.MaxValue)
return seeds.BinarySearch((ushort)seed);
}
@@ -93,9 +92,9 @@ public static (int Index, int SubIndex) GetSeedIndexes(uint seed)
var index = seeds.BinarySearch((ushort)seed);
return (index, -1);
}
- for (int i = 0; i < 5; i++)
+ for (int i = 0; i < MewPerRestrictedSeed; i++)
{
- seed = LCRNG.Prev5(seed);
+ seed = LCRNG.Prev5(seed); // BACD{?}
if (seed <= ushort.MaxValue)
{
var index = seeds.BinarySearch((ushort)seed);
diff --git a/PKHeX.Core/Legality/Verifiers/Ability/AbilityChangeRules.cs b/PKHeX.Core/Legality/Verifiers/Ability/AbilityChangeRules.cs
index 11f5e7a99..ad9403516 100644
--- a/PKHeX.Core/Legality/Verifiers/Ability/AbilityChangeRules.cs
+++ b/PKHeX.Core/Legality/Verifiers/Ability/AbilityChangeRules.cs
@@ -17,11 +17,8 @@ public static class AbilityChangeRules
/// Current context
/// Original context
/// True if possible to obtain
- public static bool IsAbilityStateValid(this IEncounterTemplate enc, EvolutionHistory evosAll, int abilityFlag, EntityContext current, EntityContext original) => (enc switch
- {
- IFixedAbilityNumber f => f.Ability,
- _ => Any12,
- }).IsAbilityStateValid(evosAll, abilityFlag, current, original);
+ public static bool IsAbilityStateValid(this IEncounterTemplate enc, EvolutionHistory evosAll, int abilityFlag, EntityContext current, EntityContext original)
+ => enc.Ability.IsAbilityStateValid(evosAll, abilityFlag, current, original);
///
/// Checks if the current value is possible to obtain based on the original and game visiting.
@@ -51,11 +48,8 @@ public static class AbilityChangeRules
/// Current context
/// Original context
/// True if the ability can be changed
- public static bool IsAbilityChangeAvailable(this IEncounterTemplate enc, EvolutionHistory evosAll, EntityContext current, EntityContext original) => (enc switch
- {
- IFixedAbilityNumber f => f.Ability,
- _ => Any12,
- }).IsAbilityChangeAvailable(evosAll, current, original);
+ public static bool IsAbilityChangeAvailable(this IEncounterTemplate enc, EvolutionHistory evosAll, EntityContext current, EntityContext original)
+ => enc.Ability.IsAbilityChangeAvailable(evosAll, current, original);
///
/// Checks if the original value can be changed based on the games visited.
diff --git a/PKHeX.Core/MysteryGifts/PL6.cs b/PKHeX.Core/MysteryGifts/PL6.cs
index dd4f2b585..d9733a605 100644
--- a/PKHeX.Core/MysteryGifts/PL6.cs
+++ b/PKHeX.Core/MysteryGifts/PL6.cs
@@ -10,15 +10,14 @@ namespace PKHeX.Core;
/// This Template object is very similar to the structure in that it stores more data than just the gift.
/// This template object is only present in Generation 6 save files.
///
-public sealed class PL6
+public sealed class PL6(Memory Raw)
{
public const int Size = 0xA47;
public const string Filter = "Pokémon Link Data|*.pl6|All Files (*.*)|*.*";
- public readonly byte[] Data;
+ public PL6() : this(new byte[Size]) { }
- public PL6() => Data = new byte[Size];
- public PL6(byte[] data) => Data = data;
+ public Span Data => Raw.Span;
///
/// Pokémon Link Flag
@@ -31,7 +30,7 @@ public byte Flags
public bool Enabled { get => (Flags & 0x80) != 0; set => Flags = value ? (byte)(1 << 7) : (byte)0; }
- private Span Source => Data.AsSpan(0x01, 110);
+ private Span Source => Data.Slice(0x01, 110);
///
/// Name of data source
@@ -39,37 +38,37 @@ public byte Flags
public string Origin { get => StringConverter6.GetString(Source); set => StringConverter6.SetString(Source, value, 54, StringConverterOption.ClearZero); }
// Pokemon transfer flags?
- public uint Flags_1 { get => ReadUInt32LittleEndian(Data.AsSpan(0x099)); set => WriteUInt32LittleEndian(Data.AsSpan(0x099), value); }
- public uint Flags_2 { get => ReadUInt32LittleEndian(Data.AsSpan(0x141)); set => WriteUInt32LittleEndian(Data.AsSpan(0x141), value); }
- public uint Flags_3 { get => ReadUInt32LittleEndian(Data.AsSpan(0x1E9)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1E9), value); }
- public uint Flags_4 { get => ReadUInt32LittleEndian(Data.AsSpan(0x291)); set => WriteUInt32LittleEndian(Data.AsSpan(0x291), value); }
- public uint Flags_5 { get => ReadUInt32LittleEndian(Data.AsSpan(0x339)); set => WriteUInt32LittleEndian(Data.AsSpan(0x339), value); }
- public uint Flags_6 { get => ReadUInt32LittleEndian(Data.AsSpan(0x3E1)); set => WriteUInt32LittleEndian(Data.AsSpan(0x3E1), value); }
+ public uint Flags1 { get => ReadUInt32LittleEndian(Data[0x099..]); set => WriteUInt32LittleEndian(Data[0x099..], value); }
+ public uint Flags2 { get => ReadUInt32LittleEndian(Data[0x141..]); set => WriteUInt32LittleEndian(Data[0x141..], value); }
+ public uint Flags3 { get => ReadUInt32LittleEndian(Data[0x1E9..]); set => WriteUInt32LittleEndian(Data[0x1E9..], value); }
+ public uint Flags4 { get => ReadUInt32LittleEndian(Data[0x291..]); set => WriteUInt32LittleEndian(Data[0x291..], value); }
+ public uint Flags5 { get => ReadUInt32LittleEndian(Data[0x339..]); set => WriteUInt32LittleEndian(Data[0x339..], value); }
+ public uint Flags6 { get => ReadUInt32LittleEndian(Data[0x3E1..]); set => WriteUInt32LittleEndian(Data[0x3E1..], value); }
// Pokémon
- public PL6_PKM Poke_1 { get => new(Data.AsSpan(0x09D, PL6_PKM.Size).ToArray()); set => value.Data.CopyTo(Data, 0x09D); }
- public PL6_PKM Poke_2 { get => new(Data.AsSpan(0x145, PL6_PKM.Size).ToArray()); set => value.Data.CopyTo(Data, 0x145); }
- public PL6_PKM Poke_3 { get => new(Data.AsSpan(0x1ED, PL6_PKM.Size).ToArray()); set => value.Data.CopyTo(Data, 0x1ED); }
- public PL6_PKM Poke_4 { get => new(Data.AsSpan(0x295, PL6_PKM.Size).ToArray()); set => value.Data.CopyTo(Data, 0x295); }
- public PL6_PKM Poke_5 { get => new(Data.AsSpan(0x33D, PL6_PKM.Size).ToArray()); set => value.Data.CopyTo(Data, 0x33D); }
- public PL6_PKM Poke_6 { get => new(Data.AsSpan(0x3E5, PL6_PKM.Size).ToArray()); set => value.Data.CopyTo(Data, 0x3E5); }
+ public LinkEntity6 Entity1 { get => new(Raw.Slice(0x09D, LinkEntity6.Size)); set => value.Data.CopyTo(Data[0x09D..]); }
+ public LinkEntity6 Entity2 { get => new(Raw.Slice(0x145, LinkEntity6.Size)); set => value.Data.CopyTo(Data[0x145..]); }
+ public LinkEntity6 Entity3 { get => new(Raw.Slice(0x1ED, LinkEntity6.Size)); set => value.Data.CopyTo(Data[0x1ED..]); }
+ public LinkEntity6 Entity4 { get => new(Raw.Slice(0x295, LinkEntity6.Size)); set => value.Data.CopyTo(Data[0x295..]); }
+ public LinkEntity6 Entity5 { get => new(Raw.Slice(0x33D, LinkEntity6.Size)); set => value.Data.CopyTo(Data[0x33D..]); }
+ public LinkEntity6 Entity6 { get => new(Raw.Slice(0x3E5, LinkEntity6.Size)); set => value.Data.CopyTo(Data[0x3E5..]); }
// Item Properties
- public int Item_1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x489)); set => WriteUInt16LittleEndian(Data.AsSpan(0x489), (ushort)value); }
- public int Quantity_1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x48B)); set => WriteUInt16LittleEndian(Data.AsSpan(0x48B), (ushort)value); }
- public int Item_2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x48D)); set => WriteUInt16LittleEndian(Data.AsSpan(0x48D), (ushort)value); }
- public int Quantity_2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x48F)); set => WriteUInt16LittleEndian(Data.AsSpan(0x48F), (ushort)value); }
- public int Item_3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x491)); set => WriteUInt16LittleEndian(Data.AsSpan(0x491), (ushort)value); }
- public int Quantity_3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x493)); set => WriteUInt16LittleEndian(Data.AsSpan(0x493), (ushort)value); }
- public int Item_4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x495)); set => WriteUInt16LittleEndian(Data.AsSpan(0x495), (ushort)value); }
- public int Quantity_4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x497)); set => WriteUInt16LittleEndian(Data.AsSpan(0x497), (ushort)value); }
- public int Item_5 { get => ReadUInt16LittleEndian(Data.AsSpan(0x499)); set => WriteUInt16LittleEndian(Data.AsSpan(0x499), (ushort)value); }
- public int Quantity_5 { get => ReadUInt16LittleEndian(Data.AsSpan(0x49B)); set => WriteUInt16LittleEndian(Data.AsSpan(0x49B), (ushort)value); }
- public int Item_6 { get => ReadUInt16LittleEndian(Data.AsSpan(0x49D)); set => WriteUInt16LittleEndian(Data.AsSpan(0x49D), (ushort)value); }
- public int Quantity_6 { get => ReadUInt16LittleEndian(Data.AsSpan(0x49F)); set => WriteUInt16LittleEndian(Data.AsSpan(0x49F), (ushort)value); }
+ public ushort Item1 { get => ReadUInt16LittleEndian(Data[0x489..]); set => WriteUInt16LittleEndian(Data[0x489..], value); }
+ public ushort Quantity1 { get => ReadUInt16LittleEndian(Data[0x48B..]); set => WriteUInt16LittleEndian(Data[0x48B..], value); }
+ public ushort Item2 { get => ReadUInt16LittleEndian(Data[0x48D..]); set => WriteUInt16LittleEndian(Data[0x48D..], value); }
+ public ushort Quantity2 { get => ReadUInt16LittleEndian(Data[0x48F..]); set => WriteUInt16LittleEndian(Data[0x48F..], value); }
+ public ushort Item3 { get => ReadUInt16LittleEndian(Data[0x491..]); set => WriteUInt16LittleEndian(Data[0x491..], value); }
+ public ushort Quantity3 { get => ReadUInt16LittleEndian(Data[0x493..]); set => WriteUInt16LittleEndian(Data[0x493..], value); }
+ public ushort Item4 { get => ReadUInt16LittleEndian(Data[0x495..]); set => WriteUInt16LittleEndian(Data[0x495..], value); }
+ public ushort Quantity4 { get => ReadUInt16LittleEndian(Data[0x497..]); set => WriteUInt16LittleEndian(Data[0x497..], value); }
+ public ushort Item5 { get => ReadUInt16LittleEndian(Data[0x499..]); set => WriteUInt16LittleEndian(Data[0x499..], value); }
+ public ushort Quantity5 { get => ReadUInt16LittleEndian(Data[0x49B..]); set => WriteUInt16LittleEndian(Data[0x49B..], value); }
+ public ushort Item6 { get => ReadUInt16LittleEndian(Data[0x49D..]); set => WriteUInt16LittleEndian(Data[0x49D..], value); }
+ public ushort Quantity6 { get => ReadUInt16LittleEndian(Data[0x49F..]); set => WriteUInt16LittleEndian(Data[0x49F..], value); }
- public int BattlePoints { get => ReadUInt16LittleEndian(Data.AsSpan(0x4A1)); set => WriteUInt16LittleEndian(Data.AsSpan(0x4A1), (ushort)value); }
- public int Pokemiles { get => ReadUInt16LittleEndian(Data.AsSpan(0x4A3)); set => WriteUInt16LittleEndian(Data.AsSpan(0x4A3), (ushort)value); }
+ public ushort BattlePoints { get => ReadUInt16LittleEndian(Data[0x4A1..]); set => WriteUInt16LittleEndian(Data[0x4A1..], value); }
+ public ushort Pokemiles { get => ReadUInt16LittleEndian(Data[0x4A3..]); set => WriteUInt16LittleEndian(Data[0x4A3..], value); }
}
///
@@ -79,44 +78,46 @@ public byte Flags
/// This Template object is very similar to the structure and similar objects, in that the structure offsets are ordered the same.
/// This template object is only present in Generation 6 save files.
///
-public sealed class PL6_PKM(byte[] Data) : IRibbonSetEvent3, IRibbonSetEvent4, IEncounterInfo, IMoveset, IRelearn,
- IContestStats, IMemoryOT, ITrainerID32, ILocation
+public sealed class LinkEntity6(Memory Raw) : IRibbonSetEvent3, IRibbonSetEvent4, IEncounterInfo, IMoveset, IRelearn,
+ IContestStats, IMemoryOT, ITrainerID32
{
internal const int Size = 0xA0;
- public readonly byte[] Data = Data;
+ public Span Data => Raw.Span;
- public PL6_PKM() : this(new byte[Size]) { }
+ public LinkEntity6() : this(new byte[Size]) { }
public TrainerIDFormat TrainerIDDisplayFormat => TrainerIDFormat.SixteenBit;
- public uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); }
- public ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); }
- public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), value); }
+ public uint ID32 { get => ReadUInt32LittleEndian(Data[..]); set => WriteUInt32LittleEndian(Data[..], value); }
+ public ushort TID16 { get => ReadUInt16LittleEndian(Data[..]); set => WriteUInt16LittleEndian(Data[..], value); }
+ public ushort SID16 { get => ReadUInt16LittleEndian(Data[0x02..]); set => WriteUInt16LittleEndian(Data[0x02..], value); }
public byte OriginGame { get => Data[0x04]; set => Data[0x04] = value; }
- public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(0x08), value); }
+ public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data[0x08..]); set => WriteUInt32LittleEndian(Data[0x08..], value); }
public byte Ball { get => Data[0xE]; set => Data[0xE] = value; }
- public int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x10)); set => WriteUInt16LittleEndian(Data.AsSpan(0x10), (ushort)value); }
- public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x12)); set => WriteUInt16LittleEndian(Data.AsSpan(0x12), value); }
- public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), value); }
- public ushort Move3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16), value); }
- public ushort Move4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), value); }
- public ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x1A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1A), value); }
+ public int HeldItem { get => ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], (ushort)value); }
+ public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x12..]); set => WriteUInt16LittleEndian(Data[0x12..], value); }
+ public ushort Move2 { get => ReadUInt16LittleEndian(Data[0x14..]); set => WriteUInt16LittleEndian(Data[0x14..], value); }
+ public ushort Move3 { get => ReadUInt16LittleEndian(Data[0x16..]); set => WriteUInt16LittleEndian(Data[0x16..], value); }
+ public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x18..]); set => WriteUInt16LittleEndian(Data[0x18..], value); }
+ public ushort Species { get => ReadUInt16LittleEndian(Data[0x1A..]); set => WriteUInt16LittleEndian(Data[0x1A..], value); }
public byte Form { get => Data[0x1C]; set => Data[0x1C] = value; }
public int Language { get => Data[0x1D]; set => Data[0x1D] = (byte)value; }
+ public Span NicknameTrash => Data.Slice(0x1E, 0x1A);
+
public string Nickname
{
- get => StringConverter6.GetString(Data.AsSpan(0x1E, 0x1A));
- set => StringConverter6.SetString(Data.AsSpan(0x1E, 0x1A), value, 12, StringConverterOption.ClearZero);
+ get => StringConverter6.GetString(NicknameTrash);
+ set => StringConverter6.SetString(NicknameTrash, value, 12, StringConverterOption.ClearZero);
}
public Nature Nature { get => (Nature)Data[0x38]; set => Data[0x38] = (byte)value; }
public byte Gender { get => Data[0x39]; set => Data[0x39] = value; }
public int AbilityType { get => Data[0x3A]; set => Data[0x3A] = (byte)value; }
public int PIDType { get => Data[0x3B]; set => Data[0x3B] = (byte)value; }
- public ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x3C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3C), value); }
- public ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x3E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3E), value); }
+ public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x3C..]); set => WriteUInt16LittleEndian(Data[0x3C..], value); }
+ public ushort Location { get => ReadUInt16LittleEndian(Data[0x3E..]); set => WriteUInt16LittleEndian(Data[0x3E..], value); }
public byte MetLevel { get => Data[0x40]; set => Data[0x40] = value; }
public byte ContestCool { get => Data[0x41]; set => Data[0x41] = value; }
@@ -135,22 +136,24 @@ public string Nickname
public byte OTGender { get => Data[0x4D]; set => Data[0x4D] = value; }
+ public Span OriginalTrainerTrash => Data.Slice(0x4E, 0x1A);
+
public string OT
{
- get => StringConverter6.GetString(Data.AsSpan(0x4E, 0x1A));
- set => StringConverter6.SetString(Data.AsSpan(0x4E, 0x1A), value, 12, StringConverterOption.ClearZero);
+ get => StringConverter6.GetString(OriginalTrainerTrash);
+ set => StringConverter6.SetString(OriginalTrainerTrash, value, 12, StringConverterOption.ClearZero);
}
public int Level { get => Data[0x68]; set => Data[0x68] = (byte)value; }
public bool IsEgg { get => Data[0x69] == 1; set => Data[0x69] = value ? (byte)1 : (byte)0; }
- public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x6C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x6C), value); }
- public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x70)); set => WriteUInt16LittleEndian(Data.AsSpan(0x70), value); }
- public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x72)); set => WriteUInt16LittleEndian(Data.AsSpan(0x72), value); }
- public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x74)); set => WriteUInt16LittleEndian(Data.AsSpan(0x74), value); }
- public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x76)); set => WriteUInt16LittleEndian(Data.AsSpan(0x76), value); }
+ public uint PID { get => ReadUInt32LittleEndian(Data[0x6C..]); set => WriteUInt32LittleEndian(Data[0x6C..], value); }
+ public ushort RelearnMove1 { get => ReadUInt16LittleEndian(Data[0x70..]); set => WriteUInt16LittleEndian(Data[0x70..], value); }
+ public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data[0x72..]); set => WriteUInt16LittleEndian(Data[0x72..], value); }
+ public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data[0x74..]); set => WriteUInt16LittleEndian(Data[0x74..], value); }
+ public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[0x76..]); set => WriteUInt16LittleEndian(Data[0x76..], value); }
public byte OriginalTrainerMemoryIntensity { get => Data[0x78]; set => Data[0x78] = value; }
public byte OriginalTrainerMemory { get => Data[0x79]; set => Data[0x79] = value; }
- public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), value); }
+ public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[0x7A..]); set => WriteUInt16LittleEndian(Data[0x7A..], value); }
public byte OriginalTrainerMemoryFeeling { get => Data[0x7C]; set => Data[0x7C] = value; }
private byte RIB0 { get => Data[0x0C]; set => Data[0x0C] = value; }
@@ -205,13 +208,16 @@ public Moveset Relearn
public bool EggEncounter => false;
public GameVersion Version => GameVersion.Gen6;
public EntityContext Context => EntityContext.Gen6;
+ public AbilityPermission Ability => (AbilityPermission)AbilityType;
+ public Ball FixedBall => (Ball)Ball;
+ public Shiny Shiny => Shiny.Never;
public PKM ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted);
public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
{
var wc6 = new WC6();
- Data.CopyTo(wc6.Data, 0x68);
+ Data.CopyTo(wc6.Data.AsSpan(0x68));
return wc6.ConvertToPKM(tr, criteria);
}
}
diff --git a/PKHeX.Core/MysteryGifts/WC3.cs b/PKHeX.Core/MysteryGifts/WC3.cs
index d7f69a785..fb727f731 100644
--- a/PKHeX.Core/MysteryGifts/WC3.cs
+++ b/PKHeX.Core/MysteryGifts/WC3.cs
@@ -160,8 +160,7 @@ private void SetForceHatchDetails(PK3 pk, ITrainerInfo sav)
}
pk.OriginalTrainerGender = sav.Gender;
- pk.TID16 = sav.TID16;
- pk.SID16 = sav.SID16;
+ pk.ID32 = sav.ID32;
pk.MetLocation = pk.FRLG ? Locations.HatchLocationFRLG : Locations.HatchLocationRSE;
pk.FatefulEncounter &= pk.FRLG; // clear flag for RSE
pk.MetLevel = 0; // hatched
diff --git a/PKHeX.Core/PKM/Util/Conversion/IEntityRejuvenator.cs b/PKHeX.Core/PKM/Util/Conversion/IEntityRejuvenator.cs
index bb11a3f4f..ea705076e 100644
--- a/PKHeX.Core/PKM/Util/Conversion/IEntityRejuvenator.cs
+++ b/PKHeX.Core/PKM/Util/Conversion/IEntityRejuvenator.cs
@@ -108,8 +108,8 @@ private static void ResetBallPLA(PKM result, IEncounterable enc)
{
if (result.Ball is >= (int)Ball.LAPoke and <= (int)Ball.LAOrigin)
return;
- if (enc is IFixedBall { FixedBall: not Ball.None } f)
- result.Ball = (byte)f.FixedBall;
+ if (enc is { FixedBall: not Ball.None })
+ result.Ball = (byte)enc.FixedBall;
else
result.Ball = result.Species == (int)Species.Unown ? (byte)Ball.LAJet : (byte)Ball.LAPoke;
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/LinkBlock6.cs b/PKHeX.Core/Saves/Substructures/Gen6/LinkBlock6.cs
index 88f482791..b6dfdfa72 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/LinkBlock6.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/LinkBlock6.cs
@@ -8,21 +8,11 @@ public sealed class LinkBlock6 : SaveBlock
public LinkBlock6(SAV6XY sav, Memory raw) : base(sav, raw) { }
public LinkBlock6(SAV6AO sav, Memory raw) : base(sav, raw) { }
- public Span InfoSpan() => Data.Slice(0x1FF, PL6.Size);
+ public Memory PL6 => Raw.Slice(0x1FF, Core.PL6.Size);
- public PL6 GetLinkInfo() => new(InfoSpan().ToArray());
+ public PL6 Gifts => new(PL6);
- public void SetLinkInfoData(ReadOnlySpan data)
- {
- data.CopyTo(Data);
- Checksum = GetCalculatedChecksum(); // [app,chk)
- }
-
- public void SetLinkInfo(PL6 pl6)
- {
- pl6.Data.CopyTo(InfoSpan());
- Checksum = GetCalculatedChecksum(); // [app,chk)
- }
+ public void RefreshChecksum() => Checksum = GetCalculatedChecksum(); // [app,chk)
private ushort GetCalculatedChecksum() => Checksums.CRC16_CCITT(Data[0x200..^4]); // [app,chk)
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs
index db3b49c79..b2d674649 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs
@@ -8,11 +8,11 @@ namespace PKHeX.Core;
///
/// Go Park Entity transferred from to .
///
-public sealed class GP1(byte[] Data)
- : IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOnly, IEncounterConvertible
+public sealed class GP1(Memory Raw)
+ : IEncounterInfo, IScaledSizeReadOnly, IEncounterConvertible
{
public const int SIZE = 0x1B0;
- public readonly byte[] Data = Data;
+ public Span Data => Raw.Span;
public GameVersion Version => GameVersion.GO;
public bool EggEncounter => false;
@@ -21,6 +21,10 @@ public sealed class GP1(byte[] Data)
public byte Generation => 7;
public EntityContext Context => EntityContext.Gen7b;
public AbilityPermission Ability => AbilityPermission.Any12;
+ public ushort Location => Locations.GO7;
+ public ushort EggLocation => 0;
+ public Ball FixedBall => Ball.None;
+ public Shiny Shiny => Shiny.Random;
public GP1() : this(new byte[SIZE]) => InitializeBlank(Data);
public void WriteTo(Span data) => Data.CopyTo(data);
@@ -55,17 +59,17 @@ private static ReadOnlySpan GetLength(ReadOnlySpan buffer)
private static string GetString(ReadOnlySpan buffer) => Encoding.ASCII.GetString(GetLength(buffer));
- public string Username1 => GetString(Data.AsSpan(0x00, 0x10));
- public string Username2 => GetString(Data.AsSpan(0x10, 0x10));
+ public string Username1 => GetString(Data[..0x10]);
+ public string Username2 => GetString(Data.Slice(0x10, 0x10));
- public ushort Species => ReadUInt16LittleEndian(Data.AsSpan(0x28)); // s32, just read as u16
- public int CP => ReadInt32LittleEndian(Data.AsSpan(0x2C));
- public float LevelF => ReadSingleLittleEndian(Data.AsSpan(0x30));
+ public ushort Species => ReadUInt16LittleEndian(Data[0x28..]); // s32, just read as u16
+ public int CP => ReadInt32LittleEndian(Data[0x2C..]);
+ public float LevelF => ReadSingleLittleEndian(Data[0x30..]);
public byte Level => Math.Max((byte)1, (byte)Math.Round(LevelF));
- public int Stat_HP => ReadInt32LittleEndian(Data.AsSpan(0x34));
+ public int Stat_HP => ReadInt32LittleEndian(Data[0x34..]);
// geolocation data 0x38-0x47?
- public float HeightF => ReadSingleLittleEndian(Data.AsSpan(0x48));
- public float WeightF => ReadSingleLittleEndian(Data.AsSpan(0x4C));
+ public float HeightF => ReadSingleLittleEndian(Data[0x48..]);
+ public float WeightF => ReadSingleLittleEndian(Data[0x4C..]);
public byte HeightScalar
{
@@ -91,10 +95,10 @@ public byte WeightScalar
}
}
- public int IV_HP => ReadInt32LittleEndian(Data.AsSpan(0x50));
- public int IV_ATK => ReadInt32LittleEndian(Data.AsSpan(0x54));
- public int IV_DEF => ReadInt32LittleEndian(Data.AsSpan(0x58));
- public int Date => ReadInt32LittleEndian(Data.AsSpan(0x5C)); // ####.##.## YYYY.MM.DD
+ public int IV_HP => ReadInt32LittleEndian(Data[0x50..]);
+ public int IV_ATK => ReadInt32LittleEndian(Data[0x54..]);
+ public int IV_DEF => ReadInt32LittleEndian(Data[0x58..]);
+ public int Date => ReadInt32LittleEndian(Data[0x5C..]); // ####.##.## YYYY.MM.DD
public int Year => Date / 1_00_00;
public int Month => (Date / 1_00) % 1_00;
public int Day => Date % 1_00;
@@ -105,12 +109,12 @@ public byte WeightScalar
public bool IsShiny => Data[0x73] == 1;
// https://bulbapedia.bulbagarden.net/wiki/List_of_moves_in_Pok%C3%A9mon_GO
- public int Move1 => ReadInt32LittleEndian(Data.AsSpan(0x74)); // uses Go Indexes
- public int Move2 => ReadInt32LittleEndian(Data.AsSpan(0x78)); // uses Go Indexes
+ public int Move1 => ReadInt32LittleEndian(Data[0x74..]); // uses Go Indexes
+ public int Move2 => ReadInt32LittleEndian(Data[0x78..]); // uses Go Indexes
- public string GeoCityName => GetString(Data.AsSpan(0x7C, 0x60)); // dunno length
+ public string GeoCityName => GetString(Data.Slice(0x7C, 0x60)); // dunno length
- public string Nickname => GetString(Data.AsSpan(0x12D, 0x20)); // dunno length
+ public string Nickname => GetString(Data.Slice(0x12D, 0x20)); // dunno length
public static readonly IReadOnlyList Genders = GameInfo.GenderSymbolASCII;
public string GenderString => (uint) Gender >= Genders.Count ? string.Empty : Genders[Gender];
@@ -152,14 +156,13 @@ public PB7 ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria)
Version = GameVersion.GO,
Species = Species,
Form = Form,
- MetLocation = 50, // Go complex
+ MetLocation = Location, // Go complex
MetYear = (byte)(Year - 2000),
MetMonth = (byte)Month,
MetDay = (byte)Day,
CurrentLevel = Level,
MetLevel = Level,
- TID16 = sav.TID16,
- SID16 = sav.SID16,
+ ID32 = sav.ID32,
OriginalTrainerName = sav.OT,
Ball = 4,
Language = sav.Language,
@@ -179,7 +182,7 @@ public PB7 ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria)
pk.IV_DEF = pk.IV_SPD = (IV_DEF * 2) + 1;
pk.IV_ATK = pk.IV_SPA = (IV_ATK * 2) + 1;
pk.IV_HP = (IV_HP * 2) + 1;
- pk.IV_SPE = Util.Rand.Next(32);
+ pk.IV_SPE = rnd.Next(32);
var pi = pk.PersonalInfo;
pk.Gender = criteria.GetGender(Gender, pi);
@@ -200,7 +203,7 @@ public PB7 ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria)
Span moves = stackalloc ushort[4];
((ILearnSource)LearnSource7GG.Instance).SetEncounterMoves(Species, Form, Level, moves);
pk.SetMoves(moves);
- pk.OriginalTrainerFriendship = pk.PersonalInfo.BaseFriendship;
+ pk.OriginalTrainerFriendship = pi.BaseFriendship;
pk.HeightScalar = HeightScalar;
pk.WeightScalar = WeightScalar;
diff --git a/PKHeX.Core/Saves/Util/BoxUtil.cs b/PKHeX.Core/Saves/Util/BoxUtil.cs
index 436ba144e..ec8382919 100644
--- a/PKHeX.Core/Saves/Util/BoxUtil.cs
+++ b/PKHeX.Core/Saves/Util/BoxUtil.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -224,21 +225,27 @@ private static IEnumerable GetPossiblePKMsFromPaths(SaveFile sav, IEnumerab
/// Returns default English box names in the event the save file does not have names (not exportable), or fails to return a box name.
public static string[] GetBoxNames(SaveFile sav)
{
- int count = sav.BoxCount;
+ var count = sav.BoxCount;
+ if (count == 0)
+ return [];
var result = new string[count];
+ GetBoxNames(sav, result);
+ return result;
+ }
+
+ private static void GetBoxNames(SaveFile sav, Span result)
+ {
if (!sav.State.Exportable || sav is not IBoxDetailNameRead r)
{
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < result.Length; i++)
result[i] = BoxDetailNameExtensions.GetDefaultBoxName(i);
- return result;
+ return;
}
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < result.Length; i++)
{
try { result[i] = r.GetBoxName(i); }
catch { result[i] = BoxDetailNameExtensions.GetDefaultBoxName(i); }
}
-
- return result;
}
}
diff --git a/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs b/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs
index 18d5a8a71..6752bb90b 100644
--- a/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs
+++ b/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs
@@ -259,9 +259,9 @@ public static Bitmap Sprite(this IEncounterTemplate enc)
var gender = GetDisplayGender(enc);
var shiny = enc.IsShiny ? Shiny.Always : Shiny.Never;
var img = GetSprite(enc.Species, enc.Form, gender, 0, 0, enc.EggEncounter, shiny, enc.Context);
- if (SpriteBuilder.ShowEncounterBall && enc is IFixedBall {FixedBall: not Ball.None} b)
+ if (SpriteBuilder.ShowEncounterBall && enc is {FixedBall: not Ball.None})
{
- var ballSprite = GetBallSprite((byte)b.FixedBall);
+ var ballSprite = GetBallSprite((byte)enc.FixedBall);
img = ImageUtil.LayerImage(img, ballSprite, 0, img.Height - ballSprite.Height);
}
if (enc is IGigantamaxReadOnly {CanGigantamax: true})
@@ -297,9 +297,9 @@ public static Bitmap GetMysteryGiftPreviewPoke(MysteryGift gift)
var gender = Math.Max((byte)0, gift.Gender);
var img = GetSprite(gift.Species, gift.Form, gender, 0, gift.HeldItem, gift.IsEgg, gift.IsShiny ? Shiny.Always : Shiny.Never, gift.Context);
- if (SpriteBuilder.ShowEncounterBall && gift is IFixedBall { FixedBall: not Ball.None } b)
+ if (SpriteBuilder.ShowEncounterBall && gift is { FixedBall: not Ball.None })
{
- var ballSprite = GetBallSprite((byte)b.FixedBall);
+ var ballSprite = GetBallSprite((byte)gift.FixedBall);
img = ImageUtil.LayerImage(img, ballSprite, 0, img.Height - ballSprite.Height);
}
diff --git a/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.cs
index 0e01c0c6f..221d12903 100644
--- a/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.cs
+++ b/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.cs
@@ -180,11 +180,11 @@ public void ResetBoxNames(int box = -1)
CurrentBox = box;
}
- private static bool GetIsSame(IReadOnlyList a, IList b)
+ private static bool GetIsSame(ReadOnlySpan a, IList b)
{
- if (a.Count != b.Count)
+ if (a.Length != b.Count)
return false;
- for (int i = 0; i < a.Count; i++)
+ for (int i = 0; i < a.Length; i++)
{
if (b[i] is not string s || s != a[i])
return false;
diff --git a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs
index 09fb83ff0..c2662ae7c 100644
--- a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs
+++ b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs
@@ -274,9 +274,9 @@ private void HandleDropPKM(PictureBox pb, DragEventArgs? e, DropModifier mod)
/// Args
/// Destination slot disallows eggs/blanks
/// True if loaded
- private bool TryLoadFiles(IReadOnlyList files, DragEventArgs e, bool badDest)
+ private bool TryLoadFiles(ReadOnlySpan files, DragEventArgs e, bool badDest)
{
- if (files.Count == 0)
+ if (files.Length == 0)
return false;
var sav = Drag.Info.Destination!.View.SAV;
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Link6.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Link6.cs
index 8edabb363..92d862e48 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Link6.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Link6.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using System.Linq;
using System.Windows.Forms;
using PKHeX.Core;
@@ -11,7 +10,7 @@ public partial class SAV_Link6 : Form
private readonly SaveFile Origin;
private readonly ISaveBlock6Main SAV;
- private PL6 LinkInfo;
+ private PL6 Gifts;
public SAV_Link6(SaveFile sav)
{
@@ -19,18 +18,20 @@ public SAV_Link6(SaveFile sav)
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
SAV = (ISaveBlock6Main)(Origin = sav).Clone();
var filtered = GameInfo.FilteredSources;
- foreach (var cb in TAB_Items.Controls.OfType())
+
+ foreach (var cb in (ComboBox[])[CB_Item1, CB_Item2, CB_Item3, CB_Item4, CB_Item5, CB_Item6])
{
cb.InitializeBinding();
cb.DataSource = new BindingSource(filtered.Items, null);
}
- LinkInfo = SAV.Link.GetLinkInfo();
+ Gifts = SAV.Link.Gifts;
LoadLinkData();
}
private void B_Save_Click(object sender, EventArgs e)
{
- SAV.Link.SetLinkInfo(LinkInfo);
+ SaveLinkData();
+ SAV.Link.RefreshChecksum();
Origin.CopyChangesFrom((SaveFile)SAV);
Close();
}
@@ -51,7 +52,7 @@ private void B_Import_Click(object sender, EventArgs e)
{ WinFormsUtil.Alert("Invalid file length"); return; }
byte[] data = File.ReadAllBytes(ofd.FileName);
- LinkInfo = new PL6(data);
+ Gifts = new PL6(data);
LoadLinkData();
B_Export.Enabled = true;
@@ -64,38 +65,69 @@ private void B_Export_Click(object sender, EventArgs e)
if (sfd.ShowDialog() != DialogResult.OK)
return;
- File.WriteAllBytes(sfd.FileName, LinkInfo.Data);
+ File.WriteAllBytes(sfd.FileName, Gifts.Data.ToArray());
WinFormsUtil.Alert("Pokémon Link data saved to:" + Environment.NewLine + sfd.FileName);
}
private void LoadLinkData()
{
- RTB_LinkSource.Text = LinkInfo.Origin;
- CHK_LinkAvailable.Checked = LinkInfo.Enabled;
+ RTB_LinkSource.Text = Gifts.Origin;
+ CHK_LinkAvailable.Checked = Gifts.Enabled;
- NUD_BP.Value = LinkInfo.BattlePoints;
- NUD_Pokemiles.Value = LinkInfo.Pokemiles;
+ NUD_BP.Value = Gifts.BattlePoints;
+ NUD_Pokemiles.Value = Gifts.Pokemiles;
- CB_Item1.SelectedIndex = LinkInfo.Item_1;
- CB_Item2.SelectedIndex = LinkInfo.Item_2;
- CB_Item3.SelectedIndex = LinkInfo.Item_3;
- CB_Item4.SelectedIndex = LinkInfo.Item_4;
- CB_Item5.SelectedIndex = LinkInfo.Item_5;
- CB_Item6.SelectedIndex = LinkInfo.Item_6;
+ CB_Item1.SelectedValue = (int)Gifts.Item1;
+ CB_Item2.SelectedValue = (int)Gifts.Item2;
+ CB_Item3.SelectedValue = (int)Gifts.Item3;
+ CB_Item4.SelectedValue = (int)Gifts.Item4;
+ CB_Item5.SelectedValue = (int)Gifts.Item5;
+ CB_Item6.SelectedValue = (int)Gifts.Item6;
- NUD_Item1.Value = LinkInfo.Quantity_1;
- NUD_Item2.Value = LinkInfo.Quantity_2;
- NUD_Item3.Value = LinkInfo.Quantity_3;
- NUD_Item4.Value = LinkInfo.Quantity_4;
- NUD_Item5.Value = LinkInfo.Quantity_5;
- NUD_Item6.Value = LinkInfo.Quantity_6;
+ NUD_Item1.Value = Gifts.Quantity1;
+ NUD_Item2.Value = Gifts.Quantity2;
+ NUD_Item3.Value = Gifts.Quantity3;
+ NUD_Item4.Value = Gifts.Quantity4;
+ NUD_Item5.Value = Gifts.Quantity5;
+ NUD_Item6.Value = Gifts.Quantity6;
// Pokemon slots
- TB_PKM1.Text = GameInfo.Strings.specieslist[LinkInfo.Poke_1.Species];
- TB_PKM2.Text = GameInfo.Strings.specieslist[LinkInfo.Poke_2.Species];
- TB_PKM3.Text = GameInfo.Strings.specieslist[LinkInfo.Poke_3.Species];
- TB_PKM4.Text = GameInfo.Strings.specieslist[LinkInfo.Poke_4.Species];
- TB_PKM5.Text = GameInfo.Strings.specieslist[LinkInfo.Poke_5.Species];
- TB_PKM6.Text = GameInfo.Strings.specieslist[LinkInfo.Poke_6.Species];
+ TB_PKM1.Text = GetSpecies(Gifts.Entity1.Species);
+ TB_PKM2.Text = GetSpecies(Gifts.Entity2.Species);
+ TB_PKM3.Text = GetSpecies(Gifts.Entity3.Species);
+ TB_PKM4.Text = GetSpecies(Gifts.Entity4.Species);
+ TB_PKM5.Text = GetSpecies(Gifts.Entity5.Species);
+ TB_PKM6.Text = GetSpecies(Gifts.Entity6.Species);
+ }
+
+ private static string GetSpecies(ushort species)
+ {
+ var arr = GameInfo.Strings.Species;
+ if (species < arr.Count)
+ return arr[species];
+ return species.ToString();
+ }
+
+ private void SaveLinkData()
+ {
+ Gifts.Origin = RTB_LinkSource.Text;
+ Gifts.Enabled = CHK_LinkAvailable.Checked;
+
+ Gifts.BattlePoints = (ushort)NUD_BP.Value;
+ Gifts.Pokemiles = (ushort)NUD_Pokemiles.Value;
+
+ Gifts.Item1 = (ushort)WinFormsUtil.GetIndex(CB_Item1);
+ Gifts.Item2 = (ushort)WinFormsUtil.GetIndex(CB_Item2);
+ Gifts.Item3 = (ushort)WinFormsUtil.GetIndex(CB_Item3);
+ Gifts.Item4 = (ushort)WinFormsUtil.GetIndex(CB_Item4);
+ Gifts.Item5 = (ushort)WinFormsUtil.GetIndex(CB_Item5);
+ Gifts.Item6 = (ushort)WinFormsUtil.GetIndex(CB_Item6);
+
+ Gifts.Quantity1 = (byte)NUD_Item1.Value;
+ Gifts.Quantity2 = (byte)NUD_Item2.Value;
+ Gifts.Quantity3 = (byte)NUD_Item3.Value;
+ Gifts.Quantity4 = (byte)NUD_Item4.Value;
+ Gifts.Quantity5 = (byte)NUD_Item5.Value;
+ Gifts.Quantity6 = (byte)NUD_Item6.Value;
}
}
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs
index a21948511..f8d1d9518 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs
@@ -207,7 +207,7 @@ private void B_ExportGoFiles_Click(object sender, EventArgs e)
var folder = fbd.SelectedPath;
foreach (var gpk in gofiles)
- File.WriteAllBytes(Path.Combine(folder, Util.CleanFileName(gpk.FileName)), gpk.Data);
+ File.WriteAllBytes(Path.Combine(folder, Util.CleanFileName(gpk.FileName)), gpk.Data.ToArray());
WinFormsUtil.Alert($"Dumped {gofiles.Length} files to {folder}");
}
@@ -243,7 +243,7 @@ private void ImportGP1From(string path, int index)
return;
}
var gp1 = new GP1();
- data.CopyTo(gp1.Data, 0);
+ data.CopyTo(gp1.Data);
Park[index] = gp1;
UpdateGoSummary((int)NUD_GoIndex.Value);
}
@@ -266,7 +266,7 @@ private void B_Export_Click(object sender, EventArgs e)
if (sfd.ShowDialog() != DialogResult.OK)
return;
- File.WriteAllBytes(sfd.FileName, data.Data);
+ File.WriteAllBytes(sfd.FileName, data.Data.ToArray());
}
private void B_ImportGoFiles_Click(object sender, EventArgs e)
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexResearchEditorLA.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexResearchEditorLA.cs
index 1e3d4d244..cd61b1d29 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexResearchEditorLA.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexResearchEditorLA.cs
@@ -13,12 +13,55 @@ public partial class SAV_PokedexResearchEditorLA : Form
private readonly PokedexSave8a Dex;
private readonly ushort Species;
-
private readonly bool WasEmpty;
private readonly NumericUpDown[] TaskNUPs;
- private readonly PokedexResearchTaskType8a[] TaskTypes;
- private readonly int[] TaskIndexes;
+
+ private static ReadOnlySpan TaskTypes =>
+ [
+ Catch,
+ CatchAlpha,
+ CatchLarge,
+ CatchSmall,
+ CatchHeavy,
+ CatchLight,
+ CatchAtTime,
+ CatchSleeping,
+ CatchInAir,
+ CatchNotSpotted,
+
+ UseMove,
+ UseMove,
+ UseMove,
+ UseMove,
+ DefeatWithMoveType,
+ DefeatWithMoveType,
+ DefeatWithMoveType,
+ Defeat,
+ UseStrongStyleMove,
+ UseAgileStyleMove,
+
+ Evolve,
+ GiveFood,
+ StunWithItems,
+ ScareWithScatterBang,
+ LureWithPokeshiDoll,
+
+ LeapFromTrees,
+ LeapFromLeaves,
+ LeapFromSnow,
+ LeapFromOre,
+ LeapFromTussocks,
+ ];
+
+ private static ReadOnlySpan TaskIndexes =>
+ [
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 0, 1, 2, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ ];
+
private readonly int[] TaskParameters;
public SAV_PokedexResearchEditorLA(SAV8LA sav, ushort species, int dexIdx, IReadOnlyList tasks, IReadOnlyList timeTasks)
@@ -107,80 +150,6 @@ public SAV_PokedexResearchEditorLA(SAV8LA sav, ushort species, int dexIdx, IRead
NUP_LeapTussocks,
];
- TaskTypes =
- [
- Catch,
- CatchAlpha,
- CatchLarge,
- CatchSmall,
- CatchHeavy,
- CatchLight,
- CatchAtTime,
- CatchSleeping,
- CatchInAir,
- CatchNotSpotted,
-
- UseMove,
- UseMove,
- UseMove,
- UseMove,
- DefeatWithMoveType,
- DefeatWithMoveType,
- DefeatWithMoveType,
- Defeat,
- UseStrongStyleMove,
- UseAgileStyleMove,
-
- Evolve,
- GiveFood,
- StunWithItems,
- ScareWithScatterBang,
- LureWithPokeshiDoll,
-
- LeapFromTrees,
- LeapFromLeaves,
- LeapFromSnow,
- LeapFromOre,
- LeapFromTussocks,
- ];
-
- TaskIndexes =
- [
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
- -1,
-
- 0,
- 1,
- 2,
- 3,
- 0,
- 1,
- 2,
- -1,
- -1,
- -1,
-
- -1,
- -1,
- -1,
- -1,
- -1,
-
- -1,
- -1,
- -1,
- -1,
- -1,
- ];
-
TaskParameters = new int[TaskIndexes.Length];
InitializeTaskParameters(dexIdx);
#endregion
@@ -253,14 +222,10 @@ private bool IsEmpty()
if (nup.Value != 0)
return false;
}
-
return true;
}
- private void B_Cancel_Click(object sender, EventArgs e)
- {
- Close();
- }
+ private void B_Cancel_Click(object sender, EventArgs e) => Close();
private void B_Save_Click(object sender, EventArgs e)
{