Decompiled source of TimerRevive v1.0.0

plugins/yazirushi-TimerRevive/TimerRevive.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TimerRevive")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TimerRevive")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("eb16fe60-8e2a-414a-9102-3de2d61c2cda")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TimerRevive;

[BepInPlugin("yazirushi.TimerRevive", "TimerRevive", "1.0.0")]
public class TimerRevive : BaseUnityPlugin
{
	public enum Scaling_type
	{
		Add,
		Multiply
	}

	public enum Language
	{
		English,
		Japanese
	}

	private readonly Harmony harmony = new Harmony("yazirushi.TimerRevive");

	internal static ManualLogSource mls;

	public static ConfigEntry<float> ReviveTime;

	public static ConfigEntry<Scaling_type> ScalingType;

	public static ConfigEntry<float> ScalingValue;

	public static ConfigEntry<Language> UI_Language;

	public static ConfigEntry<float> UIText_Offset_X;

	public static ConfigEntry<float> UIText_Offset_Y;

	public static ConfigEntry<float> UIText_FontSize;

	public static ConfigEntry<Color> UIText_Color;

	public static ConfigEntry<bool> DebugLog;

	public static Canvas canvas;

	public static TextMeshProUGUI text;

	public static void CreateUI()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0069: 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_0099: Expected O, but got Unknown
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("TimerReviveCanvas");
		canvas = val.AddComponent<Canvas>();
		canvas.renderMode = (RenderMode)0;
		canvas.worldCamera = null;
		canvas.sortingOrder = 999;
		canvas.scaleFactor = 1f;
		CanvasScaler val2 = val.AddComponent<CanvasScaler>();
		val2.uiScaleMode = (ScaleMode)1;
		val2.referenceResolution = new Vector2(1920f, 1080f);
		val2.matchWidthOrHeight = 1f;
		val.AddComponent<GraphicRaycaster>();
		Object.DontDestroyOnLoad((Object)(object)val);
		GameObject val3 = new GameObject("TimerReviveText");
		val3.transform.SetParent(val.transform);
		text = val3.AddComponent<TextMeshProUGUI>();
		TMP_FontAsset tekoFont = FontUtil.GetTekoFont();
		if ((Object)(object)tekoFont != (Object)null)
		{
			((TMP_Text)text).font = tekoFont;
			((TMP_Text)text).fontMaterial = FontUtil.GetTekoMaterial();
		}
		((TMP_Text)text).enableWordWrapping = false;
		((TMP_Text)text).overflowMode = (TextOverflowModes)0;
		((TMP_Text)text).alignment = (TextAlignmentOptions)1026;
		((TMP_Text)text).rectTransform.anchorMin = new Vector2(1f, 0f);
		((TMP_Text)text).rectTransform.anchorMax = new Vector2(1f, 0f);
		((TMP_Text)text).rectTransform.pivot = new Vector2(1f, 0f);
		((TMP_Text)text).rectTransform.anchoredPosition = Vector2.zero;
		((TMP_Text)text).rectTransform.sizeDelta = new Vector2(400f, 200f);
		if (DebugLog.Value)
		{
			mls.LogInfo((object)"CreateUI!");
		}
	}

	public static void UpdateUI(float time)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		switch (UI_Language.Value)
		{
		case Language.English:
			((TMP_Text)text).text = $"Revive in {(int)time + 1} seconds";
			break;
		case Language.Japanese:
			((TMP_Text)text).text = $"{(int)time + 1}秒後に復活します!";
			break;
		}
		((TMP_Text)text).fontSize = UIText_FontSize.Value;
		((Graphic)text).color = Color.white;
		((TMP_Text)text).rectTransform.anchoredPosition = new Vector2(UIText_Offset_X.Value, UIText_Offset_Y.Value);
		if (DebugLog.Value)
		{
			mls.LogInfo((object)"UpdateUI!");
		}
	}

	private void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Expected O, but got Unknown
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Expected O, but got Unknown
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Expected O, but got Unknown
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Expected O, but got Unknown
		ReviveTime = ((BaseUnityPlugin)this).Config.Bind<float>("Revive Settings", "Revive Time", 30f, new ConfigDescription("Base time required for revival", (AcceptableValueBase)null, Array.Empty<object>()));
		ScalingType = ((BaseUnityPlugin)this).Config.Bind<Scaling_type>("Revive Settings", "Scaling Type", Scaling_type.Add, new ConfigDescription("How it increases", (AcceptableValueBase)null, Array.Empty<object>()));
		ScalingValue = ((BaseUnityPlugin)this).Config.Bind<float>("Revive Settings", "Scaling value", 15f, new ConfigDescription("Increasing value(We recommend reading the README.)", (AcceptableValueBase)null, Array.Empty<object>()));
		UI_Language = ((BaseUnityPlugin)this).Config.Bind<Language>("UI Settings", "Language", Language.English, new ConfigDescription("Language used in UI text", (AcceptableValueBase)null, Array.Empty<object>()));
		UIText_Offset_X = ((BaseUnityPlugin)this).Config.Bind<float>("UI Settings", "X Offset", 0f, new ConfigDescription("X-axis offset", (AcceptableValueBase)null, Array.Empty<object>()));
		UIText_Offset_Y = ((BaseUnityPlugin)this).Config.Bind<float>("UI Settings", "Y Offset", 0f, new ConfigDescription("Y-axis offset", (AcceptableValueBase)null, Array.Empty<object>()));
		UIText_FontSize = ((BaseUnityPlugin)this).Config.Bind<float>("UI Settings", "Text Size", 50f, new ConfigDescription("UI text size", (AcceptableValueBase)null, Array.Empty<object>()));
		DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("DebugLog", "EnableLogging", false, new ConfigDescription("Display the logs used during debugging", (AcceptableValueBase)null, Array.Empty<object>()));
		mls = ((BaseUnityPlugin)this).Logger;
		mls.LogInfo((object)"Starting TimerRevive...");
		harmony.PatchAll();
	}
}
public class FontUtil
{
	private static TMP_FontAsset cachedFont;

