diff --git a/Influx/AllaganTools/AllaganToolsIpc.cs b/Influx/AllaganTools/AllaganToolsIpc.cs
index 80af870..8fddcbc 100644
--- a/Influx/AllaganTools/AllaganToolsIpc.cs
+++ b/Influx/AllaganTools/AllaganToolsIpc.cs
@@ -86,6 +86,9 @@ internal sealed class AllaganToolsIpc : IDisposable
return new Currencies
{
Gil = inv.Sum(1),
+ GcSealsMaelstrom = inv.Sum(20),
+ GcSealsTwinAdders = inv.Sum(21),
+ GcSealsImmortalFlames = inv.Sum(22),
FcCredits = inv.Sum(80),
Ventures = inv.Sum(21072),
CeruleumTanks = inv.Sum(10155),
diff --git a/Influx/AllaganTools/Currencies.cs b/Influx/AllaganTools/Currencies.cs
index 274db81..fc05a63 100644
--- a/Influx/AllaganTools/Currencies.cs
+++ b/Influx/AllaganTools/Currencies.cs
@@ -3,7 +3,9 @@ namespace Influx.AllaganTools;
internal struct Currencies
{
public long Gil { get; init; }
- public long GcSeals { get; init; }
+ public long GcSealsMaelstrom { get; init; }
+ public long GcSealsTwinAdders { get; init; }
+ public long GcSealsImmortalFlames { get; init; }
public long FcCredits { get; init; }
public long Ventures { get; init; }
public long CeruleumTanks { get; init; }
diff --git a/Influx/Influx.csproj b/Influx/Influx.csproj
index ee08837..455bd8e 100644
--- a/Influx/Influx.csproj
+++ b/Influx/Influx.csproj
@@ -22,8 +22,8 @@
-
-
+
+
@@ -58,10 +58,10 @@
-
+
-
+
diff --git a/Influx/Influx/InfluxStatisticsClient.cs b/Influx/Influx/InfluxStatisticsClient.cs
index 78f3e99..247a5d0 100644
--- a/Influx/Influx/InfluxStatisticsClient.cs
+++ b/Influx/Influx/InfluxStatisticsClient.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Game.Gui;
+using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Influx.AllaganTools;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
@@ -61,6 +62,40 @@ internal class InfluxStatisticsClient : IDisposable
.Field("ceruleum_tanks", currencies.CeruleumTanks)
.Field("repair_kits", currencies.RepairKits)
.Timestamp(date, WritePrecision.S));
+
+ if (update.LocalStats.TryGetValue(character, out var localStats))
+ {
+ values.Add(PointData.Measurement("grandcompany")
+ .Tag("id", character.CharacterId.ToString())
+ .Tag("player_name", character.Name)
+ .Tag("type", character.CharacterType.ToString())
+ .Field("gc", localStats.GrandCompany)
+ .Field("gc_rank", localStats.GcRank)
+ .Field("seals", (GrandCompany)localStats.GrandCompany switch
+ {
+ GrandCompany.Maelstrom => currencies.GcSealsMaelstrom,
+ GrandCompany.TwinAdder => currencies.GcSealsTwinAdders,
+ GrandCompany.ImmortalFlames => currencies.GcSealsImmortalFlames,
+ _ => 0,
+ })
+ .Field("seal_cap", localStats.GcRank switch
+ {
+ 1 => 10_000,
+ 2 => 15_000,
+ 3 => 20_000,
+ 4 => 25_000,
+ 5 => 30_000,
+ 6 => 35_000,
+ 7 => 40_000,
+ 8 => 45_000,
+ 9 => 50_000,
+ 10 => 80_000,
+ 11 => 90_000,
+ _ => 0,
+ })
+ .Field("squadron_unlocked", localStats?.SquadronUnlocked == true ? 1 : 0)
+ .Timestamp(date, WritePrecision.S));
+ }
}
else if (character.CharacterType == CharacterType.Retainer)
{
diff --git a/Influx/InfluxPlugin.cs b/Influx/InfluxPlugin.cs
index 48c83ec..ed6c205 100644
--- a/Influx/InfluxPlugin.cs
+++ b/Influx/InfluxPlugin.cs
@@ -11,6 +11,7 @@ using Dalamud.Plugin;
using ECommons;
using Influx.AllaganTools;
using Influx.Influx;
+using Influx.LocalStatistics;
using Influx.SubmarineTracker;
using Influx.Windows;
@@ -27,6 +28,7 @@ public class InfluxPlugin : IDalamudPlugin
private readonly CommandManager _commandManager;
private readonly AllaganToolsIpc _allaganToolsIpc;
private readonly SubmarineTrackerIpc _submarineTrackerIpc;
+ private readonly LocalStatsCalculator _localStatsCalculator;
private readonly InfluxStatisticsClient _influxStatisticsClient;
private readonly WindowSystem _windowSystem;
private readonly StatisticsWindow _statisticsWindow;
@@ -44,6 +46,7 @@ public class InfluxPlugin : IDalamudPlugin
_commandManager = commandManager;
_allaganToolsIpc = new AllaganToolsIpc(pluginInterface, chatGui, _configuration);
_submarineTrackerIpc = new SubmarineTrackerIpc(chatGui);
+ _localStatsCalculator = new LocalStatsCalculator(pluginInterface, clientState, chatGui);
_influxStatisticsClient = new InfluxStatisticsClient(chatGui, _configuration);
_windowSystem = new WindowSystem(typeof(InfluxPlugin).FullName);
@@ -86,6 +89,8 @@ public class InfluxPlugin : IDalamudPlugin
{
Currencies = currencies,
Submarines = _submarineTrackerIpc.GetSubmarineStats(characters),
+ LocalStats = _localStatsCalculator.GetAllCharacterStats()
+ .ToDictionary(x => characters.First(y => y.CharacterId == x.Key), x => x.Value),
};
_statisticsWindow.OnStatisticsUpdate(update);
_influxStatisticsClient.OnStatisticsUpdate(update);
@@ -103,6 +108,7 @@ public class InfluxPlugin : IDalamudPlugin
_windowSystem.RemoveAllWindows();
_commandManager.RemoveHandler("/influx");
_influxStatisticsClient.Dispose();
+ _localStatsCalculator.Dispose();
_allaganToolsIpc.Dispose();
ECommonsMain.Dispose();
diff --git a/Influx/LocalStatistics/LocalStats.cs b/Influx/LocalStatistics/LocalStats.cs
new file mode 100644
index 0000000..3f79141
--- /dev/null
+++ b/Influx/LocalStatistics/LocalStats.cs
@@ -0,0 +1,9 @@
+namespace Influx.LocalStatistics;
+
+public record LocalStats
+{
+ public ulong ContentId { get; init; }
+ public byte GrandCompany { get; init; }
+ public byte GcRank { get; init; }
+ public bool SquadronUnlocked { get; init; }
+}
diff --git a/Influx/LocalStatistics/LocalStatsCalculator.cs b/Influx/LocalStatistics/LocalStatsCalculator.cs
new file mode 100644
index 0000000..4f06965
--- /dev/null
+++ b/Influx/LocalStatistics/LocalStatsCalculator.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Dalamud.Game.ClientState;
+using Dalamud.Game.Gui;
+using Dalamud.Logging;
+using Dalamud.Plugin;
+using FFXIVClientStructs.FFXIV.Client.Game;
+using FFXIVClientStructs.FFXIV.Client.Game.UI;
+using FFXIVClientStructs.FFXIV.Client.UI.Agent;
+using Newtonsoft.Json;
+
+namespace Influx.LocalStatistics;
+
+public class LocalStatsCalculator : IDisposable
+{
+ private readonly DalamudPluginInterface _pluginInterface;
+ private readonly ClientState _clientState;
+ private readonly ChatGui _chatGui;
+ private readonly Dictionary _cache = new();
+
+ public LocalStatsCalculator(DalamudPluginInterface pluginInterface, ClientState clientState, ChatGui chatGui)
+ {
+ _pluginInterface = pluginInterface;
+ _clientState = clientState;
+ _chatGui = chatGui;
+
+ _clientState.Login += UpdateStatistics;
+ _clientState.Logout += UpdateStatistics;
+ _clientState.TerritoryChanged += UpdateStatistics;
+
+ foreach (var file in _pluginInterface.ConfigDirectory.GetFiles("l.*.json"))
+ {
+ try
+ {
+ var stats = JsonConvert.DeserializeObject(File.ReadAllText(file.FullName));
+ if (stats == null)
+ continue;
+
+ _cache[stats.ContentId] = stats;
+ }
+ catch (Exception e)
+ {
+ PluginLog.Warning(e, $"Could not parse file {file.FullName}");
+ }
+ }
+
+ if (_clientState.IsLoggedIn)
+ UpdateStatistics();
+ }
+
+ public void Dispose()
+ {
+ _clientState.Login += UpdateStatistics;
+ _clientState.Logout += UpdateStatistics;
+ _clientState.TerritoryChanged += UpdateStatistics;
+ }
+
+ private void UpdateStatistics(object? sender, EventArgs e) => UpdateStatistics();
+
+ private void UpdateStatistics(object? sender, ushort territoryType) => UpdateStatistics();
+
+ private unsafe void UpdateStatistics()
+ {
+ var localContentId = _clientState.LocalContentId;
+ if (localContentId == 0)
+ {
+ PluginLog.Warning("No local character id");
+ return;
+ }
+
+ try
+ {
+ PlayerState* playerState = PlayerState.Instance();
+ if (playerState == null)
+ return;
+
+ LocalStats localStats = new()
+ {
+ ContentId = localContentId,
+ GrandCompany = playerState->GrandCompany,
+ GcRank = playerState->GetGrandCompanyRank(),
+ SquadronUnlocked = (GrandCompany)playerState->GrandCompany switch
+ {
+ GrandCompany.Maelstrom => QuestManager.IsQuestComplete(67926),
+ GrandCompany.TwinAdder => QuestManager.IsQuestComplete(67925),
+ GrandCompany.ImmortalFlames => QuestManager.IsQuestComplete(67927),
+ _ => false
+ },
+ };
+
+ if (_cache.TryGetValue(localContentId, out var existingStats))
+ {
+ if (existingStats != localStats)
+ {
+ _cache[localContentId] = localStats;
+ File.WriteAllText(
+ Path.Join(_pluginInterface.GetPluginConfigDirectory(), $"l.{localContentId:X8}.json"),
+ JsonConvert.SerializeObject(localStats));
+ }
+ }
+ else
+ {
+ _cache[localContentId] = localStats;
+ File.WriteAllText(
+ Path.Join(_pluginInterface.GetPluginConfigDirectory(), $"l.{localContentId:X8}.json"),
+ JsonConvert.SerializeObject(localStats));
+ }
+ }
+ catch (Exception e)
+ {
+ PluginLog.Error(e, "Failed to update local stats");
+ }
+ }
+
+ public IReadOnlyDictionary GetAllCharacterStats() => _cache.AsReadOnly();
+}
diff --git a/Influx/StatisticsUpdate.cs b/Influx/StatisticsUpdate.cs
index fc8696b..74e3c4c 100644
--- a/Influx/StatisticsUpdate.cs
+++ b/Influx/StatisticsUpdate.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Influx.AllaganTools;
+using Influx.LocalStatistics;
using Influx.SubmarineTracker;
namespace Influx;
@@ -8,4 +9,5 @@ internal sealed class StatisticsUpdate
{
public required IReadOnlyDictionary Currencies { get; init; }
public required Dictionary> Submarines { get; init; }
+ public required Dictionary LocalStats { get; init; }
}