Fix reaction wheel UI display

revised structure, need to abstract things a little for it
Closes #427
see also #428
This commit is contained in:
Kurt
2020-11-22 19:57:29 -08:00
parent 1e0bd10bdb
commit eb554a623b
12 changed files with 104 additions and 8 deletions

View File

@@ -100,6 +100,12 @@ public IReadOnlyList<Item> ItemChest
set => BitConverter.GetBytes(value).CopyTo(Data, Offsets.ItemChest + (Offsets.ItemChestCount * Item.SIZE));
}
public IReactionStore Reactions
{
get => Offsets.ReadReactions(Data);
set => Offsets.SetReactions(Data, value);
}
public AchievementList Achievements
{
get => Data.Slice(Offsets.CountAchievement, AchievementList.SIZE).ToStructure<AchievementList>();

View File

@@ -63,5 +63,8 @@ public static PersonalOffsets GetOffsets(FileHeaderInfo Info)
_ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info),
};
}
public abstract IReactionStore ReadReactions(byte[] data);
public abstract void SetReactions(byte[] data, IReactionStore value);
}
}

View File

@@ -40,5 +40,8 @@ public sealed class PersonalOffsets10 : PersonalOffsets
public override int MaxRecipeID => 0x2A0;
public override int MaxRemakeBitFlag => 0x754 * 32;
public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure<GSavePlayerManpu>();
public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu);
}
}

View File

@@ -40,5 +40,8 @@ public sealed class PersonalOffsets11 : PersonalOffsets
public override int MaxRecipeID => 0x2C8;
public override int MaxRemakeBitFlag => 0x7D0 * 32;
public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure<GSavePlayerManpu>();
public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu);
}
}

View File

@@ -40,5 +40,8 @@ public sealed class PersonalOffsets12 : PersonalOffsets
public override int MaxRecipeID => 0x2DA; // mermaid stuff
public override int MaxRemakeBitFlag => 0x7D0 * 32;
public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure<GSavePlayerManpu>();
public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu);
}
}

View File

@@ -40,5 +40,8 @@ public sealed class PersonalOffsets13 : PersonalOffsets
public override int MaxRecipeID => 0x2DA;
public override int MaxRemakeBitFlag => 0x7D0 * 32;
public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure<GSavePlayerManpu>();
public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu);
}
}

View File

@@ -40,5 +40,8 @@ public sealed class PersonalOffsets14 : PersonalOffsets
public override int MaxRecipeID => 0x2DA;
public override int MaxRemakeBitFlag => 0x7D0 * 32;
public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu.SIZE).ToStructure<GSavePlayerManpu>();
public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu)value).ToBytes().CopyTo(data, Manpu);
}
}

View File

@@ -40,5 +40,8 @@ public sealed class PersonalOffsets15 : PersonalOffsets
public override int MaxRecipeID => 0x2E1;
public override int MaxRemakeBitFlag => 0x7D0 * 32;
public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure<GSavePlayerManpu15>();
public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu);
}
}

View File

@@ -40,5 +40,8 @@ public sealed class PersonalOffsets16 : PersonalOffsets
public override int MaxRecipeID => 0x2E1;
public override int MaxRemakeBitFlag => 0x7D0 * 32;
public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure<GSavePlayerManpu15>();
public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu);
}
}

View File

@@ -4,8 +4,11 @@
#pragma warning disable CS8618, CA1815, CA1819, IDE1006
namespace NHSE.Core
{
/// <summary>
/// Original Reactions object from release
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct GSavePlayerManpu
public struct GSavePlayerManpu : IReactionStore
{
public const int SIZE = 0x88;
private const int MaxCount = 64;
@@ -55,4 +58,68 @@ public bool AddReaction(Reaction react)
private int EmptyIndex => Array.FindIndex(ManpuBit, z => z == 0);
}
/// <summary>
/// Reactions object revised in v1.5.0
/// </summary>
[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;
/// <summary>
/// List of known Reaction IDs
/// </summary>
[field: MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxCount)]
public Reaction[] ManpuBit { get; set; }
/// <summary>
/// Emotions that are currently bound to the Reaction Wheel.
/// </summary>
[field: MarshalAs(UnmanagedType.ByValArray, SizeConst = WheelCount)]
public Reaction[] UIList { get; set; }
/// <summary>
/// Flags indicating if an Reaction (at the same index?) is newly learned or not.
/// </summary>
[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();
}
}

View File

@@ -270,8 +270,8 @@ private void B_EditPlayerReceivedItems_Click(object sender, EventArgs e)
private void B_EditPlayerReactions_Click(object sender, EventArgs e)
{
var player = SAV.Players[PlayerIndex].Personal;
using var editor = new ReactionEditor(player);
var player = SAV.Players[PlayerIndex];
using var editor = new ReactionEditor(player.Personal);
editor.ShowDialog();
}

View File

@@ -14,7 +14,7 @@ public ReactionEditor(Personal p)
this.TranslateInterface(GameInfo.CurrentLanguage);
Personal = p;
var manpu = p.Data.Slice(p.Offsets.Manpu, GSavePlayerManpu.SIZE).ToStructure<GSavePlayerManpu>();
var manpu = p.Reactions;
PG_Manpu.SelectedObject = manpu;
}
@@ -24,15 +24,14 @@ public ReactionEditor(Personal p)
private void B_Save_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
var val = (GSavePlayerManpu) PG_Manpu.SelectedObject;
var bytes = val.ToBytes();
bytes.CopyTo(Personal.Data, Personal.Offsets.Manpu);
var val = (IReactionStore) PG_Manpu.SelectedObject;
Personal.Reactions = val;
Close();
}
private void B_GiveAll_Click(object sender, EventArgs e)
{
var val = (GSavePlayerManpu)PG_Manpu.SelectedObject;
var val = (IReactionStore)PG_Manpu.SelectedObject;
val.AddMissingReactions();
PG_Manpu.SelectedObject = val;
System.Media.SystemSounds.Asterisk.Play();