Decompiled source of HpRegenBySchleimi v1.0.3

BepInEx/plugins/HpRegenBySchleimi/HpRegenBySchleimi.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace HpRegenRebuilt;

[BepInPlugin("schleimi.hpregen", "HP Regen by Schleimi", "1.0.3")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Guid = "schleimi.hpregen";

	public const string Name = "HP Regen by Schleimi";

	public const string Version = "1.0.3";

	internal static ConfigEntry<float> Interval;

	internal static ConfigEntry<int> BaseHeal;

	internal static ConfigEntry<int> PerUpgrade;

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Expected O, but got Unknown
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected O, but got Unknown
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		Interval = ((BaseUnityPlugin)this).Config.Bind<float>("HP regeneration", "IntervalSeconds", 20f, new ConfigDescription("Seconds between healing pulses.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 300f), new object[0]));
		BaseHeal = ((BaseUnityPlugin)this).Config.Bind<int>("HP regeneration", "BaseHeal", 1, new ConfigDescription("HP restored every pulse.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), new object[0]));
		PerUpgrade = ((BaseUnityPlugin)this).Config.Bind<int>("HP regeneration", "HealPerHealthUpgrade", 1, new ConfigDescription("Extra HP per regeneration tier (tiers unlock at 1, 3, 6, 10... Health upgrades).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), new object[0]));
		Log = ((BaseUnityPlugin)this).Logger;
		new Harmony("schleimi.hpregen").PatchAll();
		Log.LogInfo((object)"HP Regen by Schleimi 1.0.3 loaded; PlayerHealth startup hook installed.");
	}
}
[HarmonyPatch(typeof(PlayerHealth), "Start")]
internal static class PlayerHealthStartPatch
{
	private static void Postfix(PlayerHealth __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			RegenUpdater regenUpdater = ((Component)__instance).gameObject.GetComponent<RegenUpdater>();
			if ((Object)(object)regenUpdater == (Object)null)
			{
				regenUpdater = ((Component)__instance).gameObject.AddComponent<RegenUpdater>();
			}
			regenUpdater.Initialize(__instance);
		}
	}
}
internal sealed class RegenUpdater : MonoBehaviour
{
	private PlayerHealth player;

	private float elapsed;

	private bool announced;

	internal void Initialize(PlayerHealth value)
	{
		player = value;
		Plugin.Log.LogInfo((object)("Regen attached to " + ((Object)value).name + "."));
	}

	private void Update()
	{
		if (!((Object)(object)player == (Object)null) && (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient))
		{
			if (!announced)
			{
				announced = true;
				Plugin.Log.LogInfo((object)"Regen timer is running.");
			}
			elapsed += Time.deltaTime;
			if (!(elapsed < Plugin.Interval.Value))
			{
				elapsed = 0f;
				Heal(player);
			}
		}
	}

	private void OnDestroy()
	{
		player = null;
	}

	private void Heal(PlayerHealth target)
	{
		if ((Object)(object)target == (Object)null)
		{
			return;
		}
		try
		{
			object obj = Field(target, "playerAvatar");
			if (obj == null || Bool(obj, "isDisabled"))
			{
				return;
			}
			int num = Int(target, "health");
			int num2 = Int(target, "maxHealth");
			if (num < num2)
			{
				int upgrades = HealthLevel(ReadString(obj, "steamID"));
				int num3 = RegenTier(upgrades);
				int num4 = Plugin.BaseHeal.Value + Plugin.PerUpgrade.Value * num3;
				int num5 = Math.Min(num2, num + num4);
				PhotonView component = ((Component)target).gameObject.GetComponent<PhotonView>();
				if (PhotonNetwork.InRoom && (Object)(object)component != (Object)null)
				{
					component.RPC("UpdateHealthRPC", (RpcTarget)0, new object[4] { num5, num2, false, false });
				}
				else
				{
					target.Heal(num5 - num, false);
				}
				Plugin.Log.LogInfo((object)("Regen: +" + (num5 - num) + " HP."));
			}
		}
		catch (MissingReferenceException)
		{
			player = null;
			Plugin.Log.LogInfo((object)"Regen stopped for a destroyed player avatar.");
		}
		catch (NullReferenceException)
		{
			player = null;
			Plugin.Log.LogInfo((object)"Regen stopped while a player avatar was changing scenes.");
		}
	}

	private static int HealthLevel(string id)
	{
		object obj = StaticField(typeof(StatsManager), "instance");
		Dictionary<string, int> dictionary = ((obj == null) ? null : (Field(obj, "playerUpgradeHealth") as Dictionary<string, int>));
		int value;
		return (dictionary != null && id != null && dictionary.TryGetValue(id, out value)) ? Math.Max(0, value) : 0;
	}

	private static int RegenTier(int upgrades)
	{
		return Mathf.FloorToInt((Mathf.Sqrt(8f * (float)Math.Max(0, upgrades) + 1f) - 1f) / 2f);
	}

	private static object Field(object target, string name)
	{
		if (target == null)
		{
			return null;
		}
		FieldInfo field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		return (field == null) ? null : field.GetValue(target);
	}

	private static object StaticField(Type type, string name)
	{
		FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		return (field == null) ? null : field.GetValue(null);
	}

	private static int Int(object target, string name)
	{
		object obj = Field(target, name);
		return (obj is int) ? ((int)obj) : 0;
	}

	private static bool Bool(object target, string name)
	{
		object obj = Field(target, name);
		return obj is bool && (bool)obj;
	}

	private static string ReadString(object target, string name)
	{
		return Field(target, name) as string;
	}
}