Decompiled source of UndyingAmulet v1.1.1

BepInEx/plugins/ReviveCharm.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ReviveCharm")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("ReviveCharm")]
[assembly: AssemblyTitle("ReviveCharm")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ReviveCharm
{
	[BepInPlugin("com.valheimmod.revivecharm", "Undying Amulet", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.valheimmod.revivecharm";

		public const string PluginName = "Undying Amulet";

		public const string DisplayItemName = "Undying Amulet";

		public const string PluginVersion = "1.1.1";

		public const string ItemPrefabName = "ReviveCharm";

		private const string LegacyItemCooldownKey = "com.valheimmod.revivecharm.Cooldown";

		private const float ConfigFlushInterval = 5f;

		private const float MaxWorldTimeSlack = 300f;

		private const float CooldownHudRightMargin = 210f;

		private const float ReadyMistRefreshInterval = 0.25f;

		private const char MessageLineBreak = '\n';

		internal static Plugin Instance = null;

		internal static ConfigEntry<float> CooldownMinutes = null;

		internal static ConfigEntry<float> InvulnerabilitySeconds = null;

		internal static ConfigEntry<bool> Enabled = null;

		private static Light _protectionLight;

		private static GameObject _readyMistEffect;

		private static Player _readyMistPlayer;

		private static float _nextReadyMistRefresh;

		private static Texture2D _overlayTexture;

		private static Player _protectedPlayer;

		private static int _lastCountdown = -1;

		private static GUIStyle _cooldownStyle;

		private static readonly Dictionary<string, ConfigEntry<float>> _savedCooldownCache = new Dictionary<string, ConfigEntry<float>>();

		private static ItemData _cachedCharm;

		private static float _charmCacheTime;

		private static Player _cachedCharmPlayer;

		private static bool _configDirty;

		private static float _lastConfigFlush;

		private Harmony _harmony;

		internal static ZNetView GetView(Player player)
		{
			return ((Component)player).GetComponent<ZNetView>();
		}

		internal static void LogInfo(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				ManualLogSource logger = ((BaseUnityPlugin)instance).Logger;
				if (logger != null)
				{
					logger.LogInfo((object)message);
				}
			}
		}

		internal static void LogWarning(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				ManualLogSource logger = ((BaseUnityPlugin)instance).Logger;
				if (logger != null)
				{
					logger.LogWarning((object)message);
				}
			}
		}

		internal static void LogError(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				ManualLogSource logger = ((BaseUnityPlugin)instance).Logger;
				if (logger != null)
				{
					logger.LogError((object)message);
				}
			}
		}

		internal static bool TryGetWorldTime(out float worldTime)
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				worldTime = 0f;
				return false;
			}
			worldTime = (float)ZNet.instance.GetTimeSeconds();
			return true;
		}

		private void Awake()
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			Instance = this;
			CooldownMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Revive", "CooldownMinutes", 30f, "Cooldown after a resurrection.");
			InvulnerabilitySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Revive", "InvulnerabilitySeconds", 30f, "Damage immunity after resurrection.");
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Revive", "Enabled", true, "Master switch. When false the amulet never activates (troubleshooting).");
			CooldownMinutes.Value = Mathf.Max(0f, CooldownMinutes.Value);
			InvulnerabilitySeconds.Value = Mathf.Max(0f, InvulnerabilitySeconds.Value);
			PrefabManager.OnVanillaPrefabsAvailable += ItemPatches.Register;
			_harmony = new Harmony("com.valheimmod.revivecharm");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Undying Amulet 1.1.1 loaded.");
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= ItemPatches.Register;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			StopProtectionVisual();
			StopReadyMistVisual();
			if ((Object)(object)_overlayTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_overlayTexture);
			}
			_overlayTexture = null;
			_cachedCharm = null;
			_cachedCharmPlayer = null;
			_savedCooldownCache.Clear();
			if ((Object)(object)ItemPatches.IconTexture != (Object)null)
			{
				Object.Destroy((Object)(object)ItemPatches.IconTexture);
				ItemPatches.IconTexture = null;
			}
			ItemPatches.Cleanup();
			FlushConfigIfNeeded(force: true);
			Instance = null;
		}

		private void Update()
		{
			FlushConfigIfNeeded();
			RefreshReadyMistVisual();
			if ((Object)(object)_protectionLight == (Object)null)
			{
				return;
			}
			Player protectedPlayer = _protectedPlayer;
			int num = Mathf.CeilToInt(GetImmunitySeconds(protectedPlayer));
			if ((Object)(object)protectedPlayer == (Object)null || (float)num <= 0f)
			{
				if ((Object)(object)protectedPlayer != (Object)null)
				{
					((Character)protectedPlayer).Message((MessageType)2, "UNDYING AMULET\nPROTECTION ENDED", 0, (Sprite)null, false);
				}
				StopProtectionVisual();
				return;
			}
			_protectionLight.intensity = 2.2f + Mathf.Sin(Time.time * 8f) * 0.7f;
			if (num != _lastCountdown)
			{
				_lastCountdown = num;
				((Character)protectedPlayer).Message((MessageType)2, $"UNDYING AMULET{'\n'}INVULNERABLE: {num}s", 0, (Sprite)null, false);
			}
		}

		private void FlushConfigIfNeeded(bool force = false)
		{
			if (_configDirty && (force || !(Time.unscaledTime - _lastConfigFlush < 5f)))
			{
				_configDirty = false;
				_lastConfigFlush = Time.unscaledTime;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		internal static void MarkConfigDirty()
		{
			_configDirty = true;
		}

		private static float GetCooldownSeconds(Player player)
		{
			if ((Object)(object)player == (Object)null || !TryGetWorldTime(out var worldTime))
			{
				return 0f;
			}
			float num = 0f;
			ZNetView view = GetView(player);
			if ((Object)(object)view != (Object)null && view.IsValid())
			{
				float num2 = SanitizeCooldown(view.GetZDO().GetFloat("com.valheimmod.revivecharm.Cooldown", 0f), worldTime);
				num = Mathf.Max(0f, num2 - worldTime);
			}
			ConfigEntry<float> val = EnsureLocalCooldownEntry(player);
			if (val != null)
			{
				float num3 = SanitizeCooldown(val.Value, worldTime);
				num = Mathf.Max(num, Mathf.Max(0f, num3 - worldTime));
			}
			return num;
		}

		internal static bool IsReadyAmuletBuffActive(Player player)
		{
			if (Enabled.Value && (Object)(object)player != (Object)null && ((Character)player).GetHealth() > 0f && TryGetWorldTime(out var _) && FindCharm(player) != null)
			{
				return GetCooldownSeconds(player) <= 0f;
			}
			return false;
		}

		internal static float GetImmunitySeconds(Player player)
		{
			if ((Object)(object)player == (Object)null || !TryGetWorldTime(out var worldTime))
			{
				return 0f;
			}
			ZNetView view = GetView(player);
			if ((Object)(object)view == (Object)null || !view.IsValid())
			{
				return 0f;
			}
			float num = view.GetZDO().GetFloat("com.valheimmod.revivecharm.Immunity", 0f);
			if (num <= worldTime)
			{
				return 0f;
			}
			if (num - worldTime > InvulnerabilitySeconds.Value + 300f)
			{
				return 0f;
			}
			return num - worldTime;
		}

		private static string FormatTime(float seconds)
		{
			int num = Mathf.Max(0, Mathf.CeilToInt(seconds));
			return $"{num / 60:00}:{num % 60:00}";
		}

		private void OnGUI()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				if (_overlayTexture == null)
				{
					_overlayTexture = CreateOverlayTexture();
				}
				if (GetImmunitySeconds(localPlayer) > 0f)
				{
					float num = 0.12f + Mathf.Abs(Mathf.Sin(Time.time * 5f)) * 0.12f;
					GUI.color = new Color(0.85f, 0.02f, 0.02f, num);
					GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_overlayTexture);
				}
				float num2 = Mathf.Clamp((float)Screen.height / 1080f, 0.75f, 2f);
				Texture2D iconTexture = ItemPatches.IconTexture;
				if (_cooldownStyle == null)
				{
					GUIStyle val = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)3,
						font = FindHudFont(),
						fontStyle = (FontStyle)1
					};
					val.normal.textColor = new Color(1f, 0.58f, 0.28f, 1f);
					_cooldownStyle = val;
				}
				_cooldownStyle.padding = new RectOffset(0, 0, 0, 0);
				_cooldownStyle.fontSize = Mathf.RoundToInt(16f * num2);
				float cooldownSeconds = GetCooldownSeconds(localPlayer);
				string text = ((cooldownSeconds > 0f) ? ("UNDYING COOLDOWN  " + FormatTime(cooldownSeconds)) : string.Empty);
				float num3 = 260f * num2;
				float num4 = (float)Screen.width - num3 - 210f * num2;
				float num5 = 142f * num2;
				GUI.color = Color.white;
				if (cooldownSeconds > 0f && (Object)(object)iconTexture != (Object)null)
				{
					GUI.DrawTexture(new Rect(num4 - 64f * num2, num5 - 8f * num2, 56f * num2, 56f * num2), (Texture)(object)iconTexture);
				}
				GUI.Label(new Rect(num4, num5, num3, 40f * num2), text, _cooldownStyle);
				GUI.color = Color.white;
			}
		}

		private static Font FindHudFont()
		{
			Font[] array = Resources.FindObjectsOfTypeAll<Font>();
			foreach (Font val in array)
			{
				if (((Object)val).name.IndexOf("Averia", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)val).name.IndexOf("Norse", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)val).name.IndexOf("Valheim", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return val;
				}
			}
			return GUI.skin.label.font;
		}

		private static Texture2D CreateOverlayTexture()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					int num = Mathf.Min(Mathf.Min(j, 127 - j), Mathf.Min(i, 127 - i));
					float num2 = 1f - Mathf.Clamp01((float)num / 44f);
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num2));
				}
			}
			val.Apply();
			return val;
		}

		private static ItemData FindCharm(Player player)
		{
			if (!Enabled.Value || (Object)(object)player == (Object)null || ((Humanoid)player).GetInventory() == null)
			{
				return null;
			}
			bool flag = (Object)(object)player == (Object)(object)Player.m_localPlayer;
			float time = Time.time;
			if (flag && _cachedCharm != null && (Object)(object)_cachedCharmPlayer == (Object)(object)player && time - _charmCacheTime < 1f)
			{
				return _cachedCharm;
			}
			foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems())
			{
				if (allItem?.m_shared != null && IsCharm(allItem))
				{
					allItem.m_customData.Remove("com.valheimmod.revivecharm.Cooldown");
					if (flag)
					{
						_cachedCharm = allItem;
						_cachedCharmPlayer = player;
						_charmCacheTime = time;
					}
					return allItem;
				}
			}
			if (flag)
			{
				_cachedCharm = null;
				_cachedCharmPlayer = null;
			}
			return null;
		}

		internal static bool IsCharm(ItemData item)
		{
			if (item?.m_shared != null)
			{
				if (!(item.m_shared.m_name == "Undying Amulet") && !(item.m_shared.m_name == "Resurrection Amulet") && !(item.m_shared.m_name == "$item_revivecharm"))
				{
					if ((Object)(object)item.m_dropPrefab != (Object)null)
					{
						return ((Object)item.m_dropPrefab).name == "ReviveCharm";
					}
					return false;
				}
				return true;
			}
			return false;
		}

		internal static bool TryUseCharm(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			ZNetView view = GetView(player);
			if ((Object)(object)view == (Object)null || !view.IsValid() || !view.IsOwner())
			{
				return false;
			}
			if (!TryGetWorldTime(out var worldTime))
			{
				return false;
			}
			if (FindCharm(player) == null)
			{
				return false;
			}
			ZDO zDO = view.GetZDO();
			float num = SanitizeCooldown(zDO.GetFloat("com.valheimmod.revivecharm.Cooldown", 0f), worldTime);
			bool flag = (Object)(object)player == (Object)(object)Player.m_localPlayer;
			ConfigEntry<float> val = (flag ? EnsureLocalCooldownEntry(player) : null);
			if (val != null)
			{
				float num2 = SanitizeCooldown(val.Value, worldTime);
				if (num2 > num)
				{
					num = num2;
					zDO.Set("com.valheimmod.revivecharm.Cooldown", num2);
				}
			}
			if (num > worldTime)
			{
				return false;
			}
			float num3 = worldTime + InvulnerabilitySeconds.Value;
			float num4 = worldTime + CooldownMinutes.Value * 60f;
			zDO.Set("com.valheimmod.revivecharm.Cooldown", num4);
			zDO.Set("com.valheimmod.revivecharm.Immunity", num3);
			StopReadyMistVisual();
			((Character)player).SetHealth(Mathf.Max(1f, ((Character)player).GetMaxHealth() * 0.5f));
			if (val != null)
			{
				val.Value = num4;
				MarkConfigDirty();
			}
			if (flag)
			{
				StartProtectionVisual(player);
			}
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)$"Undying Amulet activated for player {player.GetPlayerID()} (cooldown {CooldownMinutes.Value:0.#} min).");
			return true;
		}

		private static ConfigEntry<float> EnsureLocalCooldownEntry(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return null;
			}
			long playerID = player.GetPlayerID();
			long num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetWorldUID() : 0);
			if (num == 0L || playerID == 0L)
			{
				return null;
			}
			string text = $"World_{num}_Player_{playerID}";
			if (_savedCooldownCache.TryGetValue(text, out var value))
			{
				return value;
			}
			ConfigEntry<float> val = ((BaseUnityPlugin)Instance).Config.Bind<float>("CharacterCooldown", text, 0f, "World-time timestamp until which this character stays on cooldown in this world.");
			_savedCooldownCache[text] = val;
			return val;
		}

		private static float SanitizeCooldown(float cooldownUntil, float worldTime)
		{
			if (cooldownUntil <= 0f)
			{
				return 0f;
			}
			float num = worldTime + Mathf.Max(0f, CooldownMinutes.Value) * 60f + 300f;
			if (!(cooldownUntil > num))
			{
				return cooldownUntil;
			}
			return 0f;
		}

		private static void StartProtectionVisual(Player player)
		{
			//IL_0021: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_protectionLight != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_protectionLight).gameObject);
			}
			GameObject val = new GameObject("ResurrectionAmuletProtectionEffect");
			val.transform.SetParent(((Component)player).transform, false);
			val.transform.localPosition = new Vector3(0f, 1f, 0f);
			_protectionLight = val.AddComponent<Light>();
			_protectionLight.type = (LightType)2;
			_protectionLight.color = new Color(1f, 0.12f, 0.03f);
			_protectionLight.range = 4f;
			_protectionLight.intensity = 2.5f;
			_protectedPlayer = player;
			_lastCountdown = -1;
		}

		private static void RefreshReadyMistVisual()
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.unscaledTime < _nextReadyMistRefresh))
			{
				_nextReadyMistRefresh = Time.unscaledTime + 0.25f;
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).GetHealth() <= 0f || !TryGetWorldTime(out var _) || FindCharm(localPlayer) == null || GetCooldownSeconds(localPlayer) > 0f)
				{
					StopReadyMistVisual();
				}
				else if (!((Object)(object)_readyMistEffect != (Object)null) || !((Object)(object)_readyMistPlayer == (Object)(object)localPlayer))
				{
					StopReadyMistVisual();
					_readyMistEffect = ItemPatches.CreateMistAura(((Component)localPlayer).transform, "UndyingAmuletReadyMist", (Vector3[])(object)new Vector3[12]
					{
						new Vector3(-0.26f, 0.3f, 0f),
						new Vector3(0.26f, 0.3f, 0f),
						new Vector3(0f, 0.3f, -0.24f),
						new Vector3(0f, 0.3f, 0.24f),
						new Vector3(-0.22f, 0.8f, -0.2f),
						new Vector3(0.22f, 0.8f, -0.2f),
						new Vector3(-0.22f, 0.8f, 0.2f),
						new Vector3(0.22f, 0.8f, 0.2f),
						new Vector3(-0.2f, 1.3f, 0f),
						new Vector3(0.2f, 1.3f, 0f),
						new Vector3(0f, 1.3f, -0.18f),
						new Vector3(0f, 1.3f, 0.18f)
					}, 12f, 0.35f, 0.55f, 0.35f, 0.2f, 0.28f, 0.52f);
					_readyMistPlayer = localPlayer;
					LogInfo("[Undying Amulet] Ready-state mist started for the local player.");
				}
			}
		}

		private static void StopReadyMistVisual()
		{
			if ((Object)(object)_readyMistEffect != (Object)null)
			{
				Object.Destroy((Object)(object)_readyMistEffect);
			}
			_readyMistEffect = null;
			_readyMistPlayer = null;
		}

		internal static void StopProtectionVisual()
		{
			if ((Object)(object)_protectionLight != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_protectionLight).gameObject);
			}
			_protectionLight = null;
			_protectedPlayer = null;
			_lastCountdown = -1;
		}
	}
	[HarmonyPatch]
	internal static class RevivePatches
	{
		internal const string CooldownKey = "com.valheimmod.revivecharm.Cooldown";

		internal const string ImmunityKey = "com.valheimmod.revivecharm.Immunity";

		[HarmonyPatch(typeof(Character), "ApplyDamage")]
		[HarmonyPrefix]
		private static bool BeforeApplyDamage(Character __instance, HitData hit)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null)
			{
				return true;
			}
			if (!Plugin.TryGetWorldTime(out var worldTime))
			{
				return true;
			}
			ZNetView view = Plugin.GetView(val);
			if ((Object)(object)view == (Object)null || !view.IsValid() || !view.IsOwner())
			{
				return true;
			}
			if (view.GetZDO().GetFloat("com.valheimmod.revivecharm.Immunity", 0f) > worldTime)
			{
				return false;
			}
			if (((Character)val).GetHealth() - hit.GetTotalDamage() > 0f)
			{
				return true;
			}
			return !Plugin.TryUseCharm(val);
		}

		[HarmonyPatch(typeof(Player), "OnDeath")]
		[HarmonyPostfix]
		private static void AfterPlayerDeath(Player __instance)
		{
			ZNetView view = Plugin.GetView(__instance);
			if ((Object)(object)view != (Object)null && view.IsValid())
			{
				view.GetZDO().Set("com.valheimmod.revivecharm.Immunity", 0f);
			}
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				Plugin.StopProtectionVisual();
			}
		}
	}
	[HarmonyPatch]
	internal static class ReadyAmuletBuffPatches
	{
		private struct DamageState
		{
			internal Player Attacker;

			internal Character Target;

			internal float HealthBefore;

			internal float MaximumDamage;
		}

		[HarmonyPatch(typeof(Player), "GetRunSpeedFactor")]
		[HarmonyPostfix]
		private static void IncreaseRunSpeed(Player __instance, ref float __result)
		{
			if (Plugin.IsReadyAmuletBuffActive(__instance))
			{
				__result *= 1.5f;
			}
		}

		[HarmonyPatch(typeof(Player), "UseStamina")]
		[HarmonyPrefix]
		private static void ReduceStaminaUse(Player __instance, ref float __0)
		{
			if (Plugin.IsReadyAmuletBuffActive(__instance))
			{
				__0 *= 0.5f;
			}
		}

		[HarmonyPatch(typeof(Character), "ApplyDamage")]
		[HarmonyPrefix]
		private static void CaptureLifestealDamage(Character __instance, HitData hit, out DamageState __state)
		{
			__state = default(DamageState);
			if (hit != null && !(hit.GetTotalDamage() <= 0f))
			{
				Character attacker = hit.GetAttacker();
				Player val = (Player)(object)((attacker is Player) ? attacker : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)__instance) && Plugin.IsReadyAmuletBuffActive(val))
				{
					__state.Attacker = val;
					__state.Target = __instance;
					__state.HealthBefore = __instance.GetHealth();
					__state.MaximumDamage = hit.GetTotalDamage();
				}
			}
		}

		[HarmonyPatch(typeof(Character), "ApplyDamage")]
		[HarmonyPostfix]
		private static void ApplyLifesteal(DamageState __state)
		{
			Player attacker = __state.Attacker;
			Character target = __state.Target;
			if (!((Object)(object)attacker == (Object)null) && !((Object)(object)target == (Object)null) && Plugin.IsReadyAmuletBuffActive(attacker))
			{
				float num = Mathf.Min(__state.MaximumDamage, Mathf.Max(0f, __state.HealthBefore - target.GetHealth()));
				if (!(num <= 0f))
				{
					float num2 = num * 0.2f;
					((Character)attacker).SetHealth(Mathf.Min(((Character)attacker).GetMaxHealth(), ((Character)attacker).GetHealth() + num2));
				}
			}
		}
	}
	internal static class ItemPatches
	{
		private sealed class MistEffectFollower : MonoBehaviour
		{
			private Transform _target;

			private Vector3 _localPosition;

			internal void Initialize(Transform target, Vector3 localPosition)
			{
				//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)
				_target = target;
				_localPosition = localPosition;
			}

			private void LateUpdate()
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: 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)
				if ((Object)(object)_target != (Object)null)
				{
					((Component)this).transform.position = _target.TransformPoint(_localPosition);
					((Component)this).transform.rotation = Quaternion.identity;
				}
			}
		}

		internal static Texture2D IconTexture;

		private static bool _registered;

		private static Material _mistMaterial;

		private static Texture2D _mistTexture;

		private static bool _loggedMissingMistShader;

		private static readonly string[] MaterialSourcePrefabs = new string[5] { "BeltStrength", "SilverNecklace", "YmirRemains", "AmberPearl", "Coins" };

		private static void LogInfo(string message)
		{
			Plugin.LogInfo(message);
		}

		private static void LogWarning(string message)
		{
			Plugin.LogWarning(message);
		}

		private static void LogError(string message)
		{
			Plugin.LogError(message);
		}

		internal static void Register()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			if (!_registered)
			{
				string description = $"Prevents one lethal hit: restores 50% health and grants {Plugin.InvulnerabilitySeconds.Value:0.#} " + $"seconds of damage immunity. Cooldown: {Plugin.CooldownMinutes.Value:0.#} minutes.";
				ItemConfig val = new ItemConfig();
				val.Name = "Undying Amulet";
				val.Description = description;
				val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
				{
					new RequirementConfig
					{
						Item = "Resin",
						Amount = 20
					}
				};
				CustomItem val2 = new CustomItem("ReviveCharm", "Resin", val);
				SharedData shared = val2.ItemDrop.m_itemData.m_shared;
				shared.m_name = "Undying Amulet";
				shared.m_description = description;
				shared.m_itemType = (ItemType)1;
				shared.m_maxStackSize = 1;
				shared.m_weight = 0.1f;
				IconTexture = CreateIcon();
				shared.m_icons = (Sprite[])(object)new Sprite[1] { Sprite.Create(IconTexture, new Rect(0f, 0f, (float)((Texture)IconTexture).width, (float)((Texture)IconTexture).height), new Vector2(0.5f, 0.5f), 64f) };
				if ((Object)(object)val2.ItemDrop.m_itemData.m_dropPrefab == (Object)null)
				{
					LogWarning("[Undying Amulet] The custom item has no drop prefab; using its registered item prefab for dropped visuals.");
					EnsureDropPrefab(val2);
				}
				GameObject dropPrefab = val2.ItemDrop.m_itemData.m_dropPrefab;
				if ((Object)(object)dropPrefab != (Object)null)
				{
					CreateMistEffect(dropPrefab.transform, "UndyingAmuletGroundMist", new Vector3(0f, 0.08f, 0f), 7f, 0.35f, 0.65f, 1.8f, 0.22f, 0.16f, 0.34f);
					LogInfo("[Undying Amulet] Ground mist attached to drop prefab '" + ((Object)dropPrefab).name + "'.");
				}
				else
				{
					LogError("[Undying Amulet] No drop prefab is available; the dropped amulet cannot show its mist effect.");
				}
				ItemManager.Instance.AddItem(val2);
				_registered = true;
				GameObject dropPrefab2 = val2.ItemDrop.m_itemData.m_dropPrefab;
				LogInfo("[Undying Amulet] Registered successfully. DropPrefab = " + (((dropPrefab2 != null) ? ((Object)dropPrefab2).name : null) ?? "null"));
			}
		}

		internal static GameObject CreateMistEffect(Transform parent, string effectName, Vector3 localPosition, float emissionRate, float minStartSpeed, float maxStartSpeed, float lifetime, float emissionRadius, float minStartSize, float maxStartSize)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			GameObject val = new GameObject(effectName);
			val.transform.SetParent(parent, false);
			val.transform.localPosition = localPosition;
			val.transform.rotation = Quaternion.identity;
			val.AddComponent<MistEffectFollower>().Initialize(parent, localPosition);
			CreateMistEmitter(val.transform, "MistEmitter", Vector3.zero, emissionRate, minStartSpeed, maxStartSpeed, lifetime, emissionRadius, minStartSize, maxStartSize, 1f);
			return val;
		}

		internal static GameObject CreateMistAura(Transform parent, string effectName, Vector3[] emitterOffsets, float emissionRate, float minStartSpeed, float maxStartSpeed, float lifetime, float emissionRadius, float minStartSize, float maxStartSize)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(effectName);
			val.transform.SetParent(parent, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.rotation = Quaternion.identity;
			val.AddComponent<MistEffectFollower>().Initialize(parent, Vector3.zero);
			for (int i = 0; i < emitterOffsets.Length; i++)
			{
				CreateMistEmitter(val.transform, $"MistEmitter_{i}", emitterOffsets[i], emissionRate, minStartSpeed, maxStartSpeed, lifetime, emissionRadius, minStartSize, maxStartSize, 0.5f);
			}
			return val;
		}

		private static void CreateMistEmitter(Transform parent, string emitterName, Vector3 localPosition, float emissionRate, float minStartSpeed, float maxStartSpeed, float lifetime, float emissionRadius, float minStartSize, float maxStartSize, float motionScale)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: 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_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Expected O, but got Unknown
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Expected O, but got Unknown
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(emitterName);
			val.transform.SetParent(parent, false);
			val.transform.localPosition = localPosition;
			val.transform.rotation = Quaternion.identity;
			ParticleSystem val2 = val.AddComponent<ParticleSystem>();
			MainModule main = val2.main;
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).playOnAwake = true;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			((MainModule)(ref main)).maxParticles = 128;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(lifetime * 0.8f, lifetime * 1.2f);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(minStartSpeed, maxStartSpeed);
			((MainModule)(ref main)).startSize = new MinMaxCurve(minStartSize, maxStartSize);
			((MainModule)(ref main)).startRotation = new MinMaxCurve(0f, (float)Math.PI * 2f);
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.66f, 0.9f, 1f, 0.82f));
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f);
			EmissionModule emission = val2.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(emissionRate);
			ShapeModule shape = val2.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)4;
			((ShapeModule)(ref shape)).angle = 10f;
			((ShapeModule)(ref shape)).radius = emissionRadius;
			((ShapeModule)(ref shape)).alignToDirection = true;
			((ShapeModule)(ref shape)).randomDirectionAmount = 0.14f;
			VelocityOverLifetimeModule velocityOverLifetime = val2.velocityOverLifetime;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)1;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x = new MinMaxCurve(-0.05f * motionScale, 0.05f * motionScale);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y = new MinMaxCurve(0.65f * motionScale, 1f * motionScale);
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z = new MinMaxCurve(-0.05f * motionScale, 0.05f * motionScale);
			SizeOverLifetimeModule sizeOverLifetime = val2.sizeOverLifetime;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, new AnimationCurve((Keyframe[])(object)new Keyframe[3]
			{
				new Keyframe(0f, 0.4f),
				new Keyframe(0.35f, 1f),
				new Keyframe(1f, 1.65f)
			}));
			ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val3 = new Gradient();
			val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(new Color(0.78f, 0.92f, 1f), 0f),
				new GradientColorKey(new Color(0.92f, 0.98f, 1f), 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
			{
				new GradientAlphaKey(0f, 0f),
				new GradientAlphaKey(0.62f, 0.16f),
				new GradientAlphaKey(0.38f, 0.62f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val3);
			NoiseModule noise = val2.noise;
			((NoiseModule)(ref noise)).enabled = true;
			((NoiseModule)(ref noise)).strength = MinMaxCurve.op_Implicit(0.12f);
			((NoiseModule)(ref noise)).frequency = 0.35f;
			((NoiseModule)(ref noise)).scrollSpeed = MinMaxCurve.op_Implicit(0.15f);
			ParticleSystemRenderer component = ((Component)val2).GetComponent<ParticleSystemRenderer>();
			component.renderMode = (ParticleSystemRenderMode)0;
			((Renderer)component).sharedMaterial = GetMistMaterial();
			val2.Play();
		}

		internal static void Cleanup()
		{
			if ((Object)(object)_mistMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_mistMaterial);
			}
			if ((Object)(object)_mistTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_mistTexture);
			}
			_mistMaterial = null;
			_mistTexture = null;
		}

		private static Material GetMistMaterial()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_mistMaterial != (Object)null)
			{
				return _mistMaterial;
			}
			Shader val = Shader.Find("Legacy Shaders/Particles/Alpha Blended") ?? Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Sprites/Default");
			if ((Object)(object)val == (Object)null)
			{
				if (!_loggedMissingMistShader)
				{
					LogWarning("[Undying Amulet] No particle shader was found; using Unity's default particle material.");
					_loggedMissingMistShader = true;
				}
				return null;
			}
			_mistMaterial = new Material(val)
			{
				name = "UndyingAmuletMistMaterial"
			};
			_mistMaterial.mainTexture = (Texture)(object)CreateMistTexture();
			if (_mistMaterial.HasProperty("_Color"))
			{
				_mistMaterial.SetColor("_Color", Color.white);
			}
			if (_mistMaterial.HasProperty("_TintColor"))
			{
				_mistMaterial.SetColor("_TintColor", Color.white);
			}
			return _mistMaterial;
		}

		private static Texture2D CreateMistTexture()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = "UndyingAmuletSoftMist",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = ((float)j + 0.5f) / 64f * 2f - 1f;
					float num2 = ((float)i + 0.5f) / 64f * 2f - 1f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					float num4 = Mathf.Clamp01(1f - num3);
					float num5 = num4 * num4 * (0.72f + 0.16f * Mathf.Sin(num2 * 9f + num * 4f));
					array[i * 64 + j] = new Color(1f, 1f, 1f, num5);
				}
			}
			val.SetPixels(array);
			val.Apply();
			_mistTexture = val;
			return val;
		}

		private static void EnsureDropPrefab(CustomItem charm)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			ItemDrop itemDrop = charm.ItemDrop;
			if ((Object)(object)itemDrop == (Object)null || itemDrop.m_itemData == null)
			{
				LogError("[Undying Amulet] The cloned item has no valid ItemDrop or ItemData.");
				return;
			}
			GameObject gameObject = ((Component)itemDrop).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				LogError("[Undying Amulet] The cloned item has no drop prefab; dropped items cannot be spawned.");
				return;
			}
			itemDrop.m_itemData.m_dropPrefab = gameObject;
			Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true);
			Renderer[] array = componentsInChildren;
			for (int i = 0; i < array.Length; i++)
			{
				array[i].enabled = true;
			}
			Collider[] componentsInChildren2 = gameObject.GetComponentsInChildren<Collider>(true);
			Collider[] array2 = componentsInChildren2;
			for (int i = 0; i < array2.Length; i++)
			{
				array2[i].enabled = true;
			}
			if (componentsInChildren2.Length == 0)
			{
				gameObject.AddComponent<BoxCollider>().size = new Vector3(0.35f, 0.35f, 0.35f);
				LogWarning("[Undying Amulet] The cloned drop prefab had no collider; added a pickup collider.");
			}
			ItemDrop component = gameObject.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null)
			{
				LogError("[Undying Amulet] The cloned drop prefab has no ItemDrop component.");
			}
			ZNetView component2 = gameObject.GetComponent<ZNetView>();
			if ((Object)(object)component2 == (Object)null)
			{
				LogError("[Undying Amulet] The cloned drop prefab has no ZNetView component.");
			}
			LogInfo("[Undying Amulet] Drop prefab inspected: " + ((Object)gameObject).name + "; " + $"renderers={componentsInChildren.Length}, colliders={componentsInChildren2.Length}, " + $"itemDrop={(Object)(object)component != (Object)null}, znetView={(Object)(object)component2 != (Object)null}.");
		}

		private static int CountEnabledRenderers(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return 0;
			}
			int num = 0;
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (componentsInChildren[i].enabled)
				{
					num++;
				}
			}
			return num;
		}

		private static int CountEnabledColliders(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return 0;
			}
			int num = 0;
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (componentsInChildren[i].enabled)
				{
					num++;
				}
			}
			return num;
		}

		private static Texture2D CreateIcon()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: 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)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(512, 512, (TextureFormat)4, false)
			{
				name = "ResurrectionAmuletIcon",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
			new Color(0.2f, 0.7f, 1f, 1f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(1f, 0.9f, 0.55f, 1f);
			new Color(0.08f, 0.3f, 0.8f, 1f);
			Color[] array = (Color[])(object)new Color[262144];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = val2;
			}
			val.SetPixels(array);
			for (int j = 0; j < 512; j++)
			{
				for (int k = 0; k < 512; k++)
				{
					float num = (float)k / 8f;
					float num2 = (float)j / 8f;
					float num3 = num - 32f;
					float num4 = num2 - 14f;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4);
					Color val4 = val2;
					if (num5 >= 11f && num5 <= 15f)
					{
						((Color)(ref val4))..ctor(1f, 0.72f, 0.08f, 1f);
					}
					if (num5 >= 12f && num5 <= 13.5f && num2 < 15f)
					{
						val4 = val3;
					}
					for (int l = 0; l < 2; l++)
					{
						float num6 = ((l == 0) ? 32f : 44f);
						float num7 = ((l == 0) ? 16f : 12f);
						float num8 = ((l == 0) ? 6f : 5f);
						float num9 = ((l == 0) ? 14f : 19f);
						float num10 = ((l == 0) ? 50f : 45f);
						float num11 = Mathf.Abs(num - num9) / num7 + Mathf.Abs(num2 - num6) / num8;
						float num12 = Mathf.Abs(num - num10) / num7 + Mathf.Abs(num2 - num6) / num8;
						if (num11 < 1.12f || num12 < 1.12f)
						{
							((Color)(ref val4))..ctor(0.12f, 0.62f, 0.82f, 1f);
						}
						float num13 = ((l == 0) ? (num6 - 4f) : (num6 - 3f));
						float num14 = ((l == 0) ? (num6 + 4f) : (num6 + 3f));
						if ((num11 < 1.08f || num12 < 1.08f) && num2 < num13)
						{
							((Color)(ref val4))..ctor(0.72f, 0.95f, 1f, 1f);
						}
						if ((num11 < 1f || num12 < 1f) && num2 > num14)
						{
							((Color)(ref val4))..ctor(0.05f, 0.35f, 0.62f, 1f);
						}
					}
					if (val4.a > 0f)
					{
						float num15 = Mathf.Clamp(0.68f + (64f - num - num2) / 180f, 0.55f, 1f);
						((Color)(ref val4))..ctor(val4.r * num15, val4.g * num15, val4.b * num15, val4.a);
						float num16 = Mathf.Sqrt((num - 27f) * (num - 27f) + (num2 - 10f) * (num2 - 10f));
						if (num5 >= 11f && num5 <= 15f && num16 < 5f)
						{
							val4 = Color.Lerp(val4, Color.white, 0.35f);
						}
					}
					int num17 = 511 - j - 80;
					if (num17 >= 0 && num17 < 512)
					{
						val.SetPixel(k, num17, val4);
					}
				}
			}
			val.Apply();
			return val;
		}

		private static void BuildAngelModel(GameObject prefab)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			string materialSource;
			Material val = FindVanillaMaterial(prefab, out materialSource);
			if ((Object)(object)val == (Object)null || (Object)(object)val.shader == (Object)null)
			{
				LogWarning("[Undying Amulet] Could not find a usable material or fallback shader; keeping the item placeholder visible.");
				return;
			}
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			Material material = val;
			GameObject val2 = new GameObject("ResurrectionAmuletAngelModel");
			val2.transform.SetParent(prefab.transform, false);
			val2.transform.localScale = Vector3.one * 0.65f;
			SphereCollider obj = val2.AddComponent<SphereCollider>();
			obj.radius = 0.22f;
			((Collider)obj).isTrigger = true;
			CreateWing(val2.transform, "LeftWing", -1f, material);
			CreateWing(val2.transform, "RightWing", 1f, material);
			CreateHalo(val2.transform, material);
			LogInfo("[Undying Amulet] Angel model created using material from " + materialSource + ".");
		}

		private static Material FindVanillaMaterial(GameObject placeholderPrefab, out string materialSource)
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			Material val = FindRendererMaterial(placeholderPrefab);
			if ((Object)(object)val != (Object)null)
			{
				materialSource = ((Object)placeholderPrefab).name + " placeholder";
				return val;
			}
			string[] materialSourcePrefabs = MaterialSourcePrefabs;
			foreach (string text in materialSourcePrefabs)
			{
				Material val2 = FindRendererMaterial(FindPrefab(text));
				if ((Object)(object)val2 != (Object)null)
				{
					materialSource = text;
					return val2;
				}
			}
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				foreach (GameObject item in ObjectDB.instance.m_items)
				{
					Material val3 = FindRendererMaterial(item);
					if ((Object)(object)val3 != (Object)null)
					{
						materialSource = ((Object)item).name;
						return val3;
					}
				}
			}
			Shader val4 = Shader.Find("Standard") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Custom/Standard");
			if ((Object)(object)val4 != (Object)null)
			{
				materialSource = "fallback shader '" + ((Object)val4).name + "'";
				return new Material(val4)
				{
					color = new Color(0.95f, 0.75f, 0.2f, 1f)
				};
			}
			materialSource = "none";
			return null;
		}

		private static GameObject FindPrefab(string prefabName)
		{
			object obj = (((Object)(object)ObjectDB.instance == (Object)null) ? null : ObjectDB.instance.GetItemPrefab(prefabName));
			if (obj == null)
			{
				if (!((Object)(object)ZNetScene.instance == (Object)null))
				{
					return ZNetScene.instance.GetPrefab(prefabName);
				}
				obj = null;
			}
			return (GameObject)obj;
		}

		private static Material FindRendererMaterial(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] sharedMaterials = componentsInChildren[i].sharedMaterials;
				foreach (Material val in sharedMaterials)
				{
					if ((Object)(object)val != (Object)null && (Object)(object)val.shader != (Object)null)
					{
						return val;
					}
				}
			}
			return null;
		}

		private static void CreateWing(Transform parent, string name, float side, Material material)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002b: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			val.transform.localPosition = new Vector3(side * 0.14f, 0f, 0f);
			val.transform.localRotation = Quaternion.Euler(0f, side * 18f, side * 10f);
			Mesh val2 = new Mesh
			{
				name = name + "Mesh"
			};
			Vector3[] vertices = (Vector3[])(object)new Vector3[6]
			{
				new Vector3(0f, 0.18f, 0f),
				new Vector3(side * 0.28f, 0.12f, 0f),
				new Vector3(side * 0.38f, -0.04f, 0f),
				new Vector3(side * 0.27f, -0.23f, 0f),
				new Vector3(side * 0.12f, -0.13f, 0f),
				new Vector3(0f, -0.03f, 0.02f)
			};
			val2.vertices = vertices;
			val2.triangles = new int[15]
			{
				0, 1, 5, 1, 2, 5, 2, 3, 5, 3,
				4, 5, 4, 0, 5
			};
			val2.RecalculateNormals();
			val.AddComponent<MeshFilter>().sharedMesh = val2;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = material;
		}

		private static void CreateHalo(Transform parent, Material material)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_002d: 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)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Halo");
			val.transform.SetParent(parent, false);
			val.transform.localPosition = new Vector3(0f, 0.28f, 0.02f);
			val.transform.localRotation = Quaternion.Euler(70f, 0f, 0f);
			Mesh val2 = new Mesh
			{
				name = "HaloMesh"
			};
			Vector3[] array = (Vector3[])(object)new Vector3[40];
			int[] array2 = new int[120];
			Vector3 val3 = default(Vector3);
			for (int i = 0; i < 20; i++)
			{
				float num = (float)i * (float)Math.PI * 2f / 20f;
				((Vector3)(ref val3))..ctor(Mathf.Cos(num), Mathf.Sin(num), 0f);
				array[i * 2] = val3 * 0.14f;
				array[i * 2 + 1] = val3 * 0.1f;
				int num2 = (i + 1) % 20;
				int num3 = i * 6;
				array2[num3] = i * 2;
				array2[num3 + 1] = num2 * 2;
				array2[num3 + 2] = i * 2 + 1;
				array2[num3 + 3] = i * 2 + 1;
				array2[num3 + 4] = num2 * 2;
				array2[num3 + 5] = num2 * 2 + 1;
			}
			val2.vertices = array;
			val2.triangles = array2;
			val2.RecalculateNormals();
			val.AddComponent<MeshFilter>().sharedMesh = val2;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = material;
		}
	}
}