Decompiled source of TimeAttack v1.0.1

TimeAttack.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using REPOLib.Modules;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TimeAttack")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TimeAttack")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("bef66bd7-b3d3-41df-a8f0-e5f682750c8e")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TimeAttack;

internal class ConfigManager
{
	public static DifficultyManager.LevelTimeDifficulty levelTimeDifficulty = DifficultyManager.LevelTimeDifficulty.Normal;

	public static DifficultyManager.ExtractionBonusDifficulty extractionBonusDifficulty = DifficultyManager.ExtractionBonusDifficulty.Normal;

	public static DifficultyManager.FinalExtractionDifficulty finalExtractionDifficulty = DifficultyManager.FinalExtractionDifficulty.Normal;

	public static DifficultyManager.RemainingTimeBonus remainingTimeBonus = DifficultyManager.RemainingTimeBonus.Normal;

	public static void Set()
	{
		levelTimeDifficulty = Plugin.ltd.Value;
		extractionBonusDifficulty = Plugin.ebd.Value;
		finalExtractionDifficulty = Plugin.fed.Value;
		remainingTimeBonus = Plugin.rtb.Value;
	}
}
public class DifficultyManager
{
	public enum LevelTimeDifficulty
	{
		Lenient,
		Easy,
		Normal,
		Hard,
		Extreme,
		Impossible
	}

	public enum ExtractionBonusDifficulty
	{
		Lenient,
		Easy,
		Normal,
		Hard,
		Extreme,
		Impossible
	}

	public enum FinalExtractionDifficulty
	{
		Lenient,
		Easy,
		Normal,
		Hard,
		Extreme,
		Impossible
	}

	public enum RemainingTimeBonus
	{
		None,
		Little,
		Less,
		Normal,
		More,
		Double
	}

	public static float LevelTimeDifficultyMultiplier => ConfigManager.levelTimeDifficulty switch
	{
		LevelTimeDifficulty.Lenient => 2f, 
		LevelTimeDifficulty.Easy => 1.5f, 
		LevelTimeDifficulty.Normal => 1f, 
		LevelTimeDifficulty.Hard => 0.75f, 
		LevelTimeDifficulty.Extreme => 0.5f, 
		LevelTimeDifficulty.Impossible => 0.25f, 
		_ => 1f, 
	};

	public static float ExtractionBonusDifficultyMultiplier => ConfigManager.extractionBonusDifficulty switch
	{
		ExtractionBonusDifficulty.Lenient => 2f, 
		ExtractionBonusDifficulty.Easy => 1.5f, 
		ExtractionBonusDifficulty.Normal => 1f, 
		ExtractionBonusDifficulty.Hard => 0.75f, 
		ExtractionBonusDifficulty.Extreme => 0.5f, 
		ExtractionBonusDifficulty.Impossible => 0.25f, 
		_ => 1f, 
	};

	public static float FinalExtractionDifficultyMultiplier => ConfigManager.finalExtractionDifficulty switch
	{
		FinalExtractionDifficulty.Lenient => 1.75f, 
		FinalExtractionDifficulty.Easy => 1.33f, 
		FinalExtractionDifficulty.Normal => 0.8f, 
		FinalExtractionDifficulty.Hard => 0.6f, 
		FinalExtractionDifficulty.Extreme => 0.35f, 
		FinalExtractionDifficulty.Impossible => 0.2f, 
		_ => 1f, 
	};

	public static float RemainingTimeBonusMultiplier => ConfigManager.remainingTimeBonus switch
	{
		RemainingTimeBonus.None => 0f, 
		RemainingTimeBonus.Little => 0.25f, 
		RemainingTimeBonus.Less => 0.5f, 
		RemainingTimeBonus.Normal => 1f, 
		RemainingTimeBonus.More => 1.4f, 
		RemainingTimeBonus.Double => 2f, 
		_ => 1f, 
	};
}
internal class NotificationManager
{
	public enum NotificationEmoji
	{
		Clock,
		Money
	}

	public static float notificationTimer = 0f;

	public static string notificationText = "";

	public static NotificationEmoji notificationEmoji = NotificationEmoji.Clock;

	private static readonly Dictionary<NotificationEmoji, string> emojis = new Dictionary<NotificationEmoji, string>
	{
		{
			NotificationEmoji.Clock,
			"{clock}"
		},
		{
			NotificationEmoji.Money,
			"{$$}"
		}
	};

