using System; using System.Runtime.InteropServices; #pragma warning disable CS8618, CA1815, CA1819, IDE1006 namespace NHSE.Core { /// /// Original Reactions object from release /// [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct GSavePlayerManpu : IReactionStore { public const int SIZE = 0x88; private const int MaxCount = 64; private const int WheelCount = 8; /// /// List of known Reaction IDs /// [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] public Reaction[] ManpuBit { get; set; } /// /// Emotions that are currently bound to the Reaction Wheel. /// [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = WheelCount)] public Reaction[] UIList { get; set; } /// /// Flags indicating if an Reaction (at the same index?) is newly learned or not. /// [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = MaxCount)] public bool[] NewFlag { get; set; } public void AddMissingReactions() { var all = (Reaction[])Enum.GetValues(typeof(Reaction)); foreach (var react in all) AddReaction(react); } // returns true if failed public bool AddReaction(Reaction react) { if (react.ToString().StartsWith("UNUSED")) return true; var index = Array.IndexOf(ManpuBit, react); if (index >= 0) return false; var empty = EmptyIndex; if (empty < 0) return true; ManpuBit[empty] = react; return false; } private int EmptyIndex => Array.FindIndex(ManpuBit, z => z == 0); } /// /// Reactions object revised in v1.5.0 /// [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct GSavePlayerManpu15 : IReactionStore { public const int SIZE = 0x208; private const int MaxCount = 256; // up from 64 private const int WheelCount = 8; /// /// List of known Reaction IDs /// [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)] public Reaction[] ManpuBit { get; set; } /// /// Emotions that are currently bound to the Reaction Wheel. /// [field: MarshalAs(UnmanagedType.ByValArray, SizeConst = WheelCount)] public Reaction[] UIList { get; set; } /// /// Flags indicating if an Reaction (at the same index?) is newly learned or not. /// [field: MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = MaxCount)] public bool[] NewFlag { get; set; } public void AddMissingReactions() { var all = (Reaction[])Enum.GetValues(typeof(Reaction)); foreach (var react in all) AddReaction(react); } // returns true if failed public bool AddReaction(Reaction react) { if (react.ToString().StartsWith("UNUSED")) return true; var index = Array.IndexOf(ManpuBit, react); if (index >= 0) return false; var empty = EmptyIndex; if (empty < 0) return true; ManpuBit[empty] = react; return false; } private int EmptyIndex => Array.FindIndex(ManpuBit, z => z == 0); } public interface IReactionStore { Reaction[] ManpuBit { get; set; } Reaction[] UIList { get; set; } bool[] NewFlag { get; set; } bool AddReaction(Reaction react); void AddMissingReactions(); } }