Decompiled source of SharedLives v1.0.0

plugins/SharedLives.dll

Decompiled a day ago
using System;
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 SharedLives.Config;
using SharedLives.Core;
using SharedLives.UI;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Kai")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+d66481a8bc647715b69d50a271b1afc2f9ecfa3b")]
[assembly: AssemblyProduct("SharedLives")]
[assembly: AssemblyTitle("SharedLives")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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 SharedLives
{
	[BepInPlugin("Kai.SharedLives", "SharedLives", "1.0")]
	public class SharedLives : BaseUnityPlugin
	{
		internal static SharedLives Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			SharedLivesConfig.Bind(((BaseUnityPlugin)this).Config);
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0025: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		private void OnGUI()
		{
			SharedLivesHUD.Draw();
		}
	}
}
namespace SharedLives.UI
{
	internal static class SharedLivesHUD
	{
		private static GUIStyle? _style;

		internal static void Draw()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if (SharedLivesConfig.Enabled.Value && !((Object)(object)StatsManager.instance == (Object)null))
			{
				bool flag = (Object)(object)MapToolController.instance != (Object)null && SharedLivesHUDState.MapOpen;
				bool holdingDeathHead = SharedLivesHUDState.HoldingDeathHead;
				bool flag2 = (Object)(object)PlayerController.instance != (Object)null && (Object)(object)PlayerController.instance.playerAvatarScript != (Object)null && PlayerController.instance.playerAvatarScript.isDisabled;
				if (flag || holdingDeathHead || flag2)
				{
					EnsureStyle();
					string text = $"Shared Lives: {SharedLivesState.CurrentLives}";
					Rect val = default(Rect);
					((Rect)(ref val))..ctor((float)Screen.width - 280f - 20f, 20f, 280f, 32f);
					GUI.Label(val, text, _style);
				}
			}
		}

		private static void EnsureStyle()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (_style == null)
			{
				_style = new GUIStyle(GUI.skin.label)
				{
					fontSize = 20,
					fontStyle = (FontStyle)0,
					alignment = (TextAnchor)2
				};
				_style.normal.textColor = Color.white;
			}
		}
	}
	internal static class SharedLivesHUDState
	{
		private static PhysGrabObject? _heldDeathHead;

		internal static bool MapOpen { get; set; }

		internal static bool HoldingDeathHead
		{
			get
			{
				if ((Object)(object)_heldDeathHead == (Object)null)
				{
					return false;
				}
				return _heldDeathHead.grabbedLocal;
			}
		}

		internal static void DeathHeadGrabStarted(PhysGrabObject physGrabObject)
		{
			_heldDeathHead = physGrabObject;
		}

		internal static void DeathHeadGrabEnded(PhysGrabObject physGrabObject)
		{
			if ((Object)(object)_heldDeathHead == (Object)(object)physGrabObject)
			{
				_heldDeathHead = null;
			}
		}
	}
}
namespace SharedLives.Patches
{
	[HarmonyPatch]
	internal static class DeathHeadGrabPatch
	{
		[HarmonyPatch(typeof(PhysGrabObject), "GrabStarted")]
		[HarmonyPostfix]
		private static void GrabStartedPostfix(PhysGrabObject __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<PlayerDeathHead>() == (Object)null))
			{
				SharedLivesHUDState.DeathHeadGrabStarted(__instance);
			}
		}

		[HarmonyPatch(typeof(PhysGrabObject), "GrabEnded")]
		[HarmonyPostfix]
		private static void GrabEndedPostfix(PhysGrabObject __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<PlayerDeathHead>() == (Object)null))
			{
				SharedLivesHUDState.DeathHeadGrabEnded(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHealth), "DeathImpulseRPC")]
	internal static class EnemyHealthDeathImpulseRPCPatch
	{
		private static void Prefix(bool ___dead, out bool __state)
		{
			__state = ___dead;
		}

		private static void Postfix(EnemyHealth __instance, bool ___dead, bool __state)
		{
			if (!SharedLivesConfig.Enabled.Value || !SharedLivesConfig.LifeGainEnabled.Value || !SharedLivesState.IsAuthority || __state || !___dead)
			{
				return;
			}
			EnemyParent componentInParent = ((Component)__instance).GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				string enemyName = componentInParent.enemyName;
				if (SharedLivesConfig.IsEnemyKillBlacklisted(enemyName))
				{
					SharedLives.Logger.LogDebug((object)("Enemy kill ignored by blacklist: " + enemyName));
					return;
				}
			}
			int value = SharedLivesConfig.EnemyKiller.Value;
			if (SharedLivesState.TryAddLives(value, out var previousLives, out var currentLives))
			{
				SharedLives.Logger.LogDebug((object)($"Life gained from enemy kill (+{value}): " + $"{previousLives} -> {currentLives}"));
			}
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "DestroyAllPhysObjectsInHaulList")]
	internal static class ExtractionPointDestroyAllHaulPatch
	{
		private static void Prefix()
		{
			if (SharedLivesConfig.Enabled.Value && SharedLivesConfig.LifeGainEnabled.Value && SharedLivesState.IsAuthority && SemiFunc.RunIsLevel())
			{
				int value = SharedLivesConfig.CompleteExtractionPoint.Value;
				if (SharedLivesState.TryAddLives(value, out var previousLives, out var currentLives))
				{
					SharedLives.Logger.LogDebug((object)($"Extraction point bonus (+{value}): " + $"{previousLives} -> {currentLives}"));
				}
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "GenerateDone")]
	internal static class LevelGeneratorGenerateDonePatch
	{
		private static void Postfix()
		{
			if (SharedLivesConfig.Enabled.Value && SharedLivesConfig.Scope.Value == LivesScope.Level && SharedLivesState.IsAuthority && SemiFunc.RunIsLevel() && SharedLivesState.ResetLives())
			{
				SharedLives.Logger.LogDebug((object)$"Shared lives reset for level: {SharedLivesState.CurrentLives}");
			}
		}
	}
	[HarmonyPatch(typeof(MapToolController), "Update")]
	internal static class MapToolControllerUpdatePatch
	{
		private static void Postfix(MapToolController __instance, bool ___Active)
		{
			if (!((Object)(object)__instance != (Object)(object)MapToolController.instance))
			{
				SharedLivesHUDState.MapOpen = ___Active;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")]
	internal static class PlayerAvatarPlayerDeathRPCPatch
	{
		private static void Prefix(bool ___deadSet, out bool __state)
		{
			__state = ___deadSet;
		}

		private static void Postfix(bool ___deadSet, bool __state)
		{
			if (SharedLivesConfig.Enabled.Value && SharedLivesConfig.ConsumeMode.Value == LifeConsumeMode.OnDeath && SharedLivesState.IsAuthority && !__state && ___deadSet && SharedLivesState.TryConsumeLife(out var previousLives, out var currentLives))
			{
				SharedLives.Logger.LogDebug((object)$"Life consumed on death: {previousLives} -> {currentLives}");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Revive")]
	internal static class PlayerAvatarRevivePatch
	{
		private static bool Prefix(bool ___deadSet, PlayerDeathHead ___playerDeathHead)
		{
			if (!SharedLivesConfig.Enabled.Value)
			{
				return true;
			}
			if (!SharedLivesState.IsLivesActiveScene)
			{
				return true;
			}
			if (!___deadSet)
			{
				return true;
			}
			if (!SharedLivesState.IsAuthority)
			{
				return true;
			}
			if ((Object)(object)___playerDeathHead == (Object)null)
			{
				return true;
			}
			if (!SharedLivesState.CanRevive())
			{
				SharedLives.Logger.LogDebug((object)"Revive blocked: no shared lives remaining.");
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")]
	internal static class PlayerAvatarReviveRPCPatch
	{
		private static bool Prefix(bool ___deadSet, PlayerDeathHead ___playerDeathHead, out bool __state)
		{
			__state = false;
			if (!SharedLivesConfig.Enabled.Value)
			{
				return true;
			}
			if (!SharedLivesState.IsLivesActiveScene)
			{
				return true;
			}
			if (!___deadSet)
			{
				return true;
			}
			if ((Object)(object)___playerDeathHead == (Object)null)
			{
				return true;
			}
			if (!SharedLivesState.CanRevive())
			{
				if (SharedLivesState.IsAuthority)
				{
					SharedLives.Logger.LogDebug((object)"ReviveRPC blocked: no shared lives remaining.");
				}
				return false;
			}
			__state = true;
			return true;
		}

		private static void Postfix(bool ___deadSet, bool __state)
		{
			if (__state && SharedLivesConfig.Enabled.Value && SharedLivesState.IsLivesActiveScene && SharedLivesConfig.ConsumeMode.Value == LifeConsumeMode.OnRevive && SharedLivesState.IsAuthority && !___deadSet)
			{
				if (!SharedLivesState.TryConsumeLife(out var previousLives, out var currentLives))
				{
					SharedLives.Logger.LogWarning((object)"Revive succeeded, but SharedLives failed to consume a life.");
				}
				else
				{
					SharedLives.Logger.LogDebug((object)("Life consumed on successful revive: " + $"{previousLives} -> {currentLives}"));
				}
			}
		}
	}
	[HarmonyPatch(typeof(SemiFunc), "LevelSuccessful")]
	internal static class SemiFuncLevelSuccessfulPatch
	{
		private static void Postfix()
		{
			if (SharedLivesConfig.Enabled.Value && SharedLivesConfig.LifeGainEnabled.Value && SharedLivesState.IsAuthority)
			{
				int value = SharedLivesConfig.CompleteLevelBonus.Value;
				if (SharedLivesState.TryAddLives(value, out var previousLives, out var currentLives))
				{
					SharedLives.Logger.LogDebug((object)($"Complete level bonus (+{value}): " + $"{previousLives} -> {currentLives}"));
				}
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "RunStartStats")]
	internal static class StatsManagerRunStartStatsPatch
	{
		private static void Postfix()
		{
			if (SharedLivesConfig.Enabled.Value)
			{
				SharedLivesState.Initialize(StatsManager.instance);
				SharedLives.Logger.LogDebug((object)$"Shared lives initialized: {SharedLivesState.StartingLives}");
			}
		}
	}
}
namespace SharedLives.Patches.Compat
{
	[HarmonyPatch]
	internal static class MedicHasRequiredHealthPatch
	{
		private const string TypeName = "Medic_.MedicHeadReviver";

		private static bool Prepare()
		{
			return AccessTools.TypeByName("Medic_.MedicHeadReviver") != null;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("Medic_.MedicHeadReviver"), "HasRequiredHealth", (Type[])null, (Type[])null);
		}

		private static void Postfix(ref bool __result)
		{
			if (SharedLivesConfig.Enabled.Value && SharedLivesState.IsLivesActiveScene && !SharedLivesState.CanRevive())
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class MedicFailedReviveMessagePatch
	{
		private const string TypeName = "Medic_.MedicPlugin";

		private static bool Prepare()
		{
			return AccessTools.TypeByName("Medic_.MedicPlugin") != null;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("Medic_.MedicPlugin"), "GetRandomFailedReviveMessage", (Type[])null, (Type[])null);
		}

		private static void Postfix(ref string __result)
		{
			if (SharedLivesConfig.Enabled.Value && SharedLivesState.IsLivesActiveScene && !SharedLivesState.CanRevive())
			{
				__result = SharedLivesConfig.GetRandomMedicNoLivesMessage();
			}
		}
	}
	[HarmonyPatch]
	internal static class MedicReviveHeadPatch
	{
		private const string MedicHeadReviverTypeName = "Medic_.MedicHeadReviver";

		private static bool Prepare()
		{
			return AccessTools.TypeByName("Medic_.MedicHeadReviver") != null;
		}

		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Medic_.MedicHeadReviver");
			return AccessTools.Method(type, "ReviveHead", (Type[])null, (Type[])null);
		}

		private static bool Prefix(PlayerDeathHead __0, PlayerAvatar __1)
		{
			if (!SharedLivesConfig.Enabled.Value)
			{
				return true;
			}
			if (!SharedLivesState.IsLivesActiveScene)
			{
				return true;
			}
			if (!SharedLivesState.IsAuthority)
			{
				return true;
			}
			if ((Object)(object)__0 == (Object)null || (Object)(object)__1 == (Object)null)
			{
				return true;
			}
			if (SharedLivesState.CanRevive())
			{
				return true;
			}
			SharedLives.Logger.LogDebug((object)"Medic revive blocked: no shared lives remaining.");
			return false;
		}
	}
}
namespace SharedLives.Core
{
	internal static class SharedLivesState
	{
		internal const string StatsKey = "SharedLives.CurrentLives";

		internal static int CurrentLives
		{
			get
			{
				if ((Object)(object)StatsManager.instance == (Object)null)
				{
					return StartingLives;
				}
				if (StatsManager.instance.runStats.TryGetValue("SharedLives.CurrentLives", out var value))
				{
					return Math.Max(0, value);
				}
				return StartingLives;
			}
		}

		internal static int MaxLives => Math.Max(0, SharedLivesConfig.MaxLives.Value);

		internal static int StartingLives => ClampLives(SharedLivesConfig.StartingLives.Value);

		internal static bool IsAuthority => SemiFunc.IsMasterClientOrSingleplayer();

		internal static bool IsLivesActiveScene
		{
			get
			{
				if (!SemiFunc.RunIsLevel())
				{
					return SemiFunc.RunIsLobby();
				}
				return true;
			}
		}

		internal static int ClampLives(int value)
		{
			return Math.Clamp(value, 0, MaxLives);
		}

		internal static void Initialize(StatsManager statsManager)
		{
			statsManager.runStats["SharedLives.CurrentLives"] = StartingLives;
		}

		internal static bool SetLives(int value)
		{
			if (!IsAuthority)
			{
				return false;
			}
			if ((Object)(object)StatsManager.instance == (Object)null)
			{
				return false;
			}
			value = ClampLives(value);
			if ((Object)(object)PunManager.instance != (Object)null)
			{
				PunManager.instance.SetRunStatSet("SharedLives.CurrentLives", value);
			}
			else
			{
				StatsManager.instance.runStats["SharedLives.CurrentLives"] = value;
			}
			return true;
		}

		internal static bool ResetLives()
		{
			return SetLives(StartingLives);
		}

		internal static bool TryConsumeLife(out int previousLives, out int currentLives)
		{
			previousLives = CurrentLives;
			currentLives = previousLives;
			if (!IsAuthority)
			{
				return false;
			}
			if (!IsLivesActiveScene)
			{
				return false;
			}
			if (previousLives <= 0)
			{
				return false;
			}
			currentLives = previousLives - 1;
			return SetLives(currentLives);
		}

		internal static bool TryAddLives(int amount, out int previousLives, out int currentLives)
		{
			previousLives = CurrentLives;
			currentLives = previousLives;
			if (!IsAuthority)
			{
				return false;
			}
			if (!IsLivesActiveScene)
			{
				return false;
			}
			if (amount <= 0)
			{
				return false;
			}
			if (previousLives >= MaxLives)
			{
				return false;
			}
			currentLives = ClampLives(previousLives + amount);
			if (currentLives == previousLives)
			{
				return false;
			}
			return SetLives(currentLives);
		}

		internal static bool CanRevive()
		{
			return CurrentLives > 0;
		}
	}
}
namespace SharedLives.Config
{
	internal enum LifeConsumeMode
	{
		OnDeath,
		OnRevive
	}
	internal enum LivesScope
	{
		Run,
		Level
	}
	internal static class SharedLivesConfig
	{
		internal static ConfigEntry<bool> Enabled { get; private set; }

		internal static ConfigEntry<int> StartingLives { get; private set; }

		internal static ConfigEntry<int> MaxLives { get; private set; }

		internal static ConfigEntry<LifeConsumeMode> ConsumeMode { get; private set; }

		internal static ConfigEntry<LivesScope> Scope { get; private set; }

		internal static ConfigEntry<bool> LifeGainEnabled { get; private set; }

		internal static ConfigEntry<int> EnemyKiller { get; private set; }

		internal static ConfigEntry<string> EnemyKillBlacklist { get; private set; }

		internal static ConfigEntry<int> CompleteLevelBonus { get; private set; }

		internal static ConfigEntry<int> CompleteExtractionPoint { get; private set; }

		internal static ConfigEntry<string> MedicNoLivesMessages { get; private set; }

		internal static void Bind(ConfigFile config)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable or disable SharedLives.");
			StartingLives = config.Bind<int>("General", "StartingLives", 5, "Number of shared lives at the start of a run or level. Clamped between 0 and MaxLives.");
			MaxLives = config.Bind<int>("General", "MaxLives", 5, "Maximum number of shared lives. Values below 0 are treated as 0.");
			ConsumeMode = config.Bind<LifeConsumeMode>("General", "ConsumeMode", LifeConsumeMode.OnDeath, "OnDeath = consume one life when a player dies. OnRevive = consume one life when a player is revived.");
			Scope = config.Bind<LivesScope>("General", "LivesScope", LivesScope.Run, "Run = lives persist across the whole run. Level = lives reset at the start of every normal level.");
			LifeGainEnabled = config.Bind<bool>("LifeGain", "Enabled", true, "Enable or disable SharedLives life gain rules.");
			EnemyKiller = config.Bind<int>("LifeGain", "EnemyKiller", 1, new ConfigDescription("Number of shared lives gained when an enemy death is confirmed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			EnemyKillBlacklist = config.Bind<string>("LifeGain", "EnemyKillBlacklist", "Gnome,Banger", "Comma-separated enemy names that do not grant lives when killed. Example: Gnome,Banger");
			CompleteLevelBonus = config.Bind<int>("LifeGain", "Complete_LevelBonus", 5, new ConfigDescription("Number of shared lives gained when a level is successfully completed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			CompleteExtractionPoint = config.Bind<int>("LifeGain", "Complete_ExtractionPoint", 5, new ConfigDescription("Number of shared lives gained when an extraction point is completed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			MedicNoLivesMessages = config.Bind<string>("Compatibility.Medic", "NoLivesMessages", "There are no shared lives left!|We're out of shared lives!|I can't revive you - we're out of lives!", "Messages used by Medic when a revive is attempted with no shared lives remaining. Separate multiple messages with |.");
		}

		internal static bool IsEnemyKillBlacklisted(string enemyName)
		{
			if (string.IsNullOrWhiteSpace(enemyName))
			{
				return false;
			}
			string[] array = EnemyKillBlacklist.Value.Split(',');
			foreach (string text in array)
			{
				if (string.Equals(text.Trim(), enemyName, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		internal static string GetRandomMedicNoLivesMessage()
		{
			string[] array = MedicNoLivesMessages.Value.Split('|');
			List<string> list = new List<string>();
			string[] array2 = array;
			foreach (string text in array2)
			{
				string text2 = text.Trim();
				if (text2.Length > 0)
				{
					list.Add(text2);
				}
			}
			if (list.Count == 0)
			{
				return "There are no shared lives left!";
			}
			int index = Random.Range(0, list.Count);
			return list[index];
		}
	}
}