mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-22 12:03:10 +00:00
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:
parent
905c80521e
commit
024bd85cc3
19 changed files with 270 additions and 263 deletions
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue