Decompiled source of DroneImprovements v1.1.0

DroneImprovements.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DroneImprovements.Skills;
using EntityStates;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RiskOfOptions;
using RiskOfOptions.Options;
using RoR2;
using RoR2.ContentManagement;
using RoR2.Navigation;
using RoR2.Networking;
using RoR2.Orbs;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.Events;
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("DroneImprovements")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DroneImprovements")]
[assembly: AssemblyTitle("DroneImprovements")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 DroneImprovements
{
	internal static class DroneBodySetup
	{
		public static void OnGameLoaded()
		{
			int num = 0;
			foreach (DroneDef allDroneDef in DroneCatalog.allDroneDefs)
			{
				if (!Object.op_Implicit((Object)(object)allDroneDef) || !Object.op_Implicit((Object)(object)allDroneDef.remoteOpBody))
				{
					continue;
				}
				num++;
				GameObject remoteOpBody = allDroneDef.remoteOpBody;
				StringBuilder stringBuilder = new StringBuilder(((Object)remoteOpBody).name);
				if (!Object.op_Implicit((Object)(object)remoteOpBody.GetComponent<Interactor>()))
				{
					remoteOpBody.AddComponent<Interactor>().maxInteractionDistance = 3f;
					stringBuilder.Append(" [added Interactor]");
				}
				if (!Object.op_Implicit((Object)(object)remoteOpBody.GetComponent<InteractionDriver>()))
				{
					if (Object.op_Implicit((Object)(object)remoteOpBody.GetComponent<InputBankTest>()))
					{
						remoteOpBody.AddComponent<InteractionDriver>();
						stringBuilder.Append(" [added InteractionDriver]");
					}
					else
					{
						stringBuilder.Append(" [no InputBankTest, cannot interact]");
					}
				}
				SkillLocator component = remoteOpBody.GetComponent<SkillLocator>();
				if (Object.op_Implicit((Object)(object)component))
				{
					stringBuilder.Append(" skills:");
					AppendSkill(stringBuilder, "primary", component.primary);
					AppendSkill(stringBuilder, "secondary", component.secondary);
					AppendSkill(stringBuilder, "utility", component.utility);
					AppendSkill(stringBuilder, "special", component.special);
				}
				DroneImprovementsPlugin.Log.LogInfo((object)stringBuilder.ToString());
			}
			DroneImprovementsPlugin.Log.LogInfo((object)$"Prepared {num} remote-op drone bodies.");
		}

		private static void AppendSkill(StringBuilder log, string slot, GenericSkill skill)
		{
			object obj;
			if (!Object.op_Implicit((Object)(object)skill))
			{
				obj = null;
			}
			else
			{
				SkillFamily skillFamily = skill.skillFamily;
				obj = ((skillFamily != null) ? skillFamily.defaultSkillDef : null);
			}
			SkillDef val = (SkillDef)obj;
			if (Object.op_Implicit((Object)(object)val))
			{
				log.Append(' ').Append(slot).Append('=')
					.Append(val.skillName ?? ((Object)val).name);
			}
		}
	}
	internal static class DroneNetworking
	{
		private class DisconnectRequestMessage : MessageBase
		{
			public GameObject networkUserObject;

			public override void Serialize(NetworkWriter writer)
			{
				writer.Write(networkUserObject);
			}

			public override void Deserialize(NetworkReader reader)
			{
				networkUserObject = reader.ReadGameObject();
			}
		}

		[HarmonyPatch(typeof(NetworkMessageHandlerAttribute), "RegisterServerMessages")]
		private static class RegisterServerMessagesPatch
		{
			[CompilerGenerated]
			private static class <>O
			{
				public static NetworkMessageDelegate <0>__HandleDisconnectRequest;
			}

			private static void Postfix()
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Expected O, but got Unknown
				object obj = <>O.<0>__HandleDisconnectRequest;
				if (obj == null)
				{
					NetworkMessageDelegate val = HandleDisconnectRequest;
					<>O.<0>__HandleDisconnectRequest = val;
					obj = (object)val;
				}
				NetworkServer.RegisterHandler((short)17392, (NetworkMessageDelegate)obj);
			}
		}

		public const short DisconnectRequestMsgType = 17392;

		private static readonly MethodInfo deathFootPositionSetter = AccessTools.PropertySetter(typeof(CharacterMaster), "deathFootPosition");

		private static readonly MethodInfo lostBodyToDeathSetter = AccessTools.PropertySetter(typeof(CharacterMaster), "lostBodyToDeath");

		private static readonly FieldRef<CharacterMaster, bool> preventRespawnUntilNextStageServer = AccessTools.FieldRefAccess<CharacterMaster, bool>("preventRespawnUntilNextStageServer");

		private static readonly MethodInfo restoreOriginalBodyPrefab = AccessTools.Method(typeof(CharacterMaster), "RestoreOriginalBodyPrefab", (Type[])null, (Type[])null);

		private static GameObject disconnectEffectPrefab;

		public static void RequestDisconnect(CharacterBody drone)
		{
			CharacterMaster val = (Object.op_Implicit((Object)(object)drone) ? drone.master : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			if (NetworkServer.active)
			{
				ServerDisconnect(val);
				return;
			}
			NetworkUser val2 = (Object.op_Implicit((Object)(object)val.playerCharacterMasterController) ? val.playerCharacterMasterController.networkUser : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				NetworkConnection readyConnection = ClientScene.readyConnection;
				if (readyConnection != null)
				{
					readyConnection.Send((short)17392, (MessageBase)(object)new DisconnectRequestMessage
					{
						networkUserObject = ((Component)val2).gameObject
					});
				}
			}
		}

		private static void HandleDisconnectRequest(NetworkMessage netMsg)
		{
			DisconnectRequestMessage disconnectRequestMessage = netMsg.ReadMessage<DisconnectRequestMessage>();
			NetworkUser val = (Object.op_Implicit((Object)(object)disconnectRequestMessage.networkUserObject) ? disconnectRequestMessage.networkUserObject.GetComponent<NetworkUser>() : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				NetworkConnection connectionToClient = ((NetworkBehaviour)val).connectionToClient;
				if (connectionToClient == null || netMsg.conn == null || connectionToClient.connectionId != netMsg.conn.connectionId)
				{
					DroneImprovementsPlugin.Log.LogWarning((object)("Rejected drone disconnect request for " + val.userName + " from a connection that does not own it."));
				}
				else
				{
					ServerDisconnect(val.master);
				}
			}
		}

		public static void ServerDisconnect(CharacterMaster master)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)master))
			{
				return;
			}
			CharacterBody body = master.GetBody();
			if (DroneUtil.IsDronePlayer(body) && Object.op_Implicit((Object)(object)body.healthComponent) && body.healthComponent.alive)
			{
				SpawnDisconnectEffect(body);
				deathFootPositionSetter.Invoke(master, new object[1] { body.footPosition });
				lostBodyToDeathSetter.Invoke(master, new object[1] { true });
				master.preventGameOver = false;
				preventRespawnUntilNextStageServer.Invoke(master) = true;
				master.inventory.SetEquipmentDisabled(false);
				if (Object.op_Implicit((Object)(object)((Component)body).GetComponent<Inventory>()))
				{
					Object.Destroy((Object)(object)((Component)body).gameObject);
					master.OnBodyDestroyed(body);
				}
				else
				{
					master.DestroyBody();
				}
				restoreOriginalBodyPrefab.Invoke(master, null);
				DroneImprovementsPlugin.Log.LogInfo((object)(((Object)master).name + " disconnected from their drone."));
			}
		}

		private static void SpawnDisconnectEffect(CharacterBody body)
		{
			//IL_002c: 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_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_0043: 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_005a: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)disconnectEffectPrefab))
			{
				disconnectEffectPrefab = LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/TeleportOutBoom");
			}
			if (Object.op_Implicit((Object)(object)disconnectEffectPrefab))
			{
				EffectManager.SpawnEffect(disconnectEffectPrefab, new EffectData
				{
					origin = body.corePosition,
					rotation = Quaternion.identity,
					scale = body.radius
				}, true);
			}
		}
	}
	internal static class DroneTeleport
	{
		private static readonly List<CharacterBody> candidates = new List<CharacterBody>();

		private static readonly float[] ringDistances = new float[4] { 4f, 6f, 2.5f, 9f };

		private static readonly float[] flierHeights = new float[3] { 2.5f, 1.5f, 4f };

		private static readonly float[] groundHeights = new float[1];

		private static GameObject teleportEffectPrefab;

		public static bool TryTeleport(CharacterBody drone, out string failReason)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody val = FindNearestTarget(drone);
			if (!Object.op_Implicit((Object)(object)val))
			{
				failReason = "No living player to teleport to.";
				return false;
			}
			if (!TryFindDestination(drone, val, out var destinationCore))
			{
				failReason = "Couldn't find a safe spot near " + GetName(val) + ".";
				return false;
			}
			SpawnEffect(drone.corePosition, drone.radius);
			Vector3 val2 = drone.footPosition - drone.corePosition;
			TeleportHelper.TeleportBody(drone, destinationCore + val2, false);
			SpawnEffect(destinationCore, drone.radius);
			failReason = null;
			return true;
		}

		public static bool HasTarget(CharacterBody drone)
		{
			return Object.op_Implicit((Object)(object)FindNearestTarget(drone));
		}

		private static CharacterBody FindNearestTarget(CharacterBody drone)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			candidates.Clear();
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.master))
				{
					candidates.Add(instance.master.GetBody());
				}
			}
			DroneTeleportApi.InvokeCollectAdditionalTargets(drone, candidates);
			CharacterBody result = null;
			float num = float.PositiveInfinity;
			Vector3 corePosition = drone.corePosition;
			foreach (CharacterBody candidate in candidates)
			{
				if (Object.op_Implicit((Object)(object)candidate) && !((Object)(object)candidate == (Object)(object)drone) && !candidate.isRemoteOp && Object.op_Implicit((Object)(object)candidate.healthComponent) && candidate.healthComponent.alive)
				{
					Vector3 val = candidate.corePosition - corePosition;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = candidate;
					}
				}
			}
			candidates.Clear();
			return result;
		}

		private static bool TryFindDestination(CharacterBody drone, CharacterBody target, out Vector3 destinationCore)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			LayerIndex world = LayerIndex.world;
			int num = LayerMask.op_Implicit(((LayerIndex)(ref world)).mask);
			float num2 = Mathf.Max(drone.radius, 0.5f) + 0.25f;
			bool flag = !Object.op_Implicit((Object)(object)drone.characterMotor) || drone.characterMotor.isFlying;
			float num3 = drone.corePosition.y - drone.footPosition.y;
			Vector3 corePosition = target.corePosition;
			Vector3 footPosition = target.footPosition;
			Vector3 val = drone.corePosition - corePosition;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = -((Component)target).transform.forward;
				val.y = 0f;
			}
			val = ((((Vector3)(ref val)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val)).normalized : Vector3.forward);
			float[] array = (flag ? flierHeights : groundHeights);
			float[] array2 = ringDistances;
			RaycastHit val5 = default(RaycastHit);
			foreach (float num4 in array2)
			{
				for (int j = 0; j < 12; j++)
				{
					int num5 = ((j % 2 == 0) ? 1 : (-1));
					Vector3 val2 = Quaternion.AngleAxis((float)((j + 1) / 2) * 30f * (float)num5, Vector3.up) * val;
					Vector3 val3 = footPosition + val2 * num4;
					float[] array3 = array;
					foreach (float num6 in array3)
					{
						Vector3 val4;
						if (flag)
						{
							val4 = val3 + Vector3.up * num6;
						}
						else
						{
							if (!Physics.Raycast(val3 + Vector3.up * 2f, Vector3.down, ref val5, 6f, num, (QueryTriggerInteraction)1))
							{
								continue;
							}
							val4 = ((RaycastHit)(ref val5)).point + Vector3.up * (num3 + 0.1f);
						}
						if (IsValidSpot(val4, corePosition, num2, num))
						{
							destinationCore = val4;
							return true;
						}
					}
				}
			}
			if (TryNodeGraphFallback(drone, target, flag, num3, num2, num, out destinationCore))
			{
				return true;
			}
			Vector3 val6 = corePosition + Vector3.up * (target.radius + num2);
			destinationCore = ((!Physics.CheckSphere(val6, num2, num, (QueryTriggerInteraction)1) && !Physics.Linecast(corePosition, val6, num, (QueryTriggerInteraction)1)) ? val6 : corePosition);
			return true;
		}

		private static bool IsValidSpot(Vector3 core, Vector3 anchor, float clearance, int worldMask)
		{
			//IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			if (Physics.CheckSphere(core, clearance, worldMask, (QueryTriggerInteraction)1))
			{
				return false;
			}
			if (Physics.Linecast(anchor, core, worldMask, (QueryTriggerInteraction)1))
			{
				return false;
			}
			return Physics.Raycast(core, Vector3.down, 150f, worldMask, (QueryTriggerInteraction)1);
		}

		private static bool TryNodeGraphFallback(CharacterBody drone, CharacterBody target, bool flier, float footToCore, float clearance, int worldMask, out Vector3 destinationCore)
		{
			//IL_0002: 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)
			//IL_0033: 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_0042: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			destinationCore = default(Vector3);
			SceneInfo instance = SceneInfo.instance;
			NodeGraph val = (Object.op_Implicit((Object)(object)instance) ? instance.GetNodeGraph((GraphType)0) : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			NodeIndex val2 = val.FindClosestNode(target.footPosition, drone.hullClassification, 30f);
			Vector3 val3 = default(Vector3);
			if (val2 == NodeIndex.invalid || !val.GetNodePosition(val2, ref val3))
			{
				return false;
			}
			float[] array = ((!flier) ? new float[1] { footToCore + 0.1f } : new float[3]
			{
				2f,
				1f,
				footToCore + 0.1f
			});
			foreach (float num in array)
			{
				Vector3 val4 = val3 + Vector3.up * num;
				if (!Physics.CheckSphere(val4, clearance, worldMask, (QueryTriggerInteraction)1))
				{
					destinationCore = val4;
					return true;
				}
			}
			return false;
		}

		private static void SpawnEffect(Vector3 position, float radius)
		{
			//IL_002c: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_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_0050: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)teleportEffectPrefab))
			{
				teleportEffectPrefab = LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/TeleportOutBoom");
			}
			if (Object.op_Implicit((Object)(object)teleportEffectPrefab))
			{
				EffectManager.SpawnEffect(teleportEffectPrefab, new EffectData
				{
					origin = position,
					rotation = Quaternion.identity,
					scale = radius
				}, true);
			}
		}

		private static string GetName(CharacterBody body)
		{
			return body.GetUserName() ?? body.GetDisplayName();
		}
	}
	public static class DroneTeleportApi
	{
		public static event Action<CharacterBody, List<CharacterBody>> CollectAdditionalTargets;

		internal static void InvokeCollectAdditionalTargets(CharacterBody drone, List<CharacterBody> targets)
		{
			DroneTeleportApi.CollectAdditionalTargets?.Invoke(drone, targets);
		}
	}
	internal static class DroneUtil
	{
		public static bool IsDronePlayer(CharacterBody body)
		{
			if (Object.op_Implicit((Object)(object)body) && body.isPlayerControlled)
			{
				return body.isRemoteOp;
			}
			return false;
		}

		public static int CountLivingNonDronePlayers()
		{
			int num = 0;
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.master))
				{
					CharacterBody body = instance.master.GetBody();
					if (Object.op_Implicit((Object)(object)body) && !body.isRemoteOp)
					{
						num++;
					}
				}
			}
			return num;
		}
	}
	internal static class HostSettings
	{
		private class SettingsMessage : MessageBase
		{
			public bool survivorActions;

			public DroneGoldMode goldMode;

			public override void Serialize(NetworkWriter writer)
			{
				writer.Write(survivorActions);
				writer.Write((byte)goldMode);
			}

			public override void Deserialize(NetworkReader reader)
			{
				survivorActions = reader.ReadBoolean();
				goldMode = (DroneGoldMode)reader.ReadByte();
			}
		}

		[HarmonyPatch(typeof(NetworkMessageHandlerAttribute), "RegisterClientMessages")]
		private static class RegisterClientMessagesPatch
		{
			[CompilerGenerated]
			private static class <>O
			{
				public static NetworkMessageDelegate <0>__HandleSettings;
			}

			private static void Postfix(NetworkClient client)
			{
				//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: Expected O, but got Unknown
				object obj = <>O.<0>__HandleSettings;
				if (obj == null)
				{
					NetworkMessageDelegate val = HandleSettings;
					<>O.<0>__HandleSettings = val;
					obj = (object)val;
				}
				client.RegisterHandler((short)17393, (NetworkMessageDelegate)obj);
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static EventHandler <>9__8_0;

			public static EventHandler <>9__8_1;

			public static Action<Run> <>9__8_2;

			public static Action<Run> <>9__8_3;

			public static NetworkUserGenericDelegate <>9__8_4;

			internal void <Init>b__8_0(object sender, EventArgs args)
			{
				if (NetworkServer.active)
				{
					Broadcast();
					ApplyToExistingDrones();
				}
			}

			internal void <Init>b__8_1(object sender, EventArgs args)
			{
				if (NetworkServer.active)
				{
					Broadcast();
				}
			}

			internal void <Init>b__8_2(Run run)
			{
				if (NetworkServer.active)
				{
					Broadcast();
				}
			}

			internal void <Init>b__8_3(Run run)
			{
				receivedSurvivorActions = false;
				receivedGoldMode = DroneGoldMode.Full;
			}

			internal void <Init>b__8_4(NetworkUser networkUser)
			{
				if (NetworkServer.active)
				{
					Broadcast();
				}
			}
		}

		public const short SettingsMsgType = 17393;

		private static bool receivedSurvivorActions;

		private static DroneGoldMode receivedGoldMode;

		public static bool SurvivorActions
		{
			get
			{
				if (!NetworkServer.active)
				{
					return receivedSurvivorActions;
				}
				return PluginConfig.DroneSurvivorActions.Value;
			}
		}

		public static DroneGoldMode GoldMode
		{
			get
			{
				if (!NetworkServer.active)
				{
					return receivedGoldMode;
				}
				return PluginConfig.DroneGold.Value;
			}
		}

		public static void Init()
		{
			//IL_00ae: 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)
			//IL_00b9: Expected O, but got Unknown
			PluginConfig.DroneSurvivorActions.SettingChanged += delegate
			{
				if (NetworkServer.active)
				{
					Broadcast();
					ApplyToExistingDrones();
				}
			};
			PluginConfig.DroneGold.SettingChanged += delegate
			{
				if (NetworkServer.active)
				{
					Broadcast();
				}
			};
			Run.onRunStartGlobal += delegate
			{
				if (NetworkServer.active)
				{
					Broadcast();
				}
			};
			Run.onRunDestroyGlobal += delegate
			{
				receivedSurvivorActions = false;
				receivedGoldMode = DroneGoldMode.Full;
			};
			object obj = <>c.<>9__8_4;
			if (obj == null)
			{
				NetworkUserGenericDelegate val = delegate
				{
					if (NetworkServer.active)
					{
						Broadcast();
					}
				};
				<>c.<>9__8_4 = val;
				obj = (object)val;
			}
			NetworkUser.onPostNetworkUserStart += (NetworkUserGenericDelegate)obj;
		}

		private static void Broadcast()
		{
			NetworkServer.SendToAll((short)17393, (MessageBase)(object)new SettingsMessage
			{
				survivorActions = PluginConfig.DroneSurvivorActions.Value,
				goldMode = PluginConfig.DroneGold.Value
			});
		}

		private static void HandleSettings(NetworkMessage netMsg)
		{
			SettingsMessage settingsMessage = netMsg.ReadMessage<SettingsMessage>();
			receivedSurvivorActions = settingsMessage.survivorActions;
			receivedGoldMode = settingsMessage.goldMode;
			ApplyToExistingDrones();
		}

		private static void ApplyToExistingDrones()
		{
			Interactor val = default(Interactor);
			foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && readOnlyInstances.isRemoteOp && ((Component)readOnlyInstances).TryGetComponent<Interactor>(ref val))
				{
					val.isRemoteOp = !SurvivorActions;
				}
			}
		}
	}
	[BepInPlugin("revor.DroneImprovements", "DroneImprovements", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class DroneImprovementsPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "revor.DroneImprovements";

		public const string PluginName = "DroneImprovements";

		public const string PluginVersion = "1.1.0";

		internal static ManualLogSource Log;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			PluginConfig.Init(((BaseUnityPlugin)this).Config);
			DroneSkills.Init();
			HostSettings.Init();
			if (RiskOfOptionsCompat.Enabled)
			{
				RiskOfOptionsCompat.Init();
			}
			harmony = new Harmony("revor.DroneImprovements");
			harmony.PatchAll(typeof(DroneImprovementsPlugin).Assembly);
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(DroneBodySetup.OnGameLoaded));
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	public enum DroneGoldMode
	{
		Full,
		NoKillGold,
		None
	}
	internal static class PluginConfig
	{
		public static ConfigEntry<bool> DroneSurvivorActions;

		public static ConfigEntry<DroneGoldMode> DroneGold;

		public static ConfigEntry<bool> DronesCanChargeHoldoutZones;

		public static ConfigEntry<bool> IgnoreDronesForAllPlayerChecks;

		public static ConfigEntry<bool> SpareDronesFromArenaVoidKill;

		public static ConfigEntry<bool> DisconnectEnabled;

		public static ConfigEntry<float> DisconnectHoldSeconds;

		public static ConfigEntry<bool> TeleportEnabled;

		public static ConfigEntry<float> TeleportCooldown;

		public static void Init(ConfigFile config)
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			DroneSurvivorActions = config.Bind<bool>("Host", "DroneSurvivorActions", true, "(host) Drones can interact, buy and pick up items like survivors.");
			DroneGold = config.Bind<DroneGoldMode>("Host", "DroneGold", DroneGoldMode.Full, "(host) How drones earn gold. They keep the gold they had.\nFull: like survivors\nNoKillGold: no gold from combat, barrels and shrines still pay\nNone: no gold, can't use barrels or Shrine of Blood");
			DronesCanChargeHoldoutZones = config.Bind<bool>("Objectives", "DronesCanChargeHoldoutZones", true, "(host) Drones inside the teleporter zone help charge it. Drones outside never slow it down.");
			IgnoreDronesForAllPlayerChecks = config.Bind<bool>("Objectives", "IgnoreDronesForAllPlayerChecks", true, "(host) The Mithrix cutscene and escape ship don't wait for drones.");
			SpareDronesFromArenaVoidKill = config.Bind<bool>("Objectives", "SpareDronesFromArenaVoidKill", true, "(host) Drones outside the sealed Mithrix arena aren't killed.");
			DisconnectEnabled = config.Bind<bool>("Abilities", "DisconnectEnabled", true, "Drone Utility skill: hold to disconnect and return to spectating.");
			DisconnectHoldSeconds = config.Bind<float>("Abilities", "DisconnectHoldSeconds", 1f, new ConfigDescription("Seconds to hold Disconnect. Needs a game restart.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			TeleportEnabled = config.Bind<bool>("Abilities", "TeleportEnabled", true, "Drone Special skill (R): teleport to the nearest living player.");
			TeleportCooldown = config.Bind<float>("Abilities", "TeleportCooldown", 30f, new ConfigDescription("Teleport cooldown in seconds. Needs a game restart.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>()));
		}
	}
	internal static class RiskOfOptionsCompat
	{
		public const string Guid = "com.rune580.riskofoptions";

		public static bool Enabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions");

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Init()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			ModSettingsManager.SetModDescription("Remote Operation improvements. Settings marked (host) are decided by the host for everyone.");
			if (Object.op_Implicit((Object)(object)DroneSkills.TeleportSkill) && Object.op_Implicit((Object)(object)((SkillDef)DroneSkills.TeleportSkill).icon))
			{
				ModSettingsManager.SetModIcon(((SkillDef)DroneSkills.TeleportSkill).icon);
			}
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.DroneSurvivorActions));
			ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.DroneGold));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.DronesCanChargeHoldoutZones));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.IgnoreDronesForAllPlayerChecks));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.SpareDronesFromArenaVoidKill));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.DisconnectEnabled));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.TeleportEnabled));
		}
	}
}
namespace DroneImprovements.Skills
{
	internal static class DroneSkills
	{
		[HarmonyPatch(typeof(BodyCatalog), "SetBodyPrefabs")]
		private static class BodyCatalogSetBodyPrefabsPatch
		{
			private static void Prefix(GameObject[] newBodyPrefabs)
			{
				foreach (GameObject val in newBodyPrefabs)
				{
					if (Object.op_Implicit((Object)(object)val) && ((Object)val).name.EndsWith("BodyRemoteOp"))
					{
						AddToBody(val);
					}
				}
			}
		}

