Decompiled source of GraceEntities v1.1.0

BepInEx/plugins/DozerEntity.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("DozerEntity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DozerEntity")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("707b5311-bc50-4ec1-ac25-901818a7c6a1")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace DozerEntity;

public class DozerBehaviour : MonoBehaviour
{
	private enum DozerState
	{
		Hidden,
		ClosedEyes,
		OpenEyes,
		Screamer
	}

	private DozerState currentState = DozerState.Hidden;

	private float timer = 0f;

	private float nextAppearTime = 0f;

	private float cooldownTimer = 0f;

	private float cooldownTime = 0f;

	private bool isOnCooldown = false;

	private float previousVolume = 1f;

	private GameObject overlayObject;

	private Image overlayImage;

	private Image blackBackground;

	private GameObject textObject;

	private Image textImage;

	private Sprite[] textSprites = (Sprite[])(object)new Sprite[25];

	private float textAnimTimer = 0f;

	private int textAnimFrame = 0;

	private bool textAnimStarted = false;

	private AudioClip openSound;

	private AudioClip killSound;

	private AudioSource audioSource;

	private AudioClip closedSound;

	private Sprite[] closedSprites = (Sprite[])(object)new Sprite[14];

	private Sprite[] openSprites = (Sprite[])(object)new Sprite[14];

	private Sprite[] screamerSprites = (Sprite[])(object)new Sprite[50];

	private float animTimer = 0f;

	private int animFrame = 0;

	private float animSpeed = 0.0667f;

	private string modFolder;

	private AudioClip LoadAudioClip(string filename)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Dozer Entity: звук не найден — " + text));
			return null;
		}
		WWW val = new WWW("file://" + text);
		try
		{
			while (!val.isDone)
			{
			}
			return val.GetAudioClip(false, false, (AudioType)20);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	private void Start()
	{
		string pluginPath = Paths.PluginPath;
		string[] directories = Directory.GetDirectories(pluginPath, "DozerEntity", SearchOption.AllDirectories);
		if (directories.Length != 0)
		{
			modFolder = directories[0];
		}
		else
		{
			modFolder = Path.Combine(pluginPath, "DozerEntity");
		}
		Debug.Log((object)("Dozer Entity: папка мода — " + modFolder));
		LoadSprites();
		closedSound = LoadAudioClip("closed_sound.wav");
		openSound = LoadAudioClip("open_sound.wav");
		killSound = LoadAudioClip("kill_sound.wav");
		audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		audioSource.loop = true;
		audioSource.volume = 1f;
		CreateOverlay();
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
	}

	private void LoadSprites()
	{
		for (int i = 0; i < 14; i++)
		{
			closedSprites[i] = LoadSprite("Closed_eyes" + (i + 1).ToString("D4") + ".png");
		}
		for (int j = 0; j < 14; j++)
		{
			openSprites[j] = LoadSprite("Opened_eyes" + (j + 1).ToString("D4") + ".png");
		}
		for (int k = 0; k < 50; k++)
		{
			screamerSprites[k] = LoadSprite("Kill" + (k + 1).ToString("D4") + ".png");
		}
		for (int l = 0; l < 25; l++)
		{
			textSprites[l] = LoadSprite($"text{l + 1}.png");
		}
	}

	public void ForceHide()
	{
		currentState = DozerState.Hidden;
		timer = 0f;
		overlayObject.SetActive(false);
		((Component)blackBackground).gameObject.SetActive(false);
		AudioListener.volume = previousVolume;
		isOnCooldown = false;
		audioSource.Stop();
	}

	private Sprite LoadSprite(string filename)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_0062: 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)
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Dozer Entity: файл не найден — " + text));
			return null;
		}
		byte[] array = File.ReadAllBytes(text);
		Texture2D val = new Texture2D(2, 2);
		ImageConversion.LoadImage(val, array);
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
	}

	private void Update()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if (currentState == DozerState.Hidden || currentState == DozerState.ClosedEyes || currentState == DozerState.OpenEyes)
		{
			previousVolume = AudioListener.volume;
		}
		if (isOnCooldown)
		{
			cooldownTimer += Time.deltaTime;
			if (cooldownTimer >= cooldownTime)
			{
				isOnCooldown = false;
				cooldownTimer = 0f;
				timer = 0f;
				nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
			}
		}
		else if (val.isPlayerDead)
		{
			if (currentState != 0)
			{
				overlayObject.SetActive(false);
				((Component)blackBackground).gameObject.SetActive(false);
				audioSource.Stop();
				currentState = DozerState.Hidden;
				timer = 0f;
				isOnCooldown = false;
			}
		}
		else
		{
			if (!IsPlayerInGame())
			{
				return;
			}
			if (val.quickMenuManager.isMenuOpen)
			{
				overlayObject.SetActive(false);
				((Component)blackBackground).gameObject.SetActive(false);
				return;
			}
			timer += Time.deltaTime;
			switch (currentState)
			{
			case DozerState.Hidden:
				if (isOnCooldown)
				{
					cooldownTimer += Time.deltaTime;
					if (cooldownTimer >= cooldownTime)
					{
						isOnCooldown = false;
						cooldownTimer = 0f;
						timer = 0f;
						nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
					}
				}
				else if (timer >= nextAppearTime)
				{
					ShowClosedEyes();
				}
				break;
			case DozerState.ClosedEyes:
				AnimateClosed();
				if (timer >= Plugin.EyeOpenDelay.Value)
				{
					OpenEyes();
				}
				break;
			case DozerState.OpenEyes:
				AnimateOpen();
				if (timer >= 0.1f && !IsPlayerSafe())
				{
					TriggerScreamer();
				}
				else if (timer >= Plugin.OpenEyesDuration.Value)
				{
					Hide();
				}
				break;
			case DozerState.Screamer:
				AnimateScreamer();
				AnimateText();
				if (timer >= 2.05f)
				{
					KillPlayer();
				}
				break;
			}
		}
	}

	private void AnimateClosed()
	{
		if (currentState != DozerState.ClosedEyes)
		{
			return;
		}
		animTimer += Time.deltaTime;
		if (animTimer >= animSpeed)
		{
			animTimer = 0f;
			animFrame = (animFrame + 1) % 14;
			if ((Object)(object)closedSprites[animFrame] != (Object)null)
			{
				overlayImage.sprite = closedSprites[animFrame];
			}
		}
	}

	private void AnimateScreamer()
	{
		animTimer += Time.deltaTime;
		if (animTimer >= 0.05f)
		{
			animTimer = 0f;
			animFrame++;
			if (animFrame >= 50)
			{
				overlayObject.SetActive(false);
			}
			else if ((Object)(object)screamerSprites[animFrame] != (Object)null)
			{
				overlayImage.sprite = screamerSprites[animFrame];
			}
		}
	}

	private void AnimateOpen()
	{
		animTimer += Time.deltaTime;
		if (animTimer >= 0.05f)
		{
			animTimer = 0f;
			animFrame = (animFrame + 1) % 14;
			if ((Object)(object)openSprites[animFrame] != (Object)null)
			{
				overlayImage.sprite = openSprites[animFrame];
			}
		}
	}

	private void ShowClosedEyes()
	{
		currentState = DozerState.ClosedEyes;
		timer = 0f;
		animFrame = 0;
		animTimer = 0f;
		overlayObject.SetActive(true);
		if ((Object)(object)closedSprites[0] != (Object)null)
		{
			overlayImage.sprite = closedSprites[0];
		}
		if ((Object)(object)closedSound != (Object)null)
		{
			audioSource.loop = true;
			audioSource.clip = closedSound;
			audioSource.Play();
		}
	}

	private void OpenEyes()
	{
		currentState = DozerState.OpenEyes;
		timer = 0f;
		animFrame = 0;
		animTimer = 0f;
		if ((Object)(object)openSound != (Object)null)
		{
			audioSource.loop = false;
			audioSource.clip = openSound;
			audioSource.Play();
		}
		if ((Object)(object)openSprites[0] != (Object)null)
		{
			overlayImage.sprite = openSprites[0];
		}
	}

	private void TriggerScreamer()
	{
		currentState = DozerState.Screamer;
		timer = 0f;
		animFrame = 0;
		animTimer = 0f;
		textAnimFrame = 0;
		textAnimTimer = 0f;
		textAnimStarted = false;
		if ((Object)(object)textSprites[0] != (Object)null)
		{
			textImage.sprite = textSprites[0];
		}
		textObject.SetActive(true);
		AudioSource val = ((Component)this).gameObject.AddComponent<AudioSource>();
		val.loop = false;
		val.volume = 1f;
		if ((Object)(object)killSound != (Object)null)
		{
			val.clip = killSound;
			val.Play();
		}
		AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
		AudioSource[] array2 = array;
		foreach (AudioSource val2 in array2)
		{
			if ((Object)(object)val2 != (Object)(object)val && (Object)(object)val2 != (Object)(object)audioSource)
			{
				val2.mute = true;
			}
		}
		((Component)blackBackground).gameObject.SetActive(true);
		overlayObject.SetActive(false);
		overlayObject.SetActive(true);
		if ((Object)(object)screamerSprites[0] != (Object)null)
		{
			overlayImage.sprite = screamerSprites[0];
		}
	}

	private void AnimateText()
	{
		textAnimTimer += Time.deltaTime;
		if (!textAnimStarted && textAnimTimer >= 1.5f)
		{
			textAnimStarted = true;
			textAnimTimer = 0f;
			textAnimFrame = 1;
		}
		if (!textAnimStarted)
		{
			return;
		}
		textAnimTimer += Time.deltaTime;
		if (textAnimTimer >= 0.0667f)
		{
			textAnimTimer = 0f;
			textAnimFrame++;
			if (textAnimFrame < 25 && (Object)(object)textSprites[textAnimFrame] != (Object)null)
			{
				textImage.sprite = textSprites[textAnimFrame];
			}
		}
	}

	public void ResetDozer()
	{
		currentState = DozerState.Hidden;
		timer = 0f;
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
		overlayObject.SetActive(false);
	}

	private void Hide()
	{
		currentState = DozerState.Hidden;
		timer = 0f;
		overlayObject.SetActive(false);
		((Component)blackBackground).gameObject.SetActive(false);
		isOnCooldown = true;
		cooldownTimer = 0f;
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
		audioSource.Stop();
	}

	private void KillPlayer()
	{
		//IL_0018: 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_0028: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
		if ((Object)(object)localPlayerController != (Object)null)
		{
			localPlayerController.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 1, default(Vector3), false);
		}
		AudioListener.volume = previousVolume;
		overlayObject.SetActive(false);
		((Component)blackBackground).gameObject.SetActive(false);
		audioSource.Stop();
		textObject.SetActive(false);
		currentState = DozerState.Hidden;
		timer = 0f;
		isOnCooldown = false;
		AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
		AudioSource[] array2 = array;
		foreach (AudioSource val in array2)
		{
			val.mute = false;
		}
	}

	private bool IsPlayerSafe()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return true;
		}
		bool isCrouching = val.isCrouching;
		Vector3 velocity = val.thisController.velocity;
		bool flag = ((Vector3)(ref velocity)).magnitude > 0.1f;
		return isCrouching && !flag;
	}

	private bool IsPlayerInGame()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (val.isPlayerDead)
		{
			return false;
		}
		if (StartOfRound.Instance?.currentLevel?.sceneName == "CompanyBuilding")
		{
			return false;
		}
		return !val.isInHangarShipRoom && (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipHasLanded;
	}

	private void CreateOverlay()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Expected O, but got Unknown
		//IL_00ff: 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_012d: 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)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Expected O, but got Unknown
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("DozerCanvas");
		Canvas val2 = val.AddComponent<Canvas>();
		val2.renderMode = (RenderMode)0;
		val2.sortingOrder = 100;
		Object.DontDestroyOnLoad((Object)(object)val);
		GameObject val3 = new GameObject("DozerBlackBg");
		val3.transform.SetParent(val.transform, false);
		blackBackground = val3.AddComponent<Image>();
		((Graphic)blackBackground).color = new Color(0f, 0f, 0f, 1f);
		RectTransform component = val3.GetComponent<RectTransform>();
		component.anchorMin = Vector2.zero;
		component.anchorMax = Vector2.one;
		component.sizeDelta = Vector2.zero;
		val3.SetActive(false);
		overlayObject = new GameObject("DozerImage");
		overlayObject.transform.SetParent(val.transform, false);
		overlayImage = overlayObject.AddComponent<Image>();
		RectTransform component2 = overlayObject.GetComponent<RectTransform>();
		component2.anchorMin = new Vector2(0.5f, 0.5f);
		component2.anchorMax = new Vector2(0.5f, 0.5f);
		component2.sizeDelta = new Vector2(600f, 600f);
		component2.anchoredPosition = Vector2.zero;
		GameObject val4 = new GameObject("DozerText");
		val4.transform.SetParent(val.transform, false);
		textImage = val4.AddComponent<Image>();
		RectTransform component3 = val4.GetComponent<RectTransform>();
		component3.anchorMin = new Vector2(0.5f, 0.5f);
		component3.anchorMax = new Vector2(0.5f, 0.5f);
		component3.sizeDelta = new Vector2(1000f, 1000f);
		component3.anchoredPosition = new Vector2(-320f, -60f);
		textObject = val4;
		textObject.SetActive(false);
		overlayObject.SetActive(false);
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "Start")]
public class DozerPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		if (((NetworkBehaviour)__instance).IsOwner && !((Object)(object)Object.FindObjectOfType<DozerBehaviour>() != (Object)null))
		{
			int num = Random.Range(0, 100);
			if (num >= Plugin.SpawnChance.Value)
			{
				Debug.Log((object)$"Dozer Entity: не появится в этом раунде (бросок {num}, нужно < {Plugin.SpawnChance.Value})");
				return;
			}
			GameObject val = new GameObject("DozerManager");
			val.AddComponent<DozerBehaviour>();
			Object.DontDestroyOnLoad((Object)(object)val);
			Debug.Log((object)$"Dozer Entity: менеджер создан! (бросок {num})");
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "SpawnDeadAnimation")]
public class DozerRespawnPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			DozerBehaviour dozerBehaviour = Object.FindObjectOfType<DozerBehaviour>();
			if ((Object)(object)dozerBehaviour != (Object)null)
			{
				dozerBehaviour.ResetDozer();
				Debug.Log((object)"Dozer Entity: сброс после возрождения!");
			}
		}
	}
}
[BepInPlugin("com.yourname.dozerentity", "Dozer Entity", "1.0.1")]
public class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
	public class DozerDeathPatch
	{
		private static void Postfix(PlayerControllerB __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				DozerBehaviour dozerBehaviour = Object.FindObjectOfType<DozerBehaviour>();
				if ((Object)(object)dozerBehaviour != (Object)null)
				{
					dozerBehaviour.ForceHide();
				}
			}
		}
	}

	private readonly Harmony harmony = new Harmony("com.yourname.dozerentity");

	public static ConfigEntry<int> SpawnChance;

	public static ConfigEntry<float> EyeOpenDelay;

	public static ConfigEntry<float> OpenEyesDuration;

	public static ConfigEntry<float> MinSpawnTime;

	public static ConfigEntry<float> MaxSpawnTime;

	private void Awake()
	{
		SpawnChance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SpawnChance", 35, "Dozer appear chance each round (0-100)");
		EyeOpenDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "EyeOpenDelay", 1.5f, "Time in seconds before Dozer opens it's eyes");
		OpenEyesDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "OpenEyesDuration", 3f, "How long Dozer stays with open eyes in seconds");
		MinSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MinSpawnTime", 10f, "Minimum time in seconds before Dozer appears");
		MaxSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MaxSpawnTime", 30f, "Maximum time in seconds before Dozer appears");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Dozer Entity загружен!");
		harmony.PatchAll();
	}
}

BepInEx/plugins/KookooEntity.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("KookooEntity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KookooEntity")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("df24efe7-a262-4aa5-981a-01c019d26f0a")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace KookooEntity;

public class KookooBehaviour : MonoBehaviour
{
	private enum KookooState
	{
		Hidden,
		Appearing,
		Counting,
		WaitingClosing,
		Closing,
		HoldingClose
	}

	private float basePitch = 0.7f;

	private bool conditionChecked = false;

	private KookooState currentState = KookooState.Hidden;

	private float timer = 0f;

	private float nextAppearTime = 0f;

	private List<GameObject> deathCopies = new List<GameObject>();

	private bool deathAnimPlaying = false;

	private float deathTimer = 0f;

	private float copyTimer = 0f;

	private GameObject deathCanvas;

	private Sprite lastClosingSprite;

	private AudioClip rememberClip;

	private AudioClip countClip;

	private AudioClip checkClip;

	private AudioClip killClip;

	private AudioSource rememberSource;

	private AudioSource countSource;

	private AudioSource checkSource;

	private AudioSource killSource;

	private bool isOnCooldown = false;

	private float cooldownTimer = 0f;

	private float cooldownTime = 0f;

	private GameObject rootObject;

	private Image bodyImage;

	private Image[] digitImages = (Image[])(object)new Image[2];

	private Image particlesImage;

	private Sprite[] rememberSprites = (Sprite[])(object)new Sprite[2];

	private Sprite[] numSprites = (Sprite[])(object)new Sprite[10];

	private Sprite particlesSprite;

	private Sprite[] countSprites = (Sprite[])(object)new Sprite[6];

	private Sprite[] closingSprites = (Sprite[])(object)new Sprite[4];

	private Sprite errorSprite;

	private bool shouldSpawnErrorSprites = false;

	private float errorSpriteSpawnTimer = 0f;

	private List<GameObject> errorSpriteInstances = new List<GameObject>();

	private float bodyAnimTimer = 0f;

	private int bodyAnimFrame = 0;

	private float countAnimTimer = 0f;

	private int countAnimFrame = 0;

	private bool countAnimPlaying = false;

	private float closingAnimTimer = 0f;

	private int closingAnimFrame = 0;

	private float particlesTimer = 0f;

	private float particlesInterval = 0f;

	private bool particlesVisible = false;

	private float particlesVisibleTimer = 0f;

	private int targetNumber = 0;

	private int currentCount = 0;

	private float countTimer = 0f;

	private float shakeTimer = 0f;

	private Vector2 basePosition = Vector2.zero;

	private bool scanBlocked = false;

	private float scanBlockTimer = 0f;

	private AudioSource scanDamageSource;

	private AudioSource scanErrorSource;

	private AudioClip scanDamageClip;

	private AudioClip scanErrorClip;

	private bool scanAttackPlaying = false;

	private float scanAttackTimer = 0f;

	private string modFolder;

