diff --git a/MosswartMassacre/CharacterStats.cs b/MosswartMassacre/CharacterStats.cs
index 4c8b42e..30918de 100644
--- a/MosswartMassacre/CharacterStats.cs
+++ b/MosswartMassacre/CharacterStats.cs
@@ -26,6 +26,8 @@ namespace MosswartMassacre
public static class CharacterStats
{
+ private static IPluginLogger _logger;
+
// Cached allegiance data (populated from network messages)
private static string allegianceName;
private static int allegianceSize;
@@ -44,8 +46,9 @@ namespace MosswartMassacre
///
/// Reset all cached data. Call on plugin init.
///
- internal static void Init()
+ internal static void Init(IPluginLogger logger = null)
{
+ _logger = logger;
allegianceName = null;
allegianceSize = 0;
followers = 0;
@@ -112,7 +115,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[CharStats] Allegiance processing error: {ex.Message}");
+ _logger?.Log($"[CharStats] Allegiance processing error: {ex.Message}");
}
}
@@ -142,7 +145,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[CharStats] Property processing error: {ex.Message}");
+ _logger?.Log($"[CharStats] Property processing error: {ex.Message}");
}
}
@@ -169,7 +172,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[CharStats] Int64 property update error: {ex.Message}");
+ _logger?.Log($"[CharStats] Int64 property update error: {ex.Message}");
}
}
@@ -186,7 +189,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[CharStats] Title processing error: {ex.Message}");
+ _logger?.Log($"[CharStats] Title processing error: {ex.Message}");
}
}
@@ -201,7 +204,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[CharStats] Set title error: {ex.Message}");
+ _logger?.Log($"[CharStats] Set title error: {ex.Message}");
}
}
@@ -329,7 +332,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[CharStats] Error collecting stats: {ex.Message}");
+ _logger?.Log($"[CharStats] Error collecting stats: {ex.Message}");
}
}
}
diff --git a/MosswartMassacre/IPluginLogger.cs b/MosswartMassacre/IPluginLogger.cs
new file mode 100644
index 0000000..c9d4157
--- /dev/null
+++ b/MosswartMassacre/IPluginLogger.cs
@@ -0,0 +1,11 @@
+namespace MosswartMassacre
+{
+ ///
+ /// Interface for writing messages to the game chat window.
+ /// Eliminates direct PluginCore.WriteToChat() dependencies from manager classes.
+ ///
+ public interface IPluginLogger
+ {
+ void Log(string message);
+ }
+}
diff --git a/MosswartMassacre/KillTracker.cs b/MosswartMassacre/KillTracker.cs
new file mode 100644
index 0000000..0541f51
--- /dev/null
+++ b/MosswartMassacre/KillTracker.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Text.RegularExpressions;
+using System.Timers;
+
+namespace MosswartMassacre
+{
+ ///
+ /// Tracks kills, deaths, and kill rate calculations.
+ /// Owns the 1-second stats update timer.
+ ///
+ internal class KillTracker
+ {
+ private readonly IPluginLogger _logger;
+ private readonly Action _onStatsUpdated;
+ private readonly Action _onElapsedUpdated;
+
+ private int _totalKills;
+ private int _sessionDeaths;
+ private int _totalDeaths;
+ private double _killsPer5Min;
+ private double _killsPerHour;
+ private DateTime _lastKillTime = DateTime.Now;
+ private DateTime _statsStartTime = DateTime.Now;
+ private Timer _updateTimer;
+
+ // Kill message patterns — all 35+ patterns preserved exactly
+ private static readonly string[] KillPatterns = new string[]
+ {
+ @"^You flatten (?.+)'s body with the force of your assault!$",
+ @"^You bring (?.+) to a fiery end!$",
+ @"^You beat (?.+) to a lifeless pulp!$",
+ @"^You smite (?.+) mightily!$",
+ @"^You obliterate (?.+)!$",
+ @"^You run (?.+) through!$",
+ @"^You reduce (?.+) to a sizzling, oozing mass!$",
+ @"^You knock (?.+) into next Morningthaw!$",
+ @"^You split (?.+) apart!$",
+ @"^You cleave (?.+) in twain!$",
+ @"^You slay (?.+) viciously enough to impart death several times over!$",
+ @"^You reduce (?.+) to a drained, twisted corpse!$",
+ @"^Your killing blow nearly turns (?.+) inside-out!$",
+ @"^Your attack stops (?.+) cold!$",
+ @"^Your lightning coruscates over (?.+)'s mortal remains!$",
+ @"^Your assault sends (?.+) to an icy death!$",
+ @"^You killed (?.+)!$",
+ @"^The thunder of crushing (?.+) is followed by the deafening silence of death!$",
+ @"^The deadly force of your attack is so strong that (?.+)'s ancestors feel it!$",
+ @"^(?.+)'s seared corpse smolders before you!$",
+ @"^(?.+) is reduced to cinders!$",
+ @"^(?.+) is shattered by your assault!$",
+ @"^(?.+) catches your attack, with dire consequences!$",
+ @"^(?.+) is utterly destroyed by your attack!$",
+ @"^(?.+) suffers a frozen fate!$",
+ @"^(?.+)'s perforated corpse falls before you!$",
+ @"^(?.+) is fatally punctured!$",
+ @"^(?.+)'s death is preceded by a sharp, stabbing pain!$",
+ @"^(?.+) is torn to ribbons by your assault!$",
+ @"^(?.+) is liquified by your attack!$",
+ @"^(?.+)'s last strength dissolves before you!$",
+ @"^Electricity tears (?.+) apart!$",
+ @"^Blistered by lightning, (?.+) falls!$",
+ @"^(?.+)'s last strength withers before you!$",
+ @"^(?.+) is dessicated by your attack!$",
+ @"^(?.+) is incinerated by your assault!$"
+ };
+
+ internal int TotalKills => _totalKills;
+ internal double KillsPerHour => _killsPerHour;
+ internal double KillsPer5Min => _killsPer5Min;
+ internal int SessionDeaths => _sessionDeaths;
+ internal int TotalDeaths => _totalDeaths;
+ internal DateTime StatsStartTime => _statsStartTime;
+ internal DateTime LastKillTime => _lastKillTime;
+ internal int RareCount { get; set; }
+
+ /// Logger for chat output
+ /// Callback(totalKills, killsPer5Min, killsPerHour) for UI updates
+ /// Callback(elapsed) for UI elapsed time updates
+ internal KillTracker(IPluginLogger logger, Action onStatsUpdated, Action onElapsedUpdated)
+ {
+ _logger = logger;
+ _onStatsUpdated = onStatsUpdated;
+ _onElapsedUpdated = onElapsedUpdated;
+ }
+
+ internal void Start()
+ {
+ _updateTimer = new Timer(Constants.StatsUpdateIntervalMs);
+ _updateTimer.Elapsed += UpdateStats;
+ _updateTimer.Start();
+ }
+
+ internal void Stop()
+ {
+ if (_updateTimer != null)
+ {
+ _updateTimer.Stop();
+ _updateTimer.Dispose();
+ _updateTimer = null;
+ }
+ }
+
+ internal bool CheckForKill(string text)
+ {
+ if (IsKilledByMeMessage(text))
+ {
+ _totalKills++;
+ _lastKillTime = DateTime.Now;
+ CalculateKillsPerInterval();
+ _onStatsUpdated?.Invoke(_totalKills, _killsPer5Min, _killsPerHour);
+ return true;
+ }
+ return false;
+ }
+
+ internal void OnDeath()
+ {
+ _sessionDeaths++;
+ }
+
+ internal void SetTotalDeaths(int totalDeaths)
+ {
+ _totalDeaths = totalDeaths;
+ }
+
+ internal void RestartStats()
+ {
+ _totalKills = 0;
+ RareCount = 0;
+ _sessionDeaths = 0;
+ _statsStartTime = DateTime.Now;
+ _killsPer5Min = 0;
+ _killsPerHour = 0;
+
+ _logger?.Log($"Stats have been reset. Session deaths: {_sessionDeaths}, Total deaths: {_totalDeaths}");
+ _onStatsUpdated?.Invoke(_totalKills, _killsPer5Min, _killsPerHour);
+ }
+
+ private void UpdateStats(object sender, ElapsedEventArgs e)
+ {
+ try
+ {
+ TimeSpan elapsed = DateTime.Now - _statsStartTime;
+ _onElapsedUpdated?.Invoke(elapsed);
+
+ CalculateKillsPerInterval();
+ _onStatsUpdated?.Invoke(_totalKills, _killsPer5Min, _killsPerHour);
+ }
+ catch (Exception ex)
+ {
+ _logger?.Log("Error updating stats: " + ex.Message);
+ }
+ }
+
+ private void CalculateKillsPerInterval()
+ {
+ double minutesElapsed = (DateTime.Now - _statsStartTime).TotalMinutes;
+
+ if (minutesElapsed > 0)
+ {
+ _killsPer5Min = (_totalKills / minutesElapsed) * 5;
+ _killsPerHour = (_totalKills / minutesElapsed) * 60;
+ }
+ }
+
+ private bool IsKilledByMeMessage(string text)
+ {
+ foreach (string pattern in KillPatterns)
+ {
+ if (Regex.IsMatch(text, pattern))
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/MosswartMassacre/MosswartMassacre.csproj b/MosswartMassacre/MosswartMassacre.csproj
index 8dad1ed..e3c0829 100644
--- a/MosswartMassacre/MosswartMassacre.csproj
+++ b/MosswartMassacre/MosswartMassacre.csproj
@@ -306,6 +306,8 @@
+
+
diff --git a/MosswartMassacre/PluginCore.cs b/MosswartMassacre/PluginCore.cs
index 602bf30..2179753 100644
--- a/MosswartMassacre/PluginCore.cs
+++ b/MosswartMassacre/PluginCore.cs
@@ -18,7 +18,7 @@ using Mag.Shared.Constants;
namespace MosswartMassacre
{
[FriendlyName("Mosswart Massacre")]
- public class PluginCore : PluginBase
+ public class PluginCore : PluginBase, IPluginLogger
{
// Hot Reload Support Properties
private static string _assemblyDirectory = null;
@@ -47,21 +47,21 @@ namespace MosswartMassacre
public static bool IsHotReload { get; set; }
internal static PluginHost MyHost;
- internal static int totalKills = 0;
internal static int rareCount = 0;
- internal static int sessionDeaths = 0; // Deaths this session
- internal static int totalDeaths = 0; // Total deaths from character
internal static int cachedPrismaticCount = 0; // Cached Prismatic Taper count
internal static int lastPrismaticCount = 0; // For delta calculation
// Track taper items and their containers for accurate release detection
private static readonly Dictionary trackedTaperContainers = new Dictionary();
private static readonly Dictionary lastKnownStackSizes = new Dictionary();
- internal static DateTime lastKillTime = DateTime.Now;
- internal static double killsPer5Min = 0;
- internal static double killsPerHour = 0;
- internal static DateTime statsStartTime = DateTime.Now;
- internal static Timer updateTimer;
+ // Bridge properties for WebSocket telemetry until IGameStats migration (Phase 5)
+ private static KillTracker _staticKillTracker;
+ internal static int totalKills => _staticKillTracker?.TotalKills ?? 0;
+ internal static double killsPerHour => _staticKillTracker?.KillsPerHour ?? 0;
+ internal static int sessionDeaths => _staticKillTracker?.SessionDeaths ?? 0;
+ internal static int totalDeaths => _staticKillTracker?.TotalDeaths ?? 0;
+ internal static DateTime statsStartTime => _staticKillTracker?.StatsStartTime ?? DateTime.Now;
+ internal static DateTime lastKillTime => _staticKillTracker?.LastKillTime ?? DateTime.Now;
private static Timer vitalsTimer;
private static System.Windows.Forms.Timer commandTimer;
private static Timer characterStatsTimer;
@@ -127,7 +127,8 @@ namespace MosswartMassacre
private static DateTime _lastSent = DateTime.MinValue;
private static readonly Queue _chatQueue = new Queue();
- // Command routing
+ // Managers
+ private KillTracker _killTracker;
private CommandRouter _commandRouter;
protected override void Startup()
@@ -186,10 +187,13 @@ namespace MosswartMassacre
// Initialize VVS view after character login
ViewManager.ViewInit();
- // Initialize the timer
- updateTimer = new Timer(Constants.StatsUpdateIntervalMs);
- updateTimer.Elapsed += UpdateStats;
- updateTimer.Start();
+ // Initialize kill tracker (owns the 1-sec stats timer)
+ _killTracker = new KillTracker(
+ this,
+ (kills, per5, perHr) => ViewManager.UpdateKillStats(kills, per5, perHr),
+ elapsed => ViewManager.UpdateElapsedTime(elapsed));
+ _staticKillTracker = _killTracker;
+ _killTracker.Start();
// Initialize vitals streaming timer
vitalsTimer = new Timer(Constants.VitalsUpdateIntervalMs);
@@ -207,13 +211,15 @@ namespace MosswartMassacre
// Initialize character stats and hook ServerDispatch early
// 0x0013 (character properties with luminance) fires DURING login,
// BEFORE LoginComplete — must hook here to catch it
- CharacterStats.Init();
+ CharacterStats.Init(this);
CoreManager.Current.EchoFilter.ServerDispatch += EchoFilter_ServerDispatch;
// Enable TLS1.2
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
//Enable vTank interface
vTank.Enable();
+ // Set logger for WebSocket
+ WebSocket.SetLogger(this);
//lyssna på commands
WebSocket.OnServerCommand += HandleServerCommand;
//starta inventory. Hanterar subscriptions i den med
@@ -263,13 +269,8 @@ namespace MosswartMassacre
// Unsubscribe from server dispatch
CoreManager.Current.EchoFilter.ServerDispatch -= EchoFilter_ServerDispatch;
- // Stop and dispose of the timers
- if (updateTimer != null)
- {
- updateTimer.Stop();
- updateTimer.Dispose();
- updateTimer = null;
- }
+ // Stop kill tracker
+ _killTracker?.Stop();
if (vitalsTimer != null)
{
@@ -390,8 +391,7 @@ namespace MosswartMassacre
}
// Initialize death tracking
- totalDeaths = CoreManager.Current.CharacterFilter.GetCharProperty((int)IntValueKey.NumDeaths);
- sessionDeaths = 0;
+ _killTracker.SetTotalDeaths(CoreManager.Current.CharacterFilter.GetCharProperty((int)IntValueKey.NumDeaths));
// Initialize cached Prismatic Taper count
InitializePrismaticTaperCount();
@@ -604,8 +604,7 @@ namespace MosswartMassacre
}
// 6. Reinitialize death tracking
- totalDeaths = CoreManager.Current.CharacterFilter.GetCharProperty((int)IntValueKey.NumDeaths);
- // Don't reset sessionDeaths - keep the current session count
+ _killTracker?.SetTotalDeaths(CoreManager.Current.CharacterFilter.GetCharProperty((int)IntValueKey.NumDeaths));
// 7. Reinitialize cached Prismatic Taper count
InitializePrismaticTaperCount();
@@ -995,8 +994,8 @@ namespace MosswartMassacre
private void OnCharacterDeath(object sender, Decal.Adapter.Wrappers.DeathEventArgs e)
{
- sessionDeaths++;
- totalDeaths = CoreManager.Current.CharacterFilter.GetCharProperty((int)IntValueKey.NumDeaths);
+ _killTracker.OnDeath();
+ _killTracker.SetTotalDeaths(CoreManager.Current.CharacterFilter.GetCharProperty((int)IntValueKey.NumDeaths));
}
private void HandleServerCommand(CommandEnvelope env)
@@ -1038,18 +1037,13 @@ namespace MosswartMassacre
try
{
- if (IsKilledByMeMessage(e.Text))
- {
- totalKills++;
- lastKillTime = DateTime.Now;
- CalculateKillsPerInterval();
- ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
- }
+ _killTracker.CheckForKill(e.Text);
if (IsRareDiscoveryMessage(e.Text, out string rareText))
{
- rareCount++;
- ViewManager.UpdateRareCount(rareCount);
+ _killTracker.RareCount++;
+ rareCount = _killTracker.RareCount; // sync static for now
+ ViewManager.UpdateRareCount(_killTracker.RareCount);
if (RareMetaEnabled)
{
@@ -1063,8 +1057,8 @@ namespace MosswartMassacre
if (e.Color == 18 && e.Text.EndsWith("!report\""))
{
- TimeSpan elapsed = DateTime.Now - statsStartTime;
- string reportMessage = $"Total Kills: {totalKills}, Kills per Hour: {killsPerHour:F2}, Elapsed Time: {elapsed:dd\\.hh\\:mm\\:ss}, Rares Found: {rareCount}";
+ TimeSpan elapsed = DateTime.Now - _killTracker.StatsStartTime;
+ string reportMessage = $"Total Kills: {_killTracker.TotalKills}, Kills per Hour: {_killTracker.KillsPerHour:F2}, Elapsed Time: {elapsed:dd\\.hh\\:mm\\:ss}, Rares Found: {_killTracker.RareCount}";
WriteToChat($"[Mosswart Massacre] Reporting to allegiance: {reportMessage}");
MyHost.Actions.InvokeChatParser($"/a {reportMessage}");
}
@@ -1098,24 +1092,6 @@ namespace MosswartMassacre
}
}
- private void UpdateStats(object sender, ElapsedEventArgs e)
- {
- try
- {
- // Update the elapsed time
- TimeSpan elapsed = DateTime.Now - statsStartTime;
- ViewManager.UpdateElapsedTime(elapsed);
-
- // Recalculate kill rates
- CalculateKillsPerInterval();
- ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
-
- }
- catch (Exception ex)
- {
- WriteToChat("Error updating stats: " + ex.Message);
- }
- }
private static void SendVitalsUpdate(object sender, ElapsedEventArgs e)
{
@@ -1211,67 +1187,6 @@ namespace MosswartMassacre
}
}
- private void CalculateKillsPerInterval()
- {
- double minutesElapsed = (DateTime.Now - statsStartTime).TotalMinutes;
-
- if (minutesElapsed > 0)
- {
- killsPer5Min = (totalKills / minutesElapsed) * 5;
- killsPerHour = (totalKills / minutesElapsed) * 60;
- }
- }
-
- private bool IsKilledByMeMessage(string text)
- {
- string[] killPatterns = new string[]
- {
- @"^You flatten (?.+)'s body with the force of your assault!$",
- @"^You bring (?.+) to a fiery end!$",
- @"^You beat (?.+) to a lifeless pulp!$",
- @"^You smite (?.+) mightily!$",
- @"^You obliterate (?.+)!$",
- @"^You run (?.+) through!$",
- @"^You reduce (?.+) to a sizzling, oozing mass!$",
- @"^You knock (?.+) into next Morningthaw!$",
- @"^You split (?.+) apart!$",
- @"^You cleave (?.+) in twain!$",
- @"^You slay (?.+) viciously enough to impart death several times over!$",
- @"^You reduce (?.+) to a drained, twisted corpse!$",
- @"^Your killing blow nearly turns (?.+) inside-out!$",
- @"^Your attack stops (?.+) cold!$",
- @"^Your lightning coruscates over (?.+)'s mortal remains!$",
- @"^Your assault sends (?.+) to an icy death!$",
- @"^You killed (?.+)!$",
- @"^The thunder of crushing (?.+) is followed by the deafening silence of death!$",
- @"^The deadly force of your attack is so strong that (?.+)'s ancestors feel it!$",
- @"^(?.+)'s seared corpse smolders before you!$",
- @"^(?.+) is reduced to cinders!$",
- @"^(?.+) is shattered by your assault!$",
- @"^(?.+) catches your attack, with dire consequences!$",
- @"^(?.+) is utterly destroyed by your attack!$",
- @"^(?.+) suffers a frozen fate!$",
- @"^(?.+)'s perforated corpse falls before you!$",
- @"^(?.+) is fatally punctured!$",
- @"^(?.+)'s death is preceded by a sharp, stabbing pain!$",
- @"^(?.+) is torn to ribbons by your assault!$",
- @"^(?.+) is liquified by your attack!$",
- @"^(?.+)'s last strength dissolves before you!$",
- @"^Electricity tears (?.+) apart!$",
- @"^Blistered by lightning, (?.+) falls!$",
- @"^(?.+)'s last strength withers before you!$",
- @"^(?.+) is dessicated by your attack!$",
- @"^(?.+) is incinerated by your assault!$"
- };
-
- foreach (string pattern in killPatterns)
- {
- if (Regex.IsMatch(text, pattern))
- return true;
- }
-
- return false;
- }
private bool IsRareDiscoveryMessage(string text, out string rareTextOnly)
{
rareTextOnly = null;
@@ -1316,18 +1231,13 @@ namespace MosswartMassacre
}
}
}
+
+ void IPluginLogger.Log(string message) => WriteToChat(message);
+
public static void RestartStats()
{
- totalKills = 0;
- rareCount = 0;
- sessionDeaths = 0; // Reset session deaths only
- statsStartTime = DateTime.Now;
- killsPer5Min = 0;
- killsPerHour = 0;
-
- WriteToChat($"Stats have been reset. Session deaths: {sessionDeaths}, Total deaths: {totalDeaths}");
- ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
- ViewManager.UpdateRareCount(rareCount);
+ _staticKillTracker?.RestartStats();
+ ViewManager.UpdateRareCount(_staticKillTracker?.RareCount ?? 0);
}
public static void ToggleRareMeta()
{
@@ -1396,8 +1306,8 @@ namespace MosswartMassacre
_commandRouter.Register("report", args =>
{
- TimeSpan elapsed = DateTime.Now - statsStartTime;
- string reportMessage = $"Total Kills: {totalKills}, Kills per Hour: {killsPerHour:F2}, Elapsed Time: {elapsed:dd\\.hh\\:mm\\:ss}, Rares Found: {rareCount}, Session Deaths: {sessionDeaths}, Total Deaths: {totalDeaths}";
+ TimeSpan elapsed = DateTime.Now - _killTracker.StatsStartTime;
+ string reportMessage = $"Total Kills: {_killTracker.TotalKills}, Kills per Hour: {_killTracker.KillsPerHour:F2}, Elapsed Time: {elapsed:dd\\.hh\\:mm\\:ss}, Rares Found: {_killTracker.RareCount}, Session Deaths: {_killTracker.SessionDeaths}, Total Deaths: {_killTracker.TotalDeaths}";
WriteToChat(reportMessage);
}, "Show current stats");
@@ -1656,17 +1566,17 @@ namespace MosswartMassacre
try
{
WriteToChat("=== Death Tracking Statistics ===");
- WriteToChat($"Session Deaths: {sessionDeaths}");
- WriteToChat($"Total Deaths: {totalDeaths}");
+ WriteToChat($"Session Deaths: {_killTracker.SessionDeaths}");
+ WriteToChat($"Total Deaths: {_killTracker.TotalDeaths}");
int currentCharDeaths = CoreManager.Current.CharacterFilter.GetCharProperty((int)IntValueKey.NumDeaths);
WriteToChat($"Character Property NumDeaths: {currentCharDeaths}");
- if (currentCharDeaths != totalDeaths)
+ if (currentCharDeaths != _killTracker.TotalDeaths)
{
WriteToChat($"[WARNING] Death count sync issue detected!");
- WriteToChat($"Updating totalDeaths from {totalDeaths} to {currentCharDeaths}");
- totalDeaths = currentCharDeaths;
+ WriteToChat($"Updating totalDeaths from {_killTracker.TotalDeaths} to {currentCharDeaths}");
+ _killTracker.SetTotalDeaths(currentCharDeaths);
}
WriteToChat("Death tracking is active and will increment on character death.");
@@ -1682,14 +1592,14 @@ namespace MosswartMassacre
try
{
WriteToChat("=== Manual Death Test ===");
- WriteToChat($"Current sessionDeaths variable: {sessionDeaths}");
- WriteToChat($"Current totalDeaths variable: {totalDeaths}");
+ WriteToChat($"Current sessionDeaths variable: {_killTracker.SessionDeaths}");
+ WriteToChat($"Current totalDeaths variable: {_killTracker.TotalDeaths}");
int currentCharDeaths = CoreManager.Current.CharacterFilter.GetCharProperty((int)IntValueKey.NumDeaths);
WriteToChat($"Character Property NumDeaths (43): {currentCharDeaths}");
- sessionDeaths++;
- WriteToChat($"Manually incremented sessionDeaths to: {sessionDeaths}");
+ _killTracker.OnDeath();
+ WriteToChat($"Manually incremented sessionDeaths to: {_killTracker.SessionDeaths}");
WriteToChat("Note: This doesn't simulate a real death, just tests the tracking variables.");
WriteToChat($"Death event subscription check:");
diff --git a/MosswartMassacre/WebSocket.cs b/MosswartMassacre/WebSocket.cs
index 288b74d..e9c96e0 100644
--- a/MosswartMassacre/WebSocket.cs
+++ b/MosswartMassacre/WebSocket.cs
@@ -35,6 +35,7 @@ namespace MosswartMassacre
private const string SharedSecret = "your_shared_secret";
private const int IntervalSec = 5;
private static string SessionId = "";
+ private static IPluginLogger _logger;
// ─── cached prismatic taper count ─── (now handled by PluginCore event system)
@@ -51,13 +52,15 @@ namespace MosswartMassacre
// ─── public API ─────────────────────────────
+ public static void SetLogger(IPluginLogger logger) => _logger = logger;
+
public static void Start()
{
if (_enabled) return;
_enabled = true;
_cts = new CancellationTokenSource();
- PluginCore.WriteToChat("[WebSocket] connecting…");
+ _logger?.Log("[WebSocket] connecting…");
_ = Task.Run(ConnectAndLoopAsync);
}
@@ -72,7 +75,7 @@ namespace MosswartMassacre
_ws?.Dispose();
_ws = null;
- PluginCore.WriteToChat("[WebSocket] DISABLED");
+ _logger?.Log("[WebSocket] DISABLED");
}
// ─── connect / receive / telemetry loop ──────────────────────
@@ -87,7 +90,7 @@ namespace MosswartMassacre
_ws = new ClientWebSocket();
_ws.Options.SetRequestHeader("X-Plugin-Secret", SharedSecret);
await _ws.ConnectAsync(WsEndpoint, _cts.Token);
- PluginCore.WriteToChat("[WebSocket] CONNECTED");
+ _logger?.Log("[WebSocket] CONNECTED");
SessionId = $"{CoreManager.Current.CharacterFilter.Name}-{DateTime.UtcNow:yyyyMMdd-HHmmss}";
// ─── Register this socket under our character name ───
@@ -98,7 +101,7 @@ namespace MosswartMassacre
};
var regJson = JsonConvert.SerializeObject(registerEnvelope);
await SendEncodedAsync(regJson, _cts.Token);
- PluginCore.WriteToChat("[WebSocket] REGISTERED");
+ _logger?.Log("[WebSocket] REGISTERED");
var buffer = new byte[4096];
@@ -118,7 +121,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[WebSocket] receive error: {ex.Message}");
+ _logger?.Log($"[WebSocket] receive error: {ex.Message}");
break;
}
@@ -151,7 +154,7 @@ namespace MosswartMassacre
});
// 5) Inline telemetry loop
- PluginCore.WriteToChat("[WebSocket] Starting telemetry loop");
+ _logger?.Log("[WebSocket] Starting telemetry loop");
while (_ws.State == WebSocketState.Open && !_cts.Token.IsCancellationRequested)
{
try
@@ -161,7 +164,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[WebSocket] Telemetry failed: {ex.Message}");
+ _logger?.Log($"[WebSocket] Telemetry failed: {ex.Message}");
break; // Exit telemetry loop on failure
}
@@ -171,30 +174,30 @@ namespace MosswartMassacre
}
catch (OperationCanceledException)
{
- PluginCore.WriteToChat("[WebSocket] Telemetry loop cancelled");
+ _logger?.Log("[WebSocket] Telemetry loop cancelled");
break;
}
}
// Log why telemetry loop exited
- PluginCore.WriteToChat($"[WebSocket] Telemetry loop ended - State: {_ws?.State}, Cancelled: {_cts.Token.IsCancellationRequested}");
+ _logger?.Log($"[WebSocket] Telemetry loop ended - State: {_ws?.State}, Cancelled: {_cts.Token.IsCancellationRequested}");
// Wait for receive loop to finish
await receiveTask;
}
catch (OperationCanceledException)
{
- PluginCore.WriteToChat("[WebSocket] Connection cancelled");
+ _logger?.Log("[WebSocket] Connection cancelled");
break;
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[WebSocket] Connection error: {ex.Message}");
+ _logger?.Log($"[WebSocket] Connection error: {ex.Message}");
}
finally
{
var finalState = _ws?.State.ToString() ?? "null";
- PluginCore.WriteToChat($"[WebSocket] Cleaning up connection - Final state: {finalState}");
+ _logger?.Log($"[WebSocket] Cleaning up connection - Final state: {finalState}");
_ws?.Abort();
_ws?.Dispose();
_ws = null;
@@ -203,7 +206,7 @@ namespace MosswartMassacre
// Pause before reconnecting
if (_enabled)
{
- PluginCore.WriteToChat("[WebSocket] Reconnecting in 2 seconds...");
+ _logger?.Log("[WebSocket] Reconnecting in 2 seconds...");
try { await Task.Delay(2000, CancellationToken.None); } catch { }
}
}
@@ -334,7 +337,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"[WebSocket] Send error: {ex.Message}");
+ _logger?.Log($"[WebSocket] Send error: {ex.Message}");
_ws?.Abort();
_ws?.Dispose();
_ws = null;