From 2eb9a7773eb286d295e767dd10a5abc5a313f51b Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 9 Dec 2025 17:31:27 +0100 Subject: [PATCH] Added chest looter --- MosswartMassacre/MosswartMassacre.csproj | 154 +++++++++++- MosswartMassacre/PluginSettings.cs | 18 ++ MosswartMassacre/Utils.cs | 104 ++++++++ MosswartMassacre/Views/VVSTabbedMainView.cs | 252 +++++++++++++++++++- MosswartMassacre/packages.config | 50 +++- 5 files changed, 569 insertions(+), 9 deletions(-) diff --git a/MosswartMassacre/MosswartMassacre.csproj b/MosswartMassacre/MosswartMassacre.csproj index 93891ca..0c1df39 100644 --- a/MosswartMassacre/MosswartMassacre.csproj +++ b/MosswartMassacre/MosswartMassacre.csproj @@ -1,5 +1,6 @@ + Debug @@ -13,6 +14,8 @@ 8.0 512 true + + true @@ -35,9 +38,12 @@ - C:\Games\Decal Plugins\UtilityBelt\0Harmony.dll + ..\..\..\..\Documents\Decal Plugins\UtilityBelt\0Harmony.dll False + + ..\packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll + lib\Decal.Adapter.dll False @@ -68,21 +74,156 @@ ..\..\..\..\..\..\Program Files (x86)\Decal 3.0\.NET 4.0 PIA\Decal.Interop.D3DService.DLL False + + False + False + ..\..\..\..\..\..\Program Files (x86)\Decal 3.0\.NET 4.0 PIA\Decal.Interop.Input.DLL + False + + + ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll + True + True + ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll + True + True + + + + ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll + True + True + + + ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll + True + True + + + ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll + True + True + + + ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll + True + True + + + ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + True + True + + + + ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll + True + True + + + ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + True + True + + + ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll + True + True + + + ..\packages\System.Linq.4.3.0\lib\net463\System.Linq.dll + True + True + + + ..\packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll + True + True + + + ..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll + True + True + + + ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll + True + True + + + ..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll + True + True + + + ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + True + True + + + ..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll + True + True + + + ..\packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll + True + True + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll + True + True + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + ..\packages\System.Text.RegularExpressions.4.3.0\lib\net463\System.Text.RegularExpressions.dll + True + True + - + + ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll + True + True + False bin\Debug\utank2-i.dll @@ -186,6 +327,8 @@ True Resources.resx + + @@ -231,12 +374,13 @@ - + - This project references NuGet package(s) that are missing on this machine. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + diff --git a/MosswartMassacre/PluginSettings.cs b/MosswartMassacre/PluginSettings.cs index 03c5cac..de256e2 100644 --- a/MosswartMassacre/PluginSettings.cs +++ b/MosswartMassacre/PluginSettings.cs @@ -25,6 +25,7 @@ namespace MosswartMassacre private bool _useTabbedInterface = true; private string _vtankProfilesPath = ""; private bool _verboseLogging = false; + private ChestLooterSettings _chestLooterSettings = new ChestLooterSettings(); public static PluginSettings Instance => _instance ?? throw new InvalidOperationException("PluginSettings not initialized"); @@ -204,5 +205,22 @@ namespace MosswartMassacre get => _verboseLogging; set { _verboseLogging = value; Save(); } } + + public ChestLooterSettings ChestLooterSettings + { + get + { + if (_chestLooterSettings == null) + { + _chestLooterSettings = new ChestLooterSettings(); + } + return _chestLooterSettings; + } + set + { + _chestLooterSettings = value; + Save(); + } + } } } diff --git a/MosswartMassacre/Utils.cs b/MosswartMassacre/Utils.cs index 667c6aa..c6a7381 100644 --- a/MosswartMassacre/Utils.cs +++ b/MosswartMassacre/Utils.cs @@ -220,5 +220,109 @@ namespace MosswartMassacre int rawIcon = GetItemIcon(itemName); return rawIcon != 0 ? rawIcon + 0x6000000 : 0x6002D14; } + + /* ---------------------------------------------------------- + * 5) Chest Looter helper methods + * -------------------------------------------------------- */ + + /// + /// Calculate 3D distance from player to a world object + /// + /// World object ID + /// Distance in meters, or float.MaxValue if object is invalid + public static float GetDistanceToWorldObject(int objectId) + { + try + { + if (!CoreManager.Current.Actions.IsValidObject(objectId)) + return float.MaxValue; + + Vector3 playerPos = GetPlayerPosition(); + Vector3 objectPos = GetWorldObjectPosition(objectId); + + return Vector3.Distance(playerPos, objectPos); + } + catch + { + return float.MaxValue; + } + } + + /// + /// Find the closest chest with the specified name in the game world + /// + /// Name of the chest to find + /// WorldObject of the closest chest, or null if not found + public static WorldObject FindClosestChestByName(string chestName) + { + try + { + WorldObject closestChest = null; + float closestDistance = float.MaxValue; + + // Search all objects in WorldFilter + using (var objects = CoreManager.Current.WorldFilter.GetAll()) + { + foreach (WorldObject wo in objects) + { + // Check if this is a container (chest) + if (wo.ObjectClass != ObjectClass.Container) + continue; + + // Check if name matches (case-insensitive, partial match allowed) + if (!wo.Name.Contains(chestName) && + !string.Equals(wo.Name, chestName, StringComparison.OrdinalIgnoreCase)) + continue; + + // Calculate distance + float distance = GetDistanceToWorldObject(wo.Id); + + // Update closest if this is nearer + if (distance < closestDistance) + { + closestDistance = distance; + closestChest = wo; + } + } + } + + return closestChest; + } + catch + { + return null; + } + } + + /// + /// Find a key in the player's inventory by name + /// + /// Name of the key to find + /// WorldObject of the key, or null if not found + public static WorldObject FindKeyInInventory(string keyName) + { + try + { + foreach (WorldObject wo in CoreManager.Current.WorldFilter.GetInventory()) + { + // Check if this is a key + if (wo.ObjectClass != ObjectClass.Key) + continue; + + // Check if name matches (case-insensitive, partial match allowed) + if (wo.Name.Contains(keyName) || + string.Equals(wo.Name, keyName, StringComparison.OrdinalIgnoreCase)) + { + return wo; + } + } + + return null; + } + catch + { + return null; + } + } } } diff --git a/MosswartMassacre/Views/VVSTabbedMainView.cs b/MosswartMassacre/Views/VVSTabbedMainView.cs index bbaf284..b11234d 100644 --- a/MosswartMassacre/Views/VVSTabbedMainView.cs +++ b/MosswartMassacre/Views/VVSTabbedMainView.cs @@ -61,7 +61,18 @@ namespace MosswartMassacre.Views private HudButton btnOpenFlagTracker; // lblFlagTrackerStatus removed - not present in XML #endregion - + + #region Chest Looter Tab Controls + private HudTextBox txtChestName; + private HudTextBox txtKeyName; + private HudButton btnSetChest; + private HudButton btnSetKey; + private HudButton btnStartLooter; + private HudButton btnStopLooter; + private HudCheckBox chkEnableChests; + private HudStaticText lblLooterStatus; + #endregion + #region Statistics Tracking private double bestHourlyKills = 0; private DateTime sessionStartTime; @@ -140,6 +151,7 @@ namespace MosswartMassacre.Views InitializeStatisticsTabControls(); InitializeNavigationTabControls(); InitializeFlagTrackerTabControls(); + InitializeChestLooterTabControls(); // Initialize the base view and set initial position Initialize(); @@ -293,7 +305,7 @@ namespace MosswartMassacre.Views { // Flag Tracker tab controls btnOpenFlagTracker = GetControl("btnOpenFlagTracker"); - + // Hook up Flag Tracker events if (btnOpenFlagTracker != null) btnOpenFlagTracker.Hit += OnOpenFlagTrackerClick; @@ -303,6 +315,41 @@ namespace MosswartMassacre.Views PluginCore.WriteToChat($"Error initializing flag tracker controls: {ex.Message}"); } } + + private void InitializeChestLooterTabControls() + { + try + { + // Chest Looter tab controls + txtChestName = GetControl("txtChestName"); + txtKeyName = GetControl("txtKeyName"); + btnSetChest = GetControl("btnSetChest"); + btnSetKey = GetControl("btnSetKey"); + btnStartLooter = GetControl("btnStartLooter"); + btnStopLooter = GetControl("btnStopLooter"); + chkEnableChests = GetControl("chkEnableChests"); + lblLooterStatus = GetControl("lblLooterStatus"); + + // Hook up Chest Looter events + if (btnSetChest != null) + btnSetChest.Hit += OnSetChestClick; + if (btnSetKey != null) + btnSetKey.Hit += OnSetKeyClick; + if (btnStartLooter != null) + btnStartLooter.Hit += OnStartLooterClick; + if (btnStopLooter != null) + btnStopLooter.Hit += OnStopLooterClick; + if (chkEnableChests != null) + chkEnableChests.Change += OnEnableChestsChanged; + + // Load current settings + LoadChestLooterSettings(); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"Error initializing chest looter controls: {ex.Message}"); + } + } #endregion #region Event Handlers - Settings Tab @@ -610,6 +657,207 @@ namespace MosswartMassacre.Views } #endregion + #region Event Handlers - Chest Looter Tab + + private void OnSetChestClick(object sender, EventArgs e) + { + try + { + var core = Decal.Adapter.CoreManager.Current; + var chest = core.WorldFilter[core.Actions.CurrentSelection]; + if (chest == null) + { + PluginCore.WriteToChat("[ChestLooter] No chest selected"); + return; + } + + if (chest.ObjectClass != Decal.Adapter.Wrappers.ObjectClass.Container) + { + PluginCore.WriteToChat("[ChestLooter] Selected object is not a container"); + return; + } + + txtChestName.Text = chest.Name; + if (PluginCore.chestLooter != null) + { + PluginCore.chestLooter.SetChestName(chest.Name); + } + PluginCore.WriteToChat($"[ChestLooter] Chest set to: {chest.Name}"); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"[ChestLooter] Error setting chest: {ex.Message}"); + } + } + + private void OnSetKeyClick(object sender, EventArgs e) + { + try + { + var core = Decal.Adapter.CoreManager.Current; + var key = core.WorldFilter[core.Actions.CurrentSelection]; + if (key == null) + { + PluginCore.WriteToChat("[ChestLooter] No key selected"); + return; + } + + if (key.ObjectClass != Decal.Adapter.Wrappers.ObjectClass.Key) + { + PluginCore.WriteToChat("[ChestLooter] Selected object is not a key"); + return; + } + + txtKeyName.Text = key.Name; + if (PluginCore.chestLooter != null) + { + PluginCore.chestLooter.SetKeyName(key.Name); + } + PluginCore.WriteToChat($"[ChestLooter] Key set to: {key.Name}"); + } + catch (Exception ex) + { + PluginCore.WriteToChat($"[ChestLooter] Error setting key: {ex.Message}"); + } + } + + private void OnStartLooterClick(object sender, EventArgs e) + { + try + { + if (PluginCore.chestLooter == null) + { + PluginCore.WriteToChat("[ChestLooter] Chest looter not initialized"); + return; + } + + string chestName = txtChestName?.Text ?? ""; + string keyName = txtKeyName?.Text ?? ""; + + if (string.IsNullOrEmpty(chestName)) + { + PluginCore.WriteToChat("[ChestLooter] Please set chest name first"); + return; + } + + if (string.IsNullOrEmpty(keyName)) + { + PluginCore.WriteToChat("[ChestLooter] Please set key name first"); + return; + } + + bool started = PluginCore.chestLooter.StartByName(chestName, keyName); + if (started) + { + UpdateLooterStatus("Starting..."); + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"[ChestLooter] Error starting looter: {ex.Message}"); + } + } + + private void OnStopLooterClick(object sender, EventArgs e) + { + try + { + if (PluginCore.chestLooter != null) + { + PluginCore.chestLooter.Stop(); + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"[ChestLooter] Error stopping looter: {ex.Message}"); + } + } + + private void OnEnableChestsChanged(object sender, EventArgs e) + { + try + { + var settings = PluginSettings.Instance; + if (settings?.ChestLooterSettings != null && chkEnableChests != null) + { + settings.ChestLooterSettings.EnableChests = chkEnableChests.Checked; + PluginSettings.Save(); + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"[ChestLooter] Error changing enable chests: {ex.Message}"); + } + } + + private void LoadChestLooterSettings() + { + try + { + var settings = PluginSettings.Instance?.ChestLooterSettings; + if (settings != null) + { + if (txtChestName != null) + txtChestName.Text = settings.ChestName ?? ""; + if (txtKeyName != null) + txtKeyName.Text = settings.KeyName ?? ""; + if (chkEnableChests != null) + chkEnableChests.Checked = settings.EnableChests; + } + } + catch (Exception ex) + { + PluginCore.WriteToChat($"[ChestLooter] Error loading settings: {ex.Message}"); + } + } + + private void UpdateLooterStatus(string status) + { + try + { + if (lblLooterStatus != null) + { + lblLooterStatus.Text = $"Status: {status}"; + } + } + catch { } + } + + public static void UpdateChestLooterStatus(string status) + { + try + { + if (instance != null) + { + instance.UpdateLooterStatus(status); + } + } + catch { } + } + + /// + /// Update chest/key text boxes from settings (called when set via command line) + /// + public static void RefreshChestLooterUI() + { + try + { + if (instance == null) return; + + var settings = PluginSettings.Instance?.ChestLooterSettings; + if (settings != null) + { + if (instance.txtChestName != null) + instance.txtChestName.Text = settings.ChestName ?? ""; + if (instance.txtKeyName != null) + instance.txtKeyName.Text = settings.KeyName ?? ""; + } + } + catch { } + } + + #endregion + #region Event Handlers - Navigation Tab private void OnNavVisualizationEnabledChanged(object sender, EventArgs e) { diff --git a/MosswartMassacre/packages.config b/MosswartMassacre/packages.config index bcad711..89d0b78 100644 --- a/MosswartMassacre/packages.config +++ b/MosswartMassacre/packages.config @@ -1,7 +1,53 @@  - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file