Decompiled source of Linked Life v1.0.1

EmpressLinkedLife.dll

Decompiled 5 hours 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 Photon.Pun;
using Photon.Realtime;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Omniscye")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c574138cfea486cfa7104eae1a6f135c166daf8b")]
[assembly: AssemblyProduct("EmpressLinkedLife")]
[assembly: AssemblyTitle("EmpressLinkedLife")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
[BepInPlugin("com.empress.linkedlife", "Empress Linked Life", "2.1.5")]
public class EmpressSharedHealth : BaseUnityPlugin
{
	[HarmonyPatch(typeof(CameraAim), "Update")]
	public static class Patch_CameraAim_Update
	{
		private static bool Prefix()
		{
			return (Object)(object)Instance == (Object)null || !Instance.waitingForRetryDecision;
		}
	}

	public static EmpressSharedHealth Instance;

	public static ManualLogSource Log;

	public static ConfigEntry<bool> ConfigEnableChosenOne;

	public int chosenOneActorID = -1;

	public bool waitingForRetryDecision = false;

	public bool forcingGameOver = false;

	public bool isRetrying = false;

	private Dictionary<int, int> playerHealthTracker = new Dictionary<int, int>();

	private bool levelInitialized = false;

	private float damageGraceTimer = 0f;

	private Texture2D boxBackground;

	private void Awake()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
		Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		ConfigEnableChosenOne = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableChosenOne", true, "");
		boxBackground = new Texture2D(1, 1);
		boxBackground.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.95f));
		boxBackground.Apply();
		Harmony.CreateAndPatchAll(typeof(EmpressSharedHealth), (string)null);
		Log.LogInfo((object)"Empress Shared Health (Host Only) Initialized.");
	}

	public bool IsHostReady()
	{
		if (!SemiFunc.IsMultiplayer() || !SemiFunc.IsMasterClient())
		{
			return false;
		}
		if ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
		{
			return false;
		}
		if ((Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelLobby)
		{
			return false;
		}
		if ((Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelShop)
		{
			return false;
		}
		return true;
	}

	private void Update()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Invalid comparison between Unknown and I4
		if (waitingForRetryDecision)
		{
			if ((int)Cursor.lockState > 0)
			{
				Cursor.lockState = (CursorLockMode)0;
			}
			if (!Cursor.visible)
			{
				Cursor.visible = true;
			}
		}
		if (damageGraceTimer > 0f)
		{
			damageGraceTimer -= Time.deltaTime;
			if (IsHostReady())
			{
				SyncTrackerWithoutDamage();
			}
		}
		else if (!IsHostReady())
		{
			levelInitialized = false;
		}
		else if (!levelInitialized)
		{
			InitializeLevel();
		}
	}

	private void SyncTrackerWithoutDamage()
	{
		foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
		{
			if ((Object)(object)player != (Object)null && (Object)(object)player.photonView != (Object)null)
			{
				playerHealthTracker[player.photonView.OwnerActorNr] = player.playerHealth.health;
			}
		}
	}

	private void InitializeLevel()
	{
		playerHealthTracker.Clear();
		foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player.photonView == (Object)null))
			{
				int ownerActorNr = player.photonView.OwnerActorNr;
				playerHealthTracker[ownerActorNr] = player.playerHealth.health;
			}
		}
		if (isRetrying)
		{
			isRetrying = false;
		}
		PickChosenOne();
		levelInitialized = true;
		damageGraceTimer = 2f;
	}

	public void OnDamageDetected(int victimActorID, int damageAmount)
	{
		if (damageGraceTimer > 0f || victimActorID == chosenOneActorID)
		{
			return;
		}
		foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
		{
			if ((Object)(object)player == (Object)null || player.isDisabled)
			{
				continue;
			}
			int ownerActorNr = player.photonView.OwnerActorNr;
			if (ownerActorNr != victimActorID && ownerActorNr != chosenOneActorID)
			{
				int num = (playerHealthTracker.ContainsKey(ownerActorNr) ? playerHealthTracker[ownerActorNr] : player.playerHealth.health);
				int num2 = Mathf.Max(0, num - damageAmount);
				playerHealthTracker[ownerActorNr] = num2;
				if (num2 <= 0)
				{
					player.photonView.RPC("UpdateHealthRPC", (RpcTarget)0, new object[3]
					{
						0,
						player.playerHealth.maxHealth,
						true
					});
					player.PlayerDeath(-1);
				}
				else
				{
					player.photonView.RPC("UpdateHealthRPC", (RpcTarget)0, new object[3]
					{
						num2,
						player.playerHealth.maxHealth,
						true
					});
				}
			}
		}
	}

	[HarmonyPatch(typeof(PlayerHealth), "UpdateHealthRPC")]
	[HarmonyPrefix]
	public static void UpdateHealthRPC_Prefix(PlayerHealth __instance, int healthNew, int healthMax, PhotonMessageInfo _info)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)Instance) && Instance.IsHostReady() && !Instance.waitingForRetryDecision)
		{
			int actorNumber = _info.Sender.ActorNumber;
			if (!Instance.playerHealthTracker.ContainsKey(actorNumber))
			{
				Instance.playerHealthTracker[actorNumber] = healthMax;
			}
			int num = Instance.playerHealthTracker[actorNumber];
			if (healthNew < num)
			{
				int damageAmount = num - healthNew;
				Instance.playerHealthTracker[actorNumber] = healthNew;
				Instance.OnDamageDetected(actorNumber, damageAmount);
			}
			else if (healthNew > num)
			{
				Instance.playerHealthTracker[actorNumber] = healthNew;
			}
		}
	}

	[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
	[HarmonyPostfix]
	public static void Hurt_Postfix(PlayerHealth __instance, int damage)
	{
		if (Object.op_Implicit((Object)(object)Instance) && Instance.IsHostReady() && !Instance.waitingForRetryDecision && __instance.photonView.IsMine)
		{
			int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
			int health = __instance.health;
			if (!Instance.playerHealthTracker.ContainsKey(actorNumber))
			{
				Instance.playerHealthTracker[actorNumber] = __instance.maxHealth;
			}
			int num = Instance.playerHealthTracker[actorNumber];
			if (health < num)
			{
				int damageAmount = num - health;
				Instance.playerHealthTracker[actorNumber] = health;
				Instance.OnDamageDetected(actorNumber, damageAmount);
			}
		}
	}

	public void PickChosenOne()
	{
		//IL_007e: 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)
		if (!IsHostReady() || !ConfigEnableChosenOne.Value)
		{
			return;
		}
		if (PhotonNetwork.CurrentRoom.PlayerCount < 3)
		{
			chosenOneActorID = -1;
			return;
		}
		Dictionary<int, Player> players = PhotonNetwork.CurrentRoom.Players;
		List<int> list = new List<int>(players.Keys);
		if (list.Count > 0)
		{
			chosenOneActorID = list[Random.Range(0, list.Count)];
			SemiFunc.UIFocusText("A Chosen One has been selected...", Color.yellow, Color.white, 5f);
		}
	}

	[HarmonyPatch(typeof(RunManager), "ChangeLevel")]
	[HarmonyPrefix]
	public static bool ChangeLevel_Prefix(bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType)
	{
		if (!Object.op_Implicit((Object)(object)Instance) || !SemiFunc.IsMasterClient())
		{
			return true;
		}
		if (Instance.forcingGameOver)
		{
			return true;
		}
		if (Instance.waitingForRetryDecision)
		{
			return false;
		}
		bool flag = (Object)(object)RunManager.instance.levelCurrent != (Object)(object)RunManager.instance.levelArena && (Object)(object)RunManager.instance.levelCurrent != (Object)(object)RunManager.instance.levelLobby && (Object)(object)RunManager.instance.levelCurrent != (Object)(object)RunManager.instance.levelShop;
		if (_levelFailed && flag)
		{
			Instance.waitingForRetryDecision = true;
			return false;
		}
		return true;
	}

	private void OnGUI()
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Expected O, but got Unknown
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		if (waitingForRetryDecision && SemiFunc.IsMasterClient())
		{
			GUI.depth = -1000;
			float num = 600f;
			float num2 = 400f;
			float num3 = ((float)Screen.width - num) / 2f;
			float num4 = ((float)Screen.height - num2) / 2f;
			GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)boxBackground);
			GUIStyle val = new GUIStyle(GUI.skin.label);
			val.fontSize = 40;
			val.fontStyle = (FontStyle)1;
			val.normal.textColor = Color.red;
			val.alignment = (TextAnchor)4;
			GUI.Label(new Rect(num3, num4 + 20f, num, 100f), "TEAM WIPED", val);
			GUIStyle val2 = new GUIStyle(GUI.skin.button);
			val2.fontSize = 30;
			if (GUI.Button(new Rect(num3 + 50f, num4 + 150f, num - 100f, 80f), "RETRY LEVEL (Revive)", val2))
			{
				DoRetry();
			}
			if (GUI.Button(new Rect(num3 + 50f, num4 + 250f, num - 100f, 80f), "GIVE UP (Arena)", val2))
			{
				DoGiveUp();
			}
		}
	}

	private void DoRetry()
	{
		waitingForRetryDecision = false;
		playerHealthTracker.Clear();
		damageGraceTimer = 5f;
		isRetrying = true;
		foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player.photonView == (Object)null))
			{
				if (player.isDisabled || player.deadSet)
				{
					player.photonView.RPC("ReviveRPC", (RpcTarget)0, new object[1] { false });
				}
				int num = Random.Range(35, 101);
				player.photonView.RPC("UpdateHealthRPC", (RpcTarget)0, new object[3]
				{
					num,
					player.playerHealth.maxHealth,
					true
				});
			}
		}
		RunManager.instance.ChangeLevel(false, false, (ChangeLevelType)1);
	}

	private void DoGiveUp()
	{
		waitingForRetryDecision = false;
		damageGraceTimer = 5f;
		playerHealthTracker.Clear();
		forcingGameOver = true;
		RunManager.instance.ChangeLevel(false, true, (ChangeLevelType)0);
		forcingGameOver = false;
	}
}