using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.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);
}
}