Decompiled source of RasenganSpell v1.0.2

BepInEx\plugins\RasenganSpell\RasenganSpell.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BlackMagicAPI.Managers;
using BlackMagicAPI.Modules.Spells;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
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: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RasenganSpell
{
	[RequireComponent(typeof(SphereCollider))]
	[RequireComponent(typeof(Rigidbody))]
	public sealed class RasenganCollision : MonoBehaviour
	{
		[Header("Damage")]
		public float baseDamage = 24f;

		public float damagePerLevel = 4f;

		public int castingLevel = 1;

		[Header("Collision")]
		public float triggerRadius = 0.6f;

		public float lifeSeconds;

		[Header("Player Knockback (via PlayerMovement)")]
		public float knockbackLevelDistPerLevel = 0.4f;

		public float knockbackLevelDistMax = 3f;

		private Transform _ownerRoot;

		private Collider[] _ownerCols = Array.Empty<Collider>();

		private Collider[] _pageCols = Array.Empty<Collider>();

		private SphereCollider _myCol;

		private bool _consumed;

		public Transform OwnerRoot => _ownerRoot;

		public bool IsOwnedBy(Transform t)
		{
			return (Object)(object)_ownerRoot == (Object)(object)t;
		}

		public void Init(Transform ownerRoot, int level, Collider[] pageColliders, float life)
		{
			_ownerRoot = ownerRoot;
			castingLevel = Mathf.Max(1, level);
			_pageCols = pageColliders ?? Array.Empty<Collider>();
			lifeSeconds = life;
		}

		private void Awake()
		{
			_myCol = ((Component)this).GetComponent<SphereCollider>();
			((Collider)_myCol).isTrigger = true;
			_myCol.radius = triggerRadius * 2f;
			Rigidbody component = ((Component)this).GetComponent<Rigidbody>();
			component.isKinematic = true;
			component.useGravity = false;
			if (lifeSeconds > 0f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject, lifeSeconds);
			}
		}

		private void OnEnable()
		{
			RasenganOrbRegistry.Register(this);
		}

		private void OnDestroy()
		{
			RasenganOrbRegistry.Unregister(this);
		}

		private void Start()
		{
			_ownerCols = (Object.op_Implicit((Object)(object)_ownerRoot) ? ((Component)_ownerRoot).GetComponentsInChildren<Collider>(true) : Array.Empty<Collider>());
			IgnoreSet(_ownerCols, "owner");
			IgnoreSet(_pageCols, "page");
			ManualLogSource log = RasenganPlugin.Log;
			if (log != null)
			{
				Transform ownerRoot = _ownerRoot;
				log.LogInfo((object)("[RasenganCollision] Ready. ownerRoot=" + (((ownerRoot != null) ? ((Object)ownerRoot).name : null) ?? "null") + ", " + $"ownerCols={_ownerCols.Length}, pageCols={_pageCols.Length}, layer={((Component)this).gameObject.layer}"));
			}
		}

		private void IgnoreSet(Collider[] cols, string label)
		{
			if (cols == null || cols.Length == 0)
			{
				return;
			}
			int num = 0;
			foreach (Collider val in cols)
			{
				if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val == (Object)(object)_myCol))
				{
					Physics.IgnoreCollision((Collider)(object)_myCol, val, true);
					num++;
				}
			}
			ManualLogSource log = RasenganPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"[RasenganCollision] Ignoring {num}/{cols.Length} colliders from {label} set.");
			}
		}

		private void OnTriggerEnter(Collider other)
		{
			if (_consumed || !Object.op_Implicit((Object)(object)other))
			{
				return;
			}
			PlayerMovement componentInParent = ((Component)other).GetComponentInParent<PlayerMovement>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				if (Object.op_Implicit((Object)(object)_ownerRoot) && (Object)(object)((Component)componentInParent).transform.root == (Object)(object)_ownerRoot)
				{
					Physics.IgnoreCollision((Collider)(object)_myCol, other, true);
					ManualLogSource log = RasenganPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)"[RasenganCollision] Ignoring owner (player).");
					}
				}
				else if (DamagePlayer(componentInParent))
				{
					ApplyPlayerKnockbackViaPM(componentInParent, castingLevel);
					Consume("player");
				}
				else
				{
					ManualLogSource log2 = RasenganPlugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)"[RasenganCollision] PlayerMovement found but no usable damage method.");
					}
					Physics.IgnoreCollision((Collider)(object)_myCol, other, true);
				}
			}
			else if (IsOurPageCollider(other))
			{
				Physics.IgnoreCollision((Collider)(object)_myCol, other, true);
				ManualLogSource log3 = RasenganPlugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)"[RasenganCollision] Ignoring our page collider.");
				}
			}
			else if (DamageMonster(other))
			{
				Consume("monster");
			}
			else
			{
				ManualLogSource log4 = RasenganPlugin.Log;
				if (log4 != null)
				{
					log4.LogInfo((object)("[RasenganCollision] Non-target contact with '" + ((Object)other).name + "'. Ignoring and continuing."));
				}
				Physics.IgnoreCollision((Collider)(object)_myCol, other, true);
			}
		}

		private bool IsOurPageCollider(Collider c)
		{
			if (!Object.op_Implicit((Object)(object)c) || _pageCols == null)
			{
				return false;
			}
			Collider[] pageCols = _pageCols;
			foreach (Collider val in pageCols)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					if ((Object)(object)c == (Object)(object)val)
					{
						return true;
					}
					if (((Component)c).transform.IsChildOf(((Component)val).transform))
					{
						return true;
					}
				}
			}
			return false;
		}

		private float ComputeDamage()
		{
			return baseDamage + damagePerLevel * (float)Mathf.Max(0, castingLevel - 1);
		}

		private bool DamagePlayer(PlayerMovement pm)
		{
			try
			{
				float num = ComputeDamage();
				GameObject val = (Object.op_Implicit((Object)(object)_ownerRoot) ? ((Component)_ownerRoot).gameObject : ((Component)this).gameObject);
				ManualLogSource log = RasenganPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[RasenganCollision] Player hit '{pm.playername}' dmg={num}");
				}
				pm.DamagePlayer(num, val, "rasengan");
				return true;
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = RasenganPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)$"[RasenganCollision] DamagePlayer failed: {arg}");
				}
				return false;
			}
		}

		private bool DamageMonster(Collider other)
		{
			try
			{
				float num = ComputeDamage() * 10f;
				MonsterHitScript component = ((Component)other).gameObject.GetComponent<MonsterHitScript>();
				if ((Object)(object)component == (Object)null)
				{
					return false;
				}
				if (((Object)((Component)component).gameObject).name == "wizardtrio (1)")
				{
					return false;
				}
				component.HitTheMonster(num);
				ManualLogSource log = RasenganPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[RasenganCollision] Monster killed '" + ((Object)((Component)component).gameObject).name + "' via " + ((object)component).GetType().Name + ".HitTheMonster"));
				}
				return true;
			}
			catch (Exception arg)
			{
				ManualLogSource log2 = RasenganPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)$"[RasenganCollision] DamageMonster failed: {arg}");
				}
				return false;
			}
		}

		private void ApplyPlayerKnockbackViaPM(PlayerMovement pm, int level)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0063: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Vector3 val = ((Component)this).transform.position - ((Component)pm).transform.position;
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				float num = Mathf.Clamp((float)(3 * level) * knockbackLevelDistPerLevel, 0f, 3f * knockbackLevelDistMax);
				Vector3 val2 = normalized * num;
				GameObject val3 = new GameObject();
				val3.transform.position = ((Component)this).transform.position + 3f * val2;
				pm.ApplyKnockback(val3);
				Object.Destroy((Object)(object)val3);
				pm.velocity.y = 10f + num / 4f;
			}
			catch (Exception arg)
			{
				ManualLogSource log = RasenganPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)$"[RasenganCollision] ApplyPlayerKnockbackViaPM failed: {arg}");
				}
			}
		}

		private void Consume(string reason)
		{
			if (!_consumed)
			{
				_consumed = true;
				if (Object.op_Implicit((Object)(object)_myCol))
				{
					((Collider)_myCol).enabled = false;
				}
				ManualLogSource log = RasenganPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[RasenganCollision] Consumed (" + reason + ")."));
				}
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	public class RasenganData : SpellData
	{
		public override string Name => "Rasengan";

		public override float Cooldown => 26f;

		public override Color GlowColor => new Color(0.2f, 0.6f, 1f, 1f);

		public override string[] SubNames => new string[5] { "rasengan", "ramen", "rasen", "gan", "gone" };
	}
	public class RasenganFXController : MonoBehaviour
	{
		public enum AxisSpace
		{
			World,
			Self
		}

		[Serializable]
		public class Layer
		{
			public Transform Transform;

			public float SpinSpeed = 600f;

			public AxisSpace AxisSpace = AxisSpace.Self;

			public Vector3 Axis = Vector3.up;
		}

		public List<Layer> layers = new List<Layer>();

		private void Update()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			foreach (Layer layer in layers)
			{
				if (Object.op_Implicit((Object)(object)layer.Transform))
				{
					Vector3 val = ((layer.AxisSpace == AxisSpace.Self) ? layer.Transform.TransformDirection(layer.Axis) : layer.Axis);
					layer.Transform.Rotate(((Vector3)(ref val)).normalized, layer.SpinSpeed * Time.deltaTime, (Space)0);
				}
			}
		}

		public static RasenganFXController AttachAndAutoSetup(GameObject root)
		{
			//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_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)root))
			{
				return null;
			}
			RasenganFXController rasenganFXController = root.GetComponent<RasenganFXController>();
			if (!Object.op_Implicit((Object)(object)rasenganFXController))
			{
				rasenganFXController = root.AddComponent<RasenganFXController>();
			}
			rasenganFXController.layers.Clear();
			Transform val = null;
			Transform val2 = null;
			Transform val3 = null;
			MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val4 in componentsInChildren)
			{
				string text = ((Object)val4).name.ToLowerInvariant();
				if ((Object)(object)val == (Object)null && (text.Contains("plane 12") || text.Contains("plane12")))
				{
					val = ((Component)val4).transform;
				}
				else if ((Object)(object)val2 == (Object)null && (text.Contains("plane 1") || text.Contains("plane1")))
				{
					val2 = ((Component)val4).transform;
				}
				else if ((Object)(object)val3 == (Object)null && (text == "plane" || text.Contains("plane")))
				{
					val3 = ((Component)val4).transform;
				}
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				rasenganFXController.layers.Add(new Layer
				{
					Transform = val,
					SpinSpeed = 1200f,
					AxisSpace = AxisSpace.World,
					Axis = new Vector3(1f, 1f, 1f)
				});
			}
			if (Object.op_Implicit((Object)(object)val2))
			{
				rasenganFXController.layers.Add(new Layer
				{
					Transform = val2,
					SpinSpeed = 600f,
					AxisSpace = AxisSpace.Self,
					Axis = new Vector3(1f, 1f, -1f)
				});
			}
			if (Object.op_Implicit((Object)(object)val3))
			{
				rasenganFXController.layers.Add(new Layer
				{
					Transform = val3,
					SpinSpeed = 600f,
					AxisSpace = AxisSpace.Self,
					Axis = new Vector3(0f, 1f, 1f)
				});
			}
			return rasenganFXController;
		}
	}
	public class RasenganLogic : SpellLogic
	{
		public sealed class RasenganHoldExtend : MonoBehaviour
		{
			private Transform _anchor;

			private Vector3 _homePos;

			private Quaternion _homeRot;

			private Vector3 _extendedOffset;

			private Quaternion _extendedRot;

			private float _moveLambda = 10f;

			private float _rotLambda = 10f;

			private Vector3 _targetPos;

			private Quaternion _targetRot;

			public void Init(Transform anchor, Vector3 homePos, Quaternion homeRot, Vector3 extendedOffset, Vector3 extendedTiltEuler, float moveLambda = 10f, float rotateLambda = 10f)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: 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_0027: 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_002f: 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_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				_anchor = (((Object)(object)anchor != (Object)null) ? anchor : ((Component)this).transform.parent);
				_homePos = homePos;
				_homeRot = homeRot;
				_extendedOffset = extendedOffset;
				_extendedRot = homeRot * Quaternion.Euler(extendedTiltEuler);
				_moveLambda = Mathf.Max(1f, moveLambda);
				_rotLambda = Mathf.Max(1f, rotateLambda);
				_targetPos = _homePos;
				_targetRot = _homeRot;
				if (Object.op_Implicit((Object)(object)_anchor) && (Object)(object)((Component)this).transform.parent != (Object)(object)_anchor)
				{
					((Component)this).transform.SetParent(_anchor, false);
				}
			}

			private void Update()
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: 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_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				bool flag = RasenganPlugin.HoldActive();
				_targetPos = (flag ? (_homePos + _extendedOffset) : _homePos);
				_targetRot = (flag ? _extendedRot : _homeRot);
				float num = 1f - Mathf.Exp((0f - _moveLambda) * Time.deltaTime);
				float num2 = 1f - Mathf.Exp((0f - _rotLambda) * Time.deltaTime);
				((Component)this).transform.localPosition = Vector3.Lerp(((Component)this).transform.localPosition, _targetPos, num);
				((Component)this).transform.localRotation = Quaternion.Slerp(((Component)this).transform.localRotation, _targetRot, num2);
				if (Object.op_Implicit((Object)(object)_anchor) && (Object)(object)((Component)this).transform.parent != (Object)(object)_anchor)
				{
					((Component)this).transform.SetParent(_anchor, false);
				}
			}
		}

		private sealed class PageVisibilityLatch : MonoBehaviour
		{
			private Renderer[] _renderers;

			private int _locks;

			private void Awake()
			{
				_renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
			}

			public static PageVisibilityLatch GetOrAdd(GameObject go)
			{
				PageVisibilityLatch pageVisibilityLatch = go.GetComponent<PageVisibilityLatch>();
				if (!Object.op_Implicit((Object)(object)pageVisibilityLatch))
				{
					pageVisibilityLatch = go.AddComponent<PageVisibilityLatch>();
				}
				return pageVisibilityLatch;
			}

			public void Acquire()
			{
				if (_locks == 0)
				{
					SetVisible(v: false);
				}
				_locks++;
			}

			public void Release()
			{
				_locks = Mathf.Max(0, _locks - 1);
				if (_locks == 0)
				{
					SetVisible(v: true);
				}
			}

			private void SetVisible(bool v)
			{
				if (_renderers == null || _renderers.Length == 0)
				{
					_renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
				}
				Renderer[] renderers = _renderers;
				foreach (Renderer val in renderers)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						val.enabled = v;
					}
				}
			}
		}

		private sealed class ReleaseOnDestroy : MonoBehaviour
		{
			private PageVisibilityLatch _latch;

			public void Init(PageVisibilityLatch latch)
			{
				_latch = latch;
			}

			private void OnDestroy()
			{
				if (Object.op_Implicit((Object)(object)_latch))
				{
					_latch.Release();
				}
			}

			private void OnDisable()
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)_latch))
				{
					Scene scene = ((Component)this).gameObject.scene;
					if (!((Scene)(ref scene)).isLoaded)
					{
						_latch.Release();
					}
				}
			}
		}

		private sealed class PageRasenganSentinel : MonoBehaviour
		{
			private Transform _ownerRoot;

			public void Init(Transform ownerRoot)
			{
				_ownerRoot = ownerRoot;
			}

			private void OnDisable()
			{
				Cleanup("page-disabled");
			}

			private void OnDestroy()
			{
				Cleanup("page-destroyed");
			}

			private void Cleanup(string reason)
			{
				Transform val = (Object.op_Implicit((Object)(object)_ownerRoot) ? _ownerRoot : ((Component)this).transform.root);
				if (Object.op_Implicit((Object)(object)val))
				{
					RasenganOrbRegistry.DestroyAllUnder(val, reason);
				}
			}
		}

		[SerializeField]
		private GameObject activeOrb;

		public static float lifeSeconds = 10f;

		public override bool CastSpell(PlayerMovement player, PageController page, Vector3 spawnPos, Vector3 dir, int castingLevel)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource log = RasenganPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[Rasengan] CastSpell invoked.");
			}
			if ((Object)(object)page == (Object)null)
			{
				ManualLogSource log2 = RasenganPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"[Rasengan] CastSpell: page was null.");
				}
				return false;
			}
			PageVisibilityLatch orAdd = PageVisibilityLatch.GetOrAdd(((Component)page).gameObject);
			orAdd.Acquire();
			activeOrb = TrySpawnFromBundle("rasengan", "TheRasengan", ((Component)page).transform, Vector3.zero);
			if (!Object.op_Implicit((Object)(object)activeOrb))
			{
				orAdd.Release();
				return false;
			}
			activeOrb.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
			RasenganFXController.AttachAndAutoSetup(activeOrb);
			AudioSource component = activeOrb.GetComponent<AudioSource>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.playOnAwake = false;
				component.loop = true;
				component.spatialBlend = 1f;
				component.rolloffMode = (AudioRolloffMode)1;
				component.minDistance = 4f;
				component.maxDistance = 22f;
				component.dopplerLevel = 0f;
				component.volume = Mathf.Clamp01(component.volume * RasenganPlugin.AudioVolumeMultiplier);
			}
			Collider[] componentsInChildren = ((Component)page).GetComponentsInChildren<Collider>(true);
			PlayerInventory val = (Object.op_Implicit((Object)(object)page) ? ((Component)page).GetComponentInParent<PlayerInventory>() : null);
			Transform val2 = (((Object)(object)player != (Object)null) ? ((Component)player).transform.root : (Object.op_Implicit((Object)(object)val) ? ((Component)val).transform.root : ((Component)page).transform.root));
			GameObject val3 = ((Object.op_Implicit((Object)(object)page) && Object.op_Implicit((Object)(object)page.pagerender)) ? ((Component)page.pagerender).gameObject : ((Component)page).gameObject);
			PageRasenganSentinel pageRasenganSentinel = val3.GetComponent<PageRasenganSentinel>() ?? val3.AddComponent<PageRasenganSentinel>();
			pageRasenganSentinel.Init(val2);
			ManualLogSource log3 = RasenganPlugin.Log;
			if (log3 != null)
			{
				log3.LogDebug((object)$"[Rasengan] Page collider count={componentsInChildren.Length}");
			}
			RasenganCollision rasenganCollision = activeOrb.GetComponent<RasenganCollision>();
			if (!Object.op_Implicit((Object)(object)rasenganCollision))
			{
				rasenganCollision = activeOrb.AddComponent<RasenganCollision>();
			}
			rasenganCollision.Init(val2, castingLevel, componentsInChildren, lifeSeconds);
			activeOrb.transform.localPosition = new Vector3(0f, 0f, 0.3f);
			activeOrb.transform.localRotation = Quaternion.identity;
			RasenganHoldExtend rasenganHoldExtend = activeOrb.AddComponent<RasenganHoldExtend>();
			rasenganHoldExtend.Init(((Component)page).transform, activeOrb.transform.localPosition, activeOrb.transform.localRotation, new Vector3(0.05f, 0.55f, -0.3f), new Vector3(-6f, 0f, -10f));
			ReleaseOnDestroy releaseOnDestroy = activeOrb.AddComponent<ReleaseOnDestroy>();
			releaseOnDestroy.Init(orAdd);
			Object.Destroy((Object)(object)activeOrb, lifeSeconds);
			ManualLogSource log4 = RasenganPlugin.Log;
			if (log4 != null)
			{
				log4.LogDebug((object)string.Format("[Rasengan] Orb ready. owner='{0}', level={1}", ((val2 != null) ? ((Object)val2).name : null) ?? "null", castingLevel));
			}
			return true;
		}

		private static GameObject TrySpawnFromBundle(string bundleBaseName, string prefabName, Transform parent, Vector3 localPos)
		{
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string pluginDir = RasenganPlugin.PluginDir;
				string text = Path.Combine(pluginDir, "Assets", bundleBaseName + ".bundle");
				string text2 = Path.Combine(pluginDir, bundleBaseName + ".bundle");
				string text3 = Path.Combine(pluginDir, bundleBaseName ?? "");
				string text4 = Path.Combine(pluginDir, "RasenganSpell", bundleBaseName + ".bundle");
				string text5 = null;
				if (File.Exists(text))
				{
					text5 = text;
				}
				else if (File.Exists(text2))
				{
					text5 = text2;
				}
				else if (File.Exists(text3))
				{
					text5 = text3;
				}
				else if (File.Exists(text4))
				{
					text5 = text4;
				}
				if (text5 == null)
				{
					ManualLogSource log = RasenganPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[Rasengan] Bundle not found. Tried: " + text + ", " + text2 + ", " + text3 + ", " + text4));
					}
					return null;
				}
				AssetBundle val = AssetBundle.LoadFromFile(text5);
				if (!Object.op_Implicit((Object)(object)val))
				{
					ManualLogSource log2 = RasenganPlugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)("[Rasengan] Failed to load AssetBundle: " + text5));
					}
					return null;
				}
				GameObject val2 = val.LoadAsset<GameObject>(prefabName);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					ManualLogSource log3 = RasenganPlugin.Log;
					if (log3 != null)
					{
						log3.LogWarning((object)("[Rasengan] Prefab '" + prefabName + "' not found in bundle: " + text5));
					}
					val.Unload(false);
					return null;
				}
				GameObject val3 = Object.Instantiate<GameObject>(val2);
				if (Object.op_Implicit((Object)(object)parent))
				{
					val3.transform.SetParent(parent, false);
					val3.transform.localPosition = localPos;
				}
				val.Unload(false);
				return val3;
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = RasenganPlugin.Log;
				if (log4 != null)
				{
					log4.LogWarning((object)("[Rasengan] Bundle spawn failed: " + ex.Message));
				}
				return null;
			}
		}
	}
	internal static class RasenganOrbRegistry
	{
		private static readonly HashSet<RasenganCollision> _all = new HashSet<RasenganCollision>();

		public static void Register(RasenganCollision c)
		{
			if (!((Object)(object)c == (Object)null))
			{
				_all.Add(c);
			}
		}

		public static void Unregister(RasenganCollision c)
		{
			if (!((Object)(object)c == (Object)null))
			{
				_all.Remove(c);
			}
		}

		public static int DestroyAllUnder(Transform root, string reason)
		{
			if ((Object)(object)root == (Object)null)
			{
				return 0;
			}
			int num = 0;
			List<RasenganCollision> list = new List<RasenganCollision>(_all);
			foreach (RasenganCollision item in list)
			{
				if ((Object)(object)item == (Object)null)
				{
					_all.Remove(item);
				}
				else if ((Object)(object)item.OwnerRoot == (Object)(object)root)
				{
					Object.Destroy((Object)(object)((Component)item).gameObject);
					num++;
				}
			}
			ManualLogSource log = RasenganPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"[Rasengan/OrbRegistry] Destroyed {num} orb(s) under '{((Object)root).name}' due to {reason}.");
			}
			return num;
		}
	}
	[BepInProcess("MageArena")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.mre42.rasengan", "RasenganSpell", "1.0.2")]
	public class RasenganPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.mre42.rasengan";

		public static string modsync = "all";

		private static bool debug = false;

		private static ConfigEntry<string> _moveHoldBinding;

		private static ConfigEntry<float> _volume;

		private static int _mouseButtonIndex = -1;

		private static KeyCode _holdKeyCode = (KeyCode)0;

		public static ManualLogSource Log { get; private set; }

		public static string PluginDir { get; private set; }

		public static float AudioVolumeMultiplier => Mathf.Clamp01(_volume?.Value ?? 0.75f);

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			PluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Directory.GetCurrentDirectory();
			Log.LogInfo((object)("[Rasengan] PluginDir = " + PluginDir));
			_moveHoldBinding = ((BaseUnityPlugin)this).Config.Bind<string>("Controls", "MoveHold", "Mouse0", "Key/button to hold for Rasengan 'extend/move' behavior. Examples: Mouse0, Mouse1, E, LeftShift");
			_volume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Volume", 0.75f, "Rasengan audio volume multiplier (0.0 - 1.0).");
			ParseMoveHold(_moveHoldBinding.Value);
			_moveHoldBinding.SettingChanged += delegate
			{
				ParseMoveHold(_moveHoldBinding.Value);
			};
			_volume.SettingChanged += delegate
			{
			};
			try
			{
				BlackMagicManager.RegisterSpell((BaseUnityPlugin)(object)this, typeof(RasenganData), typeof(RasenganLogic));
				BlackMagicManager.RegisterDeathIcon((BaseUnityPlugin)(object)this, "rasengan", "Rasengan_Death");
				Log.LogInfo((object)"[Rasengan] Registered Rasengan spell with BlackMagic.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"[Rasengan] RegisterSpell failed: {arg}");
			}
			RenderPipelineAsset currentRenderPipeline = GraphicsSettings.currentRenderPipeline;
			string text = (((Object)(object)currentRenderPipeline == (Object)null) ? "Built-in (no SRP)" : ((object)currentRenderPipeline).GetType().FullName);
			Log.LogInfo((object)("[Rasengan] Render Pipeline: " + text));
			Log.LogInfo((object)("[Rasengan] Shader.globalRenderPipeline = '" + Shader.globalRenderPipeline + "'"));
		}

		private void Update()
		{
			//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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00c5: 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_00d4: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			if (!Input.GetKeyDown((KeyCode)287) || !debug)
			{
				return;
			}
			try
			{
				Camera main = Camera.main;
				Transform val = (Object.op_Implicit((Object)(object)main) ? ((Component)main).transform : null);
				if ((Object)(object)val == (Object)null)
				{
					Scene activeScene = SceneManager.GetActiveScene();
					GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
					GameObject[] array = rootGameObjects;
					foreach (GameObject val2 in array)
					{
						if (Object.op_Implicit((Object)(object)val2) && val2.activeInHierarchy)
						{
							val = val2.transform;
							break;
						}
					}
				}
				Vector3 value = (Object.op_Implicit((Object)(object)val) ? (val.position + val.forward * 0.7f + val.up * 0.1f) : Vector3.zero);
				Quaternion value2 = (Object.op_Implicit((Object)(object)val) ? Quaternion.LookRotation(val.forward, Vector3.up) : Quaternion.identity);
				BlackMagicManager.SpawnSpell<RasenganLogic>((Vector3?)value, (Quaternion?)value2);
				Log.LogInfo((object)"[Rasengan] Debug page request (F6) spawned at camera.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[Rasengan] F6 page spawn failed (" + ex.Message + ")."));
			}
		}

		public static bool HoldActive()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (_mouseButtonIndex >= 0)
			{
				return Input.GetMouseButton(_mouseButtonIndex);
			}
			if ((int)_holdKeyCode > 0)
			{
				return Input.GetKey(_holdKeyCode);
			}
			return Input.GetMouseButton(0);
		}

		private static void ParseMoveHold(string raw)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			_mouseButtonIndex = -1;
			_holdKeyCode = (KeyCode)0;
			if (string.IsNullOrWhiteSpace(raw))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)"[Rasengan] Controls.MoveHold was empty; defaulting to Mouse0.");
				}
				_mouseButtonIndex = 0;
				return;
			}
			raw = raw.Trim();
			KeyCode result2;
			if (raw.StartsWith("Mouse", StringComparison.InvariantCultureIgnoreCase))
			{
				string s = raw.Substring("Mouse".Length);
				if (int.TryParse(s, out var result) && result >= 0 && result <= 2)
				{
					_mouseButtonIndex = result;
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"[Rasengan] MoveHold bound to Mouse{result}.");
					}
				}
				else
				{
					ManualLogSource log3 = Log;
					if (log3 != null)
					{
						log3.LogWarning((object)("[Rasengan] Invalid mouse button '" + raw + "'. Falling back to Mouse0."));
					}
					_mouseButtonIndex = 0;
				}
			}
			else if (Enum.TryParse<KeyCode>(raw, ignoreCase: true, out result2))
			{
				_holdKeyCode = result2;
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogInfo((object)$"[Rasengan] MoveHold bound to KeyCode.{result2}.");
				}
			}
			else
			{
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogWarning((object)("[Rasengan] Could not parse MoveHold='" + raw + "'. Falling back to Mouse0."));
				}
				_mouseButtonIndex = 0;
			}
		}
	}
}