diff --git a/NHSE.Core/Hashing/FileHashRevision.cs b/NHSE.Core/Hashing/FileHashRevision.cs
index eba8fcb..e418864 100644
--- a/NHSE.Core/Hashing/FileHashRevision.cs
+++ b/NHSE.Core/Hashing/FileHashRevision.cs
@@ -10,6 +10,7 @@ public static class FileHashRevision
private const string FN_POSTBOX = "postbox.dat";
private const string FN_PHOTO = "photo_studio_island.dat";
private const string FN_PROFILE = "profile.dat";
+ private const string FN_WHEREAREN = "wherearen.dat";
#region REVISION 1.0.0
@@ -572,6 +573,7 @@ public static class FileHashRevision
internal const int REV_200_POSTBOX = REV_170_POSTBOX;
internal const int REV_200_PHOTO = 0x2F650;
internal const int REV_200_PROFILE = REV_110_PROFILE;
+ internal const int REV_200_WHEREAREN = 0xB8A4E0;
public static readonly FileHashInfo REV_200 = new(new FileHashDetails[]
{
@@ -614,7 +616,11 @@ public static class FileHashRevision
{
new(0x100, 0x6945c),
}),
- });
+ new(FN_WHEREAREN, REV_200_WHEREAREN, new FileHashRegion[]
+ {
+ new(0x100, 0xB8A3DC),
+ }),
+ } );
#endregion
}
diff --git a/NHSE.Core/Save/Files/WhereAreN.cs b/NHSE.Core/Save/Files/WhereAreN.cs
new file mode 100644
index 0000000..e03705f
--- /dev/null
+++ b/NHSE.Core/Save/Files/WhereAreN.cs
@@ -0,0 +1,18 @@
+namespace NHSE.Core
+{
+ ///
+ ///
+ public sealed class WhereAreN : EncryptedFilePair
+ {
+ public const string FileName = "wherearen";
+
+ public readonly WhereAreNOffsets Offsets;
+ public WhereAreN(string folder) : base(folder, FileName) => Offsets = WhereAreNOffsets.GetOffsets(Info);
+
+ public EncryptedInt32 Poki
+ {
+ get => EncryptedInt32.ReadVerify(Data, Offsets.Poki);
+ set => value.Write(Data, Offsets.Poki);
+ }
+ }
+}
diff --git a/NHSE.Core/Save/Meta/EncryptedFilePair.cs b/NHSE.Core/Save/Meta/EncryptedFilePair.cs
index b851131..8b78ff5 100644
--- a/NHSE.Core/Save/Meta/EncryptedFilePair.cs
+++ b/NHSE.Core/Save/Meta/EncryptedFilePair.cs
@@ -19,6 +19,15 @@ public abstract class EncryptedFilePair
public readonly string NameData;
public readonly string NameHeader;
+ public static bool Exists(string folder, string name)
+ {
+ var NameData = $"{name}.dat";
+ var NameHeader = $"{name}Header.dat";
+ var hdr = Path.Combine(folder, NameHeader);
+ var dat = Path.Combine(folder, NameData);
+ return File.Exists(hdr) && File.Exists(dat);
+ }
+
protected EncryptedFilePair(string folder, string name)
{
NameData = $"{name}.dat";
diff --git a/NHSE.Core/Save/Meta/HorizonSave.cs b/NHSE.Core/Save/Meta/HorizonSave.cs
index ac4258a..573ca0f 100644
--- a/NHSE.Core/Save/Meta/HorizonSave.cs
+++ b/NHSE.Core/Save/Meta/HorizonSave.cs
@@ -78,6 +78,8 @@ public bool ValidateSizes()
return false;
if (p.Profile.Data.Length != sizes.Profile)
return false;
+ if (p.WhereAreN is { } x && x.Data.Length != sizes.WhereAreN)
+ return false;
}
return true;
}
diff --git a/NHSE.Core/Save/Meta/Player.cs b/NHSE.Core/Save/Meta/Player.cs
index 40c7173..5df8394 100644
--- a/NHSE.Core/Save/Meta/Player.cs
+++ b/NHSE.Core/Save/Meta/Player.cs
@@ -14,6 +14,7 @@ public sealed class Player : IEnumerable
public readonly PhotoStudioIsland Photo;
public readonly PostBox PostBox;
public readonly Profile Profile;
+ public readonly WhereAreN? WhereAreN;
///
/// Directory Name where the player data was loaded from. Not the full path.
@@ -21,7 +22,14 @@ public sealed class Player : IEnumerable
public readonly string DirectoryName;
#region Override Implementations
- public IEnumerator GetEnumerator() => new EncryptedFilePair[] {Personal, Photo, PostBox, Profile}.AsEnumerable().GetEnumerator();
+ public IEnumerator GetEnumerator()
+ {
+ IEnumerable baseFiles = new EncryptedFilePair[] { Personal, Photo, PostBox, Profile };
+ if (WhereAreN is not null)
+ baseFiles = baseFiles.Concat(new EncryptedFilePair[] { WhereAreN });
+ return baseFiles.AsEnumerable().GetEnumerator();
+ }
+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public override string ToString() => Personal.PlayerName;
@@ -49,6 +57,9 @@ private Player(string folder)
Photo = new PhotoStudioIsland(folder);
PostBox = new PostBox(folder);
Profile = new Profile(folder);
+
+ if (EncryptedFilePair.Exists(folder, WhereAreN.FileName))
+ WhereAreN = new WhereAreN(folder);
}
}
}
diff --git a/NHSE.Core/Save/Meta/RevisionChecker.cs b/NHSE.Core/Save/Meta/RevisionChecker.cs
index b3418d5..c2e23de 100644
--- a/NHSE.Core/Save/Meta/RevisionChecker.cs
+++ b/NHSE.Core/Save/Meta/RevisionChecker.cs
@@ -26,7 +26,7 @@ public static class RevisionChecker
new(REV_190_MAIN, REV_190_PERSONAL, REV_190_PHOTO, REV_190_POSTBOX, REV_190_PROFILE), // 1.9.0
new(REV_1100_MAIN,REV_1100_PERSONAL,REV_1100_PHOTO,REV_1100_POSTBOX,REV_1100_PROFILE),// 1.10.0
new(REV_1110_MAIN,REV_1110_PERSONAL,REV_1110_PHOTO,REV_1110_POSTBOX,REV_1110_PROFILE),// 1.11.0
- new(REV_200_MAIN, REV_200_PERSONAL, REV_200_PHOTO, REV_200_POSTBOX, REV_200_PROFILE), // 2.0.0
+ new(REV_200_MAIN, REV_200_PERSONAL, REV_200_PHOTO, REV_200_POSTBOX, REV_200_PROFILE, REV_200_WHEREAREN), // 2.0.0
};
private static readonly FileHeaderInfo[] RevisionInfo =
diff --git a/NHSE.Core/Save/Meta/SaveFileSizes.cs b/NHSE.Core/Save/Meta/SaveFileSizes.cs
index f03d640..2eaadb0 100644
--- a/NHSE.Core/Save/Meta/SaveFileSizes.cs
+++ b/NHSE.Core/Save/Meta/SaveFileSizes.cs
@@ -10,14 +10,16 @@ public class SaveFileSizes
public readonly uint PhotoStudioIsland;
public readonly uint PostBox;
public readonly uint Profile;
+ public readonly uint WhereAreN;
- public SaveFileSizes(uint main, uint personal, uint photo, uint postbox, uint profile)
+ public SaveFileSizes(uint main, uint personal, uint photo, uint postbox, uint profile, uint wherearen = 0)
{
Main = main;
Personal = personal;
PhotoStudioIsland = photo;
PostBox = postbox;
Profile = profile;
+ WhereAreN = wherearen;
}
}
-}
\ No newline at end of file
+}
diff --git a/NHSE.Core/Save/Offsets/WhereAreNOffsets.cs b/NHSE.Core/Save/Offsets/WhereAreNOffsets.cs
new file mode 100644
index 0000000..e63932c
--- /dev/null
+++ b/NHSE.Core/Save/Offsets/WhereAreNOffsets.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace NHSE.Core
+{
+ ///
+ /// Offset info and object retrieval logic for
+ ///
+ public abstract class WhereAreNOffsets
+ {
+ public abstract int Poki { get; }
+
+ public static WhereAreNOffsets GetOffsets(FileHeaderInfo Info)
+ {
+ var rev = Info.GetKnownRevisionIndex();
+ return rev switch
+ {
+ 22 => new WhereAreNOffsets20(),
+ 23 => new WhereAreNOffsets20(),
+ 24 => new WhereAreNOffsets20(),
+ 25 => new WhereAreNOffsets20(),
+ _ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info),
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/NHSE.Core/Save/Offsets/WhereAreNOffsets20.cs b/NHSE.Core/Save/Offsets/WhereAreNOffsets20.cs
new file mode 100644
index 0000000..90cc233
--- /dev/null
+++ b/NHSE.Core/Save/Offsets/WhereAreNOffsets20.cs
@@ -0,0 +1,10 @@
+namespace NHSE.Core
+{
+ ///
+ ///
+ ///
+ public sealed class WhereAreNOffsets20 : WhereAreNOffsets
+ {
+ public override int Poki => 0xB84228;
+ }
+}
diff --git a/NHSE.WinForms/Editor.Designer.cs b/NHSE.WinForms/Editor.Designer.cs
index 5149f63..751ef9d 100644
--- a/NHSE.WinForms/Editor.Designer.cs
+++ b/NHSE.WinForms/Editor.Designer.cs
@@ -38,6 +38,7 @@ private void InitializeComponent()
this.Menu_VerifyHashes = new System.Windows.Forms.ToolStripMenuItem();
this.Menu_LoadDecrypted = new System.Windows.Forms.ToolStripMenuItem();
this.Menu_RAMEdit = new System.Windows.Forms.ToolStripMenuItem();
+ this.Menu_ItemImages = new System.Windows.Forms.ToolStripMenuItem();
this.Menu_Options = new System.Windows.Forms.ToolStripMenuItem();
this.Menu_Language = new System.Windows.Forms.ToolStripComboBox();
this.Menu_Settings = new System.Windows.Forms.ToolStripMenuItem();
@@ -67,6 +68,8 @@ private void InitializeComponent()
this.B_RecycleBin = new System.Windows.Forms.Button();
this.Tab_Villagers = new System.Windows.Forms.TabPage();
this.Tab_Players = new System.Windows.Forms.TabPage();
+ this.L_Poki = new System.Windows.Forms.Label();
+ this.NUD_Poki = new System.Windows.Forms.NumericUpDown();
this.L_EarnedMiles = new System.Windows.Forms.Label();
this.NUD_TotalNookMiles = new System.Windows.Forms.NumericUpDown();
this.L_StorageCount = new System.Windows.Forms.Label();
@@ -98,13 +101,13 @@ private void InitializeComponent()
this.CB_Players = new System.Windows.Forms.ComboBox();
this.PB_Player = new System.Windows.Forms.PictureBox();
this.TC_Editors = new System.Windows.Forms.TabControl();
- this.Menu_ItemImages = new System.Windows.Forms.ToolStripMenuItem();
this.Menu_Editor.SuspendLayout();
this.CM_Picture.SuspendLayout();
this.Tab_Map.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.NUD_WeatherSeed)).BeginInit();
this.CM_EditMap.SuspendLayout();
this.Tab_Players.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.NUD_Poki)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.NUD_TotalNookMiles)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.NUD_StorageCount)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.NUD_PocketCount2)).BeginInit();
@@ -191,6 +194,14 @@ private void InitializeComponent()
this.Menu_RAMEdit.Text = "RAM Edit";
this.Menu_RAMEdit.Click += new System.EventHandler(this.Menu_RAMEdit_Click);
//
+ // Menu_ItemImages
+ //
+ this.Menu_ItemImages.Name = "Menu_ItemImages";
+ this.Menu_ItemImages.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.M)));
+ this.Menu_ItemImages.Size = new System.Drawing.Size(206, 22);
+ this.Menu_ItemImages.Text = "Item Images";
+ this.Menu_ItemImages.Click += new System.EventHandler(this.Menu_ItemImages_Click);
+ //
// Menu_Options
//
this.Menu_Options.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -259,8 +270,8 @@ private void InitializeComponent()
this.Tab_Map.Controls.Add(this.B_RecycleBin);
this.Tab_Map.Location = new System.Drawing.Point(4, 22);
this.Tab_Map.Name = "Tab_Map";
- this.Tab_Map.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
- this.Tab_Map.Size = new System.Drawing.Size(396, 212);
+ this.Tab_Map.Padding = new System.Windows.Forms.Padding(3);
+ this.Tab_Map.Size = new System.Drawing.Size(396, 261);
this.Tab_Map.TabIndex = 2;
this.Tab_Map.Text = "Map";
this.Tab_Map.UseVisualStyleBackColor = true;
@@ -469,14 +480,16 @@ private void InitializeComponent()
//
this.Tab_Villagers.Location = new System.Drawing.Point(4, 22);
this.Tab_Villagers.Name = "Tab_Villagers";
- this.Tab_Villagers.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
- this.Tab_Villagers.Size = new System.Drawing.Size(396, 212);
+ this.Tab_Villagers.Padding = new System.Windows.Forms.Padding(3);
+ this.Tab_Villagers.Size = new System.Drawing.Size(396, 261);
this.Tab_Villagers.TabIndex = 0;
this.Tab_Villagers.Text = "Villagers";
this.Tab_Villagers.UseVisualStyleBackColor = true;
//
// Tab_Players
//
+ this.Tab_Players.Controls.Add(this.L_Poki);
+ this.Tab_Players.Controls.Add(this.NUD_Poki);
this.Tab_Players.Controls.Add(this.L_EarnedMiles);
this.Tab_Players.Controls.Add(this.NUD_TotalNookMiles);
this.Tab_Players.Controls.Add(this.L_StorageCount);
@@ -501,12 +514,33 @@ private void InitializeComponent()
this.Tab_Players.Controls.Add(this.PB_Player);
this.Tab_Players.Location = new System.Drawing.Point(4, 22);
this.Tab_Players.Name = "Tab_Players";
- this.Tab_Players.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
- this.Tab_Players.Size = new System.Drawing.Size(396, 211);
+ this.Tab_Players.Padding = new System.Windows.Forms.Padding(3);
+ this.Tab_Players.Size = new System.Drawing.Size(396, 261);
this.Tab_Players.TabIndex = 1;
this.Tab_Players.Text = "Players";
this.Tab_Players.UseVisualStyleBackColor = true;
//
+ // L_Poki
+ //
+ this.L_Poki.Location = new System.Drawing.Point(142, 224);
+ this.L_Poki.Name = "L_Poki";
+ this.L_Poki.Size = new System.Drawing.Size(84, 20);
+ this.L_Poki.TabIndex = 28;
+ this.L_Poki.Text = "Poki:";
+ this.L_Poki.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // NUD_Poki
+ //
+ this.NUD_Poki.Location = new System.Drawing.Point(232, 224);
+ this.NUD_Poki.Maximum = new decimal(new int[] {
+ 2147483647,
+ 0,
+ 0,
+ 0});
+ this.NUD_Poki.Name = "NUD_Poki";
+ this.NUD_Poki.Size = new System.Drawing.Size(100, 20);
+ this.NUD_Poki.TabIndex = 27;
+ //
// L_EarnedMiles
//
this.L_EarnedMiles.Location = new System.Drawing.Point(142, 117);
@@ -558,7 +592,7 @@ private void InitializeComponent()
// L_PocketCount2
//
this.L_PocketCount2.AutoSize = true;
- this.L_PocketCount2.Location = new System.Drawing.Point(148, 191);
+ this.L_PocketCount2.Location = new System.Drawing.Point(200, 192);
this.L_PocketCount2.Name = "L_PocketCount2";
this.L_PocketCount2.Size = new System.Drawing.Size(81, 13);
this.L_PocketCount2.TabIndex = 22;
@@ -568,7 +602,7 @@ private void InitializeComponent()
// L_PocketCount1
//
this.L_PocketCount1.AutoSize = true;
- this.L_PocketCount1.Location = new System.Drawing.Point(148, 170);
+ this.L_PocketCount1.Location = new System.Drawing.Point(200, 171);
this.L_PocketCount1.Name = "L_PocketCount1";
this.L_PocketCount1.Size = new System.Drawing.Size(81, 13);
this.L_PocketCount1.TabIndex = 21;
@@ -577,14 +611,14 @@ private void InitializeComponent()
//
// NUD_PocketCount2
//
- this.NUD_PocketCount2.Location = new System.Drawing.Point(104, 188);
+ this.NUD_PocketCount2.Location = new System.Drawing.Point(151, 189);
this.NUD_PocketCount2.Maximum = new decimal(new int[] {
2147483647,
0,
0,
0});
this.NUD_PocketCount2.Name = "NUD_PocketCount2";
- this.NUD_PocketCount2.Size = new System.Drawing.Size(41, 20);
+ this.NUD_PocketCount2.Size = new System.Drawing.Size(46, 20);
this.NUD_PocketCount2.TabIndex = 20;
this.NUD_PocketCount2.Value = new decimal(new int[] {
20,
@@ -595,14 +629,14 @@ private void InitializeComponent()
//
// NUD_PocketCount1
//
- this.NUD_PocketCount1.Location = new System.Drawing.Point(104, 167);
+ this.NUD_PocketCount1.Location = new System.Drawing.Point(151, 168);
this.NUD_PocketCount1.Maximum = new decimal(new int[] {
2147483647,
0,
0,
0});
this.NUD_PocketCount1.Name = "NUD_PocketCount1";
- this.NUD_PocketCount1.Size = new System.Drawing.Size(41, 20);
+ this.NUD_PocketCount1.Size = new System.Drawing.Size(46, 20);
this.NUD_PocketCount1.TabIndex = 19;
this.NUD_PocketCount1.Value = new decimal(new int[] {
20,
@@ -614,9 +648,9 @@ private void InitializeComponent()
// B_EditPlayer
//
this.B_EditPlayer.ContextMenuStrip = this.CM_EditPlayer;
- this.B_EditPlayer.Location = new System.Drawing.Point(300, 168);
+ this.B_EditPlayer.Location = new System.Drawing.Point(6, 214);
this.B_EditPlayer.Name = "B_EditPlayer";
- this.B_EditPlayer.Size = new System.Drawing.Size(92, 40);
+ this.B_EditPlayer.Size = new System.Drawing.Size(130, 40);
this.B_EditPlayer.TabIndex = 18;
this.B_EditPlayer.Text = "Edit Player...";
this.B_EditPlayer.UseVisualStyleBackColor = true;
@@ -689,7 +723,7 @@ private void InitializeComponent()
//
this.B_EditPlayerItems.Location = new System.Drawing.Point(6, 168);
this.B_EditPlayerItems.Name = "B_EditPlayerItems";
- this.B_EditPlayerItems.Size = new System.Drawing.Size(92, 40);
+ this.B_EditPlayerItems.Size = new System.Drawing.Size(130, 40);
this.B_EditPlayerItems.TabIndex = 12;
this.B_EditPlayerItems.Text = "Edit Items";
this.B_EditPlayerItems.UseVisualStyleBackColor = true;
@@ -817,26 +851,17 @@ private void InitializeComponent()
this.TC_Editors.Controls.Add(this.Tab_Players);
this.TC_Editors.Controls.Add(this.Tab_Villagers);
this.TC_Editors.Controls.Add(this.Tab_Map);
- this.TC_Editors.Dock = System.Windows.Forms.DockStyle.Fill;
this.TC_Editors.Location = new System.Drawing.Point(0, 24);
this.TC_Editors.Name = "TC_Editors";
this.TC_Editors.SelectedIndex = 0;
- this.TC_Editors.Size = new System.Drawing.Size(404, 237);
+ this.TC_Editors.Size = new System.Drawing.Size(404, 287);
this.TC_Editors.TabIndex = 1;
//
- // Menu_ItemImages
- //
- this.Menu_ItemImages.Name = "Menu_ItemImages";
- this.Menu_ItemImages.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.M)));
- this.Menu_ItemImages.Size = new System.Drawing.Size(206, 22);
- this.Menu_ItemImages.Text = "Item Images";
- this.Menu_ItemImages.Click += new System.EventHandler(this.Menu_ItemImages_Click);
- //
// Editor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(404, 261);
+ this.ClientSize = new System.Drawing.Size(404, 311);
this.Controls.Add(this.TC_Editors);
this.Controls.Add(this.Menu_Editor);
this.Icon = global::NHSE.WinForms.Properties.Resources.icon;
@@ -854,6 +879,7 @@ private void InitializeComponent()
this.CM_EditMap.ResumeLayout(false);
this.Tab_Players.ResumeLayout(false);
this.Tab_Players.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.NUD_Poki)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.NUD_TotalNookMiles)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.NUD_StorageCount)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.NUD_PocketCount2)).EndInit();
@@ -940,6 +966,8 @@ private void InitializeComponent()
private System.Windows.Forms.Label L_WeatherSeed;
private System.Windows.Forms.NumericUpDown NUD_WeatherSeed;
private System.Windows.Forms.ToolStripMenuItem Menu_ItemImages;
+ private System.Windows.Forms.Label L_Poki;
+ private System.Windows.Forms.NumericUpDown NUD_Poki;
}
}
diff --git a/NHSE.WinForms/Editor.cs b/NHSE.WinForms/Editor.cs
index fd844f3..7dcd619 100644
--- a/NHSE.WinForms/Editor.cs
+++ b/NHSE.WinForms/Editor.cs
@@ -308,6 +308,15 @@ private void LoadPlayer(int index)
NUD_PocketCount2.Value = Math.Min(int.MaxValue, pers.BagCount);
NUD_StorageCount.Value = Math.Min(int.MaxValue, pers.ItemChestCount);
+ if (player.WhereAreN is not null)
+ {
+ NUD_Poki.Value = Math.Min(int.MaxValue, player.WhereAreN.Poki.Value);
+ }
+ else
+ {
+ L_Poki.Visible = NUD_Poki.Visible = false;
+ }
+
try
{
var photo = pers.GetPhotoData();
@@ -367,6 +376,11 @@ private void SavePlayer(int index)
pers.BagCount = (uint)NUD_PocketCount2.Value;
pers.ItemChestCount = (uint)NUD_StorageCount.Value;
+
+ if (player.WhereAreN is not null)
+ {
+ player.WhereAreN.Poki.Value = (uint)NUD_Poki.Value;
+ }
}
private void B_EditAchievements_Click(object sender, EventArgs e)