Add Swarm data get/set for gen3-5

#3245
This commit is contained in:
Kurt 2021-08-20 19:52:31 -07:00
parent cd12962a50
commit 48024f1245
20 changed files with 167 additions and 32 deletions

View File

@ -15,5 +15,6 @@ public interface ISaveBlock5BW
BattleSubway5 BattleSubway { get; }
Entralink5 Entralink { get; }
Musical5 Musical { get; }
Encount5 Encount { get; }
}
}

View File

@ -96,6 +96,7 @@ public SaveBlockAccessor5B2W2(SAV5B2W2 sav)
Misc = new Misc5B2W2(sav, 0x21100);
Entralink = new Entralink5B2W2(sav, 0x21200);
Zukan = new Zukan5(sav, 0x21400, 0x328); // form flags size is + 8 from bw with new forms (therians)
Encount = new Encount5B2W2(sav, 0x21900);
BattleSubway = new BattleSubway5(sav, 0x21B00);
PWT = new PWTBlock5(sav, 0x23700);
Festa = new FestaBlock5(sav, 0x25900);
@ -114,5 +115,6 @@ public SaveBlockAccessor5B2W2(SAV5B2W2 sav)
public Entralink5 Entralink { get; }
public FestaBlock5 Festa { get; }
public Musical5 Musical { get; }
public Encount5 Encount { get; }
}
}

View File

@ -92,6 +92,7 @@ public SaveBlockAccessor5BW(SAV5BW sav)
Misc = new Misc5BW(sav, 0x21200);
Entralink = new Entralink5BW(sav, 0x21300);
Zukan = new Zukan5(sav, 0x21600, 0x320);
Encount = new Encount5BW(sav, 0x21B00);
BattleSubway = new BattleSubway5(sav, 0x21D00);
}
@ -106,5 +107,6 @@ public SaveBlockAccessor5BW(SAV5BW sav)
public BattleSubway5 BattleSubway { get; }
public Entralink5 Entralink { get; }
public Musical5 Musical { get; }
public Encount5 Encount { get; }
}
}

View File

@ -154,6 +154,12 @@ public DecorationInventory3 Decorations
set => SetData(Large, value.ToBytes(), 0x2734);
}
public Swarm3 Swarm
{
get => Large.Slice(0x2B90, Swarm3.SIZE).ToClass<Swarm3>();
set => SetData(Large, value.ToBytesClass(), 0x2B90);
}
protected override int MailOffset => 0x2BE0;
protected override int GetDaycareEXPOffset(int slot) => GetDaycareSlotOffset(0, slot + 1) - 4; // @ end of each pkm slot

View File

@ -117,6 +117,12 @@ public DecorationInventory3 Decorations
set => SetData(Large, value.ToBytes(), 0x26A0);
}
public Swarm3 Swarm
{
get => Large.Slice(0x2AFC, Swarm3.SIZE).ToClass<Swarm3>();
set => SetData(Large, value.ToBytesClass(), 0x2AFC);
}
protected override int MailOffset => 0x2B4C;
protected override int GetDaycareEXPOffset(int slot) => GetDaycareSlotOffset(0, 2) + (2 * 0x38) + (4 * slot); // consecutive vals, after both consecutive slots & 2 mail

View File

@ -534,5 +534,19 @@ public Mail4 GetMail(int mailIndex)
int ofs = GetMailOffset(mailIndex);
return new Mail4(GetMailData(ofs), ofs);
}
public abstract uint SwarmSeed { get; set; }
public abstract uint SwarmMaxCountModulo { get; }
public uint SwarmIndex
{
get => SwarmSeed % SwarmMaxCountModulo;
set
{
value %= SwarmMaxCountModulo;
while (SwarmIndex != value)
++SwarmSeed;
}
}
}
}

View File

@ -148,5 +148,9 @@ private void SetActiveGiftFlags(IReadOnlyList<MysteryGift> gifts)
public override int X2 { get => BitConverter.ToUInt16(General, 0x25FA); set => BitConverter.GetBytes((ushort)value).CopyTo(General, 0x25FA); }
public override int Y2 { get => BitConverter.ToUInt16(General, 0x25FE); set => BitConverter.GetBytes((ushort)value).CopyTo(General, 0x25FE); }
public override int Z { get => BitConverter.ToUInt16(General, 0x2602); set => BitConverter.GetBytes((ushort)value).CopyTo(General, 0x2602); }
public override uint SafariSeed { get => BitConverter.ToUInt32(General, 0x72D0); set => BitConverter.GetBytes(value).CopyTo(General, 0x72D0); }
public override uint SwarmSeed { get => BitConverter.ToUInt32(General, 0x72D4); set => BitConverter.GetBytes(value).CopyTo(General, 0x72D4); }
public override uint SwarmMaxCountModulo => 28;
}
}

