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 BetterEquipmentDrone v1.0.1
BetterEquipmentDrone/BetterEquipmentDronePlugin.dll
Decompiled 8 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.GoldGat; using HG.Reflection; using Microsoft.CodeAnalysis; using On.EntityStates.GoldGat; using On.RoR2; using On.RoR2.Items; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Orbs; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BetterEquipmentDronePlugin")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a69bc379391abbe0b438e7eb07c28555c6634dae")] [assembly: AssemblyProduct("BetterEquipmentDronePlugin")] [assembly: AssemblyTitle("BetterEquipmentDronePlugin")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BetterEquipmentDronePlugin { internal static class CrowdfunderSupport { [CompilerGenerated] private static class <>O { public static hook_OnEnter <0>__BaseGoldGatState_OnEnter; public static hook_FixedUpdate <1>__BaseGoldGatState_FixedUpdate; public static Action<Run> <2>__Run_onRunStartGlobal; } private const string BodyMasterFieldName = "bodyMaster"; private const string ToggleCommandName = "bed_toggle_crowdfunder"; private static FieldInfo bodyMasterField; private static readonly HashSet<CharacterMaster> ownersFiring = new HashSet<CharacterMaster>(); internal static void SubmitToggleForLocalPlayer() { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); NetworkUser val = ((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)Console.instance)) { Console.instance.SubmitCmd(val, "bed_toggle_crowdfunder", false); } } [ConCommand(/*Could not decode attribute arguments.*/)] public static void CCToggleCrowdfunder(ConCommandArgs args) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) CharacterMaster val = (Object.op_Implicit((Object)(object)args.sender) ? args.sender.master : null); if (Object.op_Implicit((Object)(object)val)) { bool flag = !ownersFiring.Remove(val); if (flag) { ownersFiring.Add(val); } SimpleChatMessage val2 = new SimpleChatMessage(); val2.baseToken = "<style=cIsUtility>{0}: drone Crowdfunder {1}.</style>"; val2.paramTokens = new string[2] { args.sender.userName, flag ? "firing" : "holding" }; Chat.SendBroadcastChat((ChatMessageBase)(object)val2); } } internal static void Init() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown bodyMasterField = typeof(BaseGoldGatState).GetField("bodyMaster", BindingFlags.Instance | BindingFlags.NonPublic); if (bodyMasterField == null || bodyMasterField.FieldType != typeof(CharacterMaster)) { Log.Warning("BaseGoldGatState.bodyMaster not found or changed type. The Crowdfunder will keep vanilla behaviour on drones."); bodyMasterField = null; return; } object obj = <>O.<0>__BaseGoldGatState_OnEnter; if (obj == null) { hook_OnEnter val = BaseGoldGatState_OnEnter; <>O.<0>__BaseGoldGatState_OnEnter = val; obj = (object)val; } BaseGoldGatState.OnEnter += (hook_OnEnter)obj; object obj2 = <>O.<1>__BaseGoldGatState_FixedUpdate; if (obj2 == null) { hook_FixedUpdate val2 = BaseGoldGatState_FixedUpdate; <>O.<1>__BaseGoldGatState_FixedUpdate = val2; obj2 = (object)val2; } BaseGoldGatState.FixedUpdate += (hook_FixedUpdate)obj2; Run.onRunStartGlobal += Run_onRunStartGlobal; } private static void Run_onRunStartGlobal(Run run) { ownersFiring.Clear(); } internal static void Dispose() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //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_0049: Expected O, but got Unknown if (!(bodyMasterField == null)) { object obj = <>O.<0>__BaseGoldGatState_OnEnter; if (obj == null) { hook_OnEnter val = BaseGoldGatState_OnEnter; <>O.<0>__BaseGoldGatState_OnEnter = val; obj = (object)val; } BaseGoldGatState.OnEnter -= (hook_OnEnter)obj; object obj2 = <>O.<1>__BaseGoldGatState_FixedUpdate; if (obj2 == null) { hook_FixedUpdate val2 = BaseGoldGatState_FixedUpdate; <>O.<1>__BaseGoldGatState_FixedUpdate = val2; obj2 = (object)val2; } BaseGoldGatState.FixedUpdate -= (hook_FixedUpdate)obj2; Run.onRunStartGlobal -= Run_onRunStartGlobal; ownersFiring.Clear(); } } private static void BaseGoldGatState_OnEnter(orig_OnEnter orig, BaseGoldGatState self) { orig.Invoke(self); CharacterBody droneBody; CharacterMaster droneOwner = GetDroneOwner(self, out droneBody); if (Object.op_Implicit((Object)(object)droneOwner)) { bodyMasterField.SetValue(self, droneOwner); } } private static void BaseGoldGatState_FixedUpdate(orig_FixedUpdate orig, BaseGoldGatState self) { orig.Invoke(self); CharacterBody droneBody; CharacterMaster droneOwner = GetDroneOwner(self, out droneBody); if (Object.op_Implicit((Object)(object)droneOwner)) { bool flag = ownersFiring.Contains(droneOwner) && !droneBody.outOfCombat && droneOwner.money != 0; if (self.shouldFire != flag) { self.shouldFire = flag; Log.Debug($"Crowdfunder on '{((Object)droneBody).name}': shouldFire={flag} " + $"(owner '{DroneEquipmentOwnership.Describe(droneOwner)}' money={droneOwner.money})."); } } } private static CharacterMaster GetDroneOwner(BaseGoldGatState self, out CharacterBody droneBody) { droneBody = null; if (bodyMasterField == null || !NetworkServer.active) { return null; } if (BetterEquipmentDrone.modEnabled == null || !BetterEquipmentDrone.modEnabled.Value) { return null; } NetworkedBodyAttachment val = (Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).GetComponent<NetworkedBodyAttachment>() : null); CharacterBody val2 = (Object.op_Implicit((Object)(object)val) ? val.attachedBody : null); if (!Object.op_Implicit((Object)(object)val2)) { return null; } CharacterMaster playerOwner = DroneEquipmentOwnership.GetPlayerOwner(val2.master); if (!Object.op_Implicit((Object)(object)playerOwner)) { return null; } droneBody = val2; return playerOwner; } } internal static class DroneCooldown { [CompilerGenerated] private static class <>O { public static hook_CalculateEquipmentCooldownScale <0>__Inventory_CalculateEquipmentCooldownScale; } internal static void Init() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__Inventory_CalculateEquipmentCooldownScale; if (obj == null) { hook_CalculateEquipmentCooldownScale val = Inventory_CalculateEquipmentCooldownScale; <>O.<0>__Inventory_CalculateEquipmentCooldownScale = val; obj = (object)val; } Inventory.CalculateEquipmentCooldownScale += (hook_CalculateEquipmentCooldownScale)obj; } internal static void Dispose() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__Inventory_CalculateEquipmentCooldownScale; if (obj == null) { hook_CalculateEquipmentCooldownScale val = Inventory_CalculateEquipmentCooldownScale; <>O.<0>__Inventory_CalculateEquipmentCooldownScale = val; obj = (object)val; } Inventory.CalculateEquipmentCooldownScale -= (hook_CalculateEquipmentCooldownScale)obj; } private static float Inventory_CalculateEquipmentCooldownScale(orig_CalculateEquipmentCooldownScale orig, Inventory self) { float num = orig.Invoke(self); if (BetterEquipmentDrone.modEnabled == null || !BetterEquipmentDrone.modEnabled.Value) { return num; } CharacterMaster val = (Object.op_Implicit((Object)(object)self) ? ((Component)self).GetComponent<CharacterMaster>() : null); if (!Object.op_Implicit((Object)(object)val)) { return num; } CharacterMaster playerOwner = DroneEquipmentOwnership.GetPlayerOwner(val); if (!Object.op_Implicit((Object)(object)playerOwner)) { return num; } if ((BetterEquipmentDrone.matchOwnerCooldown == null || BetterEquipmentDrone.matchOwnerCooldown.Value) && Object.op_Implicit((Object)(object)playerOwner.inventory) && (Object)(object)playerOwner.inventory != (Object)(object)self) { num = orig.Invoke(playerOwner.inventory); } int num2 = BetterEquipmentDrone.cooldownPercent?.Value ?? 100; if (num2 != 100) { num *= (float)num2 / 100f; } return num; } } public class DroneEquipmentOwnership : MonoBehaviour { private const int MaxOwnerChainDepth = 8; private CharacterMaster rememberedOwner; public CharacterMaster RememberedOwner { get { if (!Object.op_Implicit((Object)(object)rememberedOwner)) { return null; } return rememberedOwner; } } public void Remember(CharacterMaster owner) { CharacterMaster val = ResolveRoot(owner); if (Object.op_Implicit((Object)(object)val)) { rememberedOwner = val; Log.Debug("Drone '" + ((Object)this).name + "' recruited by '" + Describe(val) + "'."); } } public static CharacterMaster GetPlayerOwner(CharacterMaster minionMaster) { if (!Object.op_Implicit((Object)(object)minionMaster) || Object.op_Implicit((Object)(object)minionMaster.playerCharacterMasterController) || !IsInScope(minionMaster)) { return null; } CharacterMaster ownerMaster = GetOwnerMaster(minionMaster); if (!Object.op_Implicit((Object)(object)ownerMaster) || (Object)(object)ownerMaster == (Object)(object)minionMaster || !Object.op_Implicit((Object)(object)ownerMaster.playerCharacterMasterController)) { return null; } return ownerMaster; } internal static IEnumerable<CharacterMaster> ManagedDronesOf(CharacterMaster owner) { MinionGroup val = MinionGroup.FindGroup(((NetworkBehaviour)owner).netId); if (val == null) { yield break; } MinionOwnership[] members = val.members; foreach (MinionOwnership val2 in members) { if (Object.op_Implicit((Object)(object)val2)) { CharacterMaster component = ((Component)val2).GetComponent<CharacterMaster>(); if (Object.op_Implicit((Object)(object)component) && (Object)(object)GetPlayerOwner(component) == (Object)(object)owner) { yield return component; } } } } private static bool IsInScope(CharacterMaster master) { //IL_0022: 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) if (BetterEquipmentDrone.allDrones == null || BetterEquipmentDrone.allDrones.Value) { return true; } if (((MasterIndex)(ref BetterEquipmentDrone.equipmentDroneIndex)).isValid) { return master.masterIndex == BetterEquipmentDrone.equipmentDroneIndex; } return false; } public static CharacterMaster GetOwnerMaster(CharacterMaster droneMaster) { if (!Object.op_Implicit((Object)(object)droneMaster)) { return null; } DroneEquipmentOwnership component = ((Component)droneMaster).GetComponent<DroneEquipmentOwnership>(); CharacterMaster val = (Object.op_Implicit((Object)(object)component) ? component.RememberedOwner : null); if (Object.op_Implicit((Object)(object)val)) { return val; } CharacterMaster val2 = ResolveRoot(Object.op_Implicit((Object)(object)droneMaster.minionOwnership) ? droneMaster.minionOwnership.ownerMaster : null); if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)component)) { component.rememberedOwner = val2; } return val2; } private static CharacterMaster ResolveRoot(CharacterMaster master) { CharacterMaster val = master; for (int i = 0; i < 8; i++) { if (!Object.op_Implicit((Object)(object)val)) { break; } if (Object.op_Implicit((Object)(object)val.playerCharacterMasterController)) { return val; } CharacterMaster val2 = (Object.op_Implicit((Object)(object)val.minionOwnership) ? val.minionOwnership.ownerMaster : null); if (!Object.op_Implicit((Object)(object)val2) || (Object)(object)val2 == (Object)(object)val) { break; } val = val2; } if (!Object.op_Implicit((Object)(object)val)) { return null; } return val; } internal static string Describe(CharacterMaster master) { if (!Object.op_Implicit((Object)(object)master)) { return "<none>"; } PlayerCharacterMasterController playerCharacterMasterController = master.playerCharacterMasterController; string text = ((playerCharacterMasterController == null) ? null : playerCharacterMasterController.networkUser?.userName); if (!string.IsNullOrEmpty(text)) { return text; } return ((Object)master).name; } } internal static class DroneTargeting { private class OwnerIndicator : MonoBehaviour { private Indicator indicator; private GameObject ownerObject; public void Show(GameObject ownerBodyObject, GameObject visualizerPrefab, Transform target) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown if (indicator != null && (Object)(object)ownerObject != (Object)(object)ownerBodyObject) { Hide(); } if (!Object.op_Implicit((Object)(object)ownerBodyObject) || !Object.op_Implicit((Object)(object)visualizerPrefab) || !Object.op_Implicit((Object)(object)target)) { Hide(); return; } if (indicator == null) { indicator = new Indicator(ownerBodyObject, visualizerPrefab); ownerObject = ownerBodyObject; } indicator.visualizerPrefab = visualizerPrefab; indicator.targetTransform = target; indicator.active = true; } public void Hide() { if (indicator != null) { indicator.active = false; indicator = null; ownerObject = null; } } private void OnDestroy() { Hide(); } } [CompilerGenerated] private static class <>O { public static hook_UpdateTargets <0>__EquipmentSlot_UpdateTargets; } private const string CurrentTargetFieldName = "currentTarget"; private const string TargetInfoTypeName = "UserTargetInfo"; private const string FindPickupControllerName = "FindPickupController"; private const float PickupMaxAngle = 10f; private const float PickupMaxDistance = 30f; private const float BossMaxAngle = 10f; private static FieldInfo currentTargetField; private static ConstructorInfo hurtBoxTargetConstructor; private static ConstructorInfo pickupTargetConstructor; private static MethodInfo findPickupController; private static readonly BullseyeSearch bossSearch = new BullseyeSearch(); private static EquipmentSlot redirectDroneSlot; private static EquipmentSlot redirectOwnerSlot; private static bool Ready => currentTargetField != null; internal static void BeginRedirect(EquipmentSlot droneSlot, EquipmentSlot ownerSlot, EquipmentDef equipmentDef) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) redirectDroneSlot = droneSlot; redirectOwnerSlot = ownerSlot; if (Ready && Object.op_Implicit((Object)(object)ownerSlot) && !((Object)(object)equipmentDef == (Object)null) && ((Object)(object)equipmentDef == (Object)(object)Equipment.Recycle || (Object)(object)equipmentDef == (Object)(object)Equipment.BossHunter)) { SubstituteRedirectedTarget(ownerSlot, droneSlot, equipmentDef.equipmentIndex); } } internal static void EndRedirect() { redirectDroneSlot = null; redirectOwnerSlot = null; } internal static void Init() { //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown Type typeFromHandle = typeof(EquipmentSlot); currentTargetField = typeFromHandle.GetField("currentTarget", BindingFlags.Instance | BindingFlags.NonPublic); Type nestedType = typeFromHandle.GetNestedType("UserTargetInfo", BindingFlags.Public | BindingFlags.NonPublic); hurtBoxTargetConstructor = nestedType?.GetConstructor(new Type[1] { typeof(HurtBox) }); pickupTargetConstructor = nestedType?.GetConstructor(new Type[1] { typeof(GenericPickupController) }); findPickupController = typeFromHandle.GetMethod("FindPickupController", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[5] { typeof(Ray), typeof(float), typeof(float), typeof(bool), typeof(bool) }, null); if (currentTargetField == null || hurtBoxTargetConstructor == null || pickupTargetConstructor == null || findPickupController == null) { Log.Warning("EquipmentSlot targeting internals not found; drones will keep vanilla targeting. Looked for currentTarget, UserTargetInfo constructors and FindPickupController."); currentTargetField = null; return; } object obj = <>O.<0>__EquipmentSlot_UpdateTargets; if (obj == null) { hook_UpdateTargets val = EquipmentSlot_UpdateTargets; <>O.<0>__EquipmentSlot_UpdateTargets = val; obj = (object)val; } EquipmentSlot.UpdateTargets += (hook_UpdateTargets)obj; } internal static void Dispose() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (Ready) { object obj = <>O.<0>__EquipmentSlot_UpdateTargets; if (obj == null) { hook_UpdateTargets val = EquipmentSlot_UpdateTargets; <>O.<0>__EquipmentSlot_UpdateTargets = val; obj = (object)val; } EquipmentSlot.UpdateTargets -= (hook_UpdateTargets)obj; } } private static void SubstituteRedirectedTarget(EquipmentSlot ownerSlot, EquipmentSlot droneSlot, EquipmentIndex targetingEquipmentIndex) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) CharacterBody characterBody = ownerSlot.characterBody; CharacterBody val = (Object.op_Implicit((Object)(object)droneSlot) ? droneSlot.characterBody : null); if (Object.op_Implicit((Object)(object)characterBody) && Object.op_Implicit((Object)(object)characterBody.inputBank) && Object.op_Implicit((Object)(object)val)) { Ray aimRay = AimRayOf(characterBody); if (targetingEquipmentIndex == Equipment.Recycle.equipmentIndex) { GenericPickupController val2 = FindPickup(droneSlot, aimRay); SetTarget(ownerSlot, val2); Log.Debug("Recycler target for '" + ((Object)characterBody).name + "': " + (Object.op_Implicit((Object)(object)val2) ? ((Object)val2).name : "none") + "."); } else if (targetingEquipmentIndex == Equipment.BossHunter.equipmentIndex) { HurtBox val3 = AliveOrNull(FindRewardingBoss(val, characterBody, aimRay)); SetTarget(ownerSlot, val3); Log.Debug("Tricorn target for '" + ((Object)characterBody).name + "': " + ((Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val3.healthComponent)) ? ((Object)val3.healthComponent.body).name : "none") + "."); } } } private static void EquipmentSlot_UpdateTargets(orig_UpdateTargets orig, EquipmentSlot self, EquipmentIndex targetingEquipmentIndex, bool userShouldAnticipateTarget) { //IL_0002: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_00ef: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self, targetingEquipmentIndex, userShouldAnticipateTarget); if (!Ready || BetterEquipmentDrone.modEnabled == null || !BetterEquipmentDrone.modEnabled.Value) { return; } if (Object.op_Implicit((Object)(object)redirectOwnerSlot) && (Object)(object)self == (Object)(object)redirectOwnerSlot) { SubstituteRedirectedTarget(self, redirectDroneSlot, targetingEquipmentIndex); return; } CharacterBody val = (Object.op_Implicit((Object)(object)self) ? self.characterBody : null); CharacterMaster val2 = (Object.op_Implicit((Object)(object)val) ? DroneEquipmentOwnership.GetPlayerOwner(val.master) : null); if (!Object.op_Implicit((Object)(object)val2)) { return; } if (!DrivesIndicator(targetingEquipmentIndex)) { ClearIndicator(self); } CharacterBody body = val2.GetBody(); if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inputBank)) { ClearIndicator(self); } else if (NetworkServer.active || Util.HasEffectiveAuthority(((Component)body).gameObject)) { Ray aimRay = AimRayOf(body); if (targetingEquipmentIndex == Equipment.Recycle.equipmentIndex) { ApplyRecyclerTarget(self, body, aimRay); } else if (targetingEquipmentIndex == Equipment.BossHunter.equipmentIndex) { ApplyTricornTarget(self, val, body, aimRay); } else if (targetingEquipmentIndex == Equipment.PassiveHealing.equipmentIndex) { ApplyWoodspriteTarget(self, val); } } } private static bool DrivesIndicator(EquipmentIndex targetingEquipmentIndex) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (targetingEquipmentIndex != Equipment.Recycle.equipmentIndex) { return targetingEquipmentIndex == Equipment.BossHunter.equipmentIndex; } return true; } private static void ApplyRecyclerTarget(EquipmentSlot slot, CharacterBody ownerBody, Ray aimRay) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) GenericPickupController val = FindPickup(slot, aimRay); SetTarget(slot, val); GameObject visualizerPrefab = null; Transform target = null; if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.pickupDisplay)) { visualizerPrefab = LegacyResourcesAPI.Load<GameObject>(val.Recycled ? "Prefabs/RecyclerBadIndicator" : "Prefabs/RecyclerIndicator"); target = ((Component)val.pickupDisplay).transform; } IndicatorFor(slot).Show(((Component)ownerBody).gameObject, visualizerPrefab, target); } private static void ApplyTricornTarget(EquipmentSlot slot, CharacterBody droneBody, CharacterBody ownerBody, Ray aimRay) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (BetterEquipmentDrone.tricornAimsWithOwner == null || !BetterEquipmentDrone.tricornAimsWithOwner.Value) { ApplySelfAimedTricornTarget(slot, droneBody); return; } HurtBox val = AliveOrNull(FindRewardingBoss(droneBody, ownerBody, aimRay)); SetTarget(slot, val); GameObject visualizerPrefab = (Object.op_Implicit((Object)(object)val) ? LegacyResourcesAPI.Load<GameObject>("Prefabs/BossHunterIndicator") : null); IndicatorFor(slot).Show(((Component)ownerBody).gameObject, visualizerPrefab, Object.op_Implicit((Object)(object)val) ? ((Component)val).transform : null); } private static void ApplySelfAimedTricornTarget(EquipmentSlot slot, CharacterBody droneBody) { ClearIndicator(slot); if (NetworkServer.active) { SetTarget(slot, FindRewardingBossAround(droneBody)); } } private static HurtBox FindRewardingBoss(CharacterBody droneBody, CharacterBody ownerBody, Ray aimRay) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) ConfigureBossSearch(droneBody, ((Ray)(ref aimRay)).origin, ((Ray)(ref aimRay)).direction, 10f, (SortMode)2, ownerBody); return FirstRewardingBoss(); } private static HurtBox FindRewardingBossAround(CharacterBody droneBody) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Vector3 direction = (Object.op_Implicit((Object)(object)droneBody.inputBank) ? droneBody.inputBank.aimDirection : droneBody.transform.forward); ConfigureBossSearch(droneBody, droneBody.corePosition, direction, 180f, (SortMode)1, droneBody); return AliveOrNull(FirstRewardingBoss()); } private static void ConfigureBossSearch(CharacterBody droneBody, Vector3 origin, Vector3 direction, float maxAngle, SortMode sortMode, CharacterBody viewer) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) TeamIndex val = (TeamIndex)((!Object.op_Implicit((Object)(object)droneBody.teamComponent)) ? 1 : ((int)droneBody.teamComponent.teamIndex)); bossSearch.teamMaskFilter = TeamMask.GetUnprotectedTeams(val); bossSearch.sortMode = sortMode; bossSearch.filterByLoS = true; bossSearch.searchOrigin = origin; bossSearch.searchDirection = direction; bossSearch.maxAngleFilter = maxAngle; bossSearch.maxDistanceFilter = float.PositiveInfinity; bossSearch.viewer = viewer; bossSearch.RefreshCandidates(); bossSearch.FilterOutGameObject(((Component)droneBody).gameObject); } private static HurtBox FirstRewardingBoss() { foreach (HurtBox result in bossSearch.GetResults()) { CharacterBody val = ((Object.op_Implicit((Object)(object)result) && Object.op_Implicit((Object)(object)result.healthComponent)) ? result.healthComponent.body : null); if (Object.op_Implicit((Object)(object)val)) { DeathRewards component = ((Component)val).GetComponent<DeathRewards>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.bossDropTable) && !val.HasBuff(Buffs.Immune)) { return result; } } } return null; } private static void ApplyWoodspriteTarget(EquipmentSlot slot, CharacterBody droneBody) { CharacterBody val = FindMostHurtPlayer(droneBody); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.mainHurtBox)) { SetTarget(slot, val.mainHurtBox); } } private static Ray AimRayOf(CharacterBody body) { //IL_0006: 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_0016: Unknown result type (might be due to invalid IL or missing references) return new Ray(body.inputBank.aimOrigin, body.inputBank.aimDirection); } private static GenericPickupController FindPickup(EquipmentSlot searchSlot, Ray aimRay) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) object? obj = findPickupController.Invoke(searchSlot, new object[5] { aimRay, 10f, 30f, true, true }); return (GenericPickupController)((obj is GenericPickupController) ? obj : null); } private static HurtBox AliveOrNull(HurtBox hurtBox) { if (!Object.op_Implicit((Object)(object)hurtBox) || !Object.op_Implicit((Object)(object)hurtBox.healthComponent) || !hurtBox.healthComponent.alive) { return null; } return hurtBox; } private static void SetTarget(EquipmentSlot slot, HurtBox hurtBox) { currentTargetField.SetValue(slot, hurtBoxTargetConstructor.Invoke(new object[1] { hurtBox })); } private static void SetTarget(EquipmentSlot slot, GenericPickupController pickup) { currentTargetField.SetValue(slot, pickupTargetConstructor.Invoke(new object[1] { pickup })); } private static OwnerIndicator IndicatorFor(EquipmentSlot slot) { return ((Component)slot).GetComponent<OwnerIndicator>() ?? ((Component)slot).gameObject.AddComponent<OwnerIndicator>(); } private static void ClearIndicator(EquipmentSlot slot) { ((Component)slot).GetComponent<OwnerIndicator>()?.Hide(); } private static CharacterBody FindMostHurtPlayer(CharacterBody droneBody) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)droneBody)) { return null; } TeamIndex val = (TeamIndex)((!Object.op_Implicit((Object)(object)droneBody.teamComponent)) ? 1 : ((int)droneBody.teamComponent.teamIndex)); CharacterBody result = null; float num = float.MaxValue; foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { CharacterBody val2 = ((Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.master)) ? instance.master.GetBody() : null); if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.healthComponent) && val2.healthComponent.alive && (!Object.op_Implicit((Object)(object)val2.teamComponent) || val2.teamComponent.teamIndex == val)) { float healthFraction = val2.healthComponent.healthFraction; if (healthFraction < num) { num = healthFraction; result = val2; } } } return result; } } internal static class EquipmentRedirector { [CompilerGenerated] private static class <>O { public static hook_OpenSummonReturnMaster <0>__SummonMasterBehavior_OpenSummonReturnMaster; public static hook_PerformEquipmentAction <1>__EquipmentSlot_PerformEquipmentAction; } private static readonly HashSet<EquipmentDef> blocked = new HashSet<EquipmentDef>(); private static readonly HashSet<EquipmentDef> dualApply = new HashSet<EquipmentDef>(); private static bool redirecting; internal static void Init() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown object obj = <>O.<0>__SummonMasterBehavior_OpenSummonReturnMaster; if (obj == null) { hook_OpenSummonReturnMaster val = SummonMasterBehavior_OpenSummonReturnMaster; <>O.<0>__SummonMasterBehavior_OpenSummonReturnMaster = val; obj = (object)val; } SummonMasterBehavior.OpenSummonReturnMaster += (hook_OpenSummonReturnMaster)obj; object obj2 = <>O.<1>__EquipmentSlot_PerformEquipmentAction; if (obj2 == null) { hook_PerformEquipmentAction val2 = EquipmentSlot_PerformEquipmentAction; <>O.<1>__EquipmentSlot_PerformEquipmentAction = val2; obj2 = (object)val2; } EquipmentSlot.PerformEquipmentAction += (hook_PerformEquipmentAction)obj2; } internal static void Dispose() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown object obj = <>O.<0>__SummonMasterBehavior_OpenSummonReturnMaster; if (obj == null) { hook_OpenSummonReturnMaster val = SummonMasterBehavior_OpenSummonReturnMaster; <>O.<0>__SummonMasterBehavior_OpenSummonReturnMaster = val; obj = (object)val; } SummonMasterBehavior.OpenSummonReturnMaster -= (hook_OpenSummonReturnMaster)obj; object obj2 = <>O.<1>__EquipmentSlot_PerformEquipmentAction; if (obj2 == null) { hook_PerformEquipmentAction val2 = EquipmentSlot_PerformEquipmentAction; <>O.<1>__EquipmentSlot_PerformEquipmentAction = val2; obj2 = (object)val2; } EquipmentSlot.PerformEquipmentAction -= (hook_PerformEquipmentAction)obj2; } private static CharacterMaster SummonMasterBehavior_OpenSummonReturnMaster(orig_OpenSummonReturnMaster orig, SummonMasterBehavior self, Interactor activator) { CharacterMaster val = orig.Invoke(self, activator); if (!NetworkServer.active || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)activator)) { return val; } CharacterBody component = ((Component)activator).GetComponent<CharacterBody>(); CharacterMaster val2 = ((component != null) ? component.master : null); if (Object.op_Implicit((Object)(object)val2)) { (((Component)val).GetComponent<DroneEquipmentOwnership>() ?? ((Component)val).gameObject.AddComponent<DroneEquipmentOwnership>()).Remember(val2); } return val; } private static bool EquipmentSlot_PerformEquipmentAction(orig_PerformEquipmentAction orig, EquipmentSlot self, EquipmentDef equipmentDef) { CharacterMaster managedOwner = GetManagedOwner(self, equipmentDef); if (Object.op_Implicit((Object)(object)managedOwner) && ManualTrigger.IsGated(equipmentDef) && !ManualTrigger.WasRequestedBy(managedOwner)) { return false; } bool flag = (Object.op_Implicit((Object)(object)managedOwner) ? PerformForDrone(orig, self, equipmentDef, managedOwner) : orig.Invoke(self, equipmentDef)); if (Object.op_Implicit((Object)(object)managedOwner) && flag) { ItemMirroring.OnDroneEquipmentUsed(managedOwner); } return flag; } private static bool PerformForDrone(orig_PerformEquipmentAction orig, EquipmentSlot self, EquipmentDef equipmentDef, CharacterMaster ownerMaster) { if (!ShouldRedirect(self, equipmentDef, ownerMaster, out var ownerSlot)) { return orig.Invoke(self, equipmentDef); } try { redirecting = true; DroneTargeting.BeginRedirect(self, ownerSlot, equipmentDef); if ((Object)(object)equipmentDef == (Object)(object)Equipment.BossHunter) { bool flag = TricornSupport.Perform(orig, self, ownerSlot, equipmentDef); string[] obj = new string[6] { "Redirected '", ((Object)equipmentDef).name, "' from drone '", null, null, null }; CharacterBody characterBody = self.characterBody; obj[3] = ((characterBody != null) ? ((Object)characterBody).name : null); obj[4] = "' "; obj[5] = $"to '{DroneEquipmentOwnership.Describe(ownerMaster)}' (performed={flag})."; Log.Debug(string.Concat(obj)); return flag; } bool flag2 = orig.Invoke(ownerSlot, equipmentDef); if (dualApply.Contains(equipmentDef)) { flag2 |= orig.Invoke(self, equipmentDef); } string[] obj2 = new string[8] { "Redirected '", ((Object)equipmentDef).name, "' from drone '", null, null, null, null, null }; CharacterBody characterBody2 = self.characterBody; obj2[3] = ((characterBody2 != null) ? ((Object)characterBody2).name : null); obj2[4] = "' to '"; CharacterBody characterBody3 = ownerSlot.characterBody; obj2[5] = DroneEquipmentOwnership.Describe((characterBody3 != null) ? characterBody3.master : null); obj2[6] = "' "; obj2[7] = $"(dual={dualApply.Contains(equipmentDef)}, performed={flag2})."; Log.Debug(string.Concat(obj2)); return flag2; } finally { DroneTargeting.EndRedirect(); redirecting = false; } } private static CharacterMaster GetManagedOwner(EquipmentSlot slot, EquipmentDef equipmentDef) { if (redirecting || !NetworkServer.active || (Object)(object)equipmentDef == (Object)null || !Object.op_Implicit((Object)(object)slot)) { return null; } if (BetterEquipmentDrone.modEnabled == null || !BetterEquipmentDrone.modEnabled.Value) { return null; } CharacterBody characterBody = slot.characterBody; if (!Object.op_Implicit((Object)(object)characterBody)) { return null; } return DroneEquipmentOwnership.GetPlayerOwner(characterBody.master); } private static bool ShouldRedirect(EquipmentSlot slot, EquipmentDef equipmentDef, CharacterMaster ownerMaster, out EquipmentSlot ownerSlot) { ownerSlot = null; CharacterBody characterBody = slot.characterBody; if (!Object.op_Implicit((Object)(object)characterBody)) { return false; } if ((Object)(object)equipmentDef == (Object)(object)Equipment.BossHunter && BetterEquipmentDrone.tricornAimsWithOwner != null && !BetterEquipmentDrone.tricornAimsWithOwner.Value) { return false; } if ((Object)(object)equipmentDef == (Object)(object)Equipment.Meteor && BetterEquipmentDrone.meteoriteFromOwner != null && !BetterEquipmentDrone.meteoriteFromOwner.Value) { return false; } if (blocked.Contains(equipmentDef)) { Log.Debug("Not redirecting '" + ((Object)equipmentDef).name + "' from '" + ((Object)characterBody).name + "': on the blocklist."); return false; } CharacterBody body = ownerMaster.GetBody(); if (!Object.op_Implicit((Object)(object)body) || (Object)(object)body == (Object)(object)characterBody || !Object.op_Implicit((Object)(object)body.healthComponent) || !body.healthComponent.alive) { Log.Debug("Not redirecting '" + ((Object)equipmentDef).name + "' from '" + ((Object)characterBody).name + "': owner has no live body."); return false; } ownerSlot = body.equipmentSlot; if (!Object.op_Implicit((Object)(object)ownerSlot) || (Object)(object)ownerSlot == (Object)(object)slot) { Log.Debug("Not redirecting '" + ((Object)equipmentDef).name + "' from '" + ((Object)characterBody).name + "': owner has no equipment slot."); return false; } return true; } internal static void BuildEquipmentSets() { blocked.Clear(); dualApply.Clear(); Add(blocked, Equipment.DroneShockDamage); Add(blocked, Equipment.CommandMissile); Add(blocked, Equipment.PassiveHealing); Add(blocked, Equipment.HealAndRevive); Add(blocked, Equipment.BurnNearby); Add(blocked, Equipment.Tonic); Add(blocked, Equipment.FireBallDash); Add(blocked, Equipment.Blackhole); Add(blocked, Equipment.TeamWarCry); Add(blocked, Equipment.LunarPortalOnUse); Add(blocked, Equipment.Scanner); Add(blocked, Equipment.DroneBackup); Add(blocked, Equipment.QuestVolatileBattery); if (BetterEquipmentDrone.useDefaultDualApply == null || BetterEquipmentDrone.useDefaultDualApply.Value) { Add(dualApply, Equipment.Cleanse); Add(dualApply, Equipment.Fruit); Add(dualApply, Equipment.GainArmor); } AddNames(dualApply, BetterEquipmentDrone.extraDualApplyEquipment?.Value, "ExtraDualApplyEquipment"); dualApply.ExceptWith(blocked); Log.Info(string.Format("Kept at vanilla behaviour ({0}): {1}", blocked.Count, string.Join(", ", blocked.Select((EquipmentDef def) => ((Object)def).name)))); Log.Info(string.Format("Applied to drone as well as owner ({0}): {1}", dualApply.Count, string.Join(", ", dualApply.Select((EquipmentDef def) => ((Object)def).name)))); } private static void Add(HashSet<EquipmentDef> set, EquipmentDef def) { if ((Object)(object)def != (Object)null) { set.Add(def); } } private static void AddNames(HashSet<EquipmentDef> set, string commaSeparated, string settingName) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(commaSeparated)) { return; } string[] array = commaSeparated.Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(EquipmentCatalog.FindEquipmentIndex(text)); if ((Object)(object)equipmentDef == (Object)null) { Log.Warning(settingName + ": unknown equipment name '" + text + "'."); } else { Add(set, equipmentDef); } } } } } internal static class ItemMirroring { private class DroneItemMirror : MonoBehaviour { private readonly Dictionary<ItemIndex, int> granted = new Dictionary<ItemIndex, int>(); private readonly Dictionary<ItemIndex, int> baseline = new Dictionary<ItemIndex, int>(); public int GetGranted(ItemIndex itemIndex) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!granted.TryGetValue(itemIndex, out var value)) { return 0; } return value; } public void SetGranted(ItemIndex itemIndex, int count) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) granted[itemIndex] = count; } public int UpdateHandPlacedFloor(ItemIndex itemIndex, int currentPermanent, int alreadyGranted) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Max(0, currentPermanent - alreadyGranted); if (!baseline.TryGetValue(itemIndex, out var value) || num > value) { value = num; baseline[itemIndex] = value; } return value; } } private const float SyncIntervalSeconds = 1f; private static readonly List<ItemDef> mirrored = new List<ItemDef>(); private static float timeUntilSync; internal static void BuildItemList() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) mirrored.Clear(); string text = BetterEquipmentDrone.mirroredItems?.Value; if (string.IsNullOrEmpty(text)) { return; } string[] array = text.Split(','); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length != 0) { ItemDef itemDef = ItemCatalog.GetItemDef(ItemCatalog.FindItemIndex(text2)); if ((Object)(object)itemDef == (Object)null) { Log.Warning("MirroredItems: unknown item name '" + text2 + "'."); } else { mirrored.Add(itemDef); } } } Log.Info($"Mirroring owner items onto drones ({mirrored.Count}): " + string.Join(", ", mirrored.ConvertAll((ItemDef d) => ((Object)d).name).ToArray())); } internal static void Tick(float deltaTime) { if (NetworkServer.active && mirrored.Count != 0 && BetterEquipmentDrone.modEnabled != null && BetterEquipmentDrone.modEnabled.Value && BetterEquipmentDrone.mirrorOwnerItems != null && BetterEquipmentDrone.mirrorOwnerItems.Value) { timeUntilSync -= deltaTime; if (!(timeUntilSync > 0f)) { timeUntilSync = 1f; SyncAll(); } } } private static void SyncAll() { foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { CharacterMaster val = (Object.op_Implicit((Object)(object)instance) ? instance.master : null); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.inventory)) { continue; } foreach (CharacterMaster item in DroneEquipmentOwnership.ManagedDronesOf(val)) { if (Object.op_Implicit((Object)(object)item.inventory)) { SyncOne(item, val); } } } } private static void SyncOne(CharacterMaster droneMaster, CharacterMaster owner) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_00b3: Unknown result type (might be due to invalid IL or missing references) DroneItemMirror droneItemMirror = ((Component)droneMaster).GetComponent<DroneItemMirror>() ?? ((Component)droneMaster).gameObject.AddComponent<DroneItemMirror>(); foreach (ItemDef item in mirrored) { ItemIndex itemIndex = item.itemIndex; int itemCountEffective = owner.inventory.GetItemCountEffective(item); int granted = droneItemMirror.GetGranted(itemIndex); int itemCountPermanent = droneMaster.inventory.GetItemCountPermanent(item); int num = droneItemMirror.UpdateHandPlacedFloor(itemIndex, itemCountPermanent, granted); int num2 = itemCountEffective - granted; if (num2 == 0) { continue; } if (num2 > 0) { droneMaster.inventory.GiveItemPermanent(item, num2); } else { int num3 = Mathf.Min(-num2, Mathf.Max(0, itemCountPermanent - num)); if (num3 > 0) { droneMaster.inventory.RemoveItemPermanent(item, num3); } } droneItemMirror.SetGranted(itemIndex, itemCountEffective); Log.Debug($"Mirrored {((Object)item).name} x{itemCountEffective} onto '{((Object)droneMaster).name}' " + $"from '{DroneEquipmentOwnership.Describe(owner)}' (delta={num2})."); } } internal static void OnDroneEquipmentUsed(CharacterMaster owner) { if (BetterEquipmentDrone.warHornBuffsOwner == null || !BetterEquipmentDrone.warHornBuffsOwner.Value || !Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)owner.inventory)) { return; } int itemCountEffective = owner.inventory.GetItemCountEffective(Items.EnergizedOnEquipmentUse); if (itemCountEffective > 0) { CharacterBody body = owner.GetBody(); if (Object.op_Implicit((Object)(object)body)) { body.AddTimedBuff(Buffs.Energized, (float)(8 + 4 * (itemCountEffective - 1))); Log.Debug($"War Horn: gave Energized x{itemCountEffective} to '{DroneEquipmentOwnership.Describe(owner)}'."); } } } } internal static class ManualTrigger { [CompilerGenerated] private static class <>O { public static hook_ExecuteIfReady <0>__EquipmentSlot_ExecuteIfReady; } private const float RequestWindowSeconds = 0.2f; private static readonly Dictionary<CharacterMaster, float> requestTimes = new Dictionary<CharacterMaster, float>(); internal static void Init() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__EquipmentSlot_ExecuteIfReady; if (obj == null) { hook_ExecuteIfReady val = EquipmentSlot_ExecuteIfReady; <>O.<0>__EquipmentSlot_ExecuteIfReady = val; obj = (object)val; } EquipmentSlot.ExecuteIfReady += (hook_ExecuteIfReady)obj; } internal static void Dispose() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__EquipmentSlot_ExecuteIfReady; if (obj == null) { hook_ExecuteIfReady val = EquipmentSlot_ExecuteIfReady; <>O.<0>__EquipmentSlot_ExecuteIfReady = val; obj = (object)val; } EquipmentSlot.ExecuteIfReady -= (hook_ExecuteIfReady)obj; requestTimes.Clear(); } private static bool EquipmentSlot_ExecuteIfReady(orig_ExecuteIfReady orig, EquipmentSlot self) { CharacterBody val = (Object.op_Implicit((Object)(object)self) ? self.characterBody : null); CharacterMaster val2 = (Object.op_Implicit((Object)(object)val) ? val.master : null); bool flag = Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.playerCharacterMasterController); if (flag) { requestTimes[val2] = Time.time; } bool result = orig.Invoke(self); if (flag) { FireOwnersAimedDroneEquipment(val2); } return result; } private static void FireOwnersAimedDroneEquipment(CharacterMaster owner) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || BetterEquipmentDrone.modEnabled == null || !BetterEquipmentDrone.modEnabled.Value) { return; } foreach (CharacterMaster item in DroneEquipmentOwnership.ManagedDronesOf(owner)) { CharacterBody body = item.GetBody(); EquipmentSlot val = (Object.op_Implicit((Object)(object)body) ? body.equipmentSlot : null); if (Object.op_Implicit((Object)(object)val) && IsGated(EquipmentCatalog.GetEquipmentDef(val.equipmentIndex))) { val.ExecuteIfReady(); } } } internal static bool IsGated(EquipmentDef equipmentDef) { if (BetterEquipmentDrone.manualAimedEquipment == null || !BetterEquipmentDrone.manualAimedEquipment.Value) { return false; } if ((Object)(object)equipmentDef == (Object)(object)Equipment.Recycle) { return true; } if ((Object)(object)equipmentDef == (Object)(object)Equipment.BossHunter) { if (BetterEquipmentDrone.tricornAimsWithOwner != null) { return BetterEquipmentDrone.tricornAimsWithOwner.Value; } return true; } return false; } internal static bool WasRequestedBy(CharacterMaster owner) { if (!Object.op_Implicit((Object)(object)owner) || !requestTimes.TryGetValue(owner, out var value)) { return false; } return Time.time - value <= 0.2f; } } internal static class MultiShopCardSupport { [CompilerGenerated] private static class <>O { public static hook_OnPurchase <0>__MultiShopCardUtils_OnPurchase; } private const float RefundFraction = 0.1f; internal static void Init() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__MultiShopCardUtils_OnPurchase; if (obj == null) { hook_OnPurchase val = MultiShopCardUtils_OnPurchase; <>O.<0>__MultiShopCardUtils_OnPurchase = val; obj = (object)val; } MultiShopCardUtils.OnPurchase += (hook_OnPurchase)obj; } internal static void Dispose() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__MultiShopCardUtils_OnPurchase; if (obj == null) { hook_OnPurchase val = MultiShopCardUtils_OnPurchase; <>O.<0>__MultiShopCardUtils_OnPurchase = val; obj = (object)val; } MultiShopCardUtils.OnPurchase -= (hook_OnPurchase)obj; } private static void MultiShopCardUtils_OnPurchase(orig_OnPurchase orig, PayCostContext context, int moneyCost) { orig.Invoke(context, moneyCost); if (!NetworkServer.active || BetterEquipmentDrone.modEnabled == null || !BetterEquipmentDrone.modEnabled.Value) { return; } CharacterMaster activatorMaster = context.activatorMaster; if (Object.op_Implicit((Object)(object)activatorMaster) && activatorMaster.hasBody && Object.op_Implicit((Object)(object)activatorMaster.playerCharacterMasterController) && !Object.op_Implicit((Object)(object)GetUsableCardSlot(activatorMaster))) { EquipmentSlot val = FindMinionCardSlot(activatorMaster) ?? FindOtherPlayersMinionCardSlot(activatorMaster); if (Object.op_Implicit((Object)(object)val)) { ApplyCardEffect(context, moneyCost, activatorMaster.GetBody(), val); } } } private static EquipmentSlot GetUsableCardSlot(CharacterMaster master) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)master) || !master.hasBody || !Object.op_Implicit((Object)(object)master.inventory)) { return null; } if (master.inventory.currentEquipmentIndex != Equipment.MultiShopCard.equipmentIndex || master.inventory.GetEquipmentDisabled()) { return null; } CharacterBody body = master.GetBody(); EquipmentSlot val = ((body != null) ? body.equipmentSlot : null); if (!Object.op_Implicit((Object)(object)val) || val.stock <= 0) { return null; } return val; } private static EquipmentSlot FindOtherPlayersMinionCardSlot(CharacterMaster buyer) { if (BetterEquipmentDrone.cardCoversAllPlayers == null || !BetterEquipmentDrone.cardCoversAllPlayers.Value) { return null; } foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.master) && !((Object)(object)instance.master == (Object)(object)buyer)) { EquipmentSlot val = FindMinionCardSlot(instance.master); if (Object.op_Implicit((Object)(object)val)) { return val; } } } return null; } private static EquipmentSlot FindMinionCardSlot(CharacterMaster owner) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) MinionGroup val = MinionGroup.FindGroup(((NetworkBehaviour)owner).netId); if (val == null) { return null; } MinionOwnership[] members = val.members; foreach (MinionOwnership val2 in members) { if (Object.op_Implicit((Object)(object)val2)) { EquipmentSlot usableCardSlot = GetUsableCardSlot(((Component)val2).GetComponent<CharacterMaster>()); if (Object.op_Implicit((Object)(object)usableCardSlot)) { return usableCardSlot; } } } return null; } private static void ApplyCardEffect(PayCostContext context, int moneyCost, CharacterBody buyerBody, EquipmentSlot droneSlot) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)buyerBody)) { return; } bool flag = false; GameObject purchasedObject = context.purchasedObject; if (moneyCost > 0) { flag = true; OrbManager.instance.AddOrb((Orb)new GoldOrb { origin = (Object.op_Implicit((Object)(object)purchasedObject) ? purchasedObject.transform.position : buyerBody.corePosition), target = buyerBody.mainHurtBox, goldAmount = (uint)(0.1f * (float)moneyCost) }); } if (Object.op_Implicit((Object)(object)purchasedObject)) { PurchaseInteraction component = purchasedObject.GetComponent<PurchaseInteraction>(); ShopTerminalBehavior component2 = purchasedObject.GetComponent<ShopTerminalBehavior>(); if (Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.serverMultiShopController)) { flag = true; component2.serverMultiShopController.SetCloseOnTerminalPurchase(component, false); } DroneVendorTerminalBehavior component3 = purchasedObject.GetComponent<DroneVendorTerminalBehavior>(); if (Object.op_Implicit((Object)(object)component3) && Object.op_Implicit((Object)(object)component3.serverMultiShopController)) { flag = true; component3.serverMultiShopController.SetCloseOnTerminalPurchase(component, false); } } if (flag) { droneSlot.OnEquipmentExecuted(); CharacterBody characterBody = droneSlot.characterBody; Log.Debug("Executive Card on drone '" + ((characterBody != null) ? ((Object)characterBody).name : null) + "' applied for " + $"'{DroneEquipmentOwnership.Describe(buyerBody.master)}' (moneyCost={moneyCost})."); } } } [BepInPlugin("Hibiscus.BetterEquipmentDrone", "BetterEquipmentDrone", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class BetterEquipmentDrone : BaseUnityPlugin { public const string PluginGUID = "Hibiscus.BetterEquipmentDrone"; public const string PluginAuthor = "Hibiscus"; public const string PluginName = "BetterEquipmentDrone"; public const string PluginVersion = "1.0.1"; private const int CooldownPercentMin = 10; private const int CooldownPercentMax = 200; internal static ConfigEntry<bool> modEnabled; internal static ConfigEntry<bool> allDrones; internal static ConfigEntry<bool> useDefaultDualApply; internal static ConfigEntry<string> extraDualApplyEquipment; internal static ConfigEntry<bool> cardCoversAllPlayers; internal static ConfigEntry<bool> tricornAimsWithOwner; internal static ConfigEntry<bool> meteoriteFromOwner; internal static ConfigEntry<bool> manualAimedEquipment; internal static ConfigEntry<bool> matchOwnerCooldown; internal static ConfigEntry<int> cooldownPercent; internal static ConfigEntry<KeyboardShortcut> droneCrowdfunderKey; internal static ConfigEntry<bool> mirrorOwnerItems; internal static ConfigEntry<string> mirroredItems; internal static ConfigEntry<bool> warHornBuffsOwner; internal static ConfigEntry<bool> verboseLogging; internal static MasterIndex equipmentDroneIndex = MasterIndex.none; private void Awake() { Log.Init(((BaseUnityPlugin)this).Logger); BindConfig(); if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions")) { SetupRiskOfOptions(); } RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnGameLoaded)); RunModule("EquipmentRedirector", "start", EquipmentRedirector.Init); RunModule("MultiShopCardSupport", "start", MultiShopCardSupport.Init); RunModule("CrowdfunderSupport", "start", CrowdfunderSupport.Init); RunModule("DroneTargeting", "start", DroneTargeting.Init); RunModule("DroneCooldown", "start", DroneCooldown.Init); RunModule("ManualTrigger", "start", ManualTrigger.Init); RunModule("TricornSupport", "start", TricornSupport.Init); Log.Info("BetterEquipmentDrone 1.0.1 loaded."); } private static void RunModule(string module, string verb, Action action) { try { action(); } catch (Exception ex) { Log.Warning(module + " failed to " + verb + " and stays inactive: " + ex.GetType().Name + ": " + ex.Message); } } private void BindConfig() { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. When off, drone equipment behaves exactly like vanilla."); allDrones = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectAllDrones", true, "Apply to every AI minion whose owner is a player. When off, only the vanilla Equipment Drone is affected."); useDefaultDualApply = ((BaseUnityPlugin)this).Config.Bind<bool>("DualApply", "UseDefaultDualApply", true, "Fire self-affecting equipment on the drone as well as the owner, so the drone also gets the heal, the cleanse or the armour and stays alive to keep firing."); extraDualApplyEquipment = ((BaseUnityPlugin)this).Config.Bind<string>("DualApply", "ExtraDualApplyEquipment", "", "Comma-separated internal equipment names to additionally fire on both bodies. Resolved names are printed to the log."); matchOwnerCooldown = ((BaseUnityPlugin)this).Config.Bind<bool>("Cooldown", "Match owner cooldown", true, "If enabled, a drone's equipment recharges exactly as fast as its owner's. If disabled, the drone recharges from its own items like vanilla."); cooldownPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Cooldown", "Cooldown percent", 100, new ConfigDescription("Drone equipment cooldown as a percent of the source above. 100 leaves it unchanged, 50 recharges twice as fast, 200 twice as slow.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 200), Array.Empty<object>())); manualAimedEquipment = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Aimed drone equipment waits for you", true, "A drone holds Recycler and Trophy Hunter's Tricorn until you press the equipment key, instead of firing the moment a target crosses your crosshair. Turn off to let the drone use them on its own."); tricornAimsWithOwner = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Tricorn aims with its owner", true, "A drone's Trophy Hunter's Tricorn picks the boss under the owner's crosshair and shows an indicator over it. Turn off to leave it aiming on its own. Recycler always follows the owner's crosshair; without that it has nothing to aim by."); meteoriteFromOwner = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "MeteoriteFromOwner", true, "A drone's Glowing Meteorite uses the owner's damage and rains around the owner. Off leaves it on the drone like vanilla."); cardCoversAllPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ExecutiveCardCoversAllPlayers", true, "One drone's Executive Card covers every player's purchases. Off means a drone only serves its own owner."); droneCrowdfunderKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Crowdfunder", "DroneCrowdfunder", new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()), "Toggles whether your own drones fire The Crowdfunder, paying per bullet from your gold. Vanilla leaves it inert on a drone because a minion master has no money. Every player with the mod gets their own toggle; it starts off on each run."); mirrorOwnerItems = ((BaseUnityPlugin)this).Config.Bind<bool>("ItemMirroring", "MirrorOwnerItems", true, "Copy the owner's equipment-related items onto their drones, so the player's Fuel Cells and Gesture of the Drowned speed up the drone's equipment too."); mirroredItems = ((BaseUnityPlugin)this).Config.Bind<string>("ItemMirroring", "MirroredItems", "EquipmentMagazine, AutoCastEquipment, RandomEquipmentTrigger, MoreMissile, Talisman", "Comma-separated internal item names to copy. Defaults are Fuel Cell, Gesture of the Drowned, Bottled Chaos, Pocket I.C.B.M. and Soulbound Catalyst. Only items whose whole effect is about equipment belong here; anything else also buffs the drone itself."); warHornBuffsOwner = ((BaseUnityPlugin)this).Config.Bind<bool>("ItemMirroring", "WarHornBuffsOwner", true, "Give the owner the War Horn attack speed when their drone fires equipment. War Horn is not copied to the drone, because vanilla would then buff the drone instead."); verboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Log every redirected equipment activation. Noisy; for troubleshooting only."); } private void SetupRiskOfOptions() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_002d: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown ModSettingsManager.SetModDescription("Drones use their equipment on behalf of the player who recruited them."); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(modEnabled)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(matchOwnerCooldown)); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(cooldownPercent, new IntSliderConfig { min = 10, max = 200 })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(manualAimedEquipment)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(tricornAimsWithOwner)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(meteoriteFromOwner)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(mirrorOwnerItems)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(warHornBuffsOwner)); ModSettingsManager.AddOption((BaseOption)new KeyBindOption(droneCrowdfunderKey)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(cardCoversAllPlayers)); } private void OnGameLoaded() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) GameObject masterPrefab = MasterCatalog.GetMasterPrefab(MasterCatalog.FindMasterIndex("EquipmentDroneMaster")); CharacterMaster val = default(CharacterMaster); if (Object.op_Implicit((Object)(object)masterPrefab) && masterPrefab.TryGetComponent<CharacterMaster>(ref val)) { equipmentDroneIndex = val.masterIndex; } else { Log.Warning("EquipmentDroneMaster not found; the AffectAllDrones=false mode will be inactive."); } EquipmentRedirector.BuildEquipmentSets(); ItemMirroring.BuildItemList(); } private void Update() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) ItemMirroring.Tick(Time.deltaTime); if (droneCrowdfunderKey != null) { KeyboardShortcut value = droneCrowdfunderKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { CrowdfunderSupport.SubmitToggleForLocalPlayer(); } } } private void OnDestroy() { RunModule("EquipmentRedirector", "stop", EquipmentRedirector.Dispose); RunModule("MultiShopCardSupport", "stop", MultiShopCardSupport.Dispose); RunModule("CrowdfunderSupport", "stop", CrowdfunderSupport.Dispose); RunModule("DroneTargeting", "stop", DroneTargeting.Dispose); RunModule("DroneCooldown", "stop", DroneCooldown.Dispose); RunModule("ManualTrigger", "stop", ManualTrigger.Dispose); RunModule("TricornSupport", "stop", TricornSupport.Dispose); RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(OnGameLoaded)); } } internal static class Log { private static ManualLogSource _logger; internal static void Init(ManualLogSource logger) { _logger = logger; } internal static void Info(object data) { ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo(data); } } internal static void Warning(object data) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning(data); } } internal static void Debug(object data) { if (BetterEquipmentDrone.verboseLogging != null && BetterEquipmentDrone.verboseLogging.Value) { ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo(data); } } } } internal static class TricornSupport { private struct EquipmentSnapshot { public uint slot; public uint set; public EquipmentState state; } [CompilerGenerated] private static class <>O { public static hook_SendTransformNotification_CharacterMaster_EquipmentIndex_EquipmentIndex_TransformationType <0>__CharacterMasterNotificationQueue_SendTransformNotification; } private static CharacterMaster suppressNotificationsFor; internal static void Init() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__CharacterMasterNotificationQueue_SendTransformNotification; if (obj == null) { hook_SendTransformNotification_CharacterMaster_EquipmentIndex_EquipmentIndex_TransformationType val = CharacterMasterNotificationQueue_SendTransformNotification; <>O.<0>__CharacterMasterNotificationQueue_SendTransformNotification = val; obj = (object)val; } CharacterMasterNotificationQueue.SendTransformNotification_CharacterMaster_EquipmentIndex_EquipmentIndex_TransformationType += (hook_SendTransformNotification_CharacterMaster_EquipmentIndex_EquipmentIndex_TransformationType)obj; } internal static void Dispose() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__CharacterMasterNotificationQueue_SendTransformNotification; if (obj == null) { hook_SendTransformNotification_CharacterMaster_EquipmentIndex_EquipmentIndex_TransformationType val = CharacterMasterNotificationQueue_SendTransformNotification; <>O.<0>__CharacterMasterNotificationQueue_SendTransformNotification = val; obj = (object)val; } CharacterMasterNotificationQueue.SendTransformNotification_CharacterMaster_EquipmentIndex_EquipmentIndex_TransformationType -= (hook_SendTransformNotification_CharacterMaster_EquipmentIndex_EquipmentIndex_TransformationType)obj; } private static void CharacterMasterNotificationQueue_SendTransformNotification(orig_SendTransformNotification_CharacterMaster_EquipmentIndex_EquipmentIndex_TransformationType orig, CharacterMaster characterMaster, EquipmentIndex oldIndex, EquipmentIndex newIndex, TransformationType transformationType) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)suppressNotificationsFor) || !((Object)(object)characterMaster == (Object)(object)suppressNotificationsFor)) { orig.Invoke(characterMaster, oldIndex, newIndex, transformationType); } } internal static bool Perform(orig_PerformEquipmentAction orig, EquipmentSlot droneSlot, EquipmentSlot ownerSlot, EquipmentDef equipmentDef) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) CharacterBody characterBody = ownerSlot.characterBody; Inventory inventory = (Object.op_Implicit((Object)(object)characterBody) ? characterBody.inventory : null); List<EquipmentSnapshot> snapshot = Snapshot(inventory); CharacterMaster master = (suppressNotificationsFor = (Object.op_Implicit((Object)(object)characterBody) ? characterBody.master : null)); bool flag; try { flag = orig.Invoke(ownerSlot, equipmentDef); } finally { suppressNotificationsFor = null; } Restore(inventory, snapshot); if (!flag) { return false; } Inventory val = (Object.op_Implicit((Object)(object)droneSlot.characterBody) ? droneSlot.characterBody.inventory : null); if (Object.op_Implicit((Object)(object)val)) { val.SetEquipmentIndex(Equipment.BossHunterConsumed.equipmentIndex, true); } string[] obj = new string[5] { "Tricorn fired from '", DroneEquipmentOwnership.Describe(master), "'; drone '", null, null }; CharacterBody characterBody2 = droneSlot.characterBody; obj[3] = ((characterBody2 != null) ? ((Object)characterBody2).name : null); obj[4] = "' spent its own charge."; Log.Debug(string.Concat(obj)); return true; } private static List<EquipmentSnapshot> Snapshot(Inventory inventory) { //IL_0048: 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) List<EquipmentSnapshot> list = new List<EquipmentSnapshot>(); if (!Object.op_Implicit((Object)(object)inventory)) { return list; } int equipmentSlotCount = inventory.GetEquipmentSlotCount(); for (uint num = 0u; num < equipmentSlotCount; num++) { int equipmentSetCount = inventory.GetEquipmentSetCount(num); for (uint num2 = 0u; num2 < equipmentSetCount; num2++) { list.Add(new EquipmentSnapshot { slot = num, set = num2, state = inventory.GetEquipment(num, num2) }); } } return list; } private static void Restore(Inventory inventory, List<EquipmentSnapshot> snapshot) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)inventory)) { return; } foreach (EquipmentSnapshot item in snapshot) { if (inventory.GetEquipment(item.slot, item.set).equipmentIndex != item.state.equipmentIndex) { inventory.SetEquipment(item.state, item.slot, item.set); } } } } }