Decompiled source of SpewOnDemand v1.0.3

OnDemandSpew.dll

Decompiled 2 months 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 Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Igor_Does_Nothing")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("OnDemandSpew")]
[assembly: AssemblyTitle("OnDemandSpew")]
[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;
		}
	}
}
[BepInPlugin("com.igor.repo.ondemandspew", "On-Demand Spew", "1.0.0")]
public class OnDemandSpew : BaseUnityPlugin
{
	public const string PluginGuid = "com.igor.repo.ondemandspew";

	public const string PluginName = "On-Demand Spew";

	public const string PluginVersion = "1.0.0";

	private ManualLogSource _log;

	private ConfigEntry<KeyboardShortcut> _spewSelfKey;

	private ConfigEntry<KeyboardShortcut> _spewAllKey;

	private ConfigEntry<bool> _onlyInMainGame;

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<float> _attachDelay;

	private ConfigEntry<float> _pukeDelay;

	private ConfigEntry<bool> _requireMaster;

	private ConfigEntry<bool> _autoSpawnIfMissing;

	private ConfigEntry<float> _spawnAheadMeters;

	private ConfigEntry<bool> _spawnDisabled;

	private ConfigEntry<bool> _heartbeatEnabled;

	private ConfigEntry<float> _heartbeatIntervalSec;

	private ConfigEntry<bool> _invisibleSpewerAttach;

	private ConfigEntry<float> _invisibleSpewerCleanupSec;

	private static SpewController _controller;

