Decompiled source of RevivalRevived v0.2.0

RevivalRevived.dll

Decompiled 9 hours 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.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RevivalRevived.Components;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("RevivalRevived")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+430d50f5f65a0a3c7db2a3751a6bc863c7cc051d")]
[assembly: AssemblyProduct("RevivalRevived")]
[assembly: AssemblyTitle("RevivalRevived")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 RevivalRevived
{
	public enum ReviveModeType
	{
		Hold,
		Press
	}
	[BepInPlugin("com.andres.revivalrevived", "RevivalRevived", "0.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.andres.revivalrevived";

		public const string PluginName = "RevivalRevived";

		public const string PluginVersion = "0.2.0";

		internal static ConfigEntry<ReviveModeType> ReviveModeCfg;

		internal static ConfigEntry<float> ReviveHoldTimeCfg;

		internal static ConfigEntry<float> ReviveWindowCfg;

		public const float ReviveHealthFraction = 0.25f;

		private Harmony? _harmony;

		internal static ManualLogSource Logger { get; private set; }

		public static float ReviveWindow => ReviveWindowCfg?.Value ?? 30f;

		public static float ReviveDuration => Mathf.Max(0.1f, ReviveHoldTimeCfg?.Value ?? 4f);

		public static bool RevivePressMode
		{
			get
			{
				if (ReviveModeCfg != null)
				{
					return ReviveModeCfg.Value == ReviveModeType.Press;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"RevivalRevived v0.2.0 loaded!");
			ReviveModeCfg = ((BaseUnityPlugin)this).Config.Bind<ReviveModeType>("Revive", "Mode", ReviveModeType.Hold, "Hold: the interact key must be held for HoldTimeSeconds to revive. Press: a single press revives instantly.");
			ReviveHoldTimeCfg = ((BaseUnityPlugin)this).Config.Bind<float>("Revive", "HoldTimeSeconds", 4f, new ConfigDescription("How long the interact key must be held to complete a revive (Hold mode).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 60f), Array.Empty<object>()));
			ReviveWindowCfg = ((BaseUnityPlugin)this).Config.Bind<float>("Revive", "WindowSeconds", 30f, new ConfigDescription("How long a downed player can be revived before dying for real.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 600f), Array.Empty<object>()));
			_harmony = Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "com.andres.revivalrevived");
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace RevivalRevived.Patches
{
	[HarmonyPatch(typeof(Character), "CheckDeath")]
	internal static class CheckDeathPatch
	{
		private static bool Prefix(Character __instance)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null)
			{
				return true;
			}
			if (!((Character)val).m_nview.IsOwner())
			{
				return true;
			}
			if (((Character)val).IsDead())
			{
				return true;
			}
			if (((Character)val).GetHealth() > 0f)
			{
				return true;
			}
			if (val.IsDowned())
			{
				if (val.IsReviveWindowExpired())
				{
					if (((Character)val).m_lastHit == null)
					{
						((Character)val).m_lastHit = new HitData
						{
							m_hitType = (HitType)14
						};
					}
					val.ExpireDownedState();
					return true;
				}
				return false;
			}
			val.EnterDownedState();
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "Awake")]
	internal static class PlayerAwakePatch
	{
		private static void Postfix(Player __instance)
		{
			ZNetView nview = ((Character)__instance).m_nview;
			nview.Register("RevivalRevived_OnDowned", (Action<long>)delegate
			{
				__instance.PlayDownedPoof();
			});
			nview.Register("RevivalRevived_Channel", (Action<long>)delegate(long sender)
			{
				if (nview.IsOwner())
				{
					((Component)__instance).GetComponent<Revivable>()?.ChannelPing(sender);
				}
			});
			if (__instance.IsDowned() && (Object)(object)((Component)__instance).GetComponent<Revivable>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<Revivable>();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "CanMove")]
	internal static class PlayerCanMovePatch
	{
		private static void Postfix(Player __instance, ref bool __result)
		{
			if (__result && __instance.IsDowned())
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(Character), "UpdateMotion")]
	internal static class CharacterUpdateMotionPatch
	{
		private static bool Prefix(Character __instance)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null && val.IsDowned())
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "LateUpdate")]
	internal static class PlayerLateUpdatePatch
	{
		private static void Postfix(Player __instance)
		{
			if (__instance.IsDowned() && (Object)(object)((Component)__instance).GetComponent<Revivable>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<Revivable>();
			}
			if (((Character)__instance).IsDead())
			{
				if ((Object)(object)((Character)__instance).m_collider != (Object)null && ((Collider)((Character)__instance).m_collider).enabled)
				{
					((Collider)((Character)__instance).m_collider).enabled = false;
				}
				if ((Object)(object)((Character)__instance).m_nview != (Object)null && ((Character)__instance).m_nview.IsValid() && ((Character)__instance).m_nview.IsOwner() && (Object)(object)((Character)__instance).m_body != (Object)null && !((Character)__instance).m_body.isKinematic)
				{
					((Character)__instance).m_body.isKinematic = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateHover")]
	internal static class PlayerUpdateHoverPatch
	{
		private static bool Prefix(Player __instance)
		{
			if (__instance.IsDowned())
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "OnRespawn")]
	internal static class PlayerOnRespawnPatch
	{
		private static bool Prefix(Player __instance)
		{
			if (__instance.IsDowned())
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(EnemyHud), "TestShow")]
	internal static class EnemyHudHideDownedPatch
	{
		private static void Postfix(Character c, ref bool __result)
		{
			if (__result)
			{
				Player val = (Player)(object)((c is Player) ? c : null);
				if (val != null && (val.IsDowned() || ((Character)val).IsDead()))
				{
					__result = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class PlayerOnSpawnedPatch
	{
		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && (Object)(object)((Character)__instance).m_nview != (Object)null && ((Character)__instance).m_nview.IsValid() && ((Character)__instance).m_nview.IsOwner() && (Object)(object)((Component)__instance).GetComponent<DisconnectDeathCheck>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<DisconnectDeathCheck>();
			}
			ReviveProgressUI.Ensure();
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetSceneAwakeRegisterPrefabsPatch
	{
		private static void Postfix(ZNetScene __instance)
		{
			DownedMarker.RegisterPrefab(__instance);
		}
	}
	[HarmonyPatch(typeof(TombStone), "Setup")]
	internal static class TombStoneSetupReplacePatch
	{
		private static void Postfix(TombStone __instance, long ownerUID)
		{
			//IL_0068: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)((Character)localPlayer).m_nview == (Object)null || !((Character)localPlayer).m_nview.IsValid() || ownerUID != localPlayer.GetPlayerID())
			{
				return;
			}
			ZDO zDO = ((Character)localPlayer).m_nview.GetZDO();
			if (zDO.GetBool(DownedKeys.GraveReplacePending, false))
			{
				zDO.Set(DownedKeys.GraveReplacePending, false);
				Vector3 vec = zDO.GetVec3(DownedKeys.GraveReplacePos, ((Component)__instance).transform.position);
				((Component)__instance).transform.position = vec;
				Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null)
				{
					component.position = vec;
					component.linearVelocity = Vector3.zero;
				}
				DownedMarker.MarkReplaced(localPlayer.FindDownedMarker() ?? DownedMarker.FindFor(localPlayer.GetPlayerID()));
				zDO.Set(DownedKeys.Marker, ZDOID.None);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnDeath")]
	internal static class PlayerOnDeathMarkerCrumblePatch
	{
		private static void Postfix(Player __instance)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			ZNetView nview = ((Character)__instance).m_nview;
			if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner())
			{
				ZDO zDO = nview.GetZDO();
				if (zDO.GetBool(DownedKeys.GraveReplacePending, false))
				{
					zDO.Set(DownedKeys.GraveReplacePending, false);
					GameObject? marker = __instance.FindDownedMarker() ?? DownedMarker.FindFor(__instance.GetPlayerID());
					zDO.Set(DownedKeys.Marker, ZDOID.None);
					DownedMarker.Crumble(marker);
					Plugin.Logger.LogInfo((object)(__instance.GetPlayerName() + " died with no grave to drop; marker crumbled"));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "CreateDeathEffects")]
	internal static class SuppressPlayerRagdollPatch
	{
		private static bool Prefix()
		{
			return false;
		}
	}
}
namespace RevivalRevived.Components
{
	public class DisconnectDeathCheck : MonoBehaviour
	{
		private Player? m_player;

		private void Awake()
		{
			m_player = ((Component)this).GetComponent<Player>();
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(Check());
		}

		private IEnumerator Check()
		{
			if ((Object)(object)m_player == (Object)null || (Object)(object)((Character)m_player).m_nview == (Object)null || !((Character)m_player).m_nview.IsValid() || !((Character)m_player).m_nview.IsOwner())
			{
				Object.Destroy((Object)(object)this);
				yield break;
			}
			long pid = m_player.GetPlayerID();
			float t = 0f;
			while (t < 12f)
			{
				if ((Object)(object)m_player == (Object)null || !((Character)m_player).m_nview.IsValid())
				{
					Object.Destroy((Object)(object)this);
					yield break;
				}
				if (m_player.IsDowned())
				{
					Object.Destroy((Object)(object)this);
					yield break;
				}
				if ((Object)(object)DownedMarker.FindFor(pid) != (Object)null)
				{
					Plugin.Logger.LogInfo((object)(m_player.GetPlayerName() + " reconnected with an orphaned downed marker -> dying"));
					KillDowned(m_player);
					Object.Destroy((Object)(object)this);
					yield break;
				}
				t += 0.5f;
				yield return (object)new WaitForSecondsRealtime(0.5f);
			}
			Object.Destroy((Object)(object)this);
		}

		private static void KillDowned(Player player)
		{
			//IL_0085: 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_00ad: 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)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			if (!((Object)(object)player == (Object)null) && ((Character)player).m_nview.IsValid() && ((Character)player).m_nview.IsOwner())
			{
				ZDO zDO = ((Character)player).m_nview.GetZDO();
				zDO.Set(DownedKeys.Downed, false);
				GameObject val = DownedMarker.FindFor(player.GetPlayerID());
				GameObject val2 = player.FindDownedMarker();
				Vector3? val3 = (((Object)(object)val != (Object)null) ? new Vector3?(val.transform.position) : (((Object)(object)val2 != (Object)null) ? new Vector3?(val2.transform.position) : ((Vector3?)null)));
				if (val3.HasValue)
				{
					zDO.Set(DownedKeys.GraveReplacePending, true);
					zDO.Set(DownedKeys.GraveReplacePos, val3.Value);
				}
				Revivable component = ((Component)player).GetComponent<Revivable>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				if (((Character)player).m_lastHit == null)
				{
					((Character)player).m_lastHit = new HitData
					{
						m_hitType = (HitType)14
					};
				}
				((Character)player).SetHealth(0f);
				Traverse.Create((object)player).Method("OnDeath", Array.Empty<object>()).GetValue();
				Plugin.Logger.LogInfo((object)(player.GetPlayerName() + " died from being downed at disconnect"));
			}
		}
	}
	public static class DownedKeys
	{
		public const string RpcOnDowned = "RevivalRevived_OnDowned";

		public const string RpcChannel = "RevivalRevived_Channel";

		public static readonly int Downed = StringExtensionMethods.GetStableHashCode("RevivalRevived_downed");

		public static readonly int DownedTime = StringExtensionMethods.GetStableHashCode("RevivalRevived_downedTime");

		public static readonly int GraveReplacePending = StringExtensionMethods.GetStableHashCode("RevivalRevived_graveReplacePending");

		public static readonly int GraveReplacePos = StringExtensionMethods.GetStableHashCode("RevivalRevived_graveReplacePos");

		public static readonly int ReviveProgress = StringExtensionMethods.GetStableHashCode("RevivalRevived_reviveProgress");

		public static readonly KeyValuePair<int, int> Marker = ZDO.GetHashZDOID("RevivalRevived_markerZDOID");

		public static readonly int IsDownedMarker = StringExtensionMethods.GetStableHashCode("RevivalRevived_isDownedMarker");

		public static readonly int OwnerPlayerId = StringExtensionMethods.GetStableHashCode("RevivalRevived_ownerPlayerID");

		public static readonly int ReplacedByGrave = StringExtensionMethods.GetStableHashCode("RevivalRevived_replacedByGrave");

		public static readonly KeyValuePair<int, int> MarkerPlayer = ZDO.GetHashZDOID("RevivalRevived_playerZDOID");

		public static readonly int OwnerName = ZDOVars.s_ownerName;
	}
	public class DownedMarker : MonoBehaviour
	{
		private struct TintedMaterial
		{
			public Material Mat;

			public bool HasEmission;

			public Color OrigEmission;

			public float EmissionIntensity;

			public bool HasColor;

			public Color OrigColor;
		}

		public static readonly Color ReviveGreen = new Color(0.25f, 1f, 0.35f);

		private static readonly int EmissionColorId = Shader.PropertyToID("_EmissionColor");

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		private readonly List<TintedMaterial> m_tinted = new List<TintedMaterial>();

		private readonly List<(Light light, Color orig)> m_lights = new List<(Light, Color)>();

		private ZNetView? m_nview;

		private static EffectList? s_crumbleEffect;

		public const string PrefabName = "RevivalRevived_DownedMarker";

		private static GameObject? s_prefabHolder;

		private static GameObject? s_prefabTemplate;

		private float m_replacedSince = -1f;

		private bool m_hiddenForReplace;

		private const float ReplaceHideTimeout = 4f;

		private const float ReplaceDestroyDelay = 5f;

		private const float ReplaceDestroyFailsafe = 10f;

		public int TintedLights => m_lights.Count;

		public int TintedMaterials => m_tinted.Count;

		public static int TemplateEffectsRemoved { get; private set; }

		public float CurrentBlend { get; private set; }

		public static float LastPopVelY { get; private set; }

		public static int LastCrumbleEffectCount { get; private set; }

		public static int CrumbleEvents { get; private set; }

		public bool HiddenForReplace => m_hiddenForReplace;

		public static void Spawn(Player player)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: 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)
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("RevivalRevived_DownedMarker") : null);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Logger.LogError((object)"DownedMarker.Spawn: prefab 'RevivalRevived_DownedMarker' is not registered");
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, ((Character)player).GetCenterPoint(), ((Component)player).transform.rotation);
			ZNetView component = val2.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				Plugin.Logger.LogError((object)"DownedMarker.Spawn: marker has no valid ZNetView");
				return;
			}
			ZDO zDO = component.GetZDO();
			zDO.Set(DownedKeys.IsDownedMarker, true);
			zDO.Set(DownedKeys.MarkerPlayer, ((Character)player).m_nview.GetZDO().m_uid);
			zDO.Set(DownedKeys.OwnerPlayerId, player.GetPlayerID());
			zDO.Set(DownedKeys.OwnerName, player.GetPlayerName());
			zDO.Set(DownedKeys.DownedTime, (float)ZNet.instance.GetTimeSeconds());
			((Character)player).m_nview.GetZDO().Set(DownedKeys.Marker, component.GetZDO().m_uid);
			Rigidbody component2 = val2.GetComponent<Rigidbody>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.linearVelocity = new Vector3(0f, 5f, 0f);
			}
			LastPopVelY = (((Object)(object)component2 != (Object)null) ? component2.linearVelocity.y : 0f);
			Plugin.Logger.LogInfo((object)$"Spawned downed marker for {player.GetPlayerName()}, ZDOID {component.GetZDO().m_uid}");
		}

		public static GameObject? FindFor(long playerId)
		{
			if (playerId == 0L)
			{
				return null;
			}
			DownedMarker[] array = Object.FindObjectsOfType<DownedMarker>();
			foreach (DownedMarker downedMarker in array)
			{
				ZNetView component = ((Component)downedMarker).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid())
				{
					ZDO zDO = component.GetZDO();
					if (!zDO.GetBool(DownedKeys.ReplacedByGrave, false) && zDO.GetLong(DownedKeys.OwnerPlayerId, 0L) == playerId)
					{
						return ((Component)downedMarker).gameObject;
					}
				}
			}
			return null;
		}

		public static void MarkReplaced(GameObject? marker)
		{
			if ((Object)(object)marker == (Object)null)
			{
				return;
			}
			ZNetView component = marker.GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				if (!component.IsOwner())
				{
					component.ClaimOwnership();
				}
				component.GetZDO().Set(DownedKeys.ReplacedByGrave, true);
			}
		}

		public static void Crumble(GameObject? marker)
		{
			//IL_001a: 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)
			if (!((Object)(object)marker == (Object)null))
			{
				EffectList val = FindGraveCrumbleEffect();
				if (val != null)
				{
					GameObject[] array = val.Create(marker.transform.position, marker.transform.rotation, (Transform)null, 1f, -1);
					LastCrumbleEffectCount = ((array != null) ? array.Length : 0);
					CrumbleEvents++;
				}
				DestroyMarker(marker);
			}
		}

		private static EffectList? FindGraveCrumbleEffect()
		{
			if (s_crumbleEffect != null)
			{
				return s_crumbleEffect;
			}
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? FindTombstonePrefab(ZNetScene.instance) : null);
			TombStone val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<TombStone>() : null);
			if ((Object)(object)val2 != (Object)null && val2.m_removeEffect != null && val2.m_removeEffect.m_effectPrefabs.Length != 0)
			{
				s_crumbleEffect = val2.m_removeEffect;
			}
			else
			{
				Plugin.Logger.LogWarning((object)"DownedMarker: no grave crumble effect found");
			}
			return s_crumbleEffect;
		}

		public static void CrumbleLinkedMarker(ZNetView playerNview)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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)
			ZDO zDO = playerNview.GetZDO();
			ZDOID zDOID = zDO.GetZDOID(DownedKeys.Marker);
			if (!(zDOID == ZDOID.None))
			{
				zDO.Set(DownedKeys.Marker, ZDOID.None);
				Crumble(ZNetScene.instance.FindInstance(zDOID));
			}
		}

		public static void DestroyMarker(GameObject? go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			ZNetView component = go.GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				if (!component.IsOwner())
				{
					component.ClaimOwnership();
				}
				component.Destroy();
			}
		}

		public static void RegisterPrefab(ZNetScene scene)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			if ((Object)(object)s_prefabTemplate == (Object)null)
			{
				GameObject val = FindTombstonePrefab(scene);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Logger.LogError((object)"DownedMarker: no TombStone prefab found to derive the marker from");
					return;
				}
				s_prefabHolder = new GameObject("RevivalRevived_Prefabs");
				s_prefabHolder.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)s_prefabHolder);
				GameObject obj = Object.Instantiate<GameObject>(val, s_prefabHolder.transform);
				((Object)obj).name = "RevivalRevived_DownedMarker";
				TombStone component = obj.GetComponent<TombStone>();
				if ((Object)(object)component != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component);
				}
				Container component2 = obj.GetComponent<Container>();
				if ((Object)(object)component2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component2);
				}
				RemoveGraveEffects(obj);
				obj.AddComponent<DownedMarker>();
				obj.AddComponent<ReviveInteractable>();
				s_prefabTemplate = obj;
				Plugin.Logger.LogInfo((object)("DownedMarker: built prefab 'RevivalRevived_DownedMarker' from '" + ((Object)val).name + "'"));
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode("RevivalRevived_DownedMarker");
			if (!scene.m_namedPrefabs.ContainsKey(stableHashCode))
			{
				scene.m_prefabs.Add(s_prefabTemplate);
				scene.m_namedPrefabs.Add(stableHashCode, s_prefabTemplate);
				Plugin.Logger.LogInfo((object)"DownedMarker: registered prefab 'RevivalRevived_DownedMarker' with ZNetScene");
			}
		}

		private static GameObject? FindTombstonePrefab(ZNetScene scene)
		{
			GameObject prefab = scene.GetPrefab("Player_tombstone");
			if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<TombStone>() != (Object)null)
			{
				return prefab;
			}
			foreach (GameObject prefab2 in scene.m_prefabs)
			{
				if ((Object)(object)prefab2 != (Object)null && (Object)(object)prefab2.GetComponent<TombStone>() != (Object)null)
				{
					return prefab2;
				}
			}
			return null;
		}

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			CaptureAccents();
			ApplyBlend(0f);
		}

		private void Start()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return;
			}
			string text = m_nview.GetZDO().GetString(DownedKeys.OwnerName, "");
			if (!string.IsNullOrEmpty(text))
			{
				TMP_Text componentInChildren = ((Component)this).GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.text = text;
				}
			}
		}

		private static void RemoveGraveEffects(GameObject template)
		{
			ParticleSystem[] componentsInChildren = template.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)(object)template)
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
					TemplateEffectsRemoved++;
				}
			}
			Transform[] componentsInChildren2 = template.GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)(object)template))
				{
					string text = ((Object)val2).name.ToLowerInvariant();
					if (text.Contains("flare") || text.Contains("glow"))
					{
						Object.DestroyImmediate((Object)(object)((Component)val2).gameObject);
						TemplateEffectsRemoved++;
					}
				}
			}
		}

		private void CaptureAccents()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			Light[] componentsInChildren = ((Component)this).GetComponentsInChildren<Light>(true);
			foreach (Light val in componentsInChildren)
			{
				m_lights.Add((val, val.color));
			}
			Renderer[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Material[] materials = componentsInChildren2[i].materials;
				foreach (Material val2 in materials)
				{
					TintedMaterial item = new TintedMaterial
					{
						Mat = val2
					};
					if (val2.HasProperty(EmissionColorId))
					{
						Color color = val2.GetColor(EmissionColorId);
						if (((Color)(ref color)).maxColorComponent > 0.05f)
						{
							item.HasEmission = true;
							item.OrigEmission = color;
							item.EmissionIntensity = ((Color)(ref color)).maxColorComponent;
						}
					}
					if (val2.HasProperty(ColorId))
					{
						Color color2 = val2.GetColor(ColorId);
						if (color2.r > 0.4f && color2.r > color2.g * 1.5f && color2.r > color2.b * 1.5f)
						{
							item.HasColor = true;
							item.OrigColor = color2;
						}
					}
					if (item.HasEmission || item.HasColor)
					{
						m_tinted.Add(item);
					}
				}
			}
		}

		private void ApplyBlend(float blend)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_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_00f1: Unknown result type (might be due to invalid IL or missing references)
			CurrentBlend = blend;
			foreach (TintedMaterial item in m_tinted)
			{
				if (!((Object)(object)item.Mat == (Object)null))
				{
					if (item.HasEmission)
					{
						Color val = ReviveGreen * item.EmissionIntensity;
						item.Mat.SetColor(EmissionColorId, Color.Lerp(val, item.OrigEmission, blend));
						item.Mat.EnableKeyword("_EMISSION");
					}
					if (item.HasColor)
					{
						item.Mat.SetColor(ColorId, Color.Lerp(ReviveGreen, item.OrigColor, blend));
					}
				}
			}
			foreach (var (val2, val3) in m_lights)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.color = Color.Lerp(ReviveGreen, val3, blend);
				}
			}
		}

		private void UpdateReplaced()
		{
			if (m_replacedSince < 0f)
			{
				m_replacedSince = Time.time;
			}
			float num = Time.time - m_replacedSince;
			if (!m_hiddenForReplace && (num > 4f || GraveNearby()))
			{
				HideLocally();
			}
			if (m_nview.IsOwner())
			{
				if (num > 5f)
				{
					m_nview.Destroy();
				}
			}
			else if (num > 10f)
			{
				m_nview.ClaimOwnership();
				m_nview.Destroy();
			}
		}

		private bool GraveNearby()
		{
			//IL_0012: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			TombStone[] array = Object.FindObjectsOfType<TombStone>();
			for (int i = 0; i < array.Length; i++)
			{
				Vector3 val = ((Component)array[i]).transform.position - ((Component)this).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude < 9f)
				{
					return true;
				}
			}
			return false;
		}

		private void HideLocally()
		{
			m_hiddenForReplace = true;
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			Collider[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Collider>();
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].enabled = false;
			}
			Light[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Light>();
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Behaviour)componentsInChildren3[i]).enabled = false;
			}
		}

		private void Update()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
			{
				ZDO zDO = m_nview.GetZDO();
				if (zDO.GetBool(DownedKeys.ReplacedByGrave, false))
				{
					UpdateReplaced();
					return;
				}
				ZDOID zDOID = zDO.GetZDOID(DownedKeys.MarkerPlayer);
				ZDO val = ((zDOID != ZDOID.None) ? ZDOMan.instance.GetZDO(zDOID) : null);
				float num = ((val != null) ? val.GetFloat(DownedKeys.DownedTime, 0f) : zDO.GetFloat(DownedKeys.DownedTime, 0f));
				float num2 = (float)ZNet.instance.GetTimeSeconds() - num;
				ApplyBlend(Mathf.Clamp01(num2 / Plugin.ReviveWindow));
			}
		}

		public bool IsGreen()
		{
			if (TintedLights > 0 || TintedMaterials > 0)
			{
				return CurrentBlend < 0.5f;
			}
			return false;
		}
	}
	public static class PlayerDownedExtensions
	{
		private static EffectList? s_cachedRemoveEffect;

		private static bool s_removeEffectSearched;

		public static int LastPoofCount { get; private set; }

		public static string LastPoofSourceName { get; private set; } = "";

		public static bool IsDowned(this Player? player)
		{
			ZNetView val = ((Character)(player?)).m_nview;
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				return val.GetZDO().GetBool(DownedKeys.Downed, false);
			}
			return false;
		}

		public static bool IsReviveWindowExpired(this Player player)
		{
			float num = ((Character)player).m_nview.GetZDO().GetFloat(DownedKeys.DownedTime, 0f);
			return (float)ZNet.instance.GetTimeSeconds() - num > Plugin.ReviveWindow;
		}

		public static float GetDownedRemainingTime(this Player? player)
		{
			ZNetView val = ((Character)(player?)).m_nview;
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return 0f;
			}
			float num = val.GetZDO().GetFloat(DownedKeys.DownedTime, 0f);
			return Mathf.Max(0f, Plugin.ReviveWindow - ((float)ZNet.instance.GetTimeSeconds() - num));
		}

		public static float GetReviveProgress(this Player? player)
		{
			ZNetView val = ((Character)(player?)).m_nview;
			if (!((Object)(object)val != (Object)null) || !val.IsValid())
			{
				return 0f;
			}
			return val.GetZDO().GetFloat(DownedKeys.ReviveProgress, 0f);
		}

		public static GameObject? FindDownedMarker(this Player? player)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = ((Character)(player?)).m_nview;
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return null;
			}
			ZDOID zDOID = val.GetZDO().GetZDOID(DownedKeys.Marker);
			if (!(zDOID == ZDOID.None))
			{
				return ZNetScene.instance.FindInstance(zDOID);
			}
			return null;
		}

		public static void EnterDownedState(this Player player)
		{
			ZDO zDO = ((Character)player).m_nview.GetZDO();
			zDO.Set(DownedKeys.GraveReplacePending, false);
			zDO.Set(DownedKeys.ReviveProgress, 0f);
			zDO.Set(DownedKeys.Downed, true);
			zDO.Set(DownedKeys.DownedTime, (float)ZNet.instance.GetTimeSeconds());
			if ((Object)(object)((Component)player).GetComponent<Revivable>() == (Object)null)
			{
				((Component)player).gameObject.AddComponent<Revivable>();
			}
			((Character)player).m_nview.InvokeRPC(ZNetView.Everybody, "RevivalRevived_OnDowned", Array.Empty<object>());
			DownedMarker.Spawn(player);
			((Character)player).Message((MessageType)2, "You are downed!", 0, (Sprite)null);
			Plugin.Logger.LogInfo((object)(player.GetPlayerName() + " entered downed state (owner)"));
		}

		public static void ReviveFromDowned(this Player player, long reviverId = 0L)
		{
			if (!((Object)(object)player == (Object)null) && ((Character)player).m_nview.IsValid())
			{
				if (!((Character)player).m_nview.IsOwner())
				{
					Plugin.Logger.LogWarning((object)"ReviveFromDowned called on non-owner; ignoring");
					return;
				}
				((Character)player).m_nview.GetZDO().Set(DownedKeys.Downed, false);
				((Character)player).SetHealth(Mathf.Max(((Character)player).GetMaxHealth() * 0.25f, 1f));
				DownedMarker.CrumbleLinkedMarker(((Character)player).m_nview);
				((Character)player).Message((MessageType)2, "You have been revived!", 0, (Sprite)null);
				Plugin.Logger.LogInfo((object)(player.GetPlayerName() + " was revived by " + ReviverName(reviverId)));
			}
		}

		public static void ExpireDownedState(this Player player)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)player == (Object)null) && ((Character)player).m_nview.IsValid())
			{
				ZDO zDO = ((Character)player).m_nview.GetZDO();
				zDO.Set(DownedKeys.Downed, false);
				GameObject val = player.FindDownedMarker();
				if ((Object)(object)val != (Object)null)
				{
					zDO.Set(DownedKeys.GraveReplacePending, true);
					zDO.Set(DownedKeys.GraveReplacePos, val.transform.position);
				}
				Plugin.Logger.LogInfo((object)(player.GetPlayerName() + " revive window expired, proceeding to death"));
			}
		}

		private static string ReviverName(long reviverId)
		{
			if (reviverId == 0L)
			{
				return "someone";
			}
			Player player = Player.GetPlayer(reviverId);
			if (!((Object)(object)player != (Object)null))
			{
				return reviverId.ToString();
			}
			return player.GetPlayerName();
		}

		public static int PlayDownedPoof(this Player player)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			EffectList val = FindRagdollRemoveEffect();
			if (val == null)
			{
				LastPoofCount = 0;
				return 0;
			}
			GameObject[] array = val.Create(((Character)player).GetCenterPoint(), Quaternion.identity, (Transform)null, 1f, -1);
			LastPoofCount = ((array != null) ? array.Length : 0);
			return LastPoofCount;
		}

		private static EffectList? FindRagdollRemoveEffect()
		{
			if (s_removeEffectSearched)
			{
				return s_cachedRemoveEffect;
			}
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			s_removeEffectSearched = true;
			string[] array = new string[2] { "Greyling_ragdoll", "Greydwarf_ragdoll" };
			foreach (string text in array)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(text);
				Ragdoll val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Ragdoll>() : null);
				if ((Object)(object)val != (Object)null && val.m_removeEffect != null && val.m_removeEffect.m_effectPrefabs.Length != 0)
				{
					s_cachedRemoveEffect = val.m_removeEffect;
					LastPoofSourceName = ((Object)prefab).name;
					Plugin.Logger.LogInfo((object)("Downed poof: using remove-effect from '" + ((Object)prefab).name + "'"));
					return s_cachedRemoveEffect;
				}
			}
			foreach (GameObject prefab2 in ZNetScene.instance.m_prefabs)
			{
				if (!((Object)(object)prefab2 == (Object)null))
				{
					Ragdoll component = prefab2.GetComponent<Ragdoll>();
					if ((Object)(object)component != (Object)null && component.m_removeEffect != null && component.m_removeEffect.m_effectPrefabs.Length != 0)
					{
						s_cachedRemoveEffect = component.m_removeEffect;
						LastPoofSourceName = ((Object)prefab2).name;
						Plugin.Logger.LogInfo((object)("Downed poof: using remove-effect from '" + ((Object)prefab2).name + "' (fallback)"));
						break;
					}
				}
			}
			if (s_cachedRemoveEffect == null)
			{
				Plugin.Logger.LogWarning((object)"Downed poof: no ragdoll prefab with a remove-effect found");
			}
			return s_cachedRemoveEffect;
		}
	}
	public class Revivable : MonoBehaviour
	{
		private Player? m_player;

		private ZNetView? m_nview;

		private float m_lastChannelTime = -999f;

		private long m_lastChannelSender;

		private float m_progress;

		private const float ChannelPingTimeout = 0.5f;

		public string PlayerName
		{
			get
			{
				if (!((Object)(object)m_player != (Object)null))
				{
					return "Viking";
				}
				return m_player.GetPlayerName();
			}
		}

		public float RemainingTime
		{
			get
			{
				if (!((Object)(object)m_player != (Object)null))
				{
					return 0f;
				}
				return m_player.GetDownedRemainingTime();
			}
		}

		private void Awake()
		{
			m_player = ((Component)this).GetComponent<Player>();
			m_nview = ((Component)this).GetComponent<ZNetView>();
		}

		private void Update()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || (Object)(object)m_player == (Object)null)
			{
				return;
			}
			if (!m_player.IsDowned())
			{
				Restore();
				Object.Destroy((Object)(object)this);
				return;
			}
			if ((Object)(object)((Character)m_player).m_visual != (Object)null && ((Character)m_player).m_visual.activeSelf)
			{
				((Character)m_player).m_visual.SetActive(false);
			}
			if ((Object)(object)((Character)m_player).m_collider != (Object)null && ((Collider)((Character)m_player).m_collider).enabled)
			{
				((Collider)((Character)m_player).m_collider).enabled = false;
			}
			if (!m_nview.IsOwner())
			{
				return;
			}
			((Character)m_player).m_body.isKinematic = true;
			if (m_player.IsReviveWindowExpired())
			{
				if (((Character)m_player).GetHealth() > 0f)
				{
					((Character)m_player).SetHealth(0f);
				}
			}
			else
			{
				UpdateReviveChannel();
			}
		}

		private void UpdateReviveChannel()
		{
			ZDO zDO = m_nview.GetZDO();
			if (Time.time - m_lastChannelTime < 0.5f)
			{
				if (Plugin.RevivePressMode)
				{
					zDO.Set(DownedKeys.ReviveProgress, 1f);
					m_player.ReviveFromDowned(m_lastChannelSender);
					return;
				}
				PauseWindowClock(zDO, Time.deltaTime);
				m_progress += Time.deltaTime;
				if (m_progress >= Plugin.ReviveDuration)
				{
					zDO.Set(DownedKeys.ReviveProgress, 1f);
					m_player.ReviveFromDowned(m_lastChannelSender);
					return;
				}
			}
			else
			{
				if (!(m_progress > 0f))
				{
					return;
				}
				m_progress = Mathf.Max(0f, m_progress - Time.deltaTime * 2f);
			}
			zDO.Set(DownedKeys.ReviveProgress, Mathf.Clamp01(m_progress / Plugin.ReviveDuration));
		}

		private void Restore()
		{
			if (!((Object)(object)m_player == (Object)null) && !((Character)m_player).IsDead())
			{
				if ((Object)(object)((Character)m_player).m_visual != (Object)null)
				{
					((Character)m_player).m_visual.SetActive(true);
				}
				if ((Object)(object)((Character)m_player).m_collider != (Object)null)
				{
					((Collider)((Character)m_player).m_collider).enabled = true;
				}
				if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner() && (Object)(object)((Character)m_player).m_body != (Object)null)
				{
					((Character)m_player).m_body.isKinematic = false;
				}
			}
		}

		private static void PauseWindowClock(ZDO zdo, float dt)
		{
			zdo.Set(DownedKeys.DownedTime, zdo.GetFloat(DownedKeys.DownedTime, 0f) + dt);
		}

		public void ChannelPing(long sender)
		{
			m_lastChannelTime = Time.time;
			m_lastChannelSender = sender;
		}
	}
	public class ReviveInteractable : MonoBehaviour, Hoverable, Interactable
	{
		private ZNetView? m_nview;

		private float m_lastPingTime = -999f;

		private const float PingInterval = 0.2f;

		private void Awake()
		{
			m_nview = ((Component)this).GetComponentInParent<ZNetView>();
		}

		private ZDOID LinkedPlayerZdoId()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid())
			{
				return ZDOID.None;
			}
			return m_nview.GetZDO().GetZDOID(DownedKeys.MarkerPlayer);
		}

		private Player? FindDownedPlayer()
		{
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			ZDOID val = LinkedPlayerZdoId();
			if (val == ZDOID.None)
			{
				return null;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(val);
			if (zDO == null)
			{
				return null;
			}
			ZNetView val2 = ZNetScene.instance.FindInstance(zDO);
			Player val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<Player>() : null);
			if (!((Object)(object)val3 != (Object)null) || !val3.IsDowned())
			{
				return null;
			}
			return val3;
		}

		private void SendChannelPing(Player downed)
		{
			if (!(Time.time - m_lastPingTime < 0.2f))
			{
				m_lastPingTime = Time.time;
				((Character)downed).m_nview.InvokeRPC("RevivalRevived_Channel", Array.Empty<object>());
			}
		}

		private bool LinkedPlayerDisconnected()
		{
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			ZDOID val = LinkedPlayerZdoId();
			if (val == ZDOID.None)
			{
				return false;
			}
			return ZDOMan.instance.GetZDO(val) == null;
		}

		private string OwnerName()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return "Viking";
			}
			string text = m_nview.GetZDO().GetString(DownedKeys.OwnerName, "");
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return "Viking";
		}

		public string GetHoverText()
		{
			Player val = FindDownedPlayer();
			if ((Object)(object)val == (Object)null)
			{
				if (LinkedPlayerDisconnected())
				{
					return Localization.instance.Localize(OwnerName() + " (disconnected)");
				}
				return "";
			}
			string text = OwnerName();
			string arg = (Plugin.RevivePressMode ? "" : "Hold ");
			string text2 = text + " (downed)\n";
			text2 += $"[<color=yellow><b>{arg}$KEY_Use</b></color>] Revive ({val.GetDownedRemainingTime():F0}s)";
			return Localization.instance.Localize(text2);
		}

		public string GetHoverName()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return "";
			}
			if ((Object)(object)FindDownedPlayer() != (Object)null || LinkedPlayerDisconnected())
			{
				return OwnerName();
			}
			return "";
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (!hold && !Plugin.RevivePressMode)
			{
				return false;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if (val == null)
			{
				return false;
			}
			Player val2 = FindDownedPlayer();
			if ((Object)(object)val2 == (Object)null || (Object)(object)val == (Object)(object)val2)
			{
				return false;
			}
			SendChannelPing(val2);
			return true;
		}

		public void SimulateHold()
		{
			Player val = FindDownedPlayer();
			if ((Object)(object)val != (Object)null)
			{
				SendChannelPing(val);
			}
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
	public class ReviveProgressUI : MonoBehaviour
	{
		private static ReviveProgressUI? s_instance;

		private GameObject? m_root;

		private Image? m_bg;

		private Image? m_fill;

		public static bool Visible { get; private set; }

		public static float Fill { get; private set; }

		public static void Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)s_instance != (Object)null))
			{
				GameObject val = new GameObject("RevivalRevived_ReviveProgressUI");
				Object.DontDestroyOnLoad((Object)val);
				s_instance = val.AddComponent<ReviveProgressUI>();
			}
		}

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Canvas");
			val.transform.SetParent(((Component)this).transform, false);
			Canvas obj = val.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 5000;
			Sprite sprite = MakeDiscSprite();
			m_bg = MakeImage(val.transform, "bg", sprite, new Color(0f, 0f, 0f, 0.55f), 84f);
			m_fill = MakeImage(val.transform, "fill", sprite, DownedMarker.ReviveGreen, 72f);
			m_fill.type = (Type)3;
			m_fill.fillMethod = (FillMethod)4;
			m_fill.fillOrigin = 2;
			m_fill.fillClockwise = true;
			m_fill.fillAmount = 0f;
			m_root = val;
			m_root.SetActive(false);
		}

		private static Image MakeImage(Transform parent, string name, Sprite sprite, Color color, float size)
		{
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			Image obj = val.AddComponent<Image>();
			obj.sprite = sprite;
			((Graphic)obj).color = color;
			RectTransform rectTransform = ((Graphic)obj).rectTransform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			rectTransform.anchorMax = val2;
			rectTransform.anchorMin = val2;
			rectTransform.anchoredPosition = new Vector2(0f, -110f);
			rectTransform.sizeDelta = new Vector2(size, size);
			return obj;
		}

		private static Sprite MakeDiscSprite()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_0031: 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)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)5, false);
			float num = 32f;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num2 = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(num, num));
					float num3 = Mathf.Clamp01((num - 1f - num2) / 2f);
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num3));
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}

		private void Update()
		{
			float num = 0f;
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if (!((Object)(object)allPlayer == (Object)null) && allPlayer.IsDowned())
				{
					num = Mathf.Max(num, allPlayer.GetReviveProgress());
				}
			}
			num = Mathf.Clamp01(num);
			bool flag = num > 0.01f;
			if ((Object)(object)m_root != (Object)null && m_root.activeSelf != flag)
			{
				m_root.SetActive(flag);
			}
			if (flag && (Object)(object)m_fill != (Object)null)
			{
				m_fill.fillAmount = num;
			}
			Visible = flag;
			Fill = (flag ? num : 0f);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}