	public static void Update()
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		if (notificationTimer != 0f)
		{
			notificationTimer = Mathf.Max(0f, notificationTimer - Time.deltaTime);
			SemiFunc.UIBigMessage(notificationText, emojis[notificationEmoji], 28f, new Color(0f, 1f, 0.2f), Color.white);
		}
	}

	public static void ShowTimerExtendedMessage(float seconds)
	{
		notificationTimer = 2.5f;
		notificationText = $"<size=48>+{Mathf.RoundToInt(seconds)}</size> SEC.";
		notificationEmoji = NotificationEmoji.Clock;
	}

	public static void ShowBonusMoneyMessage(int amount)
	{
		notificationTimer = 3f;
		notificationText = $"<size=48>+${Mathf.RoundToInt((float)amount)}K</size>\nTIME BONUS";
		notificationEmoji = NotificationEmoji.Money;
	}
}
internal class Patches
{
	private static float surplusBonusFactor = 1f;

	[HarmonyPatch(typeof(RunManager), "Update")]
	[HarmonyPostfix]
	private static void RunManager_Update()
	{
		if (SemiFunc.RunIsLevel())
		{
			TimeManager.Update();
		}
	}

	[HarmonyPatch(typeof(GoalUI), "Update")]
	[HarmonyPostfix]
	[HarmonyPriority(1)]
	private static void GoalUI_Update(ref TextMeshProUGUI ___Text)
	{
		if (SemiFunc.RunIsLevel())
		{
			((TMP_Text)___Text).text = "<line-height=75%>" + ((TMP_Text)___Text).text + "\n" + TimeManager.timerString;
			((TMP_Text)___Text).alignment = (TextAlignmentOptions)260;
		}
	}

	[HarmonyPatch(typeof(RunManager), "ChangeLevel")]
	[HarmonyPostfix]
	public static void RunManager_ChangeLevel(RunManager __instance)
	{
		TimeManager.timerRunning = false;
		if (SemiFunc.RunIsLevel())
		{
			ConfigManager.Set();
			TimeProperties.BaseLevelTimer = TimeProperties.GetThisLevelBaseTime(__instance.levelsCompleted + 1);
			TimeManager.SetTimer(TimeProperties.GetThisLevelTime(__instance.levelsCompleted + 1), pause: true);
			Plugin.loggy.LogDebug((object)"Change level called, setting timer");
		}
	}

	[HarmonyPatch(typeof(RunManager), "UpdateLevel")]
	[HarmonyPostfix]
	public static void RunManager_UpdateLevel(RunManager __instance)
	{
		TimeManager.timerRunning = false;
		if (SemiFunc.RunIsLevel())
		{
			TimeProperties.BaseLevelTimer = TimeProperties.GetThisLevelBaseTime(__instance.levelsCompleted + 1);
			TimeManager.SetTimer(TimeProperties.GetThisLevelTime(__instance.levelsCompleted + 1), pause: true);
			Plugin.loggy.LogDebug((object)"Change level called, setting timer");
		}
	}

	[HarmonyPatch(typeof(ExtractionPoint), "ButtonPress")]
	[HarmonyPostfix]
	public static void ExtractionPoint_ButtonPress()
	{
		if (SemiFunc.RunIsLevel())
		{
			if (!TimeManager.timerRunning)
			{
				TimeProperties.BaseLevelTimer = TimeProperties.GetThisLevelBaseTime(RunManager.instance.levelsCompleted + 1);
				TimeManager.SetTimer(TimeProperties.GetThisLevelTime(RunManager.instance.levelsCompleted + 1));
				TimeManager.timerRunning = true;
				Plugin.loggy.LogDebug((object)"Extraction activated, starting timer...");
			}
			else
			{
				Plugin.loggy.LogDebug((object)"Extraction activated, adding time...");
				TimeManager.SetTimer(TimeManager.currentTimeRemaining);
				TimeManager.AddTimeToTimer(TimeProperties.ExtractionActivationBonusTime);
			}
		}
	}

