Decompiled source of ZeroGravityExtraction v1.2.4

ZeroGravityExtraction.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using ZeroGravityExtraction.Configuration;
using ZeroGravityExtraction.Patches;
using ZeroGravityExtraction.Services;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("Vippy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.4.0")]
[assembly: AssemblyInformationalVersion("1.2.4+c1cd91d849c4fbf3be433e6ab79b8ef6562e238e")]
[assembly: AssemblyProduct("ZeroGravityExtraction")]
[assembly: AssemblyTitle("ZeroGravityExtraction")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 ZeroGravityExtraction
{
	internal static class BuildInfo
	{
		public const string Version = "1.2.4";
	}
	[BepInPlugin("Vippy.ZeroGravityExtraction", "ZeroGravityExtraction", "1.2.4")]
	public class ZeroGravityExtraction : BaseUnityPlugin
	{
		internal static ZeroGravityExtraction Instance { get; private set; }

		internal static ManualLogSource Logger => Instance.BaseLogger;

		private ManualLogSource BaseLogger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			//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)
			//IL_004f: Expected O, but got Unknown
			//IL_0054: Expected O, but got Unknown
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			PluginConfig.Init(((BaseUnityPlugin)this).Config);
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} loaded.");
		}

		internal static void LogInfo(string msg)
		{
			if (PluginConfig.LoggingLevel.Value >= VerbosityLevel.Debug)
			{
				Logger.LogInfo((object)msg);
			}
		}

		internal static void LogVerbose(string msg)
		{
			if (PluginConfig.LoggingLevel.Value >= VerbosityLevel.Verbose)
			{
				Logger.LogDebug((object)msg);
			}
		}
	}
}
namespace ZeroGravityExtraction.Services
{
	public class AnchorLock : MonoBehaviour
	{
		private Rigidbody? _rb;

		private void Awake()
		{
			_rb = ((Component)this).GetComponent<Rigidbody>();
		}

		private void FixedUpdate()
		{
			Pin();
		}

		private void LateUpdate()
		{
			Pin();
		}

		private void Pin()
		{
			//IL_002d: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_rb != (Object)null)
			{
				_rb.isKinematic = true;
				_rb.constraints = (RigidbodyConstraints)126;
			}
			((Component)this).transform.localPosition = AnchorSettings.GrabOffset;
			((Component)this).transform.localRotation = Quaternion.identity;
			((Component)this).transform.localScale = Vector3.one * 0.15f;
		}
	}
	internal static class AnchorSettings
	{
		public static readonly Vector3 GrabOffset = new Vector3(0f, 1.55f, -1.5f);

		public const float Size = 0.15f;

		public const float PokeHeight = 3f;

		public const float ZoneRadius = 2.5f;

		public const float Headroom = 20f;

		public const float ZoneHeight = 26f;
	}
	public class PadAnchor : MonoBehaviour
	{
		public bool ZeroGravityOn;

		public bool ButtonMode;

		public ExtractionPoint? Point;

		private const float ToggleCooldown = 0.5f;

		private static readonly Collider[] PokeHits = (Collider[])(object)new Collider[64];

		private static int _pokeMask;

		private bool _wasPoked;

		private float _cooldownTimer;

		private void Awake()
		{
			if (_pokeMask == 0)
			{
				_pokeMask = LayerMask.GetMask(new string[3] { "PhysGrabObject", "PhysGrabObjectHinge", "PhysGrabObjectCart" });
			}
		}

		private void Update()
		{
			if (_cooldownTimer > 0f)
			{
				_cooldownTimer -= Time.deltaTime;
			}
			if (!ButtonMode)
			{
				_wasPoked = false;
			}
			else if (SemiFunc.IsMasterClientOrSingleplayer() && PluginConfig.NonHostButton.Value)
			{
				PokeCheck();
			}
		}

		internal void Toggle(string source)
		{
			if (!(_cooldownTimer > 0f))
			{
				ZeroGravityOn = !ZeroGravityOn;
				_cooldownTimer = 0.5f;
				ZeroGravityExtraction.LogInfo("Pad zero-gravity toggled " + (ZeroGravityOn ? "on" : "off") + " (" + source + ").");
				ZeroGravityPadService.Instance?.PlayToggleSound(ZeroGravityOn, Point);
			}
		}

		private void PokeCheck()
		{
			bool flag = SomethingPoking();
			if (flag && !_wasPoked)
			{
				Toggle("head");
			}
			_wasPoked = flag;
		}

		private bool SomethingPoking()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			float num = 0.15f;
			Vector3 val = ((Component)this).transform.position + Vector3.up * 1.5f;
			Vector3 val2 = ((Component)this).transform.position - Vector3.up * 1.5f;
			int num2 = Physics.OverlapCapsuleNonAlloc(val, val2, num, PokeHits, _pokeMask, (QueryTriggerInteraction)2);
			for (int i = 0; i < num2; i++)
			{
				Collider val3 = PokeHits[i];
				if (!((Component)val3).transform.IsChildOf(((Component)this).transform))
				{
					Rigidbody attachedRigidbody = val3.attachedRigidbody;
					if ((Object)(object)attachedRigidbody != (Object)null && (Object)(object)((Component)attachedRigidbody).GetComponentInParent<PlayerDeathHead>() != (Object)null)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	internal static class PadBox
	{
		private const string Tag = "Vippy.ZeroGravityExtraction";

		private static readonly Vector3 Scale = new Vector3(1f, 1f, 0.15f);

		private static readonly Vector3 Spot = new Vector3(AnchorSettings.GrabOffset.x, 0.8f, -1.35f);

		private static readonly Vector3 BodyOffset = new Vector3(0f, 0f, 0.4f);

		private static readonly Quaternion Facing = Quaternion.Euler(0f, 180f, 0f);

		private static readonly Dictionary<GameObject, ExtractionPoint> SoloSpawns = new Dictionary<GameObject, ExtractionPoint>();

		private static readonly Dictionary<PhysGrabObject, ExtractionPoint?> Boxes = new Dictionary<PhysGrabObject, ExtractionPoint>();

		public static GameObject? Spawn(ExtractionPoint point)
		{
			//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)
			//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_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_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_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)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			PrefabRef val = CommonBox();
			if (val == null)
			{
				return null;
			}
			Transform obj = (((Object)(object)point.platform != (Object)null) ? point.platform : ((Component)point).transform);
			Quaternion val2 = obj.rotation * Facing;
			Vector3 val3 = obj.TransformPoint(Spot) - val2 * Vector3.Scale(BodyOffset, Scale);
			if (!SemiFunc.IsMultiplayer())
			{
				GameObject val4 = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)val).Prefab, val3, val2);
				val4.transform.localScale = Scale;
				SoloSpawns[val4] = point;
				return val4;
			}
			int num = (((Object)(object)point.photonView != (Object)null) ? point.photonView.ViewID : 0);
			return PhotonNetwork.InstantiateRoomObject(((PrefabRef<GameObject>)(object)val).ResourcePath, val3, val2, (byte)0, new object[5] { Scale.x, Scale.y, Scale.z, "Vippy.ZeroGravityExtraction", num });
		}

