Minor tweaks

make PL6 use memory instead of byte[]
make GP1 use memory instead of byte[]
move IEncounterable properties higher to IEncounterTemplate
This commit is contained in:
Kurt 2024-03-24 20:12:33 -05:00
parent 905c80521e
commit 024bd85cc3
19 changed files with 270 additions and 263 deletions

View file

@ -6,9 +6,10 @@ namespace PKHeX.Core;
/// <summary>
/// Generation 7 PGL QR Code encoded <see cref="PKM"/> entities.
/// </summary>
public sealed class QRPK7(byte[] Data) : IEncounterInfo
public sealed class QRPK7(Memory<byte> Raw) : IEncounterInfo
{
private readonly byte[] Data = (byte[])Data.Clone();
public const int SIZE = 0x30;
private Span<byte> 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];

View file

@ -203,6 +203,11 @@ public static class EncounterMovesetGenerator
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<ushort> moves, GameVersion version, byte generation, EntityContext context)

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
namespace PKHeX.Core;
@ -81,9 +80,9 @@ public sealed record EncounterTrade1 : IEncounterable, IEncounterMatch, IFixedTr
private int GetNicknameIndex(ReadOnlySpan<char> nickname) => GetIndex(nickname, Nicknames);
private static int GetIndex(ReadOnlySpan<char> name, IReadOnlyList<string> arr)
private static int GetIndex(ReadOnlySpan<char> name, ReadOnlySpan<string> arr)
{
for (int i = 0; i < arr.Count; i++)
for (int i = 0; i < arr.Length; i++)
{
if (name.SequenceEqual(arr[i]))
return i;

View file

@ -3,7 +3,7 @@ namespace PKHeX.Core;
/// <summary>
/// Represents all details that an entity may be encountered with.
/// </summary>
public interface IEncounterTemplate : ISpeciesForm, IVersion, IGeneration, IShiny, ILevelRange
public interface IEncounterTemplate : ISpeciesForm, IVersion, IGeneration, IShiny, ILevelRange, ILocation, IFixedAbilityNumber, IFixedBall, IShinyPotential
{
/// <summary>
/// Original Context
@ -27,6 +27,10 @@ public static partial class Extensions
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);
}
}

View file

@ -1,10 +1,10 @@
namespace PKHeX.Core;
namespace PKHeX.Core;
/// <summary>
/// Common Encounter Properties base interface.
/// <inheritdoc cref="IEncounterInfo"/>
/// </summary>
public interface IEncounterable : IEncounterInfo, ILocation, IFixedAbilityNumber, IFixedBall, IShinyPotential
public interface IEncounterable : IEncounterInfo
{
/// <summary>
/// Short name to describe the encounter data, usually just indicating which of the main component encounter types the data is.

View file

@ -33,7 +33,6 @@ public static class MystryMew
0xFE9D,
];
//private const int FramesPerMew = 5;
private const int MewPerRestrictedSeed = 5;
/// <summary>
@ -70,9 +69,9 @@ public static class MystryMew
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 class MystryMew
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);

View file

@ -17,11 +17,8 @@ public static class AbilityChangeRules
/// <param name="current">Current context</param>
/// <param name="original">Original context</param>
/// <returns>True if possible to obtain <see cref="abilityFlag"/></returns>
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);
/// <summary>
/// Checks if the current <see cref="abilityFlag"/> value is possible to obtain based on the original <see cref="ability"/> and game visiting.
@ -51,11 +48,8 @@ public static class AbilityChangeRules
/// <param name="current">Current context</param>
/// <param name="original">Original context</param>
/// <returns>True if the ability can be changed</returns>
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);
/// <summary>
/// Checks if the original <see cref="ability"/> value can be changed based on the games visited.

View file

@ -10,15 +10,14 @@ namespace PKHeX.Core;
/// This Template object is very similar to the <see cref="PCD"/> structure in that it stores more data than just the gift.
/// This template object is only present in Generation 6 save files.
/// </remarks>
public sealed class PL6
public sealed class PL6(Memory<byte> 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<byte> Data => Raw.Span;
/// <summary>
/// Pokémon Link Flag
@ -31,7 +30,7 @@ public sealed class PL6
public bool Enabled { get => (Flags & 0x80) != 0; set => Flags = value ? (byte)(1 << 7) : (byte)0; }
private Span<byte> Source => Data.AsSpan(0x01, 110);
private Span<byte> Source => Data.Slice(0x01, 110);
/// <summary>
/// Name of data source
@ -39,37 +38,37 @@ public sealed class PL6
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); }
}
/// <summary>
@ -79,44 +78,46 @@ public sealed class PL6
/// This Template object is very similar to the <see cref="WC6"/> structure and similar objects, in that the structure offsets are ordered the same.
/// This template object is only present in Generation 6 save files.
/// </remarks>
public sealed class PL6_PKM(byte[] Data) : IRibbonSetEvent3, IRibbonSetEvent4, IEncounterInfo, IMoveset, IRelearn,
IContestStats, IMemoryOT, ITrainerID32, ILocation
public sealed class LinkEntity6(Memory<byte> Raw) : IRibbonSetEvent3, IRibbonSetEvent4, IEncounterInfo, IMoveset, IRelearn,
IContestStats, IMemoryOT, ITrainerID32
{
internal const int Size = 0xA0;
public readonly byte[] Data = Data;
public Span<byte> 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<byte> 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 sealed class PL6_PKM(byte[] Data) : IRibbonSetEvent3, IRibbonSetEvent4, I
public byte OTGender { get => Data[0x4D]; set => Data[0x4D] = value; }
public Span<byte> 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 sealed class PL6_PKM(byte[] Data) : IRibbonSetEvent3, IRibbonSetEvent4, I
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);
}
}