	private void Awake()
	{
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		_log = ((BaseUnityPlugin)this).Logger;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turn the mod on/off without removing it.");
		_onlyInMainGame = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OnlyInMainGame", true, "If true, hotkeys only work during gameplay (not in menus).");
		_requireMaster = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RequireMasterClient", true, "If true, actions only run when you are master client or in singleplayer (network-safe prank).");
		_spewSelfKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "SpewSelf", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Trigger spew on yourself using a Spewer.");
		_spewAllKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "SpewAll", new KeyboardShortcut((KeyCode)112, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Attempt to spew all players (host-only; needs enough Spewers).");
		_attachDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "AttachDelay", 0.1f, "Seconds to wait after forcing Attack/Attached before puking.");
		_pukeDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "PukeDelay", 0.75f, "Seconds to keep in Puke before returning to Attached.");
		_autoSpawnIfMissing = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawn", "AutoSpawnIfMissing", true, "If true and no Spewer exists, host will spawn one near the target (networked).");
		_spawnAheadMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Spawn", "SpawnAheadMeters", 4f, "Distance in front of the player to spawn a Spewer when needed.");
		_spawnDisabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawn", "Disabled", false, "If true, never spawn Spewers (host-only prank disabled; only local visual fallback possible).");
		_heartbeatEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "HeartbeatEnabled", true, "If true, writes periodic heartbeat logs from the controller.");
		_heartbeatIntervalSec = ((BaseUnityPlugin)this).Config.Bind<float>("Debug", "HeartbeatIntervalSeconds", 10f, "Seconds between heartbeat logs.");
		_invisibleSpewerAttach = ((BaseUnityPlugin)this).Config.Bind<bool>("Network", "InvisibleSpewerAttach", true, "If true (host only), always spawn a new Spewer, hide its body, and drive Attack→Puke over the network.");
		_invisibleSpewerCleanupSec = ((BaseUnityPlugin)this).Config.Bind<float>("Network", "InvisibleSpewerCleanupSeconds", 0f, "If > 0, auto-destroy the spawned invisible spewer after this many seconds (host only). 0 = no auto-destroy.");
		_log.LogInfo((object)string.Format("{0} {1} loaded. Self={2}, All={3}, RequireMaster={4}", "On-Demand Spew", "1.0.0", _spewSelfKey.Value, _spewAllKey.Value, _requireMaster.Value));
		BuildOrAttachController();
		SceneManager.activeSceneChanged += OnActiveSceneChanged;
	}

	private void Update()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: 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_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		if (!_enabled.Value || (_onlyInMainGame.Value && (Object)(object)GameDirector.instance == (Object)null))
		{
			return;
		}
		KeyboardShortcut value = _spewSelfKey.Value;
		if (((KeyboardShortcut)(ref value)).IsDown())
		{
			_log.LogInfo((object)string.Format("[{0}] SpewSelf hotkey pressed: {1}", "On-Demand Spew", _spewSelfKey.Value));
			if ((Object)(object)_controller != (Object)null)
			{
				_controller.TriggerSpewSelf();
			}
		}
		value = _spewAllKey.Value;
		if (((KeyboardShortcut)(ref value)).IsDown())
		{
			_log.LogInfo((object)string.Format("[{0}] SpewAll hotkey pressed: {1}", "On-Demand Spew", _spewAllKey.Value));
			if ((Object)(object)_controller != (Object)null)
			{
				_controller.TriggerSpewAll();
			}
		}
	}

	private void OnDestroy()
	{
		SceneManager.activeSceneChanged -= OnActiveSceneChanged;
		ManualLogSource log = _log;
		if (log != null)
		{
			log.LogWarning((object)"OnDemandSpew plugin OnDestroy() called (controller left running if hosted).");
		}
	}

	private void OnActiveSceneChanged(Scene from, Scene to)
	{
		ManualLogSource log = _log;
		if (log != null)
		{
			log.LogInfo((object)("[Scene] activeSceneChanged: " + ((Scene)(ref from)).name + " -> " + ((Scene)(ref to)).name));
		}
		BuildOrAttachController();
	}

	private void BuildOrAttachController()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		try
		{
			GameObject val = null;
			val = GameObject.Find("SpewOnDemandHost (BepInEx)");
			if ((Object)(object)val == (Object)null)
			{
				val = new GameObject("SpewOnDemandHost (BepInEx)");
				Object.DontDestroyOnLoad((Object)(object)val);
				((Object)val).hideFlags = (HideFlags)61;
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)"Created persistent SpewOnDemand host GameObject.");
				}
			}
			_controller = val.GetComponent<SpewController>();
			if ((Object)(object)_controller == (Object)null)
			{
				_controller = val.AddComponent<SpewController>();
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogInfo((object)"Attached SpewController to host.");
				}
			}
			_controller.Configure(_log, _enabled, _onlyInMainGame, _spewSelfKey, _spewAllKey, _attachDelay, _pukeDelay, _requireMaster, _autoSpawnIfMissing, _spawnAheadMeters, _spawnDisabled, _heartbeatEnabled, _heartbeatIntervalSec, _invisibleSpewerAttach, _invisibleSpewerCleanupSec);
		}
		catch (Exception ex)
		{
			ManualLogSource log3 = _log;
			if (log3 != null)
			{
				log3.LogWarning((object)("[BuildOrAttachController] Exception: " + ex.GetType().Name + ": " + ex.Message));
			}
		}
	}

	private bool IsMasterOrSingle()
	{
		try
		{
			return SemiFunc.IsMasterClientOrSingleplayer();
		}
		catch
		{
			return PhotonNetwork.OfflineMode || (!PhotonNetwork.IsConnected && !PhotonNetwork.InRoom);
		}
	}

	private void TrySpewSelf()
	{
		_log.LogInfo((object)"[OnDemandSpew] TrySpewSelf() start");
		PlayerAvatar instance = PlayerAvatar.instance;
		if ((Object)(object)instance == (Object)null)
		{
			_log.LogWarning((object)"No PlayerAvatar.instance found.");
			return;
		}
		_log.LogInfo((object)"[OnDemandSpew] Using local attach+puke route (no network)");
		((MonoBehaviour)this).StartCoroutine(AttachJawAndPukeLocal(instance));
	}

	private void TrySpewAll()
	{
		if (_requireMaster.Value && !IsMasterOrSingle())
		{
			_log.LogWarning((object)"SpewAll blocked: not master client.");
			return;
		}
		List<PlayerAvatar> list = SafeGetPlayers();
		if (list.Count == 0)
		{
			_log.LogWarning((object)"No players found.");
			return;
		}
		if (_spawnDisabled.Value)
		{
			_log.LogWarning((object)"Spawn disabled by config; cannot spew-all over network. Skipping.");
			return;
		}
		_log.LogInfo((object)$"Spawning Spewer per player and triggering puke on {list.Count} players.");
		foreach (PlayerAvatar item in list)
		{
			((MonoBehaviour)this).StartCoroutine(EnsureSpewerThenPuke(item));
		}
	}

	private IEnumerator EnsureSpewerThenPuke(PlayerAvatar target)
	{
		Vector3 position = target.localCameraTransform.position + target.localCameraTransform.forward * Mathf.Max(1f, _spawnAheadMeters.Value);
		EnemySlowMouth val = DirectInstantiateSpewer(position);
		if ((Object)(object)val != (Object)null)
		{
			yield return ForceAttachAndPuke(val, target);
			yield break;
		}
		if (!SpawnSpewerAt(position))
		{
			_log.LogWarning((object)"Failed to spawn Spewer via EnemySetup; trying direct resource instantiate...");
			val = DirectInstantiateSpewer(position);
			if ((Object)(object)val != (Object)null)
			{
				yield return ForceAttachAndPuke(val, target);
				yield break;
			}
		}
		float wait = 0f;
		EnemySlowMouth val2 = null;
		while (wait < 2f && (Object)(object)val2 == (Object)null)
		{
			yield return null;
			wait += Time.deltaTime;
			val2 = FindClosestSpewer(((Component)target).transform.position);
		}
		if ((Object)(object)val2 == (Object)null)
		{
			_log.LogWarning((object)"Could not find Spewer after spawn attempt.");
			TryLocalOnlyPuke();
		}
		else
		{
			yield return ForceAttachAndPuke(val2, target);
		}
	}

	private IEnumerator AttachJawAndPukeLocal(PlayerAvatar target)
	{
		_log.LogInfo((object)"[OnDemandSpew] AttachJawAndPukeLocal: begin");
		GameObject val = Resources.Load<GameObject>("Enemies/Enemy - Slow Mouth");
		if ((Object)(object)val == (Object)null)
		{
			_log.LogWarning((object)"Resources.Load failed for 'Enemies/Enemy - Slow Mouth'. Cannot spawn jaw.");
			yield break;
		}
		_log.LogInfo((object)"[OnDemandSpew] Loaded Slow Mouth prefab from Resources");
		EnemySlowMouth componentInChildren = val.GetComponentInChildren<EnemySlowMouth>();
		if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.enemySlowMouthAttack == (Object)null)
		{
			_log.LogWarning((object)"EnemySlowMouth prefab or its enemySlowMouthAttack is missing.");
			yield break;
		}
		Vector3 val2 = target.localCameraTransform.position + target.localCameraTransform.forward * Mathf.Max(0.25f, _spawnAheadMeters.Value * 0.25f);
		Quaternion rotation = target.localCameraTransform.rotation;
		GameObject val3 = Object.Instantiate<GameObject>(componentInChildren.enemySlowMouthAttack, val2, rotation);
		_log.LogInfo((object)$"[OnDemandSpew] Instantiated attack prefab at {val2}");
		EnemySlowMouthAttaching component = val3.GetComponent<EnemySlowMouthAttaching>();
		if ((Object)(object)component == (Object)null)
		{
			_log.LogWarning((object)"Spawned attack prefab has no EnemySlowMouthAttaching component.");
			yield break;
		}
		component.targetPlayerAvatar = target;
		_log.LogInfo((object)"[OnDemandSpew] Calling GoTime() on EnemySlowMouthAttaching");
		component.GoTime();
		yield return null;
		yield return (object)new WaitForSeconds(0.05f);
		EnemySlowMouthCameraVisuals componentInChildren2 = ((Component)target.localCameraTransform).GetComponentInChildren<EnemySlowMouthCameraVisuals>();
		if ((Object)(object)componentInChildren2 != (Object)null)
		{
			_log.LogInfo((object)"[OnDemandSpew] Found EnemySlowMouthCameraVisuals under local camera");
			try
			{
				FieldInfo field = typeof(EnemySlowMouthCameraVisuals).GetField("playerTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(componentInChildren2, target);
					_log.LogInfo((object)"[OnDemandSpew] playerTarget set via reflection");
				}
				else
				{
					_log.LogWarning((object)"[OnDemandSpew] Could not reflect playerTarget field");
				}
			}
			catch
			{
			}
			componentInChildren2.StateSet((State)2);
			try
			{
				DisableJawMeshesKeepParticles(((Component)componentInChildren2).transform);
				object? obj2 = typeof(EnemySlowMouthCameraVisuals).GetField("pukeCapsuleRenderer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(componentInChildren2);
				Renderer val4 = (Renderer)((obj2 is Renderer) ? obj2 : null);
				if ((Object)(object)val4 != (Object)null)
				{
					val4.enabled = false;
				}
			}
			catch
			{
			}
			_log.LogInfo((object)"Forced local camera visuals to Puke.");
		}
		else
		{
			SemiPuke componentInChildren3 = ((Component)target).GetComponentInChildren<SemiPuke>();
			if ((Object)(object)componentInChildren3 != (Object)null)
			{
				componentInChildren3.PukeActive(target.localCameraTransform.position, target.localCameraTransform.rotation);
				_log.LogInfo((object)"Triggered SemiPuke directly (fallback).");
			}
			else
			{
				_log.LogWarning((object)"No EnemySlowMouthCameraVisuals or SemiPuke found for local attach.");
			}
		}
		_log.LogInfo((object)"[OnDemandSpew] AttachJawAndPukeLocal: end");
	}

	private bool SpawnSpewerAt(Vector3 position)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			EnemySetup val = FindSlowMouthSetup();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			LevelGenerator.Instance.EnemySpawn(val, position);
			_log.LogInfo((object)"Spawned Spewer via EnemySetup.");
			return true;
		}
		catch (Exception ex)
		{
			_log.LogWarning((object)("EnemySpawn via setup failed: " + ex.Message));
			return false;
		}
	}

	private EnemySetup? FindSlowMouthSetup()
	{
		try
		{
			List<EnemySetup> list = new List<EnemySetup>();
			if (EnemyDirector.instance.enemiesDifficulty1 != null)
			{
				list.AddRange(EnemyDirector.instance.enemiesDifficulty1);
			}
			if (EnemyDirector.instance.enemiesDifficulty2 != null)
			{
				list.AddRange(EnemyDirector.instance.enemiesDifficulty2);
			}
			if (EnemyDirector.instance.enemiesDifficulty3 != null)
			{
				list.AddRange(EnemyDirector.instance.enemiesDifficulty3);
			}
			foreach (EnemySetup item in list)
			{
				if ((Object)(object)item == (Object)null || item.spawnObjects == null)
				{
					continue;
				}
				foreach (GameObject spawnObject in item.spawnObjects)
				{
					if ((Object)(object)spawnObject != (Object)null && ((Object)spawnObject).name.IndexOf("Slow Mouth", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return item;
					}
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private EnemySlowMouth? DirectInstantiateSpewer(Vector3 position)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			GameObject val = PhotonNetwork.InstantiateRoomObject("Enemies/Enemy - Slow Mouth", position, Quaternion.identity, (byte)0, (object[])null);
			Enemy componentInChildren = val.GetComponentInChildren<Enemy>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.EnemyTeleported(position);
			}
			_log.LogInfo((object)"Direct-instantiated Spewer prefab.");
			return val.GetComponentInChildren<EnemySlowMouth>();
		}
		catch (Exception ex)
		{
			_log.LogWarning((object)("Direct instantiate failed: " + ex.Message));
			return null;
		}
	}

	private EnemySlowMouth? FindClosestSpewer(Vector3 pos)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		EnemySlowMouth result = null;
		float num = float.MaxValue;
		EnemySlowMouth[] array = Object.FindObjectsOfType<EnemySlowMouth>();
		foreach (EnemySlowMouth val in array)
		{
			float num2 = Vector3.SqrMagnitude(((Component)val).transform.position - pos);
			if (num2 < num)
			{
				num = num2;
				result = val;
			}
		}
		return result;
	}

	private List<PlayerAvatar> SafeGetPlayers()
	{
		try
		{
			return new List<PlayerAvatar>(SemiFunc.PlayerGetList());
		}
		catch
		{
			PlayerAvatar instance = PlayerAvatar.instance;
			return ((Object)(object)instance != (Object)null) ? new List<PlayerAvatar> { instance } : new List<PlayerAvatar>();
		}
	}

	private void DisableJawMeshesKeepParticles(Transform root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (!(val is ParticleSystemRenderer) && val.enabled)
			{
				val.enabled = false;
			}
		}
	}

	private IEnumerator ForceAttachAndPuke(EnemySlowMouth spewer, PlayerAvatar target)
	{
		if (!((Object)(object)spewer == (Object)null) && !((Object)(object)target == (Object)null))
		{
			PhotonView component = ((Component)spewer).GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null)
			{
				_log.LogWarning((object)"Selected spewer has no PhotonView; aborting.");
				yield break;
			}
			component.RPC("UpdatePlayerTargetRPC", (RpcTarget)0, new object[1] { target.photonView.ViewID });
			spewer.UpdateState((State)8);
			yield return (object)new WaitForSeconds(Mathf.Max(0.02f, _attachDelay.Value));
			spewer.UpdateState((State)9);
			yield return (object)new WaitForSeconds(0.05f);
			spewer.UpdateState((State)10);
			yield return (object)new WaitForSeconds(Mathf.Max(0.05f, _pukeDelay.Value));
			spewer.UpdateState((State)9);
			_log.LogInfo((object)("Spewed: " + ((Object)target).name + " using " + ((Object)spewer).name));
		}
	}

	private void TryLocalOnlyPuke()
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			EnemySlowMouthCameraVisuals[] array = Object.FindObjectsOfType<EnemySlowMouthCameraVisuals>();
			EnemySlowMouthCameraVisuals[] array2 = array;
			foreach (EnemySlowMouthCameraVisuals val in array2)
			{
				if ((Object)(object)val.semiPuke != (Object)null && (Object)(object)PlayerAvatar.instance != (Object)null)
				{
					val.semiPuke.PukeActive(((Component)val.semiPuke).transform.position, PlayerAvatar.instance.localCameraTransform.rotation);
					_log.LogInfo((object)"Triggered local camera puke visuals.");
					return;
				}
			}
		}
		catch
		{
		}
		_log.LogInfo((object)"Local-only puke not available (no camera jaw/semiPuke present).");
	}
}
public class SpewController : MonoBehaviour
{
	private ManualLogSource _log;