		private class DroneContentPackProvider : IContentPackProvider
		{
			private readonly ContentPack contentPack = new ContentPack();

			public string identifier => "revor.DroneImprovements";

			public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
			{
				contentPack.skillDefs.Add((SkillDef[])(object)new SkillDef[2] { TeleportSkill, DisconnectSkill });
				contentPack.skillFamilies.Add((SkillFamily[])(object)new SkillFamily[2] { TeleportFamily, DisconnectFamily });
				contentPack.entityStateTypes.Add(new Type[2]
				{
					typeof(DroneTeleportState),
					typeof(DroneDisconnectState)
				});
				args.ReportProgress(1f);
				yield break;
			}

			public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args)
			{
				ContentPack.Copy(contentPack, args.output);
				args.ReportProgress(1f);
				yield break;
			}

			public IEnumerator FinalizeAsync(FinalizeAsyncArgs args)
			{
				args.ReportProgress(1f);
				yield break;
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static CollectContentPackProvidersDelegate <>9__18_0;

			internal void <Init>b__18_0(AddContentPackProviderDelegate add)
			{
				add.Invoke((IContentPackProvider)(object)new DroneContentPackProvider());
			}
		}

		public const string StateMachineName = "DroneImprovementsAbility";

		private static readonly FieldInfo skillFamilyField = AccessTools.Field(typeof(GenericSkill), "_skillFamily");

