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 CleanupSnatcher v1.0.2
plugins/com.pwdcat.CleanupSnatcher.dll
Decompiled 5 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Drifter; using EntityStates.Drifter.Bag; using HarmonyLib; using Microsoft.CodeAnalysis; using RiskOfOptions; using RiskOfOptions.Options; using RoR2; using RoR2.Projectile; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.pwdcat.CleanupSnatcher")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("com.pwdcat.CleanupSnatcher")] [assembly: AssemblyTitle("CleanupSnatcher")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] 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; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace CleanupSnatcher { internal static class Constants { public const string LogPrefix = "[CleanupSnatcher]"; public const string PluginGuid = "pwdcat.CleanupSnatcher"; public const string PluginName = "CleanupSnatcher"; public const string PluginVersion = "1.0.0"; } internal static class Log { private static ManualLogSource? _logSource; private const string ERROR_PREFIX = "[ERROR] "; private const string FATAL_PREFIX = "[FATAL] "; private const string INFO_PREFIX = "[INFO] "; private const string WARNING_PREFIX = "[WARNING] "; internal static bool EnableDebugLogs { get; set; } internal static void Init(ManualLogSource logSource) { _logSource = logSource; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Error(object data) { ManualLogSource? logSource = _logSource; if (logSource != null) { logSource.LogMessage((object)("[ERROR] " + data)); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Fatal(object data) { ManualLogSource? logSource = _logSource; if (logSource != null) { logSource.LogMessage((object)("[FATAL] " + data)); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Info(object data) { if (EnableDebugLogs) { ManualLogSource? logSource = _logSource; if (logSource != null) { logSource.LogMessage((object)("[INFO] " + data)); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Message(object data) { ManualLogSource? logSource = _logSource; if (logSource != null) { logSource.LogMessage(data); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Warning(object data) { ManualLogSource? logSource = _logSource; if (logSource != null) { logSource.LogMessage((object)("[WARNING] " + data)); } } } [BepInPlugin("pwdcat.CleanupSnatcher", "CleanupSnatcher", "1.0.0")] public class CleanupSnatcherPlugin : BaseUnityPlugin { private EventHandler debugLogsHandler; private EventHandler projectileGrabbingHandler; public static CleanupSnatcherPlugin Instance { get; private set; } public static bool RooInstalled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"); public string DirectoryName => Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); public void Awake() { Instance = this; Log.Init(((BaseUnityPlugin)this).Logger); Log.Info("[CleanupSnatcher] CleanupSnatcherPlugin.Awake() called"); PluginConfig.Init(((BaseUnityPlugin)this).Config); Log.EnableDebugLogs = PluginConfig.EnableDebugLogs.Value; Log.Info(string.Format("{0} Debug logs enabled: {1}", "[CleanupSnatcher]", Log.EnableDebugLogs)); SetupConfigurationEventHandlers(); ApplyHarmonyPatches(); RegisterGameEvents(); Log.Info("[CleanupSnatcher] Plugin initialization complete"); } public void OnDestroy() { PluginConfig.RemoveEventHandlers(debugLogsHandler, projectileGrabbingHandler); } public void Start() { SetupRiskOfOptions(); } private void SetupConfigurationEventHandlers() { debugLogsHandler = delegate { Log.EnableDebugLogs = PluginConfig.EnableDebugLogs.Value; }; PluginConfig.EnableDebugLogs.SettingChanged += debugLogsHandler; projectileGrabbingHandler = delegate { }; PluginConfig.EnableProjectileGrabbing.SettingChanged += projectileGrabbingHandler; } private void ApplyHarmonyPatches() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown Harmony val = new Harmony("pwdcat.CleanupSnatcher"); val.PatchAll(); } private void RegisterGameEvents() { SceneManager.activeSceneChanged += OnSceneChanged; } private static void OnSceneChanged(Scene oldScene, Scene newScene) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Scene changed from " + ((Scene)(ref oldScene)).name + " to " + ((Scene)(ref newScene)).name); } } private void SetupRiskOfOptions() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (RooInstalled) { ModSettingsManager.SetModDescription("Allows Drifter to grab projectiles from their Cleanup ability.", "pwdcat.CleanupSnatcher", "CleanupSnatcher"); try { byte[] array = File.ReadAllBytes(Path.Combine(DirectoryName, "icon.png")); Texture2D val = new Texture2D(256, 256); ImageConversion.LoadImage(val, array); ModSettingsManager.SetModIcon(Sprite.Create(val, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f))); } catch (Exception) { } AddConfigurationOptions(); } } private void AddConfigurationOptions() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if (RooInstalled) { ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.EnableProjectileGrabbing)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.EnableDebugLogs)); } } } public static class PluginConfig { public static ConfigEntry<bool> EnableProjectileGrabbing { get; private set; } public static ConfigEntry<bool> EnableDebugLogs { get; private set; } public static void Init(ConfigFile cfg) { EnableProjectileGrabbing = cfg.Bind<bool>("General", "EnableProjectileGrabbing", true, "Enable grabbing of projectiles from Drifter's Cleanup ability"); EnableDebugLogs = cfg.Bind<bool>("General", "EnableDebugLogs", false, "Enable debug logging for projectile grabbing operations"); } public static void RemoveEventHandlers(EventHandler debugLogsHandler, EventHandler projectileGrabbingHandler) { EnableDebugLogs.SettingChanged -= debugLogsHandler; EnableProjectileGrabbing.SettingChanged -= projectileGrabbingHandler; } } } namespace CleanupSnatcher.Patches { public static class ProjectilePatches { [HarmonyPatch(typeof(DrifterCleanupController), "ToggleVisuals")] public class DrifterCleanupController_ToggleVisuals_Patch { [HarmonyPrefix] public static void Prefix(DrifterCleanupController __instance, GameObject target, bool enabled, float duration) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} ToggleVisuals called - target: {1}, enabled: {2}, duration: {3}", "[CleanupSnatcher]", (target != null) ? ((Object)target).name : null, enabled, duration)); } _isToggleVisualsDisplayActive = enabled; if (!enabled) { _shouldMakeNextProjectilesGrabbable = false; if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Display disabled - clearing grab flag"); } } } } [HarmonyPatch(typeof(ProjectileManager), "FireProjectileServer", new Type[] { typeof(FireProjectileInfo), typeof(NetworkConnection), typeof(ushort), typeof(double) })] public class ProjectileManager_FireProjectileServer_Patch { [HarmonyPostfix] public static void Postfix(FireProjectileInfo fireProjectileInfo) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (PluginConfig.EnableDebugLogs.Value) { object[] obj = new object[4] { "[CleanupSnatcher]", null, null, null }; GameObject projectilePrefab = fireProjectileInfo.projectilePrefab; obj[1] = ((projectilePrefab != null) ? ((Object)projectilePrefab).name : null); obj[2] = fireProjectileInfo.position; GameObject owner = fireProjectileInfo.owner; obj[3] = ((owner != null) ? ((Object)owner).name : null); Log.Info(string.Format("{0} ProjectileManager.FireProjectileServer - prefab: {1}, position: {2}, owner: {3}", obj)); } if (PluginConfig.EnableProjectileGrabbing.Value && _shouldMakeNextProjectilesGrabbable) { if (PluginConfig.EnableDebugLogs.Value) { GameObject projectilePrefab2 = fireProjectileInfo.projectilePrefab; Log.Info("[CleanupSnatcher] ProjectileManager.FireProjectileServer - flag set for projectile: " + ((projectilePrefab2 != null) ? ((Object)projectilePrefab2).name : null)); } _shouldMakeNextProjectilesGrabbable = false; } } } [HarmonyPatch(typeof(NetworkServer), "Spawn", new Type[] { typeof(GameObject) })] public class NetworkServer_Spawn_Patch { [HarmonyPostfix] public static void Postfix(GameObject obj) { if (PluginConfig.EnableProjectileGrabbing.Value && _shouldMakeNextProjectilesGrabbable && !((Object)(object)obj == (Object)null) && (Object)(object)obj.GetComponent<ProjectileController>() != (Object)null) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] NetworkServer.Spawn - making projectile grabbable: " + ((Object)obj).name); } AddSpecialObjectAttributesToProjectile(obj); _activeProjectile = obj; if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Set active projectile: " + ((Object)obj).name); } } } } [HarmonyPatch(typeof(GenericSkill), "ExecuteIfReady")] public class GenericSkill_ExecuteIfReady_Patch { [HarmonyPrefix] public static bool Prefix(GenericSkill __instance, ref bool __result) { //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_061b: Unknown result type (might be due to invalid IL or missing references) //IL_061d: Unknown result type (might be due to invalid IL or missing references) //IL_0624: Unknown result type (might be due to invalid IL or missing references) //IL_0626: Unknown result type (might be due to invalid IL or missing references) //IL_062b: Unknown result type (might be due to invalid IL or missing references) //IL_0630: Unknown result type (might be due to invalid IL or missing references) //IL_0661: Unknown result type (might be due to invalid IL or missing references) //IL_0677: Unknown result type (might be due to invalid IL or missing references) //IL_0679: Unknown result type (might be due to invalid IL or missing references) //IL_0680: Unknown result type (might be due to invalid IL or missing references) //IL_05f0: Unknown result type (might be due to invalid IL or missing references) //IL_05f7: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04a5: Unknown result type (might be due to invalid IL or missing references) //IL_04aa: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0538: Unknown result type (might be due to invalid IL or missing references) //IL_053d: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_0546: Unknown result type (might be due to invalid IL or missing references) //IL_054a: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Unknown result type (might be due to invalid IL or missing references) if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] ExecuteIfReady called for skill: " + __instance.skillDef?.skillName); } if (!PluginConfig.EnableProjectileGrabbing.Value) { return true; } GameObject value; float value2; float value3; float value4; GameObject gameObject; Vector3 val5; Vector3 val6; if (__instance.skillDef?.skillName == "Repossess" && _isToggleVisualsDisplayActive) { if (!__instance.CanExecute()) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Repossess pressed but skill is not ready (cooldown) - skipping projectile spawn"); } return true; } if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Repossess pressed while ToggleVisuals display is ACTIVE - spawning projectile directly"); } SkillLocator component = ((Component)__instance).GetComponent<SkillLocator>(); if ((Object)(object)component != (Object)null && (Object)(object)component.secondary != (Object)null) { GenericSkill secondary = component.secondary; EntityStateMachine val = EntityStateMachine.FindByCustomName(((Component)component).gameObject, "Bag"); if ((Object)(object)val != (Object)null && val.state is BaggedObject) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Bag is already full, skipping projectile spawn"); } return true; } DrifterCleanupController component2 = ((Component)component).gameObject.GetComponent<DrifterCleanupController>(); if ((Object)(object)component2 != (Object)null) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Manually cycling projectile index in DrifterCleanupController"); } FieldInfo field = typeof(DrifterCleanupController).GetField("prefabIndex", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { try { FieldInfo field2 = typeof(DrifterCleanupController).GetField("projectileCandidateSelection", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null) { if (field2.GetValue(component2) is WeightedSelection<Candidate> val2) { int num = (int)field.GetValue(component2); int num2 = Math.Abs(num); int num3 = (num2 + 1) % val2.Count; if (num < 0) { num3 = -num3; } field.SetValue(component2, num3); if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Cycled prefabIndex from {1} to {2} (total candidates: {3})", "[CleanupSnatcher]", num, num3, val2.Count)); } } else if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Could not get projectile candidate selection"); } } else { int num4 = (int)field.GetValue(component2); int num5 = Math.Abs(num4); int num6 = (num5 + 1) % 3; if (num4 < 0) { num6 = -num6; } field.SetValue(component2, num6); if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Fallback cycling prefabIndex from {1} to {2}", "[CleanupSnatcher]", num4, num6)); } } } catch (Exception ex) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Failed to cycle prefabIndex: " + ex.Message); } } } else if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Could not find prefabIndex field in DrifterCleanupController"); } } else if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Could not find DrifterCleanupController for manual cycling"); } if ((Object)(object)secondary.stateMachine != (Object)null) { EntityState state = secondary.stateMachine.state; AimMagicBag val3 = (AimMagicBag)(object)((state is AimMagicBag) ? state : null); if (val3 != null) { Traverse val4 = Traverse.Create((object)val3); value = val4.Field("projectilePrefab").GetValue<GameObject>(); if ((Object)(object)value != (Object)null) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Spawning cycled projectile: " + ((Object)value).name); } _shouldMakeNextProjectilesGrabbable = true; value2 = val4.Field("damageCoefficient").GetValue<float>(); value3 = val4.Field("force").GetValue<float>(); value4 = val4.Field("damageStat").GetValue<float>(); gameObject = ((Component)component).gameObject; if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Drifter position: {1}", "[CleanupSnatcher]", gameObject.transform.position)); Log.Info(string.Format("{0} Drifter forward: {1}", "[CleanupSnatcher]", gameObject.transform.forward)); Camera main = Camera.main; Log.Info(string.Format("{0} Camera position: {1}", "[CleanupSnatcher]", (main != null) ? new Vector3?(((Component)main).transform.position) : null)); Camera main2 = Camera.main; Log.Info(string.Format("{0} Camera forward: {1}", "[CleanupSnatcher]", (main2 != null) ? new Vector3?(((Component)main2).transform.forward) : null)); } val5 = gameObject.transform.position + gameObject.transform.forward * 2f + Vector3.up * 1f; val6 = gameObject.transform.forward; if ((Object)(object)secondary.stateMachine != (Object)null) { EntityState state2 = secondary.stateMachine.state; AimMagicBag val7 = (AimMagicBag)(object)((state2 is AimMagicBag) ? state2 : null); if (val7 != null) { Traverse val8 = Traverse.Create((object)val7); object value5 = val8.Field("currentTrajectoryInfo").GetValue(); if (value5 != null) { try { Ray val9 = (Ray)value5.GetType().GetField("finalRay").GetValue(value5); val5 = ((Ray)(ref val9)).origin; val6 = ((Ray)(ref val9)).direction; if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Using AimMagicBag trajectory - position: {1}, direction: {2}", "[CleanupSnatcher]", val5, val6)); } } catch (Exception ex2) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Failed to get trajectory data: " + ex2.Message + ", using fallback"); } } } else if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] No trajectory info available, using fallback values"); } goto IL_05da; } } if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Could not find AimMagicBag state, using fallback values"); } goto IL_05da; } if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] No projectile prefab found after Cleanup execution"); } goto IL_06e5; } } if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Could not find AimMagicBag state after Cleanup execution"); } } else if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Could not find SkillLocator or Cleanup skill"); } goto IL_06e5; } return true; IL_05da: if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Final spawn position: {1}, direction: {2}", "[CleanupSnatcher]", val5, val6)); } FireProjectileInfo val10 = default(FireProjectileInfo); val10.projectilePrefab = value; val10.position = val5; val10.rotation = Util.QuaternionSafeLookRotation(val6, Vector3.up); ((FireProjectileInfo)(ref val10)).speedOverride = 0f; val10.damage = value2 * value4; val10.owner = gameObject; val10.crit = false; val10.damageColorIndex = (DamageColorIndex)0; val10.force = value3; val10.target = null; FireProjectileInfo val11 = val10; ProjectileManager.instance.FireProjectile(val11); if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Cycled projectile spawned for Repossess grab"); } goto IL_06e5; IL_06e5: return true; } } [HarmonyPatch(typeof(BaggedObject), "OnEnter")] public class BaggedObject_OnEnter_Patch { [HarmonyPostfix] public static void Postfix(BaggedObject __instance) { if ((Object)(object)_activeProjectile != (Object)null) { Traverse val = Traverse.Create((object)__instance); GameObject value = val.Field("targetObject").GetValue<GameObject>(); if ((Object)(object)value == (Object)(object)_activeProjectile) { Log.Info("[CleanupSnatcher] Active projectile grabbed: " + ((Object)_activeProjectile).name); _activeProjectile = null; } } } } [HarmonyPatch(typeof(ThrownObjectProjectileController), "ImpactBehavior")] public class ThrownObjectProjectileController_ImpactBehavior_Patch { [HarmonyPostfix] public static void Postfix(ThrownObjectProjectileController __instance) { if ((Object)(object)_activeProjectile != (Object)null && (Object)(object)((Component)__instance).gameObject == (Object)(object)_activeProjectile) { Log.Info("[CleanupSnatcher] Active projectile impacted: " + ((Object)_activeProjectile).name); _activeProjectile = null; } } } [HarmonyPatch(typeof(Object), "Destroy", new Type[] { typeof(Object) })] public class Object_Destroy_Patch { [HarmonyPrefix] public static void Prefix(Object obj) { if ((Object)(object)_activeProjectile != (Object)null) { GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null); if (val != null && (Object)(object)val == (Object)(object)_activeProjectile) { Log.Info("[CleanupSnatcher] Active projectile destroyed: " + ((Object)_activeProjectile).name); _activeProjectile = null; } } } } [HarmonyPatch(typeof(RepossessBullseyeSearch), "GetResults")] public class RepossessBullseyeSearch_GetResults_Patch { [HarmonyPostfix] public static void Postfix(ref IEnumerable<GameObject> __result) { if ((Object)(object)_activeProjectile != (Object)null) { List<GameObject> list = new List<GameObject>(__result); if (!list.Contains(_activeProjectile)) { list.Insert(0, _activeProjectile); Log.Info("[CleanupSnatcher] Force-added active projectile to repossess results: " + ((Object)_activeProjectile).name); } else { list.Remove(_activeProjectile); list.Insert(0, _activeProjectile); Log.Info("[CleanupSnatcher] Moved active projectile to front of repossess results: " + ((Object)_activeProjectile).name); } __result = list; } } } private static bool _shouldMakeNextProjectilesGrabbable; private static bool _isToggleVisualsDisplayActive; private static GameObject _activeProjectile; private static Texture GetProjectileIcon(string projectileName) { //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) string text = projectileName switch { "DrifterGrenade" => "RoR2/Base/StickyBomb/texStickyBombIcon.png", "DrifterJunkBall" => "RoR2/DLC3/Items/texJunkIcon.png", "DrifterToolbotCrate" => "RoR2/DLC3/Items/PowerCube/texPowerCubeIcon.png", "DrifterHotSauce" => "RoR2/DLC1/Molotov/texMolotovIcon.png", "DrifterKnife" => "RoR2/Base/Dagger/texDaggerIcon.png", "DrifterBubbleShield" => "RoR2/Junk/Engi/texEngiShieldSpriteCrosshair.png", "DrifterGeode" => "RoR2/DLC2/texAFUIChunkIcon.png", "DrifterBarrel" => "RoR2/Base/Common/MiscIcons/texBarrelIcon.png", "DrifterBrokenDrone" => "RoR2/Base/Drones/texDrone2Icon.png", "DrifterBrokenHAND" => "RoR2/Base/Toolbot/texToolbotIcon.png", "DrifterEvilSkull" => "RoR2/Base/AltarSkeleton/texAltarSkeletonBody.png", _ => "RoR2/Base/Common/MiscIcons/texMysteryIcon.png", }; if (!string.IsNullOrEmpty(text)) { try { Texture2D val = Addressables.LoadAssetAsync<Texture2D>((object)text).WaitForCompletion(); if ((Object)(object)val != (Object)null) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Loaded icon via Addressables: " + text); } return (Texture)(object)val; } } catch (Exception ex) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Failed to load via Addressables " + text + ": " + ex.Message + ", falling back to LegacyResourcesAPI"); } } } return null; } private static void AddSpecialObjectAttributesToProjectile(GameObject obj) { //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Unknown result type (might be due to invalid IL or missing references) //IL_0559: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return; } string text = ((Object)obj).name; string text2 = text.ToLowerInvariant(); if (string.IsNullOrEmpty(text)) { string text4 = (((Object)obj).name = "Projectile_" + ((Object)obj).GetInstanceID()); text = text4; text2 = text.ToLowerInvariant(); } if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Using projectile object " + ((Object)obj).name + " for SpecialObjectAttributes (original: " + text + ")"); } NetworkIdentity component = obj.GetComponent<NetworkIdentity>(); if ((Object)(object)component != (Object)null) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Target {1} already has NetworkIdentity: netId = {2}", "[CleanupSnatcher]", ((Object)obj).name, component.netId)); } } else { component = obj.AddComponent<NetworkIdentity>(); component.serverOnly = false; component.localPlayerAuthority = false; try { if (NetworkServer.active) { NetworkServer.Spawn(obj); if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Successfully spawned projectile {1} on network with netId = {2}", "[CleanupSnatcher]", ((Object)obj).name, component.netId)); } } else if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] NetworkServer not active, cannot spawn projectile " + ((Object)obj).name); } } catch (Exception ex) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Failed to spawn projectile " + ((Object)obj).name + " on network: " + ex.Message); } } if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Added NetworkIdentity to projectile {1}: netId = {2}", "[CleanupSnatcher]", ((Object)obj).name, component.netId)); } } SpecialObjectAttributes component2 = obj.GetComponent<SpecialObjectAttributes>(); if ((Object)(object)component2 != (Object)null) { if (!component2.grabbable || string.IsNullOrEmpty(component2.breakoutStateMachineName)) { component2.grabbable = true; component2.breakoutStateMachineName = ""; component2.orientToFloor = true; if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Updated existing SpecialObjectAttributes on projectile " + ((Object)obj).name); } } return; } SpecialObjectAttributes val = obj.AddComponent<SpecialObjectAttributes>(); val.renderersToDisable = new List<Renderer>(); val.behavioursToDisable = new List<MonoBehaviour>(); val.collisionToDisable = new List<GameObject>(); val.childObjectsToDisable = new List<GameObject>(); val.pickupDisplaysToDisable = new List<PickupDisplay>(); val.lightsToDisable = new List<Light>(); val.objectsToDetach = new List<GameObject>(); val.childSpecialObjectAttributes = new List<SpecialObjectAttributes>(); val.skillHighlightRenderers = new List<Renderer>(); val.soundEventsToStop = new List<AkEvent>(); val.soundEventsToPlay = new List<AkEvent>(); (float massOverride, int maxDurability) tuple = CalculateScaledAttributes(obj, text); float item = tuple.massOverride; int item2 = tuple.maxDurability; val.grabbable = true; val.massOverride = item; val.maxDurability = item2; val.durability = item2; val.hullClassification = (HullClassification)0; val.breakoutStateMachineName = ""; val.orientToFloor = true; string input = text.Replace("(Clone)", ""); Regex regex = new Regex("\\s*\\(\\d+\\)$"); input = (val.bestName = regex.Replace(input, "")); val.isVoid = text2.Contains("void"); if (PluginConfig.EnableDebugLogs.Value && val.isVoid) { Log.Info("[CleanupSnatcher] Marked projectile " + text + " as void object"); } val.portraitIcon = GetProjectileIcon(input); if (PluginConfig.EnableDebugLogs.Value && (Object)(object)val.portraitIcon != (Object)null) { Log.Info("[CleanupSnatcher] Set icon for projectile " + text); } Renderer[] componentsInChildren = obj.GetComponentsInChildren<Renderer>(false); Renderer[] array = componentsInChildren; foreach (Renderer item3 in array) { val.renderersToDisable.Add(item3); } Collider[] componentsInChildren2 = obj.GetComponentsInChildren<Collider>(false); Collider[] array2 = componentsInChildren2; foreach (Collider val2 in array2) { val.collisionToDisable.Add(((Component)val2).gameObject); } Light[] componentsInChildren3 = obj.GetComponentsInChildren<Light>(false); Light[] array3 = componentsInChildren3; foreach (Light item4 in array3) { val.lightsToDisable.Add(item4); } PickupDisplay[] componentsInChildren4 = obj.GetComponentsInChildren<PickupDisplay>(false); PickupDisplay[] array4 = componentsInChildren4; foreach (PickupDisplay item5 in array4) { val.pickupDisplaysToDisable.Add(item5); } MonoBehaviour[] componentsInChildren5 = obj.GetComponentsInChildren<MonoBehaviour>(true); MonoBehaviour[] array5 = componentsInChildren5; foreach (MonoBehaviour val3 in array5) { if ((Object)(object)val3 == (Object)null || !((Behaviour)val3).enabled) { continue; } Type type = ((object)val3).GetType(); if (!(type == typeof(NetworkIdentity)) && !(type == typeof(SpecialObjectAttributes)) && !(type == typeof(CharacterBody))) { val.behavioursToDisable.Add(val3); if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Disabled behavior: " + type.Name + " on " + text); } } } CharacterBody component3 = obj.GetComponent<CharacterBody>(); if (!((Object)(object)component3 != (Object)null)) { return; } try { component3.bodyFlags = (BodyFlags)(component3.bodyFlags & -524289); if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Cleared Ungrabbable flag on CharacterBody for projectile " + text); } } catch (Exception ex2) { if (PluginConfig.EnableDebugLogs.Value) { Log.Info("[CleanupSnatcher] Failed to clear Ungrabbable flag on CharacterBody for projectile " + text + ": " + ex2.Message); } } } private static (float massOverride, int maxDurability) CalculateScaledAttributes(GameObject obj, string objName) { float num = CalculateObjectSizeMetric(obj); float num2 = Mathf.Clamp(num / 10f, 0.5f, 5f); float num3 = 100f * num2; int num4 = Mathf.RoundToInt(8f * num2); num3 = Mathf.Max(num3, 25f); num4 = Mathf.Max(num4, 3); if (PluginConfig.EnableDebugLogs.Value) { Log.Info(string.Format("{0} Size scaling for {1}: sizeMetric={2:F2}, scaleFactor={3:F2}, mass={4:F0}, durability={5}", "[CleanupSnatcher]", objName, num, num2, num3, num4)); } return (num3, num4); } private static float CalculateObjectSizeMetric(GameObject obj) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return 1f; } float num = 0f; Collider[] componentsInChildren = obj.GetComponentsInChildren<Collider>(false); Collider[] array = componentsInChildren; foreach (Collider val in array) { if ((Object)(object)val == (Object)null || !val.enabled) { continue; } BoxCollider val2 = (BoxCollider)(object)((val is BoxCollider) ? val : null); if (val2 != null) { Vector3 size = val2.size; num += size.x * size.y * size.z; continue; } SphereCollider val3 = (SphereCollider)(object)((val is SphereCollider) ? val : null); if (val3 != null) { float radius = val3.radius; num += 4.1887903f * radius * radius * radius; continue; } CapsuleCollider val4 = (CapsuleCollider)(object)((val is CapsuleCollider) ? val : null); if (val4 != null) { float radius2 = val4.radius; float height = val4.height; num += MathF.PI * radius2 * radius2 * height; continue; } MeshCollider val5 = (MeshCollider)(object)((val is MeshCollider) ? val : null); if (val5 != null) { Bounds bounds = ((Collider)val5).bounds; num += ((Bounds)(ref bounds)).size.x * ((Bounds)(ref bounds)).size.y * ((Bounds)(ref bounds)).size.z; } } return Mathf.Max(num, 0.1f); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }