PKHeX/PKHeX.Core/Saves/Substructures/PokeDex/PokeDexEntry9SV.cs
Kurt 88830e0d00
Update from .NET Framework 4.6 to .NET 7 (#3729)
Updates from net46->net7, dropping support for mono in favor of using the latest runtime (along with the performance/API improvements). Releases will be posted as 64bit only for now.

Refactors a good amount of internal API methods to be more performant and more customizable for future updates & fixes.

Adds functionality for Batch Editor commands to `>`, `<` and <=/>=

TID/SID properties renamed to TID16/SID16 for clarity; other properties exposed for Gen7 / display variants.

Main window has a new layout to account for DPI scaling (8 point grid)

Fixed: Tatsugiri and Paldean Tauros now output Showdown form names as Showdown expects
Changed: Gen9 species now interact based on the confirmed National Dex IDs (closes #3724)
Fixed: Pokedex set all no longer clears species with unavailable non-base forms (closes #3720)
Changed: Hyper Training suggestions now apply for level 50 in SV. (closes #3714)
Fixed: B2/W2 hatched egg met locations exclusive to specific versions are now explicitly checked (closes #3691)
Added: Properties for ribbon/mark count (closes #3659)
Fixed: Traded SV eggs are now checked correctly (closes #3692)
2023-01-21 20:02:33 -08:00

140 lines
5.1 KiB
C#

using System;
using System.Buffers.Binary;
namespace PKHeX.Core;
public readonly ref struct PokeDexEntry9SV
{
public const int SIZE = 0x18;
private readonly Span<byte> Data;
public PokeDexEntry9SV(Span<byte> data) => Data = data;
public void Clear() => Data.Clear();
/* Structure: 0x18 bytes
0x0 u32 0 = not shown, 1 = shown, don't have, 2 = seen, 3 = obtained
0x4 u32 forms obtained (flags)
0x8 u16 flags for genders seen, can be on mons you don't have
01 = male seen
02 = female seen
04 = genderless seen
0x0A u16 language obtained
0x0C u8 shiny obtained (bool)
0x0D u8 New
0x0E u8 - unused alignment
0x0F u8 - unused alignment
0x10 u16? display form
0x14 u8 display gender (0 = male, 1 = female, 2 = genderless)
0x15 u8 display shiny (bool)
0x16 u8 has gender difference (bool)
0x17 u8 - unused alignment
*/
public uint GetState() => BinaryPrimitives.ReadUInt32LittleEndian(Data);
private uint FlagsFormSeen { get => BinaryPrimitives.ReadUInt32LittleEndian(Data[0x04..]); set => BinaryPrimitives.WriteUInt32LittleEndian(Data[0x04..], value); }
private ushort FlagsGenderSeen { get => BinaryPrimitives.ReadUInt16LittleEndian(Data[0x08..]); set => BinaryPrimitives.WriteUInt16LittleEndian(Data[0x08..], value); }
private ushort FlagsLanguage { get => BinaryPrimitives.ReadUInt16LittleEndian(Data[0x0A..]); set => BinaryPrimitives.WriteUInt16LittleEndian(Data[0x0A..], value); }
public bool GetSeenIsShiny() => Data[0x0C] != 0;
public bool GetDisplayIsNew() => Data[0x0D] != 0;
public byte GetUnused0E() => Data[0x0E];
public byte GetUnused0F() => Data[0x0F];
private uint DisplayFormIndex { get => BinaryPrimitives.ReadUInt32LittleEndian(Data[0x10..]); set => BinaryPrimitives.WriteUInt32LittleEndian(Data[0x10..], value); }
private byte DisplayGender { get => Data[0x14]; set => Data[0x14] = value; }
public bool GetDisplayIsShiny() => Data[0x15] != 0;
public bool GetDisplayGenderIsDifferent() => Data[0x16] != 0;
public byte GetUnused17() => Data[0x17];
public void SetState(uint value) => BinaryPrimitives.WriteUInt32LittleEndian(Data, value);
public void SetSeenIsShiny(bool value = true) => Data[0x0C] = value ? (byte)1 : (byte)0;
public void SetDisplayIsNew(bool value = true) => Data[0x0D] = value ? (byte)1 : (byte)0;
public void SetUnused0E(byte value) => Data[0x0E] = value;
public void SetUnused0F(byte value) => Data[0x0F] = value;
public void SetDisplayIsShiny(bool value = true) => Data[0x15] = value ? (byte)1 : (byte)0;
public void SetDisplayGenderIsDifferent(bool value = true) => Data[0x16] = value ? (byte)1 : (byte)0;
public void SetUnused17(byte value) => Data[0x17] = value;
public bool IsUnknown => GetState() == 0;
public bool IsKnown => GetState() != 0;
public bool IsSeen => GetState() >= 2;
public bool IsCaught => GetState() >= 3;
public void SetCaught(bool value) => SetState(value ? 3u : 2u);
public void SetSeen(bool value)
{
var newValue = !value ? 1 : Math.Min(GetState(), 2);
SetState(newValue);
}
public bool GetIsGenderSeen(int gender) => (FlagsGenderSeen & (1u << gender)) != 0;
public void SetIsGenderSeen(int gender, bool value)
{
if (value)
FlagsGenderSeen |= (ushort)(1u << gender);
else
FlagsGenderSeen &= (ushort)~(1u << gender);
}
public bool GetIsFormSeen(byte form) => (FlagsFormSeen & (1u << form)) != 0;
public void SetIsFormSeen(byte form, bool value)
{
if (value)
FlagsFormSeen |= 1u << form;
else
FlagsFormSeen &= ~(1u << form);
}
public uint GetDisplayForm() => DisplayFormIndex;
public void SetDisplayForm(uint form) => DisplayFormIndex = form;
public static int GetDexLangFlag(int lang) => lang switch
{
> 10 or 6 or <= 0 => 0, // invalid language
// skip over langID 0 (unused) => [0-8]
// skip over langID 6 (unused)
>= 7 => lang - 2,
_ => lang - 1,
};
private static int GetLanguageBitMask(int langIndex) => 1 << GetDexLangFlag(langIndex);
public bool GetLanguageFlag(int langIndex) => (FlagsLanguage & GetLanguageBitMask(langIndex)) != 0;
public void SetLanguageFlag(int langIndex, bool value)
{
var mask = GetLanguageBitMask(langIndex);
if (value)
FlagsLanguage |= (ushort)mask;
else
FlagsLanguage &= (ushort)~mask;
}
public uint GetDisplayGender() => DisplayGender switch
{
0 => 0,
1 => 1,
_ => 2,
};
public void SetDisplayGender(int value)
{
DisplayGender = value switch
{
0 => 0,
1 => 1,
_ => 2,
};
}
public void ClearCaught()
{
SetCaught(false);
SetSeenIsShiny(false);
SetDisplayForm(0);
SetDisplayGender(0);
SetDisplayIsShiny(false);
SetDisplayGenderIsDifferent(false);
FlagsLanguage = 0;
}
}