	private AudioClip LoadAudioClip(string filename)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Kookoo Entity: звук не найден — " + text));
			return null;
		}
		WWW val = new WWW("file://" + text);
		try
		{
			while (!val.isDone)
			{
			}
			return val.GetAudioClip(false, false, (AudioType)13);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	private void Start()
	{
		string[] directories = Directory.GetDirectories(Paths.PluginPath, "KookooEntity", SearchOption.AllDirectories);
		modFolder = ((directories.Length != 0) ? directories[0] : Path.Combine(Paths.PluginPath, "KookooEntity"));
		LoadSprites();
		rememberClip = LoadAudioClip("remember.mp3");
		countClip = LoadAudioClip("count.mp3");
		checkClip = LoadAudioClip("check.mp3");
		killClip = LoadAudioClip("kill.mp3");
		rememberSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		rememberSource.loop = false;
		rememberSource.playOnAwake = false;
		countSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		countSource.loop = false;
		countSource.playOnAwake = false;
		checkSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		checkSource.loop = false;
		checkSource.playOnAwake = false;
		killSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		killSource.loop = false;
		killSource.playOnAwake = false;
		scanDamageClip = LoadAudioClip("scandamage.mp3");
		scanErrorClip = LoadAudioClip("scanerror.mp3");
		scanDamageSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		scanDamageSource.loop = false;
		scanDamageSource.playOnAwake = false;
		scanErrorSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		scanErrorSource.loop = false;
		scanErrorSource.playOnAwake = false;
		CreateOverlay();
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
	}

	private void LoadSprites()
	{
		rememberSprites[0] = LoadSprite("remember1.png");
		rememberSprites[1] = LoadSprite("remember2.png");
		for (int i = 0; i < 10; i++)
		{
			numSprites[i] = LoadSprite($"num{i}.png");
		}
		particlesSprite = LoadSprite("particles.png");
		for (int j = 0; j < 6; j++)
		{
			countSprites[j] = LoadSprite($"count{j + 1}.png");
		}
		for (int k = 0; k < 4; k++)
		{
			closingSprites[k] = LoadSprite($"closing{k + 1}.png");
		}
		errorSprite = LoadSprite("error.png");
	}

	private Sprite LoadSprite(string filename)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_0062: 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)
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Kookoo Entity: файл не найден — " + text));
			return null;
		}
		byte[] array = File.ReadAllBytes(text);
		Texture2D val = new Texture2D(2, 2);
		ImageConversion.LoadImage(val, array);
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
	}

	private void Update()
	{
		//IL_00ef: 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_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_037c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0382: Unknown result type (might be due to invalid IL or missing references)
		if (scanBlocked)
		{
			scanBlockTimer += Time.deltaTime;
			if (scanBlockTimer >= Plugin.ScanBlockDuration.Value)
			{
				scanBlocked = false;
				scanBlockTimer = 0f;
			}
		}
		if (scanAttackPlaying)
		{
			scanAttackTimer += Time.deltaTime;
			if (!(scanAttackTimer >= 0.5f))
			{
				return;
			}
			scanAttackPlaying = false;
			rootObject.SetActive(false);
			((Component)particlesImage).gameObject.SetActive(false);
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val != (Object)null)
			{
				int num = val.health - 1;
				if (num > 0)
				{
					val.DamagePlayer(num, true, true, (CauseOfDeath)0, 0, false, default(Vector3));
				}
			}
			scanBlocked = true;
			scanBlockTimer = 0f;
			return;
		}
		PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val2 == (Object)null)
		{
			return;
		}
		if (isOnCooldown)
		{
			cooldownTimer += Time.deltaTime;
			if (cooldownTimer >= cooldownTime)
			{
				isOnCooldown = false;
				cooldownTimer = 0f;
				timer = 0f;
				nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
			}
		}
		else if (deathAnimPlaying)
		{
			deathTimer += Time.deltaTime;
			copyTimer += Time.deltaTime;
			if (shouldSpawnErrorSprites && (Object)(object)errorSprite != (Object)null && deathTimer >= 1f)
			{
				errorSpriteSpawnTimer += Time.deltaTime;
				if (errorSpriteSpawnTimer >= 0.01f)
				{
					errorSpriteSpawnTimer = 0f;
					SpawnErrorSprite();
				}
			}
			if (copyTimer >= 0.01f)
			{
				copyTimer = 0f;
				CreateDeathCopy();
			}
			if (!(deathTimer >= 2f))
			{
				return;
			}
			deathAnimPlaying = false;
			shouldSpawnErrorSprites = false;
			deathCanvas.SetActive(false);
			foreach (GameObject deathCopy in deathCopies)
			{
				Object.Destroy((Object)(object)deathCopy);
			}
			deathCopies.Clear();
			foreach (GameObject errorSpriteInstance in errorSpriteInstances)
			{
				if ((Object)(object)errorSpriteInstance != (Object)null)
				{
					Object.Destroy((Object)(object)errorSpriteInstance);
				}
			}
			errorSpriteInstances.Clear();
			PlayerControllerB val3 = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val3 != (Object)null)
			{
				val3.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 1, default(Vector3), false);
			}
			Hide();
		}
		else if (val2.isPlayerDead)
		{
			ForceHide();
		}
		else
		{
			if (!IsPlayerInGame())
			{
				return;
			}
			timer += Time.deltaTime;
			if (currentState != 0)
			{
				AnimateBody();
			}
			switch (currentState)
			{
			case KookooState.Hidden:
				if (timer >= nextAppearTime)
				{
					Appear();
				}
				break;
			case KookooState.Appearing:
				if (timer >= Plugin.AppearDuration.Value)
				{
					StartCounting();
				}
				break;
			case KookooState.Counting:
				UpdateCounting();
				UpdateParticles();
				if (countAnimPlaying)
				{
					AnimateCount();
				}
				Shake();
				break;
			case KookooState.WaitingClosing:
				if (countAnimPlaying)
				{
					AnimateCount();
				}
				UpdateParticles();
				Shake();
				if (timer >= 1f)
				{
					StartClosing();
				}
				break;
			case KookooState.Closing:
				AnimateClosing();
				break;
			case KookooState.HoldingClose:
				if (!conditionChecked)
				{
					conditionChecked = true;
					CheckCondition();
				}
				break;
			}
		}
	}

	private void AnimateBody()
	{
		if (currentState != KookooState.Appearing)
		{
			return;
		}
		bodyAnimTimer += Time.deltaTime;
		if (bodyAnimTimer >= 0.0667f)
		{
			bodyAnimTimer = 0f;
			bodyAnimFrame = (bodyAnimFrame + 1) % 2;
			if ((Object)(object)rememberSprites[bodyAnimFrame] != (Object)null)
			{
				bodyImage.sprite = rememberSprites[bodyAnimFrame];
			}
		}
	}

	public bool IsScanBlocked()
	{
		return scanBlocked;
	}

	public void PlayScanError()
	{
		if ((Object)(object)scanErrorClip != (Object)null)
		{
			scanErrorSource.clip = scanErrorClip;
			scanErrorSource.Play();
		}
	}

	public void TryTriggerScanAttack()
	{
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		if (!scanAttackPlaying && Random.Range(0, Plugin.ScanAttackChance.Value) == 0)
		{
			scanAttackPlaying = true;
			scanAttackTimer = 0f;
			rootObject.SetActive(true);
			if ((Object)(object)closingSprites[3] != (Object)null)
			{
				bodyImage.sprite = closingSprites[3];
			}
			((Component)particlesImage).gameObject.SetActive(true);
			if ((Object)(object)scanDamageClip != (Object)null)
			{
				scanDamageSource.clip = scanDamageClip;
				scanDamageSource.Play();
			}
			float num = Random.Range(-500f, 500f);
			float num2 = Random.Range(-250f, 250f);
			rootObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(num, num2);
		}
	}

	private void AnimateCount()
	{
		countAnimTimer += Time.deltaTime;
		if (!(countAnimTimer >= 0.0667f))
		{
			return;
		}
		countAnimTimer = 0f;
		countAnimFrame++;
		if (countAnimFrame >= 6)
		{
			countAnimPlaying = false;
			countAnimFrame = 0;
			if ((Object)(object)countSprites[5] != (Object)null)
			{
				bodyImage.sprite = countSprites[5];
			}
		}
		else if ((Object)(object)countSprites[countAnimFrame] != (Object)null)
		{
			bodyImage.sprite = countSprites[countAnimFrame];
		}
	}

	private void AnimateClosing()
	{
		closingAnimTimer += Time.deltaTime;
		if (closingAnimTimer >= 0.0667f)
		{
			closingAnimTimer = 0f;
			closingAnimFrame++;
			if (closingAnimFrame >= 4)
			{
				currentState = KookooState.HoldingClose;
				timer = 0f;
			}
			else if ((Object)(object)closingSprites[closingAnimFrame] != (Object)null)
			{
				bodyImage.sprite = closingSprites[closingAnimFrame];
			}
		}
	}

	private void UpdateCounting()
	{
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		countTimer += Time.deltaTime;
		if (countTimer >= Plugin.CountInterval.Value)
		{
			countTimer = 0f;
			currentCount++;
			if ((Object)(object)countClip != (Object)null)
			{
				countSource.clip = countClip;
				countSource.Play();
				countSource.pitch = basePitch + (float)currentCount / (float)targetNumber * 0.6f;
			}
			UpdateDigits(currentCount);
			float num = Random.Range(-500f, 500f);
			float num2 = Random.Range(-250f, 250f);
			basePosition = new Vector2(num, num2);
			rootObject.GetComponent<RectTransform>().anchoredPosition = basePosition;
			countAnimPlaying = true;
			countAnimFrame = 0;
			countAnimTimer = 0f;
			if ((Object)(object)countSprites[0] != (Object)null)
			{
				bodyImage.sprite = countSprites[0];
			}
			if (currentCount >= targetNumber)
			{
				currentState = KookooState.WaitingClosing;
				timer = 0f;
			}
		}
	}

	private void UpdateParticles()
	{
		if (particlesVisible)
		{
			particlesVisibleTimer += Time.deltaTime;
			if (particlesVisibleTimer >= 0.2f)
			{
				particlesVisible = false;
				((Component)particlesImage).gameObject.SetActive(false);
			}
			return;
		}
		particlesTimer += Time.deltaTime;
		if (particlesTimer >= particlesInterval)
		{
			particlesTimer = 0f;
			particlesInterval = Random.Range(0.1f, 1f);
			particlesVisible = true;
			particlesVisibleTimer = 0f;
			((Component)particlesImage).gameObject.SetActive(true);
		}
	}

	private void Shake()
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		shakeTimer += Time.deltaTime;
		if (shakeTimer >= 0.05f)
		{
			shakeTimer = 0f;
			float num = Random.Range(-5f, 5f);
			float num2 = Random.Range(-5f, 5f);
			rootObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(basePosition.x + num, basePosition.y + num2);
		}
	}

	private void UpdateDigits(int number)
	{
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		if (number < 10)
		{
			((Component)digitImages[0]).gameObject.SetActive(false);
			((Component)digitImages[1]).gameObject.SetActive(true);
			digitImages[1].sprite = numSprites[number];
			((Component)digitImages[1]).GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
			return;
		}
		int num = number / 10;
		int num2 = number % 10;
		((Component)digitImages[0]).gameObject.SetActive(true);
		((Component)digitImages[1]).gameObject.SetActive(true);
		digitImages[0].sprite = numSprites[num];
		digitImages[1].sprite = numSprites[num2];
		((Component)digitImages[0]).GetComponent<RectTransform>().anchoredPosition = new Vector2(-40f, 0f);
		((Component)digitImages[1]).GetComponent<RectTransform>().anchoredPosition = new Vector2(40f, 0f);
	}

	private void Appear()
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: 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)
		currentState = KookooState.Appearing;
		timer = 0f;
		currentCount = 0;
		targetNumber = Random.Range(1, 31);
		float num = Random.Range(-500f, 500f);
		float num2 = Random.Range(-250f, 250f);
		basePosition = new Vector2(num, num2);
		rootObject.GetComponent<RectTransform>().anchoredPosition = basePosition;
		if ((Object)(object)rememberClip != (Object)null)
		{
			rememberSource.clip = rememberClip;
			rememberSource.Play();
		}
		rootObject.SetActive(true);
		if ((Object)(object)rememberSprites[0] != (Object)null)
		{
			bodyImage.sprite = rememberSprites[0];
		}
		UpdateDigits(targetNumber);
	}

	private void StartCounting()
	{
		currentState = KookooState.Counting;
		timer = 0f;
		countTimer = 0f;
		currentCount = 0;
		UpdateDigits(0);
		countSource.pitch = basePitch;
	}

	private void StartClosing()
	{
		conditionChecked = false;
		currentState = KookooState.Closing;
		closingAnimFrame = 0;
		closingAnimTimer = 0f;
		countAnimPlaying = false;
		((Component)digitImages[0]).gameObject.SetActive(false);
		((Component)digitImages[1]).gameObject.SetActive(false);
		((Component)particlesImage).gameObject.SetActive(false);
		if ((Object)(object)checkClip != (Object)null)
		{
			checkSource.clip = checkClip;
			checkSource.Play();
		}
		if ((Object)(object)closingSprites[0] != (Object)null)
		{
			bodyImage.sprite = closingSprites[0];
		}
	}

	public void CheckCondition()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			Hide();
		}
		else if ((Object)(object)val.currentlyHeldObjectServer != (Object)null)
		{
			if ((Object)(object)killClip != (Object)null)
			{
				killSource.clip = killClip;
				killSource.Play();
			}
			deathAnimPlaying = true;
			shouldSpawnErrorSprites = true;
			errorSpriteSpawnTimer = 0f;
			deathTimer = 0f;
			copyTimer = 0f;
			lastClosingSprite = closingSprites[3];
			deathCanvas.SetActive(true);
			rootObject.SetActive(true);
		}
		else
		{
			Hide();
		}
	}

	private void SpawnErrorSprite()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Expected O, but got Unknown
		//IL_0095: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = GameObject.Find("KookooErrorSpriteCanvas");
		Canvas val2;
		if ((Object)(object)val == (Object)null)
		{
			val = new GameObject("KookooErrorSpriteCanvas");
			val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = 10000;
			Object.DontDestroyOnLoad((Object)(object)val);
		}
		else
		{
			val2 = val.GetComponent<Canvas>();
		}
		GameObject val3 = new GameObject("KookooErrorSprite");
		val3.transform.SetParent(((Component)val2).transform, false);
		Image val4 = val3.AddComponent<Image>();
		val4.sprite = errorSprite;
		RectTransform component = val3.GetComponent<RectTransform>();
		Rect rect = errorSprite.rect;
		float width = ((Rect)(ref rect)).width;
		rect = errorSprite.rect;
		component.sizeDelta = new Vector2(width, ((Rect)(ref rect)).height);
		component.anchoredPosition = new Vector2((float)Random.Range(-Screen.width / 2 + 160, Screen.width / 2 - 160), (float)Random.Range(-Screen.height / 2 + 80, Screen.height / 2 - 80));
		errorSpriteInstances.Add(val3);
	}

	private void CreateDeathCopy()
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		float num = Random.Range((float)(-Screen.width) * 0.5f, (float)Screen.width * 0.5f);
		float num2 = Random.Range((float)(-Screen.height) * 0.5f, (float)Screen.height * 0.5f);
		GameObject val = new GameObject("KookooCopy");
		val.transform.SetParent(deathCanvas.transform, false);
		Image val2 = val.AddComponent<Image>();
		val2.sprite = lastClosingSprite;
		RectTransform component = val.GetComponent<RectTransform>();
		component.anchorMin = new Vector2(0.5f, 0.5f);
		component.anchorMax = new Vector2(0.5f, 0.5f);
		component.sizeDelta = new Vector2(800f, 800f);
		component.anchoredPosition = new Vector2(num, num2);
		deathCopies.Add(val);
	}

	private void Hide()
	{
		currentState = KookooState.Hidden;
		timer = 0f;
		rootObject.SetActive(false);
		isOnCooldown = true;
		cooldownTimer = 0f;
		cooldownTime = Plugin.CooldownTime.Value;
		((Component)particlesImage).gameObject.SetActive(false);
		rememberSource.Stop();
		countSource.Stop();
		checkSource.Stop();
		killSource.Stop();
	}

	public void ForceHide()
	{
		currentState = KookooState.Hidden;
		timer = 0f;
		rootObject.SetActive(false);
		isOnCooldown = false;
		((Component)particlesImage).gameObject.SetActive(false);
		((MonoBehaviour)this).CancelInvoke("StartClosing");
		deathAnimPlaying = false;
		shouldSpawnErrorSprites = false;
		if ((Object)(object)deathCanvas != (Object)null)
		{
			deathCanvas.SetActive(false);
		}
		foreach (GameObject deathCopy in deathCopies)
		{
			Object.Destroy((Object)(object)deathCopy);
		}
		deathCopies.Clear();
		foreach (GameObject errorSpriteInstance in errorSpriteInstances)
		{
			if ((Object)(object)errorSpriteInstance != (Object)null)
			{
				Object.Destroy((Object)(object)errorSpriteInstance);
			}
		}
		errorSpriteInstances.Clear();
		rememberSource.Stop();
		countSource.Stop();
		checkSource.Stop();
		killSource.Stop();
	}

	public void ResetKookoo()
	{
		ForceHide();
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
		cooldownTimer = 0f;
	}

	private bool IsPlayerInGame()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (val.isPlayerDead)
		{
			return false;
		}
		if (StartOfRound.Instance?.currentLevel?.sceneName == "CompanyBuilding")
		{
			return false;
		}
		return !val.isInHangarShipRoom && (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipHasLanded;
	}

	private void CreateOverlay()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: 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_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Expected O, but got Unknown
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Expected O, but got Unknown
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Expected O, but got Unknown
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Expected O, but got Unknown
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("KookooCanvas");
		Canvas val2 = val.AddComponent<Canvas>();
		val2.renderMode = (RenderMode)0;
		val2.sortingOrder = 100;
		Object.DontDestroyOnLoad((Object)(object)val);
		deathCanvas = new GameObject("KookooDeathCanvas");
		Canvas val3 = deathCanvas.AddComponent<Canvas>();
		val3.renderMode = (RenderMode)0;
		val3.sortingOrder = 200;
		Object.DontDestroyOnLoad((Object)(object)deathCanvas);
		deathCanvas.SetActive(false);
		rootObject = new GameObject("KookooRoot");
		rootObject.transform.SetParent(val.transform, false);
		RectTransform val4 = rootObject.AddComponent<RectTransform>();
		val4.anchorMin = new Vector2(0.5f, 0.5f);
		val4.anchorMax = new Vector2(0.5f, 0.5f);
		val4.sizeDelta = new Vector2(800f, 800f);
		val4.anchoredPosition = Vector2.zero;
		GameObject val5 = new GameObject("KookooParticles");
		val5.transform.SetParent(rootObject.transform, false);
		particlesImage = val5.AddComponent<Image>();
		if ((Object)(object)particlesSprite != (Object)null)
		{
			particlesImage.sprite = particlesSprite;
		}
		RectTransform component = val5.GetComponent<RectTransform>();
		component.anchorMin = Vector2.zero;
		component.anchorMax = Vector2.one;
		component.sizeDelta = Vector2.zero;
		val5.SetActive(false);
		GameObject val6 = new GameObject("KookooBody");
		val6.transform.SetParent(rootObject.transform, false);
		bodyImage = val6.AddComponent<Image>();
		RectTransform component2 = val6.GetComponent<RectTransform>();
		component2.anchorMin = Vector2.zero;
		component2.anchorMax = Vector2.one;
		component2.sizeDelta = Vector2.zero;
		for (int i = 0; i < 2; i++)
		{
			GameObject val7 = new GameObject($"KookooDigit_{i}");
			val7.transform.SetParent(rootObject.transform, false);
			digitImages[i] = val7.AddComponent<Image>();
			RectTransform component3 = val7.GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0.5f, 0.5f);
			component3.anchorMax = new Vector2(0.5f, 0.5f);
			component3.sizeDelta = new Vector2(800f, 800f);
			component3.anchoredPosition = new Vector2(((float)i - 0.5f) * 35f, 0f);
			val7.SetActive(false);
		}
		rootObject.SetActive(false);
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "Start")]
public class KookooPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		if (((NetworkBehaviour)__instance).IsOwner && !((Object)(object)Object.FindObjectOfType<KookooBehaviour>() != (Object)null))
		{
			int num = Random.Range(0, 100);
			if (num >= Plugin.SpawnChance.Value)
			{
				Debug.Log((object)$"Kookoo Entity: не появится в этом раунде (бросок {num})");
				return;
			}
			GameObject val = new GameObject("KookooManager");
			val.AddComponent<KookooBehaviour>();
			Object.DontDestroyOnLoad((Object)(object)val);
			Debug.Log((object)"Kookoo Entity: менеджер создан!");
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "SpawnDeadAnimation")]
public class KookooRespawnPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			KookooBehaviour kookooBehaviour = Object.FindObjectOfType<KookooBehaviour>();
			if ((Object)(object)kookooBehaviour != (Object)null)
			{
				kookooBehaviour.ResetKookoo();
			}
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
public class KookooDeathPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			KookooBehaviour kookooBehaviour = Object.FindObjectOfType<KookooBehaviour>();
			if ((Object)(object)kookooBehaviour != (Object)null)
			{
				kookooBehaviour.ForceHide();
			}
		}
	}
}
[HarmonyPatch(typeof(HUDManager), "CanPlayerScan")]
public class TestPatch
{
	private static void Postfix()
	{
		Debug.Log((object)"MethodFinder: CanPlayerScan!");
	}
}
public class KookooScanPatch
{
	public static void OnScan()
	{
		Debug.Log((object)"Kookoo: скан нажат!");
		KookooBehaviour kookooBehaviour = Object.FindObjectOfType<KookooBehaviour>();
		if ((Object)(object)kookooBehaviour != (Object)null)
		{
			kookooBehaviour.TryTriggerScanAttack();
		}
	}
}
[BepInPlugin("com.yourname.kookooentity", "Kookoo Entity", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	private readonly Harmony harmony = new Harmony("com.yourname.kookooentity");

	public static ConfigEntry<int> SpawnChance;

	public static ConfigEntry<float> MinSpawnTime;

	public static ConfigEntry<float> MaxSpawnTime;

	public static ConfigEntry<float> CooldownTime;

	public static ConfigEntry<float> AppearDuration;

	public static ConfigEntry<float> CountInterval;

	public static ConfigEntry<int> ScanAttackChance;

	public static ConfigEntry<float> ScanBlockDuration;

	private void Awake()
	{
		SpawnChance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SpawnChance", 50, "Chance of Kookoo appearing each round (0-100)");
		MinSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MinSpawnTime", 30f, "Minimum time before Kookoo appears");
		MaxSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MaxSpawnTime", 90f, "Maximum time before Kookoo appears");
		CooldownTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "CooldownTime", 60f, "Cooldown before Kookoo can appear again");
		AppearDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "AppearDuration", 2f, "Time Kookoo shows the number before counting");
		CountInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "CountInterval", 1f, "Time between each count");
		ScanAttackChance = ((BaseUnityPlugin)this).Config.Bind<int>("Scan", "ScanAttackChance", 5, "1 in X chance of Kookoo appearing on scan");
		ScanBlockDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Scan", "ScanBlockDuration", 30f, "How long scan is blocked after Kookoo attack");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Kookoo Entity loaded!");
		harmony.PatchAll();
	}
}

BepInEx/plugins/LitanyEntity.dll

Decompiled 2 weeks 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.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LitanyEntity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LitanyEntity")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e9825634-eec7-4ae6-80c6-e82bbadddd91")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LitanyEntity;

public class LitanyBehaviour : MonoBehaviour
{
	private enum LitanyState
	{
		Hidden,
		Preparing,
		Warning,
		EyeOpen,
		BetweenEyes,
		Screamer
	}

	private LitanyState currentState = LitanyState.Hidden;

	private float timer = 0f;

	private float nextAppearTime = 0f;

	private int currentEye = 0;

	private bool isOnCooldown = false;

	private float cooldownTimer = 0f;

	private float cooldownTime = 0f;

	private GameObject rootObject;

	private Image bodyImage;

	private Image eyeImage;

	private Sprite bodySprite;

	private Sprite eyesClosedSprite;

	private Sprite[] eyeWarningSprites = (Sprite[])(object)new Sprite[3];

	private Sprite[] eyeOpenedSprites = (Sprite[])(object)new Sprite[3];

	private float shakeTimer = 0f;

	private float eyeAnimTimer = 0f;

	private int eyeAnimFrame = 0;

	private Vector2 basePosition;

	private AudioSource idleSource;

	private AudioSource screamsSource;

	private AudioSource oneShotSource;

	private AudioClip idleClip;

	private AudioClip prepareClip;

	private AudioClip[] openClips = (AudioClip[])(object)new AudioClip[3];

	private AudioClip screamsClip;

	private VideoPlayer videoPlayer;

	private RawImage videoImage;

	private RenderTexture videoTexture;

	private bool videoFinished = false;

	private string modFolder;

	private void Start()
	{
		modFolder = Path.Combine(Paths.PluginPath, "LitanyEntity");
		string[] directories = Directory.GetDirectories(Paths.PluginPath, "LitanyEntity", SearchOption.AllDirectories);
		if (directories.Length != 0)
		{
			modFolder = directories[0];
		}
		LoadSprites();
		CreateOverlay();
		LoadAudio();
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
	}

	private void LoadSprites()
	{
		bodySprite = LoadSprite("body.png");
		eyesClosedSprite = LoadSprite("eyes_closed.png");
		for (int i = 0; i < 3; i++)
		{
			eyeWarningSprites[i] = LoadSprite($"eye{i + 1}_warning.png");
			eyeOpenedSprites[i] = LoadSprite($"eye{i + 1}_opened.png");
		}
	}

	private void LoadAudio()
	{
		idleClip = LoadAudioClip("idle.mp3");
		prepareClip = LoadAudioClip("prepare.mp3");
		openClips[0] = LoadAudioClip("open1.mp3");
		openClips[1] = LoadAudioClip("open2.mp3");
		openClips[2] = LoadAudioClip("open3.mp3");
		screamsClip = LoadAudioClip("screams.mp3");
		idleSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		idleSource.loop = true;
		idleSource.playOnAwake = false;
		screamsSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		screamsSource.loop = true;
		screamsSource.playOnAwake = false;
		oneShotSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		oneShotSource.loop = false;
		oneShotSource.playOnAwake = false;
	}

	private AudioClip LoadAudioClip(string filename)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Litany Entity: звук не найден — " + text));
			return null;
		}
		WWW val = new WWW("file://" + text);
		try
		{
			while (!val.isDone)
			{
			}
			return val.GetAudioClip(false, false, (AudioType)13);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	private Sprite LoadSprite(string filename)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_0062: 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)
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Litany Entity: file not found — " + text));
			return null;
		}
		byte[] array = File.ReadAllBytes(text);
		Texture2D val = new Texture2D(2, 2);
		ImageConversion.LoadImage(val, array);
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
	}

	private void Update()
	{
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_02be: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if (currentState != 0)
		{
			AnimateBody();
		}
		if (val.isPlayerDead)
		{
			ForceHide();
		}
		else if (isOnCooldown)
		{
			cooldownTimer += Time.deltaTime;
			if (cooldownTimer >= cooldownTime)
			{
				isOnCooldown = false;
				cooldownTimer = 0f;
				timer = 0f;
				nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
			}
		}
		else
		{
			if (!IsPlayerInGame())
			{
				return;
			}
			if (val.quickMenuManager.isMenuOpen)
			{
				rootObject.SetActive(false);
				return;
			}
			if (currentState != 0 && currentState != LitanyState.Screamer)
			{
				rootObject.SetActive(true);
			}
			timer += Time.deltaTime;
			switch (currentState)
			{
			case LitanyState.Hidden:
				if (timer >= nextAppearTime)
				{
					Appear();
				}
				break;
			case LitanyState.Preparing:
				if (timer >= Plugin.PrepareDuration.Value)
				{
					StartWarning();
				}
				break;
			case LitanyState.Warning:
				AnimateWarning();
				if (timer >= Plugin.WarningDuration.Value)
				{
					OpenEye();
				}
				break;
			case LitanyState.EyeOpen:
				if (!IsPlayerCrouching())
				{
					TriggerDeath();
				}
				else if (timer >= Plugin.OpenEyeDuration.Value)
				{
					CloseEye();
				}
				break;
			case LitanyState.BetweenEyes:
				if (timer >= Plugin.BetweenEyesDuration.Value)
				{
					if (currentEye >= 3)
					{
						Hide();
					}
					else
					{
						StartWarning();
					}
				}
				break;
			case LitanyState.Screamer:
				if (videoFinished)
				{
					((Graphic)videoImage).color = new Color(1f, 1f, 1f, 0f);
					PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController;
					if ((Object)(object)val2 != (Object)null)
					{
						val2.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 1, default(Vector3), false);
					}
					Hide();
				}
				break;
			}
		}
	}

	private void AnimateBody()
	{
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		shakeTimer += Time.deltaTime;
		if (shakeTimer >= Plugin.ShakeSpeed.Value)
		{
			shakeTimer = 0f;
			float num = Random.Range(-8f, 8f);
			float num2 = Random.Range(-8f, 8f);
			float num3 = Random.Range(-5f, 5f);
			rootObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(basePosition.x + num, basePosition.y + num2);
			((Transform)rootObject.GetComponent<RectTransform>()).localRotation = Quaternion.Euler(0f, 0f, num3);
		}
	}

	private void AnimateWarning()
	{
		eyeAnimTimer += Time.deltaTime;
		if (eyeAnimTimer >= 0.15f)
		{
			eyeAnimTimer = 0f;
			eyeAnimFrame = (eyeAnimFrame + 1) % 2;
			eyeImage.sprite = ((eyeAnimFrame == 0) ? eyesClosedSprite : eyeWarningSprites[currentEye]);
		}
	}

	private void Appear()
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		currentState = LitanyState.Preparing;
		timer = 0f;
		currentEye = 0;
		float num = Random.Range(-500f, 500f);
		float num2 = Random.Range(-250f, 250f);
		basePosition = new Vector2(num, num2);
		rootObject.GetComponent<RectTransform>().anchoredPosition = basePosition;
		rootObject.SetActive(true);
		if ((Object)(object)bodySprite != (Object)null)
		{
			bodyImage.sprite = bodySprite;
		}
		if ((Object)(object)eyesClosedSprite != (Object)null)
		{
			eyeImage.sprite = eyesClosedSprite;
		}
		if ((Object)(object)idleClip != (Object)null)
		{
			idleSource.clip = idleClip;
			idleSource.Play();
		}
	}

	private void StartWarning()
	{
		currentState = LitanyState.Warning;
		timer = 0f;
		eyeAnimFrame = 0;
		eyeAnimTimer = 0f;
		if ((Object)(object)prepareClip != (Object)null)
		{
			oneShotSource.Stop();
			oneShotSource.clip = prepareClip;
			oneShotSource.Play();
		}
	}

	private void OpenEye()
	{
		currentState = LitanyState.EyeOpen;
		timer = 0f;
		if ((Object)(object)eyeOpenedSprites[currentEye] != (Object)null)
		{
			eyeImage.sprite = eyeOpenedSprites[currentEye];
		}
		if ((Object)(object)openClips[currentEye] != (Object)null)
		{
			oneShotSource.Stop();
			oneShotSource.clip = openClips[currentEye];
			oneShotSource.Play();
		}
		if (currentEye == 0 && (Object)(object)screamsClip != (Object)null)
		{
			screamsSource.clip = screamsClip;
			screamsSource.Play();
		}
	}

	private void CloseEye()
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		currentEye++;
		if (currentEye >= 3)
		{
			Hide();
			return;
		}
		if ((Object)(object)eyesClosedSprite != (Object)null)
		{
			eyeImage.sprite = eyesClosedSprite;
		}
		float num = Random.Range(-500f, 500f);
		float num2 = Random.Range(-250f, 250f);
		basePosition = new Vector2(num, num2);
		rootObject.GetComponent<RectTransform>().anchoredPosition = basePosition;
		currentState = LitanyState.BetweenEyes;
		timer = 0f;
	}

	private void TriggerDeath()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		currentState = LitanyState.Screamer;
		videoFinished = false;
		rootObject.SetActive(false);
		idleSource.Stop();
		screamsSource.Stop();
		oneShotSource.Stop();
		string text = Path.Combine(modFolder, "Death.mp4");
		videoPlayer.url = "file://" + text;
		videoPlayer.Play();
		((Graphic)videoImage).color = new Color(1f, 1f, 1f, 1f);
	}

	private void OnVideoFinished(VideoPlayer vp)
	{
		videoFinished = true;
	}

	private void Hide()
	{
		currentState = LitanyState.Hidden;
		timer = 0f;
		rootObject.SetActive(false);
		isOnCooldown = true;
		cooldownTimer = 0f;
		cooldownTime = Plugin.CooldownTime.Value;
		idleSource.Stop();
		screamsSource.Stop();
		oneShotSource.Stop();
	}

	public void ForceHide()
	{
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		currentState = LitanyState.Hidden;
		timer = 0f;
		rootObject.SetActive(false);
		isOnCooldown = false;
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
		idleSource.Stop();
		screamsSource.Stop();
		oneShotSource.Stop();
		if ((Object)(object)videoPlayer != (Object)null)
		{
			videoPlayer.Stop();
		}
		if ((Object)(object)videoImage != (Object)null)
		{
			((Graphic)videoImage).color = new Color(1f, 1f, 1f, 0f);
		}
	}

	public void ResetLitany()
	{
		currentState = LitanyState.Hidden;
		timer = 0f;
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
		rootObject.SetActive(false);
		isOnCooldown = false;
		cooldownTimer = 0f;
		idleSource.Stop();
		screamsSource.Stop();
		oneShotSource.Stop();
	}

	public void ForceAppear()
	{
		if (currentState == LitanyState.Hidden)
		{
			isOnCooldown = false;
			timer = nextAppearTime + 1f;
		}
	}

	private bool IsPlayerCrouching()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return true;
		}
		return val.isCrouching;
	}

	private bool IsPlayerInGame()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (val.isPlayerDead)
		{
			return false;
		}
		if (StartOfRound.Instance?.currentLevel?.sceneName == "CompanyBuilding")
		{
			return false;
		}
		return !val.isInHangarShipRoom && (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipHasLanded;
	}

	private void CreateOverlay()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: 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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		//IL_00f1: 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_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Expected O, but got Unknown
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Expected O, but got Unknown
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Expected O, but got Unknown
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Expected O, but got Unknown
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Expected O, but got Unknown
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("LitanyCanvas");
		Canvas val2 = val.AddComponent<Canvas>();
		val2.renderMode = (RenderMode)0;
		val2.sortingOrder = 100;
		Object.DontDestroyOnLoad((Object)(object)val);
		rootObject = new GameObject("LitanyRoot");
		rootObject.transform.SetParent(val.transform, false);
		RectTransform val3 = rootObject.AddComponent<RectTransform>();
		val3.anchorMin = new Vector2(0.5f, 0.5f);
		val3.anchorMax = new Vector2(0.5f, 0.5f);
		val3.sizeDelta = new Vector2(500f, 500f);
		val3.anchoredPosition = Vector2.zero;
		basePosition = Vector2.zero;
		GameObject val4 = new GameObject("LitanyBody");
		val4.transform.SetParent(rootObject.transform, false);
		bodyImage = val4.AddComponent<Image>();
		RectTransform component = val4.GetComponent<RectTransform>();
		component.anchorMin = Vector2.zero;
		component.anchorMax = Vector2.one;
		component.sizeDelta = Vector2.zero;
		GameObject val5 = new GameObject("LitanyEyes");
		val5.transform.SetParent(rootObject.transform, false);
		eyeImage = val5.AddComponent<Image>();
		RectTransform component2 = val5.GetComponent<RectTransform>();
		component2.anchorMin = Vector2.zero;
		component2.anchorMax = Vector2.one;
		component2.sizeDelta = Vector2.zero;
		videoTexture = new RenderTexture(1920, 1080, 0);
		GameObject val6 = new GameObject("LitanyVideoPlayer");
		val6.transform.SetParent(val.transform, false);
		videoPlayer = val6.AddComponent<VideoPlayer>();
		videoPlayer.playOnAwake = false;
		videoPlayer.renderMode = (VideoRenderMode)2;
		videoPlayer.targetTexture = videoTexture;
		videoPlayer.loopPointReached += new EventHandler(OnVideoFinished);
		GameObject val7 = new GameObject("LitanyVideo");
		val7.transform.SetParent(val.transform, false);
		videoImage = val7.AddComponent<RawImage>();
		videoImage.texture = (Texture)(object)videoTexture;
		((Graphic)videoImage).color = new Color(1f, 1f, 1f, 0f);
		RectTransform component3 = val7.GetComponent<RectTransform>();
		component3.anchorMin = Vector2.zero;
		component3.anchorMax = Vector2.one;
		component3.sizeDelta = Vector2.zero;
		rootObject.SetActive(false);
	}
}
public class LitanyDomain : MonoBehaviour
{
	private enum DomainState
	{
		Inactive,
		Active
	}

