Decompiled source of YAPYAP Expanded v0.13.1

YAPYAPExpanded/YAPYAPExpanded.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Utilities;
using YAPYAP;
using YAPYAP.Npc.Frog;
using YAPYAP.Npc.Shopkeeper;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("YAPYAP Expanded")]
[assembly: AssemblyDescription("YAPYAP Expanded Beta 1")]
[assembly: AssemblyFileVersion("0.13.0.0")]
[assembly: AssemblyVersion("0.13.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 YAPYAPExpanded
{
	internal static class AssetLoader
	{
		internal static AssetBundle Bundle { get; private set; }

		internal static GameObject ChaosVisual { get; private set; }

		internal static GameObject FrostVisual { get; private set; }

		internal static void Load()
		{
			string text = Path.Combine(Paths.PluginPath, "YAPYAPExpanded", "yapyapexpanded");
			if (!File.Exists(text))
			{
				Plugin.Log.LogError((object)("AssetBundle not found: " + text));
				return;
			}
			Bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)Bundle == (Object)null)
			{
				Plugin.Log.LogError((object)"AssetBundle.LoadFromFile returned null");
				return;
			}
			Plugin.Log.LogInfo((object)"AssetBundle loaded");
			string[] allAssetNames = Bundle.GetAllAssetNames();
			string[] array = allAssetNames;
			foreach (string text2 in array)
			{
				Plugin.Log.LogInfo((object)("Asset: " + text2));
			}
			ChaosVisual = LoadPrefabByEnding(allAssetNames, "/haos.prefab");
			FrostVisual = LoadPrefabByEnding(allAssetNames, "/frost.prefab");
			Plugin.Log.LogInfo((object)("Chaos visual: " + (((Object)(object)ChaosVisual != (Object)null) ? ((Object)ChaosVisual).name : "NOT FOUND")));
			Plugin.Log.LogInfo((object)("Frost visual: " + (((Object)(object)FrostVisual != (Object)null) ? ((Object)FrostVisual).name : "NOT FOUND")));
		}

		private static GameObject LoadPrefabByEnding(string[] names, string ending)
		{
			foreach (string text in names)
			{
				if (text.EndsWith(ending, StringComparison.OrdinalIgnoreCase))
				{
					return Bundle.LoadAsset<GameObject>(text);
				}
			}
			return null;
		}
	}
	internal static class ChaosRollSync
	{
		internal static Quaternion Encode(int face)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (face < 1 || face > 6)
			{
				throw new ArgumentOutOfRangeException("face");
			}
			double num = (double)face * Math.PI / 12.0;
			return new Quaternion(0f, (float)Math.Sin(num), 0f, (float)Math.Cos(num));
		}

		internal static int Decode(Quaternion rotation)
		{
			//IL_0000: 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)
			double num = Math.Atan2(rotation.y, rotation.w) * 12.0 / Math.PI;
			int num2 = (int)Math.Round(num);
			if (num2 < 1 || num2 > 6 || !(Math.Abs(num - (double)num2) < 0.01))
			{
				return 0;
			}
			return num2;
		}

		internal static void Receive(Spell spell, Quaternion payload)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			int num = Decode(payload);
			if (num != 0 && !((Object)(object)spell.CasterIdentity == (Object)null) && spell.CasterIdentity.isLocalPlayer)
			{
				RollOverlay.ShowRoll(num);
			}
		}
	}
	internal struct UpgradeRequest : NetworkMessage
	{
		internal uint Merchant;

		internal uint Token;

		internal int Kind;

		internal int Expected;
	}
	internal struct UpgradeState : NetworkMessage
	{
		internal uint Pawn;

		internal uint Token;

		internal int Hp;

		internal int Speed;

		internal int Inventory;

		internal bool Open;

		internal string Result;
	}
	internal sealed class CharacterUpgrades : MonoBehaviour
	{
		private static readonly Dictionary<uint, UpgradeLevels> Clients = new Dictionary<uint, UpgradeLevels>();

		private static readonly Dictionary<int, double> LastRequest = new Dictionary<int, double>();

		internal static bool Ready;

		private bool serverRegistered;

		private bool clientRegistered;

		private double nextSync;

		internal static void Install(Harmony harmony)
		{
			Ready = false;
			try
			{
				UpgradeInventory.Install(harmony);
				InstallCodecs();
				Ready = true;
			}
			catch (Exception ex)
			{
				harmony.UnpatchSelf();
				Plugin.Log.LogError((object)("Upgrade system unavailable: " + ex));
			}
		}

		internal static void InstallCodecs()
		{
			Writer<UpgradeRequest>.write = delegate(NetworkWriter w, UpgradeRequest m)
			{
				NetworkWriterExtensions.WriteUInt(w, m.Merchant);
				NetworkWriterExtensions.WriteUInt(w, m.Token);
				NetworkWriterExtensions.WriteInt(w, m.Kind);
				NetworkWriterExtensions.WriteInt(w, m.Expected);
			};
			Reader<UpgradeRequest>.read = (NetworkReader r) => new UpgradeRequest
			{
				Merchant = NetworkReaderExtensions.ReadUInt(r),
				Token = NetworkReaderExtensions.ReadUInt(r),
				Kind = NetworkReaderExtensions.ReadInt(r),
				Expected = NetworkReaderExtensions.ReadInt(r)
			};
			Writer<UpgradeState>.write = delegate(NetworkWriter w, UpgradeState m)
			{
				NetworkWriterExtensions.WriteUInt(w, m.Pawn);
				NetworkWriterExtensions.WriteUInt(w, m.Token);
				NetworkWriterExtensions.WriteInt(w, m.Hp);
				NetworkWriterExtensions.WriteInt(w, m.Speed);
				NetworkWriterExtensions.WriteInt(w, m.Inventory);
				NetworkWriterExtensions.WriteBool(w, m.Open);
				NetworkWriterExtensions.WriteString(w, m.Result);
			};
			Reader<UpgradeState>.read = (NetworkReader r) => new UpgradeState
			{
				Pawn = NetworkReaderExtensions.ReadUInt(r),
				Token = NetworkReaderExtensions.ReadUInt(r),
				Hp = NetworkReaderExtensions.ReadInt(r),
				Speed = NetworkReaderExtensions.ReadInt(r),
				Inventory = NetworkReaderExtensions.ReadInt(r),
				Open = NetworkReaderExtensions.ReadBool(r),
				Result = NetworkReaderExtensions.ReadString(r)
			};
		}

		internal static string Key(Pawn pawn, int kind)
		{
			return "PLAYER." + pawn.PlayerId + ".YAPYAPEXP.UPGRADE." + kind;
		}

		internal static UpgradeLevels Levels(Pawn pawn)
		{
			if ((Object)(object)pawn == (Object)null)
			{
				return default(UpgradeLevels);
			}
			if (NetworkServer.active)
			{
				UpgradeLevels result = default(UpgradeLevels);
				SaveManager val = default(SaveManager);
				if (!string.IsNullOrEmpty(pawn.PlayerId) && Service.Get<SaveManager>(ref val))
				{
					val.TryGetInt(Key(pawn, 0), ref result.Hp);
					val.TryGetInt(Key(pawn, 1), ref result.Speed);
					val.TryGetInt(Key(pawn, 2), ref result.Inventory);
					result.Hp = UpgradeRules.Clamp(0, result.Hp);
					result.Speed = UpgradeRules.Clamp(1, result.Speed);
					result.Inventory = UpgradeRules.Clamp(2, result.Inventory);
				}
				return result;
			}
			if (!Clients.TryGetValue(((NetworkBehaviour)pawn).netId, out var value))
			{
				return default(UpgradeLevels);
			}
			return value;
		}

		internal static bool MerchantValid(Pawn pawn, uint merchantId, out ShopkeeperStateMachine merchant)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: 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_0161: 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)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: 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)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			merchant = null;
			Dictionary<uint, NetworkIdentity> dictionary = (NetworkServer.active ? NetworkServer.spawned : NetworkClient.spawned);
			if ((Object)(object)pawn == (Object)null || pawn.IsDead || pawn.IsExtracted || !dictionary.TryGetValue(merchantId, out var value))
			{
				return false;
			}
			merchant = ((Component)value).GetComponentInChildren<ShopkeeperStateMachine>(true);
			if ((Object)(object)merchant == (Object)null || !((Behaviour)merchant).isActiveAndEnabled || (Object)(object)merchant._npcBehaviour == (Object)null || merchant._npcBehaviour.IsKilled)
			{
				return false;
			}
			object? value2 = AccessTools.Field(typeof(ShopkeeperStateMachine), "_shop").GetValue(merchant);
			Shop val = (Shop)((value2 is Shop) ? value2 : null);
			if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy)
			{
				Vector3 val2 = ((Component)pawn).transform.position - ((Component)merchant).transform.position;
				if (!(((Vector3)(ref val2)).sqrMagnitude > 16f))
				{
					object? value3 = AccessTools.Field(typeof(ShopkeeperStateMachine), "_collider").GetValue(merchant);
					Collider val3 = (Collider)((value3 is Collider) ? value3 : null);
					? val4;
					if (!((Object)(object)val3 != (Object)null))
					{
						val4 = ((Component)merchant).transform.position + Vector3.up;
					}
					else
					{
						Bounds bounds = val3.bounds;
						float x = ((Bounds)(ref bounds)).center.x;
						bounds = val3.bounds;
						float num = ((Bounds)(ref bounds)).max.y - 0.15f;
						bounds = val3.bounds;
						val4 = new Vector3(x, num, ((Bounds)(ref bounds)).center.z);
					}
					Vector3 val5 = (Vector3)val4;
					Vector3 lookOrigin = pawn.LookOrigin;
					val2 = val5 - pawn.LookOrigin;
					Vector3 normalized = ((Vector3)(ref val2)).normalized;
					val2 = val5 - pawn.LookOrigin;
					foreach (RaycastHit item in from val6 in Physics.RaycastAll(lookOrigin, normalized, ((Vector3)(ref val2)).magnitude, -1, (QueryTriggerInteraction)1)
						orderby ((RaycastHit)(ref val6)).distance
						select val6)
					{
						RaycastHit current = item;
						NetworkIdentity componentInParent = ((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<NetworkIdentity>();
						if (!((Object)(object)componentInParent == (Object)(object)((NetworkBehaviour)pawn).netIdentity))
						{
							if ((Object)(object)componentInParent == (Object)(object)value)
							{
								return true;
							}
							if ((Object)(object)((RaycastHit)(ref current)).collider.attachedRigidbody == (Object)null)
							{
								return false;
							}
						}
					}
					return true;
				}
			}
			return false;
		}

		private void Update()
		{
			if (!Ready)
			{
				return;
			}
			if (NetworkServer.active && !serverRegistered)
			{
				NetworkServer.RegisterHandler<UpgradeRequest>((Action<NetworkConnectionToClient, UpgradeRequest>)Purchase, true);
				serverRegistered = true;
			}
			if (!NetworkServer.active && serverRegistered)
			{
				serverRegistered = false;
				LastRequest.Clear();
				nextSync = 0.0;
			}
			if (NetworkClient.active && !clientRegistered)
			{
				NetworkClient.RegisterHandler<UpgradeState>((Action<UpgradeState>)Receive, true);
				clientRegistered = true;
			}
			if (!NetworkClient.active && clientRegistered)
			{
				clientRegistered = false;
				Clients.Clear();
			}
			if (!NetworkServer.active || !(NetworkTime.time >= nextSync))
			{
				return;
			}
			nextSync = NetworkTime.time + 1.0;
			foreach (NetworkConnectionToClient value in NetworkServer.connections.Values)
			{
				Pawn val = (((Object)(object)((value != null) ? ((NetworkConnection)value).identity : null) != (Object)null) ? ((Component)((NetworkConnection)value).identity).GetComponent<Pawn>() : null);
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(val.PlayerId))
				{
					EnsureSlots(val);
					NetworkServer.SendToAll<UpgradeState>(State(val, 0u, open: false, ""), 0, false);
				}
			}
		}

		internal static void EnsureSlots(Pawn pawn)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active && !((Object)(object)((pawn != null) ? pawn.Inventory : null) == (Object)null))
			{
				int num = UpgradeRules.Capacity(Levels(pawn).Inventory);
				while (pawn.Inventory.Items.Count < num)
				{
					pawn.Inventory.Items.Add(InventoryItem.Empty);
				}
			}
		}

		private static UpgradeState State(Pawn pawn, uint token, bool open, string result)
		{
			UpgradeLevels upgradeLevels = Levels(pawn);
			return new UpgradeState
			{
				Pawn = ((NetworkBehaviour)pawn).netId,
				Token = token,
				Hp = upgradeLevels.Hp,
				Speed = upgradeLevels.Speed,
				Inventory = upgradeLevels.Inventory,
				Open = open,
				Result = result
			};
		}

		private static void Purchase(NetworkConnectionToClient connection, UpgradeRequest request)
		{
			//IL_050b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready)
			{
				return;
			}
			NetworkConnectionToClient obj = connection;
			if ((Object)(object)((obj != null) ? ((NetworkConnection)obj).identity : null) == (Object)null)
			{
				return;
			}
			Pawn pawn = ((Component)((NetworkConnection)connection).identity).GetComponent<Pawn>();
			if ((Object)(object)pawn == (Object)null)
			{
				return;
			}
			if (LastRequest.TryGetValue(connection.connectionId, out var value) && NetworkTime.time - value < 0.15)
			{
				Reply("error.wait");
				return;
			}
			LastRequest[connection.connectionId] = NetworkTime.time;
			if (!MerchantValid(pawn, request.Merchant, out var _))
			{
				Reply("error.merchant");
				return;
			}
			SaveManager val = default(SaveManager);
			if (string.IsNullOrEmpty(pawn.PlayerId) || !Service.Get<SaveManager>(ref val) || !(bool)AccessTools.Method(typeof(SaveManager), "IsSlotValid", (Type[])null, (Type[])null).Invoke(val, null))
			{
				Reply("error.save");
				return;
			}
			if (request.Kind == -1)
			{
				Reply("", open: true);
				return;
			}
			if (!UpgradeRules.ValidKind(request.Kind) || (Object)(object)GameManager.Instance == (Object)null)
			{
				Reply("error.kind");
				return;
			}
			int num = Levels(pawn).Get(request.Kind);
			int gold = GameManager.Instance.Gold;
			int num2 = UpgradeRules.Price(request.Kind, num);
			if (!UpgradeRules.CanBuy(request.Kind, num, request.Expected, gold))
			{
				Reply((num2 < 0) ? "error.max" : ((num != request.Expected) ? "error.stale" : "error.gold"));
				return;
			}
			if ((request.Kind == 0 && (Object)(object)pawn.Hurtbox == (Object)null) || (request.Kind == 2 && (Object)(object)pawn.Inventory == (Object)null))
			{
				Reply("error.pawn");
				return;
			}
			int network_maxHealth = (((Object)(object)pawn.Hurtbox != (Object)null) ? pawn.Hurtbox.MaxHealth : 0);
			int num3 = (((Object)(object)pawn.Hurtbox != (Object)null) ? pawn.Hurtbox.Health : 0);
			PawnInventory inventory = pawn.Inventory;
			int num4 = ((inventory != null) ? inventory.Items.Count : 0);
			try
			{
				GameManager.Instance.ModifyGold(-num2);
				val.SetInt(Key(pawn, request.Kind), num + 1);
				if (request.Kind == 0)
				{
					pawn.Hurtbox.SvModifyMaxHp(10);
					pawn.Hurtbox.SvPersistMaxHp();
				}
				if (request.Kind == 2)
				{
					EnsureSlots(pawn);
				}
				val.SetInt("GAME.GOLD", GameManager.Instance.Gold);
				val.WriteCurrent();
				NetworkServer.SendToAll<UpgradeState>(State(pawn, 0u, open: false, ""), 0, false);
				Reply("upgrade.success");
				Plugin.Log.LogInfo((object)("UPGRADE " + pawn.PlayerId + " kind=" + request.Kind + " level=" + (num + 1) + " price=" + num2));
			}
			catch (Exception ex)
			{
				val.SetInt(Key(pawn, request.Kind), num);
				GameManager.Instance.ModifyGold(num2);
				val.SetInt("GAME.GOLD", GameManager.Instance.Gold);
				if (request.Kind == 0 && (Object)(object)pawn.Hurtbox != (Object)null)
				{
					pawn.Hurtbox.Network_maxHealth = network_maxHealth;
					pawn.Hurtbox.SvSetHealth(num3);
					pawn.Hurtbox.SvPersistMaxHp();
				}
				if (request.Kind == 2 && (Object)(object)pawn.Inventory != (Object)null)
				{
					while (pawn.Inventory.Items.Count > num4)
					{
						InventoryItem val2 = pawn.Inventory.Items[pawn.Inventory.Items.Count - 1];
						if (!((InventoryItem)(ref val2)).IsEmpty)
						{
							break;
						}
						pawn.Inventory.Items.RemoveAt(pawn.Inventory.Items.Count - 1);
					}
				}
				Reply("error.purchase");
				Plugin.Log.LogError((object)("Upgrade purchase rolled back: " + ex));
			}
			void Reply(string result, bool open = false)
			{
				((NetworkConnection)connection).Send<UpgradeState>(State(pawn, request.Token, open, result), 0);
			}
		}

		private static void Receive(UpgradeState state)
		{
			Clients[state.Pawn] = new UpgradeLevels
			{
				Hp = UpgradeRules.Clamp(0, state.Hp),
				Speed = UpgradeRules.Clamp(1, state.Speed),
				Inventory = UpgradeRules.Clamp(2, state.Inventory)
			};
			UpgradeMenu.Receive(state);
		}
	}
	internal static class CustomSpellPatcher
	{
		internal static void Install(Harmony harmony)
		{
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Expected O, but got Unknown
			CustomSpellSystem.Ready = false;
			string text = "Spell base reverse patches";
			try
			{
				SpellVanilla.Install(harmony);
				Dictionary<string, string> dictionary = new Dictionary<string, string>
				{
					{ "OnSpellActivate", "Activate" },
					{ "CastSpell", "Activate" },
					{ "OnSpellDeactivate", "Stop" },
					{ "StopSpell", "Stop" },
					{ "Initialize", "Initialize" },
					{ "CanCast", "CanCast" },
					{ "Update", "Update" },
					{ "SetCastData", "SetCastData" },
					{ "SetWandHeld", "SetWandHeld" },
					{ "get_CooldownProgress", "CooldownReady" },
					{ "get_IsInstantCast", "Instant" },
					{ "get_IsCasting", "IsCasting" },
					{ "get_SpellName", "Name" },
					{ "get_ChargeableName", "Name" },
					{ "OnCasterIdentityChanged", "CasterChanged" },
					{ "OnCurrentChargesChanged", "ChargesChanged" },
					{ "OnIsCastingChanged", "CastingChanged" },
					{ "OnCastTimeChanged", "CastTimeChanged" },
					{ "GetSpawnPositionRotation", "SpawnPose" },
					{ "UserCode_RpcPlayEffect__SpellEffectType__Vector3__Quaternion", "Effect" },
					{ "FixedUpdate", "Skip" },
					{ "LateUpdate", "Skip" },
					{ "ClCastSpell", "Skip" },
					{ "ClStopSpell", "Skip" },
					{ "OnPickedUpWandsChanged", "Skip" },
					{ "OnRegenerationStartTimeChanged", "Skip" }
				};
				Type[] types;
				try
				{
					types = typeof(Spell).Assembly.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					types = ex.Types;
				}
				int num = 0;
				foreach (MethodInfo patchCandidate in GetPatchCandidates(types))
				{
					if (dictionary.TryGetValue(patchCandidate.Name, out var value))
					{
						text = patchCandidate.DeclaringType.FullName + "." + patchCandidate.Name;
						MethodInfo method = typeof(CustomSpellPatcher).GetMethod(value, BindingFlags.Static | BindingFlags.NonPublic);
						harmony.Patch((MethodBase)patchCandidate, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						num++;
					}
				}
				CustomSpellSystem.Ready = true;
				Plugin.Log.LogInfo((object)("Custom spell lifecycle hooks: " + num));
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogError((object)("Spell API incompatible at " + text + "; custom wand spawning disabled: " + ex2));
			}
		}

		internal static IEnumerable<MethodInfo> GetPatchCandidates(IEnumerable<Type> types)
		{
			HashSet<Type> visited = new HashSet<Type>();
			foreach (Type type2 in types)
			{
				if (type2 == null || type2.ContainsGenericParameters || !typeof(Spell).IsAssignableFrom(type2))
				{
					continue;
				}
				Type type = type2;
				while (type != null && typeof(Spell).IsAssignableFrom(type))
				{
					if (!type.ContainsGenericParameters && visited.Add(type))
					{
						MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						foreach (MethodInfo methodInfo in methods)
						{
							if (!methodInfo.IsAbstract && !methodInfo.ContainsGenericParameters)
							{
								yield return methodInfo;
							}
						}
					}
					type = type.BaseType;
				}
			}
		}

		private static bool Skip(Spell __instance)
		{
			return !CustomSpellSystem.IsManagedChild(__instance);
		}

		private static bool Activate(Spell __instance)
		{
			if (Skip(__instance))
			{
				return true;
			}
			CustomSpellSystem.Activate(__instance);
			return false;
		}

		private static bool Stop(Spell __instance)
		{
			if (Skip(__instance))
			{
				return true;
			}
			if (NetworkServer.active && __instance.NetworkisCasting)
			{
				SpellVanilla.Deactivate(__instance);
			}
			return false;
		}

		private static bool Initialize(Spell __instance, NetworkIdentity __0)
		{
			if (Skip(__instance))
			{
				return true;
			}
			SpellVanilla.Initialize(__instance, __0);
			return false;
		}

		private static bool CanCast(Spell __instance, ref bool __result)
		{
			if (Skip(__instance))
			{
				return true;
			}
			__result = CustomSpellSystem.Definition(__instance) != null && CustomSpellSystem.IsHeld(__instance) && SpellVanilla.CanCast(__instance);
			return false;
		}

		private static bool Update(Spell __instance)
		{
			if (Skip(__instance))
			{
				return true;
			}
			SpellVanilla.Update(__instance);
			return false;
		}

		private static bool SetCastData(Spell __instance)
		{
			if (Skip(__instance))
			{
				return true;
			}
			if (NetworkServer.active)
			{
				SpellVanilla.SetCastData(__instance);
			}
			return false;
		}

		private static bool SetWandHeld(Spell __instance, bool __0)
		{
			if (Skip(__instance))
			{
				return true;
			}
			SpellVanilla.SetWandHeld(__instance, __0);
			return false;
		}

		private static bool CooldownReady(Spell __instance, ref float __result)
		{
			if (Skip(__instance))
			{
				return true;
			}
			__result = 1f;
			return false;
		}

		private static bool Instant(Spell __instance, ref bool __result)
		{
			if (Skip(__instance))
			{
				return true;
			}
			__result = true;
			return false;
		}

		private static bool IsCasting(Spell __instance, ref bool __result)
		{
			if (Skip(__instance))
			{
				return true;
			}
			__result = __instance.NetworkisCasting;
			return false;
		}

		private static bool Name(Spell __instance, ref string __result)
		{
			if (Skip(__instance))
			{
				return true;
			}
			SpellDefinition spellDefinition = CustomSpellSystem.Definition(__instance);
			__result = ((spellDefinition == null) ? "" : spellDefinition.LocalName);
			return false;
		}

		private static bool CasterChanged(Spell __instance, NetworkIdentity __0, NetworkIdentity __1)
		{
			if (Skip(__instance))
			{
				return true;
			}
			SpellVanilla.CasterChanged(__instance, __0, __1);
			return false;
		}

		private static bool ChargesChanged(Spell __instance, int __0, int __1)
		{
			if (Skip(__instance))
			{
				return true;
			}
			SpellVanilla.ChargesChanged(__instance, __0, __1);
			return false;
		}

		private static bool CastingChanged(Spell __instance, bool __0, bool __1)
		{
			if (Skip(__instance))
			{
				return true;
			}
			SpellVanilla.CastingChanged(__instance, __0, __1);
			return false;
		}

		private static bool CastTimeChanged(Spell __instance, double __0, double __1)
		{
			return Skip(__instance);
		}

		private static bool SpawnPose(Spell __instance, ref Vector3 __0, ref Quaternion __1)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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)
			if (Skip(__instance))
			{
				return true;
			}
			SpellTargets.Aim(__instance, out __0, out var direction);
			__1 = Quaternion.LookRotation(direction);
			return false;
		}

		private static bool Effect(Spell __instance, SpellEffectType __0, Vector3 __1, Quaternion __2)
		{
			//IL_0031: 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_0039: 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_003b: 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_001f: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (Skip(__instance))
			{
				return true;
			}
			SpellDefinition spellDefinition = CustomSpellSystem.Definition(__instance);
			if (spellDefinition != null)
			{
				if (spellDefinition.Id == SpellId.ChaosRoll && (int)__0 == 3)
				{
					ChaosRollSync.Receive(__instance, __2);
					__2 = Quaternion.identity;
				}
				SpellVisuals.Play(__instance, spellDefinition, __0, __1);
				SpellVanilla.ClientEffect(__instance, __0, __1, __2);
			}
			return false;
		}
	}
	internal static class CustomSpellSystem
	{
		private static readonly BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly FieldInfo SpellDataField = typeof(Spell).GetField("spellData", Fields);

		private static readonly FieldInfo SecretField = typeof(Spell).GetField("isSecret", Fields);

		private static readonly FieldInfo VoiceSpellsField = typeof(VoiceSpell).GetField("spells", Fields);

		internal static bool Ready;

		private static readonly Random DiceRandom = new Random();

		internal static bool CanConfigure(GameObject root)
		{
			return GetChildren(root).Count >= 4;
		}

		private static List<Spell> GetChildren(GameObject root)
		{
			List<Spell> list = new List<Spell>();
			if ((Object)(object)root == (Object)null || VoiceSpellsField == null)
			{
				return list;
			}
			NetworkPuppetWandProp componentInChildren = root.GetComponentInChildren<NetworkPuppetWandProp>(true);
			VoiceSpell val = (VoiceSpell)(((Object)(object)componentInChildren != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val == (Object)null)
			{
				return list;
			}
			if (!(VoiceSpellsField.GetValue(val) is Spell[] array))
			{
				return list;
			}
			Spell[] array2 = array;
			foreach (Spell val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null && !(val2 is VoiceSpell) && (Object)(object)val2.SpellData != (Object)null && !list.Contains(val2))
				{
					list.Add(val2);
				}
			}
			return list;
		}

		internal static bool ConfigureWand(GameObject root, WandKind kind)
		{
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready || SpellDataField == null || SecretField == null)
			{
				Plugin.Log.LogError((object)("Cannot configure " + kind.ToString() + ": spell lifecycle initialization failed. See the startup error above."));
				return false;
			}
			List<Spell> children = GetChildren(root);
			if (children.Count < 4)
			{
				Plugin.Log.LogError((object)("Cannot configure " + kind.ToString() + ": donor needs four distinct child spells."));
				return false;
			}
			ManagedWandState component = root.GetComponent<ManagedWandState>();
			if ((Object)(object)component != (Object)null)
			{
				return true;
			}
			component = root.AddComponent<ManagedWandState>();
			SpellDefinition[] array = SpellCatalog.For(kind);
			try
			{
				for (int i = 0; i < children.Count; i++)
				{
					Spell val = children[i];
					SpellDefinition spellDefinition = ((i < array.Length) ? array[i] : null);
					Object val2 = (Object)(object)Object.Instantiate<SpellData>(val.SpellData);
					component.Data.Add(val2);
					val2.name = ((spellDefinition != null) ? spellDefinition.Key : ("YAPYAPEXP_DISABLED_" + i));
					SetRequired(val2, "voiceCommandKey", (spellDefinition != null) ? spellDefinition.Key : string.Empty);
					SetRequired(val2, "spellName", (spellDefinition != null) ? spellDefinition.LocalName : "");
					SetRequired(val2, "charges", spellDefinition?.Charges ?? 0);
					SetRequired(val2, "cooldown", spellDefinition?.Cooldown ?? 999f);
					SetRequired(val2, "chargePerCast", 1);
					SetRequired(val2, "chargeCostPerSecondCast", 0);
					SetRequired(val2, "chargesRegenPerInterval", (spellDefinition != null) ? 1 : 0);
					SetRequired(val2, "chargeRegenInterval", spellDefinition?.Regen ?? 1f);
					SetRequired(val2, "chargeRegenDelay", 0f);
					SetRequired(val2, "chargeColor", (object)((kind == WandKind.Frost) ? new Color(0.35f, 0.85f, 1f) : new Color(0.85f, 0.35f, 1f)));
					string[] array2 = new string[4] { "castVFXPrefab", "spawnVFXPrefab", "endVFXPrefab", "impactVFXPrefab" };
					foreach (string name in array2)
					{
						SetRequired(val2, name, null);
					}
					FieldInfo field = typeof(Spell).GetField("castVFX", Fields);
					if (field != null)
					{
						field.SetValue(val, null);
					}
					SpellDataField.SetValue(val, val2);
					SecretField.SetValue(val, spellDefinition == null);
					val.OverrideSecret = spellDefinition == null;
					((Behaviour)val).enabled = true;
				}
				Plugin.Log.LogInfo((object)(kind.ToString() + ": four spells ready; Mirror component layout unchanged."));
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Wand spell setup failed; refusing to spawn partial wand: " + ex));
				return false;
			}
		}

		private static void SetRequired(object target, string name, object value)
		{
			FieldInfo? field = target.GetType().GetField(name, Fields);
			if (field == null)
			{
				throw new MissingFieldException(target.GetType().FullName, name);
			}
			field.SetValue(target, value);
		}

		internal static bool TryGetKind(Spell spell, out WandKind kind)
		{
			kind = WandKind.Chaos;
			if ((Object)(object)spell == (Object)null)
			{
				return false;
			}
			NetworkIdentity componentInParent = ((Component)spell).GetComponentInParent<NetworkIdentity>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return false;
			}
			if (componentInParent.assetId == 1497712210)
			{
				kind = WandKind.Frost;
				return true;
			}
			return componentInParent.assetId == 1497711432;
		}

		internal static bool IsManagedChild(Spell spell)
		{
			if ((Object)(object)spell != (Object)null && !(spell is VoiceSpell) && TryGetKind(spell, out var _) && (Object)(object)spell.SpellData != (Object)null)
			{
				return ((Object)spell.SpellData).name.StartsWith("YAPYAPEXP_", StringComparison.Ordinal);
			}
			return false;
		}

		internal static SpellDefinition Definition(Spell spell)
		{
			if (!IsManagedChild(spell))
			{
				return null;
			}
			SpellDefinition spellDefinition = SpellCatalog.Find(spell.VoiceCommandKey);
			if (spellDefinition == null || !TryGetKind(spell, out var kind) || kind != spellDefinition.Kind)
			{
				return null;
			}
			return spellDefinition;
		}

		internal static bool IsHeld(Spell spell)
		{
			if ((Object)(object)spell == (Object)null || (Object)(object)spell.CasterIdentity == (Object)null)
			{
				return false;
			}
			NetworkIdentity componentInParent = ((Component)spell).GetComponentInParent<NetworkIdentity>();
			NetworkPuppetWandProp val = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).GetComponentInChildren<NetworkPuppetWandProp>(true) : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.Spell != (Object)null && val.Spell.NetworkisWandActive)
			{
				return (Object)(object)val.Spell.CasterIdentity == (Object)(object)spell.CasterIdentity;
			}
			return false;
		}

		internal static void Activate(Spell spell)
		{
			//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_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_0048: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: 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_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			SpellDefinition spellDefinition = Definition(spell);
			if (!NetworkServer.active || spellDefinition == null || !IsHeld(spell) || !SpellVanilla.CanCast(spell))
			{
				return;
			}
			GameObject val = null;
			Vector3 val2 = ((Component)spell.CasterIdentity).transform.position + Vector3.up * 0.5f;
			SpellTargets.Aim(spell, out var _, out var direction);
			if (spellDefinition.Range > 0f && spellDefinition.Id != SpellId.ChaosRoll)
			{
				if (!SpellTargets.FirstHit(spell, spellDefinition.Range, out var first))
				{
					return;
				}
				val2 = ((RaycastHit)(ref first)).point + ((RaycastHit)(ref first)).normal * 0.08f;
				val = SpellTargets.Resolve(((RaycastHit)(ref first)).collider);
				if ((spellDefinition.Id == SpellId.FrostBind || spellDefinition.Id == SpellId.FrostShard || spellDefinition.Id == SpellId.ChaosBolt) && ((Object)(object)val == (Object)null || (spellDefinition.Id == SpellId.FrostShard && (Object)(object)val.GetComponent<NpcBehaviour>() == (Object)null)))
				{
					return;
				}
			}
			int num = 0;
			try
			{
				SpellVanilla.Activate(spell);
				switch (spellDefinition.Id)
				{
				case SpellId.FrostBind:
					FreezeState.ApplyTo(val, spellDefinition.Duration, frost: true);
					break;
				case SpellId.FrostShard:
				{
					FreezeState component = val.GetComponent<FreezeState>();
					int num2 = spellDefinition.Damage;
					if ((Object)(object)component != (Object)null && component.IsFrozen)
					{
						num2 += spellDefinition.FrozenBonus;
						component.Thaw();
					}
					SpellTargets.Damage(val, spell.CasterIdentity, num2, direction);
					break;
				}
				case SpellId.FrostNova:
					foreach (GameObject item in SpellTargets.Nearby(spell, val2, spellDefinition.Radius))
					{
						NetworkIdentity casterIdentity = spell.CasterIdentity;
						int damage = spellDefinition.Damage;
						Vector3 val3 = item.transform.position - val2;
						SpellTargets.Damage(item, casterIdentity, damage, ((Vector3)(ref val3)).normalized);
						if ((Object)(object)item != (Object)null)
						{
							FreezeState.ApplyTo(item, spellDefinition.Duration, frost: true);
						}
					}
					break;
				case SpellId.FrostBlizzard:
				case SpellId.ChaosVortex:
					SpellZone.Create(spell, spellDefinition, val2);
					break;
				case SpellId.ChaosRoll:
					num = SpellCatalog.Roll(DiceRandom);
					ApplyRoll(spell, num, val2);
					Plugin.Log.LogInfo((object)("CHAOS ROLL face=" + num + " | " + SpellCatalog.RollName(num, russian: false)));
					break;
				case SpellId.ChaosBolt:
					SpellTargets.Damage(val, spell.CasterIdentity, spellDefinition.Damage + Random.Range(0, spellDefinition.DamageVariance + 1), direction);
					if ((Object)(object)val != (Object)null)
					{
						if ((Object)(object)val.GetComponent<NpcBehaviour>() != (Object)null)
						{
							FreezeState.ApplyTo(val, spellDefinition.Duration, frost: false);
							break;
						}
						SpellTargets.DamageProp(val, spell.CasterIdentity, 8, direction);
						SpellTargets.Impulse(val, direction * 5f + Vector3.up * 5f);
					}
					break;
				case SpellId.ChaosBurst:
					Burst(spell, val2, spellDefinition.Radius, 8f, spellDefinition.Damage, spellDefinition.Duration);
					break;
				}
				spell.RpcPlayEffect((SpellEffectType)((spellDefinition.Id == SpellId.FrostBlizzard || spellDefinition.Id == SpellId.ChaosVortex) ? 1 : 3), val2, (num > 0) ? ChaosRollSync.Encode(num) : Quaternion.LookRotation(direction));
				Plugin.Log.LogInfo((object)("CAST " + spellDefinition.Id.ToString() + " | charges=" + spell.CurrentCharges + "/" + spell.MaxCharges));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Spell " + spellDefinition.Id.ToString() + " failed: " + ex));
			}
			finally
			{
				if ((Object)(object)spell != (Object)null && spell.IsCasting)
				{
					SpellVanilla.Deactivate(spell);
				}
			}
		}

		private static void ApplyRoll(Spell spell, int roll, Vector3 center)
		{
			//IL_0022: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_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_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			switch (roll)
			{
			case 1:
				Burst(spell, center, 4.5f, 4f, 0, 0f);
				break;
			case 2:
			{
				foreach (GameObject item in SpellTargets.Nearby(spell, center, 5.5f))
				{
					Vector3 val2 = center - item.transform.position;
					SpellTargets.Impulse(item, ((Vector3)(ref val2)).normalized * 5.5f + Vector3.up);
				}
				break;
			}
			case 3:
			case 4:
			{
				RaycastHit first;
				GameObject val = (SpellTargets.FirstHit(spell, 12f, out first) ? SpellTargets.Resolve(((RaycastHit)(ref first)).collider) : null);
				if ((Object)(object)val != (Object)null)
				{
					if (roll == 4)
					{
						FreezeState.ApplyTo(val, 2.5f, frost: true);
					}
					else if ((Object)(object)val.GetComponent<NpcBehaviour>() != (Object)null)
					{
						FreezeState.ApplyTo(val, 1f, frost: false);
					}
					else
					{
						SpellTargets.Impulse(val, Vector3.up * 6.5f);
					}
					break;
				}
				{
					foreach (GameObject item2 in SpellTargets.Nearby(spell, center, 3f))
					{
						if (roll == 4)
						{
							FreezeState.ApplyTo(item2, 1f, frost: true);
						}
						else if ((Object)(object)item2.GetComponent<NpcBehaviour>() != (Object)null)
						{
							FreezeState.ApplyTo(item2, 0.75f, frost: false);
						}
						else
						{
							SpellTargets.Impulse(item2, Vector3.up * 5f);
						}
					}
					break;
				}
			}
			case 5:
			{
				foreach (GameObject item3 in SpellTargets.Nearby(spell, center, 5.5f))
				{
					float num = Random.Range(0f, MathF.PI * 2f);
					SpellTargets.Impulse(item3, new Vector3(Mathf.Cos(num) * 6.5f, 2f, Mathf.Sin(num) * 6.5f));
				}
				break;
			}
			case 6:
				Burst(spell, center, 6f, 8f, 0, 0f);
				spell.SetCurrentCharges(Math.Min(spell.MaxCharges, spell.CurrentCharges + 1));
				break;
			}
		}

		private static void Burst(Spell spell, Vector3 center, float radius, float force, int damage, float stun)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			foreach (GameObject item in SpellTargets.Nearby(spell, center, radius))
			{
				Vector3 val = item.transform.position - center;
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				SpellTargets.Damage(item, spell.CasterIdentity, damage, normalized);
				if (!((Object)(object)item == (Object)null))
				{
					if (stun > 0f && (Object)(object)item.GetComponent<NpcBehaviour>() != (Object)null)
					{
						FreezeState.ApplyTo(item, stun, frost: false);
					}
					else
					{
						SpellTargets.Impulse(item, normalized * force + Vector3.up * 1.5f);
					}
				}
			}
		}
	}
	internal sealed class ManagedWandState : MonoBehaviour
	{
		internal readonly List<Object> Data = new List<Object>();

		private void OnDestroy()
		{
			foreach (Object datum in Data)
			{
				if (datum != (Object)null)
				{
					Object.Destroy(datum);
				}
			}
			Data.Clear();
		}
	}
	internal static class ExtraRules
	{
		internal const float VacuumCastRange = 8f;

		internal const int VacuumPropDamage = 6;

		internal const double VacuumDamageInterval = 0.5;

		internal static bool WithinVacuumReach(Vector3 caster, Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//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)
			Vector3 val = point - caster;
			return ((Vector3)(ref val)).sqrMagnitude <= 64f;
		}

		internal static bool VacuumTargetInRange(Vector3 caster, Vector3 center, Vector3 point, float radius)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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)
			//IL_0012: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			if (radius > 0f && WithinVacuumReach(caster, center) && WithinVacuumReach(caster, point))
			{
				Vector3 val = point - center;
				return ((Vector3)(ref val)).sqrMagnitude <= radius * radius;
			}
			return false;
		}

		internal static float Suction(float distance, float radius)
		{
			if (radius <= 0f || distance >= radius)
			{
				return 0f;
			}
			float num = 1f - Math.Max(0f, distance) / radius;
			return 14f + 46f * num * num;
		}

		internal static int RainCount(double age, double interval, int max)
		{
			if (!(age < 0.0) && !(interval <= 0.0))
			{
				return Math.Min(max, 1 + (int)Math.Floor(age / interval));
			}
			return 0;
		}

		internal static Vector3 OrbitPoint(Vector3 center, float radius, double age, int index, int count)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			double num = age * 1.6 + (double)index * Math.PI * 2.0 / (double)Math.Max(1, count);
			return center + new Vector3((float)Math.Cos(num) * radius, 1.15f, (float)Math.Sin(num) * radius);
		}

		internal static Vector3 OrbitForce(Vector3 error, Vector3 velocity, Vector3 targetVelocity, Vector3 gravity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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)
			//IL_001c: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.ClampMagnitude(error * 18f + (targetVelocity - velocity) * 7f - gravity, 32f);
		}

		internal static bool PortalCrossing(Vector3 previous, Vector3 current, float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0020: 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_0030: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (previous.z <= 0f || current.z > 0.12f || current.z >= previous.z)
			{
				return false;
			}
			float val = previous.z / (previous.z - current.z);
			val = Math.Max(0f, Math.Min(1f, val));
			float num = previous.x + (current.x - previous.x) * val;
			float num2 = previous.y + (current.y - previous.y) * val;
			return num * num + num2 * num2 < radius * radius;
		}

		internal static bool PortalContact(Vector3 local, float bodyRadius, float portalRadius)
		{
			//IL_0012: 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_002c: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			float num = portalRadius - bodyRadius * 0.25f;
			if (num > 0f && Math.Abs(local.z) <= bodyRadius + 0.18f)
			{
				return local.x * local.x + local.y * local.y < num * num;
			}
			return false;
		}

		internal static bool InPuddle(Vector3 point, Vector3 center, float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//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)
			Vector3 val = point - center;
			if (val.y >= -0.12f && val.y <= 1.6f)
			{
				return val.x * val.x + val.z * val.z <= radius * radius;
			}
			return false;
		}
	}
	internal sealed class EffectPulse
	{
		private double next;

		internal EffectPulse(double start, double interval)
		{
			next = start + interval;
		}

		internal bool Tick(double now, double interval)
		{
			if (now < next)
			{
				return false;
			}
			next = now + interval;
			return true;
		}
	}
	internal sealed class ExtraLifetime
	{
		internal double Started;

		internal double Expires;

		internal bool Paired;

		internal bool Stopped;

		internal ExtraLifetime(double now, double duration)
		{
			Started = now;
			Expires = now + duration;
		}

		internal bool Alive(double now)
		{
			if (!Stopped)
			{
				return now < Expires;
			}
			return false;
		}

		internal bool Pair(double now, double duration)
		{
			if (Paired || !Alive(now))
			{
				return false;
			}
			Paired = true;
			Expires = now + duration;
			return true;
		}

		internal void Stop()
		{
			Stopped = true;
		}
	}
	internal sealed class EffectClaims<T>
	{
		private readonly Dictionary<T, int> owners = new Dictionary<T, int>();

		internal int Count => owners.Count;

		internal bool Claim(T item, int owner)
		{
			if (owners.TryGetValue(item, out var value))
			{
				return value == owner;
			}
			owners.Add(item, owner);
			return true;
		}

		internal bool Contains(T item)
		{
			return owners.ContainsKey(item);
		}

		internal void Release(T item, int owner)
		{
			if (owners.TryGetValue(item, out var value) && value == owner)
			{
				owners.Remove(item);
			}
		}
	}
	internal static class ExtraPhysics
	{
		internal static bool Eligible(Rigidbody body, bool allowWands = false)
		{
			//IL_001f: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body == (Object)null || !((Component)body).gameObject.activeInHierarchy || body.isKinematic || (body.constraints & 0xE) != 0 || body.mass > 45f || (Object)(object)((Component)body).GetComponentInParent<Pawn>() != (Object)null || (Object)(object)((Component)body).GetComponentInParent<NpcBehaviour>() != (Object)null)
			{
				return false;
			}
			NetworkIdentity componentInParent = ((Component)body).GetComponentInParent<NetworkIdentity>();
			if ((Object)(object)componentInParent == (Object)null || componentInParent.netId == 0 || componentInParent.connectionToClient != null || !NetworkServer.spawned.ContainsKey(componentInParent.netId))
			{
				return false;
			}
			NetworkPuppetProp componentInParent2 = ((Component)body).GetComponentInParent<NetworkPuppetProp>();
			if ((Object)(object)componentInParent2 != (Object)null && (componentInParent2.IsShopItem || (int)componentInParent2.CurrentState.state != 0 || (!allowWands && componentInParent2 is NetworkPuppetWandProp)))
			{
				return false;
			}
			return (Object)(object)((Component)body).GetComponent<Joint>() == (Object)null;
		}

		internal static List<Rigidbody> Bodies(ExtraSpell spell, Vector3 point, float radius)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			List<Rigidbody> list = new List<Rigidbody>();
			foreach (GameObject item in SpellTargets.Nearby((Spell)(object)spell, point, radius))
			{
				Rigidbody[] componentsInChildren = item.GetComponentsInChildren<Rigidbody>();
				foreach (Rigidbody val in componentsInChildren)
				{
					if (Eligible(val) && !list.Contains(val))
					{
						list.Add(val);
					}
				}
			}
			list.Sort(delegate(Rigidbody a, Rigidbody b)
			{
				//IL_0001: 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_000c: 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)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: 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)
				Vector3 val2 = a.worldCenterOfMass - point;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				val2 = b.worldCenterOfMass - point;
				return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude);
			});
			return list;
		}

		internal static bool Clear(Vector3 point, float radius, Rigidbody ignore = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(point, radius, -1, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i].attachedRigidbody != (Object)(object)ignore || (Object)(object)ignore == (Object)null)
				{
					return false;
				}
			}
			return true;
		}

		internal static Quaternion Frame(Vector3 normal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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_0013: 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)
			return Quaternion.LookRotation(normal, (Mathf.Abs(normal.y) > 0.9f) ? Vector3.forward : Vector3.up);
		}
	}
	internal sealed class ExtraZone : MonoBehaviour
	{
		private sealed class TimedObject
		{
			internal GameObject Object;

			internal double Expires;
		}

		private sealed class FireParticle
		{
			internal Vector3 Position;

			internal Vector3 Velocity;

			internal double Expires;
		}

		internal static readonly List<ExtraZone> Active = new List<ExtraZone>();

		private static readonly EffectClaims<Rigidbody> Orbits = new EffectClaims<Rigidbody>();

		private static readonly Dictionary<Rigidbody, double> PortalCooldown = new Dictionary<Rigidbody, double>();

		private static int nextOwner;

		internal ExtraSpell Spell;

		internal ExtraLifetime Life;

		internal Vector3 A;

		internal Vector3 B;

		private Quaternion frameA;

		private Quaternion frameB;

		private double heartbeat;

		private EffectPulse damagePulse;

		private int emitted;

		private int claimOwner;

		private readonly List<Rigidbody> orbit = new List<Rigidbody>();

		private readonly Dictionary<Rigidbody, Vector3> previous = new Dictionary<Rigidbody, Vector3>();

		private NetworkIdentity[] fish;

		private GameObject fireHitbox;

		private readonly List<TimedObject> spawned = new List<TimedObject>();

		private readonly List<FireParticle> drops = new List<FireParticle>();

		private bool ended;

		internal ExtraDefinition Definition => Spell.Definition;

		internal static bool TryCast(ExtraSpell spell, Vector3 point, Vector3 normal)
		{
			//IL_001f: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: 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_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			double time = NetworkTime.time;
			ExtraDefinition definition = spell.Definition;
			if (definition.Id == ExtraId.Vacuum)
			{
				SpellTargets.Aim((Spell)(object)spell, out var origin, out var _);
				if (!ExtraRules.WithinVacuumReach(origin, point + normal * 0.55f))
				{
					return false;
				}
			}
			if (definition.Id == ExtraId.Rift && (Object)(object)spell.Zone != (Object)null && spell.Zone.Life.Alive(time) && !spell.Zone.Life.Paired)
			{
				ExtraZone zone = spell.Zone;
				Vector3 val = point - zone.A;
				if (((Vector3)(ref val)).sqrMagnitude < 9f)
				{
					return false;
				}
				zone.B = point + normal * 0.15f;
				zone.frameB = ExtraPhysics.Frame(normal);
				if (!zone.Life.Pair(time, definition.Duration))
				{
					return false;
				}
				zone.SendVisuals();
				Plugin.Log.LogInfo((object)("RIFT pair active for " + definition.Duration + " seconds"));
				return true;
			}
			NetworkIdentity[] prefabs = null;
			GameObject prefab = null;
			if (definition.Id == ExtraId.FishRain && !ExtraNativeAssets.TryFish(spell, out prefabs))
			{
				return false;
			}
			if (definition.Id == ExtraId.IgnisRain && !ExtraNativeAssets.TryFire(spell, out prefab))
			{
				return false;
			}
			List<Rigidbody> list = null;
			if (definition.Id == ExtraId.Orbit)
			{
				list = (from x in ExtraPhysics.Bodies(spell, point + Vector3.up, 4f)
					where !Orbits.Contains(x)
					select x).Take(4).ToList();
				if ((Object)(object)spell.Zone != (Object)null)
				{
					spell.Zone.End();
					list = (from x in ExtraPhysics.Bodies(spell, point + Vector3.up, 4f)
						where !Orbits.Contains(x)
						select x).Take(4).ToList();
				}
				if (list.Count == 0)
				{
					return false;
				}
			}
			if ((Object)(object)spell.Zone != (Object)null)
			{
				spell.Zone.End();
			}
			while (Active.Count >= 16)
			{
				Active[0].End();
			}
			ExtraZone extraZone = new GameObject("YAPYAPExpanded_Extra_" + definition.Id).AddComponent<ExtraZone>();
			extraZone.Spell = spell;
			spell.Zone = extraZone;
			extraZone.A = point + ((definition.Id == ExtraId.Rift) ? (normal * 0.15f) : ((definition.Id == ExtraId.Vacuum) ? (normal * 0.55f) : (Vector3.up * 0.08f)));
			extraZone.frameA = ExtraPhysics.Frame(normal);
			extraZone.fish = prefabs;
			extraZone.fireHitbox = prefab;
			extraZone.Life = new ExtraLifetime(time, (definition.Id == ExtraId.Rift) ? 10f : definition.Duration);
			extraZone.damagePulse = new EffectPulse(time, 0.5);
			extraZone.claimOwner = ++nextOwner;
			if (list != null)
			{
				foreach (Rigidbody item in list)
				{
					if (Orbits.Claim(item, extraZone.claimOwner))
					{
						extraZone.orbit.Add(item);
					}
				}
			}
			Active.Add(extraZone);
			extraZone.SendVisuals();
			return true;
		}

		private void FixedUpdate()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (ended)
			{
				return;
			}
			if (NetworkServer.active && !((Object)(object)Spell == (Object)null) && !((Object)(object)((Spell)Spell).CasterIdentity == (Object)null))
			{
				Pawn component = ((Component)((Spell)Spell).CasterIdentity).GetComponent<Pawn>();
				if (component == null || (!component.IsDead && !component.IsExtracted))
				{
					try
					{
						double time = NetworkTime.time;
						bool flag = Life.Alive(time);
						if (flag)
						{
							if (Definition.Id == ExtraId.Orbit)
							{
								A = ((Component)((Spell)Spell).CasterIdentity).transform.position;
							}
							if (time >= heartbeat)
							{
								SendVisuals();
								heartbeat = time + 0.5;
							}
							switch (Definition.Id)
							{
							case ExtraId.Vacuum:
								Vacuum(time);
								break;
							case ExtraId.Rift:
								if (Life.Paired)
								{
									Portals(time);
								}
								break;
							case ExtraId.Orbit:
								Orbit(time);
								break;
							case ExtraId.IgnisRain:
								Rain(time, isFish: false);
								break;
							case ExtraId.FishRain:
								Rain(time, isFish: true);
								break;
							}
						}
						TickDrops(time);
						for (int num = spawned.Count - 1; num >= 0; num--)
						{
							TimedObject timedObject = spawned[num];
							if ((Object)(object)timedObject.Object == (Object)null || time >= timedObject.Expires)
							{
								if ((Object)(object)timedObject.Object != (Object)null)
								{
									NetworkServer.Destroy(timedObject.Object);
								}
								spawned.RemoveAt(num);
							}
						}
						if (!flag && drops.Count == 0 && spawned.Count == 0)
						{
							End();
						}
						return;
					}
					catch (Exception ex)
					{
						Plugin.Log.LogError((object)("Extra effect ended safely: " + ex));
						End();
						return;
					}
				}
			}
			End();
		}

		private void Vacuum(double now)
		{
			//IL_000f: 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)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00f7: 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)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			SpellTargets.Aim((Spell)(object)Spell, out var origin, out var _);
			if (!ExtraRules.WithinVacuumReach(origin, A))
			{
				End();
				return;
			}
			bool flag = damagePulse.Tick(now, 0.5);
			HashSet<NetworkIdentity> hashSet = (flag ? new HashSet<NetworkIdentity>() : null);
			foreach (Rigidbody item in ExtraPhysics.Bodies(Spell, A, Definition.Radius))
			{
				if (!ExtraPhysics.Eligible(item) || Orbits.Contains(item) || !ExtraRules.VacuumTargetInRange(origin, A, item.worldCenterOfMass, Definition.Radius))
				{
					continue;
				}
				Vector3 val = A - item.worldCenterOfMass;
				float num = ExtraRules.Suction(((Vector3)(ref val)).magnitude, Definition.Radius);
				item.AddForce(((Vector3)(ref val)).normalized * num - item.linearVelocity * 2.2f - (item.useGravity ? (Physics.gravity * 0.85f) : Vector3.zero), (ForceMode)5);
				item.linearVelocity = Vector3.ClampMagnitude(item.linearVelocity, 14f);
				if (flag)
				{
					NetworkIdentity componentInParent = ((Component)item).GetComponentInParent<NetworkIdentity>();
					if ((Object)(object)componentInParent != (Object)null && hashSet.Add(componentInParent))
					{
						SpellTargets.DamageProp(((Component)componentInParent).gameObject, ((Spell)Spell).CasterIdentity, 6, ((Vector3)(ref val)).normalized);
					}
				}
			}
		}

		private void Orbit(double now)
		{
			//IL_002a: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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)
			//IL_010f: 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_011e: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			for (int num = orbit.Count - 1; num >= 0; num--)
			{
				Rigidbody val = orbit[num];
				if (ExtraPhysics.Eligible(val))
				{
					Vector3 val2 = val.position - A;
					if (!(((Vector3)(ref val2)).sqrMagnitude > 64f))
					{
						double num2 = now - Life.Started;
						Vector3 val3 = ExtraRules.OrbitPoint(A, Definition.Radius, num2, num, orbit.Count);
						Vector3 val4 = ExtraRules.OrbitPoint(A, Definition.Radius, num2 + 0.02, num, orbit.Count);
						Vector3 val5 = Vector3.zero;
						Rigidbody component = ((Component)((Spell)Spell).CasterIdentity).GetComponent<Rigidbody>();
						if ((Object)(object)component != (Object)null)
						{
							val5 = component.linearVelocity;
						}
						val.AddForce(ExtraRules.OrbitForce(val3 - val.worldCenterOfMass, val.linearVelocity, (val4 - val3) / 0.02f + val5, val.useGravity ? Physics.gravity : Vector3.zero), (ForceMode)5);
						continue;
					}
				}
				Orbits.Release(val, claimOwner);
				orbit.RemoveAt(num);
			}
		}

		private void Portals(double now)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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)
			Rigidbody[] array = (from x in PortalCooldown
				where (Object)(object)x.Key == (Object)null || x.Value <= now
				select x.Key).ToArray();
			foreach (Rigidbody key in array)
			{
				PortalCooldown.Remove(key);
			}
			HashSet<Rigidbody> hashSet = new HashSet<Rigidbody>();
			PortalEnd(A, frameA, B, frameB, now, hashSet);
			PortalEnd(B, frameB, A, frameA, now, hashSet);
			foreach (Rigidbody item in hashSet)
			{
				if ((Object)(object)item != (Object)null)
				{
					previous[item] = item.worldCenterOfMass;
				}
			}
			array = previous.Keys.ToArray();
			foreach (Rigidbody val in array)
			{
				if ((Object)(object)val == (Object)null || !hashSet.Contains(val))
				{
					previous.Remove(val);
				}
			}
		}

		private void PortalEnd(Vector3 from, Quaternion fromFrame, Vector3 to, Quaternion toFrame, double now, HashSet<Rigidbody> seen)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: 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_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: 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_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			HashSet<Rigidbody> hashSet = new HashSet<Rigidbody>();
			Collider[] array = Physics.OverlapSphere(from, 2.4f, -1, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				Rigidbody attachedRigidbody = array[i].attachedRigidbody;
				if (!ExtraPhysics.Eligible(attachedRigidbody, allowWands: true) || !hashSet.Add(attachedRigidbody))
				{
					continue;
				}
				seen.Add(attachedRigidbody);
				if (Orbits.Contains(attachedRigidbody) || PortalCooldown.ContainsKey(attachedRigidbody))
				{
					continue;
				}
				Vector3 worldCenterOfMass = attachedRigidbody.worldCenterOfMass;
				if (!previous.TryGetValue(attachedRigidbody, out var value))
				{
					value = worldCenterOfMass - attachedRigidbody.linearVelocity * Time.fixedDeltaTime;
				}
				Quaternion val = Quaternion.Inverse(fromFrame);
				float num = 0.12f;
				Collider[] componentsInChildren = ((Component)attachedRigidbody).GetComponentsInChildren<Collider>();
				foreach (Collider val2 in componentsInChildren)
				{
					if ((Object)(object)val2.attachedRigidbody == (Object)(object)attachedRigidbody && !val2.isTrigger)
					{
						float num2 = num;
						Bounds bounds = val2.bounds;
						float x = ((Bounds)(ref bounds)).extents.x;
						bounds = val2.bounds;
						float y = ((Bounds)(ref bounds)).extents.y;
						bounds = val2.bounds;
						num = Mathf.Max(num2, Mathf.Max(x, Mathf.Max(y, ((Bounds)(ref bounds)).extents.z)));
					}
				}
				if (num > 0.8f)
				{
					continue;
				}
				Vector3 val3 = val * (value - from);
				Vector3 current = val * (worldCenterOfMass - from);
				val3.z -= num;
				current.z -= num;
				if (!ExtraRules.PortalCrossing(val3, current, Definition.Radius - num * 0.25f) && !ExtraRules.PortalContact(val * (worldCenterOfMass - from), num, Definition.Radius))
				{
					continue;
				}
				Quaternion val4 = toFrame * Quaternion.Euler(0f, 180f, 0f) * val;
				Vector3 val5 = val * (worldCenterOfMass - from);
				val5.z = 0f;
				Vector3 val6 = to + toFrame * new Vector3(0f - val5.x, val5.y, num + 0.22f);
				bool flag = false;
				for (int k = 0; k < 4; k++)
				{
					val6 = to + toFrame * new Vector3(0f - val5.x, val5.y, num + 0.25f + (float)k * 0.35f);
					if (Physics.Linecast(to + toFrame * Vector3.forward * 0.06f, val6, -1, (QueryTriggerInteraction)1))
					{
						break;
					}
					if (ExtraPhysics.Clear(val6, num * 0.95f, attachedRigidbody))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					continue;
				}
				Vector3 linearVelocity = val4 * attachedRigidbody.linearVelocity;
				Vector3 angularVelocity = val4 * attachedRigidbody.angularVelocity;
				attachedRigidbody.position = val6 + val4 * (attachedRigidbody.position - worldCenterOfMass);
				attachedRigidbody.rotation = val4 * attachedRigidbody.rotation;
				NetworkTransformBase[] componentsInParent = ((Component)attachedRigidbody).GetComponentsInParent<NetworkTransformBase>();
				foreach (NetworkTransformBase val7 in componentsInParent)
				{
					if ((Object)(object)val7.target == (Object)(object)((Component)attachedRigidbody).transform)
					{
						val7.ServerTeleport(attachedRigidbody.position, attachedRigidbody.rotation);
					}
				}
				attachedRigidbody.linearVelocity = linearVelocity;
				attachedRigidbody.angularVelocity = angularVelocity;
				attachedRigidbody.WakeUp();
				PortalCooldown[attachedRigidbody] = now + 0.65;
				previous[attachedRigidbody] = val6;
				Plugin.Log.LogInfo((object)("RIFT transported " + ((Object)attachedRigidbody).name));
			}
		}

		private void Rain(double now, bool isFish)
		{
			//IL_0043: 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)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00d6: 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_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: 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_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			int num = ExtraRules.RainCount(now - Life.Started, isFish ? 0.4 : 0.5, isFish ? 10 : 8);
			if (emitted >= num)
			{
				return;
			}
			emitted = num;
			Vector2 val = Random.insideUnitCircle * Definition.Radius;
			Vector3 val2 = A + new Vector3(val.x, 0f, val.y);
			Vector3 val3 = val2 + Vector3.up * 4f;
			RaycastHit val4 = default(RaycastHit);
			if (Physics.Raycast(val2 + Vector3.up * 0.2f, Vector3.up, ref val4, 4f, -1, (QueryTriggerInteraction)1))
			{
				val3 = ((RaycastHit)(ref val4)).point - Vector3.up * 0.4f;
			}
			if (val3.y - val2.y < 0.65f || !ExtraPhysics.Clear(val3, 0.15f))
			{
				return;
			}
			if (isFish)
			{
				GameObject val5 = GameManager.SpawnNetworkPrefab(fish[Random.Range(0, fish.Length)], val3, Random.rotation, Vector3.one * 0.4f, false);
				if ((Object)(object)val5 == (Object)null)
				{
					return;
				}
				spawned.Add(new TimedObject
				{
					Object = val5,
					Expires = now + 12.0
				});
				Rigidbody[] componentsInChildren = val5.GetComponentsInChildren<Rigidbody>();
				foreach (Rigidbody val6 in componentsInChildren)
				{
					if (!val6.isKinematic)
					{
						val6.linearVelocity = Vector3.down * 1.5f;
					}
				}
			}
			else
			{
				Vector3 val7 = Vector3.down * 8f;
				drops.Add(new FireParticle
				{
					Position = val3,
					Velocity = val7,
					Expires = now + 1.5
				});
				((Spell)Spell).RpcPlayEffect((SpellEffectType)3, val3, Quaternion.LookRotation(val7));
			}
		}

		private void TickDrops(double now)
		{
			//IL_0038: 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_0047: 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_0055: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit hit = default(RaycastHit);
			for (int num = drops.Count - 1; num >= 0; num--)
			{
				FireParticle fireParticle = drops[num];
				if (now >= fireParticle.Expires)
				{
					drops.RemoveAt(num);
				}
				else
				{
					Vector3 val = fireParticle.Velocity * Time.fixedDeltaTime;
					if (Physics.SphereCast(fireParticle.Position, 0.1f, ((Vector3)(ref val)).normalized, ref hit, ((Vector3)(ref val)).magnitude, -1, (QueryTriggerInteraction)1))
					{
						ExtraNativeAssets.FireImpact(Spell, fireHitbox, hit);
						drops.RemoveAt(num);
					}
					else
					{
						fireParticle.Position += val;
					}
				}
			}
		}

		private void SendVisuals()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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)
			if (!((Object)(object)Spell == (Object)null) && NetworkServer.active && Life != null && Life.Alive(NetworkTime.time))
			{
				((Spell)Spell).RpcPlayEffect((SpellEffectType)1, A, frameA);
				if (Life.Paired)
				{
					((Spell)Spell).RpcPlayEffect((SpellEffectType)3, B, frameB);
				}
			}
		}

		internal void End()
		{
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			if (ended)
			{
				return;
			}
			ended = true;
			Life?.Stop();
			Active.Remove(this);
			foreach (Rigidbody item in orbit)
			{
				Orbits.Release(item, claimOwner);
			}
			orbit.Clear();
			previous.Clear();
			drops.Clear();
			foreach (TimedObject item2 in spawned)
			{
				if ((Object)(object)item2.Object != (Object)null)
				{
					if (NetworkServer.active)
					{
						NetworkServer.Destroy(item2.Object);
					}
					else
					{
						Object.Destroy((Object)(object)item2.Object);
					}
				}
			}
			spawned.Clear();
			if ((Object)(object)Spell != (Object)null)
			{
				if ((Object)(object)Spell.Zone == (Object)(object)this)
				{
					Spell.Zone = null;
				}
				if (NetworkServer.active && ((NetworkBehaviour)Spell).netId != 0)
				{
					((Spell)Spell).RpcPlayEffect((SpellEffectType)4, Vector3.zero, Quaternion.identity);
				}
				Spell.ClearVisuals();
			}
			if (Active.Count == 0)
			{
				PortalCooldown.Clear();
			}
			((Behaviour)this).enabled = false;
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		private void OnDestroy()
		{
			End();
		}
	}
	internal static class ExtraNativeAssets
	{
		private static readonly BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		internal static bool TryFish(ExtraSpell spell, out NetworkIdentity[] prefabs)
		{
			FishifySpell componentInChildren = ((Component)((NetworkBehaviour)spell).netIdentity).GetComponentInChildren<FishifySpell>(true);
			FieldInfo field = typeof(FishifySpell).GetField("fishPrefabs", Fields);
			prefabs = (((Object)(object)componentInChildren != (Object)null && field != null) ? (field.GetValue(componentInChildren) as NetworkIdentity[]) : null)?.Where((NetworkIdentity x) => (Object)(object)x != (Object)null && (Object)(object)((Component)x).GetComponentInChildren<Rigidbody>(true) != (Object)null).ToArray();
			if (prefabs != null && prefabs.Length != 0)
			{
				return true;
			}
			Plugin.Log.LogWarning((object)"FISH RAIN: vanilla fish prefabs unavailable; no charge consumed.");
			return false;
		}

		internal static bool TryFire(ExtraSpell spell, out GameObject prefab)
		{
			FireSelfSpell componentInChildren = ((Component)((NetworkBehaviour)spell).netIdentity).GetComponentInChildren<FireSelfSpell>(true);
			FieldInfo field = typeof(FireSelfSpell).GetField("hitboxPrefab", Fields);
			prefab = (GameObject)(((Object)(object)componentInChildren != (Object)null && field != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<NetworkIdentity>() != (Object)null && (Object)(object)prefab.GetComponent<HitboxBase>() != (Object)null)
			{
				return true;
			}
			Plugin.Log.LogWarning((object)"IGNIS RAIN: vanilla fire hitbox unavailable; no charge consumed.");
			return false;
		}

		internal static void FireImpact(ExtraSpell spell, GameObject prefab, RaycastHit hit)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null || (Object)(object)((Spell)spell).CasterIdentity == (Object)null)
			{
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(prefab, ((RaycastHit)(ref hit)).point + ((RaycastHit)(ref hit)).normal * 0.12f, Quaternion.identity);
			HitboxBase component = val.GetComponent<HitboxBase>();
			component.doTtl = true;
			component.ttl = 0.12f;
			component.Networkdamage = 6;
			component.propDamage = 4;
			component.NetworkpushForce = 1f;
			component.owner = ((Spell)spell).CasterIdentity;
			component.allowSelfHit = false;
			component.forceRagdoll = false;
			component.forceNpcStun = false;
			component.NetworkdoLineOfSight = true;
			float num = 0f;
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>();
			foreach (Collider val2 in componentsInChildren)
			{
				float num2 = num;
				Bounds bounds = val2.bounds;
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				num = Mathf.Max(num2, ((Vector3)(ref extents)).magnitude);
			}
			if (num > 0.001f)
			{
				Transform transform = val.transform;
				transform.localScale *= 0.65f / num;
			}
			NetworkServer.Spawn(val, (NetworkConnectionToClient)null);
			Type type = typeof(Spell).Assembly.GetType("YAPYAP.IIgnitable");
			if (type != null)
			{
				Component componentInParent = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent(type);
				if ((Object)(object)componentInParent != (Object)null)
				{
					type.GetMethod("SetIgnited").Invoke(componentInParent, new object[1] { true });
				}
			}
		}
	}
	internal sealed class ExtraVisual : MonoBehaviour
	{
		internal static readonly List<ExtraVisual> Active = new List<ExtraVisual>();

		internal ExtraSpell Spell;

		internal double Expires;

		private LineRenderer line;

		private Material material;

		private Mesh disk;

		internal static Color Tint(ExtraId id)
		{
			//IL_0042: Unknown result type (might be due to invalid IL o