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.Logging;
using HarmonyLib;
using UnityEngine;
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;
[BepInPlugin("com.nico.yourtakingtoolong", "YOUR TAKING TOO LONG", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
public static Plugin Instance;
public ManualLogSource log;
public GameObject stalkerPrefab;
public AudioClip spawnSound;
public AudioClip catchSound;
public KeyCode debugSpawnKey = (KeyCode)287;
private void Awake()
{
//IL_007b: 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 is loaded!");
stalkerPrefab = LoadFromAssetBundle() ?? BuildStalkerTemplate();
((MonoBehaviour)this).StartCoroutine(LoadClip("spawn.ogg", delegate(AudioClip clip)
{
spawnSound = clip;
}));
((MonoBehaviour)this).StartCoroutine(LoadClip("catch.ogg", delegate(AudioClip clip)
{
catchSound = clip;
}));
new Harmony("com.nico.yourtakingtoolong").PatchAll();
}
private IEnumerator LoadClip(string fileName, Action<AudioClip> onLoaded)
{
string path = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), fileName);
if (!File.Exists(path))
{
log.LogWarning((object)("[SRankStalker] no " + fileName + " 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 " + fileName + ": " + www.error));
yield break;
}
AudioClip clip = DownloadHandlerAudioClip.GetContent(www);
log.LogInfo((object)$"[SRankStalker] loaded {fileName} ok - length {clip.length:0.00}s, {clip.channels} channel(s), {clip.frequency}Hz");
onLoaded(clip);
}
finally
{
((IDisposable)www)?.Dispose();
}
}
private GameObject LoadFromAssetBundle()
{
string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "stalker");
if (!File.Exists(text))
{
log.LogInfo((object)("[SRankStalker] no bundle found at " + text + ", using the placeholder template."));
return null;
}
AssetBundle val = AssetBundle.LoadFromFile(text);
if ((Object)(object)val == (Object)null)
{
log.LogWarning((object)"[SRankStalker] found a bundle file but it failed to load - usually means it was built with a Unity version that doesn't match the game (needs 2022.3.x to match ULTRAKILL's current engine).");
return null;
}
GameObject val2 = val.LoadAsset<GameObject>("Stalker");
if ((Object)(object)val2 == (Object)null)
{
log.LogWarning((object)"[SRankStalker] bundle loaded, but no asset named 'Stalker' was found in it. Check the GameObject's name in Unity.");
return null;
}
return val2;
}
private GameObject BuildStalkerTemplate()
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "stalker.png");
GameObject val = new GameObject("StalkerTemplate");
val.SetActive(false);
SpriteRenderer val2 = val.AddComponent<SpriteRenderer>();
if (File.Exists(text))
{
val2.sprite = LoadSpriteFromFile(text);
}
else
{
log.LogWarning((object)("[SRankStalker] no stalker.png found at " + text + " - spawning an invisible entity. Drop an image there."));
}
SphereCollider val3 = val.AddComponent<SphereCollider>();
((Collider)val3).isTrigger = true;
val3.radius = 1f;
return val;
}
private Sprite LoadSpriteFromFile(string path)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
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), 100f);
}
}
public static class PluginInfo
{
public const string GUID = "com.nico.yourtakingtoolong";
public const string NAME = "YOUR TAKING TOO LONG";
public const string VERSION = "0.1.0";
}
public static class SRankTimes
{
public static readonly HashSet<string> Blacklist = new HashSet<string> { "uk_construct", "Endless", "MainMenu" };
public static bool TryGetHalfTime(out float halfTime)
{
halfTime = 0f;
if (Blacklist.Contains(SceneHelper.CurrentScene))
{
return false;
}
int[] timeRanks = MonoSingleton<StatsManager>.Instance.timeRanks;
if (timeRanks == null || timeRanks.Length == 0)
{
return false;
}
float num = timeRanks[^1];
if (num <= 0f)
{
return false;
}
halfTime = num / 2f;
return true;
}
}
[HarmonyPatch(typeof(NewMovement), "Update")]
public static class StalkerSpawnController
{
private static bool spawnedThisLevel;
private static string lastSeenScene;
[HarmonyPostfix]
public static void Postfix(NewMovement __instance)
{
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
if (SceneHelper.CurrentScene != lastSeenScene)
{
lastSeenScene = SceneHelper.CurrentScene;
spawnedThisLevel = false;
if ((Object)(object)Stalker.Instance != (Object)null)
{
Stalker.Instance.Despawn();
}
}
if (!MonoSingleton<StatsManager>.Instance.timer || ((Component)MonoSingleton<FinalRank>.Instance).gameObject.activeSelf || __instance.dead)
{
spawnedThisLevel = false;
if ((Object)(object)Stalker.Instance != (Object)null)
{
Stalker.Instance.Despawn();
}
}
else
{
if (spawnedThisLevel || (Object)(object)Stalker.Instance != (Object)null)
{
return;
}
bool keyDown = Input.GetKeyDown(Plugin.Instance.debugSpawnKey);
if (!SRankTimes.TryGetHalfTime(out var halfTime))
{
if (keyDown)
{
SpawnStalker(__instance, 120f);
}
}
else if (keyDown || MonoSingleton<StatsManager>.Instance.seconds >= halfTime)
{
SpawnStalker(__instance, halfTime * 2f);
spawnedThisLevel = true;
}
}
}
private static void SpawnStalker(NewMovement player, float fullSRankTime)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: 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_005f: 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_0069: 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_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Expected O, but got Unknown
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Plugin.Instance.stalkerPrefab == (Object)null)
{
Plugin.Instance.log.LogWarning((object)"[SRankStalker] stalkerPrefab is not set - did you wire up your asset bundle in Plugin.Awake?");
return;
}
Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * -15f + Vector3.up * 2f;
GameObject val2 = Object.Instantiate<GameObject>(Plugin.Instance.stalkerPrefab, val, Quaternion.identity);
val2.SetActive(true);
Stalker stalker = val2.AddComponent<Stalker>();
stalker.fullSRankTime = fullSRankTime;
if ((Object)(object)Plugin.Instance.spawnSound != (Object)null)
{
GameObject val3 = new GameObject("Stalker Spawn Sound");
val3.transform.position = val;
AudioSource val4 = val3.AddComponent<AudioSource>();
val4.clip = Plugin.Instance.spawnSound;
val4.volume = 5f;
val4.spatialBlend = 1f;
val4.minDistance = 20f;
val4.maxDistance = 200f;
val4.playOnAwake = false;
val4.Play();
Object.Destroy((Object)(object)val3, val4.clip.length);
}
}
}
public class Stalker : MonoBehaviour
{
public static Stalker Instance;
public float fullSRankTime;
public float baseSpeed = 12f;
public float maxSpeed = 30f;
private bool killing;
private void Awake()
{
Instance = this;
}
private void Update()
{
//IL_0057: 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)
//IL_0069: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
Transform transform = ((Component)MonoSingleton<NewMovement>.Instance).transform;
float num = fullSRankTime - MonoSingleton<StatsManager>.Instance.seconds;
float num2 = Mathf.Clamp01(1f - num / (fullSRankTime / 2f));
float num3 = Mathf.Lerp(baseSpeed, maxSpeed, num2);
((Component)this).transform.position = Vector3.MoveTowards(((Component)this).transform.position, transform.position, num3 * 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 OnTriggerEnter(Collider other)
{
if (((Component)other).CompareTag("Player"))
{
((MonoBehaviour)this).StartCoroutine(KillPlayer());
}
}
private void OnTriggerStay(Collider other)
{
if (((Component)other).CompareTag("Player"))
{
((MonoBehaviour)this).StartCoroutine(KillPlayer());
}
}
private IEnumerator KillPlayer()
{
if (!killing)
{
killing = true;
if ((Object)(object)Plugin.Instance.catchSound != (Object)null)
{
GameObject soundObj = new GameObject("Stalker Catch Sound");
soundObj.transform.position = ((Component)this).transform.position;
AudioSource source = soundObj.AddComponent<AudioSource>();
source.clip = Plugin.Instance.catchSound;
source.volume = 20f;
source.spatialBlend = 1f;
source.minDistance = 15f;
source.maxDistance = 150f;
source.playOnAwake = false;
source.Play();
Object.Destroy((Object)(object)soundObj, source.clip.length);
}
MonoSingleton<NewMovement>.Instance.GetHurt(999, false, 1f, false, false, 1f, false);
yield return (object)new WaitForSeconds(0.5f);
SceneHelper.LoadScene(SceneHelper.CurrentScene, false);
}
}
public void Despawn()
{
Instance = null;
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}