Decompiled source of RitualDaggerZombieSacrifice v1.1.7

plugins/OvrSlepr_RitualDaggerZombieSacrifice.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using HarmonyLib;
using Peak;
using Photon.Pun;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("OvrSlepr_RitualDaggerZombieSacrifice")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("OvrSlepr_RitualDaggerZombieSacrifice")]
[assembly: AssemblyTitle("OvrSlepr_RitualDaggerZombieSacrifice")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.ovrslepr.peak.zombiedagger", "Ritual Dagger: Zombie Sacrifice", "1.1.5")]
public class ZombieDaggerPlugin : BaseUnityPlugin
{
	private void Awake()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		new Harmony("com.ovrslepr.peak.zombiedagger").PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[ZombieDaggerMod] Version 1.1.4 loaded.");
		ZombieDaggerDiagnostics.DumpZombieTemplates("Plugin.Awake");
		((MonoBehaviour)this).StartCoroutine(ZombieDaggerDiagnostics.DelayedScans());
		((MonoBehaviour)this).StartCoroutine(ZombieDaggerDiagnostics.TrackZombieTemplate());
		((MonoBehaviour)this).StartCoroutine(ZombieDaggerDiagnostics.RetryTfaTemplateLookup());
	}
}
internal static class ZombieDaggerDiagnostics
{
	private static bool firstAwakeScanDone;

