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 });
}
}