	private DomainState currentState = DomainState.Inactive;

	private float eventTimer = 0f;

	private float eventDuration = 278f;

	private float commandTimer = 0f;

	private float commandInterval = 5f;

	private float commandDuration = 2f;

	private float commandActiveTimer = 0f;

	private bool commandActive = false;

	private bool isJumpCommand = false;

	private bool playerReacted = false;

	private bool playerViolated = false;

	private float scheduleTimer = 0f;

	private float scheduledTime = 0f;

	private bool scheduled = false;

	private float litanyTimer = 0f;

	private float litanyDelay = 65f;

	private bool litanyPhaseStarted = false;

	private GameObject commandObject;

	private Image commandImage;

	private Sprite jumpSprite;

	private Sprite dontJumpSprite;

	private AudioSource musicSource;

	private AudioSource orderBGSource;

	private AudioSource orderSource;

	private AudioClip musicClip;

	private AudioClip orderBGClip;

	private AudioClip[] orderClips = (AudioClip[])(object)new AudioClip[4];

	private float textShakeTimer = 0f;

	private float textShakeSpeed = 0.05f;

	private Vector2 textBasePosition = new Vector2(0f, -120f);

	private bool orderPlayedFinal = false;

	private float previousFallValue = -7f;

	private string modFolder;

	private void Start()
	{
		modFolder = Path.Combine(Paths.PluginPath, "LitanyEntity");
		string[] directories = Directory.GetDirectories(Paths.PluginPath, "LitanyEntity", SearchOption.AllDirectories);
		if (directories.Length != 0)
		{
			modFolder = directories[0];
		}
		LoadAssets();
		CreateUI();
	}

	private void LoadAssets()
	{
		jumpSprite = LoadSprite("jump.png");
		dontJumpSprite = LoadSprite("dont_jump.png");
		musicClip = LoadAudioClip("OWYH.mp3");
		orderBGClip = LoadAudioClip("orderBG.mp3");
		for (int i = 0; i < 4; i++)
		{
			orderClips[i] = LoadAudioClip($"order{i + 1}.mp3");
		}
		musicSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		musicSource.loop = false;
		musicSource.playOnAwake = false;
		if ((Object)(object)musicClip != (Object)null)
		{
			musicSource.clip = musicClip;
		}
		orderBGSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		orderBGSource.loop = false;
		orderBGSource.playOnAwake = false;
		orderSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		orderSource.loop = false;
		orderSource.playOnAwake = false;
	}

	private Sprite LoadSprite(string filename)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		string path = Path.Combine(modFolder, filename);
		if (!File.Exists(path))
		{
			return null;
		}
		byte[] array = File.ReadAllBytes(path);
		Texture2D val = new Texture2D(2, 2);
		ImageConversion.LoadImage(val, array);
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
	}

	private AudioClip LoadAudioClip(string filename)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			return null;
		}
		WWW val = new WWW("file://" + text);
		try
		{
			while (!val.isDone)
			{
			}
			return val.GetAudioClip(false, false, (AudioType)13);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	private void Update()
	{
		if (scheduled && currentState == DomainState.Inactive)
		{
			scheduleTimer += Time.deltaTime;
			if (scheduleTimer >= scheduledTime)
			{
				scheduled = false;
				StartEvent();
			}
		}
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if ((Object)(object)StartOfRound.Instance == (Object)null || !StartOfRound.Instance.shipHasLanded)
		{
			if (currentState == DomainState.Active)
			{
				EndEvent();
			}
		}
		else if (val.isInHangarShipRoom)
		{
			if (commandActive)
			{
				HideCommand();
			}
		}
		else if (val.isPlayerDead)
		{
			if (commandActive)
			{
				HideCommand();
			}
		}
		else
		{
			if (currentState == DomainState.Inactive)
			{
				return;
			}
			eventTimer += Time.deltaTime;
			if (eventTimer >= eventDuration)
			{
				EndEvent();
				return;
			}
			if (!litanyPhaseStarted && eventTimer >= litanyDelay)
			{
				litanyPhaseStarted = true;
				TriggerLitany();
			}
			if (litanyPhaseStarted)
			{
				litanyTimer += Time.deltaTime;
				if (litanyTimer >= Random.Range(15f, 20f))
				{
					litanyTimer = 0f;
					TriggerLitany();
				}
			}
			if (!commandActive)
			{
				commandTimer += Time.deltaTime;
				if (commandTimer >= commandInterval)
				{
					commandTimer = 0f;
					ShowCommand();
				}
				return;
			}
			ShakeCommand();
			commandActiveTimer += Time.deltaTime;
			if (!orderPlayedFinal && commandActiveTimer >= commandDuration - 3f)
			{
				orderPlayedFinal = true;
				int num = Random.Range(0, 4);
				if ((Object)(object)orderClips[num] != (Object)null)
				{
					orderSource.clip = orderClips[num];
					orderSource.Play();
				}
			}
			if (!playerReacted)
			{
				bool flag = IngamePlayerSettings.Instance.playerInput.actions["Jump"].WasPressedThisFrame();
				if (isJumpCommand && flag)
				{
					playerReacted = true;
				}
				if (!isJumpCommand && flag)
				{
					playerViolated = true;
				}
			}
			if (commandActiveTimer >= commandDuration)
			{
				if (isJumpCommand && !playerReacted)
				{
					DamagePlayer(val);
				}
				else if (!isJumpCommand && playerViolated)
				{
					DamagePlayer(val);
				}
				HideCommand();
			}
		}
	}

	private void ShakeCommand()
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		textShakeTimer += Time.deltaTime;
		if (textShakeTimer >= textShakeSpeed)
		{
			textShakeTimer = 0f;
			float num = Random.Range(-5f, 5f);
			float num2 = Random.Range(-5f, 5f);
			commandObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(textBasePosition.x + num, textBasePosition.y + num2);
		}
	}

	private void TriggerLitany()
	{
		LitanyBehaviour litanyBehaviour = Object.FindObjectOfType<LitanyBehaviour>();
		if ((Object)(object)litanyBehaviour != (Object)null)
		{
			litanyBehaviour.ForceAppear();
		}
	}

	private void ShowCommand()
	{
		isJumpCommand = Random.Range(0, 2) == 0;
		commandActive = true;
		commandActiveTimer = 0f;
		playerReacted = false;
		playerViolated = false;
		orderPlayedFinal = false;
		commandImage.sprite = (isJumpCommand ? jumpSprite : dontJumpSprite);
		commandObject.SetActive(true);
		if ((Object)(object)orderBGClip != (Object)null)
		{
			orderBGSource.clip = orderBGClip;
			orderBGSource.time = Random.Range(0f, orderBGClip.length * 0.7f);
			orderBGSource.Play();
		}
	}

	private void HideCommand()
	{
		commandActive = false;
		commandActiveTimer = 0f;
		orderPlayedFinal = false;
		commandObject.SetActive(false);
		orderBGSource.Stop();
	}

	private void DamagePlayer(PlayerControllerB player)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		player.DamagePlayer(20, true, true, (CauseOfDeath)0, 0, false, default(Vector3));
	}

	public void StartEvent()
	{
		currentState = DomainState.Active;
		eventTimer = 0f;
		commandTimer = 0f;
		litanyTimer = 0f;
		litanyPhaseStarted = false;
		musicSource.Play();
		Debug.Log((object)"Litany Domain: событие началось!");
	}

	private void EndEvent()
	{
		currentState = DomainState.Inactive;
		HideCommand();
		Debug.Log((object)"Litany Domain: событие закончилось!");
	}

	public void ScheduleEvent(float delay)
	{
		scheduledTime = delay;
		scheduled = true;
		scheduleTimer = 0f;
	}

	private void CreateUI()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("DomainCanvas");
		Canvas val2 = val.AddComponent<Canvas>();
		val2.renderMode = (RenderMode)0;
		val2.sortingOrder = 99;
		Object.DontDestroyOnLoad((Object)(object)val);
		commandObject = new GameObject("DomainCommand");
		commandObject.transform.SetParent(val.transform, false);
		commandImage = commandObject.AddComponent<Image>();
		RectTransform component = commandObject.GetComponent<RectTransform>();
		component.anchorMin = new Vector2(0.5f, 1f);
		component.anchorMax = new Vector2(0.5f, 1f);
		component.sizeDelta = new Vector2(300f, 100f);
		component.anchoredPosition = textBasePosition;
		commandObject.SetActive(false);
	}
}
public class LitanyDomainNetwork : NetworkBehaviour
{
	[CompilerGenerated]
	private sealed class <ScheduleCoroutine>d__4 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public float delay;

