Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VoidfiendSupressRework v1.0.2
BepInEx/plugins/SupressRework.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.VoidSurvivor.Weapon; using HarmonyLib; using Microsoft.CodeAnalysis; using On.RoR2; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Skills; using RoR2.UI; using UnityEngine; using UnityEngine.AddressableAssets; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SupressRework")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+08bbd3a7d90de663ad916caf69871e85548e44b3")] [assembly: AssemblyProduct("SupressRework")] [assembly: AssemblyTitle("SupressRework")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace SuppressRework { [BepInPlugin("com.renovice.suppressrework", "Suppress Rework", "1.4.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class SuppressRework : BaseUnityPlugin { public static ConfigEntry<bool> EnableAllOrNothingScaling; public static ConfigEntry<bool> EnableEfficientTrades; public static ConfigEntry<float> MaxHealthSacrifice; public static ConfigEntry<float> FixedTradeValue; public static ConfigEntry<int> MaxChargesNormalMode; public static ConfigEntry<int> MaxChargesCorruptedMode; public static ConfigEntry<bool> InfiniteChargesNormalMode; public static ConfigEntry<bool> InfiniteChargesCorruptedMode; internal static SkillDef _crushHealthDef; internal static SkillDef _crushCorruptionDef; internal static ManualLogSource Log; public static SuppressRework Instance { get; private set; } public void Awake() { //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; try { EnableAllOrNothingScaling = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "Enable All-or-Nothing Scaling", false, "If true, the ability consumes your resource bar for a 1:1 reward. If false, it uses a fixed percentage."); EnableEfficientTrades = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "Enable Efficient Trades", true, "If true, the ability will not spend more resources than needed to fill the target bar."); MaxHealthSacrifice = ((BaseUnityPlugin)this).Config.Bind<float>("All-or-Nothing Mode", "Max Health Sacrifice Percent", 50f, "When 'All-or-Nothing' is ON, this is the MAXIMUM percentage of your health you can sacrifice in one go."); FixedTradeValue = ((BaseUnityPlugin)this).Config.Bind<float>("Fixed Trade Mode", "Fixed Trade Percentage", 35f, "When 'All-or-Nothing' is OFF, this is the percentage of health/corruption that will be traded."); MaxChargesNormalMode = ((BaseUnityPlugin)this).Config.Bind<int>("Charge Settings", "Max Charges - Suppress", 1, "Maximum charges for the suppress ability (spend corruption to heal in normal mode). No cooldown - you get this many per transformation."); MaxChargesCorruptedMode = ((BaseUnityPlugin)this).Config.Bind<int>("Charge Settings", "Max Charges - Corrupted Suppress", 2, "Maximum charges for the corrupted suppress ability (sacrifice health for corruption in void mode). No cooldown - you get this many per transformation."); InfiniteChargesNormalMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Charge Settings", "Infinite Charges - Suppress", true, "If true, suppress ability has infinite charges in normal mode."); InfiniteChargesCorruptedMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Charge Settings", "Infinite Charges - Corrupted Suppress", false, "If true, corrupted suppress ability has infinite charges in void mode."); SetupRiskOfOptions(); Harmony val = new Harmony("com.renovice.suppressrework"); val.PatchAll(); SurvivorCatalog.Init += (hook_Init)delegate(orig_Init orig) { orig.Invoke(); OnGameLoaded(); }; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Suppress Rework v1.4.2 - Performance-Safe Voidfiend Complete Overhaul loaded successfully!"); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Error in Awake: {arg}"); } } private void SetupRiskOfOptions() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown try { ModSettingsManager.SetModDescription("A complete overhaul of Voidfiend's Suppress ability with customizable trading mechanics, charge systems, and dynamic tooltips."); SetModIcon(); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(EnableAllOrNothingScaling)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(EnableEfficientTrades)); ModSettingsManager.AddOption((BaseOption)new SliderOption(MaxHealthSacrifice, new SliderConfig { min = 1f, max = 100f, FormatString = "{0:0}%" })); ModSettingsManager.AddOption((BaseOption)new SliderOption(FixedTradeValue, new SliderConfig { min = 1f, max = 100f, FormatString = "{0:0}%" })); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(MaxChargesNormalMode, new IntSliderConfig { min = 0, max = 20 })); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(MaxChargesCorruptedMode, new IntSliderConfig { min = 0, max = 20 })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(InfiniteChargesNormalMode)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(InfiniteChargesCorruptedMode)); EnableAllOrNothingScaling.SettingChanged += delegate { OnSettingChanged(); }; EnableEfficientTrades.SettingChanged += delegate { OnSettingChanged(); }; MaxHealthSacrifice.SettingChanged += delegate { OnSettingChanged(); }; FixedTradeValue.SettingChanged += delegate { OnSettingChanged(); }; MaxChargesNormalMode.SettingChanged += delegate { OnSettingChanged(); }; MaxChargesCorruptedMode.SettingChanged += delegate { OnSettingChanged(); }; InfiniteChargesNormalMode.SettingChanged += delegate { OnSettingChanged(); }; InfiniteChargesCorruptedMode.SettingChanged += delegate { OnSettingChanged(); }; } catch (Exception arg) { Log.LogError((object)$"Error setting up Risk of Options: {arg}"); } } private void SetModIcon() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("V8_supressrework.icon.png"); if (stream != null) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); Sprite modIcon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ModSettingsManager.SetModIcon(modIcon); Log.LogInfo((object)"Mod icon set successfully"); } } catch (Exception arg) { Log.LogError((object)$"Failed to set mod icon: {arg}"); } } private void OnSettingChanged() { try { ModifySkillDefs(); TooltipRefresher.RefreshTooltipsAfterSettingsChange(); Log.LogInfo((object)"Settings changed - skill descriptions should update dynamically"); } catch (Exception arg) { Log.LogError((object)$"Error in OnSettingChanged: {arg}"); } } private void OnGameLoaded() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0023: Unknown result type (might be due to invalid IL or missing references) try { _crushHealthDef = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/DLC1/VoidSurvivor/CrushHealth.asset").WaitForCompletion(); _crushCorruptionDef = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/DLC1/VoidSurvivor/CrushCorruption.asset").WaitForCompletion(); if ((Object)(object)_crushHealthDef != (Object)null) { Log.LogInfo((object)("CrushHealth loaded successfully. Token: " + _crushHealthDef.skillDescriptionToken)); } else { Log.LogError((object)"Failed to load CrushHealth skill definition"); } if ((Object)(object)_crushCorruptionDef != (Object)null) { Log.LogInfo((object)("CrushCorruption loaded successfully. Token: " + _crushCorruptionDef.skillDescriptionToken)); } else { Log.LogError((object)"Failed to load CrushCorruption skill definition"); } ModifySkillDefs(); } catch (Exception arg) { Log.LogError((object)$"Error in OnGameLoaded: {arg}"); } } public void ModifySkillDefs() { try { if ((Object)(object)_crushHealthDef != (Object)null) { if (InfiniteChargesCorruptedMode.Value) { _crushHealthDef.baseMaxStock = 1; _crushHealthDef.rechargeStock = 1; _crushHealthDef.baseRechargeInterval = 0f; Log.LogInfo((object)"Corrupted Suppress: Infinite charges enabled (instant recharge)"); } else { _crushHealthDef.baseMaxStock = MaxChargesCorruptedMode.Value; _crushHealthDef.rechargeStock = 0; _crushHealthDef.baseRechargeInterval = 0f; Log.LogInfo((object)$"Corrupted Suppress: {MaxChargesCorruptedMode.Value} charges, no recharge"); } } if (!((Object)(object)_crushCorruptionDef != (Object)null)) { return; } if (InfiniteChargesNormalMode.Value) { _crushCorruptionDef.baseMaxStock = 1; _crushCorruptionDef.rechargeStock = 1; _crushCorruptionDef.baseRechargeInterval = 0f; Log.LogInfo((object)"Suppress: Infinite charges enabled (instant recharge)"); } else { _crushCorruptionDef.baseMaxStock = MaxChargesNormalMode.Value; _crushCorruptionDef.rechargeStock = 0; _crushCorruptionDef.baseRechargeInterval = 0f; Log.LogInfo((object)$"Suppress: {MaxChargesNormalMode.Value} charges, no recharge"); } if (((object)_crushCorruptionDef).GetType().Name == "VoidSurvivorSkillDef") { FieldInfo field = ((object)_crushCorruptionDef).GetType().GetField("minimumCorruption"); FieldInfo field2 = ((object)_crushCorruptionDef).GetType().GetField("maximumCorruption"); if (field != null) { field.SetValue(_crushCorruptionDef, 0.1f); Log.LogInfo((object)"Set CrushCorruption minimumCorruption to: 0.1"); } if (field2 != null) { field2.SetValue(_crushCorruptionDef, 100f); Log.LogInfo((object)"Set CrushCorruption maximumCorruption to: 100"); } } } catch (Exception arg) { Log.LogError((object)$"Error in ModifySkillDefs: {arg}"); } } } [HarmonyPatch(typeof(CrushBase), "OnEnter")] public static class CrushBase_OnEnter_Patch { private static bool Prefix(CrushBase __instance) { try { CharacterBody characterBody = ((EntityState)__instance).characterBody; if ((Object)(object)characterBody == (Object)null) { return true; } if (!SuppressRework.EnableAllOrNothingScaling.Value) { float value = SuppressRework.FixedTradeValue.Value; if (__instance is CrushHealth) { HealthComponent healthComponent = characterBody.healthComponent; if ((Object)(object)healthComponent != (Object)null && healthComponent.fullHealth > 0f) { float num = healthComponent.health / healthComponent.fullHealth * 100f; if (num < value) { ManualLogSource log = SuppressRework.Log; if (log != null) { log.LogWarning((object)$"BLOCKED CrushHealth execution: {num:F1}% < {value}% required"); } ((EntityState)__instance).outer.SetNextStateToMain(); return false; } } } else if (__instance is CrushCorruption) { VoidSurvivorController component = ((Component)characterBody).GetComponent<VoidSurvivorController>(); if ((Object)(object)component != (Object)null) { float corruption = component.corruption; if (corruption < value) { ManualLogSource log2 = SuppressRework.Log; if (log2 != null) { log2.LogWarning((object)$"BLOCKED CrushCorruption execution: {corruption:F1}% < {value}% required"); } ((EntityState)__instance).outer.SetNextStateToMain(); return false; } } } } float num2 = 0f; float num3 = 0f; if (SuppressRework.EnableAllOrNothingScaling.Value) { if (__instance is CrushHealth) { HealthComponent healthComponent2 = characterBody.healthComponent; if ((Object)(object)healthComponent2 == (Object)null || healthComponent2.fullHealth <= 0f) { ManualLogSource log3 = SuppressRework.Log; if (log3 != null) { log3.LogWarning((object)"CrushHealth: No health component, aborting"); } ((EntityState)__instance).outer.SetNextStateToMain(); return false; } float num4 = healthComponent2.health - 1f; if (num4 <= 0f) { ManualLogSource log4 = SuppressRework.Log; if (log4 != null) { log4.LogWarning((object)$"CrushHealth: Insufficient health to sacrifice. Current: {healthComponent2.health:F1}, need at least 2 HP"); } ((EntityState)__instance).outer.SetNextStateToMain(); return false; } float val = healthComponent2.fullHealth * (SuppressRework.MaxHealthSacrifice.Value / 100f); float num5 = Math.Min(num4, val); if (num5 <= 0.1f) { ManualLogSource log5 = SuppressRework.Log; if (log5 != null) { log5.LogWarning((object)$"CrushHealth: Health sacrifice too small ({num5:F2} HP), aborting"); } ((EntityState)__instance).outer.SetNextStateToMain(); return false; } float num6 = num5 / healthComponent2.fullHealth; num2 = 0f - num6; num3 = num6 * 100f; ManualLogSource log6 = SuppressRework.Log; if (log6 != null) { log6.LogInfo((object)$"CrushHealth All-or-Nothing: Sacrificing {num5:F1} HP ({num6 * 100f:F1}%) for {num3:F1}% corruption"); } } else if (__instance is CrushCorruption) { VoidSurvivorController component2 = ((Component)characterBody).GetComponent<VoidSurvivorController>(); if ((Object)(object)component2 == (Object)null) { ManualLogSource log7 = SuppressRework.Log; if (log7 != null) { log7.LogWarning((object)"CrushCorruption: No void survivor controller, aborting"); } ((EntityState)__instance).outer.SetNextStateToMain(); return false; } float corruption2 = component2.corruption; if (corruption2 <= 0.1f) { ManualLogSource log8 = SuppressRework.Log; if (log8 != null) { log8.LogWarning((object)$"CrushCorruption: Insufficient corruption to spend ({corruption2:F1}%), aborting"); } ((EntityState)__instance).outer.SetNextStateToMain(); return false; } float num7 = corruption2 / 100f; num2 = num7; num3 = 0f - corruption2; ManualLogSource log9 = SuppressRework.Log; if (log9 != null) { log9.LogInfo((object)$"CrushCorruption All-or-Nothing: Spending {corruption2:F1}% corruption for {num7 * 100f:F1}% heal"); } } } else { float value2 = SuppressRework.FixedTradeValue.Value; if (__instance is CrushHealth) { num2 = 0f - value2 / 100f; num3 = value2; ManualLogSource log10 = SuppressRework.Log; if (log10 != null) { log10.LogInfo((object)$"CrushHealth Fixed: sacrificing {value2}% health for {value2}% corruption"); } } else if (__instance is CrushCorruption) { num2 = value2 / 100f; num3 = 0f - value2; ManualLogSource log11 = SuppressRework.Log; if (log11 != null) { log11.LogInfo((object)$"CrushCorruption Fixed: spending {value2}% corruption for {value2}% heal"); } } } if (SuppressRework.EnableEfficientTrades.Value) { if (__instance is CrushHealth && num3 > 0f) { VoidSurvivorController component3 = ((Component)characterBody).GetComponent<VoidSurvivorController>(); if ((Object)(object)component3 == (Object)null) { return true; } float num8 = 100f - component3.corruption; if (num3 > num8) { float num9 = num8 / num3; num3 *= num9; num2 *= num9; ManualLogSource log12 = SuppressRework.Log; if (log12 != null) { log12.LogInfo((object)$"CrushHealth scaled down due to corruption cap: scale={num9:F2}"); } } } else if (__instance is CrushCorruption && num2 > 0f) { HealthComponent healthComponent3 = characterBody.healthComponent; if ((Object)(object)healthComponent3 == (Object)null) { return true; } float num10 = healthComponent3.fullHealth - healthComponent3.health; float num11 = num10 / healthComponent3.fullHealth; if (num2 > num11) { float num12 = num11 / num2; num2 *= num12; num3 *= num12; ManualLogSource log13 = SuppressRework.Log; if (log13 != null) { log13.LogInfo((object)$"CrushCorruption scaled down due to overheal prevention: scale={num12:F2}"); } } } } __instance.selfHealFraction = num2; __instance.corruptionChange = num3; return true; } catch (Exception arg) { ManualLogSource log14 = SuppressRework.Log; if (log14 != null) { log14.LogError((object)$"Error in CrushBase_OnEnter_Patch: {arg}"); } return true; } } } [HarmonyPatch] public static class VoidSurvivorSkillDef_HasRequiredCorruption_Patch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("RoR2.Skills.VoidSurvivorSkillDef"); return AccessTools.Method(type, "HasRequiredCorruption", (Type[])null, (Type[])null); } private static bool Prefix(object __instance, GenericSkill skillSlot, ref bool __result) { try { if (SuppressRework.EnableAllOrNothingScaling.Value) { return true; } if (__instance == SuppressRework._crushHealthDef) { CharacterBody val = ((skillSlot != null) ? skillSlot.characterBody : null); if ((Object)(object)((val != null) ? val.healthComponent : null) != (Object)null) { float num = val.healthComponent.health / val.healthComponent.fullHealth * 100f; float value = SuppressRework.FixedTradeValue.Value; __result = num >= value; return false; } } else if (__instance == SuppressRework._crushCorruptionDef) { CharacterBody val2 = ((skillSlot != null) ? skillSlot.characterBody : null); VoidSurvivorController val3 = ((val2 != null) ? ((Component)val2).GetComponent<VoidSurvivorController>() : null); if ((Object)(object)val3 != (Object)null) { float corruption = val3.corruption; float value2 = SuppressRework.FixedTradeValue.Value; __result = corruption >= value2; return false; } } } catch (Exception arg) { ManualLogSource log = SuppressRework.Log; if (log != null) { log.LogError((object)$"Error in HasRequiredCorruption patch: {arg}"); } } return true; } } [HarmonyPatch(typeof(Language), "GetString", new Type[] { typeof(string) })] public static class Language_GetString_Patch { private static string? _crushHealthToken = null; private static string? _crushCorruptionToken = null; private static string? _corruptionUpgradeToken = null; private static readonly HashSet<string> _voidSurvivorTokens = new HashSet<string> { "VOIDSURVIVOR_PRIMARY_DESCRIPTION", "VOIDSURVIVOR_SECONDARY_DESCRIPTION", "VOIDSURVIVOR_UTILITY_DESCRIPTION", "VOIDSURVIVOR_SPECIAL_DESCRIPTION" }; private static bool Prefix(string token, ref string __result) { try { if (string.IsNullOrEmpty(token) || token.Length < 15) { return true; } if (_crushHealthToken == null && (Object)(object)SuppressRework._crushHealthDef != (Object)null) { _crushHealthToken = SuppressRework._crushHealthDef.skillDescriptionToken; _crushCorruptionToken = SuppressRework._crushCorruptionDef?.skillDescriptionToken; if (_crushHealthToken != null) { _voidSurvivorTokens.Add(_crushHealthToken); } if (_crushCorruptionToken != null) { _voidSurvivorTokens.Add(_crushCorruptionToken); } } if (_corruptionUpgradeToken == null && token.Length > 25 && token.Contains("Corruption Upgrade") && token.Contains("Transform to crush")) { _corruptionUpgradeToken = token; _voidSurvivorTokens.Add(token); ManualLogSource log = SuppressRework.Log; if (log != null) { log.LogInfo((object)("Safely cached corruption upgrade token: " + token)); } } if (token == _corruptionUpgradeToken) { if (SuppressRework.EnableAllOrNothingScaling.Value) { __result = "<style=cKeywordName>□Corruption Upgrade□</style><style=cSub>Transform to crush a portion of your maximum health to gain an equal percentage of Corruption instead.</style>"; } else { string text = $"{SuppressRework.FixedTradeValue.Value:0}"; __result = "<style=cKeywordName>□Corruption Upgrade□</style><style=cSub>Transform to crush " + text + "% health to gain " + text + "% Corruption instead.</style>"; } return false; } if (!_voidSurvivorTokens.Contains(token)) { return true; } bool flag = IsPlayerInVoidModeState(); if (token == _crushCorruptionToken && (Object)(object)SuppressRework._crushCorruptionDef != (Object)null) { if (flag) { if (SuppressRework.EnableAllOrNothingScaling.Value) { __result = "Crush a portion of your <style=cIsHealth>maximum health</style> to gain an equal percentage of <style=cIsVoid>Corruption</style>."; } else { string text2 = $"{SuppressRework.FixedTradeValue.Value:0}"; __result = "Crush <style=cIsHealth>" + text2 + "% maximum health</style> to gain <style=cIsVoid>" + text2 + "% Corruption</style>."; } } else if (SuppressRework.EnableAllOrNothingScaling.Value) { __result = "Crush your entire <style=cIsVoid>Corruption</style> bar to heal yourself for an equal percentage of <style=cIsHealing>maximum health</style>."; } else { string text3 = $"{SuppressRework.FixedTradeValue.Value:0}"; __result = "Crush <style=cIsVoid>" + text3 + "% Corruption</style> to heal yourself for <style=cIsHealing>" + text3 + "% maximum health</style>."; } return false; } switch (token) { case "VOIDSURVIVOR_PRIMARY_DESCRIPTION": __result = (flag ? "Fire a short-range beam for <style=cIsDamage>300% damage</style>." : "Fire a slowing long-range beam for <style=cIsDamage>300% damage</style>."); return false; case "VOIDSURVIVOR_SECONDARY_DESCRIPTION": __result = (flag ? "Fire an arcing plasma bomb for <style=cIsDamage>1100% damage</style>." : "Fire a plasma missile for <style=cIsDamage>600% damage</style>. Fully charge it for an <style=cIsDamage>explosive plasma ball</style> instead, dealing <style=cIsDamage>1100% damage</style>."); return false; case "VOIDSURVIVOR_UTILITY_DESCRIPTION": __result = (flag ? "Disappear into the Void, <style=cIsUtility>cleansing all debuffs</style> while moving at a fast forward angle." : "Disappear into the Void, <style=cIsUtility>cleansing all debuffs</style> while moving in an upward arc."); return false; default: if (token == _crushHealthToken && (Object)(object)SuppressRework._crushHealthDef != (Object)null) { if (SuppressRework.EnableAllOrNothingScaling.Value) { __result = "Crush a portion of your <style=cIsHealth>maximum health</style> to gain an equal percentage of <style=cIsVoid>Corruption</style>."; } else { string text4 = $"{SuppressRework.FixedTradeValue.Value:0}"; __result = "Crush <style=cIsHealth>" + text4 + "% maximum health</style> to gain <style=cIsVoid>" + text4 + "% Corruption</style>."; } return false; } break; } } catch (Exception arg) { ManualLogSource log2 = SuppressRework.Log; if (log2 != null) { log2.LogError((object)$"Error in Language_GetString_Patch: {arg}"); } } return true; } private static bool IsPlayerInVoidModeState() { try { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); object obj; if (firstLocalUser == null) { obj = null; } else { PlayerCharacterMasterController cachedMasterController = firstLocalUser.cachedMasterController; if (cachedMasterController == null) { obj = null; } else { CharacterMaster master = cachedMasterController.master; obj = ((master != null) ? master.GetBody() : null); } } if ((Object)obj == (Object)null) { return false; } CharacterBody body = firstLocalUser.cachedMasterController.master.GetBody(); if (body.baseNameToken != "VOIDSURVIVOR_BODY_NAME") { return false; } VoidSurvivorController component = ((Component)body).GetComponent<VoidSurvivorController>(); if ((Object)(object)component == (Object)null) { return false; } if ((Object)(object)component.corruptedBuffDef != (Object)null && body.HasBuff(component.corruptedBuffDef)) { return true; } EntityStateMachine corruptionModeStateMachine = component.corruptionModeStateMachine; if (((corruptionModeStateMachine != null) ? corruptionModeStateMachine.state : null) != null) { string name = ((object)component.corruptionModeStateMachine.state).GetType().Name; if (name == "CorruptMode") { return true; } } return component.corruption >= 100f; } catch (Exception arg) { ManualLogSource log = SuppressRework.Log; if (log != null) { log.LogError((object)$"Error in IsPlayerInVoidModeState: {arg}"); } return false; } } } public static class TooltipRefresher { public static void RefreshTooltipsAfterSettingsChange() { //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) try { FieldInfo field = typeof(Language).GetField("currentLanguage", BindingFlags.Static | BindingFlags.NonPublic); if (field != null) { object? value = field.GetValue(null); Language val = (Language)((value is Language) ? value : null); if (val != null) { FieldInfo field2 = typeof(Language).GetField("stringsByToken", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null) { object value2 = field2.GetValue(val); if (value2 != null) { MethodInfo method = value2.GetType().GetMethod("Remove"); if (method != null && (Object)(object)SuppressRework._crushCorruptionDef != (Object)null) { method.Invoke(value2, new object[1] { SuppressRework._crushCorruptionDef.skillDescriptionToken }); if ((Object)(object)SuppressRework._crushHealthDef != (Object)null) { method.Invoke(value2, new object[1] { SuppressRework._crushHealthDef.skillDescriptionToken }); } } } } } } TooltipProvider[] array = Object.FindObjectsOfType<TooltipProvider>(); TooltipProvider[] array2 = array; foreach (TooltipProvider val2 in array2) { if (val2.bodyToken == null || (!val2.bodyToken.Contains("CRUSH") && !val2.bodyToken.Contains("SPECIAL"))) { continue; } MethodInfo method2 = typeof(TooltipProvider).GetMethod("SetContent", BindingFlags.Instance | BindingFlags.Public); if (method2 != null) { TooltipProvider component = ((Component)val2).GetComponent<TooltipProvider>(); if ((Object)(object)component != (Object)null) { method2.Invoke(val2, new object[1] { (object)default(TooltipContent) }); } } } ManualLogSource log = SuppressRework.Log; if (log != null) { log.LogInfo((object)"Cleared tooltip cache to force refresh"); } } catch (Exception arg) { ManualLogSource log2 = SuppressRework.Log; if (log2 != null) { log2.LogError((object)$"Error refreshing tooltips: {arg}"); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }