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 ROR O v1.0.4
plugins/ror-o/ROR-O.dll
Decompiled 5 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates.Assassin.Weapon; using EntityStates.BeetleQueenMonster; using EntityStates.Chef; using EntityStates.ClaymanMonster; using EntityStates.Drone.DroneWeapon; using EntityStates.FalseSon; using EntityStates.FalseSonBoss; using EntityStates.FriendUnit; using EntityStates.GolemMonster; using EntityStates.GrandParentBoss; using EntityStates.Huntress; using EntityStates.LemurianBruiserMonster; using EntityStates.Loader; using EntityStates.LunarWisp; using EntityStates.Mage.Weapon; using EntityStates.Merc; using EntityStates.NewtMonster; using EntityStates.Paladin; using EntityStates.Seeker; using EntityStates.SolusAmalgamator; using EntityStates.SolusWing; using EntityStates.Tanker; using EntityStates.Toolbot; using EntityStates.VagrantMonster.Weapon; using HarmonyLib; using KinematicCharacterController; using LookingGlass.ItemStatsNameSpace; using Microsoft.CodeAnalysis; using ROR_O.Utilities; using RoR2; using RoR2.PostProcessing; using RoR2.Projectile; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("LookingGlass")] [assembly: IgnoresAccessChecksTo("RoR2")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ROR-O")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c61dbc246dd63e9ec06aadddf51acfd32e966ec8")] [assembly: AssemblyProduct("ROR-O")] [assembly: AssemblyTitle("ROR-O")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace ROR_O { internal static class ROROConfig { private static ConfigEntry<bool>? enableDamageNumberLoadShedding; private static ConfigEntry<int>? softParticleCap; private static ConfigEntry<int>? hardParticleCap; private static ConfigEntry<int>? absoluteParticleCap; private static ConfigEntry<int>? softSpawnsPerFrame; private static ConfigEntry<int>? hardSpawnsPerFrame; private static ConfigEntry<int>? absoluteSpawnsPerFrame; private static ConfigEntry<float>? softPeakDamageFraction; private static ConfigEntry<float>? hardPeakDamageFraction; private static ConfigEntry<float>? absolutePeakDamageFraction; private static ConfigEntry<float>? softMinimumDamage; private static ConfigEntry<float>? hardMinimumDamage; private static ConfigEntry<float>? absoluteMinimumDamage; private static ConfigEntry<float>? peakDamageHalfLifeSeconds; private static ConfigEntry<bool>? preserveCriticalHits; private static ConfigEntry<bool>? preserveImportantColors; private static ConfigEntry<bool>? enableDynamicBoneInvisibleThrottling; private static ConfigEntry<int>? dynamicBoneInvisibleUpdateInterval; private static ConfigEntry<int>? dynamicBoneRecentlyVisibleGraceFrames; private static ConfigEntry<float>? dynamicBoneVisibleMidDistance; private static ConfigEntry<float>? dynamicBoneVisibleFarDistance; private static ConfigEntry<int>? dynamicBoneVisibleMidUpdateInterval; private static ConfigEntry<int>? dynamicBoneVisibleFarUpdateInterval; private static ConfigEntry<bool>? enableGenericIkInvisibleThrottling; private static ConfigEntry<int>? genericIkInvisibleUpdateInterval; private static ConfigEntry<int>? genericIkRecentlyVisibleGraceFrames; public static bool EnableDamageNumberLoadShedding => enableDamageNumberLoadShedding?.Value ?? true; public static int SoftParticleCap => softParticleCap?.Value ?? 128; public static int HardParticleCap => hardParticleCap?.Value ?? 192; public static int AbsoluteParticleCap => absoluteParticleCap?.Value ?? 256; public static int SoftSpawnsPerFrame => softSpawnsPerFrame?.Value ?? 24; public static int HardSpawnsPerFrame => hardSpawnsPerFrame?.Value ?? 40; public static int AbsoluteSpawnsPerFrame => absoluteSpawnsPerFrame?.Value ?? 56; public static float SoftPeakDamageFraction => softPeakDamageFraction?.Value ?? 0.03f; public static float HardPeakDamageFraction => hardPeakDamageFraction?.Value ?? 0.08f; public static float AbsolutePeakDamageFraction => absolutePeakDamageFraction?.Value ?? 0.16f; public static float SoftMinimumDamage => softMinimumDamage?.Value ?? 1f; public static float HardMinimumDamage => hardMinimumDamage?.Value ?? 2f; public static float AbsoluteMinimumDamage => absoluteMinimumDamage?.Value ?? 4f; public static float PeakDamageHalfLifeSeconds => peakDamageHalfLifeSeconds?.Value ?? 1.5f; public static bool PreserveCriticalHits => preserveCriticalHits?.Value ?? true; public static bool PreserveImportantColors => preserveImportantColors?.Value ?? true; public static bool EnableDynamicBoneInvisibleThrottling => enableDynamicBoneInvisibleThrottling?.Value ?? true; public static int DynamicBoneInvisibleUpdateInterval => dynamicBoneInvisibleUpdateInterval?.Value ?? 3; public static int DynamicBoneRecentlyVisibleGraceFrames => dynamicBoneRecentlyVisibleGraceFrames?.Value ?? 12; public static float DynamicBoneVisibleMidDistance => dynamicBoneVisibleMidDistance?.Value ?? 30f; public static float DynamicBoneVisibleFarDistance => dynamicBoneVisibleFarDistance?.Value ?? 55f; public static int DynamicBoneVisibleMidUpdateInterval => dynamicBoneVisibleMidUpdateInterval?.Value ?? 2; public static int DynamicBoneVisibleFarUpdateInterval => dynamicBoneVisibleFarUpdateInterval?.Value ?? 3; public static bool EnableGenericIkInvisibleThrottling => enableGenericIkInvisibleThrottling?.Value ?? true; public static int GenericIkInvisibleUpdateInterval => genericIkInvisibleUpdateInterval?.Value ?? 2; public static int GenericIkRecentlyVisibleGraceFrames => genericIkRecentlyVisibleGraceFrames?.Value ?? 8; public static void Bind(ConfigFile config) { enableDamageNumberLoadShedding = config.Bind<bool>("Damage Numbers", "Enable Load Shedding", true, "Reduces the number of spawned damage number particles during heavy combat."); softParticleCap = config.Bind<int>("Damage Numbers", "Soft Particle Cap", 128, "Starts lightly sampling regular damage numbers when active particles reach this amount."); hardParticleCap = config.Bind<int>("Damage Numbers", "Hard Particle Cap", 192, "Uses stronger sampling when active particles reach this amount."); absoluteParticleCap = config.Bind<int>("Damage Numbers", "Absolute Particle Cap", 256, "Uses the strongest sampling when active particles reach this amount."); softSpawnsPerFrame = config.Bind<int>("Damage Numbers", "Soft Spawns Per Frame", 24, "Starts lightly sampling regular damage numbers when this many spawns happen in one frame."); hardSpawnsPerFrame = config.Bind<int>("Damage Numbers", "Hard Spawns Per Frame", 40, "Uses stronger sampling when this many spawns happen in one frame."); absoluteSpawnsPerFrame = config.Bind<int>("Damage Numbers", "Absolute Spawns Per Frame", 56, "Uses the strongest sampling when this many spawns happen in one frame."); softPeakDamageFraction = config.Bind<float>("Damage Numbers", "Soft Peak Damage Fraction", 0.03f, "During soft load shedding, regular hits at or above this fraction of the recent peak damage are preserved."); hardPeakDamageFraction = config.Bind<float>("Damage Numbers", "Hard Peak Damage Fraction", 0.08f, "During hard load shedding, regular hits at or above this fraction of the recent peak damage are preserved."); absolutePeakDamageFraction = config.Bind<float>("Damage Numbers", "Absolute Peak Damage Fraction", 0.16f, "During the strongest load shedding, regular hits at or above this fraction of the recent peak damage are preserved."); softMinimumDamage = config.Bind<float>("Damage Numbers", "Soft Minimum Damage", 1f, "During soft load shedding, regular hits at or above this raw damage value are preserved even if recent peak damage is low."); hardMinimumDamage = config.Bind<float>("Damage Numbers", "Hard Minimum Damage", 2f, "During hard load shedding, regular hits at or above this raw damage value are preserved even if recent peak damage is low."); absoluteMinimumDamage = config.Bind<float>("Damage Numbers", "Absolute Minimum Damage", 4f, "During the strongest load shedding, regular hits at or above this raw damage value are preserved even if recent peak damage is low."); peakDamageHalfLifeSeconds = config.Bind<float>("Damage Numbers", "Peak Damage Half Life Seconds", 1.5f, "How quickly the recent peak damage estimate decays back down after large hits stop happening."); preserveCriticalHits = config.Bind<bool>("Damage Numbers", "Preserve Critical Hits", true, "Always allow critical hit damage numbers through the load shedding filter."); preserveImportantColors = config.Bind<bool>("Damage Numbers", "Preserve Important Colors", true, "Always allow important color categories like heal and weak point through the load shedding filter."); enableDynamicBoneInvisibleThrottling = config.Bind<bool>("Dynamic Bones", "Enable Invisible Update Throttling", true, "Throttles DynamicBone LateUpdate calls when the affected renderers are offscreen."); dynamicBoneInvisibleUpdateInterval = config.Bind<int>("Dynamic Bones", "Invisible Update Interval", 3, "When a DynamicBone is offscreen for a while, only let it fully update once every N frames."); dynamicBoneRecentlyVisibleGraceFrames = config.Bind<int>("Dynamic Bones", "Recently Visible Grace Frames", 12, "Keeps DynamicBone updating normally for a short time after it leaves the screen to reduce visible popping."); dynamicBoneVisibleMidDistance = config.Bind<float>("Dynamic Bones", "Visible Mid Distance", 30f, "When a visible DynamicBone rig is at least this far from the camera, it can be updated less often."); dynamicBoneVisibleFarDistance = config.Bind<float>("Dynamic Bones", "Visible Far Distance", 55f, "When a visible DynamicBone rig is at least this far from the camera, it can be updated even less often."); dynamicBoneVisibleMidUpdateInterval = config.Bind<int>("Dynamic Bones", "Visible Mid Update Interval", 2, "When a visible DynamicBone rig is beyond the mid distance, only run a full LateUpdate once every N frames."); dynamicBoneVisibleFarUpdateInterval = config.Bind<int>("Dynamic Bones", "Visible Far Update Interval", 3, "When a visible DynamicBone rig is beyond the far distance, only run a full LateUpdate once every N frames."); enableGenericIkInvisibleThrottling = config.Bind<bool>("Generic IK", "Enable Invisible Update Throttling", true, "Throttles GenericIK LateUpdate calls when the animated character has been offscreen for a short time."); genericIkInvisibleUpdateInterval = config.Bind<int>("Generic IK", "Invisible Update Interval", 2, "When a GenericIK rig is offscreen, only let it run a full LateUpdate once every N frames."); genericIkRecentlyVisibleGraceFrames = config.Bind<int>("Generic IK", "Recently Visible Grace Frames", 8, "Keeps GenericIK updating normally for a short time after it leaves the screen to reduce visible snapping."); } } [BepInPlugin("net.sixik.plugin.roro", "ROR-O", "1.0.4")] public sealed class RORO : BaseUnityPlugin { private const string Modguid = "net.sixik.plugin.roro"; private const string ModName = "ROR-O"; private const string ModVersion = "1.0.4"; public static ManualLogSource? GlobalLogger { get; private set; } private void Awake() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) GlobalLogger = ((BaseUnityPlugin)this).Logger; GlobalLogger.LogInfo((object)"Initialize ROR-O mod: ROR-O v1.0.4"); ROROConfig.Bind(((BaseUnityPlugin)this).Config); new Harmony("net.sixik.plugin.roro").PatchAll(); GlobalLogger.LogInfo((object)"Harmony patches applied successfully!"); } } } namespace ROR_O.Utilities { internal sealed class FixedConditionalWeakTable<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, FixedConditionalWeakTableManager.IShrinkable where TKey : class where TValue : class { private readonly struct WeakReferenceWrapper<T> where T : class { public readonly int TargetHashCode; public readonly WeakReference<T>? WeakReference; public readonly T? Target; public WeakReferenceWrapper(T target, bool strongReference) { TargetHashCode = target.GetHashCode(); if (strongReference) { Target = target; WeakReference = null; } else { Target = null; WeakReference = new WeakReference<T>(target); } } public WeakReferenceWrapper(int targetHashCode) { TargetHashCode = targetHashCode; Target = null; WeakReference = null; } } [StructLayout(LayoutKind.Sequential, Size = 1)] private readonly struct WeakReferenceWrapperComparer<T> : IEqualityComparer<WeakReferenceWrapper<T>> where T : class { public bool Equals(WeakReferenceWrapper<T> first, WeakReferenceWrapper<T> second) { T target = first.Target; T target2 = second.Target; T target3; if (target == null && first.WeakReference == null) { if (second.WeakReference != null) { return !second.WeakReference.TryGetTarget(out target3); } return false; } if (target2 == null && second.WeakReference == null) { if (first.WeakReference != null) { return !first.WeakReference.TryGetTarget(out target3); } return false; } if (target == null && (first.WeakReference == null || !first.WeakReference.TryGetTarget(out target))) { return false; } if (target2 == null && (second.WeakReference == null || !second.WeakReference.TryGetTarget(out target2))) { return false; } return target == target2; } public int GetHashCode(WeakReferenceWrapper<T> obj) { return obj.TargetHashCode; } } private ConstructorInfo? cachedConstructor; private readonly ConcurrentDictionary<WeakReferenceWrapper<TKey>, TValue> valueByKey = new ConcurrentDictionary<WeakReferenceWrapper<TKey>, TValue>(default(WeakReferenceWrapperComparer<TKey>)); public TValue this[TKey key] { get { return valueByKey[new WeakReferenceWrapper<TKey>(key, strongReference: true)]; } set { valueByKey[new WeakReferenceWrapper<TKey>(key, strongReference: false)] = value; } } public ICollection<TKey> Keys { get { List<TKey> list = new List<TKey>(valueByKey.Count); foreach (WeakReferenceWrapper<TKey> key in valueByKey.Keys) { if (key.WeakReference != null && key.WeakReference.TryGetTarget(out var target)) { list.Add(target); } } return list.AsReadOnly(); } } public ICollection<TValue> Values { get { List<TValue> list = new List<TValue>(valueByKey.Count); foreach (KeyValuePair<WeakReferenceWrapper<TKey>, TValue> item in valueByKey) { if (item.Key.WeakReference != null && item.Key.WeakReference.TryGetTarget(out var _)) { list.Add(item.Value); } } return list.AsReadOnly(); } } public int Count { get { int num = 0; foreach (WeakReferenceWrapper<TKey> key in valueByKey.Keys) { if (key.WeakReference != null && key.WeakReference.TryGetTarget(out var _)) { num++; } } return num; } } public int SpeculativeCount => valueByKey.Count; bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false; IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys; IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values; public FixedConditionalWeakTable() { FixedConditionalWeakTableManager.Add(this); } public void Add(TKey key, TValue value) { if (key == null) { throw new ArgumentNullException("key"); } if (!valueByKey.TryAdd(new WeakReferenceWrapper<TKey>(key, strongReference: false), value)) { throw new ArgumentException("The key already exists", "key"); } } public bool Remove(TKey key) { TValue value; return valueByKey.TryRemove(new WeakReferenceWrapper<TKey>(key, strongReference: true), out value); } public bool TryGetValue(TKey key, out TValue value) { return valueByKey.TryGetValue(new WeakReferenceWrapper<TKey>(key, strongReference: true), out value); } public TValue GetValue(TKey key, Func<TKey, TValue> defaultFunc) { if (TryGetValue(key, out var value)) { return value; } value = defaultFunc(key); Add(key, value); return value; } public TValue GetOrCreateValue(TKey key) { if (TryGetValue(key, out var value)) { return value; } if (cachedConstructor == null) { Type typeFromHandle = typeof(TValue); cachedConstructor = typeFromHandle.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (cachedConstructor == null) { throw new MissingMethodException(typeFromHandle.FullName + " doesn't have a parameterless constructor"); } } value = (TValue)cachedConstructor.Invoke(Array.Empty<object>()); Add(key, value); return value; } void FixedConditionalWeakTableManager.IShrinkable.Shrink() { foreach (KeyValuePair<WeakReferenceWrapper<TKey>, TValue> item in valueByKey) { if (item.Key.WeakReference != null && !item.Key.WeakReference.TryGetTarget(out var _)) { valueByKey.TryRemove(new WeakReferenceWrapper<TKey>(item.Key.TargetHashCode), out var _); } } } public bool ContainsKey(TKey key) { return valueByKey.ContainsKey(new WeakReferenceWrapper<TKey>(key, strongReference: true)); } public void Clear() { valueByKey.Clear(); } void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) { Add(item.Key, item.Value); } bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) { if (TryGetValue(item.Key, out var value)) { return EqualityComparer<TValue>.Default.Equals(value, item.Value); } return false; } void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0 || arrayIndex >= array.Length) { throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is not a valid index in array"); } int count = Count; if (arrayIndex + count > array.Length) { throw new ArgumentOutOfRangeException("array", "Destination array is not long enough to copy all the items in the collection."); } foreach (KeyValuePair<WeakReferenceWrapper<TKey>, TValue> item in valueByKey) { if (item.Key.WeakReference != null && item.Key.WeakReference.TryGetTarget(out var target)) { array[arrayIndex++] = new KeyValuePair<TKey, TValue>(target, item.Value); } } } bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) { if (TryGetValue(item.Key, out var value) && EqualityComparer<TValue>.Default.Equals(value, item.Value)) { return Remove(item.Key); } return false; } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { foreach (KeyValuePair<WeakReferenceWrapper<TKey>, TValue> item in valueByKey) { if (item.Key.WeakReference != null && item.Key.WeakReference.TryGetTarget(out var target)) { yield return new KeyValuePair<TKey, TValue>(target, item.Value); } } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal static class FixedConditionalWeakTableManager { internal interface IShrinkable { void Shrink(); } private const int ShrinkAttemptDelayMilliseconds = 2000; private static readonly object LockObject = new object(); private static readonly List<WeakReference<IShrinkable>> Instances = new List<WeakReference<IShrinkable>>(); private static int lastCollectionCount; public static void Add(IShrinkable weakTable) { lock (LockObject) { if (Instances.Count == 0) { Thread thread = new Thread(ShrinkThreadLoop); thread.IsBackground = true; thread.Name = "ROR-O FixedConditionalWeakTable Shrinker"; thread.Start(); } Instances.Add(new WeakReference<IShrinkable>(weakTable)); } } private static void ShrinkThreadLoop() { while (true) { Thread.Sleep(2000); int num = GC.CollectionCount(2); if (lastCollectionCount == num) { continue; } lastCollectionCount = num; lock (LockObject) { for (int num2 = Instances.Count - 1; num2 >= 0; num2--) { if (!Instances[num2].TryGetTarget(out IShrinkable target)) { Instances.RemoveAt(num2); } else { target.Shrink(); } } if (Instances.Count == 0) { break; } } } } } } namespace ROR_O.patches { [HarmonyPatch(typeof(Glaze), "FixedUpdate")] public class OptimizeChefGlazePatch { private static readonly MethodInfo GetFastMuzzleMethod = AccessTools.Method(typeof(OptimizeChefGlazePatch), "GetFastMuzzle", (Type[])null, (Type[])null); private static readonly string[] CachedMuzzles = new string[6] { "MuzzleGlaze0", "MuzzleGlaze1", "MuzzleGlaze2", "MuzzleGlaze3", "MuzzleGlaze4", "MuzzleGlaze5" }; public static string GetFastMuzzle(Glaze instance) { int muzzleStringEndNum = instance.muzzleStringEndNum; if (muzzleStringEndNum >= 0 && muzzleStringEndNum < CachedMuzzles.Length) { return CachedMuzzles[muzzleStringEndNum]; } return "MuzzleGlaze" + muzzleStringEndNum; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); MethodInfo objB = AccessTools.Method(typeof(string), "Concat", new Type[2] { typeof(string), typeof(string) }, (Type[])null); int num = -1; for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldstr && object.Equals(list[i].operand, "MuzzleGlaze")) { num = i; break; } } if (num >= 0) { int num2 = -1; for (int j = num; j < list.Count; j++) { if (list[j].opcode == OpCodes.Call && object.Equals(list[j].operand, objB)) { num2 = j; break; } } if (num2 >= num) { list.RemoveRange(num, num2 - num + 1); list.Insert(num, new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Insert(num + 1, new CodeInstruction(OpCodes.Call, (object)GetFastMuzzleMethod)); } } return list; } } [HarmonyPatch(typeof(TitanRockController), "FixedUpdate")] public static class OptimizeTitanRockControllerPatch { private static readonly MethodInfo ComponentGetParticleSystemsInChildrenMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentsInChildrenMethod(typeof(ParticleSystem)); private static readonly MethodInfo ComponentGetLightsInChildrenMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentsInChildrenMethod(typeof(Light)); private static readonly MethodInfo ComponentGetParticleSystemMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(ParticleSystem)); private static readonly MethodInfo TransformFindMethod = AccessTools.Method(typeof(Transform), "Find", new Type[1] { typeof(string) }, (Type[])null); private static readonly MethodInfo CachedParticleSystemsInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetParticleSystemsInChildren", new Type[1] { typeof(Component) }, (Type[])null); private static readonly MethodInfo CachedLightsInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetLightsInChildren", (Type[])null, (Type[])null); private static readonly MethodInfo CachedParticleSystemMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetParticleSystem", (Type[])null, (Type[])null); private static readonly MethodInfo CachedTransformFindMethod = AccessTools.Method(typeof(OptimizedComponentCache), "FindTransform", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetParticleSystemsInChildrenMethod, CachedParticleSystemsInChildrenMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetLightsInChildrenMethod, CachedLightsInChildrenMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetParticleSystemMethod, CachedParticleSystemMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, TransformFindMethod, CachedTransformFindMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"TitanRockController.FixedUpdate optimized: cached hierarchy calls={replacements}"); } } } [HarmonyPatch(typeof(TalismanAnimator), "FixedUpdate")] public static class OptimizeTalismanAnimatorPatch { private static readonly MethodInfo GameObjectGetParticleSystemsInChildrenMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentsInChildrenMethod(typeof(ParticleSystem)); private static readonly MethodInfo CachedParticleSystemsInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetParticleSystemsInChildren", new Type[1] { typeof(GameObject) }, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetParticleSystemsInChildrenMethod, CachedParticleSystemsInChildrenMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"TalismanAnimator.FixedUpdate optimized: cached hierarchy calls={replacements}"); } } } [HarmonyPatch(typeof(GravCubeController), "Update")] public static class OptimizeGravCubeControllerPatch { private static readonly MethodInfo GameObjectGetAnimatorInChildrenMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentInChildrenMethod(typeof(Animator)); private static readonly MethodInfo CachedAnimatorInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetAnimatorInChildren", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetAnimatorInChildrenMethod, CachedAnimatorInChildrenMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"GravCubeController.Update optimized: cached hierarchy calls={replacements}"); } } } [HarmonyPatch(typeof(JellyBarrage), "FixedUpdate")] public static class OptimizeJellyBarragePatch { private static readonly MethodInfo ChildLocatorFindChildMethod = AccessTools.Method(typeof(ChildLocator), "FindChild", new Type[1] { typeof(string) }, (Type[])null); private static readonly MethodInfo CachedChildLocatorFindMethod = AccessTools.Method(typeof(OptimizedComponentCache), "FindChild", new Type[2] { typeof(ChildLocator), typeof(string) }, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ChildLocatorFindChildMethod, CachedChildLocatorFindMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"JellyBarrage.FixedUpdate optimized: cached hierarchy calls={replacements}"); } } } [HarmonyPatch(typeof(JellyStorm), "FixedUpdate")] public static class OptimizeJellyStormPatch { private static readonly MethodInfo ChildLocatorFindChildMethod = AccessTools.Method(typeof(ChildLocator), "FindChild", new Type[1] { typeof(string) }, (Type[])null); private static readonly MethodInfo CachedChildLocatorFindMethod = AccessTools.Method(typeof(OptimizedComponentCache), "FindChild", new Type[2] { typeof(ChildLocator), typeof(string) }, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ChildLocatorFindChildMethod, CachedChildLocatorFindMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"JellyStorm.FixedUpdate optimized: cached hierarchy calls={replacements}"); } } } [HarmonyPatch(typeof(SwipeForward), "FixedUpdate")] public static class OptimizeSwipeForwardPatch { private static readonly MethodInfo ComponentGetCharacterDirectionMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterDirection)); private static readonly MethodInfo CachedCharacterDirectionMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterDirectionFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterDirectionMethod, CachedCharacterDirectionMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"SwipeForward.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(GroundLight), "FixedUpdate")] public static class OptimizeGroundLightPatch { private static readonly MethodInfo ComponentGetCharacterDirectionMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterDirection)); private static readonly MethodInfo CachedCharacterDirectionMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterDirectionFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterDirectionMethod, CachedCharacterDirectionMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"GroundLight.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(SlashCombo), "FixedUpdate")] public static class OptimizeSlashComboPatch { private static readonly MethodInfo ComponentGetCharacterDirectionMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterDirection)); private static readonly MethodInfo CachedCharacterDirectionMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterDirectionFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterDirectionMethod, CachedCharacterDirectionMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"SlashCombo.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(Assaulter), "FixedUpdate")] public static class OptimizeAssaulterPatch { private static readonly MethodInfo ComponentGetCharacterModelMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterModel)); private static readonly MethodInfo CachedCharacterModelMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterModelFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterModelMethod, CachedCharacterModelMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"Assaulter.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(Evis), "FixedUpdate")] public static class OptimizeEvisPatch { private static readonly MethodInfo ComponentGetCharacterModelMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterModel)); private static readonly MethodInfo CachedCharacterModelMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterModelFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterModelMethod, CachedCharacterModelMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"Evis.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(EvisDash), "FixedUpdate")] public static class OptimizeEvisDashPatch { private static readonly MethodInfo ComponentGetCharacterModelMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterModel)); private static readonly MethodInfo ComponentGetHurtBoxMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(HurtBox)); private static readonly MethodInfo CachedCharacterModelMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterModelFromComponent", (Type[])null, (Type[])null); private static readonly MethodInfo CachedHurtBoxMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHurtBoxFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterModelMethod, CachedCharacterModelMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetHurtBoxMethod, CachedHurtBoxMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"EvisDash.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(KickFromShop), "FixedUpdate")] public static class OptimizeKickFromShopPatch { private static readonly MethodInfo ComponentGetHurtBoxGroupMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(HurtBoxGroup)); private static readonly MethodInfo CachedHurtBoxGroupMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHurtBoxGroupFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetHurtBoxGroupMethod, CachedHurtBoxGroupMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"KickFromShop.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(DashSlam), "FixedUpdate")] public static class OptimizeDashSlamPatch { private static readonly MethodInfo ComponentGetHurtBoxMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(HurtBox)); private static readonly MethodInfo CachedHurtBoxMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHurtBoxFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetHurtBoxMethod, CachedHurtBoxMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"DashSlam.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(ClapState), "FixedUpdate")] public static class OptimizeClapStatePatch { private static readonly MethodInfo ComponentGetChildLocatorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(ChildLocator)); private static readonly MethodInfo CachedChildLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetChildLocatorFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetChildLocatorMethod, CachedChildLocatorMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"ClapState.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(LaserFather), "FixedUpdate")] public static class OptimizeLaserFatherPatch { private static readonly MethodInfo ComponentGetChildLocatorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(ChildLocator)); private static readonly MethodInfo CachedChildLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetChildLocatorFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetChildLocatorMethod, CachedChildLocatorMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"LaserFather.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } internal enum DamageNumberLoadLevel { None, Soft, Hard, Absolute } internal static class DamageNumberLoadShedState { private static readonly FieldRef<DamageNumberManager, ParticleSystem> ParticleSystemField = AccessTools.FieldRefAccess<DamageNumberManager, ParticleSystem>("ps"); private static int lastFrame = -1; private static int spawnsThisFrame; private static uint noisySpawnSequence; private static float recentPeakDamage = 1f; private static float lastPeakUpdateTime; public static bool ShouldAllowSpawn(DamageNumberManager? manager, float damage, bool crit, DamageColorIndex damageColorIndex) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!ROROConfig.EnableDamageNumberLoadShedding) { return true; } int frameCount = Time.frameCount; if (frameCount != lastFrame) { lastFrame = frameCount; spawnsThisFrame = 0; } int activeDamageNumberCount = GetActiveDamageNumberCount(manager); bool flag = IsCriticalColor(damageColorIndex); UpdateRecentPeakDamage(damage); int orderedThreshold = GetOrderedThreshold(ROROConfig.SoftParticleCap, 1); int orderedThreshold2 = GetOrderedThreshold(ROROConfig.HardParticleCap, orderedThreshold); int orderedThreshold3 = GetOrderedThreshold(ROROConfig.AbsoluteParticleCap, orderedThreshold2); int orderedThreshold4 = GetOrderedThreshold(ROROConfig.SoftSpawnsPerFrame, 1); int orderedThreshold5 = GetOrderedThreshold(ROROConfig.HardSpawnsPerFrame, orderedThreshold4); DamageNumberLoadLevel damageNumberLoadLevel = GetLoadLevel(absoluteSpawnsPerFrame: GetOrderedThreshold(ROROConfig.AbsoluteSpawnsPerFrame, orderedThreshold5), activeDamageNumbers: activeDamageNumberCount, currentSpawnsPerFrame: spawnsThisFrame, softParticleCap: orderedThreshold, hardParticleCap: orderedThreshold2, absoluteParticleCap: orderedThreshold3, softSpawnsPerFrame: orderedThreshold4, hardSpawnsPerFrame: orderedThreshold5); if (damageNumberLoadLevel == DamageNumberLoadLevel.None) { spawnsThisFrame++; return true; } if (flag || crit || IsHighPriorityDamage(damage, damageNumberLoadLevel)) { spawnsThisFrame++; return true; } switch (damageNumberLoadLevel) { case DamageNumberLoadLevel.Absolute: if (!ShouldSample(crit, flag, 3, 8)) { return false; } break; case DamageNumberLoadLevel.Hard: if (!ShouldSample(crit, flag, 2, 4)) { return false; } break; default: if (!ShouldSample(crit, flag, 1, 2)) { return false; } break; } spawnsThisFrame++; return true; } private static int GetActiveDamageNumberCount(DamageNumberManager? manager) { if ((Object)(object)manager == (Object)null) { return 0; } ParticleSystem val = ParticleSystemField.Invoke(manager); if ((Object)(object)val == (Object)null) { return 0; } return val.particleCount; } private static void UpdateRecentPeakDamage(float damage) { float unscaledTime = Time.unscaledTime; float num = recentPeakDamage; float num2 = unscaledTime - lastPeakUpdateTime; lastPeakUpdateTime = unscaledTime; float num3 = Mathf.Max(0.05f, ROROConfig.PeakDamageHalfLifeSeconds); if (num2 > 0f) { float num4 = Mathf.Pow(0.5f, num2 / num3); num = Mathf.Max(1f, num * num4); } if (damage > num) { num = damage; } recentPeakDamage = Mathf.Max(1f, num); } private static DamageNumberLoadLevel GetLoadLevel(int activeDamageNumbers, int currentSpawnsPerFrame, int softParticleCap, int hardParticleCap, int absoluteParticleCap, int softSpawnsPerFrame, int hardSpawnsPerFrame, int absoluteSpawnsPerFrame) { if (activeDamageNumbers >= absoluteParticleCap || currentSpawnsPerFrame >= absoluteSpawnsPerFrame) { return DamageNumberLoadLevel.Absolute; } if (activeDamageNumbers >= hardParticleCap || currentSpawnsPerFrame >= hardSpawnsPerFrame) { return DamageNumberLoadLevel.Hard; } if (activeDamageNumbers >= softParticleCap || currentSpawnsPerFrame >= softSpawnsPerFrame) { return DamageNumberLoadLevel.Soft; } return DamageNumberLoadLevel.None; } private static int GetOrderedThreshold(int configuredValue, int minimumValue) { if (configuredValue >= minimumValue) { return configuredValue; } return minimumValue; } private static bool IsHighPriorityDamage(float damage, DamageNumberLoadLevel loadLevel) { float orderedFraction; float orderedFloat; switch (loadLevel) { case DamageNumberLoadLevel.Absolute: orderedFraction = GetOrderedFraction(ROROConfig.AbsolutePeakDamageFraction, ROROConfig.HardPeakDamageFraction); orderedFloat = GetOrderedFloat(ROROConfig.AbsoluteMinimumDamage, ROROConfig.HardMinimumDamage); break; case DamageNumberLoadLevel.Hard: orderedFraction = GetOrderedFraction(ROROConfig.HardPeakDamageFraction, ROROConfig.SoftPeakDamageFraction); orderedFloat = GetOrderedFloat(ROROConfig.HardMinimumDamage, ROROConfig.SoftMinimumDamage); break; default: orderedFraction = GetOrderedFraction(ROROConfig.SoftPeakDamageFraction, 0f); orderedFloat = GetOrderedFloat(ROROConfig.SoftMinimumDamage, 0f); break; } float num = recentPeakDamage * orderedFraction; float num2 = Mathf.Max(orderedFloat, num); return damage >= num2; } private static float GetOrderedFraction(float configuredValue, float minimumValue) { return Mathf.Clamp((configuredValue < minimumValue) ? minimumValue : configuredValue, 0f, 1f); } private static float GetOrderedFloat(float configuredValue, float minimumValue) { if (!(configuredValue < minimumValue)) { return configuredValue; } return minimumValue; } private static bool ShouldSample(bool crit, bool criticalColor, int critDivisor, int noisyDivisor) { if (criticalColor) { return true; } int num = (crit ? critDivisor : noisyDivisor); if (num <= 1) { return true; } noisySpawnSequence++; return noisySpawnSequence % (uint)num == 0; } private static bool IsCriticalColor(DamageColorIndex damageColorIndex) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: 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_0011: Invalid comparison between Unknown and I4 //IL_0013: 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_0018: Invalid comparison between Unknown and I4 if (!ROROConfig.PreserveImportantColors) { return false; } if ((int)damageColorIndex == 1 || damageColorIndex - 5 <= 1 || damageColorIndex - 12 <= 2) { return true; } return false; } } [HarmonyPatch(typeof(DamageNumberManager), "SpawnDamageNumber")] public static class OptimizeDamageNumberManagerSpawnPatch { [HarmonyPrefix] private static bool Prefix(DamageNumberManager __instance, float amount, bool crit, DamageColorIndex damageColorIndex) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) bool crit2 = ROROConfig.PreserveCriticalHits && crit; return DamageNumberLoadShedState.ShouldAllowSpawn(__instance, amount, crit2, damageColorIndex); } } internal static class OptimizedComponentCache { private sealed class CacheBox<T> where T : class { public T? Value; } private sealed class NamedTransformCache { public readonly Dictionary<string, Transform?> Values = new Dictionary<string, Transform>(); } private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterBody>> CharacterBodies = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterBody>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterMaster>> CharacterMasters = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterMaster>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<EquipmentSlot>> EquipmentSlots = new FixedConditionalWeakTable<GameObject, CacheBox<EquipmentSlot>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<HealthComponent>> HealthComponents = new FixedConditionalWeakTable<GameObject, CacheBox<HealthComponent>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<HuntressTracker>> HuntressTrackers = new FixedConditionalWeakTable<GameObject, CacheBox<HuntressTracker>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<DamageTrail>> DamageTrails = new FixedConditionalWeakTable<GameObject, CacheBox<DamageTrail>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Rigidbody>> Rigidbodies = new FixedConditionalWeakTable<GameObject, CacheBox<Rigidbody>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Rigidbody2D>> Rigidbodies2D = new FixedConditionalWeakTable<GameObject, CacheBox<Rigidbody2D>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<IInspectable>> Inspectables = new FixedConditionalWeakTable<GameObject, CacheBox<IInspectable>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<IInteractable>> Interactables = new FixedConditionalWeakTable<GameObject, CacheBox<IInteractable>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<InteractionDriver>> InteractionDrivers = new FixedConditionalWeakTable<GameObject, CacheBox<InteractionDriver>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<InputBankTest>> InputBankTests = new FixedConditionalWeakTable<GameObject, CacheBox<InputBankTest>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CameraTargetParams>> CameraTargetParamsCache = new FixedConditionalWeakTable<GameObject, CacheBox<CameraTargetParams>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ChefController>> ChefControllers = new FixedConditionalWeakTable<GameObject, CacheBox<ChefController>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterMotor>> CharacterMotors = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterMotor>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<RigidbodyMotor>> RigidbodyMotors = new FixedConditionalWeakTable<GameObject, CacheBox<RigidbodyMotor>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<KinematicCharacterMotor>> KinematicCharacterMotors = new FixedConditionalWeakTable<GameObject, CacheBox<KinematicCharacterMotor>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<NetworkIdentity>> NetworkIdentities = new FixedConditionalWeakTable<GameObject, CacheBox<NetworkIdentity>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<NetworkUser>> NetworkUsers = new FixedConditionalWeakTable<GameObject, CacheBox<NetworkUser>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<FalseSonBossController>> FalseSonBossControllers = new FixedConditionalWeakTable<GameObject, CacheBox<FalseSonBossController>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<OilGhostController>> OilGhostControllers = new FixedConditionalWeakTable<GameObject, CacheBox<OilGhostController>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<PlayerCharacterMasterController>> PlayerCharacterMasterControllers = new FixedConditionalWeakTable<GameObject, CacheBox<PlayerCharacterMasterController>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<SkillLocator>> SkillLocators = new FixedConditionalWeakTable<GameObject, CacheBox<SkillLocator>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<TeamFilter>> TeamFilters = new FixedConditionalWeakTable<GameObject, CacheBox<TeamFilter>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ProjectileController>> ProjectileControllers = new FixedConditionalWeakTable<GameObject, CacheBox<ProjectileController>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ProjectileDamage>> ProjectileDamages = new FixedConditionalWeakTable<GameObject, CacheBox<ProjectileDamage>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ChildLocator>> ChildLocators = new FixedConditionalWeakTable<GameObject, CacheBox<ChildLocator>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ScaleParticleSystemDuration>> ScaleParticleSystemDurations = new FixedConditionalWeakTable<GameObject, CacheBox<ScaleParticleSystemDuration>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ObjectScaleCurve>> ObjectScaleCurves = new FixedConditionalWeakTable<GameObject, CacheBox<ObjectScaleCurve>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterDirection>> CharacterDirections = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterDirection>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterModel>> CharacterModels = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterModel>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<HurtBoxGroup>> HurtBoxGroups = new FixedConditionalWeakTable<GameObject, CacheBox<HurtBoxGroup>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<HurtBox>> HurtBoxes = new FixedConditionalWeakTable<GameObject, CacheBox<HurtBox>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Animator>> AnimatorsInChildren = new FixedConditionalWeakTable<GameObject, CacheBox<Animator>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ParticleSystem>> ParticleSystems = new FixedConditionalWeakTable<GameObject, CacheBox<ParticleSystem>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ParticleSystem[]>> ParticleSystemsInChildren = new FixedConditionalWeakTable<GameObject, CacheBox<ParticleSystem[]>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Light[]>> LightsInChildren = new FixedConditionalWeakTable<GameObject, CacheBox<Light[]>>(); private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Renderer[]>> RenderersInChildren = new FixedConditionalWeakTable<GameObject, CacheBox<Renderer[]>>(); private static readonly FixedConditionalWeakTable<Transform, NamedTransformCache> TransformFindCache = new FixedConditionalWeakTable<Transform, NamedTransformCache>(); private static readonly FixedConditionalWeakTable<ChildLocator, NamedTransformCache> ChildLocatorFindCache = new FixedConditionalWeakTable<ChildLocator, NamedTransformCache>(); public static CharacterBody? GetCharacterBody(GameObject gameObject) { return GetOrAdd(gameObject, CharacterBodies, (GameObject target) => target.GetComponent<CharacterBody>()); } public static CharacterBody? GetCharacterBodyFromComponent(Component component) { return GetOrAdd(component, CharacterBodies, (GameObject target) => target.GetComponent<CharacterBody>()); } public static CharacterMaster? GetCharacterMaster(GameObject gameObject) { return GetOrAdd(gameObject, CharacterMasters, (GameObject target) => target.GetComponent<CharacterMaster>()); } public static EquipmentSlot? GetEquipmentSlot(GameObject gameObject) { return GetOrAdd(gameObject, EquipmentSlots, (GameObject target) => target.GetComponent<EquipmentSlot>()); } public static HealthComponent? GetHealthComponent(GameObject gameObject) { return GetOrAdd(gameObject, HealthComponents, (GameObject target) => target.GetComponent<HealthComponent>()); } public static HealthComponent? GetHealthComponentFromComponent(Component component) { return GetOrAdd(component, HealthComponents, (GameObject target) => target.GetComponent<HealthComponent>()); } public static HuntressTracker? GetHuntressTracker(GameObject gameObject) { return GetOrAdd(gameObject, HuntressTrackers, (GameObject target) => target.GetComponent<HuntressTracker>()); } public static DamageTrail? GetDamageTrail(GameObject gameObject) { return GetOrAdd(gameObject, DamageTrails, (GameObject target) => target.GetComponent<DamageTrail>()); } public static Rigidbody? GetRigidbody(GameObject gameObject) { return GetOrAdd(gameObject, Rigidbodies, (GameObject target) => target.GetComponent<Rigidbody>()); } public static Rigidbody? GetRigidbodyFromComponent(Component component) { return GetOrAdd(component, Rigidbodies, (GameObject target) => target.GetComponent<Rigidbody>()); } public static Rigidbody2D? GetRigidbody2D(GameObject gameObject) { return GetOrAdd(gameObject, Rigidbodies2D, (GameObject target) => target.GetComponent<Rigidbody2D>()); } public static IInspectable? GetInspectable(GameObject gameObject) { return GetOrAdd(gameObject, Inspectables, (GameObject target) => target.GetComponent<IInspectable>()); } public static IInteractable? GetInteractable(GameObject gameObject) { return GetOrAdd(gameObject, Interactables, (GameObject target) => target.GetComponent<IInteractable>()); } public static InteractionDriver? GetInteractionDriver(GameObject gameObject) { return GetOrAdd(gameObject, InteractionDrivers, (GameObject target) => target.GetComponent<InteractionDriver>()); } public static InteractionDriver? GetInteractionDriverFromComponent(Component component) { return GetOrAdd(component, InteractionDrivers, (GameObject target) => target.GetComponent<InteractionDriver>()); } public static InputBankTest? GetInputBankTest(GameObject gameObject) { return GetOrAdd(gameObject, InputBankTests, (GameObject target) => target.GetComponent<InputBankTest>()); } public static CameraTargetParams? GetCameraTargetParamsFromComponent(Component component) { return GetOrAdd(component, CameraTargetParamsCache, (GameObject target) => target.GetComponent<CameraTargetParams>()); } public static ChefController? GetChefController(GameObject gameObject) { return GetOrAdd(gameObject, ChefControllers, (GameObject target) => target.GetComponent<ChefController>()); } public static CharacterMotor? GetCharacterMotor(GameObject gameObject) { return GetOrAdd(gameObject, CharacterMotors, (GameObject target) => target.GetComponent<CharacterMotor>()); } public static CharacterMotor? GetCharacterMotor(Component component) { return GetOrAdd(component, CharacterMotors, (GameObject target) => target.GetComponent<CharacterMotor>()); } public static RigidbodyMotor? GetRigidbodyMotor(Component component) { return GetOrAdd(component, RigidbodyMotors, (GameObject target) => target.GetComponent<RigidbodyMotor>()); } public static KinematicCharacterMotor? GetKinematicCharacterMotor(Component component) { return GetOrAdd(component, KinematicCharacterMotors, (GameObject target) => target.GetComponent<KinematicCharacterMotor>()); } public static NetworkIdentity? GetNetworkIdentity(Component component) { return GetOrAdd(component, NetworkIdentities, (GameObject target) => target.GetComponent<NetworkIdentity>()); } public static NetworkUser? GetNetworkUser(GameObject gameObject) { return GetOrAdd(gameObject, NetworkUsers, (GameObject target) => target.GetComponent<NetworkUser>()); } public static FalseSonBossController? GetFalseSonBossControllerFromComponent(Component component) { return GetOrAdd(component, FalseSonBossControllers, (GameObject target) => target.GetComponent<FalseSonBossController>()); } public static OilGhostController? GetOilGhostController(GameObject gameObject) { return GetOrAdd(gameObject, OilGhostControllers, (GameObject target) => target.GetComponent<OilGhostController>()); } public static PlayerCharacterMasterController? GetPlayerCharacterMasterController(Component component) { return GetOrAdd(component, PlayerCharacterMasterControllers, (GameObject target) => target.GetComponent<PlayerCharacterMasterController>()); } public static SkillLocator? GetSkillLocator(GameObject gameObject) { return GetOrAdd(gameObject, SkillLocators, (GameObject target) => target.GetComponent<SkillLocator>()); } public static SkillLocator? GetSkillLocatorFromComponent(Component component) { return GetOrAdd(component, SkillLocators, (GameObject target) => target.GetComponent<SkillLocator>()); } public static TeamFilter? GetTeamFilter(GameObject gameObject) { return GetOrAdd(gameObject, TeamFilters, (GameObject target) => target.GetComponent<TeamFilter>()); } public static ProjectileController? GetProjectileController(GameObject gameObject) { return GetOrAdd(gameObject, ProjectileControllers, (GameObject target) => target.GetComponent<ProjectileController>()); } public static ProjectileDamage? GetProjectileDamage(GameObject gameObject) { return GetOrAdd(gameObject, ProjectileDamages, (GameObject target) => target.GetComponent<ProjectileDamage>()); } public static ChildLocator? GetChildLocatorFromComponent(Component component) { return GetOrAdd(component, ChildLocators, (GameObject target) => target.GetComponent<ChildLocator>()); } public static ChildLocator? GetChildLocator(GameObject gameObject) { return GetOrAdd(gameObject, ChildLocators, (GameObject target) => target.GetComponent<ChildLocator>()); } public static ScaleParticleSystemDuration? GetScaleParticleSystemDuration(GameObject gameObject) { return GetOrAdd(gameObject, ScaleParticleSystemDurations, (GameObject target) => target.GetComponent<ScaleParticleSystemDuration>()); } public static ScaleParticleSystemDuration? GetScaleParticleSystemDurationFromComponent(Component component) { return GetOrAdd(component, ScaleParticleSystemDurations, (GameObject target) => target.GetComponent<ScaleParticleSystemDuration>()); } public static ObjectScaleCurve? GetObjectScaleCurve(GameObject gameObject) { return GetOrAdd(gameObject, ObjectScaleCurves, (GameObject target) => target.GetComponent<ObjectScaleCurve>()); } public static CharacterDirection? GetCharacterDirectionFromComponent(Component component) { return GetOrAdd(component, CharacterDirections, (GameObject target) => target.GetComponent<CharacterDirection>()); } public static CharacterModel? GetCharacterModelFromComponent(Component component) { return GetOrAdd(component, CharacterModels, (GameObject target) => target.GetComponent<CharacterModel>()); } public static HurtBoxGroup? GetHurtBoxGroupFromComponent(Component component) { return GetOrAdd(component, HurtBoxGroups, (GameObject target) => target.GetComponent<HurtBoxGroup>()); } public static HurtBox? GetHurtBoxFromComponent(Component component) { return GetOrAdd(component, HurtBoxes, (GameObject target) => target.GetComponent<HurtBox>()); } public static Animator? GetAnimatorInChildren(GameObject gameObject) { return GetOrAdd(gameObject, AnimatorsInChildren, (GameObject target) => target.GetComponentInChildren<Animator>()); } public static ParticleSystem? GetParticleSystem(Component component) { return GetOrAdd(component, ParticleSystems, (GameObject target) => target.GetComponent<ParticleSystem>()); } public static ParticleSystem[]? GetParticleSystemsInChildren(Component component) { return GetOrAddArray<ParticleSystem>(component, ParticleSystemsInChildren, (Func<GameObject, ParticleSystem[]?>)((GameObject target) => target.GetComponentsInChildren<ParticleSystem>())); } public static ParticleSystem[]? GetParticleSystemsInChildren(GameObject gameObject) { return GetOrAddArray<ParticleSystem>(gameObject, ParticleSystemsInChildren, (Func<GameObject, ParticleSystem[]?>)((GameObject target) => target.GetComponentsInChildren<ParticleSystem>())); } public static Light[]? GetLightsInChildren(Component component) { return GetOrAddArray<Light>(component, LightsInChildren, (Func<GameObject, Light[]?>)((GameObject target) => target.GetComponentsInChildren<Light>())); } public static Renderer[]? GetRenderersInChildren(Component component) { return GetOrAddArray<Renderer>(component, RenderersInChildren, (Func<GameObject, Renderer[]?>)((GameObject target) => target.GetComponentsInChildren<Renderer>())); } public static Renderer[]? GetRenderersInChildren(GameObject gameObject) { return GetOrAddArray<Renderer>(gameObject, RenderersInChildren, (Func<GameObject, Renderer[]?>)((GameObject target) => target.GetComponentsInChildren<Renderer>())); } public static Transform? FindTransform(Transform transform, string childName) { string childName2 = childName; return GetOrFindTransform(transform, childName2, (Transform target) => target.Find(childName2), TransformFindCache); } public static Transform? FindChild(ChildLocator childLocator, string childName) { string childName2 = childName; return GetOrFindTransform(childLocator, childName2, (ChildLocator target) => target.FindChild(childName2), ChildLocatorFindCache); } private static T? GetOrAdd<T>(Component component, FixedConditionalWeakTable<GameObject, CacheBox<T>> cache, Func<GameObject, T?> factory) where T : class { if (!Object.op_Implicit((Object)(object)component)) { return null; } return GetOrAdd(component.gameObject, cache, factory); } private static T? GetOrAdd<T>(GameObject gameObject, FixedConditionalWeakTable<GameObject, CacheBox<T>> cache, Func<GameObject, T?> factory) where T : class { if (!Object.op_Implicit((Object)(object)gameObject)) { return null; } CacheBox<T> orCreateValue = cache.GetOrCreateValue(gameObject); if (IsMissing(orCreateValue.Value)) { orCreateValue.Value = factory(gameObject); } return orCreateValue.Value; } private static T[]? GetOrAddArray<T>(Component component, FixedConditionalWeakTable<GameObject, CacheBox<T[]>> cache, Func<GameObject, T[]?> factory) where T : Object { if (!Object.op_Implicit((Object)(object)component)) { return null; } return GetOrAddArray(component.gameObject, cache, factory); } private static T[]? GetOrAddArray<T>(GameObject gameObject, FixedConditionalWeakTable<GameObject, CacheBox<T[]>> cache, Func<GameObject, T[]?> factory) where T : Object { if (!Object.op_Implicit((Object)(object)gameObject)) { return null; } CacheBox<T[]> orCreateValue = cache.GetOrCreateValue(gameObject); if (IsMissingArray(orCreateValue.Value)) { orCreateValue.Value = factory(gameObject); } return orCreateValue.Value; } private static Transform? GetOrFindTransform<TSource>(TSource source, string childName, Func<TSource, Transform?> finder, FixedConditionalWeakTable<TSource, NamedTransformCache> cache) where TSource : class { if (source == null) { return null; } Object val = (Object)(object)((source is Object) ? source : null); if (val != null && !Object.op_Implicit(val)) { return null; } NamedTransformCache orCreateValue = cache.GetOrCreateValue(source); if (orCreateValue.Values.TryGetValue(childName, out Transform value) && Object.op_Implicit((Object)(object)value)) { return value; } Transform val2 = finder(source); if (Object.op_Implicit((Object)(object)val2)) { orCreateValue.Values[childName] = val2; } else { orCreateValue.Values.Remove(childName); } return val2; } private static bool IsMissing<T>(T? value) where T : class { if (value == null) { return true; } Object val = (Object)(object)((value is Object) ? value : null); if (val != null) { return !Object.op_Implicit(val); } return false; } private static bool IsMissingArray<T>(T[]? value) where T : Object { if (value == null) { return true; } for (int i = 0; i < value.Length; i++) { if (!Object.op_Implicit((Object)(object)value[i])) { return true; } } return false; } } [HarmonyPatch] internal static class OptimizeDynamicBoneLateUpdatePatch { private sealed class DynamicBoneState { public int LastVisibleFrame = int.MinValue; } private static readonly Type? DynamicBoneType = AccessTools.TypeByName("DynamicBone"); private static readonly MethodInfo? DynamicBoneLateUpdateMethod = ((DynamicBoneType != null) ? AccessTools.DeclaredMethod(DynamicBoneType, "LateUpdate", (Type[])null, (Type[])null) : null); private static readonly FieldInfo? DynamicBoneRootField = ((DynamicBoneType != null) ? AccessTools.Field(DynamicBoneType, "m_Root") : null); private static readonly FieldInfo? DynamicBoneNeverOptimizeField = ((DynamicBoneType != null) ? AccessTools.Field(DynamicBoneType, "neverOptimize") : null); private static readonly FixedConditionalWeakTable<Component, DynamicBoneState> StateByBone = new FixedConditionalWeakTable<Component, DynamicBoneState>(); private static int cachedCameraFrame = int.MinValue; private static Camera? cachedMainCamera; private static bool Prepare() { if (DynamicBoneLateUpdateMethod == null) { ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogWarning((object)"DynamicBone.LateUpdate not found, skipping DynamicBone optimization."); } return false; } ManualLogSource? globalLogger2 = RORO.GlobalLogger; if (globalLogger2 != null) { globalLogger2.LogInfo((object)"DynamicBone.LateUpdate optimization enabled."); } return true; } private static MethodBase TargetMethod() { return DynamicBoneLateUpdateMethod; } [HarmonyPrefix] private static bool Prefix(Component __instance) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_00e4: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)__instance)) { return true; } Behaviour val = (Behaviour)(object)((__instance is Behaviour) ? __instance : null); if (val != null && !val.isActiveAndEnabled) { return true; } bool flag = default(bool); int num; if (DynamicBoneNeverOptimizeField != null) { object value = DynamicBoneNeverOptimizeField.GetValue(__instance); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } Renderer[] array = ResolveRenderers(__instance); if (!ROROConfig.EnableDynamicBoneInvisibleThrottling || array == null || array.Length == 0) { return true; } int num2 = Mathf.Max(2, ROROConfig.DynamicBoneInvisibleUpdateInterval); int num3 = Mathf.Max(1, ROROConfig.DynamicBoneVisibleMidUpdateInterval); int num4 = Mathf.Max(num3, ROROConfig.DynamicBoneVisibleFarUpdateInterval); int num5 = 1; int frameCount = Time.frameCount; DynamicBoneState orCreateValue = StateByBone.GetOrCreateValue(__instance); if (AnyRendererVisible(array)) { orCreateValue.LastVisibleFrame = frameCount; Camera mainCamera = GetMainCamera(); if ((Object)(object)mainCamera != (Object)null) { Vector3 val2 = GetReferencePosition(__instance) - ((Component)mainCamera).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; float num6 = Mathf.Max(0f, ROROConfig.DynamicBoneVisibleMidDistance); float num7 = Mathf.Max(num6, ROROConfig.DynamicBoneVisibleFarDistance); float num8 = num6 * num6; float num9 = num7 * num7; if (sqrMagnitude >= num9) { num5 = num4; } else if (sqrMagnitude >= num8) { num5 = num3; } } } else { if (frameCount - orCreateValue.LastVisibleFrame <= ROROConfig.DynamicBoneRecentlyVisibleGraceFrames) { return true; } num5 = num2; } if (num5 <= 1) { return true; } return (frameCount + (((Object)__instance).GetInstanceID() & 0x7FFFFFFF)) % num5 == 0; } private static Renderer[]? ResolveRenderers(Component dynamicBone) { object? obj = DynamicBoneRootField?.GetValue(dynamicBone); Transform val = (Transform)((obj is Transform) ? obj : null); Renderer[] array = (((Object)(object)val != (Object)null) ? OptimizedComponentCache.GetRenderersInChildren(((Component)val).gameObject) : null); if (array == null || array.Length == 0) { array = OptimizedComponentCache.GetRenderersInChildren(dynamicBone.gameObject); } return array; } private static Vector3 GetReferencePosition(Component dynamicBone) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) object? obj = DynamicBoneRootField?.GetValue(dynamicBone); Transform val = (Transform)((obj is Transform) ? obj : null); if (!((Object)(object)val != (Object)null)) { return dynamicBone.transform.position; } return val.position; } private static Camera? GetMainCamera() { int frameCount = Time.frameCount; if (cachedCameraFrame != frameCount) { cachedMainCamera = Camera.main; cachedCameraFrame = frameCount; } return cachedMainCamera; } private static bool AnyRendererVisible(Renderer[] renderers) { foreach (Renderer val in renderers) { if (Object.op_Implicit((Object)(object)val) && val.enabled && val.isVisible) { return true; } } return false; } } [HarmonyPatch] internal static class OptimizeGenericIkLateUpdatePatch { private sealed class GenericIkState { public int LastVisibleFrame = int.MinValue; } private static readonly Type? InverseKinematicsType = AccessTools.TypeByName("Generics.Dynamics.InverseKinematics"); private static readonly MethodInfo? InverseKinematicsLateUpdateMethod = ((InverseKinematicsType != null) ? AccessTools.DeclaredMethod(InverseKinematicsType, "LateUpdate", (Type[])null, (Type[])null) : null); private static readonly FieldInfo? AnimatorField = ((InverseKinematicsType != null) ? AccessTools.Field(InverseKinematicsType, "animator") : null); private static readonly FixedConditionalWeakTable<Component, GenericIkState> StateByIk = new FixedConditionalWeakTable<Component, GenericIkState>(); private static bool Prepare() { if (InverseKinematicsLateUpdateMethod == null) { ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogWarning((object)"Generics.Dynamics.InverseKinematics.LateUpdate not found, skipping GenericIK optimization."); } return false; } ManualLogSource? globalLogger2 = RORO.GlobalLogger; if (globalLogger2 != null) { globalLogger2.LogInfo((object)"Generics.Dynamics.InverseKinematics.LateUpdate optimization enabled."); } return true; } private static MethodBase TargetMethod() { return InverseKinematicsLateUpdateMethod; } [HarmonyPrefix] private static bool Prefix(Component __instance) { if (!ROROConfig.EnableGenericIkInvisibleThrottling || !Object.op_Implicit((Object)(object)__instance)) { return true; } Behaviour val = (Behaviour)(object)((__instance is Behaviour) ? __instance : null); if (val != null && !val.isActiveAndEnabled) { return true; } Renderer[] array = ResolveRenderers(__instance); if (array == null || array.Length == 0) { return true; } int frameCount = Time.frameCount; GenericIkState orCreateValue = StateByIk.GetOrCreateValue(__instance); if (AnyRendererVisible(array)) { orCreateValue.LastVisibleFrame = frameCount; return true; } if (frameCount - orCreateValue.LastVisibleFrame <= ROROConfig.GenericIkRecentlyVisibleGraceFrames) { return true; } int num = Mathf.Max(2, ROROConfig.GenericIkInvisibleUpdateInterval); return (frameCount + (((Object)__instance).GetInstanceID() & 0x7FFFFFFF)) % num == 0; } private static Renderer[]? ResolveRenderers(Component inverseKinematics) { object? obj = AnimatorField?.GetValue(inverseKinematics); Animator val = (Animator)((obj is Animator) ? obj : null); if ((Object)(object)val != (Object)null) { Renderer[] renderersInChildren = OptimizedComponentCache.GetRenderersInChildren(((Component)val).gameObject); if (renderersInChildren != null && renderersInChildren.Length != 0) { return renderersInChildren; } } return OptimizedComponentCache.GetRenderersInChildren(inverseKinematics.gameObject); } private static bool AnyRendererVisible(Renderer[] renderers) { foreach (Renderer val in renderers) { if (Object.op_Implicit((Object)(object)val) && val.enabled && val.isVisible) { return true; } } return false; } } [HarmonyPatch(typeof(ContextManager), "Update")] public static class OptimizeContextManagerPatch { private static readonly MethodInfo GameObjectGetInteractionDriverMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(InteractionDriver)); private static readonly MethodInfo GameObjectGetInteractableMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(IInteractable)); private static readonly MethodInfo GameObjectGetInspectableMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(IInspectable)); private static readonly MethodInfo ComponentGetPlayerCharacterMasterControllerMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(PlayerCharacterMasterController)); private static readonly MethodInfo CachedInteractionDriverMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInteractionDriver", (Type[])null, (Type[])null); private static readonly MethodInfo CachedInteractableMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInteractable", (Type[])null, (Type[])null); private static readonly MethodInfo CachedInspectableMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInspectable", (Type[])null, (Type[])null); private static readonly MethodInfo CachedPlayerCharacterMasterControllerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetPlayerCharacterMasterController", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetInteractionDriverMethod, CachedInteractionDriverMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetInteractableMethod, CachedInteractableMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetInspectableMethod, CachedInspectableMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetPlayerCharacterMasterControllerMethod, CachedPlayerCharacterMasterControllerMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"ContextManager.Update optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(HUD), "Update")] public static class OptimizeHUDPatch { private static readonly MethodInfo GameObjectGetCharacterBodyMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(CharacterBody)); private static readonly MethodInfo GameObjectGetEquipmentSlotMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(EquipmentSlot)); private static readonly MethodInfo GameObjectGetHealthComponentMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(HealthComponent)); private static readonly MethodInfo GameObjectGetSkillLocatorMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(SkillLocator)); private static readonly MethodInfo ComponentGetPlayerCharacterMasterControllerMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(PlayerCharacterMasterController)); private static readonly MethodInfo CachedCharacterBodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterBody", (Type[])null, (Type[])null); private static readonly MethodInfo CachedEquipmentSlotMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetEquipmentSlot", (Type[])null, (Type[])null); private static readonly MethodInfo CachedHealthComponentMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHealthComponent", (Type[])null, (Type[])null); private static readonly MethodInfo CachedPlayerCharacterMasterControllerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetPlayerCharacterMasterController", (Type[])null, (Type[])null); private static readonly MethodInfo CachedSkillLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetSkillLocator", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetCharacterBodyMethod, CachedCharacterBodyMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetEquipmentSlotMethod, CachedEquipmentSlotMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetHealthComponentMethod, CachedHealthComponentMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetSkillLocatorMethod, CachedSkillLocatorMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetPlayerCharacterMasterControllerMethod, CachedPlayerCharacterMasterControllerMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"HUD.Update optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(NetworkProximityChecker), "Update")] public static class OptimizeNetworkProximityCheckerPatch { private static readonly MethodInfo ComponentGetNetworkIdentityMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(NetworkIdentity)); private static readonly MethodInfo CachedNetworkIdentityMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetNetworkIdentity", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetNetworkIdentityMethod, CachedNetworkIdentityMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"NetworkProximityChecker.Update optimized: cached GetComponent calls={replacements}"); } } } internal static class OptimizeGetComponentPatchTools { private static readonly MethodInfo ComponentGetComponentDefinition = typeof(Component).GetMethod("GetComponent", Type.EmptyTypes).GetGenericMethodDefinition(); private static readonly MethodInfo GameObjectGetComponentDefinition = typeof(GameObject).GetMethod("GetComponent", Type.EmptyTypes).GetGenericMethodDefinition(); private static readonly MethodInfo GameObjectGetComponentInChildrenDefinition = typeof(GameObject).GetMethod("GetComponentInChildren", Type.EmptyTypes).GetGenericMethodDefinition(); private static readonly MethodInfo ComponentGetComponentsInChildrenDefinition = typeof(Component).GetMethod("GetComponentsInChildren", Type.EmptyTypes).GetGenericMethodDefinition(); private static readonly MethodInfo GameObjectGetComponentsInChildrenDefinition = typeof(GameObject).GetMethod("GetComponentsInChildren", Type.EmptyTypes).GetGenericMethodDefinition(); public static MethodInfo MakeComponentGetComponentMethod(Type componentType) { return ComponentGetComponentDefinition.MakeGenericMethod(componentType); } public static MethodInfo MakeGameObjectGetComponentMethod(Type componentType) { return GameObjectGetComponentDefinition.MakeGenericMethod(componentType); } public static MethodInfo MakeGameObjectGetComponentInChildrenMethod(Type componentType) { return GameObjectGetComponentInChildrenDefinition.MakeGenericMethod(componentType); } public static MethodInfo MakeComponentGetComponentsInChildrenMethod(Type componentType) { return ComponentGetComponentsInChildrenDefinition.MakeGenericMethod(componentType); } public static MethodInfo MakeGameObjectGetComponentsInChildrenMethod(Type componentType) { return GameObjectGetComponentsInChildrenDefinition.MakeGenericMethod(componentType); } public static bool ReplaceCall(CodeInstruction instruction, MethodInfo source, MethodInfo target) { if (!CodeInstructionExtensions.Calls(instruction, source)) { return false; } instruction.opcode = OpCodes.Call; instruction.operand = target; return true; } } internal static class MenuHotspotThrottleState { private sealed class ThrottleState { public bool IsDirty = true; public float NextAllowedTime; } private static readonly FixedConditionalWeakTable<LobbyUserList, ThrottleState> LobbyStates = new FixedConditionalWeakTable<LobbyUserList, ThrottleState>(); private static readonly FixedConditionalWeakTable<SocialUserIconBehavior, ThrottleState> AvatarStates = new FixedConditionalWeakTable<SocialUserIconBehavior, ThrottleState>(); private static readonly FixedConditionalWeakTable<SurvivorIconController, ThrottleState> SurvivorStates = new FixedConditionalWeakTable<SurvivorIconController, ThrottleState>(); public static void MarkLobbyDirty(LobbyUserList? lobbyUserList) { MarkDirty(lobbyUserList, LobbyStates); } public static void MarkAvatarDirty(SocialUserIconBehavior? behavior) { MarkDirty(behavior, AvatarStates); } public static void MarkSurvivorDirty(SurvivorIconController? controller) { MarkDirty(controller, SurvivorStates); } public static bool ShouldRunLobbyRefresh(LobbyUserList? lobbyUserList, float intervalSeconds) { return ShouldRun(lobbyUserList, intervalSeconds, LobbyStates); } public static bool ShouldRunAvatarRefresh(SocialUserIconBehavior? behavior, bool shouldForceRefresh, float intervalSeconds) { if (!shouldForceRefresh) { return ShouldRun(behavior, intervalSeconds, AvatarStates); } return true; } public static bool ShouldRunSurvivorAvailabilityRefresh(SurvivorIconController? controller, float intervalSeconds) { return ShouldRun(controller, intervalSeconds, SurvivorStates); } private static void MarkDirty<T>(T? instance, FixedConditionalWeakTable<T, ThrottleState> table) where T : class { if (instance != null) { ThrottleState orCreateValue = table.GetOrCreateValue(instance); orCreateValue.IsDirty = true; orCreateValue.NextAllowedTime = 0f; } } private static bool ShouldRun<T>(T? instance, float intervalSeconds, FixedConditionalWeakTable<T, ThrottleState> table) where T : class { if (instance == null) { return false; } ThrottleState orCreateValue = table.GetOrCreateValue(instance); float unscaledTime = Time.unscaledTime; if (!orCreateValue.IsDirty && unscaledTime < orCreateValue.NextAllowedTime) { return false; } orCreateValue.IsDirty = false; orCreateValue.NextAllowedTime = unscaledTime + intervalSeconds; return true; } } internal static class SteamAvatarHotspotCache { private readonly struct AvatarCacheKey : IEquatable<AvatarCacheKey> { private readonly ulong steamId; private readonly int size; public AvatarCacheKey(PlatformID platformId, AvatarSize avatarSize) { //IL_0001: 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_0013: Expected I4, but got Unknown steamId = platformId.ID; size = (int)avatarSize; } public bool Equals(AvatarCacheKey other) { if (steamId == other.steamId) { return size == other.size; } return false; } public override bool Equals(object? obj) { if (obj is AvatarCacheKey other) { return Equals(other); } return false; } public override int GetHashCode() { return ((int)steamId * 397) ^ size; } } private sealed class PendingAvatarRequest { public readonly List<Action<Texture2D>> WaitingCallbacks = new List<Action<Texture2D>>(); public float StartedAt; } private const float PendingRequestTimeoutSeconds = 5f; private static readonly object Sync = new object(); private static readonly Dictionary<AvatarCacheKey, Texture2D> CachedTextures = new Dictionary<AvatarCacheKey, Texture2D>(); private static readonly Dictionary<AvatarCacheKey, PendingAvatarRequest> PendingRequests = new Dictionary<AvatarCacheKey, PendingAvatarRequest>(); public static bool ShouldRunOriginalRequest(PlatformID id, AvatarSize size, Action<Texture2D>? onReceived) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) AvatarCacheKey key = new AvatarCacheKey(id, size); Texture2D val = null; bool result = false; lock (Sync) { if (CachedTextures.TryGetValue(key, out Texture2D value)) { if (Object.op_Implicit((Object)(object)value)) { val = value; } else { CachedTextures.Remove(key); } } if (!Object.op_Implicit((Object)(object)val)) { float unscaledTime = Time.unscaledTime; if (PendingRequests.TryGetValue(key, out PendingAvatarRequest value2)) { if (unscaledTime - value2.StartedAt < 5f) { if (onReceived != null) { value2.WaitingCallbacks.Add(onReceived); } return false; } PendingRequests.Remove(key); } PendingRequests[key] = new PendingAvatarRequest { StartedAt = unscaledTime }; result = true; } } if (Object.op_Implicit((Object)(object)val) && onReceived != null) { onReceived(val); return false; } return result; } public static void CompleteRequest(PlatformID id, AvatarSize size, Texture2D? texture) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) AvatarCacheKey key = new AvatarCacheKey(id, size); List<Action<Texture2D>> list = null; lock (Sync) { if (PendingRequests.TryGetValue(key, out PendingAvatarRequest value)) { list = value.WaitingCallbacks; PendingRequests.Remove(key); } if (Object.op_Implicit((Object)(object)texture)) { CachedTextures[key] = texture; } else { CachedTextures.Remove(key); } } if (!((Object)(object)texture == (Object)null) && list != null) { for (int i = 0; i < list.Count; i++) { list[i](texture); } } } } [HarmonyPatch(typeof(LobbyUserList), "Update")] public static class OptimizeLobbyUserListUpdatePatch { private const float RefreshIntervalSeconds = 0.2f; [HarmonyPrefix] private static bool Prefix(LobbyUserList __instance) { return MenuHotspotThrottleState.ShouldRunLobbyRefresh(__instance, 0.2f); } } [HarmonyPatch(typeof(LobbyUserList), "OnEnable")] public static class OptimizeLobbyUserListOnEnablePatch { [HarmonyPostfix] private static void Postfix(LobbyUserList __instance) { MenuHotspotThrottleState.MarkLobbyDirty(__instance); } } [HarmonyPatch(typeof(LobbyUserList), "OnLobbyChanged")] public static class OptimizeLobbyUserListOnLobbyChangedPatch { [HarmonyPostfix] private static void Postfix(LobbyUserList __instance) { MenuHotspotThrottleState.MarkLobbyDirty(__instance); } } [HarmonyPatch(typeof(LobbyUserList), "OnLobbyMemberDataUpdated")] public static class OptimizeLobbyUserListOnLobbyMemberDataUpdatedPatch { [HarmonyPostfix] private static void Postfix(LobbyUserList __instance) { MenuHotspotThrottleState.MarkLobbyDirty(__instance); } } [HarmonyPatch(typeof(LobbyUserList), "OnLobbyStateChanged")] public static class OptimizeLobbyUserListOnLobbyStateChangedPatch { [HarmonyPostfix] private static void Postfix(LobbyUserList __instance) { MenuHotspotThrottleState.MarkLobbyDirty(__instance); } } [HarmonyPatch(typeof(LobbyUserListElement), "Refresh")] public static class OptimizeLobbyUserListElementRefreshPatch { private static readonly MethodInfo ChildLocatorFindChildMethod = AccessTools.Method(typeof(ChildLocator), "FindChild", new Type[1] { typeof(string) }, (Type[])null); private static readonly MethodInfo CachedFindChildMethod = AccessTools.Method(typeof(OptimizedComponentCache), "FindChild", new Type[2] { typeof(ChildLocator), typeof(string) }, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ChildLocatorFindChildMethod, CachedFindChildMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"LobbyUserListElement.Refresh optimized: cached ChildLocator.FindChild calls={replacements}"); } } } [HarmonyPatch(typeof(SocialUserIconBehavior), "Refresh")] public static class OptimizeSocialUserIconBehaviorRefreshPatch { private const float RefreshIntervalSeconds = 0.25f; [HarmonyPrefix] private static bool Prefix(SocialUserIconBehavior __instance, bool shouldForceRefresh) { return MenuHotspotThrottleState.ShouldRunAvatarRefresh(__instance, shouldForceRefresh, 0.25f); } } [HarmonyPatch(typeof(SteamUserManager), "GetSteamAvatar")] public static class OptimizeSteamUserManagerGetSteamAvatarPatch { [HarmonyPrefix] private static bool Prefix(PlatformID id, AvatarSize size, Action<Texture2D> onRecieved) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return SteamAvatarHotspotCache.ShouldRunOriginalRequest(id, size, onRecieved); } } [HarmonyPatch(typeof(SocialUserIconBehavior), "HandleNewTexture")] public static class OptimizeSocialUserIconBehaviorHandleNewTexturePatch { [HarmonyPostfix] private static void Postfix(SocialUserIconBehavior __instance, Texture2D tex) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) SteamAvatarHotspotCache.CompleteRequest(__instance.userID, __instance.avatarSize, tex); } } [HarmonyPatch(typeof(SocialUserIconBehavior), "OnEnableBehavior")] public static class OptimizeSocialUserIconBehaviorOnEnablePatch { [HarmonyPostfix] private static void Postfix(SocialUserIconBehavior __instance) { MenuHotspotThrottleState.MarkAvatarDirty(__instance); } } [HarmonyPatch(typeof(SocialUserIconBehavior), "RefreshWithUser")] public static class OptimizeSocialUserIconBehaviorRefreshWithUserPatch { [HarmonyPostfix] private static void Postfix(SocialUserIconBehavior __instance) { MenuHotspotThrottleState.MarkAvatarDirty(__instance); } } [HarmonyPatch(typeof(SurvivorIconController), "UpdateAvailability")] public static class OptimizeSurvivorIconControllerAvailabilityPatch { private const float RefreshIntervalSeconds = 0.25f; [HarmonyPrefix] private static bool Prefix(SurvivorIconController __instance) { return MenuHotspotThrottleState.ShouldRunSurvivorAvailabilityRefresh(__instance, 0.25f); } } [HarmonyPatch(typeof(SurvivorIconController), "Awake")] public static class OptimizeSurvivorIconControllerAwakePatch { [HarmonyPostfix] private static void Postfix(SurvivorIconController __instance) { MenuHotspotThrottleState.MarkSurvivorDirty(__instance); } } [HarmonyPatch(typeof(KineticAura), "FixedUpdate")] public static class OptimizeKineticAuraPatch { private static readonly MethodInfo ComponentGetCharacterMotorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterMotor)); private static readonly MethodInfo ComponentGetRigidbodyMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(Rigidbody)); private static readonly MethodInfo CachedCharacterMotorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterMotor", new Type[1] { typeof(Component) }, (Type[])null); private static readonly MethodInfo CachedRigidbodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetRigidbodyFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterMotorMethod, CachedCharacterMotorMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetRigidbodyMethod, CachedRigidbodyMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"KineticAura.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(ToolbotDash), "FixedUpdate")] public static class OptimizeToolbotDashPatch { private static readonly MethodInfo ComponentGetCharacterMotorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterMotor)); private static readonly MethodInfo ComponentGetRigidbodyMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(Rigidbody)); private static readonly MethodInfo CachedCharacterMotorMethod = AccessTools.Method(typeof(OptimizedC