		public static void Despawn(GameObject? box)
		{
			if (!((Object)(object)box == (Object)null))
			{
				PhysGrabObject key = default(PhysGrabObject);
				if (box.TryGetComponent<PhysGrabObject>(ref key))
				{
					Boxes.Remove(key);
				}
				if (SemiFunc.IsMultiplayer())
				{
					PhotonNetwork.Destroy(box);
				}
				else
				{
					Object.Destroy((Object)(object)box);
				}
			}
		}

		public static void Forget()
		{
			SoloSpawns.Clear();
			Boxes.Clear();
		}

		public static void Adopt(CosmeticWorldObject box)
		{
			if (SoloSpawns.TryGetValue(((Component)box).gameObject, out ExtractionPoint value))
			{
				SoloSpawns.Remove(((Component)box).gameObject);
			}
			else if (!IsTagged(((Component)box).GetComponent<PhotonView>(), out value))
			{
				return;
			}
			RoundDirector.instance.cosmeticWorldObjects.Remove(box);
			box.tutorialActive = false;
			ValuableDiscoverCustom val = default(ValuableDiscoverCustom);
			if (((Component)box).TryGetComponent<ValuableDiscoverCustom>(ref val))
			{
				val.customMap.Clear();
				val.discovered = true;
			}
			Boxes[box.physGrabObject] = value;
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				((Component)box).gameObject.AddComponent<PadBoxPin>().Pin(box.physGrabObject);
			}
		}

		public static ExtractionPoint? PointFor(PhysGrabObject grab)
		{
			if (!((Object)(object)grab != (Object)null) || !Boxes.TryGetValue(grab, out ExtractionPoint value))
			{
				return null;
			}
			return value;
		}

		private static bool IsTagged(PhotonView? view, out ExtractionPoint? point)
		{
			point = null;
			object[] array = (((Object)(object)view != (Object)null) ? view.InstantiationData : null);
			if (array == null || array.Length != 5 || !(array[3] is string text) || text != "Vippy.ZeroGravityExtraction")
			{
				return false;
			}
			if (array[4] is int num)
			{
				PhotonView val = PhotonView.Find(num);
				if (val != null)
				{
					point = ((Component)val).GetComponent<ExtractionPoint>();
				}
			}
			return true;
		}

