catastropy averted?
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AssemblyName>CrystallineConflictWinsTracker</AssemblyName>
|
||||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<LangVersion>14.0</LangVersion>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup />
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Reference Include="Dalamud" />
|
||||
<Reference Include="FFXIVClientStructs" />
|
||||
<Reference Include="Newtonsoft.Json" />
|
||||
<Reference Include="Lumina.Excel" />
|
||||
<Reference Include="Lumina" />
|
||||
<Reference Include="ImGui.NET" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using Dalamud.Configuration;
|
||||
using Dalamud.Plugin;
|
||||
|
||||
namespace CrystallineConflictWinsTracker;
|
||||
|
||||
[Serializable]
|
||||
public class Configuration : IPluginConfiguration
|
||||
{
|
||||
[NonSerialized]
|
||||
private DalamudPluginInterface? pluginInterface;
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public int RightClickDelay { get; set; } = 250;
|
||||
|
||||
public void Initialize(DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
this.pluginInterface = pluginInterface;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
pluginInterface.SavePluginConfig((IPluginConfiguration)(object)this);
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace CrystallineConflictWinsTracker;
|
||||
|
||||
public class DalamudApi
|
||||
{
|
||||
[PluginService]
|
||||
public static IChatGui ChatGui { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static IClientState ClientState { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static ICommandManager CommandManager { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static DalamudPluginInterface PluginInterface { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static IDataManager DataManager { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static IDtrBar DtrBar { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static IFramework Framework { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static IGameGui GameGui { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static ISigScanner SigScanner { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static IGameInteropProvider Hooks { get; private set; }
|
||||
|
||||
[PluginService]
|
||||
public static IPluginLog PluginLog { get; private set; }
|
||||
|
||||
public static void Initialize(DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
pluginInterface.Create<DalamudApi>(Array.Empty<object>());
|
||||
}
|
||||
}
|
||||
+378
@@ -0,0 +1,378 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CrystallineConflictWinsTracker;
|
||||
|
||||
public sealed class Plugin : IDalamudPlugin, IDisposable
|
||||
{
|
||||
private unsafe delegate void* AgentShow(void* a1);
|
||||
|
||||
private unsafe delegate void* FireCallbackDelegate(AtkUnitBase* atkUnitBase, int valueCount, AtkValue* atkValues, ulong a4);
|
||||
|
||||
private const string commandName = "/ccwins";
|
||||
|
||||
public bool dutyFinderVisible;
|
||||
|
||||
public bool pvpPageVisible;
|
||||
|
||||
public bool casualCCEnabled;
|
||||
|
||||
public bool rankedCCEnabled;
|
||||
|
||||
public bool alertedDebugWindow;
|
||||
|
||||
private Hook<FireCallbackDelegate> addonReceiveEventHook;
|
||||
|
||||
public string Name => "Crystaline Conflict Winratio tracker";
|
||||
|
||||
private DalamudPluginInterface PluginInterface { get; init; }
|
||||
|
||||
private ICommandManager CommandManager { get; init; }
|
||||
|
||||
private Configuration Configuration { get; init; }
|
||||
|
||||
private PluginUI PluginUi { get; init; }
|
||||
|
||||
public long rcStartTime { get; private set; }
|
||||
|
||||
private Hook<AgentShow> DutyFinderHook { get; set; }
|
||||
|
||||
public unsafe AtkUnitBase* dutyFinderAtkUnitBase { get; private set; }
|
||||
|
||||
public string DataPath { get; }
|
||||
|
||||
public Plugin([RequiredVersion("1.0")] DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0048: Expected O, but got Unknown
|
||||
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_011e: Expected O, but got Unknown
|
||||
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_012e: Expected O, but got Unknown
|
||||
//IL_019f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_01a9: Expected O, but got Unknown
|
||||
DalamudApi.Initialize(pluginInterface);
|
||||
DalamudApi.PluginLog.Debug("Initializing the plugin...", Array.Empty<object>());
|
||||
PluginInterface = pluginInterface;
|
||||
CommandManager = DalamudApi.CommandManager;
|
||||
DalamudApi.Framework.Update += new OnUpdateDelegate(Framework_UpdateNew);
|
||||
Configuration = (PluginInterface.GetPluginConfig() as Configuration) ?? new Configuration();
|
||||
Configuration.Initialize(PluginInterface);
|
||||
DataPath = PluginInterface.ConfigDirectory?.ToString() + "/data/";
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(DataPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.LogError(ex, "Failed to create data directory.", Array.Empty<object>());
|
||||
}
|
||||
if (!File.Exists(DataPath + "pvpstats.json"))
|
||||
{
|
||||
File.Create(DataPath + "pvpstats.json");
|
||||
}
|
||||
PluginUi = new PluginUI(Configuration, DataPath);
|
||||
DalamudApi.CommandManager.AddHandler("/ccwins", new CommandInfo(new HandlerDelegate(OnCommand))
|
||||
{
|
||||
HelpMessage = "Show the tracker UI"
|
||||
});
|
||||
PluginInterface.UiBuilder.Draw += DrawUI;
|
||||
PluginInterface.UiBuilder.OpenConfigUi += DrawConfigUI;
|
||||
DalamudApi.ClientState.EnterPvP += ClientState_EnterPvP;
|
||||
DalamudApi.ClientState.LeavePvP += ClientState_LeavePvP;
|
||||
DalamudApi.ChatGui.ChatMessage += new OnMessageDelegate(Chat_ChatMessage);
|
||||
}
|
||||
|
||||
private void Framework_UpdateNew(IFramework framework)
|
||||
{
|
||||
if (Configuration.Enabled && DalamudApi.ClientState.IsLoggedIn)
|
||||
{
|
||||
CheckForDfSelections();
|
||||
}
|
||||
}
|
||||
|
||||
private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled)
|
||||
{
|
||||
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Invalid comparison between Unknown and I4
|
||||
if ((int)type != 2112)
|
||||
{
|
||||
return;
|
||||
}
|
||||
PluginLog.Debug(message.TextValue, Array.Empty<object>());
|
||||
if (message.TextValue.Contains("900 Series EXP."))
|
||||
{
|
||||
PluginLog.Debug("WE WON THE GAME?", Array.Empty<object>());
|
||||
if (casualCCEnabled)
|
||||
{
|
||||
PluginLog.Debug("CASUAL WIN", Array.Empty<object>());
|
||||
StoreNewPvpRow(ranked: false, win: true);
|
||||
}
|
||||
else if (rankedCCEnabled)
|
||||
{
|
||||
PluginLog.Debug("RANKED WIN", Array.Empty<object>());
|
||||
StoreNewPvpRow(ranked: true, win: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLog.Error("NEITHER MODE IS UP? WAT?", Array.Empty<object>());
|
||||
}
|
||||
}
|
||||
else if (message.TextValue.Contains("700 Series EXP."))
|
||||
{
|
||||
PluginLog.Debug("WE LOST THE GAME?", Array.Empty<object>());
|
||||
if (casualCCEnabled)
|
||||
{
|
||||
PluginLog.Debug("CASUAL LOSS", Array.Empty<object>());
|
||||
StoreNewPvpRow(ranked: false, win: false);
|
||||
}
|
||||
else if (rankedCCEnabled)
|
||||
{
|
||||
PluginLog.Debug("RANKED LOSS", Array.Empty<object>());
|
||||
StoreNewPvpRow(ranked: true, win: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLog.Error("NEITHER MODE IS UP? WAT?", Array.Empty<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StoreNewPvpRow(bool ranked, bool win)
|
||||
{
|
||||
string text = File.ReadAllText(DataPath + "pvpstats.json");
|
||||
List<PvpWinEntry> obj = JsonConvert.DeserializeObject<List<PvpWinEntry>>(text) ?? new List<PvpWinEntry>();
|
||||
obj.Add(new PvpWinEntry
|
||||
{
|
||||
classId = ((Character)DalamudApi.ClientState.LocalPlayer).ClassJob.Id,
|
||||
win = win,
|
||||
ranked = ranked,
|
||||
className = ((Character)DalamudApi.ClientState.LocalPlayer).ClassJob.GameData.Name.RawString,
|
||||
matchDate = DateTime.Now
|
||||
});
|
||||
text = JsonConvert.SerializeObject((object)obj);
|
||||
File.WriteAllText(DataPath + "pvpstats.json", text);
|
||||
}
|
||||
|
||||
private void ClientState_LeavePvP()
|
||||
{
|
||||
PluginLog.Debug("Yes, we left pvp :)", Array.Empty<object>());
|
||||
}
|
||||
|
||||
private unsafe void* CallbackDetour(AtkUnitBase* atkunitbase, int valuecount, AtkValue* atkvalues, ulong a4)
|
||||
{
|
||||
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0081: Expected I4, but got Unknown
|
||||
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0143: Invalid comparison between Unknown and I4
|
||||
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0179: Invalid comparison between Unknown and I4
|
||||
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0186: Invalid comparison between Unknown and I4
|
||||
if (dutyFinderAtkUnitBase == null)
|
||||
{
|
||||
return addonReceiveEventHook.Original(atkunitbase, valuecount, atkvalues, a4);
|
||||
}
|
||||
if (atkunitbase == dutyFinderAtkUnitBase)
|
||||
{
|
||||
PluginLog.Debug("OMG ITS CONTENTSFINDER :D", Array.Empty<object>());
|
||||
List<object> list = new List<object>();
|
||||
List<ValueType> list2 = new List<ValueType>();
|
||||
try
|
||||
{
|
||||
AtkValue* ptr = atkvalues;
|
||||
for (int i = 0; i < valuecount; i++)
|
||||
{
|
||||
list2.Add(((AtkValue)ptr).Type);
|
||||
ValueType type = ((AtkValue)ptr).Type;
|
||||
switch (type - 2)
|
||||
{
|
||||
case 0:
|
||||
list.Add(((AtkValue)ptr).Byte > 0);
|
||||
break;
|
||||
case 1:
|
||||
list.Add(((AtkValue)ptr).Int);
|
||||
break;
|
||||
case 2:
|
||||
list.Add(((AtkValue)ptr).UInt);
|
||||
break;
|
||||
case 4:
|
||||
list.Add(Marshal.PtrToStringUTF8(new IntPtr(((AtkValue)ptr).String)));
|
||||
break;
|
||||
default:
|
||||
list.Add($"Unknown Type: {((AtkValue)ptr).Type}");
|
||||
break;
|
||||
}
|
||||
ptr = (AtkValue*)((byte*)ptr + Unsafe.SizeOf<AtkValue>());
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return addonReceiveEventHook.Original(atkunitbase, valuecount, atkvalues, a4);
|
||||
}
|
||||
if (valuecount > 1)
|
||||
{
|
||||
object obj2 = list[1];
|
||||
ValueType val = list2[1];
|
||||
if ((int)val == 3)
|
||||
{
|
||||
if ((int)obj2 == 8)
|
||||
{
|
||||
PluginLog.Debug("HOOO BOY WE GOING PVP", Array.Empty<object>());
|
||||
pvpPageVisible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pvpPageVisible = false;
|
||||
}
|
||||
}
|
||||
else if ((int)val == 4 && (int)list2[0] == 3 && (int)list[0] == 3)
|
||||
{
|
||||
PluginLog.Debug("SOMETHIGNG CLICKED?", Array.Empty<object>());
|
||||
if (pvpPageVisible)
|
||||
{
|
||||
AtkComponentCheckBox* nodeById = (AtkComponentCheckBox*)((AtkUnitBase)(nint)DalamudApi.GameGui.GetAddonByName("ContentsFinder", 1)).GetNodeById(4u);
|
||||
AtkComponentCheckBox* ptr2 = (AtkComponentCheckBox*)2267615832848uL;
|
||||
if ((uint)list[1] == 1)
|
||||
{
|
||||
PluginLog.Debug("FUCKING CASUAL :D", Array.Empty<object>());
|
||||
}
|
||||
else if ((uint)list[1] == 2)
|
||||
{
|
||||
PluginLog.Debug("FUCKING HARDCORE RANKED :D", Array.Empty<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return addonReceiveEventHook.Original(atkunitbase, valuecount, atkvalues, a4);
|
||||
}
|
||||
|
||||
private void ClientState_EnterPvP()
|
||||
{
|
||||
PluginLog.Debug("Yes, we entered pvp :)", Array.Empty<object>());
|
||||
}
|
||||
|
||||
private unsafe void InstallAddonReceiveEventHook()
|
||||
{
|
||||
string text = "E8 ?? ?? ?? ?? 8B 4C 24 20 0F B6 D8";
|
||||
nint num = DalamudApi.SigScanner.ScanText(text);
|
||||
addonReceiveEventHook = DalamudApi.Hooks.HookFromAddress<FireCallbackDelegate>((IntPtr)num, (FireCallbackDelegate)CallbackDetour, (HookBackend)0);
|
||||
}
|
||||
|
||||
private unsafe AtkUnitBase* GetDutyFinderPointer()
|
||||
{
|
||||
nint addonByName = DalamudApi.GameGui.GetAddonByName("ContentsFinder", 1);
|
||||
if (addonByName != IntPtr.Zero)
|
||||
{
|
||||
AtkUnitBase* ptr = (AtkUnitBase*)addonByName;
|
||||
if (((AtkUnitBase)ptr).RootNode != null)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void Framework_Update(IFramework framework)
|
||||
{
|
||||
if (Configuration.Enabled && DalamudApi.ClientState.IsLoggedIn)
|
||||
{
|
||||
CheckForDfSelections();
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void CheckForDfSelections()
|
||||
{
|
||||
nint addonByName = DalamudApi.GameGui.GetAddonByName("ContentsFinderConfirm", 1);
|
||||
AtkUnitBase* ptr = (AtkUnitBase*)addonByName;
|
||||
if (ptr != null && ((AtkUnitBase)ptr).IsVisible)
|
||||
{
|
||||
AtkTextNode* nodeById = (AtkTextNode*)((AtkUnitBase)ptr).GetNodeById(49u);
|
||||
if (nodeById != null && ((Utf8String)(&((AtkTextNode)nodeById).NodeText)).StringPtr != null)
|
||||
{
|
||||
string text = Marshal.PtrToStringUTF8(new IntPtr(((Utf8String)(&((AtkTextNode)nodeById).NodeText)).StringPtr));
|
||||
if (text != null)
|
||||
{
|
||||
if (text.Contains("Crystalline Conflict (Casual Match)"))
|
||||
{
|
||||
if (!casualCCEnabled)
|
||||
{
|
||||
casualCCEnabled = true;
|
||||
rankedCCEnabled = false;
|
||||
PluginLog.Debug("CASUAL CC MATCH INCOMING, SETTING TRUE", Array.Empty<object>());
|
||||
}
|
||||
}
|
||||
else if (text.Contains("Crystalline Conflict (Ranked Match)") && !rankedCCEnabled)
|
||||
{
|
||||
rankedCCEnabled = true;
|
||||
casualCCEnabled = false;
|
||||
PluginLog.Debug("RANKED CC MATCH INCOMING, SETTING TRUE", Array.Empty<object>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nint addonByName2 = DalamudApi.GameGui.GetAddonByName("ContentsFinder", 1);
|
||||
if (addonByName2 != IntPtr.Zero)
|
||||
{
|
||||
AtkUnitBase* ptr2 = (dutyFinderAtkUnitBase = (AtkUnitBase*)addonByName2);
|
||||
if (((AtkUnitBase)ptr2).RootNode != null && ((AtkUnitBase)ptr2).IsVisible)
|
||||
{
|
||||
dutyFinderVisible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0031: Expected O, but got Unknown
|
||||
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0073: Expected O, but got Unknown
|
||||
PluginUi.Dispose();
|
||||
DalamudApi.CommandManager.RemoveHandler("/ccwins");
|
||||
DalamudApi.Framework.Update -= new OnUpdateDelegate(Framework_Update);
|
||||
DalamudApi.ClientState.LeavePvP -= ClientState_LeavePvP;
|
||||
DalamudApi.ClientState.EnterPvP -= ClientState_EnterPvP;
|
||||
DalamudApi.ChatGui.ChatMessage -= new OnMessageDelegate(Chat_ChatMessage);
|
||||
}
|
||||
|
||||
private void OnCommand(string command, string args)
|
||||
{
|
||||
PluginUi.Visible = true;
|
||||
}
|
||||
|
||||
private void DrawUI()
|
||||
{
|
||||
PluginUi.Draw();
|
||||
}
|
||||
|
||||
private void DrawConfigUI()
|
||||
{
|
||||
PluginUi.SettingsVisible = true;
|
||||
}
|
||||
}
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using ImGuiNET;
|
||||
using Lumina.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CrystallineConflictWinsTracker;
|
||||
|
||||
internal class PluginUI : IDisposable
|
||||
{
|
||||
private Configuration configuration;
|
||||
|
||||
private bool settingsVisible;
|
||||
|
||||
private bool visible;
|
||||
|
||||
public List<PvpSeason> pvpSeasons = new List<PvpSeason>();
|
||||
|
||||
private List<PvpWinEntry>? currentData;
|
||||
|
||||
private string currentlySelectedClassName;
|
||||
|
||||
private List<PvpWinEntry> currentClassGames;
|
||||
|
||||
private bool pickedClass;
|
||||
|
||||
private PvpSeason currentlySelectedSeason;
|
||||
|
||||
private PvpSeason previouslySelectedSeason;
|
||||
|
||||
private string previouslySelectedClassName;
|
||||
|
||||
public string DataPath { get; }
|
||||
|
||||
public bool SettingsVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
return settingsVisible;
|
||||
}
|
||||
set
|
||||
{
|
||||
settingsVisible = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return visible;
|
||||
}
|
||||
set
|
||||
{
|
||||
visible = value;
|
||||
}
|
||||
}
|
||||
|
||||
public PluginUI(Configuration configuration, string DataPath)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.DataPath = DataPath;
|
||||
pvpSeasons.Add(new PvpSeason
|
||||
{
|
||||
startDate = new DateTime(1970, 1, 1),
|
||||
endDate = new DateTime(2095, 1, 1),
|
||||
season = 0,
|
||||
seasonLabel = "All"
|
||||
});
|
||||
pvpSeasons.Add(new PvpSeason
|
||||
{
|
||||
startDate = new DateTime(2022, 4, 12),
|
||||
endDate = new DateTime(2022, 7, 6),
|
||||
season = 1,
|
||||
seasonLabel = "Season 1"
|
||||
});
|
||||
pvpSeasons.Add(new PvpSeason
|
||||
{
|
||||
startDate = new DateTime(2022, 7, 6),
|
||||
endDate = new DateTime(2022, 8, 22),
|
||||
season = 2,
|
||||
seasonLabel = "Season 2"
|
||||
});
|
||||
pvpSeasons.Add(new PvpSeason
|
||||
{
|
||||
startDate = new DateTime(2022, 8, 23),
|
||||
endDate = new DateTime(2022, 10, 31),
|
||||
season = 3,
|
||||
seasonLabel = "Season 3"
|
||||
});
|
||||
pvpSeasons.Add(new PvpSeason
|
||||
{
|
||||
startDate = new DateTime(2022, 10, 31),
|
||||
endDate = new DateTime(2023, 1, 10),
|
||||
season = 4,
|
||||
seasonLabel = "Season 4"
|
||||
});
|
||||
pvpSeasons.Add(new PvpSeason
|
||||
{
|
||||
startDate = new DateTime(2023, 1, 10),
|
||||
endDate = new DateTime(2023, 4, 4),
|
||||
season = 5,
|
||||
seasonLabel = "Season 5"
|
||||
});
|
||||
pvpSeasons.Add(new PvpSeason
|
||||
{
|
||||
startDate = new DateTime(2023, 4, 4),
|
||||
endDate = new DateTime(2024, 10, 3),
|
||||
season = 6,
|
||||
seasonLabel = "Season 6"
|
||||
});
|
||||
pvpSeasons.Add(new PvpSeason
|
||||
{
|
||||
startDate = new DateTime(2023, 10, 3),
|
||||
season = 7,
|
||||
seasonLabel = "Season 7"
|
||||
});
|
||||
currentlySelectedSeason = pvpSeasons[7];
|
||||
}
|
||||
|
||||
public void DrawMainWindow()
|
||||
{
|
||||
if (!Visible)
|
||||
{
|
||||
pickedClass = false;
|
||||
return;
|
||||
}
|
||||
List<PvpWinEntry> list = (currentData = JsonConvert.DeserializeObject<List<PvpWinEntry>>(File.ReadAllText(DataPath + "pvpstats.json")) ?? new List<PvpWinEntry>());
|
||||
List<PvpWinEntry> list2 = list.FindAll((PvpWinEntry c) => !c.matchDate.HasValue);
|
||||
List<PvpWinEntry> list3 = list.FindAll((PvpWinEntry c) => c.matchDate >= new DateTime(2022, 7, 6) && c.matchDate <= new DateTime(2022, 8, 22));
|
||||
List<PvpWinEntry> list4 = list.FindAll((PvpWinEntry c) => c.matchDate >= new DateTime(2022, 8, 22) && c.matchDate <= new DateTime(2022, 10, 31));
|
||||
List<PvpWinEntry> list5 = list.FindAll((PvpWinEntry c) => c.matchDate >= new DateTime(2022, 11, 1) && c.matchDate <= new DateTime(2023, 1, 10));
|
||||
List<PvpWinEntry> list6 = list.FindAll((PvpWinEntry c) => c.matchDate >= new DateTime(2023, 1, 10) && c.matchDate <= new DateTime(2023, 4, 4));
|
||||
List<PvpWinEntry> list7 = list.FindAll((PvpWinEntry c) => c.matchDate >= new DateTime(2023, 4, 4) && c.matchDate <= new DateTime(2023, 10, 3));
|
||||
List<PvpWinEntry> list8 = list.FindAll((PvpWinEntry c) => c.matchDate >= new DateTime(2023, 10, 3));
|
||||
if (currentlySelectedSeason != null && currentlySelectedSeason.season != 0)
|
||||
{
|
||||
List<PvpWinEntry> list9 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
switch (currentlySelectedSeason.season)
|
||||
{
|
||||
case 1:
|
||||
currentData = list2;
|
||||
list9 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list9;
|
||||
break;
|
||||
case 2:
|
||||
currentData = list3;
|
||||
list9 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list9;
|
||||
break;
|
||||
case 3:
|
||||
currentData = list4;
|
||||
list9 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list9;
|
||||
break;
|
||||
case 4:
|
||||
currentData = list5;
|
||||
list9 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list9;
|
||||
break;
|
||||
case 5:
|
||||
currentData = list6;
|
||||
list9 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list9;
|
||||
break;
|
||||
case 6:
|
||||
currentData = list7;
|
||||
list9 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list9;
|
||||
break;
|
||||
case 7:
|
||||
currentData = list8;
|
||||
list9 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list9;
|
||||
break;
|
||||
}
|
||||
}
|
||||
List<string> list10 = new List<string>();
|
||||
foreach (PvpWinEntry currentDatum in currentData)
|
||||
{
|
||||
if (!list10.Contains(currentDatum.className))
|
||||
{
|
||||
list10.Add(currentDatum.className);
|
||||
}
|
||||
}
|
||||
if (!pickedClass && DalamudApi.ClientState.IsLoggedIn && (GameObject)(object)DalamudApi.ClientState.LocalPlayer != (GameObject)null && ((Character)DalamudApi.ClientState.LocalPlayer).ClassJob.GameData != null)
|
||||
{
|
||||
currentlySelectedClassName = SeString.op_Implicit(((Character)DalamudApi.ClientState.LocalPlayer).ClassJob.GameData.Name);
|
||||
List<PvpWinEntry> list11 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list11;
|
||||
}
|
||||
ImGui.SetNextWindowSize(new Vector2(700f, 330f), (ImGuiCond)4);
|
||||
ImGui.SetNextWindowSizeConstraints(new Vector2(700f, 330f), new Vector2(float.MaxValue, float.MaxValue));
|
||||
if (ImGui.Begin("Crystalline Conflict stats", ref visible, (ImGuiWindowFlags)24) && (GameObject)(object)DalamudApi.ClientState.LocalPlayer != (GameObject)null && ((Character)DalamudApi.ClientState.LocalPlayer).ClassJob.GameData != null)
|
||||
{
|
||||
if (ImGui.BeginCombo("###seasonSelection", (currentlySelectedSeason == null) ? "All" : currentlySelectedSeason.seasonLabel))
|
||||
{
|
||||
foreach (PvpSeason pvpSeason in pvpSeasons)
|
||||
{
|
||||
if (ImGui.Selectable(pvpSeason.seasonLabel))
|
||||
{
|
||||
currentlySelectedSeason = pvpSeason;
|
||||
}
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
if (ImGui.BeginCombo("###jobSelection", (currentlySelectedClassName == null) ? SeString.op_Implicit(((Character)DalamudApi.ClientState.LocalPlayer).ClassJob.GameData.Name) : currentlySelectedClassName))
|
||||
{
|
||||
foreach (string item in list10)
|
||||
{
|
||||
if (ImGui.Selectable(item))
|
||||
{
|
||||
currentlySelectedClassName = item;
|
||||
List<PvpWinEntry> list12 = currentData.FindAll((PvpWinEntry b) => b.className == currentlySelectedClassName);
|
||||
currentClassGames = list12;
|
||||
pickedClass = true;
|
||||
}
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
}
|
||||
ImGui.Separator();
|
||||
if (currentClassGames != null)
|
||||
{
|
||||
List<PvpWinEntry> list13 = currentClassGames.FindAll((PvpWinEntry b) => !b.win);
|
||||
List<PvpWinEntry> list14 = currentClassGames.FindAll((PvpWinEntry b) => b.win);
|
||||
int count = list14.FindAll((PvpWinEntry b) => b.ranked).Count;
|
||||
int count2 = list14.FindAll((PvpWinEntry b) => !b.ranked).Count;
|
||||
int count3 = list13.FindAll((PvpWinEntry b) => b.ranked).Count;
|
||||
int count4 = list13.FindAll((PvpWinEntry b) => !b.ranked).Count;
|
||||
decimal num = default(decimal);
|
||||
if (count3 > 0 || count > 0)
|
||||
{
|
||||
num = Math.Round(decimal.Divide(count, count + count3) * 100m, 2);
|
||||
}
|
||||
decimal num2 = default(decimal);
|
||||
if (count2 > 0 || count4 > 0)
|
||||
{
|
||||
num2 = Math.Round(decimal.Divide(count2, count2 + count4) * 100m, 2);
|
||||
}
|
||||
ImGui.Text(currentlySelectedClassName + " stats");
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 1f, 1f), "Ranked");
|
||||
ImGui.TextColored(new Vector4(1f, 0f, 0f, 1f), "Losses: " + count3);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 0f, 1f), "Wins: " + count);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 0f, 1f), "(WR: " + num + " %%)");
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 1f, 1f), "Casual");
|
||||
ImGui.TextColored(new Vector4(1f, 0f, 0f, 1f), "Losses: " + count4);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 0f, 1f), "Wins: " + count2);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 0f, 1f), "(WR: " + num2 + " %%)");
|
||||
ImGui.Separator();
|
||||
List<PvpWinEntry> list15 = currentData.FindAll((PvpWinEntry w) => w.win && w.ranked);
|
||||
List<PvpWinEntry> list16 = currentData.FindAll((PvpWinEntry w) => !w.win && w.ranked);
|
||||
decimal num3 = default(decimal);
|
||||
if (list15.Count > 0 && list16.Count > 0)
|
||||
{
|
||||
num3 = Math.Round(decimal.Divide(list15.Count, list15.Count + list16.Count) * 100m, 2);
|
||||
}
|
||||
ImGui.Text("Total stats");
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 1f, 1f), "Ranked");
|
||||
ImGui.TextColored(new Vector4(1f, 0f, 0f, 1f), "Losses: " + list16.Count);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 0f, 1f), "Wins: " + list15.Count);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 0f, 1f), "(WR: " + num3 + " %%)");
|
||||
List<PvpWinEntry> list17 = currentData.FindAll((PvpWinEntry w) => w.win && !w.ranked);
|
||||
List<PvpWinEntry> list18 = currentData.FindAll((PvpWinEntry w) => !w.win && !w.ranked);
|
||||
decimal num4 = default(decimal);
|
||||
if (list17.Count > 0 && list18.Count > 0)
|
||||
{
|
||||
num4 = Math.Round(decimal.Divide(list17.Count, list17.Count + list18.Count) * 100m, 2);
|
||||
}
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 1f, 1f), "Casual");
|
||||
ImGui.TextColored(new Vector4(1f, 0f, 0f, 1f), "Losses: " + list18.Count);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 0f, 1f), "Wins: " + list17.Count);
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0f, 1f, 0f, 1f), "(WR: " + num4 + " %%)");
|
||||
}
|
||||
ImGui.End();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
DrawMainWindow();
|
||||
DrawSettingsWindow();
|
||||
}
|
||||
|
||||
public void DrawSettingsWindow()
|
||||
{
|
||||
if (!SettingsVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ImGui.SetNextWindowSize(new Vector2(450f, 100f), (ImGuiCond)1);
|
||||
if (ImGui.Begin("World Map Enhancer Settings", ref settingsVisible, (ImGuiWindowFlags)58))
|
||||
{
|
||||
bool enabled = configuration.Enabled;
|
||||
if (ImGui.Checkbox("Enable zooming out with right click", ref enabled))
|
||||
{
|
||||
configuration.Enabled = enabled;
|
||||
configuration.Save();
|
||||
}
|
||||
int rightClickDelay = configuration.RightClickDelay;
|
||||
if (ImGui.InputInt("Right click release delay", ref rightClickDelay, 25, 100))
|
||||
{
|
||||
configuration.RightClickDelay = rightClickDelay;
|
||||
configuration.Save();
|
||||
}
|
||||
}
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace CrystallineConflictWinsTracker;
|
||||
|
||||
public class PvpSeason
|
||||
{
|
||||
public DateTime startDate { get; set; }
|
||||
|
||||
public DateTime? endDate { get; set; }
|
||||
|
||||
public int season { get; set; }
|
||||
|
||||
public string seasonLabel { get; set; }
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace CrystallineConflictWinsTracker;
|
||||
|
||||
public class PvpWinEntry
|
||||
{
|
||||
public bool ranked { get; set; }
|
||||
|
||||
public bool win { get; set; }
|
||||
|
||||
public uint classId { get; set; }
|
||||
|
||||
public string className { get; set; }
|
||||
|
||||
public DateTime? matchDate { get; set; }
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
namespace CrystallineConflictWinsTracker;
|
||||
|
||||
public class Service
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
|
||||
[assembly: AssemblyCompany("aRkker")]
|
||||
[assembly: AssemblyConfiguration("Release")]
|
||||
[assembly: AssemblyDescription("Yes, we track winners only here")]
|
||||
[assembly: AssemblyFileVersion("0.0.2.9")]
|
||||
[assembly: AssemblyInformationalVersion("0.0.1.4")]
|
||||
[assembly: AssemblyProduct("CrystallineConflictWinsTracker")]
|
||||
[assembly: AssemblyTitle("CrystallineConflictWinsTracker")]
|
||||
[assembly: AssemblyVersion("0.0.2.9")]
|
||||
Reference in New Issue
Block a user