using HarmonyLib; using UnityEngine; namespace TownOfUsStatsExporter.Patches; /// /// Tracks when the game actually starts (after intro cutscene ends). /// This allows calculating actual game duration instead of lobby time. /// [HarmonyPatch] public static class GameStartTimePatch { /// /// Time when the game started (after intro cutscene), in Unity Time.time format. /// Null if game hasn't started yet. /// public static float? GameStartTime { get; private set; } /// /// Duration of the last completed game in seconds. /// Set when the game ends, persists until next game starts. /// public static float LastGameDuration { get; private set; } /// /// Gets the duration of the last completed game in seconds. /// This value is set when the game ends and remains available for async export. /// public static float GetGameDuration() { return LastGameDuration; } /// /// Patch on ShipStatus.Begin - called when the game round starts. /// This is more reliable than IntroCutscene.OnDestroy as it's always called when gameplay begins. /// [HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.Begin))] [HarmonyPostfix] public static void OnShipStatusBegin() { GameStartTime = Time.time; LastGameDuration = 0f; // Reset duration for new game TownOfUsStatsPlugin.Logger.LogInfo($"Game started at Time.time = {GameStartTime.Value:F2}"); } /// /// Calculate and store game duration when game ends. /// This runs before the export, so duration is available for async export. /// [HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnGameEnd))] [HarmonyPrefix] public static void OnGameEndPrefix() { if (GameStartTime.HasValue) { LastGameDuration = Time.time - GameStartTime.Value; TownOfUsStatsPlugin.Logger.LogInfo($"Game ended. Duration: {LastGameDuration:F2} seconds ({LastGameDuration / 60:F2} minutes)"); } else { LastGameDuration = 0f; TownOfUsStatsPlugin.Logger.LogWarning("Game ended but GameStartTime was not set! Duration will be 0."); } } /// /// Clear game start time after game ends to prepare for next game. /// LastGameDuration is preserved for async export. /// [HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnGameEnd))] [HarmonyPostfix] [HarmonyPriority(Priority.Last)] public static void OnGameEndPostfix() { GameStartTime = null; TownOfUsStatsPlugin.Logger.LogInfo("Game start time cleared (duration preserved for export)"); } }