Decompiled source of YOURTAKINGTOOLONG v0.2.1

YOUR TAKING TOO LONG.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("UKMod template")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UKMod template")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3d018c2f-f5bc-47be-a844-3e9888579d1f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SRankStalker;

public class StalkerDefinition
{
	public string FolderName;

	public string FolderPath;

	public GameObject Prefab;

	public int SpawnRequirementIndex = 0;

	public float RequirementVariable = 50f;

	public float SpawnWeight = 1f;

	public float BaseSpeed = 5f;

	public float SpeedGain = 1f;

	public float MaxSpeed = 999999f;

	public float GracePeriod = 2f;

	public bool Parriable = true;

	public float ParryPushDistance = 15f;

	public float ParryPauseDuration = 1.5f;

	public KeyCode DebugKey = (KeyCode)287;

	public string StalkerName = "";

	public string SpawnLog = "";

	public string CatchLog = "";

	public string ParriedLog = "";

	public AudioClip SpawnClip;

	public AudioClip CatchClip;

	public AudioClip LoopClip;

	public AudioClip ParryClip;
}
[BepInPlugin("com.nico.yourtakingtoolong", "YOUR TAKING TOO LONG", "0.2.1")]
public class Plugin : BaseUnityPlugin
{
	public static Plugin Instance;

	public ManualLogSource log;

	public List<StalkerDefinition> Definitions = new List<StalkerDefinition>();

	private static Dictionary<string, AssetBundle> LoadedBundles = new Dictionary<string, AssetBundle>(StringComparer.OrdinalIgnoreCase);

	public static ConfigEntry<int> PunchHitboxLayer;

