Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TimerRevive v1.0.0
plugins/yazirushi-TimerRevive/TimerRevive.dll
Decompiled 2 months agousing 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"); } } } }