	public static IEnumerator RetryTfaTemplateLookup()
	{
		Type cloudType = AccessTools.TypeByName("TrueFinalAscent.FinalAscentSporeCloud");
		if (cloudType == null)
		{
			Debug.LogError((object)"[ZombieDaggerDiag] TFA spore cloud type not found. Retry workaround disabled.");
			yield break;
		}
		FieldInfo searchedField = AccessTools.Field(cloudType, "_searched");
		FieldInfo seedField = AccessTools.Field(cloudType, "_seed");
		if (searchedField == null || seedField == null)
		{
			Debug.LogError((object)"[ZombieDaggerDiag] TFA fields _searched/_seed not found. Retry workaround disabled.");
			yield break;
		}
		Debug.Log((object)"[ZombieDaggerDiag] TFA template retry workaround started.");
		while (true)
		{
			yield return (object)new WaitForSecondsRealtime(3f);
			try
			{
				object? value = seedField.GetValue(null);
				GameObject seed = (GameObject)((value is GameObject) ? value : null);
				bool searched = (bool)searchedField.GetValue(null);
				if (!((Object)(object)seed != (Object)null) && searched)
				{
					searchedField.SetValue(null, false);
					Debug.Log((object)"[ZombieDaggerDiag] TFA template was null; retry flag reset.");
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[ZombieDaggerDiag] TFA retry failed: " + ex));
			}
		}
	}

	public static IEnumerator DelayedScans()
	{
		float[] delays = new float[3] { 10f, 25f, 40f };
		float[] array = delays;
		for (int i = 0; i < array.Length; i++)
		{
			float delay = array[i];
			yield return (object)new WaitForSecondsRealtime(delay);
			DumpZombieTemplates("Delayed scan after " + delay + " seconds");
		}
	}

	public static IEnumerator TrackZombieTemplate()
	{
		MushroomZombie tracked = null;
		int trackedId = 0;
		string lastSnapshot = null;
		Debug.Log((object)"[ZombieDaggerDiag] Template tracker started");
		for (int sample = 1; sample <= 24; sample++)
		{
			yield return (object)new WaitForSecondsRealtime(5f);
			MushroomZombie[] all = Resources.FindObjectsOfTypeAll<MushroomZombie>();
			int total = 0;
			int prefabCount = 0;
			int targetCount = 0;
			int targetSceneCount = 0;
			bool foundTrackedInResources = false;
			StringBuilder snapshot = new StringBuilder();
			MushroomZombie[] array = all;
			foreach (MushroomZombie zombie in array)
			{
				if ((Object)(object)zombie == (Object)null)
				{
					continue;
				}
				total++;
				GameObject go = ((Component)zombie).gameObject;
				Scene scene = go.scene;
				bool sceneValid = ((Scene)(ref scene)).IsValid();
				bool active = go.activeInHierarchy;
				int id = ((Object)go).GetInstanceID();
				if (!sceneValid)
				{
					prefabCount++;
				}
				if (((Object)go).name == "MushroomZombie_Player")
				{
					targetCount++;
					if (sceneValid)
					{
						targetSceneCount++;
					}
					if (!sceneValid && (Object)(object)tracked == (Object)null)
					{
						tracked = zombie;
						trackedId = id;
						Debug.Log((object)("[ZombieDaggerDiag] TARGET ACQUIRED | name=" + ((Object)go).name + " | instanceId=" + id + " | active=" + active + " | sceneValid=" + sceneValid));
					}
				}
				if ((Object)(object)tracked != (Object)null && (Object)(object)zombie == (Object)(object)tracked)
				{
					foundTrackedInResources = true;
				}
				snapshot.Append(((Object)go).name).Append("|id=").Append(id)
					.Append("|sceneValid=")
					.Append(sceneValid)
					.Append("|active=")
					.Append(active)
					.Append(";");
			}
			bool referenceAlive = (Object)(object)tracked != (Object)null;
			string snapshotText = snapshot.ToString();
			if (snapshotText != lastSnapshot)
			{
				Debug.Log((object)("[ZombieDaggerDiag] RESOURCE SNAPSHOT | sample=" + sample + " | total=" + total + " | prefabs=" + prefabCount + " | targetNamed=" + targetCount + " | targetInScene=" + targetSceneCount + " | referenceAlive=" + referenceAlive + " | trackedInResources=" + foundTrackedInResources + " | trackedInstanceId=" + (referenceAlive ? trackedId : 0) + " | objects=" + snapshotText));
				lastSnapshot = snapshotText;
			}
			else
			{
				Debug.Log((object)("[ZombieDaggerDiag] Template check | sample=" + sample + " | total=" + total + " | prefabs=" + prefabCount + " | targetNamed=" + targetCount + " | targetInScene=" + targetSceneCount + " | referenceAlive=" + referenceAlive + " | trackedInResources=" + foundTrackedInResources + " | trackedInstanceId=" + (referenceAlive ? trackedId : 0)));
			}
			if (trackedId != 0 && !referenceAlive)
			{
				Debug.LogWarning((object)("[ZombieDaggerDiag] TRACKED TEMPLATE LOST | previousInstanceId=" + trackedId + " | sample=" + sample));
				tracked = null;
				trackedId = 0;
			}
			else if (referenceAlive && !foundTrackedInResources)
			{
				Debug.LogWarning((object)("[ZombieDaggerDiag] TRACKED TEMPLATE NOT IN RESOURCES | instanceId=" + trackedId + " | sample=" + sample));
			}
		}
		Debug.Log((object)"[ZombieDaggerDiag] Template tracker finished");
	}

	public static void LogZombieAwake(MushroomZombie zombie)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)zombie == (Object)null)
			{
				Debug.LogWarning((object)"[ZombieDaggerDiag] MushroomZombie.Awake: instance is null.");
				return;
			}
			GameObject gameObject = ((Component)zombie).gameObject;
			string[] obj = new string[8]
			{
				"[ZombieDaggerDiag] MushroomZombie.Awake | object=",
				((Object)gameObject).name,
				" | sceneValid=",
				null,
				null,
				null,
				null,
				null
			};
			Scene scene = gameObject.scene;
			obj[3] = ((Scene)(ref scene)).IsValid().ToString();
			obj[4] = " | active=";
			obj[5] = gameObject.activeInHierarchy.ToString();
			obj[6] = " | instanceId=";
			obj[7] = ((Object)gameObject).GetInstanceID().ToString();
			Debug.Log((object)string.Concat(obj));
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[ZombieDaggerDiag] Awake diagnostic error: " + ex));
		}
		if (!firstAwakeScanDone)
		{
			firstAwakeScanDone = true;
			DumpZombieTemplates("First MushroomZombie.Awake");
		}
	}

	public static void DumpZombieTemplates(string reason)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			MushroomZombie[] array = Resources.FindObjectsOfTypeAll<MushroomZombie>();
			Debug.Log((object)("[ZombieDaggerDiag] Template scan BEGIN | reason=" + reason + " | count=" + array.Length));
			int num = 0;
			MushroomZombie[] array2 = array;
			foreach (MushroomZombie val in array2)
			{
				if (!((Object)(object)val == (Object)null))
				{
					GameObject gameObject = ((Component)val).gameObject;
					Scene scene = gameObject.scene;
					bool flag = ((Scene)(ref scene)).IsValid();
					bool flag2 = !flag;
					if (flag2)
					{
						num++;
					}
					Debug.Log((object)("[ZombieDaggerDiag] Candidate | object=" + ((Object)gameObject).name + " | sceneValid=" + flag + " | active=" + gameObject.activeInHierarchy + " | instanceId=" + ((Object)gameObject).GetInstanceID() + " | acceptedByTFA=" + flag2));
				}
			}
			Debug.Log((object)("[ZombieDaggerDiag] Template scan END | reason=" + reason + " | total=" + array.Length + " | acceptedByTFA=" + num));
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[ZombieDaggerDiag] Template scan failed: " + ex));
		}
	}
}
[HarmonyPatch(typeof(LootData), "PopulateLootData")]
public static class RitualDaggerPoolDebugPatch
{
	private const ushort RitualDaggerId = 173;

