Decompiled source of ModdedTools ThreadsOfTheFlame v1.5.6

ThreadsoftheFlame/HKTestMod1.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using EffectFinder;
using GlobalEnums;
using HarmonyLib;
using InControl;
using NeedolinWispfires;
using PhaseStepDash;
using ProjectileLabNS;
using TeamCherry.Localization;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("HKTestMod1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HKTestMod1")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("13ac8ee8-84a7-4c6f-9726-58a612930d2d")]
[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")]
[BepInPlugin("com.sammods.keycode.logger", "KeyCode Logger", "1.0.0")]
public class KeycodeLogger : BaseUnityPlugin
{
	private void Update()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
		{
			if (Input.GetKeyDown(value))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[KeyCodeLogger] Pressed: {(object)value}");
			}
		}
	}
}
[BepInPlugin("com.sammods.coordprobe", "Coord Probe", "1.0.0")]
public class CoordProbe : BaseUnityPlugin
{
	private void Update()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//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)
		//IL_004b: 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 (Input.GetKeyDown((KeyCode)112))
		{
			HeroController instance = HeroController.instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				Vector3 position = ((Component)instance).transform.position;
				Scene activeScene = SceneManager.GetActiveScene();
				string name = ((Scene)(ref activeScene)).name;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[CoordProbe] Scene='{name}', Position=({position.x:F2}, {position.y:F2})");
			}
		}
	}
}
internal static class WispExternalAudio
{
	private static bool _tried;

	public static AudioClip RewindClip { get; private set; }

	public static AudioClip ChantClip { get; private set; }

	public static void TryLoad(ManualLogSource log, BaseUnityPlugin plugin)
	{
		if (!_tried)
		{
			_tried = true;
			string directoryName = Path.GetDirectoryName(plugin.Info.Location);
			RewindClip = LoadOne(log, Path.Combine(directoryName, "rewind.wav"), (AudioType)20);
			ChantClip = LoadOne(log, Path.Combine(directoryName, "chant.wav"), (AudioType)20);
		}
	}

	private static AudioClip LoadOne(ManualLogSource log, string path, AudioType type)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!File.Exists(path))
			{
				return null;
			}
			string text = "file://" + path.Replace("\\", "/");
			UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(text, type);
			UnityWebRequestAsyncOperation val = audioClip.SendWebRequest();
			while (!((AsyncOperation)val).isDone)
			{
			}
			if (audioClip.isNetworkError || audioClip.isHttpError)
			{
				if (log != null)
				{
					log.LogWarning((object)("[WispAudio] Failed to load " + path + ": " + audioClip.error));
				}
				return null;
			}
			AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip);
			if (log != null)
			{
				log.LogInfo((object)("[WispAudio] Loaded " + Path.GetFileName(path)));
			}
			return content;
		}
		catch (Exception ex)
		{
			if (log != null)
			{
				log.LogWarning((object)("[WispAudio] Exception loading " + path + ": " + ex.Message));
			}
			return null;
		}
	}
}
internal static class WispAudioUtils
{
	public static void PlayOneShot(AudioClip clip, float volume = 1f)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		if (!((Object)(object)clip == (Object)null))
		{
			GameObject val = new GameObject("Wisp_AudioOneShot");
			Object.DontDestroyOnLoad((Object)(object)val);
			AudioSource val2 = val.AddComponent<AudioSource>();
			val2.playOnAwake = false;
			val2.ignoreListenerPause = true;
			val2.dopplerLevel = 0f;
			val2.rolloffMode = (AudioRolloffMode)1;
			val2.minDistance = 1f;
			val2.maxDistance = 100000f;
			val2.spatialBlend = 0f;
			val2.volume = volume;
			val2.pitch = 1f;
			val2.PlayOneShot(clip);
			float num = Mathf.Max(clip.length, 0.25f) + 0.15f;
			Object.Destroy((Object)(object)val, num);
		}
	}
}
[HarmonyPatch]
internal static class ChantPatch
{
	private static bool _lastPlaying;

	private static MethodBase TargetMethod()
	{
		return AccessTools.Method("NeedolinWispfires.NeedolinWispfiresPlugin+WispBus:SetPlaying", (Type[])null, (Type[])null);
	}

	private static void Postfix()
	{
		bool flag = false;
		try
		{
			flag = NeedolinWispfiresPlugin.WispBus.IsPlaying;
		}
		catch
		{
		}
		if (flag && !_lastPlaying)
		{
			WispAudioUtils.PlayOneShot(WispExternalAudio.ChantClip);
		}
		_lastPlaying = flag;
	}
}
namespace WispTester
{
	[BepInPlugin("com.sammods.wisptester", "Wisp Tester", "1.4.0")]
	public class WispTesterPlugin : BaseUnityPlugin
	{
		private static class DamageHooker
		{
			private static Harmony _h;

			private static bool _patched;

			private static readonly string PlannedFxName = "Particle Rest";

			internal static void EnsurePatched(ManualLogSource log)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Expected O, but got Unknown
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Expected O, but got Unknown
				if (_patched)
				{
					return;
				}
				_h = new Harmony("com.sammods.wisptester.damage");
				Type type = AccessTools.TypeByName("HeroController");
				if (type == null)
				{
					if (log != null)
					{
						log.LogWarning((object)"[WispTester] HeroController not found for damage hook.");
					}
					return;
				}
				int num = 0;
				string[] array = new string[4] { "TakeDamage", "TakeHit", "Hit", "ApplyDamage" };
				for (int i = 0; i < array.Length; i++)
				{
					MethodInfo methodInfo = AccessTools.Method(type, array[i], (Type[])null, (Type[])null);
					if (!(methodInfo == null))
					{
						_h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(DamageHooker), "Post_HeroDamaged", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						num++;
					}
				}
				if (num > 0)
				{
					_patched = true;
					if (log != null)
					{
						log.LogInfo((object)$"[WispTester] Damage hook active ({num} method(s)).");
					}
				}
				else if (log != null)
				{
					log.LogWarning((object)"[WispTester] No damage method found to hook; playing won't auto-stop on damage.");
				}
			}

			internal static void Unpatch()
			{
				try
				{
					Harmony h = _h;
					if (h != null)
					{
						h.UnpatchSelf();
					}
				}
				catch
				{
				}
				_patched = false;
			}

			public static void Post_HeroDamaged()
			{
				if (NeedolinWispfiresPlugin.WispBus.IsPlaying)
				{
					NeedolinWispfiresPlugin.WispBus.SetPlaying(v: false);
				}
			}

