Decompiled source of Crimson Clicky Illusions v1.0.4
BoneLordItems.dll
Decompiled 5 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; 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: AssemblyTitle("BoneLordItems")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BoneLordItems")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("cf5606d8-438e-4729-947c-e892ebfe446e")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace BoneLordItems; [BepInPlugin("com.yourname.bonelorditems", "Bone Lord Items", "1.5.20")] public class Plugin : BaseUnityPlugin { private static bool injected = false; private static int attempts = 0; private static float nextTryAt = 0f; private const float RetryInterval = 1f; private const int MaxAttempts = 300; private const string ID_SOUL_ECHO = "20832306"; private const string ID_NEOPHYTE = "29042550"; private const string ID_FLUORITE = "57247840"; private const string ID_PLAIN = "14265295"; private const string HYDRATED_ID = "20309875"; private const string ID_CELESTIAL_SMITE = "11565860"; private const string ID_PAGE1 = "11021645"; private const string ID_PAGE2 = "271648"; private const string ORIGINAL_CAPTAIN = "A Skeleton Captain"; private const string FABLED_CAPTAIN = "Fabled Skeletal Captain"; private const string ORIGINAL_LAZALITH = "Lazalith, Soldier of Sivakaya"; private const string FABLED_LAZALITH = "Fabled Lazalith, Demon of Sivakaya"; private const string ORIGINAL_PEON = "Peon"; private const string FABLED_PEON = "The Fabled Crimson Peon"; private const string ORIGINAL_GUARD = "Spectral King's Guard"; private const string FABLED_GUARD = "Fabled Spectral King's Guard"; private const float FABLED_CHANCE = 0.15f; private const float GUARD_FABLED_CHANCE = 0.5f; private const float STAT_MULTIPLIER = 1.5f; private const int LEVEL_BONUS = 4; private const int FORCED_HP = 3048; private const int PEON_HP = 30000; private const float TARGET_SCALE = 1.8f; private const float PEON_SCALE = 2.5f; private const float LAZALITH_SCALE = 4f; private const int LAZALITH_LEVEL = 25; private const int PEON_LEVEL = 28; private const int GUARD_LEVEL = 23; private const float PEON_RESPAWN_SECONDS = 600f; private const float FABLED_MSG_INTERVAL = 180f; private const float WORLD_SCAN_INTERVAL = 2f; private static object cloneSkeleton; private static object cloneKnight; private static object cloneHero; private static object cloneTorment; private static object talismanItemRef; private static object visageItemRef; private static object amuletItemRef; private static object sigilItemRef; private static object celestialSmiteRef; private static object page1Ref; private static object page2Ref; private static readonly HashSet<int> processedCaptains = new HashSet<int>(); private static readonly HashSet<int> processedLazalith = new HashSet<int>(); private static readonly HashSet<int> processedGuards = new HashSet<int>(); private static bool fireFxSpawned = false; private static float nextFireTry = 0f; private static int fireFxFailLogs = 0; private static string lastScene = ""; private static bool bonepitsMessageShown = false; private static bool braxMessageShown = false; private static float nextPeonSpawnAt = 0f; private static float nextWorldScanAt = 0f; private static float nextCaptainMsgAt = 0f; private static float nextLazalithMsgAt = 0f; private static float nextPeonMsgAt = 0f; private static float nextGuardMsgAt = 0f; private static GameObject cachedFabledCaptain; private static GameObject cachedFabledLazalith; private static GameObject cachedFabledPeon; private static GameObject cachedFabledGuard; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) new Harmony("com.yourname.bonelorditems").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Bone Lord Items 1.5.20 – share build (no Reaper override; Guard 50%)"); nextTryAt = Time.unscaledTime + 3f; } private void Update() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); string text = ((Scene)(ref activeScene)).name ?? ""; if (text != lastScene) { lastScene = text; bonepitsMessageShown = false; braxMessageShown = false; fireFxSpawned = false; nextFireTry = 0f; fireFxFailLogs = 0; nextPeonSpawnAt = 0f; nextCaptainMsgAt = 0f; nextLazalithMsgAt = 0f; nextPeonMsgAt = 0f; nextGuardMsgAt = 0f; nextWorldScanAt = 0f; processedCaptains.Clear(); processedLazalith.Clear(); processedGuards.Clear(); cachedFabledCaptain = null; cachedFabledLazalith = null; cachedFabledPeon = null; cachedFabledGuard = null; } bool flag = text.IndexOf("Bonepit", StringComparison.OrdinalIgnoreCase) >= 0; bool flag2 = text.IndexOf("Braxonian", StringComparison.OrdinalIgnoreCase) >= 0; bool flag3 = text.IndexOf("Undercity", StringComparison.OrdinalIgnoreCase) >= 0; bool flag4 = text.IndexOf("SaltedStrand", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Salted Strand", StringComparison.OrdinalIgnoreCase) >= 0; if (!bonepitsMessageShown && flag) { bonepitsMessageShown = true; ShowBonepitsSenseMessage(); } if (flag2) { if (!braxMessageShown) { braxMessageShown = true; SendYellow("*** THE OBELISK IN BRAXONIAN DESERT EMITS A CRIMSON AURA, DISCOURAGING ALL BUT THE MOST HARDY ADVENTURERS ***"); } if (!fireFxSpawned && Time.time >= nextFireTry) { nextFireTry = Time.time + 5f; if (TrySpawnFireFx()) { fireFxSpawned = true; Debug.Log((object)"[BoneLordItems] ★ FX_Fire_01 (20,1,20) + FX_Fire_Embers_01 (10,10,10) spawned"); } else if (fireFxFailLogs < 3) { fireFxFailLogs++; Debug.Log((object)("[BoneLordItems] Fire FX not in memory yet – retry " + fireFxFailLogs + "/3")); } } ProcessCrimsonPeon(); } ProcessFabledMessageTimersCached(); if (!injected && Time.unscaledTime >= nextTryAt) { nextTryAt = Time.unscaledTime + 1f; if (LooksLikeGameDataPresent()) { attempts++; if (attempts > 300) { if (attempts == 301) { ((BaseUnityPlugin)this).Logger.LogError((object)("[BoneLordItems] Gave up after " + 300 + " attempts.")); } } else { try { int num = InjectEverything(); if (num > 0) { injected = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[BoneLordItems] === SUCCESS – " + num + " objects ===")); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[BoneLordItems] " + ex)); } } } } if (Time.time >= nextWorldScanAt) { nextWorldScanAt = Time.time + 2f; if (flag || flag2 || flag3 || flag4) { RunCombinedWorldScan(flag, flag2, flag3, flag4); } } } private static void RunCombinedWorldScan(bool inBonepits, bool inBrax, bool inUndercity, bool inSaltedStrand) { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cachedFabledCaptain != (Object)null && !Object.op_Implicit((Object)(object)cachedFabledCaptain)) { cachedFabledCaptain = null; } if ((Object)(object)cachedFabledLazalith != (Object)null && !Object.op_Implicit((Object)(object)cachedFabledLazalith)) { cachedFabledLazalith = null; } if ((Object)(object)cachedFabledPeon != (Object)null && !Object.op_Implicit((Object)(object)cachedFabledPeon)) { cachedFabledPeon = null; } if ((Object)(object)cachedFabledGuard != (Object)null && !Object.op_Implicit((Object)(object)cachedFabledGuard)) { cachedFabledGuard = null; } GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null || !val.activeInHierarchy) { continue; } Scene scene = val.scene; if (!string.IsNullOrEmpty(((Scene)(ref scene)).name)) { string name = ((Object)val).name; if (inBonepits && (name == "A Skeleton Captain" || name == "Fabled Skeletal Captain")) { HandleCaptain(val); } else if (inSaltedStrand && (name == "Lazalith, Soldier of Sivakaya" || name == "Fabled Lazalith, Demon of Sivakaya")) { HandleLazalith(val); } else if (inBrax && name == "The Fabled Crimson Peon") { cachedFabledPeon = val; } else if (inUndercity && name.IndexOf("Spectral King's Guard", StringComparison.OrdinalIgnoreCase) >= 0) { HandleGuard(val); } } } } private static void HandleCaptain(GameObject go) { int instanceID = ((Object)go).GetInstanceID(); if (processedCaptains.Contains(instanceID)) { if (((Object)go).name == "Fabled Skeletal Captain") { cachedFabledCaptain = go; } return; } processedCaptains.Add(instanceID); if (((Object)go).name == "Fabled Skeletal Captain") { ForceAllNameFields(go, "Fabled Skeletal Captain"); ForceNameplateText(go, "Fabled Skeletal Captain"); ScaleStats(go); ApplyScale(go, 1.8f); InjectCelestialSmite(go); InjectGuaranteed(go, ref page1Ref, "11021645", "Pg.1"); cachedFabledCaptain = go; if (nextCaptainMsgAt <= 0f) { nextCaptainMsgAt = Time.time + 180f; } } else if (Random.value > 0.15f) { ShowNormalCaptainMessage(); } else { ((Object)go).name = "Fabled Skeletal Captain"; ForceAllNameFields(go, "Fabled Skeletal Captain"); ForceNameplateText(go, "Fabled Skeletal Captain"); ScaleStats(go); ApplyScale(go, 1.8f); InjectTalismanIntoDrops(go); InjectCelestialSmite(go); InjectGuaranteed(go, ref page1Ref, "11021645", "Pg.1"); ShowFabledCaptainMessage(); nextCaptainMsgAt = Time.time + 180f; cachedFabledCaptain = go; Debug.Log((object)"[BoneLordItems] ★ Captain → Fabled"); } } private static void HandleLazalith(GameObject go) { int instanceID = ((Object)go).GetInstanceID(); if (processedLazalith.Contains(instanceID)) { if (((Object)go).name == "Fabled Lazalith, Demon of Sivakaya") { cachedFabledLazalith = go; } return; } processedLazalith.Add(instanceID); if (((Object)go).name == "Fabled Lazalith, Demon of Sivakaya") { ForceAllNameFields(go, "Fabled Lazalith, Demon of Sivakaya"); ForceNameplateText(go, "Fabled Lazalith, Demon of Sivakaya"); ScaleStats(go); ForceLevel(go, 25); ApplyScale(go, 4f); InjectGuaranteed(go, ref page2Ref, "271648", "Pg.2"); cachedFabledLazalith = go; if (nextLazalithMsgAt <= 0f) { nextLazalithMsgAt = Time.time + 180f; } } else if (!(Random.value > 0.15f)) { ((Object)go).name = "Fabled Lazalith, Demon of Sivakaya"; ForceAllNameFields(go, "Fabled Lazalith, Demon of Sivakaya"); ForceNameplateText(go, "Fabled Lazalith, Demon of Sivakaya"); ScaleStats(go); ForceLevel(go, 25); ApplyScale(go, 4f); InjectVisageIntoDrops(go); InjectGuaranteed(go, ref page2Ref, "271648", "Pg.2"); ShowFabledLazalithMessage(); nextLazalithMsgAt = Time.time + 180f; cachedFabledLazalith = go; Debug.Log((object)"[BoneLordItems] ★ Lazalith → Fabled (Lv25, scale 4) [SaltedStrand]"); } } private static void HandleGuard(GameObject go) { if (((Object)go).name.StartsWith("Fabled") || ((Object)go).name == "Fabled Spectral King's Guard") { cachedFabledGuard = go; return; } int instanceID = ((Object)go).GetInstanceID(); if (!processedGuards.Contains(instanceID)) { processedGuards.Add(instanceID); if (!(Random.value > 0.5f)) { ((Object)go).name = "Fabled Spectral King's Guard"; ForceAllNameFields(go, "Fabled Spectral King's Guard"); ForceNameplateText(go, "Fabled Spectral King's Guard"); ScaleStats(go); ForceLevel(go, 23); ApplyScale(go, 1.8f); InjectSigilIntoDrops(go); ShowFabledGuardMessage(); nextGuardMsgAt = Time.time + 180f; cachedFabledGuard = go; Debug.Log((object)"[BoneLordItems] ★ Spectral Guard → Fabled (Lv23, 50%) [Undercity]"); } } } private static void ProcessFabledMessageTimersCached() { if (Time.frameCount % 180 == 0) { if (IsCachedAlive(ref cachedFabledCaptain) && Time.time >= nextCaptainMsgAt) { ShowFabledCaptainMessage(); nextCaptainMsgAt = Time.time + 180f; } if (IsCachedAlive(ref cachedFabledLazalith) && Time.time >= nextLazalithMsgAt) { ShowFabledLazalithMessage(); nextLazalithMsgAt = Time.time + 180f; } if (IsCachedAlive(ref cachedFabledPeon) && Time.time >= nextPeonMsgAt) { SendYellow("*** FABLED CRIMSON PEON'S BLOODLUST RISES AS HE YEARNS TO PAINT HIS BONES IN THE BLOOD OF ANY WHO DARE TO CHALLENGE HIS DOMAIN ***"); nextPeonMsgAt = Time.time + 180f; } if (IsCachedAlive(ref cachedFabledGuard) && Time.time >= nextGuardMsgAt) { ShowFabledGuardMessage(); nextGuardMsgAt = Time.time + 180f; } } } private static bool IsCachedAlive(ref GameObject go) { if ((Object)(object)go == (Object)null) { return false; } if (!Object.op_Implicit((Object)(object)go)) { go = null; return false; } if (!go.activeInHierarchy) { go = null; return false; } return true; } private static bool TrySpawnFireFx() { //IL_001c: 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_005c: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) Vector3 pos = default(Vector3); ((Vector3)(ref pos))..ctor(565.3357f, 24.5367f, 359.0786f); GameObject val = SpawnProp("FX_Fire_01", pos); if ((Object)(object)val == (Object)null) { return false; } val.transform.localScale = new Vector3(20f, 1f, 20f); val.transform.rotation = Quaternion.identity; GameObject val2 = SpawnProp("FX_Fire_Embers_01", pos); if ((Object)(object)val2 != (Object)null) { val2.transform.localScale = new Vector3(10f, 10f, 10f); val2.transform.rotation = Quaternion.Euler(270f, 0f, 0f); } return true; } private static void ProcessCrimsonPeon() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (Time.frameCount % 90 == 0 && !IsCachedAlive(ref cachedFabledPeon) && !(Time.time < nextPeonSpawnAt)) { Vector3 pos = default(Vector3); ((Vector3)(ref pos))..ctor(562.2698f, 24.1933f, 362.584f); GameObject val = SpawnNpc("Peon", pos); if (!((Object)(object)val == (Object)null)) { ((Object)val).name = "The Fabled Crimson Peon"; ForceAllNameFields(val, "The Fabled Crimson Peon"); ForceNameplateText(val, "The Fabled Crimson Peon"); ScaleStats(val); ForcePeonHP(val); ApplyScale(val, 2.5f); ForceLevel(val, 28); InjectAmuletRareOnly(val); SendYellow("*** FABLED CRIMSON PEON'S BLOODLUST RISES AS HE YEARNS TO PAINT HIS BONES IN THE BLOOD OF ANY WHO DARE TO CHALLENGE HIS DOMAIN ***"); nextPeonMsgAt = Time.time + 180f; nextPeonSpawnAt = Time.time + 600f; cachedFabledPeon = val; Debug.Log((object)"[BoneLordItems] ★ The Fabled Crimson Peon spawned (HP 30000, scale 2.5, 10-min timer)"); } } } private static void ForcePeonHP(GameObject go) { Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Type type = ((object)val).GetType(); string[] array = new string[7] { "BaseHP", "CurrentMaxHP", "CurrentHP", "MaxHP", "HP", "Health", "MaxHealth" }; string[] array2 = array; foreach (string name in array2) { FieldInfo fieldInfo = FindField(type, name); if (fieldInfo != null && fieldInfo.FieldType == typeof(int)) { try { fieldInfo.SetValue(val, 30000); } catch { } } } } } private static void ApplyScale(GameObject root, float scale) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } try { root.transform.localScale = new Vector3(scale, scale, scale); } catch { } } private static void ForceLevel(GameObject go, int level) { Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } FieldInfo fieldInfo = FindField(((object)val).GetType(), "Level"); if (fieldInfo != null && fieldInfo.FieldType == typeof(int)) { try { fieldInfo.SetValue(val, level); } catch { } } } } private static GameObject SpawnNpc(string nameContains, Vector3 pos) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if (!((Object)(object)val == (Object)null) && ((Object)val).name.IndexOf(nameContains, StringComparison.OrdinalIgnoreCase) >= 0) { try { GameObject val2 = Object.Instantiate<GameObject>(val, pos, Quaternion.identity); val2.SetActive(true); return val2; } catch { } } } return null; } private static GameObject SpawnProp(string propName, Vector3 pos) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if (!((Object)(object)val == (Object)null) && ((Object)val).name.IndexOf(propName, StringComparison.OrdinalIgnoreCase) >= 0) { try { GameObject val2 = Object.Instantiate<GameObject>(val, pos, Quaternion.identity); val2.SetActive(true); return val2; } catch { } } } return null; } private static void ScaleStats(GameObject root) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Type type = ((object)val).GetType(); string name = type.Name; if (name != "Stats" && name != "Character" && name != "NPC") { continue; } string[] array = new string[18] { "BaseHP", "CurrentMaxHP", "CurrentHP", "MaxHP", "HP", "Health", "MaxHealth", "Strength", "Dexterity", "Endurance", "Agility", "Wisdom", "Intelligence", "AC", "Armor", "Attack", "Damage", "Level" }; string[] array2 = array; foreach (string text in array2) { FieldInfo fieldInfo = FindField(type, text); if (fieldInfo == null) { continue; } try { if (fieldInfo.FieldType == typeof(int)) { int num = (int)fieldInfo.GetValue(val); if (text.Contains("HP") || text.Contains("Health")) { fieldInfo.SetValue(val, 3048); continue; } int num2 = Mathf.RoundToInt((float)num * 1.5f); if (text == "Level") { num2 = Mathf.Max(num2, num + 4); } fieldInfo.SetValue(val, num2); } else if (fieldInfo.FieldType == typeof(float)) { fieldInfo.SetValue(val, (float)fieldInfo.GetValue(val) * 1.5f); } } catch { } } } } private static void InjectGuaranteed(GameObject npc, ref object itemRef, string id, string label) { if (itemRef == null) { itemRef = FindFirstByStringField("Id", id); } if (itemRef == null) { return; } string[] array = new string[6] { "GuaranteeOneDrop", "ActualDrops", "RareDrop", "UncommonDrop", "CommonDrop", "AlwaysDrop" }; Component[] componentsInChildren = npc.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null || ((object)val).GetType().Name != "LootTable") { continue; } string[] array2 = array; foreach (string text in array2) { FieldInfo fieldInfo = FindField(((object)val).GetType(), text); if (fieldInfo == null || !(fieldInfo.GetValue(val) is IList list)) { continue; } bool flag = false; foreach (object item in list) { if (item == itemRef) { flag = true; break; } } if (!flag) { list.Add(itemRef); Debug.Log((object)("[BoneLordItems] " + label + " added to " + text)); } } } } private static void InjectTalismanIntoDrops(GameObject npc) { if (talismanItemRef == null) { talismanItemRef = FindFirstByStringField("ItemName", "Talisman of the Bone Knight") ?? FindFirstByStringField("Id", "29042550"); } InjectToLoot(npc, talismanItemRef, "Talisman"); } private static void InjectVisageIntoDrops(GameObject npc) { if (visageItemRef == null) { visageItemRef = FindFirstByStringField("ItemName", "Visage of the Gnoll God") ?? FindFirstByStringField("Id", "57247840"); } InjectToLoot(npc, visageItemRef, "Visage"); } private static void InjectAmuletRareOnly(GameObject npc) { if (amuletItemRef == null) { amuletItemRef = FindFirstByStringField("ItemName", "Amulet of Necropotence") ?? FindFirstByStringField("Id", "20832306"); } if (amuletItemRef == null) { return; } Component[] componentsInChildren = npc.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null || ((object)val).GetType().Name != "LootTable") { continue; } FieldInfo fieldInfo = FindField(((object)val).GetType(), "RareDrop"); if (fieldInfo == null || !(fieldInfo.GetValue(val) is IList list)) { continue; } bool flag = false; foreach (object item in list) { if (item == amuletItemRef) { flag = true; break; } } if (!flag) { list.Add(amuletItemRef); Debug.Log((object)"[BoneLordItems] Amulet added to RareDrop only (~5%)"); } } } private static void InjectSigilIntoDrops(GameObject npc) { if (sigilItemRef == null) { sigilItemRef = FindFirstByStringField("ItemName", "Sigil of the Anguished Shade") ?? FindFirstByStringField("Id", "14265295"); } InjectToLoot(npc, sigilItemRef, "Sigil"); } private static void InjectToLoot(GameObject npc, object itemRef, string label) { if (itemRef == null) { return; } string[] array = new string[4] { "RareDrop", "UncommonDrop", "CommonDrop", "ActualDrops" }; Component[] componentsInChildren = npc.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null || ((object)val).GetType().Name != "LootTable") { continue; } string[] array2 = array; foreach (string text in array2) { FieldInfo fieldInfo = FindField(((object)val).GetType(), text); if (fieldInfo == null || !(fieldInfo.GetValue(val) is IList list)) { continue; } bool flag = false; foreach (object item in list) { if (item == itemRef) { flag = true; break; } } if (!flag) { list.Add(itemRef); Debug.Log((object)("[BoneLordItems] " + label + " added to " + text)); } } } } private static void InjectCelestialSmite(GameObject npc) { if (celestialSmiteRef == null) { celestialSmiteRef = FindFirstByStringField("Id", "11565860") ?? FindFirstByStringField("SpellName", "Celestial Smite I"); } if (celestialSmiteRef == null) { return; } string[] array = new string[8] { "Spells", "SpellList", "KnownSpells", "Abilities", "Skills", "SpellBook", "CombatSpells", "NPCSpells" }; Component[] componentsInChildren = npc.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } string[] array2 = array; foreach (string name in array2) { FieldInfo fieldInfo = FindField(((object)val).GetType(), name); if (fieldInfo == null || !(fieldInfo.GetValue(val) is IList list)) { continue; } bool flag = false; foreach (object item in list) { if (item == celestialSmiteRef) { flag = true; break; } } if (!flag) { try { list.Add(celestialSmiteRef); } catch { } } } } } private static void ShowBonepitsSenseMessage() { SendYellow("*** YOU SENSE A FABLED MAGIC STIRRING IN THE BONEPITS... ANCIENT POWER AWAKENS BENEATH THE DUST AND BONE. ***"); } private static void ShowFabledCaptainMessage() { SendYellow("*** A FABLED SKELETAL CAPTAIN RAISES HIS RUSTED BLADE AND BELLOWS A DEFIANT CHALLENGE, DARING ANY ADVENTURER TO TEST THEIR MIGHT AGAINST HIS ANCIENT BONES! ***"); } private static void ShowNormalCaptainMessage() { SendYellow("*** A SKELETON CAPTAIN'S HOLLOW EYES GLEAM WITH THE FAINT ECHOES OF FABLED MEMORIES, AS IF RECALLING A TIME WHEN TRUE POWER STILL WALKED THESE HALLS. ***"); } private static void ShowFabledLazalithMessage() { SendYellow("*** A DEMONIC HOWL ECHOES AS FABLED LAZALITH, DEMON OF SIVAKAYA, AWAKENS ***"); } private static void ShowFabledGuardMessage() { SendYellow("*** A COLD WAIL DRIFTS THROUGH THE UNDERCITY AS THE FABLED SPECTRAL KING'S GUARD MANIFESTS ***"); } private static void SendYellow(string msg) { try { Type type = Type.GetType("UpdateSocialLog, Assembly-CSharp"); if (type == null) { return; } MethodInfo method = type.GetMethod("LogAdd", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(string) }, null); if (method != null) { method.Invoke(null, new object[2] { msg, "yellow" }); return; } method = type.GetMethod("LogAdd", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); if (method != null) { method.Invoke(null, new object[1] { msg }); } } catch { } } private static void ForceAllNameFields(GameObject root, string newName) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { Type type = ((object)val).GetType(); string[] array = new string[11] { "Name", "DisplayName", "NPCName", "CharacterName", "MyName", "ActorName", "UnitName", "EntityName", "m_Name", "VisibleName", "Title" }; string[] array2 = array; foreach (string fieldName in array2) { Set(val, type, fieldName, newName); } } } } private static void ForceNameplateText(GameObject root, string newName) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } string name = ((object)val).GetType().Name; if (!(name == "Text") && !name.Contains("TextMeshPro") && !name.Contains("TMP_Text") && !(name == "TextMesh")) { continue; } try { PropertyInfo property = ((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (property != null) { string text = property.GetValue(val, null) as string; if (!string.IsNullOrEmpty(text) && (text.Contains("Captain") || text.Contains("Lazalith") || text.Contains("Peon") || text.Contains("Guard") || text.Contains("Skeleton"))) { property.SetValue(val, newName, null); } } } catch { } } } private static bool LooksLikeGameDataPresent() { try { Type type = Type.GetType("GameData, Assembly-CSharp"); if (type != null) { FieldInfo field = type.GetField("PlayerStats", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.GetValue(null) != null) { return true; } } } catch { } return FindFirstByStringField("ItemName", "Soul Echo") != null || FindFirstByStringField("Id", "20309875") != null; } private static int InjectEverything() { object obj = FindHydrated(); if (obj == null) { return 0; } int num = 0; object classesTemplate = FindClassesTemplate(); if (cloneSkeleton == null) { cloneSkeleton = MakeClone(obj, "90000001", "Amulet of Necropotence", "Skeleton", "You take the form of Nazura the Traitor."); } if (cloneKnight == null) { cloneKnight = MakeClone(obj, "90000002", "Talisman of the Bone Knight", "SkeletonKnight", "You take the form of a Skeleton Knight."); } if (cloneHero == null) { cloneHero = MakeClone(obj, "90000003", "Visage of the Gnoll God", "HeroKnightFemale", "You take the form of the Gnoll God."); } if (cloneTorment == null) { cloneTorment = MakeClone(obj, "90000004", "Sigil of the Anguished Shade", "TormentedSoul", "You take the form of an Anguished Shade."); } if (cloneSkeleton == null || cloneKnight == null || cloneHero == null || cloneTorment == null) { return 0; } num += 4; num += ModItem("20832306", "Soul Echo", "Amulet of Necropotence", "Click: Become Nazura the Traitor.", classesTemplate, cloneSkeleton); num += ModItem("29042550", "Neophyte Necklace", "Talisman of the Bone Knight", "Click: Skeleton Knight form.", classesTemplate, cloneKnight); num += ModItem("57247840", "Fluorite Amulet", "Visage of the Gnoll God", "Click: Gnoll God form.", classesTemplate, cloneHero); num += ModItem("14265295", "Plain Necklace", "Sigil of the Anguished Shade", "Click: Anguished Shade form.", classesTemplate, cloneTorment); num += ModItemByName("Amulet of Necropotence", "Amulet of Necropotence", "Click: Become Nazura the Traitor.", classesTemplate, cloneSkeleton); num += ModItemByName("Talisman of the Bone Knight", "Talisman of the Bone Knight", "Click: Skeleton Knight form.", classesTemplate, cloneKnight); num += ModItemByName("Visage of Anubis", "Visage of the Gnoll God", "Click: Gnoll God form.", classesTemplate, cloneHero); num += ModItemByName("Visage of the Gnoll God", "Visage of the Gnoll God", "Click: Gnoll God form.", classesTemplate, cloneHero); num += ModItemByName("Sigil of the Anguished Shade", "Sigil of the Anguished Shade", "Click: Anguished Shade form.", classesTemplate, cloneTorment); num += ModItemByName("Wail of the Tormented", "Sigil of the Anguished Shade", "Click: Anguished Shade form.", classesTemplate, cloneTorment); num += UpdatePage1Lore(); return num + UpdateMathersNoteLore(); } private static int UpdatePage1Lore() { int num = 0; string value = "******** You pick up a faded page from a family journal. Seek out the descendants of the Fabled Captain Mathers. They may hold knowledge of the fabled magic you have encountered. The page is dusted with black salt, and a faded photograph of a seaside cottage is carefully tucked within. ********"; foreach (object item in FindAllByStringField("Id", "11021645")) { Type type = item.GetType(); Set(item, type, "Lore", value); Set(item, type, "ItemLore", value); Set(item, type, "Description", value); Set(item, type, "Desc", value); num++; Debug.Log((object)"[BoneLordItems] Updated Pg.1 Faded Entry lore (ID 11021645)"); } return num; } private static int UpdateMathersNoteLore() { int num = 0; string value = "******** Strange Fabled Magic permeates this note, continue investigating the Mathers to track down the source of this magic****I fear for our safety. I fear that our time is nearing its end. \n\nThere have been cloaked figures lurking on the beach at night, after dark. I wonder if they know what knowledge I possess... and how they plan to extract it from me. I can only wonder what Eldoth has asked of them...\n\nIf you find this letter after my demise, see my Brother Yarren in Goodsoil. I've given something of great interest to him for safe keeping. Ask for him - he's often toiling away out of sight."; foreach (object item in FindAllByStringFieldContains("ItemName", "Mathers")) { Type type = item.GetType(); Set(item, type, "Lore", value); Set(item, type, "ItemLore", value); Set(item, type, "Description", value); Set(item, type, "Desc", value); num++; Debug.Log((object)"[BoneLordItems] Updated Mathers Note lore (found by ItemName)"); } if (num == 0) { string[] array = new string[4] { "Mathers Note", "Mathers' Note", "Note from Mathers", "A Mathers Note" }; string[] array2 = array; foreach (string text in array2) { foreach (object item2 in FindAllByStringField("ItemName", text)) { Type type2 = item2.GetType(); Set(item2, type2, "Lore", value); Set(item2, type2, "ItemLore", value); Set(item2, type2, "Description", value); Set(item2, type2, "Desc", value); num++; Debug.Log((object)("[BoneLordItems] Updated Mathers Note lore (name match: " + text + ")")); } } } if (num == 0) { Debug.LogWarning((object)"[BoneLordItems] Mathers Note not found by name – open it in Unity Explorer and tell me the exact ItemName or Id string"); } return num; } private static object FindHydrated() { using (IEnumerator<object> enumerator = FindAllByStringField("Id", "20309875").GetEnumerator()) { if (enumerator.MoveNext()) { return enumerator.Current; } } string[] array = new string[2] { "SpellName", "Name" }; foreach (string fieldName in array) { using IEnumerator<object> enumerator2 = FindAllByStringField(fieldName, "Hydrated").GetEnumerator(); if (enumerator2.MoveNext()) { return enumerator2.Current; } } return null; } private static object MakeClone(object template, string newId, string newName, string form, string msg) { try { ScriptableObject val = (ScriptableObject)((template is ScriptableObject) ? template : null); if ((Object)(object)val == (Object)null) { return null; } ScriptableObject val2 = Object.Instantiate<ScriptableObject>(val); ((Object)val2).name = newName; Type type = ((object)val2).GetType(); Set(val2, type, "Id", newId); Set(val2, type, "SpellName", newName); Set(val2, type, "Name", newName); Set(val2, type, "ShapeshiftForm", form); Set(val2, type, "StatusEffectMessageOnPlayer", msg); Set(val2, type, "SpellDesc", msg); Set(val2, type, "Lore", msg); Set(val2, type, "SelfOnly", true); Set(val2, type, "InflictOnSelf", true); Set(val2, type, "ApplyToCaster", true); Set(val2, type, "GroupEffect", false); Set(val2, type, "TargetDamage", 0); Set(val2, type, "Damage", 0); Set(val2, type, "HealAmount", 0); Set(val2, type, "ManaCost", 0); Set(val2, type, "SpellDurationInTicks", 3600); Set(val2, type, "Duration", 3600f); Set(val2, type, "IsBuff", true); Set(val2, type, "Beneficial", true); Set(val2, type, "IsStatusEffect", true); Debug.Log((object)("[BoneLordItems] ✓ Clone " + newName + " form=" + form)); return val2; } catch (Exception ex) { Debug.LogError((object)("[BoneLordItems] Clone failed: " + ex)); return null; } } private static int ModItem(string id, string oldName, string newName, string lore, object classesTemplate, object spellRef) { int num = 0; foreach (object item in FindAllByStringField("Id", id)) { if (ApplyItem(item, newName, lore, classesTemplate, spellRef)) { num++; } } return num; } private static int ModItemByName(string name, string newName, string lore, object classesTemplate, object spellRef) { int num = 0; foreach (object item in FindAllByStringField("ItemName", name)) { if (ApplyItem(item, newName, lore, classesTemplate, spellRef)) { num++; } } return num; } private static bool ApplyItem(object item, string newName, string lore, object classesTemplate, object spellRef) { Type type = item.GetType(); Set(item, type, "ItemName", newName); Set(item, type, "Lore", lore); Set(item, type, "Relic", true); Set(item, type, "RareItem", true); if (classesTemplate != null) { FieldInfo fieldInfo = FindField(type, "Classes"); if (fieldInfo != null) { try { fieldInfo.SetValue(item, classesTemplate); } catch { } } } if (spellRef != null) { Set(item, type, "ItemEffectOnClick", spellRef); Set(item, type, "SpellOnClick", spellRef); Set(item, type, "OnClickSpell", spellRef); Set(item, type, "ClickSpell", spellRef); } return true; } private static object FindClassesTemplate() { Object[] array = Resources.FindObjectsOfTypeAll(typeof(ScriptableObject)); foreach (Object val in array) { if (val == (Object)null) { continue; } FieldInfo fieldInfo = FindField(((object)val).GetType(), "Classes"); if (!(fieldInfo == null)) { object value = fieldInfo.GetValue(val); if (value is IList { Count: >=6 }) { return value; } } } return null; } private static object FindFirstByStringField(string fieldName, string value) { using (IEnumerator<object> enumerator = FindAllByStringField(fieldName, value).GetEnumerator()) { if (enumerator.MoveNext()) { return enumerator.Current; } } return null; } private static IEnumerable<object> FindAllByStringField(string fieldName, string value) { List<object> list = new List<object>(); Object[] array = Resources.FindObjectsOfTypeAll(typeof(ScriptableObject)); foreach (Object val in array) { if (!(val == (Object)null)) { FieldInfo fieldInfo = FindField(((object)val).GetType(), fieldName); if (!(fieldInfo == null) && !(fieldInfo.FieldType != typeof(string)) && fieldInfo.GetValue(val) as string == value) { list.Add(val); } } } return list; } private static IEnumerable<object> FindAllByStringFieldContains(string fieldName, string contains) { List<object> list = new List<object>(); Object[] array = Resources.FindObjectsOfTypeAll(typeof(ScriptableObject)); foreach (Object val in array) { if (val == (Object)null) { continue; } FieldInfo fieldInfo = FindField(((object)val).GetType(), fieldName); if (!(fieldInfo == null) && !(fieldInfo.FieldType != typeof(string))) { string text = fieldInfo.GetValue(val) as string; if (!string.IsNullOrEmpty(text) && text.IndexOf(contains, StringComparison.OrdinalIgnoreCase) >= 0) { list.Add(val); } } } return list; } private static FieldInfo FindField(Type type, string name) { while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type = type.BaseType; } return null; } private static void Set(object obj, Type type, string fieldName, object value) { FieldInfo fieldInfo = FindField(type, fieldName); if (fieldInfo == null) { return; } try { if (value == null) { if (!fieldInfo.FieldType.IsValueType) { fieldInfo.SetValue(obj, null); } } else if (fieldInfo.FieldType == typeof(bool) && value is bool flag) { fieldInfo.SetValue(obj, flag); } else if (fieldInfo.FieldType == typeof(int) && value is int num) { fieldInfo.SetValue(obj, num); } else if (fieldInfo.FieldType == typeof(float) && value is float num2) { fieldInfo.SetValue(obj, num2); } else if (fieldInfo.FieldType.IsAssignableFrom(value.GetType())) { fieldInfo.SetValue(obj, value); } else { fieldInfo.SetValue(obj, Convert.ChangeType(value, fieldInfo.FieldType)); } } catch { } } }
SkeletonShapeshift.dll
Decompiled 5 hours agousing 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.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using HarmonyLib; using UnityEngine; using UnityEngine.AI; 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: AssemblyTitle("SkeletonShapeshift")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SkeletonShapeshift")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("95a4b4eb-c4f8-4021-a033-971d6730881a")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace SkeletonShapeshift; [BepInPlugin("com.yourname.skeletonshapeshift", "Skeleton Shapeshift", "1.23.6")] public class Plugin : BaseUnityPlugin { private class IllusionDef { public string FormKey; public string PrimaryMesh; public string[] FallbackMeshes; public float AttackHitChance; public bool UseSkeletonSfx; public string SpawnWav; public string AttackWav; } private static bool isInSkeletonForm = false; private static float nextCheckTime = 0f; private static float graceUntil = 0f; private static int missingBuffStrikes = 0; private static GameObject currentClone = null; private static bool hadPlayerStats = false; private static List<GameObject> attachedWeapons = new List<GameObject>(); private static float nextSoundTime = 0f; private static float nextAttackSfxTime = 0f; private static float weaponCycleCooldownUntil = 0f; private static bool weaponCycleRunning = false; private static bool pendingF7Cycle = false; private static bool visualPatchDone = false; private static bool suppressNextSpawn = false; private static string lastEquipSig = ""; private static float nextEquipPoll = 0f; private static bool fpvActive = false; private static readonly List<Renderer> humanRenderersHidden = new List<Renderer>(); private const float FPV_CLOSE_DISTANCE = 2f; private static string currentPrimaryMesh = "SM_Chr_Skeleton_LightArmor_01"; private static string currentFormKey = "Skeleton"; private static float currentAttackChance = 0.1f; private static AudioClip currentSpawnClip = null; private static AudioClip currentAttackClip = null; private static AudioClip skeletonLaugh = null; private static AudioClip skeletonAttack = null; private static AudioClip tormentedSpawn = null; private static AudioClip tormentedAttack = null; private static AudioClip heroFemaleSpawn = null; private static AudioClip heroFemaleAttack = null; private static AudioClip dingClip = null; private static bool soundLoadStarted = false; private static AudioSource sfxSource = null; private static int lastKnownLevel = -1; private static string lastSpawnFormKey = ""; private static float spawnSfxReadyAt = 0f; private static Harmony harmonyInstance; private static GameObject ancientWarriorTemplateCache = null; private static string ancientWarriorCacheSourceName = ""; private static GameObject nazuraTemplateCache = null; private static string nazuraCacheSourceName = ""; private const float FORCE_SCALE = 1f; private const float LAUGH_INTERVAL = 120f; private const float LOGIN_SFX_GRACE = 6f; private const float ATTACK_SFX_COOLDOWN = 0.85f; private const float WEAPON_CYCLE_COOLDOWN = 0.85f; private const float EQUIP_POLL_INTERVAL = 0.15f; private const float ANCIENT_WARRIOR_WEAPON_SCALE = 0.01f; private static readonly Vector3 ANCIENT_WARRIOR_OFFSET_RIGHT = new Vector3(0.1023f, 0.0385f, -0.0424f); private static readonly Vector3 ANCIENT_WARRIOR_OFFSET_LEFT = new Vector3(-0.0909f, -0.0388f, 0.0089f); private static readonly IllusionDef[] IllusionList = new IllusionDef[4] { new IllusionDef { FormKey = "Skeleton", PrimaryMesh = "SM_Chr_Skeleton_LightArmor_01", FallbackMeshes = new string[5] { "SM_Chr_Skeleton_LightArmor_01", "Character_Skeleton_Slave_01", "Character_Skeleton_Knight", "Character_Skeleton_Soldier_01", "Skeleton" }, AttackHitChance = 0.1f, UseSkeletonSfx = true, SpawnWav = "Skeleton_laugh", AttackWav = "Skeleton_Attack" }, new IllusionDef { FormKey = "SkeletonKnight", PrimaryMesh = "Character_Skeleton_Knight", FallbackMeshes = new string[3] { "Character_Skeleton_Slave_01", "Character_Skeleton_Soldier_01", "Skeleton" }, AttackHitChance = 0.1f, UseSkeletonSfx = true, SpawnWav = "Skeleton_laugh", AttackWav = "Skeleton_Attack" }, new IllusionDef { FormKey = "TormentedSoul", PrimaryMesh = "Character_Tormented_Soul", FallbackMeshes = new string[3] { "Character_Ghost_02", "Character_Ghost_01", "Character_Tormented_Soul" }, AttackHitChance = 0.1f, UseSkeletonSfx = false, SpawnWav = "TormentedSpawn", AttackWav = "TormentedAttack" }, new IllusionDef { FormKey = "HeroKnightFemale", PrimaryMesh = "Character_Ancient_Warrior_01", FallbackMeshes = new string[3] { "Character_DarkElf_01", "Character_Hero_Knight_Female", "Character_Skeleton_Knight" }, AttackHitChance = 0.1f, UseSkeletonSfx = false, SpawnWav = "HeroFemaleSpawn", AttackWav = "HeroFemaleAttack" } }; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown harmonyInstance = new Harmony("com.yourname.skeletonshapeshift"); foreach (MethodInfo item in from m in typeof(Stats).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "AddStatusEffect" select m) { harmonyInstance.Patch((MethodBase)item, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "PostfixAddStatusEffect", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo method = typeof(Plugin).GetMethod("PostfixDamageMe", BindingFlags.Static | BindingFlags.Public); int num = 0; foreach (MethodInfo item2 in from m in typeof(Character).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "DamageMe" select m) { harmonyInstance.Patch((MethodBase)item2, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } Debug.Log((object)("[SkeletonMod] Patched Character.DamageMe overloads: " + num)); EnsureSfxSource(); TryLoadSounds(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Skeleton Shapeshift 1.23.6 loaded (all attack SFX 10% on hit)"); } private static void TryPatchUpdatePlayerVisuals() { //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown if (visualPatchDone || harmonyInstance == null || (Object)(object)GameData.PlayerInv == (Object)null) { return; } object obj = null; try { Type type = ((object)GameData.PlayerInv).GetType(); obj = type.GetField("Modulars", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerInv) ?? type.GetProperty("Modulars", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerInv, null); } catch { return; } if (obj == null) { return; } int num = 0; try { foreach (MethodInfo item in from x in obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where x.Name == "UpdatePlayerVisuals" select x) { harmonyInstance.Patch((MethodBase)item, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "PostfixUpdatePlayerVisuals", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } } catch { return; } visualPatchDone = true; Debug.Log((object)("[SkeletonMod] Patched UpdatePlayerVisuals overloads: " + num)); } public static void PostfixUpdatePlayerVisuals() { if (isInSkeletonForm && !weaponCycleRunning && IsGameplayWorld()) { QueueIfEquipChanged("UpdatePlayerVisuals"); } } private static void QueueIfEquipChanged(string reason) { if (isInSkeletonForm && !weaponCycleRunning && !(Time.time < weaponCycleCooldownUntil) && IsGameplayWorld()) { string text = BuildEquipSignature(); if (!string.IsNullOrEmpty(text) && !(text == lastEquipSig)) { lastEquipSig = text; pendingF7Cycle = true; Debug.Log((object)("[SkeletonMod][Weapons] EQUIP CHANGED (" + reason + ") → queue F6 | " + text)); } } } private static string BuildEquipSignature() { string text = BuildSignatureFromEquipmentSlots(weaponSlotsOnly: true); if (!string.IsNullOrEmpty(text)) { return text; } string text2 = BuildSignatureFromEquipmentSlots(weaponSlotsOnly: false); if (!string.IsNullOrEmpty(text2)) { return text2; } return BuildSignatureFromUiSlots(); } private static string BuildSignatureFromEquipmentSlots(bool weaponSlotsOnly) { try { if ((Object)(object)GameData.PlayerInv == (Object)null) { return ""; } Type type = ((object)GameData.PlayerInv).GetType(); object obj = type.GetField("EquipmentSlots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerInv) ?? type.GetProperty("EquipmentSlots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerInv, null); if (!(obj is IList { Count: not 0 } list)) { return ""; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; for (int i = 0; i < list.Count; i++) { object obj2 = list[i]; if (obj2 == null) { continue; } string slotKey = GetSlotKey(obj2, i); if (!weaponSlotsOnly || IsPrimaryOrSecondaryKey(slotKey)) { string text = DescribeSlotItem(obj2); if (!(text == "empty") && !string.IsNullOrEmpty(text)) { stringBuilder.Append(slotKey).Append('=').Append(text) .Append(';'); num++; } } } return (num > 0) ? stringBuilder.ToString() : ""; } catch { return ""; } } private static string BuildSignatureFromUiSlots() { try { if ((Object)(object)GameData.PlayerInv == (Object)null) { return ""; } Inventory playerInv = GameData.PlayerInv; Transform val = ((playerInv != null) ? ((Component)playerInv).transform : null); if ((Object)(object)val == (Object)null) { return ""; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; string[] array = new string[6] { "Primary", "Secondary", "MainHand", "OffHand", "mainhand", "offhand" }; foreach (string text in array) { Transform val2 = FindDeepChild(val, text); if (!((Object)(object)val2 == (Object)null)) { string value = ReadUiSlotIcon(((Component)val2).gameObject); if (!string.IsNullOrEmpty(value)) { stringBuilder.Append(text).Append('=').Append(value) .Append(';'); num++; } } } return (num > 0) ? stringBuilder.ToString() : ""; } catch { return ""; } } private static string BuildSignatureFromHumanHands() { try { Transform humanRoot = GetHumanRoot(); if ((Object)(object)humanRoot == (Object)null) { return ""; } Transform hand = FindDeepChild(humanRoot, "Hand_R") ?? FindDeepChild(humanRoot, "hand_r"); Transform hand2 = FindDeepChild(humanRoot, "Hand_L") ?? FindDeepChild(humanRoot, "hand_l"); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("R="); AppendHandWeaponNames(hand, stringBuilder); stringBuilder.Append(";L="); AppendHandWeaponNames(hand2, stringBuilder); string text = stringBuilder.ToString(); return (text == "R=;L=") ? "" : text; } catch { return ""; } } private static void AppendHandWeaponNames(Transform hand, StringBuilder sb) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if ((Object)(object)hand == (Object)null) { return; } bool flag = true; foreach (Transform item in hand) { Transform val = item; if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeSelf) { continue; } string text = ((Object)val).name.ToLowerInvariant(); if (!text.Contains("hand") && !text.Contains("finger") && !text.Contains("wrist") && (!((Object)(object)((Component)val).GetComponentInChildren<MeshRenderer>(true) == (Object)null) || !((Object)(object)((Component)val).GetComponentInChildren<SkinnedMeshRenderer>(true) == (Object)null))) { if (!flag) { sb.Append('+'); } sb.Append(((Object)val).name); flag = false; } } } private static string ReadUiSlotIcon(GameObject slotGo) { if ((Object)(object)slotGo == (Object)null) { return ""; } try { Component[] componentsInChildren = slotGo.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } string name = ((object)val).GetType().Name; if (name != "Image" && name != "RawImage") { continue; } PropertyInfo property = ((object)val).GetType().GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public); if (!(property != null)) { continue; } object value = property.GetValue(val, null); if (value != null) { string text = value.GetType().GetProperty("name")?.GetValue(value, null) as string; if (!string.IsNullOrEmpty(text)) { return text; } } } Transform val2 = FindDeepChild(slotGo.transform, "ItemIcon"); if ((Object)(object)val2 != (Object)null) { Component[] components = ((Component)val2).GetComponents<Component>(); foreach (Component val3 in components) { if ((Object)(object)val3 == (Object)null) { continue; } object obj = ((object)val3).GetType().GetProperty("sprite", BindingFlags.Instance | BindingFlags.Public)?.GetValue(val3, null); if (obj != null) { string text2 = obj.GetType().GetProperty("name")?.GetValue(obj, null) as string; if (!string.IsNullOrEmpty(text2)) { return text2; } } } } } catch { } return ""; } private static string GetSlotKey(object slot, int index) { try { Type type = slot.GetType(); string[] array = new string[6] { "SlotName", "MySlot", "slotName", "Name", "SlotType", "Type" }; foreach (string name in array) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(slot); if (value != null && !string.IsNullOrEmpty(value.ToString())) { return value.ToString(); } } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { object value2 = property.GetValue(slot, null); if (value2 != null && !string.IsNullOrEmpty(value2.ToString())) { return value2.ToString(); } } } Component val = (Component)((slot is Component) ? slot : null); if (val != null && (Object)(object)val.gameObject != (Object)null) { return ((Object)val.gameObject).name; } } catch { } return "idx" + index; } private static bool IsPrimaryOrSecondaryKey(string key) { if (string.IsNullOrEmpty(key)) { return false; } string text = key.ToLowerInvariant(); int result; if (!text.Contains("primary") && !text.Contains("secondary") && !text.Contains("mainhand") && !text.Contains("main_hand") && !text.Contains("main hand") && !text.Contains("offhand") && !text.Contains("off_hand") && !text.Contains("off hand")) { switch (text) { case "weapon": case "weapon1": case "weapon2": goto IL_00eb; } if (!text.Contains("righthand") && !text.Contains("lefthand") && !text.Contains("r_hand")) { result = (text.Contains("l_hand") ? 1 : 0); goto IL_00ec; } } goto IL_00eb; IL_00ec: return (byte)result != 0; IL_00eb: result = 1; goto IL_00ec; } private static string DescribeSlotItem(object slot) { try { Type type = slot.GetType(); string[] array = new string[6] { "MyItem", "Item", "item", "CurrentItem", "EquippedItem", "Content" }; foreach (string name in array) { object obj = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(slot) ?? type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(slot, null); if (obj != null) { Type type2 = obj.GetType(); FieldInfo fieldInfo = type2.GetField("Id", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type2.GetField("ID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return string.Concat(str2: (type2.GetField("ItemName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type2.GetField("Name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(obj)?.ToString() ?? obj.ToString(), str0: fieldInfo?.GetValue(obj)?.ToString(), str1: ":"); } } } catch { } return "empty"; } private static void ForceUpdatePlayerVisuals() { try { if ((Object)(object)GameData.PlayerInv == (Object)null) { return; } Type type = ((object)GameData.PlayerInv).GetType(); object obj = type.GetField("Modulars", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerInv) ?? type.GetProperty("Modulars", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerInv, null); if (obj == null) { return; } object obj2 = type.GetField("EquipmentSlots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerInv) ?? type.GetProperty("EquipmentSlots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerInv, null); MethodInfo method = obj.GetType().GetMethod("UpdatePlayerVisuals", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null)) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 0) { method.Invoke(obj, null); } else if (parameters.Length >= 1 && obj2 != null) { method.Invoke(obj, new object[1] { obj2 }); } } } catch { } } private static ShapeshiftMngr GetShapeShift() { try { if ((Object)(object)GameData.PlayerStats == (Object)null) { return null; } object? obj = typeof(Stats).GetField("MyShapeShift", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(GameData.PlayerStats); return (ShapeshiftMngr)((obj is ShapeshiftMngr) ? obj : null); } catch { return null; } } private static bool IsCameraInFpv() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)GameData.PlayerControl != (Object)null) ? ((Component)GameData.PlayerControl).transform.position : Vector3.zero); Vector3 val2 = val + Vector3.up * 1.55f; Camera[] array = null; try { array = Camera.allCameras; } catch { } if (array == null || array.Length == 0) { Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return false; } array = (Camera[])(object)new Camera[1] { main }; } Camera[] array2 = array; foreach (Camera val3 in array2) { if (!((Object)(object)val3 == (Object)null) && ((Behaviour)val3).enabled && ((Component)val3).gameObject.activeInHierarchy && !val3.orthographic) { float num = Vector3.Distance(((Component)val3).transform.position, val2); if (num < 2f) { return true; } } } return false; } private static void HideHumanBodyRenderers(Transform playerRoot) { humanRenderersHidden.Clear(); if ((Object)(object)playerRoot == (Object)null) { return; } Renderer[] componentsInChildren = ((Component)playerRoot).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); if (!text.Contains("canvas") && !text.Contains("ui") && !text.Contains("text") && val.enabled) { val.enabled = false; humanRenderersHidden.Add(val); } } } } private static void RestoreHumanBodyRenderers() { foreach (Renderer item in humanRenderersHidden) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } humanRenderersHidden.Clear(); } private static void EnterFpvMode() { if (fpvActive || weaponCycleRunning) { return; } ShapeshiftMngr shapeShift = GetShapeShift(); if (!((Object)(object)shapeShift == (Object)null)) { if ((Object)(object)currentClone != (Object)null) { currentClone.SetActive(false); } if ((Object)(object)shapeShift.PlayerRoot != (Object)null) { shapeShift.PlayerRoot.SetActive(true); HideHumanBodyRenderers(shapeShift.PlayerRoot.transform); } fpvActive = true; Debug.Log((object)"[SkeletonMod][FPV] Enter FPV (PlayerRoot on, clone hidden, human meshes off)"); } } private static void ExitFpvMode() { if (!fpvActive) { return; } ShapeshiftMngr shapeShift = GetShapeShift(); RestoreHumanBodyRenderers(); if ((Object)(object)shapeShift != (Object)null && (Object)(object)shapeShift.PlayerRoot != (Object)null) { shapeShift.PlayerRoot.SetActive(false); } if ((Object)(object)currentClone != (Object)null) { currentClone.SetActive(true); if ((Object)(object)shapeShift != (Object)null) { shapeShift.CurrentModel = currentClone; } } fpvActive = false; Debug.Log((object)"[SkeletonMod][FPV] Exit FPV (clone shown, PlayerRoot off)"); } private static void UpdateFpvMode() { if (!isInSkeletonForm || (Object)(object)currentClone == (Object)null || weaponCycleRunning) { if (fpvActive) { ExitFpvMode(); } return; } bool flag = IsCameraInFpv(); if (flag && !fpvActive) { EnterFpvMode(); } else if (!flag && fpvActive) { ExitFpvMode(); } } private static void ClearFpvState() { if (fpvActive) { ExitFpvMode(); } RestoreHumanBodyRenderers(); fpvActive = false; } private void Update() { if (!soundLoadStarted) { soundLoadStarted = true; EnsureSfxSource(); TryLoadSounds(); } if (!visualPatchDone && (Object)(object)GameData.PlayerInv != (Object)null) { TryPatchUpdatePlayerVisuals(); } if ((Object)(object)GameData.PlayerStats == (Object)null) { if (hadPlayerStats) { hadPlayerStats = false; isInSkeletonForm = false; lastKnownLevel = -1; lastEquipSig = ""; weaponCycleRunning = false; pendingF7Cycle = false; ClearFpvState(); CleanupWeapons(); if ((Object)(object)currentClone != (Object)null) { Object.Destroy((Object)(object)currentClone); currentClone = null; } } return; } if (!hadPlayerStats) { hadPlayerStats = true; spawnSfxReadyAt = Time.time + 6f; lastKnownLevel = GameData.PlayerStats.Level; } CheckLevelUpDing(); if (isInSkeletonForm && IsGameplayWorld()) { UpdateFpvMode(); } if (!IsGameplayWorld()) { if (isInSkeletonForm || (Object)(object)currentClone != (Object)null) { RestoreHumanForm(); } pendingF7Cycle = false; return; } if (isInSkeletonForm && !weaponCycleRunning && !fpvActive && Time.unscaledTime >= nextEquipPoll) { nextEquipPoll = Time.unscaledTime + 0.15f; QueueIfEquipChanged("poll"); } if (pendingF7Cycle && isInSkeletonForm && !weaponCycleRunning && !fpvActive && Time.time >= weaponCycleCooldownUntil) { pendingF7Cycle = false; weaponCycleCooldownUntil = Time.time + 0.85f; Debug.Log((object)"[SkeletonMod][Weapons] Running F6-cycle (auto)"); ((MonoBehaviour)this).StartCoroutine(F7StyleWeaponRefreshFast()); } else if (pendingF7Cycle && !isInSkeletonForm) { pendingF7Cycle = false; } if (!(Time.time >= nextCheckTime)) { return; } nextCheckTime = Time.time + 0.35f; if (HasIllusionBuff()) { missingBuffStrikes = 0; if (!weaponCycleRunning && !fpvActive && (!isInSkeletonForm || (Object)(object)currentClone == (Object)null || !Object.op_Implicit((Object)(object)currentClone)) && Time.time >= graceUntil) { TryForceSkeleton(); } if (isInSkeletonForm && Time.time >= nextSoundTime) { nextSoundTime = Time.time + 120f; PlaySpawn(force: false); } } else if (isInSkeletonForm && Time.time >= graceUntil) { missingBuffStrikes++; if (missingBuffStrikes >= 3) { RestoreHumanForm(); } } } private IEnumerator F7StyleWeaponRefreshFast() { weaponCycleRunning = true; try { if (fpvActive) { ExitFpvMode(); } suppressNextSpawn = true; string handsBefore = BuildSignatureFromHumanHands(); RestoreHumanForm(); nextCheckTime = Time.time + 1f; string handsAfter = handsBefore; for (int i = 0; i < 12; i++) { ForceUpdatePlayerVisuals(); yield return null; handsAfter = BuildSignatureFromHumanHands(); if (!string.IsNullOrEmpty(handsAfter) && handsAfter != handsBefore) { Debug.Log((object)("[SkeletonMod] Hands updated frame " + (i + 1) + ": " + handsAfter)); break; } } if (string.IsNullOrEmpty(handsAfter) || handsAfter == handsBefore) { Debug.Log((object)("[SkeletonMod] Hands did not change (using whatever is on model now) before=" + handsBefore + " after=" + handsAfter)); } if (HasIllusionBuff()) { TryForceSkeleton(); } else { nextCheckTime = 0f; } } finally { weaponCycleRunning = false; } } private static bool IsGameplayWorld() { //IL_0055: 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) try { if ((Object)(object)GameData.PlayerStats == (Object)null || (Object)(object)GameData.PlayerControl == (Object)null || !((Behaviour)GameData.PlayerControl).enabled) { return false; } string text = null; try { text = GameData.SceneName; } catch { } if (string.IsNullOrEmpty(text)) { try { Scene activeScene = SceneManager.GetActiveScene(); text = ((Scene)(ref activeScene)).name; } catch { } } if (string.IsNullOrEmpty(text)) { return false; } string text2 = text.ToLowerInvariant(); return !text2.Contains("load") && !text2.Contains("char") && !text2.Contains("menu") && !text2.Contains("title") && !text2.Contains("login") && !text2.Contains("select"); } catch { return false; } } public static void PostfixAddStatusEffect(Stats __instance, Spell spell) { if ((Object)(object)__instance != (Object)(object)GameData.PlayerStats || (Object)(object)spell == (Object)null) { return; } IllusionDef illusionDef = ResolveIllusion(spell); if (illusionDef == null) { return; } if (!IsGameplayWorld()) { ApplyIllusionDef(illusionDef); RemoveOtherIllusionBuffs(illusionDef); return; } graceUntil = Time.time + 3.5f; missingBuffStrikes = 0; bool flag = isInSkeletonForm && currentFormKey == illusionDef.FormKey && (Object)(object)currentClone != (Object)null && Object.op_Implicit((Object)(object)currentClone); RemoveOtherIllusionBuffs(illusionDef); ApplyIllusionDef(illusionDef); Debug.Log((object)("[SkeletonMod] === FOUND ILLUSION: " + illusionDef.FormKey + " → " + illusionDef.PrimaryMesh + " | " + (flag ? "same-form re-click" : "full rebuild") + " ===")); if (flag) { nextSoundTime = Time.time + 120f; PlaySpawn(force: true); return; } if (fpvActive) { ExitFpvMode(); } isInSkeletonForm = false; CleanupWeapons(); if ((Object)(object)currentClone != (Object)null) { Object.Destroy((Object)(object)currentClone); currentClone = null; } suppressNextSpawn = false; TryForceSkeleton(); } public static void PostfixDamageMe(Character __instance, int _incdmg, bool _fromPlayer) { if (!isInSkeletonForm || !IsGameplayWorld() || Time.time < graceUntil || Time.time < nextAttackSfxTime || !_fromPlayer || _incdmg <= 0) { return; } try { if ((Object)(object)__instance == (Object)null || ((Object)(object)GameData.PlayerStats != (Object)null && (Object)(object)__instance == (Object)(object)GameData.PlayerStats.Myself) || ((Object)(object)GameData.PlayerControl != (Object)null && (Object)(object)((Component)__instance).gameObject == (Object)(object)((Component)GameData.PlayerControl).gameObject)) { return; } } catch { return; } if (!(Random.value > currentAttackChance)) { nextAttackSfxTime = Time.time + 0.85f; PlayAttack(); } } private static IllusionDef ResolveIllusion(Spell spell) { if ((Object)(object)spell == (Object)null) { return null; } string text = null; try { text = spell.ShapeshiftForm; } catch { } if (string.IsNullOrEmpty(text)) { return null; } text = text.Trim(); IllusionDef[] illusionList = IllusionList; foreach (IllusionDef illusionDef in illusionList) { if (string.Equals(illusionDef.FormKey, text, StringComparison.OrdinalIgnoreCase)) { return illusionDef; } } if (text.IndexOf("Skeleton", StringComparison.OrdinalIgnoreCase) >= 0 && text.IndexOf("Knight", StringComparison.OrdinalIgnoreCase) >= 0) { return IllusionList.FirstOrDefault((IllusionDef x) => x.FormKey == "SkeletonKnight"); } if (text.IndexOf("Torment", StringComparison.OrdinalIgnoreCase) >= 0) { return IllusionList.FirstOrDefault((IllusionDef x) => x.FormKey == "TormentedSoul"); } if (text.IndexOf("Hero", StringComparison.OrdinalIgnoreCase) >= 0 && text.IndexOf("Female", StringComparison.OrdinalIgnoreCase) >= 0) { return IllusionList.FirstOrDefault((IllusionDef x) => x.FormKey == "HeroKnightFemale"); } if (text.IndexOf("Skeleton", StringComparison.OrdinalIgnoreCase) >= 0) { return IllusionList.FirstOrDefault((IllusionDef x) => x.FormKey == "Skeleton"); } return null; } private static IllusionDef ResolveActiveIllusion() { Stats playerStats = GameData.PlayerStats; if (((playerStats != null) ? playerStats.StatusEffects : null) == null) { return null; } StatusEffect[] statusEffects = GameData.PlayerStats.StatusEffects; foreach (StatusEffect se in statusEffects) { IllusionDef illusionDef = ResolveIllusion(GetSpellFromStatusEffect(se)); if (illusionDef != null) { return illusionDef; } } return null; } private static bool HasIllusionBuff() { return ResolveActiveIllusion() != null; } private static Spell GetSpellFromStatusEffect(StatusEffect se) { if (se == null) { return null; } try { Type type = ((object)se).GetType(); FieldInfo fieldInfo = type.GetField("Effect", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("Spell", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("MySpell", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null) { object? value = fieldInfo.GetValue(se); return (Spell)((value is Spell) ? value : null); } object? obj = (type.GetProperty("Effect", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("Spell", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(se, null); return (Spell)((obj is Spell) ? obj : null); } catch { return null; } } private static void ApplyIllusionDef(IllusionDef def) { if (def == null) { return; } currentFormKey = def.FormKey; currentPrimaryMesh = def.PrimaryMesh; currentAttackChance = def.AttackHitChance; currentSpawnClip = null; currentAttackClip = null; if (def.SpawnWav == "Skeleton_laugh") { currentSpawnClip = skeletonLaugh; } else if (def.SpawnWav == "TormentedSpawn") { currentSpawnClip = tormentedSpawn; } else if (def.SpawnWav == "HeroFemaleSpawn") { currentSpawnClip = heroFemaleSpawn; } if (def.AttackWav == "Skeleton_Attack") { currentAttackClip = skeletonAttack; } else if (def.AttackWav == "TormentedAttack") { currentAttackClip = tormentedAttack; } else if (def.AttackWav == "HeroFemaleAttack") { currentAttackClip = heroFemaleAttack; } if (def.UseSkeletonSfx) { if ((Object)(object)currentSpawnClip == (Object)null) { currentSpawnClip = skeletonLaugh; } if ((Object)(object)currentAttackClip == (Object)null) { currentAttackClip = skeletonAttack; } } } private static void RemoveOtherIllusionBuffs(IllusionDef keep) { Stats playerStats = GameData.PlayerStats; if (((playerStats != null) ? playerStats.StatusEffects : null) == null || keep == null) { return; } try { StatusEffect[] statusEffects = GameData.PlayerStats.StatusEffects; for (int i = 0; i < statusEffects.Length; i++) { IllusionDef illusionDef = ResolveIllusion(GetSpellFromStatusEffect(statusEffects[i])); if (illusionDef != null && !(illusionDef.FormKey == keep.FormKey)) { try { GameData.PlayerStats.RemoveStatusEffect(i); } catch { } } } } catch { } } private static GameObject GetOrCacheAncientWarriorSource() { if ((Object)(object)ancientWarriorTemplateCache != (Object)null) { return ancientWarriorTemplateCache; } string[] array = new string[8] { "A Lesser Avatar of Sivakaya", "Lesser Avatar of Sivakaya", "An Apparition of Sivakaya", "Apparition of Sivakaya", "The Gardener of Loomingwood", "Gardener of Loomingwood", "Sivakayan Emissary", "SivakayanEmissary" }; GameObject[] array2 = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array2) { if ((Object)(object)val == (Object)null) { continue; } string name = ((Object)val).name; bool flag = false; string[] array3 = array; foreach (string value in array3) { if (name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { flag = true; break; } } if (!flag) { continue; } SkinnedMeshRenderer[] componentsInChildren = val.GetComponentsInChildren<SkinnedMeshRenderer>(true); SkinnedMeshRenderer[] array4 = componentsInChildren; foreach (SkinnedMeshRenderer val2 in array4) { if ((Object)(object)val2 != (Object)null && (((Object)((Component)val2).gameObject).name.IndexOf("Character_Ancient_Warrior_01", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)((Component)val2).gameObject).name.IndexOf("Ancient_Warrior", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)(object)val2.sharedMesh != (Object)null && ((Object)val2.sharedMesh).name != null && ((Object)val2.sharedMesh).name.IndexOf("Ancient_Warrior", StringComparison.OrdinalIgnoreCase) >= 0))) { ancientWarriorTemplateCache = val; ancientWarriorCacheSourceName = ((Object)val).name; Debug.Log((object)("[SkeletonMod] Cached Ancient Warrior template from preferred parent: " + ((Object)val).name)); return val; } } } SkinnedMeshRenderer[] array5 = Resources.FindObjectsOfTypeAll<SkinnedMeshRenderer>(); foreach (SkinnedMeshRenderer val3 in array5) { if ((Object)(object)val3 == (Object)null || (((Object)((Component)val3).gameObject).name.IndexOf("Character_Ancient_Warrior_01", StringComparison.OrdinalIgnoreCase) < 0 && ((Object)((Component)val3).gameObject).name.IndexOf("Ancient_Warrior", StringComparison.OrdinalIgnoreCase) < 0 && (!((Object)(object)val3.sharedMesh != (Object)null) || ((Object)val3.sharedMesh).name == null || ((Object)val3.sharedMesh).name.IndexOf("Ancient_Warrior", StringComparison.OrdinalIgnoreCase) < 0))) { continue; } Transform val4 = ((Component)val3).transform; while ((Object)(object)val4.parent != (Object)null && (Object)(object)val4.parent.parent != (Object)null) { Animator componentInChildren = ((Component)val4).GetComponentInChildren<Animator>(true); Transform val5 = FindDeepChild(val4, "Hand_R") ?? FindDeepChild(val4, "Hand_L"); if ((Object)(object)componentInChildren != (Object)null || (Object)(object)val5 != (Object)null) { break; } val4 = val4.parent; } ancientWarriorTemplateCache = ((Component)val4).gameObject; ancientWarriorCacheSourceName = ((Object)((Component)val4).gameObject).name + " (mesh climb)"; Debug.Log((object)("[SkeletonMod] Cached Ancient Warrior via mesh climb: " + ancientWarriorCacheSourceName)); return ancientWarriorTemplateCache; } Debug.LogWarning((object)"[SkeletonMod] Character_Ancient_Warrior_01 not found"); return null; } private static GameObject GetOrCacheNazuraSource() { if ((Object)(object)nazuraTemplateCache != (Object)null) { return nazuraTemplateCache; } GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null || ((Object)val).name.IndexOf("Nazura", StringComparison.OrdinalIgnoreCase) < 0) { continue; } SkinnedMeshRenderer[] componentsInChildren = val.GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null && (((Object)((Component)val2).gameObject).name.IndexOf("SM_Chr_Skeleton_LightArmor_01", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)((Component)val2).gameObject).name.IndexOf("LightArmor", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)(object)val2.sharedMesh != (Object)null && ((Object)val2.sharedMesh).name != null && ((Object)val2.sharedMesh).name.IndexOf("LightArmor", StringComparison.OrdinalIgnoreCase) >= 0))) { nazuraTemplateCache = val; nazuraCacheSourceName = ((Object)val).name; Debug.Log((object)("[SkeletonMod] Cached Nazura template: " + ((Object)val).name)); return val; } } } return null; } private static void EnsureDarkLordCape(GameObject clone) { if ((Object)(object)clone == (Object)null) { return; } Transform[] componentsInChildren = clone.GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val == (Object)null || (((Object)val).name.IndexOf("SM_Chr_Attach_DarkLord_Cape_01", StringComparison.OrdinalIgnoreCase) < 0 && ((Object)val).name.IndexOf("DarkLord_Cape", StringComparison.OrdinalIgnoreCase) < 0)) { continue; } ((Component)val).gameObject.SetActive(true); Renderer[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null) { val2.enabled = true; } } Transform parent = val.parent; while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)clone.transform) { ((Component)parent).gameObject.SetActive(true); parent = parent.parent; } Debug.Log((object)("[SkeletonMod] Enabled existing DarkLord cape: " + ((Object)val).name)); break; } } private static void TryForceSkeleton() { //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) if (!IsGameplayWorld() || (Object)(object)GameData.PlayerStats == (Object)null) { return; } IllusionDef illusionDef = ResolveActiveIllusion(); if (illusionDef == null) { return; } ApplyIllusionDef(illusionDef); ShapeshiftMngr shapeShift = GetShapeShift(); if ((Object)(object)shapeShift == (Object)null) { return; } GameObject val = null; bool flag = string.Equals(currentFormKey, "HeroKnightFemale", StringComparison.OrdinalIgnoreCase) || string.Equals(currentPrimaryMesh, "Character_Ancient_Warrior_01", StringComparison.OrdinalIgnoreCase); bool flag2 = string.Equals(currentFormKey, "Skeleton", StringComparison.OrdinalIgnoreCase) || string.Equals(currentPrimaryMesh, "SM_Chr_Skeleton_LightArmor_01", StringComparison.OrdinalIgnoreCase); if (flag) { val = GetOrCacheAncientWarriorSource(); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)"[SkeletonMod] Ancient Warrior source missing – aborting Visage swap"); if ((Object)(object)shapeShift.PlayerRoot != (Object)null) { shapeShift.PlayerRoot.SetActive(true); } if ((Object)(object)shapeShift.CurrentModel != (Object)null) { shapeShift.CurrentModel.SetActive(true); } isInSkeletonForm = false; currentClone = null; return; } Debug.Log((object)("[SkeletonMod] Ancient Warrior source: " + ancientWarriorCacheSourceName + " | mesh: Character_Ancient_Warrior_01")); } else if (flag2) { val = GetOrCacheNazuraSource(); if ((Object)(object)val == (Object)null) { string[] array = new string[3] { "npcs/Skeleton Captain", "Skeleton Captain", "npcs/SkeletonCaptain" }; foreach (string text in array) { val = Resources.Load<GameObject>(text); if ((Object)(object)val != (Object)null) { break; } } } if ((Object)(object)val == (Object)null) { return; } Debug.Log((object)("[SkeletonMod] Nazura source: " + (string.IsNullOrEmpty(nazuraCacheSourceName) ? ((Object)val).name : nazuraCacheSourceName) + " | mesh: SM_Chr_Skeleton_LightArmor_01")); } else { string[] array2 = new string[3] { "npcs/Skeleton Captain", "Skeleton Captain", "npcs/SkeletonCaptain" }; foreach (string text2 in array2) { val = Resources.Load<GameObject>(text2); if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val == (Object)null) { return; } Debug.Log((object)("[SkeletonMod] Bundle: Skeleton Captain | mesh: " + currentPrimaryMesh)); } GameObject val2 = Object.Instantiate<GameObject>(val); ((Object)val2).name = "SkeletonMod_IllusionClone"; val2.SetActive(true); object obj; if (!((Object)(object)GameData.PlayerControl != (Object)null)) { Character myChar = shapeShift.MyChar; obj = ((myChar != null) ? ((Component)myChar).transform : null); } else { obj = ((Component)GameData.PlayerControl).transform; } Transform val3 = (Transform)obj; if ((Object)(object)val3 != (Object)null) { val2.transform.SetParent(val3, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; } val2.transform.localScale = Vector3.one * 1f; MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val4 in componentsInChildren) { if ((Object)(object)val4 == (Object)null) { continue; } string name = ((object)val4).GetType().Name; switch (name) { default: if (!(name == "PlayerControl")) { continue; } break; case "NPC": case "Stats": case "Character": case "LootTable": case "CastSpell": case "Inventory": case "UseSkill": case "SimPlayer": break; } ((Behaviour)val4).enabled = false; } NavMeshAgent[] componentsInChildren2 = val2.GetComponentsInChildren<NavMeshAgent>(true); foreach (NavMeshAgent val5 in componentsInChildren2) { ((Behaviour)val5).enabled = false; } Collider[] componentsInChildren3 = val2.GetComponentsInChildren<Collider>(true); foreach (Collider val6 in componentsInChildren3) { val6.enabled = false; } SkinnedMeshRenderer[] componentsInChildren4 = val2.GetComponentsInChildren<SkinnedMeshRenderer>(true); SkinnedMeshRenderer val7 = null; SkinnedMeshRenderer[] array3 = componentsInChildren4; foreach (SkinnedMeshRenderer val8 in array3) { if (!((Object)(object)((val8 != null) ? val8.sharedMesh : null) == (Object)null) && (((Object)((Component)val8).gameObject).name.IndexOf(currentPrimaryMesh, StringComparison.OrdinalIgnoreCase) >= 0 || (((Object)val8.sharedMesh).name != null && ((Object)val8.sharedMesh).name.IndexOf(currentPrimaryMesh, StringComparison.OrdinalIgnoreCase) >= 0))) { val7 = val8; break; } } if ((Object)(object)val7 == (Object)null && illusionDef.FallbackMeshes != null) { string[] fallbackMeshes = illusionDef.FallbackMeshes; foreach (string value in fallbackMeshes) { SkinnedMeshRenderer[] array4 = componentsInChildren4; foreach (SkinnedMeshRenderer val9 in array4) { if (!((Object)(object)val9 == (Object)null) && (((Object)((Component)val9).gameObject).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)(object)val9.sharedMesh != (Object)null && ((Object)val9.sharedMesh).name != null && ((Object)val9.sharedMesh).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0))) { val7 = val9; break; } } if ((Object)(object)val7 != (Object)null) { break; } } } if ((Object)(object)val7 == (Object)null && componentsInChildren4.Length != 0) { val7 = componentsInChildren4[0]; } SkinnedMeshRenderer[] array5 = componentsInChildren4; foreach (SkinnedMeshRenderer val10 in array5) { if ((Object)(object)val10 != (Object)null) { ((Component)val10).gameObject.SetActive((Object)(object)val10 == (Object)(object)val7); } } if ((Object)(object)val7 != (Object)null) { ((Component)val7).gameObject.SetActive(true); Transform val11 = ((Component)val7).transform; while ((Object)(object)val11 != (Object)null && (Object)(object)val11 != (Object)(object)val2.transform.parent) { ((Component)val11).gameObject.SetActive(true); val11 = val11.parent; } Debug.Log((object)("[SkeletonMod] Keeping mesh: " + ((Object)((Component)val7).gameObject).name)); } if (flag2) { EnsureDarkLordCape(val2); } if ((Object)(object)shapeShift.CurrentModel != (Object)null) { shapeShift.CurrentModel.SetActive(false); } shapeShift.CurrentModel = val2; if ((Object)(object)shapeShift.PlayerRoot != (Object)null) { shapeShift.PlayerRoot.SetActive(false); } Animator componentInChildren = val2.GetComponentInChildren<Animator>(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)shapeShift.MyChar != (Object)null) { shapeShift.MyChar.AssignAnim(componentInChildren); typeof(ShapeshiftMngr).GetMethod("RebindAnim", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(shapeShift, null); } currentClone = val2; isInSkeletonForm = true; missingBuffStrikes = 0; graceUntil = Time.time + 0.6f; nextCheckTime = Time.time + 0.35f; nextSoundTime = Time.time + 120f; nextAttackSfxTime = Time.time + 0.5f; weaponCycleCooldownUntil = Time.time + 0.85f; pendingF7Cycle = false; fpvActive = false; AttachPlayerWeapons(val2); lastEquipSig = BuildEquipSignature(); bool flag3 = !suppressNextSpawn; suppressNextSpawn = false; if (flag3) { PlaySpawn(force: true); } Debug.Log((object)("[SkeletonMod] Swapped to " + (((Object)(object)val7 != (Object)null) ? ((Object)((Component)val7).gameObject).name : currentPrimaryMesh) + " + weapons" + (flag3 ? "" : " (silent re-click)"))); } private static void RestoreHumanForm() { if ((Object)(object)GameData.PlayerStats == (Object)null) { return; } ClearFpvState(); ShapeshiftMngr shapeShift = GetShapeShift(); CleanupWeapons(); if ((Object)(object)currentClone != (Object)null) { Object.Destroy((Object)(object)currentClone); currentClone = null; } if ((Object)(object)shapeShift != (Object)null) { try { shapeShift.SwapToHuman(); } catch { } if ((Object)(object)shapeShift.PlayerRoot != (Object)null) { shapeShift.PlayerRoot.SetActive(true); } } isInSkeletonForm = false; missingBuffStrikes = 0; lastSpawnFormKey = ""; ForceUpdatePlayerVisuals(); Debug.Log((object)"[SkeletonMod] Forced player visual refresh"); Debug.Log((object)"[SkeletonMod] Restored human form"); } private static void CleanupWeapons() { foreach (GameObject attachedWeapon in attachedWeapons) { if ((Object)(object)attachedWeapon != (Object)null) { Object.Destroy((Object)(object)attachedWeapon); } } attachedWeapons.Clear(); } private static Transform FindDeepChild(Transform parent, string name) { if ((Object)(object)parent == (Object)null) { return null; } if (((Object)parent).name == name) { return parent; } for (int i = 0; i < parent.childCount; i++) { Transform val = FindDeepChild(parent.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Transform GetHumanRoot() { try { ShapeshiftMngr shapeShift = GetShapeShift(); if ((Object)(object)shapeShift?.PlayerRoot != (Object)null) { return shapeShift.PlayerRoot.transform; } PlayerControl playerControl = GameData.PlayerControl; return (playerControl != null) ? ((Component)playerControl).transform : null; } catch { return null; } } private static void AttachPlayerWeapons(GameObject skeletonRoot) { if ((Object)(object)skeletonRoot == (Object)null) { return; } Transform humanRoot = GetHumanRoot(); if (!((Object)(object)humanRoot == (Object)null)) { Transform val = FindDeepChild(skeletonRoot.transform, "Hand_R") ?? FindDeepChild(skeletonRoot.transform, "hand_r"); Transform val2 = FindDeepChild(skeletonRoot.transform, "Hand_L") ?? FindDeepChild(skeletonRoot.transform, "hand_l"); Transform val3 = FindDeepChild(humanRoot, "Hand_R") ?? FindDeepChild(humanRoot, "hand_r"); Transform val4 = FindDeepChild(humanRoot, "Hand_L") ?? FindDeepChild(humanRoot, "hand_l"); int num = 0; if ((Object)(object)val3 != (Object)null && (Object)(object)val != (Object)null) { num += CloneActiveWeaponMeshes(val3, val, "Right"); } if ((Object)(object)val4 != (Object)null && (Object)(object)val2 != (Object)null) { num += CloneActiveWeaponMeshes(val4, val2, "Left"); } Debug.Log((object)("[SkeletonMod][Weapons] Total: " + num)); } } private static bool IsVfxRelatedTypeName(string n) { if (string.IsNullOrEmpty(n)) { return false; } return n.IndexOf("Particle", StringComparison.OrdinalIgnoreCase) >= 0 || n.IndexOf("Trail", StringComparison.OrdinalIgnoreCase) >= 0 || n.IndexOf("VFX", StringComparison.OrdinalIgnoreCase) >= 0 || n.IndexOf("Effect", StringComparison.OrdinalIgnoreCase) >= 0 || n.IndexOf("FX", StringComparison.OrdinalIgnoreCase) >= 0; } private static int CloneActiveWeaponMeshes(Transform humanHand, Transform skelHand, string side) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) int num = 0; if ((Object)(object)humanHand == (Object)null || (Object)(object)skelHand == (Object)null) { return 0; } bool flag = string.Equals(currentFormKey, "HeroKnightFemale", StringComparison.OrdinalIgnoreCase) || string.Equals(currentPrimaryMesh, "Character_Ancient_Warrior_01", StringComparison.OrdinalIgnoreCase); bool flag2 = string.Equals(currentFormKey, "Skeleton", StringComparison.OrdinalIgnoreCase) || string.Equals(currentPrimaryMesh, "SM_Chr_Skeleton_LightArmor_01", StringComparison.OrdinalIgnoreCase); List<GameObject> list = new List<GameObject>(); Transform val = humanHand; while ((Object)(object)val != (Object)null) { if (!((Component)val).gameObject.activeSelf) { list.Add(((Component)val).gameObject); ((Component)val).gameObject.SetActive(true); } val = val.parent; } foreach (Transform item in humanHand) { Transform val2 = item; if ((Object)(object)val2 == (Object)null || !((Component)val2).gameObject.activeSelf) { continue; } string text = ((Object)val2).name.ToLowerInvariant(); if (text.Contains("hand") || text.Contains("finger") || text.Contains("wrist") || ((Object)(object)((Component)val2).GetComponentInChildren<MeshRenderer>(true) == (Object)null && (Object)(object)((Component)val2).GetComponentInChildren<SkinnedMeshRenderer>(true) == (Object)null)) { continue; } GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, skelHand); ((Object)val3).name = ((Object)val2).name; val3.SetActive(true); if (flag || flag2) { Vector3 localPosition = ((side == "Right") ? ANCIENT_WARRIOR_OFFSET_RIGHT : ANCIENT_WARRIOR_OFFSET_LEFT); val3.transform.localPosition = localPosition; val3.transform.localRotation = val2.localRotation; val3.transform.localScale = val2.localScale * 0.01f; } else { val3.transform.localPosition = val2.localPosition; val3.transform.localRotation = val2.localRotation; val3.transform.localScale = val2.localScale; } Renderer[] componentsInChildren = val3.GetComponentsInChildren<Renderer>(true); foreach (Renderer val4 in componentsInChildren) { if ((Object)(object)val4 != (Object)null) { val4.enabled = true; } } MonoBehaviour[] componentsInChildren2 = val3.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val5 in componentsInChildren2) { if (!((Object)(object)val5 == (Object)null) && !IsVfxRelatedTypeName(((object)val5).GetType().Name)) { ((Behaviour)val5).enabled = false; } } ParticleSystem[] componentsInChildren3 = val3.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val6 in componentsInChildren3) { if ((Object)(object)val6 != (Object)null && !val6.isPlaying) { val6.Play(true); } } TrailRenderer[] componentsInChildren4 = val3.GetComponentsInChildren<TrailRenderer>(true); foreach (TrailRenderer val7 in componentsInChildren4) { if (!((Object)(object)val7 == (Object)null)) { ((Renderer)val7).enabled = true; val7.Clear(); } } LineRenderer[] componentsInChildren5 = val3.GetComponentsInChildren<LineRenderer>(true); foreach (LineRenderer val8 in componentsInChildren5) { if ((Object)(object)val8 != (Object)null) { ((Renderer)val8).enabled = true; } } attachedWeapons.Add(val3); num++; Debug.Log((object)("[SkeletonMod][Weapons] Attached " + side + ": " + ((Object)val2).name + ((flag || flag2) ? " (scale 0.01 + Anubis offsets)" : ""))); } foreach (GameObject item2 in list) { if ((Object)(object)item2 != (Object)null) { item2.SetActive(false); } } return num; } private static void EnsureSfxSource() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)sfxSource != (Object)null)) { GameObject val = new GameObject("SkeletonMod_SFX"); Object.DontDestroyOnLoad((Object)(object)val); sfxSource = val.AddComponent<AudioSource>(); sfxSource.playOnAwake = false; sfxSource.spatialBlend = 0f; sfxSource.volume = 1f; } } private static void TryLoadSounds() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); skeletonLaugh = LoadWavFromDir(directoryName, "Skeleton_laugh"); skeletonAttack = LoadWavFromDir(directoryName, "Skeleton_Attack"); tormentedSpawn = LoadWavFromDir(directoryName, "TormentedSpawn"); tormentedAttack = LoadWavFromDir(directoryName, "TormentedAttack"); heroFemaleSpawn = LoadWavFromDir(directoryName, "HeroFemaleSpawn"); heroFemaleAttack = LoadWavFromDir(directoryName, "HeroFemaleAttack"); dingClip = LoadWavFromDir(directoryName, "EQ_DING"); Debug.Log((object)"[SkeletonMod] Sounds loaded"); } private static AudioClip LoadWavFromDir(string dir, string baseName) { if (string.IsNullOrEmpty(dir)) { return null; } string[] array = new string[2] { Path.Combine(dir, baseName + ".wav"), Path.Combine(dir, baseName) }; foreach (string path in array) { if (File.Exists(path)) { AudioClip val = LoadWavFile(path); if ((Object)(object)val != (Object)null) { ((Object)val).name = baseName; Debug.Log((object)("[SkeletonMod] WAV loaded: " + baseName)); return val; } } } return null; } private static AudioClip LoadWavFile(string path) { try { byte[] array = File.ReadAllBytes(path); if (array.Length < 44 || array[0] != 82) { return null; } int num = BitConverter.ToInt16(array, 22); int num2 = BitConverter.ToInt32(array, 24); int num3 = BitConverter.ToInt16(array, 34); int num4 = BitConverter.ToInt16(array, 20); int i = 12; int num5 = 0; int num6; for (; i + 8 < array.Length; i += 8 + num6) { string text = Encoding.ASCII.GetString(array, i, 4); num6 = BitConverter.ToInt32(array, i + 4); if (text == "data") { i += 8; num5 = num6; break; } } if (num5 <= 0) { return null; } int num7; float[] array2; if (num4 == 1 && num3 == 16) { num7 = num5 / 2; array2 = new float[num7]; for (int j = 0; j < num7; j++) { array2[j] = (float)BitConverter.ToInt16(array, i + j * 2) / 32768f; } } else { if (num4 != 1 || num3 != 8) { return null; } num7 = num5; array2 = new float[num7]; for (int k = 0; k < num7; k++) { array2[k] = (float)(array[i + k] - 128) / 128f; } } AudioClip val = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num7 / Mathf.Max(1, num), num, num2, false); val.SetData(array2, 0); return val; } catch { return null; } } private static void PlayClip(AudioClip clip, float vol = 1f) { if (!((Object)(object)clip == (Object)null)) { EnsureSfxSource(); if ((Object)(object)sfxSource != (Object)null) { sfxSource.PlayOneShot(clip, vol); Debug.Log((object)("[SkeletonMod] *sound* " + ((Object)clip).name)); } } } private static void PlaySpawn(bool force) { if (IsGameplayWorld() && (!(Time.time < spawnSfxReadyAt) || force)) { PlayClip(currentSpawnClip ?? skeletonLaugh); lastSpawnFormKey = currentFormKey; } } private static void PlayAttack() { if (IsGameplayWorld()) { PlayClip(currentAttackClip, 0.9f); } } private static void CheckLevelUpDing() { if ((Object)(object)GameData.PlayerStats == (Object)null) { return; } int level = GameData.PlayerStats.Level; if (lastKnownLevel < 0) { lastKnownLevel = level; } else if (level > lastKnownLevel) { int num = level - lastKnownLevel; lastKnownLevel = level; if (num <= 3 && IsGameplayWorld()) { PlayClip(dingClip); } } else if (level < lastKnownLevel) { lastKnownLevel = level; } } }