	private const int RitualDaggerWeight = 15;

	[HarmonyPostfix]
	public static void Postfix()
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Item val = default(Item);
			if (!ItemDatabase.TryGetItem((ushort)173, ref val) || (Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)"[ZombieDaggerMod] RitualDagger ID 173 not found.");
				return;
			}
			LootData component = ((Component)val).GetComponent<LootData>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)"[ZombieDaggerMod] RitualDagger has no LootData.");
				return;
			}
			component.banInSolo = false;
			component.spawnLocations = (SpawnPool)(component.spawnLocations | 0x8000);
			if (LootData.AllSpawnWeightData == null)
			{
				Debug.LogWarning((object)"[ZombieDaggerMod] Loot pools are not initialized.");
				return;
			}
			if (!LootData.AllSpawnWeightData.TryGetValue((SpawnPool)32768, out var value) || value == null)
			{
				Debug.LogWarning((object)"[ZombieDaggerMod] LuggageAncient pool not found.");
				return;
			}
			value[173] = 15;
			Debug.Log((object)("[ZombieDaggerMod] RitualDagger spawn patched. | ID=" + (ushort)173 + " | Pool=LuggageAncient | Weight=" + 15 + " | banInSolo=" + component.banInSolo + " | spawnLocations=" + ((object)Unsafe.As<SpawnPool, SpawnPool>(ref component.spawnLocations)/*cast due to .constrained prefix*/).ToString()));
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[ZombieDaggerMod] RitualDagger spawn patch failed: " + ex));
		}
	}
}
[HarmonyPatch(typeof(MushroomZombie), "Awake")]
public static class ZombieNetworkSetupPatch
{
	[HarmonyPostfix]
	public static void Postfix(MushroomZombie __instance)
	{
		ZombieDaggerDiagnostics.LogZombieAwake(__instance);
		if (!((Object)(object)__instance == (Object)null))
		{
			ZombieSacrificeNetwork.ClearStaleStateForNewZombie(__instance);
			ZombieSacrificeNetwork.EnsureInstalled(__instance);
		}
	}
}
[HarmonyPatch(typeof(CharacterCustomization), "OnPlayerDataChange")]
public static class ZombieEyesSyncPatch
{
	[HarmonyPostfix]
	public static void Postfix(CharacterCustomization __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		MushroomZombie val = ((Component)__instance).GetComponent<MushroomZombie>();
		if ((Object)(object)val == (Object)null)
		{
			val = ((Component)__instance).GetComponentInParent<MushroomZombie>();
		}
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		try
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(MushroomZombie), "zombieEyeTexture");
			MethodInfo methodInfo = AccessTools.Method(typeof(MushroomZombie), "SetZombieEyes", (Type[])null, (Type[])null);
			if (!(fieldInfo == null) && !(methodInfo == null))
			{
				object? value = fieldInfo.GetValue(val);
				Texture val2 = (Texture)((value is Texture) ? value : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					methodInfo.Invoke(val, null);
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[ZombieDaggerMod] Could not update zombie eyes: " + ex));
		}
	}
}
[HarmonyPatch(typeof(CharacterInteractible), "IsInteractible")]
public static class MushroomZombieInteractionPatch
{
	[HarmonyPostfix]
	public static void Postfix(CharacterInteractible __instance, Character interactor, ref bool __result)
	{
		if ((Object)(object)__instance == (Object)null || (Object)(object)interactor == (Object)null)
		{
			return;
		}
		Character character = __instance.character;
		if (!((Object)(object)character == (Object)null) && !character.data.dead)
		{
			MushroomZombie component = ((Component)character).GetComponent<MushroomZombie>();
			if (!((Object)(object)component == (Object)null))
			{
				__result = true;
				ZombieSacrificeNetwork.EnsureInstalled(component);
			}
		}
	}
}
[HarmonyPatch(typeof(RitualDaggerFeedBehavior), "FeederAction")]
public static class RitualDaggerZombieFeedPatch
{
	[HarmonyPostfix]
	public static void Postfix(Character feeder, Character fedCharacter)
	{
		if ((Object)(object)fedCharacter == (Object)null)
		{
			Debug.LogWarning((object)"[ZombieDaggerMod] FeederAction: fedCharacter is null.");
			return;
		}
		MushroomZombie val = ((Component)fedCharacter).GetComponent<MushroomZombie>();
		if ((Object)(object)val == (Object)null)
		{
			val = ((Component)fedCharacter).GetComponentInParent<MushroomZombie>();
		}
		if ((Object)(object)val == (Object)null)
		{
			val = ((Component)fedCharacter).GetComponentInChildren<MushroomZombie>(true);
		}
		if ((Object)(object)val == (Object)null)
		{
			Debug.Log((object)("[ZombieDaggerMod] FeederAction executed, but MushroomZombie was not found on the target hierarchy. Target=" + ((Object)fedCharacter).name));
			return;
		}
		if ((Object)(object)((MonoBehaviourPun)val).photonView == (Object)null)
		{
			Debug.LogWarning((object)"[ZombieDaggerMod] MushroomZombie has no PhotonView.");
			return;
		}
		Debug.Log((object)("[ZombieDaggerMod] Ritual Dagger target found. Target=" + ((Object)val).name + ", ViewID=" + ((MonoBehaviourPun)val).photonView.ViewID + ", IsMasterClient=" + PhotonNetwork.IsMasterClient));
		ZombieSacrificeNetwork.EnsureInstalled(val);
		ZombieSacrificeNetwork component = ((Component)val).GetComponent<ZombieSacrificeNetwork>();
		if ((Object)(object)component == (Object)null)
		{
			Debug.LogError((object)"[ZombieDaggerMod] ZombieSacrificeNetwork was not installed.");
		}
		else if (PhotonNetwork.IsMasterClient)
		{
			ZombieSacrificeNetwork.ProcessSacrifice(val);
		}
		else
		{
			component.RequestSacrifice();
		}
	}
}
public class ZombieSacrificeNetwork : MonoBehaviour
{
	private MushroomZombie zombie;