		public LitanyDomainNetwork <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(delay);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>4__this.StartDomainEventClientRpc();
				return false;
			}
		}

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

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

	public static LitanyDomainNetwork Instance;

	private void Awake()
	{
		Instance = this;
	}

	[ClientRpc]
	public void StartDomainEventClientRpc()
	{
		Debug.Log((object)"Litany Domain: получена команда начать событие!");
		LitanyDomain litanyDomain = Object.FindObjectOfType<LitanyDomain>();
		if ((Object)(object)litanyDomain != (Object)null)
		{
			litanyDomain.StartEvent();
		}
	}

	public void ScheduleEventForAll(float delay)
	{
		((MonoBehaviour)this).StartCoroutine(ScheduleCoroutine(delay));
	}

	[IteratorStateMachine(typeof(<ScheduleCoroutine>d__4))]
	private IEnumerator ScheduleCoroutine(float delay)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ScheduleCoroutine>d__4(0)
		{
			<>4__this = this,
			delay = delay
		};
	}
}
[HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")]
public class LitanyDomainPatch
{
	public static bool eventHappenedThisRound;

	private static void Postfix()
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Expected O, but got Unknown
		if (eventHappenedThisRound || (Object)(object)GameObject.Find("LitanyDomainManager") != (Object)null)
		{
			return;
		}
		GameObject val = new GameObject("LitanyDomainManager");
		val.AddComponent<LitanyDomain>();
		Object.DontDestroyOnLoad((Object)(object)val);
		if (GameNetworkManager.Instance.isHostingGame)
		{
			int num = Random.Range(0, 100);
			if (num >= Plugin.DomainChance.Value)
			{
				Debug.Log((object)"Litany Domain: событие не выпало");
				return;
			}
			eventHappenedThisRound = true;
			GameObject val2 = new GameObject("LitanyDomainNetworkManager");
			LitanyDomainNetwork litanyDomainNetwork = val2.AddComponent<LitanyDomainNetwork>();
			Object.DontDestroyOnLoad((Object)(object)val2);
			float num2 = Random.Range(Plugin.DomainMinDelay.Value, Plugin.DomainMaxDelay.Value);
			litanyDomainNetwork.ScheduleEventForAll(num2);
			Debug.Log((object)$"Litany Domain: событие запланировано через {num2} секунд!");
		}
	}
}
[HarmonyPatch(typeof(RoundManager), "UnloadSceneObjectsEarly")]
public class LitanyDomainCleanupPatch
{
	private static void Postfix()
	{
		LitanyDomainPatch.eventHappenedThisRound = false;
		GameObject val = GameObject.Find("LitanyDomainManager");
		if ((Object)(object)val != (Object)null)
		{
			Object.Destroy((Object)(object)val);
		}
		GameObject val2 = GameObject.Find("LitanyDomainNetworkManager");
		if ((Object)(object)val2 != (Object)null)
		{
			Object.Destroy((Object)(object)val2);
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "Start")]
public class LitanyPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		if (((NetworkBehaviour)__instance).IsOwner && !((Object)(object)Object.FindObjectOfType<LitanyBehaviour>() != (Object)null))
		{
			int num = Random.Range(0, 100);
			if (num >= Plugin.SpawnChance.Value)
			{
				Debug.Log((object)$"Litany Entity: won't appear this round (roll {num})");
				return;
			}
			GameObject val = new GameObject("LitanyManager");
			val.AddComponent<LitanyBehaviour>();
			Object.DontDestroyOnLoad((Object)(object)val);
			Debug.Log((object)"Litany Entity: manager created!");
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
public class LitanyDeathPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			LitanyBehaviour litanyBehaviour = Object.FindObjectOfType<LitanyBehaviour>();
			if ((Object)(object)litanyBehaviour != (Object)null)
			{
				litanyBehaviour.ForceHide();
			}
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "SpawnDeadAnimation")]
public class LitanyRespawnPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			LitanyBehaviour litanyBehaviour = Object.FindObjectOfType<LitanyBehaviour>();
			if ((Object)(object)litanyBehaviour != (Object)null)
			{
				litanyBehaviour.ResetLitany();
				Debug.Log((object)"Litany Entity: reset after respawn!");
			}
		}
	}
}
[BepInPlugin("com.yourname.litanyentity", "Litany Entity", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	private readonly Harmony harmony = new Harmony("com.yourname.litanyentity");

	public static ConfigEntry<int> SpawnChance;

	public static ConfigEntry<float> MinSpawnTime;

	public static ConfigEntry<float> MaxSpawnTime;

	public static ConfigEntry<float> PrepareDuration;

	public static ConfigEntry<float> WarningDuration;

	public static ConfigEntry<float> OpenEyeDuration;

	public static ConfigEntry<float> BetweenEyesDuration;

	public static ConfigEntry<float> CooldownTime;

	public static ConfigEntry<float> ShakeSpeed;

	public static ConfigEntry<int> DomainChance;

	public static ConfigEntry<float> DomainMinDelay;

	public static ConfigEntry<float> DomainMaxDelay;

	private void Awake()
	{
		SpawnChance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SpawnChance", 35, "Chance of Litany appearing each round (0-100)");
		MinSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MinSpawnTime", 10f, "Minimum time before Litany appears");
		MaxSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MaxSpawnTime", 30f, "Maximum time before Litany appears");
		PrepareDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "PrepareDuration", 4f, "Time before first eye warning");
		WarningDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "WarningDuration", 1.5f, "Duration of warning animation");
		OpenEyeDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "OpenEyeDuration", 0.5f, "How long eye stays open");
		BetweenEyesDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "BetweenEyesDuration", 2f, "Time between each eye attack");
		CooldownTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "CooldownTime", 60f, "Cooldown time in seconds before Litany can appear again");
		ShakeSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "ShakeSpeed", 0.05f, "Speed of Litany shaking (lower = faster)");
		DomainChance = ((BaseUnityPlugin)this).Config.Bind<int>("Domain", "DomainChance", 50, "Chance of Litany Domain event (0-100)");
		DomainMinDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Domain", "DomainMinDelay", 30f, "Minimum time before event starts");
		DomainMaxDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Domain", "DomainMaxDelay", 60f, "Maximum time before event starts");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Litany Entity loaded!");
		harmony.PatchAll();
	}
}

BepInEx/plugins/SeesayEntity.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SeesayEntity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SeesayEntity")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e798d498-5a9e-440e-8887-01ec34d10e37")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SeesayEntity;

[BepInPlugin("com.yourname.seesayentity", "Seesay Entity", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	private readonly Harmony harmony = new Harmony("com.yourname.seesayentity");

	public static ConfigEntry<int> SpawnChance;

	public static ConfigEntry<float> MinSpawnTime;

	public static ConfigEntry<float> MaxSpawnTime;

	public static ConfigEntry<float> SeesaySpeed;

	public static ConfigEntry<float> CooldownTime;

	public static ConfigEntry<bool> EnableTrainSound;

	public static ConfigEntry<float> MinFollowTime;

	public static ConfigEntry<float> MaxFollowTime;

	private void Awake()
	{
		SpawnChance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SpawnChance", 50, "Chance of Seesay appearing each round (0-100)");
		MinSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MinSpawnTime", 30f, "Minimum time before Seesay appears");
		MaxSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MaxSpawnTime", 90f, "Maximum time before Seesay appears");
		SeesaySpeed = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SeesaySpeed", 5f, "Speed of Seesay flying towards player");
		CooldownTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "CooldownTime", 60f, "Cooldown time in seconds before Seesay can appear again");
		MinFollowTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MinFollowTime", 3f, "Minimum time before Seesay opens its eye");
		MaxFollowTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MaxFollowTime", 8f, "Maximum time before Seesay opens its eye");
		EnableTrainSound = ((BaseUnityPlugin)this).Config.Bind<bool>("Fun", "EnableTrainSound", true, "Don't");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Seesay Entity loaded!");
		harmony.PatchAll();
	}
}
public class SeesayBehaviour : MonoBehaviour
{
	private enum SeesayState
	{
		Hidden,
		Following,
		Opening,
		Flying,
		Screamer
	}

	private VideoPlayer videoPlayer;

	private RawImage videoImage;

	private RenderTexture videoTexture;

	private bool videoFinished = false;

	private SeesayState currentState = SeesayState.Hidden;

	private float timer = 0f;

	private float nextAppearTime = 0f;

	private float followDuration = 5f;

	private bool isOnCooldown = false;

	private float cooldownTimer = 0f;

	private float cooldownTime = 0f;

	private AudioSource audioSource;

	private AudioClip appearClip;

	private AudioClip open1Clip;

	private AudioClip open2Clip;

	private AudioClip attackClip;

	private AudioClip flashedClip;

	private AudioSource flyingAudioSource;

	private AudioClip flyingClip;

	private AudioClip trainClip;

	private AudioSource trainAudioSource;

	private GameObject seesayObject;

	private SpriteRenderer spriteRenderer;

	private Camera mainCamera;

	private Sprite closedSprite;

	private Sprite[] animSprites = (Sprite[])(object)new Sprite[10];

	private Sprite flashedSprite;

	private float animTimer = 0f;

	private int animFrame = 0;

	private bool animPaused = false;

	private float animPauseTimer = 0f;

	private bool isFlashed = false;

	private float flashedTimer = 0f;

	private float distanceFromCamera = 3f;

	private Vector3 frozenWorldPos = Vector3.zero;

	private float shakeTimer = 0f;

	private float shakeSpeed = 0.05f;

	private Vector3 shakeOffset = Vector3.zero;

	private string modFolder;

	private void Start()
	{
		string[] directories = Directory.GetDirectories(Paths.PluginPath, "SeesayEntity", SearchOption.AllDirectories);
		modFolder = ((directories.Length != 0) ? directories[0] : Path.Combine(Paths.PluginPath, "SeesayEntity"));
		LoadSprites();
		CreateSeesay3D();
		audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		audioSource.loop = false;
		audioSource.playOnAwake = false;
		audioSource.volume = 10f;
		audioSource.spatialBlend = 0f;
		flyingClip = LoadAudioClip("Flying.mp3");
		flyingAudioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		flyingAudioSource.loop = true;
		flyingAudioSource.playOnAwake = false;
		flyingAudioSource.volume = 1f;
		flyingAudioSource.spatialBlend = 1f;
		flyingAudioSource.maxDistance = 20f;
		flyingAudioSource.rolloffMode = (AudioRolloffMode)1;
		trainClip = LoadAudioClip("Train.mp3");
		trainAudioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		trainAudioSource.loop = true;
		trainAudioSource.playOnAwake = false;
		trainAudioSource.volume = 1f;
		trainAudioSource.spatialBlend = 1f;
		trainAudioSource.maxDistance = 15f;
		trainAudioSource.rolloffMode = (AudioRolloffMode)1;
		appearClip = LoadAudioClip("Appear.mp3");
		open1Clip = LoadAudioClip("Open1.mp3");
		open2Clip = LoadAudioClip("Open2.mp3");
		attackClip = LoadAudioClip("Attack.mp3");
		flashedClip = LoadAudioClip("Flashed.mp3");
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
	}

