Decompiled source of SelfSacrifice v1.1.6

self-sacrifice.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("self-sacrifice")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("self-sacrifice")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ae45a597-8fb9-40e6-99b2-7864179fb0c1")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SelfSacrifice;

[BepInPlugin("mod.selfsacrifice", "SelfSacrifice", "1.1.6")]
public class SelfSacrificePlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(PlayerAvatar), "Start")]
	public class PlayerAvatarStartPatch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<PossessChatHandler>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<PossessChatHandler>();
			}
		}
	}

	public class PossessChatHandler : MonoBehaviourPun
	{
		[PunRPC]
		public void ForcePossessChat(string message, float typingSpeed, float delay)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ChatManager.instance != (Object)null)
			{
				ChatManager.instance.PossessChatScheduleStart(2);
				ChatManager.instance.PossessChat((PossessChatID)3, message, typingSpeed, Color.yellow, delay, true, 2, (UnityEvent)null);
				ChatManager.instance.PossessChatScheduleEnd();
			}
		}
	}

	[HarmonyPatch(typeof(PlayerHealthGrab), "Update")]
	public class PlayerHealthGrabPatch
	{
		private static void Postfix(PlayerHealthGrab __instance)
		{
			//IL_0598: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0503: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			List<PhysGrabber> list = staticGrabObjectRef.Invoke(__instance).playerGrabbing.ToList();
			float num = grabbingTimerRef.Invoke(__instance);
			if (list == null || list.Count == 0)
			{
				if (num != 0f)
				{
					grabbingTimerRef.Invoke(__instance) = 0f;
				}
				return;
			}
			grabbingTimerRef.Invoke(__instance) = num + Time.deltaTime;
			if (grabbingTimerRef.Invoke(__instance) < 1f)
			{
				return;
			}
			foreach (PhysGrabber item in list)
			{
				if ((Object)(object)item == (Object)null || (Object)(object)item.playerAvatar == (Object)null || (Object)(object)item.playerAvatar.playerHealth == (Object)null)
				{
					continue;
				}
				PlayerAvatar playerAvatar = item.playerAvatar;
				PlayerHealth playerHealth = playerAvatar.playerHealth;
				PlayerHealth playerHealth2 = __instance.playerAvatar.playerHealth;
				PlayerAvatar playerAvatar2 = __instance.playerAvatar;
				int num2 = healthRef.Invoke(playerHealth);
				int num3 = healthRef.Invoke(playerHealth2);
				int num4 = maxHealthRef.Invoke(playerHealth2);
				if (num3 >= num4)
				{
					continue;
				}
				if (num2 <= 10)
				{
					float num5 = Random.Range(0f, 1f);
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)$"Self-Sacrifice: RNG roll = {num5:F4}");
					if (num5 <= 0.01f)
					{
						playerHealth2.HealOther(999, true);
						playerHealth.HealOther(999, true);
						playerAvatar.HealedOther();
						string text = RareHealChats[Random.Range(0, RareHealChats.Count)];
						((Component)playerAvatar2).GetComponent<PhotonView>().RPC("ForcePossessChat", ((Component)playerAvatar2).GetComponent<PhotonView>().Owner, new object[3] { text, 3f, 0f });
						playerAvatar2.OverridePupilSize(3f, 4, 1f, 1f, 15f, 0.3f, 3f);
						playerAvatar2.playerHealth.EyeMaterialOverride((EyeOverrideState)3, 5f, 10);
						((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: super-rare RNG roll achieved, both players healed to full");
					}
					else if (num5 <= 0.21f)
					{
						playerHealth.HurtOther(10, Vector3.zero, false, -1);
						((MonoBehaviour)playerAvatar2).StartCoroutine(Instance.DelayedKill(playerAvatar2, 5f));
						string text2 = FailedHealChats[Random.Range(0, FailedHealChats.Count)];
						((Component)playerAvatar2).GetComponent<PhotonView>().RPC("ForcePossessChat", ((Component)playerAvatar2).GetComponent<PhotonView>().Owner, new object[3] { text2, 3f, 0f });
						playerAvatar2.OverridePupilSize(4f, 4, 1f, 1f, 15f, 0.3f, 3f);
						playerAvatar2.playerHealth.EyeMaterialOverride((EyeOverrideState)1, 5f, 10);
						((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: recipient struck down during sacrifice. F in chat");
					}
					else if (num5 <= 0.31f)
					{
						string text3 = steamIDRef.Invoke(playerAvatar2);
						int num6 = Random.Range(0, 6);
						string text4 = "";
						switch (num6)
						{
						case 0:
							PunManager.instance.UpgradePlayerHealth(text3);
							text4 = "I feel healthy as a horse";
							((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: recipient granted bonus MAX HEALTH");
							break;
						case 1:
							PunManager.instance.UpgradePlayerEnergy(text3);
							text4 = "I could run a marathon right now";
							((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: recipient granted bonus STAMINA");
							break;
						case 2:
							PunManager.instance.UpgradePlayerSprintSpeed(text3);
							text4 = "I am speeeeeeeeeeed";
							((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: recipient granted bonus SPRINT SPEED");
							break;
						case 3:
							PunManager.instance.UpgradePlayerExtraJump(text3);
							text4 = "boing boing";
							((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: recipient granted bonus EXTRA JUMP");
							break;
						case 4:
							PunManager.instance.UpgradePlayerGrabStrength(text3);
							text4 = "strength blessing activate";
							((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: recipient granted bonus GRAB STRENGTH");
							break;
						case 5:
							PunManager.instance.UpgradePlayerTumbleLaunch(text3);
							text4 = "launch blessing activate";
							((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: recipient granted bonus TUMBLE LAUNCH");
							break;
						}
						playerHealth.HurtOther(10, Vector3.zero, false, -1);
						((Component)playerAvatar2).GetComponent<PhotonView>().RPC("ForcePossessChat", ((Component)playerAvatar2).GetComponent<PhotonView>().Owner, new object[3] { text4, 3f, 0f });
						playerAvatar2.OverridePupilSize(3f, 4, 1f, 1f, 15f, 0.3f, 3f);
						playerAvatar2.playerHealth.EyeMaterialOverride((EyeOverrideState)3, 5f, 10);
					}
					else
					{
						playerHealth2.HealOther(25, true);
						playerHealth.HurtOther(10, Vector3.zero, false, -1);
						playerAvatar.HealedOther();
						string text5 = SuccessfulHealChats[Random.Range(0, SuccessfulHealChats.Count)];
						((Component)playerAvatar2).GetComponent<PhotonView>().RPC("ForcePossessChat", ((Component)playerAvatar2).GetComponent<PhotonView>().Owner, new object[3] { text5, 3f, 0f });
						((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Self-Sacrifice: donor healed recipient successfully");
					}
				}
				else
				{
					playerHealth2.HealOther(10, true);
					playerHealth.HurtOther(10, Vector3.zero, false, -1);
					playerAvatar.HealedOther();
				}
			}
			grabbingTimerRef.Invoke(__instance) = 0f;
		}
	}

	[CompilerGenerated]
	private sealed class <DelayedKill>d__18 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public float delay;

		public PlayerAvatar recipient;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <DelayedKill>d__18(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(delay);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				recipient.playerHealth.HurtOther(999, Vector3.zero, false, -1);
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private static readonly FieldRef<PlayerHealthGrab, StaticGrabObject> staticGrabObjectRef = AccessTools.FieldRefAccess<PlayerHealthGrab, StaticGrabObject>("staticGrabObject");

	private static readonly FieldRef<PlayerHealth, int> healthRef = AccessTools.FieldRefAccess<PlayerHealth, int>("health");

	private static readonly FieldRef<PlayerHealth, int> maxHealthRef = AccessTools.FieldRefAccess<PlayerHealth, int>("maxHealth");

	private static readonly FieldRef<PlayerHealthGrab, float> grabbingTimerRef = AccessTools.FieldRefAccess<PlayerHealthGrab, float>("grabbingTimer");

	private static readonly FieldRef<PlayerAvatar, string> steamIDRef = AccessTools.FieldRefAccess<PlayerAvatar, string>("steamID");

	private static List<string> SuccessfulHealChats = new List<string>();

	private static List<string> FailedHealChats = new List<string>();

	private static List<string> RareHealChats = new List<string>();

	public static SelfSacrificePlugin Instance { get; private set; }

	public static ManualLogSource LogInstance { get; private set; }

	private void Awake()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		LogInstance = ((BaseUnityPlugin)this).Logger;
		new Harmony("mod.selfsacrifice").PatchAll();
		LoadHealMessages();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"SelfSacrifice 1.1.5 loaded");
	}

	private void LoadHealMessages()
	{
		SuccessfulHealChats = new List<string>();
		FailedHealChats = new List<string>();
		RareHealChats = new List<string>();
		try
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string name) => name.EndsWith("HealChats.txt"));
			if (text == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"HealChats.txt embedded resource not found");
				return;
			}
			using (Stream stream = executingAssembly.GetManifestResourceStream(text))
			{
				using StreamReader streamReader = new StreamReader(stream);
				List<string> list = SuccessfulHealChats;
				while (!streamReader.EndOfStream)
				{
					string text2 = streamReader.ReadLine().Trim();
					if (string.IsNullOrEmpty(text2))
					{
						continue;
					}
					if (text2.StartsWith("#"))
					{
						if (text2.Contains("SuccessfulHealChats"))
						{
							list = SuccessfulHealChats;
						}
						else if (text2.Contains("FailedHealChats"))
						{
							list = FailedHealChats;
						}
						else if (text2.Contains("RareHealChats"))
						{
							list = RareHealChats;
						}
					}
					else
					{
						list.Add(text2);
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"loaded {SuccessfulHealChats.Count} successful chats, {FailedHealChats.Count} failed chats, {RareHealChats.Count} rare chats");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("failed to load HealChats.txt: " + ex.Message));
		}
	}

	[IteratorStateMachine(typeof(<DelayedKill>d__18))]
	public IEnumerator DelayedKill(PlayerAvatar recipient, float delay)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DelayedKill>d__18(0)
		{
			recipient = recipient,
			delay = delay
		};
	}
}