Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SSVoidsong v1.1.0
HKVoidsongMod.dll
Decompiled 6 months 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 BepInEx; using GlobalSettings; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("HKVoidsongMod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HKVoidsongMod")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1d46aad1-ba46-46ed-ad7e-6a5ad731ed2e")] [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")] [BepInPlugin("com.layeredone.SSVS", "SSVoidsong", "1.0.0")] public class VoidSongMod : BaseUnityPlugin { [CompilerGenerated] private sealed class <ActivateAttackRoutine>d__20 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public BlackThreadState __instance; public GameObject attackObj; private GameObject <attackObjClone>5__1; private FieldInfo <atkField>5__2; private BlackThreadAttack <atk>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ActivateAttackRoutine>d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <attackObjClone>5__1 = null; <atkField>5__2 = null; <atk>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <attackObjClone>5__1 = Object.Instantiate<GameObject>(attackObj, ((Component)__instance).transform.position, Quaternion.identity); if ((Object)(object)<attackObjClone>5__1 == (Object)null) { return false; } <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; case 1: { <>1__state = -1; <atkField>5__2 = typeof(BlackThreadState).GetField("chosenAttack", BindingFlags.Instance | BindingFlags.NonPublic); ref BlackThreadAttack reference = ref <atk>5__3; object? obj = <atkField>5__2?.GetValue(__instance); reference = (BlackThreadAttack)((obj is BlackThreadAttack) ? obj : null); <attackObjClone>5__1.SetActive(true); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 2; return true; } case 2: <>1__state = -1; Object.Destroy((Object)(object)<attackObjClone>5__1, 3f); <>2__current = (object)new WaitForSeconds(3f); <>1__state = 3; return true; case 3: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DummyIdleRoutine>d__21 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DummyIdleRoutine>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } <>2__current = null; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SimpleThreadRoutine>d__18 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public BlackThreadState state; private MethodInfo <setVisiblyThreaded>5__1; private GameObject <startEffect>5__2; private MethodInfo <setBlackThreadAmount>5__3; private MethodInfo <startAttackTest>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SimpleThreadRoutine>d__18(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <setVisiblyThreaded>5__1 = null; <startEffect>5__2 = null; <setBlackThreadAmount>5__3 = null; <startAttackTest>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <setVisiblyThreaded>5__1 = typeof(BlackThreadState).GetMethod("SetVisiblyThreaded", BindingFlags.Instance | BindingFlags.NonPublic); <setVisiblyThreaded>5__1?.Invoke(state, null); <startEffect>5__2 = Effects.BlackThreadEnemyStartEffect; if ((Object)(object)<startEffect>5__2 != (Object)null) { ObjectPoolExtensions.Spawn(<startEffect>5__2, ((Component)state).transform, Vector2.op_Implicit(Vector2.zero)); } <setBlackThreadAmount>5__3 = typeof(BlackThreadState).GetMethod("SetBlackThreadAmount", BindingFlags.Instance | BindingFlags.NonPublic); <setBlackThreadAmount>5__3?.Invoke(state, new object[1] { 1f }); <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; <startAttackTest>5__4 = typeof(BlackThreadState).GetMethod("StartAttackTest", BindingFlags.Instance | BindingFlags.NonPublic); break; case 2: <>1__state = -1; break; } <startAttackTest>5__4?.Invoke(state, null); <>2__current = (object)new WaitForSeconds(Random.Range(3f, 10f)); <>1__state = 2; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <WaitFix>d__7 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public VoidSongMod <>4__this; private IEnumerable<AssetBundle> <existingBundles>5__1; private string <markedAsset>5__2; private IEnumerator<AssetBundle> <>s__3; private AssetBundle <ab>5__4; private string[] <>s__5; private int <>s__6; private string <assetName>5__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitFix>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <existingBundles>5__1 = null; <markedAsset>5__2 = null; <>s__3 = null; <ab>5__4 = null; <>s__5 = null; <assetName>5__7 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(5f); <>1__state = 1; return true; case 1: <>1__state = -1; ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)">>>VoidHelper>>>Loading Void Attacks AssetBundle..."); <existingBundles>5__1 = AssetBundle.GetAllLoadedAssetBundles(); <markedAsset>5__2 = "Assets/Data Assets/Black Thread Attacks/Ball.asset"; voidAttacksBundle = null; <>s__3 = <existingBundles>5__1.GetEnumerator(); try { while (<>s__3.MoveNext()) { <ab>5__4 = <>s__3.Current; if (<ab>5__4.Contains(<markedAsset>5__2)) { voidAttacksBundle = <ab>5__4; ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)(">>>VoidHelper>>>Found VoidAttacksBundle: " + ((Object)<ab>5__4).name)); break; } <ab>5__4 = null; } } finally { if (<>s__3 != null) { <>s__3.Dispose(); } } <>s__3 = null; if ((Object)(object)voidAttacksBundle == (Object)null) { voidAttacksBundle = <>4__this.LoadBundleHelper("blackthread_assets_all.bundle"); } <>s__5 = voidAttacksBundle.GetAllAssetNames(); for (<>s__6 = 0; <>s__6 < <>s__5.Length; <>s__6++) { <assetName>5__7 = <>s__5[<>s__6]; Debug.Log((object)(">>>VoidSong:AssetLogger>>>Asset in bundle: " + <assetName>5__7)); <assetName>5__7 = null; } <>s__5 = null; ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)">>>VoidHelper>>>AssetBundle Load Attempt Finished."); Harmony.CreateAndPatchAll(typeof(VoidSongMod), (string)null); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static AssetBundle voidAttacksBundle; private static bool canRandomizeAttacks = true; private static Dictionary<AssetBundle, string> bundlePaths = new Dictionary<AssetBundle, string>(); private static GameObject cachedWorkingAttackPrefab = new GameObject(); private static string GetPlatformFolderName() { //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) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 RuntimePlatform platform = Application.platform; RuntimePlatform val = platform; if ((int)val <= 2) { if ((int)val <= 1) { return "StandaloneOSX"; } if ((int)val == 2) { goto IL_002d; } } else { if ((int)val == 7) { goto IL_002d; } if ((int)val == 13 || (int)val == 16) { return "StandaloneLinux64"; } } Debug.LogWarning((object)"Didnt find platform, going to default StandaloneWindows64"); return "StandaloneWindows64"; IL_002d: return "StandaloneWindows64"; } private AssetBundle LoadBundleHelper(string bundleName) { if ((Object)(object)voidAttacksBundle != (Object)null) { return voidAttacksBundle; } string text = Path.Combine(Application.dataPath, "StreamingAssets", "aa", GetPlatformFolderName(), bundleName); if (File.Exists(text)) { AssetBundle val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)"Failed to load AssetBundle!"); return null; } Debug.Log((object)"AssetBundle loaded successfully."); string[] allAssetNames = val.GetAllAssetNames(); foreach (string text2 in allAssetNames) { Debug.Log((object)(">>>VoidSong:AssetLogger>>>Asset in bundle: " + text2)); } if (bundleName == "blackthread_assets_all.bundle") { voidAttacksBundle = val; } return val; } Debug.LogWarning((object)("AssetBundle file not found at path: " + text)); return null; } private static GameObject LoadPref(string prefName) { if ((Object)(object)voidAttacksBundle == (Object)null) { return null; } return voidAttacksBundle.LoadAsset<GameObject>(prefName); } private static BlackThreadAttack LoadAttackAsset(string assetName) { if ((Object)(object)voidAttacksBundle == (Object)null) { return null; } return voidAttacksBundle.LoadAsset<BlackThreadAttack>(assetName); } private void Awake() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin loaded and initialized."); ((MonoBehaviour)this).StartCoroutine(WaitFix()); } [IteratorStateMachine(typeof(<WaitFix>d__7))] private IEnumerator WaitFix() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitFix>d__7(0) { <>4__this = this }; } [HarmonyPatch(typeof(PlayMakerFSM), "Awake")] private static void PostFix(PlayMakerFSM __instance) { GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)gameObject == (Object)null || (Object)(object)__instance == (Object)null || __instance.Fsm == null) { return; } FsmState state = __instance.Fsm.GetState("P1"); if (state != null) { safeSet<SetFloatValue>(state.Actions.OfType<SetFloatValue>().FirstOrDefault((Func<SetFloatValue, bool>)((SetFloatValue a) => a.floatVariable != null && ((NamedVariable)a.floatVariable).Name == "Idle Time")), delegate(SetFloatValue a) { a.floatValue = FsmFloat.op_Implicit(0f); }); safeSet<SetFloatValue>(state.Actions.OfType<SetFloatValue>().FirstOrDefault((Func<SetFloatValue, bool>)((SetFloatValue a) => a.floatVariable != null && ((NamedVariable)a.floatVariable).Name == "Time Between Attacks")), delegate(SetFloatValue a) { a.floatValue = FsmFloat.op_Implicit(0f); }); safeSet<SetStringValue>(state.Actions.OfType<SetStringValue>().FirstOrDefault((Func<SetStringValue, bool>)((SetStringValue a) => a.stringVariable != null && ((NamedVariable)a.stringVariable).Name == "isFalse")), delegate(SetStringValue a) { a.stringValue = FsmString.op_Implicit(""); }); safeSet<SetFloatValue>(state.Actions.OfType<SetFloatValue>().FirstOrDefault((Func<SetFloatValue, bool>)((SetFloatValue a) => a.floatVariable != null && ((NamedVariable)a.floatVariable).Name == "time")), delegate(SetFloatValue a) { a.floatValue = FsmFloat.op_Implicit(0f); }); safeSet<SetFloatValue>(state.Actions.OfType<SetFloatValue>().FirstOrDefault((Func<SetFloatValue, bool>)((SetFloatValue a) => a.floatVariable != null && ((NamedVariable)a.floatVariable).Name == "delay")), delegate(SetFloatValue a) { a.floatValue = FsmFloat.op_Implicit(0f); }); safeSet<SetFloatValue>(state.Actions.OfType<SetFloatValue>().FirstOrDefault((Func<SetFloatValue, bool>)((SetFloatValue a) => a.floatVariable != null && ((NamedVariable)a.floatVariable).Name == "Delay")), delegate(SetFloatValue a) { a.floatValue = FsmFloat.op_Implicit(0f); }); safeSet<SetIntValue>(state.Actions.OfType<SetIntValue>().FirstOrDefault((Func<SetIntValue, bool>)((SetIntValue a) => a.intVariable != null && ((NamedVariable)a.intVariable).Name == "damageAmount")), delegate(SetIntValue a) { a.intValue = FsmInt.op_Implicit(3); }); safeSet<SetColorValue>(state.Actions.OfType<SetColorValue>().FirstOrDefault((Func<SetColorValue, bool>)((SetColorValue a) => a.colorVariable != null && ((NamedVariable)a.colorVariable).Name == "color")), delegate(SetColorValue a) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) a.color = FsmColor.op_Implicit(new Color(23f / 85f, 1f / 85f, 0.47843137f, 1f)); }); } static void safeSet<T>(T action, Action<T> setter) where T : class { if (action != null) { setter(action); } } } [HarmonyPatch(typeof(PlayerData), "Awake")] private static void PlayerData_PostFix(PlayerData __instance) { if (__instance != null) { __instance.blackThreadWorld = true; __instance.defeatedCloverDancers = false; __instance.cloverDancerRegrowth = false; __instance.pilbyKilled = false; Debug.Log((object)"PlayerData modified to allow access to verdania again and other qol."); } } [HarmonyPatch(typeof(HealthManager), "Start")] [HarmonyPostfix] private static void HealthManager_PostFix(HealthManager __instance) { if ((Object)(object)__instance != (Object)null) { GameObject gameObject = ((Component)__instance).gameObject; __instance.hp *= 3; if ((Object)(object)gameObject.GetComponent<BlackThreadState>() == (Object)null) { gameObject.AddComponent<BlackThreadState>(); Debug.Log((object)("Added CustomEnemyBlackThreadState to " + ((Object)gameObject).name)); } } } [HarmonyPatch(typeof(BlackThreadState), "Start")] [HarmonyPrefix] private static void InjectCustomAttacksToBlackThreadAttack_PreFix(BlackThreadState __instance) { GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)__instance == (Object)null) { __instance = gameObject.AddComponent<BlackThreadState>(); } if (!((Object)(object)__instance != (Object)null)) { return; } FieldInfo field = typeof(BlackThreadState).GetField("attacks", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { Debug.Log((object)"Found BlackThreadAttack.attacks field"); BlackThreadAttack val = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/Ball.asset"); BlackThreadAttack val2 = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/Grand Vomit.asset"); BlackThreadAttack val3 = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/Heavy Vomit.asset"); BlackThreadAttack val4 = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/MachineGun Shot Garmond.asset"); BlackThreadAttack val5 = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/MachineGun Shot.asset"); BlackThreadAttack val6 = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/Shot.asset"); BlackThreadAttack val7 = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/Vomit Drop.asset"); BlackThreadAttack val8 = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/Vomit.asset"); BlackThreadAttack val9 = LoadAttackAsset("Assets/Data Assets/Black Thread Attacks/Whip.asset"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { Debug.Log((object)">>>VoidHelper>>>One or more BlackThreadAttack assets failed to load!"); } field.SetValue(__instance, new BlackThreadAttack[9] { val, val2, val3, val4, val5, val6, val7, val8, val9 }); Debug.Log((object)(">>>VoidHelper>>>3 BlackThreadAttacks Added for: " + ((Object)__instance).name)); } } [HarmonyPatch(typeof(BlackThreadState), "Start")] [HarmonyPostfix] private static void BlackThreadState_Start_Postfix(BlackThreadState __instance) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) EnsureValidPrefabs(__instance); BlackThreadAttack[] array = typeof(BlackThreadState).GetField("attacks", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) as BlackThreadAttack[]; Dictionary<BlackThreadAttack, GameObject> dictionary = typeof(BlackThreadState).GetField("spawnedAttackObjs", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) as Dictionary<BlackThreadAttack, GameObject>; if (array != null && dictionary != null) { BlackThreadAttack[] array2 = array; foreach (BlackThreadAttack val in array2) { if ((Object)(object)val != (Object)null && (Object)(object)val.Prefab != (Object)null && !dictionary.ContainsKey(val)) { GameObject val2 = Object.Instantiate<GameObject>(val.Prefab, ((Component)__instance).transform); val2.transform.localPosition = Vector3.zero; val2.SetActive(false); dictionary[val] = val2; Debug.Log((object)("VoidSong: Spawned prefab for " + ((Object)val).name)); } } } __instance.BecomeThreadedNoSing(); } private static void EnsureValidPrefabs(BlackThreadState state) { if (!(typeof(BlackThreadState).GetField("attacks", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(state) is BlackThreadAttack[] array)) { return; } BlackThreadAttack[] array2 = array; foreach (BlackThreadAttack val in array2) { if ((Object)(object)val == (Object)null) { continue; } FieldInfo field = typeof(BlackThreadAttack).GetField("Prefab", BindingFlags.Instance | BindingFlags.Public); object? obj = field?.GetValue(val); GameObject val2 = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val2 == (Object)null) { GameObject val3 = null; if ((Object)(object)cachedWorkingAttackPrefab != (Object)null) { val3 = Object.Instantiate<GameObject>(cachedWorkingAttackPrefab); Debug.Log((object)("VoidSong_FallbackManager: Using cached working prefab " + ((Object)val3).name + " for attack " + ((Object)val).name)); } else { val3 = LoadPref("Assets/Prefabs/Props/Thread Spines/thread_spines_standard.prefab"); } if ((Object)(object)val3 != (Object)null) { field?.SetValue(val, val3); ((Object)val).name = ((Object)val).name + "_VsFallbackFix"; Debug.Log((object)("VoidSong_FallbackManager: Assigned real prefab " + ((Object)val3).name + " to attack " + ((Object)val).name)); } } else { Debug.Log((object)("VoidSong_FallbackManager: Attack " + ((Object)val).name + " already has a valid prefab: " + ((Object)val2).name)); Debug.Log((object)"VoidSong_FallbackManager: This prefab will be new fallback obj"); cachedWorkingAttackPrefab = val2; } } } [HarmonyPatch(typeof(BlackThreadState), "ChooseAttack")] [HarmonyPrefix] private static bool ForceChooseAttack_Prefix(BlackThreadState __instance, bool force) { if (typeof(BlackThreadState).GetField("attacks", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) is BlackThreadAttack[] array && array.Length != 0) { BlackThreadAttack val = array[Random.Range(0, array.Length)]; typeof(BlackThreadState).GetField("chosenAttack", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(__instance, val); typeof(BlackThreadState).GetField("hasChosenAttack", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(__instance, true); Debug.Log((object)("Forced attack: " + ((Object)val).name + " | for: " + ((Object)__instance).name)); return false; } return true; } [HarmonyPatch(typeof(BlackThreadState), "BecomeThreadedRoutine")] [HarmonyPrefix] private static bool BecomeThreadedRoutine_Prefix(BlackThreadState __instance, ref IEnumerator __result, bool waitForSing) { FieldInfo field = typeof(BlackThreadState).GetField("singFsm", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = typeof(BlackThreadState).GetField("stunControlFsm", BindingFlags.Instance | BindingFlags.NonPublic); object? obj = field?.GetValue(__instance); PlayMakerFSM val = (PlayMakerFSM)((obj is PlayMakerFSM) ? obj : null); object? obj2 = field2?.GetValue(__instance); PlayMakerFSM val2 = (PlayMakerFSM)((obj2 is PlayMakerFSM) ? obj2 : null); if ((Object)(object)val != (Object)null || (Object)(object)val2 != (Object)null) { Debug.Log((object)(">>>VoidSong_EnemyVoidSkipper>>>: " + ((Object)__instance).name + " has no sing/stun FSM, using Simple threading that avoids waits.")); __result = SimpleThreadRoutine(__instance); return false; } return true; } [IteratorStateMachine(typeof(<SimpleThreadRoutine>d__18))] private static IEnumerator SimpleThreadRoutine(BlackThreadState state) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SimpleThreadRoutine>d__18(0) { state = state }; } [HarmonyPatch(typeof(BlackThreadState), "ThreadAttackTest")] [HarmonyPrefix] private static bool ThreadAttackTest_Prefix(BlackThreadState __instance, ref IEnumerator __result) { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) object? obj = typeof(BlackThreadState).GetField("chosenAttack", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance); BlackThreadAttack val = (BlackThreadAttack)((obj is BlackThreadAttack) ? obj : null); BlackThreadAttack[] array = typeof(BlackThreadState).GetField("attacks", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) as BlackThreadAttack[]; Dictionary<BlackThreadAttack, GameObject> dictionary = typeof(BlackThreadState).GetField("spawnedAttackObjs", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) as Dictionary<BlackThreadAttack, GameObject>; if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)("VoidSong: " + ((Object)__instance).name + " has no chosenAttack, skipping.")); __result = DummyIdleRoutine(); return false; } if (canRandomizeAttacks) { val = array[Random.Range(0, array.Length)]; } GameObject val2 = null; if (dictionary != null && dictionary.ContainsKey(val)) { val2 = dictionary[val]; } if ((Object)(object)val2 == (Object)null) { object? obj2 = typeof(BlackThreadAttack).GetField("Prefab", BindingFlags.Instance | BindingFlags.Public)?.GetValue(val); GameObject val3 = (GameObject)((obj2 is GameObject) ? obj2 : null); if (!((Object)(object)val3 != (Object)null)) { Debug.LogWarning((object)("VoidSong: " + ((Object)__instance).name + " has no prefab for " + ((Object)val).name + ", skipping.")); __result = DummyIdleRoutine(); return false; } val2 = Object.Instantiate<GameObject>(val3, ((Component)__instance).transform.position, Quaternion.identity); val2.SetActive(true); Debug.Log((object)("VoidSong: Fallback-spawned prefab " + ((Object)val3).name + " for " + ((Object)__instance).name)); } __result = ActivateAttackRoutine(__instance, val2); return false; } [IteratorStateMachine(typeof(<ActivateAttackRoutine>d__20))] private static IEnumerator ActivateAttackRoutine(BlackThreadState __instance, GameObject attackObj) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ActivateAttackRoutine>d__20(0) { __instance = __instance, attackObj = attackObj }; } [IteratorStateMachine(typeof(<DummyIdleRoutine>d__21))] private static IEnumerator DummyIdleRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DummyIdleRoutine>d__21(0); } }