Decompiled source of ValalaMods v1.3.4

ValalaMods.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using MT.Core;
using MT.Core.Habilidades;
using MT.Core.I18n;
using MT.Core.Mana;
using MT.Magia;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using ValalaMods.NorseFx;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ValalaMods")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.4.0")]
[assembly: AssemblyInformationalVersion("1.3.4+1022c824e6383dfb1c665578418a0a9420724956")]
[assembly: AssemblyProduct("ValalaMods")]
[assembly: AssemblyTitle("ValalaMods")]
[assembly: AssemblyVersion("1.3.4.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 ValalaMods
{
	internal static class ElementIcons
	{
		private const int Size = 128;

		private static readonly Dictionary<Element, Sprite> Cache = new Dictionary<Element, Sprite>();

		private static Sprite _hub;

		internal static Sprite Get(Element element)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (Cache.TryGetValue(element, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			value = Build(element, ElementRegistry.Get(element).Tint);
			Cache[element] = value;
			return value;
		}

		internal static Sprite Hub()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_hub != (Object)null)
			{
				return _hub;
			}
			_hub = Build(Element.Lightning, new Color(0.1f, 0.11f, 0.14f), drawGlyph: false);
			((Object)_hub).name = "Valala_ElementHub";
			return _hub;
		}

		private static Sprite Build(Element element, Color tint, bool drawGlyph = true)
		{
			//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_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_007a: 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_0082: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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)
			Color32[] array = (Color32[])(object)new Color32[16384];
			float num = 63.5f;
			float num2 = 63.5f;
			float num3 = 58.88f;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num4 = (float)j - num;
					float num5 = (float)i - num2;
					float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5);
					float num7 = Mathf.Clamp01((num3 - num6) / 2f);
					if (num7 <= 0f)
					{
						continue;
					}
					float num8 = Mathf.Lerp(0.55f, 1.05f, num6 / num3);
					Color val = tint * num8;
					float num9 = num7 * 0.92f;
					if (drawGlyph)
					{
						float x = (float)j / 127f;
						float y = (float)i / 127f;
						if (InGlyph(element, x, y))
						{
							val = Color.white;
							num9 = num7;
						}
					}
					array[i * 128 + j] = Color32.op_Implicit(new Color(val.r, val.g, val.b, num9));
				}
			}
			Texture2D val2 = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			val2.SetPixels32(array);
			val2.Apply();
			Sprite obj = Sprite.Create(val2, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f));
			((Object)obj).name = "Valala_ElementIcon_" + element;
			return obj;
		}

		private static bool InGlyph(Element element, float x, float y)
		{
			switch (element)
			{
			case Element.Lightning:
				if (!(DistanceToSegment(x, y, 0.58f, 0.84f, 0.4f, 0.54f) < 0.045f) && !(DistanceToSegment(x, y, 0.4f, 0.54f, 0.6f, 0.5f) < 0.045f))
				{
					return DistanceToSegment(x, y, 0.6f, 0.5f, 0.42f, 0.16f) < 0.045f;
				}
				return true;
			case Element.Rock:
				if (!(DistanceToSegment(x, y, 0.5f, 0.82f, 0.24f, 0.62f) < 0.035f) && !(DistanceToSegment(x, y, 0.24f, 0.62f, 0.32f, 0.3f) < 0.035f) && !(DistanceToSegment(x, y, 0.32f, 0.3f, 0.68f, 0.3f) < 0.035f) && !(DistanceToSegment(x, y, 0.68f, 0.3f, 0.76f, 0.62f) < 0.035f) && !(DistanceToSegment(x, y, 0.76f, 0.62f, 0.5f, 0.82f) < 0.035f))
				{
					return DistanceToSegment(x, y, 0.38f, 0.58f, 0.62f, 0.46f) < 0.025f;
				}
				return true;
			case Element.Fire:
				if (InTriangle(x, y, 0.5f, 0.86f, 0.28f, 0.34f, 0.72f, 0.34f))
				{
					return !InTriangle(x, y, 0.5f, 0.62f, 0.42f, 0.28f, 0.58f, 0.28f);
				}
				return false;
			case Element.Poison:
				if (!InCircle(x, y, 0.5f, 0.38f, 0.17f) && !InCircle(x, y, 0.5f, 0.64f, 0.09f) && !InCircle(x, y, 0.33f, 0.72f, 0.055f))
				{
					return InCircle(x, y, 0.67f, 0.72f, 0.055f);
				}
				return true;
			case Element.Ice:
				if (!(DistanceToSegment(x, y, 0.5f, 0.16f, 0.5f, 0.84f) < 0.035f) && !(DistanceToSegment(x, y, 0.3f, 0.28f, 0.7f, 0.72f) < 0.035f))
				{
					return DistanceToSegment(x, y, 0.7f, 0.28f, 0.3f, 0.72f) < 0.035f;
				}
				return true;
			default:
				return false;
			}
		}

		private static float DistanceToSegment(float px, float py, float ax, float ay, float bx, float by)
		{
			float num = bx - ax;
			float num2 = by - ay;
			float num3 = px - ax;
			float num4 = py - ay;
			float num5 = num * num + num2 * num2;
			float num6 = ((num5 <= 0f) ? 0f : Mathf.Clamp01((num3 * num + num4 * num2) / num5));
			float num7 = num3 - num * num6;
			float num8 = num4 - num2 * num6;
			return Mathf.Sqrt(num7 * num7 + num8 * num8);
		}

		private static bool InCircle(float px, float py, float cx, float cy, float radius)
		{
			float num = px - cx;
			float num2 = py - cy;
			return num * num + num2 * num2 <= radius * radius;
		}

		private static bool InTriangle(float px, float py, float ax, float ay, float bx, float by, float cx, float cy)
		{
			float num = Sign(px, py, ax, ay, bx, by);
			float num2 = Sign(px, py, bx, by, cx, cy);
			float num3 = Sign(px, py, cx, cy, ax, ay);
			bool flag = num < 0f || num2 < 0f || num3 < 0f;
			bool flag2 = num > 0f || num2 > 0f || num3 > 0f;
			return !(flag && flag2);
		}

		private static float Sign(float px, float py, float ax, float ay, float bx, float by)
		{
			return (px - bx) * (ay - by) - (ax - bx) * (py - by);
		}
	}
	internal enum Element
	{
		Lightning,
		Rock,
		Fire,
		Poison,
		Ice
	}
	internal enum ElementDamage
	{
		Lightning,
		Blunt,
		Fire,
		Poison,
		Frost
	}
	internal sealed class ElementDef
	{
		internal Element Id { get; }

		internal string Name { get; }

		internal string ColorHex { get; }

		internal bool Implemented { get; }

		internal ElementDamage Damage { get; }

		internal float StaggerMultiplier { get; }

		internal string[] BoltPrefabs { get; }

		internal string[] AoePrefabs { get; }

		internal string[] LandingAoePrefabs { get; }

		internal string[] SparkPrefabs { get; }

		internal string NorseEffectId { get; }

		internal string NorseSfxId { get; }

		internal Color Tint => ValalaModsPlugin.ParseColor(ColorHex);

		internal ElementDef(Element id, string name, string colorHex, bool implemented, ElementDamage damage, float staggerMultiplier, string[] boltPrefabs, string[] aoePrefabs, string[] sparkPrefabs, string[] landingAoePrefabs = null, string norseEffectId = null, string norseSfxId = null)
		{
			Id = id;
			Name = name;
			ColorHex = colorHex;
			Implemented = implemented;
			Damage = damage;
			StaggerMultiplier = staggerMultiplier;
			BoltPrefabs = boltPrefabs;
			AoePrefabs = aoePrefabs;
			LandingAoePrefabs = landingAoePrefabs ?? aoePrefabs;
			SparkPrefabs = sparkPrefabs;
			NorseEffectId = norseEffectId;
			NorseSfxId = norseSfxId;
		}
	}
	internal static class ElementRegistry
	{
		internal static readonly ElementDef[] All = new ElementDef[5]
		{
			new ElementDef(Element.Lightning, "Foudre", "59BFFF", implemented: true, ElementDamage.Lightning, 1f, new string[1] { "fx_Lightning" }, new string[1] { "lightningAOE" }, new string[1] { "fx_chainlightning_hit" }),
			new ElementDef(Element.Rock, "Roche", "B08A5A", implemented: true, ElementDamage.Blunt, 2f, new string[2] { "vfx_RockHit", "vfx_stonegolem_attack_hit" }, new string[3] { "vfx_RockDestroyed_large", "vfx_RockDestroyed", "vfx_RockHit" }, new string[2] { "vfx_RockHit", "vfx_stonegolem_attack_hit" }),
			new ElementDef(Element.Fire, "Feu", "FF7A3C", implemented: true, ElementDamage.Fire, 1f, new string[4] { "fireball_explosion", "fx_fireball_explosion", "fx_groundfire", "fx_burning" }, new string[1] { "fx_groundfire" }, new string[2] { "fx_sword_fire_hit", "fx_burning" }, new string[3] { "fireball_explosion", "fx_fireball_explosion", "fx_groundfire" }),
			new ElementDef(Element.Poison, "Poison", "8BD450", implemented: true, ElementDamage.Poison, 1f, new string[3] { "vfx_BombBlob_explode_poison", "vfx_BombBlob_explode_poisonelite", "vfx_Poison" }, new string[3] { "vfx_BombBlob_explode_poisonelite", "vfx_BombBlob_explode_poison", "vfx_Poison" }, new string[2] { "vfx_poisonarrow_hit", "vfx_Poison" }),
			new ElementDef(Element.Ice, "Glace", "9FE8FF", implemented: true, ElementDamage.Frost, 1f, new string[3] { "vfx_BombBlob_explode_frost", "FenringIceNova_aoe", "vfx_FrostOrbs" }, new string[3] { "FenringIceNova_aoe", "vfx_BombBlob_explode_frost", "vfx_Frost" }, new string[3] { "fx_iceshard_hit", "vfx_frostarrow_hit", "vfx_blob_frost_hit" }, new string[3] { "vfx_BombBlob_explode_frost", "vfx_Frost", "FenringIceNova_aoe" })
		};

		internal static Element Current { get; set; } = Element.Lightning;

		internal static ElementDef Get(Element id)
		{
			if (id < Element.Lightning || (int)id >= All.Length)
			{
				return All[0];
			}
			return All[(int)id];
		}

		internal static Element Parse(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return Element.Lightning;
			}
			if (string.Equals(name, "Vent", StringComparison.OrdinalIgnoreCase) || string.Equals(name, "Wind", StringComparison.OrdinalIgnoreCase))
			{
				return Element.Rock;
			}
			ElementDef[] all = All;
			foreach (ElementDef elementDef in all)
			{
				if (string.Equals(elementDef.Name, name, StringComparison.OrdinalIgnoreCase) || string.Equals(elementDef.Id.ToString(), name, StringComparison.OrdinalIgnoreCase))
				{
					return elementDef.Id;
				}
			}
			return Element.Lightning;
		}
	}
	internal static class ElementFx
	{
		internal static void Spawn(Element element, Vector3 pos, float duration, float radius, float height, Color color)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ElementDef elementDef = ElementRegistry.Get(element);
			if (elementDef.Implemented)
			{
				ElementVfx.Spawn(elementDef, pos, duration, radius, height, color);
			}
		}

		internal static void SpawnLanding(Element element, Vector3 pos, float duration, float radius, Color color)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			ElementDef elementDef = ElementRegistry.Get(element);
			if (elementDef.Implemented)
			{
				ElementVfx.SpawnLanding(elementDef, pos, duration, radius, color);
			}
		}
	}
	internal sealed class ElementSelectorUi : MonoBehaviour
	{
		private const float WheelRadius = 132f;

		private const float ButtonSize = 116f;

		private const float HubSize = 132f;

		private const float AnimSpeed = 6f;

		private GameObject _panel;

		private RectTransform _panelRect;

		private CanvasGroup _group;

		private TextMeshProUGUI _hubLabel;

		private Image _hub;

		private readonly Image[] _icons = (Image[])(object)new Image[ElementRegistry.All.Length];

		private readonly TextMeshProUGUI[] _labels = (TextMeshProUGUI[])(object)new TextMeshProUGUI[ElementRegistry.All.Length];

		private bool _built;

		private bool _open;

		private float _anim;

		private float _animTarget;

		private Element _lastRendered;

		internal static bool IsMenuVisible { get; private set; }

		private void Update()
		{
			if (ValalaModsPlugin.IsHeadless)
			{
				return;
			}
			try
			{
				if (!_built)
				{
					if (!((Object)(object)Player.m_localPlayer == (Object)null))
					{
						TryBuild();
					}
					return;
				}
				Animate();
				if ((Object)(object)Player.m_localPlayer == (Object)null)
				{
					if (_open)
					{
						SetVisible(visible: false);
					}
					return;
				}
				if (_lastRendered != ElementRegistry.Current)
				{
					RefreshVisuals();
				}
				if (!TextInput.IsVisible() && ValalaModsPlugin.IsMenuKeyDown())
				{
					SetVisible(!_open);
				}
			}
			catch (Exception ex)
			{
				ValalaModsPlugin.Log.LogError((object)("ElementSelectorUi.Update failed: " + ex));
			}
		}

		private void TryBuild()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_00ec: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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)
			_built = true;
			TMP_FontAsset val = ResolveFont();
			if ((Object)(object)val == (Object)null)
			{
				ValalaModsPlugin.Log.LogWarning((object)"Element menu: no TextMeshPro font found, UI disabled.");
				return;
			}
			GameObject val2 = new GameObject("Valala_ElementMenu");
			Object.DontDestroyOnLoad((Object)(object)val2);
			Canvas obj = val2.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 30000;
			CanvasScaler obj2 = val2.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 0.5f;
			val2.AddComponent<GraphicRaycaster>();
			EnsureEventSystem();
			float num = 440f;
			_panel = new GameObject("Wheel", new Type[1] { typeof(RectTransform) });
			_panel.transform.SetParent(val2.transform, false);
			_panelRect = (RectTransform)_panel.transform;
			_panelRect.anchorMin = new Vector2(0.5f, 0.5f);
			_panelRect.anchorMax = new Vector2(0.5f, 0.5f);
			_panelRect.pivot = new Vector2(0.5f, 0.5f);
			_panelRect.anchoredPosition = Vector2.zero;
			_panelRect.sizeDelta = new Vector2(num, num);
			_group = _panel.AddComponent<CanvasGroup>();
			CreateHub(val);
			for (int i = 0; i < ElementRegistry.All.Length; i++)
			{
				CreateButton(val, i);
			}
			RefreshVisuals();
			SetVisible(visible: false);
		}

		private void CreateHub(TMP_FontAsset font)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			_hub = CreateDisc(_panel.transform, "Hub", ElementIcons.Hub(), 132f);
			((Graphic)_hub).raycastTarget = false;
			_hubLabel = CreateText(_panel.transform, font, "Classe", 24f, (TextAlignmentOptions)514);
			RectTransform rectTransform = ((TMP_Text)_hubLabel).rectTransform;
			rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			rectTransform.pivot = new Vector2(0.5f, 0.5f);
			rectTransform.sizeDelta = new Vector2(132f, 40f);
			rectTransform.anchoredPosition = Vector2.zero;
		}

		private void CreateButton(TMP_FontAsset font, int index)
		{
			//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_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_00a1: 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_00b6: 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_00cb: 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_00e0: 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_00f5: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_0158: Expected O, but got Unknown
			//IL_0187: 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_01b1: 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_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			ElementDef elementDef = ElementRegistry.All[index];
			int num = ElementRegistry.All.Length;
			float num2 = (90f - (float)index * (360f / (float)num)) * ((float)Math.PI / 180f);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(Mathf.Cos(num2), Mathf.Sin(num2));
			GameObject val2 = new GameObject("Element_" + elementDef.Id, new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(_panel.transform, false);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = new Vector2(0.5f, 0.5f);
			val3.anchorMax = new Vector2(0.5f, 0.5f);
			val3.pivot = new Vector2(0.5f, 0.5f);
			val3.sizeDelta = new Vector2(116f, 116f);
			val3.anchoredPosition = val * 132f;
			Image val4 = val2.AddComponent<Image>();
			val4.sprite = ElementIcons.Get(elementDef.Id);
			((Graphic)val4).raycastTarget = true;
			Button obj = val2.AddComponent<Button>();
			((Selectable)obj).targetGraphic = (Graphic)(object)val4;
			Element captured = elementDef.Id;
			((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
			{
				Select(captured);
			});
			TextMeshProUGUI val5 = CreateText(val2.transform, font, elementDef.Name, 20f, (TextAlignmentOptions)514);
			RectTransform rectTransform = ((TMP_Text)val5).rectTransform;
			rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			rectTransform.pivot = new Vector2(0.5f, 0.5f);
			rectTransform.sizeDelta = new Vector2(220f, 26f);
			rectTransform.anchoredPosition = val * 70f;
			_icons[index] = val4;
			_labels[index] = val5;
		}

		private static Image CreateDisc(Transform parent, string name, Sprite sprite, float size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0066: 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_0073: 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)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = new Vector2(0.5f, 0.5f);
			val2.anchorMax = new Vector2(0.5f, 0.5f);
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.sizeDelta = new Vector2(size, size);
			val2.anchoredPosition = Vector2.zero;
			Image obj = val.AddComponent<Image>();
			obj.sprite = sprite;
			return obj;
		}

		private static TextMeshProUGUI CreateText(Transform parent, TMP_FontAsset font, string text, float size, TextAlignmentOptions align)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			GameObject val = new GameObject("Text", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).font = font;
			((TMP_Text)obj).fontSize = size;
			((TMP_Text)obj).text = text;
			((TMP_Text)obj).alignment = align;
			((Graphic)obj).color = Color.white;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private void Select(Element element)
		{
			if (element != ElementRegistry.Current)
			{
				ElementRegistry.Current = element;
				try
				{
					ValalaModsPlugin.SelectedElement.Value = ElementRegistry.Get(element).Name;
				}
				catch (Exception ex)
				{
					ValalaModsPlugin.Log.LogError((object)("Element menu: could not persist selection: " + ex));
				}
			}
			RefreshVisuals();
			SetVisible(visible: false);
		}

		private void RefreshVisuals()
		{
			//IL_005c: 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_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			_lastRendered = ElementRegistry.Current;
			for (int i = 0; i < _icons.Length; i++)
			{
				bool flag = ElementRegistry.All[i].Id == ElementRegistry.Current;
				if ((Object)(object)_icons[i] != (Object)null)
				{
					((Graphic)_icons[i]).color = (Color)(flag ? Color.white : new Color(1f, 1f, 1f, 0.6f));
					((Transform)((Graphic)_icons[i]).rectTransform).localScale = Vector3.one * (flag ? 1.12f : 1f);
				}
				if ((Object)(object)_labels[i] != (Object)null)
				{
					((Graphic)_labels[i]).color = (Color)(flag ? Color.white : new Color(0.75f, 0.75f, 0.75f, 1f));
				}
			}
			if ((Object)(object)_hubLabel != (Object)null)
			{
				((TMP_Text)_hubLabel).text = ElementRegistry.Get(ElementRegistry.Current).Name;
			}
			if ((Object)(object)_hub != (Object)null)
			{
				((Graphic)_hub).color = Color.Lerp(Color.white, ElementRegistry.Get(ElementRegistry.Current).Tint, 0.35f);
			}
		}

		private void SetVisible(bool visible)
		{
			if ((Object)(object)_panel == (Object)null)
			{
				return;
			}
			_open = visible;
			IsMenuVisible = visible;
			_animTarget = (visible ? 1f : 0f);
			if (visible)
			{
				if ((Object)(object)_panel != (Object)null && !_panel.activeSelf)
				{
					_panel.SetActive(true);
				}
				if (_anim <= 0f)
				{
					_anim = 0.0001f;
				}
				ApplyAnim(_anim);
				RefreshVisuals();
			}
		}

		private void Animate()
		{
			if (Mathf.Approximately(_anim, _animTarget))
			{
				if (_animTarget <= 0f)
				{
					Deactivate();
				}
				return;
			}
			_anim = Mathf.MoveTowards(_anim, _animTarget, Time.unscaledDeltaTime * 6f);
			ApplyAnim(_anim);
			if (_anim <= 0f)
			{
				Deactivate();
			}
		}

		private void ApplyAnim(float t)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			float num = t * t * (3f - 2f * t);
			if ((Object)(object)_group != (Object)null)
			{
				_group.alpha = num;
			}
			if ((Object)(object)_panelRect != (Object)null)
			{
				((Transform)_panelRect).localScale = Vector3.one * (0.72f + 0.28f * num);
				((Transform)_panelRect).localRotation = Quaternion.Euler(0f, 0f, -8f * (1f - num));
			}
		}

		private void Deactivate()
		{
			if ((Object)(object)_panel != (Object)null && _panel.activeSelf)
			{
				_panel.SetActive(false);
			}
		}

		private static void EnsureEventSystem()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)EventSystem.current != (Object)null) && !((Object)(object)Object.FindFirstObjectByType<EventSystem>() != (Object)null))
			{
				GameObject val = new GameObject("Valala_EventSystem");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<EventSystem>();
				val.AddComponent<StandaloneInputModule>();
			}
		}

		private static TMP_FontAsset ResolveFont()
		{
			if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null)
			{
				return TMP_Settings.defaultFontAsset;
			}
			TextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll<TextMeshProUGUI>();
			foreach (TextMeshProUGUI val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null)
				{
					return ((TMP_Text)val).font;
				}
			}
			return null;
		}
	}
	internal static class LandingBoom
	{
		internal const string EffectId = "norse.landing.lightning_boom";

		private const string ThorVfxPrefab = "vfx_sledge_iron_hit";

		private const string ThorSfxPrefab = "sfx_sledge_iron_hit";

		private const float DestroyAfter = 5f;

		private static bool _thorVfxWarned;

		private static bool _thorSfxWarned;

		internal static void Spawn(Vector3 position, float fallHeight)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0023: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType == 4 || !ValalaModsPlugin.Enabled.Value || !ValalaModsPlugin.LandingBoom.Value)
			{
				return;
			}
			try
			{
				if (!SpawnThorImpact(position))
				{
					if ((Object)(object)NorseFxService.SpawnVfx("norse.landing.lightning_boom", position, Quaternion.identity, null, 3f) != (Object)null)
					{
						NorseFxService.PlaySfx("norse.landing.lightning_boom", position);
						return;
					}
					ElementDef elementDef = ElementRegistry.Get(Element.Lightning);
					ElementFx.Spawn(Element.Lightning, position, 1.5f, 1f, 1f, elementDef.Tint);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = ValalaModsPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Landing boom failed: " + ex.Message));
				}
			}
		}

		private static bool SpawnThorImpact(Vector3 position)
		{
			//IL_004d: 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)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return false;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("vfx_sledge_iron_hit");
			if ((Object)(object)prefab == (Object)null)
			{
				if (!_thorVfxWarned)
				{
					_thorVfxWarned = true;
					ManualLogSource log = ValalaModsPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"Vanilla VFX not found: vfx_sledge_iron_hit (using Norse fallback)");
					}
				}
				return false;
			}
			SpawnLocal(prefab, position);
			PlayImpactSound(position);
			return true;
		}

		internal static void PlayImpactSound(Vector3 position)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			try
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("sfx_sledge_iron_hit");
				if ((Object)(object)prefab != (Object)null)
				{
					SpawnLocal(prefab, position);
				}
				else if (!_thorSfxWarned)
				{
					_thorSfxWarned = true;
					ManualLogSource log = ValalaModsPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"Vanilla SFX not found: sfx_sledge_iron_hit");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = ValalaModsPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Landing impact sound failed: " + ex.Message));
				}
			}
		}

		private static void SpawnLocal(GameObject prefab, Vector3 position)
		{
			//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)
			Object.Destroy((Object)(object)Object.Instantiate<GameObject>(prefab, position, Quaternion.identity), 5f);
		}
	}
	[HarmonyPatch(typeof(Character), "UpdateGroundContact")]
	internal static class LandingBoomPatch
	{
		private static readonly FieldRef<Character, bool> GroundContact = AccessTools.FieldRefAccess<Character, bool>("m_groundContact");

		private static readonly FieldRef<Character, float> MaxAirAltitude = AccessTools.FieldRefAccess<Character, float>("m_maxAirAltitude");

		private static readonly FieldRef<Character, Vector3> GroundContactPoint = AccessTools.FieldRefAccess<Character, Vector3>("m_groundContactPoint");

		private static float _nextAllowedTime;

		private static float LandingThreshold(bool landingBoom, bool landingThunder)
		{
			float num = float.MaxValue;
			if (landingBoom)
			{
				num = Mathf.Min(num, ValalaModsPlugin.LandingHeight.Value);
			}
			if (landingThunder)
			{
				num = Mathf.Min(num, Mathf.Max(ValalaModsPlugin.LandingThunderHeight.Value, ValalaModsPlugin.LandingHeight.Value));
			}
			return num;
		}

		private static void Prefix(Character __instance)
		{
			//IL_00b2: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				Element current = ElementRegistry.Current;
				ElementDef elementDef = ElementRegistry.Get(current);
				bool value = ValalaModsPlugin.LandingBoom.Value;
				bool flag = current == Element.Lightning && ValalaModsPlugin.LandingThunder.Value;
				if (!ValalaModsPlugin.Enabled.Value || !elementDef.Implemented || !ValalaRings.IsEquipped(val, current) || (!value && !flag) || !GroundContact.Invoke(__instance) || __instance.IsDead() || __instance.IsTeleporting() || __instance.IsSwimming())
				{
					return;
				}
				float num = MaxAirAltitude.Invoke(__instance) - ((Component)__instance).transform.position.y;
				if (num < LandingThreshold(value, flag) || Time.time < _nextAllowedTime)
				{
					return;
				}
				_nextAllowedTime = Time.time + 0.5f;
				Vector3 val2 = GroundContactPoint.Invoke(__instance);
				if (val2 == Vector3.zero)
				{
					val2 = ((Component)__instance).transform.position;
				}
				bool flag2 = flag && LandingThunder.IsAboveThreshold(num);
				RpcSync.BroadcastLanding(current, val2, num);
				if (ValalaModsPlugin.Damage.Value)
				{
					if (flag2)
					{
						LandingThunder.Damage(val, val2, num);
					}
					else if (value)
					{
						ValalaModsPlugin.DamageEnemiesAt(val, val2, ValalaModsPlugin.LandingRadius.Value, current);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = ValalaModsPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Landing boom check failed: " + ex.Message));
				}
			}
		}
	}
	internal static class LandingEffects
	{
		internal static void Spawn(Element element, Vector3 position, float fallHeight)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0026: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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)
			if ((int)SystemInfo.graphicsDeviceType == 4 || !ValalaModsPlugin.Enabled.Value)
			{
				return;
			}
			try
			{
				if (element == Element.Lightning)
				{
					if (ValalaModsPlugin.LandingBoom.Value)
					{
						LandingBoom.Spawn(position, fallHeight);
					}
					if (ValalaModsPlugin.LandingThunder.Value)
					{
						LandingThunder.Spawn(position, fallHeight);
					}
				}
				else if (ValalaModsPlugin.LandingBoom.Value)
				{
					ElementDef elementDef = ElementRegistry.Get(element);
					if (elementDef.Implemented)
					{
						ElementFx.SpawnLanding(element, position, ValalaModsPlugin.Duration.Value, ValalaModsPlugin.LandingRadius.Value, elementDef.Tint);
						LandingBoom.PlayImpactSound(position);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = ValalaModsPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Landing effect failed: " + ex.Message));
				}
			}
		}
	}
	internal static class LandingThunder
	{
		internal static bool IsAboveThreshold(float fallHeight)
		{
			float num = Mathf.Max(ValalaModsPlugin.LandingThunderHeight.Value, ValalaModsPlugin.LandingHeight.Value);
			return fallHeight >= num;
		}

		internal static void Spawn(Vector3 position, float fallHeight)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType == 4 || !ValalaModsPlugin.Enabled.Value || !ValalaModsPlugin.LandingThunder.Value || !IsAboveThreshold(fallHeight))
			{
				return;
			}
			try
			{
				ElementFx.Spawn(Element.Lightning, position, ValalaModsPlugin.Duration.Value, ValalaModsPlugin.Radius.Value, ValalaModsPlugin.Height.Value, ValalaModsPlugin.ParseColor(ValalaModsPlugin.ColorHex.Value));
			}
			catch (Exception ex)
			{
				ManualLogSource log = ValalaModsPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Landing thunder VFX failed: " + ex.Message));
				}
			}
		}

		internal static void Damage(Player player, Vector3 position, float fallHeight)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || !ValalaModsPlugin.Enabled.Value || !ValalaModsPlugin.LandingThunder.Value || !ValalaModsPlugin.Damage.Value || !IsAboveThreshold(fallHeight))
			{
				return;
			}
			try
			{
				ValalaModsPlugin.DamageEnemiesAt(player, position, ValalaModsPlugin.LandingThunderRadius.Value, Element.Lightning);
			}
			catch (Exception ex)
			{
				ManualLogSource log = ValalaModsPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Landing thunder damage failed: " + ex.Message));
				}
			}
		}
	}
	[BepInPlugin("odin.valala.raja.mods", "Valala Mods", "1.3.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ValalaModsPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "odin.valala.raja.mods";

		public const string PluginName = "Valala Mods";

		public const string PluginVersion = "1.3.4";

		private const int CastLandingDamageMinQuality = 3;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<string> Mode;

		internal static ConfigEntry<float> Duration;

		internal static ConfigEntry<float> Radius;

		internal static ConfigEntry<float> Height;

		internal static ConfigEntry<string> ColorHex;

		internal static ConfigEntry<bool> AffectMk1Jump;

		internal static ConfigEntry<bool> Damage;

		internal static ConfigEntry<float> DamageMin;

		internal static ConfigEntry<float> DamageMax;

		internal static ConfigEntry<bool> SyncToOthers;

		internal static ConfigEntry<string> MenuKey;

		internal static ConfigEntry<string> SelectedElement;

		internal static ConfigEntry<float> RingDamageBonus;

		internal static ConfigEntry<float> RingDamageBonusPerLevel;

		internal static ConfigEntry<bool> EnableSecondTrinketSlot;

		internal static ConfigEntry<bool> EnableStaffFreeWindImpulse;

		internal static ConfigEntry<string> StaffFreeCastKey;

		internal static ConfigEntry<bool> EnableNorseFx;

		internal static ConfigEntry<bool> LandingBoom;

		internal static ConfigEntry<float> LandingHeight;

		internal static ConfigEntry<float> LandingRadius;

		internal static ConfigEntry<bool> LandingThunder;

		internal static ConfigEntry<float> LandingThunderHeight;

		internal static ConfigEntry<float> LandingThunderRadius;

		internal static KeyCode MenuKeyCode = (KeyCode)59;

		internal static ManualLogSource Log;

		internal static ValalaModsPlugin Instance;

		private static readonly string[] MenuKeyPresets = new string[16]
		{
			"Semicolon", "F7", "F8", "F9", "F10", "B", "N", "J", "K", "L",
			"LeftBracket", "RightBracket", "Minus", "Equals", "BackQuote", "Quote"
		};

		private static readonly string[] StaffFreeCastKeyPresets = new string[16]
		{
			"Alt+E", "Alt+R", "Alt+F", "Alt+Q", "Alt+T", "Alt+G", "Alt+V", "Alt+C", "E", "R",
			"F", "Q", "T", "G", "V", "C"
		};

		private Harmony _harmony;

		private FileSystemWatcher _configWatcher;

		private volatile bool _pendingReload;

		private float _reloadDelay;

		internal static bool IsHeadless { get; private set; }

		private void Awake()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Expected O, but got Unknown
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Expected O, but got Unknown
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Expected O, but got Unknown
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Expected O, but got Unknown
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Expected O, but got Unknown
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ac: Expected O, but got Unknown
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Expected O, but got Unknown
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Expected O, but got Unknown
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Expected O, but got Unknown
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_054f: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			IsHeadless = Application.isBatchMode || (int)SystemInfo.graphicsDeviceType == 4;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Add or replace an elemental VFX on the Wind Impulse / Wind Boost dash.");
			Mode = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Mode", "Add", new ConfigDescription("Add = keep the wind VFX and overlay the selected element. Replace = selected element only when its ring is equipped. Staff-free casts always use the Valala VFX.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Add", "Replace" }), Array.Empty<object>()));
			Duration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Duration", 1.5f, "Lifetime of the single elemental strike VFX in seconds.");
			Radius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Radius", 0.5f, "Blast radius for the strike visuals and damage.");
			Height = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Height", 1.8f, "Elemental VFX height factor.");
			ColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Color", "59BFFF", "Lightning tint as hex RRGGBB. Other elements use their own tint.");
			AffectMk1Jump = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectMk1Jump", false, "Also trigger the strike (and damage) on the Mk-I armor jump (which shares the same VFX call).");
			Damage = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Damage", true, "Deal elemental damage to hostile enemies only (never to you, other players, tames or NPCs).");
			DamageMin = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DamageMin", 8f, "Elemental damage at Elemental Magic skill level 0.");
			DamageMax = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DamageMax", 60f, "Elemental damage at Elemental Magic skill level 100.");
			SyncToOthers = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SyncToOthers", true, "Broadcast the strike to every player in range (client-side RPC). Off = only you see it.");
			MenuKey = ((BaseUnityPlugin)this).Config.Bind<string>("General", "MenuKey", "Semicolon", new ConfigDescription("Key that toggles the element class menu (preset dropdown).", (AcceptableValueBase)(object)new AcceptableValueList<string>(MenuKeyPresets), Array.Empty<object>()));
			SelectedElement = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SelectedElement", "Foudre", new ConfigDescription("Selected element class (persisted).", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[5] { "Foudre", "Roche", "Feu", "Poison", "Glace" }), Array.Empty<object>()));
			RingDamageBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Rings", "DamageBonus", 0.15f, new ConfigDescription("Damage bonus applied when the matching Valala ring is equipped. 0.15 = +15%.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			RingDamageBonusPerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Rings", "DamageBonusPerLevel", 0.15f, new ConfigDescription("Additional damage bonus per ring quality above 1. 0.15 = +15% per level; quality 4 gives +60% total.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
			EnableSecondTrinketSlot = ((BaseUnityPlugin)this).Config.Bind<bool>("Rings", "SecondTrinketSlot", true, "Enable a second trinket slot through ExtraSlotsCustomSlots. Set ExtraSlotsCustomSlots custom slot 1 Enabled=true.");
			EnableStaffFreeWindImpulse = ((BaseUnityPlugin)this).Config.Bind<bool>("Rings", "StaffFreeWindImpulse", true, "Cast Wind Impulse without a staff using any Valala ring quality. Own charge/jump system with free movement and no charge animation.");
			StaffFreeCastKey = ((BaseUnityPlugin)this).Config.Bind<string>("Rings", "StaffFreeCastKey", "Alt+F", new ConfigDescription("Shortcut for staff-free Wind Impulse. Alt+F keeps plain F free for MT Toki Step.", (AcceptableValueBase)(object)new AcceptableValueList<string>(StaffFreeCastKeyPresets), Array.Empty<object>()));
			LandingBoom = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LandingBoom", true, "Spawn an elemental landing impact when landing after a fall (requires the matching ring; non-Lightning impacts have no light flash).");
			LandingHeight = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LandingHeight", 10f, new ConfigDescription("Minimum fall height for the landing impact, meters. Vanilla fall damage: 10 m ~= 37.5, 20 m = 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 50f), Array.Empty<object>()));
			LandingRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LandingRadius", 4f, new ConfigDescription("Elemental landing and q3/q4 cast damage radius, meters. Damage uses DamageMin/DamageMax, the ElementalMagic skill and the ring bonus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			LandingThunder = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LandingThunder", true, "Spawn the high-fall lightning VFX on landing from a higher fall (Lightning class only).");
			LandingThunderHeight = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LandingThunderHeight", 20f, new ConfigDescription("Minimum fall height for the high-fall lightning VFX and damage, meters. Effective threshold is at least LandingHeight.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 80f), Array.Empty<object>()));
			LandingThunderRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LandingThunderRadius", 4f, new ConfigDescription("High-fall lightning damage radius, meters. Damage uses DamageMin/DamageMax and the ElementalMagic skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			MigrateSelectedElement();
			if (!IsHeadless)
			{
				MigrateStaffFreeCastKey();
			}
			RefreshMenuKeyCode();
			RefreshSelectedElement();
			MenuKey.SettingChanged += delegate
			{
				RefreshMenuKeyCode();
			};
			SelectedElement.SettingChanged += delegate
			{
				RefreshSelectedElement();
			};
			ValalaRings.Register();
			ValidateElementRegistry();
			if (NorseFxCatalog.Count > 0)
			{
				EnableNorseFx = ((BaseUnityPlugin)this).Config.Bind<bool>("Norse FX", "Enabled", true, "Use the selected VFX/SFX from the local norsefx.bundle. Vanilla fallback when the bundle is missing.");
			}
			SetupConfigWatcher();
			if (!IsHeadless)
			{
				CreateElementMenu();
				CreateWindChargeHud();
			}
			_harmony = new Harmony("odin.valala.raja.mods");
			try
			{
				_harmony.PatchAll(typeof(WindImpulsePatch));
				_harmony.PatchAll(typeof(ZNetAwakePatch));
				_harmony.PatchAll(typeof(LandingBoomPatch));
				SecondTrinketSlot.Apply(_harmony);
				if (!IsHeadless)
				{
					_harmony.PatchAll(typeof(CursorCapturePatch));
					_harmony.PatchAll(typeof(CameraLookPatch));
					StaffFreeWindImpulse.Initialize(_harmony);
				}
				Log.LogInfo((object)("Valala Mods loaded: patched WindImpulseVfx.Spawn (Mode=" + Mode.Value + ", rings + elemental VFX), landing effects" + (IsHeadless ? "; headless server mode (client input/UI disabled)." : " and staff-free Wind Impulse (own charge/jump).")));
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not install Harmony patches: " + ex));
			}
			if (NorseFxCatalog.Count > 0)
			{
				Log.LogInfo((object)("Norse FX module: " + NorseFxCatalog.Count + " selected effect(s), bundle " + (NorseFxResolver.BundlePresent ? "found." : "missing (vanilla fallback).")));
			}
		}

		private static void CreateElementMenu()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			try
			{
				GameObject val = new GameObject("Valala_ElementMenuHost");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<ElementSelectorUi>();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not create the element menu: " + ex));
			}
		}

		private static void CreateWindChargeHud()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			try
			{
				GameObject val = new GameObject("Valala_WindChargeHud");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<WindChargeHud>();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not create the Wind Impulse charge HUD: " + ex));
			}
		}

		internal static bool IsMenuKeyDown()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHeadless)
			{
				return Input.GetKeyDown(MenuKeyCode);
			}
			return false;
		}

		private static void RefreshMenuKeyCode()
		{
			//IL_0020: 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)
			MenuKeyCode = (KeyCode)((MenuKey == null || !Enum.TryParse<KeyCode>(MenuKey.Value, ignoreCase: true, out KeyCode result)) ? 59 : ((int)result));
		}

		private static void RefreshSelectedElement()
		{
			ElementRegistry.Current = ElementRegistry.Parse(SelectedElement.Value);
		}

		private static void MigrateSelectedElement()
		{
			string value = SelectedElement.Value;
			if (string.Equals(value, "Vent", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "Wind", StringComparison.OrdinalIgnoreCase))
			{
				SelectedElement.Value = "Roche";
				Log.LogInfo((object)"Migrated SelectedElement from Vent/Wind to Roche.");
			}
		}

		private unsafe void MigrateStaffFreeCastKey()
		{
			//IL_0025: 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_0030: Invalid comparison between Unknown and I4
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (EnableStaffFreeWindImpulse.Value && Enum.TryParse<KeyCode>(StaffFreeCastKey.Value, ignoreCase: true, out KeyCode result) && (int)result != 0 && ((int)result == 102 || (MTKeys.Paso != null && result == MTKeys.Paso.Value)))
				{
					StaffFreeCastKey.Value = "Alt+F";
					((BaseUnityPlugin)this).Config.Save();
					Log.LogWarning((object)("StaffFreeCastKey " + ((object)(*(KeyCode*)(&result))/*cast due to .constrained prefix*/).ToString() + " conflicts with MT Toki Step; migrated to Alt+F."));
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not migrate StaffFreeCastKey: " + ex.Message));
			}
		}

		private static void ValidateElementRegistry()
		{
			for (int i = 0; i < ElementRegistry.All.Length; i++)
			{
				if (ElementRegistry.All[i].Id != (Element)i)
				{
					Log.LogError((object)("Element registry order mismatch at index " + i + ": " + ElementRegistry.All[i].Id));
				}
			}
		}

		private void SetupConfigWatcher()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				if (!string.IsNullOrEmpty(configFilePath))
				{
					_configWatcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath))
					{
						NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime),
						EnableRaisingEvents = true
					};
					_configWatcher.Changed += OnConfigFileChanged;
					_configWatcher.Created += OnConfigFileChanged;
					_configWatcher.Renamed += OnConfigFileChanged;
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Config hot-reload unavailable: " + ex.Message));
			}
		}

		private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
		{
			_pendingReload = true;
		}

		private void Update()
		{
			if (_pendingReload)
			{
				_pendingReload = false;
				_reloadDelay = 0.35f;
			}
			else
			{
				if (_reloadDelay <= 0f)
				{
					return;
				}
				_reloadDelay -= Time.unscaledDeltaTime;
				if (!(_reloadDelay > 0f))
				{
					try
					{
						((BaseUnityPlugin)this).Config.Reload();
						RefreshMenuKeyCode();
						RefreshSelectedElement();
						Log.LogInfo((object)("Config hot-reloaded (MenuKey=" + MenuKey.Value + ")."));
					}
					catch (Exception ex)
					{
						Log.LogWarning((object)("Config reload failed: " + ex.Message));
					}
				}
			}
		}

		private void OnDestroy()
		{
			NorseFxResolver.Unload();
			if (_configWatcher != null)
			{
				_configWatcher.EnableRaisingEvents = false;
				_configWatcher.Dispose();
				_configWatcher = null;
			}
		}

		internal static bool TrySpawnElementStrike(Player player)
		{
			//IL_006e: 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_0073: 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_009e: 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)
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!Enabled.Value)
			{
				return false;
			}
			bool flag = IsFromMk1Jump();
			if (!AffectMk1Jump.Value && flag)
			{
				return false;
			}
			try
			{
				Element current = ElementRegistry.Current;
				ElementDef elementDef = ElementRegistry.Get(current);
				if (!elementDef.Implemented || !ValalaRings.IsEquipped(player, current))
				{
					return false;
				}
				Color color = ((current == Element.Lightning) ? ParseColor(ColorHex.Value) : elementDef.Tint);
				RpcSync.Broadcast(current, ((Component)player).transform.position, Duration.Value, Radius.Value, Height.Value, color);
				if (Damage.Value)
				{
					if (!flag && ValalaRings.GetEquippedQuality(player, current) >= 3)
					{
						DamageEnemiesAt(player, ((Component)player).transform.position, LandingRadius.Value, current);
					}
					else
					{
						DamageEnemies(player, Radius.Value, current);
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("TrySpawnElementStrike failed: " + ex));
				return false;
			}
		}

		private static void DamageEnemies(Player player, float radius, Element element)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			DamageEnemiesAt(player, ((Component)player).transform.position, radius, element);
		}

		internal static void DamageEnemiesAt(Player player, Vector3 center, float radius, Element element)
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || !ValalaRings.IsEquipped(player, element))
			{
				return;
			}
			ElementDef elementDef = ElementRegistry.Get(element);
			float skillLevel = ((Character)player).GetSkillLevel((SkillType)9);
			float num = Mathf.Lerp(DamageMin.Value, DamageMax.Value, Mathf.Clamp01(skillLevel / 100f));
			num *= ValalaRings.GetDamageMultiplier(player, element);
			float num2 = radius * radius;
			foreach (Character item in new List<Character>(Character.GetAllCharacters()))
			{
				if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)player || item.IsDead() || item.IsPlayer() || item.IsTamed() || (Object)(object)((Component)item).GetComponent<Trader>() != (Object)null || !BaseAI.IsEnemy((Character)(object)player, item))
				{
					continue;
				}
				Vector3 val = ((Component)item).transform.position - center;
				if (!(((Vector3)(ref val)).sqrMagnitude > num2))
				{
					HitData val2 = new HitData();
					switch (elementDef.Damage)
					{
					case ElementDamage.Blunt:
						val2.m_damage.m_blunt = num;
						break;
					case ElementDamage.Fire:
						val2.m_damage.m_fire = num;
						break;
					case ElementDamage.Poison:
						val2.m_damage.m_poison = num;
						break;
					case ElementDamage.Frost:
						val2.m_damage.m_frost = num;
						break;
					default:
						val2.m_damage.m_lightning = num;
						break;
					}
					val2.m_staggerMultiplier = elementDef.StaggerMultiplier;
					val2.m_point = item.GetCenterPoint();
					val2.m_dir = ((Vector3)(ref val)).normalized;
					val2.m_skill = (SkillType)9;
					val2.m_skillLevel = skillLevel;
					val2.SetAttacker((Character)(object)player);
					item.Damage(val2);
				}
			}
		}

		private static bool IsFromMk1Jump()
		{
			try
			{
				StackTrace stackTrace = new StackTrace(fNeedFileInfo: false);
				for (int i = 0; i < stackTrace.FrameCount; i++)
				{
					Type type = stackTrace.GetFrame(i)?.GetMethod()?.DeclaringType;
					if (type != null && type.Name == "Mk1SaltoPatch")
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		internal static Color ParseColor(string hex)
		{
			//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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(hex))
			{
				hex = "59BFFF";
			}
			hex = hex.TrimStart(new char[1] { '#' });
			try
			{
				byte num = Convert.ToByte(hex.Substring(0, 2), 16);
				byte b = Convert.ToByte(hex.Substring(2, 2), 16);
				byte b2 = Convert.ToByte(hex.Substring(4, 2), 16);
				return new Color((float)(int)num / 255f, (float)(int)b / 255f, (float)(int)b2 / 255f, 1f);
			}
			catch
			{
				return new Color(0.35f, 0.75f, 1f, 1f);
			}
		}
	}
	internal static class ElementVfx
	{
		private static readonly HashSet<string> MissingWarned = new HashSet<string>();

		private static readonly string[] LandingWavePrefabs = new string[1] { "vfx_sledge_iron_hit" };

		private static bool _neutralizeErrorLogged;

		public static void Spawn(ElementDef def, Vector3 pos, float duration, float radius, float height, Color color)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00d4: 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_00de: 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_0014: 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)
			if (!string.IsNullOrEmpty(def.NorseEffectId) && (Object)(object)NorseFxService.SpawnVfx(def.NorseEffectId, pos, Quaternion.identity, null, duration) != (Object)null)
			{
				if (!string.IsNullOrEmpty(def.NorseSfxId))
				{
					NorseFxService.PlaySfx(def.NorseSfxId, pos);
				}
				return;
			}
			float num = Mathf.Max(0.5f, duration);
			float scale = Mathf.Clamp(0.8f + radius * 0.6f + height * 0.4f, 0.8f, 4f);
			SpawnLocal(def.BoltPrefabs, pos, scale, num, color);
			SpawnLocal(def.SparkPrefabs, pos, 1f, Mathf.Min(num, 2.5f), color);
			SpawnLocal(def.AoePrefabs, pos, Mathf.Clamp(radius, 0.5f, 3f), Mathf.Min(num, 2.5f), color);
			SpawnFlash(pos, color, radius);
		}

		public static void SpawnLanding(ElementDef def, Vector3 pos, float duration, float radius, Color color)
		{
			//IL_002d: 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_0043: 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_0064: 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)
			float lifetime = Mathf.Clamp(duration, 0.5f, 2.5f);
			float scale = Mathf.Clamp(radius / 4f, 0.9f, 1.6f);
			SpawnLocal(LandingWavePrefabs, pos, scale, 5f, color, disableLights: true);
			SpawnLocal(def.LandingAoePrefabs, pos, Mathf.Clamp(radius, 0.5f, 3f), lifetime, color, disableLights: true);
			SpawnLocal(def.SparkPrefabs, pos, 1f, lifetime, color, disableLights: true);
		}

		private static void SpawnFlash(Vector3 pos, Color color, float radius)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			GameObject val = new GameObject("Valala_ElementFlash");
			val.transform.position = pos + Vector3.up * 1.2f;
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.color = color;
			obj.range = Mathf.Max(6f, radius * 8f);
			obj.intensity = 4f;
			Object.Destroy((Object)val, 0.25f);
		}

		private static GameObject SpawnLocal(string[] candidates, Vector3 pos, float scale, float lifetime, Color color, bool disableLights = false)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ResolvePrefab(candidates);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			bool forceDisableInit = ZNetView.m_forceDisableInit;
			ZNetView.m_forceDisableInit = true;
			GameObject val2;
			try
			{
				val2 = Object.Instantiate<GameObject>(val, pos, Quaternion.identity);
			}
			finally
			{
				ZNetView.m_forceDisableInit = forceDisableInit;
			}
			Transform transform = val2.transform;
			transform.localScale *= scale;
			Neutralize(val2);
			if (disableLights)
			{
				DisableParticleLights(val2);
			}
			Tint(val2, color);
			Object.Destroy((Object)(object)val2, lifetime);
			return val2;
		}

		private static void DisableParticleLights(GameObject go)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystem[] componentsInChildren = go.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				LightsModule lights = componentsInChildren[i].lights;
				if (((LightsModule)(ref lights)).enabled)
				{
					((LightsModule)(ref lights)).enabled = false;
				}
			}
		}

		private static GameObject ResolvePrefab(string[] candidates)
		{
			if (candidates == null || candidates.Length == 0 || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			foreach (string text in candidates)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(text);
				if ((Object)(object)prefab != (Object)null)
				{
					return prefab;
				}
			}
			string text2 = string.Join(", ", candidates);
			if (MissingWarned.Add(text2))
			{
				ValalaModsPlugin.Log.LogWarning((object)("Vanilla VFX not found: " + text2));
			}
			return null;
		}

		private static void Neutralize(GameObject go)
		{
			Behaviour[] componentsInChildren = go.GetComponentsInChildren<Behaviour>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				try
				{
					componentsInChildren[i].enabled = false;
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
				catch (Exception e)
				{
					LogNeutralizeOnce(e);
				}
			}
			Collider[] componentsInChildren2 = go.GetComponentsInChildren<Collider>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				try
				{
					componentsInChildren2[j].enabled = false;
					Object.Destroy((Object)(object)componentsInChildren2[j]);
				}
				catch (Exception e2)
				{
					LogNeutralizeOnce(e2);
				}
			}
			Rigidbody[] componentsInChildren3 = go.GetComponentsInChildren<Rigidbody>(true);
			for (int k = 0; k < componentsInChildren3.Length; k++)
			{
				try
				{
					componentsInChildren3[k].isKinematic = true;
					Object.Destroy((Object)(object)componentsInChildren3[k]);
				}
				catch (Exception e3)
				{
					LogNeutralizeOnce(e3);
				}
			}
		}

		private static void LogNeutralizeOnce(Exception e)
		{
			if (!_neutralizeErrorLogged)
			{
				_neutralizeErrorLogged = true;
				ValalaModsPlugin.Log.LogWarning((object)("Neutralize error (reported once): " + e.Message));
			}
		}

		private static void Tint(GameObject go, Color color)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0043: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystem[] componentsInChildren = go.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				MainModule main = componentsInChildren[i].main;
				((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(color);
			}
			TrailRenderer[] componentsInChildren2 = go.GetComponentsInChildren<TrailRenderer>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				componentsInChildren2[j].startColor = color;
			}
			LineRenderer[] componentsInChildren3 = go.GetComponentsInChildren<LineRenderer>(true);
			for (int k = 0; k < componentsInChildren3.Length; k++)
			{
				componentsInChildren3[k].startColor = color;
			}
			Light[] componentsInChildren4 = go.GetComponentsInChildren<Light>(true);
			for (int l = 0; l < componentsInChildren4.Length; l++)
			{
				componentsInChildren4[l].color = color;
			}
		}
	}
	internal static class RpcSync
	{
		private const string RpcSpawnVfx = "odin.valala.raja.mods.spawn";

		private const string RpcLanding = "odin.valala.raja.mods.landing";

		public static void EnsureRegistered()
		{
			if (ZRoutedRpc.instance == null)
			{
				return;
			}
			try
			{
				ZRoutedRpc.instance.Register<int, Vector3, Vector3, float, float, float>("odin.valala.raja.mods.spawn", (Method<int, Vector3, Vector3, float, float, float>)OnSpawnVfx);
			}
			catch (Exception ex)
			{
				ValalaModsPlugin.Log.LogWarning((object)("VFX RPC already registered: " + ex.Message));
			}
			try
			{
				ZRoutedRpc.instance.Register<int, Vector3, float>("odin.valala.raja.mods.landing", (Action<long, int, Vector3, float>)OnLanding);
			}
			catch (Exception ex2)
			{
				ValalaModsPlugin.Log.LogWarning((object)("Landing RPC already registered: " + ex2.Message));
			}
		}

		public static void Broadcast(Element element, Vector3 pos, float duration, float radius, float height, Color color)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_004f: 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)
			if (!ValalaModsPlugin.SyncToOthers.Value || ZRoutedRpc.instance == null)
			{
				ElementFx.Spawn(element, pos, duration, radius, height, color);
				return;
			}
			try
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "odin.valala.raja.mods.spawn", new object[6]
				{
					(int)element,
					pos,
					(object)new Vector3(color.r, color.g, color.b),
					duration,
					radius,
					height
				});
			}
			catch (Exception ex)
			{
				ValalaModsPlugin.Log.LogError((object)("VFX RPC failed, spawning locally: " + ex));
				ElementFx.Spawn(element, pos, duration, radius, height, color);
			}
		}

		private static void OnSpawnVfx(long sender, int element, Vector3 pos, Vector3 color, float duration, float radius, float height)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_000b: 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_0018: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				return;
			}
			try
			{
				ElementFx.Spawn((Element)element, pos, duration, radius, height, new Color(color.x, color.y, color.z, 1f));
			}
			catch (Exception ex)
			{
				ValalaModsPlugin.Log.LogError((object)("OnSpawnVfx failed: " + ex));
			}
		}

		public static void BroadcastLanding(Element element, Vector3 pos, float fallHeight)
		{
			//IL_0014: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!ValalaModsPlugin.SyncToOthers.Value || ZRoutedRpc.instance == null)
			{
				LandingEffects.Spawn(element, pos, fallHeight);
				return;
			}
			try
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "odin.valala.raja.mods.landing", new object[3]
				{
					(int)element,
					pos,
					fallHeight
				});
			}
			catch (Exception ex)
			{
				ValalaModsPlugin.Log.LogError((object)("Landing RPC failed, spawning locally: " + ex));
				LandingEffects.Spawn(element, pos, fallHeight);
			}
		}

		private static void OnLanding(long sender, int element, Vector3 pos, float fallHeight)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				return;
			}
			try
			{
				LandingEffects.Spawn((Element)element, pos, fallHeight);
			}
			catch (Exception ex)
			{
				ValalaModsPlugin.Log.LogError((object)("OnLanding failed: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Awake")]
	internal static class ZNetAwakePatch
	{
		private static void Postfix()
		{
			RpcSync.EnsureRegistered();
		}
	}
	[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
	internal static class CursorCapturePatch
	{
		private static bool Prefix()
		{
			if (!ElementSelectorUi.IsMenuVisible)
			{
				return true;
			}
			try
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
			catch
			{
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerController), "LateUpdate")]
	internal static class CameraLookPatch
	{
		private static bool Prefix()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!ElementSelectorUi.IsMenuVisible)
			{
				return true;
			}
			try
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					localPlayer.SetMouseLook(Vector2.zero);
				}
			}
			catch
			{
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(WindImpulseVfx), "Spawn")]
	internal static class WindImpulsePatch
	{
		private static bool Prefix(Player player)
		{
			try
			{
				if (!ValalaModsPlugin.Enabled.Value)
				{
					return true;
				}
				if (ValalaModsPlugin.Mode.Value.Equals("Replace", StringComparison.OrdinalIgnoreCase))
				{
					return !ValalaModsPlugin.TrySpawnElementStrike(player);
				}
			}
			catch
			{
			}
			return true;
		}

		private static void Postfix(Player player)
		{
			try
			{
				if (ValalaModsPlugin.Enabled.Value && !ValalaModsPlugin.Mode.Value.Equals("Replace", StringComparison.OrdinalIgnoreCase))
				{
					ValalaModsPlugin.TrySpawnElementStrike(player);
				}
			}
			catch
			{
			}
		}
	}
	internal static class SecondTrinketSlot
	{
		private const string PluginGuid = "shudnal.ExtraSlotsCustomSlots";

		internal static void Apply(Harmony harmony)
		{
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			if (!ValalaModsPlugin.EnableSecondTrinketSlot.Value)
			{
				return;
			}
			if (!Chainloader.PluginInfos.ContainsKey("shudnal.ExtraSlotsCustomSlots"))
			{
				ValalaModsPlugin.Log.LogInfo((object)"ExtraSlotsCustomSlots not installed; second trinket slot disabled.");
				return;
			}
			try
			{
				Type? type = Type.GetType("ExtraSlotsCustomSlots.UserDefinedSlot, ExtraSlotsCustomSlots");
				object obj = (((type?.GetField("userDefinedSlots", BindingFlags.Static | BindingFlags.Public))?.GetValue(null) is Array { Length: >0 } array) ? array.GetValue(0) : null);
				FieldInfo fieldInfo = type?.GetField("itemIsValid", BindingFlags.Instance | BindingFlags.Public);
				FieldInfo? obj2 = type?.GetField("slotEnabled", BindingFlags.Instance | BindingFlags.Public);
				MethodInfo methodInfo = Type.GetType("ExtraSlots.Slots, ExtraSlots")?.GetMethod("IsCustomSlotItem", BindingFlags.Static | BindingFlags.Public);
				if (obj == null || fieldInfo == null || methodInfo == null)
				{
					throw new MissingFieldException("ExtraSlots custom slot support was not initialized.");
				}
				int num;
				if (obj2?.GetValue(obj) is ConfigEntry<bool> val)
				{
					num = (val.Value ? 1 : 0);
					if (num != 0)
					{
						goto IL_0119;
					}
				}
				else
				{
					num = 0;
				}
				ValalaModsPlugin.Log.LogWarning((object)"ExtraSlotsCustomSlots custom slot 1 is disabled; set Enabled=true in shudnal.ExtraSlotsCustomSlots.cfg.");
				goto IL_0119;
				IL_0119:
				Func<ItemData, bool> original = fieldInfo.GetValue(obj) as Func<ItemData, bool>;
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(SecondTrinketSlot), "IsCustomSlotItemPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				fieldInfo.SetValue(obj, (Func<ItemData, bool>)((ItemData item) => (original != null && original(item)) || IsTrinket(item)));
				if (num != 0)
				{
					ValalaModsPlugin.Log.LogInfo((object)"Second trinket slot enabled through ExtraSlotsCustomSlots custom slot 1.");
				}
			}
			catch (Exception ex)
			{
				ValalaModsPlugin.Log.LogError((object)("Could not enable the second trinket slot: " + ex));
			}
		}

		private static bool IsTrinket(ItemData item)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if (item != null && item.m_shared != null)
			{
				return (int)item.m_shared.m_itemType == 24;
			}
			return false;
		}

		private static void IsCustomSlotItemPostfix(ItemData item, ref bool __result)
		{
			if (__result && IsTrinket(item))
			{
				__result = false;
			}
		}
	}
	internal static class StaffFreeWindImpulse
	{
		private const string WindImpulseId = "impulso_viento";

		private const string NoFallStatus = "MT_ImpulsoViento";

		private const string DashStatus = "MT_ImpulsoCarrera";

		private const int MaxRingQuality = 4;

		private const float MaxChargeMultiplier = 5f;

		private const float MinChargeTime = 0.25f;

		private static readonly Type MagicPluginType = AccessTools.TypeByName("MT.Magia.MTMagiaPlugin");

		private static readonly FieldInfo ChargeSpeedField = ((MagicPluginType == null) ? null : AccessTools.Field(MagicPluginType, "CargaVelocidad"));

		private static readonly FieldInfo ChargeManaField = ((MagicPluginType == null) ? null : AccessTools.Field(MagicPluginType, "CargaMana"));

		private static readonly MethodInfo CanTakeInputMethod = AccessTools.Method(typeof(Caster), "CanTakeInput", (Type[])null, (Type[])null);

		private static bool _staffFreeCharging;

		private static float _chargeStart;

		private static float _chargePaid;

		private static float _chargeMult = 1f;

		private static int _chargeQuality;

		private static Spell _chargeSpell;

		private static Player _chargePlayer;

		private static bool _errorLogged;

		internal static bool IsCharging
		{
			get
			{
				Player localPlayer = Player.m_localPlayer;
				if (_staffFreeCharging && (Object)(object)localPlayer != (Object)null && (Object)(object)_chargePlayer == (Object)(object)localPlayer)
				{
					return !((Character)localPlayer).IsDead();
				}
				return false;
			}
		}

		internal static float ChargeFraction => Mathf.Clamp01((_chargeMult - 1f) / 4f);

		internal static float LimitFraction
		{
			get
			{
				if (_chargeQuality <= 0)
				{
					return 0f;
				}
				return Mathf.Clamp01((ChargeMaxForQuality(_chargeQuality) - 1f) / 4f);
			}
		}

		internal static void Initialize(Harmony harmony)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			if (ValalaModsPlugin.IsHeadless)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Caster), "Update", (Type[])null, (Type[])null);
				Type type = AccessTools.TypeByName("MT.Paso.HabilidadPaso");
				MethodInfo methodInfo2 = ((type == null) ? null : AccessTools.Method(type, "Usar", (Type[])null, (Type[])null));
				if (methodInfo == null)
				{
					throw new MissingMethodException("Required MT.Magia method Caster.Update was not found.");
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(StaffFreeWindImpulse), "UpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				if (methodInfo2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(StaffFreeWindImpulse), "TokiStepPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex)
			{
				LogErrorOnce("Could not patch staff-free Wind Impulse: " + ex);
			}
		}

		private static bool TokiStepPrefix(Player p, ref bool __result)
		{
			if (ValalaModsPlugin.IsHeadless)
			{
				return true;
			}
			if (!ShouldBlockTokiStep(p))
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static bool ShouldBlockTokiStep(Player player)
		{
			if (_staffFreeCharging)
			{
				return true;
			}
			if (!ValalaModsPlugin.Enabled.Value || !ValalaModsPlugin.EnableStaffFreeWindImpulse.Value || (Object)(object)player == (Object)null || ((Character)player).IsDead() || ((Character)player).InPlaceMode() || IsInputBlocked() || Focus.HasFocus(player) || ValalaRings.GetBestEquippedQuality(player) <= 0 || !IsCastKeyHeld())
			{
				return false;
			}
			Spell val = FindWindImpulse();
			if (val != null && Pergaminos.Knows(player, val.Id))
			{
				return Pergaminos.CanCast(player, val);
			}
			return false;
		}

		private static void UpdatePostfix(Caster __instance)
		{
			if (ValalaModsPlugin.IsHeadless)
			{
				return;
			}
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					if (_staffFreeCharging)
					{
						CancelCharge(Player.m_localPlayer);
					}
				}
				else if (_staffFreeCharging)
				{
					UpdateStaffFreeCharge();
				}
				else if (ValalaModsPlugin.Enabled.Value && ValalaModsPlugin.EnableStaffFreeWindImpulse.Value && !((Object)(object)__instance != (Object)(object)Caster.Instance) && !IsInputBlocked() && IsCastKeyDown())
				{
					TryStartCharge();
				}
			}
			catch (Exception ex)
			{
				CancelCharge(Player.m_localPlayer);
				LogErrorOnce("Staff-free Wind Impulse tick failed: " + ex);
			}
		}

		private static void TryStartCharge()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InPlaceMode() || IsInputBlocked() || Focus.HasFocus(localPlayer) || Caster.IsActiveCasting || Caster.SegundoActivo)
			{
				return;
			}
			int bestEquippedQuality = ValalaRings.GetBestEquippedQuality(localPlayer);
			if (bestEquippedQuality <= 0)
			{
				return;
			}
			Spell val = FindWindImpulse();
			if (val == null || !Pergaminos.Knows(localPlayer, val.Id) || !Pergaminos.CanCast(localPlayer, val))
			{
				return;
			}
			if (Agotamiento.IsExhausted(localPlayer))
			{
				((Character)localPlayer).Message((MessageType)1, Tr.Get("magia_are_exhausted_can_t_cast"), 0, (Sprite)null, false);
				return;
			}
			float num = Esperas.Restante(localPlayer, (Habilidad)(object)val);
			if (num > 0f)
			{
				((Character)localPlayer).Message((MessageType)1, val.Name + ": " + Mathf.CeilToInt(num) + " s", 0, (Sprite)null, false);
				return;
			}
			string text = null;
			if (!((Habilidad)val).Alcanza(localPlayer, ref text))
			{
				if (!string.IsNullOrEmpty(text))
				{
					((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false);
				}
				return;
			}
			_staffFreeCharging = true;
			_chargeStart = Time.time;
			_chargePaid = 0f;
			_chargeMult = 1f;
			_chargeQuality = bestEquippedQuality;
			_chargeSpell = val;
			_chargePlayer = localPlayer;
		}

		private static void UpdateStaffFreeCharge()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)_chargePlayer != (Object)(object)localPlayer)
			{
				CancelCharge(_chargePlayer);
				return;
			}
			if (!ValalaModsPlugin.Enabled.Value || !ValalaModsPlugin.EnableStaffFreeWindImpulse.Value || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsStaggering() || ((Character)localPlayer).InPlaceMode() || ((Character)localPlayer).IsSwimming() || ((Character)localPlayer).IsAttached() || ((Character)localPlayer).IsEncumbered() || ((Character)localPlayer).InDodge() || IsInputBlocked() || Focus.HasFocus(localPlayer) || Caster.IsActiveCasting || Caster.SegundoActivo || _chargeSpell == null || !Pergaminos.Knows(localPlayer, _chargeSpell.Id) || !Pergaminos.CanCast(localPlayer, _chargeSpell))
			{
				CancelCharge(localPlayer);
				return;
			}
			int bestEquippedQuality = ValalaRings.GetBestEquippedQuality(localPlayer);
			if (bestEquippedQuality <= 0)
			{
				CancelCharge(localPlayer);
				return;
			}
			if (!IsCastKeyHeld())
			{
				FinishCharge(localPlayer);
				return;
			}
			_chargeQuality = bestEquippedQuality;
			float num = Time.time - _chargeStart;
			float num2 = ChargeMaxForQuality(bestEquippedQuality);
			float num3 = Mathf.Min(num2, 1f + Mathf.Max(0f, num - 0.25f) * ChargeSpeed());
			float num4 = Mathf.Max(Caster.ManaCost(localPlayer, _chargeSpell) * ChargeManaCost(), 0.01f);
			float num5 = (num3 - 1f) * num4;
			if (num5 > _chargePaid)
			{
				float num6 = num5 - _chargePaid;
				if (localPlayer.GetEitr() - Caster.ManaCost(localPlayer, _chargeSpell) >= num6)
				{
					((Character)localPlayer).UseEitr(num6);
					_chargePaid += num6;
				}
			}
			_chargeMult = Mathf.Min(1f + _chargePaid / num4, num2);
		}

		private static void FinishCharge(Player player)
		{
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			Spell chargeSpell = _chargeSpell;
			int chargeQuality = _chargeQuality;
			float chargeMult = _chargeMult;
			float chargePaid = _chargePaid;
			_staffFreeCharging = false;
			_chargeSpell = null;
			_chargeQuality = 0;
			_chargePlayer = null;
			_chargePaid = 0f;
			_chargeMult = 1f;
			if ((Object)(object)player == (Object)null || chargeSpell == null || ((Character)player).IsDead())
			{
				Refund(player, chargePaid);
				return;
			}
			chargeQuality = ValalaRings.GetBestEquippedQuality(player);
			if (chargeQuality <= 0 || !Pergaminos.Knows(player, chargeSpell.Id) || !Pergaminos.CanCast(player, chargeSpell))
			{
				Refund(player, chargePaid);
				return;
			}
			if (Esperas.Restante(player, (Habilidad)(object)chargeSpell) > 0f)
			{
				Refund(player, chargePaid);
				return;
			}
			try
			{
				bool flag = default(bool);
				if (!((Habilidad)chargeSpell).Pagar(player, ref flag))
				{
					Refund(player, chargePaid);
					return;
				}
			}
			catch (Exception ex)
			{
				Refund(player, chargePaid);
				LogErrorOnce("Staff-free Wind Impulse payment failed: " + ex);
				return;
			}
			try
			{
				UsoMagia.Lanzado(player, chargeSpell);
				Caster.PlayLaunchSound(player, chargeSpell);
				((Character)player).RaiseSkill(Escuelas.Skill(chargeSpell.School), Mathf.Max(((Habilidad)chargeSpell).Mana, 5f) / 10f);
				ApplyJump(player, chargeQuality, chargeMult);
				ApplyLaunchStatuses(player);
				ValalaModsPlugin.TrySpawnElementStrike(player);
			}
			catch (Exception ex2)
			{
				LogErrorOnce("Staff-free Wind Impulse release failed: " + ex2);
			}
		}

		private static void ApplyLaunchStatuses(Player player)
		{
			SEMan sEMan = ((Character)player).GetSEMan();
			if (sEMan != null)
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode("MT_ImpulsoViento");
				sEMan.RemoveStatusEffect(stableHashCode, false);
				sEMan.AddStatusEffect(stableHashCode, true, 0, 0f, (short)(-1));
				Fx.AddSE((Character)(object)player, "MT_ImpulsoCarrera", 0f);
			}
		}

		private static void ApplyJump(Player player, int quality, float charge)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_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)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_00f8: 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)
			Vector3 val = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform.forward : Fx.AimDir(player));
			float num = ChargeMaxForQuality(quality);
			float num2 = Mathf.InverseLerp(1f, num, Mathf.Clamp(charge, 1f, num));
			float num3 = Mathf.Lerp(1f, JumpMaxForQuality(quality), num2);
			if (Levitacion.Active)
			{
				Levitacion.Impulsar(val * 26f * num3);
				return;
			}
			float num4 = val.y * 26f * num3 + 4f;
			if (((Character)player).IsOnGround() && val.y < 0.15f)
			{
				num4 = Mathf.Max(num4, 6f);
			}
			((Character)player).ForceJump(new Vector3(val.x * 26f * num3, num4, val.z * 26f * num3), false);
			ImpulsoInercia.Lanzar(new Vector3(val.x, 0f, val.z) * 11f * num3);
		}

		private static void CancelCharge(Player player)
		{
			float chargePaid = _chargePaid;
			_staffFreeCharging = false;
			_chargeSpell = null;
			_chargeQuality = 0;
			_chargePlayer = null;
			_chargePaid = 0f;
			_chargeMult = 1f;
			Refund(player, chargePaid);
		}

		private static void Refund(Player player, float paid)
		{
			if ((Object)(object)player != (Object)null && paid > 0f)
			{
				((Character)player).AddEitr(paid);
			}
		}

		private static float ReadConfig(FieldInfo field, float fallback)
		{
			if (!(field != null) || !(field.GetValue(null) is ConfigEntry<float> val))
			{
				return fallback;
			}
			return val.Value;
		}

		private static float ChargeSpeed()
		{
			return ReadConfig(ChargeSpeedField, 0.4f);
		}

		private static float ChargeManaCost()
		{
			return ReadConfig(ChargeManaField, 6f);
		}

		private static float ChargeMaxForQuality(int quality)
		{
			return 1f + (float)Mathf.Clamp(quality, 1, 4);
		}

		private static float JumpMaxForQuality(int quality)
		{
			return 2.5f + 0.5f * (float)(Mathf.Clamp(quality, 1, 4) - 1);
		}

		private static Spell FindWindImpulse()
		{
			foreach (Spell item in SpellBook.All)
			{
				if (item.Id == "impulso_viento")
				{
					return item;
				}
			}
			return null;
		}

		private static bool IsCastKeyDown()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (ValalaModsPlugin.IsHeadless)
			{
				return false;
			}
			if (TryParseKey(ValalaModsPlugin.StaffFreeCastKey.Value, out var key, out var alt) && Input.GetKeyDown(key))
			{
				if (alt)
				{
					return IsAltHeld();
				}
				return true;
			}
			return false;
		}

		private static bool IsCastKeyHeld()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (ValalaModsPlugin.IsHeadless)
			{
				return false;
			}
			if (TryParseKey(ValalaModsPlugin.StaffFreeCastKey.Value, out var key, out var alt) && Input.GetKey(key))
			{
				if (alt)
				{
					return IsAltHeld();
				}
				return true;
			}
			return false;
		}

		private static bool TryParseKey(string value, out KeyCode key, out bool alt)
		{
			key = (KeyCode)0;
			alt = false;
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			string text = value.Trim();
			if (text.StartsWith("Alt+", StringComparison.OrdinalIgnoreCase))
			{
				alt = true;
				text = text.Substring(4);
			}
			if (Enum.TryParse<KeyCode>(text, ignoreCase: true, out key))
			{
				return (int)key != 0;
			}
			return false;
		}

		private static bool IsAltHeld()
		{
			if (!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307))
			{
				return Input.GetKey((KeyCode)313);
			}
			return true;
		}

		private static bool IsInputBlocked()
		{
			if (ValalaModsPlugin.IsHeadless)
			{
				return true;
			}
			if (!Application.isFocused || MTKeys.Bloqueadas || Caster.MenuOpen || ElementSelectorUi.IsMenuVisible)
			{
				return true;
			}
			try
			{
				if (CanTakeInputMethod != null && !(bool)CanTakeInputMethod.Invoke(null, null))
				{
					return true;
				}
			}
			catch
			{
			}
			if (!Console.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !TextInput.IsVisible() && !Minimap.IsOpen())
			{
				if ((Object)(object)Chat.instance != (Object)null)
				{
					return Chat.instance.HasFocus();
				}
				return false;
			}
			return true;
		}

		private static void LogErrorOnce(string message)
		{
			if (!_errorLogged)
			{
				_errorLogged = true;
				ValalaModsPlugin.Log.LogError((object)message);
			}
		}
	}
	internal static class ValalaRings
	{
		internal const int MaxQuality = 4;

		private const string BasePrefab = "SilverRing";

		private static bool _registered;

		internal static void Register()
		{
			if (_registered)
			{
				return;
			}
			_registered = true;
			try
			{
				if ((Object)(object)PrefabManager.Instance.GetPrefab("SilverRing") == (Object)null)
				{
					ValalaModsPlugin.Log.LogError((object)"EpicLoot SilverRing prefab not found; Valala rings are disabled.");
					return;
				}
				RegisterLocalizations();
				RegisterRing(Element.Lightning);
				RegisterRing(Element.Rock);
				RegisterRing(Element.Fire);
				RegisterRing(Element.Poison);
				RegisterRing(Element.Ice);
			}
			catch (Exception ex)
			{
				ValalaModsPlugin.Log.LogError((object)("Valala ring registration failed: " + ex));
			}
		}

		internal static bool IsEquipped(Player player, Element element)
		{
			return GetEquippedQuality(player, element) > 0;
		}

		internal static bool IsAnyMaxRingEquipped(Player player)
		{
			return GetBestEquippedQuality(player) >= 4;
		}

		internal static int GetBestEquippedQuality(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData equippedItem in inventory.GetEquippedItems())
			{
				if (equippedItem != null && equippedItem.m_shared != null && IsValalaRing(equippedItem))
				{
					num = Mathf.Max(num, equippedItem.m_quality);
				}
			}
			return num;
		}

		internal static float GetDamageMultiplier(Player player, Element element)
		{
			int equippedQuality = GetEquippedQuality(player, element);
			if (equippedQuality <= 0)
			{
				return 1f;
			}
			float num = Mathf.Clamp01(ValalaModsPlugin.RingDamageBonus.Value);
			float num2 = Mathf.Max(0f, ValalaModsPlugin.RingDamageBonusPerLevel.Value);
			return 1f + num + num2 * (float)(equippedQuality - 1);
		}

		internal static int GetEquippedQuality(Player player, Element element)
		{
			string text = PrefabName(element);
			if ((Object)(object)player == (Object)null || text == null)
			{
				return 0;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return 0;
			}
			string token = NameToken(element);
			int num = 0;
			foreach (ItemData equippedItem in inventory.GetEquippedItems())
			{
				if (equippedItem != null && Matches(equippedItem, text, token))
				{
					num = Mathf.Max(num, equippedItem.m_quality);
				}
			}
			return num;
		}

		private static bool Matches(ItemData item, string prefabName, string token)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == prefabName)
			{
				return true;
			}
			if (item.m_shared != null)
			{
				return item.m_shared.m_name == token;
			}
			return false;
		}

		private static bool IsValalaRing(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name.StartsWith("ValalaSilverRing", StringComparison.Ordinal))
			{
				return true;
			}
			if (item.m_shared != null && item.m_shared.m_name != null)
			{
				return item.m_shared.m_name.StartsWith("$item_valala_silverring", StringComparison.Ordinal);
			}
			return false;
		}

		private static void RegisterRing(Element element)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0024: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0060: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_