	private string StalkersRoot => Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "stalkers");

	private void Awake()
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		log = ((BaseUnityPlugin)this).Logger;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"YOUR TAKING TOO LONG");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"RAHAHAHAHAHAHAHA");
		LoadAllDefinitions();
		new Harmony("com.nico.yourtakingtoolong").PatchAll();
		PunchHitboxLayer = ((BaseUnityPlugin)this).Config.Bind<int>("Parry", "Punch Hitbox Layer", 14, "Layer index the parry hitbox sits on. Must be 14 to match the layer mask (16384 = 1<<14) the game's own Punch code checks - change only if that turns out to be wrong for your game version.");
	}

	public void ReloadAfterDelay(float delay)
	{
		((MonoBehaviour)this).StartCoroutine(ReloadCoroutine(delay));
	}

	private IEnumerator ReloadCoroutine(float delay)
	{
		yield return (object)new WaitForSeconds(delay);
		SceneHelper.LoadScene(SceneHelper.CurrentScene, false);
	}

	private void LoadAllDefinitions()
	{
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		if (!Directory.Exists(StalkersRoot))
		{
			log.LogWarning((object)("[SRankStalker] no 'stalkers' folder found at " + StalkersRoot + " - no stalkers will ever spawn."));
			return;
		}
		string[] directories = Directory.GetDirectories(StalkersRoot);
		foreach (string text in directories)
		{
			string fileName = Path.GetFileName(text);
			StalkerDefinition def = new StalkerDefinition
			{
				FolderName = fileName,
				FolderPath = text
			};
			ParseConfig(Path.Combine(text, "stalker.cfg"), def);
			GameObject val = LoadFromAssetBundle(text);
			if ((Object)(object)val == (Object)null)
			{
				val = BuildStalkerTemplate();
			}
			((Object)val).name = fileName;
			def.Prefab = val;
			((MonoBehaviour)this).StartCoroutine(LoadClipFromPath(Path.Combine(text, "spawn.ogg"), delegate(AudioClip c)
			{
				def.SpawnClip = c;
			}));
			((MonoBehaviour)this).StartCoroutine(LoadClipFromPath(Path.Combine(text, "catch.ogg"), delegate(AudioClip c)
			{
				def.CatchClip = c;
			}));
			((MonoBehaviour)this).StartCoroutine(LoadClipFromPath(Path.Combine(text, "loop.ogg"), delegate(AudioClip c)
			{
				def.LoopClip = c;
			}));
			((MonoBehaviour)this).StartCoroutine(LoadClipFromPath(Path.Combine(text, "parry.ogg"), delegate(AudioClip c)
			{
				def.ParryClip = c;
			}));
			Definitions.Add(def);
			log.LogInfo((object)string.Format("[SRankStalker] loaded definition '{0}' (name: {1}, requirement {2}/{3}, weight {4}, debug key {5})", def.FolderName, string.IsNullOrEmpty(def.StalkerName) ? "<none set>" : def.StalkerName, def.SpawnRequirementIndex, def.RequirementVariable, def.SpawnWeight, def.DebugKey));
		}
		if (Definitions.Count == 0)
		{
			log.LogWarning((object)"[SRankStalker] the 'stalkers' folder exists but has no subfolders in it - no stalkers will ever spawn.");
		}
	}

	private void ParseConfig(string path, StalkerDefinition def)
	{
		//IL_0437: Unknown result type (might be due to invalid IL or missing references)
		//IL_043c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0441: Unknown result type (might be due to invalid IL or missing references)
		if (!File.Exists(path))
		{
			log.LogWarning((object)("[SRankStalker] no stalker.cfg found for '" + def.FolderName + "' - using defaults."));
			return;
		}
		string[] array = File.ReadAllLines(path);
		foreach (string text in array)
		{
			string text2 = text.Trim();
			if (text2.Length == 0 || text2.StartsWith("#"))
			{
				continue;
			}
			int num = text2.IndexOf(':');
			if (num >= 0)
			{
				string text3 = text2.Substring(0, num).Trim().ToLowerInvariant()
					.Replace(" ", "");
				string text4 = StripQuotes(text2.Substring(num + 1).Trim());
				switch (text3)
				{
				case "spawnrequirement":
					def.SpawnRequirementIndex = ParseIntSafe(text4, def.SpawnRequirementIndex);
					continue;
				case "requirementvariable":
					def.RequirementVariable = ParseFloatSafe(text4, def.RequirementVariable);
					continue;
				case "spawnweight":
					def.SpawnWeight = ParseFloatSafe(text4, def.SpawnWeight);
					continue;
				case "basespeed":
					def.BaseSpeed = ParseFloatSafe(text4, def.BaseSpeed);
					continue;
				case "speedgain":
					def.SpeedGain = ParseFloatSafe(text4, def.SpeedGain);
					continue;
				case "maxspeed":
					def.MaxSpeed = ParseFloatSafe(text4, def.MaxSpeed);
					continue;
				case "graceperiod":
					def.GracePeriod = ParseFloatSafe(text4, def.GracePeriod);
					continue;
				case "parriable":
					def.Parriable = ParseBoolSafe(text4, def.Parriable);
					continue;
				case "parrypushdistance":
					def.ParryPushDistance = ParseFloatSafe(text4, def.ParryPushDistance);
					continue;
				case "parrypauseduration":
					def.ParryPauseDuration = ParseFloatSafe(text4, def.ParryPauseDuration);
					continue;
				case "debugkey":
					def.DebugKey = ParseKeySafe(text4, def.DebugKey);
					continue;
				case "stalkername":
					def.StalkerName = text4;
					continue;
				case "spawnlog":
					def.SpawnLog = text4;
					continue;
				case "catchlog":
					def.CatchLog = text4;
					continue;
				case "parriedlog":
					def.ParriedLog = text4;
					continue;
				}
				log.LogWarning((object)("[SRankStalker] unknown config key '" + text3 + "' in '" + def.FolderName + "/stalker.cfg' - ignored."));
			}
		}
	}

	private string StripQuotes(string v)
	{
		if (v.Length >= 2)
		{
			char c = v[0];
			char c2 = v[v.Length - 1];
			bool flag = c == '"' && c2 == '"';
			bool flag2 = c == '\'' && c2 == '\'';
			bool flag3 = c == '“' && c2 == '”';
			if (flag || flag2 || flag3)
			{
				return v.Substring(1, v.Length - 2);
			}
		}
		return v;
	}

	private int ParseIntSafe(string v, int fallback)
	{
		int result;
		return int.TryParse(v, out result) ? result : fallback;
	}

	private float ParseFloatSafe(string v, float fallback)
	{
		float result;
		return float.TryParse(v, NumberStyles.Float, CultureInfo.InvariantCulture, out result) ? result : fallback;
	}

	private bool ParseBoolSafe(string v, bool fallback)
	{
		bool result;
		return bool.TryParse(v, out result) ? result : fallback;
	}

	private KeyCode ParseKeySafe(string v, KeyCode fallback)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		KeyCode result;
		return Enum.TryParse<KeyCode>(v, ignoreCase: true, out result) ? result : fallback;
	}

	private IEnumerator LoadClipFromPath(string path, Action<AudioClip> onLoaded)
	{
		if (!File.Exists(path))
		{
			log.LogWarning((object)("[SRankStalker] no file found at " + path + " - that sound won't play until it's added."));
			yield break;
		}
		UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip("file://" + path, (AudioType)14);
		try
		{
			yield return www.SendWebRequest();
			if ((int)www.result != 1)
			{
				log.LogWarning((object)("[SRankStalker] failed to load " + path + ": " + www.error));
				yield break;
			}
			AudioClip clip = DownloadHandlerAudioClip.GetContent(www);
			log.LogInfo((object)$"[SRankStalker] loaded {path} ok - length {clip.length:0.00}s, {clip.channels} channel(s), {clip.frequency}Hz");
			onLoaded(clip);
		}
		finally
		{
			((IDisposable)www)?.Dispose();
		}
	}

	private GameObject LoadFromAssetBundle(string folderDir)
	{
		string text = null;
		string[] files = Directory.GetFiles(folderDir);
		foreach (string path in files)
		{
			string text2 = Path.GetExtension(path).ToLowerInvariant();
			string text3 = Path.GetFileName(path).ToLowerInvariant();
			switch (text2)
			{
			default:
				if (text3.EndsWith(".meta") || text3.EndsWith(".manifest"))
				{
					continue;
				}
				break;
			case ".cfg":
			case ".png":
			case ".ogg":
			case ".mp3":
			case ".wav":
				continue;
			}
			text = Path.GetFullPath(path);
			break;
		}
		if (string.IsNullOrEmpty(text))
		{
			string stalkersRoot = StalkersRoot;
			if (Directory.Exists(stalkersRoot))
			{
				string[] files2 = Directory.GetFiles(stalkersRoot);
				foreach (string path2 in files2)
				{
					string text4 = Path.GetExtension(path2).ToLowerInvariant();
					string text5 = Path.GetFileName(path2).ToLowerInvariant();
					string fullPath;
					switch (text4)
					{
					default:
					{
						if (text5.EndsWith(".meta") || text5.EndsWith(".manifest"))
						{
							continue;
						}
						fullPath = Path.GetFullPath(path2);
						AssetBundle orLoadBundle = GetOrLoadBundle(fullPath);
						if (!((Object)(object)orLoadBundle != (Object)null))
						{
							continue;
						}
						string[] allAssetNames = orLoadBundle.GetAllAssetNames();
						if (!allAssetNames.Any((string n) => n.ToLowerInvariant().Contains("stalker") && n.ToLowerInvariant().EndsWith(".prefab")) && !((Object)(object)orLoadBundle.LoadAsset<GameObject>("stalker") != (Object)null))
						{
							continue;
						}
						break;
					}
					case ".cfg":
					case ".png":
					case ".ogg":
					case ".mp3":
					case ".wav":
						continue;
					}
					text = fullPath;
					log.LogInfo((object)("[SRankStalker] Found root shared bundle containing 'stalker' prefab for folder '" + Path.GetFileName(folderDir) + "': " + Path.GetFileName(text)));
					break;
				}
			}
		}
		if (string.IsNullOrEmpty(text))
		{
			log.LogInfo((object)("[SRankStalker] No custom asset bundle found for '" + Path.GetFileName(folderDir) + "'. Using procedural fallback template."));
			return null;
		}
		AssetBundle orLoadBundle2 = GetOrLoadBundle(text);
		if ((Object)(object)orLoadBundle2 == (Object)null)
		{
			return null;
		}
		string[] allAssetNames2 = orLoadBundle2.GetAllAssetNames();
		string[] array = allAssetNames2;
		foreach (string text6 in array)
		{
			log.LogInfo((object)("[SRankStalker] Bundle Internal Asset -> '" + text6 + "'"));
		}
		if (allAssetNames2.Length == 0)
		{
			log.LogError((object)"[SRankStalker] Asset bundle contains no assets!");
			return null;
		}
		string text7 = allAssetNames2.FirstOrDefault((string n) => n.ToLowerInvariant().EndsWith("stalker.prefab")) ?? allAssetNames2.FirstOrDefault((string n) => n.ToLowerInvariant().EndsWith(".prefab")) ?? allAssetNames2[0];
		log.LogInfo((object)("[SRankStalker] Loading target asset from bundle: '" + text7 + "'"));
		GameObject val = orLoadBundle2.LoadAsset<GameObject>(text7);
		if ((Object)(object)val == (Object)null)
		{
			Object val2 = orLoadBundle2.LoadAsset(text7);
			GameObject val3 = (GameObject)(object)((val2 is GameObject) ? val2 : null);
			if (val3 != null)
			{
				val = val3;
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			log.LogError((object)("[SRankStalker] Bundle loaded, but failed to extract a valid GameObject from '" + text7 + "'."));
			return null;
		}
		return val;
	}

	private AssetBundle GetOrLoadBundle(string fullPath)
	{
		if (LoadedBundles.TryGetValue(fullPath, out var value))
		{
			return value;
		}
		log.LogInfo((object)("[SRankStalker] Attempting to load bundle from file: " + fullPath));
		AssetBundle val = AssetBundle.LoadFromFile(fullPath);
		if ((Object)(object)val == (Object)null)
		{
			log.LogError((object)("[SRankStalker] Failed to load asset bundle from '" + fullPath + "'."));
			return null;
		}
		LoadedBundles[fullPath] = val;
		return val;
	}

	private GameObject BuildStalkerTemplate()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		GameObject val = new GameObject("StalkerTemplate");
		val.SetActive(false);
		val.AddComponent<SpriteRenderer>();
		SphereCollider val2 = val.AddComponent<SphereCollider>();
		((Collider)val2).isTrigger = true;
		val2.radius = 1f;
		return val;
	}

	public static void ApplySpriteFromFile(GameObject target, string imgPath)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		if (File.Exists(imgPath))
		{
			byte[] array = File.ReadAllBytes(imgPath);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			Sprite sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			SpriteRenderer[] componentsInChildren = target.GetComponentsInChildren<SpriteRenderer>(true);
			SpriteRenderer[] array2 = componentsInChildren;
			foreach (SpriteRenderer val2 in array2)
			{
				val2.sprite = sprite;
			}
		}
	}
}
public static class PluginInfo
{
	public const string GUID = "com.nico.yourtakingtoolong";

	public const string NAME = "YOUR TAKING TOO LONG";

	public const string VERSION = "0.2.1";
}
public static class SRankTimes
{
	public static readonly HashSet<string> Blacklist = new HashSet<string> { "uk_construct", "Endless", "MainMenu" };

	public static bool TryGetFullTime(out float fullTime)
	{
		fullTime = 0f;
		if (Blacklist.Contains(SceneHelper.CurrentScene))
		{
			return false;
		}
		int[] timeRanks = MonoSingleton<StatsManager>.Instance.timeRanks;
		if (timeRanks == null || timeRanks.Length == 0)
		{
			return false;
		}
		fullTime = timeRanks[^1];
		return fullTime > 0f;
	}
}
[HarmonyPatch(typeof(NewMovement), "Update")]
public static class StalkerSpawnController
{
	private static string lastSeenScene;

	private static HashSet<(int, float)> firedGroups = new HashSet<(int, float)>();

	[HarmonyPostfix]
	public static void Postfix(NewMovement __instance)
	{
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		if (SceneHelper.CurrentScene != lastSeenScene)
		{
			lastSeenScene = SceneHelper.CurrentScene;
			firedGroups.Clear();
			if ((Object)(object)Stalker.Instance != (Object)null)
			{
				Stalker.Instance.Despawn();
			}
		}
		if (!MonoSingleton<StatsManager>.Instance.timer || ((Component)MonoSingleton<FinalRank>.Instance).gameObject.activeSelf || __instance.dead)
		{
			if ((Object)(object)Stalker.Instance != (Object)null)
			{
				Stalker.Instance.Despawn();
			}
		}
		else
		{
			if ((Object)(object)Stalker.Instance != (Object)null)
			{
				return;
			}
			float fullTime;
			bool flag = SRankTimes.TryGetFullTime(out fullTime);
			if (!flag)
			{
				fullTime = 120f;
			}
			foreach (StalkerDefinition definition in Plugin.Instance.Definitions)
			{
				if (Input.GetKeyDown(definition.DebugKey))
				{
					SpawnStalker(definition, __instance, fullTime);
					firedGroups.Add((definition.SpawnRequirementIndex, definition.RequirementVariable));
					return;
				}
			}
			IEnumerable<IGrouping<(int, float), StalkerDefinition>> enumerable = from d in Plugin.Instance.Definitions
				where d.SpawnRequirementIndex == 0
				group d by (SpawnRequirementIndex: d.SpawnRequirementIndex, RequirementVariable: d.RequirementVariable);
			foreach (IGrouping<(int, float), StalkerDefinition> item in enumerable)
			{
				if (!firedGroups.Contains(item.Key))
				{
					float num = fullTime * (item.Key.Item2 / 100f);
					if (flag && MonoSingleton<StatsManager>.Instance.seconds >= num)
					{
						StalkerDefinition def = WeightedPick(item.ToList());
						SpawnStalker(def, __instance, fullTime);
						firedGroups.Add(item.Key);
						break;
					}
				}
			}
		}
	}

	private static StalkerDefinition WeightedPick(List<StalkerDefinition> defs)
	{
		float num = defs.Sum((StalkerDefinition d) => Mathf.Max(0f, d.SpawnWeight));
		if (num <= 0f)
		{
			return defs[Random.Range(0, defs.Count)];
		}
		float num2 = Random.Range(0f, num);
		float num3 = 0f;
		foreach (StalkerDefinition def in defs)
		{
			num3 += Mathf.Max(0f, def.SpawnWeight);
			if (num2 <= num3)
			{
				return def;
			}
		}
		return defs[defs.Count - 1];
	}

	private static void SpawnStalker(StalkerDefinition def, NewMovement player, float fullSRankTime)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: 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_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Expected O, but got Unknown
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)def.Prefab == (Object)null)
		{
			Plugin.Instance.log.LogWarning((object)("[SRankStalker] '" + def.FolderName + "' has no prefab set, skipping spawn."));
			return;
		}
		Vector3 val = -((Component)player).transform.forward;
		Vector3 val2 = ((Component)player).transform.position + val * 40f + Vector3.up * 5f;
		GameObject val3 = Object.Instantiate<GameObject>(def.Prefab, val2, Quaternion.identity);
		val3.SetActive(true);
		Plugin.ApplySpriteFromFile(val3, Path.Combine(def.FolderPath, "stalker.png"));
		Stalker stalker = val3.AddComponent<Stalker>();
		stalker.Def = def;
		stalker.fullSRankTime = fullSRankTime;
		((Component)stalker).transform.position = val2;
		if ((Object)(object)def.SpawnClip != (Object)null)
		{
			GameObject val4 = new GameObject("Stalker Spawn Sound");
			val4.transform.position = val2;
			AudioSource val5 = val4.AddComponent<AudioSource>();
			val5.clip = def.SpawnClip;
			val5.volume = 5f;
			val5.spatialBlend = 1f;
			val5.minDistance = 20f;
			val5.maxDistance = 200f;
			val5.playOnAwake = false;
			((Behaviour)val5).enabled = true;
			val5.Play();
			Object.Destroy((Object)(object)val4, val5.clip.length);
		}
		if (!string.IsNullOrEmpty(def.StalkerName))
		{
			Plugin.Instance.log.LogInfo((object)$"Spawned {def.StalkerName} with index {def.SpawnRequirementIndex}");
			if (!string.IsNullOrEmpty(def.SpawnLog))
			{
				Plugin.Instance.log.LogInfo((object)def.SpawnLog);
			}
		}
		else
		{
			Plugin.Instance.log.LogWarning((object)("[SRankStalker] '" + def.FolderName + "' has no Stalker name set - skipping its spawn log."));
		}
	}
}
public class Stalker : MonoBehaviour
{
	public static Stalker Instance;

