Add DWORD properties and titles list to character stats payload

Parse augmentation, rating, mastery, society, and general DWORD properties
from the 0x0013 login message. Capture the full titles list from 0x0029.
Both are included in the character_stats WebSocket payload for the new
TreeStats-style character window in the frontend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erik 2026-02-27 14:39:08 +00:00
parent a4d2108b3a
commit a446158f63
2 changed files with 38 additions and 1 deletions

View file

@ -42,6 +42,19 @@ namespace MosswartMassacre
// Cached title data (populated from network messages) // Cached title data (populated from network messages)
private static int currentTitle = -1; private static int currentTitle = -1;
private static List<string> titlesList = new List<string>();
// Cached DWORD properties (populated from 0x0013 message)
private static Dictionary<int, int> characterProperties = new Dictionary<int, int>();
// DWORD blacklist — exclude cosmetic/internal properties (same as TreeStats)
private static readonly HashSet<int> dwordBlacklist = new HashSet<int> {
2, 5, 7, 10, 17, 19, 20, 24, 25, 26, 28, 30, 33, 35, 36, 38, 43, 45,
86, 87, 88, 89, 90, 91, 92, 98,
105, 106, 107, 108, 109, 110, 111, 113, 114, 115, 117, 125, 129, 131, 134,
158, 159, 160, 166, 170, 171, 172, 174, 175, 176, 177, 178, 179, 188, 193,
270, 271, 272, 293
};
/// <summary> /// <summary>
/// Reset all cached data. Call on plugin init. /// Reset all cached data. Call on plugin init.
@ -58,6 +71,8 @@ namespace MosswartMassacre
luminanceEarned = -1; luminanceEarned = -1;
luminanceTotal = -1; luminanceTotal = -1;
currentTitle = -1; currentTitle = -1;
titlesList.Clear();
characterProperties.Clear();
} }
/// <summary> /// <summary>
@ -142,6 +157,18 @@ namespace MosswartMassacre
else if (key == Constants.MaximumLuminanceKey) else if (key == Constants.MaximumLuminanceKey)
luminanceTotal = value; luminanceTotal = value;
} }
// Parse DWORD properties (augmentations, ratings, masteries, society, etc.)
MessageStruct dwords = props.Struct("dwords");
characterProperties.Clear();
for (int i = 0; i < dwords.Count; i++)
{
var tmpStruct = dwords.Struct(i);
int key = tmpStruct.Value<Int32>("key");
int value = tmpStruct.Value<Int32>("value");
if (!dwordBlacklist.Contains(key))
characterProperties[key] = value;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -185,6 +212,14 @@ namespace MosswartMassacre
{ {
try try
{ {
// Capture full titles list
MessageStruct titles = e.Message.Struct("titles");
titlesList.Clear();
for (int i = 0; i < titles.Count; i++)
{
titlesList.Add(titles.Struct(i).Value<string>("value"));
}
currentTitle = e.Message.Value<Int32>("current"); currentTitle = e.Message.Value<Int32>("current");
} }
catch (Exception ex) catch (Exception ex)
@ -325,7 +360,9 @@ namespace MosswartMassacre
attributes = attributes, attributes = attributes,
vitals = vitals, vitals = vitals,
skills = skills, skills = skills,
allegiance = allegiance allegiance = allegiance,
properties = characterProperties.Count > 0 ? new Dictionary<int, int>(characterProperties) : null,
titles = titlesList.Count > 0 ? new List<string>(titlesList) : null
}; };
_ = WebSocket.SendCharacterStatsAsync(payload); _ = WebSocket.SendCharacterStatsAsync(payload);