		public static DroneTeleportSkillDef TeleportSkill { get; private set; }

		public static DroneDisconnectSkillDef DisconnectSkill { get; private set; }

		public static SkillFamily TeleportFamily { get; private set; }

		public static SkillFamily DisconnectFamily { get; private set; }

		public static void Init()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Expected O, but got Unknown
			TeleportSkill = ScriptableObject.CreateInstance<DroneTeleportSkillDef>();
			((Object)TeleportSkill).name = "DroneImprovementsTeleport";
			((SkillDef)TeleportSkill).skillName = "DroneImprovementsTeleport";
			((SkillDef)TeleportSkill).skillNameToken = "Teleport to Player";
			((SkillDef)TeleportSkill).skillDescriptionToken = $"Teleport next to the nearest living player. <style=cIsUtility>{PluginConfig.TeleportCooldown.Value:0.#}s cooldown</style>.";
			((SkillDef)TeleportSkill).icon = LoadIcon("texDroneTeleportIcon.png");
			((SkillDef)TeleportSkill).activationStateMachineName = "DroneImprovementsAbility";
			((SkillDef)TeleportSkill).activationState = new SerializableEntityStateType(typeof(DroneTeleportState));
			((SkillDef)TeleportSkill).interruptPriority = (InterruptPriority)1;
			((SkillDef)TeleportSkill).baseRechargeInterval = PluginConfig.TeleportCooldown.Value;
			((SkillDef)TeleportSkill).baseMaxStock = 1;
			((SkillDef)TeleportSkill).rechargeStock = 1;
			((SkillDef)TeleportSkill).requiredStock = 1;
			((SkillDef)TeleportSkill).stockToConsume = 1;
			((SkillDef)TeleportSkill).fullRestockOnAssign = true;
			((SkillDef)TeleportSkill).isCombatSkill = false;
			((SkillDef)TeleportSkill).cancelSprintingOnActivation = false;
			((SkillDef)TeleportSkill).canceledFromSprinting = false;
			((SkillDef)TeleportSkill).mustKeyPress = true;
			DisconnectSkill = ScriptableObject.CreateInstance<DroneDisconnectSkillDef>();
			((Object)DisconnectSkill).name = "DroneImprovementsDisconnect";
			((SkillDef)DisconnectSkill).skillName = "DroneImprovementsDisconnect";
			((SkillDef)DisconnectSkill).skillNameToken = "Disconnect";
			((SkillDef)DisconnectSkill).skillDescriptionToken = "<style=cIsUtility>Hold</style> to end remote operation and return to spectating.";
			((SkillDef)DisconnectSkill).icon = LoadIcon("texDroneDisconnectIcon.png");
			((SkillDef)DisconnectSkill).activationStateMachineName = "DroneImprovementsAbility";
			((SkillDef)DisconnectSkill).activationState = new SerializableEntityStateType(typeof(DroneDisconnectState));
			((SkillDef)DisconnectSkill).interruptPriority = (InterruptPriority)0;
			((SkillDef)DisconnectSkill).baseRechargeInterval = Mathf.Max(0.1f, PluginConfig.DisconnectHoldSeconds.Value);
			((SkillDef)DisconnectSkill).beginSkillCooldownOnSkillEnd = true;
			((SkillDef)DisconnectSkill).baseMaxStock = 1;
			((SkillDef)DisconnectSkill).rechargeStock = 1;
			((SkillDef)DisconnectSkill).requiredStock = 1;
			((SkillDef)DisconnectSkill).stockToConsume = 1;
			((SkillDef)DisconnectSkill).fullRestockOnAssign = true;
			((SkillDef)DisconnectSkill).isCombatSkill = false;
			((SkillDef)DisconnectSkill).cancelSprintingOnActivation = false;
			((SkillDef)DisconnectSkill).canceledFromSprinting = false;
			((SkillDef)DisconnectSkill).mustKeyPress = true;
			TeleportFamily = CreateFamily("DroneImprovementsTeleportFamily", (SkillDef)(object)TeleportSkill);
			DisconnectFamily = CreateFamily("DroneImprovementsDisconnectFamily", (SkillDef)(object)DisconnectSkill);
			object obj = <>c.<>9__18_0;
			if (obj == null)
			{
				CollectContentPackProvidersDelegate val = delegate(AddContentPackProviderDelegate add)
				{
					add.Invoke((IContentPackProvider)(object)new DroneContentPackProvider());
				};
				<>c.<>9__18_0 = val;
				obj = (object)val;
			}
			ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)obj;
		}

		private static SkillFamily CreateFamily(string name, SkillDef skill)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			SkillFamily val = ScriptableObject.CreateInstance<SkillFamily>();
			((Object)val).name = name;
			Variant[] array = new Variant[1];
			Variant val2 = new Variant
			{
				skillDef = skill
			};
			((Variant)(ref val2)).viewableNode = new Node(skill.skillName, false, (Node)null);
			array[0] = val2;
			val.variants = (Variant[])(object)array;
			return val;
		}

		public static void AddToBody(GameObject prefab)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)EntityStateMachine.FindByCustomName(prefab, "DroneImprovementsAbility")))
			{
				return;
			}
			SkillLocator component = prefab.GetComponent<SkillLocator>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				DroneImprovementsPlugin.Log.LogWarning((object)(((Object)prefab).name + " has no SkillLocator; drone abilities not added."));
				return;
			}
			EntityStateMachine obj = prefab.AddComponent<EntityStateMachine>();
			obj.customName = "DroneImprovementsAbility";
			obj.initialStateType = new SerializableEntityStateType(typeof(Idle));
			obj.mainStateType = new SerializableEntityStateType(typeof(Idle));
			if (!Object.op_Implicit((Object)(object)component.utility))
			{
				component.utility = AddSkill(prefab, DisconnectFamily, "DroneDisconnect");
			}
			else
			{
				DroneImprovementsPlugin.Log.LogWarning((object)(((Object)prefab).name + " already has a utility skill; Disconnect not added."));
			}
			if (!Object.op_Implicit((Object)(object)component.special))
			{
				component.special = AddSkill(prefab, TeleportFamily, "DroneTeleport");
			}
			else
			{
				DroneImprovementsPlugin.Log.LogWarning((object)(((Object)prefab).name + " already has a special skill; Teleport not added."));
			}
		}

		private static GenericSkill AddSkill(GameObject prefab, SkillFamily family, string slotName)
		{
			GenericSkill val = prefab.AddComponent<GenericSkill>();
			val.skillName = slotName;
			val.hideInCharacterSelect = true;
			skillFamilyField.SetValue(val, family);
			return val;
		}

		private static Sprite LoadIcon(string fileName)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			using (Stream stream = typeof(DroneSkills).Assembly.GetManifestResourceStream("DroneImprovements.Assets." + fileName))
			{
				if (stream == null)
				{
					DroneImprovementsPlugin.Log.LogError((object)("Missing embedded icon " + fileName));
					return null;
				}
				byte[] array = new byte[stream.Length];
				stream.Read(array, 0, array.Length);
				ImageConversion.LoadImage(val, array);
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Object)val).name = Path.GetFileNameWithoutExtension(fileName);
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
	}
	public class DroneTeleportSkillDef : SkillDef
	{
		public override bool IsReady(GenericSkill skillSlot)
		{
			if (((SkillDef)this).IsReady(skillSlot))
			{
				return IsAvailable(skillSlot);
			}
			return false;
		}

		public override bool CanExecute(GenericSkill skillSlot)
		{
			if (((SkillDef)this).CanExecute(skillSlot))
			{
				return IsAvailable(skillSlot);
			}
			return false;
		}

		private static bool IsAvailable(GenericSkill skillSlot)
		{
			if (PluginConfig.TeleportEnabled.Value && Object.op_Implicit((Object)(object)skillSlot.characterBody))
			{
				return DroneTeleport.HasTarget(skillSlot.characterBody);
			}
			return false;
		}
	}
	public class DroneDisconnectSkillDef : SkillDef
	{
		public override bool IsReady(GenericSkill skillSlot)
		{
			if (((SkillDef)this).IsReady(skillSlot))
			{
				return PluginConfig.DisconnectEnabled.Value;
			}
			return false;
		}

		public override bool CanExecute(GenericSkill skillSlot)
		{
			if (((SkillDef)this).CanExecute(skillSlot))
			{
				return PluginConfig.DisconnectEnabled.Value;
			}
			return false;
		}
	}
	public class DroneTeleportState : BaseSkillState
	{
		public override void OnEnter()
		{
			((BaseState)this).OnEnter();
			if (((EntityState)this).isAuthority && !DroneTeleport.TryTeleport(((EntityState)this).characterBody, out var failReason))
			{
				DroneImprovementsPlugin.Log.LogInfo((object)("Teleport failed: " + failReason));
				GenericSkill activatorSkillSlot = ((BaseSkillState)this).activatorSkillSlot;
				if (activatorSkillSlot != null)
				{
					activatorSkillSlot.AddOneStock();
				}
			}
		}

		public override void FixedUpdate()
		{
			((EntityState)this).FixedUpdate();
			if (((EntityState)this).isAuthority)
			{
				((EntityState)this).outer.SetNextStateToMain();
			}
		}

		public override InterruptPriority GetMinimumInterruptPriority()
		{
			return (InterruptPriority)0;
		}
	}
	public class DroneDisconnectState : BaseSkillState
	{
		private float holdDuration;

		private bool requested;

		public override void OnEnter()
		{
			((BaseState)this).OnEnter();
			holdDuration = Mathf.Max(0f, PluginConfig.DisconnectHoldSeconds.Value);
		}

		public override void FixedUpdate()
		{
			((EntityState)this).FixedUpdate();
			if (!((EntityState)this).isAuthority)
			{
				return;
			}
			if (!requested)
			{
				if (!IsDisconnectKeyHeld())
				{
					((EntityState)this).outer.SetNextStateToMain();
					return;
				}
				if (Object.op_Implicit((Object)(object)((BaseSkillState)this).activatorSkillSlot))
				{
					((BaseSkillState)this).activatorSkillSlot.rechargeStopwatch = Mathf.Min(((EntityState)this).fixedAge, ((BaseSkillState)this).activatorSkillSlot.CalculateFinalRechargeInterval() - 0.01f);
				}
				if (((EntityState)this).fixedAge >= holdDuration)
				{
					requested = true;
					DroneNetworking.RequestDisconnect(((EntityState)this).characterBody);
				}
			}
			else if (((EntityState)this).fixedAge >= holdDuration + 3f)
			{
				((EntityState)this).outer.SetNextStateToMain();
			}
		}

		private bool IsDisconnectKeyHeld()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected I4, but got Unknown
			CharacterMaster val = (Object.op_Implicit((Object)(object)((EntityState)this).characterBody) ? ((EntityState)this).characterBody.master : null);
			PlayerCharacterMasterController val2 = (Object.op_Implicit((Object)(object)val) ? val.playerCharacterMasterController : null);
			NetworkUser val3 = (Object.op_Implicit((Object)(object)val2) ? val2.networkUser : null);
			LocalUser val4 = (Object.op_Implicit((Object)(object)val3) ? val3.localUser : null);
			if (((val4 != null) ? val4.inputPlayer : null) == null)
			{
				return ((BaseSkillState)this).IsKeyDownAuthority();
			}
			if (val4.isUIFocused)
			{
				return false;
			}
			SkillSlot val5 = (SkillSlot)((!Object.op_Implicit((Object)(object)((EntityState)this).skillLocator)) ? (-1) : ((int)((EntityState)this).skillLocator.FindSkillSlot(((BaseSkillState)this).activatorSkillSlot)));
			int num;
			switch ((int)val5)
			{
			case 0:
				num = 7;
				break;
			case 1:
				num = 8;
				break;
			case 2:
				num = 9;
				break;
			case 3:
				num = 10;
				break;
			default:
				return ((BaseSkillState)this).IsKeyDownAuthority();
			}
			return val4.inputPlayer.GetButton(num);
		}

		public override void OnExit()
		{
			if (Object.op_Implicit((Object)(object)((BaseSkillState)this).activatorSkillSlot))
			{
				((BaseSkillState)this).activatorSkillSlot.stock = ((BaseSkillState)this).activatorSkillSlot.maxStock;
				((BaseSkillState)this).activatorSkillSlot.rechargeStopwatch = 0f;
			}
			((EntityState)this).OnExit();
		}

		public override InterruptPriority GetMinimumInterruptPriority()
		{
			return (InterruptPriority)0;
		}
	}
}
namespace DroneImprovements.Patches
{
	internal static class CombatGold
	{
		[ThreadStatic]
		private static int depth;