View File

@ -234,5 +234,8 @@ public void PokeGearUnlockAllCallersNoTrainers()
public void SetPokewalkerCoursesUnlocked(bool[] value) => ArrayUtil.SetBitFlagArray(General, OFS_WALKER + 0x8, value);
public void PokewalkerCoursesSetAll(uint value = 0x07FF_FFFFu) => SetData(General, BitConverter.GetBytes(value), OFS_WALKER + 0x8);
public override uint SwarmSeed { get => BitConverter.ToUInt32(General, 0x68A8); set => BitConverter.GetBytes(value).CopyTo(General, 0x68A8); }
public override uint SwarmMaxCountModulo => 20;
}
}

View File

@ -114,5 +114,9 @@ public override IReadOnlyList<InventoryPouch> Inventory
public override int X2 { get => BitConverter.ToUInt16(General, 0x287E); set => BitConverter.GetBytes((ushort)value).CopyTo(General, 0x287E); }
public override int Y2 { get => BitConverter.ToUInt16(General, 0x2882); set => BitConverter.GetBytes((ushort)value).CopyTo(General, 0x2882); }
public override int Z { get => BitConverter.ToUInt16(General, 0x2886); set => BitConverter.GetBytes((ushort)value).CopyTo(General, 0x2886); }
public override uint SafariSeed { get => BitConverter.ToUInt32(General, 0x72D4); set => BitConverter.GetBytes(value).CopyTo(General, 0x72D4); }
public override uint SwarmSeed { get => BitConverter.ToUInt32(General, 0x72D8); set => BitConverter.GetBytes(value).CopyTo(General, 0x72D8); }
public override uint SwarmMaxCountModulo => 22;
}
}

View File

@ -182,6 +182,10 @@ private static int[] CalculateMunchlaxTrees(int tid, int sid)
public void SetUGI_Spheres(byte[] value) => SetData(General, value, OFS_UG_Items + 0x78);
#endregion
public abstract uint SafariSeed { get; set; }
public uint GetSafariIndex(int slot) => (SafariSeed >> (slot * 5)) & 0x1F;
public void SetSafariIndex(int slot, uint value) => SafariSeed = (SafariSeed & ~(0x1Fu << (slot * 5))) | (value << (slot * 5));
}
public enum PoketchColor

View File

@ -206,6 +206,7 @@ public EntreeForest EntreeData
public abstract BattleSubway5 BattleSubway { get; }
public abstract Entralink5 Entralink { get; }
public abstract Musical5 Musical { get; }
public abstract Encount5 Encount { get; }
public static int GetMailOffset(int index) => (index * Mail5.SIZE) + 0x1DD00;
public byte[] GetMailData(int offset) => GetData(offset, Mail5.SIZE);

View File

@ -51,6 +51,7 @@ private void Initialize()
public override BattleSubway5 BattleSubway => Blocks.BattleSubway;
public override Entralink5 Entralink => Blocks.Entralink;
public override Musical5 Musical => Blocks.Musical;
public override Encount5 Encount => Blocks.Encount;
public FestaBlock5 Festa => Blocks.Festa;
public PWTBlock5 PWT => Blocks.PWT;
public override int Fused => 0x1FA00 + sizeof(uint);

View File

@ -51,6 +51,7 @@ private void Initialize()
public override BattleSubway5 BattleSubway => Blocks.BattleSubway;
public override Entralink5 Entralink => Blocks.Entralink;
public override Musical5 Musical => Blocks.Musical;
public override Encount5 Encount => Blocks.Encount;
public override int Fused => int.MinValue;
public override int GTS => 0x20500;
}

View File

@ -9,6 +9,7 @@ public interface IGen3Hoenn
RTC3 ClockElapsed { get; set; }
PokeBlock3Case PokeBlocks { get; set; }
DecorationInventory3 Decorations { get; set; }
Swarm3 Swarm { get; set; }
bool HasReceivedWishmkrJirachi { get; set; }
}
}

View File

