Decompiled source of CorpseBloomReborn v1.3.0

plugins/CorpseBloomReborn/CorpseBloomReborn.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using On.RoR2;
using On.RoR2.UI;
using RoR2;
using RoR2.ContentManagement;
using RoR2.UI;
using UnityEngine;
using UnityEngine.Networking;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("CorpseBloomReborn")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CorpseBloomReborn")]
[assembly: AssemblyTitle("CorpseBloomReborn")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace TPDespair.CorpseBloomReborn;

public static class Configuration
{
	public static ConfigEntry<bool> HideReserveBuff { get; set; }

	public static ConfigEntry<bool> HealBeforeReserve { get; set; }

	public static ConfigEntry<bool> HealWhenReserveFull { get; set; }

	public static ConfigEntry<float> BaseAbsorbMult { get; set; }

	public static ConfigEntry<float> AddedAbsorbMult { get; set; }

	public static ConfigEntry<float> BaseExportMult { get; set; }

	public static ConfigEntry<float> AddedExportMult { get; set; }

	public static ConfigEntry<int> AegisInteraction { get; set; }

	public static ConfigEntry<bool> RestoreRejuvBehavior { get; set; }

	public static ConfigEntry<float> BaseHealthReserve { get; set; }

	public static ConfigEntry<float> AddedHealthReserve { get; set; }

	public static ConfigEntry<bool> VanillaUsageBehavior { get; set; }

	public static ConfigEntry<float> BaseMaxUsageRate { get; set; }

	public static ConfigEntry<float> StackMaxUsageRate { get; set; }

	public static ConfigEntry<float> BaseMinUsageRate { get; set; }

	public static ConfigEntry<float> StackMinUsageRate { get; set; }

	internal static void Init(ConfigFile Config)
	{
		HideReserveBuff = Config.Bind<bool>("General", "HideReserveBuff", true, "Set CBReserve buff as hidden, preventing it from being drawn on your active buffs bar.");
		HealBeforeReserve = Config.Bind<bool>("General", "HealBeforeReserve", false, "If incoming healing should apply to health before going into reserve.");
		HealWhenReserveFull = Config.Bind<bool>("General", "HealWhenReserveFull", false, "If incoming healing should apply to health after reserve is full.");
		BaseAbsorbMult = Config.Bind<float>("General", "BaseAbsorbMult", 2f, "Reserve absorption. Base effectiveness of healing going into reserve.");
		AddedAbsorbMult = Config.Bind<float>("General", "AddedAbsorbMult", 1f, "Increased absorption effect per stack.");
		BaseExportMult = Config.Bind<float>("General", "BaseExportMult", 1f, "Base effectiveness of healing coming out of reserve.");
		AddedExportMult = Config.Bind<float>("General", "AddedExportMult", 0f, "Increased healing effect per stack.");
		AegisInteraction = Config.Bind<int>("General", "AegisInteraction", 1, "How does Aegis affect usage rate. 0 = No Effect, 1 = MaxUsage at MinBarrier / MinUsage at MaxBarrier, 2 = Always MaxUsage. Chooses highest between this and amount going to health (amount going to health is highest between MinUsage and HealMissingHealth capped at MaxUsage).");
		RestoreRejuvBehavior = Config.Bind<bool>("General", "RestoreRejuvBehavior", false, "Most healing multipliers used to apply twice when used with Corpsebloom. Set to true to restore this behavior for Rejuvenation Rack.");
		BaseHealthReserve = Config.Bind<float>("General", "BaseHealthReserve", 1f, "Base reserve gained from health.");
		AddedHealthReserve = Config.Bind<float>("General", "AddedHealthReserve", 0.5f, "Added reserve gained from health per stack.");
		VanillaUsageBehavior = Config.Bind<bool>("General", "VanillaUsageBehavior", false, "Scale reserve outputs by 1 / stack count.");
		BaseMaxUsageRate = Config.Bind<float>("General", "BaseMaxUsageRate", 0.1f, "Base maximum healing output from reserve per second.");
		StackMaxUsageRate = Config.Bind<float>("General", "StackMaxUsageRate", 0f, "Stack maximum healing output from reserve per second.");
		BaseMinUsageRate = Config.Bind<float>("General", "BaseMinUsageRate", 0.05f, "Base minimum healing output from reserve per second. Set to 0 to disable reserve decay.");
		StackMinUsageRate = Config.Bind<float>("General", "StackMinUsageRate", 0f, "Stack minimum healing output from reserve per second.");
		if (BaseAbsorbMult.Value < 0.1f)
		{
			BaseAbsorbMult.Value = 0.1f;
		}
		if (BaseExportMult.Value < 0.1f)
		{
			BaseExportMult.Value = 0.1f;
		}
		if (BaseHealthReserve.Value < 0.1f)
		{
			BaseHealthReserve.Value = 0.1f;
		}
		if (BaseMaxUsageRate.Value < 0.01f)
		{
			BaseMaxUsageRate.Value = 0.01f;
		}
		if (BaseMinUsageRate.Value < 0f)
		{
			BaseMinUsageRate.Value = 0f;
		}
	}
}
public class CorpseBloomRebornContent : IContentPackProvider
{
	public static class Buffs
	{
		public static BuffDef CBReserve;

		public static List<BuffDef> buffDefs = new List<BuffDef>();

		public static void Create()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			CBReserve = ScriptableObject.CreateInstance<BuffDef>();
			((Object)CBReserve).name = "CBReserve";
			CBReserve.buffColor = new Color(0.65f, 0.35f, 1f);
			CBReserve.canStack = true;
			CBReserve.isDebuff = false;
			CBReserve.iconSprite = LegacyResourcesAPI.Load<BuffDef>("BuffDefs/MedkitHeal").iconSprite;
			if (Configuration.HideReserveBuff.Value)
			{
				CBReserve.isHidden = true;
			}
			buffDefs.Add(CBReserve);
		}
	}

	public ContentPack contentPack = new ContentPack();

	public string identifier => "CorpseBloomRebornContent";

	public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
	{
		Buffs.Create();
		ReserveManager.IndicatorBuff = Buffs.CBReserve;
		contentPack.buffDefs.Add(Buffs.buffDefs.ToArray());
		args.ReportProgress(1f);
		yield break;
	}

	public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args)
	{
		ContentPack.Copy(contentPack, args.output);
		args.ReportProgress(1f);
		yield break;
	}

	public IEnumerator FinalizeAsync(FinalizeAsyncArgs args)
	{
		args.ReportProgress(1f);
		yield break;
	}
}
[BepInPlugin("com.TPDespair.CorpseBloomReborn", "CorpseBloomReborn", "1.3.0")]
public class CorpseBloomRebornPlugin : BaseUnityPlugin
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static hook_Awake <>9__11_0;

		public static hook_Awake <>9__12_0;

		public static hook_TokenIsRegistered <>9__14_0;

		public static hook_GetString_string <>9__14_1;

		internal void <HudAwakeHook>b__11_0(orig_Awake orig, HUD self)
		{
			orig.Invoke(self);
			HudReserveDisplay hudReserveDisplay = ((Component)self).gameObject.AddComponent<HudReserveDisplay>();
			hudReserveDisplay.hud = self;
		}

		internal void <AllyCardAwakeHook>b__12_0(orig_Awake orig, AllyCardController self)
		{
			orig.Invoke(self);
			AllyReserveDisplay allyReserveDisplay = ((Component)self).gameObject.AddComponent<AllyReserveDisplay>();
			allyReserveDisplay.controller = self;
		}

		internal bool <LanguageOverride>b__14_0(orig_TokenIsRegistered orig, Language self, string token)
		{
			if (token != null && LangTokens.ContainsKey(token))
			{
				return true;
			}
			return orig.Invoke(self, token);
		}

		internal string <LanguageOverride>b__14_1(orig_GetString_string orig, string token)
		{
			if (token != null && LangTokens.ContainsKey(token))
			{
				return LangTokens[token];
			}
			return orig.Invoke(token);
		}
	}

	public const string ModVer = "1.3.0";

	public const string ModName = "CorpseBloomReborn";

	public const string ModGuid = "com.TPDespair.CorpseBloomReborn";

	public static Dictionary<string, string> LangTokens = new Dictionary<string, string>();

	public static ArtifactIndex DiluvianArtifact = (ArtifactIndex)(-1);

	public void Awake()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		RoR2Application.isModded = true;
		NetworkModCompatibilityHelper.networkModList = NetworkModCompatibilityHelper.networkModList.Append("com.TPDespair.CorpseBloomReborn:1.3.0");
		Configuration.Init(((BaseUnityPlugin)this).Config);
		ContentManager.collectContentPackProviders += new CollectContentPackProvidersDelegate(ContentManager_collectContentPackProviders);
		ReserveManager.Init();
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(ApplicationOnLoad));
		HudAwakeHook();
		AllyCardAwakeHook();
		HUD.onHudTargetChangedGlobal += HudTargetChanged;
		LanguageOverride();
		RegisterLanguageToken("ITEM_REPEATHEAL_DESC", GetCorpseBloomDesc());
		RegisterLanguageToken("ITEM_REPEATHEAL_PICKUP", GetCorpseBloomPickup());
	}

	public void FixedUpdate()
	{
		ReserveManager.OnFixedUpdate();
	}

	private void ContentManager_collectContentPackProviders(AddContentPackProviderDelegate addContentPackProvider)
	{
		addContentPackProvider.Invoke((IContentPackProvider)(object)new CorpseBloomRebornContent());
	}

	private static void ApplicationOnLoad()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Invalid comparison between Unknown and I4
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		Run.onRunStartGlobal += RunStartHealPriority;
		ArtifactIndex val = ArtifactCatalog.FindArtifactIndex("ARTIFACT_DILUVIFACT");
		if ((int)val != -1)
		{
			DiluvianArtifact = val;
			RunArtifactManager.onArtifactEnabledGlobal += new ArtifactStateChangeDelegate(ArtifactEnabledHealPriority);
		}
	}

	private static void RunStartHealPriority(Run run)
	{
		ReserveManager.RequestPriorityHealHook();
	}

	private static void ArtifactEnabledHealPriority(RunArtifactManager manager, ArtifactDef artifactDef)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)artifactDef) && artifactDef.artifactIndex == DiluvianArtifact)
		{
			ReserveManager.RequestPriorityHealHook();
		}
	}

	private static void HudAwakeHook()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		object obj = <>c.<>9__11_0;
		if (obj == null)
		{
			hook_Awake val = delegate(orig_Awake orig, HUD self)
			{
				orig.Invoke(self);
				HudReserveDisplay hudReserveDisplay = ((Component)self).gameObject.AddComponent<HudReserveDisplay>();
				hudReserveDisplay.hud = self;
			};
			<>c.<>9__11_0 = val;
			obj = (object)val;
		}
		HUD.Awake += (hook_Awake)obj;
	}

	private static void AllyCardAwakeHook()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		object obj = <>c.<>9__12_0;
		if (obj == null)
		{
			hook_Awake val = delegate(orig_Awake orig, AllyCardController self)
			{
				orig.Invoke(self);
				AllyReserveDisplay allyReserveDisplay = ((Component)self).gameObject.AddComponent<AllyReserveDisplay>();
				allyReserveDisplay.controller = self;
			};
			<>c.<>9__12_0 = val;
			obj = (object)val;
		}
		AllyCardController.Awake += (hook_Awake)obj;
	}

	private static void HudTargetChanged(HUD hud)
	{
		HudReserveDisplay component = ((Component)hud).GetComponent<HudReserveDisplay>();
		if (Object.op_Implicit((Object)(object)component))
		{
			component.RequestRebuild();
		}
	}

	private static void LanguageOverride()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		object obj = <>c.<>9__14_0;
		if (obj == null)
		{
			hook_TokenIsRegistered val = (orig_TokenIsRegistered orig, Language self, string token) => (token != null && LangTokens.ContainsKey(token)) || orig.Invoke(self, token);
			<>c.<>9__14_0 = val;
			obj = (object)val;
		}
		Language.TokenIsRegistered += (hook_TokenIsRegistered)obj;
		object obj2 = <>c.<>9__14_1;
		if (obj2 == null)
		{
			hook_GetString_string val2 = (orig_GetString_string orig, string token) => (token != null && LangTokens.ContainsKey(token)) ? LangTokens[token] : orig.Invoke(token);
			<>c.<>9__14_1 = val2;
			obj2 = (object)val2;
		}
		Language.GetString_string += (hook_GetString_string)obj2;
	}

	public static void RegisterLanguageToken(string token, string text)
	{
		if (!LangTokens.ContainsKey(token))
		{
			LangTokens.Add(token, text);
		}
		else
		{
			LangTokens[token] = text;
		}
	}

	private static string GetCorpseBloomDesc()
	{
		string text = "";
		text = (Configuration.HealBeforeReserve.Value ? (text + "Gain extra healing as reserve.") : ((!Configuration.HealWhenReserveFull.Value) ? (text + "All healing is applied over time.") : (text + "Store healing to heal over time.")));
		text += "\nGain <style=cIsHealing>";
		text += $"{Configuration.BaseHealthReserve.Value * 100f:0.##}%</style>";
		if (Configuration.AddedHealthReserve.Value != 0f)
		{
			text += " <style=cStack>(";
			if (Configuration.AddedHealthReserve.Value > 0f)
			{
				text += "+";
			}
			text += $"{Configuration.AddedHealthReserve.Value * 100f:0.##}% per stack)</style>";
		}
		text += " of your <style=cIsHealing>maximum health</style> as <style=cIsHealing>maximum reserve</style>.";
		text = text + "\nStore <style=cIsHealing>" + Configuration.BaseAbsorbMult.Value * 100f + "%</style>";
		if (Configuration.AddedAbsorbMult.Value != 0f)
		{
			text += " <style=cStack>(";
			if (Configuration.AddedAbsorbMult.Value > 0f)
			{
				text += "+";
			}
			text = text + Configuration.AddedAbsorbMult.Value * 100f + "% per stack)</style>";
		}
		text += " of healing as <style=cIsHealing>reserve</style>.";
		text += "\nCan <style=cIsHealing>heal</style> for <style=cIsHealing>";
		text += $"{Configuration.BaseMaxUsageRate.Value * 100f:0.##}%</style>";
		if (Configuration.StackMaxUsageRate.Value != 0f)
		{
			text += " <style=cStack>(";
			if (Configuration.StackMaxUsageRate.Value > 0f)
			{
				text += "+";
			}
			text += $"{Configuration.StackMaxUsageRate.Value * 100f:0.##}% per stack)</style>";
		}
		text += " of your <style=cIsHealing>maximum health</style> every second from <style=cIsHealing>reserve</style>.";
		if (Configuration.VanillaUsageBehavior.Value)
		{
			text += "\n<style=cStack>(Additional stacks further reduce healing rate)</style>";
		}
		text += "\n";
		if (Configuration.BaseExportMult.Value != 1f || Configuration.AddedExportMult.Value != 0f)
		{
			string text2 = ((Configuration.AddedExportMult.Value == 0f) ? ((!(Configuration.BaseExportMult.Value > 1f)) ? "<style=cDeath>" : "<style=cIsHealing>") : ((Configuration.AddedExportMult.Value > 0f) ? ((!(Configuration.BaseExportMult.Value >= 1f)) ? "<style=cIsDamage>" : "<style=cIsHealing>") : ((!(Configuration.BaseExportMult.Value > 1f)) ? "<style=cDeath>" : "<style=cIsDamage>")));
			text = text + "\n" + text2;
			if (Configuration.BaseExportMult.Value >= 1f)
			{
				text += "+";
			}
			text += $"{(Configuration.BaseExportMult.Value - 1f) * 100f:0.##}%</style>";
			if (Configuration.AddedExportMult.Value != 0f)
			{
				text += " <style=cStack>(";
				if (Configuration.AddedExportMult.Value > 0f)
				{
					text += "+";
				}
				text += $"{Configuration.AddedExportMult.Value * 100f:0.##}% per stack)</style>";
			}
			text += " Healing Multiplier.";
		}
		return text;
	}

	private static string GetCorpseBloomPickup()
	{
		if (Configuration.HealBeforeReserve.Value)
		{
			return "Gain extra healing as reserve.";
		}
		if (Configuration.HealWhenReserveFull.Value)
		{
			return "Store healing to heal over time.";
		}
		return "All healing is applied over time.";
	}
}
public class BaseReserveDisplay : MonoBehaviour
{
	public HealthBar healthBar;