		private static readonly ConditionalWeakTable<GoldOrb, object> combatOrbs = new ConditionalWeakTable<GoldOrb, object>();

		private static readonly object marker = new object();

		public static bool InCombatContext => depth > 0;

		private static DroneGoldMode Mode => HostSettings.GoldMode;

		public static bool ExcludeDronesFromTeamPayout
		{
			get
			{
				if (Mode != DroneGoldMode.None)
				{
					if (Mode == DroneGoldMode.NoKillGold)
					{
						return InCombatContext;
					}
					return false;
				}
				return true;
			}
		}

		public static bool BlocksAllGold => Mode == DroneGoldMode.None;

		public static bool BlockOrbForDrone(GoldOrb orb)
		{
			if (Mode != DroneGoldMode.None)
			{
				if (Mode == DroneGoldMode.NoKillGold)
				{
					return IsCombatOrb(orb);
				}
				return false;
			}
			return true;
		}

		public static void Enter()
		{
			depth++;
		}

		public static void Exit()
		{
			depth = Math.Max(0, depth - 1);
		}

		public static void MarkOrb(GoldOrb orb)
		{
			combatOrbs.GetValue(orb, (GoldOrb _) => marker);
		}

		public static bool IsCombatOrb(GoldOrb orb)
		{
			object value;
			return combatOrbs.TryGetValue(orb, out value);
		}
	}
	[HarmonyPatch(typeof(DeathRewards), "OnKilledServer")]
	internal static class DeathRewardsContextPatch
	{
		private static void Prefix()
		{
			CombatGold.Enter();
		}