View file

@ -160,8 +160,7 @@ public sealed class WC3(GameVersion Version, bool Fateful = false)
}
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

View file

@ -108,8 +108,8 @@ public sealed class LegalityRejuvenator : IEntityRejuvenator
{
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;
}

View file

@ -8,21 +8,11 @@ public sealed class LinkBlock6 : SaveBlock<SAV6>
public LinkBlock6(SAV6XY sav, Memory<byte> raw) : base(sav, raw) { }
public LinkBlock6(SAV6AO sav, Memory<byte> raw) : base(sav, raw) { }
public Span<byte> InfoSpan() => Data.Slice(0x1FF, PL6.Size);
public Memory<byte> PL6 => Raw.Slice(0x1FF, Core.PL6.Size);
public PL6 GetLinkInfo() => new(InfoSpan().ToArray());
public PL6 Gifts => new(PL6);
public void SetLinkInfoData(ReadOnlySpan<byte> 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)

View file

@ -8,11 +8,11 @@ namespace PKHeX.Core;
/// <summary>
/// Go Park Entity transferred from <see cref="GameVersion.GO"/> to <see cref="GameVersion.GG"/>.
/// </summary>
public sealed class GP1(byte[] Data)
: IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOnly, IEncounterConvertible<PB7>
public sealed class GP1(Memory<byte> Raw)
: IEncounterInfo, IScaledSizeReadOnly, IEncounterConvertible<PB7>
{
public const int SIZE = 0x1B0;
public readonly byte[] Data = Data;
public Span<byte> 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<byte> data) => Data.CopyTo(data);
@ -55,17 +59,17 @@ public sealed class GP1(byte[] Data)
private static string GetString(ReadOnlySpan<byte> 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 sealed class GP1(byte[] Data)
}
}
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 sealed class GP1(byte[] Data)
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<string> Genders = GameInfo.GenderSymbolASCII;
public string GenderString => (uint) Gender >= Genders.Count ? string.Empty : Genders[Gender];
@ -152,14 +156,13 @@ public sealed class GP1(byte[] Data)
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 sealed class GP1(byte[] Data)
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 sealed class GP1(byte[] Data)
Span<ushort> 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;

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -224,21 +225,27 @@ public static class BoxUtil
/// <returns>Returns default English box names in the event the save file does not have names (not exportable), or fails to return a box name.</returns>
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<string> 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;
}
}

View file

@ -259,9 +259,9 @@ public static class SpriteUtil
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 class SpriteUtil
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);
}

View file

@ -180,11 +180,11 @@ public partial class BoxEditor : UserControl, ISlotViewer<PictureBox>
CurrentBox = box;
}
private static bool GetIsSame(IReadOnlyList<string> a, IList b)
private static bool GetIsSame(ReadOnlySpan<string> 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;

View file

@ -274,9 +274,9 @@ public sealed class SlotChangeManager(SAVEditor se) : IDisposable
/// <param name="e">Args</param>
/// <param name="badDest">Destination slot disallows eggs/blanks</param>
/// <returns>True if loaded</returns>
private bool TryLoadFiles(IReadOnlyList<string> files, DragEventArgs e, bool badDest)
private bool TryLoadFiles(ReadOnlySpan<string> files, DragEventArgs e, bool badDest)
{
if (files.Count == 0)
if (files.Length == 0)
return false;
var sav = Drag.Info.Destination!.View.SAV;

View file

@ -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 partial class SAV_Link6 : Form
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
SAV = (ISaveBlock6Main)(Origin = sav).Clone();
var filtered = GameInfo.FilteredSources;
foreach (var cb in TAB_Items.Controls.OfType<ComboBox>())
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 @@ public partial class SAV_Link6 : Form
{ 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 @@ public partial class SAV_Link6 : Form
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;
}
}

View file

@ -207,7 +207,7 @@ public partial class SAV_Trainer7GG : Form
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 @@ public partial class SAV_Trainer7GG : Form
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 @@ public partial class SAV_Trainer7GG : Form
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)

View file

@ -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<PokedexResearchTaskType8a> 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<sbyte> 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<string> tasks, IReadOnlyList<string> timeTasks)
@ -107,80 +150,6 @@ public partial class SAV_PokedexResearchEditorLA : Form
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 @@ public partial class SAV_PokedexResearchEditorLA : Form
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)
{