		private static PrefabRef? CommonBox()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ValuableDirector.instance == (Object)null)
			{
				return null;
			}
			foreach (CosmeticWorldObjectSetup cosmeticWorldObjectSetup in ValuableDirector.instance.cosmeticWorldObjectSetups)
			{
				if ((int)cosmeticWorldObjectSetup.rarity == 0)
				{
					return cosmeticWorldObjectSetup.prefab;
				}
			}
			return null;
		}
	}
	internal class PadBoxPin : MonoBehaviour
	{
		private PhysGrabObject _grab;

		private Vector3 _position;

		private Quaternion _rotation;

		public void Pin(PhysGrabObject grab)
		{
			//IL_000e: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			_grab = grab;
			_position = ((Component)this).transform.position;
			_rotation = ((Component)this).transform.rotation;
			grab.impactDetector.destroyDisable = true;
		}

		private void FixedUpdate()
		{
			//IL_0026: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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)
			_grab.OverrideKinematic(0.2f);
			_grab.OverrideIndestructible(0.2f);
			if (!(((Component)this).transform.position == _position) || !(((Component)this).transform.rotation == _rotation))
			{
				_grab.rb.position = _position;
				_grab.rb.rotation = _rotation;
				((Component)this).transform.SetPositionAndRotation(_position, _rotation);
			}
		}
	}
	public class ZeroGravityNet : MonoBehaviour
	{
		[PunRPC]
		public void ZGE_TogglePad(int padViewId, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			PhotonView val = PhotonView.Find(padViewId);
			if (!((Object)(object)val == (Object)null))
			{
				ExtractionPoint component = ((Component)val).GetComponent<ExtractionPoint>();
				if ((Object)(object)component != (Object)null)
				{
					ZeroGravityPadService.Instance?.TogglePadByPoint(component, "remote");
				}
			}
		}
	}
	public class ZeroGravityPadService : MonoBehaviour
	{
		private readonly struct FloatTarget
		{
			public readonly int Key;

			public readonly int ViewId;

			public readonly Vector3 Position;

			public readonly PhysGrabObject? PhysObject;

			public readonly PlayerAvatar? Player;

			public readonly float Ceiling;

			public readonly Collider[] Colliders;

			public FloatTarget(int key, int viewId, Vector3 position, PhysGrabObject? physObject, PlayerAvatar? player, float ceiling, Collider[] colliders)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				Ceiling = ceiling;
				Colliders = colliders;
				Key = key;
				ViewId = viewId;
				Position = position;
				PhysObject = physObject;
				Player = player;
			}
		}

		private const float AffectTime = 1.5f;

		private const float TickInterval = 0.5f;

		private const float CeilingSkin = 0.05f;

		private const float CeilingBounce = 0.3f;

		private const float CeilingSafeZone = 1f;

		private const float MaxTopReach = 1.5f;

		internal static ZeroGravityPadService? Instance;

		private const string RoomKey = "zge_host";

		private GameObject? _affectPrefab;

		private string? _orbResourcePath;

		private bool _resolveFailed;

		private int _resolveAttempts;

		private bool _anchorsFailed;

		private readonly HashSet<int> _seen = new HashSet<int>();

		private readonly List<int> _stale = new List<int>();

		private readonly List<FloatTarget> _targets = new List<FloatTarget>();

		private readonly List<FloatTarget> _held = new List<FloatTarget>();

		private float _scanCeiling;

		private readonly Dictionary<int, GameObject> _anchors = new Dictionary<int, GameObject>();

		private readonly Dictionary<int, GameObject> _boxes = new Dictionary<int, GameObject>();

		private readonly HashSet<int> _anchorsWanted = new HashSet<int>();

		private readonly Dictionary<int, SemiAffect> _activeAffects = new Dictionary<int, SemiAffect>();

		private readonly Dictionary<ItemDrone, bool> _dronesEncouraged = new Dictionary<ItemDrone, bool>();

		private readonly List<ItemDrone> _dronesToRelease = new List<ItemDrone>();

		private const float NetworkPulseInterval = 2.5f;

		private float _nextPulse;

		private int _playerCount;

		private readonly HashSet<int> _pulsed = new HashSet<int>();

		private readonly List<int> _viewIds = new List<int>();

		private readonly List<float> _times = new List<float>();

		private const float ToggleVolume = 1f;

		private const float ToggleFalloff = 3f;

		private Sound? _onSound;

		private Sound? _offSound;

		private bool _soundsResolved;

		private static readonly ParameterInfo[]? AffectParams = typeof(SemiAreaOfEffect).GetMethod("CreateAffectsRPC", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetParameters();

		private void OnEnable()
		{
			Instance = this;
			((MonoBehaviour)this).StartCoroutine(Loop());
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			RoundDirectorStartPatch.ServiceGone(this);
		}

		internal void ResetLevelState()
		{
			_anchors.Clear();
			_boxes.Clear();
			PadBox.Forget();
			_anchorsWanted.Clear();
			_activeAffects.Clear();
			_dronesEncouraged.Clear();
			_pulsed.Clear();
			_nextPulse = 0f;
			_playerCount = 0;
			_anchorsFailed = false;
		}

		private void FixedUpdate()
		{
			//IL_005d: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_00ce: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			foreach (FloatTarget item in _held)
			{
				PhysGrabObject physObject = item.PhysObject;
				Rigidbody val = (((Object)(object)physObject != (Object)null) ? physObject.rb : null);
				if ((Object)(object)physObject == (Object)null || (Object)(object)val == (Object)null || val.isKinematic)
				{
					continue;
				}
				float num = TopOf(item.Colliders, val.position.y);
				if (num < item.Ceiling - 1f)
				{
					continue;
				}
				if (physObject.isValuable)
				{
					physObject.OverrideIndestructible(1f);
				}
				float num2 = num - (item.Ceiling - 0.05f);
				if (!(num2 <= 0f))
				{
					val.position -= Vector3.up * num2;
					Vector3 linearVelocity = val.linearVelocity;
					if (linearVelocity.y > 0f)
					{
						linearVelocity.y = (0f - linearVelocity.y) * 0.3f;
						val.linearVelocity = linearVelocity;
					}
				}
			}
		}

		private static float TopOf(Collider[] colliders, float fallback)
		{
			//IL_002b: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			float num = float.NegativeInfinity;
			foreach (Collider val in colliders)
			{
				if ((Object)(object)val != (Object)null && val.enabled && !val.isTrigger)
				{
					float num2 = num;
					Bounds bounds = val.bounds;
					num = Mathf.Max(num2, ((Bounds)(ref bounds)).max.y);
				}
			}
			if (!float.IsNegativeInfinity(num))
			{
				return Mathf.Min(num, fallback + 1.5f);
			}
			return fallback;
		}

		private IEnumerator Loop()
		{
			WaitForSeconds wait = new WaitForSeconds(0.5f);
			while (true)
			{
				yield return wait;
				Tick();
			}
		}

		private void Tick()
		{
			_held.Clear();
			if (!PluginConfig.Enabled.Value)
			{
				SwitchOff();
			}
			else
			{
				if ((Object)(object)RoundDirector.instance == (Object)null || !SemiFunc.RunIsLevel())
				{
					return;
				}
				bool num = SemiFunc.IsMasterClientOrSingleplayer();
				if (num)
				{
					StampRoom(present: true);
				}
				if (num || RoomStamped())
				{
					EnsureAnchors();
				}
				else
				{
					DropAnchors(null);
				}
				if (!num || _resolveFailed || ((Object)(object)_affectPrefab == (Object)null && !TryResolveEffect()))
				{
					return;
				}
				_targets.Clear();
				_seen.Clear();
				if (PluginConfig.VanillaPlus.Value)
				{
					CollectDroneZoneTargets();
				}
				else
				{
					CollectButtonToggledTargets();
					ReleaseDrones(keepDeployed: false);
				}
				_held.AddRange(_targets);
				if (SemiFunc.IsMultiplayer())
				{
					NetworkPulse();
					return;
				}
				foreach (FloatTarget target in _targets)
				{
					ApplyFloat(target);
				}
				PruneLeftBehind();
			}
		}

		private void SwitchOff()
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				StampRoom(present: false);
			}
			if (_activeAffects.Count != 0 || _anchors.Count != 0 || _boxes.Count != 0 || _dronesEncouraged.Count != 0)
			{
				_seen.Clear();
				PruneLeftBehind();
				DropAnchors(null);
				ReleaseDrones(keepDeployed: false);
				_pulsed.Clear();
				ZeroGravityExtraction.LogInfo("Switched off: anchors and affects torn down.");
			}
		}

		private static void StampRoom(bool present)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0048: Expected O, but got Unknown
			if (SemiFunc.IsMultiplayer())
			{
				Room currentRoom = PhotonNetwork.CurrentRoom;
				if (currentRoom != null && ((Dictionary<object, object>)(object)((RoomInfo)currentRoom).CustomProperties).ContainsKey((object)"zge_host") != present)
				{
					Hashtable val = new Hashtable();
					((Dictionary<object, object>)val).Add((object)"zge_host", (object)(present ? "1.2.4" : null));
					currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
					ZeroGravityExtraction.LogVerbose(present ? "Room stamped: host runs the mod." : "Room stamp cleared.");
				}
			}
		}

		private static bool RoomStamped()
		{
			Room currentRoom = PhotonNetwork.CurrentRoom;
			if (currentRoom != null)
			{
				return ((Dictionary<object, object>)(object)((RoomInfo)currentRoom).CustomProperties).ContainsKey((object)"zge_host");
			}
			return false;
		}

		private void CollectDroneZoneTargets()
		{
			foreach (GameObject extractionPoint in RoundDirector.instance.extractionPointList)
			{
				ExtractionPoint val = ActivePoint(extractionPoint);
				if ((Object)(object)val != (Object)null && IsPadPowered(val))
				{
					FloatColumn(val);
				}
			}
			EncourageDronesToGrabAnchors();
		}

		private void CollectButtonToggledTargets()
		{
			foreach (GameObject extractionPoint in RoundDirector.instance.extractionPointList)
			{
				ExtractionPoint val = ActivePoint(extractionPoint);
				if (!((Object)(object)val == (Object)null) && _anchors.TryGetValue(((Object)val).GetInstanceID(), out GameObject value) && !((Object)(object)value == (Object)null))
				{
					PadAnchor component = value.GetComponent<PadAnchor>();
					if ((Object)(object)component != (Object)null && component.ZeroGravityOn)
					{
						FloatPadVolume(val);
					}
				}
			}
		}

		private static ExtractionPoint? ActivePoint(GameObject pointObject)
		{
			if ((Object)(object)pointObject == (Object)null)
			{
				return null;
			}
			ExtractionPoint component = pointObject.GetComponent<ExtractionPoint>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.roomVolume == (Object)null || !component.roomVolume.activeInHierarchy)
			{
				return null;
			}
			return component;
		}

		internal void TogglePadByPoint(ExtractionPoint point, string source)
		{
			if (_anchors.TryGetValue(((Object)point).GetInstanceID(), out GameObject value) && !((Object)(object)value == (Object)null))
			{
				PadAnchor component = value.GetComponent<PadAnchor>();
				if ((Object)(object)component != (Object)null)
				{
					component.Toggle(source);
				}
			}
		}

		internal void PlayToggleSound(bool on, ExtractionPoint point)
		{
			//IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			ResolveToggleSounds();
			Vector3 val = AnchorPosition(point);
			Sound val2 = (on ? _onSound : _offSound);
			if (val2 != null)
			{
				val2.Play(val, 1f, 3f, 1f, 1f);
			}
			else if ((Object)(object)point != (Object)null)
			{
				Sound obj = (on ? point.soundButton : point.soundCancel);
				if (obj != null)
				{
					obj.Play(val, 1f, 1f, 1f, 1f);
				}
			}
		}

		private Vector3 AnchorPosition(ExtractionPoint point)
		{
			//IL_0042: 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_0055: 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)
			if ((Object)(object)point != (Object)null && _anchors.TryGetValue(((Object)point).GetInstanceID(), out GameObject value) && (Object)(object)value != (Object)null)
			{
				return value.transform.position;
			}
			if ((Object)(object)point != (Object)null)
			{
				return ((Component)point).transform.position;
			}
			if (!((Object)(object)Camera.main != (Object)null))
			{
				return Vector3.zero;
			}
			return ((Component)Camera.main).transform.position;
		}

		private void ResolveToggleSounds()
		{
			if (_soundsResolved || (Object)(object)StatsManager.instance == (Object)null)
			{
				return;
			}
			foreach (Item value in StatsManager.instance.itemDictionary.Values)
			{
				GameObject val = ((!((Object)(object)value != (Object)null)) ? null : ((PrefabRef<GameObject>)(object)value.prefab)?.Prefab);
				ItemDrone val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInChildren<ItemDrone>(true) : null);
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).GetComponentInChildren<ItemDroneZeroGravity>(true) == (Object)null))
				{
					ItemDroneSounds itemDroneSounds = val2.itemDroneSounds;
					if (!((Object)(object)itemDroneSounds == (Object)null))
					{
						_onSound = itemDroneSounds.DroneStart;
						_offSound = itemDroneSounds.DroneEnd;
						_soundsResolved = true;
						break;
					}
				}
			}
		}

		private void EnsureAnchors()
		{
			bool flag = SemiFunc.IsMasterClientOrSingleplayer();
			bool flag2 = !PluginConfig.VanillaPlus.Value;
			_anchorsWanted.Clear();
			foreach (GameObject extractionPoint in RoundDirector.instance.extractionPointList)
			{
				ExtractionPoint val = ActivePoint(extractionPoint);
				if (!((Object)(object)val == (Object)null))
				{
					int instanceID = ((Object)val).GetInstanceID();
					if (flag || !flag2)
					{
						_anchorsWanted.Add(instanceID);
						EnsureAnchor(val);
					}
					if (flag && flag2 && !_anchorsFailed)
					{
						EnsureBox(val, instanceID);
					}
					else if (flag)
					{
						DropBox(instanceID);
					}
				}
			}
			DropAnchors(_anchorsWanted);
		}

		private void EnsureBox(ExtractionPoint point, int key)
		{
			if (!_boxes.TryGetValue(key, out GameObject value) || !((Object)(object)value != (Object)null))
			{
				GameObject val = PadBox.Spawn(point);
				if ((Object)(object)val != (Object)null)
				{
					_boxes[key] = val;
				}
			}
		}

		private void DropBox(int key)
		{
			if (_boxes.TryGetValue(key, out GameObject value))
			{
				PadBox.Despawn(value);
				_boxes.Remove(key);
			}
		}

		private void DropAnchors(HashSet<int>? keep)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				DropBoxes(keep);
			}
			foreach (int item in Unwanted(_anchors, keep))
			{
				if ((Object)(object)_anchors[item] != (Object)null)
				{
					Object.Destroy((Object)(object)_anchors[item]);
				}
				_anchors.Remove(item);
			}
		}

		private void DropBoxes(HashSet<int>? keep)
		{
			foreach (int item in Unwanted(_boxes, keep))
			{
				DropBox(item);
			}
		}

		private List<int> Unwanted(Dictionary<int, GameObject> entries, HashSet<int>? keep)
		{
			_stale.Clear();
			foreach (int key in entries.Keys)
			{
				if (keep == null || !keep.Contains(key))
				{
					_stale.Add(key);
				}
			}
			return _stale;
		}

		private void EncourageDronesToGrabAnchors()
		{
			foreach (ItemDrone activeDrone in ItemDrone.activeDrones)
			{
				if (!((Object)(object)activeDrone == (Object)null) && activeDrone.itemActivated && !((Object)(object)((Component)activeDrone).GetComponent<ItemDroneZeroGravity>() == (Object)null) && !_dronesEncouraged.ContainsKey(activeDrone))
				{
					_dronesEncouraged[activeDrone] = activeDrone.targetNonValuables;
					activeDrone.targetNonValuables = true;
				}
			}
			ReleaseDrones(keepDeployed: true);
		}

		private void ReleaseDrones(bool keepDeployed)
		{
			if (_dronesEncouraged.Count == 0)
			{
				return;
			}
			_dronesToRelease.Clear();
			foreach (KeyValuePair<ItemDrone, bool> item in _dronesEncouraged)
			{
				ItemDrone key = item.Key;
				if (!keepDeployed || !StillDeployed(key))
				{
					_dronesToRelease.Add(key);
					if ((Object)(object)key != (Object)null)
					{
						key.targetNonValuables = item.Value;
					}
				}
			}
			foreach (ItemDrone item2 in _dronesToRelease)
			{
				_dronesEncouraged.Remove(item2);
			}
		}

		private static bool StillDeployed(ItemDrone drone)
		{
			if ((Object)(object)drone != (Object)null && drone.itemActivated)
			{
				return ItemDrone.activeDrones.Contains(drone);
			}
			return false;
		}

		private void EnsureAnchor(ExtractionPoint point)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if (_anchorsFailed)
			{
				return;
			}
			int instanceID = ((Object)point).GetInstanceID();
			bool flag = !PluginConfig.VanillaPlus.Value;
			if (_anchors.TryGetValue(instanceID, out GameObject value) && (Object)(object)value != (Object)null)
			{
				PadAnchor component = value.GetComponent<PadAnchor>();
				if ((Object)(object)component != (Object)null && component.ButtonMode == flag)
				{
					return;
				}
				Object.Destroy((Object)(object)value);
				_anchors.Remove(instanceID);
			}
			try
			{
				Transform val = (((Object)(object)point.platform != (Object)null) ? point.platform : ((Component)point).transform);
				GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)val2).name = "ZeroGravityExtraction_Anchor";
				val2.tag = "Phys Grab Object";
				val2.layer = LayerMask.NameToLayer("PhysGrabObject");
				val2.transform.SetParent(val, false);
				val2.transform.localPosition = AnchorSettings.GrabOffset;
				val2.transform.localRotation = Quaternion.identity;
				val2.GetComponent<Renderer>().enabled = false;
				if (flag)
				{
					Object.Destroy((Object)(object)val2.GetComponent<Collider>());
				}
				else
				{
					val2.AddComponent<PhotonView>();
					val2.AddComponent<Rigidbody>();
					val2.AddComponent<PhysGrabObject>();
					val2.AddComponent<PhysGrabObjectCollider>();
				}
				PadAnchor padAnchor = val2.AddComponent<PadAnchor>();
				padAnchor.ButtonMode = flag;
				padAnchor.Point = point;
				val2.AddComponent<AnchorLock>();
				_anchors[instanceID] = val2;
				ZeroGravityExtraction.LogVerbose(string.Format("Anchor placed on pad {0} ({1}).", instanceID, flag ? "button" : "drone"));
			}
			catch (Exception ex)
			{
				_anchorsFailed = true;
				ZeroGravityExtraction.Logger.LogWarning((object)("Anchor creation failed: " + ex.Message));
			}
		}

		private void FloatColumn(ExtractionPoint point)
		{
			//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_0048: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)point.platform != (Object)null) ? point.platform : ((Component)point).transform);
			float num = 26f;
			Vector3 val2 = val.TransformPoint(new Vector3(AnchorSettings.GrabOffset.x, 0f, AnchorSettings.GrabOffset.z)) + val.up * (num * 0.5f);
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(2.5f, num * 0.5f, 2.5f);
			_scanCeiling = RoomTop(point);
			Collider[] array = Physics.OverlapBox(val2, val3, val.rotation, -1, (QueryTriggerInteraction)2);
			foreach (Collider hit in array)
			{
				Consider(hit);
			}
		}

		private void FloatPadVolume(ExtractionPoint point)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0047: 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_0056: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			_scanCeiling = RoomTop(point);
			Collider[] componentsInChildren = point.roomVolume.GetComponentsInChildren<Collider>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Bounds bounds = componentsInChildren[i].bounds;
				Vector3 val = ((Bounds)(ref bounds)).center + Vector3.up * 10f;
				Vector3 val2 = ((Bounds)(ref bounds)).extents + Vector3.up * 10f;
				Collider[] array = Physics.OverlapBox(val, val2, Quaternion.identity, -1, (QueryTriggerInteraction)2);
				foreach (Collider hit in array)
				{
					Consider(hit);
				}
			}
		}

		private static float RoomTop(ExtractionPoint point)
		{
			//IL_001c: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			float num = float.NegativeInfinity;
			Collider[] componentsInChildren = point.roomVolume.GetComponentsInChildren<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				float num2 = num;
				Bounds bounds = val.bounds;
				num = Mathf.Max(num2, ((Bounds)(ref bounds)).max.y);
			}
			return num;
		}

		private bool IsPadPowered(ExtractionPoint point)
		{
			if (!_anchors.TryGetValue(((Object)point).GetInstanceID(), out GameObject value) || (Object)(object)value == (Object)null)
			{
				return false;
			}
			PhysGrabObject component = value.GetComponent<PhysGrabObject>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			foreach (ItemDrone activeDrone in ItemDrone.activeDrones)
			{
				if (!((Object)(object)activeDrone == (Object)null) && activeDrone.itemActivated && !((Object)(object)((Component)activeDrone).GetComponent<ItemDroneZeroGravity>() == (Object)null))
				{
					ItemBattery component2 = ((Component)activeDrone).GetComponent<ItemBattery>();
					if (!((Object)(object)component2 == (Object)null) && !(component2.batteryLife <= 0f) && activeDrone.magnetActive && (Object)(object)activeDrone.magnetTargetPhysGrabObject == (Object)(object)component)
					{
						return true;
					}
				}
			}
			return false;
		}

		private void Consider(Collider hit)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar componentInParent = ((Component)hit).GetComponentInParent<PlayerAvatar>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				if (PluginConfig.FloatPlayers.Value)
				{
					Register(((Object)componentInParent).GetInstanceID(), ViewIdOf(componentInParent.photonView), ((Component)componentInParent).transform.position, componentInParent.tumble.physGrabObject, componentInParent);
				}
				return;
			}
			EnemyParent componentInParent2 = ((Component)hit).GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent2 != (Object)null)
			{
				if (PluginConfig.FloatEnemies.Value)
				{
					Register(((Object)componentInParent2).GetInstanceID(), ViewIdOf(((MonoBehaviourPun)componentInParent2).photonView), ((Component)componentInParent2).transform.position, ((Component)componentInParent2).GetComponentInChildren<PhysGrabObject>(), null);
				}
				return;
			}
			PhysGrabObject componentInParent3 = ((Component)hit).GetComponentInParent<PhysGrabObject>();
			CosmeticWorldObject item = default(CosmeticWorldObject);
			if ((!((Object)(object)componentInParent3 != (Object)null) || !((Component)componentInParent3).TryGetComponent<CosmeticWorldObject>(ref item) || RoundDirector.instance.cosmeticWorldObjects.Contains(item)) && (Object)(object)componentInParent3 != (Object)null && PhysObjectAllowed(componentInParent3))
			{
				Register(((Object)componentInParent3).GetInstanceID(), ViewIdOf(componentInParent3.photonView), ((Component)componentInParent3).transform.position, componentInParent3, null);
			}
		}

		private static int ViewIdOf(PhotonView? view)
		{
			if (!((Object)(object)view != (Object)null))
			{
				return 0;
			}
			return view.ViewID;
		}

		private static bool PhysObjectAllowed(PhysGrabObject physObject)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)physObject).GetComponent<ValuableObject>() != (Object)null)
			{
				return PluginConfig.FloatValuables.Value;
			}
			if ((Object)(object)((Component)physObject).GetComponent<CosmeticWorldObject>() != (Object)null)
			{
				return PluginConfig.FloatCosmeticBoxes.Value;
			}
			ItemAttributes component = ((Component)physObject).GetComponent<ItemAttributes>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.item != (Object)null && IsWeapon(component.item.itemType))
			{
				return PluginConfig.FloatWeapons.Value;
			}
			return PluginConfig.FloatItems.Value;
		}

		private static bool IsWeapon(itemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			if ((int)type != 9 && (int)type != 7 && (int)type != 15 && (int)type != 6)
			{
				return (int)type == 11;
			}
			return true;
		}

		private void Register(int key, int viewId, Vector3 position, PhysGrabObject? physObject, PlayerAvatar? player)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (_seen.Add(key))
			{
				Collider[] colliders = (((Object)(object)physObject != (Object)null) ? ((Component)physObject).GetComponentsInChildren<Collider>() : Array.Empty<Collider>());
				_targets.Add(new FloatTarget(key, viewId, position, physObject, player, _scanCeiling, colliders));
			}
		}

		private void NetworkPulse()
		{
			int num = ((PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.PlayerCount : 0);
			if (num != _playerCount)
			{
				_playerCount = num;
				_nextPulse = 0f;
			}
			if (_targets.Count == 0)
			{
				_pulsed.Clear();
				return;
			}
			bool flag = Time.time >= _nextPulse;
			_viewIds.Clear();
			_times.Clear();
			foreach (FloatTarget target in _targets)
			{
				if (target.ViewId != 0 && (flag || !_pulsed.Contains(target.Key)))
				{
					_viewIds.Add(target.ViewId);
					_times.Add(1.5f);
				}
			}
			if (_viewIds.Count > 0)
			{
				FireOrb(_viewIds.ToArray(), _times.ToArray());
			}
			if (flag)
			{
				_nextPulse = Time.time + 2.5f;
				_pulsed.Clear();
			}
			foreach (FloatTarget target2 in _targets)
			{
				_pulsed.Add(target2.Key);
			}
		}

		private void FireOrb(int[] viewIds, float[] times)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(_orbResourcePath))
			{
				return;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f, -1000f, 0f);
			GameObject val2 = PhotonNetwork.Instantiate(_orbResourcePath, val, Quaternion.identity, (byte)0, (object[])null);
			if (!((Object)(object)val2 == (Object)null))
			{
				SlowProjectile component = val2.GetComponent<SlowProjectile>();
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = false;
				}
				SemiAreaOfEffect componentInChildren = val2.GetComponentInChildren<SemiAreaOfEffect>(true);
				if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.photonView == (Object)null)
				{
					PhotonNetwork.Destroy(val2);
					return;
				}
				componentInChildren.photonView.RPC("CreateAffectsRPC", (RpcTarget)0, AffectArgs(viewIds, times, val, Vector3.up));
				((MonoBehaviour)this).StartCoroutine(DestroyOrbLater(val2));
			}
		}

		private static object[] AffectArgs(int[] viewIds, float[] times, Vector3 position, Vector3 direction)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			if (AffectParams == null)
			{
				return new object[4] { viewIds, times, position, direction };
			}
			List<object> list = new List<object>();
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			ParameterInfo[] affectParams = AffectParams;
			for (int i = 0; i < affectParams.Length; i++)
			{
				Type parameterType = affectParams[i].ParameterType;
				if (parameterType == typeof(Vector3))
				{
					list.Add(flag3 ? direction : position);
					flag3 = true;
				}
				else if (parameterType == typeof(int[]) && !flag)
				{
					list.Add(viewIds);
					flag = true;
				}
				else if (parameterType == typeof(float[]) && !flag2)
				{
					list.Add(times);
					flag2 = true;
				}
				else if (parameterType.IsArray)
				{
					list.Add(Array.CreateInstance(parameterType.GetElementType(), viewIds.Length));
				}
			}
			return list.ToArray();
		}

		private IEnumerator DestroyOrbLater(GameObject orb)
		{
			yield return (object)new WaitForSeconds(1f);
			if ((Object)(object)orb != (Object)null)
			{
				PhotonNetwork.Destroy(orb);
			}
		}

		private void ApplyFloat(FloatTarget target)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_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)
			if ((Object)(object)target.PhysObject == (Object)null)
			{
				return;
			}
			if (_activeAffects.TryGetValue(target.Key, out SemiAffect value) && (Object)(object)value != (Object)null)
			{
				value.timer = value.timerTotal;
				return;
			}
			SemiAffect component = Object.Instantiate<GameObject>(_affectPrefab, target.Position, Quaternion.identity).GetComponent<SemiAffect>();
			component.direction = Vector3.up;
			component.positionOfOriginalAreaOfEffect = target.Position;
			component.SetupSingleplayer(((Component)target.PhysObject).transform, target.PhysObject, 1.5f, target.Player);
			ParticleSystem[] componentsInChildren = ((Component)component).GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				MainModule main = componentsInChildren[i].main;
				((MainModule)(ref main)).stopAction = (ParticleSystemStopAction)0;
			}
			_activeAffects[target.Key] = component;
		}

		private void PruneLeftBehind()
		{
			if (_activeAffects.Count == 0)
			{
				return;
			}
			_stale.Clear();
			foreach (KeyValuePair<int, SemiAffect> activeAffect in _activeAffects)
			{
				if (!_seen.Contains(activeAffect.Key))
				{
					if ((Object)(object)activeAffect.Value != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)activeAffect.Value).gameObject);
					}
					_stale.Add(activeAffect.Key);
				}
			}
			foreach (int item in _stale)
			{
				_activeAffects.Remove(item);
			}
		}

		private bool TryResolveEffect()
		{
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null || instance.itemDictionary.Count == 0)
			{
				return false;
			}
			bool flag = false;
			int num = 0;
			Item val = null;
			GameObject affectPrefab = null;
			string orbPath = null;
			foreach (Item value in instance.itemDictionary.Values)
			{
				GameObject val2 = ((!((Object)(object)value != (Object)null)) ? null : ((PrefabRef<GameObject>)(object)value.prefab)?.Prefab);
				ItemStaffZeroGravity val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponentInChildren<ItemStaffZeroGravity>(true) : null);
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				flag = true;
				PrefabRef projectilePrefab = val3.projectilePrefab;
				if (projectilePrefab == null || (Object)(object)((PrefabRef<GameObject>)(object)projectilePrefab).Bundle != (Object)null || !((PrefabRef<GameObject>)(object)projectilePrefab).IsValid())
				{
					num++;
					continue;
				}
				GameObject prefab = ((PrefabRef<GameObject>)(object)projectilePrefab).Prefab;
				GameObject val4 = ((PrefabRef<GameObject>)(object)(((Object)(object)prefab != (Object)null) ? prefab.GetComponentInChildren<SemiAreaOfEffect>(true) : null)?.semiAffectPrefab)?.Prefab;
				if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4.GetComponentInChildren<SemiAffectZeroGravity>(true) == (Object)null))
				{
					string resourcePath = ((PrefabRef<GameObject>)(object)projectilePrefab).ResourcePath;
					if (Resources.Load(resourcePath) != (Object)null)
					{
						Adopt(value, val4, resourcePath, num, "vanilla");
						return true;
					}
					if ((Object)(object)val == (Object)null && (Object)(object)Resources.Load<GameObject>(resourcePath) != (Object)null)
					{
						val = value;
						affectPrefab = val4;
						orbPath = resourcePath;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				Adopt(val, affectPrefab, orbPath, num, "registered by another mod, no vanilla staff found");
				return true;
			}
			if (++_resolveAttempts >= 5)
			{
				_resolveFailed = true;
				ZeroGravityExtraction.Logger.LogWarning((object)$"Zero-gravity staff effect not found (scanned {instance.itemDictionary.Count} items, staff present: {flag}, bundle look-alikes skipped: {num}); floating disabled.");
			}
			return false;
		}

		private void Adopt(Item item, GameObject affectPrefab, string orbPath, int skipped, string how)
		{
			_affectPrefab = affectPrefab;
			_orbResourcePath = orbPath;
			ZeroGravityExtraction.LogInfo($"Resolved zero-gravity effect from '{((Object)item).name}' ({how}; bundle look-alikes skipped: {skipped}).");
		}
	}
}
namespace ZeroGravityExtraction.Patches
{
	[HarmonyPatch]
	internal class PadBoxPatches
	{
		[HarmonyPatch(typeof(CosmeticWorldObject), "Start")]
		[HarmonyPostfix]
		public static void Spawned(CosmeticWorldObject __instance)
		{
			PadBox.Adopt(__instance);
		}

