using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; using On.RoR2; using RoR2; using UnityEngine; using UnityEngine.Networking; [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("AutoDroneRecovery")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+78c0535fc0df6fb306204f5d1f8a47dbd986efdd")] [assembly: AssemblyProduct("AutoDroneRecovery")] [assembly: AssemblyTitle("AutoDroneRecovery")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RoR2AutoDroneBuy { [BepInPlugin("NCSGeek.AutoDroneRecovery", "AutoDroneRecovery", "1.1.0")] public class RoR2AutoDronePlugin : BaseUnityPlugin { private class DebugInputHandler : MonoBehaviour { private void Update() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (Input.GetKeyDown((KeyCode)283)) { Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] F2 pressed — running test sequence..." }); ((MonoBehaviour)((Component)this).GetComponent()).StartCoroutine(((Component)this).GetComponent().TestKillDroneAndExit()); } } } [CompilerGenerated] private sealed class d__23 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public RoR2AutoDronePlugin <>4__this; private CharacterMaster 5__2; private GameObject 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Expected O, but got Unknown //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Expected O, but got Unknown //IL_0065: 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_007a: Expected O, but got Unknown //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Expected O, but got Unknown //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Expected O, but got Unknown //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Expected O, but got Unknown //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_045c: Expected O, but got Unknown //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_00fd: Expected O, but got Unknown //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Expected O, but got Unknown //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Expected O, but got Unknown //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Expected O, but got Unknown //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown int num = <>1__state; RoR2AutoDronePlugin roR2AutoDronePlugin = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogInfo((object)"F2 test: Starting test sequence..."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] F2 test starting..." }); if (!NetworkServer.active) { ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogWarning((object)"F2 test: Not running on server."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Not running on server." }); return false; } PlayerCharacterMasterController? obj = ((IEnumerable)PlayerCharacterMasterController.instances).FirstOrDefault((Func)((PlayerCharacterMasterController p) => (Object)(object)p.networkUser != (Object)null && ((NetworkBehaviour)p.networkUser).isLocalPlayer)); 5__2 = ((obj != null) ? obj.master : null); if ((Object)(object)5__2 == (Object)null || (Object)(object)5__2.GetBody() == (Object)null) { ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogWarning((object)"F2 test: No local player body found."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] No local player body found." }); return false; } DroneDef val2 = null; DroneDef[] droneDefs = DroneCatalog.droneDefs; foreach (DroneDef val3 in droneDefs) { if ((Object)(object)val3?.bodyPrefab != (Object)null && val3.nameToken.Contains("HEALING")) { val2 = val3; break; } } if ((Object)(object)val2?.droneBrokenSpawnCard?.prefab == (Object)null) { ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogWarning((object)"F2 test: Could not find healing drone broken spawn card."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Failed to find healing drone def." }); return false; } ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogInfo((object)"F2 test: Spawning broken healing drone at player feet..."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Spawning broken healing drone..." }); Vector3 val4 = 5__2.GetBody().transform.position + Vector3.up * 0.5f; 5__3 = Object.Instantiate(val2.droneBrokenSpawnCard.prefab, val4, Quaternion.identity); <>2__current = null; <>1__state = 1; return true; } case 1: { <>1__state = -1; ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogInfo((object)"F2 test: Purchasing broken drone..."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Purchasing drone..." }); PurchaseInteraction component = 5__3.GetComponent(); if ((Object)(object)component == (Object)null || !roR2AutoDronePlugin.TryBuyDroneFree(component, 5__2)) { ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogWarning((object)"F2 test: Failed to purchase drone."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Failed to purchase drone." }); return false; } ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogInfo((object)"F2 test: Drone purchased. Finding and killing it..."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Drone purchased. Killing it then waiting 7s..." }); CharacterBody val = null; foreach (CharacterMaster instances in CharacterMaster.instancesList) { if (!((Object)(object)((instances != null) ? instances.GetBody() : null) == (Object)null)) { MinionOwnership minionOwnership = instances.minionOwnership; if ((Object)(object)((minionOwnership != null) ? minionOwnership.ownerMaster : null) == (Object)(object)5__2) { val = instances.GetBody(); break; } } } if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogWarning((object)"F2 test: Could not find owned drone to kill."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Could not find owned drone." }); return false; } ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogInfo((object)("F2 test: Killing " + val.baseNameToken + "...")); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Killing owned drone..." }); HealthComponent component2 = ((Component)val).GetComponent(); if (component2 != null) { component2.Suicide(((Component)val).gameObject, (GameObject)null, default(DamageTypeCombo)); } ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogInfo((object)"F2 test: Drone killed. Waiting 7 seconds for it to fall into void..."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Drone killed. Waiting 7s before stage exit..." }); <>2__current = (object)new WaitForSeconds(7f); <>1__state = 2; return true; } case 2: { <>1__state = -1; ((BaseUnityPlugin)roR2AutoDronePlugin).Logger.LogInfo((object)"F2 test: Triggering stage exit now..."); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] Triggering stage exit..." }); TeleporterInteraction instance = TeleporterInteraction.instance; if ((Object)(object)instance != (Object)null) { SceneExitController componentInChildren = ((Component)instance).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.Begin(); } else { Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] No SceneExitController found." }); } } else { Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "[Auto Drone Buy] No teleporter found." }); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGUID = "NCSGeek.AutoDroneRecovery"; public const string PluginAuthor = "NCSGeek"; public const string PluginName = "AutoDroneRecovery"; public const string PluginVersion = "1.1.0"; private static readonly List pendingDeaths = new List(); private static readonly Dictionary bodyToDroneTokenPrefix = new Dictionary(); private static bool droneMappingBuilt; private static readonly Dictionary bodyToDroneDef = new Dictionary(); private static readonly HashSet blacklistedBodies = new HashSet { "BackupDroneBody", "EquipmentDroneBody", "Turret1Body", "EngiTurretBody" }; public static ConfigEntry Debug { get; set; } private void Awake() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown Debug = ((BaseUnityPlugin)this).Config.Bind("General", "Debug", false, "Enables the F2 debug hotkey for testing"); DebugInputHandler debugHandler = ((Component)this).gameObject.AddComponent(); ((Behaviour)debugHandler).enabled = Debug.Value; Debug.SettingChanged += delegate { ((Behaviour)debugHandler).enabled = Debug.Value; }; CharacterDeathBehavior.OnDeath += new hook_OnDeath(OnDroneDeath); PurchaseInteraction.Awake += new hook_Awake(OnBrokenDroneSpawn); SceneExitController.Begin += new hook_Begin(OnSceneExitBegin); Run.onRunStartGlobal += OnRunStart; } private void OnRunStart(Run run) { pendingDeaths.Clear(); BuildDroneTokenMapping(); } private void BuildDroneTokenMapping() { if (droneMappingBuilt) { return; } droneMappingBuilt = true; bodyToDroneTokenPrefix.Clear(); DroneDef[] droneDefs = DroneCatalog.droneDefs; foreach (DroneDef val in droneDefs) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.bodyPrefab == (Object)null)) { string name = ((Object)val.bodyPrefab).name; string nameToken = val.nameToken; if (!string.IsNullOrEmpty(nameToken)) { string text = nameToken.Replace("_NAME", "").Replace("_BODY", ""); bodyToDroneTokenPrefix[name] = text; bodyToDroneDef[name] = val; ((BaseUnityPlugin)this).Logger.LogInfo((object)("DroneMapping: " + name + " -> " + text)); } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"DroneMapping: Built {bodyToDroneTokenPrefix.Count} entries"); } private void OnDroneDeath(orig_OnDeath orig, CharacterDeathBehavior self) { //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); if (!NetworkServer.active) { return; } CharacterBody component = ((Component)self).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.master == (Object)null) { return; } MinionOwnership minionOwnership = component.master.minionOwnership; if (!((Object)(object)minionOwnership != (Object)null) || !((Object)(object)minionOwnership.ownerMaster != (Object)null)) { return; } CharacterMaster ownerMaster = minionOwnership.ownerMaster; if (!((Object)(object)ownerMaster.playerCharacterMasterController != (Object)null)) { return; } string name = ((Object)component.master.bodyPrefab).name; if (!blacklistedBodies.Contains(name)) { CharacterMaster master = component.master; if (!pendingDeaths.Any((PendingDeath d) => d.masterNetId == ((NetworkBehaviour)master).netId)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("OnDroneDeath: Recorded death of " + name + " owned by " + ownerMaster.GetBody()?.baseNameToken)); pendingDeaths.Add(new PendingDeath { bodyPrefabName = name, ownerMaster = ownerMaster, masterNetId = ((NetworkBehaviour)master).netId }); } } } private void OnBrokenDroneSpawn(orig_Awake orig, PurchaseInteraction self) { orig.Invoke(self); if (!NetworkServer.active || (!self.displayNameToken.Contains("DRONE") && !self.displayNameToken.Contains("TURRET"))) { return; } foreach (PendingDeath pendingDeath in pendingDeaths) { if (!pendingDeath.paired && IsDroneTypeMatch(pendingDeath.bodyPrefabName, self.displayNameToken)) { pendingDeath.paired = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("OnBrokenDroneSpawn: Owner of " + pendingDeath.ownerMaster.GetBody()?.baseNameToken + " assigned to " + self.displayNameToken)); ((Component)self).gameObject.AddComponent().ownerMaster = pendingDeath.ownerMaster; break; } } } private bool IsDroneTypeMatch(string bodyPrefabName, string displayNameToken) { if (bodyToDroneTokenPrefix.TryGetValue(bodyPrefabName, out var value)) { return displayNameToken.StartsWith(value, StringComparison.OrdinalIgnoreCase); } string value2 = bodyPrefabName.Replace("Body", "").ToUpperInvariant(); return displayNameToken.Contains(value2); } private void OnSceneExitBegin(orig_Begin orig, SceneExitController self) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active) { List list = new List(); Vector3 val = (Object.op_Implicit((Object)(object)TeleporterInteraction.instance) ? ((Component)TeleporterInteraction.instance).transform.position : Vector3.zero); foreach (PurchaseInteraction item in (from d in InstanceTracker.GetInstancesList() where d.displayNameToken.Contains("DRONE") || d.displayNameToken.Contains("TURRET") select d).ToList()) { DroneOwnerTracker component = ((Component)item).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.ownerMaster == (Object)null) { continue; } CharacterMaster ownerMaster = component.ownerMaster; ((BaseUnityPlugin)this).Logger.LogInfo((object)("OnSceneExitBegin: Processing " + item.displayNameToken + " owned by " + (ownerMaster.GetBody()?.baseNameToken ?? "dead player"))); if (ownerMaster.IsDeadAndOutOfLivesServer()) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"OnSceneExitBegin: Owner is dead, attempting revive at teleporter"); if (!TryRevivePlayer(ownerMaster, val)) { list.Add("Owner of " + item.displayNameToken + " could not be revived"); continue; } } if (!TryBuyDroneFree(item, ownerMaster)) { list.Add("Failed to revive " + item.displayNameToken); } } foreach (PendingDeath pendingDeath in pendingDeaths) { if (pendingDeath.paired) { continue; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("OnSceneExitBegin: Unpaired death for " + pendingDeath.bodyPrefabName + " — spawning broken interactable at teleporter")); DroneDef value; if (pendingDeath.ownerMaster.IsDeadAndOutOfLivesServer() && !TryRevivePlayer(pendingDeath.ownerMaster, val)) { list.Add("Owner of unrecoverable drone " + pendingDeath.bodyPrefabName + " could not be revived"); } else if (bodyToDroneDef.TryGetValue(pendingDeath.bodyPrefabName, out value) && (Object)(object)value.droneBrokenSpawnCard?.prefab != (Object)null) { GameObject obj = Object.Instantiate(value.droneBrokenSpawnCard.prefab, val, Quaternion.identity); obj.AddComponent().ownerMaster = pendingDeath.ownerMaster; PurchaseInteraction component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null && !TryBuyDroneFree(component2, pendingDeath.ownerMaster)) { list.Add("Failed to buy unrecoverable " + pendingDeath.bodyPrefabName); } } else { list.Add("No broken spawn card for unrecoverable drone: " + pendingDeath.bodyPrefabName); } } if (list.Count > 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"AutoDroneRecovery: {list.Count} failure(s):"); foreach (string item2 in list) { ((BaseUnityPlugin)this).Logger.LogWarning((object)(" - " + item2)); } } pendingDeaths.Clear(); } orig.Invoke(self); } private bool TryRevivePlayer(CharacterMaster playerMaster, Vector3 spawnPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { playerMaster.Respawn(spawnPosition, Quaternion.identity, false); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to revive player: " + ex.Message)); return false; } } private bool TryBuyDroneFree(PurchaseInteraction drone, CharacterMaster owner) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)drone == (Object)null || (Object)(object)owner == (Object)null) { return false; } CharacterBody body = owner.GetBody(); Interactor val = ((body != null) ? ((Component)body).GetComponent() : null); if ((Object)(object)val == (Object)null) { return false; } int cost = drone.cost; CostTypeIndex costType = drone.costType; drone.cost = 0; drone.costType = (CostTypeIndex)1; drone.OnInteractionBegin(val); drone.cost = cost; drone.costType = costType; return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to buy drone: " + ex.Message)); return false; } } [IteratorStateMachine(typeof(d__23))] private IEnumerator TestKillDroneAndExit() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__23(0) { <>4__this = this }; } } public class PendingDeath { public string bodyPrefabName; public CharacterMaster ownerMaster; public bool paired; public NetworkInstanceId masterNetId; } public class DroneOwnerTracker : MonoBehaviour { public CharacterMaster ownerMaster; } }