	private ConfigEntry<KeyboardShortcut> _spewSelfKey;

	private ConfigEntry<KeyboardShortcut> _spewAllKey;

	private ConfigEntry<bool> _onlyInMainGame;

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<bool> _requireMaster;

	private ConfigEntry<float> _attachDelay;

	private ConfigEntry<float> _pukeDelay;

	private ConfigEntry<float> _spawnAheadMeters;

	private ConfigEntry<bool> _autoSpawnIfMissing;

	private ConfigEntry<bool> _spawnDisabled;

	private ConfigEntry<bool> _heartbeatEnabled;

	private ConfigEntry<float> _heartbeatIntervalSec;

	private float _nextHeartbeatAt;

	private ConfigEntry<bool> _invisibleSpewerAttach;

	private ConfigEntry<float> _invisibleSpewerCleanupSec;

	private float _nextKeyAllowedAt;

	public void Configure(ManualLogSource log, ConfigEntry<bool> enabled, ConfigEntry<bool> onlyMain, ConfigEntry<KeyboardShortcut> spewSelf, ConfigEntry<KeyboardShortcut> spewAll, ConfigEntry<float> attachDelay, ConfigEntry<float> pukeDelay, ConfigEntry<bool> requireMaster, ConfigEntry<bool> autoSpawn, ConfigEntry<float> spawnAhead, ConfigEntry<bool> spawnDisabled, ConfigEntry<bool> heartbeat, ConfigEntry<float> heartbeatInterval, ConfigEntry<bool> invisibleSpewerAttach, ConfigEntry<float> invisibleSpewerCleanupSec)
	{
		_log = log;
		_enabled = enabled;
		_onlyInMainGame = onlyMain;
		_spewSelfKey = spewSelf;
		_spewAllKey = spewAll;
		_attachDelay = attachDelay;
		_pukeDelay = pukeDelay;
		_requireMaster = requireMaster;
		_autoSpawnIfMissing = autoSpawn;
		_spawnAheadMeters = spawnAhead;
		_spawnDisabled = spawnDisabled;
		_heartbeatEnabled = heartbeat;
		_heartbeatIntervalSec = heartbeatInterval;
		_invisibleSpewerAttach = invisibleSpewerAttach;
		_invisibleSpewerCleanupSec = invisibleSpewerCleanupSec;
		_nextHeartbeatAt = Time.unscaledTime + Mathf.Max(1f, _heartbeatIntervalSec?.Value ?? 10f);
		((MonoBehaviour)this).CancelInvoke("RealtimeTick");
		((MonoBehaviour)this).InvokeRepeating("RealtimeTick", 1f, 1f);
		ManualLogSource log2 = _log;
		if (log2 != null)
		{
			log2.LogInfo((object)"SpewController configured and alive.");
		}
	}