		[HarmonyPatch(typeof(PhysGrabObject), "GrabStartedRPC")]
		[HarmonyPrefix]
		public static void BeforeGrab(PhysGrabObject __instance, out int __state)
		{
			__state = __instance.playerGrabbing.Count;
		}

		[HarmonyPatch(typeof(PhysGrabObject), "GrabStartedRPC")]
		[HarmonyPostfix]
		public static void AfterGrab(PhysGrabObject __instance, int __state)
		{
			if (SemiFunc.IsMasterClient())
			{
				PressIfNew(__instance, __state);
			}
		}

		[HarmonyPatch(typeof(PhysGrabObject), "GrabStarted")]
		[HarmonyPrefix]
		public static void BeforeSoloGrab(PhysGrabObject __instance, out int __state)
		{
			__state = __instance.playerGrabbing.Count;
		}

		[HarmonyPatch(typeof(PhysGrabObject), "GrabStarted")]
		[HarmonyPostfix]
		public static void AfterSoloGrab(PhysGrabObject __instance, int __state)
		{
			if (!SemiFunc.IsMultiplayer())
			{
				PressIfNew(__instance, __state);
			}
		}

		private static void PressIfNew(PhysGrabObject grab, int countBefore)
		{
			if (grab.playerGrabbing.Count > countBefore)
			{
				ExtractionPoint val = PadBox.PointFor(grab);
				if ((Object)(object)val != (Object)null)
				{
					ZeroGravityPadService.Instance?.TogglePadByPoint(val, "box");
				}
			}
		}
	}
	[HarmonyPatch(typeof(PunManager), "Awake")]
	internal class PunManagerPatch
	{
		[HarmonyPostfix]
		public static void Postfix(PunManager __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<ZeroGravityNet>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<ZeroGravityNet>();
			}
		}
	}
	[HarmonyPatch(typeof(RoundDirector), "Start")]
	internal class RoundDirectorStartPatch
	{
		private static ZeroGravityPadService? _service;

		[HarmonyPostfix]
		public static void Postfix()
		{
			//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_0032: Expected O, but got Unknown
			if ((Object)(object)_service != (Object)null)
			{
				_service.ResetLevelState();
				return;
			}
			GameObject val = new GameObject("ZeroGravityExtraction_Service");
			_service = val.AddComponent<ZeroGravityPadService>();
			Object.DontDestroyOnLoad((Object)val);
			ZeroGravityExtraction.LogVerbose("Float service created.");
		}

		internal static void ServiceGone(ZeroGravityPadService service)
		{
			if ((Object)(object)_service == (Object)(object)service)
			{
				_service = null;
			}
		}
	}
}
namespace ZeroGravityExtraction.Configuration
{
	public enum VerbosityLevel
	{
		Off,
		Debug,
		Verbose
	}
	internal static class PluginConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<bool> VanillaPlus;

