using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Agents;
using BepInEx;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils;
using GTFOStats.Data;
using GTFOStats.Patches;
using GameData;
using GameEvent;
using HarmonyLib;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Localization;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Danos-GTFOStats")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a051f01da11965b6cb59b661659a7a43d6a851c8")]
[assembly: AssemblyProduct("Danos-GTFOStats")]
[assembly: AssemblyTitle("Danos-GTFOStats")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace GTFOStats
{
[BepInPlugin("danos.GTFOStats", "GTFOStats", "0.5.4")]
public class Plugin : BasePlugin
{
public override void Load()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
((BasePlugin)this).Log.LogInfo((object)"GTFOStats is loaded!");
Harmony val = new Harmony("danos.GTFOStats");
val.PatchAll(typeof(GameStatePatch));
}
}
}
namespace GTFOStats.Patches
{
[HarmonyPatch]
internal static class GameStatePatch
{
private static Coroutine positionCollectorCoroutine;
[HarmonyPatch(typeof(GameEventManager), "PostEvent", new Type[]
{
typeof(eGameEvent),
typeof(PlayerAgent),
typeof(float),
typeof(string),
typeof(Dictionary<string, string>)
})]
[HarmonyPrefix]
public static void Patch_PostEvent_Overload2(eGameEvent e, PlayerAgent player, float floatVal, string stringVal, Dictionary<string, string> customAnalyticsPayload)
{
string text = ((object)(eGameEvent)(ref e)).ToString();
if (text == "gs_StopElevatorRide")
{
Console.WriteLine("Elevator ride ended");
ResetRunDownData();
InitializeRunDownData();
StartPositionCollector();
return;
}
if (text == "gs_ExpeditionFail" || text == "gs_ExpeditionSuccess")
{
Console.WriteLine("Expedition ended");
ExportRunDownData(text);
StopPositionCollector();
return;
}
switch (text)
{
case "gs_ExpeditionAbort":
Console.WriteLine("Expedition Aborted");
ExportRunDownData(text);
StopPositionCollector();
break;
case "player_downed":
DanosStaticStore.currentRunDownDataStore.AddPlayerDownData((long)player.Owner.Lookup, player);
break;
case "player_reload":
DanosStaticStore.currentRunDownDataStore.AddPlayerReloadData((long)player.Owner.Lookup);
break;
case "player_apply_medikit":
DanosStaticStore.currentRunDownDataStore.AddPlayerHealthPackUsed((long)player.Owner.Lookup);
break;
case "player_apply_ammokit":
DanosStaticStore.currentRunDownDataStore.AddPlayerAmmoPackUsed((long)player.Owner.Lookup);
break;
case "player_apply_disinfection":
DanosStaticStore.currentRunDownDataStore.AddPlayerDisinfectionUsed((long)player.Owner.Lookup);
break;
case "player_pickup_artifact":
DanosStaticStore.currentRunDownDataStore.AddPlayerArtifactPickup((long)player.Owner.Lookup);
break;
case "player_place_tripmine":
DanosStaticStore.currentRunDownDataStore.AddPlayerTripMinePlaced((long)player.Owner.Lookup);
break;
case "player_pickup_keycard":
DanosStaticStore.currentRunDownDataStore.AddPlayerKeyCardPickup((long)player.Owner.Lookup);
break;
case "player_hacking_success":
DanosStaticStore.currentRunDownDataStore.AddPlayerHackingSuccess((long)player.Owner.Lookup);
break;
case "bioscan_start":
DanosStaticStore.currentRunDownDataStore.IncrementBioscanStart();
break;
case "scout_enemy_dead":
DanosStaticStore.currentRunDownDataStore.IncrementScoutEnemiesDead();
break;
case "enemy_dead":
DanosStaticStore.currentRunDownDataStore.IncrementEnemiesDead();
break;
case "enemy_wave_spawned":
DanosStaticStore.currentRunDownDataStore.IncrementEnemyWavesSpawned();
break;
case "scout_enemy_found_player":
DanosStaticStore.currentRunDownDataStore.IncrementScoutEnemiesFoundPlayer();
break;
case "hibernating_enemy_dead":
DanosStaticStore.currentRunDownDataStore.IncrementHibernatingEnemiesDead();
break;
case "hibernating_enemy_wakeup":
DanosStaticStore.currentRunDownDataStore.IncrementHibernatingEnemiesWokeUp();
break;
case "enemy_dead_from_melee":
DanosStaticStore.currentRunDownDataStore.IncrementEnemiesDeadFromMelee();
break;
case "enemy_scout_dead_from_melee":
DanosStaticStore.currentRunDownDataStore.IncrementScoutEnemiesDeadFromMelee();
break;
}
}
private static void StartPositionCollector()
{
if (positionCollectorCoroutine == null)
{
PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
positionCollectorCoroutine = ((localPlayerAgent != null) ? MonoBehaviourExtensions.StartCoroutine((MonoBehaviour)(object)localPlayerAgent, CollectPositionsCoroutine()) : null);
if (positionCollectorCoroutine == null)
{
Console.WriteLine("Failed to start position collector coroutine.");
}
}
}
private static void CollectPlayerPositions()
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
try
{
List<PlayerAgent> playerAgentsInLevel = PlayerManager.PlayerAgentsInLevel;
long st = DanosStaticStore.currentRunDownDataStore.st;
long num = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
long timestamp = num - st;
Enumerator<PlayerAgent> enumerator = playerAgentsInLevel.GetEnumerator();
while (enumerator.MoveNext())
{
PlayerAgent current = enumerator.Current;
if (!((Object)(object)current == (Object)null) && ((Agent)current).m_replicator != null)
{
Vector3 position = ((Component)current).transform.position;
ulong lookup = ((Agent)current).m_replicator.OwningPlayer.Lookup;
DanosPositionalDataTransfer dataTransfer = new DanosPositionalDataTransfer
{
x = position.x,
z = position.z,
Timestamp = timestamp,
sid = (long)lookup,
Name = current.PlayerName
};
DanosStaticStore.currentRunDownDataStore.AddPositionalData(dataTransfer);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error collecting player positions: " + ex.Message);
}
}
private static IEnumerator CollectPositionsCoroutine()
{
while (true)
{
CollectPlayerPositions();
yield return (object)new WaitForSeconds(3f);
}
}
private static void StopPositionCollector()
{
if (positionCollectorCoroutine != null)
{
PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
if (localPlayerAgent != null)
{
((MonoBehaviour)localPlayerAgent).StopCoroutine(positionCollectorCoroutine);
}
positionCollectorCoroutine = null;
}
}
private static void ExportRunDownData(string reason)
{
try
{
if (DanosStaticStore.currentRunDownDataStore == null)
{
Debug.LogError(Object.op_Implicit("No rundown data store to export."));
return;
}
JsonSerializerOptions options = new JsonSerializerOptions
{
WriteIndented = true,
Converters = { (JsonConverter)new OneDecimalJsonConverter() }
};
DanosStaticStore.currentRunDownDataStore.et = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
DanosStaticStore.currentRunDownDataStore.rer = reason;
DanosStaticStore.currentRunDownDataStore.wasHost = SNet.IsMaster;
List<PlayerAgent> playerAgentsInLevel = PlayerManager.PlayerAgentsInLevel;
Enumerator<PlayerAgent> enumerator = playerAgentsInLevel.GetEnumerator();
while (enumerator.MoveNext())
{
PlayerAgent current = enumerator.Current;
if (!((Object)(object)current == (Object)null) && ((Agent)current).m_replicator != null)
{
DanosStaticStore.currentRunDownDataStore.AddPlayerToSummary((long)((Agent)current).m_replicator.OwningPlayer.Lookup, current);
}
}
string json = JsonSerializer.Serialize(DanosStaticStore.currentRunDownDataStore, options);
List<string> list = new List<string>();
foreach (Func<string> jsonContributor in DanosStaticStore.JsonContributors)
{
try
{
string text = jsonContributor();
if (!string.IsNullOrEmpty(text))
{
list.Add(text);
}
}
catch (Exception ex)
{
Console.WriteLine("Error invoking JSON contributor: " + ex.Message);
}
}
Dictionary<string, object> dictionary = JsonSerializer.Deserialize<Dictionary<string, object>>(json, options);
foreach (string item in list)
{
Dictionary<string, object> dictionary2 = JsonSerializer.Deserialize<Dictionary<string, object>>(item, options);
if (dictionary2 == null)
{
continue;
}
foreach (KeyValuePair<string, object> item2 in dictionary2)
{
dictionary[item2.Key] = item2.Value;
}
}
string text2 = JsonSerializer.Serialize(dictionary, options);
string text3 = Path.Combine(Application.persistentDataPath, "RunDownData.json");
File.WriteAllText(text3, text2);
Console.WriteLine("Rundown data exported to " + text3);
PostDataToAPI(text2).Wait();
}
catch (Exception ex2)
{
Console.WriteLine("Error exporting rundown data: " + ex2.Message);
}
}
private static async Task PostDataToAPI(string json)
{
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13;
using HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync("https://gtfoapi.splitstats.io/api/rundown/upload", content);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Data posted to API successfully.");
return;
}
Console.WriteLine($"Error posting data to API: {response.StatusCode}");
}
catch (Exception ex2)
{
Exception ex = ex2;
Console.WriteLine("Error posting data to API: " + ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine("Inner Exception: " + ex.InnerException.Message);
}
}
}
private static void InitializeRunDownData()
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Invalid comparison between Unknown and I4
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
try
{
pActiveExpedition activeExpeditionData = RundownManager.GetActiveExpeditionData();
if ((int)activeExpeditionData.tier != 1 || activeExpeditionData.expeditionIndex == 0)
{
}
RundownName currentRundownName = AchievementManager.GetCurrentRundownName();
string rid = ((object)(RundownName)(ref currentRundownName)).ToString();
eRundownTier val = activeExpeditionData.tier;
string en = ((object)(eRundownTier)(ref val)).ToString();
string text = activeExpeditionData.expeditionIndex.ToString();
string rsg = activeExpeditionData.sessionGUID.m_data.ToString();
DanosExtraRundownData extraData = new DanosExtraRundownData();
try
{
string storyTitle = "";
string otherTitle = "";
string storyDescription = "";
uint num = default(uint);
if (RundownManager.TryGetIdFromLocalRundownKey(RundownManager.ActiveRundownKey, ref num))
{
RundownDataBlock block = GameDataBlockBase<RundownDataBlock>.GetBlock(num);
storyTitle = LocalizedText.op_Implicit(block.StorytellingData.Title);
storyDescription = LocalizedText.op_Implicit(block.StorytellingData.SurfaceDescription);
otherTitle = LocalizedText.op_Implicit(block.StorytellingData.ExternalExpTitle);
}
ExpeditionInTierData activeExpedition = RundownManager.ActiveExpedition;
DescriptiveData descriptive = activeExpedition.Descriptive;
string rundownprefix = descriptive.Prefix + ((!descriptive.SkipExpNumberInName) ? (text + 1).ToString() : "");
string rundownName = descriptive.PublicName + (descriptive.IsExtraExpedition ? "://EXT" : "");
string devInfo = descriptive.DevInfo;
val = descriptive.CustomMatchmakingTier;
string matchmakingtier = ((object)(eRundownTier)(ref val)).ToString();
string desc = LocalizedText.op_Implicit(descriptive.ExpeditionDescription);
string depth = descriptive.ExpeditionDepth.ToString();
extraData = new DanosExtraRundownData
{
rundownKey = RundownManager.ActiveRundownKey,
rundownName = rundownName,
otherTitle = otherTitle,
rundownprefix = rundownprefix,
storyDescription = storyDescription,
storyTitle = storyTitle,
devInfo = devInfo,
matchmakingtier = matchmakingtier,
desc2 = desc,
depth = depth
};
}
catch (Exception ex)
{
Debug.LogError(Object.op_Implicit("Error initializing DanosExtraRundownData: " + ex.Message));
}
DanosRunDownDataStore currentRunDownDataStore = new DanosRunDownDataStore
{
st = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
rid = rid,
en = en,
ei = text,
rsg = rsg,
msid = GetLocalPlayerSteamID(),
mv = "0.5.4",
extraData = extraData
};
DanosStaticStore.currentRunDownDataStore = currentRunDownDataStore;
}
catch (Exception ex2)
{
Debug.LogError(Object.op_Implicit("Error initializing DanosRunDownDataStore: " + ex2.Message));
}
}
private static void LogEventData(string eventName, PlayerAgent player, string customString, float floatVal = 0f, Dictionary<string, string> customAnalyticsPayload = null)
{
try
{
if (customAnalyticsPayload == null)
{
customAnalyticsPayload = new Dictionary<string, string>();
}
Dictionary<string, string> dictionary = new Dictionary<string, string>();
Enumerator<string, string> enumerator = customAnalyticsPayload.GetEnumerator();
while (enumerator.MoveNext())
{
KeyValuePair<string, string> current = enumerator.Current;
if (current.Key != null && current.Value != null && !dictionary.ContainsKey(current.Key))
{
dictionary[current.Key] = current.Value;
}
}
DanosGameEvent value = new DanosGameEvent
{
eventName = eventName,
playerInfo = (((player != null) ? player.PlayerName : null) ?? "No Player"),
customString = (customString ?? "No String")
};
string text = JsonSerializer.Serialize(value);
Console.WriteLine("Event Data: " + text);
}
catch (Exception ex)
{
Debug.LogError(Object.op_Implicit("Error logging event data: " + ex.Message));
}
}
private static long GetLocalPlayerSteamID()
{
try
{
PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
ulong? obj;
if (localPlayerAgent == null)
{
obj = null;
}
else
{
SNet_Replicator replicator = ((Agent)localPlayerAgent).m_replicator;
obj = ((replicator != null) ? new ulong?(replicator.OwningPlayer.Lookup) : null);
}
ulong? num = obj;
return (long)num.GetValueOrDefault();
}
catch
{
return 0L;
}
}
public static void ResetRunDownData()
{
DanosStaticStore.currentRunDownDataStore = new DanosRunDownDataStore();
}
}
public class DanosGameEvent
{
public string eventName { get; set; }
public string playerInfo { get; set; }
public string customString { get; set; }
}
}
namespace GTFOStats.Data
{
public class DanosStaticStore
{
public const string ModVersion = "0.5.4";
public static List<Func<string>> JsonContributors = new List<Func<string>>();
public static DanosRunDownDataStore currentRunDownDataStore { get; set; } = new DanosRunDownDataStore();
public static void RegisterJsonContributor(Func<string> contributor)
{
if (contributor != null)
{
JsonContributors.Add(contributor);
}
}
}
public class DanosRunDownDataStore
{
public bool wasHost { get; set; } = false;
public string mv { get; set; } = "0.5.4";
public string rer { get; set; } = "";
public long st { get; set; } = 0L;
public long et { get; set; } = 0L;
public string rid { get; set; } = "";
public string en { get; set; } = "";
public string ei { get; set; } = "";
public string rsg { get; set; } = "";
public long msid { get; set; } = 0L;
public int bioscanStarts { get; set; } = 0;
public int scoutEnemiesDead { get; set; } = 0;
public int enemiesDead { get; set; } = 0;
public int enemyWavesSpawned { get; set; } = 0;
public int scoutEnemiesFoundPlayer { get; set; } = 0;
public int hibernatingEnemiesDead { get; set; } = 0;
public int hibernatingEnemiesWokeUp { get; set; } = 0;
public int enemiesDeadFromMelee { get; set; } = 0;
public int scoutEnemiesDeadFromMelee { get; set; } = 0;
public DanosExtraRundownData extraData { get; set; } = new DanosExtraRundownData();
public Dictionary<long, string> pl { get; set; } = new Dictionary<long, string>();
public Dictionary<long, List<DanosPositionalData>> pd { get; set; } = new Dictionary<long, List<DanosPositionalData>>();
public Dictionary<long, DanosSummaryData> sd { get; set; } = new Dictionary<long, DanosSummaryData>();
public Dictionary<long, DanosDeathSummary> ds { get; set; } = new Dictionary<long, DanosDeathSummary>();
public void IncrementBioscanStart()
{
bioscanStarts++;
}
public void IncrementScoutEnemiesDead()
{
scoutEnemiesDead++;
}
public void IncrementEnemiesDead()
{
enemiesDead++;
}
public void IncrementEnemyWavesSpawned()
{
enemyWavesSpawned++;
}
public void IncrementScoutEnemiesFoundPlayer()
{
scoutEnemiesFoundPlayer++;
}
public void IncrementHibernatingEnemiesDead()
{
hibernatingEnemiesDead++;
}
public void IncrementHibernatingEnemiesWokeUp()
{
hibernatingEnemiesWokeUp++;
}
public void IncrementEnemiesDeadFromMelee()
{
enemiesDeadFromMelee++;
}
public void IncrementScoutEnemiesDeadFromMelee()
{
scoutEnemiesDeadFromMelee++;
}
public void AddPlayerDownData(long sid, PlayerAgent playerAgent)
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].downs++;
if (!ds.ContainsKey(sid))
{
ds[sid] = new DanosDeathSummary();
}
ds[sid].x = ((Component)playerAgent).transform.position.x;
ds[sid].z = ((Component)playerAgent).transform.position.z;
}
public void AddPlayerReloadData(long sid)
{
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].reloads++;
}
public void AddPlayerHealthPackUsed(long sid)
{
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].healthpacksused++;
}
public void AddPlayerAmmoPackUsed(long sid)
{
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].ammopacksused++;
}
public void AddPlayerArtifactPickup(long sid)
{
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].artifacts++;
}
public void AddPlayerDisinfectionUsed(long sid)
{
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].disinfections++;
}
public void AddPlayerTripMinePlaced(long sid)
{
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].tripminesplaced++;
}
public void AddPlayerKeyCardPickup(long sid)
{
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].keycards++;
}
public void AddPlayerHackingSuccess(long sid)
{
if (!sd.ContainsKey(sid))
{
sd[sid] = new DanosSummaryData();
}
sd[sid].hackingSuccesses++;
}
public void AddPositionalData(DanosPositionalDataTransfer dataTransfer)
{
if (!pl.ContainsKey(dataTransfer.sid))
{
pl[dataTransfer.sid] = dataTransfer.Name;
}
if (!pd.ContainsKey(dataTransfer.sid))
{
pd[dataTransfer.sid] = new List<DanosPositionalData>();
}
pd[dataTransfer.sid].Add(new DanosPositionalData
{
x = (float)dataTransfer.x,
z = (float)dataTransfer.z,
rt = (int)dataTransfer.Timestamp
});
}
public void AddPlayerToSummary(long lookup, PlayerAgent playerAgent)
{
if (!pl.ContainsKey(lookup))
{
pl[lookup] = playerAgent.PlayerName;
}
if (!sd.ContainsKey(lookup))
{
sd[lookup] = new DanosSummaryData();
}
}
}
public class DanosPositionalData
{
[JsonConverter(typeof(OneDecimalJsonConverter))]
public float x { get; set; }
[JsonConverter(typeof(OneDecimalJsonConverter))]
public float z { get; set; }
public int rt { get; set; }
}
public class DanosPositionalDataTransfer
{
public double x { get; set; }
public double z { get; set; }
public long Timestamp { get; set; }
public long sid { get; set; }
public string Name { get; set; }
}
public class DanosDeathSummary
{
[JsonConverter(typeof(OneDecimalJsonConverter))]
public float x { get; set; } = 0f;
[JsonConverter(typeof(OneDecimalJsonConverter))]
public float z { get; set; } = 0f;
}
public class DanosExtraRundownData
{
public string storyTitle { get; set; } = "";
public string storyDescription { get; set; } = "";
public string rundownKey { get; set; } = "";
public string rundownprefix { get; set; } = "";
public string rundownName { get; set; } = "";
public string devInfo { get; set; } = "";
public string matchmakingtier { get; set; } = "";
public string desc2 { get; set; } = "";
public string depth { get; set; } = "";
public string otherTitle { get; set; } = "";
}
public class DanosSummaryData
{
public int reloads { get; set; } = 0;
public int downs { get; set; } = 0;
public int healthpacksused { get; set; } = 0;
public int ammopacksused { get; set; } = 0;
public int artifacts { get; set; } = 0;
public int disinfections { get; set; } = 0;
public int tripminesplaced { get; set; } = 0;
public int keycards { get; set; } = 0;
public int hackingSuccesses { get; set; } = 0;
}
public class OneDecimalJsonConverter : JsonConverter<float>
{
public override float Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return (float)reader.GetDouble();
}
public override void Write(Utf8JsonWriter writer, float value, JsonSerializerOptions options)
{
writer.WriteNumberValue(Math.Round(value, 1));
}
}
}