catastropy averted?

This commit is contained in:
2026-04-30 11:18:02 +03:00
parent 3e19aac2c2
commit 585abc7132
149 changed files with 25785 additions and 14 deletions
@@ -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>
@@ -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);
}
}
@@ -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>());
}
}
@@ -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;
}
}
@@ -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();
}
}
@@ -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; }
}
@@ -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; }
}
@@ -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")]