	private GameObject reserveContainer;

	private RectTransform containerTransform;

	private GameObject reserveBar;

	private RectTransform barTransform;

	private float reserveFraction = 0f;

	private float displayScale = 0f;

	private bool rebuild = true;

	private float rebuildTimer = 0.25f;

	public void UpdateReserveDisplay()
	{
		UpdateDisplayValues();
		UpdateContainer();
		UpdateDisplay();
	}

	public void UpdateDisplayValues()
	{
		reserveFraction = 0f;
		if (!Object.op_Implicit((Object)(object)healthBar))
		{
			return;
		}
		HealthComponent source = healthBar.source;
		if (!Object.op_Implicit((Object)(object)source))
		{
			return;
		}
		CharacterBody body = source.body;
		if (Object.op_Implicit((Object)(object)body))
		{
			int buffCount = body.GetBuffCount(CorpseBloomRebornContent.Buffs.CBReserve);
			if (buffCount > 0)
			{
				reserveFraction = Mathf.Clamp((float)buffCount / 100f, 0f, 1f);
				displayScale = 1f / body.cursePenalty * (source.fullHealth / source.fullCombinedHealth);
			}
		}
	}

	public void UpdateContainer()
	{
		if (Object.op_Implicit((Object)(object)reserveContainer) && rebuild)
		{
			rebuildTimer -= Time.deltaTime;
			if (rebuildTimer <= 0f)
			{
				rebuildTimer = 0.25f;
				rebuild = false;
				DestroyReserveBar();
			}
		}
		if (reserveFraction > 0f && !Object.op_Implicit((Object)(object)reserveContainer))
		{
			CreateReserveBar();
		}
	}

