using System;
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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ThuliumAPI")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ThuliumAPI")]
[assembly: AssemblyTitle("ThuliumAPI")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ThuliumAPI;
[BepInPlugin("com.ngeorge.thuliumapi", "Thulium API", "1.1.0")]
public class ThuliumAPI : BaseUnityPlugin
{
public static ManualLogSource Log;
public static Harmony Harmony;
public static bool EnableAssemblyDump { get; private set; }
public static bool DumpClassesOnly { get; private set; }
public static string AssemblyDumpPath => Path.Combine(Path.GetTempPath(), "ThuliumAPI_AssemblyDump.txt");
private void Awake()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Harmony = new Harmony("com.ngeorge.thuliumapi");
Log.LogMessage((object)"Thulium API loading...");
ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableAssemblyDump", false, "Enable assembly dump to console (logs all classes and methods)");
EnableAssemblyDump = val.Value;
ConfigEntry<bool> val2 = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DumpClassesOnly", false, "If enabled, only dump class names without methods");
DumpClassesOnly = val2.Value;
try
{
Hooks.Init();
GameAPI.Init();
ContentRegistry.Init();
if (EnableAssemblyDump || DumpClassesOnly)
{
Log.LogMessage((object)("Assembly dump enabled. Writing to: " + AssemblyDumpPath));
DumpAssembly();
}
Log.LogMessage((object)"Thulium API loaded successfully.");
}
catch (Exception arg)
{
Log.LogError((object)$"API INIT FAILED: {arg}");
}
}
private void DumpAssembly()
{
try
{
Log.LogMessage((object)"=== ASSEMBLY DUMP START ===");
Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "Assembly-CSharp");
if (assembly == null)
{
Log.LogWarning((object)"Assembly-CSharp not found!");
return;
}
List<Type> list = (from t in assembly.GetTypes()
orderby t.Name
select t).ToList();
Log.LogMessage((object)$"Total Classes: {list.Count}");
Log.LogMessage((object)"");
foreach (Type item in list)
{
if (DumpClassesOnly)
{
Log.LogMessage((object)("[" + item.Name + "]"));
continue;
}
List<MethodInfo> declaredMethods = AccessTools.GetDeclaredMethods(item);
if (!declaredMethods.Any())
{
continue;
}
Log.LogMessage((object)("┌─ [" + item.Name + "]"));
foreach (MethodInfo item2 in declaredMethods.OrderBy((MethodInfo m) => m.Name))
{
string text = string.Join(", ", from p in item2.GetParameters()
select p.ParameterType.Name);
Log.LogMessage((object)(" ├─ " + item2.ReturnType.Name + " " + item2.Name + "(" + text + ")"));
}
Log.LogMessage((object)"└──");
}
Log.LogMessage((object)"=== ASSEMBLY DUMP COMPLETE ===");
}
catch (Exception arg)
{
Log.LogError((object)$"Assembly dump failed: {arg}");
}
}
}
public static class Hooks
{
public static event Action OnGameStart;
public static event Action OnGameUpdate;
public static event Action<string> OnSceneLoaded;
public static event Action<KeyCode> OnKeyPressed;
public static event Action<int> OnDifficultyChanged;
public static event Action<UnitPropertyProxy> OnEnemySpawn;
public static event Action<UnitPropertyProxy> OnEnemyDeath;
public static event Action<DamageProxy> OnPlayerDamaged;
public static event Action<DamageProxy> OnEnemyDamaged;
public static event Func<DamageProxy, bool> OnBeforePlayerDamage;
public static event Func<DamageProxy, bool> OnBeforeEnemyDamage;
public static event Func<SpawnRequestProxy, bool> OnBeforeEnemySpawn;
public static event Action<UnitPropertyProxy, float> OnPlayerHealed;
public static void Init()
{
Harmony harmony = ThuliumAPI.Harmony;
ThuliumAPI.Log.LogMessage((object)"Patching GameMgr.Start...");
Patch(harmony, "GameMgr", "Start", null, "GameStart_Postfix");
ThuliumAPI.Log.LogMessage((object)"Patching GameMgr.Update...");
Patch(harmony, "GameMgr", "Update", null, "GameUpdate_Postfix");
ThuliumAPI.Log.LogMessage((object)"Patching DataMgr.SaveSelectedWorldData...");
Patch(harmony, "DataMgr", "SaveSelectedWorldData", null, "DifficultyChanged_Postfix");
ThuliumAPI.Log.LogMessage((object)"Patching UnitProperty.TakeDamage...");
Type type = AccessTools.TypeByName("UnitProperty");
PatchMethod(harmony, type, "TakeDamage", new Type[3]
{
typeof(float),
AccessTools.TypeByName("AttackerType"),
AccessTools.TypeByName("TakeDamageInfo")
}, "TakeDamage_Prefix", "TakeDamage_Postfix");
ThuliumAPI.Log.LogMessage((object)"Patching UnitProperty.HPRecovery...");
PatchMethod(harmony, type, "HPRecovery", null, null, "HPRecovery_Postfix");
ThuliumAPI.Log.LogMessage((object)"Patching UnitProperty.AnnouncedDeath...");
PatchMethod(harmony, type, "AnnouncedDeath", null, null, "AnnouncedDeath_Postfix");
ThuliumAPI.Log.LogMessage((object)"Patching BattleMgr.SpawnUnit...");
PatchByName(harmony, "BattleMgr", "SpawnUnit", "SpawnUnit_Prefix", "SpawnUnit_Postfix");
ThuliumAPI.Log.LogMessage((object)"Patching SceneManager.Internal_SceneLoaded...");
MethodInfo methodInfo = AccessTools.Method("UnityEngine.SceneManagement.SceneManager:Internal_SceneLoaded", (Type[])null, (Type[])null);
if (methodInfo != null)
{
harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, HM("SceneLoaded_Postfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
ThuliumAPI.Log.LogMessage((object)"✓ All hooks initialized successfully!");
}
private static void Patch(Harmony h, string type, string method, string prefix = null, string postfix = null)
{
MethodInfo methodInfo = AccessTools.Method(type + ":" + method, (Type[])null, (Type[])null);
if (methodInfo == null)
{
ThuliumAPI.Log.LogWarning((object)("Hook target not found: " + type + "." + method));
}
else
{
h.Patch((MethodBase)methodInfo, (prefix != null) ? HM(prefix) : null, (postfix != null) ? HM(postfix) : null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
private static void PatchMethod(Harmony h, Type type, string method, Type[] args, string prefix = null, string postfix = null)
{
MethodInfo methodInfo = ((args != null) ? AccessTools.Method(type, method, args, (Type[])null) : AccessTools.Method(type, method, (Type[])null, (Type[])null));
if (methodInfo == null)
{
ThuliumAPI.Log.LogWarning((object)("Hook target not found: " + type?.Name + "." + method));
}
else
{
h.Patch((MethodBase)methodInfo, (prefix != null) ? HM(prefix) : null, (postfix != null) ? HM(postfix) : null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
private static void PatchByName(Harmony h, string type, string method, string prefix = null, string postfix = null)
{
Type type2 = AccessTools.TypeByName(type);
if (type2 == null)
{
ThuliumAPI.Log.LogWarning((object)("Type not found: " + type));
return;
}
foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type2))
{
if (!(declaredMethod.Name != method))
{
h.Patch((MethodBase)declaredMethod, (prefix != null) ? HM(prefix) : null, (postfix != null) ? HM(postfix) : null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
}
private static HarmonyMethod HM(string name)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
return new HarmonyMethod(typeof(Hooks), name, (Type[])null);
}
private static void GameStart_Postfix()
{
Hooks.OnGameStart?.Invoke();
}
private static void GameUpdate_Postfix()
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
Hooks.OnGameUpdate?.Invoke();
foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
{
if (Input.GetKeyDown(value))
{
Hooks.OnKeyPressed?.Invoke(value);
}
}
}
private static void DifficultyChanged_Postfix()
{
try
{
Hooks.OnDifficultyChanged?.Invoke(GameAPI.GetDifficulty());
}
catch
{
}
}
private static void SceneLoaded_Postfix(Scene scene)
{
Hooks.OnSceneLoaded?.Invoke(((Scene)(ref scene)).name);
}
private static bool TakeDamage_Prefix(object __instance, ref float damage, object info)
{
DamageProxy damageProxy = new DamageProxy(__instance, damage, info);
Component val = (Component)((__instance is Component) ? __instance : null);
Func<DamageProxy, bool> func = (((Object)(object)val != (Object)null && val.CompareTag("Player")) ? Hooks.OnBeforePlayerDamage : Hooks.OnBeforeEnemyDamage);
if (func != null)
{
Delegate[] invocationList = func.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++)
{
Func<DamageProxy, bool> func2 = (Func<DamageProxy, bool>)invocationList[i];
if (!func2(damageProxy))
{
return false;
}
}
damage = damageProxy.Damage;
}
return true;
}
private static void TakeDamage_Postfix(object __instance, float damage, object info)
{
DamageProxy obj = new DamageProxy(__instance, damage, info);
Component val = (Component)((__instance is Component) ? __instance : null);
if ((Object)(object)val != (Object)null && val.CompareTag("Player"))
{
Hooks.OnPlayerDamaged?.Invoke(obj);
}
else
{
Hooks.OnEnemyDamaged?.Invoke(obj);
}
}
private static void HPRecovery_Postfix(object __instance, float hp)
{
UnitPropertyProxy arg = new UnitPropertyProxy(__instance);
Hooks.OnPlayerHealed?.Invoke(arg, hp);
}
private static void AnnouncedDeath_Postfix(object __instance)
{
object obj = ((__instance is Component) ? __instance : null);
GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
if ((Object)(object)val != (Object)null && !val.CompareTag("Player"))
{
Hooks.OnEnemyDeath?.Invoke(new UnitPropertyProxy(__instance));
}
}
private static bool SpawnUnit_Prefix(object __instance, ref object unitConfig, ref Vector3 pos)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
SpawnRequestProxy spawnRequestProxy = new SpawnRequestProxy(unitConfig, pos);
if (Hooks.OnBeforeEnemySpawn != null)
{
Delegate[] invocationList = Hooks.OnBeforeEnemySpawn.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++)
{
Func<SpawnRequestProxy, bool> func = (Func<SpawnRequestProxy, bool>)invocationList[i];
if (!func(spawnRequestProxy))
{
return false;
}
}
pos = spawnRequestProxy.Position;
}
return true;
}
private static void SpawnUnit_Postfix(object __instance, GameObject __result)
{
if ((Object)(object)__result != (Object)null)
{
Hooks.OnEnemySpawn?.Invoke(new UnitPropertyProxy(__result.GetComponent<Component>()));
}
}
}
public sealed class UnitPropertyProxy
{
private static readonly FieldInfo _f_currentHP = AccessTools.Field(AccessTools.TypeByName("UnitProperty"), "currentHP");
private static readonly FieldInfo _f_maxHP = AccessTools.Field(AccessTools.TypeByName("UnitConfig"), "maxHP");
private static readonly PropertyInfo _p_isUnitDead = AccessTools.Property(AccessTools.TypeByName("UnitProperty"), "isUnitDead");
private static readonly PropertyInfo _p_isInvincible = AccessTools.Property(AccessTools.TypeByName("UnitProperty"), "IsInvincible");
private static readonly PropertyInfo _p_unitCfg = AccessTools.Property(AccessTools.TypeByName("UnitProperty"), "UnitCfg");
private static readonly FieldInfo _f_invincibleCtr = AccessTools.Field(AccessTools.TypeByName("UnitProperty"), "invincibleCounter");
private readonly object _raw;
public float CurrentHP
{
get
{
return (_raw != null) ? ((float)(_f_currentHP?.GetValue(_raw) ?? ((object)0f))) : 0f;
}
set
{
_f_currentHP?.SetValue(_raw, value);
}
}
public float MaxHP
{
get
{
object obj = _p_unitCfg?.GetValue(_raw);
return (obj != null) ? ((float)(_f_maxHP?.GetValue(obj) ?? ((object)0f))) : 0f;
}
}
public bool IsDead => (bool)(_p_isUnitDead?.GetValue(_raw) ?? ((object)true));
public bool IsInvincible => (bool)(_p_isInvincible?.GetValue(_raw) ?? ((object)false));
public GameObject GameObject
{
get
{
object raw = _raw;
object obj = ((raw is Component) ? raw : null);
return (obj != null) ? ((Component)obj).gameObject : null;
}
}
public Transform Transform
{
get
{
object raw = _raw;
object obj = ((raw is Component) ? raw : null);
return (obj != null) ? ((Component)obj).transform : null;
}
}
public UnitPropertyProxy(object rawUnitProperty)
{
_raw = rawUnitProperty;
}
public void SetInvincible(bool on)
{
int num = (int)(_f_invincibleCtr?.GetValue(_raw) ?? ((object)0));
_f_invincibleCtr?.SetValue(_raw, on ? Mathf.Max(1, num) : 0);
}
public override string ToString()
{
return $"UnitPropertyProxy(HP={CurrentHP}/{MaxHP}, dead={IsDead})";
}
}
public sealed class DamageProxy
{
private static readonly Type _t = AccessTools.TypeByName("TakeDamageInfo");
private static readonly FieldInfo _f_damage = AccessTools.Field(_t, "damage");
private static readonly FieldInfo _f_isCrit = AccessTools.Field(_t, "isCriticalDamage");
private static readonly FieldInfo _f_immune = AccessTools.Field(_t, "immuneDamage");
private static readonly FieldInfo _f_isPerc = AccessTools.Field(_t, "isPercentageDamage");
private static readonly FieldInfo _f_trap = AccessTools.Field(_t, "isTrapDamage");
private static readonly FieldInfo _f_kb = AccessTools.Field(_t, "knockbackForce");
private static readonly FieldInfo _f_attPpt = AccessTools.Field(_t, "attackerPpt");
private static readonly FieldInfo _f_hitPpt = AccessTools.Field(_t, "beHitPpt");
private readonly object _info;
public UnitPropertyProxy Victim { get; }
public float Damage
{
get
{
return (_info != null) ? ((float)(_f_damage?.GetValue(_info) ?? ((object)0f))) : 0f;
}
set
{
if (_info != null)
{
_f_damage?.SetValue(_info, value);
}
}
}
public bool IsCritical
{
get
{
return _info != null && (bool)(_f_isCrit?.GetValue(_info) ?? ((object)false));
}
set
{
if (_info != null)
{
_f_isCrit?.SetValue(_info, value);
}
}
}
public bool ImmuneToThisHit
{
get
{
return _info != null && (bool)(_f_immune?.GetValue(_info) ?? ((object)false));
}
set
{
if (_info != null)
{
_f_immune?.SetValue(_info, value);
}
}
}
public bool IsPercentageDamage => _info != null && (bool)(_f_isPerc?.GetValue(_info) ?? ((object)false));
public bool IsTrapDamage => _info != null && (bool)(_f_trap?.GetValue(_info) ?? ((object)false));
public Vector3 KnockbackForce
{
get
{
//IL_0008: 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_002a: Unknown result type (might be due to invalid IL or missing references)
return (Vector3)((_info != null) ? ((Vector3)(_f_kb?.GetValue(_info) ?? ((object)Vector3.zero))) : Vector3.zero);
}
set
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
if (_info != null)
{
_f_kb?.SetValue(_info, value);
}
}
}
public DamageProxy(object rawUnitProperty, float damage, object rawInfo)
{
Victim = new UnitPropertyProxy(rawUnitProperty);
_info = rawInfo;
if (rawInfo != null && _f_damage != null)
{
_f_damage.SetValue(rawInfo, damage);
}
}
public void SuppressKnockback()
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
KnockbackForce = Vector3.zero;
}
public override string ToString()
{
return $"DamageProxy(dmg={Damage}, crit={IsCritical}, immune={ImmuneToThisHit})";
}
}
public sealed class SpawnRequestProxy
{
private static readonly FieldInfo _f_id = AccessTools.Field(AccessTools.TypeByName("UnitConfig"), "id");
private readonly object _unitCfg;
public int UnitID => (_unitCfg != null) ? ((int)(_f_id?.GetValue(_unitCfg) ?? ((object)(-1)))) : (-1);
public Vector3 Position { get; set; }
public SpawnRequestProxy(object unitConfig, Vector3 pos)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
_unitCfg = unitConfig;
Position = pos;
}
public override string ToString()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
return $"SpawnRequest(id={UnitID}, pos={Position})";
}
}
public static class GameAPI
{
private static Type _tDataMgr;
private static Type _tWorldData;
private static Type _tUnitProperty;
private static Type _tBattleMgr;
private static Type _tPlayerMgr;
private static FieldInfo _f_selectedWorldData;
private static FieldInfo _f_selectedDifficulty;
private static PropertyInfo _p_battleMgrInst;
private static PropertyInfo _p_playerMgrInst;
private static PropertyInfo _p_gameMgrInst;
private static MethodInfo _m_hpRecovery;
private static MethodInfo _m_announcedDeath;
private static GameObject _playerCache;
public static object BattleMgr => _p_battleMgrInst?.GetValue(null);
public static object PlayerMgr => _p_playerMgrInst?.GetValue(null);
public static object GameMgr => _p_gameMgrInst?.GetValue(null);
public static void Init()
{
_tDataMgr = AccessTools.TypeByName("DataMgr");
_tWorldData = AccessTools.TypeByName("WorldData");
_tUnitProperty = AccessTools.TypeByName("UnitProperty");
_tBattleMgr = AccessTools.TypeByName("BattleMgr");
_tPlayerMgr = AccessTools.TypeByName("PlayerMgr");
_f_selectedWorldData = AccessTools.Field(_tDataMgr, "selectedWorldData");
_f_selectedDifficulty = AccessTools.Field(_tWorldData, "selectedDifficulty");
_p_battleMgrInst = AccessTools.Property(_tBattleMgr, "Inst");
_p_playerMgrInst = AccessTools.Property(_tPlayerMgr, "Inst");
_p_gameMgrInst = AccessTools.Property(AccessTools.TypeByName("GameMgr"), "Inst");
_m_hpRecovery = AccessTools.Method(_tUnitProperty, "HPRecovery", (Type[])null, (Type[])null);
_m_announcedDeath = AccessTools.Method(_tUnitProperty, "AnnouncedDeath", (Type[])null, (Type[])null);
ThuliumAPI.Log.LogMessage((object)"GameAPI ready.");
}
public static object GetWorldData()
{
return _f_selectedWorldData?.GetValue(null);
}
public static int GetDifficulty()
{
object worldData = GetWorldData();
return (worldData != null) ? ((int)(_f_selectedDifficulty?.GetValue(worldData) ?? ((object)0))) : 0;
}
public static void SetDifficulty(int difficulty)
{
object worldData = GetWorldData();
if (worldData != null)
{
_f_selectedDifficulty?.SetValue(worldData, difficulty);
}
}
public static GameObject GetPlayer()
{
if ((Object)(object)_playerCache == (Object)null)
{
_playerCache = GameObject.FindWithTag("Player");
}
return _playerCache;
}
public static void InvalidatePlayerCache()
{
_playerCache = null;
}
public static UnitPropertyProxy GetPlayerProperty()
{
GameObject player = GetPlayer();
Component val = ((player != null) ? player.GetComponent(AccessTools.TypeByName("UnitProperty")) : null);
return ((Object)(object)val != (Object)null) ? new UnitPropertyProxy(val) : null;
}
public static Vector3 GetPlayerPosition()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
GameObject player = GetPlayer();
return (player != null) ? player.transform.position : Vector3.zero;
}
public static void TeleportPlayer(Vector3 pos)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
GameObject player = GetPlayer();
if ((Object)(object)player != (Object)null)
{
player.transform.position = pos;
}
}
public static void HealPlayer(float amount)
{
Component playerComponent = GetPlayerComponent();
if ((Object)(object)playerComponent != (Object)null)
{
_m_hpRecovery?.Invoke(playerComponent, new object[2] { amount, true });
}
}
public static void SetPlayerHP(float hp)
{
UnitPropertyProxy playerProperty = GetPlayerProperty();
if (playerProperty != null)
{
playerProperty.CurrentHP = hp;
}
}
public static void KillPlayer()
{
Component playerComponent = GetPlayerComponent();
if ((Object)(object)playerComponent != (Object)null)
{
_m_announcedDeath?.Invoke(playerComponent, new object[2] { null, true });
}
}
private static Component GetPlayerComponent()
{
GameObject player = GetPlayer();
if ((Object)(object)player == (Object)null)
{
return null;
}
return player.GetComponent(_tUnitProperty);
}
public static GameObject[] GetAllEnemies()
{
return GameObject.FindGameObjectsWithTag("Enemy");
}
public static UnitPropertyProxy[] GetAllEnemyProperties()
{
GameObject[] allEnemies = GetAllEnemies();
UnitPropertyProxy[] array = new UnitPropertyProxy[allEnemies.Length];
for (int i = 0; i < allEnemies.Length; i++)
{
Component component = allEnemies[i].GetComponent(_tUnitProperty);
array[i] = new UnitPropertyProxy(component);
}
return array;
}
public static void KillAllEnemies()
{
GameObject[] allEnemies = GetAllEnemies();
foreach (GameObject val in allEnemies)
{
Object.Destroy((Object)(object)val);
}
}
public static void KillAllEnemiesViaGame()
{
UnitPropertyProxy[] allEnemyProperties = GetAllEnemyProperties();
foreach (UnitPropertyProxy unitPropertyProxy in allEnemyProperties)
{
GameObject gameObject = unitPropertyProxy.GameObject;
Component val = ((gameObject != null) ? gameObject.GetComponent(_tUnitProperty) : null);
if ((Object)(object)val != (Object)null)
{
_m_announcedDeath?.Invoke(val, new object[2] { null, true });
}
}
}
}
public static class ContentRegistry
{
public delegate float DamageModifier(DamageProxy dmg);
public delegate bool SpawnFilter(SpawnRequestProxy req);
private static readonly List<DamageModifier> _playerDamageMods = new List<DamageModifier>();
private static readonly List<DamageModifier> _enemyDamageMods = new List<DamageModifier>();
private static readonly List<SpawnFilter> _spawnFilters = new List<SpawnFilter>();
private static readonly Dictionary<int, List<Action<UnitPropertyProxy>>> _deathCallbacks = new Dictionary<int, List<Action<UnitPropertyProxy>>>();
private static readonly Dictionary<string, GameObject> _customPrefabs = new Dictionary<string, GameObject>();
public static void Init()
{
Hooks.OnBeforePlayerDamage += delegate(DamageProxy proxy)
{
foreach (DamageModifier playerDamageMod in _playerDamageMods)
{
proxy.Damage = playerDamageMod(proxy);
}
return true;
};
Hooks.OnBeforeEnemyDamage += delegate(DamageProxy proxy)
{
foreach (DamageModifier enemyDamageMod in _enemyDamageMods)
{
proxy.Damage = enemyDamageMod(proxy);
}
return true;
};
Hooks.OnBeforeEnemySpawn += delegate(SpawnRequestProxy proxy)
{
foreach (SpawnFilter spawnFilter in _spawnFilters)
{
if (!spawnFilter(proxy))
{
return false;
}
}
return true;
};
Hooks.OnEnemyDeath += delegate(UnitPropertyProxy ppt)
{
if (_deathCallbacks.TryGetValue(ppt.GetInstanceID_Safe(), out var value))
{
foreach (Action<UnitPropertyProxy> item in value)
{
item(ppt);
}
}
};
ThuliumAPI.Log.LogMessage((object)"ContentRegistry ready.");
}
public static void RegisterPlayerDamageModifier(DamageModifier mod)
{
_playerDamageMods.Add(mod);
}
public static void RegisterEnemyDamageModifier(DamageModifier mod)
{
_enemyDamageMods.Add(mod);
}
public static void RegisterSpawnFilter(SpawnFilter filter)
{
_spawnFilters.Add(filter);
}
public static void OnUnitDeath(int unitID, Action<UnitPropertyProxy> cb)
{
if (!_deathCallbacks.ContainsKey(unitID))
{
_deathCallbacks[unitID] = new List<Action<UnitPropertyProxy>>();
}
_deathCallbacks[unitID].Add(cb);
}
public static void RegisterPrefab(string key, GameObject prefab)
{
if ((Object)(object)prefab == (Object)null)
{
throw new ArgumentNullException("prefab");
}
_customPrefabs[key] = prefab;
ThuliumAPI.Log.LogMessage((object)("[ContentRegistry] Registered prefab '" + key + "'"));
}
public static GameObject SpawnRegisteredPrefab(string key, Vector3 position, Quaternion? rotation = null)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
if (!_customPrefabs.TryGetValue(key, out var value))
{
ThuliumAPI.Log.LogWarning((object)("[ContentRegistry] No prefab registered with key '" + key + "'"));
return null;
}
return Object.Instantiate<GameObject>(value, position, (Quaternion)(((??)rotation) ?? Quaternion.identity));
}
public static bool HasPrefab(string key)
{
return _customPrefabs.ContainsKey(key);
}
}
public static class Utils
{
public static void Print(object msg)
{
ThuliumAPI.Log.LogMessage(msg);
}
public static void Warn(object msg)
{
ThuliumAPI.Log.LogWarning(msg);
}
public static void Error(object msg)
{
ThuliumAPI.Log.LogError(msg);
}
public static T GetField<T>(object obj, string field)
{
FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), field);
return (fieldInfo != null) ? ((T)fieldInfo.GetValue(obj)) : default(T);
}
public static void SetField(object obj, string field, object value)
{
AccessTools.Field(obj.GetType(), field)?.SetValue(obj, value);
}
public static object Call(object obj, string method, params object[] args)
{
return AccessTools.Method(obj.GetType(), method, (Type[])null, (Type[])null)?.Invoke(obj, args);
}
public static void SetTimeScale(float scale)
{
Time.timeScale = scale;
}
public static void PauseGame()
{
Time.timeScale = 0f;
}
public static void ResumeGame()
{
Time.timeScale = 1f;
}
public static GameObject SpawnPrefab(GameObject prefab, Vector3 pos, Quaternion? rot = null)
{
//IL_0001: 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_000d: Unknown result type (might be due to invalid IL or missing references)
return Object.Instantiate<GameObject>(prefab, pos, (Quaternion)(((??)rot) ?? Quaternion.identity));
}
public static GameObject[] GetAllEnemies()
{
return GameObject.FindGameObjectsWithTag("Enemy");
}
public static Component GetMainCanvas()
{
Type type = AccessTools.TypeByName("UnityEngine.Canvas");
return (Component)((type != null) ? /*isinst with value type is only supported in some contexts*/: null);
}
}
internal static class UnitPropertyProxyExtensions
{
public static int GetInstanceID_Safe(this UnitPropertyProxy proxy)
{
GameObject val = proxy?.GameObject;
return ((Object)(object)val != (Object)null) ? ((Object)val).GetInstanceID() : (-1);
}
}