Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of CorpseBloomReborn v1.3.0
plugins/CorpseBloomReborn/CorpseBloomReborn.dll
Decompiled a year agousing 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 }); } }