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 RavagerNoSacrifice v1.3.1
plugins/RavagerNoSacrifice/RavagerNoSacrifice.dll
Decompiled 7 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using HarmonyLib; using LocalTweaks; using Microsoft.CodeAnalysis; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.HudOverlay; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RavagerNoSacrifice")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.1.0")] [assembly: AssemblyInformationalVersion("1.3.1+f04e2f06ceca206eeac461b3cccb063d18037226")] [assembly: AssemblyProduct("RavagerNoSacrifice")] [assembly: AssemblyTitle("RavagerNoSacrifice")] [assembly: AssemblyVersion("1.3.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LocalTweaks { internal static class PatchTools { internal static MethodInfo Method(string type, string name) { Type type2 = AccessTools.TypeByName(type); if (!(type2 == null)) { return AccessTools.DeclaredMethod(type2, name, (Type[])null, (Type[])null) ?? throw new MissingMethodException(type, name); } throw new TypeLoadException(type); } internal static IEnumerable<CodeInstruction> ReplaceFloat(IEnumerable<CodeInstruction> source, float value, MethodInfo replacement) { List<CodeInstruction> list = source.ToList(); List<CodeInstruction> list2 = list.Where((CodeInstruction x) => x.opcode == OpCodes.Ldc_R4 && x.operand is float num && Math.Abs(num - value) < 1E-06f).ToList(); if (list2.Count != 1) { throw new InvalidOperationException($"Expected one {value} constant, found {list2.Count}."); } list2[0].opcode = OpCodes.Call; list2[0].operand = replacement; return list; } } internal static class TweakSettings { internal static ConfigEntry<int> Slider(ConfigFile file, string section, string name, int value, int min, int max, string description, string guid, string modName) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown ConfigEntry<int> obj = file.Bind<int>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>())); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(obj, new IntSliderConfig { min = min, max = max }), guid, modName); return obj; } internal static ConfigEntry<bool> Checkbox(ConfigFile file, string section, string name, bool value, string description, string guid, string modName) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown ConfigEntry<bool> obj = file.Bind<bool>(section, name, value, description); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(obj), guid, modName); return obj; } } } namespace RavagerNoSacrifice { internal static class LookingGlassSupport { internal static void Install(ManualLogSource logger) { Type type = AccessTools.TypeByName("LookingGlass.ItemStatsNameSpace.ProcCoefficientData"); if (type == null) { return; } try { IDictionary dictionary = AccessTools.Field(type, "skills")?.GetValue(null) as IDictionary; IDictionary dictionary2 = AccessTools.Field(type, "skillsAdditional")?.GetValue(null) as IDictionary; if (dictionary == null || dictionary2 == null) { throw new MissingFieldException(type.FullName, "skills"); } Add(dictionary, "ROB_RAVAGER_BODY_PRIMARY_SLASH_NAME", 1f); Add(dictionary, "ROB_RAVAGER_BODY_PRIMARY_SLASHCOMBO_NAME", 1f); Add(dictionary, "ROB_RAVAGER_BODY_SECONDARY_SPINSLASH_NAME", 1f); Add(dictionary, "ROB_RAVAGER_BODY_UTILITY_HEAL_NAME", -1f); Add(dictionary, "ROB_RAVAGER_BODY_UTILITY_BEAM_NAME", 1f); Add(dictionary, "ROB_RAVAGER_BODY_SPECIAL_GRAB_NAME", 1f); Add(dictionary, "ROB_RAVAGER_BODY_SPECIAL_PUNCH_NAME", 1f); Add(dictionary, "ROB_RAVAGER_BODY_SPECIAL_THROW_NAME", 1f); Add(dictionary, "ROB_RAVAGER_BODY_SPECIAL_GRAB_SCEPTER_NAME", 1f); Add(dictionary2, "ROB_RAVAGER_BODY_UTILITY_BEAM_NAME", "\nTicks: <style=cIsDamage>30 * Attack Speed</style> per second"); logger.LogInfo((object)"Added Ravager's skill proc coefficients to LookingGlass."); } catch (Exception arg) { logger.LogWarning((object)$"LookingGlass skill details were not added.\n{arg}"); } } private static void Add(IDictionary dictionary, string key, object value) { dictionary[key] = value; } } [BepInPlugin("com.youssef.RavagerNoSacrifice", "Ravager No Sacrifice", "1.3.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.youssef.RavagerNoSacrifice"; public const string Name = "Ravager No Sacrifice"; private static ConfigEntry<int> healthCost; private static ConfigEntry<bool> quickNullifyCooldown; private static PropertyInfo fixedAge; private static PropertyInfo cooldownOverride; private readonly Harmony harmony = new Harmony("com.youssef.RavagerNoSacrifice"); private void Awake() { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown healthCost = TweakSettings.Slider(((BaseUnityPlugin)this).Config, "Twisted Mutation", "Health cost percent", 0, 0, 10, "Maximum percent of full combined health spent on the charged aerial blink. Partial charge still costs proportionally less. Applies on the next blink.", "com.youssef.RavagerNoSacrifice", "Ravager No Sacrifice"); quickNullifyCooldown = TweakSettings.Checkbox(((BaseUnityPlugin)this).Config, "Nullify", "Short-release cooldown", value: true, "Releasing Nullify in under two seconds gives it a four-second base cooldown. Longer charges keep the original cooldown.", "com.youssef.RavagerNoSacrifice", "Ravager No Sacrifice"); ModSettingsManager.SetModDescription("Configure Twisted Mutation and Nullify, rebuild the Blood Well display, and add Ravager skill details to LookingGlass.", "com.youssef.RavagerNoSacrifice", "Ravager No Sacrifice"); Sprite val = SettingsIcon.Load("RavagerNoSacrifice.SettingsIcon.png"); if (Object.op_Implicit((Object)(object)val)) { ModSettingsManager.SetModIcon(val, "com.youssef.RavagerNoSacrifice", "Ravager No Sacrifice"); } try { fixedAge = AccessTools.Property(typeof(EntityState), "fixedAge"); cooldownOverride = AccessTools.Property(typeof(GenericSkill), "cooldownOverride"); if (fixedAge == null) { throw new MissingMemberException("EntityState.fixedAge was not found."); } harmony.Patch((MethodBase)PatchTools.Method("RedGuyMod.SkillStates.Ravager.BlinkBig", "OnEnter"), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ChangeHealthCost", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)PatchTools.Method("RedGuyMod.SkillStates.Ravager.ChargeBeam", "OnExit"), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ApplyQuickNullifyCooldown", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Ravager skill tweaks loaded."); } catch (Exception arg) { harmony.UnpatchSelf(); ((BaseUnityPlugin)this).Logger.LogError((object)$"The Ravager tweak was not applied. The installed Ravager version may have changed.\n{arg}"); } RavagerHud.Install(((BaseUnityPlugin)this).Logger); LookingGlassSupport.Install(((BaseUnityPlugin)this).Logger); } private void OnDestroy() { RavagerHud.Uninstall(); harmony.UnpatchSelf(); } private static float CostFraction() { return (float)healthCost.Value / 100f; } private static IEnumerable<CodeInstruction> ChangeHealthCost(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = PatchTools.ReplaceFloat(instructions, 0.1f, AccessTools.Method(typeof(Plugin), "CostFraction", (Type[])null, (Type[])null)).ToList(); MethodInfo takeDamage = AccessTools.Method(typeof(HealthComponent), "TakeDamage", new Type[1] { typeof(DamageInfo) }, (Type[])null); List<CodeInstruction> list2 = list.Where((CodeInstruction x) => CodeInstructionExtensions.Calls(x, takeDamage)).ToList(); if (list2.Count != 1) { throw new InvalidOperationException("Twisted Mutation's health-cost call no longer matches."); } list2[0].opcode = OpCodes.Call; list2[0].operand = AccessTools.Method(typeof(Plugin), "ApplyHealthCost", (Type[])null, (Type[])null); return list; } private static void ApplyHealthCost(HealthComponent healthComponent, DamageInfo damageInfo) { if (healthCost.Value > 0 && damageInfo.damage > 0f) { healthComponent.TakeDamage(damageInfo); } } private static void ApplyQuickNullifyCooldown(EntityState __instance) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!quickNullifyCooldown.Value || (float)fixedAge.GetValue(__instance) >= 2f || !Object.op_Implicit((Object)(object)__instance.outer)) { return; } SkillLocator component = ((Component)__instance.outer).GetComponent<SkillLocator>(); GenericSkill val = (Object.op_Implicit((Object)(object)component) ? component.utility : null); if (!Object.op_Implicit((Object)(object)val)) { return; } SerializableEntityStateType activationState = val.activationState; if (!(((SerializableEntityStateType)(ref activationState)).stateType != ((object)__instance).GetType())) { float num = val.CalculateFinalRechargeInterval(); float num2 = num * 4f / val.baseRechargeInterval; if (cooldownOverride != null) { float num3 = (float)cooldownOverride.GetValue(val); cooldownOverride.SetValue(val, 4f); num2 = val.CalculateFinalRechargeInterval(); cooldownOverride.SetValue(val, num3); } val.rechargeStopwatch = Mathf.Max(val.rechargeStopwatch, num - num2); } } } internal static class RavagerHud { private static readonly Harmony harmony = new Harmony("com.youssef.RavagerNoSacrifice.hud"); private static Type controllerType; private static FieldInfo meterField; private static FieldInfo drainingField; private static ManualLogSource logger; internal static void Install(ManualLogSource log) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown logger = log; try { controllerType = AccessTools.TypeByName("RedGuyMod.Content.Components.RedGuyController"); meterField = AccessTools.Field(controllerType, "meter"); drainingField = AccessTools.Field(controllerType, "draining"); MethodInfo methodInfo = AccessTools.Method(AccessTools.TypeByName("RedGuyMod.Content.Survivors.RedGuy"), "HUDSetup", (Type[])null, (Type[])null); if (controllerType == null || meterField == null || drainingField == null || methodInfo == null) { throw new MissingMemberException("Ravager's Blood Well members were not found."); } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(RavagerHud), "SkipOriginalGauge", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); CharacterBody.onBodyStartGlobal += AddGauge; logger.LogInfo((object)"Centered Blood Well overlay loaded."); } catch (Exception arg) { harmony.UnpatchSelf(); logger.LogError((object)$"The Blood Well overlay was not installed.\n{arg}"); } } internal static void Uninstall() { CharacterBody.onBodyStartGlobal -= AddGauge; harmony.UnpatchSelf(); logger = null; } private static bool SkipOriginalGauge() { return false; } private static void AddGauge(CharacterBody body) { Component val = (Object.op_Implicit((Object)(object)body) ? ((Component)body).GetComponent(controllerType) : null); if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)((Component)body).GetComponent<RavagerMeterController>())) { ((Component)body).gameObject.AddComponent<RavagerMeterController>().Initialize(val, meterField, drainingField, logger); } } } internal sealed class RavagerMeterController : MonoBehaviour { private static GameObject overlayPrefab; private static string overlayChild; private static readonly Color bloodColor = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)0, (byte)46, byte.MaxValue)); private static readonly int meterParameter = Animator.StringToHash("corruption"); private static readonly int drainParameter = Animator.StringToHash("isCorrupted"); private readonly List<ImageFillController> fills = new List<ImageFillController>(); private readonly List<TextMeshProUGUI> texts = new List<TextMeshProUGUI>(); private readonly List<Image> images = new List<Image>(); private readonly List<Animator> animators = new List<Animator>(); private Component target; private FieldInfo meterField; private FieldInfo drainingField; private OverlayController overlay; private ManualLogSource logger; internal void Initialize(Component target, FieldInfo meter, FieldInfo draining, ManualLogSource log) { this.target = target; meterField = meter; drainingField = draining; logger = log; } private void Start() { //IL_0025: 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) try { LoadOverlay(); if (!Object.op_Implicit((Object)(object)overlayPrefab)) { throw new MissingMemberException("Void Fiend's meter overlay was not found."); } overlay = HudOverlayManager.AddOverlay(((Component)this).gameObject, new OverlayCreationParams { prefab = overlayPrefab, childLocatorEntry = overlayChild }); overlay.onInstanceAdded += InstanceAdded; overlay.onInstanceRemove += InstanceRemoved; foreach (GameObject instances in overlay.instancesList) { InstanceAdded(overlay, instances); } } catch (Exception arg) { ManualLogSource obj = logger; if (obj != null) { obj.LogError((object)$"The Blood Well meter could not be created.\n{arg}"); } Object.Destroy((Object)(object)this); } } private static void LoadOverlay() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)overlayPrefab)) { GameObject val = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/DLC1/VoidSurvivor/VoidSurvivorBody.prefab").WaitForCompletion(); VoidSurvivorController val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<VoidSurvivorController>() : null); if (Object.op_Implicit((Object)(object)val2)) { overlayPrefab = Object.Instantiate<GameObject>(val2.overlayPrefab); ((Object)overlayPrefab).name = "RavagerBloodWellOverlayPrefab"; overlayPrefab.SetActive(false); Object.DontDestroyOnLoad((Object)(object)overlayPrefab); ApplyRedTheme(overlayPrefab); overlayChild = val2.overlayChildLocatorEntry; } } } private void Update() { if (!Object.op_Implicit((Object)(object)target)) { return; } float num = Mathf.Clamp((float)meterField.GetValue(target), 0f, 100f); float tValue = num / 100f; foreach (ImageFillController fill in fills) { if (Object.op_Implicit((Object)(object)fill)) { fill.SetTValue(tValue); } } foreach (TextMeshProUGUI text in texts) { if (Object.op_Implicit((Object)(object)text)) { ((TMP_Text)text).SetText(Mathf.FloorToInt(num).ToString(), true); } } bool flag = (bool)drainingField.GetValue(target); foreach (Animator animator in animators) { if (Object.op_Implicit((Object)(object)animator)) { animator.SetFloat(meterParameter, num); animator.SetBool(drainParameter, flag); } } } private void LateUpdate() { foreach (Image image in images) { ApplyRed(image); } foreach (TextMeshProUGUI text in texts) { ApplyRed(text); } } private void InstanceAdded(OverlayController _, GameObject instance) { ImageFillController[] componentsInChildren = instance.GetComponentsInChildren<ImageFillController>(true); foreach (ImageFillController item in componentsInChildren) { if (!fills.Contains(item)) { fills.Add(item); } } TextMeshProUGUI[] componentsInChildren2 = instance.GetComponentsInChildren<TextMeshProUGUI>(true); foreach (TextMeshProUGUI item2 in componentsInChildren2) { if (!texts.Contains(item2)) { texts.Add(item2); } } Image[] componentsInChildren3 = instance.GetComponentsInChildren<Image>(true); foreach (Image item3 in componentsInChildren3) { if (!images.Contains(item3)) { images.Add(item3); } } Animator[] componentsInChildren4 = instance.GetComponentsInChildren<Animator>(true); foreach (Animator item4 in componentsInChildren4) { if (!animators.Contains(item4)) { animators.Add(item4); } } } private void InstanceRemoved(OverlayController _, GameObject instance) { fills.RemoveAll((ImageFillController fill) => !Object.op_Implicit((Object)(object)fill) || ((Component)fill).transform.IsChildOf(instance.transform)); texts.RemoveAll((TextMeshProUGUI text) => !Object.op_Implicit((Object)(object)text) || ((TMP_Text)text).transform.IsChildOf(instance.transform)); images.RemoveAll((Image image) => !Object.op_Implicit((Object)(object)image) || ((Component)image).transform.IsChildOf(instance.transform)); animators.RemoveAll((Animator animator) => !Object.op_Implicit((Object)(object)animator) || ((Component)animator).transform.IsChildOf(instance.transform)); } private void OnDestroy() { if (overlay != null) { overlay.onInstanceAdded -= InstanceAdded; overlay.onInstanceRemove -= InstanceRemoved; HudOverlayManager.RemoveOverlay(overlay); overlay = null; } } private static void ApplyRedTheme(GameObject root) { Image[] componentsInChildren = root.GetComponentsInChildren<Image>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ApplyRed(componentsInChildren[i]); } TextMeshProUGUI[] componentsInChildren2 = root.GetComponentsInChildren<TextMeshProUGUI>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { ApplyRed(componentsInChildren2[i]); } } private static void ApplyRed(Image image) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)image) && (int)image.type == 3) { Color color = ((Graphic)image).color; Color color2 = default(Color); ((Color)(ref color2))..ctor(bloodColor.r, bloodColor.g, bloodColor.b, color.a); ((Graphic)image).color = color2; ((Graphic)image).canvasRenderer.SetColor(color2); } } private static void ApplyRed(TextMeshProUGUI text) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)text)) { Color color = ((Graphic)text).color; Color color2 = default(Color); ((Color)(ref color2))..ctor(bloodColor.r, bloodColor.g, bloodColor.b, color.a); ((Graphic)text).color = color2; Color32 faceColor = ((TMP_Text)text).faceColor; ((TMP_Text)text).faceColor = new Color32(byte.MaxValue, (byte)0, (byte)46, faceColor.a); text.canvasRenderer.SetColor(color2); } } } internal static class SettingsIcon { internal static Sprite Load(string resourceName) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num == 0) { throw new EndOfStreamException(resourceName); } } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { return null; } ((Object)val).name = "RavagerNoSacrifice settings icon"; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } } }