Decompiled source of LethalOtis v1.3.1

LethalOtis.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using LethalOtis;
using LethalOtisMod;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("LethalOtis")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LethalOtis")]
[assembly: AssemblyTitle("LethalOtis")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public class MilkBucketItem : PhysicsProp
{
	private ScanNodeProperties _scanNode;

	private bool _lastHeld;

	public override void Start()
	{
		((GrabbableObject)this).itemProperties = Object.Instantiate<Item>(((GrabbableObject)this).itemProperties);
		((GrabbableObject)this).itemProperties.floorYOffset = 0;
		((GrabbableObject)this).Start();
		((Component)this).gameObject.layer = 6;
		((Component)this).gameObject.tag = "PhysicsProp";
		((GrabbableObject)this).propColliders = ((Component)this).GetComponents<Collider>();
		((GrabbableObject)this).mainObjectRenderer = ((Component)this).GetComponentInChildren<MeshRenderer>();
		AudioSource[] componentsInChildren = ((Component)this).GetComponentsInChildren<AudioSource>(true);
		foreach (AudioSource val in componentsInChildren)
		{
			val.spatialBlend = 1f;
		}
	}

	public override void Update()
	{
		((GrabbableObject)this).Update();
		if ((Object)(object)_scanNode == (Object)null)
		{
			_scanNode = ((Component)this).GetComponentInChildren<ScanNodeProperties>();
		}
		if ((Object)(object)_scanNode != (Object)null && ((GrabbableObject)this).isHeld != _lastHeld)
		{
			_lastHeld = ((GrabbableObject)this).isHeld;
			((Component)_scanNode).gameObject.SetActive(!((GrabbableObject)this).isHeld);
		}
	}
}
public class OtisCurse : NetworkBehaviour
{
	[Header("Curse Settings")]
	public float shrinkDuration = 60f;

	public float targetScale = 0.75f;

	public float curseRadius = 2f;

	public float shrinkTransitionTime = 10f;

	private float[] curseProgress;

	[Header("Stat Debuff Multipliers")]
	public float targetJump = 13f;

	public float targetSpeed = 4.6f;

	[Header("Voice Change Settings")]
	public float targetPitch = 1.5f;

	[Header("Sound Effect Logic")]
	public AudioSource headAudioSource;

	public AudioClip curseSoundEffect;

	private OtisRoam roam;

	private AudioSource debugMicSource;

	private string selectedMicDevice;

	private void Awake()
	{
		roam = ((Component)this).GetComponent<OtisRoam>();
	}

	private void OnTriggerEnter(Collider other)
	{
		//IL_0046: 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)
		if ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipIsLeaving)
		{
			return;
		}
		PlayerControllerB componentInParent = ((Component)other).gameObject.GetComponentInParent<PlayerControllerB>();
		if ((Object)(object)componentInParent == (Object)null || Vector3.Distance(((Component)this).transform.position, ((Component)componentInParent).transform.position) > curseRadius || !((NetworkBehaviour)componentInParent).IsOwner)
		{
			return;
		}
		if ((Object)(object)roam == (Object)null)
		{
			roam = ((Component)this).GetComponent<OtisRoam>();
		}
		if (!((Object)(object)roam == (Object)null))
		{
			int num = 1 << (int)componentInParent.playerClientId;
			if ((roam.cursedBitmask.Value & num) == 0)
			{
				Plugin.logger.LogInfo((object)("[OtisCurse] Local player '" + componentInParent.playerUsername + "' touched Otis — sending curse request."));
				roam.CursePlayerSend(componentInParent.playerClientId);
			}
		}
	}

	public void ApplyShrinkEffect(ulong playerId)
	{
		PlayerControllerB playerById = GetPlayerById(playerId);
		if ((Object)(object)playerById == (Object)null)
		{
			Plugin.logger.LogWarning((object)$"ApplyShrinkEffect: could not resolve player {playerId} on this client.");
			return;
		}
		if (((NetworkBehaviour)playerById).IsOwner)
		{
			playerById.movementSpeed = targetSpeed;
			playerById.jumpForce = targetJump;
		}
		if ((Object)(object)headAudioSource != (Object)null && (Object)(object)curseSoundEffect != (Object)null)
		{
			headAudioSource.PlayOneShot(curseSoundEffect);
		}
		Plugin.logger.LogInfo((object)(playerById.playerUsername + " was cursed by Otis!"));
	}

	private PlayerControllerB GetPlayerById(ulong playerId)
	{
		GameObject[] allPlayerObjects = StartOfRound.Instance.allPlayerObjects;
		foreach (GameObject val in allPlayerObjects)
		{
			PlayerControllerB component = val.GetComponent<PlayerControllerB>();
			if ((Object)(object)component != (Object)null && component.playerClientId == playerId)
			{
				return component;
			}
		}
		return null;
	}

	public override void OnNetworkDespawn()
	{
		if ((Object)(object)headAudioSource != (Object)null && headAudioSource.isPlaying)
		{
			headAudioSource.Stop();
		}
		((NetworkBehaviour)this).OnNetworkDespawn();
	}

	private void LateUpdate()
	{
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)SoundManager.Instance == (Object)null || StartOfRound.Instance.shipIsLeaving || (Object)(object)roam == (Object)null || roam.cursedBitmask.Value == 0)
		{
			return;
		}
		PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
		if (curseProgress == null || curseProgress.Length != allPlayerScripts.Length)
		{
			curseProgress = new float[allPlayerScripts.Length];
		}
		for (int i = 0; i < allPlayerScripts.Length; i++)
		{
			if ((roam.cursedBitmask.Value & (1 << i)) == 0)
			{
				continue;
			}
			PlayerControllerB val = allPlayerScripts[i];
			if ((Object)(object)val == (Object)null || val.disconnectedMidGame)
			{
				continue;
			}
			curseProgress[i] = Mathf.Min(1f, curseProgress[i] + Time.deltaTime / shrinkTransitionTime);
			float num = curseProgress[i];
			((Component)val).transform.localScale = Vector3.Lerp(Vector3.one, Vector3.one * targetScale, num);
			float num2 = Mathf.Lerp(1f, targetPitch, num);
			SoundManager.Instance.playerVoicePitchTargets[i] = num2;
			SoundManager.Instance.SetPlayerPitch(num2, i);
			if ((Object)(object)val.currentVoiceChatAudioSource != (Object)null)
			{
				val.currentVoiceChatAudioSource.pitch = num2;
			}
			if (((NetworkBehaviour)val).IsOwner && val.isPlayerControlled)
			{
				if (val.movementSpeed != targetSpeed)
				{
					val.movementSpeed = targetSpeed;
				}
				if (val.jumpForce != targetJump)
				{
					val.jumpForce = targetJump;
				}
			}
		}
	}

	private void StartMicLoopback()
	{
		if ((Object)(object)debugMicSource == (Object)null)
		{
			debugMicSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			debugMicSource.spatialBlend = 0f;
		}
		string text = 4.ToString();
		int num = (int)StartOfRound.Instance.localPlayerController.playerClientId;
		debugMicSource.pitch = 1.6f;
		if (Microphone.devices.Length != 0)
		{
			selectedMicDevice = Microphone.devices[0];
			debugMicSource.clip = Microphone.Start(selectedMicDevice, true, 1, 44100);
			debugMicSource.loop = true;
			((MonoBehaviour)this).StartCoroutine(WaitForMicToStart());
		}
		else
		{
			Plugin.logger.LogWarning((object)"No microphone detected for testing!");
		}
	}

	private IEnumerator WaitForMicToStart()
	{
		while (Microphone.GetPosition(selectedMicDevice) <= 0)
		{
			yield return null;
		}
		debugMicSource.Play();
		Plugin.logger.LogInfo((object)$"Mic Test Started! Playing back at Pitch: {debugMicSource.pitch}");
	}

	private void StopMicLoopback()
	{
		if ((Object)(object)debugMicSource != (Object)null && debugMicSource.isPlaying)
		{
			debugMicSource.Stop();
			Microphone.End(selectedMicDevice);
			Plugin.logger.LogInfo((object)"Mic Test Ended.");
		}
	}
}
public class OtisRoam : EnemyAI
{
	private const string MSG_CURSE_PLAYER = "LethalOtis.CursePlayer";

	private const string MSG_MILK_COLLECTED = "LethalOtis.MilkCollected";

	private const string MSG_SELF_DESTRUCT = "LethalOtis.TriggerSelfDestruct";

	private const string MSG_START_FLASHING = "LethalOtis.StartFlashing";

	private const string MSG_EXPLODE = "LethalOtis.Explode";

	private const string MSG_SHRINK_PLAYER = "LethalOtis.ShrinkPlayer";

	private static int s_instanceCount;

	[Header("Roaming Settings")]
	public float detectionRadius = 15f;

	public float NormalSpeed = 3f;

	public float StalkSpeed = 5f;

	[Header("Self-Destruct Settings")]
	public float selfDestructDelay = 5f;

	public float explosionKillRadius = 4f;

	public float explosionDamageRadius = 8f;

	public int explosionNonLethalDamage = 50;

	public float otisExplosionForceMin = 0.1f;

	public float otisExplosionForceMax = 1f;

	public float otisTimeToDespawn = 8f;

	public Transform[] explodePieces;

	[Header("Stalking Settings")]
	private bool isChasing = false;

	private float timeSinceLastSeen = 0f;

	private Vector3 lastKnownPosition;

	public float giveUpTime = 3f;

	[Header("Wandering Settings")]
	public float WanderDistance = 20f;

	public float MaxWanderTime = 7.5f;

	private float WanderTimer = 0f;

	private Vector3 previousPosition;

	private bool isSelfDestructing = false;

	private OtisCurse curse;

	public NetworkVariable<int> cursedBitmask = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

	public override void Start()
	{
		//IL_008c: 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)
		base.agent = ((Component)this).GetComponent<NavMeshAgent>();
		base.enemyType = Plugin.OtisEnemyType;
		((EnemyAI)this).Start();
		curse = ((Component)this).GetComponent<OtisCurse>();
		if ((Object)(object)base.creatureAnimator == (Object)null)
		{
			base.creatureAnimator = ((Component)this).GetComponentInChildren<Animator>();
			if ((Object)(object)base.creatureAnimator != (Object)null)
			{
				Plugin.logger.LogInfo((object)"Successfully linked Animator!");
			}
			else
			{
				Plugin.logger.LogWarning((object)"CRITICAL: No Animator component found!");
			}
		}
		NavMeshHit val = default(NavMeshHit);
		if (((NetworkBehaviour)this).IsServer && NavMesh.SamplePosition(((Component)this).transform.position, ref val, 10f, -1))
		{
			base.agent.Warp(((NavMeshHit)(ref val)).position);
			Plugin.logger.LogInfo((object)"Otis NavMesh position confirmed.");
		}
	}

	public override void OnNetworkSpawn()
	{
		((NetworkBehaviour)this).OnNetworkSpawn();
		s_instanceCount++;
		if (s_instanceCount == 1)
		{
			RegisterHandlers();
		}
	}

	public override void OnNetworkDespawn()
	{
		s_instanceCount = Math.Max(0, s_instanceCount - 1);
		if (s_instanceCount == 0)
		{
			UnregisterHandlers();
		}
		((NetworkBehaviour)this).OnNetworkDespawn();
	}

	public override void Update()
	{
		//IL_0031: 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_0061: 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 (!((Object)(object)base.agent == (Object)null))
		{
			((EnemyAI)this).Update();
			if ((Object)(object)base.creatureAnimator != (Object)null)
			{
				float num = Vector3.Distance(((Component)this).transform.position, previousPosition) / Time.deltaTime;
				base.creatureAnimator.SetFloat("Speed", num);
				previousPosition = ((Component)this).transform.position;
			}
		}
	}

	public override void DoAIInterval()
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		((EnemyAI)this).DoAIInterval();
		if (!((NetworkBehaviour)this).IsServer || (Object)(object)base.agent == (Object)null || !base.agent.isOnNavMesh || isSelfDestructing)
		{
			return;
		}
		Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, 1.5f);
		Collider[] array2 = array;
		foreach (Collider val in array2)
		{
			DoorLock componentInParent = ((Component)val).GetComponentInParent<DoorLock>();
			if (!((Object)(object)componentInParent == (Object)null) && !Traverse.Create((object)componentInParent).Field("isDoorOpened").GetValue<bool>() && !componentInParent.isLocked)
			{
				componentInParent.OpenDoorAsEnemyServerRpc();
			}
		}
		PlayerControllerB val2 = null;
		float num = detectionRadius;
		PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
		foreach (PlayerControllerB val3 in allPlayerScripts)
		{
			if (!val3.isPlayerDead && val3.isInsideFactory && (cursedBitmask.Value & (1 << (int)val3.playerClientId)) == 0)
			{
				float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)val3).transform.position);
				if (num2 < num)
				{
					num = num2;
					val2 = val3;
				}
			}
		}
		if ((Object)(object)val2 != (Object)null)
		{
			StalkPlayer(val2);
		}
		else
		{
			HandleWandering();
		}
	}

	private void StalkPlayer(PlayerControllerB target)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		if (!Physics.Linecast(((Component)this).transform.position, ((Component)target).transform.position, StartOfRound.Instance.collidersAndRoomMask))
		{
			isChasing = true;
			timeSinceLastSeen = 0f;
			lastKnownPosition = ((Component)target).transform.position;
			base.agent.speed = StalkSpeed;
			base.agent.SetDestination(lastKnownPosition);
		}
		else if (isChasing)
		{
			timeSinceLastSeen += base.AIIntervalTime;
			base.agent.SetDestination(lastKnownPosition);
			if (timeSinceLastSeen >= giveUpTime)
			{
				isChasing = false;
				timeSinceLastSeen = 0f;
				Plugin.logger.LogInfo((object)"Otis gave up chasing!");
				HandleWandering();
			}
		}
		else
		{
			HandleWandering();
		}
	}

	private void HandleWandering()
	{
		//IL_0073: 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_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)base.agent == (Object)null) && base.agent.isOnNavMesh)
		{
			WanderTimer += base.AIIntervalTime;
			if (MaxWanderTime <= WanderTimer || base.agent.remainingDistance <= base.agent.stoppingDistance)
			{
				Vector3 destination = RandomNavSphere(((Component)this).transform.position, WanderDistance, -1);
				base.agent.SetDestination(destination);
				base.agent.speed = NormalSpeed;
				WanderTimer = 0f;
			}
		}
	}

	public static Vector3 RandomNavSphere(Vector3 origin, float dist, int layermask)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = Random.insideUnitSphere * dist;
		val += origin;
		NavMeshHit val2 = default(NavMeshHit);
		if (NavMesh.SamplePosition(val, ref val2, dist, layermask))
		{
			return ((NavMeshHit)(ref val2)).position;
		}
		return origin;
	}

	private static void RegisterHandlers()
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Expected O, but got Unknown
		CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager;
		customMessagingManager.RegisterNamedMessageHandler("LethalOtis.CursePlayer", new HandleNamedMessageDelegate(HandleCursePlayerMsg));
		customMessagingManager.RegisterNamedMessageHandler("LethalOtis.MilkCollected", new HandleNamedMessageDelegate(HandleMilkCollectedMsg));
		customMessagingManager.RegisterNamedMessageHandler("LethalOtis.TriggerSelfDestruct", new HandleNamedMessageDelegate(HandleTriggerSelfDestructMsg));
		customMessagingManager.RegisterNamedMessageHandler("LethalOtis.StartFlashing", new HandleNamedMessageDelegate(HandleStartFlashingMsg));
		customMessagingManager.RegisterNamedMessageHandler("LethalOtis.Explode", new HandleNamedMessageDelegate(HandleExplodeMsg));
		customMessagingManager.RegisterNamedMessageHandler("LethalOtis.ShrinkPlayer", new HandleNamedMessageDelegate(HandleShrinkPlayerMsg));
		Plugin.logger.LogInfo((object)"[OtisRoam] CustomMessagingManager handlers registered.");
	}

	private static void UnregisterHandlers()
	{
		NetworkManager singleton = NetworkManager.Singleton;
		CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null);
		if (val != null)
		{
			val.UnregisterNamedMessageHandler("LethalOtis.CursePlayer");
			val.UnregisterNamedMessageHandler("LethalOtis.MilkCollected");
			val.UnregisterNamedMessageHandler("LethalOtis.TriggerSelfDestruct");
			val.UnregisterNamedMessageHandler("LethalOtis.StartFlashing");
			val.UnregisterNamedMessageHandler("LethalOtis.Explode");
			val.UnregisterNamedMessageHandler("LethalOtis.ShrinkPlayer");
		}
	}

	private static bool TryFindInstance(ulong networkObjectId, out OtisRoam otis)
	{
		otis = null;
		if (!NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out var value))
		{
			return false;
		}
		otis = ((Component)value).GetComponent<OtisRoam>();
		return (Object)(object)otis != (Object)null;
	}

	private static void SendToAllClients(string messageName, FastBufferWriter writer)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager;
		foreach (ulong connectedClientsId in NetworkManager.Singleton.ConnectedClientsIds)
		{
			if (connectedClientsId != 0)
			{
				customMessagingManager.SendNamedMessage(messageName, connectedClientsId, writer, (NetworkDelivery)3);
			}
		}
	}

	public unsafe void CursePlayerSend(ulong playerId)
	{
		//IL_0019: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1);
		try
		{
			ulong networkObjectId = ((NetworkBehaviour)this).NetworkObjectId;
			((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref playerId, default(ForPrimitives));
			NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalOtis.CursePlayer", 0uL, val, (NetworkDelivery)3);
		}
		finally
		{
			((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
		}
	}

	private static void HandleCursePlayerMsg(ulong senderClientId, FastBufferReader reader)
	{
		//IL_001a: 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_002e: 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)
		if (NetworkManager.Singleton.IsServer)
		{
			ulong networkObjectId = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			ulong playerId = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref playerId, default(ForPrimitives));
			if (TryFindInstance(networkObjectId, out var otis))
			{
				otis.ServerHandleCursePlayer(playerId);
			}
		}
	}

	private void ServerHandleCursePlayer(ulong playerId)
	{
		if ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipIsLeaving)
		{
			return;
		}
		if ((Object)(object)curse == (Object)null)
		{
			curse = ((Component)this).GetComponent<OtisCurse>();
		}
		if (!((Object)(object)curse == (Object)null))
		{
			int num = 1 << (int)playerId;
			if ((cursedBitmask.Value & num) == 0)
			{
				NetworkVariable<int> obj = cursedBitmask;
				obj.Value |= num;
				Plugin.logger.LogInfo((object)$"[OtisCurse] Server cursed player {playerId}. Bitmask={cursedBitmask.Value}");
				BroadcastShrinkPlayer(playerId);
			}
		}
	}

	private unsafe void BroadcastShrinkPlayer(ulong playerId)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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_0051: Unknown result type (might be due to invalid IL or missing references)
		curse?.ApplyShrinkEffect(playerId);
		FastBufferWriter writer = default(FastBufferWriter);
		((FastBufferWriter)(ref writer))..ctor(16, (Allocator)2, -1);
		try
		{
			ulong networkObjectId = ((NetworkBehaviour)this).NetworkObjectId;
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref playerId, default(ForPrimitives));
			SendToAllClients("LethalOtis.ShrinkPlayer", writer);
		}
		finally
		{
			((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
		}
	}

	private static void HandleShrinkPlayerMsg(ulong senderClientId, FastBufferReader reader)
	{
		//IL_0007: 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_001a: 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)
		ulong networkObjectId = default(ulong);
		((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
		ulong playerId = default(ulong);
		((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref playerId, default(ForPrimitives));
		if (TryFindInstance(networkObjectId, out var otis))
		{
			if ((Object)(object)otis.curse == (Object)null)
			{
				otis.curse = ((Component)otis).GetComponent<OtisCurse>();
			}
			otis.curse?.ApplyShrinkEffect(playerId);
		}
	}

	public unsafe void MilkCollectedSend(Vector3 milkSpawnPosition, ulong thiefClientId, ulong bucketNetworkId)
	{
		//IL_0019: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(40, (Allocator)2, -1);
		try
		{
			ulong networkObjectId = ((NetworkBehaviour)this).NetworkObjectId;
			((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			((FastBufferWriter)(ref val)).WriteValueSafe(ref milkSpawnPosition);
			((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref thiefClientId, default(ForPrimitives));
			((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref bucketNetworkId, default(ForPrimitives));
			NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalOtis.MilkCollected", 0uL, val, (NetworkDelivery)3);
		}
		finally
		{
			((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
		}
	}

	private static void HandleMilkCollectedMsg(ulong senderClientId, FastBufferReader reader)
	{
		//IL_001c: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkManager.Singleton.IsServer)
		{
			ulong networkObjectId = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			Vector3 milkSpawnPosition = default(Vector3);
			((FastBufferReader)(ref reader)).ReadValueSafe(ref milkSpawnPosition);
			ulong thiefClientId = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref thiefClientId, default(ForPrimitives));
			ulong bucketNetworkId = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref bucketNetworkId, default(ForPrimitives));
			if (TryFindInstance(networkObjectId, out var otis))
			{
				otis.ServerHandleMilkCollected(milkSpawnPosition, thiefClientId, bucketNetworkId);
			}
		}
	}

	private void ServerHandleMilkCollected(Vector3 milkSpawnPosition, ulong thiefClientId, ulong bucketNetworkId)
	{
		//IL_0064: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(bucketNetworkId, out var value))
		{
			value.Despawn(true);
		}
		Item fullBucketItemData = SetupMilkBucket.fullBucketItemData;
		if ((Object)(object)fullBucketItemData == (Object)null || (Object)(object)fullBucketItemData.spawnPrefab == (Object)null)
		{
			Plugin.logger.LogError((object)"MilkCollectedSend: fullBucketItemData is null — cannot spawn milk bottle.");
		}
		else
		{
			GameObject val = Object.Instantiate<GameObject>(fullBucketItemData.spawnPrefab, milkSpawnPosition, Quaternion.identity);
			NetworkObject component = val.GetComponent<NetworkObject>();
			component.Spawn(false);
			GrabbableObject component2 = val.GetComponent<GrabbableObject>();
			if ((Object)(object)component2 != (Object)null)
			{
				int num = Random.Range(60, 101);
				component2.SetScrapValue(num);
				RoundManager.Instance.SyncScrapValuesClientRpc((NetworkObjectReference[])(object)new NetworkObjectReference[1] { NetworkObjectReference.op_Implicit(component) }, new int[1] { num });
			}
			Plugin.logger.LogInfo((object)"Full milk bottle spawned!");
		}
		BeginSelfDestruct();
	}

	public unsafe void TriggerSelfDestructSend()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
		try
		{
			ulong networkObjectId = ((NetworkBehaviour)this).NetworkObjectId;
			((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalOtis.TriggerSelfDestruct", 0uL, val, (NetworkDelivery)3);
		}
		finally
		{
			((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
		}
	}

	private static void HandleTriggerSelfDestructMsg(ulong senderClientId, FastBufferReader reader)
	{
		//IL_001a: 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)
		if (NetworkManager.Singleton.IsServer)
		{
			ulong networkObjectId = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			if (TryFindInstance(networkObjectId, out var otis))
			{
				otis.BeginSelfDestruct();
			}
		}
	}

	private void BeginSelfDestruct()
	{
		if (!isSelfDestructing)
		{
			isSelfDestructing = true;
			if ((Object)(object)base.agent != (Object)null)
			{
				base.agent.speed = 0f;
				base.agent.isStopped = true;
			}
			Plugin.logger.LogInfo((object)"Otis self-destruct sequence started!");
			BroadcastStartFlashing();
			((MonoBehaviour)this).StartCoroutine(SelfDestructCountdown());
		}
	}

	private unsafe void BroadcastStartFlashing()
	{
		//IL_0025: 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_0037: Unknown result type (might be due to invalid IL or missing references)
		((MonoBehaviour)this).StartCoroutine(FlashRedRoutine());
		FastBufferWriter writer = default(FastBufferWriter);
		((FastBufferWriter)(ref writer))..ctor(8, (Allocator)2, -1);
		try
		{
			ulong networkObjectId = ((NetworkBehaviour)this).NetworkObjectId;
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			SendToAllClients("LethalOtis.StartFlashing", writer);
		}
		finally
		{
			((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
		}
	}

	private static void HandleStartFlashingMsg(ulong senderClientId, FastBufferReader reader)
	{
		//IL_0007: 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)
		ulong networkObjectId = default(ulong);
		((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
		if (TryFindInstance(networkObjectId, out var otis))
		{
			((MonoBehaviour)otis).StartCoroutine(otis.FlashRedRoutine());
		}
	}

	private unsafe void BroadcastExplode(Vector3 explosionPos)
	{
		//IL_0002: 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_0027: 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)
		ApplyExplode(explosionPos);
		FastBufferWriter writer = default(FastBufferWriter);
		((FastBufferWriter)(ref writer))..ctor(20, (Allocator)2, -1);
		try
		{
			ulong networkObjectId = ((NetworkBehaviour)this).NetworkObjectId;
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe(ref explosionPos);
			SendToAllClients("LethalOtis.Explode", writer);
		}
		finally
		{
			((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
		}
	}

	private static void HandleExplodeMsg(ulong senderClientId, FastBufferReader reader)
	{
		//IL_0007: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		ulong networkObjectId = default(ulong);
		((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
		Vector3 val = default(Vector3);
		((FastBufferReader)(ref reader)).ReadValueSafe(ref val);
		Landmine.SpawnExplosion(val, true, 0f, 0f, 0, 0f, (GameObject)null, false);
		if (TryFindInstance(networkObjectId, out var otis))
		{
			otis.ApplyExplode(val);
		}
	}

	private IEnumerator SelfDestructCountdown()
	{
		yield return (object)new WaitForSeconds(selfDestructDelay);
		Vector3 pos = ((Component)this).transform.position;
		BroadcastExplode(pos);
		yield return (object)new WaitForSeconds(0.15f);
		Landmine.SpawnExplosion(pos, true, explosionKillRadius, explosionDamageRadius, explosionNonLethalDamage, 0f, (GameObject)null, false);
		Plugin.logger.LogInfo((object)"Otis exploded!");
		base.isEnemyDead = true;
		((Component)this).GetComponent<NetworkObject>().Despawn(true);
	}

	private IEnumerator FlashRedRoutine()
	{
		Renderer[] renderers = ((Component)this).GetComponentsInChildren<Renderer>();
		Color[] originalColors = (Color[])(object)new Color[renderers.Length];
		for (int i = 0; i < renderers.Length; i++)
		{
			originalColors[i] = renderers[i].material.color;
		}
		GameObject lightObj = new GameObject("SelfDestructWarningLight");
		lightObj.transform.SetParent(((Component)this).transform);
		lightObj.transform.localPosition = Vector3.up * 0.5f;
		Light warningLight = lightObj.AddComponent<Light>();
		warningLight.color = Color.red;
		warningLight.range = 12f;
		warningLight.intensity = 0f;
		float elapsed = 0f;
		bool isRed = false;
		for (; elapsed < selfDestructDelay; elapsed += 0.3f)
		{
			isRed = !isRed;
			for (int j = 0; j < renderers.Length; j++)
			{
				renderers[j].material.color = (isRed ? Color.red : originalColors[j]);
			}
			warningLight.intensity = (isRed ? 3f : 0f);
			yield return (object)new WaitForSeconds(0.3f);
		}
		Object.Destroy((Object)(object)lightObj);
	}

	private void ApplyExplode(Vector3 explosionPos)
	{
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		if (explodePieces == null || explodePieces.Length == 0)
		{
			Plugin.logger.LogWarning((object)"OtisRoam: explodePieces not assigned — skipping body piece launch.");
			return;
		}
		SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>();
		foreach (SkinnedMeshRenderer val in componentsInChildren)
		{
			((Renderer)val).enabled = false;
		}
		Transform[] array = explodePieces;
		foreach (Transform val2 in array)
		{
			if (!((Object)(object)val2 == (Object)null))
			{
				val2.SetParent((Transform)null, true);
				Rigidbody val3 = ((Component)val2).GetComponent<Rigidbody>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = ((Component)val2).gameObject.AddComponent<Rigidbody>();
				}
				val3.isKinematic = false;
				Vector3 val4 = new Vector3(Random.Range(-1f, 1f), Random.Range(0.3f, 1f), Random.Range(-1f, 1f));
				Vector3 normalized = ((Vector3)(ref val4)).normalized;
				val3.AddForce(normalized * Random.Range(otisExplosionForceMin, otisExplosionForceMax), (ForceMode)1);
				val3.AddTorque(Random.insideUnitSphere * 10f, (ForceMode)1);
				Object.Destroy((Object)(object)((Component)val2).gameObject, otisTimeToDespawn);
			}
		}
	}
}
namespace LethalOtisMod
{
	[BepInPlugin("com.bazookaben.LethalOtis", "LethalOtis", "1.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static class PluginInfo
		{
			public const string PLUGIN_GUID = "com.bazookaben.LethalOtis";

			public const string PLUGIN_NAME = "LethalOtis";

			public const string PLUGIN_VERSION = "1.2.1";
		}

		public static ManualLogSource logger;

		private readonly Harmony harmony = new Harmony("com.BazookaB3n.LethalOtis");

		public static AssetBundle ModAssets;

		public static EnemyType OtisEnemyType;

		private void Awake()
		{
			logger = ((BaseUnityPlugin)this).Logger;
			logger.LogInfo((object)"Plugin com.bazookaben.LethalOtis is loading...");
			logger.LogInfo((object)"OTIS WAS HERE! BOOM BEACH TOO!");
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "modassets");
			ModAssets = AssetBundle.LoadFromFile(text);
			if ((Object)(object)ModAssets == (Object)null)
			{
				logger.LogError((object)"Failed to load Mod Assets!");
				return;
			}
			harmony.PatchAll();
			logger.LogInfo((object)"[Harmony] PatchAll() completed.");
			IEnumerable<MethodBase> patchedMethods = harmony.GetPatchedMethods();
			foreach (MethodBase item in patchedMethods)
			{
				logger.LogInfo((object)("[Harmony] Patched: " + item.DeclaringType?.Name + "." + item.Name));
			}
			MethodInfo method = typeof(StartOfRound).GetMethod("ReviveDeadPlayers", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				logger.LogInfo((object)"[Harmony] ReviveDeadPlayers found in StartOfRound — patches should fire.");
			}
			else
			{
				logger.LogError((object)"[Harmony] ReviveDeadPlayers NOT found in StartOfRound! Patches will never fire. Method was likely renamed in this LC version.");
			}
			GameObject val = ModAssets.LoadAsset<GameObject>("Otis");
			if ((Object)(object)val == (Object)null)
			{
				logger.LogError((object)"Failed to load the prefab 'Otis' from the bundle!");
				return;
			}
			NetworkPrefabs.RegisterNetworkPrefab(val);
			OtisEnemyType = ScriptableObject.CreateInstance<EnemyType>();
			OtisEnemyType.enemyName = "Otis";
			OtisEnemyType.enemyPrefab = val;
			OtisEnemyType.isDaytimeEnemy = false;
			OtisEnemyType.isOutsideEnemy = false;
			OtisEnemyType.canDie = true;
			OtisEnemyType.PowerLevel = 1f;
			OtisEnemyType.MaxCount = 2;
			Enemies.RegisterEnemy(OtisEnemyType, 30, (LevelTypes)(-1), (TerminalNode)null, (TerminalKeyword)null);
			logger.LogInfo((object)"Otis successfully registered as an enemy!");
			Item val2 = ModAssets.LoadAsset<Item>("Assets/EmptyMilkItemData.asset");
			Item val3 = ModAssets.LoadAsset<Item>("Assets/FullMilkItemData.asset");
			TerminalNode val4 = ModAssets.LoadAsset<TerminalNode>("Assets/EmptyMilkBottleTerminal.asset");
			SetupMilkBucket.SetupMilkBuckets();
		}

		public static GameObject GetModAssetItem(string name)
		{
			return ModAssets.LoadAsset<GameObject>(name);
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "EndGameClientRpc")]
	internal class CurseResetPatch
	{
		[HarmonyPostfix]
		private static void ResetAllCurses()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			Plugin.logger.LogInfo((object)"[CurseResetPatch] Postfix fired — EndGameClientRpc was called.");
			if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)SoundManager.Instance == (Object)null)
			{
				return;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (((NetworkBehaviour)val).IsOwner)
				{
					val.movementSpeed = 4.6f;
					val.jumpForce = 13f;
				}
				((Component)val).transform.localScale = Vector3.one;
				SoundManager.Instance.playerVoicePitchTargets[(uint)val.playerClientId] = 1f;
				SoundManager.Instance.SetPlayerPitch(1f, (int)val.playerClientId);
			}
			Plugin.logger.LogInfo((object)"The Otis effects have been cleared!");
		}
	}
}
namespace LethalOtis
{
	public class EmptyMilkBucketItem : PhysicsProp
	{
		public Item fullMilkItemData;

		[Header("Collection Settings")]
		public float collectionRange = 3f;

		public float aimForgiveness = 0.75f;

		private ScanNodeProperties _scanNode;

		private bool _lastHeld;

		public override void ItemActivate(bool used, bool buttonDown = true)
		{
			//IL_0047: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			((GrabbableObject)this).ItemActivate(used, buttonDown);
			if (!buttonDown || (Object)(object)((GrabbableObject)this).playerHeldBy == (Object)null)
			{
				return;
			}
			Plugin.logger.LogInfo((object)"Empty Bucket Left-Click Activated!");
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(((Component)((GrabbableObject)this).playerHeldBy.gameplayCamera).transform.position, ((Component)((GrabbableObject)this).playerHeldBy.gameplayCamera).transform.forward);
			RaycastHit[] array = Physics.SphereCastAll(val, aimForgiveness, collectionRange);
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val2 = array2[i];
				OtisRoam componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<OtisRoam>();
				if (!((Object)(object)componentInParent == (Object)null))
				{
					Plugin.logger.LogInfo((object)"Successfully scooped the Milk!");
					Vector3 milkSpawnPosition = ((Component)((GrabbableObject)this).playerHeldBy).transform.position + ((Component)((GrabbableObject)this).playerHeldBy).transform.forward * 0.5f + Vector3.up * 0.5f;
					ulong playerClientId = ((GrabbableObject)this).playerHeldBy.playerClientId;
					ulong networkObjectId = ((Component)this).GetComponent<NetworkObject>().NetworkObjectId;
					((GrabbableObject)this).playerHeldBy.DiscardHeldObject(false, (NetworkObject)null, default(Vector3), true);
					componentInParent.MilkCollectedSend(milkSpawnPosition, playerClientId, networkObjectId);
					break;
				}
			}
		}

		public override void Start()
		{
			((GrabbableObject)this).itemProperties = Object.Instantiate<Item>(((GrabbableObject)this).itemProperties);
			((GrabbableObject)this).itemProperties.floorYOffset = 0;
			((GrabbableObject)this).Start();
			((Component)this).gameObject.layer = 6;
			((Component)this).gameObject.tag = "PhysicsProp";
			((GrabbableObject)this).propColliders = ((Component)this).GetComponents<Collider>();
			((GrabbableObject)this).mainObjectRenderer = ((Component)this).GetComponentInChildren<MeshRenderer>();
			_scanNode = ((Component)this).GetComponentInChildren<ScanNodeProperties>();
			_lastHeld = false;
			AudioSource[] componentsInChildren = ((Component)this).GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource val in componentsInChildren)
			{
				val.spatialBlend = 1f;
			}
		}

		public override void Update()
		{
			((GrabbableObject)this).Update();
			if ((Object)(object)_scanNode != (Object)null && ((GrabbableObject)this).isHeld != _lastHeld)
			{
				_lastHeld = ((GrabbableObject)this).isHeld;
				((Component)_scanNode).gameObject.SetActive(!((GrabbableObject)this).isHeld);
			}
		}
	}
	public class SetupMilkBucket
	{
		public static Item emptyBucketItemData;

		public static Item fullBucketItemData;

		public static void SetupMilkBuckets()
		{
			emptyBucketItemData = Plugin.ModAssets.LoadAsset<Item>("Assets/EmptyMilkItemData.asset");
			fullBucketItemData = Plugin.ModAssets.LoadAsset<Item>("Assets/FullMilkItemData.asset");
			if ((Object)(object)emptyBucketItemData == (Object)null)
			{
				Plugin.logger.LogError((object)"Could not load Item assets from bundle! \nCheck file names.");
				return;
			}
			if ((Object)(object)fullBucketItemData == (Object)null)
			{
				Plugin.logger.LogError((object)"Could not load Item assets from bundle! \nCheck file names!");
				return;
			}
			GameObject spawnPrefab = emptyBucketItemData.spawnPrefab;
			GameObject spawnPrefab2 = fullBucketItemData.spawnPrefab;
			if ((Object)(object)spawnPrefab == (Object)null)
			{
				Plugin.logger.LogError((object)"CRASH PREVENTED: Empty Milk Bucket Prefab is NULL!");
				return;
			}
			if ((Object)(object)spawnPrefab2 == (Object)null)
			{
				Plugin.logger.LogError((object)"CRASH PREVENTED: Full Milk Bucket Prefab is NULL!");
				return;
			}
			EmptyMilkBucketItem component = spawnPrefab.GetComponent<EmptyMilkBucketItem>();
			if ((Object)(object)component != (Object)null)
			{
				component.fullMilkItemData = fullBucketItemData;
			}
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)val).name = "Empty Milk Bucket";
			val.displayText = "Allows you to milk Otis.\n\n";
			val.clearPreviousText = true;
			val.maxCharactersToType = 15;
			NetworkPrefabs.RegisterNetworkPrefab(spawnPrefab);
			NetworkPrefabs.RegisterNetworkPrefab(spawnPrefab2);
			ScanNodeProperties componentInChildren = spawnPrefab.GetComponentInChildren<ScanNodeProperties>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.subText = "Store item";
			}
			ScanNodeProperties componentInChildren2 = spawnPrefab2.GetComponentInChildren<ScanNodeProperties>();
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.subText = "Full Milk Bottle";
			}
			Plugin.logger.LogInfo((object)("[CHECK] Empty Milk Bucket Name: " + emptyBucketItemData.itemName));
			Plugin.logger.LogInfo((object)("[CHECK] Full Milk Bucket Name: " + fullBucketItemData.itemName));
			Items.RegisterShopItem(emptyBucketItemData, (TerminalNode)null, (TerminalNode)null, val, 10);
			Items.RegisterItem(fullBucketItemData);
			Utilities.FixMixerGroups(spawnPrefab);
			Utilities.FixMixerGroups(spawnPrefab2);
			Plugin.logger.LogInfo((object)"Milk Buckets successfully loaded and registered!");
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}