	public void UpdateDisplay()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)reserveContainer))
		{
			return;
		}
		if (reserveFraction > 0f)
		{
			float num = -0.5f + reserveFraction * displayScale;
			barTransform.anchorMax = new Vector2(num, 0.5f);
			if (!reserveContainer.activeSelf)
			{
				reserveContainer.SetActive(true);
			}
		}
		else if (reserveContainer.activeSelf)
		{
			reserveContainer.SetActive(false);
		}
	}

	public void RequestRebuild()
	{
		rebuildTimer = 0.25f;
		rebuild = true;
	}

	private void DestroyReserveBar()
	{
		reserveContainer.SetActive(false);
		Object.Destroy((Object)(object)reserveContainer);
		reserveContainer = null;
		containerTransform = null;
		reserveBar = null;
		barTransform = null;
	}

	private void CreateReserveBar()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Expected O, but got Unknown
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		Rect rect = healthBar.barContainer.rect;
		float width = ((Rect)(ref rect)).width;
		float num = Mathf.CeilToInt(((Rect)(ref rect)).height / 3.125f);
		float num2 = width / 2f;
		reserveContainer = new GameObject("ReserveRect");
		containerTransform = reserveContainer.AddComponent<RectTransform>();
		((Transform)containerTransform).position = new Vector3(0f, 0f);
		containerTransform.anchoredPosition = new Vector2(num2, 0f);
		containerTransform.anchorMin = new Vector2(0f, 0f);
		containerTransform.anchorMax = new Vector2(0f, 0f);
		containerTransform.offsetMin = new Vector2(num2, 0f);
		containerTransform.offsetMax = new Vector2(num2, num);
		containerTransform.sizeDelta = new Vector2(width, num);
		containerTransform.pivot = new Vector2(0f, 0f);
		reserveBar = new GameObject("ReserveBar");
		reserveBar.transform.SetParent(((Component)containerTransform).transform);
		barTransform = reserveBar.AddComponent<RectTransform>();
		barTransform.sizeDelta = new Vector2(width, num);
		barTransform.pivot = new Vector2(0.5f, 1f);
		((Graphic)reserveBar.AddComponent<Image>()).color = new Color(0.625f, 0.25f, 1f, 0.65f);
		reserveContainer.transform.SetParent(((Component)healthBar).transform, false);
	}
}
public class HudReserveDisplay : BaseReserveDisplay
{
	public HUD hud;

