Please disclose if any significant portion of your mod was created 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 JustRetryLimited v1.0.1
JustRetryLimited.dll
Decompiled 3 hours agousing System; using System.Collections; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; 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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("JustRetryLimited")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("JustRetryLimited")] [assembly: AssemblyTitle("JustRetryLimited")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace JustRetryLimited { internal static class MyPluginInfo { public const string PLUGIN_GUID = "justretylimited.plugin"; public const string PLUGIN_NAME = "JustRetryLimited"; public const string PLUGIN_VERSION = "1.0.1"; } public enum HealMode { Fixed, Percentage, FullHeal } [BepInPlugin("justretylimited.plugin", "JustRetryLimited", "1.0.1")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; private static ConfigEntry<bool> _isEnabled; private static ConfigEntry<bool> _unlimitedRetries; private static ConfigEntry<int> _maxRetries; private static ConfigEntry<bool> _shouldResetLevel; private static ConfigEntry<bool> _shouldHealAfterFail; private static ConfigEntry<HealMode> _healMode; private static ConfigEntry<int> _healthToHeal; private static ConfigEntry<int> _healthPercentage; private static ConfigEntry<bool> _shouldResetUpgrades; public static bool IsEnabled => _isEnabled.Value; public static bool UnlimitedRetries => _unlimitedRetries.Value; public static int MaxRetries => _maxRetries.Value; public static bool ShouldResetLevel => _shouldResetLevel.Value; public static bool ShouldHealAfterFail => _shouldHealAfterFail.Value; public static HealMode CurrentHealMode => _healMode.Value; public static int HealthToHealValue => _healthToHeal.Value; public static int HealthPercentageValue => _healthPercentage.Value; public static bool ShouldResetUpgrades => _shouldResetUpgrades.Value; public static bool DidFailLevel { get; set; } public static int RetryCount { get; set; } internal static Plugin Instance { get; private set; } private void Awake() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin justretylimited.plugin is loaded!"); Harmony val = new Harmony("justretylimited.plugin"); val.PatchAll(); _isEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "IsEnabled", true, "Toggle the plugin on or off."); _unlimitedRetries = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "UnlimitedRetries", false, "If true, retries are unlimited and MaxRetries is ignored."); _maxRetries = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "MaxRetries", 3, new ConfigDescription("Maximum number of retries per level before the game ends normally.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 99), Array.Empty<object>())); _shouldResetLevel = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ShouldResetLevel", false, "If true, restarts from level one when failing a level."); _shouldHealAfterFail = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ShouldHealAfterFail", true, "If true, all players are healed when retrying after a failed level."); _healMode = ((BaseUnityPlugin)this).Config.Bind<HealMode>("Settings", "HealMode", HealMode.FullHeal, "Fixed = heal up to a flat HP value. Percentage = heal up to a percentage of max HP. FullHeal = heal up to max HP (accounts for health upgrades)."); _healthToHeal = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "HealthToHeal", 100, new ConfigDescription("Target HP to heal up to when retrying. Only used if HealMode is Fixed. If players already have more than this, they are not healed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), Array.Empty<object>())); _healthPercentage = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "HealthPercentage", 100, new ConfigDescription("Percentage of max HP to heal up to when retrying. Only used if HealMode is Percentage. 100 = full heal.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); _shouldResetUpgrades = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ShouldResetUpgrades", false, "If true, resets all upgrades when failing a level (only if ShouldResetLevel is true)."); } public void StartHealCoroutine() { ((MonoBehaviour)this).StartCoroutine(HealPlayersDelayed()); } private IEnumerator HealPlayersDelayed() { if (!ShouldHealAfterFail || !DidFailLevel || !SemiFunc.IsMasterClientOrSingleplayer()) { yield break; } yield return (object)new WaitForSeconds(2f); for (float elapsed = 0f; elapsed <= 6f; elapsed += 1f) { foreach (PlayerAvatar player in SemiFunc.PlayerGetAll()) { PlayerHealth health = player?.playerHealth; if (!((Object)(object)health == (Object)null)) { Traverse healthField = Traverse.Create((object)health).Field("health"); Traverse maxHealthField = Traverse.Create((object)health).Field("maxHealth"); int currentHp = healthField.GetValue<int>(); int maxHp = maxHealthField.GetValue<int>(); int targetHp = CurrentHealMode switch { HealMode.FullHeal => maxHp, HealMode.Percentage => Mathf.RoundToInt((float)maxHp * ((float)HealthPercentageValue / 100f)), _ => Mathf.Min(HealthToHealValue, maxHp), }; int missing = targetHp - currentHp; if (missing > 0) { health.HealOther(missing, true); Logger.LogInfo((object)$"Healed {((Object)player).name} by {missing} to reach {targetHp}/{maxHp}"); } } } yield return (object)new WaitForSeconds(1f); } } } [HarmonyPatch(typeof(RunManager), "ChangeLevel")] public static class ChangeLevelPatch { private static void Prefix(RunManager __instance, ref bool _completedLevel, ref bool _levelFailed, ref ChangeLevelType _changeLevelType) { if (!Plugin.IsEnabled) { return; } if (!SemiFunc.RunIsLevel()) { Plugin.Logger.LogInfo((object)"Not an extraction level, skipping retry logic."); return; } Plugin.DidFailLevel = _levelFailed; Plugin.Logger.LogInfo((object)$"Level failed: {_levelFailed}"); if (!Plugin.DidFailLevel) { Plugin.RetryCount = 0; Plugin.Logger.LogInfo((object)"Level completed, retry counter reset."); return; } if (!Plugin.UnlimitedRetries && Plugin.RetryCount >= Plugin.MaxRetries) { Plugin.Logger.LogInfo((object)$"Retry limit of {Plugin.MaxRetries} reached, ending run."); Plugin.RetryCount = 0; return; } Plugin.RetryCount++; Plugin.Logger.LogInfo((object)($"Retry {Plugin.RetryCount}" + (Plugin.UnlimitedRetries ? " (unlimited)" : $" of {Plugin.MaxRetries}"))); if (Plugin.ShouldResetLevel) { Plugin.Logger.LogInfo((object)"Resetting to level one"); __instance.levelsCompleted = 0; Traverse.Create((object)__instance).Field("loadLevel").SetValue((object)0); __instance.SetRunLevel(); if (Plugin.ShouldResetUpgrades && (Object)(object)StatsManager.instance != (Object)null) { StatsManager.instance.ResetAllStats(); } StatsManager instance = StatsManager.instance; if (instance != null) { instance.StuffNeedingResetAtTheEndOfAScene(); } TutorialDirector.instance.TipCancel(); ItemManager.instance.FetchLocalPlayersInventory(); ItemManager.instance.powerCrystals.Clear(); SemiFunc.StatSyncAll(); SessionManager.instance.Reset(); } __instance.RestartScene(); Traverse.Create((object)RoundDirector.instance).Field("totalHaul").SetValue((object)0); Traverse.Create((object)RoundDirector.instance).Field("currentHaul").SetValue((object)0); Traverse.Create((object)RoundDirector.instance).Field("currentHaulMax").SetValue((object)0); Traverse.Create((object)RoundDirector.instance).Field("extractionPointSurplus").SetValue((object)0); Plugin.Logger.LogInfo((object)"Scene restarted, queuing heal..."); Plugin.Instance.StartHealCoroutine(); } } }