Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of UncappedAttackSpeed v2.0.4
plugins/UncapAttackSpeed.dll
Decompiled 4 hours agousing System; using System.Collections.Generic; using System.Diagnostics; 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 System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Dolso; using EntityStates; using EntityStates.Commando.CommandoWeapon; using EntityStates.Huntress.HuntressWeapon; using EntityStates.Toolbot; using EntityStates.VoidSurvivor.Weapon; using HG.GeneralSerializer; using HG.Reflection; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Orbs; using RoR2.Skills; using RoR2BepInExPack.Utilities; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("UncapAttackSpeed")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+d6c99d9196968be3f0ba41bf42917e3abd212624")] [assembly: AssemblyProduct("UncapAttackSpeed")] [assembly: AssemblyTitle("UncapAttackSpeed")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Dolso { internal static class log { private static readonly ManualLogSource logger = Logger.CreateLogSource(Assembly.GetExecutingAssembly().GetName().Name); [Conditional("DEBUG")] internal static void debug(object data) { logger.LogDebug(data); } internal static void info(object data) { logger.LogInfo(data); } internal static void message(object data) { logger.LogMessage(data); } internal static void warning(object data) { logger.LogWarning(data); } internal static void error(object data) { logger.LogError(data); } internal static void fatal(object data) { logger.LogFatal(data); } internal static void LogError(this ILCursor c, object data) { logger.LogError((object)$"ILCursor failure, skipping: {data}\n{c}"); } internal static void LogErrorCaller(this ILCursor c, object data) { logger.LogError((object)$"ILCursor failed in {new StackFrame(1).GetMethod().Name}, skipping: {data}\n{c}"); } } internal static class HookManager { internal delegate bool ConfigEnabled<T>(T configValue); private class HookedConfig<T> { private readonly ConfigEnabled<T> enabled; private readonly IDetour detour; internal HookedConfig(ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, IDetour detour) { this.enabled = enabled; this.detour = detour; if (configEntry != null) { configEntry.SettingChanged += ConfigChanged; ConfigChanged(configEntry, null); } else { detour.Apply(); } } private void ConfigChanged(object sender, EventArgs args) { if (enabled(((ConfigEntry<T>)sender).Value)) { if (!detour.IsApplied) { detour.Apply(); } } else if (detour.IsApplied) { detour.Undo(); } } } internal const BindingFlags allFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static readonly ConfigEnabled<bool> boolConfigEnabled = BoolEnabled; private static ILHookConfig ilHookConfig = new ILHookConfig { ManualApply = true }; private static HookConfig onHookConfig = new HookConfig { ManualApply = true }; internal static void Hook(Type typeFrom, string fromMethod, Manipulator ilHook) { Hook(GetMethod(typeFrom, fromMethod), ilHook); } internal static void Hook(Delegate fromMethod, Manipulator ilHook) { Hook(fromMethod.Method, ilHook); } internal static void Hook(MethodBase fromMethod, Manipulator ilHook) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) try { new ILHook(fromMethod, ilHook, ref ilHookConfig).Apply(); } catch (Exception e) { e.LogHookError(fromMethod, ((Delegate)(object)ilHook).Method); } } internal static void Hook(Type typeFrom, string fromMethod, Delegate onHook) { Hook(GetMethod(typeFrom, fromMethod), onHook.Method, onHook.Target); } internal static void Hook(Delegate fromMethod, Delegate onHook) { Hook(fromMethod.Method, onHook.Method, onHook.Target); } internal static void Hook(MethodBase fromMethod, Delegate onHook) { Hook(fromMethod, onHook.Method, onHook.Target); } internal static void Hook(MethodBase fromMethod, MethodInfo onHook, object target = null) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) try { new Hook(fromMethod, onHook, target, ref onHookConfig).Apply(); } catch (Exception e) { e.LogHookError(fromMethod, onHook); } } internal static void HookConfig(this ConfigEntry<bool> configEntry, Type typeFrom, string fromMethod, Delegate hook) { configEntry.HookConfig(boolConfigEnabled, GetMethod(typeFrom, fromMethod), hook.Method, hook.Target); } internal static void HookConfig(this ConfigEntry<bool> configEntry, MethodBase fromMethod, Delegate hook) { configEntry.HookConfig(boolConfigEnabled, fromMethod, hook.Method, hook.Target); } internal static void HookConfig(this ConfigEntry<bool> configEntry, MethodBase fromMethod, MethodInfo hook) { configEntry.HookConfig(boolConfigEnabled, fromMethod, hook); } internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, Type typeFrom, string fromMethod, Delegate hook) { configEntry.HookConfig(enabled, GetMethod(typeFrom, fromMethod), hook.Method, hook.Target); } internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase fromMethod, Delegate hook) { configEntry.HookConfig(enabled, fromMethod, hook.Method, hook.Target); } internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase fromMethod, MethodInfo hook, object target = null) { try { new HookedConfig<T>(configEntry, enabled, ManualDetour(fromMethod, hook, target)); } catch (Exception e) { e.LogHookError(fromMethod, hook); } } internal static IDetour ManualDetour(Type typeFrom, string fromMethod, Delegate hook) { return ManualDetour(GetMethod(typeFrom, fromMethod), hook.Method, hook.Target); } internal static IDetour ManualDetour(MethodBase fromMethod, Delegate hook) { return ManualDetour(fromMethod, hook.Method, hook.Target); } internal static IDetour ManualDetour(MethodBase fromMethod, MethodInfo hook, object target = null) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown try { ParameterInfo[] parameters = hook.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(ILContext)) { return (IDetour)new ILHook(fromMethod, (Manipulator)hook.CreateDelegate(typeof(Manipulator)), ref ilHookConfig); } return (IDetour)new Hook(fromMethod, hook, target, ref onHookConfig); } catch (Exception e) { e.LogHookError(fromMethod, hook); return null; } } internal static MethodInfo GetMethod(Type typeFrom, string methodName) { if (typeFrom == null || methodName == null) { log.error($"Null argument in GetMethod: type={typeFrom}, name={methodName}"); return null; } MethodInfo[] array = (from a in typeFrom.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where a.Name == methodName select a).ToArray(); switch (array.Length) { case 1: return array[0]; case 0: log.error($"Failed to find method: {typeFrom}::{methodName}"); return null; default: { string text = $"{array.Length} ambiguous matches found for: {typeFrom}::{methodName}, may be incorrect"; MethodInfo[] array2 = array; for (int i = 0; i < array2.Length; i++) { text = text + "\n" + array2[i]; } log.warning(text); return array[0]; } } } internal static MethodInfo GetMethod(Type typeFrom, string methodName, params Type[] parameters) { if (typeFrom == null || methodName == null) { log.error($"Null argument in GetMethod: type={typeFrom}, name={methodName}"); return null; } MethodInfo? method = typeFrom.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameters, null); if (method == null) { log.error($"Failed to find method: {typeFrom}::{methodName}_{parameters.Length}"); } return method; } internal static void SetPriority(string[] before_il = null, string[] before_on = null, string[] after_il = null, string[] after_on = null) { ilHookConfig.Before = before_il; onHookConfig.Before = before_on; ilHookConfig.After = after_il; onHookConfig.After = after_on; } internal static void LogHookError(this Exception e, MethodBase fromMethod, MethodInfo hook) { log.error((fromMethod == null) ? $"null from-method for hook: {hook.Name}\n{e}" : $"Failed to hook: {fromMethod.DeclaringType}::{fromMethod.Name} - {hook.Name}\n{e}"); } private static bool BoolEnabled(bool configValue) { return configValue; } } internal static class Utilities { internal struct AsyncHandle<T> : IDisposable { private AsyncOperationHandle<T> handle; public T result => handle.Result; public Task<T> task => handle.Task; internal AsyncHandle(AsyncOperationHandle<T> handle) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) this.handle = handle; } public TaskAwaiter<T> GetAwaiter() { return handle.Task.GetAwaiter(); } public void Dispose() { handle.Release(); } public static implicit operator AsyncOperationHandle<T>(AsyncHandle<T> handle) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return handle.handle; } } private static GameObject _prefabParent; internal static GameObject CreatePrefab(GameObject gameObject, string name = null) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)_prefabParent)) { _prefabParent = new GameObject("DolsoPrefabs"); Object.DontDestroyOnLoad((Object)(object)_prefabParent); ((Object)_prefabParent).hideFlags = (HideFlags)61; _prefabParent.SetActive(false); } GameObject val = Object.Instantiate<GameObject>(gameObject, _prefabParent.transform); if (name != null) { ((Object)val).name = name; } return val; } internal static AsyncHandle<T> GetAddressableAsync<T>(string addressable) where T : Object { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new AsyncHandle<T>(Addressables.LoadAssetAsync<T>((object)addressable)); } internal static AsyncHandle<GameObject> GetAddressableAsync(string addressable) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new AsyncHandle<GameObject>(Addressables.LoadAssetAsync<GameObject>((object)addressable)); } internal static void DoAddressable<T>(string addressable, Action<T> callback, bool release = false) where T : Object { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) AsyncOperationHandle<T> handle = Addressables.LoadAssetAsync<T>((object)addressable); handle.Completed += delegate(AsyncOperationHandle<T> a) { callback(a.Result); if (release) { handle.Release(); } }; } internal static void DoAddressable(string addressable, Action<GameObject> callback, bool release = false) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>((object)addressable); handle.Completed += delegate(AsyncOperationHandle<GameObject> a) { callback(a.Result); if (release) { handle.Release(); } }; } internal static void AddressableAddComp<TComp>(string addressable, Action<TComp> callback = null) where TComp : Component { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable); val.Completed += delegate(AsyncOperationHandle<GameObject> a) { TComp obj = a.Result.AddComponent<TComp>(); callback?.Invoke(obj); }; } internal static void AddressableAddCompSingle<Comp>(string addressable) where Comp : Component { //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) AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable); val.Completed += delegate(AsyncOperationHandle<GameObject> a) { if (!Object.op_Implicit((Object)(object)a.Result.GetComponent<Comp>())) { a.Result.AddComponent<Comp>(); } }; } internal static void ModifyStateConfig(this EntityStateConfiguration stateConfig, string fieldName, object newValue) { SerializedField[] serializedFields = stateConfig.serializedFieldsCollection.serializedFields; for (int i = 0; i < serializedFields.Length; i++) { if (serializedFields[i].fieldName == fieldName) { Object val = (Object)((newValue is Object) ? newValue : null); if (val != null) { serializedFields[i].fieldValue.objectValue = val; } else if (newValue != null && StringSerializer.CanSerializeType(newValue.GetType())) { serializedFields[i].fieldValue.stringValue = StringSerializer.Serialize(newValue.GetType(), newValue); } else { log.error("Invalid value for SerializedField: " + newValue); } return; } } log.error("Failed to find " + fieldName + " for " + ((Object)stateConfig).name); } internal static bool IsKeyDown(this KeyboardShortcut key, bool onlyJustPressed) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (onlyJustPressed) { if (!Input.GetKeyDown(((KeyboardShortcut)(ref key)).MainKey)) { return false; } } else if (!Input.GetKey(((KeyboardShortcut)(ref key)).MainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref key)).Modifiers) { if (!Input.GetKey(modifier)) { return false; } } return true; } } internal static class RiskofOptions { internal const string RooGuid = "com.rune580.riskofoptions"; internal static bool enabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"); [MethodImpl(MethodImplOptions.NoInlining)] internal static void SetSprite(Sprite sprite) { ModSettingsManager.SetModIcon(sprite); } internal static void SetSpriteDefaultIcon() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) try { string fullName = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)).FullName; Texture2D val = new Texture2D(256, 256); if (ImageConversion.LoadImage(val, File.ReadAllBytes(Path.Combine(fullName, "icon.png")))) { ModSettingsManager.SetModIcon(Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f))); } else { log.error("Failed to load icon.png"); } } catch (Exception ex) { log.error("Failed to load icon.png\n" + ex); } } internal static void AddOption(ConfigEntryBase entry) { AddOption(entry, string.Empty, string.Empty); } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddOption(ConfigEntryBase entry, string categoryName = "", string name = "", bool restartRequired = false) { //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00a5: 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_0095: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) Type settingType = entry.SettingType; object obj; if (!(settingType == typeof(float))) { obj = ((!(settingType == typeof(string))) ? ((!(settingType == typeof(bool))) ? ((!(settingType == typeof(int))) ? ((!(settingType == typeof(Color))) ? ((!(settingType == typeof(KeyboardShortcut))) ? ((object)((!settingType.IsEnum) ? ((ChoiceOption)null) : new ChoiceOption(entry, new ChoiceConfig()))) : ((object)new KeyBindOption((ConfigEntry<KeyboardShortcut>)(object)entry, new KeyBindConfig()))) : ((object)new ColorOption((ConfigEntry<Color>)(object)entry, new ColorOptionConfig()))) : ((object)new IntFieldOption((ConfigEntry<int>)(object)entry, new IntFieldConfig()))) : ((object)new CheckBoxOption((ConfigEntry<bool>)(object)entry, new CheckBoxConfig()))) : ((object)new StringInputFieldOption((ConfigEntry<string>)(object)entry, new InputFieldConfig { submitOn = (SubmitEnum)6, lineType = (LineType)0 }))); } else if (entry.Description.AcceptableValues is AcceptableValueRange<float>) { obj = (object)new SliderOption((ConfigEntry<float>)(object)entry, new SliderConfig { min = ((AcceptableValueRange<float>)(object)entry.Description.AcceptableValues).MinValue, max = ((AcceptableValueRange<float>)(object)entry.Description.AcceptableValues).MaxValue, FormatString = "{0:f2}", description = entry.DescWithDefault("{0:f2}") }); } else { ConfigEntry<float> obj2 = (ConfigEntry<float>)(object)entry; FloatFieldConfig val = new FloatFieldConfig(); ((NumericFieldConfig<float>)val).FormatString = "{0:f2}"; ((BaseOptionConfig)val).description = entry.DescWithDefault("{0:f2}"); obj = (object)new FloatFieldOption(obj2, val); } BaseOption val2 = (BaseOption)obj; if (val2 == null) { return; } BaseOptionConfig config = val2.GetConfig(); config.category = categoryName; config.name = name; config.restartRequired = restartRequired; if (config.description == "") { config.description = entry.DescWithDefault(); } try { ModSettingsManager.AddOption(val2); } catch (Exception arg) { log.error($"AddOption {entry.Definition} failed\n{arg}"); } } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddOption(ConfigEntry<float> entry, float min, float max, string format = "{0:f2}", string categoryName = "") { //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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) //IL_0035: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new SliderOption(entry, new SliderConfig { min = min, max = max, FormatString = format, category = categoryName, description = ((ConfigEntryBase)(object)entry).DescWithDefault(format) })); } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddIntSlider(ConfigEntry<int> entry, int min, int max, string categoryName = "") { //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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new IntSliderOption(entry, new IntSliderConfig { min = min, max = max, category = categoryName, description = ((ConfigEntryBase)(object)entry).DescWithDefault() })); } private static string DescWithDefault(this ConfigEntryBase entry, string format = "{0}") { return string.Format("{1}\n[Default: " + format + "]", entry.DefaultValue, entry.Description.Description); } } } namespace UncapAttackSpeed { internal class AttackFraction { internal static FixedConditionalWeakTable<BaseSkillInstanceData, AttackFraction> skillInstanceToAttackFraction = new FixedConditionalWeakTable<BaseSkillInstanceData, AttackFraction>(); public float attackFraction; public static AttackFraction Constructor(object _) { return new AttackFraction(); } } internal static class Commando { internal const float baseDuration = 0.1666f; private static bool interrupt; internal static void DoSetup() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown HookManager.Hook(typeof(FirePistol2).GetMethod("FixedUpdate"), new Manipulator(IL_FirePistol2_FixedUpdate_ExtraAttacks)); HookManager.Hook((MethodBase)typeof(FirePistol2).GetMethod("GetMinimumInterruptPriority"), (Delegate)new Func<Func<FirePistol2, InterruptPriority>, FirePistol2, InterruptPriority>(On_FirePistol2_Priority_AfterDuration)); Utilities.DoAddressable<EntityStateConfiguration>("RoR2/Base/Commando/EntityStates.Commando.CommandoWeapon.FirePistol2.asset", (Action<EntityStateConfiguration>)delegate(EntityStateConfiguration a) { a.ModifyStateConfig("baseDuration", 0.1666f); }, release: false); } private static void IL_FirePistol2_FixedUpdate_ExtraAttacks(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); if (!val.TryGotoNext(new Func<Instruction, bool>[3] { (Instruction a) => ILPatternMatchingExt.MatchLdarg(a, 0), (Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt<BaseSkillState>(a, "get_activatorSkillSlot"), (Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt<GenericSkill>(a, "get_stock") })) { val.LogErrorCaller("commando state transition"); return; } val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<FirePistol2, bool>>((Func<FirePistol2, bool>)delegate(FirePistol2 self) { if (((BaseSkillState)self).IsKeyDownAuthority()) { BaseSkillInstanceData skillInstanceData = ((BaseSkillState)self).activatorSkillSlot.skillInstanceData; InstanceData val2 = (InstanceData)(object)((skillInstanceData is InstanceData) ? skillInstanceData : null); if (val2 != null) { float num = ((EntityState)self).fixedAge - self.duration; while (num >= self.duration) { num -= self.duration; Main.extraAttacks = 1; val2.step++; if (val2.step >= 2) { val2.step = 0; } if (val2.step % 2 == 0) { ((EntityState)self).PlayAnimation("Gesture Additive, Left", FirePistol2.FirePistolLeftStateHash); self.FireBullet("MuzzleLeft"); } else { ((EntityState)self).PlayAnimation("Gesture Additive, Right", FirePistol2.FirePistolRightStateHash); self.FireBullet("MuzzleRight"); } Main.extraAttacks = 0; } interrupt = true; ((BaseSkillState)self).activatorSkillSlot.OnExecute(); interrupt = false; EntityState nextState = ((EntityState)self).outer.nextState; FirePistol2 val3 = (FirePistol2)(object)((nextState is FirePistol2) ? nextState : null); if (val3 != null) { ((EntityState)val3).fixedAge = num; } return true; } } return false; }); val.Emit(OpCodes.Brfalse, val.Next); val.Emit(OpCodes.Ret); } private static InterruptPriority On_FirePistol2_Priority_AfterDuration(Func<FirePistol2, InterruptPriority> orig, FirePistol2 self) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (!interrupt) { return orig(self); } return (InterruptPriority)0; } } internal static class Config { private static ConfigFile configFile; internal static ConfigEntry<bool> nailgunFinalBurst; internal static ConfigEntry<EffectsFlags> disableExtraEffects; internal static void DoConfig(ConfigFile bepConfigFile) { configFile = bepConfigFile; nailgunFinalBurst = configFile.Bind<bool>("", "Nailgun Final Burst", false, "If should force Nailgun to always fire its final burst exactly once."); disableExtraEffects = configFile.Bind<EffectsFlags>("", "Disable extra effects", EffectsFlags.None, "Effects chosen here will be hidden for extra attacks generated by this mod"); if (RiskofOptions.enabled) { DoRiskOfOptions(); } } internal static void DoRiskOfOptions() { RiskofOptions.SetSpriteDefaultIcon(); RiskofOptions.AddOption((ConfigEntryBase)(object)nailgunFinalBurst); RiskofOptions.AddOption((ConfigEntryBase)(object)disableExtraEffects); } [ConCommand(/*Could not decode attribute arguments.*/)] private static void ReloadConfig(ConCommandArgs args) { configFile.Reload(); Debug.Log((object)"UncapAttackSpeed config reloaded"); } } [Flags] internal enum EffectsFlags { None = 0, Tracers = 1, Impacts = 2 } internal static class Huntress { internal const float sbaseDuration = 0.5166f; internal const float fbaseDuration = 1.3333f; private static bool interrupt; internal static void DoSetup() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown HookManager.Hook(typeof(FireSeekingArrow), "FixedUpdate", new Manipulator(IL_FireSeekingArrow_FixedUpdate_Stuff)); HookManager.Hook(typeof(FireSeekingArrow), "GetMinimumInterruptPriority", (Delegate)new Func<Func<FireSeekingArrow, InterruptPriority>, FireSeekingArrow, InterruptPriority>(On_FireSeekingArrow_Priority_AfterDuration)); HookManager.Hook(typeof(FireSeekingArrow), "OnExit", (Delegate)new Action<Action<FireSeekingArrow>, FireSeekingArrow>(On_FireSeekingArrow_OnExit_Excess)); HookManager.Hook(typeof(HuntressArrowOrb), "GetOrbEffect", (Delegate)(Func<Func<HuntressArrowOrb, GameObject>, HuntressArrowOrb, GameObject>)((Func<HuntressArrowOrb, GameObject> orig, HuntressArrowOrb self) => (Main.extraAttacks == 0) ? orig(self) : null)); HookManager.Hook(typeof(HuntressFlurryArrowOrb), "GetOrbEffect", (Delegate)(Func<Func<HuntressFlurryArrowOrb, GameObject>, HuntressFlurryArrowOrb, GameObject>)((Func<HuntressFlurryArrowOrb, GameObject> orig, HuntressFlurryArrowOrb self) => (Main.extraAttacks == 0) ? orig(self) : null)); Utilities.DoAddressable<EntityStateConfiguration>("RoR2/Base/Huntress/EntityStates.Huntress.HuntressWeapon.FireSeekingArrow.asset", (Action<EntityStateConfiguration>)delegate(EntityStateConfiguration a) { a.ModifyStateConfig("baseDuration", 0.5166f); }, release: false); Utilities.DoAddressable<EntityStateConfiguration>("RoR2/Base/Huntress/EntityStates.Huntress.HuntressWeapon.FireFlurrySeekingArrow.asset", (Action<EntityStateConfiguration>)delegate(EntityStateConfiguration a) { a.ModifyStateConfig("baseDuration", 1.3333f); }, release: false); } private static void IL_FireSeekingArrow_FixedUpdate_Stuff(ILContext context) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(context); ILCursor[] array = default(ILCursor[]); if (val.TryGotoNext(new Func<Instruction, bool>[2] { (Instruction a) => ILPatternMatchingExt.MatchLdarg(a, 0), (Instruction a) => ILPatternMatchingExt.MatchLdfld(a, typeof(FireSeekingArrow), "animator") }) && val.TryFindNext(ref array, new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchCall(a, typeof(FireSeekingArrow), "FireOrbArrow") })) { val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<FireSeekingArrow, bool>>((Func<FireSeekingArrow, bool>)((FireSeekingArrow self) => ((EntityState)self).fixedAge >= self.duration / 2f)); ILCursor val2 = array[0]; if (val2.TryGotoPrev(new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchLdarg(a, 0) })) { val.Emit(OpCodes.Brtrue, (object)val2.MarkLabel()); if (val2.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchCall(a, typeof(FireSeekingArrow), "FireOrbArrow") })) { val.Emit(OpCodes.Br, (object)val2.MarkLabel()); goto IL_015e; } } } log.error($"Failed to find IL FireSeekingArrow_FixedUpdate duration\n{val}"); goto IL_015e; IL_015e: if (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(EntityStateMachine), "SetNextStateToMain") }) && val.TryGotoPrev(new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchLdarg(a, 0) })) { val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<FireSeekingArrow, bool>>((Func<FireSeekingArrow, bool>)delegate(FireSeekingArrow self) { if (!((EntityState)self).inputBank.skill1.down || !Object.op_Implicit((Object)(object)self.huntressTracker) || !Object.op_Implicit((Object)(object)self.huntressTracker.GetTrackingTarget())) { return false; } interrupt = true; ((EntityState)self).skillLocator.primary.OnExecute(); interrupt = false; return true; }); val.Emit(OpCodes.Brfalse, val.Next); val.Emit(OpCodes.Ret); } else { log.error($"Failed to find IL FireSeekingArrow_FixedUpdate nextState\n{val}"); } } private static void On_FireSeekingArrow_OnExit_Excess(Action<FireSeekingArrow> orig, FireSeekingArrow self) { orig(self); if (!NetworkServer.active) { return; } while (self.firedArrowCount < self.maxArrowCount) { FireExcess(self); } BaseSkillInstanceData skillInstanceData = ((EntityState)self).skillLocator.primary.skillInstanceData; if (skillInstanceData == null) { return; } AttackFraction value = AttackFraction.skillInstanceToAttackFraction.GetValue(skillInstanceData, (Func<BaseSkillInstanceData, AttackFraction>)AttackFraction.Constructor); float num; for (num = (((EntityState)self).fixedAge - self.duration) / self.duration + value.attackFraction; num >= 1f; num -= 1f) { for (int i = 0; i < self.maxArrowCount; i++) { self.firedArrowCount--; FireExcess(self); } } value.attackFraction = num; } private static void FireExcess(FireSeekingArrow self) { self.arrowReloadTimer = 0f; Main.extraAttacks = 1; self.FireOrbArrow(); Main.extraAttacks = 0; } private static InterruptPriority On_FireSeekingArrow_Priority_AfterDuration(Func<FireSeekingArrow, InterruptPriority> orig, FireSeekingArrow self) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (!interrupt) { return orig(self); } return (InterruptPriority)0; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("dolso.uncapattackspeed", "UncapAttackSpeed", "2.0.4")] public class Main : BaseUnityPlugin { public static int extraAttacks; private void Awake() { Config.DoConfig(((BaseUnityPlugin)this).Config); Commando.DoSetup(); Nailgun.DoSetup(); VoidFiend.DoSetup(); Huntress.DoSetup(); Config.disableExtraEffects.HookConfig((EffectsFlags a) => a != EffectsFlags.None, typeof(BulletAttack), "FireSingle", new Action<Action<BulletAttack, FireSingleArgs>, BulletAttack, FireSingleArgs>(On_BulletAttack_FireSingle_RemoveTracer)); HookManager.Hook(typeof(BaseState), "AddRecoil", (Delegate)new Action<Action<BaseState, float, float, float, float>, BaseState, float, float, float, float>(On_BaseState_AddRecoil_RemoveRecoil)); } private static void On_BulletAttack_FireSingle_RemoveTracer(Action<BulletAttack, FireSingleArgs> orig, BulletAttack self, FireSingleArgs args) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (extraAttacks > 0) { EffectsFlags value = Config.disableExtraEffects.Value; extraAttacks--; GameObject tracerEffectPrefab = self.tracerEffectPrefab; GameObject hitEffectPrefab = self.hitEffectPrefab; if ((value & EffectsFlags.Tracers) != 0) { self.tracerEffectPrefab = null; } if ((value & EffectsFlags.Impacts) != 0) { self.hitEffectPrefab = null; } orig(self, args); if ((value & EffectsFlags.Tracers) != 0) { self.tracerEffectPrefab = tracerEffectPrefab; } if ((value & EffectsFlags.Impacts) != 0) { self.hitEffectPrefab = hitEffectPrefab; } } else { orig(self, args); } } private static void On_BaseState_AddRecoil_RemoveRecoil(Action<BaseState, float, float, float, float> orig, BaseState self, float verticalMin, float verticalMax, float horizontalMin, float horizontalMax) { if (extraAttacks == 0) { orig(self, verticalMin, verticalMax, horizontalMin, horizontalMax); } } } internal static class Nailgun { private static List<FireNailgun> nailgunInstances = new List<FireNailgun>(); internal static void DoSetup() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown HookManager.Hook(typeof(FireNailgun).GetMethod("FixedUpdate"), new Manipulator(IL_FireNailgun_FixedUpdate_ExtraAttacks)); HookManager.Hook((MethodBase)typeof(FireNailgun).GetMethod("OnExit"), (Delegate)new Action<Action<FireNailgun>, FireNailgun>(On_FireNailgun_OnExit_ForceBurst)); HookManager.Hook((MethodBase)typeof(FireNailgun).GetMethod("OnEnter"), (Delegate)new Action<Action<FireNailgun>, FireNailgun>(On_FireNailgun_OnEnter_Track)); } private static void IL_FireNailgun_FixedUpdate_ExtraAttacks(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); int num2 = default(int); if (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt<BaseNailgunState>(a, "FireBullet") }) && val.TryGotoPrev((MoveType)2, new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchLdcI4(a, ref num2) })) { val.Emit(OpCodes.Ldarg, 0); val.EmitDelegate<Func<FireNailgun, int>>((Func<FireNailgun, int>)delegate(FireNailgun self) { int num = Mathf.FloorToInt(self.refireStopwatch / ((BaseNailgunState)self).duration); if (num > 0) { self.refireStopwatch -= (float)num * ((BaseNailgunState)self).duration; Main.extraAttacks = num; return num; } return 0; }); val.Emit(OpCodes.Add); if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt<BaseNailgunState>(a, "FireBullet") })) { val.Emit(OpCodes.Ldc_I4, 0); val.Emit(OpCodes.Stsfld, typeof(Main).GetField("extraAttacks")); } else { log.error($"Failed to find BaseNailgunState.FireBullet\n{val}"); } if (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt<EntityStateMachine>(a, "SetNextState") })) { val.Emit(OpCodes.Ldsfld, typeof(Nailgun).GetField("nailgunInstances", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); val.Emit(OpCodes.Ldarg, 0); val.Emit<List<FireNailgun>>(OpCodes.Call, "Remove"); val.Emit(OpCodes.Pop); return; } } log.error($"Failed IL hook Nailgun\n{val}"); } private static void On_FireNailgun_OnEnter_Track(Action<FireNailgun> orig, FireNailgun self) { orig(self); nailgunInstances.Add(self); } private static void On_FireNailgun_OnExit_ForceBurst(Action<FireNailgun> orig, FireNailgun self) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) orig(self); if (!nailgunInstances.Contains(self)) { return; } nailgunInstances.Remove(self); if (Config.nailgunFinalBurst.Value) { Util.PlayAttackSpeedSound(NailgunSpinDown.spinDownSound, ((EntityState)self).gameObject, ((BaseState)self).attackSpeedStat); ((EntityState)self).characterBody.SetSpreadBloom(1f, false); Ray aimRay = ((BaseState)self).GetAimRay(); ((BaseNailgunState)self).FireBullet(((BaseState)self).GetAimRay(), NailgunFinalBurst.finalBurstBulletCount, BaseNailgunState.spreadPitchScale, BaseNailgunState.spreadYawScale); if (!((BaseToolbotPrimarySkillState)self).isInDualWield) { ((EntityState)self).PlayAnimation("Gesture, Additive", "FireGrenadeLauncher", "FireGrenadeLauncher.playbackRate", 0.45f / ((BaseState)self).attackSpeedStat, 0f); } else { BaseToolbotPrimarySkillStateMethods.PlayGenericFireAnim<FireNailgun>(self, ((EntityState)self).gameObject, ((EntityState)self).skillLocator, 0.45f / ((BaseState)self).attackSpeedStat); } Util.PlaySound(NailgunFinalBurst.burstSound, ((EntityState)self).gameObject); if (((EntityState)self).isAuthority) { float num = NailgunFinalBurst.selfForce * (((EntityState)self).characterMotor.isGrounded ? 0.5f : 1f) * ((EntityState)self).characterMotor.mass; ((EntityState)self).characterMotor.ApplyForce(((Ray)(ref aimRay)).direction * (0f - num), false, false); } Util.PlaySound(BaseNailgunState.fireSoundString, ((EntityState)self).gameObject); Util.PlaySound(BaseNailgunState.fireSoundString, ((EntityState)self).gameObject); Util.PlaySound(BaseNailgunState.fireSoundString, ((EntityState)self).gameObject); } } } internal static class VoidFiend { internal const float baseDuration = 7.5f; internal static void DoSetup() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown HookManager.Hook(typeof(FireCorruptHandBeam), "FixedUpdate", new Manipulator(IL_FireCorruptHandBeam_FixedUpdate_ExtraAttacks)); HookManager.Hook(typeof(FireCorruptHandBeam), "FireBullet", (Delegate)new Action<Action<FireCorruptHandBeam>, FireCorruptHandBeam>(On_FireCorruptHandBeam_FireBullet_RemoveEffects)); Utilities.DoAddressable<EntityStateConfiguration>("RoR2/DLC1/VoidSurvivor/EntityStates.VoidSurvivor.Weapon.FireCorruptHandBeam.asset", (Action<EntityStateConfiguration>)delegate(EntityStateConfiguration a) { a.ModifyStateConfig("tickRate", 7.5f); }, release: false); } private static void IL_FireCorruptHandBeam_FixedUpdate_ExtraAttacks(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); float num = default(float); if (val.TryGotoNext(new Func<Instruction, bool>[3] { (Instruction a) => ILPatternMatchingExt.MatchLdarg(a, 0), (Instruction a) => ILPatternMatchingExt.MatchLdfld(a, typeof(FireCorruptHandBeam), "fireCountdown"), (Instruction a) => ILPatternMatchingExt.MatchLdcR4(a, ref num) })) { ILLabel val2 = val.MarkLabel(); if (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchStfld(a, typeof(FireCorruptHandBeam), "fireCountdown") })) { val.Emit(OpCodes.Ldarg_0); val.Emit<FireCorruptHandBeam>(OpCodes.Ldfld, "fireCountdown"); val.Emit(OpCodes.Add); if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction a) => ILPatternMatchingExt.MatchCallOrCallvirt(a, typeof(FireCorruptHandBeam), "FireBullet") })) { val.Emit(OpCodes.Br, (object)val2); return; } } } log.error($"Failed to find IL for IL_FireCorruptHandBeam_FixedUpdate_ExtraAttacks\n{val}"); } private static void On_FireCorruptHandBeam_FireBullet_RemoveEffects(Action<FireCorruptHandBeam> orig, FireCorruptHandBeam self) { if (self.fireCountdown <= 0f) { Main.extraAttacks = 1; orig(self); Main.extraAttacks = 0; } else { orig(self); } } } }