diff --git a/NHSE.Core/Structures/Villager/IVillager.cs b/NHSE.Core/Structures/Villager/IVillager.cs index 79c7ffa..04a5f18 100644 --- a/NHSE.Core/Structures/Villager/IVillager.cs +++ b/NHSE.Core/Structures/Villager/IVillager.cs @@ -25,6 +25,11 @@ public interface IVillager : IVillagerOrigin GSaveRoomFloorWall Room { get; set; } DesignPatternPRO Design { get; set; } + public byte DIYEndHour { get; set; } + public byte DIYEndMinute { get; set; } + public byte DIYEndSecond { get; set; } + public ushort DIYRecipeIndex { get; set; } + GSaveMemory GetMemory(int index); GSaveMemory[] GetMemories(); void SetMemory(GSaveMemory memory, int index); diff --git a/NHSE.Core/Structures/Villager/Villager1.cs b/NHSE.Core/Structures/Villager/Villager1.cs index 3839497..6dedbf3 100644 --- a/NHSE.Core/Structures/Villager/Villager1.cs +++ b/NHSE.Core/Structures/Villager/Villager1.cs @@ -116,6 +116,11 @@ public DesignPatternPRO Design set => value.Data.CopyTo(Data, 0x12128); } + public byte DIYEndHour { get => Data[0x129D1]; set => Data[0x129D1] = value; } + public byte DIYEndMinute { get => Data[0x129D2]; set => Data[0x129D2] = value; } + public byte DIYEndSecond { get => Data[0x129D3]; set => Data[0x129D3] = value; } + public ushort DIYRecipeIndex { get => Data.Slice(0x129D4, sizeof(ushort)).ToStructure(); set => value.ToBytes().CopyTo(Data, 0x129D4); } + public void SetFriendshipAll(byte value = byte.MaxValue) { for (int i = 0; i < PlayerMemoryCount; i++) diff --git a/NHSE.Core/Structures/Villager/Villager2.cs b/NHSE.Core/Structures/Villager/Villager2.cs index f6b9013..696c5f9 100644 --- a/NHSE.Core/Structures/Villager/Villager2.cs +++ b/NHSE.Core/Structures/Villager/Villager2.cs @@ -116,6 +116,11 @@ public DesignPatternPRO Design set => value.Data.CopyTo(Data, 0x128a8); } + public byte DIYEndHour { get => Data[0x13151]; set => Data[0x13151] = value; } + public byte DIYEndMinute { get => Data[0x13152]; set => Data[0x13152] = value; } + public byte DIYEndSecond { get => Data[0x13153]; set => Data[0x13153] = value; } + public ushort DIYRecipeIndex { get => Data.Slice(0x13154, sizeof(ushort)).ToStructure(); set => value.ToBytes().CopyTo(Data, 0x13154); } + public void SetFriendshipAll(byte value = byte.MaxValue) { for (int i = 0; i < PlayerMemoryCount; i++) diff --git a/NHSE.WinForms/Controls/VillagerEditor.Designer.cs b/NHSE.WinForms/Controls/VillagerEditor.Designer.cs index f433a01..e13bff1 100644 --- a/NHSE.WinForms/Controls/VillagerEditor.Designer.cs +++ b/NHSE.WinForms/Controls/VillagerEditor.Designer.cs @@ -57,6 +57,7 @@ private void InitializeComponent() this.NUD_Villager = new System.Windows.Forms.NumericUpDown(); this.B_EditHouses = new System.Windows.Forms.Button(); this.B_SetPhraseOriginal = new System.Windows.Forms.Button(); + this.B_EditDIYTimer = new System.Windows.Forms.ToolStripMenuItem(); this.CM_EditVillager.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.NUD_Variant)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.NUD_Species)).BeginInit(); @@ -104,10 +105,11 @@ private void InitializeComponent() this.B_EditVillagerRoom, this.B_EditVillagerDesign, this.B_EditVillagerPlayerMemories, + this.B_EditDIYTimer, this.TSS_toolStripSeparator1, this.B_MoveOutAllVillagers}); this.CM_EditVillager.Name = "CM_EditPlayer"; - this.CM_EditVillager.Size = new System.Drawing.Size(186, 114); + this.CM_EditVillager.Size = new System.Drawing.Size(186, 186); // // B_EditFurniture // @@ -144,6 +146,11 @@ private void InitializeComponent() this.B_EditVillagerPlayerMemories.Text = "Edit Player Memories"; this.B_EditVillagerPlayerMemories.Click += new System.EventHandler(this.B_EditVillagerPlayerMemories_Click); // + // TSS_toolStripSeparator1 + // + this.TSS_toolStripSeparator1.Name = "TSS_toolStripSeparator1"; + this.TSS_toolStripSeparator1.Size = new System.Drawing.Size(182, 6); + // // B_MoveOutAllVillagers // this.B_MoveOutAllVillagers.Name = "B_MoveOutAllVillagers"; @@ -321,6 +328,13 @@ private void InitializeComponent() this.B_SetPhraseOriginal.UseVisualStyleBackColor = true; this.B_SetPhraseOriginal.Click += new System.EventHandler(this.B_SetPhraseOriginal_Click); // + // B_EditDIYTimer + // + this.B_EditDIYTimer.Name = "B_EditDIYTimer"; + this.B_EditDIYTimer.Size = new System.Drawing.Size(185, 22); + this.B_EditDIYTimer.Text = "Edit DIY Timer"; + this.B_EditDIYTimer.Click += new System.EventHandler(this.B_EditDIYTimer_Click); + // // VillagerEditor // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -387,5 +401,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem B_MoveOutAllVillagers; private System.Windows.Forms.ToolStripMenuItem B_EditWear; private System.Windows.Forms.Button B_SetPhraseOriginal; + private System.Windows.Forms.ToolStripMenuItem B_EditDIYTimer; } } diff --git a/NHSE.WinForms/Controls/VillagerEditor.cs b/NHSE.WinForms/Controls/VillagerEditor.cs index 969e9ea..86e14f6 100644 --- a/NHSE.WinForms/Controls/VillagerEditor.cs +++ b/NHSE.WinForms/Controls/VillagerEditor.cs @@ -247,6 +247,14 @@ private void B_EditVillagerPlayerMemories_Click(object sender, EventArgs e) { } // editor saves our changes } + private void B_EditDIYTimer_Click(object sender, EventArgs e) + { + var v = Villagers[VillagerIndex]; + using var editor = new VillagerDIYTimerEditor(v); + if (editor.ShowDialog() == DialogResult.OK) + { } // editor saves our changes + } + private void B_MoveOutAllVillagers_Click(object sender, EventArgs e) { if (Loading) diff --git a/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.Designer.cs b/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.Designer.cs new file mode 100644 index 0000000..006e1df --- /dev/null +++ b/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.Designer.cs @@ -0,0 +1,144 @@ + +namespace NHSE.WinForms +{ + partial class VillagerDIYTimerEditor + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.CHK_Crafting = new System.Windows.Forms.CheckBox(); + this.DT_Time = new System.Windows.Forms.DateTimePicker(); + this.L_EndTime = new System.Windows.Forms.Label(); + this.L_Recipe = new System.Windows.Forms.Label(); + this.CB_Recipe = new System.Windows.Forms.ComboBox(); + this.B_Save = new System.Windows.Forms.Button(); + this.B_Cancel = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // CHK_Crafting + // + this.CHK_Crafting.AutoSize = true; + this.CHK_Crafting.CheckAlign = System.Drawing.ContentAlignment.MiddleRight; + this.CHK_Crafting.Location = new System.Drawing.Point(21, 13); + this.CHK_Crafting.Name = "CHK_Crafting"; + this.CHK_Crafting.Size = new System.Drawing.Size(78, 17); + this.CHK_Crafting.TabIndex = 1; + this.CHK_Crafting.Text = "Is crafting?"; + this.CHK_Crafting.UseVisualStyleBackColor = true; + this.CHK_Crafting.CheckedChanged += new System.EventHandler(this.CHK_Crafting_CheckedChanged); + // + // DT_Time + // + this.DT_Time.Format = System.Windows.Forms.DateTimePickerFormat.Time; + this.DT_Time.Location = new System.Drawing.Point(91, 38); + this.DT_Time.Name = "DT_Time"; + this.DT_Time.ShowUpDown = true; + this.DT_Time.Size = new System.Drawing.Size(78, 20); + this.DT_Time.TabIndex = 2; + this.DT_Time.ValueChanged += new System.EventHandler(this.DT_Time_ValueChanged); + // + // L_EndTime + // + this.L_EndTime.AutoSize = true; + this.L_EndTime.Location = new System.Drawing.Point(21, 41); + this.L_EndTime.Name = "L_EndTime"; + this.L_EndTime.Size = new System.Drawing.Size(68, 13); + this.L_EndTime.TabIndex = 3; + this.L_EndTime.Text = "Crafting until:"; + // + // L_Recipe + // + this.L_Recipe.AutoSize = true; + this.L_Recipe.Location = new System.Drawing.Point(20, 68); + this.L_Recipe.Name = "L_Recipe"; + this.L_Recipe.Size = new System.Drawing.Size(44, 13); + this.L_Recipe.TabIndex = 4; + this.L_Recipe.Text = "Recipe:"; + // + // CB_Recipe + // + this.CB_Recipe.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + this.CB_Recipe.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + this.CB_Recipe.DropDownWidth = 322; + this.CB_Recipe.FormattingEnabled = true; + this.CB_Recipe.Location = new System.Drawing.Point(65, 66); + this.CB_Recipe.Name = "CB_Recipe"; + this.CB_Recipe.Size = new System.Drawing.Size(160, 21); + this.CB_Recipe.TabIndex = 5; + this.CB_Recipe.SelectedIndexChanged += new System.EventHandler(this.CB_Recipe_SelectedIndexChanged); + // + // B_Save + // + this.B_Save.Location = new System.Drawing.Point(21, 100); + this.B_Save.Name = "B_Save"; + this.B_Save.Size = new System.Drawing.Size(92, 23); + this.B_Save.TabIndex = 6; + this.B_Save.Text = "Save"; + this.B_Save.UseVisualStyleBackColor = true; + this.B_Save.Click += new System.EventHandler(this.B_Save_Click); + // + // B_Cancel + // + this.B_Cancel.Location = new System.Drawing.Point(133, 100); + this.B_Cancel.Name = "B_Cancel"; + this.B_Cancel.Size = new System.Drawing.Size(92, 23); + this.B_Cancel.TabIndex = 7; + this.B_Cancel.Text = "Cancel"; + this.B_Cancel.UseVisualStyleBackColor = true; + this.B_Cancel.Click += new System.EventHandler(this.B_Cancel_Click); + // + // VillagerDIYTimerEditor + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(245, 142); + this.Controls.Add(this.B_Cancel); + this.Controls.Add(this.B_Save); + this.Controls.Add(this.CB_Recipe); + this.Controls.Add(this.L_Recipe); + this.Controls.Add(this.L_EndTime); + this.Controls.Add(this.DT_Time); + this.Controls.Add(this.CHK_Crafting); + this.Icon = global::NHSE.WinForms.Properties.Resources.icon; + this.Name = "VillagerDIYTimerEditor"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Villager DIY Editor"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.CheckBox CHK_Crafting; + private System.Windows.Forms.DateTimePicker DT_Time; + private System.Windows.Forms.Label L_EndTime; + private System.Windows.Forms.Label L_Recipe; + private System.Windows.Forms.ComboBox CB_Recipe; + private System.Windows.Forms.Button B_Save; + private System.Windows.Forms.Button B_Cancel; + } +} \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.cs b/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.cs new file mode 100644 index 0000000..f5d1b82 --- /dev/null +++ b/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.cs @@ -0,0 +1,79 @@ +using NHSE.Core; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace NHSE.WinForms +{ + public partial class VillagerDIYTimerEditor : Form + { + private readonly List Recipes = GameInfo.Strings.CreateItemDataSource(RecipeList.Recipes, false); + + private readonly IVillager Villager; + + private byte Hour, Minute, Second; + private ushort RecipeIndex; + + public VillagerDIYTimerEditor(IVillager v) + { + Villager = v; + Hour = Villager.DIYEndHour; + Minute = Villager.DIYEndMinute; + Second = Villager.DIYEndSecond; + + InitializeComponent(); + + // Both hour and minute will be 255 in most cases when villager is idling. + // If another villager's end time is earlier, this villager will not craft UNLESS the villager is crafting an "event" item, in which case it seems it will take priority. + bool idleState = Hour == byte.MaxValue || Minute == byte.MaxValue; + DT_Time.Value = idleState ? new DateTime(1970, 01, 01, 0, 0, 0) : new DateTime(1970, 01, 01, Hour, Minute, Second); + + CHK_Crafting.Checked = DT_Time.Enabled = !idleState; + + CB_Recipe.DisplayMember = nameof(ComboItem.Text); + CB_Recipe.ValueMember = nameof(ComboItem.Value); + CB_Recipe.DataSource = Recipes; + + RecipeIndex = Villager.DIYRecipeIndex; + CB_Recipe.SelectedValue = (int)RecipeIndex; + } + + private void CB_Recipe_SelectedIndexChanged(object sender, EventArgs e) + { + var val = WinFormsUtil.GetIndex((ComboBox)sender); + RecipeIndex = (ushort)Math.Max(0, Math.Min(ushort.MaxValue, val)); + } + + private void B_Cancel_Click(object sender, EventArgs e) => Close(); + + private void B_Save_Click(object sender, EventArgs e) + { + Villager.DIYEndHour = Hour; + Villager.DIYEndMinute = Minute; + Villager.DIYEndSecond = Second; + Villager.DIYRecipeIndex = RecipeIndex; + DialogResult = DialogResult.OK; + Close(); + } + + private void CHK_Crafting_CheckedChanged(object sender, EventArgs e) + { + Hour = CHK_Crafting.Checked ? (byte)DT_Time.Value.Hour : byte.MaxValue; + Minute = CHK_Crafting.Checked ? (byte)DT_Time.Value.Minute : byte.MaxValue; + DT_Time.Enabled = CHK_Crafting.Checked; + } + + private void DT_Time_ValueChanged(object sender, EventArgs e) + { + Hour = (byte)DT_Time.Value.Hour; + Minute = (byte)DT_Time.Value.Minute; + Second = (byte)DT_Time.Value.Second; + } + } +} diff --git a/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.resx b/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/NHSE.WinForms/Subforms/Villager/VillagerDIYTimerEditor.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file