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
};
}
}