	public void TriggerSpewSelf()
	{
		try
		{
			((MonoBehaviour)this).StartCoroutine(SpewHostOrLocal(PlayerAvatar.instance));
		}
		catch
		{
		}
	}

	public void TriggerSpewAll()
	{
		try
		{
			foreach (PlayerAvatar item in SafeGetPlayers())
			{
				((MonoBehaviour)this).StartCoroutine(SpewHostOrLocal(item));
			}
		}
		catch
		{
		}
	}

	private void Update()
	{
		//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_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_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (_enabled != null && !_enabled.Value)
			{
				return;
			}
			bool flag = (Object)(object)GameDirector.instance != (Object)null;
			bool flag2 = _onlyInMainGame != null && _onlyInMainGame.Value && !flag;
			KeyboardShortcut value;
			if (_spewSelfKey != null)
			{
				value = _spewSelfKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					if (flag2)
					{
						ManualLogSource log = _log;
						if (log != null)
						{
							log.LogInfo((object)"[Controller] Self hotkey ignored (OnlyInMainGame=true, not in gameplay).");
						}
					}
					else if (Time.unscaledTime >= _nextKeyAllowedAt)
					{
						_nextKeyAllowedAt = Time.unscaledTime + 0.25f;
						ManualLogSource log2 = _log;
						if (log2 != null)
						{
							log2.LogInfo((object)$"[Controller] Self hotkey pressed: {_spewSelfKey.Value}");
						}
						((MonoBehaviour)this).StartCoroutine(SpewHostOrLocal(PlayerAvatar.instance));
					}
				}
			}
			if (_spewAllKey != null)
			{
				value = _spewAllKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					if (flag2)
					{
						ManualLogSource log3 = _log;
						if (log3 != null)
						{
							log3.LogInfo((object)"[Controller] All hotkey ignored (OnlyInMainGame=true, not in gameplay).");
						}
					}
					else if (Time.unscaledTime >= _nextKeyAllowedAt)
					{
						_nextKeyAllowedAt = Time.unscaledTime + 0.25f;
						ManualLogSource log4 = _log;
						if (log4 != null)
						{
							log4.LogInfo((object)$"[Controller] All hotkey pressed: {_spewAllKey.Value}");
						}
						foreach (PlayerAvatar item in SafeGetPlayers())
						{
							((MonoBehaviour)this).StartCoroutine(SpewHostOrLocal(item));
						}
					}
				}
			}
			if (_heartbeatEnabled != null && _heartbeatEnabled.Value && Time.unscaledTime >= _nextHeartbeatAt)
			{
				_nextHeartbeatAt = Time.unscaledTime + Mathf.Max(1f, _heartbeatIntervalSec?.Value ?? 10f);
				ManualLogSource log5 = _log;
				if (log5 != null)
				{
					log5.LogInfo((object)"[Controller] Heartbeat alive");
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log6 = _log;
			if (log6 != null)
			{
				log6.LogWarning((object)("[Controller.Update] " + ex.GetType().Name + ": " + ex.Message));
			}
		}
	}

	private void RealtimeTick()
	{
		try
		{
			if (_heartbeatEnabled != null && _heartbeatEnabled.Value)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)"[Controller.Tick] alive");
				}
			}
		}
		catch
		{
		}
	}

	private List<PlayerAvatar> SafeGetPlayers()
	{
		try
		{
			return new List<PlayerAvatar>(SemiFunc.PlayerGetList());
		}
		catch
		{
			PlayerAvatar instance = PlayerAvatar.instance;
			return ((Object)(object)instance != (Object)null) ? new List<PlayerAvatar> { instance } : new List<PlayerAvatar>();
		}
	}

	private IEnumerator AttachJawAndPukeLocal(PlayerAvatar target)
	{
		if ((Object)(object)target == (Object)null)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogWarning((object)"[Controller] No PlayerAvatar for local puke.");
			}
			yield break;
		}
		ManualLogSource log2 = _log;
		if (log2 != null)
		{
			log2.LogInfo((object)"[Controller] AttachJawAndPukeLocal: begin");
		}
		EnemySlowMouthCameraVisuals componentInChildren = ((Component)target.localCameraTransform).GetComponentInChildren<EnemySlowMouthCameraVisuals>();
		if ((Object)(object)componentInChildren != (Object)null)
		{
			try
			{
				FieldInfo field = typeof(EnemySlowMouthCameraVisuals).GetField("playerTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(componentInChildren, target);
				}
			}
			catch
			{
			}
			componentInChildren.StateSet((State)2);
			ManualLogSource log3 = _log;
			if (log3 != null)
			{
				log3.LogInfo((object)"[Controller] Forced camera visuals to Puke.");
			}
		}
		else
		{
			SemiPuke componentInChildren2 = ((Component)target).GetComponentInChildren<SemiPuke>(true);
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.PukeActive(target.localCameraTransform.position, target.localCameraTransform.rotation);
				ManualLogSource log4 = _log;
				if (log4 != null)
				{
					log4.LogInfo((object)"[Controller] Triggered SemiPuke directly (existing).");
				}
			}
			else if (!SpawnStandaloneSemiPuke(target))
			{
				ManualLogSource log5 = _log;
				if (log5 != null)
				{
					log5.LogWarning((object)"[Controller] No camera visuals and failed to spawn standalone SemiPuke.");
				}
			}
		}
		ManualLogSource log6 = _log;
		if (log6 != null)
		{
			log6.LogInfo((object)"[Controller] AttachJawAndPukeLocal: end");
		}
	}

	private bool SpawnStandaloneSemiPuke(PlayerAvatar target)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: 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)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			GameObject val = Resources.Load<GameObject>("Enemies/Enemy - Slow Mouth");
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)"[Controller] Resources.Load failed for 'Enemies/Enemy - Slow Mouth' (for standalone SemiPuke).");
				}
				return false;
			}
			SemiPuke componentInChildren = val.GetComponentInChildren<SemiPuke>(true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogWarning((object)"[Controller] Could not find SemiPuke inside Slow Mouth prefab.");
				}
				return false;
			}
			Transform localCameraTransform = target.localCameraTransform;
			Vector3 val2 = localCameraTransform.position + localCameraTransform.forward * Mathf.Max(0.25f, (_spawnAheadMeters?.Value ?? 4f) * 0.15f);
			GameObject val3 = Object.Instantiate<GameObject>(((Component)componentInChildren).gameObject, val2, localCameraTransform.rotation, localCameraTransform);
			SemiPuke component = val3.GetComponent<SemiPuke>();
			if ((Object)(object)component == (Object)null)
			{
				ManualLogSource log3 = _log;
				if (log3 != null)
				{
					log3.LogWarning((object)"[Controller] SemiPuke clone missing component.");
				}
				Object.Destroy((Object)(object)val3);
				return false;
			}
			component.PukeActive(val2, localCameraTransform.rotation);
			ManualLogSource log4 = _log;
			if (log4 != null)
			{
				log4.LogInfo((object)"[Controller] Spawned standalone SemiPuke and triggered puke.");
			}
			((MonoBehaviour)this).StartCoroutine(DestroyAfter(val3, 2f));
			return true;
		}
		catch (Exception ex)
		{
			ManualLogSource log5 = _log;
			if (log5 != null)
			{
				log5.LogWarning((object)("[Controller] SpawnStandaloneSemiPuke exception: " + ex.GetType().Name + ": " + ex.Message));
			}
			return false;
		}
	}

	private IEnumerator DestroyAfter(GameObject go, float seconds)
	{
		yield return (object)new WaitForSeconds(Mathf.Max(0.05f, seconds));
		if ((Object)(object)go != (Object)null)
		{
			Object.Destroy((Object)(object)go);
		}
	}

	private IEnumerator SpewHostOrLocal(PlayerAvatar target)
	{
		if ((Object)(object)target == (Object)null)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogWarning((object)"[Controller] Target player is null.");
			}
			yield break;
		}
		((MonoBehaviour)this).StartCoroutine(KnockdownInvulnAllPlayers(0.5f));
		bool flag;
		try
		{
			flag = SemiFunc.IsMasterClientOrSingleplayer();
		}
		catch
		{
			flag = PhotonNetwork.OfflineMode || PhotonNetwork.IsMasterClient;
		}
		if (flag && (_spawnDisabled == null || !_spawnDisabled.Value))
		{
			if (_invisibleSpewerAttach != null && _invisibleSpewerAttach.Value)
			{
				yield return NetInvisibleAttachAndPuke(target);
			}
			else
			{
				yield return NetSpawnAndPuke(target);
			}
			yield break;
		}
		ManualLogSource log2 = _log;
		if (log2 != null)
		{
			log2.LogInfo((object)"[Controller] Falling back to local-only puke.");
		}
		yield return AttachJawAndPukeLocal(target);
	}

	private IEnumerator KnockdownInvulnAllPlayers(float seconds)
	{
		float end = Time.unscaledTime + Mathf.Max(0.05f, seconds);
		while (Time.unscaledTime < end)
		{
			List<PlayerAvatar> list;
			try
			{
				list = new List<PlayerAvatar>(SemiFunc.PlayerGetList());
			}
			catch
			{
				PlayerAvatar instance = PlayerAvatar.instance;
				list = (((Object)(object)instance != (Object)null) ? new List<PlayerAvatar> { instance } : new List<PlayerAvatar>());
			}
			foreach (PlayerAvatar item in list)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				try
				{
					PlayerTumble tumble = item.tumble;
					if ((Object)(object)tumble != (Object)null)
					{
						MethodInfo method = ((object)tumble).GetType().GetMethod("TumbleRequest", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (method != null && method.GetParameters().Length == 2)
						{
							method.Invoke(tumble, new object[2] { false, false });
						}
					}
					try
					{
						Type type = ((object)item).GetType();
						PropertyInfo property = type.GetProperty("isDisabled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (property != null && property.CanWrite)
						{
							property.SetValue(item, false);
						}
						FieldInfo field = type.GetField("isDisabled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field != null)
						{
							field.SetValue(item, false);
						}
					}
					catch
					{
					}
				}
				catch
				{
				}
			}
			yield return null;
		}
	}

	private IEnumerator NetSpawnAndPuke(PlayerAvatar target)
	{
		ManualLogSource log = _log;
		if (log != null)
		{
			log.LogInfo((object)"[Controller] NetSpawnAndPuke: begin");
		}
		EnemySlowMouth spewer = null;
		Vector3 val = target.localCameraTransform.position + target.localCameraTransform.forward * Mathf.Max(1f, _spawnAheadMeters?.Value ?? 4f);
		GameObject val2 = null;
		try
		{
			val2 = PhotonNetwork.InstantiateRoomObject("Enemies/Enemy - Slow Mouth", val, target.localCameraTransform.rotation, (byte)0, (object[])null);
		}
		catch (Exception ex)
		{
			ManualLogSource log2 = _log;
			if (log2 != null)
			{
				log2.LogWarning((object)("[Controller] Photon instantiate failed: " + ex.Message));
			}
		}
		if ((Object)(object)val2 != (Object)null)
		{
			spewer = val2.GetComponentInChildren<EnemySlowMouth>();
		}
		if ((Object)(object)spewer == (Object)null)
		{
			ManualLogSource log3 = _log;
			if (log3 != null)
			{
				log3.LogWarning((object)"[Controller] Could not get a Spewer. Aborting network puke.");
			}
			yield break;
		}
		PhotonView component = ((Component)spewer).GetComponent<PhotonView>();
		if ((Object)(object)component == (Object)null)
		{
			ManualLogSource log4 = _log;
			if (log4 != null)
			{
				log4.LogWarning((object)"[Controller] Spewer has no PhotonView.");
			}
			yield break;
		}
		component.RPC("UpdatePlayerTargetRPC", (RpcTarget)0, new object[1] { target.photonView.ViewID });
		yield return null;
		spewer.UpdateState((State)8);
		yield return (object)new WaitForSeconds(Mathf.Max(0.02f, _attachDelay?.Value ?? 0.1f));
		spewer.UpdateState((State)9);
		yield return (object)new WaitForSeconds(0.05f);
		spewer.UpdateState((State)10);
		yield return (object)new WaitForSeconds(Mathf.Max(0.05f, _pukeDelay?.Value ?? 0.75f));
		spewer.UpdateState((State)9);
		ManualLogSource log5 = _log;
		if (log5 != null)
		{
			log5.LogInfo((object)"[Controller] NetSpawnAndPuke: done");
		}
	}

	private IEnumerator NetInvisibleAttachAndPuke(PlayerAvatar target)
	{
		ManualLogSource log = _log;
		if (log != null)
		{
			log.LogInfo((object)"[Controller] NetInvisibleAttachAndPuke: begin");
		}
		if ((Object)(object)target == (Object)null)
		{
			ManualLogSource log2 = _log;
			if (log2 != null)
			{
				log2.LogWarning((object)"[Controller] Target null.");
			}
			yield break;
		}
		if (!PhotonNetwork.OfflineMode && !PhotonNetwork.IsMasterClient)
		{
			ManualLogSource log3 = _log;
			if (log3 != null)
			{
				log3.LogWarning((object)"[Controller] Not MasterClient; cannot run invisible spewer attach.");
			}
			yield break;
		}
		Vector3 val = target.localCameraTransform.position + target.localCameraTransform.forward * Mathf.Max(1f, _spawnAheadMeters?.Value ?? 4f);
		Quaternion rotation = target.localCameraTransform.rotation;
		GameObject go = null;
		try
		{
			go = PhotonNetwork.InstantiateRoomObject("Enemies/Enemy - Slow Mouth", val, rotation, (byte)0, (object[])null);
		}
		catch (Exception ex)
		{
			ManualLogSource log4 = _log;
			if (log4 != null)
			{
				log4.LogWarning((object)("[Controller] Photon instantiate failed: " + ex.Message));
			}
		}
		if ((Object)(object)go == (Object)null)
		{
			ManualLogSource log5 = _log;
			if (log5 != null)
			{
				log5.LogWarning((object)"[Controller] Could not spawn Spewer (Photon). Aborting.");
			}
			yield break;
		}
		EnemySlowMouth spewer = go.GetComponentInChildren<EnemySlowMouth>();
		if ((Object)(object)spewer == (Object)null)
		{
			ManualLogSource log6 = _log;
			if (log6 != null)
			{
				log6.LogWarning((object)"[Controller] Spawned object missing EnemySlowMouth component.");
			}
			yield break;
		}
		int num = 0;
		try
		{
			GameObject val2 = (((Object)(object)spewer.enemyVisuals != (Object)null) ? ((Component)spewer.enemyVisuals).gameObject : ((Component)spewer).gameObject);
			Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				val3.enabled = false;
				num++;
			}
			ManualLogSource log7 = _log;
			if (log7 != null)
			{
				log7.LogInfo((object)$"[Controller] Hidden {num} renderers for invisible Spewer.");
			}
		}
		catch (Exception ex2)
		{
			ManualLogSource log8 = _log;
			if (log8 != null)
			{
				log8.LogWarning((object)("[Controller] Hiding renderers failed: " + ex2.Message));
			}
		}
		PhotonView component = ((Component)spewer).GetComponent<PhotonView>();
		if ((Object)(object)component == (Object)null)
		{
			ManualLogSource log9 = _log;
			if (log9 != null)
			{
				log9.LogWarning((object)"[Controller] Spewer has no PhotonView.");
			}
			yield break;
		}
		component.RPC("UpdatePlayerTargetRPC", (RpcTarget)0, new object[1] { target.photonView.ViewID });
		ManualLogSource log10 = _log;
		if (log10 != null)
		{
			log10.LogInfo((object)"[Controller] UpdatePlayerTargetRPC sent.");
		}
		yield return null;
		((MonoBehaviour)this).StartCoroutine(HideAttackVisualsForWindow(target, spewer, 5f));
		((MonoBehaviour)this).StartCoroutine(HideJawMeshesForWindow(target, 5f));
		((MonoBehaviour)this).StartCoroutine(SuppressTumbleForWindow(target, 3f));
		spewer.UpdateState((State)8);
		ManualLogSource log11 = _log;
		if (log11 != null)
		{
			log11.LogInfo((object)"[Controller] Spewer state -> Attack");
		}
		float num2 = Mathf.Max(0.2f, _attachDelay?.Value ?? 0.1f);
		yield return WaitForAttachOverlayOrTimeout(target, Mathf.Max(1.25f, num2 + 0.5f));
		yield return ((MonoBehaviour)this).StartCoroutine(HideAttackVisualsForWindow(target, spewer, 2f));
		spewer.UpdateState((State)10);
		ManualLogSource log12 = _log;
		if (log12 != null)
		{
			log12.LogInfo((object)"[Controller] Spewer state -> Puke");
		}
		float num3 = Mathf.Max(1f, _pukeDelay?.Value ?? 0.75f);
		float pukeHoldEnd = Time.unscaledTime + num3;
		((MonoBehaviour)this).StartCoroutine(HideJawMeshesForWindow(target, 3f));
		while (Time.unscaledTime < pukeHoldEnd)
		{
			yield return null;
		}
		spewer.UpdateState((State)6);
		ManualLogSource log13 = _log;
		if (log13 != null)
		{
			log13.LogInfo((object)"[Controller] Spewer state -> Leave (no knockdown)");
		}
		yield return (object)new WaitForSeconds(2f);
		spewer.UpdateState((State)2);
		yield return (object)new WaitForSeconds(0.5f);
		float num4 = ((_invisibleSpewerCleanupSec != null && _invisibleSpewerCleanupSec.Value > 0.01f) ? _invisibleSpewerCleanupSec.Value : 0.25f);
		ManualLogSource log14 = _log;
		if (log14 != null)
		{
			log14.LogInfo((object)$"[Controller] Scheduling spewer cleanup in {num4:F2}s.");
		}
		((MonoBehaviour)this).StartCoroutine(DestroyNetworkObjectAfter(go, num4));
		ManualLogSource log15 = _log;
		if (log15 != null)
		{
			log15.LogInfo((object)"[Controller] NetInvisibleAttachAndPuke: done");
		}
	}

	private IEnumerator WaitForAttachOverlayOrTimeout(PlayerAvatar target, float timeoutSec)
	{
		float end = Time.unscaledTime + Mathf.Max(0.1f, timeoutSec);
		while (Time.unscaledTime < end)
		{
			bool flag = false;
			try
			{
				if ((Object)(object)target != (Object)null)
				{
					Transform localCameraTransform = target.localCameraTransform;
					if ((Object)(object)localCameraTransform != (Object)null && (Object)(object)((Component)localCameraTransform).GetComponentInChildren<EnemySlowMouthCameraVisuals>(true) != (Object)null)
					{
						flag = true;
					}
					if (!flag)
					{
						PlayerAvatarVisuals playerAvatarVisuals = target.playerAvatarVisuals;
						if ((Object)(object)playerAvatarVisuals != (Object)null && (Object)(object)((Component)playerAvatarVisuals).GetComponentInChildren<EnemySlowMouthPlayerAvatarAttached>(true) != (Object)null)
						{
							flag = true;
						}
					}
				}
			}
			catch
			{
			}
			if (flag)
			{
				break;
			}
			yield return null;
		}
	}

	private IEnumerator SuppressTumbleForWindow(PlayerAvatar target, float seconds)
	{
		float end = Time.unscaledTime + Mathf.Max(0.05f, seconds);
		while (Time.unscaledTime < end)
		{
			try
			{
				if ((Object)(object)target != (Object)null)
				{
					PlayerTumble tumble = target.tumble;
					if ((Object)(object)tumble != (Object)null)
					{
						MethodInfo method = ((object)tumble).GetType().GetMethod("TumbleRequest", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (method != null)
						{
							ParameterInfo[] parameters = method.GetParameters();
							if (parameters.Length == 2)
							{
								method.Invoke(tumble, new object[2] { false, false });
							}
						}
					}
					try
					{
						Type type = ((object)target).GetType();
						PropertyInfo property = type.GetProperty("isDisabled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (property != null && property.CanWrite)
						{
							property.SetValue(target, false);
						}
						FieldInfo field = type.GetField("isDisabled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (field != null)
						{
							field.SetValue(target, false);
						}
					}
					catch
					{
					}
				}
			}
			catch
			{
			}
			yield return null;
		}
	}

	private IEnumerator HideAttackVisualsForWindow(PlayerAvatar target, EnemySlowMouth spewer, float seconds)
	{
		float end = Time.unscaledTime + Mathf.Max(0.05f, seconds);
		while (Time.unscaledTime < end)
		{
			try
			{
				EnemySlowMouthAttaching[] array = Object.FindObjectsOfType<EnemySlowMouthAttaching>();
				foreach (EnemySlowMouthAttaching val in array)
				{
					bool flag = false;
					try
					{
						if ((Object)(object)val != (Object)null && (Object)(object)val.targetPlayerAvatar == (Object)(object)target)
						{
							flag = true;
						}
						if (!flag)
						{
							object obj = typeof(EnemySlowMouthAttaching).GetField("enemySlowMouth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val);
							if (obj != null && obj == spewer)
							{
								flag = true;
							}
						}
					}
					catch
					{
					}
					if (!flag)
					{
						continue;
					}
					int num = 0;
					Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val2 in componentsInChildren)
					{
						if (val2.enabled)
						{
							val2.enabled = false;
							num++;
						}
					}
					if (num > 0)
					{
						ManualLogSource log = _log;
						if (log != null)
						{
							log.LogInfo((object)$"[Controller] Hid {num} attach-visual renderers.");
						}
					}
				}
			}
			catch
			{
			}
			yield return null;
		}
	}

	private IEnumerator HideJawMeshesForWindow(PlayerAvatar target, float seconds)
	{
		float end = Time.unscaledTime + Mathf.Max(0.05f, seconds);
		while (Time.unscaledTime < end)
		{
			try
			{
				EnemySlowMouthPlayerAvatarAttached[] array = (EnemySlowMouthPlayerAvatarAttached[])(((Object)(object)target.playerAvatarVisuals != (Object)null) ? ((Array)((Component)target.playerAvatarVisuals).GetComponentsInChildren<EnemySlowMouthPlayerAvatarAttached>(true)) : ((Array)new EnemySlowMouthPlayerAvatarAttached[0]));
				EnemySlowMouthPlayerAvatarAttached[] array2 = array;
				foreach (EnemySlowMouthPlayerAvatarAttached val in array2)
				{
					DisableJawMeshesKeepParticles(((Component)val).transform);
				}
			}
			catch
			{
			}
			try
			{
				Transform localCameraTransform = target.localCameraTransform;
				if ((Object)(object)localCameraTransform != (Object)null)
				{
					EnemySlowMouthCameraVisuals[] componentsInChildren = ((Component)localCameraTransform).GetComponentsInChildren<EnemySlowMouthCameraVisuals>(true);
					foreach (EnemySlowMouthCameraVisuals val2 in componentsInChildren)
					{
						DisableJawMeshesKeepParticles(((Component)val2).transform);
						try
						{
							object? obj2 = typeof(EnemySlowMouthCameraVisuals).GetField("pukeCapsuleRenderer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val2);
							Renderer val3 = (Renderer)((obj2 is Renderer) ? obj2 : null);
							if ((Object)(object)val3 != (Object)null && val3.enabled)
							{
								val3.enabled = false;
							}
						}
						catch
						{
						}
					}
				}
			}
			catch
			{
			}
			yield return null;
		}
	}

	private void DisableJawMeshesKeepParticles(Transform root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (!(val is ParticleSystemRenderer) && val.enabled)
			{
				val.enabled = false;
			}
		}
	}

	private IEnumerator DestroyNetworkObjectAfter(GameObject go, float seconds)
	{
		yield return (object)new WaitForSeconds(Mathf.Max(0.05f, seconds));
		if ((Object)(object)go == (Object)null)
		{
			yield break;
		}
		try
		{
			if (!PhotonNetwork.OfflineMode && PhotonNetwork.IsMasterClient)
			{
				PhotonNetwork.Destroy(go);
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)"[Controller] PhotonNetwork.Destroy called for invisible spewer.");
				}
			}
			else
			{
				Object.Destroy((Object)(object)go);
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogInfo((object)"[Controller] Locally destroyed invisible spewer (not master).");
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log3 = _log;
			if (log3 != null)
			{
				log3.LogWarning((object)("[Controller] DestroyNetworkObjectAfter exception: " + ex.Message));
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}