	public void Update()
	{
		if (Object.op_Implicit((Object)(object)hud))
		{
			healthBar = hud.healthBar;
		}
		UpdateReserveDisplay();
	}
}
public class AllyReserveDisplay : BaseReserveDisplay
{
	public AllyCardController controller;

	public bool indented = false;

	public void Update()
	{
		if (Object.op_Implicit((Object)(object)controller))
		{
			healthBar = controller.healthBar;
			bool shouldIndent = controller.shouldIndent;
			if (indented != shouldIndent)
			{
				RequestRebuild();
				indented = shouldIndent;
			}
		}
		UpdateReserveDisplay();
	}
}
public static class ReserveManager
{
	public class ReserveInfo
	{
		public HealthComponent healthComponent;

		public float healTimer = 0.25f;

		public float displayTimer = 0.25f;

		public int buffCount = 0;

		public float maximum = 1f;

		public float reserve = 0f;

		public float maxRate = 0.1f;

		public float minRate = 0f;

		public float absorbMult = 1f;

		public float exportMult = 1f;

		public bool healingDisabled = false;

		public int aegisState = 0;
	}

	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static hook_RecalculateStats <>9__15_0;

		public static hook_OnDestroy <>9__16_0;

		internal void <RecalculateReserveHook>b__15_0(orig_RecalculateStats orig, CharacterBody self)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			if (NetworkServer.active && Object.op_Implicit((Object)(object)self) && ReserveData.ContainsKey(((NetworkBehaviour)self).netId))
			{
				RecalcReserveInfo(self);
			}
		}

		internal void <DestroyReserveHook>b__16_0(orig_OnDestroy orig, CharacterBody self)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active & Object.op_Implicit((Object)(object)self))
			{
				DestroyedBodies.Add(((NetworkBehaviour)self).netId, 3.5f);
				if (ReserveData.ContainsKey(((NetworkBehaviour)self).netId))
				{
					ReserveData[((NetworkBehaviour)self).netId].healthComponent = null;
				}
			}
			orig.Invoke(self);
		}
	}

	public static Dictionary<NetworkInstanceId, ReserveInfo> ReserveData = new Dictionary<NetworkInstanceId, ReserveInfo>();

	private static Dictionary<NetworkInstanceId, float> DestroyedBodies = new Dictionary<NetworkInstanceId, float>();

	private static float DestroyFixedUpdateStopwatch = 0f;

	private const float ReserveUpdateInterval = 0.25f;

	internal static BuffDef IndicatorBuff;

	private static bool Rehook = false;

	private static float RehookTimer = 0f;

	private static bool HealHooked = false;

	public static ReserveInfo GetReserveInfo(HealthComponent healthComponent)
	{
		CharacterBody body = healthComponent.body;
		if (Object.op_Implicit((Object)(object)body))
		{
			return GetReserveInfo(body);
		}
		return null;
	}

	public static ReserveInfo GetReserveInfo(CharacterBody body)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		if (DestroyedBodies.ContainsKey(((NetworkBehaviour)body).netId))
		{
			return null;
		}
		if (!ReserveData.ContainsKey(((NetworkBehaviour)body).netId))
		{
			ReserveInfo value = new ReserveInfo();
			ReserveData.Add(((NetworkBehaviour)body).netId, value);
			RecalcReserveInfo(body);
		}
		return ReserveData[((NetworkBehaviour)body).netId];
	}

	private static void RecalcReserveInfo(CharacterBody body)
	{
		ReserveInfo reserveInfo = GetReserveInfo(body);
		if (reserveInfo == null)
		{
			return;
		}
		float num = 1f;
		float num2 = 0.1f;
		float num3 = 0f;
		float num4 = 1f;
		float exportMult = 1f;
		int aegisState = 0;
		if (!Object.op_Implicit((Object)(object)reserveInfo.healthComponent))
		{
			HealthComponent healthComponent = body.healthComponent;
			if (Object.op_Implicit((Object)(object)healthComponent))
			{
				reserveInfo.healthComponent = healthComponent;
			}
		}
		Inventory inventory = body.inventory;
		if (Object.op_Implicit((Object)(object)inventory))
		{
			int itemCount = inventory.GetItemCount(Items.RepeatHeal);
			if (itemCount > 0)
			{
				num = Mathf.Max(0.1f, Configuration.BaseHealthReserve.Value + Configuration.AddedHealthReserve.Value * (float)(itemCount - 1));
				num3 = Mathf.Max(0f, Configuration.BaseMinUsageRate.Value + Configuration.StackMinUsageRate.Value * (float)(itemCount - 1));
				num2 = Mathf.Max(new float[3]
				{
					0.01f,
					num3,
					Configuration.BaseMaxUsageRate.Value + Configuration.StackMaxUsageRate.Value * (float)(itemCount - 1)
				});
				if (Configuration.VanillaUsageBehavior.Value)
				{
					num3 = Mathf.Max(0f, num3 / (float)itemCount);
					num2 = Mathf.Max(0.01f, num2 / (float)itemCount);
				}
				num4 = Mathf.Max(0.1f, Configuration.BaseAbsorbMult.Value + Configuration.AddedAbsorbMult.Value * (float)(itemCount - 1));
				exportMult = Mathf.Max(0.1f, Configuration.BaseExportMult.Value + Configuration.AddedExportMult.Value * (float)(itemCount - 1));
			}
			else
			{
				reserveInfo.reserve = 0f;
			}
			if (Configuration.RestoreRejuvBehavior.Value)
			{
				itemCount = inventory.GetItemCount(Items.IncreaseHealing);
				if (itemCount > 0)
				{
					num4 *= 1f + (float)itemCount;
				}
			}
			if (Configuration.AegisInteraction.Value > 0)
			{
				itemCount = inventory.GetItemCount(Items.BarrierOnOverHeal);
				if (itemCount > 0)
				{
					aegisState = Configuration.AegisInteraction.Value;
				}
			}
		}
		reserveInfo.maximum = Mathf.Max(1f, body.maxHealth * num);
		reserveInfo.reserve = Mathf.Min(reserveInfo.reserve, reserveInfo.maximum);
		reserveInfo.maxRate = num2;
		reserveInfo.minRate = num3;
		reserveInfo.absorbMult = num4;
		reserveInfo.exportMult = exportMult;
		reserveInfo.healingDisabled = body.HasBuff(Buffs.HealingDisabled);
		reserveInfo.aegisState = aegisState;
	}

	public static void AddReserve(ReserveInfo reserveInfo, float amount)
	{
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		float num = 0f;
		float num2 = 0f;
		HealthComponent healthComponent = reserveInfo.healthComponent;
		if (Object.op_Implicit((Object)(object)healthComponent))
		{
			if (Configuration.HealBeforeReserve.Value)
			{
				num = Math.Min(amount, (healthComponent.fullHealth - healthComponent.health) / reserveInfo.exportMult);
				amount -= num;
			}
			if (amount > 0f)
			{
				num2 = Math.Min(amount, (reserveInfo.maximum - reserveInfo.reserve) / reserveInfo.absorbMult);
				amount -= num2;
			}
			if (amount > 0f && Configuration.HealWhenReserveFull.Value)
			{
				num += amount;
			}
			if (num > 0f)
			{
				ProcChainMask val = default(ProcChainMask);
				((ProcChainMask)(ref val)).AddProc((ProcType)13);
				healthComponent.Heal(num * reserveInfo.exportMult, val, true);
			}
		}
		else
		{
			num2 = amount;
		}
		reserveInfo.reserve = Mathf.Min(reserveInfo.reserve + num2 * reserveInfo.absorbMult, reserveInfo.maximum);
	}

	internal static void Init()
	{
		RecalculateReserveHook();
		DestroyReserveHook();
	}

	internal static void OnFixedUpdate()
	{
		PrioritizeHealHook();
		DestroyReserveData();
		if (NetworkServer.active && Object.op_Implicit((Object)(object)Run.instance))
		{
			UpdateReserveInfos();
		}
	}

	private static void RecalculateReserveHook()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		object obj = <>c.<>9__15_0;
		if (obj == null)
		{
			hook_RecalculateStats val = delegate(orig_RecalculateStats orig, CharacterBody self)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				orig.Invoke(self);
				if (NetworkServer.active && Object.op_Implicit((Object)(object)self) && ReserveData.ContainsKey(((NetworkBehaviour)self).netId))
				{
					RecalcReserveInfo(self);
				}
			};
			<>c.<>9__15_0 = val;
			obj = (object)val;
		}
		CharacterBody.RecalculateStats += (hook_RecalculateStats)obj;
	}

	private static void DestroyReserveHook()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		object obj = <>c.<>9__16_0;
		if (obj == null)
		{
			hook_OnDestroy val = delegate(orig_OnDestroy orig, CharacterBody self)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				if (NetworkServer.active & Object.op_Implicit((Object)(object)self))
				{
					DestroyedBodies.Add(((NetworkBehaviour)self).netId, 3.5f);
					if (ReserveData.ContainsKey(((NetworkBehaviour)self).netId))
					{
						ReserveData[((NetworkBehaviour)self).netId].healthComponent = null;
					}
				}
				orig.Invoke(self);
			};
			<>c.<>9__16_0 = val;
			obj = (object)val;
		}
		CharacterBody.OnDestroy += (hook_OnDestroy)obj;
	}

	internal static void RequestPriorityHealHook()
	{
		RehookTimer = 1f;
		Rehook = true;
	}

	private static void PrioritizeHealHook()
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Expected O, but got Unknown
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		if (!Rehook)
		{
			return;
		}
		RehookTimer -= Time.fixedDeltaTime;
		if (RehookTimer <= 0f)
		{
			RehookTimer = 1f;
			Rehook = false;
			if (HealHooked)
			{
				HealthComponent.Heal -= new hook_Heal(PriorityHealHook);
				HealHooked = false;
			}
			HealthComponent.Heal += new hook_Heal(PriorityHealHook);
			HealHooked = true;
		}
	}

	private static float PriorityHealHook(orig_Heal orig, HealthComponent self, float amount, ProcChainMask procChainMask, bool nonRegen)
	{
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkServer.active && nonRegen && Object.op_Implicit((Object)(object)self.repeatHealComponent) && !((ProcChainMask)(ref procChainMask)).HasProc((ProcType)13))
		{
			if (self.alive && amount > 0f && !self.body.HasBuff(Buffs.HealingDisabled))
			{
				ReserveInfo reserveInfo = GetReserveInfo(self);
				if (reserveInfo != null)
				{
					AddReserve(reserveInfo, amount);
				}
			}
			return 0f;
		}
		return orig.Invoke(self, amount, procChainMask, nonRegen);
	}

	private static void DestroyReserveData()
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		DestroyFixedUpdateStopwatch += Time.fixedDeltaTime;
		if (!(DestroyFixedUpdateStopwatch >= 0.5f))
		{
			return;
		}
		List<NetworkInstanceId> list = new List<NetworkInstanceId>(DestroyedBodies.Keys);
		foreach (NetworkInstanceId item in list)
		{
			DestroyedBodies[item] -= DestroyFixedUpdateStopwatch;
			if (DestroyedBodies[item] <= 0f)
			{
				DestroyedBodies.Remove(item);
				if (ReserveData.ContainsKey(item))
				{
					ReserveData.Remove(item);
				}
			}
		}
		DestroyFixedUpdateStopwatch = 0f;
	}

	private static void UpdateReserveInfos()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		float fixedDeltaTime = Time.fixedDeltaTime;
		List<NetworkInstanceId> list = new List<NetworkInstanceId>(ReserveData.Keys);
		foreach (NetworkInstanceId item in list)
		{
			if (!DestroyedBodies.ContainsKey(item))
			{
				UpdateReserveInfo(ReserveData[item], fixedDeltaTime);
			}
		}
	}

	private static void UpdateReserveInfo(ReserveInfo reserveInfo, float deltaTime)
	{
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		HealthComponent healthComponent = reserveInfo.healthComponent;
		if (!Object.op_Implicit((Object)(object)healthComponent) || !healthComponent.alive)
		{
			return;
		}
		reserveInfo.displayTimer -= deltaTime;
		if (reserveInfo.displayTimer <= 0f)
		{
			reserveInfo.displayTimer = 0.25f;
			CharacterBody body = healthComponent.body;
			if (Object.op_Implicit((Object)(object)body))
			{
				int num = 0;
				if (reserveInfo.reserve > 0f)
				{
					num = Mathf.Clamp(Mathf.RoundToInt(reserveInfo.reserve / reserveInfo.maximum * 100f), 1, 100);
				}
				reserveInfo.buffCount = num;
				if (body.GetBuffCount(IndicatorBuff) != num)
				{
					body.SetBuffCount(IndicatorBuff.buffIndex, num);
				}
			}
		}
		if (ResetTimer(reserveInfo))
		{
			reserveInfo.healTimer = 0.25f;
			return;
		}
		reserveInfo.healTimer -= deltaTime;
		if (reserveInfo.healTimer <= 0f)
		{
			reserveInfo.healTimer = 0.25f;
			reserveInfo.displayTimer = Mathf.Clamp(reserveInfo.displayTimer, 0.15f, 0.2f);
			float num2 = ReserveHealAmount(reserveInfo);
			reserveInfo.reserve -= num2;
			ProcChainMask val = default(ProcChainMask);
			((ProcChainMask)(ref val)).AddProc((ProcType)13);
			reserveInfo.healthComponent.Heal(num2 * reserveInfo.exportMult, val, true);
		}
	}

	private static bool ResetTimer(ReserveInfo reserveInfo)
	{
		if (reserveInfo.reserve <= 0f)
		{
			return true;
		}
		if (reserveInfo.healingDisabled)
		{
			return true;
		}
		if (reserveInfo.minRate > 0f)
		{
			return false;
		}
		if (reserveInfo.aegisState > 0)
		{
			return false;
		}
		HealthComponent healthComponent = reserveInfo.healthComponent;
		if (healthComponent.health >= healthComponent.fullHealth)
		{
			return true;
		}
		return false;
	}

	private static float ReserveHealAmount(ReserveInfo reserveInfo)
	{
		HealthComponent healthComponent = reserveInfo.healthComponent;
		float fullHealth = healthComponent.fullHealth;
		float num = fullHealth * reserveInfo.maxRate * 0.25f;
		if (reserveInfo.aegisState >= 2)
		{
			return Mathf.Min(reserveInfo.reserve, num);
		}
		float num2 = fullHealth * reserveInfo.minRate * 0.25f;
		float num3 = (fullHealth - healthComponent.health) / reserveInfo.exportMult;
		float num4 = Mathf.Max(num2, num3);
		if (reserveInfo.aegisState == 1)
		{
			float num5 = Mathf.Lerp(num, num2, healthComponent.barrier / healthComponent.fullBarrier);
			num4 = Mathf.Max(num4, num5);
		}
		return Mathf.Min(new float[3] { reserveInfo.reserve, num, num4 });
	}
}