	private bool requestRunning;

	private const int MaxRequestAttempts = 5;

	private const float RetryDelaySeconds = 0.75f;

	private static readonly HashSet<int> Processing = new HashSet<int>();

	private static readonly HashSet<int> DaggerSacrificeIds = new HashSet<int>();

	private void Awake()
	{
		zombie = ((Component)this).GetComponent<MushroomZombie>();
	}

	public static void EnsureInstalled(MushroomZombie target)
	{
		if (!((Object)(object)target == (Object)null) && (Object)(object)((Component)target).GetComponent<ZombieSacrificeNetwork>() == (Object)null)
		{
			((Component)target).gameObject.AddComponent<ZombieSacrificeNetwork>();
		}
	}

	public static void ClearStaleStateForNewZombie(MushroomZombie target)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Invalid comparison between Unknown and I4
		if (!((Object)(object)target == (Object)null) && !((Object)(object)((MonoBehaviourPun)target).photonView == (Object)null) && (int)target._currentState != 6)
		{
			int viewID = ((MonoBehaviourPun)target).photonView.ViewID;
			bool flag = DaggerSacrificeIds.Remove(viewID);
			Processing.Remove(viewID);
			if (flag)
			{
				Debug.Log((object)("[ZombieDaggerMod] Cleared stale sacrifice state. ID=" + viewID));
			}
			ZombieDestroyPatch.ClearStatueState(viewID);
		}
	}

	public void RequestSacrifice()
	{
		if (!requestRunning)
		{
			if ((Object)(object)zombie == (Object)null)
			{
				zombie = ((Component)this).GetComponent<MushroomZombie>();
			}
			if ((Object)(object)zombie == (Object)null || (Object)(object)((MonoBehaviourPun)zombie).photonView == (Object)null)
			{
				Debug.LogWarning((object)"[ZombieDaggerMod] Cannot request sacrifice: no PhotonView.");
			}
			else if (!PhotonNetwork.InRoom)
			{
				Debug.LogWarning((object)"[ZombieDaggerMod] Cannot request sacrifice outside a room.");
			}
			else
			{
				((MonoBehaviour)this).StartCoroutine(RetrySacrificeRequest());
			}
		}
	}

	private IEnumerator RetrySacrificeRequest()
	{
		requestRunning = true;
		try
		{
			for (int attempt = 1; attempt <= 5; attempt++)
			{
				if ((Object)(object)zombie == (Object)null)
				{
					break;
				}
				if ((Object)(object)((MonoBehaviourPun)zombie).photonView == (Object)null)
				{
					break;
				}
				if (!PhotonNetwork.InRoom)
				{
					break;
				}
				if (PhotonNetwork.IsMasterClient)
				{
					ProcessSacrifice(zombie);
					break;
				}
				int viewId = ((MonoBehaviourPun)zombie).photonView.ViewID;
				Debug.Log((object)("[ZombieDaggerMod] Sacrifice request attempt " + attempt + "/" + 5 + ", ViewID=" + viewId));
				((MonoBehaviourPun)zombie).photonView.RPC("RPC_RequestZombieSacrifice", (RpcTarget)2, Array.Empty<object>());
				if (attempt < 5)
				{
					yield return (object)new WaitForSecondsRealtime(0.75f);
				}
			}
		}
		finally
		{
			requestRunning = false;
		}
	}

	[PunRPC]
	public void RPC_RequestZombieSacrifice()
	{
		if (PhotonNetwork.IsMasterClient)
		{
			if ((Object)(object)zombie == (Object)null)
			{
				zombie = ((Component)this).GetComponent<MushroomZombie>();
			}
			ProcessSacrifice(zombie);
		}
	}

	public static bool WasKilledByDagger(int viewId)
	{
		return DaggerSacrificeIds.Contains(viewId);
	}

	public static void ProcessSacrifice(MushroomZombie target)
	{
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Invalid comparison between Unknown and I4
		if (!PhotonNetwork.IsMasterClient || (Object)(object)target == (Object)null || (Object)(object)((MonoBehaviourPun)target).photonView == (Object)null)
		{
			return;
		}
		int viewID = ((MonoBehaviourPun)target).photonView.ViewID;
		if (Processing.Contains(viewID) || DaggerSacrificeIds.Contains(viewID))
		{
			return;
		}
		if (!((MonoBehaviourPun)target).photonView.IsMine)
		{
			Debug.LogWarning((object)("[ZombieDaggerMod] Host does not own zombie. ID=" + viewID));
		}
		else
		{
			if ((int)target._currentState == 6)
			{
				return;
			}
			ZombieSacrificeNetwork component = ((Component)target).GetComponent<ZombieSacrificeNetwork>();
			MethodInfo methodInfo = AccessTools.Method(typeof(MushroomZombie), "Die", (Type[])null, (Type[])null);
			if (!((Object)(object)component == (Object)null) && !(methodInfo == null))
			{
				Processing.Add(viewID);
				DaggerSacrificeIds.Add(viewID);
				Debug.Log((object)("[ZombieDaggerMod] Marking dagger sacrifice for all clients. ID=" + viewID));
				try
				{
					((MonoBehaviourPun)target).photonView.RPC("RPC_MarkDaggerSacrifice", (RpcTarget)5, new object[1] { viewID });
					methodInfo.Invoke(target, null);
					target.DestroyZombie();
					return;
				}
				catch (Exception ex)
				{
					DaggerSacrificeIds.Remove(viewID);
					Debug.LogError((object)("[ZombieDaggerMod] Sacrifice failed. ID=" + viewID + ", Error=" + ex));
					return;
				}
				finally
				{
					Processing.Remove(viewID);
				}
			}
			Debug.LogError((object)("[ZombieDaggerMod] Cannot process sacrifice. Handler or Die method is missing. ID=" + viewID));
		}
	}

	[PunRPC]
	public void RPC_MarkDaggerSacrifice(int viewId)
	{
		DaggerSacrificeIds.Add(viewId);
		Debug.Log((object)("[ZombieDaggerMod] Dagger sacrifice marker received. ID=" + viewId));
	}
}
[HarmonyPatch(typeof(MushroomZombie), "DestroyZombie")]
public static class ZombieDestroyPatch
{
	private static readonly HashSet<int> StatueCreated = new HashSet<int>();

