Decompiled source of ZeroGravityExtraction v1.0.0

ZeroGravityExtraction.dll

Decompiled 7 hours 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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using ZeroGravityExtraction.Configuration;
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.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ZeroGravityExtraction")]
[assembly: AssemblyTitle("ZeroGravityExtraction")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ZeroGravityExtraction
{
	internal static class BuildInfo
	{
		public const string Version = "1.0.0";
	}
	[BepInPlugin("Vippy.ZeroGravityExtraction", "ZeroGravityExtraction", "1.0.0")]
	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 ZoneHeight = 6f;
	}
	public class PadAnchor : MonoBehaviour
	{
		public bool ZeroGravityOn;

		public bool ButtonMode;

		public int PadViewId;

		public ExtractionPoint? Point;

		private const float PokeCooldown = 0.5f;

		private StaticGrabObject? _staticGrab;

		private bool _wasGrabbed;

		private bool _wasPoked;

		private float _pokeCooldownTimer;

		private void Awake()
		{
			_staticGrab = ((Component)this).GetComponent<StaticGrabObject>();
		}

		private void Update()
		{
			if (!ButtonMode)
			{
				_wasGrabbed = false;
				_wasPoked = false;
				return;
			}
			if ((Object)(object)_staticGrab != (Object)null)
			{
				bool flag = (Object)(object)PhysGrabber.instance != (Object)null && (Object)(object)PhysGrabber.instance.grabbedStaticGrabObject == (Object)(object)_staticGrab;
				if (flag && !_wasGrabbed)
				{
					GrabToggle();
				}
				_wasGrabbed = flag;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer() && PluginConfig.NonHostButton.Value)
			{
				PokeCheck();
			}
		}

		private void PokeCheck()
		{
			if (_pokeCooldownTimer > 0f)
			{
				_pokeCooldownTimer -= Time.deltaTime;
			}
			bool flag = SomethingPoking();
			if (flag && !_wasPoked && _pokeCooldownTimer <= 0f)
			{
				ZeroGravityOn = !ZeroGravityOn;
				_pokeCooldownTimer = 0.5f;
				ZeroGravityExtraction.LogInfo("Pad zero-gravity toggled " + (ZeroGravityOn ? "on" : "off") + " (poked).");
				ZeroGravityPadService.Instance?.PlayToggleSound(ZeroGravityOn, Point);
			}
			_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)
			//IL_0088: 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)
			float num = 0.15f;
			Vector3 val = ((Component)this).transform.position + Vector3.up * 1.5f;
			Vector3 val2 = ((Component)this).transform.position - Vector3.up * 1.5f;
			Collider[] array = Physics.OverlapCapsule(val, val2, num, -1, (QueryTriggerInteraction)2);
			foreach (Collider val3 in array)
			{
				if (((Component)val3).transform.IsChildOf(((Component)this).transform))
				{
					continue;
				}
				Rigidbody attachedRigidbody = val3.attachedRigidbody;
				float num2 = PluginConfig.PokeSpeedMetersPerSecond();
				if ((Object)(object)attachedRigidbody != (Object)null)
				{
					Vector3 velocity = attachedRigidbody.velocity;
					if (((Vector3)(ref velocity)).sqrMagnitude > num2 * num2)
					{
						return true;
					}
				}
			}
			return false;
		}

		private void GrabToggle()
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				ZeroGravityOn = !ZeroGravityOn;
				ZeroGravityExtraction.LogInfo("Pad zero-gravity toggled " + (ZeroGravityOn ? "on" : "off") + ".");
				ZeroGravityPadService.Instance?.PlayToggleSound(ZeroGravityOn, Point);
			}
			else if ((Object)(object)PunManager.instance != (Object)null && PadViewId != 0)
			{
				PunManager.instance.photonView.RPC("ZGE_TogglePad", (RpcTarget)2, new object[1] { PadViewId });
			}
		}
	}
	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);
				}
			}
		}
	}
	public class ZeroGravityPadService : MonoBehaviour
	{
		private readonly struct FloatTarget
		{
			public readonly int Key;

			public readonly Vector3 Position;

			public readonly PhysGrabObject? PhysObject;

			public readonly PlayerAvatar? Player;

			public FloatTarget(int key, Vector3 position, PhysGrabObject? physObject, PlayerAvatar? player)
			{
				//IL_0008: 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)
				Key = key;
				Position = position;
				PhysObject = physObject;
				Player = player;
			}
		}

		[CompilerGenerated]
		private sealed class <Loop>d__14 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public ZeroGravityPadService <>4__this;

			private WaitForSeconds <wait>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Loop>d__14(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<wait>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Expected O, but got Unknown
				int num = <>1__state;
				ZeroGravityPadService zeroGravityPadService = <>4__this;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					zeroGravityPadService.Tick();
				}
				else
				{
					<>1__state = -1;
					<wait>5__2 = new WaitForSeconds(0.5f);
				}
				<>2__current = <wait>5__2;
				<>1__state = 1;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const float AffectTime = 1.5f;

		private const float TickInterval = 0.5f;

		internal static ZeroGravityPadService? Instance;

		private GameObject? _affectPrefab;

		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 Dictionary<int, GameObject> _anchors = new Dictionary<int, GameObject>();

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

		private const float ToggleVolume = 1f;

		private const float ToggleFalloff = 3f;

		private Sound? _onSound;

		private Sound? _offSound;

		private bool _soundsResolved;

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

		[IteratorStateMachine(typeof(<Loop>d__14))]
		private IEnumerator Loop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Loop>d__14(0)
			{
				<>4__this = this
			};
		}

		private void Tick()
		{
			if (!PluginConfig.Enabled.Value || (Object)(object)RoundDirector.instance == (Object)null)
			{
				return;
			}
			EnsureAnchors();
			if (!SemiFunc.IsMasterClientOrSingleplayer() || _resolveFailed || ((Object)(object)_affectPrefab == (Object)null && !TryResolveEffect()))
			{
				return;
			}
			_targets.Clear();
			_seen.Clear();
			if (PluginConfig.VanillaPlus.Value)
			{
				CollectDroneZoneTargets();
			}
			else
			{
				CollectButtonToggledTargets();
			}
			foreach (FloatTarget target in _targets)
			{
				ApplyFloat(target);
			}
			PruneLeftBehind();
		}

		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)
		{
			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.ZeroGravityOn = !component.ZeroGravityOn;
					ZeroGravityExtraction.LogInfo("Pad zero-gravity toggled " + (component.ZeroGravityOn ? "on" : "off") + " (remote).");
					PlayToggleSound(component.ZeroGravityOn, point);
				}
			}
		}

		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()
		{
			foreach (GameObject extractionPoint in RoundDirector.instance.extractionPointList)
			{
				ExtractionPoint val = ActivePoint(extractionPoint);
				if ((Object)(object)val != (Object)null)
				{
					EnsureAnchor(val);
				}
			}
		}

		private static void EncourageDronesToGrabAnchors()
		{
			foreach (ItemDrone activeDrone in ItemDrone.activeDrones)
			{
				if ((Object)(object)activeDrone != (Object)null && activeDrone.itemActivated && (Object)(object)((Component)activeDrone).GetComponent<ItemDroneZeroGravity>() != (Object)null)
				{
					activeDrone.targetNonValuables = true;
				}
			}
		}

		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;
				val2.AddComponent<PhotonView>();
				if (flag)
				{
					StaticGrabObject obj = val2.AddComponent<StaticGrabObject>();
					obj.colliderTransform = val2.transform;
					obj.uiPosition = val2.transform;
					obj.hoverText = "Zero Gravity";
				}
				else
				{
					val2.AddComponent<Rigidbody>();
					val2.AddComponent<PhysGrabObject>();
					val2.AddComponent<PhysGrabObjectCollider>();
				}
				PadAnchor padAnchor = val2.AddComponent<PadAnchor>();
				padAnchor.ButtonMode = flag;
				padAnchor.Point = point;
				padAnchor.PadViewId = (((Object)(object)point.photonView != (Object)null) ? point.photonView.ViewID : 0);
				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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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 = 6f;
			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);
			Collider[] array = Physics.OverlapBox(val2, val3, val.rotation, -1, (QueryTriggerInteraction)2);
			foreach (Collider hit in array)
			{
				Consider(hit);
			}
		}

		private void FloatPadVolume(ExtractionPoint point)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = point.roomVolume.GetComponentsInChildren<Collider>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Bounds bounds = componentsInChildren[i].bounds;
				Collider[] array = Physics.OverlapBox(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents, Quaternion.identity, -1, (QueryTriggerInteraction)2);
				foreach (Collider hit in array)
				{
					Consider(hit);
				}
			}
		}

		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_0029: 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_00a0: 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(), ((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(), ((Component)componentInParent2).transform.position, ((Component)componentInParent2).GetComponentInChildren<PhysGrabObject>(), null);
				}
				return;
			}
			PhysGrabObject componentInParent3 = ((Component)hit).GetComponentInParent<PhysGrabObject>();
			if ((Object)(object)componentInParent3 != (Object)null && PhysObjectAllowed(componentInParent3))
			{
				Register(((Object)componentInParent3).GetInstanceID(), ((Component)componentInParent3).transform.position, componentInParent3, null);
			}
		}

		private static bool PhysObjectAllowed(PhysGrabObject physObject)
		{
			//IL_003d: 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;
			}
			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, Vector3 position, PhysGrabObject? physObject, PlayerAvatar? player)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (_seen.Add(key))
			{
				_targets.Add(new FloatTarget(key, position, physObject, player));
			}
		}

		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;
			foreach (Item value in instance.itemDictionary.Values)
			{
				GameObject val = ((!((Object)(object)value != (Object)null)) ? null : ((PrefabRef<GameObject>)(object)value.prefab)?.Prefab);
				ItemStaffZeroGravity val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInChildren<ItemStaffZeroGravity>(true) : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					flag = true;
					GameObject val3 = ((PrefabRef<GameObject>)(object)val2.projectilePrefab)?.Prefab;
					GameObject val4 = ((PrefabRef<GameObject>)(object)(((Object)(object)val3 != (Object)null) ? val3.GetComponentInChildren<SemiAreaOfEffect>(true) : null)?.semiAffectPrefab)?.Prefab;
					if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4.GetComponentInChildren<SemiAffectZeroGravity>(true) == (Object)null))
					{
						_affectPrefab = val4;
						ZeroGravityExtraction.LogInfo("Resolved zero-gravity effect from '" + ((Object)value).name + "'.");
						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}); floating disabled.");
			}
			return false;
		}
	}
}
namespace ZeroGravityExtraction.Patches
{
	[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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			if (!((Object)(object)_service != (Object)null))
			{
				GameObject val = new GameObject("ZeroGravityExtraction_Service");
				_service = val.AddComponent<ZeroGravityPadService>();
				Object.DontDestroyOnLoad((Object)val);
				ZeroGravityExtraction.LogVerbose("Float service created.");
			}
		}
	}
}
namespace ZeroGravityExtraction.Configuration
{
	public enum VerbosityLevel
	{
		Off,
		Debug,
		Verbose
	}
	public enum PokeSpeedLevel
	{
		Low,
		Medium,
		High
	}
	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> FloatItems;

		public static ConfigEntry<bool> FloatWeapons;

		public static ConfigEntry<bool> FloatPlayers;

		public static ConfigEntry<bool> FloatEnemies;

		public static ConfigEntry<PokeSpeedLevel> PokeSpeed;

		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 by poking the spot. On: only a drone latched onto the pad floats a zone there.");
			NonHostButton = config.Bind<bool>("General", "Non-host button", true, "Let players without the mod flip a pad by poking the spot with something fast — a tumbling Semibot, a thrown valuable, a dead head. Turn it off to keep toggling to modded players grabbing the spot.");
			PokeSpeed = config.Bind<PokeSpeedLevel>("General", "Poke speed", PokeSpeedLevel.Medium, "How hard you have to hit the spot to toggle it. Low trips on a gentle nudge; High needs a fast throw. Only matters with the non-host button on.");
			FloatValuables = config.Bind<bool>("What floats", "Valuables", true, "Float the loot you're extracting.");
			FloatItems = config.Bind<bool>("What floats", "Items", true, "Float tools, carts and other non-weapon props.");
			FloatWeapons = config.Bind<bool>("What floats", "Weapons", true, "Float guns, melee weapons, grenades, mines and launchers.");
			FloatPlayers = config.Bind<bool>("What floats", "Players", true, "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.");
		}

		public static float PokeSpeedMetersPerSecond()
		{
			return PokeSpeed.Value switch
			{
				PokeSpeedLevel.Low => 2f, 
				PokeSpeedLevel.High => 7f, 
				_ => 4f, 
			};
		}
	}
}