Decompiled source of UltimateReviveNew v1.1.0

UltimateReviveMod.dll

Decompiled 6 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
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("UltimateReviveMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("UltimateReviveMod")]
[assembly: AssemblyTitle("UltimateReviveMod")]
[assembly: AssemblyVersion("1.0.0.0")]
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;
		}
	}
}
namespace RevivePlayer
{
	[BepInPlugin("com.yuniverse.reviveplayer", "Revive Player", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		public static ManualLogSource Log;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigManager.Init(((BaseUnityPlugin)this).Config);
			harmony = new Harmony("com.yuniverse.reviveplayer");
			harmony.PatchAll();
			Log.LogInfo((object)"RevivePlayer 模組已成功載入!(修正多人連線血量同步問題)");
		}
	}
	public static class ConfigManager
	{
		public static ConfigEntry<float> HpPercentCost;

		public static ConfigEntry<int> TargetReviveHp;

		public static ConfigEntry<string> ReviveKey;

		public static void Init(ConfigFile config)
		{
			HpPercentCost = config.Bind<float>("General", "HP Percent Cost", 0.1f, "施救者需要消耗自己當前血量的百分比 (0.10 = 10%)");
			TargetReviveHp = config.Bind<int>("General", "Target Revive HP", 100, "隊友復活後的血量 (預設 100 為滿血)");
			ReviveKey = config.Bind<string>("Controls", "Revive Key", "H", "執行復活的按鍵");
		}
	}
	[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
	public static class PlayerControllerPatch
	{
		public static PlayerDeathHead GrabbedHead;

		public static PlayerAvatar GrabbedAvatar;

		public static bool IsGrabbing;

		private static void Postfix(PlayerController __instance)
		{
			IsGrabbing = false;
			GrabbedHead = null;
			GrabbedAvatar = null;
			if ((Object)(object)__instance != (Object)null && __instance.physGrabActive && (Object)(object)__instance.physGrabObject != (Object)null)
			{
				PlayerDeathHead component = __instance.physGrabObject.GetComponent<PlayerDeathHead>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.playerAvatar != (Object)null)
				{
					GrabbedHead = component;
					GrabbedAvatar = component.playerAvatar;
					IsGrabbing = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "Update")]
	public static class PhysGrabCartPatch
	{
		private static void Postfix()
		{
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.RunIsShop() || !PlayerControllerPatch.IsGrabbing)
			{
				return;
			}
			PlayerAvatar grabbedAvatar = PlayerControllerPatch.GrabbedAvatar;
			if ((Object)(object)grabbedAvatar == (Object)null)
			{
				return;
			}
			PlayerController instance = PlayerController.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarScript == (Object)null)
			{
				return;
			}
			PlayerHealth playerHealth = instance.playerAvatarScript.playerHealth;
			if ((Object)(object)playerHealth != (Object)null)
			{
				int healthInternal = Helpers.GetHealthInternal(playerHealth);
				float num = Mathf.Clamp01(ConfigManager.HpPercentCost.Value);
				int num2 = Mathf.Max(1, Mathf.CeilToInt((float)healthInternal * num));
				string value = ConfigManager.ReviveKey.Value;
				if (healthInternal <= num2)
				{
					ItemInfoExtraUI.instance.ItemInfoText($"血量不足以施展復活 (需要 {num2} HP)", new Color(1f, 0.2f, 0.2f));
					return;
				}
				string name = ((Object)grabbedAvatar).name;
				ItemInfoExtraUI.instance.ItemInfoText($"按下 [{value}] 復活 {name} (-{num2} HP / {Mathf.RoundToInt(num * 100f)}%)", new Color(0.2f, 1f, 0.2f));
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController), "Awake")]
	public static class InjectPatch
	{
		private static void Postfix(PlayerController __instance)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<ReviveManager>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<ReviveManager>();
			}
		}
	}
	public class ReviveManager : MonoBehaviourPun
	{
		private void Update()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			if (!Input.GetKeyDown(Helpers.ParseKey(ConfigManager.ReviveKey.Value)) || !PlayerControllerPatch.IsGrabbing)
			{
				return;
			}
			PlayerAvatar grabbedAvatar = PlayerControllerPatch.GrabbedAvatar;
			if ((Object)(object)grabbedAvatar == (Object)null || (Object)(object)grabbedAvatar.photonView == (Object)null)
			{
				return;
			}
			PlayerController instance = PlayerController.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarScript == (Object)null)
			{
				return;
			}
			PlayerHealth playerHealth = instance.playerAvatarScript.playerHealth;
			if ((Object)(object)playerHealth == (Object)null)
			{
				return;
			}
			int healthInternal = Helpers.GetHealthInternal(playerHealth);
			float num = Mathf.Clamp01(ConfigManager.HpPercentCost.Value);
			int num2 = Mathf.Max(1, Mathf.CeilToInt((float)healthInternal * num));
			if (healthInternal > num2)
			{
				PhotonView val = PhotonView.Get((Component)this);
				if ((Object)(object)val != (Object)null)
				{
					int viewID = grabbedAvatar.photonView.ViewID;
					Plugin.Log.LogInfo((object)$"[連線要求] 正在向伺服器申請復活 {((Object)grabbedAvatar).name} (ID: {viewID}),扣除自身 {num2} HP");
					val.RPC("HostRevive", (RpcTarget)2, new object[1] { viewID });
					playerHealth.Hurt(num2, true, -1, false);
				}
			}
		}

		[PunRPC]
		private void HostRevive(int viewID)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			Plugin.Log.LogInfo((object)$"[伺服器端] 房主收到復活請求,正在處理 ViewID: {viewID}");
			PhotonView val = PhotonView.Find(viewID);
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			PlayerAvatar component = ((Component)val).GetComponent<PlayerAvatar>();
			if ((Object)(object)component != (Object)null)
			{
				component.Revive(false);
				int value = ConfigManager.TargetReviveHp.Value;
				PhotonView val2 = PhotonView.Get((Component)this);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.RPC("SyncHealth", (RpcTarget)0, new object[2] { viewID, value });
				}
			}
		}

		[PunRPC]
		private void SyncHealth(int viewID, int targetHp)
		{
			PhotonView val = PhotonView.Find(viewID);
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			PlayerHealth component = ((Component)val).GetComponent<PlayerHealth>();
			if ((Object)(object)component != (Object)null)
			{
				Traverse.Create((object)component).Field("health").SetValue((object)targetHp);
				if (val.IsMine)
				{
					Traverse.Create((object)component).Method("UpdateHealthUI", Array.Empty<object>()).GetValue();
				}
				Plugin.Log.LogInfo((object)$"[連線同步] 玩家 (ViewID: {viewID}) 的血量已強制同步為: {targetHp}");
			}
		}
	}
	public static class Helpers
	{
		public static KeyCode ParseKey(string key)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(key))
			{
				return (KeyCode)104;
			}
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), key.ToUpperInvariant(), ignoreCase: true);
			}
			catch
			{
				return (KeyCode)104;
			}
		}

		public static int GetHealthInternal(PlayerHealth health)
		{
			return Traverse.Create((object)health).Field("health").GetValue<int>();
		}
	}
}