@ -3,7 +3,7 @@
namespace PKHeX.Core
{
internal static class StructConverter
public static class StructConverter
{
public static T ToStructure<T>(this byte[] bytes) where T : struct
{

View File

@ -0,0 +1,23 @@
using System.Runtime.InteropServices;
namespace PKHeX.Core
{
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = SIZE)]
public sealed class Swarm3
{
public const int SIZE = 0x14;
public ushort Species { get; set; }
public byte MapNum { get; set; }
public byte MapGroup { get; set; }
public byte Level { get; set; }
// 3byte align
public ushort Move1 { get; set; }
public ushort Move2 { get; set; }
public ushort Move3 { get; set; }
public ushort Move4 { get; set; }
public byte Zero { get; set; }
public byte EncounterProbability { get; set; }
public ushort DaysLeft { get; set; }
}
}

View File

@ -0,0 +1,39 @@
using System;
namespace PKHeX.Core
{
public abstract class Encount5 : SaveBlock
{
protected Encount5(SAV5 SAV, int offset) : base(SAV) => Offset = offset;
public abstract uint SwarmSeed { get; set; }
public abstract uint SwarmMaxCountModulo { get; }
public uint SwarmIndex
{
get => SwarmSeed % SwarmMaxCountModulo;
set
{
value %= SwarmMaxCountModulo;
while (SwarmIndex != value)
++SwarmSeed;
}
}
}
public sealed class Encount5BW : Encount5
{
public Encount5BW(SAV5BW SAV, int offset) : base(SAV, offset) { }
public override uint SwarmSeed { get => BitConverter.ToUInt32(Data, Offset + 0x30); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x30); }
public override uint SwarmMaxCountModulo => 17;
}
public sealed class Encount5B2W2 : Encount5
{
public Encount5B2W2(SAV5B2W2 SAV, int offset) : base(SAV, offset) { }
public override uint SwarmSeed { get => BitConverter.ToUInt32(Data, Offset + 0x2C); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x2C); }
public override uint SwarmMaxCountModulo => 19;
}
}

View File

@ -19,37 +19,6 @@ public ushort BlackCityLevel
}
}
public sealed class Musical5 : SaveBlock
{
public Musical5(SAV5BW SAV, int offset) : base(SAV) => Offset = offset;
public Musical5(SAV5B2W2 SAV, int offset) : base(SAV) => Offset = offset;
private const int PropOffset = 0x258;
public void UnlockAllMusicalProps()
{
// 101 props, which is 12.X bytes of bitflags.
var bitFieldOffset = Offset + PropOffset;
for (int i = 0; i < 0xC; i++)
Data[bitFieldOffset + i] = 0xFF;
Data[bitFieldOffset + 0xC] = 0x1F; // top 3 bits unset, to complete multiple of 8 (101=>104 bits).
}
public bool GetHasProp(int prop)
{
var bitFieldOffset = Offset + PropOffset;
var bitOffset = prop >> 3;
return SAV.GetFlag(bitFieldOffset + bitOffset, prop & 7);
}
public void SetHasProp(int prop, bool value = true)
{
var bitFieldOffset = Offset + PropOffset;
var bitOffset = prop >> 3;
SAV.SetFlag(bitFieldOffset + bitOffset, prop & 7, value);
}
}
public sealed class Entralink5BW : Entralink5
{
public Entralink5BW(SAV5BW SAV, int offset) : base(SAV, offset) { }

View File

@ -0,0 +1,33 @@
namespace PKHeX.Core
{
public sealed class Musical5 : SaveBlock
{
public Musical5(SAV5BW SAV, int offset) : base(SAV) => Offset = offset;
public Musical5(SAV5B2W2 SAV, int offset) : base(SAV) => Offset = offset;
private const int PropOffset = 0x258;
public void UnlockAllMusicalProps()
{
// 101 props, which is 12.X bytes of bitflags.
var bitFieldOffset = Offset + PropOffset;
for (int i = 0; i < 0xC; i++)
Data[bitFieldOffset + i] = 0xFF;
Data[bitFieldOffset + 0xC] = 0x1F; // top 3 bits unset, to complete multiple of 8 (101=>104 bits).
}
public bool GetHasProp(int prop)
{
var bitFieldOffset = Offset + PropOffset;
var bitOffset = prop >> 3;
return SAV.GetFlag(bitFieldOffset + bitOffset, prop & 7);
}
public void SetHasProp(int prop, bool value = true)
{
var bitFieldOffset = Offset + PropOffset;
var bitOffset = prop >> 3;
SAV.SetFlag(bitFieldOffset + bitOffset, prop & 7, value);
}
}
}

View File

@ -0,0 +1,21 @@
using FluentAssertions;
using PKHeX.Core;
using Xunit;
namespace PKHeX.Tests.General
{
public class MarshalTests
{
[Fact]
public void MarshalStructure()
{
new DecorationInventory3().ToBytes().Length.Should().Be(DecorationInventory3.SIZE);
}
[Fact]
public void MarshalClass()
{
new Swarm3().ToBytesClass().Length.Should().Be(Swarm3.SIZE);
}
}
}