Decompiled source of StolenRealmModAPI v0.2.0

plugins/StolenRealmModAPI.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Burst2Flame;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using StolenRealmModAPI.Data;
using StolenRealmModAPI.Enemies;
using StolenRealmModAPI.Quests;
using StolenRealmModAPI.Skills;
using StolenRealmModAPI.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("StolenRealmModAPI")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Community modding API for Stolen Realm - provides fluent builders, event systems, and utilities for mod development")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+6d15af02c05a70b8609abf94951300d51caa2a05")]
[assembly: AssemblyProduct("StolenRealmModAPI")]
[assembly: AssemblyTitle("StolenRealmModAPI")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace StolenRealmModAPI
{
	public static class GameAccessor
	{
		private static object _gameInstance;

		private static object _gameLogicInstance;

		private static bool _gameInstanceCached;

		private static bool _gameLogicCached;

		private static Type _gameType;

		private static Type _gameLogicType;

		private static Type _skillTreeManagerType;

		private static Type _battleManagerType;

		private static Type _characterMenusManagerType;

		public static object GameInstance
		{
			get
			{
				if (!_gameInstanceCached)
				{
					if ((object)_gameType == null)
					{
						_gameType = ReflectionHelper.FindType("Game");
					}
					if (_gameType != null)
					{
						PropertyInfo propertyInfo = AccessTools.Property(_gameType, "Instance");
						if (propertyInfo != null)
						{
							try
							{
								_gameInstance = propertyInfo.GetValue(null);
							}
							catch
							{
								_gameInstance = null;
							}
						}
					}
					_gameInstanceCached = true;
				}
				return _gameInstance;
			}
		}

		public static object GameLogicInstance
		{
			get
			{
				if (!_gameLogicCached)
				{
					if ((object)_gameLogicType == null)
					{
						_gameLogicType = ReflectionHelper.FindType("GameLogic");
					}
					if (_gameLogicType != null)
					{
						FieldInfo fieldInfo = AccessTools.Field(_gameLogicType, "_instance");
						if (fieldInfo != null)
						{
							try
							{
								_gameLogicInstance = fieldInfo.GetValue(null);
							}
							catch
							{
								_gameLogicInstance = null;
							}
						}
					}
					_gameLogicCached = true;
				}
				return _gameLogicInstance;
			}
		}

		public static object Skills
		{
			get
			{
				object gameInstance = GameInstance;
				if (gameInstance == null)
				{
					return null;
				}
				return ReflectionHelper.GetFieldOrProperty<object>(gameInstance, "Skills");
			}
		}

		public static object Actions
		{
			get
			{
				object gameInstance = GameInstance;
				if (gameInstance == null)
				{
					return null;
				}
				return ReflectionHelper.GetFieldOrProperty<object>(gameInstance, "Actions");
			}
		}

		public static object PlayerList
		{
			get
			{
				object gameLogicInstance = GameLogicInstance;
				if (gameLogicInstance == null)
				{
					return null;
				}
				return ReflectionHelper.GetFieldOrProperty<object>(gameLogicInstance, "playerList");
			}
		}

		public static object SkillTreeManager
		{
			get
			{
				if ((object)_skillTreeManagerType == null)
				{
					_skillTreeManagerType = ReflectionHelper.FindType("SkillTreeManager");
				}
				if (_skillTreeManagerType == null)
				{
					return null;
				}
				return Object.FindObjectOfType(_skillTreeManagerType);
			}
		}

		public static object BattleManager
		{
			get
			{
				if ((object)_battleManagerType == null)
				{
					_battleManagerType = ReflectionHelper.FindType("BattleManager");
				}
				if (_battleManagerType == null)
				{
					return null;
				}
				return Object.FindObjectOfType(_battleManagerType);
			}
		}

		public static object CharacterMenusManager
		{
			get
			{
				if ((object)_characterMenusManagerType == null)
				{
					_characterMenusManagerType = ReflectionHelper.FindType("CharacterMenusManager");
				}
				if (_characterMenusManagerType == null)
				{
					return null;
				}
				return Object.FindObjectOfType(_characterMenusManagerType);
			}
		}

		public static object CurrentCharacterUI
		{
			get
			{
				Type type = ReflectionHelper.FindType("CurrentCharacterUI");
				if (type == null)
				{
					return null;
				}
				return Object.FindObjectOfType(type);
			}
		}

		public static void InvalidateCache()
		{
			_gameInstance = null;
			_gameLogicInstance = null;
			_gameInstanceCached = false;
			_gameLogicCached = false;
		}
	}
	[BepInPlugin("com.stolenrealm.modapi", "Stolen Realm Mod API", "0.1.0")]
	[BepInProcess("Stolen Realm.exe")]
	public class ModAPIPlugin : BaseUnityPlugin
	{
		private static readonly Dictionary<string, StolenRealmMod> _registeredMods = new Dictionary<string, StolenRealmMod>();

		private static bool _isShuttingDown;

		private static bool _gameReady;

		internal static ModAPIPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static Harmony HarmonyInstance { get; private set; }

		public static IReadOnlyCollection<StolenRealmMod> RegisteredMods => _registeredMods.Values;

		public static bool IsShuttingDown => _isShuttingDown;

		public static bool IsGameReady => _gameReady;

		private void Awake()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_isShuttingDown = false;
			_gameReady = false;
			Log.LogInfo((object)"Stolen Realm Mod API v0.1.0 loading...");
			HarmonyInstance = new Harmony("com.stolenrealm.modapi");
			HarmonyInstance.PatchAll(typeof(ModAPIPlugin).Assembly);
			SceneManager.sceneLoaded += OnSceneLoaded;
			Log.LogInfo((object)string.Format("{0} initialized. {1} internal patches applied.", "Stolen Realm Mod API", HarmonyInstance.GetPatchedMethods().GetEnumerator().Current));
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (_isShuttingDown)
			{
				return;
			}
			try
			{
				ModData.OnSceneChange();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"ModData.OnSceneChange: {arg}");
			}
			GameAccessor.InvalidateCache();
			SkillTreeUI.ResetInjectionState();
			ActionBarUI.ResetInjectionState();
			MenuUI.ResetInjectionState();
			TooltipHelper.ResetState();
			bool gameReady = _gameReady;
			_gameReady = GameAccessor.GameInstance != null;
			if (!_gameReady || gameReady)
			{
				return;
			}
			Log.LogInfo((object)"Game.Instance became available — notifying subsystems and mods.");
			try
			{
				SpawnManager.OnGameReady();
			}
			catch (Exception arg2)
			{
				Log.LogError((object)$"SpawnManager.OnGameReady: {arg2}");
			}
			try
			{
				QuestRegistry.OnGameReady();
			}
			catch (Exception arg3)
			{
				Log.LogError((object)$"QuestRegistry.OnGameReady: {arg3}");
			}
			foreach (StolenRealmMod value in _registeredMods.Values)
			{
				try
				{
					value.InvokeOnGameReady();
				}
				catch (Exception arg4)
				{
					Log.LogError((object)$"Error in OnGameReady for mod '{value.ModGuid}': {arg4}");
				}
			}
		}

		internal static void RegisterMod(StolenRealmMod mod)
		{
			if (_registeredMods.ContainsKey(mod.ModGuid))
			{
				Log.LogWarning((object)("Mod '" + mod.ModGuid + "' is already registered."));
				return;
			}
			_registeredMods[mod.ModGuid] = mod;
			Log.LogInfo((object)("Registered mod: " + mod.ModGuid));
			if (!_gameReady)
			{
				return;
			}
			try
			{
				mod.InvokeOnGameReady();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Error in OnGameReady for mod '{mod.ModGuid}': {arg}");
			}
		}

		internal static void UnregisterMod(string modGuid)
		{
			_registeredMods.Remove(modGuid);
		}

		private void OnApplicationQuit()
		{
			_isShuttingDown = true;
			foreach (StolenRealmMod value in _registeredMods.Values)
			{
				try
				{
					value.InvokeOnModUnloading();
				}
				catch (Exception arg)
				{
					Log.LogError((object)$"Error in OnModUnloading for mod '{value.ModGuid}': {arg}");
				}
			}
			try
			{
				ModData.FlushAll();
			}
			catch (Exception arg2)
			{
				Log.LogError((object)$"ModData.FlushAll on quit: {arg2}");
			}
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private void OnDestroy()
		{
			_isShuttingDown = true;
		}
	}
	public static class PluginInfo
	{
		public const string GUID = "com.stolenrealm.modapi";

		public const string NAME = "Stolen Realm Mod API";

		public const string VERSION = "0.1.0";
	}
	public class ModLogger
	{
		private readonly ManualLogSource _source;

		private readonly string _prefix;

		public ModLogger(ManualLogSource source, string prefix = null)
		{
			_source = source ?? throw new ArgumentNullException("source");
			_prefix = (string.IsNullOrEmpty(prefix) ? null : prefix);
		}

		public ModLogger(string modGuid)
		{
			_source = Logger.CreateLogSource(modGuid);
			_prefix = null;
		}

		public void Info(string message)
		{
			_source.LogInfo((object)FormatMessage(message));
		}

		public void Debug(string message)
		{
			_source.LogDebug((object)FormatMessage(message));
		}

		public void Warning(string message)
		{
			_source.LogWarning((object)FormatMessage(message));
		}

		public void Error(string message)
		{
			_source.LogError((object)FormatMessage(message));
		}

		public void Error(string message, Exception ex)
		{
			_source.LogError((object)$"{FormatMessage(message)}\n{ex}");
		}

		public void Fatal(string message)
		{
			_source.LogFatal((object)FormatMessage(message));
		}

		public void Log(LogLevel level, string message)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			_source.Log(level, (object)FormatMessage(message));
		}

		private string FormatMessage(string message)
		{
			return (_prefix != null) ? ("[" + _prefix + "] " + message) : message;
		}
	}
	public static class ReflectionHelper
	{
		private static readonly Dictionary<string, Type> _typeCache = new Dictionary<string, Type>();

		private static readonly Dictionary<string, FieldInfo> _fieldCache = new Dictionary<string, FieldInfo>();

		private static readonly Dictionary<string, PropertyInfo> _propCache = new Dictionary<string, PropertyInfo>();

		private static readonly Dictionary<string, object> _enumCache = new Dictionary<string, object>();

		public static Type FindType(string typeName)
		{
			if (string.IsNullOrEmpty(typeName))
			{
				return null;
			}
			if (_typeCache.TryGetValue(typeName, out var value))
			{
				return value;
			}
			Type type = AccessTools.TypeByName(typeName);
			_typeCache[typeName] = type;
			if (type == null)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("ReflectionHelper: Type '" + typeName + "' not found."));
				}
			}
			return type;
		}

		public static T GetField<T>(object instance, string fieldName)
		{
			if (instance == null)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("ReflectionHelper.GetField: instance is null for field '" + fieldName + "'"));
				}
				return default(T);
			}
			FieldInfo cachedField = GetCachedField(instance.GetType(), fieldName);
			if (cachedField == null)
			{
				return default(T);
			}
			try
			{
				object value = cachedField.GetValue(instance);
				if (value is T result)
				{
					return result;
				}
				if (value == null)
				{
					return default(T);
				}
				return (T)Convert.ChangeType(value, typeof(T));
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = ModAPIPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("ReflectionHelper.GetField<" + typeof(T).Name + ">(" + fieldName + "): " + ex.Message));
				}
				return default(T);
			}
		}

		public static T GetStaticField<T>(Type type, string fieldName)
		{
			if (type == null)
			{
				return default(T);
			}
			FieldInfo cachedField = GetCachedField(type, fieldName);
			if (cachedField == null)
			{
				return default(T);
			}
			try
			{
				object value = cachedField.GetValue(null);
				if (value is T result)
				{
					return result;
				}
				if (value == null)
				{
					return default(T);
				}
				return (T)Convert.ChangeType(value, typeof(T));
			}
			catch (Exception ex)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogError((object)("ReflectionHelper.GetStaticField<" + typeof(T).Name + ">(" + type.Name + "." + fieldName + "): " + ex.Message));
				}
				return default(T);
			}
		}

		public static void SetField(object instance, string fieldName, object value)
		{
			if (instance == null)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("ReflectionHelper.SetField: instance is null for field '" + fieldName + "'"));
				}
				return;
			}
			FieldInfo cachedField = GetCachedField(instance.GetType(), fieldName);
			if (cachedField == null)
			{
				return;
			}
			try
			{
				cachedField.SetValue(instance, value);
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = ModAPIPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("ReflectionHelper.SetField(" + fieldName + "): " + ex.Message));
				}
			}
		}

		public static void SetStaticField(Type type, string fieldName, object value)
		{
			if (type == null)
			{
				return;
			}
			FieldInfo cachedField = GetCachedField(type, fieldName);
			if (cachedField == null)
			{
				return;
			}
			try
			{
				cachedField.SetValue(null, value);
			}
			catch (Exception ex)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogError((object)("ReflectionHelper.SetStaticField(" + type.Name + "." + fieldName + "): " + ex.Message));
				}
			}
		}

		public static T GetProperty<T>(object instance, string propertyName)
		{
			if (instance == null)
			{
				return default(T);
			}
			PropertyInfo cachedProperty = GetCachedProperty(instance.GetType(), propertyName);
			if (cachedProperty == null)
			{
				return default(T);
			}
			try
			{
				object value = cachedProperty.GetValue(instance, null);
				if (value is T result)
				{
					return result;
				}
				if (value == null)
				{
					return default(T);
				}
				return (T)Convert.ChangeType(value, typeof(T));
			}
			catch (Exception ex)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogError((object)("ReflectionHelper.GetProperty<" + typeof(T).Name + ">(" + propertyName + "): " + ex.Message));
				}
				return default(T);
			}
		}

		public static void SetProperty(object instance, string propertyName, object value)
		{
			if (instance == null)
			{
				return;
			}
			PropertyInfo cachedProperty = GetCachedProperty(instance.GetType(), propertyName);
			if (cachedProperty == null)
			{
				return;
			}
			try
			{
				cachedProperty.SetValue(instance, value, null);
			}
			catch (Exception ex)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogError((object)("ReflectionHelper.SetProperty(" + propertyName + "): " + ex.Message));
				}
			}
		}

		public static T GetFieldOrProperty<T>(object instance, string memberName)
		{
			if (instance == null)
			{
				return default(T);
			}
			FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), memberName);
			if (fieldInfo != null)
			{
				try
				{
					object value = fieldInfo.GetValue(instance);
					if (value is T result)
					{
						return result;
					}
					if (value == null)
					{
						return default(T);
					}
					return (T)Convert.ChangeType(value, typeof(T));
				}
				catch
				{
				}
			}
			return GetProperty<T>(instance, memberName);
		}

		public static T CallMethod<T>(object instance, string methodName, params object[] args)
		{
			if (instance == null)
			{
				return default(T);
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(instance.GetType(), methodName, (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					ManualLogSource log = ModAPIPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("ReflectionHelper.CallMethod: Method '" + methodName + "' not found on " + instance.GetType().Name));
					}
					return default(T);
				}
				object obj = methodInfo.Invoke(instance, args);
				if (obj is T result)
				{
					return result;
				}
				if (obj == null)
				{
					return default(T);
				}
				return (T)Convert.ChangeType(obj, typeof(T));
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = ModAPIPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("ReflectionHelper.CallMethod<" + typeof(T).Name + ">(" + methodName + "): " + ex.Message));
				}
				return default(T);
			}
		}

		public static void CallMethod(object instance, string methodName, params object[] args)
		{
			if (instance == null)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(instance.GetType(), methodName, (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					ManualLogSource log = ModAPIPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("ReflectionHelper.CallMethod: Method '" + methodName + "' not found on " + instance.GetType().Name));
					}
				}
				else
				{
					methodInfo.Invoke(instance, args);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = ModAPIPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("ReflectionHelper.CallMethod(" + methodName + "): " + ex.Message));
				}
			}
		}

		public static T CallStaticMethod<T>(Type type, string methodName, params object[] args)
		{
			if (type == null)
			{
				return default(T);
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					ManualLogSource log = ModAPIPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("ReflectionHelper.CallStaticMethod: Method '" + methodName + "' not found on " + type.Name));
					}
					return default(T);
				}
				object obj = methodInfo.Invoke(null, args);
				if (obj is T result)
				{
					return result;
				}
				if (obj == null)
				{
					return default(T);
				}
				return (T)Convert.ChangeType(obj, typeof(T));
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = ModAPIPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("ReflectionHelper.CallStaticMethod<" + typeof(T).Name + ">(" + type.Name + "." + methodName + "): " + ex.Message));
				}
				return default(T);
			}
		}

		public static T ParseEnum<T>(string valueName, T defaultValue = default(T)) where T : struct
		{
			if (string.IsNullOrEmpty(valueName))
			{
				return defaultValue;
			}
			if (Enum.TryParse<T>(valueName, ignoreCase: true, out var result))
			{
				return result;
			}
			ManualLogSource log = ModAPIPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("ReflectionHelper.ParseEnum: '" + valueName + "' not found in " + typeof(T).Name));
			}
			return defaultValue;
		}

		public static object ParseEnum(Type enumType, string valueName)
		{
			if (enumType == null || string.IsNullOrEmpty(valueName))
			{
				return null;
			}
			string key = enumType.FullName + "." + valueName;
			if (_enumCache.TryGetValue(key, out var value))
			{
				return value;
			}
			try
			{
				object obj = Enum.Parse(enumType, valueName, ignoreCase: true);
				_enumCache[key] = obj;
				return obj;
			}
			catch
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("ReflectionHelper.ParseEnum: '" + valueName + "' not found in " + enumType.Name));
				}
				return null;
			}
		}

		public static object ParseGameEnum(string enumTypeName, string valueName)
		{
			Type type = FindType(enumTypeName);
			if (type == null)
			{
				return null;
			}
			return ParseEnum(type, valueName);
		}

		public static Array CreateTypedArray(Type elementType, IList items)
		{
			if (elementType == null || items == null)
			{
				return Array.CreateInstance(elementType ?? typeof(object), 0);
			}
			Array array = Array.CreateInstance(elementType, items.Count);
			for (int i = 0; i < items.Count; i++)
			{
				array.SetValue(items[i], i);
			}
			return array;
		}

		public static T[] CreateArray<T>(IList<T> items)
		{
			if (items == null)
			{
				return Array.Empty<T>();
			}
			T[] array = new T[items.Count];
			items.CopyTo(array, 0);
			return array;
		}

		public static Array AppendToArray(Array original, object newItem)
		{
			if (original == null)
			{
				Array array = Array.CreateInstance(newItem.GetType(), 1);
				array.SetValue(newItem, 0);
				return array;
			}
			Type elementType = original.GetType().GetElementType();
			Array array2 = Array.CreateInstance(elementType, original.Length + 1);
			Array.Copy(original, array2, original.Length);
			array2.SetValue(newItem, original.Length);
			return array2;
		}

		public static T[] AppendToArray<T>(T[] original, T newItem)
		{
			if (original == null)
			{
				return new T[1] { newItem };
			}
			T[] array = new T[original.Length + 1];
			Array.Copy(original, array, original.Length);
			array[original.Length] = newItem;
			return array;
		}

		public static Object CreateScriptableObject(string typeName)
		{
			Type type = FindType(typeName);
			if (type == null)
			{
				return null;
			}
			return (Object)(object)ScriptableObject.CreateInstance(type);
		}

		public static T CloneObject<T>(T original) where T : Object
		{
			if ((Object)(object)original == (Object)null)
			{
				return default(T);
			}
			return Object.Instantiate<T>(original);
		}

		private static FieldInfo GetCachedField(Type type, string fieldName)
		{
			string key = type.FullName + "." + fieldName;
			if (_fieldCache.TryGetValue(key, out var value))
			{
				return value;
			}
			FieldInfo fieldInfo = AccessTools.Field(type, fieldName);
			_fieldCache[key] = fieldInfo;
			if (fieldInfo == null)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("ReflectionHelper: Field '" + fieldName + "' not found on " + type.Name));
				}
			}
			return fieldInfo;
		}

		private static PropertyInfo GetCachedProperty(Type type, string propertyName)
		{
			string key = type.FullName + "." + propertyName;
			if (_propCache.TryGetValue(key, out var value))
			{
				return value;
			}
			PropertyInfo propertyInfo = AccessTools.Property(type, propertyName);
			_propCache[key] = propertyInfo;
			if (propertyInfo == null)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("ReflectionHelper: Property '" + propertyName + "' not found on " + type.Name));
				}
			}
			return propertyInfo;
		}

		public static void ClearCaches()
		{
			_typeCache.Clear();
			_fieldCache.Clear();
			_propCache.Clear();
			_enumCache.Clear();
		}
	}
	public abstract class StolenRealmMod : BaseUnityPlugin
	{
		protected ManualLogSource Log { get; private set; }

		protected Harmony HarmonyInstance { get; private set; }

		public string ModGuid { get; private set; }

		public string ModName { get; private set; }

		public string ModVersion { get; private set; }

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			BepInPlugin val = (BepInPlugin)Attribute.GetCustomAttribute(((object)this).GetType(), typeof(BepInPlugin));
			if (val != null)
			{
				ModGuid = val.GUID;
				ModName = val.Name;
				ModVersion = val.Version.ToString();
			}
			else
			{
				ModGuid = ((object)this).GetType().FullName;
				ModName = ((object)this).GetType().Name;
				ModVersion = "0.0.0";
			}
			Log = ((BaseUnityPlugin)this).Logger;
			HarmonyInstance = new Harmony(ModGuid);
			HarmonyInstance.PatchAll(((object)this).GetType().Assembly);
			Log.LogInfo((object)$"{ModName} v{ModVersion} loaded ({HarmonyInstance.GetPatchedMethods()} patches applied).");
			ModAPIPlugin.RegisterMod(this);
			try
			{
				OnModLoaded();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Error in OnModLoaded: {arg}");
			}
		}

		protected virtual void OnModLoaded()
		{
		}

		protected virtual void OnGameReady()
		{
		}

		protected virtual void OnModUnloading()
		{
		}

		internal void InvokeOnGameReady()
		{
			OnGameReady();
		}

		internal void InvokeOnModUnloading()
		{
			OnModUnloading();
		}

		private void OnDestroy()
		{
			ModAPIPlugin.UnregisterMod(ModGuid);
		}
	}
}
namespace StolenRealmModAPI.UI
{
	public static class ActionBarUI
	{
		private class ButtonInfo
		{
			public string Name;