	private void CreateSeesay3D()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_004a: 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)
		//IL_006d: Expected O, but got Unknown
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Expected O, but got Unknown
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Expected O, but got Unknown
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Expected O, but got Unknown
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		seesayObject = new GameObject("SeesaySprite");
		spriteRenderer = seesayObject.AddComponent<SpriteRenderer>();
		((Renderer)spriteRenderer).sortingOrder = 100;
		seesayObject.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
		seesayObject.SetActive(false);
		GameObject val = new GameObject("SeesayCanvas");
		Canvas val2 = val.AddComponent<Canvas>();
		val2.renderMode = (RenderMode)0;
		val2.sortingOrder = 200;
		Object.DontDestroyOnLoad((Object)(object)val);
		videoTexture = new RenderTexture(1920, 1080, 0);
		GameObject val3 = new GameObject("SeesayVideoPlayer");
		val3.transform.SetParent(val.transform, false);
		videoPlayer = val3.AddComponent<VideoPlayer>();
		videoPlayer.playOnAwake = false;
		videoPlayer.renderMode = (VideoRenderMode)2;
		videoPlayer.targetTexture = videoTexture;
		videoPlayer.loopPointReached += new EventHandler(OnVideoFinished);
		GameObject val4 = new GameObject("SeesayVideo");
		val4.transform.SetParent(val.transform, false);
		videoImage = val4.AddComponent<RawImage>();
		videoImage.texture = (Texture)(object)videoTexture;
		((Graphic)videoImage).color = new Color(1f, 1f, 1f, 0f);
		RectTransform component = val4.GetComponent<RectTransform>();
		component.anchorMin = Vector2.zero;
		component.anchorMax = Vector2.one;
		component.sizeDelta = Vector2.zero;
	}

	private void OnVideoFinished(VideoPlayer vp)
	{
		videoFinished = true;
	}

	private AudioClip LoadAudioClip(string filename)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Seesay Entity: звук не найден — " + text));
			return null;
		}
		WWW val = new WWW("file://" + text);
		try
		{
			while (!val.isDone)
			{
			}
			return val.GetAudioClip(false, false, (AudioType)13);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	private void LoadSprites()
	{
		closedSprite = LoadSprite("closed.png");
		flashedSprite = LoadSprite("flashed.png");
		for (int i = 0; i < 10; i++)
		{
			animSprites[i] = LoadSprite($"anim{i + 1}.png");
		}
	}

	private Sprite LoadSprite(string filename)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_0062: 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)
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Seesay Entity: файл не найден — " + text));
			return null;
		}
		byte[] array = File.ReadAllBytes(text);
		Texture2D val = new Texture2D(2, 2);
		ImageConversion.LoadImage(val, array);
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
	}

	private void Update()
	{
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if ((Object)(object)mainCamera == (Object)null)
		{
			Camera[] allCameras = Camera.allCameras;
			foreach (Camera val2 in allCameras)
			{
				if (((Behaviour)val2).isActiveAndEnabled && ((Object)val2).name == "MainCamera")
				{
					mainCamera = val2;
					break;
				}
			}
		}
		if (isOnCooldown)
		{
			cooldownTimer += Time.deltaTime;
			if (cooldownTimer >= cooldownTime)
			{
				isOnCooldown = false;
				cooldownTimer = 0f;
				timer = 0f;
				nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
			}
		}
		else if (val.isPlayerDead)
		{
			ForceHide();
		}
		else
		{
			if (!IsPlayerInGame())
			{
				return;
			}
			timer += Time.deltaTime;
			switch (currentState)
			{
			case SeesayState.Hidden:
				if (timer >= nextAppearTime)
				{
					Appear(val);
				}
				break;
			case SeesayState.Following:
				UpdateFollowingPosition(val);
				if (timer >= followDuration)
				{
					StartOpening();
				}
				break;
			case SeesayState.Opening:
				seesayObject.transform.position = frozenWorldPos + shakeOffset;
				if ((Object)(object)mainCamera != (Object)null)
				{
					seesayObject.transform.rotation = ((Component)mainCamera).transform.rotation;
				}
				AnimateOpening(val);
				break;
			case SeesayState.Flying:
				if (isFlashed)
				{
					flashedTimer += Time.deltaTime;
					if (flashedTimer >= 0.5f)
					{
						Hide();
					}
					return;
				}
				FlyTowardsPlayer(val);
				break;
			case SeesayState.Screamer:
				if (videoFinished)
				{
					((Graphic)videoImage).color = new Color(1f, 1f, 1f, 0f);
					PlayerControllerB val3 = GameNetworkManager.Instance?.localPlayerController;
					if ((Object)(object)val3 != (Object)null)
					{
						val3.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 1, default(Vector3), false);
					}
					Hide();
				}
				break;
			}
			if (currentState == SeesayState.Following || currentState == SeesayState.Opening)
			{
				UpdateShake();
			}
		}
	}

	private void UpdateFollowingPosition(PlayerControllerB player)
	{
		//IL_001e: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)mainCamera == (Object)null))
		{
			Vector3 val = ((Component)mainCamera).transform.position + ((Component)mainCamera).transform.forward * distanceFromCamera;
			seesayObject.transform.position = val + shakeOffset;
			seesayObject.transform.rotation = ((Component)mainCamera).transform.rotation;
		}
	}

	private void UpdateShake()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		shakeTimer += Time.deltaTime;
		if (shakeTimer >= shakeSpeed)
		{
			shakeTimer = 0f;
			shakeOffset = new Vector3(Random.Range(-0.05f, 0.05f), Random.Range(-0.05f, 0.05f), 0f);
		}
	}

	private void StartOpening()
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		currentState = SeesayState.Opening;
		timer = 0f;
		animFrame = 0;
		animTimer = 0f;
		animPaused = false;
		if ((Object)(object)mainCamera != (Object)null)
		{
			frozenWorldPos = ((Component)mainCamera).transform.position + ((Component)mainCamera).transform.forward * distanceFromCamera;
		}
		if ((Object)(object)animSprites[0] != (Object)null)
		{
			spriteRenderer.sprite = animSprites[0];
		}
	}

	private void AnimateOpening(PlayerControllerB player)
	{
		if (animPaused)
		{
			animPauseTimer += Time.deltaTime;
			if (animPauseTimer >= 0.2f)
			{
				animPaused = false;
				animPauseTimer = 0f;
				if ((Object)(object)open2Clip != (Object)null)
				{
					audioSource.clip = open2Clip;
					audioSource.Play();
				}
			}
			return;
		}
		animTimer += Time.deltaTime;
		if (animTimer >= 0.0667f)
		{
			animTimer = 0f;
			animFrame++;
			if (animFrame == 1 && (Object)(object)open1Clip != (Object)null)
			{
				audioSource.clip = open1Clip;
				audioSource.Play();
			}
			if (animFrame == 3)
			{
				animPaused = true;
				spriteRenderer.sprite = animSprites[3];
			}
			else if (animFrame >= 10)
			{
				StartFlying(player);
			}
			else if ((Object)(object)animSprites[animFrame] != (Object)null)
			{
				spriteRenderer.sprite = animSprites[animFrame];
			}
		}
	}

	private void StartFlying(PlayerControllerB player)
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		currentState = SeesayState.Flying;
		timer = 0f;
		if ((Object)(object)attackClip != (Object)null)
		{
			audioSource.clip = attackClip;
			audioSource.Play();
		}
		if ((Object)(object)flyingClip != (Object)null)
		{
			((Component)flyingAudioSource).transform.position = seesayObject.transform.position;
			flyingAudioSource.clip = flyingClip;
			flyingAudioSource.Play();
		}
	}

	private void FlyTowardsPlayer(PlayerControllerB player)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: 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)
		if ((Object)(object)mainCamera == (Object)null)
		{
			return;
		}
		Vector3 position = ((Component)mainCamera).transform.position;
		seesayObject.transform.position = Vector3.MoveTowards(seesayObject.transform.position, position, Plugin.SeesaySpeed.Value * Time.deltaTime);
		seesayObject.transform.rotation = ((Component)mainCamera).transform.rotation;
		if (IsFlashlightAimingAtSeesay(player))
		{
			TriggerFlashed();
			return;
		}
		float num = Vector3.Distance(seesayObject.transform.position, position);
		if (Plugin.EnableTrainSound.Value && num < 10f)
		{
			if ((Object)(object)trainClip != (Object)null && !trainAudioSource.isPlaying)
			{
				((Component)trainAudioSource).transform.position = seesayObject.transform.position;
				trainAudioSource.clip = trainClip;
				trainAudioSource.Play();
			}
		}
		else if (trainAudioSource.isPlaying)
		{
			trainAudioSource.Stop();
		}
		((Component)trainAudioSource).transform.position = seesayObject.transform.position;
		if (num < 0.5f)
		{
			TriggerScreamer();
		}
		((Component)flyingAudioSource).transform.position = seesayObject.transform.position;
	}

	private void TriggerScreamer()
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		currentState = SeesayState.Screamer;
		videoFinished = false;
		seesayObject.SetActive(false);
		string text = Path.Combine(modFolder, "Death.mp4");
		videoPlayer.url = "file://" + text;
		videoPlayer.Play();
		((Graphic)videoImage).color = new Color(1f, 1f, 1f, 1f);
		flyingAudioSource.Stop();
		trainAudioSource.Stop();
	}

	private void TriggerFlashed()
	{
		if ((Object)(object)flashedClip != (Object)null)
		{
			audioSource.clip = flashedClip;
			audioSource.Play();
		}
		isFlashed = true;
		flashedTimer = 0f;
		if ((Object)(object)flashedSprite != (Object)null)
		{
			spriteRenderer.sprite = flashedSprite;
		}
		flyingAudioSource.Stop();
	}

	private bool CheckFlashlightCondition(PlayerControllerB player)
	{
		GrabbableObject[] itemSlots = player.ItemSlots;
		foreach (GrabbableObject val in itemSlots)
		{
			if ((Object)(object)val != (Object)null && val is FlashlightItem)
			{
				return true;
			}
		}
		if ((Object)(object)player.currentlyHeldObjectServer != (Object)null && player.currentlyHeldObjectServer is FlashlightItem)
		{
			return true;
		}
		return false;
	}

	private bool IsFlashlightAimingAtSeesay(PlayerControllerB player)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: 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_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: 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_0169: 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_0177: Unknown result type (might be due to invalid IL or missing references)
		GrabbableObject[] itemSlots = player.ItemSlots;
		foreach (GrabbableObject val in itemSlots)
		{
			if (!((Object)(object)val != (Object)null))
			{
				continue;
			}
			FlashlightItem val2 = (FlashlightItem)(object)((val is FlashlightItem) ? val : null);
			if (val2 != null && ((GrabbableObject)val2).isBeingUsed)
			{
				if ((Object)(object)mainCamera == (Object)null)
				{
					return false;
				}
				Vector3 val3 = mainCamera.WorldToViewportPoint(seesayObject.transform.position);
				if (val3.z > 0f && val3.x > 0.2f && val3.x < 0.8f && val3.y > 0.2f && val3.y < 0.8f)
				{
					return true;
				}
			}
		}
		if ((Object)(object)player.currentlyHeldObjectServer != (Object)null)
		{
			GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer;
			FlashlightItem val4 = (FlashlightItem)(object)((currentlyHeldObjectServer is FlashlightItem) ? currentlyHeldObjectServer : null);
			if (val4 != null && ((GrabbableObject)val4).isBeingUsed)
			{
				if ((Object)(object)mainCamera == (Object)null)
				{
					return false;
				}
				Vector3 val5 = mainCamera.WorldToViewportPoint(seesayObject.transform.position);
				if (val5.z > 0f && val5.x > 0.2f && val5.x < 0.8f && val5.y > 0.2f && val5.y < 0.8f)
				{
					return true;
				}
			}
		}
		return false;
	}

	private void Appear(PlayerControllerB player)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		currentState = SeesayState.Following;
		timer = 0f;
		seesayObject.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
		followDuration = Random.Range(Plugin.MinFollowTime.Value, Plugin.MaxFollowTime.Value);
		if ((Object)(object)appearClip != (Object)null)
		{
			audioSource.clip = appearClip;
			audioSource.Play();
		}
		seesayObject.SetActive(true);
		if ((Object)(object)closedSprite != (Object)null)
		{
			spriteRenderer.sprite = closedSprite;
		}
	}

	private void Hide()
	{
		currentState = SeesayState.Hidden;
		timer = 0f;
		seesayObject.SetActive(false);
		isFlashed = false;
		isOnCooldown = true;
		cooldownTimer = 0f;
		cooldownTime = Plugin.CooldownTime.Value;
		flyingAudioSource.Stop();
		trainAudioSource.Stop();
	}

	public void ForceHide()
	{
		currentState = SeesayState.Hidden;
		timer = 0f;
		seesayObject.SetActive(false);
		isOnCooldown = false;
	}

	public void ResetSeesay()
	{
		currentState = SeesayState.Hidden;
		timer = 0f;
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
		seesayObject.SetActive(false);
		isOnCooldown = false;
		cooldownTimer = 0f;
	}

	private bool IsPlayerInGame()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (val.isPlayerDead)
		{
			return false;
		}
		if (StartOfRound.Instance?.currentLevel?.sceneName == "CompanyBuilding")
		{
			return false;
		}
		if ((Object)(object)TimeOfDay.Instance != (Object)null && TimeOfDay.Instance.timesFulfilledQuota < 1)
		{
			return false;
		}
		return !val.isInHangarShipRoom && (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipHasLanded;
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "Start")]
public class SeesayPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		if (((NetworkBehaviour)__instance).IsOwner && !((Object)(object)Object.FindObjectOfType<SeesayBehaviour>() != (Object)null))
		{
			int num = Random.Range(0, 100);
			if (num >= Plugin.SpawnChance.Value)
			{
				Debug.Log((object)$"Seesay Entity: не появится в этом раунде (бросок {num})");
				return;
			}
			GameObject val = new GameObject("SeesayManager");
			val.AddComponent<SeesayBehaviour>();
			Object.DontDestroyOnLoad((Object)(object)val);
			Debug.Log((object)"Seesay Entity: менеджер создан!");
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
public class SeesayDeathPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			SeesayBehaviour seesayBehaviour = Object.FindObjectOfType<SeesayBehaviour>();
			if ((Object)(object)seesayBehaviour != (Object)null)
			{
				seesayBehaviour.ForceHide();
			}
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "SpawnDeadAnimation")]
public class SeesayRespawnPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			SeesayBehaviour seesayBehaviour = Object.FindObjectOfType<SeesayBehaviour>();
			if ((Object)(object)seesayBehaviour != (Object)null)
			{
				seesayBehaviour.ResetSeesay();
			}
		}
	}
}

BepInEx/plugins/StemEntity.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using DozerEntity;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("StemEntity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("StemEntity")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("dea806e2-4ea2-4416-8557-a5243135a1f3")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace StemEntity;

[BepInPlugin("com.yourname.stementity", "Stem Entity", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	private readonly Harmony harmony = new Harmony("com.yourname.stementity");

	public static ConfigEntry<int> SpawnChance;

	public static ConfigEntry<float> MinSpawnTime;

	public static ConfigEntry<float> MaxSpawnTime;

	public static ConfigEntry<float> OpenEyeDuration;

	public static ConfigEntry<float> CooldownTime;

	public static ConfigEntry<float> OpeningPauseTime;

	public static ConfigEntry<float> CheckDelay;

	private void Awake()
	{
		SpawnChance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SpawnChance", 50, "Chance of Stem appearing each round (0-100)");
		MinSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MinSpawnTime", 30f, "Minimum time before Stem appears");
		MaxSpawnTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "MaxSpawnTime", 90f, "Maximum time before Stem appears");
		OpenEyeDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "OpenEyeDuration", 3f, "How long Stem stays with open eye");
		CooldownTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "CooldownTime", 60f, "Cooldown before Stem can appear again");
		OpeningPauseTime = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "OpeningPauseTime", 1f, "Pause duration at opening7");
		CheckDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "CheckDelay", 0.1f, "Delay before checking sprint condition");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Stem Entity loaded!");
		harmony.PatchAll();
	}
}
public class StemBehaviour : MonoBehaviour
{
	private enum StemState
	{
		Hidden,
		Opening,
		OpenEye
	}

	private List<List<GameObject>> vineChains = new List<List<GameObject>>();

	private float[] vineAngles = new float[8];

	private float[] vineCurves = new float[8];

	private bool deathAnimPlaying = false;

	private float deathTimer = 0f;

	private float vineGrowTimer = 0f;

	private int[] vineSegmentCounts = new int[8];

	private GameObject deathCanvas;

	private Vector2 stemScreenPos = Vector2.zero;

	private StemState currentState = StemState.Hidden;

	private float timer = 0f;

	private float nextAppearTime = 0f;

	private float shakeTimer = 0f;

	private float shakeSpeed = 0.05f;

