diff --git a/pkNX.Containers/GARC/GARC.cs b/pkNX.Containers/GARC/GARC.cs
index 51337736..8592f6c1 100644
--- a/pkNX.Containers/GARC/GARC.cs
+++ b/pkNX.Containers/GARC/GARC.cs
@@ -127,7 +127,7 @@ public override void Dump(string path, ContainerHandler handler)
br.BaseStream.Position = 10;
var ver = br.ReadUInt16();
- if (ver == 0x0600 || ver == 0x0400)
+ if (ver is 0x0600 or 0x0400)
return new GARC(br);
return null;
}
diff --git a/pkNX.Containers/GARC/GARCHeader.cs b/pkNX.Containers/GARC/GARCHeader.cs
index c842f8f4..376e15b1 100644
--- a/pkNX.Containers/GARC/GARCHeader.cs
+++ b/pkNX.Containers/GARC/GARCHeader.cs
@@ -27,12 +27,12 @@ public class GARCHeader
public GARCHeader(GARCVersion version)
{
- if (version == GARCVersion.VER_6)
- Version = VER_6;
- else if (version == GARCVersion.VER_4)
- Version = VER_4;
- else
- Version = (ushort)version;
+ Version = version switch
+ {
+ GARCVersion.VER_6 => VER_6,
+ GARCVersion.VER_4 => VER_4,
+ _ => (ushort)version,
+ };
HeaderSize = VER6 ? 0x24 : 0x1C;
}
diff --git a/pkNX.Containers/LargeContainerEntry.cs b/pkNX.Containers/LargeContainerEntry.cs
index aa9a7624..55bbbbbe 100644
--- a/pkNX.Containers/LargeContainerEntry.cs
+++ b/pkNX.Containers/LargeContainerEntry.cs
@@ -14,7 +14,7 @@ public byte[] GetFileData(Stream parent)
{
parent.Seek(Start + ParentDataPosition, SeekOrigin.Begin);
byte[] data = new byte[Length];
- parent.Read(data, 0, Length);
+ _ = parent.Read(data, 0, Length);
return data;
}
diff --git a/pkNX.Containers/Mini/Mini.cs b/pkNX.Containers/Mini/Mini.cs
index e8552a7e..71d561cf 100644
--- a/pkNX.Containers/Mini/Mini.cs
+++ b/pkNX.Containers/Mini/Mini.cs
@@ -47,14 +47,11 @@ public void CancelEdits()
Files[i] = (byte[]) Backup[i].Clone();
}
- public Task SaveAs(string path, ContainerHandler handler, CancellationToken token)
+ public Task SaveAs(string path, ContainerHandler handler, CancellationToken token) => new(() =>
{
- return new(() =>
- {
- byte[] data = MiniUtil.PackMini(Files, Identifier);
- FileMitm.WriteAllBytes(path, data);
- }, token);
- }
+ byte[] data = MiniUtil.PackMini(Files, Identifier);
+ FileMitm.WriteAllBytes(path, data);
+ }, token);
public void Dump(string path, ContainerHandler handler)
{
diff --git a/pkNX.Containers/Misc/FnvHash.cs b/pkNX.Containers/Misc/FnvHash.cs
index a5202cd6..12cf267d 100644
--- a/pkNX.Containers/Misc/FnvHash.cs
+++ b/pkNX.Containers/Misc/FnvHash.cs
@@ -15,10 +15,10 @@ public static class FnvHash
/// Gets the hash code of the input sequence via the default Fnv1 method.
///
/// Input sequence
+ /// Initial hash value
/// Computed hash code
- public static ulong HashFnv1_64(IEnumerable input)
+ public static ulong HashFnv1_64(IEnumerable input, ulong hash = kOffsetBasis_64)
{
- ulong hash = kOffsetBasis_64;
foreach (var c in input)
{
hash *= kFnvPrime_64;
@@ -31,10 +31,10 @@ public static ulong HashFnv1_64(IEnumerable input)
/// Gets the hash code of the input sequence via the default Fnv1 method.
///
/// Input sequence
+ /// Initial hash value
/// Computed hash code
- public static ulong HashFnv1_64(IEnumerable input)
+ public static ulong HashFnv1_64(IEnumerable input, ulong hash = kOffsetBasis_64)
{
- ulong hash = kOffsetBasis_64;
foreach (var c in input)
{
hash *= kFnvPrime_64;
@@ -47,10 +47,10 @@ public static ulong HashFnv1_64(IEnumerable input)
/// Gets the hash code of the input sequence via the alternative Fnv1 method.
///
/// Input sequence
+ /// Initial hash value
/// Computed hash code
- public static ulong HashFnv1a_64(IEnumerable input)
+ public static ulong HashFnv1a_64(IEnumerable input, ulong hash = kOffsetBasis_64)
{
- ulong hash = kOffsetBasis_64;
foreach (var c in input)
{
hash ^= c;
@@ -63,10 +63,10 @@ public static ulong HashFnv1a_64(IEnumerable input)
/// Gets the hash code of the input sequence via the alternative Fnv1 method.
///
/// Input sequence
+ /// Initial hash value
/// Computed hash code
- public static ulong HashFnv1a_64(IEnumerable input)
+ public static ulong HashFnv1a_64(IEnumerable input, ulong hash = kOffsetBasis_64)
{
- ulong hash = kOffsetBasis_64;
foreach (var c in input)
{
hash ^= c;
@@ -83,10 +83,10 @@ public static ulong HashFnv1a_64(IEnumerable input)
/// Gets the hash code of the input sequence via the default Fnv1 method.
///
/// Input sequence
+ /// Initial hash value
/// Computed hash code
- public static uint HashFnv1_32(IEnumerable input)
+ public static uint HashFnv1_32(IEnumerable input, uint hash = kOffsetBasis_32)
{
- uint hash = kOffsetBasis_32;
foreach (var c in input)
{
hash *= kFnvPrime_32;
@@ -99,10 +99,10 @@ public static uint HashFnv1_32(IEnumerable input)
/// Gets the hash code of the input sequence via the alternative Fnv1 method.
///
/// Input sequence
+ /// Initial hash value
/// Computed hash code
- public static uint HashFnv1a_32(IEnumerable input)
+ public static uint HashFnv1a_32(IEnumerable input, uint hash = kOffsetBasis_32)
{
- uint hash = kOffsetBasis_32;
foreach (var c in input)
{
hash ^= c;
diff --git a/pkNX.Containers/Misc/GFPack.cs b/pkNX.Containers/Misc/GFPack.cs
index bbbeceae..c7adc714 100644
--- a/pkNX.Containers/Misc/GFPack.cs
+++ b/pkNX.Containers/Misc/GFPack.cs
@@ -127,6 +127,10 @@ public byte[] GetDataFileName(string name)
return DecompressedFiles[index];
}
+ public byte[] GetDataFull(ulong hash) => DecompressedFiles[GetIndexFull(hash)];
+
+ public byte[] GetDataFullPath(string path) => GetDataFull(FnvHash.HashFnv1a_64(path));
+
public void SetDataFileName(string name, byte[] data)
{
int index = GetIndexFileName(name);
@@ -169,7 +173,7 @@ public void LoadFiles(string[] directories, string parent, CompressionType type
for (var i = 0; i < files.Length; i++)
{
var file = files[i];
- var namelong = file.Substring(file.IndexOf(parent, StringComparison.Ordinal));
+ var namelong = file[file.IndexOf(parent, StringComparison.Ordinal)..];
ulong hashFull = FnvHash.HashFnv1a_64(namelong);
HashAbsolute[i] = new FileHashAbsolute { HashFnv1aPathFull = hashFull };
@@ -211,7 +215,13 @@ private static byte[] Decompress(byte[] encryptedData, int decryptedLength, Comp
{
CompressionType.None => encryptedData,
CompressionType.Zlib => throw new NotSupportedException(nameof(CompressionType.Zlib)), // not implemented
- _ => LZ4.Decode(encryptedData, decryptedLength)
+ CompressionType.Lz4 => LZ4.Decode(encryptedData, decryptedLength),
+ CompressionType.OodleKraken => Oodle.Decompress(encryptedData, decryptedLength)!,
+ CompressionType.OodleLeviathan => Oodle.Decompress(encryptedData, decryptedLength)!,
+ CompressionType.OodleMermaid => Oodle.Decompress(encryptedData, decryptedLength)!,
+ CompressionType.OodleSelkie => Oodle.Decompress(encryptedData, decryptedLength)!,
+ CompressionType.OodleHydra => Oodle.Decompress(encryptedData, decryptedLength)!,
+ _ => throw new ArgumentOutOfRangeException(nameof(type)),
};
}
@@ -221,7 +231,13 @@ private static byte[] Compress(byte[] decryptedData, CompressionType type)
{
CompressionType.None => decryptedData,
CompressionType.Zlib => throw new NotSupportedException(nameof(CompressionType.Zlib)), // not implemented
- _ => LZ4.Encode(decryptedData)
+ CompressionType.Lz4 => LZ4.Encode(decryptedData),
+ CompressionType.OodleKraken => Oodle.Compress(decryptedData, out _, OodleFormat.Kraken).ToArray(),
+ CompressionType.OodleLeviathan => Oodle.Compress(decryptedData, out _, OodleFormat.Leviathan).ToArray(),
+ CompressionType.OodleMermaid => Oodle.Compress(decryptedData, out _, OodleFormat.Mermaid).ToArray(),
+ CompressionType.OodleSelkie => Oodle.Compress(decryptedData, out _, OodleFormat.Selkie).ToArray(),
+ CompressionType.OodleHydra => Oodle.Compress(decryptedData, out _, OodleFormat.Hydra).ToArray(),
+ _ => throw new ArgumentOutOfRangeException(nameof(type)),
};
}
@@ -280,7 +296,7 @@ public void Dump(string path, ContainerHandler handler)
var data = DecompressedFiles[f.Index];
var subfolder = HashInFolder.Length == 1 ? fn : Path.Combine(dirName.ToString("X16"), fn);
- var loc = Path.Combine(path ?? FilePath, subfolder);
+ var loc = Path.Combine(path, subfolder);
FileMitm.WriteAllBytes(loc, data);
}
}
@@ -416,5 +432,10 @@ public enum CompressionType : ushort
None = 0,
Zlib = 1,
Lz4 = 2,
+ OodleKraken = 3,
+ OodleLeviathan = 4,
+ OodleMermaid = 5,
+ OodleSelkie = 6,
+ OodleHydra = 7,
}
}
diff --git a/pkNX.Containers/Misc/Oodle.cs b/pkNX.Containers/Misc/Oodle.cs
new file mode 100644
index 00000000..15e87ce6
--- /dev/null
+++ b/pkNX.Containers/Misc/Oodle.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace pkNX.Containers
+{
+ ///
+ /// Oodle Compression and Decompression wrapper around the external dll.
+ ///
+ ///
+ /// These methods are safely tuned for Span in order to minimize allocation.
+ ///
+ public static class Oodle
+ {
+ ///
+ /// Oodle Library Path
+ ///
+ private const string OodleLibraryPath = "oo2core_8_win64";
+
+ ///
+ /// Oodle64 Decompression Method
+ ///
+ [DllImport(OodleLibraryPath, CallingConvention = CallingConvention.Cdecl)]
+ private static extern long OodleLZ_Decompress(ref byte buffer, long bufferSize, ref byte result, long outputBufferSize,
+ OodleFuzzSafe fuzz = OodleFuzzSafe.Yes,
+ OodleCheckCrc crc = OodleCheckCrc.No,
+ OodleVerbosity verbosity = OodleVerbosity.None,
+ long context = 0, long e = 0, long callback = 0, long callback_ctx = 0, long scratch = 0, long scratch_size = 0,
+ OodleThreadPhase threadPhase = OodleThreadPhase.Unthreaded);
+
+ ///
+ /// Oodle64 Compression Method
+ ///
+ [DllImport(OodleLibraryPath)]
+ private static extern long OodleLZ_Compress(OodleFormat format, ref byte buffer, long bufferSize, ref byte result, OodleCompressionLevel level,
+ long opts = 0, long context = 0, long unused = 0, long scratch = 0, long scratch_size = 0);
+
+ ///
+ /// Decompresses a span of Oodle Compressed bytes (Requires Oodle DLL)
+ ///
+ /// Input Compressed Data
+ /// Decompressed Size
+ /// Resulting Array if success, otherwise null.
+ public static byte[]? Decompress(ReadOnlySpan input, long decompressedLength)
+ {
+ var result = new byte[decompressedLength];
+ return Decompress(input, result);
+ }
+
+ private static byte[]? Decompress(ReadOnlySpan input, byte[] result)
+ {
+ var dest = result.AsSpan();
+ long decodedSize = OodleLZ_Decompress(ref MemoryMarshal.GetReference(input), input.Length, ref MemoryMarshal.GetReference(dest), result.Length);
+ if (decodedSize == 0)
+ return null; // failed
+ return result;
+ }
+
+ ///
+ /// Compresses a span of bytes to Oodle Compressed bytes (Requires Oodle DLL)
+ ///
+ /// Input Decompressed Data
+ /// Actual Compressed Data size
+ /// Compression format to use
+ /// Compression setting to use
+ /// Span of compressed data with remainder aligned working bytes.
+ public static Span Compress(ReadOnlySpan input, out int compressedSize,
+ OodleFormat format = OodleFormat.Kraken, OodleCompressionLevel level = OodleCompressionLevel.Optimal2)
+ {
+ var maxSize = GetCompressedBufferSizeNeeded(input.Length);
+ var result = new byte[maxSize].AsSpan();
+ return Compress(input, result, out compressedSize, format, level);
+ }
+
+ private static Span Compress(ReadOnlySpan input, Span result, out int compressedSize, OodleFormat format, OodleCompressionLevel level)
+ {
+ var encodedSize = OodleLZ_Compress(format, ref MemoryMarshal.GetReference(input), input.Length, ref MemoryMarshal.GetReference(result), level);
+
+ // Oodle's compressed result leaves data after the "compressed length" return index.
+ // Return an aligned span (ensuring length is a multiple of 4).
+ // Retaining these unused bytes matches the behavior observed in New Pokémon Snap DRPF files.
+ compressedSize = (int)encodedSize;
+ var align = (compressedSize + 3) & ~3;
+ return result[..align];
+ }
+
+ ///
+ /// Gets the dimension required to compress the data.
+ ///
+ ///
+ ///
+ private static long GetCompressedBufferSizeNeeded(long inputSize)
+ {
+ return inputSize + (274 * ((inputSize + 0x3FFFF) / 0x40000));
+ }
+ }
+
+ public enum OodleFormat : uint
+ {
+ LZH = 0,
+ LZHLW = 1,
+ LZNIB = 2,
+ None = 3,
+ LZB16 = 4,
+ LZBLW = 5,
+ LZA = 6,
+ LZNA = 7,
+ Kraken = 8,
+ Mermaid = 9,
+ BitKnit = 10,
+ Selkie = 11,
+ Hydra = 12,
+ Leviathan = 13,
+ }
+
+ public enum OodleCompressionLevel : ulong
+ {
+ None = 0,
+ SuperFast = 1,
+ VeryFast = 2,
+ Fast = 3,
+ Normal = 4,
+ Optimal1 = 5,
+ Optimal2 = 6,
+ Optimal3 = 7,
+ Optimal4 = 8,
+ Optimal5 = 9,
+ }
+
+ public enum OodleFuzzSafe
+ {
+ No = 0,
+ Yes = 1,
+ }
+
+ public enum OodleCheckCrc
+ {
+ No = 0,
+ Yes = 1,
+ }
+
+ public enum OodleVerbosity
+ {
+ None = 0,
+ Max = 3,
+ }
+
+ [Flags]
+ public enum OodleThreadPhase
+ {
+ Invalid = 0,
+ ThreadPhase1 = 1,
+ ThreadPhase2 = 2,
+
+ Unthreaded = ThreadPhase1 | ThreadPhase2, // 3
+ }
+}
diff --git a/pkNX.Containers/pkNX.Containers.csproj b/pkNX.Containers/pkNX.Containers.csproj
index 04851892..ff322c46 100644
--- a/pkNX.Containers/pkNX.Containers.csproj
+++ b/pkNX.Containers/pkNX.Containers.csproj
@@ -3,12 +3,14 @@
netstandard2.0;net461
Packing & Unpacking
- 9
+ 10
enable
+
+
diff --git a/pkNX.Game/Editors/TypeChartEditor.cs b/pkNX.Game/Editors/TypeChartEditor.cs
index 1085d3c7..19b7b7d9 100644
--- a/pkNX.Game/Editors/TypeChartEditor.cs
+++ b/pkNX.Game/Editors/TypeChartEditor.cs
@@ -24,14 +24,13 @@ public void Randomize()
private static byte GetEffectiveness(int rv)
{
- if (rv < 2) // 2%
- return (byte)TypeEffectiveness.Immune;
- if (rv < 19) // 17%
- return (byte)TypeEffectiveness.NotVery;
- if (rv < 36) // 17%
- return (byte)TypeEffectiveness.Super;
-
- return (byte)TypeEffectiveness.Normal;
+ return rv switch
+ {
+ < 2 => (byte)TypeEffectiveness.Immune, // 2%
+ < 19 => (byte)TypeEffectiveness.NotVery, // 17%
+ < 36 => (byte)TypeEffectiveness.Super, // 17%
+ _ => (byte)TypeEffectiveness.Normal,
+ };
}
private static readonly uint[] Colors =
@@ -42,7 +41,7 @@ private static byte GetEffectiveness(int rv)
0, // unused
0xFFFFFFFF,
0, 0, 0, // unused
- 0xFF008000
+ 0xFF008000,
};
public static byte[] GetTypeChartImageData(int itemsize, int itemsPerRow, byte[] vals, out int width, out int height)
diff --git a/pkNX.Game/File/GameFile.cs b/pkNX.Game/File/GameFile.cs
index 42ce5b6b..548fcb13 100644
--- a/pkNX.Game/File/GameFile.cs
+++ b/pkNX.Game/File/GameFile.cs
@@ -175,5 +175,20 @@ public enum GameFile
/// Symbol Behavior Definition
SymbolBehave,
+
+ /// Area Resident Archive
+ Resident,
+
+ /// "PokeEncount" Rate Multipler Archive
+ EncounterRateTable,
+
+ /// huge_outbreak.bin
+ Outbreak,
+
+ /// wazashop_table.bin
+ MoveShop,
+
+ /// "PokeMisc" Details about a given Species-Form not stored in
+ PokeMisc,
}
}
diff --git a/pkNX.Game/File/GameFileMapping.cs b/pkNX.Game/File/GameFileMapping.cs
index 37491469..911beaeb 100644
--- a/pkNX.Game/File/GameFileMapping.cs
+++ b/pkNX.Game/File/GameFileMapping.cs
@@ -23,7 +23,7 @@ public class GameFileMapping
internal IFileContainer GetFile(GameFile file, int language)
{
- if (file == GameFile.GameText || file == GameFile.StoryText)
+ if (file is GameFile.GameText or GameFile.StoryText)
file += language + 1; // shift to localized language
if (Cache.TryGetValue(file, out var container))
@@ -67,6 +67,7 @@ public static IReadOnlyCollection GetMapping(GameVersion game
GameVersion.SW => SWSH,
GameVersion.SH => SWSH,
GameVersion.SWSH => SWSH,
+ GameVersion.PLA => PLA,
GameVersion.ORASDEMO => AO,
GameVersion.ORAS => AO,
GameVersion.SMDEMO => SMDEMO,
@@ -412,6 +413,58 @@ public static IReadOnlyCollection GetMapping(GameVersion game
// Models bin\archive\pokemon
// pretty much everything is obviously named :)
};
+
+ ///
+ /// Sword
+ ///
+ private static readonly GameFileReference[] PLA =
+ {
+ new(GameFile.TrainerData, "bin", "trainer"),
+
+ new(GameFile.GameText0, 0, "bin", "message", "JPN", "common"),
+ new(GameFile.GameText1, 1, "bin", "message", "JPN_KANJI", "common"),
+ new(GameFile.GameText2, 2, "bin", "message", "English", "common"),
+ new(GameFile.GameText3, 3, "bin", "message", "French", "common"),
+ new(GameFile.GameText4, 4, "bin", "message", "Italian", "common"),
+ new(GameFile.GameText5, 5, "bin", "message", "German", "common"),
+ // 6 unused lang
+ new(GameFile.GameText6, 7, "bin", "message", "Spanish", "common"),
+ new(GameFile.GameText7, 8, "bin", "message", "Korean", "common"),
+ new(GameFile.GameText8, 9, "bin", "message", "Simp_Chinese", "common"),
+ new(GameFile.GameText9, 10, "bin", "message", "Trad_Chinese", "common"),
+
+ new(GameFile.StoryText0, 0, "bin", "message", "JPN", "script"),
+ new(GameFile.StoryText1, 1, "bin", "message", "JPN_KANJI", "script"),
+ new(GameFile.StoryText2, 2, "bin", "message", "English", "script"),
+ new(GameFile.StoryText3, 3, "bin", "message", "French", "script"),
+ new(GameFile.StoryText4, 4, "bin", "message", "Italian", "script"),
+ new(GameFile.StoryText5, 5, "bin", "message", "German", "script"),
+ // 6 unused lang
+ new(GameFile.StoryText6, 7, "bin", "message", "Spanish", "script"),
+ new(GameFile.StoryText7, 8, "bin", "message", "Korean", "script"),
+ new(GameFile.StoryText8, 9, "bin", "message", "Simp_Chinese", "script"),
+ new(GameFile.StoryText9, 10, "bin", "message", "Trad_Chinese", "script"),
+
+ new(GameFile.ItemStats, ContainerType.SingleFile, "bin", "pml", "item", "item.dat"),
+ new(GameFile.Evolutions, "bin", "pml", "evolution"),
+ new(GameFile.PersonalStats, ContainerType.SingleFile, "bin", "pml", "personal", "personal_data_total.perbin"),
+ new(GameFile.MoveStats, "bin", "pml", "waza"),
+ new(GameFile.EncounterStatic, ContainerType.SingleFile, "bin", "pokemon", "data", "poke_event_encount.bin"),
+ new(GameFile.EncounterTrade, ContainerType.SingleFile, "bin", "script_event_data", "field_trade.bin"),
+ new(GameFile.EncounterGift, ContainerType.SingleFile, "bin", "pokemon", "data", "poke_add.bin"),
+ new(GameFile.Learnsets, ContainerType.SingleFile, "bin", "pml", "waza_oboe", "waza_oboe_total.wazaoboe"),
+
+ new(GameFile.Resident, ContainerType.SingleFile, "bin", "archive", "field", "resident_release.gfpak"),
+
+ new(GameFile.EncounterRateTable, ContainerType.SingleFile, "bin", "pokemon", "data", "poke_encount.bin"),
+ new(GameFile.PokeMisc, ContainerType.SingleFile, "bin", "pokemon", "data", "poke_misc.bin"),
+ new(GameFile.Outbreak, ContainerType.SingleFile, "bin", "field", "encount", "huge_outbreak.bin"),
+ new(GameFile.MoveShop, ContainerType.SingleFile, "bin", "appli", "wazaremember", "bin", "wazashop_table.bin"),
+
+ // Cutscenes bin\demo
+ // Models bin\archive\pokemon
+ // pretty much everything is obviously named :)
+ };
#endregion
#region Split Versions
diff --git a/pkNX.Game/GameLocation.cs b/pkNX.Game/GameLocation.cs
index a783cb12..c9b5301b 100644
--- a/pkNX.Game/GameLocation.cs
+++ b/pkNX.Game/GameLocation.cs
@@ -67,6 +67,8 @@ public static GameLocation GetGame(string dir)
private const int FILECOUNT_SWSH_1 = 41951; // Ver. 1.1.0 update (Galarian Slowpoke)
private const int FILECOUNT_SWSH_2 = 46867; // Ver. 1.2.0 update (Isle of Armor)
private const int FILECOUNT_SWSH_3 = 50494; // Ver. 1.3.0 update (Crown Tundra)
+ private const int FILECOUNT_LA = 18_370;
+ private const int FILECOUNT_LA_1 = 18_371; // Ver. 1.0.1
private static GameVersion GetGameFromCount(int fileCount, string romfs, string exefs)
{
@@ -112,6 +114,9 @@ private static GameVersion GetGameFromCount(int fileCount, string romfs, string
return GetTitleID() == "0100ABF008968000" ? GameVersion.SW : GameVersion.SH;
}
+ case FILECOUNT_LA or FILECOUNT_LA_1:
+ return GameVersion.PLA;
+
default:
return GameVersion.Invalid;
}
diff --git a/pkNX.Game/GameManager.cs b/pkNX.Game/GameManager.cs
index 4c52f097..0ae48157 100644
--- a/pkNX.Game/GameManager.cs
+++ b/pkNX.Game/GameManager.cs
@@ -117,6 +117,7 @@ public static GameManager GetManager(GameLocation loc, int language)
{
GameVersion.GP or GameVersion.GE or GameVersion.GG => new GameManagerGG(loc, language),
GameVersion.SW or GameVersion.SH or GameVersion.SWSH => new GameManagerSWSH(loc, language),
+ GameVersion.PLA => new GameManagerPLA(loc, language),
_ => throw new ArgumentException(nameof(loc.Game))
};
}
diff --git a/pkNX.Game/GameManagerGG.cs b/pkNX.Game/GameManagerGG.cs
index ad09b758..c238bd53 100644
--- a/pkNX.Game/GameManagerGG.cs
+++ b/pkNX.Game/GameManagerGG.cs
@@ -55,7 +55,7 @@ public override void Initialize()
},
EvolutionData = new DataCache(GetFilteredFolder(GameFile.Evolutions))
{
- Create = (data) => new EvolutionSet7(data),
+ Create = data => new EvolutionSet7(data),
Write = evo => evo.Write(),
},
};
diff --git a/pkNX.Game/GameManagerPLA.cs b/pkNX.Game/GameManagerPLA.cs
new file mode 100644
index 00000000..ae39d18d
--- /dev/null
+++ b/pkNX.Game/GameManagerPLA.cs
@@ -0,0 +1,77 @@
+using System;
+using System.IO;
+using pkNX.Containers;
+using pkNX.Structures.FlatBuffers;
+
+namespace pkNX.Game
+{
+ public class GameManagerPLA : GameManager
+ {
+ public GameManagerPLA(GameLocation rom, int language) : base(rom, language) { }
+ private string PathNPDM => Path.Combine(PathExeFS, "main.npdm");
+ private string TitleID => BitConverter.ToUInt64(File.ReadAllBytes(PathNPDM), 0x290).ToString("X16");
+
+ protected override void SetMitm()
+ {
+ var basePath = Path.GetDirectoryName(ROM.RomFS);
+ var tid = ROM.ExeFS != null ? TitleID : "arceus";
+ var redirect = Path.Combine(basePath, tid);
+ FileMitm.SetRedirect(basePath, redirect);
+ }
+
+ private Learnset8a Learn;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ // initialize gametext
+ ResetText();
+
+ // initialize common structures
+ var personal = GetFile(GameFile.PersonalStats)[0];
+ var learn = this[GameFile.Learnsets][0];
+ Learn = FlatBufferConverter.DeserializeFrom(learn);
+
+ var move = this[GameFile.MoveStats];
+ ((FolderContainer)move).Initialize();
+ //Data = new GameData
+ //{
+ // MoveData = new DataCache(move)
+ // {
+ // Create = FlatBufferConverter.DeserializeFrom,
+ // Write = z => FlatBufferConverter.SerializeFrom((Waza8a)z),
+ // },
+ // LevelUpData = new DataCache(Array.Empty())
+ // {
+ // Create = z => new Learnset8(z),
+ // Write = z => z.Write(),
+ // },
+ //
+ // // folders
+ // PersonalData = new PersonalTable(personal, Game),
+ // EvolutionData = new DataCache(GetFilteredFolder(GameFile.Evolutions))
+ // {
+ // Create = data => new EvolutionSet8(data),
+ // Write = evo => evo.Write(),
+ // },
+ //};
+ }
+
+ public void ResetMoves() => GetFilteredFolder(GameFile.MoveStats);
+
+ public void ResetText()
+ {
+ GetFilteredFolder(GameFile.GameText, z => Path.GetExtension(z) == ".dat");
+ }
+
+ protected override void Terminate()
+ {
+ // Store Personal Data back in the file. Let the container detect if it is modified.
+ var personal = this[GameFile.PersonalStats];
+ //personal[0] = Data.PersonalData.Table.SelectMany(z => z.Write()).ToArray();
+ var learn = this[GameFile.Learnsets];
+ //learn[0] = Learn.Entries.SelectMany(z => z.Write()).ToArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/pkNX.Game/Misc/PLAInfo.cs b/pkNX.Game/Misc/PLAInfo.cs
new file mode 100644
index 00000000..5baa46ad
--- /dev/null
+++ b/pkNX.Game/Misc/PLAInfo.cs
@@ -0,0 +1,89 @@
+namespace pkNX.Game
+{
+ public static class PLAInfo
+ {
+
+ public static readonly string[][] AreaNames =
+ {
+ new[] {
+ "ha_area00",
+ "ha_area00_s01",
+ "ha_area00_s02",
+ "ha_area00_s03_a",
+ "ha_area00_s03_b",
+ "ha_area00_s03_c",
+ "ha_area00_s03_d",
+ "ha_area00_s03_e",
+ "ha_area00_s03_f",
+ "ha_area00_s03_g",
+ "ha_area00_s03_h",
+ "ha_area00_s03_i",
+ "ha_area00_s03_j",
+ "ha_area00_s03_k",
+ "ha_area00_s03_l",
+ "ha_area00_s03_m",
+ "ha_area00_s03_n",
+ "ha_area00_s03_o",
+ "ha_area00_s03_p",
+ "ha_area00_s03_q",
+ "ha_area00_s03_r",
+ "ha_area00_s03_s",
+ "ha_area00_s03_t",
+ "ha_area00_s06",
+ "ha_area00_s07",
+ "ha_area00_s09",
+ "ha_area00_s12_a",
+ "ha_area00_s12_b",
+ "ha_area00_s12_c",
+ "ha_area00_s12_d",
+ "ha_area00_s16_a",
+ "ha_area00_s16_b",
+ },
+ new[] {
+ "ha_area01",
+ "ha_area01_s01",
+ },
+ new[] {
+ "ha_area02",
+ "ha_area02_s01",
+ "ha_area02_s01_a",
+ "ha_area02_s01_b",
+ "ha_area02_s01_c",
+ "ha_area02_s01_d",
+ "ha_area02_s02",
+ },
+ new[] {
+ "ha_area03",
+ "ha_area03_s01",
+ "ha_area03_s02",
+ "ha_area03_s03",
+ "ha_area03_s04",
+ },
+ new[] {
+ "ha_area04",
+ "ha_area04_s01",
+ "ha_area04_s02",
+ "ha_area04_s03",
+ "ha_area04_s04",
+ },
+ new[] {
+ "ha_area05",
+ "ha_area05_s01",
+ "ha_area05_s02",
+ "ha_area05_s03",
+ "ha_area05_s04",
+ "ha_area05_s04_a",
+ "ha_area05_s04_b",
+ "ha_area05_s04_c",
+ "ha_area05_s04_d",
+ },
+ new[] {
+ "ha_area06",
+ "ha_area06_s01",
+ },
+ new[] {
+ "ha_area11",
+ }
+ };
+ }
+}
diff --git a/pkNX.Game/Misc/SWSHEncounterType.cs b/pkNX.Game/Misc/SWSHEncounterType.cs
new file mode 100644
index 00000000..c8a99e39
--- /dev/null
+++ b/pkNX.Game/Misc/SWSHEncounterType.cs
@@ -0,0 +1,16 @@
+namespace pkNX.Game;
+
+public enum SWSHEncounterType
+{
+ Normal_Weather,
+ Overcast,
+ Raining,
+ Thunderstorm,
+ Intense_Sun,
+ Snowing,
+ Snowstorm,
+ Sandstorm,
+ Heavy_Fog,
+ Shaking_Trees,
+ Fishing,
+}
diff --git a/pkNX.Game/Misc/SWSHInfo.cs b/pkNX.Game/Misc/SWSHInfo.cs
index 22a2b108..1897e9d3 100644
--- a/pkNX.Game/Misc/SWSHInfo.cs
+++ b/pkNX.Game/Misc/SWSHInfo.cs
@@ -628,40 +628,4 @@ public static class SWSHInfo
{0x9BDD6D11FFBEDA3F, (byte)Surfing}, // at Ballimere Lake (Surfing)
};
}
-
- public enum SWSHEncounterType
- {
- Normal_Weather,
- Overcast,
- Raining,
- Thunderstorm,
- Intense_Sun,
- Snowing,
- Snowstorm,
- Sandstorm,
- Heavy_Fog,
- Shaking_Trees,
- Fishing,
- };
-
- public enum SWSHSlotType: ushort
- {
- SymbolMain,
- SymbolMain2,
- SymbolMain3,
-
- HiddenMain, // Table with the tree/fishing slots
- HiddenMain2,
-
- Surfing,
- Surfing2,
- Sky,
- Sky2,
- Ground,
- Ground2,
- Sharpedo,
-
- OnlyFishing,
- Inaccessible,
- };
}
diff --git a/pkNX.Game/Misc/SWSHSlotType.cs b/pkNX.Game/Misc/SWSHSlotType.cs
new file mode 100644
index 00000000..76b34d77
--- /dev/null
+++ b/pkNX.Game/Misc/SWSHSlotType.cs
@@ -0,0 +1,22 @@
+namespace pkNX.Game;
+
+public enum SWSHSlotType : ushort
+{
+ SymbolMain,
+ SymbolMain2,
+ SymbolMain3,
+
+ HiddenMain, // Table with the tree/fishing slots
+ HiddenMain2,
+
+ Surfing,
+ Surfing2,
+ Sky,
+ Sky2,
+ Ground,
+ Ground2,
+ Sharpedo,
+
+ OnlyFishing,
+ Inaccessible,
+}
diff --git a/pkNX.Game/Text/TextMapping.cs b/pkNX.Game/Text/TextMapping.cs
index 23f2b1e7..8bf2ecc8 100644
--- a/pkNX.Game/Text/TextMapping.cs
+++ b/pkNX.Game/Text/TextMapping.cs
@@ -23,6 +23,7 @@ public static IReadOnlyCollection GetMapping(GameVersion game)
GameVersion.SW => SWSH,
GameVersion.SH => SWSH,
GameVersion.SWSH => SWSH,
+ GameVersion.PLA => PLA,
_ => null
};
}
@@ -173,5 +174,32 @@ public static IReadOnlyCollection GetMapping(GameVersion game)
new("ribbon.dat", TextName.RibbonMark),
new("poke_memory_feeling.dat", TextName.MemoryFeelings),
};
+
+
+ private static readonly TextReference[] PLA =
+ {
+ new("iteminfo.dat", TextName.ItemFlavor),
+ new("itemname.dat", TextName.ItemNames),
+ new("monsname.dat", TextName.SpeciesNames),
+ new("place_name_indirect.dat", TextName.metlist_00000),
+ new("place_name_spe.dat", TextName.metlist_30000),
+ new("place_name_out.dat", TextName.metlist_40000),
+ new("place_name_per.dat", TextName.metlist_60000),
+ new("seikaku.dat", TextName.Natures),
+ new("tokusei.dat", TextName.AbilityNames),
+ new("tokuseiinfo.dat", TextName.AbilityFlavor),
+ new("trname.dat", TextName.TrainerNames),
+ new("trtype.dat", TextName.TrainerClasses),
+ new("trmsg.dat", TextName.TrainerText),
+ new("typename.dat", TextName.Types),
+ new("wazainfo.dat", TextName.MoveFlavor),
+ new("wazaname.dat", TextName.MoveNames),
+ new("zkn_form.dat", TextName.Forms),
+ new("zkn_type.dat", TextName.SpeciesClassifications),
+ new("zukan_comment_A.dat", TextName.PokedexEntry1),
+ new("zukan_comment_B.dat", TextName.PokedexEntry2),
+ new("ribbon.dat", TextName.RibbonMark),
+ new("poke_memory_feeling.dat", TextName.MemoryFeelings),
+ };
}
}
\ No newline at end of file
diff --git a/pkNX.Game/pkNX.Game.csproj b/pkNX.Game/pkNX.Game.csproj
index f5a57397..cfd0c190 100644
--- a/pkNX.Game/pkNX.Game.csproj
+++ b/pkNX.Game/pkNX.Game.csproj
@@ -3,9 +3,14 @@
netstandard2.0;net461
Game Data Manager
- 9
+ 10
+
+
+
+
+
diff --git a/pkNX.Randomization/Randomizers/EvolutionRandomizer.cs b/pkNX.Randomization/Randomizers/EvolutionRandomizer.cs
index 670740fc..e11e8a65 100644
--- a/pkNX.Randomization/Randomizers/EvolutionRandomizer.cs
+++ b/pkNX.Randomization/Randomizers/EvolutionRandomizer.cs
@@ -113,10 +113,10 @@ private void ReplaceTradeMethod(EvolutionMethod evo, int species, int evoIndex)
}
}
- private void MakeEvolveEveryLevel(EvolutionSet evos, int species)
+ private static void MakeEvolveEveryLevel(EvolutionSet evos, int species)
{
var evoSet = evos.PossibleEvolutions;
- var evoNew = new EvolutionMethod()
+ evoSet[0] = new EvolutionMethod
{
Argument = 0, // clear
Form = 0, // randomized later
@@ -125,8 +125,6 @@ private void MakeEvolveEveryLevel(EvolutionSet evos, int species)
Species = species, // randomized later
};
- evoSet[0] = evoNew;
-
if (evoSet[1].HasData) // has other branched evolutions; remove them
{
for (int i = 1; i < evoSet.Length; i++)
diff --git a/pkNX.Randomization/Randomizers/FormRandomizer.cs b/pkNX.Randomization/Randomizers/FormRandomizer.cs
index 581ccad2..b5b39c25 100644
--- a/pkNX.Randomization/Randomizers/FormRandomizer.cs
+++ b/pkNX.Randomization/Randomizers/FormRandomizer.cs
@@ -63,7 +63,7 @@ public int GetRandomForme(int species, bool mega, bool fused, bool alola, bool g
}
}
- if (Personal.TableLength == 980 && (species == (int)Pikachu || species == (int)Eevee)) // gg tableB -- no starters, they crash trainer battles.
+ if (Personal.TableLength == 980 && species is (int)Pikachu or (int)Eevee) // gg tableB -- no starters, they crash trainer battles.
return 0;
if (alola && Legal.EvolveToAlolanForms.Contains(species))
return Util.Random.Next(2);
@@ -74,14 +74,11 @@ public int GetRandomForme(int species, bool mega, bool fused, bool alola, bool g
return 0;
}
- public int GetInvalidForm(int species, bool galar, PersonalTable stats)
+ public static int GetInvalidForm(int species, bool galar, PersonalTable stats) => species switch
{
- return species switch
- {
- (int)Pikachu when stats.TableLength == 1192 => 8, // LGPE Partner Pikachu
- (int)Slowbro when galar => 1, // Mega Slowbro
- _ => throw new ArgumentOutOfRangeException(nameof(species))
- };
- }
+ (int)Pikachu when stats.TableLength == 1192 => 8, // LGPE Partner Pikachu
+ (int)Slowbro when galar => 1, // Mega Slowbro
+ _ => throw new ArgumentOutOfRangeException(nameof(species))
+ };
}
}
diff --git a/pkNX.Randomization/Randomizers/TrainerRandomizer.cs b/pkNX.Randomization/Randomizers/TrainerRandomizer.cs
index 9b55c47e..a9f24fae 100644
--- a/pkNX.Randomization/Randomizers/TrainerRandomizer.cs
+++ b/pkNX.Randomization/Randomizers/TrainerRandomizer.cs
@@ -255,7 +255,7 @@ private void UpdatePKMFromSettings(TrainerPoke pk)
return;
c.Species = AllowedGigantamaxes[Util.Random.Next(AllowedGigantamaxes.Length)];
- c.Form = c.Species == (int)Species.Pikachu || c.Species == (int)Species.Meowth ? 0 : RandForm.GetRandomForme(c.Species, false, false, false, false, Personal.Table); // Pikachu & Meowth altforms can't gmax
+ c.Form = c.Species is (int)Species.Pikachu or (int)Species.Meowth ? 0 : RandForm.GetRandomForme(c.Species, false, false, false, false, Personal.Table); // Pikachu & Meowth altforms can't gmax
}
if (Settings.MaxDynamaxLevel && c.CanDynamax)
c.DynamaxLevel = 10;
diff --git a/pkNX.Randomization/Util.cs b/pkNX.Randomization/Util.cs
index 3c53ec61..a15f1ca2 100644
--- a/pkNX.Randomization/Util.cs
+++ b/pkNX.Randomization/Util.cs
@@ -22,9 +22,7 @@ public static void Shuffle(IList array)
for (int i = 0; i < n; i++)
{
int r = i + (int)(Random.NextDouble() * (n - i));
- var t = array[r];
- array[r] = array[i];
- array[i] = t;
+ (array[r], array[i]) = (array[i], array[r]);
}
}
@@ -50,8 +48,8 @@ public static uint GetHexValue(string s)
return string.IsNullOrWhiteSpace(str) ? 0 : Convert.ToUInt32(str, 16);
}
- private static bool IsHex(char c) => (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
- private static string TitleCase(string word) => char.ToUpper(word[0]) + word.Substring(1, word.Length - 1).ToLower();
+ private static bool IsHex(char c) => c is >= '0' and <= '9' or >= 'A' and <= 'F' or >= 'a' and <= 'f';
+ private static string TitleCase(string word) => char.ToUpper(word[0]) + word[1..].ToLower();
///
/// Filters the string down to only valid hex characters, returning a new string.
diff --git a/pkNX.Randomization/pkNX.Randomization.csproj b/pkNX.Randomization/pkNX.Randomization.csproj
index d28f5399..45972359 100644
--- a/pkNX.Randomization/pkNX.Randomization.csproj
+++ b/pkNX.Randomization/pkNX.Randomization.csproj
@@ -3,10 +3,15 @@
netstandard2.0;net461
Randomizer Utility
- 9
+ 10
enable
+
+
+
+
+
diff --git a/pkNX.Sprites/FormConverter.cs b/pkNX.Sprites/FormConverter.cs
index d2e62e39..f59c5312 100644
--- a/pkNX.Sprites/FormConverter.cs
+++ b/pkNX.Sprites/FormConverter.cs
@@ -15,7 +15,7 @@ public static bool IsTotemForm(int species, int form, int generation = 7)
if (!Legal.Totem_USUM.Contains(species))
return false;
if (species == (int)Mimikyu)
- return form == 2 || form == 3;
+ return form is 2 or 3;
if (Legal.Totem_Alolan.Contains(species))
return form == 2;
return form == 1;
diff --git a/pkNX.Sprites/SpriteBuilder.cs b/pkNX.Sprites/SpriteBuilder.cs
index 4ed9b957..b0bfe017 100644
--- a/pkNX.Sprites/SpriteBuilder.cs
+++ b/pkNX.Sprites/SpriteBuilder.cs
@@ -101,9 +101,9 @@ private Image GetBaseImageFallback(int species, int form, int gender, bool shiny
private Image LayerOverImageItem(Image baseImage, int item, int generation)
{
Image itemimg = (Image?)Resources.ResourceManager.GetObject(GetItemResourceName(item)) ?? Resources.bitem_unk;
- if (328 <= item && item <= 419) // gen2/3/4 TM
+ if (item is >= 328 and <= 419) // gen2/3/4 TM
itemimg = ItemTM;
- else if (1130 <= item && item <= 1229) // Gen8 TR
+ else if (item is >= 1130 and <= 1229) // Gen8 TR
itemimg = ItemTR;
// Redraw item in bottom right corner; since images are cropped, try to not have them at the edge
diff --git a/pkNX.Sprites/SpriteName.cs b/pkNX.Sprites/SpriteName.cs
index 4476c011..d3f85d75 100644
--- a/pkNX.Sprites/SpriteName.cs
+++ b/pkNX.Sprites/SpriteName.cs
@@ -9,11 +9,11 @@ public static class SpriteName
public static bool AllowShinySprite { get; set; } = true;
public static bool AllowGigantamaxSprite { get; set; } = true;
- private const string Separator = "_";
- private const string Cosplay = "c";
- private const string Shiny = "s";
+ private const char Separator = '_';
+ private const char Cosplay = 'c';
+ private const char Shiny = 's';
private const string Gigantamax = "gmax";
- private const string GGStarter = "p";
+ private const char GGStarter = 'p';
public static string GetResourceStringBall(int ball) => $"_ball{ball}";
@@ -25,15 +25,15 @@ public static string GetResourceStringSprite(int species, int form, int gender,
if (SpeciesDefaultFormSprite.Contains(species) && !gmax) // Species who show their default sprite regardless of Form
form = 0;
- if (gmax && (species == (int)Species.Toxtricity || species == (int)Species.Alcremie)) // same sprites for all altform gmaxes
+ if (gmax && species is (int)Species.Toxtricity or (int)Species.Alcremie) // same sprites for all altform gmaxes
form = 0;
switch (form)
{
- case 30 when species >= (int)Species.Scatterbug && species <= (int)Species.Vivillon: // save file specific
+ case 30 when species is >= (int)Species.Scatterbug and <= (int)Species.Vivillon: // save file specific
form = 0;
break;
- case 31 when species == (int)Species.Unown || species == (int)Species.Deerling || species == (int)Species.Sawsbuck: // Random
+ case 31 when species is (int)Species.Unown or (int)Species.Deerling or (int)Species.Sawsbuck: // Random
form = 0;
break;
}
@@ -43,7 +43,8 @@ public static string GetResourceStringSprite(int species, int form, int gender,
if (form != 0)
{
- sb.Append(Separator); sb.Append(form);
+ sb.Append(Separator)
+ .Append(form);
if (species == (int)Species.Pikachu)
{
diff --git a/pkNX.Sprites/pkNX.Sprites.csproj b/pkNX.Sprites/pkNX.Sprites.csproj
index 37cec757..c859b79c 100644
--- a/pkNX.Sprites/pkNX.Sprites.csproj
+++ b/pkNX.Sprites/pkNX.Sprites.csproj
@@ -2,7 +2,7 @@
net5.0;net461
- 9
+ 10
enable
true
@@ -12,6 +12,8 @@
+
+
True
diff --git a/pkNX.Structures.FlatBuffers/Arceus/ArchiveContents8a.cs b/pkNX.Structures.FlatBuffers/Arceus/ArchiveContents8a.cs
new file mode 100644
index 00000000..50719e2f
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/ArchiveContents8a.cs
@@ -0,0 +1,27 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class ArchiveContents8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public ArchiveContent8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class ArchiveContent8a
+{
+ [FlatBufferItem(00)] public ulong Field_00 { get; set; }
+ [FlatBufferItem(01)] public ulong[] Field_01 { get; set; } = Array.Empty();
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Condition/Condition8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Condition/Condition8a.cs
new file mode 100644
index 00000000..09d1a9d3
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Condition/Condition8a.cs
@@ -0,0 +1,16 @@
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedMember.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferEnum(typeof(ulong))]
+public enum Condition8a : ulong
+{
+ GreaterThanEqual = 0x34F605C97C571896,
+ LessThanEqual = 0x488B1F9FBC949365,
+ NotEqual = 0x88C99E99F1FC6C55,
+ Equal = 0xB763CBE88B6F844F,
+ None = 0xCBF29CE484222645,
+ Between = 0xE5E34D77DC75E2EF,
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Condition/Condition8aUtil.cs b/pkNX.Structures.FlatBuffers/Arceus/Condition/Condition8aUtil.cs
new file mode 100644
index 00000000..5eec1514
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Condition/Condition8aUtil.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Linq;
+
+namespace pkNX.Structures.FlatBuffers;
+
+public static class Condition8aUtil
+{
+ public static string GetConditionTypeSummary(this IHasCondition8a cond)
+ {
+ if (!Enum.IsDefined(typeof(ConditionType8a), cond.ConditionTypeID))
+ return $"0x{(ulong)cond.ConditionTypeID:X16}";
+ //throw new ArgumentOutOfRangeException(nameof(cond.ConditionTypeID), cond.ConditionTypeID, "Unknown.");
+ return $"{cond.ConditionTypeID}";
+ }
+
+ public static string GetConditionArgsSummary(this IHasCondition8a cond)
+ {
+ var args = new[] { cond.ConditionArg1, cond.ConditionArg2, cond.ConditionArg3, cond.ConditionArg4, cond.ConditionArg5 };
+ var firstEmpty = -1;
+ for (var i = 0; i < args.Length; i++)
+ {
+ if (firstEmpty >= 0 && !string.IsNullOrEmpty(args[i]))
+ throw new ArgumentException($"Invalid ConditionArg at index {i}!");
+ else if (firstEmpty < 0 && string.IsNullOrEmpty(args[i]))
+ firstEmpty = i;
+ }
+
+ return string.Join(", ", args.Select(s => $"\"{s}\"").Take(firstEmpty >= 0 ? firstEmpty : args.Length));
+ }
+
+ public static string GetConditionSummary(this IHasCondition8a cond)
+ {
+ if (!Enum.IsDefined(typeof(Condition8a), cond.ConditionID))
+ throw new ArgumentOutOfRangeException(nameof(cond.ConditionID), cond.ConditionID, "Unknown.");
+ return $"{cond.ConditionID}({GetConditionArgsSummary(cond)})";
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Condition/ConditionType8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Condition/ConditionType8a.cs
new file mode 100644
index 00000000..a8824704
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Condition/ConditionType8a.cs
@@ -0,0 +1,23 @@
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedMember.Global
+#pragma warning disable RCS1154 // Sort enum members.
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferEnum(typeof(ulong))]
+public enum ConditionType8a : ulong
+{
+ FlagComparison = 0x3DDD5FEB4A68A149, // "flag_comparison
+ FlagComparisonMultiAnd = 0x1474C7C46A813955, // "flag_comparison_multi_and"
+ FlagComparisonMultiOr = 0x99A60B9D95356789, // "flag_comparison_multi_or"
+ Force = 0x344570C1301A7584, // "force"
+ MkrgCondition = 0xF8ADF49E06E61C30, // "mkrg_condition
+ PhaseCondition = 0x8E77D62D1E38721E, // "phase_condition"
+ PokeGetSelf = 0x7AAB4D6FEBAC4C0E, // "poke_get_self"
+ ProgressWorkCondition = 0x43C4820F12B5385C, // "progress_work_condition"
+ Probability = 0x5E53C6367A2D36BC, // "probability"
+ QuestProgressCondition = 0x2041C674206FE0A7, // "quest_progress_condition"
+ WorkCondition = 0x2557279B949C81D6, // "work_condition
+ None = 0xCBF29CE484222645, // ""
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Event/Trigger8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Event/Trigger8a.cs
new file mode 100644
index 00000000..68d06b93
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Event/Trigger8a.cs
@@ -0,0 +1,56 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class TriggerTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public Trigger8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class Trigger8a
+{
+ [FlatBufferItem(00)] public Trigger8a_F00 Field_00 { get; set; } = new();
+ [FlatBufferItem(01)] public Trigger8a_F01[] Field_01 { get; set; } = Array.Empty();
+ [FlatBufferItem(02)] public Trigger8a_F02[] Field_02 { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class Trigger8a_F00
+{
+ [FlatBufferItem(00)] public ulong Field_00 { get; set; }
+ [FlatBufferItem(01)] public ulong Field_01 { get; set; }
+ [FlatBufferItem(02)] public string Field_02 { get; set; } = string.Empty;
+ [FlatBufferItem(03)] public string Field_03 { get; set; } = string.Empty;
+ [FlatBufferItem(04)] public string Field_04 { get; set; } = string.Empty; // assumed
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class Trigger8a_F01
+{
+ [FlatBufferItem(00)] public ulong Field_00 { get; set; }
+ [FlatBufferItem(01)] public byte Field_01 { get; set; } // unk
+ [FlatBufferItem(02)] public string Field_02 { get; set; } = string.Empty;
+ [FlatBufferItem(03)] public string Field_03 { get; set; } = string.Empty; // assumed
+ [FlatBufferItem(04)] public string Field_04 { get; set; } = string.Empty; // assumed
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class Trigger8a_F02
+{
+ [FlatBufferItem(00)] public ulong Field_00 { get; set; }
+ [FlatBufferItem(01)] public string[] Field_01 { get; set; } = Array.Empty();
+ [FlatBufferItem(02)] public string[] Field_02 { get; set; } = Array.Empty();
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/EvolutionTable8.cs b/pkNX.Structures.FlatBuffers/Arceus/EvolutionTable8.cs
new file mode 100644
index 00000000..008733a5
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/EvolutionTable8.cs
@@ -0,0 +1,59 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EvolutionTable8 : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public EvolutionSet8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EvolutionSet8a
+{
+ [FlatBufferItem(0)] public ushort Index { get; set; }
+ [FlatBufferItem(1)] public ushort Form { get; set; }
+ [FlatBufferItem(2)] public EvolutionEntry8a[]? Table { get; set; } = Array.Empty();
+
+ public byte[] Write()
+ {
+ if (Table is null)
+ return Array.Empty();
+
+ using MemoryStream ms = new();
+ using BinaryWriter bw = new(ms);
+ foreach (var evo in Table)
+ {
+ // ReSharper disable RedundantCast
+ bw.Write((ushort)evo.Method);
+ bw.Write((ushort)evo.Argument);
+ bw.Write((ushort)evo.Species);
+ bw.Write((sbyte)evo.Form);
+ bw.Write((byte)evo.Level);
+ // ReSharper restore RedundantCast
+ }
+ return ms.ToArray();
+ }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EvolutionEntry8a
+{
+ [FlatBufferItem(0)] public ushort Method { get; set; }
+ [FlatBufferItem(1)] public ushort Argument { get; set; }
+ [FlatBufferItem(2)] public ushort Species { get; set; }
+ [FlatBufferItem(3)] public byte Form { get; set; }
+ [FlatBufferItem(4)] public byte Level { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/ISlotTableConsumer.cs b/pkNX.Structures.FlatBuffers/Arceus/ISlotTableConsumer.cs
new file mode 100644
index 00000000..a337086d
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/ISlotTableConsumer.cs
@@ -0,0 +1,6 @@
+namespace pkNX.Structures.FlatBuffers;
+
+public interface ISlotTableConsumer
+{
+ bool UsesTable(ulong table);
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/KeyAssignmentTable.cs b/pkNX.Structures.FlatBuffers/Arceus/KeyAssignmentTable.cs
new file mode 100644
index 00000000..b1966d1e
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/KeyAssignmentTable.cs
@@ -0,0 +1,28 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class KeyAssignmentTable : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public KeyAssignment[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class KeyAssignment
+{
+ [FlatBufferItem(00)] public string Field_00 { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public string[] Field_01 { get; set; } = Array.Empty();
+ [FlatBufferItem(02)] public byte Field_02 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/LandmarkItemSpawnTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/LandmarkItemSpawnTable8a.cs
new file mode 100644
index 00000000..b6214aa1
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/LandmarkItemSpawnTable8a.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+using pkNX.Containers;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class LandmarkItemSpawnTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public LandmarkItemSpawn8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class LandmarkItemSpawn8a
+{
+ [FlatBufferItem(00)] public ulong LandmarkItemSpawnTableID { get; set; }
+ [FlatBufferItem(01)] public int Field_01 { get; set; }
+ [FlatBufferItem(02)] public int Field_02 { get; set; }
+ [FlatBufferItem(03)] public LandmarkItemSpawn8a_F03[] Field_03 { get; set; } = Array.Empty();
+ [FlatBufferItem(04)] public int Field_04 { get; set; }
+ [FlatBufferItem(05)] public byte Field_05 { get; set; } // unused
+ [FlatBufferItem(06)] public byte Field_06 { get; set; } // unused
+ [FlatBufferItem(07)] public ulong EncounterTableID { get; set; }
+ [FlatBufferItem(08)] public byte Field_08 { get; set; } // unused
+ [FlatBufferItem(09)] public int Field_09 { get; set; }
+
+ public bool UsesTable(ulong table) => EncounterTableID == table;
+
+ public string NameSummary
+ {
+ get
+ {
+ var map = GetNameMap();
+ if (map.TryGetValue(LandmarkItemSpawnTableID, out var name))
+ return $"\"{name}\"";
+
+ return $"0x{LandmarkItemSpawnTableID:X16}";
+ }
+ }
+
+ private static IReadOnlyDictionary? _spawnerNameMap;
+ private static IReadOnlyDictionary GetNameMap() => _spawnerNameMap ??= GenerateSpawnerNameMap();
+
+ private static IReadOnlyDictionary GenerateSpawnerNameMap()
+ {
+ var result = new Dictionary();
+
+ result[FnvHash.HashFnv1a_64("hoge")] = "hoge";
+
+ var gimmicks = new[] { "no", "tree", "rock", "crystal", "snow", "box", "leaves_r", "leaves_g", "yachi" };
+ foreach (var gimmick in gimmicks)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}")] = $"{gimmick}";
+ for (var which = 0; which < 20; which++)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}{which:00}")] = $"{gimmick}{which:00}";
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{which:00}")] = $"{gimmick}_{which:00}";
+ for (var i = 0; i < 100; i++)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{which:00}_{i:00}")] = $"{gimmick}_{which:00}_{i:00}";
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{which:00}_ex{i:00}")] = $"{gimmick}_{which:00}_ex{i:00}";
+ for (var j = 0; j < 3; j++)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{which:00}_{i:00}_{j:00}")] = $"{gimmick}_{which:00}_{i:00}_{j:00}";
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{which:00}_ex{i:00}_{j:00}")] = $"{gimmick}_{which:00}_ex{i:00}_{j:00}";
+ for (var k = 0; k < 3; k++)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{which:00}_{i:00}{j:00}_{k:00}")] = $"{gimmick}_{which:00}_{i:00}{j:00}_{k:00}";
+ }
+ }
+ }
+ }
+
+
+ for (var w1 = 0; w1 < 5; w1++)
+ {
+ for (var w2 = 0; w2 < 5; w2++)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{w1:00}_{w2:00}")] = $"{gimmick}_{w1:00}_{w2:00}";
+ for (var i = 0; i < 100; i++)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{w1:00}_{w2:00}_{i:00}")] = $"{gimmick}_{w1:00}_{w2:00}_{i:00}";
+ for (var j = 0; j < 3; j++)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{w1:00}_{w2:00}_{i:00}_{j:00}")] = $"{gimmick}_{w1:00}_{w2:00}_{i:00}_{j:00}";
+ for (var k = 0; k < 3; k++)
+ {
+ result[FnvHash.HashFnv1a_64($"{gimmick}_{w1:00}_{w2:00}_{i:00}{j:00}_{k:00}")] = $"{gimmick}_{w1:00}_{w2:00}_{i:00}{j:00}_{k:00}";
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class LandmarkItemSpawn8a_F03
+{
+ [FlatBufferItem(00)] public int Field_00 { get; set; }
+ [FlatBufferItem(01)] public int Field_01 { get; set; }
+ [FlatBufferItem(02)] public bool Field_02 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/LandmarkItemTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/LandmarkItemTable8a.cs
new file mode 100644
index 00000000..2251b164
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/LandmarkItemTable8a.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using FlatSharp.Attributes;
+using pkNX.Containers;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class LandmarkItemTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public LandmarkItem8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class LandmarkItem8a : ISlotTableConsumer
+{
+ [FlatBufferItem(00)] public string Field_00 { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public ulong Field_01 { get; set; }
+ [FlatBufferItem(02)] public ulong LandmarkItemNameID { get; set; }
+ [FlatBufferItem(03)] public PlacementParameters8a[] Field_03 { get; set; } = Array.Empty();
+ [FlatBufferItem(04)] public float Scalar { get; set; }
+ [FlatBufferItem(05)] public FlatDummyObject Field_05 { get; set; } = new();
+ [FlatBufferItem(06)] public FlatDummyObject Field_06 { get; set; } = new();
+ [FlatBufferItem(07)] public FlatDummyObject Field_07 { get; set; } = new();
+ [FlatBufferItem(08)] public ulong LandmarkItemSpawnTableID { get; set; }
+
+ public PlacementParameters8a Parameters
+ {
+ get { if (Field_03.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_03)}"); return Field_03[0]; }
+ set { if (Field_03.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_03)}"); Field_03[0] = value; }
+ }
+
+ public bool UsesTable(ulong table) => LandmarkItemSpawnTableID == table;
+
+ public IEnumerable GetIntersectingLocations(IReadOnlyList locations, float bias)
+ {
+ var c = Parameters.Coordinates;
+ return GetIntersectingLocations(locations, bias, c, Scalar + bias);
+ }
+
+ private static IEnumerable GetIntersectingLocations(IReadOnlyList locations, float bias, PlacementV3f8a c, float scalar)
+ {
+ var result = new List();
+ foreach (var loc in locations)
+ {
+ if (!loc.IsNamedPlace)
+ continue;
+ if (loc.IntersectsSphere(c.X, c.Y, c.Z, scalar))
+ result.Add(loc);
+ }
+
+ if (result.Count == 0)
+ result.Add(locations.First(l => l.IsNamedPlace)); // base area name
+ return result;
+ }
+
+ public IEnumerable GetContainingLocations(IReadOnlyList locations)
+ {
+ var result = new List();
+ foreach (var loc in locations)
+ {
+ if (!loc.IsNamedPlace)
+ continue;
+ if (loc.Contains(Parameters.Coordinates))
+ result.Add(loc);
+ }
+ if (result.Count == 0)
+ result.Add(locations.First(l => l.IsNamedPlace)); // base area name
+ return result;
+ }
+
+ public string NameSummary
+ {
+ get
+ {
+ var map = GetNameMap();
+ if (map.TryGetValue(LandmarkItemNameID, out var name))
+ return $"\"{name}\"";
+
+ return $"0x{LandmarkItemNameID:X16}";
+ }
+ }
+
+ private static IReadOnlyDictionary? _landmarkItemNameMap;
+ private static IReadOnlyDictionary GetNameMap() => _landmarkItemNameMap ??= GenerateLandmarkItemNameMap();
+
+ private static IReadOnlyDictionary GenerateLandmarkItemNameMap()
+ {
+ var result = new Dictionary();
+
+ var gimmicks = new[] { "no", "tree", "rock", "crystal", "snow", "box", "leaves_r", "leaves_g", "yachi" };
+ foreach (var gimmick in gimmicks)
+ {
+ result[FnvHash.HashFnv1a_64($"gimmick_{gimmick}")] = $"gimmick_{gimmick}";
+ for (var which = 0; which < 20; which++)
+ {
+ result[FnvHash.HashFnv1a_64($"gimmick_{gimmick}{which:00}")] = $"gimmick_{gimmick}{which:00}";
+ result[FnvHash.HashFnv1a_64($"gimmick_{gimmick}_{which:00}")] = $"gimmick_{gimmick}_{which:00}";
+ }
+ }
+
+ for (var which = 0; which < 20; which++)
+ {
+ result[FnvHash.HashFnv1a_64($"gimmick_tree{which:00}_snow")] = $"gimmick_tree{which:00}_snow";
+ foreach (var color in new[] { "blue", "pink", "yellow" })
+ {
+ result[FnvHash.HashFnv1a_64($"gimmick_tree{which:00}_{color}")] = $"gimmick_tree{which:00}_{color}";
+ result[FnvHash.HashFnv1a_64($"gimmick_tree{which:00}_snow_{color}")] = $"gimmick_tree{which:00}_snow_{color}";
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/LbPointsTable.cs b/pkNX.Structures.FlatBuffers/Arceus/LbPointsTable.cs
new file mode 100644
index 00000000..c4a5499c
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/LbPointsTable.cs
@@ -0,0 +1,31 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class LbPointsTable : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public LbPointsInfo[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class LbPointsInfo
+{
+ [FlatBufferItem(00)] public int Field_00 { get; set; }
+ [FlatBufferItem(01)] public float Field_01 { get; set; }
+ [FlatBufferItem(02)] public float Field_02 { get; set; }
+ [FlatBufferItem(03)] public float Field_03 { get; set; }
+ [FlatBufferItem(04)] public int Field_04 { get; set; }
+ [FlatBufferItem(05)] public ulong Field_05 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Learnset8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Learnset8a.cs
new file mode 100644
index 00000000..edfa092a
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Learnset8a.cs
@@ -0,0 +1,51 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class Learnset8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public Learnset8aMeta[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class Learnset8aMeta
+{
+ [FlatBufferItem(0)] public ushort Species { get; set; }
+ [FlatBufferItem(1)] public ushort Form { get; set; }
+ [FlatBufferItem(2)] public Learnset8aEntry[] Mainline { get; set; } = Array.Empty();
+ [FlatBufferItem(3)] public Learnset8aEntry[] Arceus { get; set; } = Array.Empty();
+
+ public byte[] WriteAsLearn6()
+ {
+ using var ms = new MemoryStream();
+ using var br = new BinaryWriter(ms);
+ foreach (var entry in Arceus)
+ {
+ br.Write(entry.Move);
+ br.Write(entry.Level);
+ }
+ br.Write(-1);
+ return ms.ToArray();
+ }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class Learnset8aEntry
+{
+ [FlatBufferItem(0)] public ushort Level { get; set; }
+ [FlatBufferItem(1)] public ushort LevelMaster { get; set; }
+ [FlatBufferItem(2)] public ushort Move { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/MassOutbreakTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/MassOutbreakTable8a.cs
new file mode 100644
index 00000000..d84ee359
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/MassOutbreakTable8a.cs
@@ -0,0 +1,45 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class MassOutbreakTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public MassOutbreak8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class MassOutbreak8a : IFlatBufferArchive
+{
+ [FlatBufferItem(0)] public ulong Hash { get; set; }
+ [FlatBufferItem(1)] public int Field_01 { get; set; }
+ [FlatBufferItem(2)] public MassOutbreakInfo8a[] Table { get; set; } = Array.Empty();
+ [FlatBufferItem(3)] public string Field_03 { get; set; } = string.Empty;
+ [FlatBufferItem(4)] public int Field_04 { get; set; }
+ [FlatBufferItem(5)] public int Field_05 { get; set; }
+ [FlatBufferItem(6)] public int Field_06 { get; set; }
+ [FlatBufferItem(7)] public int Field_07 { get; set; }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class MassOutbreakInfo8a
+{
+ [FlatBufferItem(0)] public ulong Hash_00 { get; set; }
+ [FlatBufferItem(1)] public ulong Hash_01 { get; set; }
+ [FlatBufferItem(2)] public string Field_02 { get; set; } = string.Empty;
+ [FlatBufferItem(3)] public string Field_03 { get; set; } = string.Empty;
+ [FlatBufferItem(4)] public string Field_04 { get; set; } = string.Empty;
+ [FlatBufferItem(5)] public string Field_05 { get; set; } = string.Empty;
+ [FlatBufferItem(6)] public string Field_06 { get; set; } = string.Empty;
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/MoveShopTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/MoveShopTable8a.cs
new file mode 100644
index 00000000..4c21ed75
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/MoveShopTable8a.cs
@@ -0,0 +1,29 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class MoveShopTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public MoveShopIndex[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class MoveShopIndex
+{
+ [FlatBufferItem(0)] public int Index { get; set; }
+ [FlatBufferItem(1)] public int Move { get; set; }
+ [FlatBufferItem(2)] public int Price { get; set; }
+ [FlatBufferItem(3)] public ulong Hash { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/PersonalInfoLAfb.cs b/pkNX.Structures.FlatBuffers/Arceus/PersonalInfoLAfb.cs
new file mode 100644
index 00000000..dd049f75
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/PersonalInfoLAfb.cs
@@ -0,0 +1,190 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+using System.Linq;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+///
+/// class with values from the games.
+///
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PersonalTableLA : IFlatBufferArchive
+{
+ [FlatBufferItem(0)] public PersonalInfoLAfb[] Table { get; set; } = Array.Empty();
+}
+
+///
+/// class with values from the games.
+///
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PersonalInfoLAfb
+{
+ [FlatBufferItem(00)] public ushort Species { get; set; } // ushort
+ [FlatBufferItem(01)] public ushort Form { get; set; } // ushort
+ [FlatBufferItem(02)] public byte IsPresentInGame { get; set; } // byte
+ [FlatBufferItem(03)] public byte Type1 { get; set; } // byte
+ [FlatBufferItem(04)] public byte Type2 { get; set; } // byte
+ [FlatBufferItem(05)] public ushort Ability1 { get; set; } // ushort
+ [FlatBufferItem(06)] public ushort Ability2 { get; set; } // ushort
+ [FlatBufferItem(07)] public ushort AbilityH { get; set; } // ushort
+ [FlatBufferItem(08)] public byte Stat_HP { get; set; } // byte
+ [FlatBufferItem(09)] public byte Stat_ATK { get; set; } // byte
+ [FlatBufferItem(10)] public byte Stat_DEF { get; set; } // byte
+ [FlatBufferItem(11)] public byte Stat_SPA { get; set; } // byte
+ [FlatBufferItem(12)] public byte Stat_SPD { get; set; } // byte
+ [FlatBufferItem(13)] public byte Stat_SPE { get; set; } // byte
+ [FlatBufferItem(14)] public byte Gender { get; set; } // byte
+ [FlatBufferItem(15)] public byte EXPGrowth { get; set; } // byte
+ [FlatBufferItem(16)] public byte EvoStage { get; set; } // byte
+ [FlatBufferItem(17)] public byte CatchRate{ get; set; } // byte
+ [FlatBufferItem(18)] public byte Field_18 { get; set; } // Always Default (0)
+ [FlatBufferItem(19)] public byte Color { get; set; } // byte
+ [FlatBufferItem(20)] public ushort Height { get; set; } // ushort
+ [FlatBufferItem(21)] public ushort Weight { get; set; } // ushort
+ [FlatBufferItem(22)] public uint TM_A { get; set; } // uint, not used by game
+ [FlatBufferItem(23)] public uint TM_B { get; set; } // uint, not used by game
+ [FlatBufferItem(24)] public uint TM_C { get; set; } // uint, not used by game
+ [FlatBufferItem(25)] public uint TM_D { get; set; } // uint, not used by game
+ [FlatBufferItem(26)] public uint TR_A { get; set; } // uint, not used by game
+ [FlatBufferItem(27)] public uint TR_B { get; set; } // uint, not used by game
+ [FlatBufferItem(28)] public uint TR_C { get; set; } // uint, not used by game
+ [FlatBufferItem(29)] public uint TR_D { get; set; } // uint, not used by game
+ [FlatBufferItem(30)] public uint TypeTutor { get; set; } // uint, not used by game
+ [FlatBufferItem(31)] public ushort BaseEXP { get; set; } // ushort
+ [FlatBufferItem(32)] public byte EV_HP { get; set; } // byte
+ [FlatBufferItem(33)] public byte EV_ATK { get; set; } // byte
+ [FlatBufferItem(34)] public byte EV_DEF { get; set; } // byte
+ [FlatBufferItem(35)] public byte EV_SPA { get; set; } // byte
+ [FlatBufferItem(36)] public byte EV_SPD { get; set; } // byte
+ [FlatBufferItem(37)] public byte EV_SPE { get; set; } // byte
+ [FlatBufferItem(38)] public ushort Item1 { get; set; } // ushort
+ [FlatBufferItem(39)] public ushort Item2 { get; set; } // ushort
+ [FlatBufferItem(40)] public ushort Item3 { get; set; } // Always Default (0)
+ [FlatBufferItem(41)] public byte EggGroup1 { get; set; } // byte
+ [FlatBufferItem(42)] public byte EggGroup2 { get; set; } // byte
+ [FlatBufferItem(43)] public ushort HatchSpecies { get; set; } // ushort
+ [FlatBufferItem(44)] public ushort LocalFormIndex { get; set; } // ushort
+ [FlatBufferItem(45)] public byte Field_45 { get; set; } // byte
+ [FlatBufferItem(46)] public ushort Field_46 { get; set; } // ushort
+ [FlatBufferItem(47)] public byte Field_47 { get; set; } // byte
+ [FlatBufferItem(48)] public byte BaseFriendship { get; set; } // byte
+ [FlatBufferItem(49)] public ushort DexIndexHisui { get; set; } // ushort
+ [FlatBufferItem(50)] public ushort DexIndexOther { get; set; } // ushort
+ [FlatBufferItem(51)] public int DexIndexLocal1 { get; set; } // uint
+ [FlatBufferItem(52)] public int DexIndexLocal2 { get; set; } // uint
+ [FlatBufferItem(53)] public int DexIndexLocal3 { get; set; } // uint
+ [FlatBufferItem(54)] public int DexIndexLocal4 { get; set; } // uint
+ [FlatBufferItem(55)] public int DexIndexLocal5 { get; set; } // uint
+ [FlatBufferItem(56)] public uint MoveShop1 { get; set; } // uint
+ [FlatBufferItem(57)] public uint MoveShop2 { get; set; } // uint
+}
+
+public static class PersonalConverter
+{
+ public static byte[] GetBin(PersonalTableLA table)
+ {
+ var all = FromArceus(table);
+ var data = all.SelectMany(z => z.Write()).ToArray();
+ return data;
+ }
+
+ public static PersonalInfoLA[] FromArceus(PersonalTableLA table)
+ {
+ var max = table.Table.Max(z => z.Species);
+ var baseForms = new PersonalInfoLA[max + 1];
+ var formTable = new List();
+
+ for (int i = 0; i <= max; i++)
+ {
+ var forms = table.Table.Where(z => z.Species == (ushort)i).OrderBy(z => z.Form).ToList();
+
+ var e = forms[0];
+ baseForms[i] = GetObj(e, forms, max, formTable);
+ for (int f = 1; f < forms.Count; f++)
+ formTable.Add(GetObj(forms[f], forms, max, formTable, f));
+ }
+
+ return baseForms.Concat(formTable).ToArray();
+ }
+
+ // ugly converter to be a data-backed object
+ private static PersonalInfoLA GetObj(PersonalInfoLAfb e, List forms, ushort max, List formTable, int f = 0)
+ {
+ var result = new PersonalInfoLA(new byte[PersonalInfoLA.SIZE])
+ {
+ HP = e.Stat_HP,
+ ATK = e.Stat_ATK,
+ DEF = e.Stat_DEF,
+ SPA = e.Stat_SPA,
+ SPD = e.Stat_SPD,
+ SPE = e.Stat_SPE,
+ FormeCount = forms.Count,
+ Type1 = e.Type1,
+ Type2 = e.Type2,
+ Gender = e.Gender,
+ Ability1 = e.Ability1,
+ Ability2 = e.Ability2,
+ AbilityH = e.AbilityH,
+ IsPresentInGame = e.IsPresentInGame == 1,
+ Item1 = e.Item1,
+ Item2 = e.Item2,
+ Height = e.Height,
+ Weight = e.Weight,
+ EggGroup1 = e.EggGroup1,
+ EggGroup2 = e.EggGroup2,
+ EvoStage = e.EvoStage,
+ BaseFriendship = e.BaseFriendship,
+ EXPGrowth = e.EXPGrowth,
+ HatchSpecies = e.HatchSpecies,
+ LocalFormIndex = e.LocalFormIndex,
+ EV_HP = e.EV_HP,
+ EV_ATK = e.EV_ATK,
+ EV_DEF = e.EV_DEF,
+ EV_SPA = e.EV_SPA,
+ EV_SPD = e.EV_SPD,
+ EV_SPE = e.EV_SPE,
+ CatchRate = e.CatchRate,
+ DexIndexHisui = e.DexIndexHisui,
+ DexIndexLocal1 = e.DexIndexLocal1,
+ DexIndexLocal2 = e.DexIndexLocal2,
+ DexIndexLocal3 = e.DexIndexLocal3,
+ DexIndexLocal4 = e.DexIndexLocal4,
+ DexIndexLocal5 = e.DexIndexLocal5,
+ Color = e.Color,
+ BaseEXP = e.BaseEXP,
+
+ Species = e.Species,
+ Form = e.Form,
+ };
+ result.SetFormStat(f != 0 ? 0 : forms.Count == 1 ? 0 : max + formTable.Count + 1);
+
+ var shop = e.MoveShop1 | ((ulong)e.MoveShop2 << 32);
+ bool[] flags = new bool[64];
+ for (int i = 0; i < flags.Length; i++)
+ flags[i] = (shop & (1ul << i)) != 0;
+ result.SpecialTutors = new[] { flags };
+
+ BitConverter.GetBytes(e.TM_A).CopyTo(result.Data, 0x28);
+ BitConverter.GetBytes(e.TM_B).CopyTo(result.Data, 0x2C);
+ BitConverter.GetBytes(e.TM_C).CopyTo(result.Data, 0x30);
+ BitConverter.GetBytes(e.TM_D).CopyTo(result.Data, 0x34);
+ BitConverter.GetBytes(e.TypeTutor).CopyTo(result.Data, 0x38);
+ BitConverter.GetBytes(e.TR_A).CopyTo(result.Data, 0x3C);
+ BitConverter.GetBytes(e.TR_B).CopyTo(result.Data, 0x40);
+ BitConverter.GetBytes(e.TR_C).CopyTo(result.Data, 0x44);
+ BitConverter.GetBytes(e.TR_D).CopyTo(result.Data, 0x48);
+ result.LoadTMHM();
+ result.LoadTutors();
+
+ return result;
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/AreaInstance8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/AreaInstance8a.cs
new file mode 100644
index 00000000..25d3a083
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/AreaInstance8a.cs
@@ -0,0 +1,66 @@
+using pkNX.Containers;
+using System;
+using System.Collections.Generic;
+
+namespace pkNX.Structures.FlatBuffers;
+
+// Not a flatbuffer; wraps the fields into a single object.
+public sealed class AreaInstance8a
+{
+ public readonly string AreaName;
+
+ public readonly PlacementLocation8a[] Locations;
+ public readonly PlacementSpawner8a[] Spawners;
+ public readonly PlacementSpawner8a[] Wormholes;
+ public readonly LandmarkItemSpawn8a[] LandItems;
+ public readonly LandmarkItem8a[] LandMarks;
+ public readonly PlacementUnnnEntry[] Unown;
+ public readonly PlacementMkrgEntry[] Mikaruge;
+
+ public readonly EncounterDataArchive8a Encounters;
+
+ public readonly AreaInstance8a? ParentArea;
+ public readonly List SubAreas;
+
+ public bool IsSubArea => ParentArea != null;
+
+ private AreaInstance8a(GFPack resident, string areaName, AreaInstance8a? parentArea)
+ {
+ var f = resident.GetDataFullPath($"bin/encount/{areaName}/encount_data.bin");
+ Encounters = FlatBufferConverter.DeserializeFrom(f);
+
+ var locationf = resident.GetDataFullPath($"bin/field/param/placement/{areaName}/location/location.bin");
+ var spawnerf = resident.GetDataFullPath($"bin/field/param/placement/{areaName}/spawner/spawner_data.bin");
+ var wh_spawnerf = resident.GetDataFullPath($"bin/field/param/placement/{areaName}/wh_spawner/spawner_data.bin");
+ var l_spawnerf = resident.GetDataFullPath($"bin/field/param/placement/{areaName}/landmark_item/expansion/landmark_item_spawn_table.bin");
+ var l_markf = resident.GetDataFullPath($"bin/field/param/placement/{areaName}/landmark_item/landmark_item.bin");
+ var unnf = resident.GetDataFullPath($"bin/field/param/placement/{areaName}/unnn/unnn.bin");
+ var mkrgf = resident.GetDataFullPath($"bin/field/param/placement/{areaName}/mkrg/mkrg.bin");
+
+ Locations = FlatBufferConverter.DeserializeFrom(locationf).Table;
+ Spawners = FlatBufferConverter.DeserializeFrom(spawnerf).Table;
+ Wormholes = FlatBufferConverter.DeserializeFrom(wh_spawnerf).Table;
+ LandItems = FlatBufferConverter.DeserializeFrom(l_spawnerf).Table;
+ LandMarks = FlatBufferConverter.DeserializeFrom(l_markf).Table;
+ Unown = FlatBufferConverter.DeserializeFrom(unnf).Table;
+ Mikaruge = FlatBufferConverter.DeserializeFrom(mkrgf).Table;
+
+ AreaName = areaName;
+
+ ParentArea = parentArea;
+ SubAreas = new List();
+ }
+
+ public static AreaInstance8a Create(GFPack resident, string[] areaNameList)
+ {
+ if (areaNameList.Length < 1)
+ throw new ArgumentException("Invalid area name list!");
+
+ var parentArea = new AreaInstance8a(resident, areaNameList[0], null);
+
+ for (var i = 1; i < areaNameList.Length; i++)
+ parentArea.SubAreas.Add(new AreaInstance8a(resident, areaNameList[i], parentArea));
+
+ return parentArea;
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/OybnSettingTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/OybnSettingTable8a.cs
new file mode 100644
index 00000000..0e2e29b4
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/OybnSettingTable8a.cs
@@ -0,0 +1,31 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class OybnSettingTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public OybnSetting8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class OybnSetting8a
+{
+ [FlatBufferItem(00)] public ulong Hash { get; set; }
+ [FlatBufferItem(01)] public int Field_01 { get; set; }
+ [FlatBufferItem(02)] public int Field_02 { get; set; }
+ [FlatBufferItem(03)] public int Field_03 { get; set; }
+ [FlatBufferItem(04)] public int Field_04 { get; set; }
+ [FlatBufferItem(05)] public int Field_05 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementItemArchive8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementItemArchive8a.cs
new file mode 100644
index 00000000..86ff2996
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementItemArchive8a.cs
@@ -0,0 +1,51 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementItemArchive8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PlacementItem8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementItem8a
+{
+ [FlatBufferItem(00)] public string Field_00 { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public ulong Field_01 { get; set; }
+ [FlatBufferItem(02)] public ulong Field_02 { get; set; }
+ [FlatBufferItem(03)] public PlacementItem8a_F03[] Field_03 { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementItem8a_F03
+{
+ [FlatBufferItem(00)] public byte Field_00 { get; set; }
+ [FlatBufferItem(01)] public byte Field_01 { get; set; }
+ [FlatBufferItem(02)] public string Field_02 { get; set; } = string.Empty;
+ [FlatBufferItem(03)] public string Field_03 { get; set; } = string.Empty;
+ [FlatBufferItem(04)] public string Field_04 { get; set; } = string.Empty;
+ [FlatBufferItem(05)] public string Field_05 { get; set; } = string.Empty;
+ [FlatBufferItem(06)] public string Field_06 { get; set; } = string.Empty;
+ [FlatBufferItem(07)] public PlacementV3f8a Field_07 { get; set; } = new();
+ [FlatBufferItem(08)] public PlacementItem8a_F08 Field_08 { get; set; } = new();
+ [FlatBufferItem(09)] public PlacementV3f8a Field_09 { get; set; } = new();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementItem8a_F08
+{
+ [FlatBufferItem(00)] public byte Field_00 { get; set; } // unk
+ [FlatBufferItem(01)] public float Field_01 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementLocation8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementLocation8a.cs
new file mode 100644
index 00000000..0c6bdaf9
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementLocation8a.cs
@@ -0,0 +1,226 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Numerics;
+using FlatSharp.Attributes;
+using pkNX.Containers;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementLocation8a
+{
+ public const ulong ShapeIdSphere = 0x645FB59E96A6F998;
+ public const ulong ShapeIdBox = 0xE6B50E272D8CD992;
+ public const ulong ShapeNone = 0xCBF29CE484222645;
+
+ [FlatBufferEnum(typeof(ulong))]
+ public enum LocationType8a : ulong
+ {
+ Bgm = 0xD090DB268FBCE531, // "Bgm"
+ BuddyInfeasibleOcclusion = 0x1713B588A00FF9F2, // "BuddyInfeasibleOcclusion"
+ Evolution = 0x51550D70709EA65E, // "Evolution"
+ LightOcclusion = 0x94FEC9F97E988350, // "LightOcclusion"
+ NoRespawnOcclusion = 0xD91EE555A7E6DC07, // "NoRespawnOcclusion"
+ OcclusionSpace = 0x613F7FD830366C6C, // "OcclusionSpace"
+ PlaceName = 0x0351C91B3FD84C97, // "PlaceName
+ RideInfeasibleOcclusion = 0x677D529DBB999AD6, // "RideInfeasibleOcclusion"
+ SafetyArea = 0x4C62CAA0FF9B445A, // "SafetyArea"
+ SaveGameOver = 0x77EEDD438D48D1B8, // "SaveGameOver"
+ TakeOffShoesOcclusion = 0x09FBFD6B423FAEA6, // "TakeOffShoesOcclusion"
+ TreeCullingFrustumFar = 0xD55673931A300690, // "TreeCullingFrustumFar"
+ WeatherOcclusion = 0x2B3435F7DF6CF454, // "WeatherOcclusion"
+ };
+
+ [FlatBufferItem(0)] public string Field_00 { get; set; } = string.Empty;
+ [FlatBufferItem(1)] public ulong Field_01 { get; set; }
+ [FlatBufferItem(2)] public PlacementParameters8a[] ParameterSet { get; set; } = { new() };
+ [FlatBufferItem(3)] public ulong ShapeID { get; set; }
+ [FlatBufferItem(4)] public float SizeX { get; set; }
+ [FlatBufferItem(5)] public float SizeY { get; set; }
+ [FlatBufferItem(6)] public float SizeZ { get; set; }
+ [FlatBufferItem(7)] public ulong LocationTypeID { get; set; }
+ [FlatBufferItem(8)] public string LocationTypeArg1 { get; set; } = string.Empty;
+ [FlatBufferItem(9)] public ulong LocationTypeArg2 { get; set; }
+
+ public PlacementParameters8a Parameters
+ {
+ get { if (ParameterSet.Length != 1) throw new ArgumentException($"Invalid {nameof(ParameterSet)}"); return ParameterSet[0]; }
+ set { if (ParameterSet.Length != 1) throw new ArgumentException($"Invalid {nameof(ParameterSet)}"); ParameterSet[0] = value; }
+ }
+
+ public bool IsNamedPlace => LocationTypeID == 0x0351C91B3FD84C97;
+ public string PlaceName => LocationTypeArg1;
+
+ public string ShapeSummary => ShapeID switch
+ {
+ ShapeIdSphere => "/* Shape = */ \"sphere\"",
+ ShapeIdBox => "/* Shape = */ \"box\"",
+ ShapeNone => "/* Shape = */ \"\"",
+ _ => $"/* Shape = */ 0x{ShapeID:X16}",
+ };
+
+ public bool Contains(float x, float y, float z)
+ {
+ if (ShapeID == ShapeIdSphere)
+ {
+ if (!Parameters.Scale.IsDefault)
+ throw new NotImplementedException("Scaled spheres not yet supported!");
+
+ var radius = Math.Abs(SizeX);
+ var distance = Parameters.Coordinates.DistanceTo(x, y, z);
+ return distance <= radius;
+ }
+ if (ShapeID == ShapeIdBox)
+ {
+ // Get the details of the box
+ var center = new Vector3(Parameters.Coordinates.X, Parameters.Coordinates.Y, Parameters.Coordinates.Z);
+ var rotation = Quaternion.CreateFromYawPitchRoll(Parameters.Rotation.Y * (float)Math.PI / 180.0f, Parameters.Rotation.X * (float)Math.PI / 180.0f, Parameters.Rotation.Z * (float)Math.PI / 180.0f);
+ var inverseRotation = Quaternion.Conjugate(rotation);
+
+ // Get the distance to the point along non-rotated axes
+ var delta = Vector3.Transform(new Vector3(x, y, z) - center, inverseRotation);
+
+ var x_unit = Parameters.Scale.X * SizeX / 2;
+ var y_unit = Parameters.Scale.Y * SizeY / 2;
+ var z_unit = Parameters.Scale.Z * SizeZ / 2;
+
+ // Check that the point is within unit-distance along all axes
+ if (Math.Abs(delta.X) > Math.Abs(x_unit))
+ return false;
+ if (Math.Abs(delta.Y) > Math.Abs(y_unit))
+ return false;
+ if (Math.Abs(delta.Z) > Math.Abs(z_unit))
+ return false;
+
+ return true;
+ }
+ {
+ if (ShapeID != ShapeNone) // ""
+ throw new NotImplementedException("Unknown ShapeID!");
+ return false;
+ }
+ }
+
+ public bool IntersectsSphere(float x, float y, float z, float sphereRadius)
+ {
+ if (sphereRadius == 0)
+ return Contains(x, y, z);
+
+ if (ShapeID == ShapeIdSphere)
+ {
+ if (!Parameters.Scale.IsDefault)
+ throw new NotImplementedException("Scaled spheres not yet supported!");
+
+ var radius = Math.Abs(SizeX);
+ var distance = Parameters.Coordinates.DistanceTo(x, y, z);
+ return distance <= radius + sphereRadius;
+ }
+ if (ShapeID == ShapeIdBox)
+ {
+ // Get the details of the box
+ var center = new Vector3(Parameters.Coordinates.X, Parameters.Coordinates.Y, Parameters.Coordinates.Z);
+ var rotation = Quaternion.CreateFromYawPitchRoll(Parameters.Rotation.Y * (float)Math.PI / 180.0f, Parameters.Rotation.X * (float)Math.PI / 180.0f, Parameters.Rotation.Z * (float)Math.PI / 180.0f);
+ var inverseRotation = Quaternion.Conjugate(rotation);
+
+ // Get the distance to the point along non-rotated axes
+ var sphereCenter = new Vector3(x, y, z);
+ var delta = Vector3.Transform(sphereCenter - center, inverseRotation);
+
+ var x_unit = Parameters.Scale.X * SizeX / 2;
+ var y_unit = Parameters.Scale.Y * SizeY / 2;
+ var z_unit = Parameters.Scale.Z * SizeZ / 2;
+
+ var contains = true;
+
+ if (Math.Abs(delta.X) > Math.Abs(x_unit))
+ {
+ contains = false;
+ delta.X = Math.Abs(x_unit) * Math.Sign(delta.X);
+ }
+
+ if (Math.Abs(delta.Y) > Math.Abs(y_unit))
+ {
+ contains = false;
+ delta.Y = Math.Abs(y_unit) * Math.Sign(delta.Y);
+ }
+
+ if (Math.Abs(delta.Z) > Math.Abs(z_unit))
+ {
+ contains = false;
+ delta.Z = Math.Abs(z_unit) * Math.Sign(delta.Z);
+ }
+
+ // If the point is contained, it necessarily intersects
+ if (contains)
+ return true;
+
+ // Get the point on the box closest to the sphere
+ var closest = center + Vector3.Transform(delta, rotation);
+
+ // Check if closest point on box is within sphere's radius
+ var distance = Vector3.Distance(closest, sphereCenter);
+ return distance <= sphereRadius;
+ }
+ {
+ if (ShapeID != ShapeNone) // ""
+ throw new NotImplementedException("Unknown ShapeID!");
+ return false;
+ }
+ }
+
+ public bool Contains(PlacementV3f8a v) => Contains(v.X, v.Y, v.Z);
+
+ public string LocationTypeSummary
+ {
+ get
+ {
+ if (LocationTypeArg2 != 0xCBF29CE484222645)
+ return $"{LocationTypeIdSummary}(\"{LocationTypeArg1}\", {LocationArg2Summary})";
+
+ if (!string.IsNullOrEmpty(LocationTypeArg1))
+ return $"{LocationTypeIdSummary}(\"{LocationTypeArg1}\")";
+
+ return LocationTypeIdSummary;
+ }
+ }
+
+ public string LocationTypeIdSummary
+ {
+ get
+ {
+ if (!Enum.IsDefined(typeof(LocationType8a), LocationTypeID))
+ throw new ArgumentOutOfRangeException(nameof(LocationTypeID), LocationTypeID, $"Unknown 0x{LocationTypeID:X16}.");
+ return Enum.GetName(typeof(LocationType8a), LocationTypeID);
+ }
+ }
+
+ // lazy init
+ private static IReadOnlyDictionary? _locationArgMap;
+ private static IReadOnlyDictionary GetLocationArgMap() => _locationArgMap ??= GenerateLocationArgMap();
+
+ private static IReadOnlyDictionary GenerateLocationArgMap()
+ {
+ var result = new Dictionary();
+ result[0xCBF29CE484222645] = "";
+
+ // PlaceName
+ result[FnvHash.HashFnv1a_64("NoneReport")] = "NoneReport";
+
+ // Bgm
+ result[FnvHash.HashFnv1a_64("LOW")] = "LOW";
+ result[FnvHash.HashFnv1a_64("HIGH")] = "HIGH";
+ return result;
+ }
+
+ public string LocationArg2Summary => GetLocationArgMap().TryGetValue(LocationTypeArg2, out var arg) ? $"\"{arg}\"" : $"0x{LocationTypeArg2:X16}";
+
+ public override string ToString() => $"Location(\"{Field_00}\", 0x{Field_01:X16}, {Parameters}, {ShapeSummary}, {SizeX}, {SizeY}, {SizeZ}, {LocationTypeSummary})";
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementLocationArchive8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementLocationArchive8a.cs
new file mode 100644
index 00000000..0444858b
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementLocationArchive8a.cs
@@ -0,0 +1,20 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementLocationArchive8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PlacementLocation8a[] Table { get; set; } = Array.Empty();
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementMkrgTable.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementMkrgTable.cs
new file mode 100644
index 00000000..d0451a97
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementMkrgTable.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementMkrgTable : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PlacementMkrgEntry[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementMkrgEntry
+{
+ [FlatBufferItem(0)] public string Identifier { get; set; } = string.Empty;
+ [FlatBufferItem(1)] public ulong Hash_01 { get; set; }
+ [FlatBufferItem(2)] public PlacementParameters8a[] Field_02 { get; set; } = Array.Empty();
+ [FlatBufferItem(3)] public float Field_03 { get; set; }
+ [FlatBufferItem(4)] public float Field_04 { get; set; }
+
+ public PlacementParameters8a Parameters
+ {
+ get { if (Field_02.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_02)}"); return Field_02[0]; }
+ set { if (Field_02.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_02)}"); Field_02[0] = value; }
+ }
+
+ public override string ToString() => $"Mikaruge(\"{Identifier}\", 0x{Hash_01:X16}, {Parameters}, {Field_03}, {Field_04})";
+
+ public IEnumerable GetContainingLocations(IReadOnlyList locations)
+ {
+ var result = new List();
+ foreach (var loc in locations)
+ {
+ if (!loc.IsNamedPlace)
+ continue;
+ if (loc.Contains(Parameters.Coordinates))
+ result.Add(loc);
+ }
+ if (result.Count == 0)
+ result.Add(locations.First(l => l.IsNamedPlace)); // base area name
+ return result;
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementParameters8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementParameters8a.cs
new file mode 100644
index 00000000..dee0330c
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementParameters8a.cs
@@ -0,0 +1,28 @@
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementParameters8a : IHasCondition8a
+{
+ [FlatBufferItem(0)] public ConditionType8a ConditionTypeID { get; set; }
+ [FlatBufferItem(1)] public Condition8a ConditionID { get; set; }
+ [FlatBufferItem(2)] public string ConditionArg1 { get; set; } = string.Empty;
+ [FlatBufferItem(3)] public string ConditionArg2 { get; set; } = string.Empty;
+ [FlatBufferItem(4)] public string ConditionArg3 { get; set; } = string.Empty;
+ [FlatBufferItem(5)] public string ConditionArg4 { get; set; } = string.Empty;
+ [FlatBufferItem(6)] public string ConditionArg5 { get; set; } = string.Empty;
+ [FlatBufferItem(7)] public PlacementV3f8a Coordinates { get; set; } = new();
+ [FlatBufferItem(8)] public PlacementV3f8a Rotation { get; set; } = new();
+ [FlatBufferItem(9)] public PlacementV3f8a Scale { get; set; } = new();
+
+ public override string ToString() => $"PlacementParameters(/* ConditionTypeID = */ {this.GetConditionTypeSummary()}, /* Condition = */ {this.GetConditionSummary()}, {Coordinates}, {Rotation}, {Scale})";
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawner8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawner8a.cs
new file mode 100644
index 00000000..43a28568
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawner8a.cs
@@ -0,0 +1,216 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using FlatSharp.Attributes;
+using pkNX.Containers;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementSpawner8a : ISlotTableConsumer
+{
+ [FlatBufferItem(0)] public ulong SpawnerID { get; set; }
+ [FlatBufferItem(1)] public ulong Field_01 { get; set; }
+ [FlatBufferItem(2)] public PlacementParameters8a[] Field_02 { get; set; } = { new() };
+ [FlatBufferItem(3)] public string Field_03 { get; set; } = string.Empty;
+ [FlatBufferItem(4)] public float Scalar { get; set; }
+ [FlatBufferItem(5)] public PlacementV3f8a Field_05 { get; set; } = new();
+ [FlatBufferItem(6)] public PlacementV3f8a Field_06 { get; set; } = new();
+ [FlatBufferItem(7)] public int Field_07 { get; set; }
+ [FlatBufferItem(8)] public int Field_08 { get; set; }
+ [FlatBufferItem(9)] public int Field_09 { get; set; }
+ [FlatBufferItem(10)] public bool Field_10 { get; set; }
+ [FlatBufferItem(11)] public bool Field_11 { get; set; }
+ [FlatBufferItem(12)] public bool Field_12 { get; set; }
+ [FlatBufferItem(13)] public ulong GroupID { get; set; }
+ [FlatBufferItem(14)] public float Field_14 { get; set; }
+ [FlatBufferItem(15)] public float Field_15 { get; set; }
+ [FlatBufferItem(16)] public int Field_16 { get; set; }
+ [FlatBufferItem(17)] public float Field_17 { get; set; }
+ [FlatBufferItem(18)] public float Field_18 { get; set; }
+ [FlatBufferItem(19)] public float Field_19 { get; set; }
+ [FlatBufferItem(20)] public PlacementSpawnerF208a[] Field_20 { get; set; } = { new() };
+ [FlatBufferItem(21)] public PlacementSpawnerF218a[] Field_21 { get; set; } = { new() };
+ [FlatBufferItem(22)] public string[] Field_22 { get; set; } = { string.Empty };
+
+ public PlacementParameters8a Parameters
+ {
+ get { if (Field_02.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_02)}"); return Field_02[0]; }
+ set { if (Field_02.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_02)}"); Field_02[0] = value; }
+ }
+
+ public PlacementSpawnerF208a Field_20_Value
+ {
+ get { if (Field_20.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_20)}"); return Field_20[0]; }
+ set { if (Field_20.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_20)}"); Field_20[0] = value; }
+ }
+
+ public PlacementSpawnerF218a Field_21_Value
+ {
+ get { if (Field_21.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_21)}"); return Field_21[0]; }
+ set { if (Field_21.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_21)}"); Field_21[0] = value; }
+ }
+
+ public string Field_22_Value
+ {
+ get { if (Field_22.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_22)}"); return Field_22[0]; }
+ set { if (Field_22.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_22)}"); Field_22[0] = value; }
+ }
+
+ public IEnumerable GetIntersectingLocations(IReadOnlyList locations, float bias)
+ {
+ var c = Parameters.Coordinates;
+ return GetIntersectingLocations(locations, bias, c, Scalar + bias);
+ }
+
+ private static IEnumerable GetIntersectingLocations(IReadOnlyList locations, float bias, PlacementV3f8a c, float scalar)
+ {
+ var result = new List();
+ foreach (var loc in locations)
+ {
+ if (!loc.IsNamedPlace)
+ continue;
+ if (loc.IntersectsSphere(c.X, c.Y, c.Z, scalar))
+ result.Add(loc);
+ }
+
+ if (result.Count == 0)
+ result.Add(locations.First(l => l.IsNamedPlace)); // base area name
+ return result;
+ }
+
+ public IEnumerable GetContainingLocations(IReadOnlyList locations)
+ {
+ var result = new List();
+ foreach (var loc in locations)
+ {
+ if (!loc.IsNamedPlace)
+ continue;
+ if (loc.Contains(Parameters.Coordinates))
+ result.Add(loc);
+ }
+ if (result.Count == 0)
+ result.Add(locations.First(l => l.IsNamedPlace)); // base area name
+ return result;
+ }
+
+ private static IReadOnlyDictionary? _spawnerNameMap;
+ private static IReadOnlyDictionary GetSpawnerNameMap() => _spawnerNameMap ??= GenerateSpawnerNameMap();
+
+ private static IReadOnlyDictionary GenerateSpawnerNameMap()
+ {
+ var result = new Dictionary();
+
+ for (var i = 0; i < 10000; i++)
+ {
+ result[FnvHash.HashFnv1a_64($"{i:0000}")] = $"{i:0000}";
+ result[FnvHash.HashFnv1a_64($"1{i:0000}")] = $"1{i:0000}";
+ result[FnvHash.HashFnv1a_64($"02{i:0000}")] = $"02{i:0000}";
+ result[FnvHash.HashFnv1a_64($"03{i:0000}")] = $"03{i:0000}";
+ result[FnvHash.HashFnv1a_64($"4{i:0000}")] = $"4{i:0000}";
+ result[FnvHash.HashFnv1a_64($"5{i:0000}")] = $"5{i:0000}";
+ result[FnvHash.HashFnv1a_64($"ev{i:0000}")] = $"ev{i:0000}";
+ result[FnvHash.HashFnv1a_64($"ex_{i:0000}")] = $"ex_{i:0000}";
+ result[FnvHash.HashFnv1a_64($"eve_ex_{i:0000}")] = $"eve_ex_{i:0000}";
+
+ result[FnvHash.HashFnv1a_64($"huge_{i:0000}")] = $"huge_{i:0000}";
+
+ for (var j = 0; j < 20; j++)
+ {
+ result[FnvHash.HashFnv1a_64($"{i:0000}_{j:00}")] = $"{i:0000}_{j:00}";
+ }
+ }
+
+ for (var i = 0; i < 100; i++)
+ {
+ result[FnvHash.HashFnv1a_64($"area00_{i:00}")] = $"area00_{i:00}";
+ result[FnvHash.HashFnv1a_64($"poke{i:00}")] = $"poke{i:00}";
+ result[FnvHash.HashFnv1a_64($"sky{i:00}")] = $"sky{i:00}";
+ result[FnvHash.HashFnv1a_64($"lnd_no_{i:00}")] = $"lnd_no_{i:00}";
+ result[FnvHash.HashFnv1a_64($"sky_{i:00}")] = $"sky_{i:00}";
+ result[FnvHash.HashFnv1a_64($"ex_mkrg_{i:00}")] = $"ex_mkrg_{i:00}";
+ result[FnvHash.HashFnv1a_64($"ex_unnn_{i:00}")] = $"ex_unnn_{i:00}";
+ }
+
+ result[FnvHash.HashFnv1a_64($"ha_area01_s01_ev001")] = $"ha_area01_s01_ev001";
+ result[FnvHash.HashFnv1a_64($"ha_area02_s02_ev001")] = $"ha_area01_s02_ev001";
+ result[FnvHash.HashFnv1a_64($"ha_area02_s02_ev002")] = $"ha_area01_s02_ev002";
+ result[FnvHash.HashFnv1a_64($"ha_area03_s03_ev001")] = $"ha_area03_s03_ev001";
+ result[FnvHash.HashFnv1a_64($"ha_area04_ev001")] = $"ha_area04_ev001";
+ result[FnvHash.HashFnv1a_64($"ha_area05_s03_ev001")] = $"ha_area05_s03_ev001";
+
+ result[FnvHash.HashFnv1a_64($"area03_s04_ev001")] = $"area03_s04_ev001";
+ result[FnvHash.HashFnv1a_64($"area03_s04_ev002")] = $"area03_s04_ev002";
+ result[FnvHash.HashFnv1a_64($"area03_s04_ev003")] = $"area03_s04_ev003";
+ result[FnvHash.HashFnv1a_64($"area03_s04_ev004")] = $"area03_s04_ev004";
+ result[FnvHash.HashFnv1a_64($"area03_s04_ev005")] = $"area03_s04_ev005";
+
+ for (var wh = 1; wh < 8; wh++)
+ {
+ for (var sub = 1; sub < 4; sub++)
+ {
+ for (var n = 1; n < 7; n++)
+ {
+ result[FnvHash.HashFnv1a_64($"main_whSpawner{wh:00}{sub:00}_{n:00}")] = $"main_whSpawner{wh:00}{sub:00}_{n:00}";
+ result[FnvHash.HashFnv1a_64($"sub_whSpawner{wh:00}{sub:00}_{n:00}")] = $"sub_whSpawner{wh:00}{sub:00}_{n:00}";
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public string NameSummary
+ {
+ get
+ {
+ var map = GetSpawnerNameMap();
+ if (map.TryGetValue(SpawnerID, out var name))
+ return $"\"{name}\"";
+
+ return $"0x{SpawnerID:X16}";
+ }
+ }
+
+ // lazy init
+ private static IReadOnlyDictionary? _groupNameMap;
+ private static IReadOnlyDictionary GetGroupNameMap() => _groupNameMap ??= GenerateGroupNameMap();
+
+ private static IReadOnlyDictionary GenerateGroupNameMap()
+ {
+ var result = new Dictionary();
+ for (var i = 0; i < 100; i++)
+ {
+ var reg = $"grp{i:00}";
+ var und = $"grp_{i:00}";
+ result[FnvHash.HashFnv1a_64(und)] = und;
+ result[FnvHash.HashFnv1a_64(reg)] = reg;
+ }
+ result[0xCBF29CE484222645] = "";
+ return result;
+ }
+
+ public string GroupSummary
+ {
+ get
+ {
+ var map = GetGroupNameMap();
+ if (map.TryGetValue(GroupID, out var name))
+ return $"\"{name}\"";
+
+ return $"0x{GroupID:X16}";
+ }
+ }
+
+ public override string ToString() => $"Spawner({NameSummary}, 0x{Field_01:X16}, {Parameters}, \"{Field_03}\", {Scalar}, {Field_05}, {Field_06}, {Field_07}, {Field_08}, {Field_09}, {Field_10}, {Field_11}, {Field_12}, /* Group = */ {GroupSummary}, {Field_14}, {Field_15}, {Field_16}, {Field_17}, {Field_18}, {Field_19}, {Field_20_Value}, {Field_21_Value}, {Field_22_Value})";
+
+ public bool UsesTable(ulong table) => Field_20_Value.EncounterTableID == table;
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerData8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerData8a.cs
new file mode 100644
index 00000000..0e6f526a
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerData8a.cs
@@ -0,0 +1,20 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementSpawnerArchive8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PlacementSpawner8a[] Table { get; set; } = Array.Empty();
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerF208a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerF208a.cs
new file mode 100644
index 00000000..e7f5e18d
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerF208a.cs
@@ -0,0 +1,28 @@
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementSpawnerF208a : IHasCondition8a
+{
+ [FlatBufferItem(0)] public ulong EncounterTableID { get; set; } // TableID in EncounterTable8a
+ [FlatBufferItem(1)] public ConditionType8a ConditionTypeID { get; set; }
+ [FlatBufferItem(2)] public Condition8a ConditionID { get; set; }
+ [FlatBufferItem(3)] public string ConditionArg1 { get; set; } = string.Empty;
+ [FlatBufferItem(4)] public string ConditionArg2 { get; set; } = string.Empty;
+ [FlatBufferItem(5)] public string ConditionArg3 { get; set; } = string.Empty;
+ [FlatBufferItem(6)] public string ConditionArg4 { get; set; } = string.Empty;
+ [FlatBufferItem(7)] public string ConditionArg5 { get; set; } = string.Empty;
+ [FlatBufferItem(8)] public int BonusLevelMin { get; set; }
+ [FlatBufferItem(9)] public int BonusLevelMax { get; set; }
+
+ public override string ToString() => $"Spawn_20(/* EncounterTableId = */ {EncounterTable8a.GetTableName(EncounterTableID)}, /* ConditionTypeID = */ {this.GetConditionTypeSummary()}, /* Condition = */ {this.GetConditionSummary()}, {BonusLevelMin}, {BonusLevelMax})";
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerF218a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerF218a.cs
new file mode 100644
index 00000000..0580d132
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementSpawnerF218a.cs
@@ -0,0 +1,60 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementSpawnerF218a
+{
+ [FlatBufferItem(0)] public ulong VarHash0 { get; set; }
+ [FlatBufferItem(1)] public ulong VarHash1 { get; set; } // Sometimes contains Slot ID from specific encounter table specified by the F20 in the same Spawner?
+ [FlatBufferItem(2)] public ulong VarHash2 { get; set; } // Sometimes contains Slot ID from specific encounter table specified by the F20 in the same Spawner?
+ [FlatBufferItem(3)] public ulong VarHash3 { get; set; } // ??? Is this as 01/02?
+ [FlatBufferItem(4)] public ulong VarHash4 { get; set; } // ??? Is this as 01/02?
+ [FlatBufferItem(5)] public ulong VarHash5 { get; set; } // ??? Is this as 01/02?
+ [FlatBufferItem(6)] public PlacementV3f8a Field_06 { get; set; } = new();
+ [FlatBufferItem(7)] public string Field_07 { get; set; } = string.Empty;
+ [FlatBufferItem(8)] public float Scalar { get; set; }
+ [FlatBufferItem(9)] public PlacementV3f8a Field_09 { get; set; } = new();
+ [FlatBufferItem(10)] public PlacementV3f8a Field_10 { get; set; } = new();
+ [FlatBufferItem(11)] public int NumVarHashes { get; set; }
+
+ public string SlotSummary
+ {
+ get
+ {
+ var rawSlots = new[] { VarHash0, VarHash1, VarHash2, VarHash3, VarHash4, VarHash5 };
+ for (var i = 0; i < NumVarHashes; i++)
+ {
+ if (rawSlots[i] == 0xCBF29CE484222645)
+ throw new ArgumentException("VarHash shouldn't be empty!");
+ }
+ for (var i = NumVarHashes; i < rawSlots.Length; i++)
+ {
+ if (rawSlots[i] != 0xCBF29CE484222645)
+ throw new ArgumentException("VarHash should be empty!");
+ }
+
+ if (NumVarHashes == 0)
+ return "/* Slots = */ None()";
+
+ if (NumVarHashes == 1)
+ throw new ArgumentException("Invalid NumVarHashes!");
+
+ var slots = rawSlots.Skip(1).Take(NumVarHashes - 1).Select(EncounterSlot8a.GetSlotName);
+
+ return $"/* Slots = */ 0x{VarHash0:X16}({string.Join(", ", slots)})";
+ }
+ }
+
+ public override string ToString() => $"Spawn_21({SlotSummary}, {Field_06}, \"{Field_07}\", {Scalar}, {Field_09}, {Field_10})";
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementUnnnTable.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementUnnnTable.cs
new file mode 100644
index 00000000..4af64222
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementUnnnTable.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementUnnnTable : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PlacementUnnnEntry[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementUnnnEntry
+{
+ [FlatBufferItem(0)] public string Identifier { get; set; } = string.Empty;
+ [FlatBufferItem(1)] public ulong Hash_01 { get; set; }
+ [FlatBufferItem(2)] public PlacementParameters8a[] Field_03 { get; set; } = Array.Empty();
+ [FlatBufferItem(3)] public ulong Hash_03 { get; set; }
+ [FlatBufferItem(4)] public int Number { get; set; }
+ [FlatBufferItem(5)] public bool Flag { get; set; }
+
+ public PlacementParameters8a Parameters
+ {
+ get { if (Field_03.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_03)}"); return Field_03[0]; }
+ set { if (Field_03.Length != 1) throw new ArgumentException($"Invalid {nameof(Field_03)}"); Field_03[0] = value; }
+ }
+
+ public IEnumerable GetIntersectingLocations(IReadOnlyList locations, float bias)
+ {
+ var c = Parameters.Coordinates;
+ return GetIntersectingLocations(locations, bias, c, 0 + bias);
+ }
+
+ private static IEnumerable GetIntersectingLocations(IReadOnlyList locations, float bias, PlacementV3f8a c, float scalar)
+ {
+ var result = new List();
+ foreach (var loc in locations)
+ {
+ if (!loc.IsNamedPlace)
+ continue;
+ if (loc.IntersectsSphere(c.X, c.Y, c.Z, scalar))
+ result.Add(loc);
+ }
+
+ if (result.Count == 0)
+ result.Add(locations.First(l => l.IsNamedPlace)); // base area name
+ return result;
+ }
+
+ public IEnumerable GetContainingLocations(IReadOnlyList locations)
+ {
+ var result = new List();
+ foreach (var loc in locations)
+ {
+ if (!loc.IsNamedPlace)
+ continue;
+ if (loc.Contains(Parameters.Coordinates))
+ result.Add(loc);
+ }
+ if (result.Count == 0)
+ result.Add(locations.First(l => l.IsNamedPlace)); // base area name
+ return result;
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementV3f8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementV3f8a.cs
new file mode 100644
index 00000000..f7899bc9
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Placement/PlacementV3f8a.cs
@@ -0,0 +1,63 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlacementV3f8a : IEquatable
+{
+ [FlatBufferItem(0)] public float X { get; set; }
+ [FlatBufferItem(1)] public float Y { get; set; }
+ [FlatBufferItem(2)] public float Z { get; set; }
+ public bool IsDefault => X is 1.0f && Y is 1.0f && Z is 1.0f;
+
+ public double DistanceTo(PlacementV3f8a other) => DistanceTo(other.X, other.Y, other.Z);
+ public double DistanceTo(float x, float y, float z) => Math.Sqrt(Math.Pow(X - x, 2) + Math.Pow(Y - y, 2) + Math.Pow(Z - z, 2));
+
+ public PlacementV3f8a Clone() => new()
+ {
+ X = X,
+ Y = Y,
+ Z = Z,
+ };
+
+ public override string ToString() => $"V3f({X}, {Y}, {Z})";
+ public string ToTriple() => $"({X}, {Y}, {Z})";
+
+ public bool Equals(PlacementV3f8a? other)
+ {
+ if (other is null) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);
+ }
+
+ public override bool Equals(object? obj)
+ {
+ if (obj is null) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((PlacementV3f8a)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = X.GetHashCode();
+ hashCode = (hashCode * 397) ^ Y.GetHashCode();
+ hashCode = (hashCode * 397) ^ Z.GetHashCode();
+ return hashCode;
+ }
+ }
+
+ public static bool operator ==(PlacementV3f8a? left, PlacementV3f8a? right) => Equals(left, right);
+ public static bool operator !=(PlacementV3f8a? left, PlacementV3f8a? right) => !Equals(left, right);
+}
\ No newline at end of file
diff --git a/pkNX.Structures.FlatBuffers/Arceus/PlayReportTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/PlayReportTable8a.cs
new file mode 100644
index 00000000..3a3e7bb5
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/PlayReportTable8a.cs
@@ -0,0 +1,47 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlayReportTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PlayReportItem8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PlayReportItem8a
+{
+ [FlatBufferItem(00)] public string Field_00 { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public ulong Field_01 { get; set; }
+ [FlatBufferItem(02)] public ulong Field_02 { get; set; }
+ [FlatBufferItem(03)] public ulong Field_03 { get; set; }
+ [FlatBufferItem(04)] public ulong Field_04 { get; set; }
+ [FlatBufferItem(05)] public ulong Field_05 { get; set; }
+ [FlatBufferItem(06)] public ulong Field_06 { get; set; }
+ [FlatBufferItem(07)] public ulong Field_07 { get; set; }
+ [FlatBufferItem(08)] public ulong Field_08 { get; set; }
+ [FlatBufferItem(09)] public ulong Field_09 { get; set; }
+ [FlatBufferItem(10)] public ulong Field_10 { get; set; }
+ [FlatBufferItem(11)] public ulong Field_11 { get; set; }
+ [FlatBufferItem(12)] public ulong Field_12 { get; set; }
+ [FlatBufferItem(13)] public ulong Field_13 { get; set; }
+ [FlatBufferItem(14)] public ulong Field_14 { get; set; }
+ [FlatBufferItem(15)] public ulong Field_15 { get; set; }
+ [FlatBufferItem(16)] public ulong Field_16 { get; set; }
+ [FlatBufferItem(17)] public ulong Field_17 { get; set; }
+ [FlatBufferItem(18)] public ulong Field_18 { get; set; }
+ [FlatBufferItem(19)] public ulong Field_19 { get; set; }
+ [FlatBufferItem(20)] public ulong Field_20 { get; set; }
+ [FlatBufferItem(21)] public ulong Field_21 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeAIArchive8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeAIArchive8a.cs
new file mode 100644
index 00000000..28f7ed2c
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeAIArchive8a.cs
@@ -0,0 +1,95 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeAIArchive8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokeAI8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeAI8a
+{
+ [FlatBufferItem(00)] public int Species { get; set; } // int
+ [FlatBufferItem(01)] public int Form { get; set; } // int
+ [FlatBufferItem(02)] public bool IsAlpha { get; set; } // bool
+ [FlatBufferItem(03)] public string Behavior1 { get; set; } = string.Empty;
+ [FlatBufferItem(04)] public string Behavior2 { get; set; } = string.Empty;
+ [FlatBufferItem(05)] public string Behavior3 { get; set; } = string.Empty;
+ [FlatBufferItem(06)] public bool Field_06 { get; set; } // bool
+ [FlatBufferItem(07)] public ulong Field_07 { get; set; } // ulong
+ [FlatBufferItem(08)] public bool Field_08 { get; set; } // bool, always true
+ [FlatBufferItem(09)] public PokeAI8a_F09 Field_09 { get; set; } = new();
+ [FlatBufferItem(10)] public bool Field_10 { get; set; } // bool, always true
+ [FlatBufferItem(11)] public PokeAI8a_F09 Field_11 { get; set; } = new();
+ [FlatBufferItem(12)] public bool Field_12 { get; set; } // bool, always true except for Darkrai
+ [FlatBufferItem(13)] public PokeAI8a_F09 Field_13 { get; set; } = new();
+ [FlatBufferItem(14)] public bool Field_14 { get; set; } // bool, always true
+ [FlatBufferItem(15)] public PokeAI8a_F09 Field_15 { get; set; } = new();
+ [FlatBufferItem(16)] public bool Field_16 { get; set; } // bool, always true
+ [FlatBufferItem(17)] public PokeAI8a_F09 Field_17 { get; set; } = new();
+ [FlatBufferItem(18)] public PokeAI8a_F18 Field_18 { get; set; } = new(); // only used by Kleavor-1
+ [FlatBufferItem(19)] public PokeAI8a_F18 Field_19 { get; set; } = new(); // assumed same as above, none use
+ [FlatBufferItem(20)] public PokeAI8a_F18 Field_20 { get; set; } = new(); // assumed same as above, none use
+ [FlatBufferItem(21)] public PokeAI8a_F18 Field_21 { get; set; } = new(); // assumed same as above, only used by Kleavor-1 with fields 0,1,2
+ [FlatBufferItem(22)] public string MoveEffect1 { get; set; } = string.Empty;
+ [FlatBufferItem(23)] public string MoveEffect2 { get; set; } = string.Empty;
+ [FlatBufferItem(24)] public PokeAI8a_F24 Field_24 { get; set; } = new();
+ [FlatBufferItem(25)] public float Field_25 { get; set; } // float
+ [FlatBufferItem(26)] public float Field_26 { get; set; } // float
+ [FlatBufferItem(27)] public PlacementV3f8a Field_27 { get; set; } = new();
+ [FlatBufferItem(28)] public PlacementV3f8a Field_28 { get; set; } = new();
+ [FlatBufferItem(29)] public PlacementV3f8a Field_29 { get; set; } = new();
+ [FlatBufferItem(30)] public PlacementV3f8a Field_30 { get; set; } = new();
+ [FlatBufferItem(31)] public int Field_31 { get; set; } // int
+ [FlatBufferItem(32)] public int Field_32 { get; set; } // int
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeAI8a_F24
+{
+ [FlatBufferItem(00)] public float Field_00 { get; set; }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeAI8a_F18
+{
+ [FlatBufferItem(00)] public bool Field_00 { get; set; }
+ [FlatBufferItem(01)] public float Field_01 { get; set; }
+ [FlatBufferItem(02)] public float Field_02 { get; set; }
+ [FlatBufferItem(03)] public float Field_03 { get; set; }
+ [FlatBufferItem(04)] public float Field_04 { get; set; }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeAI8a_F09
+{
+ [FlatBufferItem(00)] public PokeAI8_F08 Field_00 { get; set; } = new();
+ [FlatBufferItem(01)] public PokeAI8_F08 Field_01 { get; set; } = new();
+ [FlatBufferItem(02)] public PokeAI8_F08 Field_02 { get; set; } = new();
+ [FlatBufferItem(03)] public PokeAI8_F08 Field_03 { get; set; } = new();
+ [FlatBufferItem(04)] public PokeAI8_F08 Field_04 { get; set; } = new();
+ [FlatBufferItem(05)] public PokeAI8_F08 Field_05 { get; set; } = new();
+ [FlatBufferItem(06)] public PokeAI8_F08 Field_06 { get; set; } = new();
+ [FlatBufferItem(07)] public PokeAI8_F08 Field_07 { get; set; } = new();
+ [FlatBufferItem(08)] public PokeAI8_F08 Field_08 { get; set; } = new();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeAI8_F08
+{
+ [FlatBufferItem(00)] public ulong Hash { get; set; }
+ [FlatBufferItem(01)] public string[] Field_01 { get; set; } = Array.Empty();
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeAdd8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeAdd8a.cs
new file mode 100644
index 00000000..a9faba1d
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeAdd8a.cs
@@ -0,0 +1,82 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeAdd8aArchive : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokeAdd8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeAdd8a
+{
+ [FlatBufferItem(00)] public string Field_00 { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public int Species { get; set; }
+ [FlatBufferItem(02)] public int Form { get; set; }
+ [FlatBufferItem(03)] public int Gender { get; set; }
+ [FlatBufferItem(04)] public int ShinyLock { get; set; }
+ [FlatBufferItem(05)] public int Level { get; set; }
+ [FlatBufferItem(06)] public int AbilityRandType { get; set; }
+ [FlatBufferItem(07)] public int Nature { get; set; }
+ [FlatBufferItem(08)] public int Height { get; set; }
+ [FlatBufferItem(09)] public int Weight { get; set; }
+ [FlatBufferItem(10)] public bool IsOybn { get; set; }
+ [FlatBufferItem(11)] public int Field_11 { get; set; } // All Entries have empty
+ [FlatBufferItem(12)] public int Field_12 { get; set; } // All Entries have empty
+ [FlatBufferItem(13)] public int Field_13 { get; set; } // All Entries have empty
+ [FlatBufferItem(14)] public int Field_14 { get; set; } // All Entries have empty
+ [FlatBufferItem(15)] public int Field_15 { get; set; } // All Entries have empty
+ [FlatBufferItem(16)] public int Field_16 { get; set; } // All Entries have empty
+ [FlatBufferItem(17)] public int Field_17 { get; set; } // All Entries have empty
+ [FlatBufferItem(18)] public int Field_18 { get; set; } // All Entries have empty
+ [FlatBufferItem(19)] public int IV_HP { get; set; }
+ [FlatBufferItem(20)] public int IV_ATK { get; set; }
+ [FlatBufferItem(21)] public int IV_DEF { get; set; }
+ [FlatBufferItem(22)] public int IV_SPA { get; set; }
+ [FlatBufferItem(23)] public int IV_SPD { get; set; }
+ [FlatBufferItem(24)] public int IV_SPE { get; set; }
+ [FlatBufferItem(25)] public int NumPerfectIvs { get; set; }
+ [FlatBufferItem(26)] public int GV_HP { get; set; }
+ [FlatBufferItem(27)] public int GV_ATK { get; set; }
+ [FlatBufferItem(28)] public int GV_DEF { get; set; }
+ [FlatBufferItem(29)] public int GV_SPA { get; set; }
+ [FlatBufferItem(30)] public int GV_SPD { get; set; }
+ [FlatBufferItem(31)] public int GV_SPE { get; set; }
+
+ public string Dump(string[] speciesNames)
+ {
+ var natureStr = Nature == -1 ? "" : $", Nature = {Nature}";
+ var shinyStr = $", Shiny = {(ShinyLock == 2 ? "Never" : ShinyLock.ToString())}";
+ var gvStr = "";
+ if (GV_HP != 0)
+ gvStr += $", GV_HP = {GV_HP}";
+ if (GV_ATK != 0)
+ gvStr += $", GV_ATK = {GV_ATK}";
+ if (GV_DEF != 0)
+ gvStr += $", GV_DEF = {GV_DEF}";
+ if (GV_SPA != 0)
+ gvStr += $", GV_SPA = {GV_SPA}";
+ if (GV_SPD != 0)
+ gvStr += $", GV_SPD = {GV_SPD}";
+ if (GV_SPE != 0)
+ gvStr += $", GV_SPE = {GV_SPE}";
+
+ var hw = $"HeightScalar = {Height:000}, WeightScalar = {Weight:000}";
+ var genderStr = Gender == -1 ? "" : $", Gender = {Gender}";
+ var iv = NumPerfectIvs == 0 ? "" : $", FlawlessIVCount = {NumPerfectIvs}";
+ string comment = $"// {speciesNames[Species]}{(Form == 0 ? "" : $"-{Form}")}";
+ return $"new({Species:000},{Form:000},{Level:00}) {{ Gift = true, {hw}{shinyStr}{genderStr}{natureStr}{iv}{gvStr} }}, {comment}";
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeDropItemArchive8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeDropItemArchive8a.cs
new file mode 100644
index 00000000..60bae10b
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeDropItemArchive8a.cs
@@ -0,0 +1,32 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeDropItemArchive8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokeDropItem8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeDropItem8a
+{
+ [FlatBufferItem(00)] public ulong Hash { get; set; }
+ [FlatBufferItem(01)] public int Field_01 { get; set; }
+ [FlatBufferItem(02)] public int Field_02 { get; set; }
+ [FlatBufferItem(03)] public int Field_03 { get; set; }
+ [FlatBufferItem(04)] public int Field_04 { get; set; }
+
+ public string Dump(string[] itemNames) => $"{Hash:X16}\t{itemNames[Field_01]}\t{Field_02}\t{itemNames[Field_03]}\t{Field_04}";
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeDropItemBattleArchive8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeDropItemBattleArchive8a.cs
new file mode 100644
index 00000000..46afb1b0
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeDropItemBattleArchive8a.cs
@@ -0,0 +1,37 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeDropItemBattleArchive8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokeDropItemBattle8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeDropItemBattle8a
+{
+ [FlatBufferItem(00)] public int RateItem1 { get; set; }
+ [FlatBufferItem(01)] public int IndexItem1 { get; set; }
+ [FlatBufferItem(02)] public int RateItem2 { get; set; }
+ [FlatBufferItem(03)] public int IndexItem2 { get; set; }
+ [FlatBufferItem(04)] public int RateItem3 { get; set; }
+ [FlatBufferItem(05)] public int IndexItem3 { get; set; }
+ [FlatBufferItem(06)] public int RateItem4 { get; set; }
+ [FlatBufferItem(07)] public int IndexItem4 { get; set; }
+ [FlatBufferItem(08)] public int RateItem5 { get; set; }
+ [FlatBufferItem(09)] public int IndexItem5 { get; set; }
+
+ public string Dump(string[] n) => $"{RateItem1}\t{n[IndexItem1]}\t{RateItem2}\t{n[IndexItem2]}\t{RateItem3}\t{n[IndexItem3]}\t{RateItem4}\t{n[IndexItem4]}\t{RateItem5}\t{n[IndexItem5]}";
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeMiscTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeMiscTable8a.cs
new file mode 100644
index 00000000..f8cea0c4
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Poke/PokeMiscTable8a.cs
@@ -0,0 +1,50 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeMiscTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokeMisc8a[] Table { get; set; } = Array.Empty();
+
+ public PokeMisc8a GetEntry(int species, int form) =>
+ Array.Find(Table, z => z.Species == species && z.Form == z.Form) ??
+ throw new IndexOutOfRangeException($"{species}-{form} is not in {nameof(PokeMiscTable8a)}.");
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeMisc8a
+{
+ [FlatBufferItem(00)] public int Species { get; set; }
+ [FlatBufferItem(01)] public int Form { get; set; }
+ [FlatBufferItem(02)] public int Field_02 { get; set; }
+ [FlatBufferItem(03)] public float Field_03 { get; set; }
+ [FlatBufferItem(04)] public float Field_04 { get; set; }
+ [FlatBufferItem(05)] public int Field_05 { get; set; }
+ [FlatBufferItem(06)] public int OybnLevelIndex { get; set; }
+ [FlatBufferItem(07)] public ulong Hash_07 { get; set; }
+ [FlatBufferItem(08)] public ulong Hash_08 { get; set; }
+ [FlatBufferItem(09)] public string Value { get; set; } = string.Empty;
+ [FlatBufferItem(10)] public int[] Field_10 { get; set; } = Array.Empty();
+ [FlatBufferItem(11)] public int Field_11 { get; set; }
+ [FlatBufferItem(12)] public int Field_12 { get; set; }
+ [FlatBufferItem(13)] public int Field_13 { get; set; }
+ [FlatBufferItem(14)] public bool Field_14 { get; set; }
+ [FlatBufferItem(15)] public int Field_15 { get; set; }
+ [FlatBufferItem(16)] public float Field_16 { get; set; }
+ [FlatBufferItem(17)] public float Field_17 { get; set; }
+ [FlatBufferItem(18)] public bool Field_18 { get; set; }
+ [FlatBufferItem(19)] public float Field_19 { get; set; }
+ [FlatBufferItem(20)] public float Field_20 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/PokeResource/PokeInfoList.cs b/pkNX.Structures.FlatBuffers/Arceus/PokeResource/PokeInfoList.cs
new file mode 100644
index 00000000..df3dae7c
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/PokeResource/PokeInfoList.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeInfoList8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public int TableDataLength { get; set; }
+ [FlatBufferItem(1)] public PokeInfo8a[] Table { get; set; } = Array.Empty();
+
+ public (ushort[] SF, byte[] Gender) Parse()
+ {
+ var entries = GetDexFormEntries().GroupBy(z => (int)(ushort)z)
+ .Select(Merge).Distinct().OrderBy(z => (ushort)z).ToList();
+ var SF = new ushort[entries.Count];
+ var Gender = new byte[entries.Count];
+ for (int i = 0; i < SF.Length; i++)
+ {
+ SF[i] = (ushort)entries[i];
+ Gender[i] = (byte)(entries[i] >> 16);
+ }
+ return (SF, Gender);
+ }
+
+ private static int Merge(IGrouping arg)
+ {
+ var species = arg.Key;
+ foreach (var value in arg)
+ species |= value;
+ return species;
+ }
+
+ public IEnumerable GetDexFormEntries()
+ {
+ foreach (var x in Table)
+ {
+ var s = x.Species;
+ foreach (var fe in x.Children)
+ {
+ var f = fe.Form;
+ foreach (var w in fe.Detail)
+ {
+ bool rare = w.IsRare;
+ foreach (var z in w.Detail)
+ {
+ var unk = z.Unknown;
+ foreach (var r in z.Detail)
+ {
+ var gender = r.Gender.GenderValue;
+ yield return (s | (f << 11)) | ((1 << (int)gender) << 16);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeInfo8a
+{
+ [FlatBufferItem(00)] public int Species { get; set; }
+ [FlatBufferItem(01)] public PokeInfoDetail8a[] Children { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeInfoDetail8a
+{
+ [FlatBufferItem(00)] public int Form { get; set; }
+ [FlatBufferItem(01)] public PokeInfoDetail8a_2[] Detail { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeInfoDetail8a_2
+{
+ [FlatBufferItem(00)] public bool IsRare { get; set; }
+ [FlatBufferItem(01)] public PokeInfoDetail8a_3[] Detail { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeInfoDetail8a_3
+{
+ [FlatBufferItem(00)] public bool Unknown { get; set; }
+ [FlatBufferItem(01)] public PokeInfoDetail8a_5[] Detail { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeInfoDetail8a_5
+{
+ [FlatBufferItem(00)] public PokeInfoGender8a Gender { get; set; } = new();
+ [FlatBufferItem(01)] public string AssetName { get; set; } = string.Empty;
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeInfoGender8a
+{
+ [FlatBufferItem(00)] public PokeInfoGender GenderValue { get; set; }
+}
+
+[FlatBufferEnum(typeof(byte))]
+public enum PokeInfoGender : byte
+{
+ GenderDiffMale,
+ GenderDiffFemale,
+ Genderless,
+ DualGenderNoDifference,
+ MaleOnly,
+ FemaleOnly,
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/PokeResource/PokeResourceTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/PokeResource/PokeResourceTable8a.cs
new file mode 100644
index 00000000..5c7c6875
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/PokeResource/PokeResourceTable8a.cs
@@ -0,0 +1,59 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+// poke_resource_table.trpmcatalog
+/// for Legends: Arceus, adding
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeResourceTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(00)] public PokeResourceMeta8a Meta { get; set; } = new();
+ [FlatBufferItem(01)] public PokeModelConfig8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeResourceMeta8a
+{
+ [FlatBufferItem(00)] public int Field0 { get; set; } = 5; // 4 in prior game format
+ [FlatBufferItem(01)] public int Field1 { get; set; } = 4; // 2 in prior game format
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeModelConfig8a
+{
+ [FlatBufferItem(00)] public PokeModelMeta8a Meta { get; set; } = new();
+ [FlatBufferItem(01)] public string PathModel { get; set; } = string.Empty; // string
+ [FlatBufferItem(02)] public string PathConfig { get; set; } = string.Empty; // string
+ [FlatBufferItem(03)] public string PathArchive { get; set; } = string.Empty; // string
+ [FlatBufferItem(04)] public byte Unused { get; set; } // unused!
+ [FlatBufferItem(05)] public AnimationConfigStringTuple8a[] Field_05 { get; set; } = Array.Empty();
+ [FlatBufferItem(06)] public AnimationConfigStringTuple8a[] Field_06 { get; set; } = Array.Empty();
+ [FlatBufferItem(07)] public int? ArceusType { get; set; } // Specified by Arceus' forms -- NEW!
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokeModelMeta8a
+{
+ [FlatBufferItem(00)] public ushort Species { get; set; }
+ [FlatBufferItem(01)] public ushort Form { get; set; }
+ [FlatBufferItem(02)] public byte Gender { get; set; }
+ [FlatBufferItem(03)] public byte Shiny { get; set; }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class AnimationConfigStringTuple8a
+{
+ [FlatBufferItem(00)] public string Name { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public string Path { get; set; } = string.Empty;
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/PokedexDistributionTable.cs b/pkNX.Structures.FlatBuffers/Arceus/PokedexDistributionTable.cs
new file mode 100644
index 00000000..9e6b51a5
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/PokedexDistributionTable.cs
@@ -0,0 +1,59 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokedexDistributionTable : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokedexDistributionEntry[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokedexDistributionEntry
+{
+ [FlatBufferItem(00)] public int Species { get; set; }
+ [FlatBufferItem(01)] public int Field_01 { get; set; }
+ [FlatBufferItem(02)] public int Field_02 { get; set; }
+ [FlatBufferItem(03)] public int Field_03 { get; set; }
+ [FlatBufferItem(04)] public int Field_04 { get; set; }
+ [FlatBufferItem(05)] public int Field_05 { get; set; }
+ [FlatBufferItem(06)] public int Field_06 { get; set; }
+ [FlatBufferItem(07)] public int Field_07 { get; set; }
+ [FlatBufferItem(08)] public int Field_08 { get; set; }
+ [FlatBufferItem(09)] public int Field_09 { get; set; }
+ [FlatBufferItem(10)] public int Field_10 { get; set; }
+ [FlatBufferItem(11)] public int Field_11 { get; set; }
+ [FlatBufferItem(12)] public int Field_12 { get; set; }
+ [FlatBufferItem(13)] public ulong Field_13 { get; set; }
+ [FlatBufferItem(14)] public ulong Field_14 { get; set; }
+ [FlatBufferItem(15)] public ulong Field_15 { get; set; }
+ [FlatBufferItem(16)] public ulong Field_16 { get; set; }
+ [FlatBufferItem(17)] public ulong Field_17 { get; set; }
+ [FlatBufferItem(18)] public ulong Field_18 { get; set; }
+ [FlatBufferItem(19)] public ulong Field_19 { get; set; }
+ [FlatBufferItem(20)] public ulong Field_20 { get; set; }
+ [FlatBufferItem(21)] public ulong Field_21 { get; set; }
+ [FlatBufferItem(22)] public ulong Field_22 { get; set; }
+ [FlatBufferItem(23)] public ulong Field_23 { get; set; }
+ [FlatBufferItem(24)] public ulong Field_24 { get; set; }
+ [FlatBufferItem(25)] public ulong Field_25 { get; set; }
+ [FlatBufferItem(26)] public ulong Field_26 { get; set; }
+ [FlatBufferItem(27)] public ulong Field_27 { get; set; }
+ [FlatBufferItem(28)] public ulong Field_28 { get; set; }
+ [FlatBufferItem(29)] public ulong Field_29 { get; set; }
+ [FlatBufferItem(30)] public ulong Field_30 { get; set; }
+ [FlatBufferItem(31)] public ulong Field_31 { get; set; }
+ [FlatBufferItem(32)] public ulong Field_32 { get; set; }
+ [FlatBufferItem(33)] public ulong Field_33 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/PokedexRankTable.cs b/pkNX.Structures.FlatBuffers/Arceus/PokedexRankTable.cs
new file mode 100644
index 00000000..a724f465
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/PokedexRankTable.cs
@@ -0,0 +1,27 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokedexRankTable : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokedexRankLevel[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokedexRankLevel
+{
+ [FlatBufferItem(0)] public int Rank { get; set; }
+ [FlatBufferItem(1)] public int Required { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/PokedexResearchTable.cs b/pkNX.Structures.FlatBuffers/Arceus/PokedexResearchTable.cs
new file mode 100644
index 00000000..529abe6e
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/PokedexResearchTable.cs
@@ -0,0 +1,42 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokedexResearchTable : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokedexResearchTask[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokedexResearchTask
+{
+ [FlatBufferItem(00)] public int Species { get; set; }
+ [FlatBufferItem(01)] public int Task { get; set; }
+ [FlatBufferItem(02)] public int Threshold { get; set; }
+ [FlatBufferItem(03)] public int Move { get; set; }
+ [FlatBufferItem(04)] public int Type { get; set; }
+ [FlatBufferItem(05)] public int TimeOfDay { get; set; }
+ [FlatBufferItem(06)] public ulong Hash_06 { get; set; }
+ [FlatBufferItem(07)] public ulong Hash_07 { get; set; }
+ [FlatBufferItem(08)] public ulong Hash_08 { get; set; }
+ [FlatBufferItem(09)] public int Threshold1 { get; set; }
+ [FlatBufferItem(10)] public int Threshold2 { get; set; }
+ [FlatBufferItem(11)] public int Threshold3 { get; set; }
+ [FlatBufferItem(12)] public int Threshold4 { get; set; }
+ [FlatBufferItem(13)] public int Threshold5 { get; set; }
+ [FlatBufferItem(14)] public int PointsSingle { get; set; }
+ [FlatBufferItem(15)] public int PointsBonus { get; set; }
+ [FlatBufferItem(16)] public bool RequiredForCompletion { get; set; } // Unused but referenced by code (bool is set to != 0)
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/PokemonRare8aTable.cs b/pkNX.Structures.FlatBuffers/Arceus/PokemonRare8aTable.cs
new file mode 100644
index 00000000..b63f8d41
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/PokemonRare8aTable.cs
@@ -0,0 +1,32 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokemonRare8aTable : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public PokemonRare8aEntry[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class PokemonRare8aEntry
+{
+ [FlatBufferItem(00)] public string Name { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public ulong Hash { get; set; }
+ [FlatBufferItem(02)] public byte UnusedValue { get; set; } // none have this
+ [FlatBufferItem(03)] public string Option { get; set; } = string.Empty;
+ [FlatBufferItem(04)] public string Value { get; set; } = string.Empty;
+ [FlatBufferItem(05)] public string[] Field_05 { get; set; } = Array.Empty();
+ [FlatBufferItem(06)] public FlatDummyEntry[] UnusedArray { get; set; } = Array.Empty(); // none have this
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Resident/AreaSettingsTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Resident/AreaSettingsTable8a.cs
new file mode 100644
index 00000000..2f6ee845
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Resident/AreaSettingsTable8a.cs
@@ -0,0 +1,109 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class AreaSettingsTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public AreaSettings8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class AreaSettings8a
+{
+ [FlatBufferItem(00)] public string Name { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public string NameParent { get; set; } = string.Empty;
+ [FlatBufferItem(02)] public PlacementV3f8a Position { get; set; } = new();
+ [FlatBufferItem(03)] public bool Flag_03 { get; set; }
+ [FlatBufferItem(04)] public bool Flag_04 { get; set; }
+ [FlatBufferItem(05)] public bool Flag_05 { get; set; }
+ [FlatBufferItem(06)] public bool Flag_06 { get; set; }
+ [FlatBufferItem(07)] public bool Flag_07 { get; set; }
+ [FlatBufferItem(08)] public bool Flag_08 { get; set; }
+ [FlatBufferItem(09)] public string NPC { get; set; } = string.Empty;
+ [FlatBufferItem(10)] public string NPCPokemon { get; set; } = string.Empty;
+ [FlatBufferItem(11)] public string BgParts { get; set; } = string.Empty;
+ [FlatBufferItem(12)] public string Emitter { get; set; } = string.Empty;
+ [FlatBufferItem(13)] public string Item { get; set; } = string.Empty;
+ [FlatBufferItem(14)] public string SearchItem { get; set; } = string.Empty;
+ [FlatBufferItem(15)] public string Spawners { get; set; } = string.Empty;
+ [FlatBufferItem(16)] public string Pos { get; set; } = string.Empty;
+ [FlatBufferItem(17)] public string BgEvent { get; set; } = string.Empty;
+ [FlatBufferItem(18)] public string Encounters { get; set; } = string.Empty;
+ [FlatBufferItem(19)] public string NavMesh { get; set; } = string.Empty;
+ [FlatBufferItem(20)] public string TerrainTable { get; set; } = string.Empty;
+ [FlatBufferItem(21)] public string NameOther { get; set; } = string.Empty;
+ [FlatBufferItem(22)] public bool Flag_22 { get; set; }
+ [FlatBufferItem(23)] public bool Flag_23 { get; set; }
+ [FlatBufferItem(24)] public string LandmarkItems { get; set; } = string.Empty;
+ [FlatBufferItem(25)] public string LandmarkItemSpawns { get; set; } = string.Empty;
+ [FlatBufferItem(26)] public string AttributeInfo { get; set; } = string.Empty;
+ [FlatBufferItem(27)] public string Locations { get; set; } = string.Empty;
+ [FlatBufferItem(28)] public string BattleStartPoint { get; set; } = string.Empty;
+ [FlatBufferItem(29)] public string SoundEvent { get; set; } = string.Empty;
+ [FlatBufferItem(30)] public string AreaCamera { get; set; } = string.Empty;
+ [FlatBufferItem(31)] public string TargetAI { get; set; } = string.Empty;
+ [FlatBufferItem(32)] public string Slot0 { get; set; } = string.Empty;
+ [FlatBufferItem(33)] public AreaSettings8a_F50 Field_33 { get; set; } = new(); // not right?
+ [FlatBufferItem(34)] public string Wormholes { get; set; } = string.Empty;
+ [FlatBufferItem(35)] public string WormholeSpawners { get; set; } = string.Empty;
+ [FlatBufferItem(36)] public string WormholeItems { get; set; } = string.Empty;
+ [FlatBufferItem(37)] public string OverViewDepth { get; set; } = string.Empty;
+ [FlatBufferItem(38)] public string RealTimeEventData { get; set; } = string.Empty;
+ [FlatBufferItem(39)] public string Mkrg { get; set; } = string.Empty;
+ [FlatBufferItem(40)] public string AreaWall { get; set; } = string.Empty;
+ [FlatBufferItem(41)] public string Balloon { get; set; } = string.Empty;
+ [FlatBufferItem(42)] public string UnownSpawners { get; set; } = string.Empty;
+ [FlatBufferItem(43)] public string MultiShapeSoundEvent { get; set; } = string.Empty;
+ [FlatBufferItem(44)] public ulong Field_44 { get; set; }
+ [FlatBufferItem(45)] public string Path { get; set; } = string.Empty;
+ [FlatBufferItem(46)] public string PopupEvent { get; set; } = string.Empty;
+ [FlatBufferItem(47)] public string Invisible { get; set; } = string.Empty;
+ [FlatBufferItem(48)] public string LocalWeather { get; set; } = string.Empty;
+ [FlatBufferItem(49)] public string SoundBank { get; set; } = string.Empty;
+ [FlatBufferItem(50)] public AreaSettings8a_F50 Field_50 { get; set; } = new();
+ [FlatBufferItem(51)] public string Archive { get; set; } = string.Empty;
+ [FlatBufferItem(52)] public AreaSettings8a_F52 Field_52 { get; set; } = new();
+ [FlatBufferItem(53)] public PlacementV3f8a Field_53 { get; set; } = new();
+ [FlatBufferItem(54)] public ulong Hash { get; set; }
+ [FlatBufferItem(55)] public bool Field_55 { get; set; }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class AreaSettings8a_F52
+{
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class AreaSettings8a_F50
+{
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class AreaSettings8a_F33
+{
+ [FlatBufferItem(00)] public ulong Field_00 { get; set; }
+ [FlatBufferItem(01)] public int[] Field_01 { get; set; } = Array.Empty(); // unknown
+ [FlatBufferItem(02)] public AreaSettings8a_F33a Field_02 { get; set; } = new();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class AreaSettings8a_F33a
+{
+ [FlatBufferItem(00)] public byte Field_00 { get; set; } // unknown
+ [FlatBufferItem(01)] public byte Field_01 { get; set; } // unknown
+ [FlatBufferItem(02)] public int[] Field_02 { get; set; } = Array.Empty(); // unknown
+ [FlatBufferItem(03)] public int[] Field_03 { get; set; } = Array.Empty(); // unknown
+ [FlatBufferItem(04)] public ulong Field_04 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/ScriptIDRecordRelease.cs b/pkNX.Structures.FlatBuffers/Arceus/ScriptIDRecordRelease.cs
new file mode 100644
index 00000000..012e894d
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/ScriptIDRecordRelease.cs
@@ -0,0 +1,29 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class ScriptIDRecordRelease : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public ScriptIDRecord[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class ScriptIDRecord
+{
+ [FlatBufferItem(00)] public string Name { get; set; } = string.Empty;
+ [FlatBufferItem(01)] public string Type { get; set; } = string.Empty;
+ [FlatBufferItem(02)] public string Lua { get; set; } = string.Empty;
+ [FlatBufferItem(03)] public string Dat { get; set; } = string.Empty;
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterData8Archive.cs b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterData8Archive.cs
new file mode 100644
index 00000000..9b96e9d5
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterData8Archive.cs
@@ -0,0 +1,20 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EncounterDataArchive8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public EncounterTable8a[] Table { get; set; } = Array.Empty();
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterEligiblityTraits8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterEligiblityTraits8a.cs
new file mode 100644
index 00000000..89f36c6d
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterEligiblityTraits8a.cs
@@ -0,0 +1,62 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EncounterEligiblityTraits8a : IHasCondition8a
+{
+ [FlatBufferItem(0)] public ConditionType8a ConditionTypeID { get; set; }
+ [FlatBufferItem(1)] public Condition8a ConditionID { get; set; }
+ [FlatBufferItem(2)] public string ConditionArg1 { get; set; } = string.Empty;
+ [FlatBufferItem(3)] public string ConditionArg2 { get; set; } = string.Empty;
+ [FlatBufferItem(4)] public string ConditionArg3 { get; set; } = string.Empty;
+ [FlatBufferItem(5)] public string ConditionArg4 { get; set; } = string.Empty;
+ [FlatBufferItem(6)] public string ConditionArg5 { get; set; } = string.Empty;
+ [FlatBufferItem(07)] public float TimeOfDayMultiplier_0 { get; set; }
+ [FlatBufferItem(08)] public float TimeOfDayMultiplier_1 { get; set; }
+ [FlatBufferItem(09)] public float TimeOfDayMultiplier_2 { get; set; }
+ [FlatBufferItem(10)] public float TimeOfDayMultiplier_3 { get; set; }
+ [FlatBufferItem(11)] public float WeatherMultiplier_1 { get; set; }
+ [FlatBufferItem(12)] public float WeatherMultiplier_2 { get; set; }
+ [FlatBufferItem(13)] public float WeatherMultiplier_3 { get; set; }
+ [FlatBufferItem(14)] public float WeatherMultiplier_4 { get; set; }
+ [FlatBufferItem(15)] public float WeatherMultiplier_5 { get; set; }
+ [FlatBufferItem(16)] public float WeatherMultiplier_6 { get; set; }
+ [FlatBufferItem(17)] public float WeatherMultiplier_7 { get; set; }
+ [FlatBufferItem(18)] public float WeatherMultiplier_8 { get; set; }
+
+ public float GetTimeMultiplier(int index) => index switch
+ {
+ 0 => TimeOfDayMultiplier_0,
+ 1 => TimeOfDayMultiplier_1,
+ 2 => TimeOfDayMultiplier_2,
+ 3 => TimeOfDayMultiplier_3,
+ _ => throw new ArgumentOutOfRangeException(nameof(index)),
+ };
+
+ public float GetWeatherMultiplier(int index) => index switch
+ {
+ 0 => 1.0f, // "No Weather" results in no modification of rate for all species/forms
+ 1 => WeatherMultiplier_1,
+ 2 => WeatherMultiplier_2,
+ 3 => WeatherMultiplier_3,
+ 4 => WeatherMultiplier_4,
+ 5 => WeatherMultiplier_5,
+ 6 => WeatherMultiplier_6,
+ 7 => WeatherMultiplier_7,
+ 8 => WeatherMultiplier_8,
+ _ => throw new ArgumentOutOfRangeException(nameof(index)),
+ };
+
+ public bool HasTimeModifier(int index) => GetTimeMultiplier(index) != -1.0f;
+ public bool HasWeatherModifier(int index) => index != 0 && GetWeatherMultiplier(index) != -1.0f;
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterMultiplerArchive8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterMultiplerArchive8a.cs
new file mode 100644
index 00000000..055acc7e
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterMultiplerArchive8a.cs
@@ -0,0 +1,28 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EncounterMultiplerArchive8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public EncounterMultiplier8a[] Table { get; set; } = Array.Empty();
+
+ public EncounterMultiplier8a GetEncounterMultiplier(EncounterSlot8a slot)
+ {
+ var result = Array.Find(Table, z => z.Species == slot.Species && z.Form == slot.Form);
+ if (result == null)
+ throw new ArgumentException($"Invalid Encounter Slot {slot.Species} - {slot.Form}");
+ return result;
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterMultiplier8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterMultiplier8a.cs
new file mode 100644
index 00000000..501262e7
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterMultiplier8a.cs
@@ -0,0 +1,57 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EncounterMultiplier8a
+{
+ [FlatBufferItem(00)] public int Species { get; set; }
+ [FlatBufferItem(01)] public int Form { get; set; }
+ [FlatBufferItem(02)] public float TimeOfDayMultiplier_0 { get; set; }
+ [FlatBufferItem(03)] public float TimeOfDayMultiplier_1 { get; set; }
+ [FlatBufferItem(04)] public float TimeOfDayMultiplier_2 { get; set; }
+ [FlatBufferItem(05)] public float TimeOfDayMultiplier_3 { get; set; }
+ [FlatBufferItem(06)] public float WeatherMultiplier_1 { get; set; }
+ [FlatBufferItem(07)] public float WeatherMultiplier_2 { get; set; }
+ [FlatBufferItem(08)] public float WeatherMultiplier_3 { get; set; }
+ [FlatBufferItem(09)] public float WeatherMultiplier_4 { get; set; }
+ [FlatBufferItem(10)] public float WeatherMultiplier_5 { get; set; }
+ [FlatBufferItem(11)] public float WeatherMultiplier_6 { get; set; }
+ [FlatBufferItem(12)] public float WeatherMultiplier_7 { get; set; }
+ [FlatBufferItem(13)] public float WeatherMultiplier_8 { get; set; }
+
+ public float GetTimeMultiplier(int index) => index switch
+ {
+ 0 => TimeOfDayMultiplier_0,
+ 1 => TimeOfDayMultiplier_1,
+ 2 => TimeOfDayMultiplier_2,
+ 3 => TimeOfDayMultiplier_3,
+ _ => throw new ArgumentOutOfRangeException(nameof(index)),
+ };
+
+ public float GetWeatherMultiplier(int index) => index switch
+ {
+ 0 => 1.0f, // "No Weather" results in no modification of rate for all species/forms
+ 1 => WeatherMultiplier_1,
+ 2 => WeatherMultiplier_2,
+ 3 => WeatherMultiplier_3,
+ 4 => WeatherMultiplier_4,
+ 5 => WeatherMultiplier_5,
+ 6 => WeatherMultiplier_6,
+ 7 => WeatherMultiplier_7,
+ 8 => WeatherMultiplier_8,
+ _ => throw new ArgumentOutOfRangeException(nameof(index)),
+ };
+
+ public bool HasTimeModifier(int index) => GetTimeMultiplier(index) != -1.0f;
+ public bool HasWeatherModifier(int index) => index != 0 && GetWeatherMultiplier(index) != -1.0f;
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterOybnTraits8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterOybnTraits8a.cs
new file mode 100644
index 00000000..73a3fd3c
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterOybnTraits8a.cs
@@ -0,0 +1,22 @@
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EncounterOybnTraits8a
+{
+ [FlatBufferItem(00)] public bool Oybn1 { get; set; }
+ [FlatBufferItem(01)] public bool Oybn2 { get; set; }
+ [FlatBufferItem(02)] public bool Field_02 { get; set; }
+ [FlatBufferItem(03)] public bool Field_03 { get; set; }
+
+ public bool IsOybnAny => Oybn1 || Oybn2 || Field_02 || Field_03;
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterSlot8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterSlot8a.cs
new file mode 100644
index 00000000..88e872cc
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterSlot8a.cs
@@ -0,0 +1,123 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+using pkNX.Containers;
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EncounterSlot8a
+{
+ [FlatBufferItem(00)] public int Species { get; set; }
+ [FlatBufferItem(01)] public ulong SlotID { get; set; }
+ [FlatBufferItem(02)] public int Gender { get; set; }
+ [FlatBufferItem(03)] public int Form { get; set; }
+ [FlatBufferItem(04)] public ShinyType8a ShinyLock { get; set; }
+ [FlatBufferItem(05)] public AbilityType8a AbilityRandType { get; set; }
+ [FlatBufferItem(06)] public NatureType8a Nature { get; set; }
+ [FlatBufferItem(07)] public int Height { get; set; }
+ [FlatBufferItem(08)] public int Weight { get; set; }
+ [FlatBufferItem(09)] public bool Field_09 { get; set; }
+ [FlatBufferItem(10)] public bool Field_10 { get; set; }
+ [FlatBufferItem(11)] public bool Field_11 { get; set; }
+ [FlatBufferItem(12)] public bool Field_12 { get; set; }
+ [FlatBufferItem(13)] public int GV_HP { get; set; }
+ [FlatBufferItem(14)] public int GV_ATK { get; set; }
+ [FlatBufferItem(15)] public int GV_DEF { get; set; }
+ [FlatBufferItem(16)] public int GV_SPA { get; set; }
+ [FlatBufferItem(17)] public int GV_SPD { get; set; }
+ [FlatBufferItem(18)] public int GV_SPE { get; set; }
+ [FlatBufferItem(19)] public int IV_HP { get; set; }
+ [FlatBufferItem(20)] public int IV_ATK { get; set; }
+ [FlatBufferItem(21)] public int IV_DEF { get; set; }
+ [FlatBufferItem(22)] public int IV_SPA { get; set; }
+ [FlatBufferItem(23)] public int IV_SPD { get; set; }
+ [FlatBufferItem(24)] public int IV_SPE { get; set; }
+ [FlatBufferItem(25)] public int NumPerfectIvs { get; set; }
+ [FlatBufferItem(26)] public string Behavior1 { get; set; } = string.Empty;
+ [FlatBufferItem(27)] public string Behavior2 { get; set; } = string.Empty;
+ [FlatBufferItem(28)] public byte Field_28_AffectsLottery { get; set; }
+ [FlatBufferItem(29)] public int BaseProbability { get; set; }
+ [FlatBufferItem(30)] public int OverrideMinLevel { get; set; }
+ [FlatBufferItem(31)] public int OverrideMaxLevel { get; set; }
+ [FlatBufferItem(32)] public int Field_32 { get; set; }
+ [FlatBufferItem(33)] public bool HasMoveset { get; set; }
+ [FlatBufferItem(34)] public int Move1 { get; set; }
+ [FlatBufferItem(35)] public int Move2 { get; set; }
+ [FlatBufferItem(36)] public int Move3 { get; set; }
+ [FlatBufferItem(37)] public int Move4 { get; set; }
+ [FlatBufferItem(38)] public bool Move1Mastered { get; set; }
+ [FlatBufferItem(39)] public bool Move2Mastered { get; set; }
+ [FlatBufferItem(40)] public bool Move3Mastered { get; set; }
+ [FlatBufferItem(41)] public bool Move4Mastered { get; set; }
+ [FlatBufferItem(42)] public string Unused { get; set; } = string.Empty;
+ [FlatBufferItem(43)] public int Field_43_Func_1A25908 { get; set; }
+ [FlatBufferItem(44)] public bool Field_44_SetsPropTo100Not8000 { get; set; }
+ [FlatBufferItem(45)] public EncounterEligiblityTraits8a Eligibility { get; set; } = new();
+ [FlatBufferItem(46)] public EncounterOybnTraits8a Oybn { get; set; } = new ();
+
+ public (bool forced, int min, int max) GetLevels(int min, int max)
+ {
+ bool force = false;
+ if (OverrideMinLevel is > 0 and <= 100)
+ {
+ force = true;
+ min = OverrideMinLevel;
+ }
+ if (OverrideMaxLevel is > 0 and <= 100)
+ {
+ force = true;
+ max = OverrideMaxLevel;
+ }
+ return (force, min, max);
+ }
+
+ public float GetTimeModifier(int time, EncounterMultiplier8a default_mults)
+ {
+ if (Eligibility.HasTimeModifier(time))
+ return Eligibility.GetTimeMultiplier(time);
+ if (default_mults.HasTimeModifier(time))
+ return default_mults.GetTimeMultiplier(time);
+ return 1.0f;
+ }
+ public float GetWeatherModifier(int weather, EncounterMultiplier8a default_mults)
+ {
+ if (Eligibility.HasWeatherModifier(weather))
+ return Eligibility.GetWeatherMultiplier(weather);
+ if (default_mults.HasWeatherModifier(weather))
+ return default_mults.GetWeatherMultiplier(weather);
+ return 1.0f;
+ }
+
+ // lazy init
+ private static Dictionary? _slotNameMap;
+ private static IReadOnlyDictionary GetSlotNameMap() => _slotNameMap ??= GenerateTableMap();
+
+ private static Dictionary GenerateTableMap()
+ {
+ var result = new Dictionary();
+ for (var i = 0; i < 1000; i++)
+ {
+ var life = $"life{i:000}";
+ var pm = $"pm{i:0000}";
+ result[FnvHash.HashFnv1a_64(life)] = life;
+ result[FnvHash.HashFnv1a_64(pm)] = pm;
+ }
+ for (var i = 0; i < 100; i++)
+ {
+ var poke = $"poke{i:00}";
+ result[FnvHash.HashFnv1a_64(poke)] = poke;
+ }
+ return result;
+ }
+
+ public static string GetSlotName(ulong slotId)
+ {
+ var map = GetSlotNameMap();
+ if (map.TryGetValue(slotId, out var name))
+ return $"\"{name}\"";
+ return $"0x{slotId:X16}";
+ }
+
+ public string SlotName => GetSlotName(SlotID);
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterTable8a.cs
new file mode 100644
index 00000000..d944f1d4
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Slots/EncounterTable8a.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+using pkNX.Containers;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EncounterTable8a
+{
+ [FlatBufferItem(0)] public ulong TableID { get; set; }
+ [FlatBufferItem(1)] public int MinLevel { get; set; }
+ [FlatBufferItem(2)] public int MaxLevel { get; set; }
+ [FlatBufferItem(3)] public EncounterSlot8a[] Table { get; set; } = Array.Empty();
+
+ // lazy init
+ private static Dictionary? _tableNameMap;
+ private static IReadOnlyDictionary GetTableNameMap() => _tableNameMap ??= GenerateTableMap();
+
+ private static Dictionary GenerateTableMap()
+ {
+ var result = new Dictionary();
+
+ result[0xCBF29CE484222645] = "";
+
+ var prefixes = new[] { "eve", "fly", "gmk", "lnd", "mas", "oyb", "swm", "whl" };
+ var kinds = new[] { "ex", "no", "ra" };
+ foreach (var prefix in prefixes)
+ {
+ foreach (var kind in kinds)
+ {
+ for (var i = 0; i < 150; i++)
+ {
+ var name = $"{prefix}_{kind}_{i:00}";
+ var hash = FnvHash.HashFnv1a_64(name);
+ result[hash] = name;
+ }
+ }
+ }
+
+ for (var area = 0; area < 6; area++)
+ {
+ for (var i = 0; i < 10; i++)
+ {
+ result[FnvHash.HashFnv1a_64($"sky_area{area}_{i:00}")] = $"sky_area{area}_{i:00}";
+ }
+ }
+
+ result[FnvHash.HashFnv1a_64("eve_ex_16_b")] = "eve_ex_16_b";
+ result[FnvHash.HashFnv1a_64("eve_ex_17_b")] = "eve_ex_17_b";
+ result[FnvHash.HashFnv1a_64("eve_ex_18_b")] = "eve_ex_18_b";
+
+ var gimmicks = new[] { "no", "tree", "rock", "crystal", "snow", "box" };
+ foreach (var gimmick in gimmicks)
+ {
+ for (var i = 0; i < 100; i++)
+ {
+ result[FnvHash.HashFnv1a_64($"gmk_{gimmick}_{i:00}")] = $"gmk_{gimmick}_{i:00}";
+ for (var j = 0; j < 3; j++)
+ {
+ result[FnvHash.HashFnv1a_64($"gmk_{gimmick}_{i:00}_{j:00}")] = $"gmk_{gimmick}_{i:00}_{j:00}";
+ for (var k = 0; k < 3; k++)
+ {
+ result[FnvHash.HashFnv1a_64($"gmk_{gimmick}_{i:00}{j:00}_{k:00}")] = $"gmk_{gimmick}_{i:00}{j:00}_{k:00}";
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public static string GetTableName(ulong tableId)
+ {
+ var map = GetTableNameMap();
+ if (map.TryGetValue(tableId, out var name))
+ return $"\"{name}\"";
+ return $"0x{tableId:X16}";
+ }
+
+ public string TableName => GetTableName(TableID);
+
+ public override string ToString() => $"{TableName} (Lv. {MinLevel}-{MaxLevel})";
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncount8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncount8a.cs
new file mode 100644
index 00000000..cdf11487
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncount8a.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EventEncount8a
+{
+ [FlatBufferItem(0)] public string EncounterName { get; set; } = string.Empty;
+ [FlatBufferItem(1)] public string Field_01 { get; set; } = string.Empty;
+ [FlatBufferItem(2)] public int Field_02 { get; set; } // All Entries have empty
+ [FlatBufferItem(3)] public EventEncountPoke8a[]? Table { get; set; } = Array.Empty();
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncount8aArchive.cs b/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncount8aArchive.cs
new file mode 100644
index 00000000..2454cb87
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncount8aArchive.cs
@@ -0,0 +1,20 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EventEncount8aArchive : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public EventEncount8a[] Table { get; set; } = Array.Empty();
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncountPoke8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncountPoke8a.cs
new file mode 100644
index 00000000..acb00f01
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Static/EventEncountPoke8a.cs
@@ -0,0 +1,75 @@
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class EventEncountPoke8a
+{
+ [FlatBufferItem(00)] public int Species { get; set; }
+ [FlatBufferItem(01)] public int Form { get; set; }
+ [FlatBufferItem(02)] public int Gender { get; set; }
+ [FlatBufferItem(03)] public int ShinyLock { get; set; }
+ [FlatBufferItem(04)] public int Level { get; set; }
+ [FlatBufferItem(05)] public int AbilityRandType { get; set; }
+ [FlatBufferItem(06)] public int Nature { get; set; }
+ [FlatBufferItem(07)] public int Height { get; set; }
+ [FlatBufferItem(08)] public int Weight { get; set; }
+ [FlatBufferItem(09)] public bool Field_09 { get; set; }
+ [FlatBufferItem(10)] public bool Field_10 { get; set; }
+ [FlatBufferItem(11)] public bool Field_11 { get; set; }
+ [FlatBufferItem(12)] public int Field_12 { get; set; }
+ [FlatBufferItem(13)] public string Field_13 { get; set; } = string.Empty;
+ [FlatBufferItem(14)] public string Field_14 { get; set; } = string.Empty;
+ [FlatBufferItem(15)] public string Field_15 { get; set; } = string.Empty;
+ [FlatBufferItem(16)] public int Field_16 { get; set; }
+ [FlatBufferItem(17)] public bool IsOybn { get; set; }
+ [FlatBufferItem(18)] public int Move1 { get; set; }
+ [FlatBufferItem(19)] public bool Mastered1 { get; set; }
+ [FlatBufferItem(20)] public int Move2 { get; set; }
+ [FlatBufferItem(21)] public bool Mastered2 { get; set; }
+ [FlatBufferItem(22)] public int Move3 { get; set; }
+ [FlatBufferItem(23)] public bool Mastered3 { get; set; }
+ [FlatBufferItem(24)] public int Move4 { get; set; }
+ [FlatBufferItem(25)] public bool Mastered4 { get; set; }
+ [FlatBufferItem(26)] public int IV_HP { get; set; }
+ [FlatBufferItem(27)] public int IV_ATK { get; set; }
+ [FlatBufferItem(28)] public int IV_DEF { get; set; }
+ [FlatBufferItem(29)] public int IV_SPA { get; set; }
+ [FlatBufferItem(30)] public int IV_SPD { get; set; }
+ [FlatBufferItem(31)] public int IV_SPE { get; set; }
+ [FlatBufferItem(32)] public int NumPerfectIvs { get; set; }
+ [FlatBufferItem(33)] public int GV_HP { get; set; }
+ [FlatBufferItem(34)] public int GV_ATK { get; set; }
+ [FlatBufferItem(35)] public int GV_DEF { get; set; }
+ [FlatBufferItem(36)] public int GV_SPA { get; set; }
+ [FlatBufferItem(37)] public int GV_SPD { get; set; }
+ [FlatBufferItem(38)] public int GV_SPE { get; set; }
+
+ public bool HasMoveset => Move1 != 0;
+ public bool HasGVs => GV_HP != 0 || GV_ATK != 0 || GV_DEF != 0 || GV_SPA != 0 || GV_SPD != 0 || GV_SPE != 0;
+
+ public string Dump(string[] speciesNames, string argEncounterName)
+ {
+ var natureStr = Nature == -1 ? "" : $", Nature = (int){(NatureType8a)Nature}";
+ var shinyStr = $", Shiny = {(ShinyLock == 2 ? "Never" : ShinyLock.ToString())}";
+ var gvStr = "";
+ if (HasGVs)
+ gvStr = $", GVs = new[]{{{GV_HP},{GV_ATK},{GV_DEF},{GV_SPE},{GV_SPA},{GV_SPD}}}";
+
+ var moves = !HasMoveset ? "" : $", Moves = new[] {{{Move1:000},{Move2:000},{Move3:000},{Move4:000}}}";
+ var mastery = !HasMoveset ? "" : $", Mastery = new[] {{{Mastered1.ToString().ToLower()},{Mastered2.ToString().ToLower()},{Mastered3.ToString().ToLower()},{Mastered4.ToString().ToLower()}}}";
+ var alpha = !IsOybn ? "" : ", IsAlpha = true";
+ var genderStr = Gender == -1 ? "" : $", Gender = {Gender}";
+ var iv = NumPerfectIvs == 0 ? "" : $", FlawlessIVCount = {NumPerfectIvs}";
+ string comment = $"// {argEncounterName}: {speciesNames[Species]}{(Form == 0 ? "" : $"-{Form}")}";
+ return $"new({Species:000},{Form:000},{Level:00},{Height},{Weight}) {{ Location = -01{shinyStr}{alpha}{genderStr}{natureStr}{iv}{gvStr}{moves}{mastery} }}, {comment}";
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Throw/ThrowParamTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Throw/ThrowParamTable8a.cs
new file mode 100644
index 00000000..dd2fc28f
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Throw/ThrowParamTable8a.cs
@@ -0,0 +1,32 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class ThrowParamTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public ThrowParam8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class ThrowParam8a
+{
+ [FlatBufferItem(00)] public ulong Hash { get; set; }
+ [FlatBufferItem(01)] public float Field_01 { get; set; }
+ [FlatBufferItem(02)] public float Field_02 { get; set; }
+ [FlatBufferItem(03)] public float Field_03 { get; set; }
+ [FlatBufferItem(04)] public float Field_04 { get; set; }
+
+ public string Dump() => $"{Hash:X16}\t{Field_01}\t{Field_02}\t{Field_03}\t{Field_04}";
+}
\ No newline at end of file
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Throw/ThrowableParamTable8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Throw/ThrowableParamTable8a.cs
new file mode 100644
index 00000000..dedf4317
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Throw/ThrowableParamTable8a.cs
@@ -0,0 +1,35 @@
+using System;
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class ThrowableParamTable8a : IFlatBufferArchive
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ [FlatBufferItem(0)] public ThrowableParam8a[] Table { get; set; } = Array.Empty();
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class ThrowableParam8a
+{
+ [FlatBufferItem(00)] public int ItemID { get; set; }
+ [FlatBufferItem(01)] public ulong Hash_01 { get; set; }
+ [FlatBufferItem(02)] public ulong Hash_02 { get; set; }
+ [FlatBufferItem(03)] public ulong Hash_03 { get; set; }
+ [FlatBufferItem(04)] public ulong Hash_04 { get; set; }
+ [FlatBufferItem(05)] public int Field_05 { get; set; }
+ [FlatBufferItem(06)] public float Field_06 { get; set; }
+ [FlatBufferItem(07)] public string Label_01 { get; set; } = string.Empty;
+ [FlatBufferItem(08)] public string Label_02 { get; set; } = string.Empty;
+ [FlatBufferItem(09)] public float Field_09 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/TrData8a.cs b/pkNX.Structures.FlatBuffers/Arceus/TrData8a.cs
new file mode 100644
index 00000000..15d16af2
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/TrData8a.cs
@@ -0,0 +1,88 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class TrData8a
+{
+ [FlatBufferItem(00)] public ulong Hash_00 { get; set; } // ulong
+ [FlatBufferItem(01)] public ulong Hash_01 { get; set; } // ulong
+ [FlatBufferItem(02)] public ulong Hash_02 { get; set; } // ulong
+ [FlatBufferItem(03)] public string Music { get; set; } = string.Empty;
+ [FlatBufferItem(04)] public string EE_04 { get; set; } = string.Empty;
+ [FlatBufferItem(05)] public string EE_05 { get; set; } = string.Empty;
+ [FlatBufferItem(06)] public string EE_06 { get; set; } = string.Empty;
+ [FlatBufferItem(07)] public ulong Hash_07 { get; set; } // ulong
+ [FlatBufferItem(08)] public ulong Hash_08 { get; set; } // ulong
+ [FlatBufferItem(09)] public TrFloatQuad Field_09 { get; set; } = new();
+ [FlatBufferItem(10)] public int Field_10 { get; set; } // int
+ [FlatBufferItem(11)] public int Field_11 { get; set; } // int
+ [FlatBufferItem(12)] public int Field_12 { get; set; } // int
+ [FlatBufferItem(13)] public byte Field_13 { get; set; } // UNUSED?
+ [FlatBufferItem(14)] public byte Field_14 { get; set; } // UNUSED?
+ [FlatBufferItem(15)] public byte Field_15 { get; set; } // UNUSED?
+ [FlatBufferItem(16)] public byte Field_16 { get; set; } // byte
+ [FlatBufferItem(17)] public byte Field_17 { get; set; } // byte
+ [FlatBufferItem(18)] public byte Field_18 { get; set; } // byte
+ [FlatBufferItem(19)] public byte Field_19 { get; set; } // UNUSED?
+ [FlatBufferItem(20)] public byte Field_20 { get; set; } // byte
+ [FlatBufferItem(21)] public byte Field_21 { get; set; } // byte
+ [FlatBufferItem(22)] public TrPoke8a[] Team { get; set; } = Array.Empty();
+
+ public string TeamSummary => Environment.NewLine + string.Join(Environment.NewLine, Team.Select(z => z.ToString()));
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class TrPoke8a
+{
+ [FlatBufferItem(00)] public int Species { get; set; }
+ [FlatBufferItem(01)] public int Form { get; set; }
+ [FlatBufferItem(02)] public TrPoke8aMove Move_01 { get; set; } = new();
+ [FlatBufferItem(03)] public TrPoke8aMove Move_02 { get; set; } = new();
+ [FlatBufferItem(04)] public TrPoke8aMove Move_03 { get; set; } = new();
+ [FlatBufferItem(05)] public TrPoke8aMove Move_04 { get; set; } = new();
+ [FlatBufferItem(06)] public int Field_06 { get; set; }
+ [FlatBufferItem(07)] public int Field_07 { get; set; }
+ [FlatBufferItem(08)] public int Field_08 { get; set; }
+ [FlatBufferItem(09)] public int Field_09 { get; set; }
+ [FlatBufferItem(10)] public int Field_10 { get; set; }
+ [FlatBufferItem(11)] public int Field_11 { get; set; }
+ [FlatBufferItem(12)] public int Field_12 { get; set; }
+ [FlatBufferItem(13)] public int Field_13 { get; set; }
+ [FlatBufferItem(14)] public int Field_14 { get; set; }
+ [FlatBufferItem(15)] public int Field_15 { get; set; }
+
+ public override string ToString()
+ {
+ return $"{Species}{(Form == 0 ? "" : $"-{Form}")}|{Move_01}|{Move_02}|{Move_03}|{Move_04}|{Field_06}|{Field_07}|{Field_08}|{Field_09}|{Field_10}|{Field_11}|{Field_12}|{Field_13}|{Field_14}|{Field_15}";
+ }
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class TrPoke8aMove
+{
+ [FlatBufferItem(00)] public int Move { get; set; }
+ [FlatBufferItem(01)] public bool Flag { get; set; }
+ public override string ToString() => $"{Move}{(Flag?"*":"")}";
+}
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class TrFloatQuad
+{
+ [FlatBufferItem(00)] public float Float_00 { get; set; }
+ [FlatBufferItem(01)] public float Float_01 { get; set; }
+ [FlatBufferItem(02)] public float Float_02 { get; set; }
+ [FlatBufferItem(03)] public float Float_03 { get; set; }
+
+ public override string ToString() => $"({Float_00},{Float_01},{Float_02},{Float_03})";
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/AbilityType8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/AbilityType8a.cs
new file mode 100644
index 00000000..d651f921
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/AbilityType8a.cs
@@ -0,0 +1,15 @@
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedMember.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferEnum(typeof(int))]
+public enum AbilityType8a
+{
+ Any12 = 0,
+ Any12H = 1,
+ Only1 = 2,
+ Only2 = 3,
+ OnlyH = 4,
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/EncounterDetail8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/EncounterDetail8a.cs
new file mode 100644
index 00000000..580a1d6d
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/EncounterDetail8a.cs
@@ -0,0 +1,78 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace pkNX.Structures.FlatBuffers;
+
+public record struct EncounterDetail8a(double Rate, double MultT, double MultW, int Unk, EncounterSlot8a Slot)
+{
+ private const int WeatherCount = (int)Weather8a.Count;
+ private const int TimeCount = (int)Time8a.Count;
+
+ public static List[,] GetEmpty()
+ {
+ var result = new List[TimeCount, WeatherCount];
+ for (var t = 0; t < TimeCount; t++)
+ {
+ for (var w = 0; w < WeatherCount; w++)
+ result[t, w] = new List();
+ }
+ return result;
+ }
+
+ public static void Divide(List[,] table)
+ {
+ for (var time = 0; time < TimeCount; time++)
+ {
+ for (var weather = 0; weather < WeatherCount; weather++)
+ {
+ table[time, weather] = table[time, weather].OrderByDescending(xt => xt.Rate).ToList();
+
+ var totalRate = 0.0;
+ foreach (var tup in table[time, weather])
+ totalRate += tup.Rate;
+
+ for (var i = 0; i < table[time, weather].Count; i++)
+ {
+ var e = table[time, weather][i];
+ var effective = (e.Rate / totalRate) * 100.0;
+ var detail = new EncounterDetail8a(effective, e.MultT, e.MultW, e.Unk, e.Slot);
+ table[time, weather][i] = detail;
+ }
+ }
+ }
+ }
+ public static TableSymmetryResult AnalyzeSymmetry(List[,] table)
+ {
+ var isWeatherSymmetric = true;
+ var isTimeSymmetric = true;
+ var weatherSymmetricPerTime = new[] { true, true, true, true };
+ for (var time = 0; time < 4; time++)
+ {
+ for (var weather = 0; weather < (int)Weather8a.Count; weather++)
+ {
+ var ts = IsSameEffectiveTable(table[time, weather], table[0, weather]);
+ var ws = IsSameEffectiveTable(table[time, weather], table[time, 0]);
+ isTimeSymmetric &= ts;
+ isWeatherSymmetric &= ws;
+ weatherSymmetricPerTime[time] &= ws;
+ }
+ }
+
+ return new TableSymmetryResult(isWeatherSymmetric, isTimeSymmetric, weatherSymmetricPerTime);
+ }
+
+ private static bool IsSameEffectiveTable(IReadOnlyList lhs, IReadOnlyList rhs)
+ {
+ if (lhs.Count != rhs.Count) return false;
+
+ for (var i = 0; i < lhs.Count; i++)
+ {
+ if (lhs[i].Rate != rhs[i].Rate) return false;
+ if (lhs[i].Unk != rhs[i].Unk) return false;
+ }
+
+ return true;
+ }
+}
+
+public record struct TableSymmetryResult(bool Weather, bool Time, bool[] Complexed);
\ No newline at end of file
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/EncounterTable8aUtil.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/EncounterTable8aUtil.cs
new file mode 100644
index 00000000..8079451d
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/EncounterTable8aUtil.cs
@@ -0,0 +1,423 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace pkNX.Structures.FlatBuffers
+{
+ public static class EncounterTable8aUtil
+ {
+ private const float SpawnerBias = 73; // lured unown and jet + run
+ private const float WormholeBias = 15;
+ private const float LandmarkBias = 15;
+
+ public static IEnumerable GetEncounterDump(AreaInstance8a area,
+ IReadOnlyDictionary map, PokeMiscTable8a misc)
+ {
+ if (area.Locations.Length == 0)
+ yield break;
+
+ foreach (var table in area.Encounters.Table)
+ {
+ var slots = table.Table.Where(z => z.ShinyLock is ShinyType8a.Random).ToList();
+ if (slots.Count == 0)
+ continue;
+
+ foreach (var p in GetAreas(area, slots, table, map, misc))
+ yield return p;
+ foreach (var x in area.SubAreas)
+ {
+ foreach (var p in GetAreas(x, slots, table, map, misc))
+ yield return p;
+ }
+ }
+ }
+
+ private static IEnumerable GetAreas(AreaInstance8a area, IReadOnlyCollection slots, EncounterTable8a table, IReadOnlyDictionary map, PokeMiscTable8a misc)
+ {
+ if (area.Locations.Length == 0)
+ yield break;
+
+ int baseArea = map[area.Locations.First(z => z.IsNamedPlace).PlaceName].Index;
+ // Spawners
+ {
+ var s = area.Spawners;
+ var spawners = s.Where(z => z.UsesTable(table.TableID));
+ var sl = spawners.SelectMany(z => z.GetIntersectingLocations(area.Locations, SpawnerBias));
+ foreach (var a in GetAll(sl, SpawnerType.Spawner))
+ yield return a;
+ }
+
+ // Wormholes
+ {
+ var s = area.Wormholes;
+ var spawners = s.Where(z => z.UsesTable(table.TableID));
+
+ // Since Wormholes can have different bonus level ranges, we defer uniqueness testing to the outer method. Just yield all spawners.
+ foreach (var w in spawners)
+ {
+ var bmin = w.Field_20_Value.BonusLevelMin;
+ var bmax = w.Field_20_Value.BonusLevelMax;
+
+ var sl = w.GetIntersectingLocations(area.Locations, WormholeBias);
+ foreach (var a in GetAll(sl, SpawnerType.Wormhole, bmin, bmax))
+ yield return a;
+ }
+ }
+
+ // Landmarks
+ {
+ var items = area.LandItems;
+ var lis = items.Where(z => z.UsesTable(table.TableID)).ToList();
+
+ var marks = area.LandMarks;
+ var li = marks.Where(z => lis.Any(sz => z.UsesTable(sz.LandmarkItemSpawnTableID)));
+ var sl = li.SelectMany(z => z.GetIntersectingLocations(area.Locations, LandmarkBias));
+ foreach (var a in GetAll(sl, SpawnerType.Landmark))
+ yield return a;
+ }
+
+ IEnumerable GetAll(IEnumerable places, SpawnerType type, int bmin = 0, int bmax = 0)
+ {
+ var temp = places.Select(z => z.PlaceName);
+ var areas = temp.Select(z => map[z].Index).Distinct().ToList();
+ if (areas.Count == 0)
+ yield break;
+ if (areas.Remove(baseArea) && areas.Count == 0)
+ areas.Add(baseArea);
+
+ foreach (var a in areas)
+ {
+ var parent = baseArea;
+ if (IsDungeonZone(a))
+ parent = a; // disallow crossover-out for dungeons
+ yield return GetArea(a, parent, slots, table.MinLevel, table.MaxLevel, type, misc, bmin, bmax);
+ }
+ }
+ }
+
+ // 064 Seaside Hollow
+ // 086 Wayward Cave
+ // 095 Snowpoint Temple
+ private static bool IsDungeonZone(int a) => a is 64 or 86 or 95;
+
+ private static readonly int[] OybnSettings = { 15, 15, 15, 20, 20 };
+
+ private static byte[] GetArea(int location, int parentArea, IReadOnlyCollection slots,
+ int tableMinLevel, int tableMaxLevel, SpawnerType type,
+ PokeMiscTable8a misc,
+ int bonusMin = 0,
+ int bonusMax = 0)
+ {
+ using var ms = new MemoryStream();
+ using var bw = new BinaryWriter(ms);
+ bw.Write((byte)location);
+ bw.Write((byte)parentArea);
+ bw.Write((byte)type);
+ bw.Write((byte)slots.Count);
+ foreach (var s in slots)
+ {
+ var (_, min, max) = s.GetLevels(tableMinLevel, tableMaxLevel);
+ min += bonusMin;
+ max += bonusMax;
+ int alpha = 0;
+ var oybn = s.Oybn;
+ if (oybn.Oybn1 || oybn.Oybn2)
+ {
+ var miscEntry = misc.GetEntry(s.Species, s.Form);
+ var boostIndex = miscEntry.OybnLevelIndex;
+ var boost = OybnSettings[boostIndex - 1];
+ max += boost;
+ min += boost;
+ if (s.Oybn.Oybn2)
+ alpha = 2; // Oybn2 -- Master All Moves Possible?
+ else if (s.Oybn.Oybn1)
+ alpha = 1; // Oybn1 -- Master only Alpha move?
+ }
+
+ var gender = s.Gender == -1 ? 2 : s.Gender;
+ bw.Write((ushort)s.Species);
+ bw.Write((byte)s.Form);
+ bw.Write((byte)alpha);
+ bw.Write((byte)min);
+ bw.Write((byte)max);
+ bw.Write((byte)gender);
+ bw.Write((byte)s.NumPerfectIvs);
+ }
+ return ms.ToArray();
+ }
+
+ public static IEnumerable GetUnownLines(AreaInstance8a area, IReadOnlyDictionary map)
+ {
+ yield return $"Area: {area.AreaName}";
+ foreach (var u in area.Unown.Concat(area.SubAreas.SelectMany(x => x.Unown)))
+ {
+ var contained = u.GetContainingLocations(area.Locations).First().PlaceName;
+ var name = map[contained].Name;
+ var p = u.Parameters;
+ yield return $"Unown {u.Identifier} @ {u.Hash_01:X16}_{u.Hash_03:X16} {u.Flag} ({p.GetConditionSummary()}) @ {p.Coordinates.ToTriple()}, {area.AreaName} = {name}";
+ }
+ }
+
+ public static IEnumerable GetUnownLinesBias(AreaInstance8a area, IReadOnlyDictionary map, float bias)
+ {
+ yield return $"Area: {area.AreaName}";
+ foreach (var u in area.Unown.Concat(area.SubAreas.SelectMany(x => x.Unown)))
+ {
+ var contained = u.GetIntersectingLocations(area.Locations, bias);
+ foreach (var c in contained)
+ {
+ var name = map[c.PlaceName].Name;
+ var p = u.Parameters;
+ yield return $"Unown {u.Identifier} @ {u.Hash_01:X16}_{u.Hash_03:X16} {u.Flag} ({p.GetConditionSummary()}) @ {p.Coordinates.ToTriple()}, {area.AreaName} = {name}";
+ }
+ }
+ }
+
+ public static IEnumerable GetLines(EncounterMultiplerArchive8a multiplier_archive,
+ PokeMiscTable8a misc, string[] speciesNames,
+ AreaInstance8a area, IReadOnlyDictionary map)
+ {
+ yield return $"Area: {area.AreaName}";
+
+ foreach (var enctable in area.Encounters.Table) {
+ foreach (var line in GetTableSummary(enctable, multiplier_archive, speciesNames, misc, area, map))
+ yield return $"\t{line}";
+
+ yield return string.Empty;
+ }
+ }
+
+ private static IEnumerable GetUsedSpawnerSummary(EncounterTable8a t, AreaInstance8a area, IReadOnlyDictionary valueTuples)
+ {
+ var usedBySpawners = Array.FindAll(area.Spawners, z => z.UsesTable(t.TableID));
+ var usedByWormholes = Array.FindAll(area.Wormholes, z => z.UsesTable(t.TableID));
+ var usedByLandmarkSpawns = Array.FindAll(area.LandItems, z => z.UsesTable(t.TableID));
+ var usedByLandmarks = Array.FindAll(area.LandMarks, z => usedByLandmarkSpawns.Any(sz => z.UsesTable(sz.LandmarkItemSpawnTableID)));
+
+ foreach (var s in usedBySpawners)
+ {
+ var contained = s.GetContainingLocations(area.Locations).First().PlaceName;
+ var name = valueTuples[contained].Name;
+ var p = s.Parameters;
+ yield return $"Spawner @ {s.NameSummary}_{s.Field_01:X16} ({p.GetConditionSummary()}) @ {p.Coordinates.ToTriple()}, {area.AreaName} = {name}";
+ }
+ foreach (var s in usedByWormholes)
+ {
+ var contained = s.GetContainingLocations(area.Locations).First().PlaceName;
+ var name = valueTuples[contained].Name;
+ var p = s.Parameters;
+ var c = s.Field_20_Value;
+ yield return $"Wormhole: {s.NameSummary}_{s.Field_01:X16} ({p.GetConditionSummary()}) [{c.BonusLevelMin}-{c.BonusLevelMax}] @ {p.Coordinates.ToTriple()}, {area.AreaName} = {name}";
+ }
+ foreach (var s in usedByLandmarks)
+ {
+ var contained = s.GetContainingLocations(area.Locations).First().PlaceName;
+ var name = valueTuples[contained].Name;
+ var spawn = usedByLandmarkSpawns.First(sz => s.UsesTable(sz.LandmarkItemSpawnTableID));
+ var p = s.Parameters;
+ yield return $"Landmark: {s.NameSummary}_{s.Field_01:X16}_{spawn.NameSummary} ({p.GetConditionSummary()}) @ {p.Coordinates.ToTriple()}, {area.AreaName} = {name}";
+ }
+ }
+
+ private static IEnumerable GetTableSummary(EncounterTable8a t,
+ EncounterMultiplerArchive8a multiplier_archive, string[] speciesNames,
+ PokeMiscTable8a misc,
+ AreaInstance8a area, IReadOnlyDictionary valueTuples)
+ {
+ yield return $"{t}:";
+
+ var totalUses = 0;
+ foreach (var line in GetUsedSpawnerSummary(t, area, valueTuples))
+ {
+ totalUses++;
+ yield return $"\t{line}";
+ }
+
+ foreach (var subArea in area.SubAreas)
+ {
+ foreach (var line in GetUsedSpawnerSummary(t, subArea, valueTuples))
+ {
+ totalUses++;
+ yield return $"\t{line}";
+ }
+ }
+
+ if (totalUses == 0)
+ {
+ yield return "\tNo spawners? Check that this is used somewhere.";
+ }
+
+ foreach (var line in GetLines(t.Table, multiplier_archive, speciesNames, t.MinLevel, t.MaxLevel, misc))
+ yield return $"\t{line}";
+ }
+
+ private static IEnumerable GetLines(IReadOnlyList arr,
+ EncounterMultiplerArchive8a multiplier_archive, IReadOnlyList speciesNames, int lvMin, int lvMax,
+ PokeMiscTable8a misc)
+ {
+ var dividedTables = EncounterDetail8a.GetEmpty();
+ FillSlots(arr, multiplier_archive, dividedTables);
+ EncounterDetail8a.Divide(dividedTables);
+
+ var sym = EncounterDetail8a.AnalyzeSymmetry(dividedTables);
+ if (sym.Time && sym.Weather)
+ {
+ yield return "Any Time/All Weather:";
+ foreach (var line in GetEffectiveTableSummary(dividedTables[0, 0], speciesNames, lvMin, lvMax, misc))
+ yield return $"\t{line}";
+ }
+ else if (sym.Weather)
+ {
+ for (var time = 0; time < dividedTables.GetLength(0); time++)
+ {
+ yield return $"{(Time8a)time}/All Weather:";
+ foreach (var line in GetEffectiveTableSummary(dividedTables[time, 0], speciesNames, lvMin, lvMax, misc))
+ yield return $"\t{line}";
+ }
+ }
+ else if (sym.Time)
+ {
+ for (var weather = 0; weather < dividedTables.GetLength(1); weather++)
+ {
+ yield return $"Any Time/{(Weather8a)weather}:";
+ foreach (var line in GetEffectiveTableSummary(dividedTables[0, weather], speciesNames, lvMin, lvMax, misc))
+ yield return $"\t{line}";
+ }
+ }
+ else
+ {
+ for (var time = 0; time < dividedTables.GetLength(0); time++)
+ {
+ if (sym.Complexed[time])
+ {
+ yield return $"{(Time8a)time}/All Weather:";
+ foreach (var line in GetEffectiveTableSummary(dividedTables[time, 0], speciesNames, lvMin, lvMax, misc))
+ yield return $"\t{line}";
+ }
+ else
+ {
+ for (var weather = 0; weather < dividedTables.GetLength(1); weather++)
+ {
+ yield return $"{(Time8a)time}/{(Weather8a)weather}:";
+ foreach (var line in GetEffectiveTableSummary(dividedTables[time, weather], speciesNames, lvMin, lvMax, misc))
+ yield return $"\t{line}";
+ }
+ }
+ }
+ }
+ }
+
+ private static void FillSlots(IEnumerable arr, EncounterMultiplerArchive8a multArchive, List[,] dividedTables)
+ {
+ var ctr = 0;
+ foreach (var slot in arr.OrderByDescending(sl => sl.BaseProbability))
+ {
+ var defaults = multArchive.GetEncounterMultiplier(slot);
+ for (var time = 0; time < dividedTables.GetLength(0); time++)
+ {
+ var MultT = slot.GetTimeModifier(time, defaults);
+ for (var weather = 0; weather < dividedTables.GetLength(1); weather++)
+ {
+ var MultW = slot.GetWeatherModifier(weather, defaults);
+ var rate = slot.BaseProbability * MultT * MultW;
+ if (rate == 0)
+ continue;
+
+ var detail = new EncounterDetail8a(slot.BaseProbability * MultT * MultW, MultT, MultW, ctr, slot);
+ dividedTables[time, weather].Add(detail);
+ }
+ }
+
+ ctr++;
+ }
+ }
+
+ private static IEnumerable GetEffectiveTableSummary(IReadOnlyList table, IReadOnlyList speciesNames, int lvMin, int lvMax, PokeMiscTable8a misc)
+ {
+ if (table.Count == 0)
+ {
+ yield return " - None";
+ yield break;
+ }
+
+ foreach (var tup in table)
+ {
+ var rate = tup.Rate;
+ var slot = tup.Slot;
+
+ string form = slot.Form == 0 ? string.Empty : $"-{slot.Form}";
+ var spec_form = $"{speciesNames[slot.Species]}{form}";
+
+ var summary = $"- {rate:00.00}%\t{spec_form,-12}";
+
+ var (force, min, max) = slot.GetLevels(lvMin, lvMax);
+ if (slot.Oybn.Oybn1 || slot.Oybn.Oybn2)
+ {
+ var miscEntry = misc.GetEntry(slot.Species, slot.Form);
+ var boostIndex = miscEntry.OybnLevelIndex;
+ var boost = OybnSettings[boostIndex - 1];
+ max += boost;
+ min += boost;
+ summary += $"\tAlphaLevel={min}-{max}";
+ }
+ else if (force)
+ {
+ summary += $"\tOverrideLevel={min}-{max}";
+ }
+
+ if (slot.Gender != -1)
+ summary += $"\tGender={slot.Gender}";
+
+ if (slot.ShinyLock is not ShinyType8a.Random)
+ summary += $"\tShinyLock={slot.ShinyLock}";
+
+ if (slot.AbilityRandType is not AbilityType8a.Any12)
+ summary += $"\tAbility={slot.AbilityRandType}";
+
+ if (slot.Nature is not NatureType8a.Random)
+ summary += $"\tNature={slot.Nature}";
+
+ var gvs = new[] { slot.GV_HP, slot.GV_ATK, slot.GV_DEF, slot.GV_SPA, slot.GV_SPD, slot.GV_SPE };
+ if (gvs.Any(x => x != -1))
+ summary += $"\tGVS={string.Join("/", gvs.Select(v => v != -1 ? v.ToString() : "*").ToArray())}";
+
+ if (slot.NumPerfectIvs != 0)
+ summary += $"\tPerfectIvs={slot.NumPerfectIvs}";
+
+ var ivs = new[] { slot.IV_HP, slot.IV_ATK, slot.IV_DEF, slot.IV_SPA, slot.IV_SPD, slot.IV_SPE };
+ if (ivs.Any(x => x != -1))
+ summary += $"\tIVS={string.Join("/", ivs.Select(v => v != -1 ? v.ToString() : "*").ToArray())}";
+
+ var oybn = slot.Oybn;
+ if (oybn.IsOybnAny)
+ {
+ if (oybn.Oybn1 && !oybn.Oybn2 && oybn.Field_02 && oybn.Field_03)
+ summary += "\tOybn=Type1";
+ else if (oybn.Oybn1 && oybn.Oybn2 && oybn.Field_02 && oybn.Field_03)
+ summary += "\tOybn=Type2";
+ else
+ summary += $"\tOybn={{{(oybn.Oybn1 ? 1 : 0)},{(oybn.Oybn2 ? 1 : 0)},{(oybn.Field_02 ? 1 : 0)},{(oybn.Field_03 ? 1 : 0)}}}";
+ }
+
+ var elg = slot.Eligibility;
+ if (slot.Eligibility.ConditionTypeID != ConditionType8a.None)
+ {
+ summary += $"\tConditionType={elg.GetConditionTypeSummary()}";
+ summary += $"\tCondition={elg.GetConditionSummary()}";
+ }
+
+ if (!string.IsNullOrEmpty(slot.Behavior1))
+ summary += $"\t{nameof(slot.Behavior1)}=\"{slot.Behavior1}\"";
+
+ if (!string.IsNullOrEmpty(slot.Behavior2))
+ summary += $"\t{nameof(slot.Behavior2)}=\"{slot.Behavior2}\"";
+
+ if (slot.SlotID != 0xCBF29CE484222645)
+ summary += $"\tSlotID={slot.SlotName}";
+
+ yield return summary;
+ }
+ }
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/IHasCondition8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/IHasCondition8a.cs
new file mode 100644
index 00000000..6b6a80c9
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/IHasCondition8a.cs
@@ -0,0 +1,14 @@
+// ReSharper disable UnusedMember.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+public interface IHasCondition8a
+{
+ ConditionType8a ConditionTypeID { get; set; }
+ Condition8a ConditionID { get; set; }
+ string ConditionArg1 { get; set; }
+ string ConditionArg2 { get; set; }
+ string ConditionArg3 { get; set; }
+ string ConditionArg4 { get; set; }
+ string ConditionArg5 { get; set; }
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/NatureType8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/NatureType8a.cs
new file mode 100644
index 00000000..faa08fdf
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/NatureType8a.cs
@@ -0,0 +1,41 @@
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedMember.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferEnum(typeof(int))]
+public enum NatureType8a
+{
+ Random = -1,
+
+ Hardy,
+ Lonely,
+ Brave,
+ Adamant,
+ Naughty,
+ Bold,
+
+ Docile,
+ Relaxed,
+ Impish,
+ Lax,
+ Timid,
+ Hasty,
+
+ Serious,
+ Jolly,
+ Naive,
+ Modest,
+ Mild,
+ Quiet,
+
+ Bashful,
+ Rash,
+ Calm,
+ Gentle,
+ Sassy,
+ Careful,
+
+ Quirky,
+}
\ No newline at end of file
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/ShinyType8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/ShinyType8a.cs
new file mode 100644
index 00000000..e824026d
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/ShinyType8a.cs
@@ -0,0 +1,13 @@
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedMember.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferEnum(typeof(int))]
+public enum ShinyType8a
+{
+ Random = 0,
+ Always = 1,
+ Never = 2,
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/SpawnerType.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/SpawnerType.cs
new file mode 100644
index 00000000..5f3290d1
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/SpawnerType.cs
@@ -0,0 +1,9 @@
+namespace pkNX.Structures.FlatBuffers;
+
+public enum SpawnerType
+{
+ Spawner,
+ Wormhole,
+ Landmark,
+ Unown,
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/Time8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/Time8a.cs
new file mode 100644
index 00000000..9187deb2
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/Time8a.cs
@@ -0,0 +1,12 @@
+// ReSharper disable UnusedMember.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+public enum Time8a
+{
+ Dawn = 0,
+ Day = 1,
+ Dusk = 2,
+ Night = 3,
+ Count = 4,
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Util/Weather8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Util/Weather8a.cs
new file mode 100644
index 00000000..3cc4f169
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Util/Weather8a.cs
@@ -0,0 +1,17 @@
+namespace pkNX.Structures.FlatBuffers;
+
+// ReSharper disable UnusedMember.Global
+
+public enum Weather8a
+{
+ None = 0,
+ Sunny = 1,
+ Cloudy = 2,
+ Rain = 3,
+ Snow = 4,
+ Drought = 5,
+ Fog = 6,
+ Rainstorm = 7,
+ Snowstorm = 8,
+ Count = 9,
+}
diff --git a/pkNX.Structures.FlatBuffers/Arceus/Waza8a.cs b/pkNX.Structures.FlatBuffers/Arceus/Waza8a.cs
new file mode 100644
index 00000000..fd5f4c31
--- /dev/null
+++ b/pkNX.Structures.FlatBuffers/Arceus/Waza8a.cs
@@ -0,0 +1,157 @@
+using System.ComponentModel;
+using FlatSharp.Attributes;
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedType.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+namespace pkNX.Structures.FlatBuffers;
+
+[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
+public class Waza8a : IMove
+{
+ public byte[] Write() => FlatBufferConverter.SerializeFrom(this);
+
+ // Type mismatch; FlatBuffer must use the correct struct type for each field
+ // We need to alias these and hide them from any PropertyGrid, so mark Browsable(false).
+
+ [FlatBufferItem(00)] public int MoveID { get; set; } // int
+ [FlatBufferItem(01)] public bool CanUseMove { get; set; }
+ [FlatBufferItem(02), Browsable(false)] public byte FType { get; set; } // byte
+ [FlatBufferItem(03), Browsable(false)] public byte FQuality { get; set; } // byte
+ [FlatBufferItem(04), Browsable(false)] public byte FCategory { get; set; } // byte
+ [FlatBufferItem(05), Browsable(false)] public byte FPower { get; set; } // byte
+ [FlatBufferItem(06), Browsable(false)] public byte FAccuracy { get; set; } // byte
+ [FlatBufferItem(07), Browsable(false)] public byte FPP { get; set; } // byte
+ [FlatBufferItem(08), Browsable(false)] public sbyte FPriority { get; set; } // byte
+ [FlatBufferItem(09), Browsable(false)] public byte FHitMin { get; set; } // byte
+ [FlatBufferItem(10), Browsable(false)] public byte FHitMax { get; set; } // byte
+ [FlatBufferItem(11), Browsable(false)] public short FInflict { get; set; } // ushort
+ [FlatBufferItem(12), Browsable(false)] public byte FInflictPercent { get; set; } // byte
+ [FlatBufferItem(13), Browsable(false)] public byte FRawInflictCount { get; set; } // byte
+ [FlatBufferItem(14), Browsable(false)] public byte FTurnMin { get; set; } // byte
+ [FlatBufferItem(15), Browsable(false)] public byte FTurnMax { get; set; } // byte
+ [FlatBufferItem(16), Browsable(false)] public byte FCritStage { get; set; } // byte
+ [FlatBufferItem(17), Browsable(false)] public byte FFlinch { get; set; } // byte
+ [FlatBufferItem(18), Browsable(false)] public ushort FEffectSequence { get; set; } // ushort
+ [FlatBufferItem(19), Browsable(false)] public byte FRecoil { get; set; } // byte
+ [FlatBufferItem(20), Browsable(false)] public byte FRawHealing { get; set; } // byte
+ [FlatBufferItem(21), Browsable(false)] public byte FRawTarget { get; set; } // byte
+ [FlatBufferItem(22), Browsable(false)] public byte FStat1 { get; set; } // byte
+ [FlatBufferItem(23), Browsable(false)] public byte FStat2 { get; set; } // byte
+ [FlatBufferItem(24), Browsable(false)] public byte FStat3 { get; set; } // byte
+ [FlatBufferItem(25), Browsable(false)] public sbyte FStat1Stage { get; set; } // byte
+ [FlatBufferItem(26), Browsable(false)] public sbyte FStat2Stage { get; set; } // byte
+ [FlatBufferItem(27), Browsable(false)] public sbyte FStat3Stage { get; set; } // byte
+ [FlatBufferItem(28), Browsable(false)] public byte FStat1Percent { get; set; } // byte
+ [FlatBufferItem(29), Browsable(false)] public byte FStat2Percent { get; set; } // byte
+ [FlatBufferItem(30), Browsable(false)] public byte FStat3Percent { get; set; } // byte
+ [FlatBufferItem(31)] public byte FStat1Duration { get; set; } // byte
+ [FlatBufferItem(32)] public byte FStat2Duration { get; set; } // byte
+ [FlatBufferItem(33)] public byte FStat3Duration { get; set; } // byte
+ [FlatBufferItem(34)] public byte GigantamaxPower { get; set; } // byte
+ [FlatBufferItem(35)] public bool Flag_MakesContact { get; set; }
+ [FlatBufferItem(36)] public bool Flag_Charge { get; set; }
+ [FlatBufferItem(37)] public bool Flag_Recharge { get; set; }
+ [FlatBufferItem(38)] public bool Flag_Protect { get; set; }
+ [FlatBufferItem(39)] public bool Flag_Reflectable { get; set; }
+ [FlatBufferItem(40)] public bool Flag_Snatch { get; set; }
+ [FlatBufferItem(41)] public bool Flag_Mirror { get; set; }
+ [FlatBufferItem(42)] public bool Flag_Punch { get; set; }
+ [FlatBufferItem(43)] public bool Flag_Sound { get; set; }
+ [FlatBufferItem(44)] public bool Flag_Gravity { get; set; }
+ [FlatBufferItem(45)] public bool Flag_Defrost { get; set; }
+ [FlatBufferItem(46)] public bool Flag_DistanceTriple { get; set; }
+ [FlatBufferItem(47)] public bool Flag_Heal { get; set; }
+ [FlatBufferItem(48)] public bool Flag_IgnoreSubstitute { get; set; }
+ [FlatBufferItem(49)] public bool Flag_FailSkyBattle { get; set; }
+ [FlatBufferItem(50)] public bool Flag_AnimateAlly { get; set; }
+ [FlatBufferItem(51)] public bool Flag_Dance { get; set; }
+ [FlatBufferItem(52)] public bool Flag_Metronome { get; set; }
+ // New additions!
+ [FlatBufferItem(53)] public byte SplinterModifier { get; set; } // byte
+ [FlatBufferItem(54)] public byte Status_Fixated { get; set; } // byte
+ [FlatBufferItem(55)] public byte Status_Obscured { get; set; } // byte
+ [FlatBufferItem(56)] public byte Status_ObscuredDuration { get; set; } // byte
+ [FlatBufferItem(57)] public byte Status_Primed { get; set; } // byte
+ [FlatBufferItem(58)] public byte Status_PrimedDuration { get; set; } // byte
+ [FlatBufferItem(59)] public byte Status_PrimedPercent { get; set; } // byte
+ [FlatBufferItem(60)] public byte Status_StanceSwap { get; set; } // byte
+ [FlatBufferItem(61)] public byte Status_StanceSwapDuration { get; set; } // byte
+ [FlatBufferItem(62)] public byte Status_FutureCrit { get; set; } // byte
+ [FlatBufferItem(63)] public byte Status_FutureCritDuration { get; set; } // byte
+ [FlatBufferItem(64)] public byte Status_FutureCritStage { get; set; } // byte
+ [FlatBufferItem(65)] public bool Flag_CureDrowsy { get; set; } // byte
+ [FlatBufferItem(66)] public bool Flag_CureFrostbite { get; set; } // byte
+ [FlatBufferItem(67)] public int DamagePercentStatused { get; set; } // int
+ [FlatBufferItem(68)] public byte CanStyle { get; set; } // byte
+ [FlatBufferItem(69)] public int ActionSpeedMod { get; set; } // int
+ [FlatBufferItem(70)] public int AgileActionSpeedMod { get; set; } // int
+ [FlatBufferItem(71)] public int StrongActionSpeedMod { get; set; } // int
+ [FlatBufferItem(72)] public int TargetActionSpeedMod { get; set; } // int
+ [FlatBufferItem(73)] public int StrongTargetActionSpeedMod { get; set; } // int
+ [FlatBufferItem(74)] public byte AgilePower { get; set; } // byte
+ [FlatBufferItem(75)] public byte AgileRawHealing { get; set; } // byte
+ [FlatBufferItem(76)] public byte AgileTurnMax { get; set; } // byte
+ [FlatBufferItem(77)] public byte AgileEffectDuration { get; set; } // byte
+ [FlatBufferItem(78)] public byte AgileStatChangeDuration { get; set; } // byte
+ [FlatBufferItem(79)] public byte StrongPower { get; set; } // byte
+ [FlatBufferItem(80)] public byte StrongAccuracy { get; set; } // byte
+ [FlatBufferItem(81)] public byte StrongCritStage { get; set; } // byte
+ [FlatBufferItem(82)] public byte StrongInflictPercent { get; set; } // byte
+ [FlatBufferItem(83)] public byte StrongStat1Percent { get; set; } // byte
+ [FlatBufferItem(84)] public byte StrongTurnMax { get; set; } // byte
+ [FlatBufferItem(85)] public byte StrongEffectDuration { get; set; } // byte
+ [FlatBufferItem(86)] public byte StrongStatChangeDuration { get; set; } // byte
+ [FlatBufferItem(87)] public int StrongRecoil { get; set; } // int
+ [FlatBufferItem(88)] public byte StrongRawHealing { get; set; } // byte
+ [FlatBufferItem(89)] public byte StrongSplinterModifier { get; set; } // byte
+
+ public int Type { get => FType; set => FType = (byte)value; }
+ public int Quality { get => FQuality ; set => FQuality = (byte)value; }
+ public int Category { get => FCategory ; set => FCategory = (byte)value; }
+ public int Power { get => FPower ; set => FPower = (byte)value; }
+ public int Accuracy { get => FAccuracy ; set => FAccuracy = (byte)value; }
+ public int PP { get => FPP ; set => FPP = (byte)value; }
+ public int Priority { get => FPriority ; set => FPriority = (sbyte)value; }
+ public int HitMin { get => FHitMin ; set => FHitMin = (byte)value; }
+ public int HitMax { get => FHitMax ; set => FHitMax = (byte)value; }
+ public int Inflict { get => FInflict ; set => FInflict = (short)value; }
+ public int InflictPercent { get => FInflictPercent ; set => FInflictPercent = (byte)value; }
+ public int TurnMin { get => FTurnMin ; set => FTurnMin = (byte)value; }
+ public int TurnMax { get => FTurnMax ; set => FTurnMax = (byte)value; }
+ public int CritStage { get => FCritStage ; set => FCritStage = (byte)value; }
+ public int Flinch { get => FFlinch ; set => FFlinch = (byte)value; }
+ public int EffectSequence { get => FEffectSequence ; set => FEffectSequence = (ushort)value; }
+ public int Recoil { get => FRecoil ; set => FRecoil = (byte)value; }
+ public int Stat1 { get => FStat1 ; set => FStat1 = (byte)value; }
+ public int Stat2 { get => FStat2 ; set => FStat2 = (byte)value; }
+ public int Stat3 { get => FStat3 ; set => FStat3 = (byte)value; }
+ public int Stat1Stage { get => FStat1Stage ; set => FStat1Stage = (sbyte)value; }
+ public int Stat2Stage { get => FStat2Stage ; set => FStat2Stage = (sbyte)value; }
+ public int Stat3Stage { get => FStat3Stage ; set => FStat3Stage = (sbyte)value; }
+ public int Stat1Percent { get => FStat1Percent ; set => FStat1Percent = (byte)value; }
+ public int Stat2Percent { get => FStat2Percent ; set => FStat2Percent = (byte)value; }
+ public int Stat3Percent { get => FStat3Percent ; set => FStat3Percent = (byte)value; }
+
+ public MoveInflictDuration InflictCount
+ {
+ get => (MoveInflictDuration)FRawInflictCount;
+ set => FRawInflictCount = (byte)value;
+ }
+
+ public Heal Healing
+ {
+ get => (Heal)FRawHealing;
+ set => FRawHealing = (byte)value;
+ }
+
+ public MoveTarget Target
+ {
+ get => (MoveTarget)FRawTarget;
+ set => FRawTarget = (byte)value;
+ }
+}
diff --git a/pkNX.Structures.FlatBuffers/Gen8/Nest/EncounterNest8Archive.cs b/pkNX.Structures.FlatBuffers/Gen8/Nest/EncounterNest8Archive.cs
index 23e6507e..52a4ac84 100644
--- a/pkNX.Structures.FlatBuffers/Gen8/Nest/EncounterNest8Archive.cs
+++ b/pkNX.Structures.FlatBuffers/Gen8/Nest/EncounterNest8Archive.cs
@@ -10,7 +10,6 @@
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
#nullable disable
-#pragma warning disable CA1819 // Properties should not return arrays
namespace pkNX.Structures.FlatBuffers
{
@@ -147,7 +146,7 @@ IEnumerable GetOrderedDrops(IReadOnlyList
string GetItemName(uint itemID)
{
- if (1130 <= itemID && itemID < 1230) // TR
+ if (itemID is >= 1130 and < 1230) // TR
return $"{items[(int) itemID]} {moves[tmtrs[100 + (int) itemID - 1130]]}";
return items[(int) itemID];
}
diff --git a/pkNX.Structures.FlatBuffers/Gen8/Nest/EncounterUnderground8Archive.cs b/pkNX.Structures.FlatBuffers/Gen8/Nest/EncounterUnderground8Archive.cs
index a943d66e..b01c49d9 100644
--- a/pkNX.Structures.FlatBuffers/Gen8/Nest/EncounterUnderground8Archive.cs
+++ b/pkNX.Structures.FlatBuffers/Gen8/Nest/EncounterUnderground8Archive.cs
@@ -7,7 +7,6 @@
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
#nullable disable
-#pragma warning disable CA1819 // Properties should not return arrays
namespace pkNX.Structures.FlatBuffers
{
diff --git a/pkNX.Structures.FlatBuffers/Gen8/Nest/NestHoleCrystalEncounter8Archive.cs b/pkNX.Structures.FlatBuffers/Gen8/Nest/NestHoleCrystalEncounter8Archive.cs
index b8c37efd..6def4c5c 100644
--- a/pkNX.Structures.FlatBuffers/Gen8/Nest/NestHoleCrystalEncounter8Archive.cs
+++ b/pkNX.Structures.FlatBuffers/Gen8/Nest/NestHoleCrystalEncounter8Archive.cs
@@ -10,7 +10,6 @@
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
#nullable disable
-#pragma warning disable CA1819 // Properties should not return arrays
namespace pkNX.Structures.FlatBuffers
{
@@ -98,26 +97,21 @@ IEnumerable GetOrderedDrops(IReadOnlyList
string GetItemName(uint itemID)
{
- if (1130 <= itemID && itemID < 1230) // TR
+ if (itemID is >= 1130 and < 1230) // TR
return $"{items[(int)itemID]} {moves[tmtrs[100 + (int)itemID - 1130]]}";
return items[(int)itemID];
}
}
- private static int GetEncounterRank(int level)
+ private static int GetEncounterRank(int level) => level switch
{
- if (15 <= level && level <= 20)
- return 1;
- if (25 <= level && level <= 30)
- return 2;
- if (35 <= level && level <= 40)
- return 3;
- if (45 <= level && level <= 50)
- return 4;
- if (55 <= level && level <= 60)
- return 5;
- return 0;
- }
+ >= 15 and <= 20 => 1,
+ >= 25 and <= 30 => 2,
+ >= 35 and <= 40 => 3,
+ >= 45 and <= 50 => 4,
+ >= 55 and <= 60 => 5,
+ _ => 0,
+ };
public IEnumerable GetSummary(IReadOnlyList species, IReadOnlyList items)
{
diff --git a/pkNX.Structures.FlatBuffers/Gen8/Nest/NestHoleDistributionEncounter8Archive.cs b/pkNX.Structures.FlatBuffers/Gen8/Nest/NestHoleDistributionEncounter8Archive.cs
index 767d98e1..9fd109ec 100644
--- a/pkNX.Structures.FlatBuffers/Gen8/Nest/NestHoleDistributionEncounter8Archive.cs
+++ b/pkNX.Structures.FlatBuffers/Gen8/Nest/NestHoleDistributionEncounter8Archive.cs
@@ -10,7 +10,6 @@
// ReSharper disable UnusedType.Global
// ReSharper disable UnusedMember.Global
#nullable disable
-#pragma warning disable CA1819 // Properties should not return arrays
namespace pkNX.Structures.FlatBuffers
{
@@ -113,7 +112,7 @@ IEnumerable GetOrderedDrops(IReadOnlyList