diff --git a/MosswartMassacre/CharacterStats.cs b/MosswartMassacre/CharacterStats.cs
deleted file mode 100644
index 6d16f03..0000000
--- a/MosswartMassacre/CharacterStats.cs
+++ /dev/null
@@ -1,309 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Runtime.InteropServices;
-using Decal.Adapter;
-using Decal.Adapter.Wrappers;
-using Newtonsoft.Json;
-
-namespace MosswartMassacre
-{
- public struct AllegianceInfoRecord
- {
- public string name;
- public int rank;
- public int race;
- public int gender;
-
- public AllegianceInfoRecord(string _name, int _rank, int _race, int _gender)
- {
- name = _name;
- rank = _rank;
- race = _race;
- gender = _gender;
- }
- }
-
- public static class CharacterStats
- {
- // Cached allegiance data (populated from network messages)
- private static string allegianceName;
- private static int allegianceSize;
- private static int followers;
- private static AllegianceInfoRecord monarch;
- private static AllegianceInfoRecord patron;
- private static int allegianceRank;
-
- // Cached luminance data (populated from network messages)
- private static long luminanceEarned = -1;
- private static long luminanceTotal = -1;
-
- // Cached title data (populated from network messages)
- private static int currentTitle = -1;
-
- ///
- /// Reset all cached data. Call on plugin init.
- ///
- internal static void Init()
- {
- allegianceName = null;
- allegianceSize = 0;
- followers = 0;
- monarch = new AllegianceInfoRecord();
- patron = new AllegianceInfoRecord();
- allegianceRank = 0;
- luminanceEarned = -1;
- luminanceTotal = -1;
- currentTitle = -1;
- }
-
- ///
- /// Process game event 0x0020 - Allegiance info.
- /// Extracts monarch, patron, rank, followers from the allegiance tree.
- /// Reference: TreeStats Character.cs:642-745
- ///
- internal static void ProcessAllegianceInfoMessage(NetworkMessageEventArgs e)
- {
- try
- {
- allegianceName = e.Message.Value("allegianceName");
- allegianceSize = e.Message.Value("allegianceSize");
- followers = e.Message.Value("followers");
-
- monarch = new AllegianceInfoRecord();
- patron = new AllegianceInfoRecord();
-
- MessageStruct records = e.Message.Struct("records");
- int currentId = CoreManager.Current.CharacterFilter.Id;
- var parentMap = new Dictionary();
- var recordMap = new Dictionary();
-
- for (int i = 0; i < records.Count; i++)
- {
- var record = records.Struct(i);
- int charId = record.Value("character");
- int treeParent = record.Value("treeParent");
-
- parentMap[charId] = treeParent;
- recordMap[charId] = new AllegianceInfoRecord(
- record.Value("name"),
- record.Value("rank"),
- record.Value("race"),
- record.Value("gender"));
-
- // Monarch: treeParent <= 1
- if (treeParent <= 1)
- {
- monarch = recordMap[charId];
- }
- }
-
- // Patron: parent of current character
- if (parentMap.ContainsKey(currentId) && recordMap.ContainsKey(parentMap[currentId]))
- {
- patron = recordMap[parentMap[currentId]];
- }
-
- // Our rank from the record
- if (recordMap.ContainsKey(currentId))
- {
- allegianceRank = recordMap[currentId].rank;
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"[CharStats] Allegiance processing error: {ex.Message}");
- }
- }
-
- ///
- /// Process game event 0x0013 - Character property data.
- /// Extracts luminance from QWORD keys 6 and 7.
- /// Reference: TreeStats Character.cs:582-640
- ///
- internal static void ProcessCharacterPropertyData(NetworkMessageEventArgs e)
- {
- try
- {
- MessageStruct props = e.Message.Struct("properties");
- MessageStruct qwords = props.Struct("qwords");
-
- for (int i = 0; i < qwords.Count; i++)
- {
- var tmpStruct = qwords.Struct(i);
- long key = tmpStruct.Value("key");
- long value = tmpStruct.Value("value");
-
- if (key == 6) // AvailableLuminance
- luminanceEarned = value;
- else if (key == 7) // MaximumLuminance
- luminanceTotal = value;
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"[CharStats] Property processing error: {ex.Message}");
- }
- }
-
- ///
- /// Process game event 0x0029 - Titles list.
- /// Extracts current title ID.
- /// Reference: TreeStats Character.cs:551-580
- ///
- internal static void ProcessTitlesMessage(NetworkMessageEventArgs e)
- {
- try
- {
- currentTitle = e.Message.Value("current");
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"[CharStats] Title processing error: {ex.Message}");
- }
- }
-
- ///
- /// Process game event 0x002b - Set title (when player changes title).
- ///
- internal static void ProcessSetTitleMessage(NetworkMessageEventArgs e)
- {
- try
- {
- currentTitle = e.Message.Value("title");
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"[CharStats] Set title error: {ex.Message}");
- }
- }
-
- ///
- /// Collect all character data and send via WebSocket.
- /// Called on login (after delay) and every 10 minutes.
- ///
- internal static void CollectAndSend()
- {
- if (!PluginCore.WebSocketEnabled)
- return;
-
- try
- {
- var cf = CoreManager.Current.CharacterFilter;
- var culture = new CultureInfo("en-US");
-
- // --- Attributes ---
- var attributes = new Dictionary();
- foreach (var attr in cf.Attributes)
- {
- attributes[attr.Name.ToLower()] = new
- {
- @base = attr.Base,
- creation = attr.Creation
- };
- }
-
- // --- Vitals (base values) ---
- var vitals = new Dictionary();
- foreach (var vital in cf.Vitals)
- {
- vitals[vital.Name.ToLower()] = new
- {
- @base = vital.Base
- };
- }
-
- // --- Skills ---
- var skills = new Dictionary();
- Decal.Filters.FileService fs = CoreManager.Current.FileService as Decal.Filters.FileService;
- if (fs != null)
- {
- for (int i = 0; i < fs.SkillTable.Length; i++)
- {
- Decal.Interop.Filters.SkillInfo skillinfo = null;
- try
- {
- skillinfo = cf.Underlying.get_Skill(
- (Decal.Interop.Filters.eSkillID)fs.SkillTable[i].Id);
-
- string name = skillinfo.Name.ToLower().Replace(" ", "_");
- string training = skillinfo.Training.ToString();
- // Training enum returns "eTrainSpecialized" etc, strip "eTrain" prefix
- if (training.Length > 6)
- training = training.Substring(6);
-
- skills[name] = new
- {
- @base = skillinfo.Base,
- training = training
- };
- }
- finally
- {
- if (skillinfo != null)
- {
- Marshal.ReleaseComObject(skillinfo);
- skillinfo = null;
- }
- }
- }
- }
-
- // --- Allegiance ---
- object allegiance = null;
- if (allegianceName != null)
- {
- allegiance = new
- {
- name = allegianceName,
- monarch = monarch.name != null ? new
- {
- name = monarch.name,
- race = monarch.race,
- rank = monarch.rank,
- gender = monarch.gender
- } : null,
- patron = patron.name != null ? new
- {
- name = patron.name,
- race = patron.race,
- rank = patron.rank,
- gender = patron.gender
- } : null,
- rank = allegianceRank,
- followers = followers
- };
- }
-
- // --- Build payload ---
- var payload = new
- {
- type = "character_stats",
- timestamp = DateTime.UtcNow.ToString("o"),
- character_name = cf.Name,
- level = cf.Level,
- race = cf.Race,
- gender = cf.Gender,
- birth = cf.Birth.ToString(culture),
- total_xp = cf.TotalXP,
- unassigned_xp = cf.UnassignedXP,
- skill_credits = cf.SkillPoints,
- deaths = cf.Deaths,
- luminance_earned = luminanceEarned >= 0 ? (long?)luminanceEarned : null,
- luminance_total = luminanceTotal >= 0 ? (long?)luminanceTotal : null,
- current_title = currentTitle >= 0 ? (int?)currentTitle : null,
- attributes = attributes,
- vitals = vitals,
- skills = skills,
- allegiance = allegiance
- };
-
- _ = WebSocket.SendCharacterStatsAsync(payload);
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"[CharStats] Error collecting stats: {ex.Message}");
- }
- }
- }
-}
diff --git a/MosswartMassacre/MosswartMassacre.csproj b/MosswartMassacre/MosswartMassacre.csproj
index 555baa8..0c1df39 100644
--- a/MosswartMassacre/MosswartMassacre.csproj
+++ b/MosswartMassacre/MosswartMassacre.csproj
@@ -35,12 +35,10 @@
TRACE;VVS_REFERENCED;DECAL_INTEROP
prompt
4
- x86
- true
- lib\0Harmony.dll
+ ..\..\..\..\Documents\Decal Plugins\UtilityBelt\0Harmony.dll
False
@@ -51,18 +49,18 @@
False
- lib\Decal.FileService.dll
+ ..\..\..\..\..\..\Program Files (x86)\Decal 3.0\Decal.FileService.dll
-
+
False
False
- lib\Decal.Interop.Core.DLL
+ ..\..\..\..\..\..\Program Files (x86)\Decal 3.0\.NET 4.0 PIA\Decal.Interop.Core.DLL
False
-
+
False
False
- lib\Decal.Interop.Filters.DLL
+ ..\..\..\..\..\..\Program Files (x86)\Decal 3.0\.NET 4.0 PIA\Decal.Interop.Filters.DLL
False
@@ -70,16 +68,16 @@
False
lib\Decal.Interop.Inject.dll
-
+
False
False
- lib\Decal.Interop.D3DService.DLL
+ ..\..\..\..\..\..\Program Files (x86)\Decal 3.0\.NET 4.0 PIA\Decal.Interop.D3DService.DLL
False
False
False
- lib\Decal.Interop.Input.DLL
+ ..\..\..\..\..\..\Program Files (x86)\Decal 3.0\.NET 4.0 PIA\Decal.Interop.Input.DLL
False
@@ -226,12 +224,12 @@
True
True
-
+
False
- lib\utank2-i.dll
+ bin\Debug\utank2-i.dll
- lib\VCS5.dll
+ ..\..\..\..\..\..\Games\Decal Plugins\Virindi\VirindiChatSystem5\VCS5.dll
lib\VirindiViewService.dll
@@ -335,7 +333,6 @@
-
@@ -357,17 +354,24 @@
-
- lib\Decal.dll
+
+ {FF7F5F6D-34E0-4B6F-B3BB-8141DE2EF732}
+ 2
+ 0
+ 0
+ primary
+ False
False
-
-
- lib\decalnet.dll
+
+
+ {572B87C4-93BD-46B3-A291-CD58181D25DC}
+ 2
+ 0
+ 0
+ primary
+ False
True
-
-
-
-
+
diff --git a/MosswartMassacre/PluginCore.cs b/MosswartMassacre/PluginCore.cs
index d784259..7a5d24a 100644
--- a/MosswartMassacre/PluginCore.cs
+++ b/MosswartMassacre/PluginCore.cs
@@ -64,7 +64,6 @@ namespace MosswartMassacre
internal static Timer updateTimer;
private static Timer vitalsTimer;
private static System.Windows.Forms.Timer commandTimer;
- private static Timer characterStatsTimer;
private static readonly Queue pendingCommands = new Queue();
public static bool RareMetaEnabled { get; set; } = true;
@@ -183,8 +182,6 @@ namespace MosswartMassacre
CoreManager.Current.WorldFilter.CreateObject += OnInventoryCreate;
CoreManager.Current.WorldFilter.ReleaseObject += OnInventoryRelease;
CoreManager.Current.WorldFilter.ChangeObject += OnInventoryChange;
- // Subscribe to server messages for allegiance/luminance/title data
- CoreManager.Current.EchoFilter.ServerDispatch += EchoFilter_ServerDispatch;
// Initialize VVS view after character login
ViewManager.ViewInit();
@@ -254,8 +251,7 @@ namespace MosswartMassacre
CoreManager.Current.WorldFilter.CreateObject -= OnInventoryCreate;
CoreManager.Current.WorldFilter.ReleaseObject -= OnInventoryRelease;
CoreManager.Current.WorldFilter.ChangeObject -= OnInventoryChange;
- // Unsubscribe from server dispatch
- CoreManager.Current.EchoFilter.ServerDispatch -= EchoFilter_ServerDispatch;
+
// Stop and dispose of the timers
if (updateTimer != null)
@@ -288,15 +284,6 @@ namespace MosswartMassacre
questStreamingTimer = null;
}
- // Stop and dispose character stats timer
- if (characterStatsTimer != null)
- {
- characterStatsTimer.Stop();
- characterStatsTimer.Elapsed -= OnCharacterStatsUpdate;
- characterStatsTimer.Dispose();
- characterStatsTimer = null;
- }
-
// Dispose quest manager
if (questManager != null)
{
@@ -416,34 +403,6 @@ namespace MosswartMassacre
WriteToChat($"[ERROR] Quest streaming initialization failed: {ex.Message}");
}
- // Initialize character stats streaming
- try
- {
- CharacterStats.Init();
-
- // Start 10-minute character stats timer
- characterStatsTimer = new Timer(600000); // 10 minutes
- characterStatsTimer.Elapsed += OnCharacterStatsUpdate;
- characterStatsTimer.AutoReset = true;
- characterStatsTimer.Start();
-
- // Send initial stats after 5-second delay (let CharacterFilter populate)
- var initialDelay = new Timer(5000);
- initialDelay.AutoReset = false;
- initialDelay.Elapsed += (s, args) =>
- {
- CharacterStats.CollectAndSend();
- ((Timer)s).Dispose();
- };
- initialDelay.Start();
-
- WriteToChat("[OK] Character stats streaming initialized (10-min interval)");
- }
- catch (Exception ex)
- {
- WriteToChat($"[ERROR] Character stats initialization failed: {ex.Message}");
- }
-
}
#region Quest Streaming Methods
@@ -1202,50 +1161,6 @@ namespace MosswartMassacre
}
}
- private static void OnCharacterStatsUpdate(object sender, ElapsedEventArgs e)
- {
- try
- {
- CharacterStats.CollectAndSend();
- }
- catch (Exception ex)
- {
- WriteToChat($"[CharStats] Timer error: {ex.Message}");
- }
- }
-
- private void EchoFilter_ServerDispatch(object sender, NetworkMessageEventArgs e)
- {
- try
- {
- if (e.Message.Type == 0xF7B0) // Game Event
- {
- int eventId = (int)e.Message["event"];
-
- if (eventId == 0x0020) // Allegiance info
- {
- CharacterStats.ProcessAllegianceInfoMessage(e);
- }
- else if (eventId == 0x0013) // Login Character (properties)
- {
- CharacterStats.ProcessCharacterPropertyData(e);
- }
- else if (eventId == 0x0029) // Titles list
- {
- CharacterStats.ProcessTitlesMessage(e);
- }
- else if (eventId == 0x002b) // Set title
- {
- CharacterStats.ProcessSetTitleMessage(e);
- }
- }
- }
- catch (Exception ex)
- {
- WriteToChat($"[CharStats] ServerDispatch error: {ex.Message}");
- }
- }
-
private void CalculateKillsPerInterval()
{
double minutesElapsed = (DateTime.Now - statsStartTime).TotalMinutes;
diff --git a/MosswartMassacre/WebSocket.cs b/MosswartMassacre/WebSocket.cs
index 288b74d..50279d5 100644
--- a/MosswartMassacre/WebSocket.cs
+++ b/MosswartMassacre/WebSocket.cs
@@ -296,12 +296,6 @@ namespace MosswartMassacre
await SendEncodedAsync(json, CancellationToken.None);
}
- public static async Task SendCharacterStatsAsync(object statsData)
- {
- var json = JsonConvert.SerializeObject(statsData);
- await SendEncodedAsync(json, CancellationToken.None);
- }
-
public static async Task SendQuestDataAsync(string questName, string countdown)
{
var envelope = new
diff --git a/MosswartMassacre/bin/Release/MosswartMassacre.dll b/MosswartMassacre/bin/Release/MosswartMassacre.dll
index b78f6c8..8e18ba6 100644
Binary files a/MosswartMassacre/bin/Release/MosswartMassacre.dll and b/MosswartMassacre/bin/Release/MosswartMassacre.dll differ
diff --git a/MosswartMassacre/lib/Decal.FileService.dll b/MosswartMassacre/lib/Decal.FileService.dll
deleted file mode 100644
index 85e6d85..0000000
Binary files a/MosswartMassacre/lib/Decal.FileService.dll and /dev/null differ
diff --git a/MosswartMassacre/lib/Decal.Interop.D3DService.DLL b/MosswartMassacre/lib/Decal.Interop.D3DService.DLL
deleted file mode 100644
index dcf1559..0000000
Binary files a/MosswartMassacre/lib/Decal.Interop.D3DService.DLL and /dev/null differ
diff --git a/MosswartMassacre/lib/Decal.Interop.Filters.DLL b/MosswartMassacre/lib/Decal.Interop.Filters.DLL
deleted file mode 100644
index 0600e62..0000000
Binary files a/MosswartMassacre/lib/Decal.Interop.Filters.DLL and /dev/null differ
diff --git a/MosswartMassacre/lib/Decal.Interop.Input.DLL b/MosswartMassacre/lib/Decal.Interop.Input.DLL
deleted file mode 100644
index b73bed2..0000000
Binary files a/MosswartMassacre/lib/Decal.Interop.Input.DLL and /dev/null differ
diff --git a/MosswartMassacre/lib/Decal.dll b/MosswartMassacre/lib/Decal.dll
deleted file mode 100644
index bbe634c..0000000
Binary files a/MosswartMassacre/lib/Decal.dll and /dev/null differ
diff --git a/MosswartMassacre/lib/VCS5.dll b/MosswartMassacre/lib/VCS5.dll
deleted file mode 100644
index 022af65..0000000
Binary files a/MosswartMassacre/lib/VCS5.dll and /dev/null differ
diff --git a/MosswartMassacre/lib/decalnet.dll b/MosswartMassacre/lib/decalnet.dll
deleted file mode 100644
index 2657264..0000000
Binary files a/MosswartMassacre/lib/decalnet.dll and /dev/null differ