using System;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
///
/// SUBE block that stores in-game event results.
///
public abstract class SubEventLog6 : SaveBlock, IGymTeamInfo
{
protected SubEventLog6(SAV6 sav, int offset) : base(sav) => Offset = offset;
protected abstract int BadgeVictoryOffset { get; }
///
/// Absolute offset of the that the player has given an NPC.
///
public abstract int Give { get; }
///
/// Absolute offset of the that is unreferenced?
///
public abstract int UnusedPKM { get; }
private int GetBadgeVictorySpeciesOffset(uint badge, uint slot)
{
if (badge >= 8)
throw new ArgumentOutOfRangeException(nameof(badge));
if (slot >= 6)
throw new ArgumentOutOfRangeException(nameof(slot));
return Offset + BadgeVictoryOffset + (int)(((6 * badge) + slot) * sizeof(ushort));
}
public ushort GetBadgeVictorySpecies(uint badge, uint slot)
{
var ofs = GetBadgeVictorySpeciesOffset(badge, slot);
return ReadUInt16LittleEndian(Data.AsSpan(ofs));
}
public void SetBadgeVictorySpecies(uint badge, uint slot, ushort species)
{
var ofs = GetBadgeVictorySpeciesOffset(badge, slot);
WriteUInt16LittleEndian(Data.AsSpan(ofs), species);
}
}
public sealed class SubEventLog6XY : SubEventLog6
{
public SubEventLog6XY(SAV6XY sav, int offset) : base(sav, offset) { }
// Structure:
// 0x00
// u8[0x28] chateau data
private ushort ChateauValue
{
get => ReadUInt16LittleEndian(Data.AsSpan(Offset));
set => WriteUInt16LittleEndian(Data.AsSpan(Offset), value);
}
public ushort ChateauRank
{
get => (ushort)(ChateauValue & 0xF);
set => ChateauValue = (ushort)((ChateauValue & ~0xFu) | (value & 0xFu));
}
public ushort ChateauPoints
{
get => (ushort)(ChateauValue >> 4);
set => ChateauValue = (ushort)((ushort)(value << 4) | (ChateauValue & 0xFu));
}
// other chateau data?
// u32 SUBE @ 0x28
// 0x2C
protected override int BadgeVictoryOffset => 0x2C; // thru 0x8B
// u16[6 * 8] trainer teams for gyms
// u32 SUBE @ 0x8C
// 0x90
// u8[0xE8] pk?
public override int Give => 0x90 + Offset;
// u32 SUBE @ 0x178
// 0x17C
// u8[0xE8] pk?
public override int UnusedPKM => 0x17C + Offset;
// u32 SUBE @ 0x264
// 0x268
// u8[0xA0] unused?
}
public sealed class SubEventLog6AO : SubEventLog6
{
public SubEventLog6AO(SAV6AO sav, int offset) : base(sav, offset) { }
// Structure:
// 0x00
// u8[0x5A] trainer rematch flags
// u8[2] unused (alignment)
// u32 SUBE @ 0x5C
// 0x60
protected override int BadgeVictoryOffset => 0x60; // thru 0xBF
// u16[6 * 8] trainer teams for gyms
// u32 SUBE @ 0xC0
// 0xC4
// u8[0xE8] pk?
public override int Give => 0xC4 + Offset;
// u32 SUBE @ 0x1AC
// 0x1B0
// u8[0xE8] pk?
public override int UnusedPKM => 0x1B0 + Offset;
// u32 SUBE @ 0x298
// 0x29C
// u16 SeasideCyclingRoadTimeMilliseconds 29C
public ushort SeasideCyclingRoadTimeMilliseconds
{
get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x29C));
set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x29C), value);
}
// u16 SeasideCyclingRoadCollisions 29E
public ushort SeasideCyclingRoadCollisions
{
get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x29E));
set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x29E), value);
}
// u16[7] 2A0
// u16[7] 2AE
// u16[17] 2BC
// u16[7] 2EA
// u16 2EC
// u16 2EE
// u16 2F0
// u16 2F2
// u32 SUBE @ 0x2F4
// 0x2F8
// u64[27] Ending Scroll ec-specform data -- player pk used & NPC used during storyline battles
// u32 ec
// u32 species:10
// u32 form:5
// u32 gender:2
// u32 isShiny:1
// u32 unused:14
// u8[16]
// u8[32] unused?
}