		public static ConfigEntry<bool> NonHostButton;

		public static ConfigEntry<bool> FloatValuables;

		public static ConfigEntry<bool> FloatCosmeticBoxes;

		public static ConfigEntry<bool> FloatItems;

		public static ConfigEntry<bool> FloatWeapons;

		public static ConfigEntry<bool> FloatPlayers;

		public static ConfigEntry<bool> FloatEnemies;

		public static ConfigEntry<VerbosityLevel> LoggingLevel;

		public static void Init(ConfigFile config)
		{
			Enabled = config.Bind<bool>("General", "Enabled", true, "Master switch.");
			VanillaPlus = config.Bind<bool>("General", "Vanilla+", false, "Off: the whole active pad is zero-gravity, toggled with the button on the pad. On: only a drone latched onto the pad floats a zone there.");
			NonHostButton = config.Bind<bool>("General", "Non-host button", true, "Flip a pad by touching the spot with a dead Semibot head. Works for players without the mod. Off means heads do nothing; the button on the pad still works.");
			FloatValuables = config.Bind<bool>("What floats", "Valuables", true, "Float the loot you're extracting.");
			FloatCosmeticBoxes = config.Bind<bool>("What floats", "Cosmetic boxes", true, "Float the cosmetic boxes you're extracting.");
			FloatItems = config.Bind<bool>("What floats", "Items", false, "Float tools, carts and other non-weapon props.");
			FloatWeapons = config.Bind<bool>("What floats", "Weapons", false, "Float guns, melee weapons, grenades, mines and launchers.");
			FloatPlayers = config.Bind<bool>("What floats", "Players", false, "Float Semibots in the pad.");
			FloatEnemies = config.Bind<bool>("What floats", "Enemies", true, "Float enemies in the pad.");
			LoggingLevel = config.Bind<VerbosityLevel>("General", "LogLevel", VerbosityLevel.Off, "Off: errors and one-time setup only. Debug: each effect. Verbose: full trace.");
		}
	}
}