2023-01-22 04:02:33 +00:00
|
|
|
using System;
|
2020-05-25 00:31:10 +00:00
|
|
|
using System.ComponentModel;
|
2022-01-03 05:35:59 +00:00
|
|
|
using static System.Buffers.Binary.BinaryPrimitives;
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
namespace PKHeX.Core;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Swarm and other overworld info
|
|
|
|
/// </summary>
|
|
|
|
public sealed class Encount6 : SaveBlock<SAV6>
|
2020-05-25 00:31:10 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
public Encount6(SAV6XY SAV, int offset) : base(SAV) => Offset = offset;
|
|
|
|
public Encount6(SAV6AO SAV, int offset) : base(SAV) => Offset = offset;
|
|
|
|
|
|
|
|
public ushort RepelItemUsed { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x00), value); }
|
|
|
|
public byte RepelSteps { get => Data[Offset + 0x02]; set => Data[Offset + 0x02] = value; }
|
|
|
|
|
|
|
|
// 0x04
|
|
|
|
|
|
|
|
public PokeRadar6 Radar
|
2020-05-25 00:31:10 +00:00
|
|
|
{
|
2023-11-09 07:33:02 +00:00
|
|
|
get => new(Data.AsMemory(Offset + 0x04, PokeRadar6.SIZE));
|
|
|
|
set => value.Data.CopyTo(Data.AsMemory(Offset + 0x04));
|
2022-06-18 18:04:24 +00:00
|
|
|
}
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
// 0x1C
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
public Roamer6 Roamer
|
|
|
|
{
|
2023-11-09 07:33:02 +00:00
|
|
|
get => new(Data.AsMemory(Offset + 0x1C, Roamer6.SIZE));
|
|
|
|
set => value.Data.CopyTo(Data.AsMemory(Offset + 0x1C, Roamer6.SIZE));
|
2022-06-18 18:04:24 +00:00
|
|
|
}
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
// 0x44
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
// 4 bytes at end??
|
|
|
|
}
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
[TypeConverter(typeof(ValueTypeTypeConverter))]
|
|
|
|
public sealed class PokeRadar6
|
|
|
|
{
|
|
|
|
public const int SIZE = 2 + (RecordCount * PokeRadarRecord.SIZE); // 0x18
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
private const int MaxCharge = 50;
|
|
|
|
private const int RecordCount = 5;
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
public readonly Memory<byte> Data;
|
|
|
|
private Span<byte> Span => Data.Span;
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
public PokeRadar6(Memory<byte> data) => Data = data;
|
2022-06-18 18:04:24 +00:00
|
|
|
public override string ToString() => ((Species)PokeRadarSpecies).ToString();
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
public ushort PokeRadarSpecies { get => ReadUInt16LittleEndian(Span[0..2]); set => WriteUInt16LittleEndian(Span[0..2], value); }
|
|
|
|
private ushort PokeRadarPacked { get => ReadUInt16LittleEndian(Span[2..4]); set => WriteUInt16LittleEndian(Span[2..4], value); }
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
public int PokeRadarCharge { get => PokeRadarPacked & 0x3FFF; set => PokeRadarPacked = (ushort)((PokeRadarPacked & ~0x3FFF) | Math.Min(MaxCharge, value)); }
|
|
|
|
public bool PokeRadarFlag1 { get => PokeRadarPacked >> 14 != 0; set => PokeRadarPacked = (ushort)((PokeRadarPacked & ~(1 << 14)) | (value ? (1 << 14) : 0)); }
|
|
|
|
public bool PokeRadarFlag2 { get => PokeRadarPacked >> 15 != 0; set => PokeRadarPacked = (ushort)((PokeRadarPacked & ~(1 << 15)) | (value ? (1 << 15) : 0)); }
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
public PokeRadarRecord GetRecord(int index) => PokeRadarRecord.ReadRecord(Span[GetRecordOffset(index)..]);
|
|
|
|
public void SetRecord(PokeRadarRecord record, int index) => record.WriteRecord(Span[GetRecordOffset(index)..]);
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
private static int GetRecordOffset(int index)
|
|
|
|
{
|
|
|
|
if ((uint) index >= RecordCount)
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(index));
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
return 6 + (index * 2);
|
|
|
|
}
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
public PokeRadarRecord Record1 { get => GetRecord(0); set => SetRecord(value, 0); }
|
|
|
|
public PokeRadarRecord Record2 { get => GetRecord(1); set => SetRecord(value, 1); }
|
|
|
|
public PokeRadarRecord Record3 { get => GetRecord(2); set => SetRecord(value, 2); }
|
|
|
|
public PokeRadarRecord Record4 { get => GetRecord(3); set => SetRecord(value, 3); }
|
|
|
|
public PokeRadarRecord Record5 { get => GetRecord(4); set => SetRecord(value, 4); }
|
|
|
|
}
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
[TypeConverter(typeof(ValueTypeTypeConverter))]
|
|
|
|
public sealed class PokeRadarRecord
|
|
|
|
{
|
|
|
|
public const int SIZE = 4;
|
|
|
|
public override string ToString() => ((Species)Species).ToString();
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
public ushort Species { get; set; }
|
|
|
|
public ushort Count { get; set; }
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
private PokeRadarRecord(ushort species, ushort count)
|
|
|
|
{
|
|
|
|
Species = species;
|
|
|
|
Count = count;
|
2020-05-25 00:31:10 +00:00
|
|
|
}
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
public static PokeRadarRecord ReadRecord(ReadOnlySpan<byte> data)
|
2020-05-25 00:31:10 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
var species = ReadUInt16LittleEndian(data);
|
|
|
|
var count = ReadUInt16LittleEndian(data[2..]);
|
|
|
|
return new PokeRadarRecord(species, count);
|
2020-05-25 00:31:10 +00:00
|
|
|
}
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
public void WriteRecord(Span<byte> data)
|
2020-05-25 00:31:10 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
WriteUInt16LittleEndian(data, Species);
|
|
|
|
WriteUInt16LittleEndian(data[2..], Count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[TypeConverter(typeof(ValueTypeTypeConverter))]
|
|
|
|
public sealed class Roamer6
|
|
|
|
{
|
|
|
|
public const int SIZE = 0x28;
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
public readonly Memory<byte> Data;
|
|
|
|
private Span<byte> Span => Data.Span;
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
public Roamer6(Memory<byte> data) => Data = data;
|
2022-06-18 18:04:24 +00:00
|
|
|
public override string ToString() => ((Species)Species).ToString();
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
private ushort SpecForm { get => ReadUInt16LittleEndian(Span[0..2]); set => WriteUInt16LittleEndian(Span[0..2], value); }
|
2023-01-22 04:02:33 +00:00
|
|
|
public ushort Species { get => (ushort)(SpecForm & 0x3FF); set => SpecForm = (ushort)((SpecForm & ~0x3FF) | (value & 0x3FF)); }
|
2022-06-18 18:04:24 +00:00
|
|
|
public bool Flag1 { get => SpecForm >> 14 != 0; set => SpecForm = (ushort)((SpecForm & 0xBFFF) | (value ? (1 << 14) : 0)); }
|
|
|
|
public bool Flag2 { get => SpecForm >> 15 != 0; set => SpecForm = (ushort)((SpecForm & 0x7FFF) | (value ? (1 << 15) : 0)); }
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
public int CurrentLevel { get => Span[4]; set => Span[4] = (byte)value; }
|
|
|
|
private int Status { get => Span[7]; set => Span[7] = (byte)value; }
|
2022-06-18 18:04:24 +00:00
|
|
|
public Roamer6State RoamStatus { get => (Roamer6State)((Status >> 4) & 0xF); set => Status = (Status & 0x0F) | (((int)value << 4) & 0xF0); }
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2023-11-09 07:33:02 +00:00
|
|
|
public uint TimesEncountered { get => ReadUInt32LittleEndian(Span[36..40]); set => WriteUInt32LittleEndian(Span[36..40], value); }
|
2022-06-18 18:04:24 +00:00
|
|
|
}
|
2020-05-25 00:31:10 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
public enum Roamer6State
|
|
|
|
{
|
|
|
|
Inactive,
|
|
|
|
Roaming,
|
|
|
|
Stationary,
|
|
|
|
Defeated,
|
|
|
|
Captured,
|
2020-05-25 00:31:10 +00:00
|
|
|
}
|