From 1db185151d17d73a464e23a2193116e7510cc9e9 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 4 Apr 2020 20:57:25 -0700 Subject: [PATCH] Add automatic read/write items for all pocket items (1-40) (#51) Decentralizes pocket injection logic from SysBotUI so that other auto-injectors can be passed in (future? like terrain/overworld items). Adds validation to not modify items if the pocket data doesn't have the expected layout. Closes #47 by implementing things in a more abstract & extendable way. Thanks @jfmherokiller for the example implementation which served as an inspiration! --- NHSE.Injection/Injector/AutoInjector.cs | 45 ++++++++ NHSE.Injection/Injector/IDataInjector.cs | 14 +++ NHSE.Injection/Injector/IRAMReadWriter.cs | 9 ++ NHSE.Injection/Injector/InjectionResult.cs | 10 ++ NHSE.Injection/NHSE.Injection.csproj | 4 + NHSE.Injection/PocketInjector.cs | 102 ++++++++++++++++++ NHSE.Injection/{ => SysBot}/Decoder.cs | 0 NHSE.Injection/{ => SysBot}/SwitchButton.cs | 0 NHSE.Injection/{ => SysBot}/SwitchCommand.cs | 0 NHSE.Injection/{ => SysBot}/SwitchStick.cs | 0 NHSE.Injection/{ => SysBot}/SysBot.cs | 4 +- NHSE.WinForms/Controls/ItemGridEditor.cs | 6 ++ NHSE.WinForms/Editor.cs | 3 +- .../Subforms/PlayerItemEditor.Designer.cs | 1 + NHSE.WinForms/Subforms/PlayerItemEditor.cs | 31 +++--- .../Subforms/SysBot/SysBotController.cs | 2 +- .../Subforms/SysBot/SysBotUI.Designer.cs | 40 ++++++- NHSE.WinForms/Subforms/SysBot/SysBotUI.cs | 52 +++++---- NHSE.WinForms/Subforms/SysBot/SysBotUI.resx | 3 + 19 files changed, 288 insertions(+), 38 deletions(-) create mode 100644 NHSE.Injection/Injector/AutoInjector.cs create mode 100644 NHSE.Injection/Injector/IDataInjector.cs create mode 100644 NHSE.Injection/Injector/IRAMReadWriter.cs create mode 100644 NHSE.Injection/Injector/InjectionResult.cs create mode 100644 NHSE.Injection/PocketInjector.cs rename NHSE.Injection/{ => SysBot}/Decoder.cs (100%) rename NHSE.Injection/{ => SysBot}/SwitchButton.cs (100%) rename NHSE.Injection/{ => SysBot}/SwitchCommand.cs (100%) rename NHSE.Injection/{ => SysBot}/SwitchStick.cs (100%) rename NHSE.Injection/{ => SysBot}/SysBot.cs (95%) diff --git a/NHSE.Injection/Injector/AutoInjector.cs b/NHSE.Injection/Injector/AutoInjector.cs new file mode 100644 index 0000000..1b155ea --- /dev/null +++ b/NHSE.Injection/Injector/AutoInjector.cs @@ -0,0 +1,45 @@ +using System; + +namespace NHSE.Injection +{ + public class AutoInjector + { + private readonly IDataInjector Injector; + private readonly Action AfterRead; + private readonly Action AfterWrite; + + public bool AutoInjectEnabled { private get; set; } + + public AutoInjector(IDataInjector inj, Action read, Action write) + { + Injector = inj; + AfterRead = read; + AfterWrite = write; + } + + public void Validate() => Injector.Validate(); + + public InjectionResult Read(bool force = false) + { + if ((!AutoInjectEnabled && !force) || !Injector.Connected) + return InjectionResult.Skipped; + var result = Injector.Read(); + AfterRead(result); + return result; + } + + public InjectionResult Write(bool force = false) + { + if ((!AutoInjectEnabled && !force) || !Injector.Connected) + return InjectionResult.Skipped; + var result = Injector.Write(); + AfterWrite(result); + return result; + } + + public void SetWriteOffset(in uint offset) + { + Injector.WriteOffset = offset; + } + } +} \ No newline at end of file diff --git a/NHSE.Injection/Injector/IDataInjector.cs b/NHSE.Injection/Injector/IDataInjector.cs new file mode 100644 index 0000000..9c054e3 --- /dev/null +++ b/NHSE.Injection/Injector/IDataInjector.cs @@ -0,0 +1,14 @@ +namespace NHSE.Injection +{ + public interface IDataInjector + { + bool ReadValidate(out byte[] data); + InjectionResult Read(); + InjectionResult Write(); + + bool Validate(); + bool Validate(byte[] data); + uint WriteOffset { set; } + bool Connected { get; } + } +} \ No newline at end of file diff --git a/NHSE.Injection/Injector/IRAMReadWriter.cs b/NHSE.Injection/Injector/IRAMReadWriter.cs new file mode 100644 index 0000000..f0a52ff --- /dev/null +++ b/NHSE.Injection/Injector/IRAMReadWriter.cs @@ -0,0 +1,9 @@ +namespace NHSE.Injection +{ + public interface IRAMReadWriter + { + bool Connected { get; } + byte[] ReadBytes(uint offset, int length); + void WriteBytes(byte[] data, uint offset); + } +} \ No newline at end of file diff --git a/NHSE.Injection/Injector/InjectionResult.cs b/NHSE.Injection/Injector/InjectionResult.cs new file mode 100644 index 0000000..3001522 --- /dev/null +++ b/NHSE.Injection/Injector/InjectionResult.cs @@ -0,0 +1,10 @@ +namespace NHSE.Injection +{ + public enum InjectionResult + { + Skipped, + Success, + Fail, + Same, + } +} \ No newline at end of file diff --git a/NHSE.Injection/NHSE.Injection.csproj b/NHSE.Injection/NHSE.Injection.csproj index 3419541..477e3a3 100644 --- a/NHSE.Injection/NHSE.Injection.csproj +++ b/NHSE.Injection/NHSE.Injection.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/NHSE.Injection/PocketInjector.cs b/NHSE.Injection/PocketInjector.cs new file mode 100644 index 0000000..0291445 --- /dev/null +++ b/NHSE.Injection/PocketInjector.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NHSE.Core; + +namespace NHSE.Injection +{ + public class PocketInjector : IDataInjector + { + private readonly IReadOnlyList Items; + private readonly IRAMReadWriter Bot; + public bool Connected => Bot.Connected; + + public uint WriteOffset { private get; set; } + + public PocketInjector(IReadOnlyList items, IRAMReadWriter bot) + { + Items = items; + Bot = bot; + } + + private const int pocket = Item.SIZE * 20; + private const int size = (pocket * 2) + 0x18; + private const int shift = -0x18 - (Item.SIZE * 20); + + private uint DataOffset => (uint)(WriteOffset + shift); + + public bool ReadValidate(out byte[] data) + { + data = Bot.ReadBytes(DataOffset, size); + return Validate(data); + } + + private byte[]? LastData; + + public InjectionResult Read() + { + if (!ReadValidate(out var data)) + return InjectionResult.Fail; + + if (LastData?.SequenceEqual(data) == true) + return InjectionResult.Same; + + var pocket2 = Items.Take(20).ToArray(); + var pocket1 = Items.Skip(20).ToArray(); + var p1 = Item.GetArray(data.Slice(0, pocket)); + var p2 = Item.GetArray(data.Slice(pocket + 0x18, pocket)); + + for (int i = 0; i < pocket1.Length; i++) + pocket1[i].CopyFrom(p1[i]); + + for (int i = 0; i < pocket2.Length; i++) + pocket2[i].CopyFrom(p2[i]); + + LastData = data; + + return InjectionResult.Success; + } + + public InjectionResult Write() + { + if (!ReadValidate(out var data)) + return InjectionResult.Fail; + + var orig = (byte[])data.Clone(); + + var pocket2 = Items.Take(20).ToArray(); + var pocket1 = Items.Skip(20).ToArray(); + var p1 = Item.SetArray(pocket1); + var p2 = Item.SetArray(pocket2); + + p1.CopyTo(data, 0); + p2.CopyTo(data, pocket + 0x18); + + if (data.SequenceEqual(orig)) + return InjectionResult.Same; + + Bot.WriteBytes(data, DataOffset); + + LastData = data; + + return InjectionResult.Success; + } + + public bool Validate() => ReadValidate(out _); + + public bool Validate(byte[] data) + { + if (BitConverter.ToUInt32(data, pocket) > 20) // pouch21-39 count + return false; + + for (int i = 4; i < 0x18; i += 4) + { + var val = BitConverter.ToInt32(data, pocket + i); + if (val != -1) + return false; + } + + return true; + } + } +} diff --git a/NHSE.Injection/Decoder.cs b/NHSE.Injection/SysBot/Decoder.cs similarity index 100% rename from NHSE.Injection/Decoder.cs rename to NHSE.Injection/SysBot/Decoder.cs diff --git a/NHSE.Injection/SwitchButton.cs b/NHSE.Injection/SysBot/SwitchButton.cs similarity index 100% rename from NHSE.Injection/SwitchButton.cs rename to NHSE.Injection/SysBot/SwitchButton.cs diff --git a/NHSE.Injection/SwitchCommand.cs b/NHSE.Injection/SysBot/SwitchCommand.cs similarity index 100% rename from NHSE.Injection/SwitchCommand.cs rename to NHSE.Injection/SysBot/SwitchCommand.cs diff --git a/NHSE.Injection/SwitchStick.cs b/NHSE.Injection/SysBot/SwitchStick.cs similarity index 100% rename from NHSE.Injection/SwitchStick.cs rename to NHSE.Injection/SysBot/SwitchStick.cs diff --git a/NHSE.Injection/SysBot.cs b/NHSE.Injection/SysBot/SysBot.cs similarity index 95% rename from NHSE.Injection/SysBot.cs rename to NHSE.Injection/SysBot/SysBot.cs index 323abae..ee94efe 100644 --- a/NHSE.Injection/SysBot.cs +++ b/NHSE.Injection/SysBot/SysBot.cs @@ -3,12 +3,12 @@ namespace NHSE.Injection { - public class SysBot + public class SysBot : IRAMReadWriter { public string IP = "192.168.1.65"; public int Port = 6000; public Socket Connection = new Socket(SocketType.Stream, ProtocolType.Tcp); - public bool Connected; + public bool Connected { get; private set; } private readonly object _sync = new object(); diff --git a/NHSE.WinForms/Controls/ItemGridEditor.cs b/NHSE.WinForms/Controls/ItemGridEditor.cs index c0895ce..0c1e1d9 100644 --- a/NHSE.WinForms/Controls/ItemGridEditor.cs +++ b/NHSE.WinForms/Controls/ItemGridEditor.cs @@ -16,6 +16,8 @@ public partial class ItemGridEditor : UserControl private int Count => Items.Count; private int Page; private int ItemsPerPage; + public Action? ItemChanged { private get; set; } + private void ItemUpdated() => ItemChanged?.Invoke(); public ItemGridEditor(ItemEditor editor, IReadOnlyList items) { @@ -122,6 +124,7 @@ private void ClickSet(object sender, EventArgs e) var index = SlotPictureBoxes.IndexOf(pb); var item = SetItem(index); pb.BackgroundImage = Sprites.GetImage(item, L_ItemName.Font); + ItemUpdated(); } private void ClickDelete(object sender, EventArgs e) @@ -133,6 +136,7 @@ private void ClickDelete(object sender, EventArgs e) var item = GetItem(index); item.Delete(); pb.BackgroundImage = Sprites.GetImage(item, L_ItemName.Font); + ItemUpdated(); } private void ClickClone(object sender, EventArgs e) @@ -149,6 +153,7 @@ private void ClickClone(object sender, EventArgs e) var dest = GetItem(i); dest.CopyFrom(item); SlotPictureBoxes[i].BackgroundImage = Sprites.GetImage(item, L_ItemName.Font); + ItemUpdated(); } System.Media.SystemSounds.Asterisk.Play(); } @@ -200,6 +205,7 @@ public void LoadItems() var item = GetItem(i); SlotPictureBoxes[i].BackgroundImage = Sprites.GetImage(item, L_ItemName.Font); } + ItemUpdated(); } private void B_Clear_Click(object sender, EventArgs e) diff --git a/NHSE.WinForms/Editor.cs b/NHSE.WinForms/Editor.cs index b43dcb3..56cf484 100644 --- a/NHSE.WinForms/Editor.cs +++ b/NHSE.WinForms/Editor.cs @@ -129,8 +129,7 @@ private void B_EditPlayerItems_Click(object sender, EventArgs e) var p1 = pers.Pocket1; var p2 = pers.Pocket2; var items = p2.Concat(p1).ToArray(); - int sys = p1.Count; // disjointed 20-20 - using var editor = new PlayerItemEditor(items, 10, 4, sysbot: sys); + using var editor = new PlayerItemEditor(items, 10, 4, sysbot: true); if (editor.ShowDialog() != DialogResult.OK) return; diff --git a/NHSE.WinForms/Subforms/PlayerItemEditor.Designer.cs b/NHSE.WinForms/Subforms/PlayerItemEditor.Designer.cs index 513f31c..ba0c48b 100644 --- a/NHSE.WinForms/Subforms/PlayerItemEditor.Designer.cs +++ b/NHSE.WinForms/Subforms/PlayerItemEditor.Designer.cs @@ -18,6 +18,7 @@ protected override void Dispose(bool disposing) components.Dispose(); } base.Dispose(disposing); + ItemGrid.Dispose(); } #region Windows Form Designer generated code diff --git a/NHSE.WinForms/Subforms/PlayerItemEditor.cs b/NHSE.WinForms/Subforms/PlayerItemEditor.cs index 66093fd..6ce6de5 100644 --- a/NHSE.WinForms/Subforms/PlayerItemEditor.cs +++ b/NHSE.WinForms/Subforms/PlayerItemEditor.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; -using System.Linq; using System.Windows.Forms; using NHSE.Core; using NHSE.Injection; @@ -12,14 +12,14 @@ public partial class PlayerItemEditor : Form where T : Item { private readonly IReadOnlyList Items; private readonly Action LoadItems; - private readonly int SysBotLength; + private readonly ItemGridEditor ItemGrid; - public PlayerItemEditor(IReadOnlyList array, int width, int height, int sysbot = 0) + public PlayerItemEditor(IReadOnlyList array, int width, int height, bool sysbot = false) { InitializeComponent(); Items = array; - var Editor = new ItemGridEditor(ItemEditor, Items) {Dock = DockStyle.Fill}; + var Editor = ItemGrid = new ItemGridEditor(ItemEditor, Items) {Dock = DockStyle.Fill}; Editor.InitializeGrid(width, height); PAN_Items.Controls.Add(Editor); @@ -27,7 +27,7 @@ public PlayerItemEditor(IReadOnlyList array, int width, int height, int sysbo Editor.LoadItems(); DialogResult = DialogResult.Cancel; LoadItems = () => Editor.LoadItems(); - B_Inject.Visible = (SysBotLength = sysbot) > 0; + B_Inject.Visible = sysbot; } private void B_Cancel_Click(object sender, EventArgs e) => Close(); @@ -79,17 +79,24 @@ private void B_Inject_Click(object sender, EventArgs e) return; } - byte[] Write() => Items.Take(SysBotLength).SelectMany(z => z.ToBytesClass()).ToArray(); - void Read(byte[] data) + void AfterRead(InjectionResult r) { - var items = Item.GetArray(data); - for (int i = 0; i < items.Length && i < Items.Count; i++) - Items[i].CopyFrom(items[i]); - LoadItems(); + if (r == InjectionResult.Success) + LoadItems(); + } + + static void AfterWrite(InjectionResult r) + { + Debug.WriteLine($"Write result: {r}"); System.Media.SystemSounds.Asterisk.Play(); } - var sysbot = new SysBotUI(Read, Write, InjectionType.Pouch); + var sb = new SysBotController(InjectionType.Pouch); + var pockInject = new PocketInjector(Items, sb.Bot); + var ai = new AutoInjector(pockInject, AfterRead, AfterWrite); + + ItemGrid.ItemChanged = () => ai.Write(true); + var sysbot = new SysBotUI(ai, sb); sysbot.Show(); } } diff --git a/NHSE.WinForms/Subforms/SysBot/SysBotController.cs b/NHSE.WinForms/Subforms/SysBot/SysBotController.cs index 5444fb9..f437bb1 100644 --- a/NHSE.WinForms/Subforms/SysBot/SysBotController.cs +++ b/NHSE.WinForms/Subforms/SysBot/SysBotController.cs @@ -10,7 +10,7 @@ public class SysBotController public SysBotController(InjectionType type) => Type = type; private readonly InjectionType Type; - private readonly SysBot Bot = new SysBot(); + public readonly SysBot Bot = new SysBot(); private readonly Settings Settings = Settings.Default; public string IP => Settings.SysBotIP; diff --git a/NHSE.WinForms/Subforms/SysBot/SysBotUI.Designer.cs b/NHSE.WinForms/Subforms/SysBot/SysBotUI.Designer.cs index f9fa45e..ae30774 100644 --- a/NHSE.WinForms/Subforms/SysBot/SysBotUI.Designer.cs +++ b/NHSE.WinForms/Subforms/SysBot/SysBotUI.Designer.cs @@ -28,16 +28,20 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); this.B_Connect = new System.Windows.Forms.Button(); this.L_Port = new System.Windows.Forms.Label(); this.TB_Port = new System.Windows.Forms.TextBox(); this.L_IP = new System.Windows.Forms.Label(); this.TB_IP = new System.Windows.Forms.TextBox(); this.GB_Inject = new System.Windows.Forms.GroupBox(); + this.CHK_AutoRead = new System.Windows.Forms.CheckBox(); + this.CHK_AutoWrite = new System.Windows.Forms.CheckBox(); this.RamOffset = new System.Windows.Forms.TextBox(); this.L_Offset = new System.Windows.Forms.Label(); this.B_ReadCurrent = new System.Windows.Forms.Button(); this.B_WriteCurrent = new System.Windows.Forms.Button(); + this.TIM_Interval = new System.Windows.Forms.Timer(this.components); this.GB_Inject.SuspendLayout(); this.SuspendLayout(); // @@ -89,6 +93,8 @@ private void InitializeComponent() // // GB_Inject // + this.GB_Inject.Controls.Add(this.CHK_AutoRead); + this.GB_Inject.Controls.Add(this.CHK_AutoWrite); this.GB_Inject.Controls.Add(this.RamOffset); this.GB_Inject.Controls.Add(this.L_Offset); this.GB_Inject.Controls.Add(this.B_ReadCurrent); @@ -96,11 +102,33 @@ private void InitializeComponent() this.GB_Inject.Enabled = false; this.GB_Inject.Location = new System.Drawing.Point(16, 66); this.GB_Inject.Name = "GB_Inject"; - this.GB_Inject.Size = new System.Drawing.Size(149, 74); + this.GB_Inject.Size = new System.Drawing.Size(149, 119); this.GB_Inject.TabIndex = 13; this.GB_Inject.TabStop = false; this.GB_Inject.Text = "Injector"; // + // CHK_AutoRead + // + this.CHK_AutoRead.AutoSize = true; + this.CHK_AutoRead.Location = new System.Drawing.Point(18, 93); + this.CHK_AutoRead.Name = "CHK_AutoRead"; + this.CHK_AutoRead.Size = new System.Drawing.Size(74, 17); + this.CHK_AutoRead.TabIndex = 22; + this.CHK_AutoRead.Text = "AutoRead"; + this.CHK_AutoRead.UseVisualStyleBackColor = true; + this.CHK_AutoRead.CheckedChanged += new System.EventHandler(this.CHK_AutoRead_CheckedChanged); + // + // CHK_AutoWrite + // + this.CHK_AutoWrite.AutoSize = true; + this.CHK_AutoWrite.Location = new System.Drawing.Point(18, 70); + this.CHK_AutoWrite.Name = "CHK_AutoWrite"; + this.CHK_AutoWrite.Size = new System.Drawing.Size(73, 17); + this.CHK_AutoWrite.TabIndex = 21; + this.CHK_AutoWrite.Text = "AutoWrite"; + this.CHK_AutoWrite.UseVisualStyleBackColor = true; + this.CHK_AutoWrite.CheckedChanged += new System.EventHandler(this.CHK_AutoWrite_CheckedChanged); + // // RamOffset // this.RamOffset.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); @@ -110,6 +138,7 @@ private void InitializeComponent() this.RamOffset.Size = new System.Drawing.Size(63, 20); this.RamOffset.TabIndex = 20; this.RamOffset.Text = "AC3B90C0"; + this.RamOffset.TextChanged += new System.EventHandler(this.RamOffset_TextChanged); // // L_Offset // @@ -140,11 +169,15 @@ private void InitializeComponent() this.B_WriteCurrent.UseVisualStyleBackColor = true; this.B_WriteCurrent.Click += new System.EventHandler(this.B_WriteCurrent_Click); // + // TIM_Interval + // + this.TIM_Interval.Interval = 5000; + // // SysBotUI // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(184, 151); + this.ClientSize = new System.Drawing.Size(184, 197); this.Controls.Add(this.GB_Inject); this.Controls.Add(this.B_Connect); this.Controls.Add(this.L_Port); @@ -177,5 +210,8 @@ private void InitializeComponent() private System.Windows.Forms.Button B_WriteCurrent; private System.Windows.Forms.TextBox RamOffset; private System.Windows.Forms.Label L_Offset; + private System.Windows.Forms.CheckBox CHK_AutoWrite; + private System.Windows.Forms.CheckBox CHK_AutoRead; + private System.Windows.Forms.Timer TIM_Interval; } } \ No newline at end of file diff --git a/NHSE.WinForms/Subforms/SysBot/SysBotUI.cs b/NHSE.WinForms/Subforms/SysBot/SysBotUI.cs index 1afe3eb..aa2b7bb 100644 --- a/NHSE.WinForms/Subforms/SysBot/SysBotUI.cs +++ b/NHSE.WinForms/Subforms/SysBot/SysBotUI.cs @@ -7,22 +7,25 @@ namespace NHSE.WinForms { public partial class SysBotUI : Form { - private readonly Func ByteFetch; - private readonly Action ByteSet; + private readonly AutoInjector Injector; private readonly SysBotController Bot; - public SysBotUI(Action read, Func write, InjectionType type) + public SysBotUI(AutoInjector injector, SysBotController c) { InitializeComponent(); - Bot = new SysBotController(type); - ByteFetch = write; - ByteSet = read; - RamOffset.Text = Bot.GetDefaultOffset().ToString("X8"); + Bot = c; + Injector = injector; + + var offset = Bot.GetDefaultOffset(); + Injector.SetWriteOffset(offset); + RamOffset.Text = offset.ToString("X8"); TB_IP.Text = Bot.IP; TB_Port.Text = Bot.Port; Bot.PopPrompt(); + + TIM_Interval.Tick += (s, e) => injector.Read(); } private void B_Connect_Click(object sender, EventArgs e) @@ -41,10 +44,13 @@ private void B_WriteCurrent_Click(object sender, EventArgs e) return; } + Injector.SetWriteOffset(offset); + try { - var data = ByteFetch(); - Bot.WriteBytes(data, offset); + var result = Injector.Write(true); + if (result != InjectionResult.Success) + WinFormsUtil.Alert(result.ToString()); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) @@ -56,18 +62,11 @@ private void B_WriteCurrent_Click(object sender, EventArgs e) private void B_ReadCurrent_Click(object sender, EventArgs e) { - var offset = StringUtil.GetHexValue(RamOffset.Text); - if (offset == 0) - { - WinFormsUtil.Error("Incorrect hex offset."); - return; - } - try { - var data = ByteFetch(); - var result = Bot.ReadBytes(offset, data.Length); - ByteSet(result); + var result = Injector.Read(true); + if (result != InjectionResult.Success) + WinFormsUtil.Alert(result.ToString()); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) @@ -76,5 +75,20 @@ private void B_ReadCurrent_Click(object sender, EventArgs e) WinFormsUtil.Error(ex.Message); } } + + private void CHK_AutoWrite_CheckedChanged(object sender, EventArgs e) => Injector.AutoInjectEnabled = CHK_AutoWrite.Checked; + private void CHK_AutoRead_CheckedChanged(object sender, EventArgs e) => TIM_Interval.Enabled = CHK_AutoRead.Checked; + + private void RamOffset_TextChanged(object sender, EventArgs e) + { + var offset = StringUtil.GetHexValue(RamOffset.Text); + if (offset == 0) + { + WinFormsUtil.Error("Incorrect hex offset."); + return; + } + + Injector.SetWriteOffset(offset); + } } } diff --git a/NHSE.WinForms/Subforms/SysBot/SysBotUI.resx b/NHSE.WinForms/Subforms/SysBot/SysBotUI.resx index 1af7de1..5af2064 100644 --- a/NHSE.WinForms/Subforms/SysBot/SysBotUI.resx +++ b/NHSE.WinForms/Subforms/SysBot/SysBotUI.resx @@ -117,4 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file