	private static Material cachedMat;

	public static TMP_FontAsset GetTekoFont()
	{
		if ((Object)(object)cachedFont != (Object)null)
		{
			return cachedFont;
		}
		TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
		foreach (TMP_FontAsset val in array)
		{
			if (((Object)val).name.Contains("Teko") && ((Object)val).name.Contains("SDF"))
			{
				cachedFont = val;
				cachedMat = ((TMP_Asset)val).material;
				return cachedFont;
			}
		}
		return null;
	}

	public static Material GetTekoMaterial()
	{
		return cachedMat;
	}
}
[HarmonyPatch(typeof(PlayerDeathHead), "Update")]
public class TimerUpdate
{
	private class ReviveState
	{
		public float reviveTimer = 0f;

		public float waitTimer = 0f;

		public int reviveCount = 0;

		public bool isdead = false;

		public bool timerReset = false;
	}

	private static readonly FieldInfo isDead = AccessTools.Field(typeof(PlayerDeathHead), "triggered");

	private static Dictionary<PlayerAvatar, ReviveState> reviveStates = new Dictionary<PlayerAvatar, ReviveState>();

	internal static float reviveTimer_local = 0f;

	private static float waitTimer_local = 0f;

	private static int reviveCount_local = 0;

	private static bool timerReset_local = false;

	private static bool createdUI = false;