	public static void ClearStatueState(int id)
	{
		StatueCreated.Remove(id);
	}

	[HarmonyPrefix]
	public static bool Prefix(MushroomZombie __instance)
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Invalid comparison between Unknown and I4
		if ((Object)(object)__instance == (Object)null || (Object)(object)((MonoBehaviourPun)__instance).photonView == (Object)null)
		{
			return true;
		}
		int viewID = ((MonoBehaviourPun)__instance).photonView.ViewID;
		if (!ZombieSacrificeNetwork.WasKilledByDagger(viewID))
		{
			return true;
		}
		if (!PhotonNetwork.IsMasterClient || !((MonoBehaviourPun)__instance).photonView.IsMine || (int)__instance._currentState != 6)
		{
			return true;
		}
		if (!StatueCreated.Add(viewID))
		{
			return true;
		}
		try
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null)
			{
				StatueCreated.Remove(viewID);
				return true;
			}
			component.SpawnStatue(true);
			Debug.Log((object)("[ZombieDaggerMod] Dagger statue spawned. ID=" + viewID));
		}
		catch (Exception ex)
		{
			StatueCreated.Remove(viewID);
			Debug.LogError((object)("[ZombieDaggerMod] Statue creation failed: " + ex));
		}
		return true;
	}
}
[HarmonyPatch(typeof(MushroomZombie), "RPC_SpawnSkelly")]
public static class PreventZombieSkeletonPatch
{
	[HarmonyPrefix]
	public static bool Prefix(MushroomZombie __instance)
	{
		if ((Object)(object)__instance == (Object)null || (Object)(object)((MonoBehaviourPun)__instance).photonView == (Object)null)
		{
			return true;
		}
		int viewID = ((MonoBehaviourPun)__instance).photonView.ViewID;
		if (ZombieSacrificeNetwork.WasKilledByDagger(viewID))
		{
			Debug.Log((object)("[ZombieDaggerMod] Skeleton blocked for dagger sacrifice. ID=" + viewID));
			return false;
		}
		return true;
	}
}
public class ZombieStatueThirdEyeSuppressor : MonoBehaviour
{
	private void LateUpdate()
	{
		CustomizationRefs[] componentsInChildren = ((Component)this).GetComponentsInChildren<CustomizationRefs>(true);
		CustomizationRefs[] array = componentsInChildren;
		foreach (CustomizationRefs val in array)
		{
			if ((Object)(object)val == (Object)null || (Object)(object)val.thirdEye == (Object)null)
			{
				continue;
			}
			if (val.thirdEye.activeSelf)
			{
				val.thirdEye.SetActive(false);
			}
			Renderer[] componentsInChildren2 = val.thirdEye.GetComponentsInChildren<Renderer>(true);
			Renderer[] array2 = componentsInChildren2;
			foreach (Renderer val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
		}
	}
}
[HarmonyPatch(typeof(PetrifiedScout), "RPC_SpawnPetrifiedScout")]
public static class PetrifiedScoutZombiePosePatch
{
	private static void CopyZombieEyesToStatue(Character sourceCharacter, PetrifiedScout statue)
	{
		if ((Object)(object)sourceCharacter == (Object)null || (Object)(object)statue == (Object)null)
		{
			return;
		}
		try
		{
			CustomizationRefs refs = sourceCharacter.refs.customization.refs;
			if ((Object)(object)refs == (Object)null || refs.EyeRenderers == null)
			{
				return;
			}
			CustomizationRefs[] componentsInChildren = ((Component)statue).GetComponentsInChildren<CustomizationRefs>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				Debug.LogWarning((object)"[ZombieDaggerMod] No statue eye renderers found.");
				return;
			}
			int num = 0;
			CustomizationRefs[] array = componentsInChildren;
			foreach (CustomizationRefs val in array)
			{
				if ((Object)(object)val == (Object)null || val.EyeRenderers == null)
				{
					continue;
				}
				int num2 = Math.Min(refs.EyeRenderers.Length, val.EyeRenderers.Length);
				for (int j = 0; j < num2; j++)
				{
					Renderer val2 = refs.EyeRenderers[j];
					Renderer val3 = val.EyeRenderers[j];
					if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
					{
						Texture texture = val2.material.GetTexture("_MainTex");
						if (!((Object)(object)texture == (Object)null))
						{
							val3.material.SetTexture("_MainTex", texture);
							num++;
						}
					}
				}
			}
			Debug.Log((object)("[ZombieDaggerMod] Zombie eye textures copied: " + num));
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[ZombieDaggerMod] Could not copy zombie eyes to statue: " + ex));
		}
	}

