Decompiled source of StolenRealmModAPI v0.2.0
plugins/StolenRealmModAPI.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
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