using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FirstPersonDeath.Patches;
using GameNetcodeStuff;
using HarmonyLib;
using TMPro;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("FirstPersonDeath")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FirstPersonDeath")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("94edb759-c44e-4b9e-8486-12654b79b044")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FirstPersonDeath
{
[BepInPlugin("rogan.FirstPersonDeath", "First Person Death", "1.2.4")]
public class FirstPersonDeathBase : BaseUnityPlugin
{
private const string modGUID = "rogan.FirstPersonDeath";
private const string modName = "First Person Death";
private const string modVersion = "1.2.4";
private readonly Harmony harmony = new Harmony("rogan.FirstPersonDeath");
private static FirstPersonDeathBase Instance;
internal static ManualLogSource mls;
public static ConfigEntry<string> SwapKey;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
LoadConfigs();
mls = Logger.CreateLogSource("rogan.FirstPersonDeath");
mls.LogInfo((object)"FirstPersonDeath Started!");
harmony.PatchAll(typeof(FirstPersonDeathBase));
harmony.PatchAll(typeof(KeyDownPatch));
harmony.PatchAll(typeof(KillPlayerPatch));
harmony.PatchAll(typeof(HudManagerPatch));
harmony.PatchAll(typeof(MaskedPlayerPatch));
harmony.PatchAll(typeof(PlayerControllerPatch));
}
private void LoadConfigs()
{
SwapKey = ((BaseUnityPlugin)this).Config.Bind<string>("FirstPersonDeath", "SwapKey", "E", "Key used to toggle perspectives; Default binding may conflict with other mods!");
}
}
}
namespace FirstPersonDeath.Patches
{
[HarmonyPatch(typeof(PlayerControllerB))]
internal class KeyDownPatch
{
public static KeyCode SwapKeyCode = (KeyCode)Enum.Parse(typeof(KeyCode), FirstPersonDeathBase.SwapKey.Value);
public static KeyboardShortcut SwapKey = new KeyboardShortcut(SwapKeyCode, Array.Empty<KeyCode>());
public static bool SwapKeyDown = false;
public static bool UsePlayerCamera = false;
public static string LastSpectatedPlayer = "";
[HarmonyPatch("Update")]
[HarmonyPostfix]
private static void SwapPatch()
{
if (GameNetworkManager.Instance.localPlayerController.isPlayerDead)
{
if (((KeyboardShortcut)(ref SwapKey)).IsDown())
{
if (!SwapKeyDown)
{
UsePlayerCamera = !UsePlayerCamera;
SwapKeyDown = true;
}
}
else if (((KeyboardShortcut)(ref SwapKey)).IsUp())
{
SwapKeyDown = false;
}
}
else
{
UsePlayerCamera = true;
}
}
}
internal class KillPlayerPatch
{
[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> DeathLengthPatch(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> list = instructions.ToList();
for (int i = 0; i < list.Count - 1; i++)
{
if (list[i].opcode == OpCodes.Ldc_R4 && list[i].operand.ToString() == "1.5")
{
list[i].operand = 0f;
FirstPersonDeathBase.mls.LogInfo((object)"Patched death camera time!");
}
}
return list;
}
}
internal class HudManagerPatch
{
[HarmonyPatch(typeof(HUDManager), "Update")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> EarlyVotePatch(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> list = instructions.ToList();
for (int i = 0; i < list.Count - 1; i++)
{
if (list[i].opcode == OpCodes.Ldstr && list[i].operand.ToString() == "Tell autopilot ship to leave early : [RMB] (Hold)")
{
CodeInstruction obj = list[i];
CodeInstruction obj2 = list[i];
obj.operand = (obj2.operand = obj2.operand?.ToString() + "\n\n\n\n\nSwitch Camera: [" + FirstPersonDeathBase.SwapKey.Value + "]");
FirstPersonDeathBase.mls.LogInfo((object)"Patched vote leave text!");
}
else if (list[i].opcode == OpCodes.Ldstr && (list[i].operand.ToString() == "Voted for ship to leave early" || list[i].operand.ToString() == "Ship leaving in one hour"))
{
CodeInstruction obj3 = list[i];
CodeInstruction obj4 = list[i];
obj3.operand = (obj4.operand = obj4.operand?.ToString() + "\n\n\n\n\n\nSwitch Camera: [" + FirstPersonDeathBase.SwapKey.Value + "]");
}
}
return list;
}
}
[HarmonyPatch(typeof(MaskedPlayerEnemy))]
internal class MaskedPlayerPatch
{
public static Transform MaskedTransform;
[HarmonyPatch("Update")]
[HarmonyPostfix]
private static void GetMaskedPatch(ref PlayerControllerB ___mimickingPlayer, Transform ___headTiltTarget)
{
if (Object.op_Implicit((Object)(object)___mimickingPlayer) && ___mimickingPlayer.playerUsername == PlayerControllerPatch.PlayerUsername)
{
MaskedTransform = ___headTiltTarget;
}
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal class PlayerControllerPatch
{
public static PlayerControllerB RoundController;
public static PlayerControllerB NetworkController;
public static GameObject MeshModel;
public static Rigidbody[] BodyParts;
public static DeadBodyInfo[] DeadMesh;
public static GameObject PivotCamera;
public static GameObject CameraHolder;
public static GameObject SpectateCamera;
public static AudioListener AudioListener;
public static int ClientId;
public static string PlayerUsername;
public static string SpectatedPlayer;
public static PlayerControllerB[] AllPlayers;
public static bool PlayerBody = true;
public static bool PlayerUnderwater = false;
public static bool PlayerDecapitated = false;
public static List<string> PlayerNames = new List<string>();
[HarmonyPatch("Update")]
[HarmonyPostfix]
public static void FirstPersonPatch()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Invalid comparison between Unknown and I4
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_021f: Invalid comparison between Unknown and I4
//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
//IL_06ba: Unknown result type (might be due to invalid IL or missing references)
//IL_06c0: Invalid comparison between Unknown and I4
//IL_07fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0892: Unknown result type (might be due to invalid IL or missing references)
//IL_0853: Unknown result type (might be due to invalid IL or missing references)
//IL_08ed: Unknown result type (might be due to invalid IL or missing references)
//IL_08c5: Unknown result type (might be due to invalid IL or missing references)
if ((!PlayerBody && (int)NetworkController.causeOfDeath != 4) || !((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null) || !((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null))
{
return;
}
RoundController = StartOfRound.Instance.localPlayerController;
NetworkController = GameNetworkManager.Instance.localPlayerController;
PivotCamera = ((Component)RoundController.spectateCameraPivot).gameObject;
SpectateCamera = ((Component)StartOfRound.Instance.spectateCamera).gameObject;
PlayerUsername = NetworkController.playerUsername;
ClientId = (int)NetworkController.playerClientId;
MeshModel = ((Component)NetworkController.thisPlayerModel).gameObject;
if (!NetworkController.isPlayerDead)
{
PlayerUnderwater = NetworkController.isUnderwater;
}
if (!NetworkController.isPlayerDead)
{
return;
}
if (Object.op_Implicit((Object)(object)NetworkController.spectatedPlayerScript))
{
SpectatedPlayer = NetworkController.spectatedPlayerScript.playerUsername;
}
AllPlayers = StartOfRound.Instance.allPlayerScripts;
if (SpectatedPlayer == PlayerUsername)
{
for (int i = 0; i < AllPlayers.Length; i++)
{
if (AllPlayers[i].playerUsername != PlayerUsername && !AllPlayers[i].playerUsername.Contains("Player #"))
{
NetworkController.spectatedPlayerScript = AllPlayers[i];
}
}
}
if (!Object.op_Implicit((Object)(object)AudioListener))
{
AudioListener = Object.FindObjectOfType<AudioListener>();
}
if (!Object.op_Implicit((Object)(object)CameraHolder))
{
if (DeadMesh == null)
{
FirstPersonDeathBase.mls.LogInfo((object)"Player dead! >.<");
}
if ((int)NetworkController.causeOfDeath == 4)
{
if (Object.op_Implicit((Object)(object)MaskedPlayerPatch.MaskedTransform))
{
CameraHolder = ((Component)MaskedPlayerPatch.MaskedTransform).gameObject;
}
else
{
DeadMesh = Object.FindObjectsOfType<DeadBodyInfo>();
DeadBodyInfo[] deadMesh = DeadMesh;
foreach (DeadBodyInfo val in deadMesh)
{
if (val.playerObjectId != ClientId)
{
continue;
}
BodyParts = val.bodyParts;
Rigidbody[] bodyParts = BodyParts;
foreach (Rigidbody val2 in bodyParts)
{
if (((Object)val2).name == "spine.004")
{
FirstPersonDeathBase.mls.LogInfo((object)"Found player head! :D");
CameraHolder = ((Component)val2).gameObject;
}
}
}
}
}
else
{
DeadMesh = Object.FindObjectsOfType<DeadBodyInfo>();
DeadBodyInfo[] deadMesh2 = DeadMesh;
foreach (DeadBodyInfo val3 in deadMesh2)
{
if (val3.playerObjectId != ClientId)
{
continue;
}
BodyParts = val3.bodyParts;
Rigidbody[] bodyParts2 = BodyParts;
foreach (Rigidbody val4 in bodyParts2)
{
if (((Object)val4).name == "spine.004")
{
FirstPersonDeathBase.mls.LogInfo((object)"Found player head! :D");
CameraHolder = ((Component)val4).gameObject;
}
}
if (!Object.op_Implicit((Object)(object)CameraHolder) && (Object)(object)val3.detachedHeadObject != (Object)null)
{
PlayerDecapitated = true;
CameraHolder = ((Component)val3.detachedHeadObject).gameObject;
FirstPersonDeathBase.mls.LogInfo((object)"Player died to coilhead! >.<");
}
}
}
}
if (StartOfRound.Instance.shipIsLeaving)
{
PlayerNames.Clear();
PlayerDecapitated = false;
if (StartOfRound.Instance.allPlayersDead)
{
NetworkController.spectatedPlayerScript = null;
((TMP_Text)HUDManager.Instance.spectatingPlayerText).text = "";
}
else
{
((TMP_Text)HUDManager.Instance.spectatingPlayerText).text = "(Spectating: " + SpectatedPlayer + ")";
}
HUDManager.Instance.setUnderwaterFilter = false;
StartOfRound.Instance.overrideSpectateCamera = false;
SpectateCamera.transform.parent = PivotCamera.transform;
SpectateCamera.transform.position = PivotCamera.transform.position;
return;
}
if (KeyDownPatch.UsePlayerCamera)
{
if (Object.op_Implicit((Object)(object)MaskedPlayerPatch.MaskedTransform))
{
MeshRenderer[] componentsInChildren = ((Component)MaskedPlayerPatch.MaskedTransform.root).gameObject.GetComponentsInChildren<MeshRenderer>();
MeshRenderer[] array = componentsInChildren;
foreach (MeshRenderer val5 in array)
{
((Renderer)val5).enabled = false;
}
SkinnedMeshRenderer[] componentsInChildren2 = ((Component)MaskedPlayerPatch.MaskedTransform.root).gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
SkinnedMeshRenderer[] array2 = componentsInChildren2;
foreach (SkinnedMeshRenderer val6 in array2)
{
((Renderer)val6).enabled = false;
}
}
if (PlayerUnderwater)
{
HUDManager.Instance.setUnderwaterFilter = true;
}
((TMP_Text)HUDManager.Instance.spectatingPlayerText).text = "";
StartOfRound.Instance.overrideSpectateCamera = true;
((Component)AudioListener).gameObject.transform.parent = SpectateCamera.transform;
((Component)AudioListener).gameObject.transform.localPosition = new Vector3(0f, 0f, 0f);
}
else
{
PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
foreach (PlayerControllerB val7 in allPlayerScripts)
{
if (!val7.playerUsername.Contains("Player #") && !PlayerNames.Contains(val7.playerUsername))
{
FirstPersonDeathBase.mls.LogInfo((object)("Added " + val7.playerUsername + " to PlayerNames!"));
PlayerNames.Add(val7.playerUsername);
}
}
if (PlayerNames.Count == 1)
{
return;
}
if ((int)NetworkController.causeOfDeath == 4 && Object.op_Implicit((Object)(object)MaskedPlayerPatch.MaskedTransform))
{
MeshRenderer[] componentsInChildren3 = ((Component)MaskedPlayerPatch.MaskedTransform.root).gameObject.GetComponentsInChildren<MeshRenderer>();
MeshRenderer[] array3 = componentsInChildren3;
foreach (MeshRenderer val8 in array3)
{
((Renderer)val8).enabled = true;
}
SkinnedMeshRenderer[] componentsInChildren4 = ((Component)MaskedPlayerPatch.MaskedTransform.root).gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
SkinnedMeshRenderer[] array4 = componentsInChildren4;
foreach (SkinnedMeshRenderer val9 in array4)
{
((Renderer)val9).enabled = true;
}
}
if (((TMP_Text)HUDManager.Instance.spectatingPlayerText).text == "")
{
((TMP_Text)HUDManager.Instance.spectatingPlayerText).text = "(Spectating: " + SpectatedPlayer + ")";
}
HUDManager.Instance.setUnderwaterFilter = false;
StartOfRound.Instance.overrideSpectateCamera = false;
((Component)AudioListener).gameObject.transform.parent = PivotCamera.transform;
((Component)AudioListener).gameObject.transform.localPosition = new Vector3(0f, 0f, 0f);
}
if (Object.op_Implicit((Object)(object)CameraHolder))
{
if ((Object)(object)SpectateCamera.transform.parent != (Object)(object)CameraHolder.transform)
{
SpectateCamera.transform.position = CameraHolder.transform.position;
}
SpectateCamera.transform.parent = CameraHolder.transform;
SpectateCamera.transform.localPosition = new Vector3(0f, 0f, 0.2f);
if (!PlayerDecapitated)
{
SpectateCamera.transform.localRotation = Quaternion.Euler(0f, 0f, 0f);
}
else
{
SpectateCamera.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
}
}
else
{
StartOfRound.Instance.overrideSpectateCamera = false;
PlayerBody = false;
}
}
}
}