		private static void Finalizer()
		{
			CombatGold.Exit();
		}
	}
	[HarmonyPatch(typeof(MoneyPickup), "OnTriggerStay")]
	internal static class MoneyPickupContextPatch
	{
		private static void Prefix()
		{
			CombatGold.Enter();
		}

		private static void Finalizer()
		{
			CombatGold.Exit();
		}
	}
	[HarmonyPatch(typeof(GlobalEventManager), "ProcessHitEnemy")]
	internal static class HitEnemyContextPatch
	{
		private static void Prefix()
		{
			CombatGold.Enter();
		}

		private static void Finalizer()
		{
			CombatGold.Exit();
		}
	}
	[HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")]
	internal static class TakeDamageContextPatch
	{
		private static void Prefix()
		{
			CombatGold.Enter();
		}

		private static void Finalizer()
		{
			CombatGold.Exit();
		}
	}
	[HarmonyPatch(typeof(TeamManager), "GiveTeamMoney", new Type[]
	{
		typeof(TeamIndex),
		typeof(uint)
	})]
	internal static class GiveTeamMoneyPatch
	{
		private static bool Prefix(TeamIndex teamIndex, uint money)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!CombatGold.ExcludeDronesFromTeamPayout)
			{
				return true;
			}
			int num = DroneUtil.CountLivingNonDronePlayers();
			if (num > 0)
			{
				money = (uint)Mathf.CeilToInt((float)money / (float)num);
			}
			ReadOnlyCollection<TeamComponent> teamMembers = TeamComponent.GetTeamMembers(teamIndex);
			for (int i = 0; i < teamMembers.Count; i++)
			{
				CharacterBody component = ((Component)teamMembers[i]).GetComponent<CharacterBody>();
				if (Object.op_Implicit((Object)(object)component) && component.isPlayerControlled && !component.isRemoteOp && Object.op_Implicit((Object)(object)component.master))
				{
					component.master.GiveMoney(money);
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(OrbManager), "AddOrb")]
	internal static class AddOrbPatch
	{
		private static void Prefix(Orb orb)
		{
			if (CombatGold.InCombatContext)
			{
				GoldOrb val = (GoldOrb)(object)((orb is GoldOrb) ? orb : null);
				if (val != null)
				{
					CombatGold.MarkOrb(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(GoldOrb), "OnArrival")]
	internal static class GoldOrbArrivalPatch
	{
		private static bool Prefix(GoldOrb __instance)
		{
			if (!CombatGold.BlockOrbForDrone(__instance))
			{
				return true;
			}
			HurtBox target = ((Orb)__instance).target;
			return !DroneUtil.IsDronePlayer((Object.op_Implicit((Object)(object)target) && Object.op_Implicit((Object)(object)target.healthComponent)) ? target.healthComponent.body : null);
		}
	}
	[HarmonyPatch(typeof(CharacterMaster), "GiveMoney")]
	internal static class GiveMoneyPatch
	{
		private static bool Prefix(CharacterMaster __instance)
		{
			if (CombatGold.BlocksAllGold)
			{
				return !DroneUtil.IsDronePlayer(__instance.GetBody());
			}
			return true;
		}
	}
	internal static class GoldInteractables
	{
		public static bool BlockedFor(Interactor activator)
		{
			if (CombatGold.BlocksAllGold && Object.op_Implicit((Object)(object)activator))
			{
				return DroneUtil.IsDronePlayer(((Component)activator).GetComponent<CharacterBody>());
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(BarrelInteraction), "GetInteractability")]
	internal static class BarrelInteractabilityPatch
	{
		private static void Postfix(Interactor activator, ref Interactability __result)
		{
			if (GoldInteractables.BlockedFor(activator))
			{
				__result = (Interactability)0;
			}
		}
	}
	[HarmonyPatch(typeof(PurchaseInteraction), "GetInteractability")]
	internal static class BloodShrineInteractabilityPatch
	{
		private static void Postfix(PurchaseInteraction __instance, Interactor activator, ref Interactability __result)
		{
			if (__result && GoldInteractables.BlockedFor(activator) && Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ShrineBloodBehavior>()))
			{
				__result = (Interactability)0;
			}
		}
	}
	[HarmonyPatch(typeof(CharacterBody), "Start")]
	internal static class CharacterBodyStartPatch
	{
		private static void Postfix(CharacterBody __instance)
		{
			Interactor val = default(Interactor);
			if (__instance.isRemoteOp && HostSettings.SurvivorActions && ((Component)__instance).TryGetComponent<Interactor>(ref val))
			{
				val.isRemoteOp = false;
			}
		}
	}
	[HarmonyPatch(typeof(GenericPickupController), "BodyHasPickupPermission")]
	internal static class PickupPermissionPatch
	{
		private static void Postfix(CharacterBody body, ref bool __result)
		{
			if (!__result && HostSettings.SurvivorActions && Object.op_Implicit((Object)(object)body) && body.isRemoteOp)
			{
				__result = Object.op_Implicit((Object)(object)body.masterObject) && Object.op_Implicit((Object)(object)body.masterObject.GetComponent<PlayerCharacterMasterController>()) && Object.op_Implicit((Object)(object)body.inventory);
			}
		}
	}
	[HarmonyPatch(typeof(HoldoutZoneController), "DoUpdate")]
	internal static class HoldoutZoneDoUpdatePatch
	{
		[ThreadStatic]
		internal static HoldoutZoneController currentZone;

		private static void Prefix(HoldoutZoneController __instance)
		{
			currentZone = __instance;
		}

		private static void Finalizer()
		{
			currentZone = null;
		}
	}
	[HarmonyPatch(typeof(HoldoutZoneController), "CountLivingPlayers")]
	internal static class HoldoutZoneCountLivingPlayersPatch
	{
		private static void Postfix(TeamIndex teamIndex, ref int __result)
		{
			//IL_002c: 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)
			HoldoutZoneController currentZone = HoldoutZoneDoUpdatePatch.currentZone;
			if (Object.op_Implicit((Object)(object)currentZone) && PluginConfig.DronesCanChargeHoldoutZones.Value)
			{
				float currentRadius = currentZone.currentRadius;
				__result += HoldoutZoneHelpers.CountDronesInRadius(currentZone, ((Component)currentZone).transform.position, currentRadius * currentRadius, teamIndex);
			}
		}
	}
	[HarmonyPatch(typeof(HoldoutZoneController), "CountPlayersInRadius")]
	internal static class HoldoutZoneCountPlayersInRadiusPatch
	{
		private static void Postfix(HoldoutZoneController holdoutZoneController, Vector3 origin, float chargingRadiusSqr, TeamIndex teamIndex, ref int __result)
		{
			//IL_0013: 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)
			if (PluginConfig.DronesCanChargeHoldoutZones.Value)
			{
				__result += HoldoutZoneHelpers.CountDronesInRadius(holdoutZoneController, origin, chargingRadiusSqr, teamIndex);
			}
		}
	}
	internal static class HoldoutZoneHelpers
	{
		private static readonly Func<HoldoutZoneController, Vector3, float, CharacterBody, bool> isBodyInChargingRadius = AccessTools.MethodDelegate<Func<HoldoutZoneController, Vector3, float, CharacterBody, bool>>(AccessTools.Method(typeof(HoldoutZoneController), "IsBodyInChargingRadius", new Type[4]
		{
			typeof(HoldoutZoneController),
			typeof(Vector3),
			typeof(float),
			typeof(CharacterBody)
		}, (Type[])null), (object)null, true);

		public static int CountDronesInRadius(HoldoutZoneController zone, Vector3 origin, float chargingRadiusSqr, TeamIndex teamIndex)
		{
			//IL_0002: 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)
			int num = 0;
			ReadOnlyCollection<TeamComponent> teamMembers = TeamComponent.GetTeamMembers(teamIndex);
			for (int i = 0; i < teamMembers.Count; i++)
			{
				CharacterBody body = teamMembers[i].body;
				if (DroneUtil.IsDronePlayer(body) && isBodyInChargingRadius(zone, origin, chargingRadiusSqr, body))
				{
					num++;
				}
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(MultiBodyTrigger), "FixedUpdate")]
	internal static class MultiBodyTriggerFixedUpdatePatch
	{
		private static readonly Action<MultiBodyTrigger, List<CharacterBody>, int> setEncounteredBodies = AccessTools.MethodDelegate<Action<MultiBodyTrigger, List<CharacterBody>, int>>(AccessTools.Method(typeof(MultiBodyTrigger), "SetEncounteredBodies", (Type[])null, (Type[])null), (object)null, true);

		private static readonly List<CharacterBody> buffer = new List<CharacterBody>();

		private static bool Prefix(MultiBodyTrigger __instance, Queue<Collider> ___collisionsQueue, List<CharacterBody> ___encounteredBodies)
		{
			if (!PluginConfig.IgnoreDronesForAllPlayerChecks.Value || !__instance.playerControlledOnly)
			{
				return true;
			}
			if (___collisionsQueue.Count == 0 && ___encounteredBodies.Count == 0)
			{
				return false;
			}
			buffer.Clear();
			while (___collisionsQueue.Count > 0)
			{
				Collider val = ___collisionsQueue.Dequeue();
				if (Object.op_Implicit((Object)(object)val))
				{
					CharacterBody component = ((Component)val).GetComponent<CharacterBody>();
					if (Object.op_Implicit((Object)(object)component) && component.isPlayerControlled && !component.isRemoteOp && !buffer.Contains(component))
					{
						buffer.Add(component);
					}
				}
			}
			int arg = (Object.op_Implicit((Object)(object)Run.instance) ? DroneUtil.CountLivingNonDronePlayers() : 0);
			setEncounteredBodies(__instance, buffer, arg);
			buffer.Clear();
			return false;
		}
	}
	[HarmonyPatch(typeof(MultiBodyTrigger), "KillAllOutsideWithVoidDeath")]
	internal static class MultiBodyTriggerVoidKillPatch
	{
		private static bool Prefix(List<CharacterBody> ___encounteredBodies)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if (!PluginConfig.SpareDronesFromArenaVoidKill.Value)
			{
				return true;
			}
			GameObject val = BodyCatalog.FindBodyPrefab("BrotherBody");
			foreach (CharacterBody item in new List<CharacterBody>(CharacterBody.readOnlyInstancesList))
			{
				if (!Object.op_Implicit((Object)(object)item) || ___encounteredBodies.Contains(item) || DroneUtil.IsDronePlayer(item))
				{
					continue;
				}
				CharacterMaster master = item.master;
				if (Object.op_Implicit((Object)(object)master))
				{
					try
					{
						master.TrueKill(val, (GameObject)null, DamageTypeCombo.op_Implicit((DamageType)65536));
					}
					catch (Exception ex)
					{
						Debug.LogError((object)ex);
					}
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(AllPlayersTrigger), "FixedUpdate")]
	internal static class AllPlayersTriggerFixedUpdatePatch
	{
		private static readonly List<CharacterBody> buffer = new List<CharacterBody>();

		private static bool Prefix(AllPlayersTrigger __instance, Queue<Collider> ___collisionQueueServer, ref bool ___triggerActiveServer)
		{
			if (!PluginConfig.IgnoreDronesForAllPlayerChecks.Value)
			{
				return true;
			}
			if (!Object.op_Implicit((Object)(object)Run.instance) || ___collisionQueueServer == null)
			{
				return false;
			}
			buffer.Clear();
			while (___collisionQueueServer.Count > 0)
			{
				Collider val = ___collisionQueueServer.Dequeue();
				if (Object.op_Implicit((Object)(object)val))
				{
					CharacterBody component = ((Component)val).GetComponent<CharacterBody>();
					if (Object.op_Implicit((Object)(object)component) && component.isPlayerControlled && !component.isRemoteOp && !buffer.Contains(component))
					{
						buffer.Add(component);
					}
				}
			}
			int count = buffer.Count;
			buffer.Clear();
			bool flag = count != 0 && count >= DroneUtil.CountLivingNonDronePlayers();
			if (___triggerActiveServer != flag)
			{
				___triggerActiveServer = flag;
				UnityEvent obj = (flag ? __instance.onTriggerStart : __instance.onTriggerEnd);
				if (obj != null)
				{
					obj.Invoke();
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(EscapeSequenceExtractionZone), "CountLivingPlayers")]
	internal static class EscapeZoneCountLivingPlayersPatch
	{
		private static bool Prefix(TeamIndex teamIndex, ref int __result)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!PluginConfig.IgnoreDronesForAllPlayerChecks.Value)
			{
				return true;
			}
			int num = 0;
			ReadOnlyCollection<TeamComponent> teamMembers = TeamComponent.GetTeamMembers(teamIndex);
			for (int i = 0; i < teamMembers.Count; i++)
			{
				CharacterBody body = teamMembers[i].body;
				if (Object.op_Implicit((Object)(object)body) && body.isPlayerControlled && !body.isRemoteOp)
				{
					num++;
				}
			}
			__result = num;
			return false;
		}
	}
	[HarmonyPatch(typeof(EscapeSequenceExtractionZone), "GetPlayersInRadius")]
	internal static class EscapeZoneGetPlayersInRadiusPatch
	{
		private static void Postfix(List<CharacterBody> dest)
		{
			if (PluginConfig.IgnoreDronesForAllPlayerChecks.Value)
			{
				dest.RemoveAll(DroneUtil.IsDronePlayer);
			}
		}
	}
	[HarmonyPatch(typeof(EscapeSequenceExtractionZone), "CountPlayersInRadius")]
	internal static class EscapeZoneCountPlayersInRadiusPatch
	{
		private static void Postfix(Vector3 origin, float chargingRadiusSqr, TeamIndex teamIndex, ref int __result)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0034: 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)
			if (!PluginConfig.IgnoreDronesForAllPlayerChecks.Value)
			{
				return;
			}
			ReadOnlyCollection<TeamComponent> teamMembers = TeamComponent.GetTeamMembers(teamIndex);
			for (int i = 0; i < teamMembers.Count; i++)
			{
				CharacterBody body = teamMembers[i].body;
				if (DroneUtil.IsDronePlayer(body))
				{
					Vector3 val = body.corePosition - origin;
					if (((Vector3)(ref val)).sqrMagnitude <= chargingRadiusSqr)
					{
						__result--;
					}
				}
			}
		}
	}
}