	private Vector2 basePosition = new Vector2(-500f, -200f);

	private bool isOnCooldown = false;

	private float cooldownTimer = 0f;

	private float cooldownTime = 0f;

	private AudioSource audioSource;

	private AudioClip spawnClip;

	private AudioClip deathClip;

	private float animTimer = 0f;

	private int animFrame = 0;

	private bool animPaused = false;

	private float animPauseTimer = 0f;

	private float checkDelayTimer = 0f;

	private bool checkStarted = false;

	private GameObject rootObject;

	private Image eyeImage;

	private Sprite[] openingSprites = (Sprite[])(object)new Sprite[11];

	private Sprite vineSprite;

	private string modFolder;

	private void Start()
	{
		string[] directories = Directory.GetDirectories(Paths.PluginPath, "StemEntity", SearchOption.AllDirectories);
		modFolder = ((directories.Length != 0) ? directories[0] : Path.Combine(Paths.PluginPath, "StemEntity"));
		LoadSprites();
		CreateOverlay();
		CreateDeathCanvas();
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
		audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
		audioSource.loop = false;
		audioSource.playOnAwake = false;
		audioSource.volume = 1f;
		spawnClip = LoadAudioClip("spawn.mp3");
		deathClip = LoadAudioClip("death.mp3");
	}

	private AudioClip LoadAudioClip(string filename)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Stem Entity: звук не найден — " + text));
			return null;
		}
		WWW val = new WWW("file://" + text);
		try
		{
			while (!val.isDone)
			{
			}
			return val.GetAudioClip(false, false, (AudioType)13);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	private void LoadSprites()
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < 11; i++)
		{
			openingSprites[i] = LoadSprite($"opening{i + 1}.png");
		}
		Texture2D val = LoadTexture("vine.png");
		if ((Object)(object)val != (Object)null)
		{
			vineSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)1);
		}
	}

	private Texture2D LoadTexture(string filename)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		string path = Path.Combine(modFolder, filename);
		if (!File.Exists(path))
		{
			return null;
		}
		byte[] array = File.ReadAllBytes(path);
		Texture2D val = new Texture2D(2, 2);
		ImageConversion.LoadImage(val, array);
		return val;
	}

	private Sprite LoadSprite(string filename)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_0062: 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)
		string text = Path.Combine(modFolder, filename);
		if (!File.Exists(text))
		{
			Debug.LogError((object)("Stem Entity: файл не найден — " + text));
			return null;
		}
		byte[] array = File.ReadAllBytes(text);
		Texture2D val = new Texture2D(2, 2);
		ImageConversion.LoadImage(val, array);
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
	}

	private void Update()
	{
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if (currentState == StemState.Opening)
		{
			Shake();
		}
		if (deathAnimPlaying)
		{
			UpdateDeathAnim();
			if (deathTimer >= 1f)
			{
				deathAnimPlaying = false;
				deathCanvas.SetActive(false);
				PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)val2 != (Object)null)
				{
					val2.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 1, default(Vector3), false);
				}
				Hide();
			}
		}
		else if (isOnCooldown)
		{
			cooldownTimer += Time.deltaTime;
			if (cooldownTimer >= cooldownTime)
			{
				isOnCooldown = false;
				cooldownTimer = 0f;
				timer = 0f;
				nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
			}
		}
		else if (val.isPlayerDead)
		{
			ForceHide();
		}
		else
		{
			if (!IsPlayerInGame())
			{
				return;
			}
			timer += Time.deltaTime;
			switch (currentState)
			{
			case StemState.Hidden:
				if (timer >= nextAppearTime)
				{
					Appear();
				}
				break;
			case StemState.Opening:
				Shake();
				if (!IsScreenBusy())
				{
					AnimateOpening();
				}
				break;
			case StemState.OpenEye:
				if (!checkStarted)
				{
					checkDelayTimer += Time.deltaTime;
					if (checkDelayTimer >= Plugin.CheckDelay.Value)
					{
						checkStarted = true;
					}
				}
				else if (!IsPlayerSprinting(val))
				{
					TriggerDeath(val);
				}
				else if (timer >= Plugin.OpenEyeDuration.Value)
				{
					Hide();
				}
				break;
			}
		}
	}

	private bool IsScreenBusy()
	{
		GameObject val = GameObject.Find("DozerManager");
		if ((Object)(object)val != (Object)null)
		{
			DozerBehaviour component = val.GetComponent<DozerBehaviour>();
			GameObject val2 = GameObject.Find("DozerImage");
			if ((Object)(object)val2 != (Object)null && val2.activeSelf)
			{
				return true;
			}
		}
		GameObject val3 = GameObject.Find("LitanyRoot");
		if ((Object)(object)val3 != (Object)null && val3.activeSelf)
		{
			return true;
		}
		return false;
	}

	private void Shake()
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		shakeTimer += Time.deltaTime;
		if (shakeTimer >= shakeSpeed)
		{
			shakeTimer = 0f;
			float num = Random.Range(-5f, 5f);
			float num2 = Random.Range(-5f, 5f);
			rootObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(basePosition.x + num, basePosition.y + num2);
		}
	}

	private void CreateDeathCanvas()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		deathCanvas = new GameObject("StemDeathCanvas");
		Canvas val = deathCanvas.AddComponent<Canvas>();
		val.renderMode = (RenderMode)0;
		val.sortingOrder = 150;
		Object.DontDestroyOnLoad((Object)(object)deathCanvas);
		deathCanvas.SetActive(false);
		for (int i = 0; i < 8; i++)
		{
			vineAngles[i] = (float)i * 45f;
			vineChains.Add(new List<GameObject>());
		}
	}

	private GameObject CreateVineSegment(int vineIndex, int segmentIndex)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: 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)
		float num = vineAngles[vineIndex];
		float num2 = vineCurves[vineIndex];
		GameObject val = new GameObject($"Vine_{vineIndex}_{segmentIndex}");
		val.transform.SetParent(deathCanvas.transform, false);
		Image val2 = val.AddComponent<Image>();
		val2.sprite = vineSprite;
		RectTransform component = val.GetComponent<RectTransform>();
		component.anchorMin = new Vector2(0.5f, 0.5f);
		component.anchorMax = new Vector2(0.5f, 0.5f);
		component.sizeDelta = new Vector2(600f, 600f);
		float num3 = (num + num2 * (float)segmentIndex * 0.3f) * ((float)Math.PI / 180f);
		float num4 = (float)segmentIndex * 200f;
		float num5 = stemScreenPos.x + Mathf.Cos(num3) * num4;
		float num6 = stemScreenPos.y + Mathf.Sin(num3) * num4;
		component.anchoredPosition = new Vector2(num5, num6);
		float num7 = num + num2 * (float)segmentIndex * 0.3f;
		((Transform)component).localRotation = Quaternion.Euler(0f, 0f, num7 - 90f);
		return val;
	}

	private void UpdateDeathAnim()
	{
		deathTimer += Time.deltaTime;
		vineGrowTimer += Time.deltaTime;
		if (vineGrowTimer >= 0.06f)
		{
			vineGrowTimer = 0f;
			for (int i = 0; i < 8; i++)
			{
				int segmentIndex = vineSegmentCounts[i];
				GameObject item = CreateVineSegment(i, segmentIndex);
				vineChains[i].Add(item);
				vineSegmentCounts[i]++;
			}
		}
	}

	private void AnimateOpening()
	{
		if (animPaused)
		{
			animPauseTimer += Time.deltaTime;
			if (animPauseTimer >= Plugin.OpeningPauseTime.Value)
			{
				animPaused = false;
				animPauseTimer = 0f;
			}
			return;
		}
		animTimer += Time.deltaTime;
		if (animTimer >= 0.0667f)
		{
			animTimer = 0f;
			animFrame++;
			if (animFrame == 6)
			{
				animPaused = true;
				eyeImage.sprite = openingSprites[6];
			}
			else if (animFrame >= 10)
			{
				OpenEye();
			}
			else if ((Object)(object)openingSprites[animFrame] != (Object)null)
			{
				eyeImage.sprite = openingSprites[animFrame];
			}
		}
	}

	private void Appear()
	{
		if ((Object)(object)spawnClip != (Object)null)
		{
			audioSource.clip = spawnClip;
			audioSource.Play();
		}
		currentState = StemState.Opening;
		timer = 0f;
		animFrame = 0;
		animTimer = 0f;
		animPaused = false;
		rootObject.SetActive(true);
		if ((Object)(object)openingSprites[0] != (Object)null)
		{
			eyeImage.sprite = openingSprites[0];
		}
	}

	private void OpenEye()
	{
		currentState = StemState.OpenEye;
		timer = 0f;
		checkDelayTimer = 0f;
		checkStarted = false;
		if ((Object)(object)openingSprites[10] != (Object)null)
		{
			eyeImage.sprite = openingSprites[10];
		}
	}

	private void TriggerDeath(PlayerControllerB player)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		deathAnimPlaying = true;
		deathTimer = 0f;
		vineGrowTimer = 0f;
		if ((Object)(object)deathClip != (Object)null)
		{
			audioSource.clip = deathClip;
			audioSource.Play();
		}
		stemScreenPos = rootObject.GetComponent<RectTransform>().anchoredPosition;
		for (int i = 0; i < 8; i++)
		{
			vineCurves[i] = Random.Range(-15f, 15f);
			vineSegmentCounts[i] = 0;
			foreach (GameObject item in vineChains[i])
			{
				Object.Destroy((Object)(object)item);
			}
			vineChains[i].Clear();
		}
		deathCanvas.SetActive(true);
	}

	private void Hide()
	{
		currentState = StemState.Hidden;
		timer = 0f;
		rootObject.SetActive(false);
		isOnCooldown = true;
		cooldownTimer = 0f;
		cooldownTime = Plugin.CooldownTime.Value;
	}

	public void ForceHide()
	{
		currentState = StemState.Hidden;
		timer = 0f;
		rootObject.SetActive(false);
		isOnCooldown = false;
		if (deathAnimPlaying)
		{
			deathAnimPlaying = false;
			deathCanvas.SetActive(false);
		}
	}

	private bool IsPlayerSprinting(PlayerControllerB player)
	{
		return player.isSprinting;
	}

	private bool IsPlayerInGame()
	{
		PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (val.isPlayerDead)
		{
			return false;
		}
		if (StartOfRound.Instance?.currentLevel?.sceneName == "CompanyBuilding")
		{
			return false;
		}
		return !val.isInHangarShipRoom && (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipHasLanded;
	}

	public void ResetStem()
	{
		currentState = StemState.Hidden;
		timer = 0f;
		nextAppearTime = Random.Range(Plugin.MinSpawnTime.Value, Plugin.MaxSpawnTime.Value);
		rootObject.SetActive(false);
		isOnCooldown = false;
		cooldownTimer = 0f;
		deathAnimPlaying = false;
		deathCanvas.SetActive(false);
	}

	private void CreateOverlay()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: 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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: 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_00c2: Expected O, but got Unknown
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("StemCanvas");
		Canvas val2 = val.AddComponent<Canvas>();
		val2.renderMode = (RenderMode)0;
		val2.sortingOrder = 100;
		Object.DontDestroyOnLoad((Object)(object)val);
		rootObject = new GameObject("StemRoot");
		rootObject.transform.SetParent(val.transform, false);
		RectTransform val3 = rootObject.AddComponent<RectTransform>();
		val3.anchorMin = new Vector2(0.5f, 0.5f);
		val3.anchorMax = new Vector2(0.5f, 0.5f);
		val3.sizeDelta = new Vector2(600f, 600f);
		val3.anchoredPosition = new Vector2(-500f, -200f);
		GameObject val4 = new GameObject("StemEye");
		val4.transform.SetParent(rootObject.transform, false);
		eyeImage = val4.AddComponent<Image>();
		RectTransform component = val4.GetComponent<RectTransform>();
		component.anchorMin = Vector2.zero;
		component.anchorMax = Vector2.one;
		component.sizeDelta = Vector2.zero;
		rootObject.SetActive(false);
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "Start")]
public class StemPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		if (((NetworkBehaviour)__instance).IsOwner && !((Object)(object)Object.FindObjectOfType<StemBehaviour>() != (Object)null))
		{
			int num = Random.Range(0, 100);
			if (num >= Plugin.SpawnChance.Value)
			{
				Debug.Log((object)$"Stem Entity: не появится в этом раунде (бросок {num})");
				return;
			}
			GameObject val = new GameObject("StemManager");
			val.AddComponent<StemBehaviour>();
			Object.DontDestroyOnLoad((Object)(object)val);
			Debug.Log((object)"Stem Entity: менеджер создан!");
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
public class StemDeathPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			StemBehaviour stemBehaviour = Object.FindObjectOfType<StemBehaviour>();
			if ((Object)(object)stemBehaviour != (Object)null)
			{
				stemBehaviour.ForceHide();
			}
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "SpawnDeadAnimation")]
public class StemRespawnPatch
{
	private static void Postfix(PlayerControllerB __instance)
	{
		if (((NetworkBehaviour)__instance).IsOwner)
		{
			StemBehaviour stemBehaviour = Object.FindObjectOfType<StemBehaviour>();
			if ((Object)(object)stemBehaviour != (Object)null)
			{
				stemBehaviour.ResetStem();
			}
		}
	}
}