	[HarmonyPatch(typeof(ExtractionPoint), "StateExtracting")]
	[HarmonyPostfix]
	public static void ExtractionPoint_StateExtracting(ref ExtractionPoint __instance)
	{
		if (SemiFunc.RunIsLevel() && !((Object)(object)__instance != (Object)(object)Traverse.Create((object)RoundDirector.instance).Field("extractionPointCurrent").GetValue<ExtractionPoint>()))
		{
			MethodInfo method = typeof(ExtractionPoint).GetMethod("StateIs", BindingFlags.Instance | BindingFlags.NonPublic);
			if ((bool)method.Invoke(__instance, new object[1] { (object)(State)6 }) && Traverse.Create((object)__instance).Field("tubeHit").GetValue<bool>() && !TimeManager.timerPaused)
			{
				Plugin.loggy.LogDebug((object)"Extraction started, pausing timer...");
				TimeManager.SetTimer(TimeManager.currentTimeRemaining, pause: true);
				int value = Traverse.Create((object)RoundDirector.instance).Field("currentHaul").GetValue<int>();
				int value2 = Traverse.Create((object)__instance).Field("haulSurplus").GetValue<int>();
				surplusBonusFactor = Mathf.Clamp((float)value / Mathf.Max(1000f, (float)value2), 1f, 10f);
			}
		}
	}

