Decompiled source of RobustRegen v1.0.0

RobustRegen.dll

Decompiled 5 days ago
using System;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
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: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Vegasx")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RobustRegen")]
[assembly: AssemblyTitle("RobustRegen")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 RobustRegen
{
	[BepInPlugin("Vegasx.RobustRegen", "RobustRegen", "1.0")]
	public class RobustRegen : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(PlayerHealth), "Start")]
		public class RegenPatch
		{
			private static void Postfix(PlayerHealth __instance)
			{
				if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).gameObject.GetComponent<RegenUpdater>() == (Object)null)
				{
					((Component)__instance).gameObject.AddComponent<RegenUpdater>().Init(__instance);
				}
			}
		}

		public class RegenUpdater : MonoBehaviour
		{
			private PlayerHealth playerHealth;

			private PlayerAvatar playerAvatar;

			private FieldInfo healthField;

			private FieldInfo maxHealthField;

			private FieldInfo playerAvatarField;

			private PhotonView playerPhotonView;

			private bool isRegenActive = false;

			private bool healthIsCritical = false;

			private float addedTime = 0f;

			private int lastKnownHP = 100;

			public void Init(PlayerHealth instance)
			{
				playerHealth = instance;
				Type type = ((object)playerHealth).GetType();
				healthField = type.GetField("health", BindingFlags.Instance | BindingFlags.NonPublic);
				maxHealthField = type.GetField("maxHealth", BindingFlags.Instance | BindingFlags.NonPublic);
				playerAvatarField = type.GetField("playerAvatar", BindingFlags.Instance | BindingFlags.NonPublic);
				playerPhotonView = ((Component)playerHealth).GetComponent<PhotonView>();
			}

			private void Update()
			{
				if (!RegenEnabled.Value || ((Object)(object)playerPhotonView != (Object)null && !playerPhotonView.IsMine))
				{
					return;
				}
				int num = (int)healthField.GetValue(playerHealth);
				int num2 = (int)maxHealthField.GetValue(playerHealth);
				float num3 = (float)num / (float)num2 * 100f;
				int num4 = (int)((float)num2 * ((float)BaseRegenMaxPerc.Value / 100f));
				if (num <= 0)
				{
					if (isRegenActive)
					{
						StopRegenCycle();
					}
					return;
				}
				if (num < num4 && !isRegenActive)
				{
					isRegenActive = true;
					((MonoBehaviour)this).CancelInvoke("PerformRegenTick");
					((MonoBehaviour)this).Invoke("PerformRegenTick", RegenIntervalSeconds.Value + RegenInitialDelay.Value);
				}
				if (num < lastKnownHP && ResetRegenOnDamage.Value)
				{
					StopRegenCycle();
					lastKnownHP = num;
					return;
				}
				if (isRegenActive && num >= num4)
				{
					StopRegenCycle();
				}
				if (isRegenActive && (int)num3 <= CriticalHealthThreshold.Value && !healthIsCritical)
				{
					healthIsCritical = true;
					((MonoBehaviour)this).CancelInvoke("PerformRegenTick");
					((MonoBehaviour)this).Invoke("PerformRegenTick", CriticalHealthIntervalSeconds.Value + RegenInitialDelay.Value);
				}
				lastKnownHP = num;
			}

			private void PerformRegenTick()
			{
				if (!RegenEnabled.Value)
				{
					StopRegenCycle();
					return;
				}
				int num = (int)healthField.GetValue(playerHealth);
				int num2 = (int)maxHealthField.GetValue(playerHealth);
				float num3 = (float)num / (float)num2 * 100f;
				int num4 = (int)((float)num2 * ((float)BaseRegenMaxPerc.Value / 100f));
				int max = (int)((float)num2 * ((float)CriticalHealthThreshold.Value / 100f));
				if (!isRegenActive || num == 0)
				{
					StopRegenCycle();
					return;
				}
				if (num >= num4)
				{
					StopRegenCycle();
					return;
				}
				if (num3 >= (float)CriticalHealthThreshold.Value)
				{
					healthIsCritical = false;
				}
				int num5 = Math.Clamp(num + RegenAmountPerTick.Value, 1, num4);
				if (healthIsCritical)
				{
					num5 = Math.Clamp(num + CriticalAmountPerTick.Value, 1, max);
				}
				if (PhotonNetwork.IsConnected && (Object)(object)playerPhotonView != (Object)null)
				{
					playerPhotonView.RPC("UpdateHealthRPC", (RpcTarget)0, new object[3] { num5, num2, false });
				}
				else
				{
					healthField.SetValue(playerHealth, num5);
				}
				if (healthIsCritical)
				{
					((MonoBehaviour)this).Invoke("PerformRegenTick", CriticalHealthIntervalSeconds.Value);
					return;
				}
				if (ExtraTimePerTickMax.Value <= 0f)
				{
					addedTime += ExtraTimePerTick.Value;
					if (addedTime < ExtraTimePerTickMax.Value)
					{
						addedTime = ExtraTimePerTickMax.Value;
					}
				}
				else
				{
					addedTime += ExtraTimePerTick.Value;
					if (addedTime > ExtraTimePerTickMax.Value)
					{
						addedTime = ExtraTimePerTickMax.Value;
					}
				}
				((MonoBehaviour)this).Invoke("PerformRegenTick", Math.Max(0.1f, RegenIntervalSeconds.Value + addedTime));
			}

			private void StopRegenCycle()
			{
				isRegenActive = false;
				addedTime = 0f;
				((MonoBehaviour)this).CancelInvoke("PerformRegenTick");
			}
		}

		public static ConfigEntry<bool> RegenEnabled;

		public static ConfigEntry<float> RegenIntervalSeconds;

		public static ConfigEntry<float> RegenInitialDelay;

		public static ConfigEntry<int> BaseRegenMaxPerc;

		public static ConfigEntry<int> CriticalHealthThreshold;

		public static ConfigEntry<int> CriticalAmountPerTick;

		public static ConfigEntry<float> CriticalHealthIntervalSeconds;

		public static ConfigEntry<float> ExtraTimePerTick;

		public static ConfigEntry<float> ExtraTimePerTickMax;

		public static ConfigEntry<int> RegenAmountPerTick;

		public static ConfigEntry<bool> ResetRegenOnDamage;

		private void Awake()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Expected O, but got Unknown
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Expected O, but got Unknown
			RegenEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled", "Regeneration Enabled", true, "Should the mod be enabled? This setting mostly exists for REPOConfig usage.");
			RegenIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Base Regen", "Regen Interval", 20f, new ConfigDescription("Interval between regeneration ticks, in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 120f), Array.Empty<object>()));
			RegenAmountPerTick = ((BaseUnityPlugin)this).Config.Bind<int>("Base Regen", "RegenAmountPerTick", 1, new ConfigDescription("Amount of HP restored per regeneration tick.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-10, 100), Array.Empty<object>()));
			BaseRegenMaxPerc = ((BaseUnityPlugin)this).Config.Bind<int>("Base Regen", "Maximum HP %", 100, new ConfigDescription("Maximum health, in percentage, that the regeneration will heal up to.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
			RegenInitialDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Base Regen", "Damage Delay Time", 8f, new ConfigDescription("Add extra time to the very first initial interval of the regeneration, which is removed for subsequent intervals.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
			ResetRegenOnDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("Base Regen", "Reset Regen On Damage", true, "Stops and restarts the regeneration cycle upon taking damage. Good if you want the ExtraTimePerTick or RegenInitialDelay to reset.");
			CriticalHealthThreshold = ((BaseUnityPlugin)this).Config.Bind<int>("Critical HP Settings", "CriticalHealthThreshold", 20, new ConfigDescription("Health percentage to be considered critical when below. To disable, set to 0", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			CriticalHealthIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Critical HP Settings", "Critical Health Regen Interval", 2f, new ConfigDescription("Interval between regeneration ticks when health is below critical threshold, in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 60f), Array.Empty<object>()));
			CriticalAmountPerTick = ((BaseUnityPlugin)this).Config.Bind<int>("Critical HP Settings", "Critical Heal Per Tick", 1, new ConfigDescription("Amount of HP restored per regeneration tick while health is critical.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-10, 100), Array.Empty<object>()));
			ExtraTimePerTick = ((BaseUnityPlugin)this).Config.Bind<float>("Regen Ramping", "Extra Time Per Tick", 0f, new ConfigDescription("Ramps time to the regen interval per successful tick. Resets if regeneration ceases. Does not ramp for critical health.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-60f, 60f), Array.Empty<object>()));
			ExtraTimePerTickMax = ((BaseUnityPlugin)this).Config.Bind<float>("Regen Ramping", "Extra Time Per Tick Max", 10f, new ConfigDescription("Limit, in seconds, for the extra time ramped per tick. Set to 0 for no limit. When set below 0, it acts as a floor rather than a ceiling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-60f, 120f), Array.Empty<object>()));
			Harmony val = new Harmony("Xmods.healthregen");
			val.PatchAll();
		}
	}
}