			private static GameObject SpawnEffectByExactName(string effectName, Vector3 pos, float scale = 1f, float ttl = 3f)
			{
				//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_00e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0111: Unknown result type (might be due to invalid IL or missing references)
				//IL_0121: Unknown result type (might be due to invalid IL or missing references)
				if (string.IsNullOrEmpty(effectName))
				{
					return null;
				}
				List<GameObject> list = null;
				GameObject val = null;
				try
				{
					GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
					list = new List<GameObject>(4);
					foreach (GameObject val2 in array)
					{
						if (Object.op_Implicit((Object)(object)val2))
						{
							Scene scene = val2.scene;
							if (!((Scene)(ref scene)).IsValid() && ((Object)val2).name == effectName)
							{
								list.Add(val2);
							}
						}
					}
					if (list.Count == 0)
					{
						Debug.LogWarning((object)("[WispTester] Effect '" + effectName + "' not found."));
						return null;
					}
					val = list[0];
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("[WispTester] FX search failed: " + ex.Message));
					return null;
				}
				GameObject val3 = null;
				try
				{
					val3 = Object.Instantiate<GameObject>(val, pos, Quaternion.identity);
					((Object)val3).name = "Wisp_PlannedFX_" + ((Object)val).name;
					Transform transform = val3.transform;
					transform.localScale *= Mathf.Max(0.01f, scale);
					val3.SetActive(true);
					ParticleSystem[] componentsInChildren = val3.GetComponentsInChildren<ParticleSystem>(true);
					foreach (ParticleSystem val4 in componentsInChildren)
					{
						if (Object.op_Implicit((Object)(object)val4))
						{
							val4.Clear(true);
							val4.Play(true);
						}
					}
					Renderer[] componentsInChildren2 = val3.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val5 in componentsInChildren2)
					{
						if (Object.op_Implicit((Object)(object)val5))
						{
							val5.sortingOrder += 2;
						}
					}
					if (ttl > 0f)
					{
						Object.Destroy((Object)(object)val3, ttl);
					}
				}
				catch (Exception ex2)
				{
					Debug.LogWarning((object)("[WispTester] FX instantiate failed: " + ex2.Message));
					return null;
				}
				Debug.Log((object)$"[EffectFinder] Spawned: {((Object)val).name} (1/{list?.Count ?? 1})");
				return val3;
			}
		}

		[CompilerGenerated]
		private sealed class <AttachAfterHeroReady>d__4 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public WispTesterPlugin <>4__this;

			private GameObject <hero>5__1;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)HeroController.instance == (Object)null || (Object)(object)((Component)HeroController.instance).gameObject == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				<hero>5__1 = ((Component)HeroController.instance).gameObject;
				if ((Object)(object)<hero>5__1.GetComponent<WispTargetingSpawner>() == (Object)null)
				{
					<hero>5__1.AddComponent<WispTargetingSpawner>();
					((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"[WispTester] Spawner attached to hero");
				}
				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();
			}
		}

		internal static ManualLogSource Log;

		private void OnEnable()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			SceneManager.sceneLoaded += OnSceneLoaded;
			DamageHooker.EnsurePatched(((BaseUnityPlugin)this).Logger);
			WispExternalAudio.TryLoad(((BaseUnityPlugin)this).Logger, (BaseUnityPlugin)(object)this);
			Harmony val = new Harmony("com.sammods.wispaudio");
			val.PatchAll(typeof(ChantPatch));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[WispAudio] Rewind + Chant patches loaded.");
		}

		private void OnDisable()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			DamageHooker.Unpatch();
		}

		private void OnSceneLoaded(Scene s, LoadSceneMode m)
		{
			((MonoBehaviour)this).StartCoroutine(AttachAfterHeroReady());
		}

		[IteratorStateMachine(typeof(<AttachAfterHeroReady>d__4))]
		private IEnumerator AttachAfterHeroReady()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AttachAfterHeroReady>d__4(0)
			{
				<>4__this = this
			};
		}
	}
	public class WispTargetingSpawner : MonoBehaviour
	{
		private class Held
		{
			public GameObject go;

			public Rigidbody2D rb;

			public RigidbodyType2D prevBody;

			public List<Behaviour> fsms;

			public Behaviour light;
		}

		[CompilerGenerated]
		private sealed class <Loop>d__40 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public WispTargetingSpawner <>4__this;

			private int <before>5__1;

			private int <after>5__2;

			private GameObject <hero>5__3;

			private Vector3 <pos>5__4;

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

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

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

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

			private bool MoveNext()
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Expected O, but got Unknown
				//IL_0150: Unknown result type (might be due to invalid IL or missing references)
				//IL_015a: Expected O, but got Unknown
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_0119: Unknown result type (might be due to invalid IL or missing references)
				//IL_0124: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					<>1__state = -1;
					<hero>5__3 = null;
					break;
				case 3:
					<>1__state = -1;
					break;
				}
				if (NeedolinWispfiresPlugin.WispBus.IsEquipped && NeedolinWispfiresPlugin.WispBus.IsPlaying)
				{
					<before>5__1 = <>4__this.HeldCount;
					<>4__this.SpawnHeldOnce();
					<after>5__2 = <>4__this.HeldCount;
					if (<after>5__2 > <before>5__1)
					{
						<>4__this.PlayRewindOneShot();
					}
					<hero>5__3 = (Object.op_Implicit((Object)(object)HeroController.instance) ? ((Component)HeroController.instance).gameObject : null);
					if (Object.op_Implicit((Object)(object)<hero>5__3))
					{
						<pos>5__4 = <hero>5__3.transform.position + new Vector3(0f, 0.1f, 0f);
						SpawnEffectByExactName(PlannedFxName, <pos>5__4, 0.55f);
					}
					<>2__current = (object)new WaitForSeconds(Mathf.Max(0.05f, <>4__this.interval));
					<>1__state = 2;
					return true;
				}
				<>2__current = null;
				<>1__state = 3;
				return true;
			}

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

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

		[Header("Spawn (while playing)")]
		public float interval = 1.5f;

		public float ySpawnJitter = 1.5f;

		[Header("Release targeting (when playing stops)")]
		public bool targetRandomEnemy = true;

		public float enemySearchRadius = 10f;

		public LayerMask enemyLayerMask = LayerMask.op_Implicit(-1);

		public bool requireLOS = false;

		public int losMask = 256;

		[Header("Release motion (fallback if no enemy)")]
		public bool randomLeftRight = true;

		public float minHorizDistance = 2f;

		public float maxHorizDistance = 20f;

		public float minReleaseSpeed = 2f;

		public float maxReleaseSpeed = 20f;

		[Header("Prefab fallback")]
		public GameObject fallbackWispPrefab = null;

		[Header("Mini Circles (Held Viz)")]
		public bool showMiniCircles = false;

		public int miniCircleSegments = 32;

		public float miniCircleRadius = 0.25f;

		public float miniCircleLineWidth = 0.05f;

		public Color miniCircleColor = new Color(1f, 0.416f, 0f, 0.9f);

		public bool miniCirclesBehindHero = true;

		public float miniHoverHeight = 1.1f;

		public float miniSpreadX = 1.6f;

		public float miniBobAmplitude = 0.2f;

		public float miniBobSpeed = 3f;

		public float miniFollowLerp = 12f;

		private GameObject _wispPrefab;

		private Coroutine _loop;

		private bool _right = true;

		private readonly List<Held> _held = new List<Held>();

		private readonly List<HealthManager> _enemyBuffer = new List<HealthManager>(32);

		private readonly List<LineRenderer> _miniPool = new List<LineRenderer>();

		private Transform _miniRoot;

		private Vector3 _miniAnchor;

		private static readonly string PlannedFxName = "Particle Rest";

		public int HeldCount => (_held != null) ? _held.Count : 0;

		private void Awake()
		{
			TryResolveWispPrefab();
			EnsureMiniRoot();
		}

		private void OnEnable()
		{
			NeedolinWispfiresPlugin.WispBus.PlayingChanged += OnPlayingChanged;
			NeedolinWispfiresPlugin.WispBus.EquippedChanged += OnEquippedChanged;
			if (_loop == null)
			{
				_loop = ((MonoBehaviour)this).StartCoroutine(Loop());
			}
		}

		private void OnDisable()
		{
			NeedolinWispfiresPlugin.WispBus.PlayingChanged -= OnPlayingChanged;
			NeedolinWispfiresPlugin.WispBus.EquippedChanged -= OnEquippedChanged;
			if (_loop != null)
			{
				((MonoBehaviour)this).StopCoroutine(_loop);
			}
			_loop = null;
			ClearHeld(destroy: true);
			SetAllMiniActive(on: false);
		}

		private void Update()
		{
			UpdateMiniCircles();
		}

		private void OnPlayingChanged(bool playing)
		{
			if (!playing)
			{
				ReleaseAll();
			}
		}

		private void OnEquippedChanged(bool equipped)
		{
			if (!equipped)
			{
				ClearHeld(destroy: true);
				SetAllMiniActive(on: false);
			}
		}

		[IteratorStateMachine(typeof(<Loop>d__40))]
		private IEnumerator Loop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Loop>d__40(0)
			{
				<>4__this = this
			};
		}

		private static GameObject SpawnEffectByExactName(string effectName, Vector3 pos, float scale = 1f, float ttl = 3f)
		{
			//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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(effectName))
			{
				return null;
			}
			List<GameObject> list = null;
			GameObject val = null;
			try
			{
				GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
				list = new List<GameObject>(4);
				foreach (GameObject val2 in array)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						Scene scene = val2.scene;
						if (!((Scene)(ref scene)).IsValid() && ((Object)val2).name == effectName)
						{
							list.Add(val2);
						}
					}
				}
				if (list.Count == 0)
				{
					Debug.LogWarning((object)("[WispTester] Effect '" + effectName + "' not found."));
					return null;
				}
				val = list[0];
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[WispTester] FX search failed: " + ex.Message));
				return null;
			}
			GameObject val3 = null;
			try
			{
				val3 = Object.Instantiate<GameObject>(val, pos, Quaternion.identity);
				((Object)val3).name = "Wisp_PlannedFX_" + ((Object)val).name;
				Transform transform = val3.transform;
				transform.localScale *= Mathf.Max(0.01f, scale);
				val3.SetActive(true);
				ParticleSystem[] componentsInChildren = val3.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val4 in componentsInChildren)
				{
					if (Object.op_Implicit((Object)(object)val4))
					{
						val4.Clear(true);
						val4.Play(true);
					}
				}
				Renderer[] componentsInChildren2 = val3.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val5 in componentsInChildren2)
				{
					if (Object.op_Implicit((Object)(object)val5))
					{
						val5.sortingOrder += 2;
					}
				}
				if (ttl > 0f)
				{
					Object.Destroy((Object)(object)val3, ttl);
				}
			}
			catch (Exception ex2)
			{
				Debug.LogWarning((object)("[WispTester] FX instantiate failed: " + ex2.Message));
				return null;
			}
			Debug.Log((object)$"[EffectFinder] Spawned: {((Object)val).name} (1/{list?.Count ?? 1})");
			return val3;
		}

		private void PlayRewindOneShot()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if (!((Object)(object)WispExternalAudio.RewindClip == (Object)null))
			{
				GameObject val = new GameObject("Wisp_Rewind_OneShot");
				Object.DontDestroyOnLoad((Object)(object)val);
				AudioSource val2 = val.AddComponent<AudioSource>();
				val2.playOnAwake = false;
				val2.ignoreListenerPause = true;
				val2.dopplerLevel = 0f;
				val2.rolloffMode = (AudioRolloffMode)1;
				val2.minDistance = 1f;
				val2.maxDistance = 100000f;
				val2.spatialBlend = 0f;
				val2.volume = 0.9f;
				val2.pitch = 1f;
				val2.PlayOneShot(WispExternalAudio.RewindClip);
				float num = Mathf.Max(WispExternalAudio.RewindClip.length, 0.35f) + 0.15f;
				Object.Destroy((Object)(object)val, num);
			}
		}

		private void SpawnHeldOnce()
		{
			//IL_0007: 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)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.position + new Vector3(0f, Random.Range(0f - ySpawnJitter, ySpawnJitter), 0f);
			if ((Object)(object)_wispPrefab == (Object)null)
			{
				GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)5);
				((Object)val2).name = "WispDebugQuad_HELD";
				val2.transform.position = val;
				Rigidbody2D val3 = val2.AddComponent<Rigidbody2D>();
				val3.gravityScale = 0f;
				val3.bodyType = (RigidbodyType2D)1;
				_held.Add(new Held
				{
					go = val2,
					rb = val3,
					prevBody = (RigidbodyType2D)1,
					fsms = new List<Behaviour>(),
					light = null
				});
				Debug.Log((object)"[WispTargetingSpawner] HELD DEBUG QUAD (no prefab found)");
				return;
			}
			GameObject val4 = Object.Instantiate<GameObject>(_wispPrefab, val, Quaternion.identity);
			if (!Object.op_Implicit((Object)(object)val4))
			{
				return;
			}
			val4.transform.SetParent((Transform)null, true);
			val4.transform.localScale = Vector3.one;
			val4.transform.rotation = Quaternion.identity;
			Rigidbody2D component = val4.GetComponent<Rigidbody2D>();
			RigidbodyType2D prevBody = (RigidbodyType2D)0;
			if ((Object)(object)component != (Object)null)
			{
				prevBody = component.bodyType;
				component.velocity = Vector2.zero;
				component.angularVelocity = 1f;
				component.gravityScale = 0f;
				component.bodyType = (RigidbodyType2D)1;
			}
			Behaviour val5 = null;
			Component component2 = val4.GetComponent("WispFireballLight");
			if ((Object)(object)component2 != (Object)null)
			{
				val5 = (Behaviour)(object)((component2 is Behaviour) ? component2 : null);
				if ((Object)(object)val5 != (Object)null)
				{
					val5.enabled = false;
				}
			}
			List<Behaviour> list = new List<Behaviour>();
			Component[] componentsInChildren = val4.GetComponentsInChildren<Component>(true);
			foreach (Component val6 in componentsInChildren)
			{
				if ((Object)(object)val6 != (Object)null && ((object)val6).GetType().Name == "PlayMakerFSM")
				{
					Behaviour val7 = (Behaviour)(object)((val6 is Behaviour) ? val6 : null);
					if ((Object)(object)val7 != (Object)null)
					{
						val7.enabled = false;
						list.Add(val7);
					}
				}
			}
			_held.Add(new Held
			{
				go = val4,
				rb = component,
				prevBody = prevBody,
				fsms = list,
				light = val5
			});
			Debug.Log((object)$"[WispTargetingSpawner] HELD wisp (count={_held.Count})");
		}

		private void ReleaseAll()
		{
			//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_005e: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_00f0: 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_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_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if (_held.Count == 0)
			{
				return;
			}
			for (int i = 0; i < _held.Count; i++)
			{
				Held held = _held[i];
				if (held == null || (Object)(object)held.go == (Object)null)
				{
					continue;
				}
				Vector3 position = held.go.transform.position;
				GameObject val = null;
				Vector3 val2 = position;
				bool flag = false;
				Vector2 val6;
				if (targetRandomEnemy)
				{
					HealthManager val3 = FindRandomEnemyHM(position, enemySearchRadius, enemyLayerMask);
					if ((Object)(object)val3 != (Object)null)
					{
						Vector2 val4 = Vector2.op_Implicit(val3.TargetPoint);
						if (!requireLOS || !RaycastHit2D.op_Implicit(Physics2D.Linecast(Vector2.op_Implicit(position), val4, losMask)))
						{
							val = ((Component)val3).gameObject;
							val2 = val3.TargetPoint;
							Vector2 val5 = val4 - Vector2.op_Implicit(position);
							val6 = ((Vector2)(ref val5)).normalized;
							if (((Vector2)(ref val6)).sqrMagnitude < 0.0001f)
							{
								val6 = Vector2.right;
							}
							ApplyRelease(held, val6, val, val2, useFire: true);
							flag = true;
						}
					}
				}
				if (!flag)
				{
					val6 = ((randomLeftRight ? (Random.value > 0.5f) : (_right = !_right)) ? Vector2.right : Vector2.left);
					float num = Random.Range(minHorizDistance, maxHorizDistance);
					val2 = position + Vector2.op_Implicit(val6 * num);
					ApplyRelease(held, val6, null, val2, useFire: true);
				}
			}
			_held.Clear();
		}

		private void ApplyRelease(Held h, Vector2 dir, GameObject targetGO, Vector3 targetPos, bool useFire)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			TrySetFsm(h.go, ((Component)this).gameObject, targetGO, targetPos);
			if (h.fsms != null)
			{
				for (int i = 0; i < h.fsms.Count; i++)
				{
					if ((Object)(object)h.fsms[i] != (Object)null)
					{
						h.fsms[i].enabled = true;
					}
				}
			}
			if ((Object)(object)h.light != (Object)null)
			{
				h.light.enabled = true;
			}
			float num = Random.Range(minReleaseSpeed, maxReleaseSpeed);
			if ((Object)(object)h.rb != (Object)null)
			{
				h.rb.bodyType = (RigidbodyType2D)0;
				h.rb.gravityScale = 0f;
				h.rb.velocity = dir * num;
			}
			Component component = h.go.GetComponent("WispFireballLight");
			if ((Object)(object)component != (Object)null)
			{
				FieldInfo field = ((object)component).GetType().GetField("curveForce", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(component, dir * num);
				}
				if (useFire)
				{
					MethodInfo method = ((object)component).GetType().GetMethod("Fire", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (method != null)
					{
						try
						{
							method.Invoke(component, null);
						}
						catch
						{
						}
					}
				}
			}
			Debug.Log((object)string.Format("[WispTargetingSpawner] RELEASE → dir=({0:0.00},{1:0.00}) speed={2:0.0} target={3}", dir.x, dir.y, num, Object.op_Implicit((Object)(object)targetGO) ? ((Object)targetGO).name : "none"));
		}

		private void ClearHeld(bool destroy)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _held.Count; i++)
			{
				Held held = _held[i];
				if (held != null && !((Object)(object)held.go == (Object)null))
				{
					if (destroy)
					{
						Object.Destroy((Object)(object)held.go);
					}
					else if ((Object)(object)held.rb != (Object)null)
					{
						held.rb.bodyType = held.prevBody;
					}
				}
			}
			_held.Clear();
		}

		private HealthManager FindRandomEnemyHM(Vector3 center, float radius, LayerMask mask)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			_enemyBuffer.Clear();
			Collider2D[] array = ((((LayerMask)(ref mask)).value != 0) ? Physics2D.OverlapCircleAll(Vector2.op_Implicit(center), radius, LayerMask.op_Implicit(mask)) : Physics2D.OverlapCircleAll(Vector2.op_Implicit(center), radius));
			foreach (Collider2D val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					HealthManager val2 = null;
					if ((Object)(object)val.attachedRigidbody != (Object)null)
					{
						val2 = ((Component)val.attachedRigidbody).GetComponent<HealthManager>();
					}
					if ((Object)(object)val2 == (Object)null)
					{
						val2 = ((Component)val).GetComponent<HealthManager>();
					}
					if ((Object)(object)val2 != (Object)null && !_enemyBuffer.Contains(val2))
					{
						_enemyBuffer.Add(val2);
					}
				}
			}
			if (_enemyBuffer.Count == 0)
			{
				return null;
			}
			int index = Random.Range(0, _enemyBuffer.Count);
			HealthManager val3 = _enemyBuffer[index];
			return Object.op_Implicit((Object)(object)val3) ? val3 : null;
		}

		private void TryResolveWispPrefab()
		{
			Component val = FindLantern();
			if ((Object)(object)val != (Object)null)
			{
				FieldInfo field = ((object)val).GetType().GetField("wispPrefab", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					ref GameObject wispPrefab = ref _wispPrefab;
					object? value = field.GetValue(val);
					wispPrefab = (GameObject)((value is GameObject) ? value : null);
					if ((Object)(object)_wispPrefab == (Object)null)
					{
						Debug.LogWarning((object)"[WispTargetingSpawner] HeroWispLantern.wispPrefab was null");
					}
				}
				else
				{
					Debug.LogWarning((object)"[WispTargetingSpawner] Field 'wispPrefab' not found on HeroWispLantern");
				}
			}
			else
			{
				Debug.LogWarning((object)"[WispTargetingSpawner] Could not find any HeroWispLantern in scene");
			}
			if ((Object)(object)_wispPrefab == (Object)null && (Object)(object)fallbackWispPrefab != (Object)null)
			{
				_wispPrefab = fallbackWispPrefab;
			}
		}

		private Component FindLantern()
		{
			GameObject val = (Object.op_Implicit((Object)(object)HeroController.instance) ? ((Component)HeroController.instance).gameObject : null);
			if ((Object)(object)val != (Object)null)
			{
				Component[] componentsInChildren = val.GetComponentsInChildren<Component>(true);
				foreach (Component val2 in componentsInChildren)
				{
					if ((Object)(object)val2 != (Object)null && ((object)val2).GetType().Name == "HeroWispLantern")
					{
						return val2;
					}
				}
			}
			MonoBehaviour[] array = Object.FindObjectsOfType<MonoBehaviour>();
			foreach (MonoBehaviour val3 in array)
			{
				if ((Object)(object)val3 != (Object)null && ((object)val3).GetType().Name == "HeroWispLantern")
				{
					return (Component)(object)val3;
				}
			}
			return null;
		}

		private static void TrySetFsm(GameObject go, GameObject spawner, GameObject target, Vector3 targetPos)
		{
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			Component component = go.GetComponent("PlayMakerFSM");
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			try
			{
				object obj = ((object)component).GetType().GetProperty("FsmVariables")?.GetValue(component, null);
				if (obj != null)
				{
					MethodInfo method = obj.GetType().GetMethod("FindFsmGameObject");
					MethodInfo method2 = obj.GetType().GetMethod("FindFsmVector3");
					object obj2 = method?.Invoke(obj, new object[1] { "Spawner" });
					obj2?.GetType().GetProperty("Value")?.SetValue(obj2, spawner, null);
					object obj3 = method?.Invoke(obj, new object[1] { "Target" });
					obj3?.GetType().GetProperty("Value")?.SetValue(obj3, target, null);
					object obj4 = method2?.Invoke(obj, new object[1] { "Target Pos" });
					obj4?.GetType().GetProperty("Value")?.SetValue(obj4, targetPos, null);
				}
			}
			catch
			{
			}
		}

		private void EnsureMiniRoot()
		{
			//IL_0019: 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_0053: 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)
			if (!((Object)(object)_miniRoot != (Object)null))
			{
				_miniRoot = new GameObject("WispMiniCircles").transform;
				_miniRoot.SetParent(((Component)this).transform, false);
				_miniRoot.localPosition = Vector3.zero;
				_miniAnchor = ((Component)this).transform.position;
			}
		}

		private void UpdateMiniCircles()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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)
			if (!showMiniCircles)
			{
				SetAllMiniActive(on: false);
				return;
			}
			_miniAnchor = Vector3.Lerp(_miniAnchor, ((Component)this).transform.position, Time.unscaledDeltaTime * Mathf.Max(miniFollowLerp, 0.01f));
			int num = ((NeedolinWispfiresPlugin.WispBus.IsEquipped && NeedolinWispfiresPlugin.WispBus.IsPlaying) ? HeldCount : 0);
			EnsureMiniPoolSize(num);
			float num2 = Time.unscaledTime * miniBobSpeed;
			float num3 = (float)Mathf.Max(0, num - 1) * 0.5f;
			for (int i = 0; i < _miniPool.Count; i++)
			{
				LineRenderer val = _miniPool[i];
				bool flag = i < num;
				((Component)val).gameObject.SetActive(flag);
				if (flag)
				{
					float num4 = ((float)i - num3) / Mathf.Max(1f, num3) * miniSpreadX * 0.5f;
					float num5 = (float)i * 0.8f;
					float num6 = Mathf.Sin(num2 + num5) * miniBobAmplitude;
					Vector3 position = _miniAnchor + new Vector3(num4, miniHoverHeight + num6, -0.01f);
					((Component)val).transform.position = position;
				}
			}
		}

		private void EnsureMiniPoolSize(int count)
		{
			EnsureMiniRoot();
			while (_miniPool.Count < count)
			{
				LineRenderer item = CreateMiniCircleRenderer($"miniCircle_{_miniPool.Count}");
				_miniPool.Add(item);
			}
			for (int i = count; i < _miniPool.Count; i++)
			{
				((Component)_miniPool[i]).gameObject.SetActive(false);
			}
		}

		private LineRenderer CreateMiniCircleRenderer(string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(_miniRoot, false);
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			val2.loop = true;
			val2.useWorldSpace = false;
			val2.alignment = (LineAlignment)0;
			val2.textureMode = (LineTextureMode)0;
			val2.positionCount = Mathf.Max(8, miniCircleSegments);
			val2.widthMultiplier = miniCircleLineWidth;
			Shader val3 = Shader.Find("Universal Render Pipeline/Unlit");
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = Shader.Find("Sprites/Default");
			}
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = Shader.Find("Unlit/Color");
			}
			((Renderer)val2).material = new Material(val3);
			((Renderer)val2).material.renderQueue = 3000;
			TrySetMaterialColor(((Renderer)val2).material, miniCircleColor);
			val2.startColor = miniCircleColor;
			val2.endColor = miniCircleColor;
			PlaceRelativeToHero((Renderer)(object)val2, miniCirclesBehindHero, 3, 3f);
			SpriteRenderer componentInChildren = ((Component)this).GetComponentInChildren<SpriteRenderer>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((Renderer)val2).sortingLayerID = ((Renderer)componentInChildren).sortingLayerID;
				((Renderer)val2).sortingOrder = ((Renderer)componentInChildren).sortingOrder + ((!miniCirclesBehindHero) ? 1 : (-1));
			}
			int num = Mathf.Max(8, miniCircleSegments);
			float num2 = (float)Math.PI * 2f / (float)num;
			for (int i = 0; i < num; i++)
			{
				float num3 = (float)i * num2;
				val2.SetPosition(i, new Vector3(Mathf.Cos(num3), Mathf.Sin(num3), 10f) * miniCircleRadius);
			}
			val.SetActive(false);
			return val2;
		}

		private static void PlaceRelativeToHero(Renderer r, bool behind, int delta = 1, float zNudge = 0f)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)r))
			{
				HeroController instance = HeroController.instance;
				SpriteRenderer val = ((instance != null) ? ((Component)instance).GetComponentInChildren<SpriteRenderer>() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					r.sortingLayerID = ((Renderer)val).sortingLayerID;
					r.sortingOrder = ((Renderer)val).sortingOrder + (behind ? (-Mathf.Abs(delta)) : Mathf.Abs(delta));
				}
				if (Mathf.Abs(zNudge) > 0f)
				{
					Transform transform = ((Component)r).transform;
					Vector3 localPosition = transform.localPosition;
					localPosition.z += (behind ? Mathf.Abs(zNudge) : (0f - Mathf.Abs(zNudge)));
					transform.localPosition = localPosition;
				}
			}
		}

		private void SetAllMiniActive(bool on)
		{
			for (int i = 0; i < _miniPool.Count; i++)
			{
				if ((Object)(object)_miniPool[i] != (Object)null)
				{
					((Component)_miniPool[i]).gameObject.SetActive(on);
				}
			}
		}

		private static void TrySetMaterialColor(Material m, Color c)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)m == (Object)null))
			{
				if (m.HasProperty("_BaseColor"))
				{
					m.SetColor("_BaseColor", c);
				}
				if (m.HasProperty("_Color"))
				{
					m.SetColor("_Color", c);
				}
			}
		}
	}
}
namespace RedSpriteSilkFollowAndStrike
{
	[BepInPlugin("com.sammods.red.spritesilk.followstrike", "Red: Sprite Silk (Follow + Strike)", "4.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RedSpriteSilkFollowAndStrikePlugin : BaseUnityPlugin
	{
		private sealed class InertProjectile : MonoBehaviour
		{
			[CompilerGenerated]
			private sealed class <DisappearNextFrame>d__1 : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private object <>2__current;

				public InertProjectile <>4__this;

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

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

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

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

				private bool MoveNext()
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>2__current = null;
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -1;
						((Component)<>4__this).gameObject.SetActive(false);
						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();
				}
			}

			private void OnEnable()
			{
				((MonoBehaviour)this).StartCoroutine(DisappearNextFrame());
			}

			[IteratorStateMachine(typeof(<DisappearNextFrame>d__1))]
			private IEnumerator DisappearNextFrame()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <DisappearNextFrame>d__1(0)
				{
					<>4__this = this
				};
			}
		}

		[CompilerGenerated]
		private sealed class <RebindAfterHeroReady>d__40 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public RedSpriteSilkFollowAndStrikePlugin <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)HeroController.instance == (Object)null || (Object)(object)((Component)HeroController.instance).gameObject == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				EnsureManager();
				_mgr.BindTarget(GetHeroTransformOrNull());
				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 const string PluginGuid = "com.sammods.red.spritesilk.followstrike";

		public const string PluginName = "Red: Sprite Silk (Follow + Strike)";

		public const string PluginVersion = "4.0.0";

		internal static ManualLogSource Log;

		internal static RedSpriteSilkFollowAndStrikePlugin Instance;

		private static Harmony _harmony;

		private const string ToolInternalName = "Red_Sprite_Silk_FollowStrike";

		private const string ToolDisplay = "Conductor's Baton";

		private const string ToolDesc = "\n A worn golden baton inlaid with special filigree. \n \n Use to inspire the soul of a fallen pilgrim to come to your aid. \n";

		private static ToolItemType _forcedTypeForClone = (ToolItemType)0;

		private static ToolItem _templateTool;

		private static ToolItem _clonedTool;

		private static ToolItemBasic _templateBasic;

		private static ToolItemBasic _cloneBasic;

		private static WeakReference<ToolItem> _cloneRef;

		private static Harmony _textPatchHarmony;

		private readonly KeyCode _modKey = (KeyCode)306;

		private readonly KeyCode _grantKey = (KeyCode)114;

		private const string EFFECT_NAME = "Sprite Silk";

		private const string PROJECTILE_NAME = "WebShot Bullet";

		private static readonly Vector3 FOLLOW_OFFSET = new Vector3(-2f, 0.45f, 0f);

		private const float FOLLOW_SMOOTH_TIME = 0.15f;

		private const float FOLLOW_MAX_LAG = 2.25f;

		private const float HUD_SORT_BUMP = 2f;

		private const float SEEK_RADIUS = 12f;

		private const float SEEK_MIN_DISTANCE = 8f;

		private const float SEEK_SPEED = 14f;

		private const float SEEK_TURN_ACCEL = 20f;

		private const float ENEMY_LOS_POLL = 0.1f;

		private const float COOLDOWN_AFTER_SHOT = 2f;

		private const float SNAPSHOT_AHEAD = 0f;

		private const float PROJECTILE_SPEED_OVERRIDE = 0f;

		private const int SHOTS_TO_LIVE = 8;

		private static readonly int _maskBlockers = LayerMask.GetMask(new string[5] { "Default", "Terrain", "Tilemap", "Hazards", "Platform" });

		private static GameObject _rootGO;

		private static RedSilkManager _mgr;

		private static GameObject _dummyThrowPrefab;

		private void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			_harmony = new Harmony("com.sammods.red.spritesilk.followstrike.core");
			PatchEnumerable("GetUnlockedTools");
			PatchEnumerable("GetAllTools");
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(ToolItemManager), "GetToolByName", (Type[])null, (Type[])null), new HarmonyMethod(typeof(RedSpriteSilkFollowAndStrikePlugin), "Prefix_GetToolByName_Alias", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(ToolItem), "OnWasUsed", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(RedSpriteSilkFollowAndStrikePlugin), "Post_ToolItem_OnWasUsed", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			TryCreateClone();
			EnsureCloneInToolDatabase(_clonedTool);
			EnsureManager();
			SceneManager.sceneLoaded += OnSceneLoaded;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[SpriteSilk] Loaded. Ctrl+R to unlock (no auto-equip).");
		}

		private void OnDestroy()
		{
			if (Instance == this)
			{
				Instance = null;
			}
			SceneManager.sceneLoaded -= OnSceneLoaded;
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}

		private void OnSceneLoaded(Scene s, LoadSceneMode m)
		{
			TryCreateClone();
			EnsureCloneInToolDatabase(_clonedTool);
			((MonoBehaviour)this).StartCoroutine(RebindAfterHeroReady());
		}

		[IteratorStateMachine(typeof(<RebindAfterHeroReady>d__40))]
		private IEnumerator RebindAfterHeroReady()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RebindAfterHeroReady>d__40(0)
			{
				<>4__this = this
			};
		}

		private void Update()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKey(_modKey) && Input.GetKeyDown(_grantKey))
			{
				UnlockSelfAndNudge();
			}
		}

		private void UnlockSelfAndNudge()
		{
			TryCreateClone();
			bool flag = EnsureCloneInToolDatabase(_clonedTool);
			if ((Object)(object)_clonedTool == (Object)null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)"[SpriteSilk] UnlockSelf: clone not ready.");
				}
				return;
			}
			TryUnlock(_clonedTool);
			TrySendEquippedChangedEvent(v: true);
			TryShowQueuedReminder();
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"[SpriteSilk] Unlocked (no auto-equip). Injected={flag}");
			}
		}

		private static void EnsureManager()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_rootGO == (Object)null)
			{
				_rootGO = new GameObject("RedSpriteSilk_ManagerRoot");
				Object.DontDestroyOnLoad((Object)(object)_rootGO);
			}
			if ((Object)(object)_mgr == (Object)null)
			{
				_mgr = _rootGO.GetComponent<RedSilkManager>();
				if ((Object)(object)_mgr == (Object)null)
				{
					_mgr = _rootGO.AddComponent<RedSilkManager>();
				}
				_mgr.Configure("Sprite Silk", "WebShot Bullet", FOLLOW_OFFSET, 0.15f, 2.25f, 2f, 12f, 8f, 14f, 20f, _maskBlockers, 0.1f, 2f, 0f, 0f, 8);
			}
		}

		private static Transform GetHeroTransformOrNull()
		{
			HeroController instance = HeroController.instance;
			return (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)((Component)instance).gameObject)) ? ((Component)instance).transform : null;
		}

		private static void Post_ToolItem_OnWasUsed(ToolItem __instance)
		{
			if (!((Object)(object)_clonedTool == (Object)null) && __instance == _clonedTool)
			{
				EnsureManager();
				_mgr.SpawnOrRefreshSilk(GetHeroTransformOrNull());
			}
		}

		private static void TryCreateClone()
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_clonedTool != (Object)null)
			{
				return;
			}
			try
			{
				_templateTool = ToolItemManager.GetToolByName("Pimpilo") ?? ToolItemManager.GetToolByName("Pimpillo") ?? ToolItemManager.GetToolByName("Tool_Pimpilo") ?? ToolItemManager.GetToolByName("Tool_Pimpillo") ?? ToolItemManager.GetAllTools().FirstOrDefault((Func<ToolItem, bool>)((ToolItem t) => Object.op_Implicit((Object)(object)t) && t.name.IndexOf("pimp", StringComparison.OrdinalIgnoreCase) >= 0)) ?? ToolItemManager.GetAllTools().FirstOrDefault((Func<ToolItem, bool>)((ToolItem t) => Object.op_Implicit((Object)(object)t) && (int)t.Type == 0)) ?? ToolItemManager.GetAllTools().FirstOrDefault((Func<ToolItem, bool>)((ToolItem t) => Object.op_Implicit((Object)(object)t)));
				if ((Object)(object)_templateTool == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)"[SpriteSilk] No Pimpillo/Pimpilo template found and no fallback tool available.");
					}
					return;
				}
				ToolItem templateTool = _templateTool;
				_templateBasic = (ToolItemBasic)(object)((templateTool is ToolItemBasic) ? templateTool : null);
				_clonedTool = Object.Instantiate<ToolItem>(_templateTool);
				_clonedTool.name = "Red_Sprite_Silk_FollowStrike";
				_forcedTypeForClone = _templateTool.Type;
				ToolItem clonedTool = _clonedTool;
				_cloneBasic = (ToolItemBasic)(object)((clonedTool is ToolItemBasic) ? clonedTool : null);
				if (Object.op_Implicit((Object)(object)_cloneBasic) && Object.op_Implicit((Object)(object)_templateBasic))
				{
					CopySpriteField(_cloneBasic, _templateBasic, "inventorySprite");
					CopySpriteField(_cloneBasic, _templateBasic, "inventorySpritePoison");
					CopySpriteField(_cloneBasic, _templateBasic, "hudSprite");
					CopySpriteField(_cloneBasic, _templateBasic, "hudSpritePoison");
					CopySpriteField(_cloneBasic, _templateBasic, "popupIconOverride");
					TrySwapIconsFromDisk_SinglePng(_cloneBasic, "sprite_silk_icon.png");
				}
				TrySetBoolField(_clonedTool, new string[4] { "visibleInMenu", "_visibleInMenu", "showInInventory", "_showInInventory" }, value: true);
				TrySetBoolField(_clonedTool, new string[6] { "isDiscovered", "_isDiscovered", "discovered", "_discovered", "revealed", "_revealed" }, value: true);
				TrySetBoolField(_clonedTool, new string[4] { "isUnlocked", "_isUnlocked", "unlocked", "_unlocked" }, value: false);
				ApplyTextOverridesForClone(_clonedTool);
				ApplyTypeOverrideForClone(_clonedTool);
				ApplyUsageOverrideForClone_StopProjectile(_clonedTool);
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("[SpriteSilk] Created tool clone from '" + _templateTool.name + "'. Type=" + ((object)(ToolItemType)(ref _forcedTypeForClone)).ToString()));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogWarning((object)("[SpriteSilk] Clone creation failed: " + ex.Message));
				}
				_clonedTool = null;
			}
		}

		private static void TrySetPrivateSpriteField(object obj, string field, Sprite value)
		{
			if (obj == null || (Object)(object)value == (Object)null)
			{
				return;
			}
			FieldInfo field2 = obj.GetType().GetField(field, BindingFlags.Instance | BindingFlags.NonPublic);
			if (!(field2 != null) || !(field2.FieldType == typeof(Sprite)))
			{
				return;
			}
			try
			{
				field2.SetValue(obj, value);
			}
			catch
			{
			}
		}

		private static Sprite LoadSpriteFromPng_WWW(string fullPath, float ppu = 100f, Vector2? pivot01 = null)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!File.Exists(fullPath))
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)("[IconSwap] PNG not found at: " + fullPath));
					}
					return null;
				}
				string text = "file://" + fullPath.Replace("\\", "/");
				WWW val = new WWW(text);
				try
				{
					float realtimeSinceStartup = Time.realtimeSinceStartup;
					while (!val.isDone && Time.realtimeSinceStartup - realtimeSinceStartup < 10f)
					{
					}
					if (!val.isDone && string.IsNullOrEmpty(val.error))
					{
						ManualLogSource log2 = Log;
						if (log2 != null)
						{
							log2.LogWarning((object)("[IconSwap] WWW timed out: " + text));
						}
						return null;
					}
					if (!string.IsNullOrEmpty(val.error))
					{
						ManualLogSource log3 = Log;
						if (log3 != null)
						{
							log3.LogWarning((object)("[IconSwap] WWW error: " + val.error));
						}
						return null;
					}
					Texture2D texture = val.texture;
					if ((Object)(object)texture == (Object)null)
					{
						ManualLogSource log4 = Log;
						if (log4 != null)
						{
							log4.LogWarning((object)("[IconSwap] WWW.texture was null for: " + fullPath));
						}
						return null;
					}
					((Texture)texture).wrapMode = (TextureWrapMode)1;
					((Texture)texture).filterMode = (FilterMode)1;
					Rect val2 = default(Rect);
					((Rect)(ref val2))..ctor(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height);
					Vector2 val3 = (Vector2)(((??)pivot01) ?? new Vector2(0.5f, 0.5f));
					Sprite val4 = Sprite.Create(texture, val2, val3, ppu);
					((Object)val4).name = Path.GetFileName(fullPath) + "_Sprite";
					return val4;
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogWarning((object)("[IconSwap] LoadSpriteFromPng_WWW exception: " + ex));
				}
				return null;
			}
		}

		private static bool TrySetSpriteByName_Deep(object obj, string memberName, Sprite value)
		{
			if (obj == null || (Object)(object)value == (Object)null)
			{
				return false;
			}
			Type type = obj.GetType();
			while (type != null)
			{
				PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && typeof(Sprite).IsAssignableFrom(property.PropertyType) && property.CanWrite)
				{
					try
					{
						property.SetValue(obj, value, null);
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogInfo((object)("[IconSwap] Set property " + type.Name + "." + memberName));
						}
						return true;
					}
					catch
					{
					}
				}
				type = type.BaseType;
			}
			Type type2 = obj.GetType();
			while (type2 != null)
			{
				FieldInfo field = type2.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && typeof(Sprite).IsAssignableFrom(field.FieldType))
				{
					try
					{
						field.SetValue(obj, value);
						ManualLogSource log2 = Log;
						if (log2 != null)
						{
							log2.LogInfo((object)("[IconSwap] Set field " + type2.Name + "." + memberName));
						}
						return true;
					}
					catch
					{
					}
				}
				type2 = type2.BaseType;
			}
			return false;
		}

		private static void ApplyIconToToolBasic(ToolItemBasic tib, Sprite spr)
		{
			if ((Object)(object)tib == (Object)null || (Object)(object)spr == (Object)null)
			{
				return;
			}
			string[] array = new string[5] { "inventorySprite", "inventorySpritePoison", "hudSprite", "hudSpritePoison", "popupIconOverride" };
			int num = 0;
			string[] array2 = array;
			foreach (string memberName in array2)
			{
				if (TrySetSpriteByName_Deep(tib, memberName, spr))
				{
					num++;
				}
			}
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)("[IconSwap] Applied sprite to " + num + " fields/properties."));
			}
		}

		private static void TrySwapIconsFromDisk_SinglePng(ToolItemBasic tib, string fileName, float ppu = 100f)
		{
			if ((Object)(object)tib == (Object)null)
			{
				return;
			}
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (string.IsNullOrEmpty(directoryName))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)"[IconSwap] Could not resolve DLL directory.");
				}
				return;
			}
			string text = Path.Combine(directoryName, fileName);
			Sprite val = LoadSpriteFromPng_WWW(text, ppu);
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[IconSwap] Load failed: " + text));
				}
				return;
			}
			ApplyIconToToolBasic(tib, val);
			try
			{
				MethodInfo methodInfo = typeof(ToolItemManager).GetMethod("SendEquippedChangedEvent", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null) ?? typeof(ToolItemManager).GetMethod("SendEquippedChangedEvent", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				methodInfo?.Invoke(null, (!(methodInfo != null) || methodInfo.GetParameters().Length != 1) ? null : new object[1] { true });
				typeof(InventoryPaneList).GetMethod("SetNextOpen", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(null, new object[1] { "Tools" });
			}
			catch
			{
			}
		}

		private static void ApplyTextOverridesForClone(ToolItem clone)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)clone))
			{
				_cloneRef = new WeakReference<ToolItem>(clone);
				if (_textPatchHarmony == null)
				{
					_textPatchHarmony = new Harmony("com.sammods.red.spritesilk.followstrike.textoverride");
				}
				Type type = ((object)clone).GetType();
				MethodInfo methodInfo = AccessTools.PropertyGetter(type, "DisplayName");
				if (methodInfo != null)
				{
					_textPatchHarmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(RedSpriteSilkFollowAndStrikePlugin), "Postfix_DisplayName", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo2 = AccessTools.PropertyGetter(type, "Description");
				if (methodInfo2 != null)
				{
					_textPatchHarmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(RedSpriteSilkFollowAndStrikePlugin), "Postfix_Description", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo3 = AccessTools.Method(typeof(ToolItem), "GetPopupName", (Type[])null, (Type[])null);
				if (methodInfo3 != null)
				{
					_textPatchHarmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(RedSpriteSilkFollowAndStrikePlugin), "Postfix_GetPopupName", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void ApplyTypeOverrideForClone(ToolItem clone)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)clone))
			{
				if (_textPatchHarmony == null)
				{
					_textPatchHarmony = new Harmony("com.sammods.red.spritesilk.followstrike.textoverride");
				}
				MethodInfo methodInfo = AccessTools.PropertyGetter(((object)clone).GetType(), "Type");
				if (methodInfo != null)
				{
					_textPatchHarmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(RedSpriteSilkFollowAndStrikePlugin), "Postfix_Type_Red", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void ApplyUsageOverrideForClone_StopProjectile(ToolItem clone)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)clone))
			{
				if (_textPatchHarmony == null)
				{
					_textPatchHarmony = new Harmony("com.sammods.red.spritesilk.followstrike.textoverride");
				}
				MethodInfo methodInfo = AccessTools.PropertyGetter(((object)clone).GetType(), "Usage");
				if (methodInfo != null)
				{
					_textPatchHarmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(RedSpriteSilkFollowAndStrikePlugin), "Postfix_Usage_SwapToDummy", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void Postfix_DisplayName(object __instance, ref LocalisedString __result)
		{
			//IL_0021: 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)
			if (IsOurClone(__instance) && TryMakeLocalisedString("Conductor's Baton", out var result))
			{
				__result = result;
			}
		}

		private static void Postfix_Description(object __instance, ref LocalisedString __result)
		{
			//IL_0021: 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)
			if (IsOurClone(__instance) && TryMakeLocalisedString("\n A worn golden baton inlaid with special filigree. \n \n Use to inspire the soul of a fallen pilgrim to come to your aid. \n", out var result))
			{
				__result = result;
			}
		}

		private static void Postfix_GetPopupName(object __instance, ref string __result)
		{
			if (IsOurClone(__instance))
			{
				__result = ("Conductor's Baton".StartsWith("@@") ? "Conductor's Baton".Substring(2) : "Conductor's Baton");
			}
		}

		private static void Postfix_Type_Red(object __instance, ref ToolItemType __result)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected I4, but got Unknown
			if (IsOurClone(__instance))
			{
				__result = (ToolItemType)(int)_forcedTypeForClone;
			}
		}

		private static void Postfix_Usage_SwapToDummy(object __instance, ref UsageOptions __result)
		{
			if (IsOurClone(__instance))
			{
				__result.ThrowPrefab = GetOrCreateDummyThrowPrefab();
			}
		}

		private static bool IsOurClone(object inst)
		{
			if (_cloneRef == null)
			{
				return false;
			}
			ToolItem target;
			return _cloneRef.TryGetTarget(out target) && inst == target;
		}

		private static void PatchEnumerable(string methodName)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(ToolItemManager), methodName, (Type[])null, (Type[])null);
			if (!(methodInfo == null) && methodInfo.ReturnType.IsGenericType && methodInfo.ReturnType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
			{
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(RedSpriteSilkFollowAndStrikePlugin), "Postfix_AppendCloneToList", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static void Postfix_AppendCloneToList(ref IEnumerable<ToolItem> __result)
		{
			if (__result != null && !((Object)(object)_clonedTool == (Object)null) && !__result.Contains(_clonedTool))
			{
				__result = __result.Concat((IEnumerable<ToolItem>)(object)new ToolItem[1] { _clonedTool });
			}
		}

		private static bool Prefix_GetToolByName_Alias(string name, ref ToolItem __result)
		{
			if ((Object)(object)_clonedTool != (Object)null && string.Equals(name, _clonedTool.name, StringComparison.Ordinal))
			{
				__result = _clonedTool;
				return false;
			}
			return true;
		}

		private static bool EnsureCloneInToolDatabase(ToolItem clone)
		{
			if ((Object)(object)clone == (Object)null)
			{
				return false;
			}
			try
			{
				ToolItemManager instance = ManagerSingleton<ToolItemManager>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				FieldInfo field = typeof(ToolItemManager).GetField("toolItems", BindingFlags.Instance | BindingFlags.NonPublic);
				object obj = ((field != null) ? field.GetValue(instance) : null);
				if (obj == null)
				{
					return false;
				}
				IList list = null;
				PropertyInfo property = obj.GetType().GetProperty("List", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(List<>) && property.PropertyType.GetGenericArguments()[0] == typeof(ToolItem))
				{
					list = (IList)property.GetValue(obj, null);
				}
				if (list == null)
				{
					return false;
				}
				bool result = false;
				if (!list.Contains(clone))
				{
					list.Add(clone);
					result = true;
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)("[SpriteSilk] Injected '" + clone.name + "' into ToolItemList."));
					}
				}
				return result;
			}
			catch
			{
				return false;
			}
		}

		private static void TryUnlock(ToolItem tool)
		{
			try
			{
				tool.SetUnlockedTestsComplete();
				tool.Unlock((Action)null, (PopupFlags)3);
			}
			catch
			{
			}
			TrySetBoolField(tool, new string[4] { "isUnlocked", "_isUnlocked", "unlocked", "_unlocked" }, value: true);
			TrySetBoolField(tool, new string[6] { "isDiscovered", "_isDiscovered", "discovered", "_discovered", "revealed", "_revealed" }, value: true);
			TrySetBoolField(tool, new string[4] { "visibleInMenu", "_visibleInMenu", "showInInventory", "_showInInventory" }, value: true);
		}

		private static void TrySendEquippedChangedEvent(bool v)
		{
			try
			{
				MethodInfo methodInfo = typeof(ToolItemManager).GetMethod("SendEquippedChangedEvent", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null) ?? typeof(ToolItemManager).GetMethod("SendEquippedChangedEvent", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				methodInfo?.Invoke(null, (methodInfo.GetParameters().Length != 1) ? null : new object[1] { v });
			}
			catch
			{
			}
		}

		private static void TryShowQueuedReminder()
		{
			try
			{
				(typeof(ToolItemManager).GetMethod("ShowQueuedReminder", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) ?? typeof(ToolItemManager).GetMethod("ShowQueuedReminder", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.Invoke(null, null);
			}
			catch
			{
			}
		}

		private static void TrySetBoolField(object obj, string[] names, bool value)
		{
			if (obj == null)
			{
				return;
			}
			Type type = obj.GetType();
			for (int i = 0; i < names.Length; i++)
			{
				FieldInfo field = type.GetField(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && field.FieldType == typeof(bool))
				{
					try
					{
						field.SetValue(obj, value);
					}
					catch
					{
					}
				}
			}
		}

		private static void CopySpriteField(object dst, object src, string field)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			Type type = dst.GetType();
			FieldInfo field2 = type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic);
			if (field2 == null || field2.FieldType != typeof(Sprite))
			{
				return;
			}
			try
			{
				Sprite val = (Sprite)field2.GetValue(src);
				Sprite val2 = (Sprite)field2.GetValue(dst);
				if ((Object)(object)val2 == (Object)null && (Object)(object)val != (Object)null)
				{
					field2.SetValue(dst, val);
				}
			}
			catch
			{
			}
		}

		private static bool TryMakeLocalisedString(string raw, out LocalisedString result)
		{
			//IL_000d: 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_00b2: 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)
			Type typeFromHandle = typeof(LocalisedString);
			result = default(LocalisedString);
			try
			{
				MethodInfo method = typeFromHandle.GetMethod("op_Implicit", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
				if (method != null)
				{
					result = (LocalisedString)method.Invoke(null, new object[1] { raw });
					return true;
				}
				ConstructorInfo constructor = typeFromHandle.GetConstructor(new Type[2]
				{
					typeof(string),
					typeof(string)
				});
				if (constructor != null)
				{
					result = (LocalisedString)constructor.Invoke(new object[2] { "", raw });
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static void ForceRealTypeOnClone(ToolItem clone, ToolItemType type)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)clone))
			{
				return;
			}
			Type type2 = ((object)clone).GetType();
			string[] array = new string[5] { "type", "_type", "m_Type", "toolType", "ToolType" };
			string[] array2 = array;
			foreach (string name in array2)
			{
				FieldInfo field = type2.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && field.FieldType == typeof(ToolItemType))
				{
					try
					{
						field.SetValue(clone, type);
						return;
					}
					catch
					{
					}
				}
			}
			Type baseType = type2.BaseType;
			while (baseType != null)
			{
				string[] array3 = array;
				foreach (string name2 in array3)
				{
					FieldInfo field2 = baseType.GetField(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field2 != null && field2.FieldType == typeof(ToolItemType))
					{
						try
						{
							field2.SetValue(clone, type);
							return;
						}
						catch
						{
						}
					}
				}
				baseType = baseType.BaseType;
			}
		}

		private static GameObject GetOrCreateDummyThrowPrefab()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			if ((Object)(object)_dummyThrowPrefab != (Object)null)
			{
				return _dummyThrowPrefab;
			}
			GameObject val = new GameObject("SpriteSilk_DummyThrow");
			val.AddComponent<InertProjectile>();
			((Object)val).hideFlags = (HideFlags)61;
			val.layer = LayerMask.NameToLayer("Ignore Raycast");
			Object.DontDestroyOnLoad((Object)(object)val);
			_dummyThrowPrefab = val;
			return _dummyThrowPrefab;
		}

		internal static GameObject SpawnEffectByExactName(string effectName, Vector3 pos, float scale = 1f, float ttl = 3f)
		{
			//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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(effectName))
			{
				return null;
			}
			List<GameObject> list = null;
			GameObject val = null;
			try
			{
				GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
				list = new List<GameObject>(4);
				foreach (GameObject val2 in array)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						Scene scene = val2.scene;
						if (!((Scene)(ref scene)).IsValid() && ((Object)val2).name == effectName)
						{
							list.Add(val2);
						}
					}
				}
				if (list.Count == 0)
				{
					Debug.LogWarning((object)("[SpriteSilk] Effect '" + effectName + "' not found."));
					return null;
				}
				val = list[0];
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[SpriteSilk] FX search failed: " + ex.Message));
				return null;
			}
			GameObject val3 = null;
			try
			{
				val3 = Object.Instantiate<GameObject>(val, pos, Quaternion.identity);
				((Object)val3).name = "SpriteSilk_FX_" + ((Object)val).name;
				Transform transform = val3.transform;
				transform.localScale *= Mathf.Max(0.01f, scale);
				val3.SetActive(true);
				ParticleSystem[] componentsInChildren = val3.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val4 in componentsInChildren)
				{
					if (Object.op_Implicit((Object)(object)val4))
					{
						val4.Clear(true);
						val4.Play(true);
					}
				}
				if (ttl > 0f)
				{
					Object.Destroy((Object)(object)val3, ttl);
				}
			}
			catch (Exception ex2)
			{
				Debug.LogWarning((object)("[SpriteSilk] FX instantiate failed: " + ex2.Message));
				return null;
			}
			Debug.Log((object)$"[EffectFinder] Spawned: {((Object)val).name} (1/{list?.Count ?? 1})");
			return val3;
		}

		public static GameObject SpawnProjectileByName(string projName, Vector3 pos, Vector2 dir, float speedOverride = 0f)
		{
			//IL_00b4: 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_00e7: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(projName))
			{
				return null;
			}
			GameObject val = null;
			try
			{
				GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
				foreach (GameObject val2 in array)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						Scene scene = val2.scene;
						if (!((Scene)(ref scene)).IsValid() && ((Object)val2).name == projName)
						{
							val = val2;
							break;
						}
					}
				}
			}
			catch
			{
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				Debug.LogWarning((object)("[ProjFinder] '" + projName + "' not found."));
				return null;
			}
			GameObject val3 = null;
			try
			{
				val3 = Object.Instantiate<GameObject>(val, pos, Quaternion.identity);
				((Object)val3).name = "Spawn_" + projName;
				if (((Vector2)(ref dir)).sqrMagnitude > 0.0001f)
				{
					float num = Mathf.Atan2(dir.y, dir.x) * 57.29578f;
					val3.transform.rotation = Quaternion.Euler(0f, 0f, num);
				}
				Rigidbody2D val4 = val3.GetComponent<Rigidbody2D>() ?? val3.GetComponentInChildren<Rigidbody2D>();
				if (!Object.op_Implicit((Object)(object)val4))
				{
					val4 = val3.AddComponent<Rigidbody2D>();
				}
				val4.isKinematic = false;
				val4.simulated = true;
				val4.gravityScale = 0f;
				val4.angularDrag = 0f;
				val4.drag = 0f;
				val4.angularVelocity = 0f;
				RemoveGravityAndForceBehaviours(val3);
				if (((Vector2)(ref dir)).sqrMagnitude < 0.0001f)
				{
					dir = Vector2.right;
				}
				((Vector2)(ref dir)).Normalize();
				float num2;
				if (!(speedOverride > 0f))
				{
					Vector2 velocity = val4.velocity;
					if (!(((Vector2)(ref velocity)).sqrMagnitude > 0.01f))
					{
						num2 = 18f;
					}
					else
					{
						velocity = val4.velocity;
						num2 = ((Vector2)(ref velocity)).magnitude;
					}
				}
				else
				{
					num2 = speedOverride;
				}
				float num3 = num2;
				val4.velocity = dir * num3;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[ProjFinder] Instantiate failed: " + ex.Message));
				return null;
			}
			Debug.Log((object)$"[ProjFinder] Spawned '{projName}' at {val3.transform.position:F2}.");
			return val3;
		}

		private static void RemoveGravityAndForceBehaviours(GameObject go)
		{
			ConstantForce2D val = go.GetComponent<ConstantForce2D>() ?? go.GetComponentInChildren<ConstantForce2D>();
			if (Object.op_Implicit((Object)(object)val))
			{
				Object.Destroy((Object)(object)val);
			}
			MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val2))
				{
					continue;
				}
				string name = ((object)val2).GetType().Name;
				if (name.IndexOf("Homing", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Seek", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Gravity", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					((Behaviour)val2).enabled = false;
				}
				if (!(name == "PlayMakerFSM"))
				{
					continue;
				}
				try
				{
					object obj = ((object)val2).GetType().GetProperty("FsmVariables")?.GetValue(val2, null);
					MethodInfo methodInfo = obj?.GetType().GetMethod("FindFsmGameObject");
					MethodInfo methodInfo2 = obj?.GetType().GetMethod("FindFsmVector3");
					string[] array = new string[3] { "Target", "Enemy", "AimTarget" };
					string[] array2 = array;
					foreach (string text in array2)
					{
						object obj2 = methodInfo?.Invoke(obj, new object[1] { text });
						obj2?.GetType().GetProperty("Value")?.SetValue(obj2, null, null);
					}
					string[] array3 = new string[3] { "Target Pos", "TargetPos", "AimPos" };
					string[] array4 = array3;
					foreach (string text2 in array4)
					{
						object obj3 = methodInfo2?.Invoke(obj, new object[1] { text2 });
						obj3?.GetType().GetProperty("UseVariable")?.SetValue(obj3, true, null);
					}
				}
				catch
				{
				}
			}
		}
	}
	internal sealed class RedSilkManager : MonoBehaviour
	{
		private string _fxName;

		private string _projName;

		private Vector3 _followOffset;

		private float _followSmooth;

		private float _followMaxLag;

		private float _hudSortBump;

		private float _seekRadius;

		private float _stopDist;

		private float _seekSpeed;

		private float _turnAccel;

		private int _losMask;

		private float _losPoll;

		private float _cooldown;

		private float _snapshotLead;

		private float _projSpeedOverride;

		private int _shotsToLive;

		private Transform _hero;

		private GameObject _silkAnchor;

		private GameObject _silkFX;

		private LooseFollower _follower;

		private SeekerShooter _seeker;

		public void Configure(string fxName, string projName, Vector3 followOffset, float followSmooth, float followMaxLag, float hudSortBump, float seekRadius, float stopDist, float seekSpeed, float turnAccel, int losMask, float losPoll, float cooldown, float snapshotLead, float projectileSpeedOverride, int shotsToLive)
		{
			//IL_0010: 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)
			_fxName = fxName;
			_projName = projName;
			_followOffset = followOffset;
			_followSmooth = followSmooth;
			_followMaxLag = followMaxLag;
			_hudSortBump = hudSortBump;
			_seekRadius = seekRadius;
			_stopDist = stopDist;
			_seekSpeed = seekSpeed;
			_turnAccel = turnAccel;
			_losMask = losMask;
			_losPoll = losPoll;
			_cooldown = cooldown;
			_snapshotLead = snapshotLead;
			_projSpeedOverride = projectileSpeedOverride;
			_shotsToLive = Mathf.Max(1, shotsToLive);
		}

		public void BindTarget(Transform t)
		{
			_hero = t;
			if ((Object)(object)_follower != (Object)null)
			{
				_follower.Target = _hero;
			}
		}

		public void SpawnOrRefreshSilk(Transform target)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			BindTarget(target);
			if ((Object)(object)_silkAnchor == (Object)null)
			{
				_silkAnchor = new GameObject("SpriteSilk_Anchor");
				_silkAnchor.transform.SetParent(((Component)this).transform, true);
			}
			if ((Object)(object)_hero != (Object)null)
			{
				float num = 1f;
				try
				{
					HeroController instance = HeroController.instance;
					if ((Object)(object)instance != (Object)null)
					{
						num = (instance.cState.facingRight ? 1f : (-1f));
					}
				}
				catch
				{
				}
				_silkAnchor.transform.position = _hero.position + new Vector3(_followOffset.x * num, _followOffset.y, _followOffset.z);
			}
			if ((Object)(object)_silkFX == (Object)null)
			{
				_silkFX = RedSpriteSilkFollowAndStrikePlugin.SpawnEffectByExactName(_fxName, _silkAnchor.transform.position, 1f, 0f);
				if ((Object)(object)_silkFX != (Object)null)
				{
					_silkFX.transform.SetParent(_silkAnchor.transform, true);
					_silkFX.transform.localPosition = Vector3.zero;
					try
					{
						Renderer[] componentsInChildren = _silkFX.GetComponentsInChildren<Renderer>(true);
						Renderer[] array = componentsInChildren;
						foreach (Renderer val in array)
						{
							if (Object.op_Implicit((Object)(object)val))
							{
								val.sortingOrder += (int)_hudSortBump;
							}
						}
					}
					catch
					{
					}
				}
			}
			else
			{
				_silkFX.SetActive(true);
			}
			_follower = _silkAnchor.GetComponent<LooseFollower>() ?? _silkAnchor.AddComponent<LooseFollower>();
			_follower.Target = _hero;
			_follower.Offset = _followOffset;
			_follower.SmoothTime = _followSmooth;
			_follower.MaxLag = _followMaxLag;
			_seeker = _silkAnchor.GetComponent<SeekerShooter>() ?? _silkAnchor.AddComponent<SeekerShooter>();
			_seeker.Init(_follower, _silkFX, _projName, _seekRadius, _stopDist, _seekSpeed, _turnAccel, _losMask, _losPoll, _cooldown, _snapshotLead, _projSpeedOverride, _shotsToLive);
		}
	}
	internal sealed class LooseFollower : MonoBehaviour
	{
		public Transform Target;

		public Vector3 Offset;

		public float SmoothTime = 0.15f;

		public float MaxLag = 2.25f;

		private Vector3 _vel;

		private float _lastFacing = 1f;

		public bool Paused { get; private set; }

		private void OnEnable()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			_vel = Vector3.zero;
			Vector3 val = ((Component)HeroController.instance).transform.position + new Vector3(0f, 0.25f, 0f);
			RedSpriteSilkFollowAndStrikePlugin.SpawnEffectByExactName("rune_particle_burst", val + new Vector3(0f, 0f, 0f));
			LooseFollower[] components = ((Component)this).GetComponents<LooseFollower>();
			for (int i = 0; i < components.Length; i++)
			{
				if ((Object)(object)components[i] != (Object)(object)this)
				{
					Object.Destroy((Object)(object)components[i]);
				}
			}
		}

		public void ForcePosition(Vector3 pos)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.position = pos;
			_vel = Vector3.zero;
		}

		public void SetPaused(bool v)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Paused = v;
			if (v)
			{
				_vel = Vector3.zero;
			}
		}

		private void LateUpdate()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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)
			if (!Paused && Object.op_Implicit((Object)(object)Target))
			{
				HeroController instance = HeroController.instance;
				if (Object.op_Implicit((Object)(object)instance))
				{
					_lastFacing = (instance.cState.facingRight ? 1f : (-1f));
				}
				Vector3 val = Target.position + new Vector3(Offset.x * _lastFacing, Offset.y, Offset.z);
				Vector3 position = ((Component)this).transform.position;
				float num = Vector3.Distance(position, val);
				float num2 = ((num > MaxLag) ? Mathf.Max(0.04f, SmoothTime * 0.5f) : SmoothTime);
				float num3 = Mathf.Max(0.0001f, Time.unscaledDeltaTime);
				Vector3 position2 = Vector3.SmoothDamp(position, val, ref _vel, num2, float.PositiveInfinity, num3);
				((Component)this).transform.position = position2;
			}
		}
	}
	internal sealed class SeekerShooter : MonoBehaviour
	{
		private enum Phase
		{
			Follow,
			Seek,
			Cooldown
		}

		private struct EnemyInfo
		{
			public HealthManager HM;

			public Transform Transform;

			public Vector2 Velocity;

			public Vector2 TargetPoint2D;

			public bool IsValid => (Object)(object)Transform != (Object)null;
		}

		private LooseFollower _follow;

		private GameObject _fxRoot;

		private string _projName;

		private float _seekRadius;

		private float _stopDist;

		private float _speed;

		private float _turnAccel;

		private float _losPoll;

		private float _cooldown;

		private float _snapshotLead;

		private float _projSpeedOverride;

		private int _losMask;

		private int _shotsToLive;

		private Transform _hero;

		private float _nextLosCheck;

		private Vector2 _seekVel;

		private float _cooldownUntil;

		private int _shotsFired;

		private readonly List<HealthManager> _tracked = new List<HealthManager>(32);

		private float _nextScanAt;

		private Phase _phase;

		private EnemyInfo _target;

		public void Init(LooseFollower follow, GameObject fxRoot, string projectileName, float seekRadius, float stopDistance, float speed, float turnAccel, int losMask, float losPoll, float cooldown, float snapshotLeadSeconds, float projectileSpeedOverride, int shotsToLive)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			_follow = follow;
			_fxRoot = fxRoot;
			_projName = projectileName;
			_seekRadius = Mathf.Max(0.1f, seekRadius);
			_stopDist = Mathf.Max(0.25f, stopDistance);
			_speed = Mathf.Max(0.1f, speed);
			_turnAccel = Mathf.Max(0.1f, turnAccel);
			_losMask = losMask;
			_losPoll = Mathf.Max(0.02f, losPoll);
			_cooldown = Mathf.Max(0.05f, cooldown);
			_snapshotLead = Mathf.Max(0f, snapshotLeadSeconds);
			_projSpeedOverride = Mathf.Max(0f, projectileSpeedOverride);
			_shotsToLive = Mathf.Max(1, shotsToLive);
			_hero = (Object.op_Implicit((Object)(object)HeroController.instance) ? ((Component)HeroController.instance).transform : null);
			_phase = Phase.Follow;
			_target = default(EnemyInfo);
			_seekVel = Vector2.zero;
			_cooldownUntil = 0f;
			_nextLosCheck = 0f;
			_shotsFired = 0;
		}

		private void Update()
		{
			if (!Object.op_Implicit((Object)(object)_hero))
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			switch (_phase)
			{
			case Phase.Follow:
				TickFollow();
				break;
			case Phase.Seek:
				TickSeek();
				break;
			case Phase.Cooldown:
				if (Time.unscaledTime >= _cooldownUntil)
				{
					EnterFollow();
				}
				break;
			}
		}

		private void EnterFollow()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			_phase = Phase.Follow;
			_seekVel = Vector2.zero;
			_follow?.SetPaused(v: false);
		}

		private void EnterSeek()
		{
			//IL_002d: 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)
			_phase = Phase.Seek;
			_follow?.SetPaused(v: true);
			_follow?.ForcePosition(((Component)this).transform.position);
			_seekVel = Vector2.zero;
		}

		private void TickFollow()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (Time.unscaledTime >= _nextLosCheck)
			{
				_nextLosCheck = Time.unscaledTime + _losPoll;
				_target = AcquireEnemyLikeNeedolin(((Component)this).transform.position, _seekRadius, _losMask);
				if (_target.IsValid)
				{
					EnterSeek();
				}
			}
		}

		private void TickSeek()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00b2: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unk