	[HarmonyPrefix]
	public static bool Prefix(PetrifiedScout __instance, int characterID, bool killedByDagger)
	{
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null)
		{
			return true;
		}
		if ((Object)(object)((Component)__instance).GetComponent<ZombieStatueThirdEyeSuppressor>() == (Object)null)
		{
			((Component)__instance).gameObject.AddComponent<ZombieStatueThirdEyeSuppressor>();
		}
		Character val = null;
		if (!Character.GetCharacterWithPhotonID(characterID, ref val))
		{
			foreach (Character allBotCharacter in Character.AllBotCharacters)
			{
				if ((Object)(object)allBotCharacter == (Object)null || (Object)(object)((MonoBehaviourPun)allBotCharacter).photonView == (Object)null || ((MonoBehaviourPun)allBotCharacter).photonView.ViewID != characterID)
				{
					continue;
				}
				val = allBotCharacter;
				break;
			}
		}
		if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).GetComponent<MushroomZombie>() == (Object)null)
		{
			return true;
		}
		try
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(PetrifiedScout), "spawnedFromCharacter");
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(__instance, val);
			}
			CopyZombieEyesToStatue(val, __instance);
			MethodInfo methodInfo = AccessTools.Method(typeof(Character), "GetBodypart", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				return false;
			}
			Bodypart[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Bodypart>(true);
			foreach (Bodypart val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					object? obj = methodInfo.Invoke(val, new object[1] { val2.partType });
					Bodypart val3 = (Bodypart)((obj is Bodypart) ? obj : null);
					if (!((Object)(object)val3 == (Object)null))
					{
						val2.transform.SetPositionAndRotation(val3.transform.position, val3.transform.rotation);
					}
				}
			}
			if ((Object)(object)__instance.daggerTransform != (Object)null)
			{
				((Component)__instance.daggerTransform).gameObject.SetActive(killedByDagger);
			}
			return false;
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[ZombieDaggerMod] NPC statue setup failed: " + ex));
			return false;
		}
	}
}
[HarmonyPatch]
internal static class TfaClassicZombieTemplatePatch
{
	private static GameObject classicSeed;

	private static MethodBase TargetMethod()
	{
		Type type = AccessTools.TypeByName("TrueFinalAscent.FinalAscentSporeCloud");
		return (type == null) ? null : AccessTools.Method(type, "Sleeper", (Type[])null, (Type[])null);
	}

	[HarmonyPostfix]
	private static void Postfix(ref GameObject __result)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		if (!((Object)(object)__result != (Object)null))
		{
			if ((Object)(object)classicSeed == (Object)null)
			{
				classicSeed = new GameObject("MushroomZombie");
				Object.DontDestroyOnLoad((Object)(object)classicSeed);
				Debug.LogWarning((object)("[ZombieDaggerMod] Using fallback network prefab name: " + ((Object)classicSeed).name));
			}
			__result = classicSeed;
		}
	}
}