	[HarmonyPatch(typeof(RoundDirector), "ExtractionCompleted")]
	[HarmonyPostfix]
	public static void RoundDirector_ExtractionCompleted(ref RoundDirector __instance)
	{
		if (SemiFunc.RunIsLevel())
		{
			int value = Traverse.Create((object)__instance).Field("extractionPointsCompleted").GetValue<int>();
			int value2 = Traverse.Create((object)__instance).Field("extractionPoints").GetValue<int>();
			if (value >= value2)
			{
				Plugin.loggy.LogDebug((object)"All extractions done, setting final extract timer...");
				TimeManager.GenerateBonusMoney(TimeManager.currentTimeRemaining);
				TimeManager.SetTimer(TimeProperties.GetThisLevelFinalExtractTime(RunManager.instance.levelsCompleted + 1));
			}
			else
			{
				Plugin.loggy.LogDebug((object)"Extraction completed, unpausing timer and adding time...");
				TimeManager.SetTimer(TimeManager.currentTimeRemaining);
				TimeManager.AddTimeToTimer(TimeProperties.GetThisLevelAddedTime(RunManager.instance.levelsCompleted + 1, value2 - 1, surplusBonusFactor));
			}
		}
	}
}
[BepInPlugin("Swaggies.TimeAttack", "TimeAttack", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	private const string _guid = "Swaggies.TimeAttack";

	private const string _name = "TimeAttack";

	public const string _ver = "1.0.0";

	private readonly Harmony harmony = new Harmony("Swaggies.TimeAttack");

	public static ManualLogSource loggy;

	public static ConfigEntry<DifficultyManager.LevelTimeDifficulty> ltd;

	public static ConfigEntry<DifficultyManager.ExtractionBonusDifficulty> ebd;

	public static ConfigEntry<DifficultyManager.FinalExtractionDifficulty> fed;

	public static ConfigEntry<DifficultyManager.RemainingTimeBonus> rtb;

	private void Awake()
	{
		loggy = Logger.CreateLogSource("Swaggies.TimeAttack");
		loggy.LogMessage((object)"TimeAttack's up and runnin' on 1.0.0");
		harmony.PatchAll(typeof(Plugin));
		harmony.PatchAll(typeof(Patches));
		Syncing.Setup();
		ltd = ((BaseUnityPlugin)this).Config.Bind<DifficultyManager.LevelTimeDifficulty>("Difficulty Settings", "Level Time Difficulty", DifficultyManager.LevelTimeDifficulty.Normal, "How much time you start each level with. Higher difficulty means less time.");
		ebd = ((BaseUnityPlugin)this).Config.Bind<DifficultyManager.ExtractionBonusDifficulty>("Difficulty Settings", "Extraction Bonus Difficulty", DifficultyManager.ExtractionBonusDifficulty.Normal, "How much time you regain after completing an extraction. Higher difficulty means less time.");
		fed = ((BaseUnityPlugin)this).Config.Bind<DifficultyManager.FinalExtractionDifficulty>("Difficulty Settings", "Final Extraction Difficulty", DifficultyManager.FinalExtractionDifficulty.Normal, "How much time you have to leave the level after completing the final extraction. Higher difficulty means less time.");
		rtb = ((BaseUnityPlugin)this).Config.Bind<DifficultyManager.RemainingTimeBonus>("Difficulty Settings", "Remaining Time Bonus", DifficultyManager.RemainingTimeBonus.Normal, "How much bonus money you earn for completing a level with time to spare.");
	}
}
internal class Syncing
{
	public static NetworkedEvent TimerSync;

	public static NetworkedEvent TimerAdd;

	public static NetworkedEvent TimerSet;

	public static NetworkedEvent GameOverSequence;

	public static NetworkedEvent BonusMoney;

	public static void Setup()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Expected O, but got Unknown
		TimerSync = new NetworkedEvent("Timer Sync", (Action<EventData>)SyncTimer);
		TimerAdd = new NetworkedEvent("Timer Add", (Action<EventData>)AddToTimer);
		TimerSet = new NetworkedEvent("Timer Set", (Action<EventData>)SetTimer);
		GameOverSequence = new NetworkedEvent("Out Of Time Sequence", (Action<EventData>)GameOverSeq);
		BonusMoney = new NetworkedEvent("Remaining Time Bonus", (Action<EventData>)RemainingTimeBonus);
	}

	private static void SyncTimer(EventData eventData)
	{
		float num = (float)eventData.CustomData;
		if (!(Math.Abs(num - TimeManager.currentTimeRemaining) < 0.5f))
		{
			TimeManager.currentTimeRemaining = num;
			Plugin.loggy.LogDebug((object)$"Set timer to {num}");
			if (TimeManager.currentTimeRemaining > 0f || TimeManager.timerPaused)
			{
				TimeManager.gameOverStarted = false;
			}
		}
	}

	private static void AddToTimer(EventData eventData)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		float num = (float)eventData.CustomData;
		TimeManager.gameOverStarted = false;
		NotificationManager.ShowTimerExtendedMessage(num);
		TimeManager.SetTimerPing(TimeManager.timerExtendedPing, 2.25f);
		if (!SemiFunc.IsMasterClientOrSingleplayer())
		{
			TimeManager.currentTimeRemaining += num;
		}
	}

	private static void SetTimer(EventData eventData)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		TimeManager.SetTimerPing(TimeManager.timerNeutralPing, 1.5f);
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			TimeManager.timerPaused = (bool)eventData.CustomData;
			if (TimeManager.timerPaused)
			{
				TimeManager.gameOverStarted = false;
			}
		}
	}

	private static void GameOverSeq(EventData eventData)
	{
		if ((bool)eventData.CustomData)
		{
			TimeManager.gameOverStarted = true;
			TimeManager.gameOverCoroutine = ((MonoBehaviour)RunManager.instance).StartCoroutine(TimeManager.Death());
			return;
		}
		foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
		{
			player.playerHealth.EyeMaterialOverride((EyeOverrideState)0, 0.25f, 2);
		}
		if (TimeManager.gameOverCoroutine != null)
		{
			((MonoBehaviour)RunManager.instance).StopCoroutine(TimeManager.gameOverCoroutine);
		}
		TimeManager.gameOverStarted = false;
	}

	private static void RemainingTimeBonus(EventData eventData)
	{
		int moneyAmount = (int)eventData.CustomData;
		((MonoBehaviour)RunManager.instance).StartCoroutine(RemainingTimeBonusNotification(moneyAmount));
	}

	private static IEnumerator RemainingTimeBonusNotification(int moneyAmount)
	{
		yield return (object)new WaitForSeconds(2.5f);
		NotificationManager.ShowBonusMoneyMessage(moneyAmount);
		SemiFunc.StatSetRunCurrency(SemiFunc.StatGetRunCurrency() + moneyAmount);
		SemiFunc.StatSetRunTotalHaul(SemiFunc.StatGetRunTotalHaul() + moneyAmount);
		CurrencyUI.instance.FetchCurrency();
	}
}
internal class TimeManager
{
	public static float lastTimerSync = 0f;

	public static float currentTimeRemaining = 0f;

	public static int lastTimeRemaining = 0;

	public static float timerPingLerp = 0f;

	public static float timerPingLerpMax = 0f;

	public static bool timerRunning = false;

	public static bool timerPaused = false;

	public static bool gameOverStarted = false;

	private static Color pingColor = Color.white;

	public static string timerString = "";

	public static Color timerExtendedPing = new Color(0f, 1f, 0.1f);

	private static Color timerLowPing = new Color(0.9f, 0.4f, 0.45f);

	public static Color timerNeutralPing = new Color(0.85f, 0.85f, 0.16f);

	private static Color timerNormalBase = new Color(0.1f, 0.4f, 0.8f);

	private static Color timerNormalColon = new Color(0.05f, 0.3f, 0.6f);

	private static Color timerLowBase = new Color(0.8f, 0.1f, 0.2f);

	private static Color timerLowColon = new Color(0.6f, 0.05f, 0.1f);

	private static Color timerPausedBase = new Color(0.6f, 0.63f, 0.66f);

	private static Color timerPausedColon = new Color(0.3f, 0.33f, 0.36f);

	public static Coroutine gameOverCoroutine;

	private static int IntSeconds => Mathf.CeilToInt(currentTimeRemaining);

	private static int IntSecondsFloor => (int)currentTimeRemaining;

	private static int DisplayCentiseconds => Mathf.CeilToInt(currentTimeRemaining * 100f) % 100;

	private static int DisplaySeconds => IntSecondsFloor % 60;

	private static int DisplayMinutes => IntSecondsFloor / 60;

	private static bool ShouldCancelGameOver => !timerRunning || timerPaused || currentTimeRemaining > 0f;

	public static void SetTimerPing(Color color, float time)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		timerPingLerp = time;
		timerPingLerpMax = time;
		pingColor = color;
	}

	public static void Update()
	{
		//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_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: 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)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		if (!timerRunning)
		{
			timerString = "";
			return;
		}
		NotificationManager.Update();
		Color val = timerNormalBase;
		Color val2 = timerNormalColon;
		if (IntSeconds <= 60)
		{
			val = timerLowBase;
			val2 = timerLowColon;
			if (lastTimeRemaining != IntSeconds)
			{
				SetTimerPing(timerLowPing, 0.8f);
			}
		}
		lastTimeRemaining = IntSeconds;
		if (timerPaused)
		{
			val = timerPausedBase;
			val2 = timerPausedColon;
		}
		else
		{
			currentTimeRemaining = Mathf.Max(0f, currentTimeRemaining - Time.deltaTime);
		}
		if (Math.Abs(currentTimeRemaining - lastTimerSync) >= 10f)
		{
			SyncTimeBetweenPlayers(currentTimeRemaining);
		}
		Color val3 = Color.Lerp(val, pingColor, timerPingLerp / timerPingLerpMax);
		Color val4 = Color.Lerp(val2, pingColor, timerPingLerp / timerPingLerpMax);
		timerPingLerp = Mathf.Clamp(timerPingLerp - Time.deltaTime, 0f, timerPingLerpMax);
		if (currentTimeRemaining < 60f)
		{
			string text = "<color=#" + ColorUtility.ToHtmlStringRGB(val4) + ">.</color>";
			string text2 = $"<b><color=#{ColorUtility.ToHtmlStringRGB(val3)}>{IntSecondsFloor:00}</color></b>";
			string text3 = $"<b><color=#{ColorUtility.ToHtmlStringRGB(val3)}>{DisplayCentiseconds:00}</color></b>";
			timerString = text2 + text + text3;
		}
		else
		{
			string text4 = $"<b><color=#{ColorUtility.ToHtmlStringRGB(val3)}>{DisplayMinutes:00}</color></b>";
			string text5 = $"<b><color=#{ColorUtility.ToHtmlStringRGB(val3)}>{DisplaySeconds:00}</color></b>";
			string text6 = "<color=#" + ColorUtility.ToHtmlStringRGB(val4) + ">:</color>";
			timerString = text4 + text6 + text5;
		}
		if (currentTimeRemaining == 0f && !timerPaused)
		{
			SyncTimeBetweenPlayers(0f);
			OutOfTime();
		}
	}

	private static void SyncTimeBetweenPlayers(float seconds)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			Syncing.TimerSync.RaiseEvent((object)seconds, NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
			lastTimerSync = seconds;
		}
	}

	public static void SetTimer(float seconds, bool pause = false)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			currentTimeRemaining = seconds;
			timerPaused = pause;
			Syncing.TimerSet.RaiseEvent((object)pause, NetworkingEvents.RaiseAll, SendOptions.SendReliable);
			SyncTimeBetweenPlayers(seconds);
		}
	}

	public static void AddTimeToTimer(float seconds)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			currentTimeRemaining += seconds;
			Syncing.TimerAdd.RaiseEvent((object)seconds, NetworkingEvents.RaiseAll, SendOptions.SendReliable);
			SyncTimeBetweenPlayers(seconds);
		}
	}

	public static void GenerateBonusMoney(float secondsRemaining)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			int bonusMoneyInThousands = TimeProperties.GetBonusMoneyInThousands(secondsRemaining);
			int num = Mathf.CeilToInt((float)bonusMoneyInThousands * DifficultyManager.RemainingTimeBonusMultiplier);
			if (num > 0)
			{
				Syncing.BonusMoney.RaiseEvent((object)num, NetworkingEvents.RaiseAll, SendOptions.SendReliable);
			}
		}
	}

	private static void OutOfTime()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.IsMasterClientOrSingleplayer() && !gameOverStarted)
		{
			Plugin.loggy.LogDebug((object)"Time's up!");
			Syncing.GameOverSequence.RaiseEvent((object)true, NetworkingEvents.RaiseAll, SendOptions.SendReliable);
		}
	}

	private static bool CancelGameOver()
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		if (!ShouldCancelGameOver || !SemiFunc.IsMasterClientOrSingleplayer() || !gameOverStarted)
		{
			return false;
		}
		Syncing.GameOverSequence.RaiseEvent((object)false, NetworkingEvents.RaiseAll, SendOptions.SendReliable);
		return true;
	}

	public static IEnumerator Death()
	{
		if (CancelGameOver())
		{
			yield break;
		}
		foreach (PlayerAvatar avatar2 in GameDirector.instance.PlayerList)
		{
			avatar2.playerHealth.EyeMaterialOverride((EyeOverrideState)1, 0.25f, 1);
		}
		if (!SemiFunc.IsMasterClientOrSingleplayer())
		{
			yield break;
		}
		yield return (object)new WaitForSeconds(1.5f);
		if (CancelGameOver())
		{
			yield break;
		}
		Plugin.loggy.LogDebug((object)"Killing everyone...");
		foreach (PlayerAvatar avatar in GameDirector.instance.PlayerList)
		{
			if (!Traverse.Create((object)avatar).Field("isDisabled").GetValue<bool>())
			{
				avatar.PlayerDeath(-1);
			}
		}
		gameOverStarted = false;
	}
}
internal class TimeProperties
{
	public static readonly int ExtractionActivationBonusTime = 30;

	public static int BaseLevelTimer = 0;

	private static int RoundTo5(float number)
	{
		return Mathf.RoundToInt(number / 5f) * 5;
	}

	public static int GetThisLevelBaseTime(int level)
	{
		if (level <= 10)
		{
			float number = 300f - 25.25f * Mathf.Pow(Mathf.Sqrt((float)(level - 1)), 1.25f);
			return RoundTo5(number);
		}
		if (level <= 100)
		{
			float number2 = 200f - 9.84f * Mathf.Pow(Mathf.Sqrt((float)(level - 10)), 1.18f);
			return RoundTo5(number2);
		}
		return 60;
	}

	public static int GetThisLevelTime(int level)
	{
		return RoundTo5((float)GetThisLevelBaseTime(level) * DifficultyManager.LevelTimeDifficultyMultiplier);
	}

	public static int GetThisLevelAddedTime(int level, int totalExtractions, float bonus)
	{
		float num = 1.1f;
		float num2 = Mathf.Clamp(1f / Mathf.Pow(1.33f, (float)totalExtractions), 0.25f, 1f);
		if (level > 10)
		{
			num = 1.1f - 0.0504f * Mathf.Pow(Mathf.Sqrt((float)(level - 10)), 1.2f);
		}
		else if (level > 100)
		{
			num = 0.35f;
		}
		float num3 = 1f;
		if (bonus >= 1.25f)
		{
			num3 = 1f + 0.5f * Mathf.Sqrt(Mathf.Clamp(bonus, 1f, 10f) - 1f);
		}
		return RoundTo5((float)BaseLevelTimer * num * num2 * num3 * DifficultyManager.ExtractionBonusDifficultyMultiplier);
	}

	public static int GetThisLevelFinalExtractTime(int level)
	{
		float num = 1f - 0.0375f * Mathf.Pow(Mathf.Sqrt((float)(level - 1)), 1.25f);
		if (level > 100)
		{
			num = 1f / 3f;
		}
		return RoundTo5((float)BaseLevelTimer * num * DifficultyManager.FinalExtractionDifficultyMultiplier);
	}

	public static int GetBonusMoneyInThousands(float timeRemaining)
	{
		if (timeRemaining < 30f)
		{
			return 0;
		}
		float num = 1.045f * Mathf.Pow(Mathf.Sqrt(timeRemaining - 30f), 1.2f);
		return Mathf.RoundToInt(Mathf.Clamp(num, 0f, 30f));
	}
}