	public StalkerDefinition Def;

	public float fullSRankTime;

	private float spawnGracePeriod;

	private Vector3 parryVelocity;

	private bool parryMoving;

	private AudioSource loopSource;

	private float lifetime;

	private bool initialized;

	private bool parrying;

	private bool staggered;

	private float staggerTimer;

	private bool killing;

	private void Awake()
	{
		Instance = this;
	}

	private void Start()
	{
		if (Def == null)
		{
			Plugin.Instance.log.LogError((object)"[SRankStalker] Stalker.Start() ran with no Def set - despawning.");
			Despawn();
			return;
		}
		lifetime = 0f;
		spawnGracePeriod = Def.GracePeriod;
		if ((Object)(object)Def.LoopClip != (Object)null)
		{
			loopSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			loopSource.clip = Def.LoopClip;
			loopSource.loop = true;
			loopSource.playOnAwake = false;
			loopSource.spatialBlend = 1f;
			loopSource.minDistance = 15f;
			loopSource.maxDistance = 150f;
			loopSource.volume = 2f;
			((Behaviour)loopSource).enabled = true;
			loopSource.Play();
		}
		if (Def.Parriable)
		{
			SetUpParryReceiver();
		}
		initialized = true;
	}

	private void SetUpParryReceiver()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Expected O, but got Unknown
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Expected O, but got Unknown
		try
		{
			GameObject val = new GameObject("StalkerParryHitbox");
			val.transform.SetParent(((Component)this).transform, false);
			int layer = ((Plugin.PunchHitboxLayer != null) ? Plugin.PunchHitboxLayer.Value : 14);
			val.layer = layer;
			SphereCollider val2 = val.AddComponent<SphereCollider>();
			((Collider)val2).isTrigger = true;
			val2.radius = 1.2f;
			ParryReceiver val3 = val.AddComponent<ParryReceiver>();
			val3.parryHeal = true;
			val3.disappearOnParry = false;
			val3.onParry = new UnityEvent();
			val3.onParry.AddListener(new UnityAction(OnRealParry));
		}
		catch (Exception arg)
		{
			Plugin.Instance.log.LogError((object)$"[SRankStalker] SetUpParryReceiver failed: {arg}");
		}
	}

	private void Update()
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: 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_0183: Unknown result type (might be due to invalid IL or missing references)
		if (!initialized)
		{
			return;
		}
		Transform transform = ((Component)MonoSingleton<NewMovement>.Instance).transform;
		if (spawnGracePeriod > 0f)
		{
			spawnGracePeriod -= Time.deltaTime;
			if ((Object)(object)Camera.current != (Object)null)
			{
				((Component)this).transform.rotation = Quaternion.LookRotation(((Component)Camera.current).transform.position - ((Component)this).transform.position);
			}
		}
		else if (parryMoving)
		{
			Transform transform2 = ((Component)this).transform;
			transform2.position += parryVelocity * Time.deltaTime;
			parryVelocity = Vector3.Lerp(parryVelocity, Vector3.zero, Time.deltaTime * 8f);
			if (((Vector3)(ref parryVelocity)).magnitude < 0.1f)
			{
				parryVelocity = Vector3.zero;
				parryMoving = false;
			}
		}
		else if (staggered)
		{
			staggerTimer -= Time.deltaTime;
			if (staggerTimer <= 0f)
			{
				staggered = false;
			}
			if ((Object)(object)Camera.current != (Object)null)
			{
				((Component)this).transform.rotation = Quaternion.LookRotation(((Component)Camera.current).transform.position - ((Component)this).transform.position);
			}
		}
		else
		{
			lifetime += Time.deltaTime;
			float num = Def.BaseSpeed + lifetime * Def.SpeedGain;
			num = Mathf.Clamp(num, Def.BaseSpeed, Def.MaxSpeed);
			((Component)this).transform.position = Vector3.MoveTowards(((Component)this).transform.position, transform.position, num * Time.deltaTime);
			if ((Object)(object)Camera.current != (Object)null)
			{
				((Component)this).transform.rotation = Quaternion.LookRotation(((Component)Camera.current).transform.position - ((Component)this).transform.position);
			}
		}
	}

	private void OnRealParry()
	{
		if (!parrying)
		{
			parrying = true;
			((MonoBehaviour)this).StartCoroutine(ParrySequence());
		}
	}

	private IEnumerator ParrySequence()
	{
		Transform player = ((Component)MonoSingleton<NewMovement>.Instance).transform;
		Vector3 val = ((Component)this).transform.position - player.position;
		Vector3 pushDir = ((Vector3)(ref val)).normalized;
		parryVelocity = pushDir * Def.ParryPushDistance / 0.15f;
		parryMoving = true;
		if ((Object)(object)Def.ParryClip != (Object)null)
		{
			GameObject soundObj = new GameObject("Stalker Parry Sound");
			soundObj.transform.position = ((Component)this).transform.position;
			AudioSource source = soundObj.AddComponent<AudioSource>();
			source.clip = Def.ParryClip;
			source.volume = 5f;
			source.spatialBlend = 1f;
			source.minDistance = 15f;
			source.maxDistance = 150f;
			source.playOnAwake = false;
			((Behaviour)source).enabled = true;
			source.Play();
			Object.Destroy((Object)(object)soundObj, source.clip.length);
		}
		if (!string.IsNullOrEmpty(Def.ParriedLog))
		{
			Plugin.Instance.log.LogInfo((object)Def.ParriedLog);
		}
		staggered = true;
		staggerTimer = Def.ParryPauseDuration;
		parrying = false;
		yield break;
	}

	private void OnTriggerEnter(Collider other)
	{
		if (!(spawnGracePeriod > 0f) && !staggered && !parrying && ((Component)other).CompareTag("Player"))
		{
			((MonoBehaviour)this).StartCoroutine(KillPlayer());
		}
	}

	private void OnTriggerStay(Collider other)
	{
		if (!(spawnGracePeriod > 0f) && !staggered && !parrying && ((Component)other).CompareTag("Player"))
		{
			((MonoBehaviour)this).StartCoroutine(KillPlayer());
		}
	}

	private IEnumerator KillPlayer()
	{
		if (!killing)
		{
			killing = true;
			if ((Object)(object)loopSource != (Object)null)
			{
				loopSource.Stop();
			}
			if ((Object)(object)Def.CatchClip != (Object)null)
			{
				GameObject soundObj = new GameObject("Stalker Catch Sound");
				soundObj.transform.position = ((Component)this).transform.position;
				AudioSource source = soundObj.AddComponent<AudioSource>();
				source.clip = Def.CatchClip;
				source.volume = 20f;
				source.spatialBlend = 1f;
				source.minDistance = 15f;
				source.maxDistance = 150f;
				source.playOnAwake = false;
				((Behaviour)source).enabled = true;
				source.Play();
				Object.Destroy((Object)(object)soundObj, source.clip.length);
			}
			if (!string.IsNullOrEmpty(Def.CatchLog))
			{
				Plugin.Instance.log.LogInfo((object)Def.CatchLog);
			}
			MonoSingleton<NewMovement>.Instance.GetHurt(999, false, 1f, false, false, 1f, false);
			Plugin.Instance.ReloadAfterDelay(1f);
		}
		yield break;
	}

	public void Despawn()
	{
		Instance = null;
		Object.Destroy((Object)(object)((Component)this).gameObject);
	}
}