Decompiled source of BetaRevive v1.2.0

BetaRevive.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BetaRevive.Patches;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyTitle("BetaRevive")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BetaRevive")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e18e20df-9b8c-4dd3-8bab-7ccaaca633f0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BetaRevive
{
	[BepInPlugin("xero.BetaRevive", "REPO Beta Revive", "1.2.0")]
	public class BetaRevive : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("xero.BetaRevive");

		internal static ManualLogSource mls;

		private static BetaRevive Instance;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls = ((BaseUnityPlugin)this).Logger;
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			mls.LogInfo((object)"[xero] Ultimate Revive Inited.");
			harmony.PatchAll(typeof(BetaRevive));
			harmony.PatchAll(typeof(ShopManagerPatch));
			harmony.PatchAll(typeof(PlayerControllerPatch));
			harmony.PatchAll(typeof(PhysGrabCartPatch));
		}
	}
}
namespace BetaRevive.Patches
{
	internal class ConfigManager
	{
		public static ConfigEntry<int> hpCost;

		public static ConfigEntry<string> reviveKey;

		public static void Initialize(ConfigFile cfg)
		{
			hpCost = cfg.Bind<int>("Ajustes de Revivir", "CostoHP", 20, "Cantidad de HP consumido al revivir.");
			reviveKey = cfg.Bind<string>("Controles", "TeclaRevivir", "h", "Tecla utilizada para activar la resurrecci\ufffdn.");
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart))]
	internal class PhysGrabCartPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void DisplayText()
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.RunIsShop() && PlayerControllerPatch.isGrab)
			{
				object value = AccessTools.Field(typeof(PlayerAvatar), "playerName").GetValue(PlayerControllerPatch.grabHead.playerAvatar);
				PlayerHealth playerHealth = PlayerController.instance.playerAvatarScript.playerHealth;
				int num = (int)AccessTools.Field(typeof(PlayerHealth), "health").GetValue(playerHealth);
				int value2 = ConfigManager.hpCost.Value;
				string value3 = ConfigManager.reviveKey.Value;
				if (num < value2)
				{
					ItemInfoExtraUI.instance.ItemInfoText($"Tu HP est\ufffd por debajo de {value2}", Color.red);
				}
				else
				{
					ItemInfoExtraUI.instance.ItemInfoText($"Pulsa [{value3}] para revivir a {value} usando {value2} HP", new Color(0.2f, 0.8f, 0.1f));
				}
			}
			else
			{
				if (SemiFunc.RunIsShop() || (!PhotonNetwork.IsMasterClient && PhotonNetwork.IsConnected))
				{
					return;
				}
				PlayerAvatar val = PlayerController.instance?.playerAvatarScript;
				if ((Object)(object)val != (Object)null)
				{
					PlayerDeathHead val2 = ReviveManager.FindAssistedHead(val);
					if ((Object)(object)val2?.playerAvatar != (Object)null)
					{
						object value4 = AccessTools.Field(typeof(PlayerAvatar), "playerName").GetValue(val2.playerAvatar);
						int value5 = ConfigManager.hpCost.Value;
						string value6 = ConfigManager.reviveKey.Value;
						ItemInfoExtraUI.instance.ItemInfoText($"Pulsa [{value6}] para revivir a {value4} usando {value5} HP", new Color(0.2f, 0.8f, 0.1f));
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal class PlayerControllerPatch
	{
		public static PlayerDeathHead grabHead;

		public static bool isGrab;

		[HarmonyPatch("FixedUpdate")]
		[HarmonyPostfix]
		private static void PlayerGrabHeadPatch(PlayerController __instance)
		{
			if (__instance != null && __instance.physGrabActive && (Object)(object)__instance.physGrabObject != (Object)null)
			{
				PlayerDeathHead component = __instance.physGrabObject.GetComponent<PlayerDeathHead>();
				if ((Object)(object)component?.playerAvatar != (Object)null)
				{
					grabHead = component;
					isGrab = true;
					return;
				}
			}
			isGrab = false;
		}
	}
	internal class ReviveManager : MonoBehaviourPunCallbacks, IOnEventCallback
	{
		private const byte ReviveEventCode = 199;

		private static readonly FieldInfo cartItemsField = AccessTools.Field(typeof(PhysGrabCart), "itemsInCart");

		public override void OnEnable()
		{
			((MonoBehaviourPunCallbacks)this).OnEnable();
			PhotonNetwork.AddCallbackTarget((object)this);
		}

		public override void OnDisable()
		{
			((MonoBehaviourPunCallbacks)this).OnDisable();
			PhotonNetwork.RemoveCallbackTarget((object)this);
		}

		private void Update()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			if (!Enum.TryParse<Key>(ConfigManager.reviveKey.Value, ignoreCase: true, out Key result) || Keyboard.current == null)
			{
				return;
			}
			ButtonControl val = (ButtonControl)(object)Keyboard.current[result];
			if (val == null || !val.wasPressedThisFrame)
			{
				return;
			}
			PlayerAvatar val2 = PlayerController.instance?.playerAvatarScript;
			if ((Object)(object)val2 == (Object)null || (Object)(object)val2.playerHealth == (Object)null || (Object)(object)val2.photonView == (Object)null)
			{
				return;
			}
			PlayerHealth playerHealth = val2.playerHealth;
			int num = (int)AccessTools.Field(typeof(PlayerHealth), "health").GetValue(playerHealth);
			int value = ConfigManager.hpCost.Value;
			if (num < value)
			{
				return;
			}
			if (PhotonNetwork.IsMasterClient || !PhotonNetwork.IsConnected)
			{
				AutoReviveHeldHeads(val2, value);
				AutoReviveInCarts(value);
			}
			PlayerDeathHead val3 = null;
			if (PlayerControllerPatch.isGrab && (Object)(object)PlayerControllerPatch.grabHead != (Object)null)
			{
				val3 = PlayerControllerPatch.grabHead;
			}
			else if (PhotonNetwork.IsMasterClient || !PhotonNetwork.IsConnected)
			{
				val3 = FindAssistedHead(val2);
				if ((Object)(object)val3 != (Object)null)
				{
					BetaRevive.mls.LogInfo((object)$"[xero] Asistencia del host: reviviendo cabeza en manos de otro jugador (pagas {value} HP).");
				}
			}
			if ((Object)(object)val3?.playerAvatar == (Object)null)
			{
				return;
			}
			if (PhotonNetwork.IsMasterClient || !PhotonNetwork.IsConnected)
			{
				if (TryReviveFromHead(val3))
				{
					string text = SemiFunc.PlayerGetSteamID(val2);
					StatsManager.instance.SetPlayerHealth(text, num - value, false);
				}
				return;
			}
			PhotonView component = ((Component)val3).GetComponent<PhotonView>();
			if (!((Object)(object)component == (Object)null))
			{
				object[] array = new object[3]
				{
					component.ViewID,
					val2.photonView.ViewID,
					value
				};
				RaiseEventOptions val4 = new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				};
				PhotonNetwork.RaiseEvent((byte)199, (object)array, val4, SendOptions.SendReliable);
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			if (photonEvent.Code != 199 || !PhotonNetwork.IsMasterClient || !(photonEvent.CustomData is object[] array) || array.Length < 3)
			{
				return;
			}
			int viewID = (int)array[0];
			int viewID2 = (int)array[1];
			int num = (int)array[2];
			PlayerDeathHead val = FindHead(viewID);
			if ((Object)(object)val?.playerAvatar == (Object)null)
			{
				return;
			}
			PlayerAvatar val2 = FindAvatar(viewID2);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.playerHealth == (Object)null))
			{
				int num2 = (int)AccessTools.Field(typeof(PlayerHealth), "health").GetValue(val2.playerHealth);
				if (num2 >= num && TryReviveFromHead(val))
				{
					string text = SemiFunc.PlayerGetSteamID(val2);
					StatsManager.instance.SetPlayerHealth(text, num2 - num, false);
				}
			}
		}

		internal static PlayerDeathHead FindAssistedHead(PlayerAvatar me)
		{
			//IL_00a1: 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)
			PlayerDeathHead result = null;
			float num = float.MaxValue;
			PlayerDeathHead[] array = Object.FindObjectsByType<PlayerDeathHead>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			foreach (PlayerDeathHead val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.playerAvatar == (Object)null || (Object)(object)val.playerAvatar == (Object)(object)me)
				{
					continue;
				}
				PhysGrabObject component = ((Component)val).GetComponent<PhysGrabObject>();
				if (!((Object)(object)component == (Object)null) && component.playerGrabbing != null && component.playerGrabbing.Count != 0 && (bool)AccessTools.Field(typeof(PlayerAvatar), "deadSet").GetValue(val.playerAvatar))
				{
					float num2 = Vector3.Distance(((Component)me).transform.position, ((Component)val).transform.position);
					if (num2 < num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		private static void AutoReviveHeldHeads(PlayerAvatar me, int cost)
		{
			if (!SemiFunc.RunIsLevel())
			{
				return;
			}
			PlayerDeathHead[] array = Object.FindObjectsByType<PlayerDeathHead>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			foreach (PlayerDeathHead val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.playerAvatar == (Object)null || (Object)(object)val.playerAvatar == (Object)(object)me)
				{
					continue;
				}
				PhysGrabObject component = ((Component)val).GetComponent<PhysGrabObject>();
				if ((Object)(object)component == (Object)null || component.playerGrabbing == null || component.playerGrabbing.Count == 0)
				{
					continue;
				}
				PlayerAvatar val2 = component.playerGrabbing[0]?.playerAvatar;
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)me) && !((Object)(object)val2.playerHealth == (Object)null))
				{
					int num = (int)AccessTools.Field(typeof(PlayerHealth), "health").GetValue(val2.playerHealth);
					if (num >= cost && TryReviveFromHead(val))
					{
						string text = SemiFunc.PlayerGetSteamID(val2);
						StatsManager.instance.SetPlayerHealth(text, num - cost, false);
						BetaRevive.mls.LogInfo((object)"[xero] Reanimacion automatica al agarrar (paga quien sujeta).");
					}
				}
			}
		}

		private static void AutoReviveInCarts(int cost)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.RunIsLevel())
			{
				return;
			}
			PhysGrabCart[] array = Object.FindObjectsByType<PhysGrabCart>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			foreach (PhysGrabCart val in array)
			{
				if ((Object)(object)val == (Object)null || !(cartItemsField.GetValue(val) is List<PhysGrabObject> list))
				{
					continue;
				}
				PhysGrabObject[] array2 = list.ToArray();
				foreach (PhysGrabObject val2 in array2)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					PlayerDeathHead component = ((Component)val2).GetComponent<PlayerDeathHead>();
					if ((Object)(object)component?.playerAvatar == (Object)null || !(bool)AccessTools.Field(typeof(PlayerAvatar), "deadSet").GetValue(component.playerAvatar))
					{
						continue;
					}
					PlayerAvatar val3 = FindNearestAlivePayer(((Component)component).transform.position, cost);
					if (!((Object)(object)val3 == (Object)null))
					{
						int num = (int)AccessTools.Field(typeof(PlayerHealth), "health").GetValue(val3.playerHealth);
						if (TryReviveFromHead(component))
						{
							StatsManager.instance.SetPlayerHealth(SemiFunc.PlayerGetSteamID(val3), num - cost, false);
							BetaRevive.mls.LogInfo((object)"[xero] Reanimacion fallback: cabeza en el carrito (paga el vivo mas cercano).");
						}
					}
				}
			}
		}

		private static PlayerAvatar FindNearestAlivePayer(Vector3 pos, int cost)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar result = null;
			float num = float.MaxValue;
			foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item.playerHealth == (Object)null) && !(bool)AccessTools.Field(typeof(PlayerAvatar), "deadSet").GetValue(item) && (int)AccessTools.Field(typeof(PlayerHealth), "health").GetValue(item.playerHealth) >= cost)
				{
					float num2 = Vector3.Distance(pos, ((Component)item).transform.position);
					if (num2 < num)
					{
						num = num2;
						result = item;
					}
				}
			}
			return result;
		}

		private static PlayerDeathHead FindHead(int viewID)
		{
			PhotonView val = PhotonView.Find(viewID);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return ((Component)val).GetComponent<PlayerDeathHead>() ?? ((Component)val).GetComponentInParent<PlayerDeathHead>();
		}

		private static PlayerAvatar FindAvatar(int viewID)
		{
			PhotonView val = PhotonView.Find(viewID);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return ((Component)val).GetComponent<PlayerAvatar>() ?? ((Component)val).GetComponentInParent<PlayerAvatar>();
		}

		private static bool TryReviveFromHead(PlayerDeathHead head)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)head?.playerAvatar == (Object)null)
			{
				return false;
			}
			GameObject gameObject = ((Component)head.playerAvatar).gameObject;
			if (!gameObject.activeInHierarchy)
			{
				gameObject.SetActive(true);
			}
			if (!(bool)AccessTools.Field(typeof(PlayerAvatar), "deadSet").GetValue(head.playerAvatar))
			{
				return false;
			}
			ForceExtractionPointTrue(head);
			head.playerAvatar.Revive(false);
			PlayerHealth playerHealth = head.playerAvatar.playerHealth;
			int num = (int)AccessTools.Field(typeof(PlayerHealth), "maxHealth").GetValue(playerHealth);
			playerHealth.Heal(num, true);
			((Component)head.playerAvatar).transform.position = ((Component)head).transform.position + Vector3.up * 2f;
			return true;
		}

		private static void ForceExtractionPointTrue(PlayerDeathHead head)
		{
			FieldInfo field = typeof(PlayerDeathHead).GetField("inExtractionPoint", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null)
			{
				field.SetValue(head, true);
			}
			FieldInfo field2 = typeof(PlayerDeathHead).GetField("inExtractionPointPrevious", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field2 != null)
			{
				field2.SetValue(head, true);
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager))]
	internal class ShopManagerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AddReviveManager(ShopManager __instance)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).gameObject.GetComponent<ReviveManager>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<ReviveManager>();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerDeathHead))]
	internal class PlayerDeathHeadPatch
	{
		[HarmonyPatch("CanBeRevived")]
		[HarmonyPrefix]
		private static bool OverrideReviveCheck(ref bool __result)
		{
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject))]
	internal class PhysGrabObjectPatch
	{
		[HarmonyPatch("CanInteract")]
		[HarmonyPostfix]
		private static void AllowReviveInteraction(ref bool __result, PhysGrabber grabber)
		{
			if ((Object)(object)grabber.playerAvatar?.playerHealth != (Object)null)
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHealthGrab))]
	internal class PlayerHealthGrabPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void PostfixUpdate(ref bool __result)
		{
			if (GameManager.Multiplayer())
			{
				__result = true;
			}
		}
	}
}