			public Sprite Icon;

			public Action OnClick;

			public GameObject ButtonGameObject;

			public bool Injected;
		}

		private static readonly Dictionary<string, ButtonInfo> _customButtons = new Dictionary<string, ButtonInfo>();

		public static void AddButton(string name, Sprite icon, Action onClick)
		{
			if (string.IsNullOrEmpty(name))
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogError((object)"ActionBarUI.AddButton: name cannot be null or empty.");
				}
			}
			else if (_customButtons.ContainsKey(name))
			{
				ManualLogSource log2 = ModAPIPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("ActionBarUI: Button '" + name + "' already registered."));
				}
			}
			else
			{
				_customButtons[name] = new ButtonInfo
				{
					Name = name,
					Icon = icon,
					OnClick = onClick,
					Injected = false
				};
				TryInjectAll();
			}
		}

		public static void RemoveButton(string name)
		{
			if (_customButtons.TryGetValue(name, out var value))
			{
				if ((Object)(object)value.ButtonGameObject != (Object)null)
				{
					UIFactory.Destroy(value.ButtonGameObject);
				}
				_customButtons.Remove(name);
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("ActionBarUI: Removed button '" + name + "'."));
				}
			}
		}

		public static void UpdateIcon(string name, Sprite newIcon)
		{
			if (_customButtons.TryGetValue(name, out var value))
			{
				value.Icon = newIcon;
				if ((Object)(object)value.ButtonGameObject != (Object)null)
				{
					UIFactory.SetIcon(value.ButtonGameObject, newIcon);
				}
			}
		}

		internal static void TryInjectAll()
		{
			object currentCharacterUI = GameAccessor.CurrentCharacterUI;
			if (currentCharacterUI == null)
			{
				return;
			}
			Type type = currentCharacterUI.GetType();
			FieldInfo fieldInfo = AccessTools.Field(type, "fortuneBtn");
			if (fieldInfo == null)
			{
				return;
			}
			object? value = fieldInfo.GetValue(currentCharacterUI);
			Component val = (Component)((value is Component) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int num = 0;
			foreach (KeyValuePair<string, ButtonInfo> customButton in _customButtons)
			{
				ButtonInfo value2 = customButton.Value;
				if (value2.Injected)
				{
					continue;
				}
				try
				{
					InjectButton(val.gameObject, value2, num);
					value2.Injected = true;
					num++;
				}
				catch (Exception arg)
				{
					ManualLogSource log = ModAPIPlugin.Log;
					if (log != null)
					{
						log.LogError((object)$"ActionBarUI: Failed to inject button '{value2.Name}': {arg}");
					}
				}
			}
		}

		private static void InjectButton(GameObject template, ButtonInfo info, int index)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			GameObject val = UIFactory.Clone(template, "CustomBtn_" + info.Name.Replace(" ", ""));
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			info.ButtonGameObject = val;
			RectTransform component = template.GetComponent<RectTransform>();
			RectTransform component2 = val.GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null)
			{
				float num = -70f * (float)(index + 1);
				component2.anchoredPosition = new Vector2(component.anchoredPosition.x + num, component.anchoredPosition.y);
			}
			UIFactory.DisableAllText(val);
			UIFactory.DisableChildLayouts(val);
			if ((Object)(object)info.Icon != (Object)null)
			{
				UIFactory.SetIcon(val, info.Icon);
			}
			if (info.OnClick != null)
			{
				UIFactory.BindClick(val, (UnityAction)delegate
				{
					info.OnClick();
				});
			}
			val.SetActive(true);
			ManualLogSource log = ModAPIPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("ActionBarUI: Injected button '" + info.Name + "'."));
			}
		}

		internal static void ResetInjectionState()
		{
			foreach (ButtonInfo value in _customButtons.Values)
			{
				value.Injected = false;
				value.ButtonGameObject = null;
			}
		}
	}
	public static class MenuUI
	{
		private class TabInfo
		{
			public string Name;

			public Action<GameObject> OnOpen;

			public Action OnClose;

			public GameObject TabButton;

			public GameObject ContentPanel;

			public bool Injected;
		}

		private static readonly Dictionary<string, TabInfo> _customTabs = new Dictionary<string, TabInfo>();

		public static void AddTab(string tabName, Action<GameObject> onOpen, Action onClose = null)
		{
			if (string.IsNullOrEmpty(tabName))
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogError((object)"MenuUI.AddTab: tabName cannot be null or empty.");
				}
			}
			else if (_customTabs.ContainsKey(tabName))
			{
				ManualLogSource log2 = ModAPIPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("MenuUI: Tab '" + tabName + "' already registered."));
				}
			}
			else
			{
				_customTabs[tabName] = new TabInfo
				{
					Name = tabName,
					OnOpen = onOpen,
					OnClose = onClose,
					Injected = false
				};
				TryInjectAll();
			}
		}

		public static void RemoveTab(string tabName)
		{
			if (_customTabs.TryGetValue(tabName, out var value))
			{
				if ((Object)(object)value.TabButton != (Object)null)
				{
					UIFactory.Destroy(value.TabButton);
				}
				if ((Object)(object)value.ContentPanel != (Object)null)
				{
					UIFactory.Destroy(value.ContentPanel);
				}
				_customTabs.Remove(tabName);
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("MenuUI: Removed tab '" + tabName + "'."));
				}
			}
		}

		internal static void TryInjectAll()
		{
			object characterMenusManager = GameAccessor.CharacterMenusManager;
			if (characterMenusManager == null)
			{
				return;
			}
			Type type = characterMenusManager.GetType();
			FieldInfo fieldInfo = AccessTools.Field(type, "TabFortunes");
			if (fieldInfo == null)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"MenuUI: Could not find TabFortunes field.");
				}
				return;
			}
			object value = fieldInfo.GetValue(characterMenusManager);
			if (value == null)
			{
				return;
			}
			GameObject val = null;
			Component val2 = (Component)((value is Component) ? value : null);
			if (val2 != null)
			{
				val = val2.gameObject;
			}
			else
			{
				GameObject val3 = (GameObject)((value is GameObject) ? value : null);
				if (val3 != null)
				{
					val = val3;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int num = 0;
			foreach (KeyValuePair<string, TabInfo> customTab in _customTabs)
			{
				TabInfo value2 = customTab.Value;
				if (value2.Injected)
				{
					continue;
				}
				try
				{
					InjectTab(val, type, characterMenusManager, value2, num);
					value2.Injected = true;
					num++;
				}
				catch (Exception arg)
				{
					ManualLogSource log2 = ModAPIPlugin.Log;
					if (log2 != null)
					{
						log2.LogError((object)$"MenuUI: Failed to inject tab '{value2.Name}': {arg}");
					}
				}
			}
		}

		private static void InjectTab(GameObject template, Type managerType, object manager, TabInfo info, int index)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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)
			//IL_019e: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = UIFactory.Clone(template, "MenuTab_" + info.Name.Replace(" ", ""));
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			info.TabButton = val;
			UIFactory.SetText(val, info.Name);
			RectTransform component = template.GetComponent<RectTransform>();
			RectTransform component2 = val.GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null)
			{
				float num = 90f * (float)(index + 1);
				component2.anchoredPosition = new Vector2(component.anchoredPosition.x + num, component.anchoredPosition.y);
			}
			Transform parent = template.transform.parent;
			Transform val2 = ((parent != null) ? parent.parent : null);
			if ((Object)(object)val2 != (Object)null)
			{
				GameObject val3 = new GameObject("MenuContent_" + info.Name.Replace(" ", ""));
				val3.transform.SetParent(val2, false);
				RectTransform val4 = val3.AddComponent<RectTransform>();
				val4.anchorMin = Vector2.zero;
				val4.anchorMax = Vector2.one;
				val4.offsetMin = Vector2.zero;
				val4.offsetMax = Vector2.zero;
				val3.SetActive(false);
				info.ContentPanel = val3;
			}
			UIFactory.BindClick(val, (UnityAction)delegate
			{
				try
				{
					AccessTools.Method(managerType, "CloseCharacterMenu", (Type[])null, (Type[])null)?.Invoke(manager, null);
					AccessTools.Method(managerType, "CloseSkillTreeMenu", (Type[])null, (Type[])null)?.Invoke(manager, null);
					AccessTools.Method(managerType, "CloseFortuneMenu", (Type[])null, (Type[])null)?.Invoke(manager, null);
				}
				catch (Exception ex)
				{
					ManualLogSource log2 = ModAPIPlugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)("MenuUI: Error closing existing menus: " + ex.Message));
					}
				}
				foreach (TabInfo value in _customTabs.Values)
				{
					if (value != info && (Object)(object)value.ContentPanel != (Object)null)
					{
						value.ContentPanel.SetActive(false);
						value.OnClose?.Invoke();
					}
				}
				if ((Object)(object)info.ContentPanel != (Object)null)
				{
					info.ContentPanel.SetActive(true);
					info.OnOpen?.Invoke(info.ContentPanel);
				}
			});
			val.SetActive(true);
			ManualLogSource log = ModAPIPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("MenuUI: Injected tab '" + info.Name + "'."));
			}
		}

		internal static void ResetInjectionState()
		{
			foreach (TabInfo value in _customTabs.Values)
			{
				value.Injected = false;
				value.TabButton = null;
				value.ContentPanel = null;
			}
		}
	}
	public static class SkillTreeUI
	{
		private class TabInfo
		{
			public string Name;

			public int SkillTypeValue;

			public GameObject TabGameObject;

			public object TabComponent;

			public object ShowerComponent;

			public GameObject TreeContainer;

			public bool Injected;
		}

		private static readonly Dictionary<int, TabInfo> _customTabs = new Dictionary<int, TabInfo>();

		public static void AddTab(string tabName, SkillTree skillTree)
		{
			int num = (int)((skillTree == SkillTree.Innate) ? SkillTree.Innate : skillTree);
			if (_customTabs.ContainsKey(num))
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)$"SkillTreeUI: Tab for SkillTree {skillTree} already registered.");
				}
				return;
			}
			_customTabs[num] = new TabInfo
			{
				Name = tabName,
				SkillTypeValue = num,
				Injected = false
			};
			ManualLogSource log2 = ModAPIPlugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"SkillTreeUI: Registered tab '{tabName}' for skill type {num}. Will inject on next UpdateSkillTreeItems.");
			}
		}

		public static void RemoveTab(SkillTree skillTree)
		{
			if (_customTabs.TryGetValue((int)skillTree, out var value))
			{
				if ((Object)(object)value.TabGameObject != (Object)null)
				{
					UIFactory.Destroy(value.TabGameObject);
				}
				if ((Object)(object)value.TreeContainer != (Object)null)
				{
					UIFactory.Destroy(value.TreeContainer);
				}
				_customTabs.Remove((int)skillTree);
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"SkillTreeUI: Removed tab for skill type {(int)skillTree}.");
				}
			}
		}

		internal static void OnUpdateSkillTreeItems(object skillTreeManager)
		{
			if (skillTreeManager == null || _customTabs.Count == 0)
			{
				return;
			}
			Type type = skillTreeManager.GetType();
			Type type2 = ReflectionHelper.FindType("SkillType");
			Type type3 = ReflectionHelper.FindType("SkillTreeTab");
			if (type2 == null || type3 == null)
			{
				return;
			}
			foreach (KeyValuePair<int, TabInfo> customTab in _customTabs)
			{
				TabInfo value = customTab.Value;
				if (value.Injected)
				{
					continue;
				}
				try
				{
					InjectTab(skillTreeManager, type, type2, type3, value);
					value.Injected = true;
				}
				catch (Exception arg)
				{
					ManualLogSource log = ModAPIPlugin.Log;
					if (log != null)
					{
						log.LogError((object)$"SkillTreeUI: Failed to inject tab '{value.Name}': {arg}");
					}
				}
			}
		}

		private static void InjectTab(object manager, Type managerType, Type skillTypeEnum, Type tabType, TabInfo info)
		{
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			FieldInfo fieldInfo = AccessTools.Field(managerType, "skillTabTypes");
			if (fieldInfo != null && fieldInfo.GetValue(manager) is IList list)
			{
				object value = Enum.ToObject(skillTypeEnum, info.SkillTypeValue);
				bool flag = false;
				foreach (object item in list)
				{
					if (Convert.ToInt32(item) == info.SkillTypeValue)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list.Add(value);
					ManualLogSource log = ModAPIPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)$"SkillTreeUI: Added skill type {info.SkillTypeValue} to skillTabTypes.");
					}
				}
			}
			FieldInfo fieldInfo2 = AccessTools.Field(managerType, "skillTreeTabs");
			if (fieldInfo2 != null && fieldInfo2.GetValue(manager) is IList list2 && list2.Count > 0)
			{
				object? obj = list2[list2.Count - 1];
				Component val = (Component)((obj is Component) ? obj : null);
				if ((Object)(object)val != (Object)null && (Object)(object)info.TabGameObject == (Object)null)
				{
					GameObject val2 = UIFactory.Clone(val.gameObject, "SkillTreeTab_" + info.Name.Replace(" ", ""));
					if ((Object)(object)val2 != (Object)null)
					{
						info.TabGameObject = val2;
						RectTransform component = val.GetComponent<RectTransform>();
						RectTransform component2 = val2.GetComponent<RectTransform>();
						if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null)
						{
							component2.anchoredPosition = new Vector2(component.anchoredPosition.x + 90f, component.anchoredPosition.y);
						}
						UIFactory.SetText(val2, info.Name);
						Component component3 = val2.GetComponent(tabType);
						if ((Object)(object)component3 != (Object)null)
						{
							info.TabComponent = component3;
							FieldInfo fieldInfo3 = AccessTools.Field(tabType, "skillType");
							if (fieldInfo3 != null)
							{
								object value2 = Enum.ToObject(skillTypeEnum, info.SkillTypeValue);
								fieldInfo3.SetValue(component3, value2);
							}
							list2.Add(component3);
						}
						val2.SetActive(true);
						ManualLogSource log2 = ModAPIPlugin.Log;
						if (log2 != null)
						{
							log2.LogInfo((object)("SkillTreeUI: Created tab button '" + info.Name + "'."));
						}
					}
				}
			}
			FieldInfo fieldInfo4 = AccessTools.Field(managerType, "skillTreeShowers");
			FieldInfo fieldInfo5 = AccessTools.Field(managerType, "skillItemContainer");
			if (!(fieldInfo4 != null) || !(fieldInfo4.GetValue(manager) is IList list3) || list3.Count <= 0)
			{
				return;
			}
			object? obj2 = list3[list3.Count - 1];
			Component val3 = (Component)((obj2 is Component) ? obj2 : null);
			if (!((Object)(object)val3 != (Object)null) || info.ShowerComponent != null)
			{
				return;
			}
			Type type = ((object)val3).GetType();
			GameObject val4 = UIFactory.Clone(val3.gameObject, "SkillTree_" + info.Name.Replace(" ", ""));
			if (!((Object)(object)val4 != (Object)null))
			{
				return;
			}
			Component component4 = val4.GetComponent(type);
			if ((Object)(object)component4 != (Object)null)
			{
				info.ShowerComponent = component4;
				FieldInfo fieldInfo6 = AccessTools.Field(type, "Type");
				if (fieldInfo6 != null)
				{
					object value3 = Enum.ToObject(skillTypeEnum, info.SkillTypeValue);
					fieldInfo6.SetValue(component4, value3);
				}
				list3.Add(component4);
			}
			if (fieldInfo5 != null)
			{
				if (fieldInfo5.GetValue(manager) is IList list4)
				{
					list4.Add(val4);
				}
				info.TreeContainer = val4;
			}
			val4.SetActive(false);
			ManualLogSource log3 = ModAPIPlugin.Log;
			if (log3 != null)
			{
				log3.LogInfo((object)("SkillTreeUI: Created skill tree container '" + info.Name + "'."));
			}
		}

		public static bool HasTab(SkillTree skillTree)
		{
			return _customTabs.ContainsKey((int)skillTree);
		}

		internal static void ResetInjectionState()
		{
			foreach (TabInfo value in _customTabs.Values)
			{
				value.Injected = false;
				value.TabGameObject = null;
				value.TabComponent = null;
				value.ShowerComponent = null;
				value.TreeContainer = null;
			}
		}
	}
	[HarmonyPatch]
	internal static class SkillTreeUIPatches
	{
		[HarmonyPatch]
		private static class UpdateSkillTreeItemsPatch
		{
			private static bool Prepare()
			{
				return ReflectionHelper.FindType("SkillTreeManager") != null;
			}

			private static MethodBase TargetMethod()
			{
				Type type = ReflectionHelper.FindType("SkillTreeManager");
				return AccessTools.Method(type, "UpdateSkillTreeItems", (Type[])null, (Type[])null);
			}

			private static void Postfix(object __instance)
			{
				try
				{
					SkillTreeUI.OnUpdateSkillTreeItems(__instance);
				}
				catch (Exception arg)
				{
					ManualLogSource log = ModAPIPlugin.Log;
					if (log != null)
					{
						log.LogError((object)$"SkillTreeUIPatches: {arg}");
					}
				}
			}
		}
	}
	public static class TooltipHelper
	{
		private static GameObject _customTooltip;

		private static bool _isInitialized;

		public static void ShowTooltip(string title, string description, Sprite icon = null)
		{
			if (!TryUseGameTooltip(title, description, icon))
			{
				ShowFallbackTooltip(title, description, icon);
			}
		}

		public static void HideTooltip()
		{
			TryHideGameTooltip();
			if ((Object)(object)_customTooltip != (Object)null)
			{
				_customTooltip.SetActive(false);
			}
		}

		private static bool TryUseGameTooltip(string title, string description, Sprite icon)
		{
			Type type = ReflectionHelper.FindType("GUIManager");
			if (type == null)
			{
				return false;
			}
			PropertyInfo propertyInfo = AccessTools.Property(type, "Instance");
			if (propertyInfo == null)
			{
				FieldInfo fieldInfo = AccessTools.Field(type, "Instance") ?? AccessTools.Field(type, "instance") ?? AccessTools.Field(type, "_instance");
				if (fieldInfo == null)
				{
					return false;
				}
				object value = fieldInfo.GetValue(null);
				if (value == null)
				{
					return false;
				}
				return InvokeShowTooltip(value, type, title, description);
			}
			object value2 = propertyInfo.GetValue(null);
			if (value2 == null)
			{
				return false;
			}
			return InvokeShowTooltip(value2, type, title, description);
		}

		private static bool InvokeShowTooltip(object instance, Type type, string title, string description)
		{
			MethodInfo methodInfo = AccessTools.Method(type, "ShowTooltip", new Type[2]
			{
				typeof(string),
				typeof(string)
			}, (Type[])null) ?? AccessTools.Method(type, "ShowTooltip", new Type[1] { typeof(string) }, (Type[])null) ?? AccessTools.Method(type, "SetTooltip", new Type[2]
			{
				typeof(string),
				typeof(string)
			}, (Type[])null) ?? AccessTools.Method(type, "SetTooltip", new Type[1] { typeof(string) }, (Type[])null);
			if (methodInfo == null)
			{
				return false;
			}
			try
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 2)
				{
					methodInfo.Invoke(instance, new object[2] { title, description });
				}
				else if (parameters.Length == 1)
				{
					methodInfo.Invoke(instance, new object[1] { "<b>" + title + "</b>\n" + description });
				}
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static void TryHideGameTooltip()
		{
			Type type = ReflectionHelper.FindType("GUIManager");
			if (type == null)
			{
				return;
			}
			PropertyInfo propertyInfo = AccessTools.Property(type, "Instance");
			object obj = null;
			if (propertyInfo != null)
			{
				obj = propertyInfo.GetValue(null);
			}
			else
			{
				FieldInfo fieldInfo = AccessTools.Field(type, "Instance") ?? AccessTools.Field(type, "instance") ?? AccessTools.Field(type, "_instance");
				if (fieldInfo != null)
				{
					obj = fieldInfo.GetValue(null);
				}
			}
			if (obj == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "HideTooltip", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "CloseTooltip", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "ClearTooltip", (Type[])null, (Type[])null);
			try
			{
				methodInfo?.Invoke(obj, null);
			}
			catch (Exception ex)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("TooltipHelper: Failed to hide game tooltip: " + ex.Message));
				}
			}
		}

		private static void ShowFallbackTooltip(string title, string description, Sprite icon)
		{
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			EnsureFallbackTooltip();
			if ((Object)(object)_customTooltip == (Object)null)
			{
				return;
			}
			Transform val = UIFactory.FindChild(_customTooltip.transform, "Title");
			if ((Object)(object)val != (Object)null)
			{
				UIFactory.SetText(((Component)val).gameObject, title);
			}
			Transform val2 = UIFactory.FindChild(_customTooltip.transform, "Description");
			if ((Object)(object)val2 != (Object)null)
			{
				UIFactory.SetText(((Component)val2).gameObject, description);
			}
			Transform val3 = UIFactory.FindChild(_customTooltip.transform, "Icon");
			if ((Object)(object)val3 != (Object)null)
			{
				((Component)val3).gameObject.SetActive((Object)(object)icon != (Object)null);
				if ((Object)(object)icon != (Object)null)
				{
					UIFactory.SetIcon(((Component)val3).gameObject, icon);
				}
			}
			RectTransform component = _customTooltip.GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null)
			{
				((Transform)component).position = Input.mousePosition + new Vector3(15f, -15f, 0f);
			}
			_customTooltip.SetActive(true);
		}

		private static void EnsureFallbackTooltip()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_customTooltip != (Object)null))
			{
				Canvas val = Object.FindObjectOfType<Canvas>();
				if (!((Object)(object)val == (Object)null))
				{
					_customTooltip = new GameObject("ModAPI_Tooltip");
					_customTooltip.transform.SetParent(((Component)val).transform, false);
					RectTransform val2 = _customTooltip.AddComponent<RectTransform>();
					val2.sizeDelta = new Vector2(300f, 120f);
					val2.pivot = new Vector2(0f, 1f);
					Image val3 = _customTooltip.AddComponent<Image>();
					((Graphic)val3).color = new Color(0.1f, 0.1f, 0.15f, 0.95f);
					VerticalLayoutGroup val4 = _customTooltip.AddComponent<VerticalLayoutGroup>();
					((LayoutGroup)val4).padding = new RectOffset(10, 10, 8, 8);
					((HorizontalOrVerticalLayoutGroup)val4).spacing = 4f;
					((HorizontalOrVerticalLayoutGroup)val4).childForceExpandWidth = true;
					((HorizontalOrVerticalLayoutGroup)val4).childForceExpandHeight = false;
					GameObject val5 = new GameObject("Icon");
					val5.transform.SetParent(_customTooltip.transform, false);
					RectTransform val6 = val5.AddComponent<RectTransform>();
					val6.sizeDelta = new Vector2(32f, 32f);
					val5.AddComponent<Image>();
					LayoutElement val7 = val5.AddComponent<LayoutElement>();
					val7.preferredHeight = 32f;
					val7.preferredWidth = 32f;
					val5.SetActive(false);
					CreateTextElement(_customTooltip.transform, "Title", 16, (FontStyle)1);
					CreateTextElement(_customTooltip.transform, "Description", 13, (FontStyle)0);
					Canvas val8 = _customTooltip.AddComponent<Canvas>();
					val8.overrideSorting = true;
					val8.sortingOrder = 9999;
					_customTooltip.AddComponent<GraphicRaycaster>();
					ContentSizeFitter val9 = _customTooltip.AddComponent<ContentSizeFitter>();
					val9.horizontalFit = (FitMode)2;
					val9.verticalFit = (FitMode)2;
					_customTooltip.SetActive(false);
					_isInitialized = true;
				}
			}
		}

		private static void CreateTextElement(Transform parent, string name, int fontSize, FontStyle style)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.sizeDelta = new Vector2(280f, 0f);
			Type type = ReflectionHelper.FindType("TMPro.TextMeshProUGUI");
			if (type != null)
			{
				Component instance = val.AddComponent(type);
				ReflectionHelper.SetProperty(instance, "text", "");
				ReflectionHelper.SetProperty(instance, "fontSize", (float)fontSize);
				ReflectionHelper.SetProperty(instance, "enableWordWrapping", true);
				ReflectionHelper.SetProperty(instance, "color", Color.white);
			}
			else
			{
				Text val3 = val.AddComponent<Text>();
				val3.text = "";
				val3.fontSize = fontSize;
				val3.fontStyle = style;
				((Graphic)val3).color = Color.white;
				val3.horizontalOverflow = (HorizontalWrapMode)0;
				val3.verticalOverflow = (VerticalWrapMode)1;
			}
			LayoutElement val4 = val.AddComponent<LayoutElement>();
			val4.preferredWidth = 280f;
		}

		internal static void ResetState()
		{
			_customTooltip = null;
			_isInitialized = false;
		}
	}
	public static class UIFactory
	{
		public static GameObject Clone(GameObject template, string name = null)
		{
			if ((Object)(object)template == (Object)null)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogError((object)"UIFactory.Clone: template is null.");
				}
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(template, template.transform.parent);
			if (!string.IsNullOrEmpty(name))
			{
				((Object)val).name = name;
			}
			return val;
		}

		public static GameObject Clone(GameObject template, Transform parent, string name = null)
		{
			if ((Object)(object)template == (Object)null)
			{
				ManualLogSource log = ModAPIPlugin.Log;
				if (log != null)
				{
					log.LogError((object)"UIFactory.Clone: template is null.");
				}
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(template, parent);
			if (!string.IsNullOrEmpty(name))
			{
				((Object)val).name = name;
			}
			return val;
		}

		public static Component CloneComponent(Component template, string name = null)
		{
			if ((Object)(object)template == (Object)null)
			{
				return null;
			}
			GameObject val = Clone(template.gameObject, name);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return val.GetComponent(((object)template).GetType());
		}

		public static void SetText(GameObject go, string text)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			Type type = ReflectionHelper.FindType("TMPro.TextMeshProUGUI");
			if (type != null)
			{
				Component componentInChildren = go.GetComponentInChildren(type, true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					ReflectionHelper.SetProperty(componentInChildren, "text", text);
					return;
				}
			}
			Text componentInChildren2 = go.GetComponentInChildren<Text>(true);
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.text = text;
			}
		}

		public static void SetIcon(GameObject go, Sprite icon, string childNameHint = null)
		{
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null || (Object)(object)icon == (Object)null)
			{
				return;
			}
			Image[] componentsInChildren = go.GetComponentsInChildren<Image>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				return;
			}
			Image val = null;
			if (!string.IsNullOrEmpty(childNameHint))
			{
				Image[] array = componentsInChildren;
				foreach (Image val2 in array)
				{
					if (((Object)((Component)val2).gameObject).name.IndexOf(childNameHint, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						val = val2;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Image[] array2 = componentsInChildren;
				foreach (Image val3 in array2)
				{
					string name = ((Object)((Component)val3).gameObject).name;
					if (name.IndexOf("Icon", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Image", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						val = val3;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null && componentsInChildren.Length > 1)
			{
				val = componentsInChildren[1];
			}
			else if ((Object)(object)val == (Object)null)
			{
				val = componentsInChildren[0];
			}
			val.sprite = icon;
			((Graphic)val).color = Color.white;
		}

		public static void BindClick(GameObject go, UnityAction onClick)
		{
			if (!((Object)(object)go == (Object)null) && onClick != null)
			{
				Button val = go.GetComponent<Button>();
				if ((Object)(object)val == (Object)null)
				{
					val = go.AddComponent<Button>();
				}
				((UnityEventBase)val.onClick).RemoveAllListeners();
				((UnityEvent)val.onClick).AddListener(onClick);
			}
		}

		public static void CopyRectLayout(RectTransform source, RectTransform target, Vector2 positionOffset = default(Vector2))
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null))
			{
				target.anchorMin = source.anchorMin;
				target.anchorMax = source.anchorMax;
				target.pivot = source.pivot;
				target.sizeDelta = source.sizeDelta;
				target.anchoredPosition = source.anchoredPosition + positionOffset;
			}
		}

		public static void DisableAllText(GameObject go)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			Type type = ReflectionHelper.FindType("TMPro.TextMeshProUGUI");
			if (type != null)
			{
				Component[] componentsInChildren = go.GetComponentsInChildren(type, true);
				Component[] array = componentsInChildren;
				foreach (Component val in array)
				{
					val.gameObject.SetActive(false);
					((Behaviour)val).enabled = false;
				}
			}
			Text[] componentsInChildren2 = go.GetComponentsInChildren<Text>(true);
			Text[] array2 = componentsInChildren2;
			foreach (Text val2 in array2)
			{
				((Component)val2).gameObject.SetActive(false);
				((Behaviour)val2).enabled = false;
			}
		}

		public static void DisableChildLayouts(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			LayoutElement[] componentsInChildren = go.GetComponentsInChildren<LayoutElement>(true);
			LayoutElement[] array = componentsInChildren;
			foreach (LayoutElement val in array)
			{
				if ((Object)(object)((Component)val).gameObject != (Object)(object)go)
				{
					((Behaviour)val).enabled = false;
				}
			}
		}

		public static void Destroy(GameObject go)
		{
			if ((Object)(object)go != (Object)null)
			{
				Object.Destroy((Object)(object)go);
			}
		}

		public static Transform FindChild(Transform parent, string name)
		{
			if ((Object)(object)parent == (Object)null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			Transform val = parent.Find(name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			for (int i = 0; i < parent.childCount; i++)
			{
				Transform val2 = FindChild(parent.GetChild(i), name);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}
	}
}
namespace StolenRealmModAPI.Skills
{
	public class ActionBuilder
	{
		private string _name;

		private string _description = "";

		private DamageType _damageType = DamageType.Physical;

		private string _damageFormula = "";

		private float _damageMultiplier = 1f;

		private ScalingType _scaling = ScalingType.SpellPower;

		private TargetMode _targetMode = TargetMode.SingleEnemy;

		private int _range = 5;

		private int _areaRadius = 0;

		private bool _canTargetSelf = false;

		private bool _requiresLineOfSight = true;

		private int _manaCost = 10;

		private int _actionPointCost = 3;

		private int _cooldown = 0;

		private int _charges = 0;

		private int _numHits = 1;

		private float _hitInterval = 0.3f;

		private bool _hasPull = false;

		private int _pullDistance = 0;

		private bool _hasKnockback = false;

		private int _knockbackDistance = 0;

		private bool _isProjectile = true;

		private int _projectileSpeed = 5;

		private bool _pierces = false;

		private int _pierceCount = 0;

		private bool _chains = false;

		private int _chainCount = 0;

		private VisualTemplate? _visualTemplate;

		private string _visualSourceActionName;

		private readonly List<StatusEffectBuilder> _statusEffects = new List<StatusEffectBuilder>();

		private Sprite _iconOverride;

		public ActionBuilder(string name)
		{
			_name = name ?? throw new ArgumentNullException("name");
		}

		public ActionBuilder WithDamageType(DamageType type)
		{
			_damageType = type;
			return this;
		}

		public ActionBuilder WithDamageFormula(string formula)
		{
			_damageFormula = formula;
			return this;
		}

		public ActionBuilder WithDamageMultiplier(float multiplier)
		{
			_damageMultiplier = multiplier;
			return this;
		}

		public ActionBuilder WithScaling(ScalingType scaling)
		{
			_scaling = scaling;
			return this;
		}

		public ActionBuilder WithTargeting(TargetMode mode, int range = 5, int areaRadius = 0)
		{
			_targetMode = mode;
			_range = range;
			_areaRadius = areaRadius;
			return this;
		}

		public ActionBuilder WithRange(int range)
		{
			_range = range;
			return this;
		}

		public ActionBuilder WithAreaRadius(int radius)
		{
			_areaRadius = radius;
			return this;
		}

		public ActionBuilder CanTargetSelf(bool canTarget = true)
		{
			_canTargetSelf = canTarget;
			return this;
		}

		public ActionBuilder RequiresLineOfSight(bool required = true)
		{
			_requiresLineOfSight = required;
			return this;
		}

		public ActionBuilder WithManaCost(int cost)
		{
			_manaCost = cost;
			return this;
		}

		public ActionBuilder WithActionPointCost(int cost)
		{
			_actionPointCost = cost;
			return this;
		}

		public ActionBuilder WithCooldown(int turns)
		{
			_cooldown = turns;
			return this;
		}

		public ActionBuilder WithCharges(int charges)
		{
			_charges = charges;
			return this;
		}

		public ActionBuilder WithMultiHit(int numHits, float hitInterval = 0.3f)
		{
			_numHits = numHits;
			_hitInterval = hitInterval;
			return this;
		}

		public ActionBuilder WithPull(int distance)
		{
			_hasPull = true;
			_pullDistance = distance;
			return this;
		}

		public ActionBuilder WithKnockback(int distance)
		{
			_hasKnockback = true;
			_knockbackDistance = distance;
			return this;
		}

		public ActionBuilder AsProjectile(int speed = 5)
		{
			_isProjectile = true;
			_projectileSpeed = speed;
			return this;
		}

		public ActionBuilder AsInstant()
		{
			_isProjectile = false;
			return this;
		}

		public ActionBuilder WithPierce(int count)
		{
			_pierces = true;
			_pierceCount = count;
			return this;
		}

		public ActionBuilder WithChain(int count)
		{
			_chains = true;
			_chainCount = count;
			return this;
		}

		public ActionBuilder WithVisualTemplate(VisualTemplate template)
		{
			_visualTemplate = template;
			return this;
		}

		public ActionBuilder WithVisualSource(string actionName)
		{
			_visualSourceActionName = actionName;
			return this;
		}

		public ActionBuilder WithIcon(Sprite icon)
		{
			_iconOverride = icon;
			return this;
		}

		public ActionBuilder WithStatusEffect(Action<StatusEffectBuilder> configure)
		{
			StatusEffectBuilder statusEffectBuilder = new StatusEffectBuilder();
			configure(statusEffectBuilder);
			_statusEffects.Add(statusEffectBuilder);
			return this;
		}

		public ActionBuilder WithDescription(string description)
		{
			_description = description;
			return this;
		}

		public object Build()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Type type = ReflectionHelper.FindType("ActionInfo");
				if (type == null)
				{
					ModAPIPlugin.Log.LogError((object)"ActionBuilder: ActionInfo type not found.");
					return null;
				}
				object obj = FindOrCreateBaseAction(type);
				if (obj == null)
				{
					ModAPIPlugin.Log.LogError((object)("ActionBuilder: Failed to create base action for '" + _name + "'."));
					return null;
				}
				((Object)obj).name = "ModAPI_" + _name.Replace(" ", "");
				SetFieldSafe(obj, "OverrideDescriptionAndName", true);
				SetFieldSafe(obj, "OverrideActionName", true);
				SetFieldSafe(obj, "ActionNameOverride", _name);
				string value = ((!string.IsNullOrEmpty(_description)) ? _description : GenerateDescription());
				SetFieldSafe(obj, "Description", value);
				ApplyDamageType(obj);
				ApplyTargeting(obj);
				ApplyCosts(obj);
				ApplyHitMechanics(obj);
				ApplyProjectile(obj);
				ApplyStatusEffects(obj);
				if ((Object)(object)_iconOverride != (Object)null)
				{
					SetFieldSafe(obj, "IconOverride", _iconOverride);
				}
				ModAPIPlugin.Log.LogInfo((object)$"ActionBuilder: Built action '{_name}' (dmg={_damageType}, target={_targetMode}, range={_range})");
				return obj;
			}
			catch (Exception arg)
			{
				ModAPIPlugin.Log.LogError((object)$"ActionBuilder: Failed to build '{_name}': {arg}");
				return null;
			}
		}

		private object FindOrCreateBaseAction(Type actionInfoType)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			string text = ResolveVisualSourceName();
			if (!string.IsNullOrEmpty(text))
			{
				object obj = FindGameAction(text);
				if (obj != null)
				{
					return Object.Instantiate((Object)obj);
				}
			}
			string[] array = new string[4] { "Fireball", "Slash", "Heal", "Smite" };
			foreach (string actionName in array)
			{
				object obj2 = FindGameAction(actionName);
				if (obj2 != null)
				{
					return Object.Instantiate((Object)obj2);
				}
			}
			return ScriptableObject.CreateInstance(actionInfoType);
		}

		private string ResolveVisualSourceName()
		{
			if (!string.IsNullOrEmpty(_visualSourceActionName))
			{
				return _visualSourceActionName;
			}
			if (_visualTemplate.HasValue)
			{
				VisualTemplate value = _visualTemplate.Value;
				if (1 == 0)
				{
				}
				string result = value switch
				{
					VisualTemplate.Fireball => "Fireball", 
					VisualTemplate.IceBolt => "Ice Bolt", 
					VisualTemplate.LightningBolt => "Thunder Bolt", 
					VisualTemplate.ShadowBolt => "Soul Bolt", 
					VisualTemplate.HolySmite => "Smite", 
					VisualTemplate.ArcaneMissile => "Magic Missile", 
					VisualTemplate.Slash => "Slash", 
					VisualTemplate.Thrust => "Piercing Strike", 
					VisualTemplate.Cleave => "Cleave", 
					VisualTemplate.Whirlwind => "Whirlwind", 
					VisualTemplate.Explosion => "Fireball", 
					VisualTemplate.Nova => "Frost Nova", 
					VisualTemplate.Rain => "Rain of Fire", 
					VisualTemplate.Shockwave => "Shockwave", 
					VisualTemplate.Heal => "Heal", 
					VisualTemplate.Buff => "Battle Shout", 
					VisualTemplate.Debuff => "Curse", 
					VisualTemplate.Teleport => "Blink", 
					VisualTemplate.Summon => "Summon Skeleton", 
					_ => "Fireball", 
				};
				if (1 == 0)
				{
				}
				return result;
			}
			return null;
		}

		private static object FindGameAction(string actionName)
		{
			object gameInstance = GameAccessor.GameInstance;
			if (gameInstance == null)
			{
				return null;
			}
			object fieldOrProperty = ReflectionHelper.GetFieldOrProperty<object>(gameInstance, "Actions");
			if (fieldOrProperty == null)
			{
				return null;
			}
			if (fieldOrProperty is IEnumerable enumerable)
			{
				foreach (object item in enumerable)
				{
					if (item != null)
					{
						Object val = (Object)((item is Object) ? item : null);
						if (val != (Object)null && val.name != null && val.name.Equals(actionName, StringComparison.OrdinalIgnoreCase))
						{
							return item;
						}
					}
				}
			}
			return null;
		}

		private void ApplyDamageType(object action)
		{
			Type type = ReflectionHelper.FindType("DamageType");
			if (type != null)
			{
				try
				{
					string valueName = _damageType.ToString();
					object obj = ReflectionHelper.ParseEnum(type, valueName);
					if (obj != null)
					{
						SetFieldSafe(action, "DamageType", obj);
					}
				}
				catch (Exception ex)
				{
					ModAPIPlugin.Log.LogWarning((object)("ActionBuilder: Failed to set DamageType: " + ex.Message));
				}
			}
			if (!string.IsNullOrEmpty(_damageFormula))
			{
				SetFieldSafe(action, "DamageExpression", _damageFormula);
			}
		}

		private void ApplyTargeting(object action)
		{
			Type type = ReflectionHelper.FindType("TargetInfo");
			if (type == null)
			{
				return;
			}
			ScriptableObject val = ScriptableObject.CreateInstance(type);
			if (!((Object)(object)val == (Object)null))
			{
				SetFieldSafe(val, "UseSimpleTargetingRange", true);
				SetFieldSafe(val, "SimpleRange", _range);
				SetFieldSafe(val, "UseSimpleTargetingBlast", false);
				SetFieldSafe(val, "SimpleBlastRange", 0);
				switch (_targetMode)
				{
				case TargetMode.SingleEnemy:
					SetFieldSafe(val, "TargetEnemies", true);
					SetFieldSafe(val, "TargetAllies", false);
					SetFieldSafe(val, "TargetSelf", false);
					break;
				case TargetMode.SingleAlly:
					SetFieldSafe(val, "TargetEnemies", false);
					SetFieldSafe(val, "TargetAllies", true);
					SetFieldSafe(val, "TargetSelf", _canTargetSelf);
					break;
				case TargetMode.Self:
					SetFieldSafe(val, "TargetEnemies", false);
					SetFieldSafe(val, "TargetAllies", false);
					SetFieldSafe(val, "TargetSelf", true);
					SetFieldSafe(val, "SimpleRange", 0);
					break;
				case TargetMode.AllEnemies:
					SetFieldSafe(val, "TargetEnemies", true);
					SetFieldSafe(val, "TargetGlobal", true);
					break;
				case TargetMode.AllAllies:
					SetFieldSafe(val, "TargetAllies", true);
					SetFieldSafe(val, "TargetSelf", _canTargetSelf);
					SetFieldSafe(val, "TargetGlobal", true);
					break;
				case TargetMode.AreaAroundTarget:
					SetFieldSafe(val, "TargetEnemies", true);
					SetFieldSafe(val, "TargetEnemiesBlast", true);
					SetFieldSafe(val, "UseSimpleTargetingBlast", true);
					SetFieldSafe(val, "SimpleBlastRange", Math.Max(1, _areaRadius));
					break;
				case TargetMode.AreaAroundSelf:
					SetFieldSafe(val, "TargetSelf", true);
					SetFieldSafe(val, "SimpleRange", 0);
					SetFieldSafe(val, "TargetEnemiesBlast", true);
					SetFieldSafe(val, "UseSimpleTargetingBlast", true);
					SetFieldSafe(val, "SimpleBlastRange", Math.Max(1, _areaRadius));
					break;
				case TargetMode.Line:
					SetFieldSafe(val, "UseSimpleTargetingRange", false);
					SetFieldSafe(val, "RangeSelection", $"Distance <= {_range}");
					SetFieldSafe(val, "Selection", "IsEnemy");
					SetFieldSafe(val, "Blast", "InLine(Source.Cell, Target.Cell)");
					break;
				case TargetMode.Cone:
					SetFieldSafe(val, "UseSimpleTargetingRange", false);
					SetFieldSafe(val, "RangeSelection", $"Distance <= {_range}");
					SetFieldSafe(val, "Selection", "IsEnemy");
					SetFieldSafe(val, "Blast", "InCone(Source.Cell, Target.Cell, 60)");
					break;
				}
				Type type2 = ReflectionHelper.FindType("ITargetInfo");
				if (type2 != null)
				{
					Array array = Array.CreateInstance(type2, 1);
					array.SetValue(val, 0);
					SetFieldSafe(action, "Targets", array);
				}
			}
		}

		private void ApplyCosts(object action)
		{
			SetFieldSafe(action, "Cost", _actionPointCost.ToString());
			SetFieldSafe(action, "ManaCostRatio", (float)_manaCost / 10f);
			if (_cooldown > 0)
			{
				SetFieldSafe(action, "Cooldown", _cooldown.ToString());
			}
			else
			{
				SetFieldSafe(action, "Cooldown", "");
			}
			if (_charges > 0)
			{
				SetFieldSafe(action, "HasCharges", true);
				SetFieldSafe(action, "MaxCharges", _charges.ToString());
				SetFieldSafe(action, "InitialCharges", _charges.ToString());
			}
			else
			{
				SetFieldSafe(action, "HasCharges", false);
			}
		}

		private void ApplyHitMechanics(object action)
		{
			if (_numHits > 1)
			{
				SetFieldSafe(action, "UseMultipleHits", true);
				SetFieldSafe(action, "NumHits", _numHits);
				SetFieldSafe(action, "HitInterval", _hitInterval);
			}
			else
			{
				SetFieldSafe(action, "UseMultipleHits", false);
				SetFieldSafe(action, "NumHits", 1);
			}
			if (_hasKnockback)
			{
				SetFieldSafe(action, "UseKnockback", true);
				SetFieldSafe(action, "KnockbackAmount", _knockbackDistance);
			}
			if (_hasPull)
			{
				SetFieldSafe(action, "PullToCenter", true);
				SetFieldSafe(action, "KnockbackAmount", _pullDistance);
			}
		}

		private void ApplyProjectile(object action)
		{
			if (!_isProjectile)
			{
				SetFieldSafe(action, "ProjectileCollisions", false);
				SetFieldSafe(action, "ProjectileChain", false);
				return;
			}
			if (_pierces)
			{
				SetFieldSafe(action, "ProjectileCollisions", true);
				SetFieldSafe(action, "ProjectilePierceCount", _pierceCount);
			}
			if (_chains)
			{
				SetFieldSafe(action, "ProjectileChain", true);
				SetFieldSafe(action, "ProjectileChainCount", _chainCount);
			}
		}

		private void ApplyStatusEffects(object action)
		{
			if (_statusEffects.Count == 0)
			{
				return;
			}
			foreach (StatusEffectBuilder statusEffect in _statusEffects)
			{
				statusEffect.ApplyToAction(action);
			}
		}

		private string GenerateDescription()
		{
			List<string> list = new List<string>();
			if (_damageType != 0)
			{
				list.Add($"Deals {_damageType} damage");
			}
			if (_areaRadius > 0)
			{
				list.Add($"in a {_areaRadius} tile radius");
			}
			if (_hasPull)
			{
				list.Add($"and pulls enemies {_pullDistance} tiles");
			}
			if (_hasKnockback)
			{
				list.Add($"and knocks back {_knockbackDistance} tiles");
			}
			if (_cooldown > 0)
			{
				list.Add($"({_cooldown} turn cooldown)");
			}
			return (list.Count > 0) ? (string.Join(" ", list) + ".") : "";
		}

		private static void SetFieldSafe(object instance, string fieldName, object value)
		{
			FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), fieldName);
			if (fieldInfo != null)
			{
				try
				{
					fieldInfo.SetValue(instance, value);
				}
				catch
				{
				}
			}
		}
	}
	public static class IconGenerator
	{
		private static readonly Dictionary<string, Sprite> _cache = new Dictionary<string, Sprite>();

		public static Sprite Generate(IconPattern pattern, Color primaryColor, Color secondaryColor = default(Color), int tier = 1, int size = 64)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0083: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if (secondaryColor == default(Color))
			{
				secondaryColor = Color.Lerp(primaryColor, Color.white, 0.4f);
			}
			string key = $"{pattern}_{primaryColor}_{tier}_{size}";
			if (_cache.TryGetValue(key, out var value))
			{
				return value;
			}
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
			Color[] pixels = GeneratePixels(size, primaryColor, secondaryColor, pattern, tier);
			val.SetPixels(pixels);
			val.Apply();
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f);
			_cache[key] = val2;
			return val2;
		}

		public static Color GetColorForDamageType(DamageType damageType)
		{
			//IL_00d8: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			if (1 == 0)
			{
			}
			Color result = (Color)(damageType switch
			{
				DamageType.Fire => new Color(1f, 0.4f, 0.2f), 
				DamageType.Cold => new Color(0.4f, 0.8f, 1f), 
				DamageType.Lightning => new Color(1f, 0.95f, 0.4f), 
				DamageType.Shadow => new Color(0.6f, 0.3f, 0.8f), 
				DamageType.Holy => new Color(1f, 0.95f, 0.7f), 
				DamageType.Healing => new Color(0.4f, 1f, 0.5f), 
				DamageType.Physical => new Color(0.75f, 0.7f, 0.65f), 
				DamageType.Weapon => new Color(0.85f, 0.85f, 0.85f), 
				_ => new Color(0.7f, 0.7f, 0.7f), 
			});
			if (1 == 0)
			{
			}
			return result;
		}

		public static void ClearCache()
		{
			foreach (Sprite value in _cache.Values)
			{
				if ((Object)(object)value != (Object)null && (Object)(object)value.texture != (Object)null)
				{
					Object.Destroy((Object)(object)value.texture);
					Object.Destroy((Object)(object)value);
				}
			}
			_cache.Clear();
		}

		private static Color[] GeneratePixels(int size, Color main, Color highlight, IconPattern pattern, int tier)
		{
			//IL_0027: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: 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)
			//IL_0195: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[size * size];
			Color val = default(Color);
			((Color)(ref val))..ctor(0.1f, 0.1f, 0.15f, 1f);
			Color tierBorderColor = GetTierBorderColor(tier);
			int num = size / 2;
			int num2 = 3;
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new Color(0f, 0f, 0f, 0f);
			}
			for (int j = 0; j < size; j++)
			{
				for (int k = 0; k < size; k++)
				{
					float num3 = Vector2.Distance(new Vector2((float)k, (float)j), new Vector2((float)num, (float)num));
					if (num3 <= (float)num && num3 >= (float)(num - num2))
					{
						array[j * size + k] = tierBorderColor;
					}
					else if (num3 < (float)(num - num2))
					{
						array[j * size + k] = val;
					}
				}
			}
			switch (pattern)
			{
			case IconPattern.Circle:
				DrawCircle(array, size, num, main, highlight);
				break;
			case IconPattern.Star:
				DrawStar(array, size, num, main, highlight);
				break;
			case IconPattern.Shield:
				DrawShield(array, size, num, main, highlight);
				break;
			case IconPattern.Spiral:
				DrawSpiral(array, size, num, main, highlight);
				break;
			case IconPattern.Claw:
				DrawClaw(array, size, num, main, highlight);
				break;
			case IconPattern.Diamond:
				DrawDiamond(array, size, num, main, highlight);
				break;
			case IconPattern.Arrow:
				DrawArrow(array, size, num, main, highlight);
				break;
			case IconPattern.Heart:
				DrawHeart(array, size, num, main, highlight);
				break;
			}
			DrawTierDots(array, size, tier, highlight);
			return array;
		}

		private static Color GetTierBorderColor(int tier)
		{
			//IL_002e: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (1 == 0)
			{
			}
			Color result = (Color)(tier switch
			{
				1 => new Color(0.6f, 0.6f, 0.6f), 
				2 => new Color(0.2f, 0.8f, 0.2f), 
				3 => new Color(0.2f, 0.4f, 1f), 
				4 => new Color(0.8f, 0.3f, 0.8f), 
				_ => new Color(1f, 0.8f, 0.2f), 
			});
			if (1 == 0)
			{
			}
			return result;
		}

		private static void DrawCircle(Color[] px, int s, int c, Color m, Color h)
		{
			//IL_0012: 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_003a: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			int num = s / 4;
			for (int i = 0; i < s; i++)
			{
				for (int j = 0; j < s; j++)
				{
					float num2 = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2((float)c, (float)c));
					if (num2 <= (float)num)
					{
						px[i * s + j] = Color.Lerp(h, m, num2 / (float)num);
					}
				}
			}
		}

		private static void DrawStar(Color[] px, int s, int c, Color m, Color h)
		{
			//IL_002b: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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)
			int num = s / 3;
			int num2 = s / 6;
			for (int i = 0; i < s; i++)
			{
				for (int j = 0; j < s; j++)
				{
					float num3 = Mathf.Atan2((float)(i - c), (float)(j - c));
					float num4 = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2((float)c, (float)c));
					float num5 = (num3 + (float)Math.PI) * 5f / (float)Math.PI;
					float num6 = Mathf.Lerp((float)num2, (float)num, (Mathf.Cos(num5) + 1f) / 2f);
					if (num4 <= num6)
					{
						px[i * s + j] = Color.Lerp(h, m, num4 / (float)num);
					}
				}
			}
		}

		private static void DrawShield(Color[] px, int s, int c, Color m, Color h)
		{
			//IL_006a: 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_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)
			int num = s / 3;
			int num2 = s / 2;
			int num3 = c - num2 / 2;
			for (int i = 0; i < s; i++)
			{
				for (int j = 0; j < s; j++)
				{
					int num4 = i - num3;
					if (num4 >= 0 && num4 < num2)
					{
						float num5 = (float)num * (1f - (float)num4 / (float)num2 * 0.6f);
						if ((float)Mathf.Abs(j - c) <= num5)
						{
							px[i * s + j] = Color.Lerp(h, m, (float)Mathf.Abs(j - c) / (float)num);
						}
					}
				}
			}
		}

		private static void DrawSpiral(Color[] px, int s, int c, Color m, Color h)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			int num = s / 3;
			for (int i = 0; i < s; i++)
			{
				for (int j = 0; j < s; j++)
				{
					float num2 = j - c;
					float num3 = i - c;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					float num5 = Mathf.Atan2(num3, num2);
					if (num4 <= (float)num)
					{
						float num6 = (num5 + num4 * 0.3f) % ((float)Math.PI / 2f);
						if (num6 < (float)Math.PI / 4f || num4 < (float)(s / 8))
						{
							px[i * s + j] = Color.Lerp(h, m, num4 / (float)num);
						}
					}
				}
			}
		}

		private static void DrawClaw(Color[] px, int s, int c, Color m, Color h)
		{
			//IL_0065: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			int num = 4;
			int num2 = s / 2;
			int num3 = 8;
			for (int i = -1; i <= 1; i++)
			{
				int num4 = c + i * num3;
				int num5 = c - num2 / 2;
				for (int j = 0; j < num2; j++)
				{
					for (int k = -num / 2; k <= num / 2; k++)
					{
						int num6 = num4 + k + j / 4;
						int num7 = num5 + j;
						if (num6 >= 0 && num6 < s && num7 >= 0 && num7 < s)
						{
							px[num7 * s + num6] = Color.Lerp(h, m, (float)j / (float)num2);
						}
					}
				}
			}
		}

		private static void DrawDiamond(Color[] px, int s, int c, Color m, Color h)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			int num = s / 3;
			for (int i = 0; i < s; i++)
			{
				for (int j = 0; j < s; j++)
				{
					int num2 = Mathf.Abs(j - c) + Mathf.Abs(i - c);
					if (num2 <= num)
					{
						px[i * s + j] = Color.Lerp(h, m, (float)num2 / (float)num);
					}
				}
			}
		}

		private static void DrawArrow(Color[] px, int s, int c, Color m, Color h)
		{
			//IL_0042: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			int num = s / 2;
			int num2 = 4;
			int num3 = s / 4;
			for (int i = c - num / 2; i < c + num / 2 - num3; i++)
			{
				for (int j = c - num2 / 2; j <= c + num2 / 2; j++)
				{
					if (j >= 0 && j < s && i >= 0 && i < s)
					{
						px[i * s + j] = m;
					}
				}
			}
			int num4 = c - num / 2;
			for (int k = 0; k < num3; k++)
			{
				int num5 = num3 - k;
				for (int l = -num5; l <= num5; l++)
				{
					int num6 = c + l;
					int num7 = num4 + k;
					if (num6 >= 0 && num6 < s && num7 >= 0 && num7 < s)
					{
						px[num7 * s + num6] = Color.Lerp(h, m, (float)k / (float)num3);
					}
				}
			}
		}

		private static void DrawHeart(Color[] px, int s, int c, Color m, Color h)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			int num = s / 3;
			for (int i = 0; i < s; i++)
			{
				for (int j = 0; j < s; j++)
				{
					float num2 = (float)(j - c) / (float)num;
					float num3 = (float)(i - c) / (float)num;
					float num4 = Mathf.Pow(num2 * num2 + num3 * num3 - 1f, 3f) - num2 * num2 * num3 * num3 * num3;
					if (num4 < 0f)
					{
						float num5 = Mathf.Sqrt(num2 * num2 + num3 * num3);
						px[i * s + j] = Color.Lerp(h, m, num5);
					}
				}
			}
		}

		private static void DrawTierDots(Color[] px, int s, int tier, Color color)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			int num = 3;
			int num2 = s / 2 - tier * (num + 2) / 2;
			int num3 = s - 8;
			for (int i = 0; i < tier && i < 5; i++)
			{
				int num4 = num2 + i * (num + 2);
				for (int j = 0; j < num; j++)
				{
					for (int k = 0; k < num; k++)
					{
						int num5 = num4 + k;
						int num6 = num3 + j;
						if (num5 >= 0 && num5 < s && num6 >= 0 && num6 < s)
						{
							px[num6 * s + num5] = color;
						}
					}
				}
			}
		}
	}
	public class SkillBuilder
	{
		private string _name;

		private string _description = "";

		private SkillTree _skillTree = SkillTree.Innate;

		private int _tier = 1;

		private int _manaCost = 10;

		private int _cooldown = 0;

		private int _range = 5;

		private string _damageFormula = "";

		private string _dependencySkillName;

		private bool _showInTree = true;

		private Sprite _iconSprite;

		private IconPattern? _iconPattern;

		private Color _iconPrimaryColor = Color.white;

		private Color _iconSecondaryColor = Color.gray;

		private int _iconTier = 1;

		private readonly List<ActionBuilder> _actionBuilders = new List<ActionBuilder>();

		private string _id;

		public SkillBuilder(string name)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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)
			_name = name ?? throw new ArgumentNullException("name");
			_id = name.Replace(" ", "").ToLowerInvariant();
		}

		public SkillBuilder WithId(string id)
		{
			_id = id;
			return this;
		}

		public SkillBuilder WithTree(SkillTree tree)
		{
			_skillTree = tree;
			return this;
		}

		public SkillBuilder WithTier(int tier)
		{
			_tier = Math.Max(0, Math.Min(5, tier));
			return this;
		}

		public SkillBuilder WithDescription(string description)
		{
			_description = description;
			return this;
		}

		public SkillBuilder WithManaCost(int cost)
		{
			_manaCost = cost;
			return this;
		}

		public SkillBuilder WithCooldown(int turns)
		{
			_cooldown = turns;
			return this;
		}

		public SkillBuilder WithRange(int range)
		{
			_range = range;
			return this;
		}

		public SkillBuilder WithDamageFormula(string formula)
		{
			_damageFormula = formula;
			return this;
		}

		public SkillBuilder WithDependency(string skillName)
		{
			_dependencySkillName = skillName;
			return this;
		}

		public SkillBuilder ShowInTree(bool show)
		{
			_showInTree = show;
			return this;
		}

		public SkillBuilder WithIcon(Sprite icon)
		{
			_iconSprite = icon;
			return this;
		}

		public SkillBuilder WithGeneratedIcon(IconPattern pattern, Color primaryColor)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_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)
			_iconPattern = pattern;
			_iconPrimaryColor = primaryColor;
			_iconSecondaryColor = Color.Lerp(primaryColor, Color.white, 0.3f);
			return this;
		}

		public SkillBuilder WithGeneratedIcon(IconPattern pattern, Color primaryColor, Color secondaryColor, int tier = 1)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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)
			_iconPattern = pattern;
			_iconPrimaryColor = primaryColor;
			_iconSecondaryColor = secondaryColor;
			_iconTier = tier;
			return this;
		}

		public SkillBuilder WithAction(Action<ActionBuilder> configure)
		{
			ActionBuilder actionBuilder = new ActionBuilder(_name);
			configure(actionBuilder);
			_actionBuilders.Add(actionBuilder);
			return this;
		}

		public SkillBuilder WithAction(ActionBuilder builder)
		{
			_actionBuilders.Add(builder);
			return this;
		}

		public object Build()
		{
			try
			{
				Type type = ReflectionHelper.FindType("SkillInfo");
				if (type == null)
				{
					ModAPIPlugin.Log.LogError((object)"SkillBuilder: SkillInfo type not found. Is Assembly-CSharp loaded?");
					return null;
				}
				ScriptableObject val = ScriptableObject.CreateInstance(type);
				if ((Object)(object)val == (Object)null)
				{
					ModAPIPlugin.Log.LogError((object)"SkillBuilder: Failed to create SkillInfo instance.");
					return null;
				}
				((Object)val).name = "ModAPI_" + _id;
				ReflectionHelper.SetField(val, "SkillName", _name);
				(AccessTools.Field(type, "Description") ?? AccessTools.Field(type, "SkillDescription"))?.SetValue(val, _description);
				Type type2 = ReflectionHelper.FindType("SkillType");
				if (type2 != null)
				{
					int num = (int)((_skillTree == SkillTree.Innate) ? SkillTree.Innate : _skillTree);
					try
					{
						object value = Enum.ToObject(type2, num);
						ReflectionHelper.SetField(val, "SkillType", value);
					}
					catch
					{
						ReflectionHelper.SetField(val, "SkillType", num);
					}
				}
				ReflectionHelper.SetField(val, "Tier", _tier);
				if (!string.IsNullOrEmpty(_damageFormula))
				{
					FieldInfo fieldInfo = AccessTools.Field(type, "DescriptionExpressions");
					if (fieldInfo != null)
					{
						string[] value2 = new string[1] { _damageFormula };
						fieldInfo.SetValue(val, value2);
					}
				}
				ReflectionHelper.SetField(val, "ManaCost", _manaCost);
				if (_cooldown > 0)
				{
					ReflectionHelper.SetField(val, "CooldownTime", _cooldown);
				}
				ReflectionHelper.SetField(val, "Range", _range);
				FieldInfo fieldInfo2 = AccessTools.Field(type, "Guid");
				if (fieldInfo2 != null)
				{
					Guid guid = GenerateDeterministicGuid(_id);
					fieldInfo2.SetValue(val, guid);
				}
				AccessTools.Field(type, "DontIncludeInTree")?.SetValue(val, !_showInTree);
				if (!string.IsNullOrEmpty(_dependencySkillName))
				{
					((Object)val).name = ((Object)val).name + "__dep:" + _dependencySkillName;
				}
				AccessTools.Field(type, "Disabled")?.SetValue(val, false);
				if (_actionBuilders.Count > 0)
				{
					Type type3 = ReflectionHelper.FindType("ActionInfo");
					if (type3 != null)
					{
						List<object> list = new List<object>();
						foreach (ActionBuilder actionBuilder in _actionBuilders)
						{
							object obj2 = actionBuilder.Build();
							if (obj2 != null)
							{
								list.Add(obj2);
							}
						}
						if (list.Count > 0)
						{
							Array value3 = ReflectionHelper.CreateTypedArray(type3, list);
							AccessTools.Field(type, "ActionsGranted")?.SetValue(val, value3);
						}
					}
				}
				ApplyIcon((Object)(object)val);
				SetEmptyArrayIfNull((Object)(object)val, type, "DisablingSkills", type);
				SetEmptyArrayIfNull((Object)(object)val, type, "SkillsThatReplace", type);
				ModAPIPlugin.Log.LogInfo((object)$"SkillBuilder: Built skill '{_name}' (tree={_skillTree}, tier={_tier}, actions={_actionBuilders.Count})");
				return val;
			}
			catch (Exception arg)
			{
				ModAPIPlugin.Log.LogError((object)$"SkillBuilder: Failed to build '{_name}': {arg}");
				return null;
			}
		}

		private void ApplyIcon(Object skill)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = _iconSprite;
			if ((Object)(object)val == (Object)null && _iconPattern.HasValue)
			{
				val = IconGenerator.Generate(_iconPattern.Value, _iconPrimaryColor, _iconSecondaryColor, _iconTier);
			}
			if ((Object)(object)val != (Object)null)
			{
				ReflectionHelper.SetField(skill, "Icon", val);
			}
		}

		private void SetEmptyArrayIfNull(Object obj, Type elementType, string fieldName, Type arrElementType)
		{
			FieldInfo fieldInfo = AccessTools.Field(elementType