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 StackFix v1.0.1
plugins/StackFix/ConfigEntryExt.dll
Decompiled 13 hours agousing System; 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 ConfigEntryExt.Patches; using Microsoft.CodeAnalysis; [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("PapitaConPuré")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+116e86dd03a7f474064a534020c9325dcec3838f")] [assembly: AssemblyProduct("BepInEx Typed Config")] [assembly: AssemblyTitle("ConfigEntryExt")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } [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; } } internal static class IsExternalInit { } } namespace ConfigEntryExt { public class ConfigEntryExt<TValue>(string section, string name, string description, TValue defaultValue) where TValue : IComparable { public string Section { get; } = section; public string Name { get; } = name; public string Description { get; } = description; public TValue Default { get; } = defaultValue; public virtual ConfigEntry<TValue> RegisterFor(BaseUnityPlugin plugin) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown return plugin.Config.Bind<TValue>(Section, Name, Default, new ConfigDescription(Description, (AcceptableValueBase)null, Array.Empty<object>())); } } public sealed class ConstrainedConfigEntry<TValue, TConstraint> : ConfigEntryExt<TValue> where TValue : IComparable where TConstraint : IEntryConstraint<TValue> { public TConstraint Constraint { get; } public ConstrainedConfigEntry(string section, string name, string description, TValue defaultValue, TConstraint constraint) { Constraint = constraint; base..ctor(section, name, description, defaultValue); } public override ConfigEntry<TValue> RegisterFor(BaseUnityPlugin plugin) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown return plugin.Config.Bind<TValue>(base.Section, base.Name, base.Default, new ConfigDescription(base.Description, Constraint.AcceptableValue, Array.Empty<object>())); } } public interface IEntryConstraint<TValue> where TValue : IComparable { AcceptableValueBase AcceptableValue { get; } TValue Clamp(TValue value); bool IsValid(object value); } } namespace ConfigEntryExt.Patches { internal sealed class AcceptableValueEnum<TValue> : AcceptableValueBase where TValue : IComparable { public IReadOnlyList<TValue> AcceptableValues { get; } public AcceptableValueEnum(params TValue[] acceptableValues) : base(typeof(TValue)) { if (acceptableValues == null) { throw new ArgumentNullException("acceptableValues"); } if (acceptableValues.Length == 0) { throw new ArgumentException("At least one acceptable value is needed.", "acceptableValues"); } AcceptableValues = acceptableValues; } public override object Clamp(object value) { if (!((AcceptableValueBase)this).IsValid(value)) { return AcceptableValues[0]; } return value; } public override bool IsValid(object value) { if (value is TValue value2) { return AcceptableValues.Contains(value2); } return false; } public override string ToDescriptionString() { return "# Acceptable values: " + string.Join(", ", AcceptableValues.Select((TValue x) => x.ToString()).ToArray()); } } } namespace ConfigEntryExt.Constraints { public sealed record ListEntryConstraint<TValue>(Type ValuesEnum) : IEntryConstraint<TValue> where TValue : struct, Enum { public AcceptableValueBase AcceptableValue { get; } public ListEntryConstraint(Type ValuesEnum) { AcceptableValue = (AcceptableValueBase)(object)new AcceptableValueEnum<TValue>(Enum.GetValues(ValuesEnum) as TValue[]); base..ctor(); } public TValue Clamp(TValue value) { return (TValue)AcceptableValue.Clamp((object)value); } public bool IsValid(object value) { return AcceptableValue.IsValid(value); } } public sealed record RangeEntryConstraint<TValue>(TValue Min, TValue Max) : IEntryConstraint<TValue> where TValue : IComparable { public AcceptableValueBase AcceptableValue { get; } public RangeEntryConstraint(TValue Min, TValue Max) { AcceptableValue = (AcceptableValueBase)(object)new AcceptableValueRange<TValue>(Min, Max); base..ctor(); } public TValue Clamp(TValue value) { return (TValue)AcceptableValue.Clamp((object)value); } public bool IsValid(object value) { return AcceptableValue.IsValid(value); } } }
plugins/StackFix/StackFix.dll
Decompiled 13 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; 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.Bootstrap; using BepInEx.Configuration; using ConfigEntryExt; using ConfigEntryExt.Constraints; using IL.RoR2; using IL.RoR2.Items; using Microsoft.CodeAnalysis; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using R2API; using R2API.Utils; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Items; using StackFix.Exceptions; using StackFix.Items; using StackFix.Settings; using StackFix.Utils; using UnityEngine; [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("PapitaConPuré")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+116e86dd03a7f474064a534020c9325dcec3838f")] [assembly: AssemblyProduct("Stack Fix")] [assembly: AssemblyTitle("StackFix")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/PapitaConPure/StackFix")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } [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; } } internal static class IsExternalInit { } } namespace StackFix { internal interface IItemFix { bool Enabled { get; } void ApplyFix(); } [BepInPlugin("com.papitaconpure.stackfix", "Stack Fix", "1.0.1")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> FaradaySpurFixEnabled; internal static ConfigEntry<bool> NetworkedSufferingFixEnabled; internal static ConfigEntry<float> FaradaySpurMoveSpeedBase; internal static ConfigEntry<float> FaradaySpurMoveSpeedStack; internal static ConfigEntry<float> FaradaySpurJumpHeightBase; internal static ConfigEntry<float> FaradaySpurJumpHeightStack; internal static ConfigEntry<float> FaradaySpurDamageBase; internal static ConfigEntry<float> FaradaySpurDamageStack; internal static ConfigEntry<int> NetworkedSufferingSpreadBase; internal static ConfigEntry<int> NetworkedSufferingSpreadStack; internal static ConfigEntry<float> NetworkedSufferingDamageBase; internal static ConfigEntry<float> NetworkedSufferingDamageStack; internal static ConfigEntry<bool> Megumin; private readonly IItemFix[] ItemFixes = new IItemFix[2] { new FaradaySpur(), new NetworkedSuffering() }; public void Awake() { RegisterSettings(); TryRegisterRiskOfOptions(); ApplyItemFixes(); } private void RegisterSettings() { Enabled = ModSettings.Enabled.RegisterFor((BaseUnityPlugin)(object)this); FaradaySpurFixEnabled = ModSettings.FaradaySpurFixEnabled.RegisterFor((BaseUnityPlugin)(object)this); NetworkedSufferingFixEnabled = ModSettings.NetworkedSufferingFixEnabled.RegisterFor((BaseUnityPlugin)(object)this); FaradaySpurMoveSpeedBase = ((ConfigEntryExt<float>)(object)ModSettings.FaradaySpurMoveSpeedBase).RegisterFor((BaseUnityPlugin)(object)this); FaradaySpurMoveSpeedStack = ((ConfigEntryExt<float>)(object)ModSettings.FaradaySpurMoveSpeedStack).RegisterFor((BaseUnityPlugin)(object)this); FaradaySpurJumpHeightBase = ((ConfigEntryExt<float>)(object)ModSettings.FaradaySpurJumpHeightBase).RegisterFor((BaseUnityPlugin)(object)this); FaradaySpurJumpHeightStack = ((ConfigEntryExt<float>)(object)ModSettings.FaradaySpurJumpHeightStack).RegisterFor((BaseUnityPlugin)(object)this); FaradaySpurDamageBase = ((ConfigEntryExt<float>)(object)ModSettings.FaradaySpurDamageBase).RegisterFor((BaseUnityPlugin)(object)this); FaradaySpurDamageStack = ((ConfigEntryExt<float>)(object)ModSettings.FaradaySpurDamageStack).RegisterFor((BaseUnityPlugin)(object)this); NetworkedSufferingSpreadBase = ((ConfigEntryExt<int>)(object)ModSettings.NetworkedSufferingSpreadBase).RegisterFor((BaseUnityPlugin)(object)this); NetworkedSufferingSpreadStack = ((ConfigEntryExt<int>)(object)ModSettings.NetworkedSufferingSpreadStack).RegisterFor((BaseUnityPlugin)(object)this); NetworkedSufferingDamageBase = ((ConfigEntryExt<float>)(object)ModSettings.NetworkedSufferingDamageBase).RegisterFor((BaseUnityPlugin)(object)this); NetworkedSufferingDamageStack = ((ConfigEntryExt<float>)(object)ModSettings.NetworkedSufferingDamageStack).RegisterFor((BaseUnityPlugin)(object)this); Megumin = ModSettings.Megumin.RegisterFor((BaseUnityPlugin)(object)this); } private void TryRegisterRiskOfOptions() { if (!RiskOfOptionsCompatManager.Enabled) { return; } try { RiskOfOptionsCompatManager.SetModDescription("Balances the initial/additional stack behavior of a few items. Configurable."); RiskOfOptionsCompatManager.SetModIcon(ModIcon.Load()); RiskOfOptionsCompatManager.AddCheckboxOption(Enabled); RiskOfOptionsCompatManager.AddCheckboxOption(FaradaySpurFixEnabled); RiskOfOptionsCompatManager.AddCheckboxOption(NetworkedSufferingFixEnabled); RiskOfOptionsCompatManager.AddSliderOption(FaradaySpurMoveSpeedBase, new RiskOfOptionsCompatManager.AddFloatSliderOptionConfig(RestartRequired: false, "{0:0.##}%", 0.5f)); RiskOfOptionsCompatManager.AddSliderOption(FaradaySpurMoveSpeedStack, new RiskOfOptionsCompatManager.AddFloatSliderOptionConfig(RestartRequired: false, "{0:0.##}%", 0.5f)); RiskOfOptionsCompatManager.AddSliderOption(FaradaySpurJumpHeightBase, new RiskOfOptionsCompatManager.AddFloatSliderOptionConfig(RestartRequired: false, "{0:0.##}%", 0.5f)); RiskOfOptionsCompatManager.AddSliderOption(FaradaySpurJumpHeightStack, new RiskOfOptionsCompatManager.AddFloatSliderOptionConfig(RestartRequired: false, "{0:0.##}%", 0.5f)); RiskOfOptionsCompatManager.AddSliderOption(FaradaySpurDamageBase, new RiskOfOptionsCompatManager.AddFloatSliderOptionConfig(RestartRequired: false, "{0:0.##}%", 0.5f)); RiskOfOptionsCompatManager.AddSliderOption(FaradaySpurDamageStack, new RiskOfOptionsCompatManager.AddFloatSliderOptionConfig(RestartRequired: false, "{0:0.##}%", 0.5f)); RiskOfOptionsCompatManager.AddSliderOption(NetworkedSufferingSpreadBase); RiskOfOptionsCompatManager.AddSliderOption(NetworkedSufferingSpreadStack); RiskOfOptionsCompatManager.AddSliderOption(NetworkedSufferingDamageBase, new RiskOfOptionsCompatManager.AddFloatSliderOptionConfig(RestartRequired: false, "{0:0.##}%", 0.5f)); RiskOfOptionsCompatManager.AddSliderOption(NetworkedSufferingDamageStack, new RiskOfOptionsCompatManager.AddFloatSliderOptionConfig(RestartRequired: false, "{0:0.##}%")); RiskOfOptionsCompatManager.AddCheckboxOption(Megumin); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Could not register Risk of Options settings: {arg}"); } } private void ApplyItemFixes() { IItemFix[] itemFixes = ItemFixes; for (int i = 0; i < itemFixes.Length; i++) { itemFixes[i].ApplyFix(); } } } public static class PluginInfo { public const string PLUGIN_GUID = "com.papitaconpure.stackfix"; public const string PLUGIN_NAME = "Stack Fix"; public const string PLUGIN_VERSION = "1.0.1"; } } namespace StackFix.Utils { internal static class FloatExt { public static bool AboutEquals(this float self, float other, float tolerance = 1E-06f) { if (self != other) { return Math.Abs(self - other) <= tolerance; } return true; } } internal static class ItD { public static string Damage(string desc) { return "<style=cIsDamage>" + desc + "</style>"; } public static string Healing(string desc) { return "<style=cIsHealing>" + desc + "</style>"; } public static string ItemGreen(string desc) { return "<style=cIsHealing>" + desc + "</style>"; } public static string Utility(string desc) { return "<style=cIsUtility>" + desc + "</style>"; } public static string Health(string desc) { return "<style=cIsHealth>" + desc + "</style>"; } public static string Stack(float value, string format = "{0:+0;-0}", float hideThreshold = 0.1f) { if (!value.AboutEquals(0f, hideThreshold)) { return " <style=cStack>(" + string.Format(CultureInfo.InvariantCulture, format, value) + " per stack)</style>"; } return ""; } public static string Mono(string desc) { return "<style=cMono>" + desc + "</style>"; } public static string Death(string desc) { return "<style=cDeath>" + desc + "</style>"; } public static string Danger(string desc) { return "<style=cDeath>" + desc + "</style>"; } public static string ItemRed(string desc) { return "<style=cDeath>" + desc + "</style>"; } public static string UserSetting(string desc) { return "<style=cUserSetting>" + desc + "</style>"; } public static string Artifact(string desc) { return "<style=cArtifact>" + desc + "</style>"; } public static string Sub(string desc) { return "<style=cSub>" + desc + "</style>"; } public static string Event(string desc) { return "<style=cEvent>" + desc + "</style>"; } public static string WorldEvent(string desc) { return "<style=cWorldEvent>" + desc + "</style>"; } public static string KeywordName(string desc) { return "<style=cKeywordName>" + desc + "</style>"; } public static string Shrine(string desc) { return "<style=cShrine>" + desc + "</style>"; } public static string ItemYellow(string desc) { return "<style=cShrine>" + desc + "</style>"; } public static string ItemsWGRY(float white, float green, float red, float yellow, string format = "{0:+0;-0}", float hideThreshold = 0.1f) { return string.Join("/", FilterAndFormatValues(new float[4] { white, green, red, yellow }, format, hideThreshold)); } public static string ItemsWGR(float white, float green, float red, string format = "{0:+0;-0}", float hideThreshold = 0.1f) { return string.Join("/", FilterAndFormatValues(new float[3] { white, green, red }, format, hideThreshold)); } public static string ItemsGRY(float green, float red, float yellow, string format = "{0:+0;-0}", float hideThreshold = 0.1f) { return string.Join("/", FilterAndFormatValues(new float[3] { green, red, yellow }, format, hideThreshold)); } public static string ItemsGR(float green, float red, string format = "{0:+0;-0}", float hideThreshold = 0.1f) { return string.Join("/", FilterAndFormatValues(new float[2] { green, red }, format, hideThreshold)); } private static IEnumerable<string> FilterAndFormatValues(float[] values, string format, float hideThreshold) { return from value in values where !value.AboutEquals(0f, hideThreshold) select string.Format(format, value); } } internal static class ItemStacking { public enum Type { Linear, Hyperbolic, Reciprocal, Exponential } public static int Linear(int initial, int perStack, int stacks) { return initial + perStack * (stacks - 1); } public static float Linear(float initial, float perStack, int stacks) { return initial + perStack * ((float)stacks - 1f); } public static float Hyperbolic(float normal, int stacks) { return normal * (float)stacks / (1f + normal * (float)stacks); } public static float Reciprocal(float initial, float perStack, int stacks) { return initial / (1f + perStack * (float)stacks); } public static float Exponential(float multiplier, int stacks) { return MathF.Pow(multiplier, stacks); } } internal static class ModIcon { public static Sprite Load() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("StackFix.icon.png") ?? throw new InvalidOperationException("Embedded mod icon resource was not found."); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), true)) { Object.Destroy((Object)(object)val); throw new InvalidOperationException("Failed to load mod icon."); } ((Object)val).name = "PapitaPure_StackFixIcon"; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } } } namespace StackFix.Settings { internal static class ModSettings { public static readonly ConfigEntryExt<bool> Enabled = new ConfigEntryExt<bool>("General", "Enable Mod", Paragraph("Enables the mod.", "Vanilla value: Off"), true); public static readonly ConfigEntryExt<bool> FaradaySpurFixEnabled = new ConfigEntryExt<bool>("General", "Fix Faraday Spur", Paragraph("Enables Faraday Spur tweaks.", "Vanilla value: Off"), true); public static readonly ConstrainedConfigEntry<float, RangeEntryConstraint<float>> FaradaySpurMoveSpeedBase = new ConstrainedConfigEntry<float, RangeEntryConstraint<float>>("Item: Faraday Spur", "Base Movement Speed", Paragraph("Bonus movement speed percentage at maximum charge for the first stack.", "Vanilla value: 160"), 70f, new RangeEntryConstraint<float>(0f, 160f)); public static readonly ConstrainedConfigEntry<float, RangeEntryConstraint<float>> FaradaySpurMoveSpeedStack = new ConstrainedConfigEntry<float, RangeEntryConstraint<float>>("Item: Faraday Spur", "Movement Speed per Stack", Paragraph("Increased bonus movement speed percentage at maximum charge for every subsequent stack.", "Vanilla value: 0"), 30f, new RangeEntryConstraint<float>(0f, 160f)); public static readonly ConstrainedConfigEntry<float, RangeEntryConstraint<float>> FaradaySpurJumpHeightBase = new ConstrainedConfigEntry<float, RangeEntryConstraint<float>>("Item: Faraday Spur", "Base Jump Height", Paragraph("Bonus jump height percentage at maximum charge for the first stack.", "Vanilla value: 200"), 80f, new RangeEntryConstraint<float>(0f, 200f)); public static readonly ConstrainedConfigEntry<float, RangeEntryConstraint<float>> FaradaySpurJumpHeightStack = new ConstrainedConfigEntry<float, RangeEntryConstraint<float>>("Item: Faraday Spur", "Jump Height per Stack", Paragraph("Increased bonus jump height percentage at maximum charge for every subsequent stack.", "Vanilla value: 0"), 40f, new RangeEntryConstraint<float>(0f, 200f)); public static readonly ConstrainedConfigEntry<float, RangeEntryConstraint<float>> FaradaySpurDamageBase = new ConstrainedConfigEntry<float, RangeEntryConstraint<float>>("Item: Faraday Spur", "Base Damage", Paragraph("Explosion damage percentage for the first stack.", "Vanilla value: 400"), 300f, new RangeEntryConstraint<float>(0f, 400f)); public static readonly ConstrainedConfigEntry<float, RangeEntryConstraint<float>> FaradaySpurDamageStack = new ConstrainedConfigEntry<float, RangeEntryConstraint<float>>("Item: Faraday Spur", "Damage per Stack", Paragraph("Increased explosion damage percentage for every subsequent stack.", "Vanilla value: 280"), 200f, new RangeEntryConstraint<float>(0f, 400f)); public static readonly ConfigEntryExt<bool> NetworkedSufferingFixEnabled = new ConfigEntryExt<bool>("General", "Fix Networked Suffering", Paragraph("Enables Networked Suffering tweaks.", "Vanilla value: Off"), true); public static readonly ConstrainedConfigEntry<int, RangeEntryConstraint<int>> NetworkedSufferingSpreadBase = new ConstrainedConfigEntry<int, RangeEntryConstraint<int>>("Item: Networked Suffering", "Base Virus Spread", Paragraph("Maximum number of infected enemies for the first stack.", "Vanilla value: 4"), 3, new RangeEntryConstraint<int>(2, 8)); public static readonly ConstrainedConfigEntry<int, RangeEntryConstraint<int>> NetworkedSufferingSpreadStack = new ConstrainedConfigEntry<int, RangeEntryConstraint<int>>("Item: Networked Suffering", "Virus Spread per Stack", Paragraph("Increased maximum number of infected enemies for every subsequent stack.", "Vanilla value: 2"), 2, new RangeEntryConstraint<int>(0, 4)); public static readonly ConstrainedConfigEntry<float, RangeEntryConstraint<float>> NetworkedSufferingDamageBase = new ConstrainedConfigEntry<float, RangeEntryConstraint<float>>("Item: Networked Suffering", "Base Damage", Paragraph("Virus damage percentage for the first stack.", "Vanilla value: 45"), 35f, new RangeEntryConstraint<float>(5f, 50f)); public static readonly ConstrainedConfigEntry<float, RangeEntryConstraint<float>> NetworkedSufferingDamageStack = new ConstrainedConfigEntry<float, RangeEntryConstraint<float>>("Item: Networked Suffering", "Damage per Stack", Paragraph("Increased virus damage percentage for every subsequent stack.", "Vanilla value: 0"), 1f, new RangeEntryConstraint<float>(0f, 10f)); public static readonly ConfigEntryExt<bool> Megumin = new ConfigEntryExt<bool>("Megumin", "Megumin", "Megumin", true); private static string Paragraph(params string[] lines) { return string.Join("\n", lines); } } internal static class RiskOfOptionsCompatManager { public record AddCheckboxOptionConfig(bool RestartRequired = false); public record AddIntSliderOptionConfig(bool RestartRequired = false, string FormatString = "{0}"); public record AddFloatSliderOptionConfig(bool RestartRequired = false, string FormatString = "{0:0.##}", float Step = 0.01f); public record AddChoiceOptionConfig(bool RestartRequired = false); private static bool? enabled; public static bool Enabled { get { bool valueOrDefault = enabled == true; if (!enabled.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"); enabled = valueOrDefault; } return enabled.Value; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void SetModIcon(Sprite sprite) { ModSettingsManager.SetModIcon(sprite); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void SetModDescription(string desc) { ModSettingsManager.SetModDescription(desc); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void AddCheckboxOption(ConfigEntry<bool> entry, AddCheckboxOptionConfig config = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(entry, new CheckBoxConfig { restartRequired = (config?.RestartRequired ?? false) })); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void AddSliderOption(ConfigEntry<int> entry, AddIntSliderOptionConfig config = null) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) //IL_001e: 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_0050: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown GetRangeFromEntry(entry, out var min, out var max); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(entry, new IntSliderConfig { min = min, max = max, restartRequired = (config?.RestartRequired ?? false), formatString = (config?.FormatString ?? "{0}") })); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void AddSliderOption(ConfigEntry<float> entry, AddFloatSliderOptionConfig config = null) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_00b2: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown GetRangeFromEntry(entry, out var min, out var max); if (config != null && config.Step > 0f) { ModSettingsManager.AddOption((BaseOption)new StepSliderOption(entry, new StepSliderConfig { min = min, max = max, restartRequired = config.RestartRequired, FormatString = (config.FormatString ?? "{0:0.##}"), increment = config.Step })); } else { ModSettingsManager.AddOption((BaseOption)new SliderOption(entry, new SliderConfig { min = min, max = max, restartRequired = (config?.RestartRequired ?? false), FormatString = (config?.FormatString ?? "{0:0.##}") })); } } public static void AddChoiceOption<TEnum>(ConfigEntry<TEnum> entry, AddChoiceOptionConfig config = null) where TEnum : struct, Enum { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)entry, new ChoiceConfig { restartRequired = (config?.RestartRequired ?? false) })); } private static void GetRangeFromEntry(ConfigEntry<int> entry, out int min, out int max) { ConfigDescription description = ((ConfigEntryBase)entry).Description; if (((description != null) ? description.AcceptableValues : null) is AcceptableValueRange<int> val) { min = val.MinValue; max = val.MaxValue; } else { min = int.MinValue; max = int.MaxValue; } } private static void GetRangeFromEntry(ConfigEntry<float> entry, out float min, out float max) { ConfigDescription description = ((ConfigEntryBase)entry).Description; if (((description != null) ? description.AcceptableValues : null) is AcceptableValueRange<float> val) { min = val.MinValue; max = val.MaxValue; } else { min = float.MinValue; max = float.MaxValue; } } } } namespace StackFix.Items { internal sealed class FaradaySpur : IItemFix { private const float VANILLA_MAX_CHARGE_MOVE_SPEED_BASE_PERCENT = 160f; private const float VANILLA_MAX_CHARGE_JUMP_HEIGHT_BASE_PERCENT = 200f; private const float VANILLA_EXPLOSION_DAMAGE_BASE_PERCENT = 400f; private const float VANILLA_EXPLOSION_DAMAGE_STACK_PERCENT = 280f; private const float VANILLA_THRESHOLD_CHARGE_DISTANCE_BASE = 5f; private const float VANILLA_MAX_CHARGE_DISTANCE_BASE = 32.3f; private const float VANILLA_MAX_CHARGE_DISTANCE_STACK = 7.5f; private const float VANILLA_CHARGE_THRESHOLD_BASE_PERCENT = 25f; public bool Enabled { get { if (Plugin.Enabled.Value) { return Plugin.FaradaySpurFixEnabled.Value; } return false; } } public void ApplyFix() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown CharacterBody.RecalculateStats += new Manipulator(CharacterBody_RecalculateStats); JumpDamageStrikeBodyBehavior.DischargeEffects += new Manipulator(JumpDamageStrikeBodyBehavior_DischargeEffects); Plugin.Enabled.SettingChanged += FaradaySpur_SettingChanged; Plugin.FaradaySpurFixEnabled.SettingChanged += FaradaySpur_SettingChanged; Plugin.FaradaySpurMoveSpeedBase.SettingChanged += FaradaySpur_SettingChanged; Plugin.FaradaySpurMoveSpeedStack.SettingChanged += FaradaySpur_SettingChanged; Plugin.FaradaySpurJumpHeightBase.SettingChanged += FaradaySpur_SettingChanged; Plugin.FaradaySpurJumpHeightStack.SettingChanged += FaradaySpur_SettingChanged; Plugin.FaradaySpurDamageBase.SettingChanged += FaradaySpur_SettingChanged; Plugin.FaradaySpurDamageStack.SettingChanged += FaradaySpur_SettingChanged; RegisterItemText(); } private void RegisterItemText() { bool enabled = Enabled; float num = (enabled ? Plugin.FaradaySpurMoveSpeedBase.Value : 160f); float value = (enabled ? Plugin.FaradaySpurMoveSpeedStack.Value : 0f); float num2 = (enabled ? Plugin.FaradaySpurJumpHeightBase.Value : 200f); float value2 = (enabled ? Plugin.FaradaySpurJumpHeightStack.Value : 0f); float num3 = (enabled ? Plugin.FaradaySpurDamageBase.Value : 400f); float value3 = (enabled ? Plugin.FaradaySpurDamageStack.Value : 280f); float num4 = 5f; float value4 = 0f; float num5 = 32.3f; float value5 = 7.5f; float num6 = 25f; float value6 = 0f; LanguageAPI.AddOverlay("ITEM_JUMPDAMAGESTRIKE_DESC", "Moving around builds up " + ItD.Utility("charge") + ", granting up to " + ItD.Utility(string.Format("+{0:0}%{1} movement speed", num, ItD.Stack(value, "+{0:0}%"))) + " " + string.Format("and {0} at 100%. At {1:0}%{2} charge ", ItD.Utility(string.Format("+{0:0}%{1} jump height", num2, ItD.Stack(value2, "+{0:0}%"))), num6, ItD.Stack(value6, "{+0;-0:0}%")) + "or higher, jumping triggers an " + ItD.Damage("explosive discharge") + " for " + ItD.Damage(string.Format("+{0:0}%{1} damage", num3, ItD.Stack(value3, "+{0:0}%"))) + " in a " + ItD.Damage(string.Format("{0:0.#}m{1}", num4, ItD.Stack(value4, "+{0:0.#}m"))) + " to " + ItD.Damage(string.Format("{0:0.#}m{1}", num5, ItD.Stack(value5, "+{0:0.#}m"))) + " area."); } private void FaradaySpur_SettingChanged(object sender, EventArgs e) { RegisterItemText(); } private void CharacterBody_RecalculateStats(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction instr) => ILPatternMatchingExt.MatchLdsfld<JumpDamageStrikeBodyBehavior>(instr, "MoveSpeedVelocityPerCharge") })) { throw new ILSeekException("Failed to match MoveSpeedVelocityPerCharge IL in CharacterBody.RecalculateStats"); } val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<float, CharacterBody, float>>((Func<float, CharacterBody, float>)ModifyMoveSpeedPerCharge); val.Index = 0; if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction instr) => ILPatternMatchingExt.MatchLdsfld<JumpDamageStrikeBodyBehavior>(instr, "JumpVelocityPerCharge") })) { throw new ILSeekException("Failed to match JumpVelocityPerCharge IL in CharacterBody.RecalculateStats"); } val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<float, CharacterBody, float>>((Func<float, CharacterBody, float>)ModifyJumpHeightPerCharge); } private float ModifyMoveSpeedPerCharge(float moveSpeedPerCharge, CharacterBody body) { if (!Enabled) { return moveSpeedPerCharge; } Inventory inventory = body.inventory; int num = ((inventory != null) ? inventory.GetItemCountEffective(Items.JumpDamageStrike) : 0); if (num <= 0) { return moveSpeedPerCharge; } float value = Plugin.FaradaySpurMoveSpeedBase.Value; float value2 = Plugin.FaradaySpurMoveSpeedStack.Value; return ItemStacking.Linear(value, value2, num) * 0.0001f; } private float ModifyJumpHeightPerCharge(float jumpHeightPerCharge, CharacterBody body) { if (!Enabled) { return jumpHeightPerCharge; } Inventory inventory = body.inventory; int num = ((inventory != null) ? inventory.GetItemCountEffective(Items.JumpDamageStrike) : 0); if (num <= 0) { return jumpHeightPerCharge; } float value = Plugin.FaradaySpurJumpHeightBase.Value; float value2 = Plugin.FaradaySpurJumpHeightStack.Value; return ItemStacking.Linear(value, value2, num) * 0.0001f; } private void JumpDamageStrikeBodyBehavior_DischargeEffects(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction instr) => ILPatternMatchingExt.MatchLdcR4(instr, 4f) })) { throw new ILSeekException("Failed to match base damage IL in JumpDamageStrikeBodyBehavior.DischargeEffects"); } val.EmitDelegate<Func<float, float>>((Func<float, float>)ModifyBaseDamage); val.Index = 0; if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction instr) => ILPatternMatchingExt.MatchLdcR4(instr, 2.8f) })) { throw new ILSeekException("Failed to match stack damage IL in JumpDamageStrikeBodyBehavior.DischargeEffects"); } val.EmitDelegate<Func<float, float>>((Func<float, float>)ModifyStackDamage); } private float ModifyBaseDamage(float baseDamage) { if (!Enabled) { return baseDamage; } return Plugin.FaradaySpurDamageBase.Value * 0.01f; } private float ModifyStackDamage(float stackDamage) { if (!Enabled) { return stackDamage; } return Plugin.FaradaySpurDamageStack.Value * 0.01f; } } internal sealed class NetworkedSuffering : IItemFix, IDisposable { private const int VANILLA_VIRUS_SPREAD_COUNT_BASE = 4; private const int VANILLA_VIRUS_SPREAD_COUNT_STACK = 2; private const float VANILLA_VIRUS_DAMAGE_BASE_PERCENT = 45f; private ILHook currentMaxHook; public bool Enabled { get { if (Plugin.Enabled.Value) { return Plugin.NetworkedSufferingFixEnabled.Value; } return false; } } public void ApplyFix() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown InstallCurrentMaxHook(); SharedSufferingManager.SendToDamagePool += new Manipulator(SharedSufferingManager_SendToDamagePool); Plugin.Enabled.SettingChanged += NetworkedSuffering_SettingChanged; Plugin.NetworkedSufferingFixEnabled.SettingChanged += NetworkedSuffering_SettingChanged; Plugin.NetworkedSufferingSpreadBase.SettingChanged += NetworkedSuffering_SettingChanged; Plugin.NetworkedSufferingSpreadStack.SettingChanged += NetworkedSuffering_SettingChanged; Plugin.NetworkedSufferingDamageBase.SettingChanged += NetworkedSuffering_SettingChanged; Plugin.NetworkedSufferingDamageStack.SettingChanged += NetworkedSuffering_SettingChanged; RegisterItemText(); } private void RegisterItemText() { bool enabled = Enabled; int num = (enabled ? Plugin.NetworkedSufferingSpreadBase.Value : 4); int num2 = (enabled ? Plugin.NetworkedSufferingSpreadStack.Value : 2); float num3 = (enabled ? Plugin.NetworkedSufferingDamageBase.Value : 45f); float value = (enabled ? Plugin.NetworkedSufferingDamageStack.Value : 0f); LanguageAPI.AddOverlay("ITEM_SHAREDSUFFERING_DESC", "Infect up to " + ItD.Utility($"{num}{ItD.Stack(num2)}") + " enemies with a computer virus that duplicates " + ItD.Damage(string.Format("{0}%{1} of all damage taken", num3, ItD.Stack(value, "+{0:0}%"))) + " and sends it to a global damage pool. Every 3 seconds, ALL infected enemies suffer " + ItD.Damage("100% pooled damage") + "."); } private void NetworkedSuffering_SettingChanged(object sender, EventArgs e) { RegisterItemText(); } private void InstallCurrentMaxHook() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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 MethodInfo methodInfo = typeof(SharedSufferingItemBehaviour).GetProperty("currentMax", BindingFlags.Instance | BindingFlags.NonPublic)?.GetGetMethod(nonPublic: true) ?? throw new MissingMethodException(typeof(SharedSufferingItemBehaviour).FullName, "get_currentMax"); currentMaxHook = new ILHook((MethodBase)methodInfo, new Manipulator(CurrentMax)); } private void CurrentMax(ILContext il) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) il.Body.Instructions.Clear(); ILCursor val = new ILCursor(il); val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<SharedSufferingItemBehaviour, int>>((Func<SharedSufferingItemBehaviour, int>)OverwriteCurrentMax); val.Emit(OpCodes.Ret); } private int OverwriteCurrentMax(SharedSufferingItemBehaviour self) { bool enabled = Enabled; int initial = (enabled ? Plugin.NetworkedSufferingSpreadBase.Value : 4); int perStack = (enabled ? Plugin.NetworkedSufferingSpreadStack.Value : 2); return ItemStacking.Linear(initial, perStack, ((BaseItemBodyBehavior)self).stack); } private void SharedSufferingManager_SendToDamagePool(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[3] { (Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0), (Instruction x) => ILPatternMatchingExt.MatchLdfld<SharedSufferingManager>(x, "_damageSentToPool"), (Instruction x) => ILPatternMatchingExt.MatchMul(x) })) { throw new ILSeekException("Failed to match damageSentToPool IL inSharedSufferingManager.SendToDamagePool"); } val.RemoveRange(3); val.Emit(OpCodes.Ldarg_0); val.Emit(OpCodes.Ldarg_1); val.EmitDelegate<Func<SharedSufferingManager, DamageReport, float>>((Func<SharedSufferingManager, DamageReport, float>)ModifyDamageMultiplier); val.Emit(OpCodes.Mul); } private float ModifyDamageMultiplier(SharedSufferingManager manager, DamageReport report) { if (!Enabled) { return manager._damageSentToPool; } CharacterBody victimBody = report.victimBody; if (!Object.op_Implicit((Object)(object)victimBody)) { return manager._damageSentToPool; } SharedSufferingBuffController component = ((Component)victimBody).GetComponent<SharedSufferingBuffController>(); CharacterBody obj = (Object.op_Implicit((Object)(object)component) ? component.attacker : null); int? obj2; if (obj == null) { obj2 = null; } else { Inventory inventory = obj.inventory; obj2 = ((inventory != null) ? new int?(inventory.GetItemCountEffective(Items.SharedSuffering)) : ((int?)null)); } int? num = obj2; int valueOrDefault = num.GetValueOrDefault(); if (valueOrDefault <= 0) { return manager._damageSentToPool; } float value = Plugin.NetworkedSufferingDamageBase.Value; float value2 = Plugin.NetworkedSufferingDamageStack.Value; return ItemStacking.Linear(value, value2, valueOrDefault) * 0.01f; } public void Dispose() { ILHook obj = currentMaxHook; if (obj != null) { obj.Dispose(); } currentMaxHook = null; } } } namespace StackFix.Exceptions { internal class ILSeekException : Exception { public ILSeekException(string message) : base(message) { } } }