	public static void Postfix(PlayerDeathHead __instance)
	{
		if ((Object)(object)__instance.playerAvatar != (Object)(object)PlayerAvatar.instance)
		{
			return;
		}
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			PlayerAvatar val = null;
			foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
			{
				if ((Object)(object)item == (Object)null || (Object)(object)item.playerDeathHead == (Object)null)
				{
					continue;
				}
				if ((Object)(object)__instance.playerAvatar == (Object)(object)item)
				{
					val = item;
				}
				if (!reviveStates.TryGetValue(item, out var value))
				{
					value = new ReviveState
					{
						reviveTimer = TimerRevive.ReviveTime.Value,
						waitTimer = 5f,
						reviveCount = 0,
						isdead = false,
						timerReset = false
					};
					reviveStates.Add(item, value);
				}
				value.isdead = (bool)isDead.GetValue(item.playerDeathHead);
				if (!value.isdead)
				{
					value.timerReset = false;
				}
				else
				{
					if (!value.isdead)
					{
						continue;
					}
					if (!value.timerReset)
					{
						value.timerReset = true;
						switch (TimerRevive.ScalingType.Value)
						{
						case TimerRevive.Scaling_type.Add:
							value.reviveTimer = TimerRevive.ReviveTime.Value + TimerRevive.ScalingValue.Value * (float)value.reviveCount;
							break;
						case TimerRevive.Scaling_type.Multiply:
							value.reviveTimer = TimerRevive.ReviveTime.Value * (float)Math.Pow(TimerRevive.ScalingValue.Value, value.reviveCount);
							break;
						}
						value.waitTimer = 5f;
					}
					value.waitTimer -= Time.deltaTime;
					if (value.waitTimer <= 0f)
					{
						value.reviveTimer -= Time.deltaTime;
						if (value.reviveTimer <= 0f && value.timerReset)
						{
							value.timerReset = false;
							value.reviveCount++;
							item.Revive(false);
						}
					}
				}
			}
			reviveStates.Keys.Where((PlayerAvatar p) => (Object)(object)p == (Object)null || !SemiFunc.PlayerGetAll().Contains(p)).ToList().ForEach(delegate(PlayerAvatar p)
			{
				reviveStates.Remove(p);
			});
			if (!((Object)(object)val != (Object)null) || !reviveStates.TryGetValue(val, out var value2))
			{
				return;
			}
			if (value2.isdead)
			{
				if (value2.waitTimer <= 0f && value2.timerReset)
				{
					if (!createdUI)
					{
						createdUI = true;
						TimerRevive.CreateUI();
					}
					if ((Object)(object)TimerRevive.canvas == (Object)null)
					{
						createdUI = false;
					}
					if ((Object)(object)TimerRevive.canvas != (Object)null)
					{
						((Behaviour)TimerRevive.canvas).enabled = true;
					}
					TimerRevive.UpdateUI(value2.reviveTimer);
				}
			}
			else if ((Object)(object)TimerRevive.canvas != (Object)null)
			{
				((Behaviour)TimerRevive.canvas).enabled = false;
			}
		}
		else if ((bool)isDead.GetValue(__instance))
		{
			if (!timerReset_local)
			{
				timerReset_local = true;
				switch (TimerRevive.ScalingType.Value)
				{
				case TimerRevive.Scaling_type.Add:
					reviveTimer_local = TimerRevive.ReviveTime.Value + TimerRevive.ScalingValue.Value * (float)reviveCount_local;
					break;
				case TimerRevive.Scaling_type.Multiply:
					reviveTimer_local = TimerRevive.ReviveTime.Value * (float)Math.Pow(TimerRevive.ScalingValue.Value, reviveCount_local);
					break;
				}
				waitTimer_local = 5f;
			}
			waitTimer_local -= Time.deltaTime;
			if (!(waitTimer_local <= 0f))
			{
				return;
			}
			reviveTimer_local -= Time.deltaTime;
			if (!createdUI)
			{
				createdUI = true;
				TimerRevive.CreateUI();
			}
			if ((Object)(object)TimerRevive.canvas == (Object)null)
			{
				createdUI = false;
			}
			if ((Object)(object)TimerRevive.canvas != (Object)null)
			{
				((Behaviour)TimerRevive.canvas).enabled = true;
			}
			TimerRevive.UpdateUI(reviveTimer_local);
			if (reviveTimer_local <= 0f && timerReset_local)
			{
				timerReset_local = false;
				if ((Object)(object)TimerRevive.canvas != (Object)null)
				{
					((Behaviour)TimerRevive.canvas).enabled = false;
				}
				reviveCount_local++;
			}
		}
		else
		{
			timerReset_local = false;
			if ((Object)(object)TimerRevive.canvas != (Object)null)
			{
				((Behaviour)TimerRevive.canvas).enabled = false;
			}
		}
	}

	public static void ResetAllReviveCounts()
	{
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			reviveStates.Clear();
		}
		else
		{
			reviveCount_local = 0;
		}
	}
}
[HarmonyPatch(typeof(GameDirector), "gameStateStart")]
internal class ReviveCountReset
{
	private static void Postfix(GameDirector __instance)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Invalid comparison between Unknown and I4
		if ((int)__instance.currentState == 2)
		{
			TimerUpdate.ResetAllReviveCounts();
			if (TimerRevive.DebugLog.Value)
			{
				TimerRevive.mls.LogInfo((object)"The state has been reset");
			}
		}
	}
}