using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Coroner.LCAPI;
using GameNetcodeStuff;
using HarmonyLib;
using LC_API.ServerAPI;
using Microsoft.CodeAnalysis;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EliteMasterEric")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Rework the Performance Report with new info, including cause of death.")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0")]
[assembly: AssemblyProduct("Coroner")]
[assembly: AssemblyTitle("Coroner")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace Coroner
{
internal class AdvancedDeathTracker
{
public const int PLAYER_CAUSE_OF_DEATH_DROPSHIP = 300;
public static readonly string[] FUNNY_NOTES = new string[36]
{
"The goofiest goober.", "The cutest employee.", "Had the most fun.", "Had the least fun.", "The bravest employee.", "Did a sick flip.", "Stubbed their toe.", "The most likely to die next time.", "The least likely to die next time.", "Dislikes smoke.",
"A team player.", "A real go-getter.", "Ate the most snacks.", "Passed GO and collected $200.", "Got freaky on a Friday night.", "I think this one's a serial killer.", "Perfectly unremarkable.", "Hasn't called their mother in a while.", "Has IP address 127.0.0.1.", "Secretly a lizard",
"If laziness was an Olympic, this playa would win gold everytime.", "So lazy they made sloths look like overachievers.", "The kind of person to take a nap during a coffee break.", "Achieved black belt in procrastination.", "The reason why the snooze button was invented.", "Had a PhD in finding the most comfortable position inside the ship.", "So lazy they've mastered the art of doing nothing without even trying.", "The kind of playa who turns any game into an epic quest.", "A playa!", "A true workhorse.",
"Went hustlin' mode!", "The epitome of laziness.", "The ultimate couch potato.", "If laziness has a human-form, this guy right here is it!", "The true definition of laid-back.", "Probably the one who baits their teammates to death."
};
private static readonly Dictionary<int, AdvancedCauseOfDeath> PlayerCauseOfDeath = new Dictionary<int, AdvancedCauseOfDeath>();
private static readonly Dictionary<int, string> PlayerNotes = new Dictionary<int, string>();
public static void ClearDeathTracker()
{
PlayerCauseOfDeath.Clear();
PlayerNotes.Clear();
}
public static void SetCauseOfDeath(int playerIndex, AdvancedCauseOfDeath causeOfDeath, bool broadcast = true)
{
PlayerCauseOfDeath[playerIndex] = causeOfDeath;
if (broadcast)
{
DeathBroadcaster.BroadcastCauseOfDeath(playerIndex, causeOfDeath);
}
}
public static void SetCauseOfDeath(int playerIndex, CauseOfDeath causeOfDeath, bool broadcast = true)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
SetCauseOfDeath(playerIndex, ConvertCauseOfDeath(causeOfDeath), broadcast);
}
public static void SetCauseOfDeath(PlayerControllerB playerController, CauseOfDeath causeOfDeath, bool broadcast = true)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
SetCauseOfDeath((int)playerController.playerClientId, ConvertCauseOfDeath(causeOfDeath), broadcast);
}
public static void SetCauseOfDeath(PlayerControllerB playerController, AdvancedCauseOfDeath causeOfDeath, bool broadcast = true)
{
SetCauseOfDeath((int)playerController.playerClientId, causeOfDeath, broadcast);
}
public static AdvancedCauseOfDeath GetCauseOfDeath(int playerIndex)
{
PlayerControllerB playerController = StartOfRound.Instance.allPlayerScripts[playerIndex];
return GetCauseOfDeath(playerController);
}
public static AdvancedCauseOfDeath GetCauseOfDeath(PlayerControllerB playerController)
{
if (!PlayerCauseOfDeath.ContainsKey((int)playerController.playerClientId))
{
Plugin.Instance.PluginLogger.LogDebug((object)$"Player {playerController.playerClientId} has no custom cause of death stored! Using fallback...");
return GuessCauseOfDeath(playerController);
}
Plugin.Instance.PluginLogger.LogDebug((object)$"Player {playerController.playerClientId} has custom cause of death stored! {PlayerCauseOfDeath[(int)playerController.playerClientId]}");
return PlayerCauseOfDeath[(int)playerController.playerClientId];
}
public static AdvancedCauseOfDeath GuessCauseOfDeath(PlayerControllerB playerController)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Invalid comparison between Unknown and I4
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Invalid comparison between Unknown and I4
if (playerController.isPlayerDead)
{
if (IsHoldingJetpack(playerController))
{
if ((int)playerController.causeOfDeath == 2)
{
return AdvancedCauseOfDeath.Player_Jetpack_Gravity;
}
if ((int)playerController.causeOfDeath == 3)
{
return AdvancedCauseOfDeath.Player_Jetpack_Blast;
}
}
return ConvertCauseOfDeath(playerController.causeOfDeath);
}
return AdvancedCauseOfDeath.Unknown;
}
public static bool IsHoldingJetpack(PlayerControllerB playerController)
{
GrabbableObject currentlyHeldObjectServer = playerController.currentlyHeldObjectServer;
if ((Object)(object)currentlyHeldObjectServer == (Object)null)
{
return false;
}
GameObject gameObject = ((Component)currentlyHeldObjectServer).gameObject;
if ((Object)(object)gameObject == (Object)null)
{
return false;
}
GrabbableObject component = gameObject.GetComponent<GrabbableObject>();
if ((Object)(object)component == (Object)null)
{
return false;
}
if (component is JetpackItem)
{
return true;
}
return false;
}
public static AdvancedCauseOfDeath ConvertCauseOfDeath(CauseOfDeath causeOfDeath)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Expected I4, but got Unknown
return (int)causeOfDeath switch
{
0 => AdvancedCauseOfDeath.Unknown,
1 => AdvancedCauseOfDeath.Bludgeoning,
2 => AdvancedCauseOfDeath.Gravity,
3 => AdvancedCauseOfDeath.Blast,
4 => AdvancedCauseOfDeath.Strangulation,
5 => AdvancedCauseOfDeath.Suffocation,
6 => AdvancedCauseOfDeath.Mauling,
7 => AdvancedCauseOfDeath.Gunshots,
8 => AdvancedCauseOfDeath.Crushing,
9 => AdvancedCauseOfDeath.Drowning,
10 => AdvancedCauseOfDeath.Abandoned,
11 => AdvancedCauseOfDeath.Electrocution,
_ => AdvancedCauseOfDeath.Unknown,
};
}
public static string StringifyCauseOfDeath(CauseOfDeath causeOfDeath)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return StringifyCauseOfDeath(ConvertCauseOfDeath(causeOfDeath), Plugin.RANDOM);
}
public static string StringifyCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath)
{
return StringifyCauseOfDeath(causeOfDeath, Plugin.RANDOM);
}
public static string StringifyCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath, Random random)
{
string[] array = SelectCauseOfDeath(causeOfDeath);
if (array.Length == 1 || Plugin.Instance.PluginConfig.ShouldUseSeriousDeathMessages())
{
return array[0];
}
return array[random.Next(array.Length)];
}
public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath)
{
if (!causeOfDeath.HasValue)
{
return FUNNY_NOTES;
}
switch (causeOfDeath)
{
case AdvancedCauseOfDeath.Bludgeoning:
return new string[4] { "Bludgeoned to death.", "Beaten up to a pulp.", "Pummeled into oblivion.", "Battered beyond recognition." };
case AdvancedCauseOfDeath.Gravity:
return new string[3] { "Fell to their death.", "Fell off a cliff.", "Forgot gravity existed." };
case AdvancedCauseOfDeath.Blast:
return new string[5] { "Exploded.", "Went out with a bang.", "Was blown to smithereens.", "Reduced to smithereens.", "Evaporated in the boom." };
case AdvancedCauseOfDeath.Strangulation:
return new string[3] { "Strangled to death.", "Got ambushed from behind.", "Was caught off guard." };
case AdvancedCauseOfDeath.Suffocation:
return new string[3] { "Suffocated to death.", "Forgot how to breathe.", "Ran out of airtime." };
case AdvancedCauseOfDeath.Mauling:
return new string[6] { "Mauled to death.", "Turned into ground beef.", "Ripped to shreds.", "Mangled beyond repair.", "Shredded to bits.", "Disassembled violently." };
case AdvancedCauseOfDeath.Gunshots:
return new string[5] { "Shot to death.", "Filled to the brim with bullets.", "Took one for the team.", "Bullet's new best friend.", "Caught the deadly rain." };
case AdvancedCauseOfDeath.Crushing:
return new string[3] { "Crushed to death.", "Squashed flat involuntarily.", "Compressed beyond limits." };
case AdvancedCauseOfDeath.Drowning:
return new string[4] { "Drowned to death.", "Turned into fish food.", "Forgot to bring a snorkel.", "Swam with the fishes." };
case AdvancedCauseOfDeath.Abandoned:
{
Terminal val = Object.FindObjectOfType<Terminal>();
string planetName = val.moonsCatalogueList[RoundManager.Instance.currentLevel.levelID].PlanetName;
return new string[3]
{
"Abandoned by their coworkers.",
"Was left behind.",
"Still left on " + planetName
};
}
case AdvancedCauseOfDeath.Electrocution:
return new string[4] { "Electrocuted to death.", "The most conductive employee.", "Zapped into oblivion.", "Met their shocking fate in a flash." };
case AdvancedCauseOfDeath.Kicking:
return new string[2] { "Kicked to death.", "Was mistakened for a soccer ball." };
case AdvancedCauseOfDeath.Enemy_Bracken:
return new string[5] { "Had their neck snapped by a Bracken.", "Stared at a Bracken too long.", "Neck busted and it wasn't even with a sledgehammer.", "Didn't look back on purpose.", "Had them looking back." };
case AdvancedCauseOfDeath.Enemy_EyelessDog:
return new string[5] { "Was eaten by an Eyeless Dog.", "Got caught using a mechanical keyboard.", "Wasn't quiet around an Eyeless Dog.", "Got gobbled up for making too much noise.", "Didn't even see what cannot see coming." };
case AdvancedCauseOfDeath.Enemy_ForestGiant:
return new string[2] { "Swallowed whole by a Forest Giant.", "Had the same faith as Bertolt Hoover." };
case AdvancedCauseOfDeath.Enemy_CircuitBees:
return new string[5] { "Electro-stung to death by Circuit Bees.", "Electrocuted to death.", "The most conductive employee.", "Zapped into oblivion.", "Met their shocking fate in a flash." };
case AdvancedCauseOfDeath.Enemy_GhostGirl:
return new string[10] { "Died a mysterious death.", "Lost their mind.", "Got a real bad headache.", "???", "Head just exploded outta nowhere.", "Definitely not schizophrenic.", "Separated from their noggin in an unfortunate case of headlessness!", "Headless in an instant!", "Was decapitated by an unknown being.", "Was decapitated by the wind." };
case AdvancedCauseOfDeath.Enemy_EarthLeviathan:
return new string[3] { "Swallowed whole by an Earth Leviathan.", "Didn't move a muscle.", "Devoured like a scrumptious snack from beneath." };
case AdvancedCauseOfDeath.Enemy_BaboonHawk:
return new string[5] { "Was eaten by a Baboon Hawk.", "Was mauled by a Baboon Hawk.", "Got played by a numbers game.", "Was handicapped and condemned by Baboons.", "Somehow was put at a diasdvantage." };
case AdvancedCauseOfDeath.Enemy_Jester:
return new string[7] { "Mauled to death by a Jester.", "Was the butt of the Jester's joke.", "Got pranked by the Jester.", "Got popped like a weasel.", "It's not just a silly little goof ball?", "Why you gotta wait for it though?", "Met their demise in a whimsical encounter." };
case AdvancedCauseOfDeath.Enemy_CoilHead:
return new string[3] { "Mauled to death by a Coil Head.", "Got in a staring contest with a Coil Head.", "Lost a staring contest with a Coil Head." };
case AdvancedCauseOfDeath.Enemy_SnareFlea:
return new string[3] { "Was suffocated by a Snare Flea.", "Got their face hugged by a Snare Flea.", "Received an affectionate embrace from a Snare Flea." };
case AdvancedCauseOfDeath.Enemy_Hygrodere:
return new string[5] { "Was absorbed by a Hygrodere.", "Got lost in the sauce.", "Had an oopsie with a Hygrodere.", "Stepped into something colourful.", "Hygrodere aren't supposed to be elastic, that's not how lethality works!" };
case AdvancedCauseOfDeath.Enemy_HoarderBug:
return new string[7] { "Was mauled by a Hoarder Bug.", "Was swarmed by a Hoarder Bug.", "Was hoarded by a Hoarder Bug.", "Tried to steal from a Hoarder Bug.", "Mistakened for an item.", "Was apprehended by a bug during a robbery.", "Caught red-handed stealin'." };
case AdvancedCauseOfDeath.Enemy_SporeLizard:
return new string[3] { "Was bitten by a Spore Lizard.", "Was puffed by a Spore Lizard.", "Wait, they're not just known for farting?" };
case AdvancedCauseOfDeath.Enemy_BunkerSpider:
return new string[3] { "Ensnared in the Bunker Spider's web.", "Caught up in the eight-legged embrace of the web-slinging maestro!", "Didn't watch out for them clever critters!" };
case AdvancedCauseOfDeath.Enemy_Thumper:
return new string[2] { "Was ravaged by a Thumper.", "Got thumped by a Thumper." };
case AdvancedCauseOfDeath.Enemy_MaskedPlayer_Wear:
return new string[2] { "Donned the Mask.", "Nobody cared who they were until they put on the Mask." };
case AdvancedCauseOfDeath.Enemy_MaskedPlayer_Victim:
return new string[2] { "Was killed by a Masked coworker.", "Became a tragedy at the hands of the Mask." };
case AdvancedCauseOfDeath.Enemy_Nutcracker_Kicked:
return new string[4] { "Was kicked to death by a Nutcracker.", "Got their nuts cracked by a Nutcracker.", "Was mistakened for a soccer ball.", "Got SIUUUUUU'ed real hard by a Nutcracker!" };
case AdvancedCauseOfDeath.Enemy_Nutcracker_Shot:
return new string[2] { "Got shot by a Nutcracker.", "Was at the wrong end of a 21-gun salute." };
case AdvancedCauseOfDeath.Player_Jetpack_Gravity:
return new string[4] { "Fell while using a jetpack.", "Flew too close to the sun.", "Ran out of fuel.", "Tryna defy gravity." };
case AdvancedCauseOfDeath.Player_Jetpack_Blast:
return new string[5] { "Blew up while using a Jetpack.", "Turned into a firework.", "Got blown up by bad piloting.", "Jetpack went boom, they became a flyin' firework in the room!", "You just wasted a $60m project, CJ!" };
case AdvancedCauseOfDeath.Player_Murder_Melee:
return new string[4] { "Was bludgeoned to death by a coworker.", "Was the victim of a murder.", "Got murdered.", "Got backstabbed by a coworker." };
case AdvancedCauseOfDeath.Player_Murder_Shotgun:
return new string[5] { "Was shot to death by a coworker.", "Was the victim of a murder.", "Got murdered.", "Got one-pumped by a coworker.", "Got 360-noscoped by a coworker." };
case AdvancedCauseOfDeath.Player_Quicksand:
return new string[8] { "Got stuck in quicksand.", "Drowned in quicksand", "Got swallowed whole by Earth itself.", "Had a flashback while getting sucked beneath.", "Life went cinematic as they slowly sunk.", "At least you'll never have to worry about leg day again!", "Took the 'sinking feeling' to a whole new level!", "Stuck between a rock and a squishy place!" };
case AdvancedCauseOfDeath.Player_StunGrenade:
return new string[2] { "Got flashbanged by a coworker.", "Was the victim of a murder." };
case AdvancedCauseOfDeath.Other_DepositItemsDesk:
return new string[2] { "Received a demotion.", "Was put on disciplinary leave." };
case AdvancedCauseOfDeath.Other_Dropship:
return new string[4] { "Was crushed by the Item Dropship.", "Couldn't wait for their items.", "Got too impatient for their items.", "No ice cream for you now!" };
case AdvancedCauseOfDeath.Other_Landmine:
return new string[2] { "Stepped on a landmine.", "Went to play minesweeper." };
case AdvancedCauseOfDeath.Other_Turret:
return new string[1] { "Got shot by a turret." };
case AdvancedCauseOfDeath.Other_Lightning:
return new string[6] { "Was struck by lightning.", "Well someone sure knows how to make an electrifying entrance!", "Someone just got a shocking surprise, courtesy of Mother Nature!", "Maybe stay somewhere safe instead of auditioning for the next Thor movie?", "Befriended Thor and went straight to the source.", "Zapped back to reality in the most electrifying way possible!" };
default:
return new string[3] { "Died somehow.", "Most sincerely dead.", "Expired in an inexplicable manner." };
}
}
internal static void SetCauseOfDeath(PlayerControllerB playerControllerB, object enemy_BaboonHawk)
{
throw new NotImplementedException();
}
}
internal enum AdvancedCauseOfDeath
{
Unknown,
Bludgeoning,
Gravity,
Blast,
Strangulation,
Suffocation,
Mauling,
Gunshots,
Crushing,
Drowning,
Abandoned,
Electrocution,
Kicking,
Enemy_BaboonHawk,
Enemy_Bracken,
Enemy_CircuitBees,
Enemy_CoilHead,
Enemy_EarthLeviathan,
Enemy_EyelessDog,
Enemy_ForestGiant,
Enemy_GhostGirl,
Enemy_Hygrodere,
Enemy_Jester,
Enemy_SnareFlea,
Enemy_SporeLizard,
Enemy_HoarderBug,
Enemy_Thumper,
Enemy_BunkerSpider,
Enemy_MaskedPlayer_Wear,
Enemy_MaskedPlayer_Victim,
Enemy_Nutcracker_Kicked,
Enemy_Nutcracker_Shot,
Player_Jetpack_Gravity,
Player_Jetpack_Blast,
Player_Quicksand,
Player_Murder_Melee,
Player_Murder_Shotgun,
Player_StunGrenade,
Other_Landmine,
Other_Turret,
Other_Lightning,
Other_DepositItemsDesk,
Other_Dropship
}
internal class DeathBroadcaster
{
private const string SIGNATURE_DEATH = "com.elitemastereric.coroner.death";
public static void Initialize()
{
if (Plugin.Instance.IsLCAPIPresent)
{
DeathBroadcasterLCAPI.Initialize();
}
else
{
Plugin.Instance.PluginLogger.LogInfo((object)"LC_API is not present! Skipping registration...");
}
}
public static void BroadcastCauseOfDeath(int playerId, AdvancedCauseOfDeath causeOfDeath)
{
AttemptBroadcast(BuildDataCauseOfDeath(playerId, causeOfDeath), "com.elitemastereric.coroner.death");
}
private static string BuildDataCauseOfDeath(int playerId, AdvancedCauseOfDeath causeOfDeath)
{
string text = playerId.ToString();
int num = (int)causeOfDeath;
return text + "|" + num;
}
private static void AttemptBroadcast(string data, string signature)
{
if (Plugin.Instance.IsLCAPIPresent)
{
DeathBroadcasterLCAPI.AttemptBroadcast(data, signature);
}
else
{
Plugin.Instance.PluginLogger.LogInfo((object)"LC_API is not present! Skipping broadcast...");
}
}
}
public static class PluginInfo
{
public const string PLUGIN_ID = "Coroner";
public const string PLUGIN_NAME = "Coroner";
public const string PLUGIN_VERSION = "1.4.0";
public const string PLUGIN_GUID = "com.elitemastereric.coroner";
}
[BepInPlugin("com.elitemastereric.coroner", "Coroner", "1.4.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
public static readonly Random RANDOM = new Random();
public ManualLogSource PluginLogger;
public PluginConfig PluginConfig;
public bool IsLCAPIPresent = false;
public static Plugin Instance { get; private set; }
private void Awake()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
Instance = this;
PluginLogger = ((BaseUnityPlugin)this).Logger;
Harmony val = new Harmony("com.elitemastereric.coroner");
val.PatchAll();
PluginLogger.LogInfo((object)"Plugin Coroner (com.elitemastereric.coroner) is loaded!");
LoadConfig();
QueryLCAPI();
DeathBroadcaster.Initialize();
}
private void QueryLCAPI()
{
PluginLogger.LogInfo((object)"Checking for LC_API...");
if (Chainloader.PluginInfos.ContainsKey("LC_API"))
{
Chainloader.PluginInfos.TryGetValue("LC_API", out var value);
if (value == null)
{
PluginLogger.LogError((object)"Detected LC_API, but could not get plugin info!");
IsLCAPIPresent = false;
}
else
{
PluginLogger.LogInfo((object)("LCAPI is present! " + value.Metadata.GUID + ":" + value.Metadata.Version));
IsLCAPIPresent = true;
}
}
else
{
PluginLogger.LogInfo((object)"LCAPI is not present.");
IsLCAPIPresent = false;
}
}
private void LoadConfig()
{
PluginConfig = new PluginConfig();
PluginConfig.BindConfig(((BaseUnityPlugin)this).Config);
}
}
public class PluginConfig
{
private ConfigEntry<bool> DisplayCauseOfDeath;
private ConfigEntry<bool> SeriousDeathMessages;
private ConfigEntry<bool> DisplayFunnyNotes;
private ConfigEntry<bool> DeathReplacesNotes;
public void BindConfig(ConfigFile _config)
{
DisplayCauseOfDeath = _config.Bind<bool>("General", "DisplayCauseOfDeath", true, "Display the cause of death in the player notes.");
SeriousDeathMessages = _config.Bind<bool>("General", "SeriousDeathMessages", false, "Cause of death messages are more to-the-point.");
DisplayFunnyNotes = _config.Bind<bool>("General", "DisplayFunnyNotes", true, "Display a random note when the player has no notes.");
DeathReplacesNotes = _config.Bind<bool>("General", "DeathReplacesNotes", true, "True to replace notes when the player dies, false to append.");
}
public bool ShouldDisplayCauseOfDeath()
{
return DisplayCauseOfDeath.Value;
}
public bool ShouldUseSeriousDeathMessages()
{
return SeriousDeathMessages.Value;
}
public bool ShouldDisplayFunnyNotes()
{
return DisplayFunnyNotes.Value;
}
public bool ShouldDeathReplaceNotes()
{
return DeathReplacesNotes.Value;
}
}
}
namespace Coroner.Patch
{
[HarmonyPatch(typeof(PlayerControllerB))]
[HarmonyPatch("KillPlayer")]
internal class PlayerControllerBKillPlayerPatch
{
public static void Prefix(PlayerControllerB __instance, ref CauseOfDeath causeOfDeath)
{
try
{
if ((int)causeOfDeath == 300)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player died from item dropship! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Other_Dropship);
causeOfDeath = (CauseOfDeath)8;
}
else if (__instance.isSinking && (int)causeOfDeath == 5)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player died of suffociation while sinking in quicksand! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Quicksand);
}
else if ((int)causeOfDeath != 3)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is dying! No cause of death registered in hook...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in PlayerControllerBKillPlayerPatch.Prefix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(DepositItemsDesk))]
[HarmonyPatch("AnimationGrabPlayer")]
internal class DepositItemsDeskAnimationGrabPlayerPatch
{
public static void Postfix(int playerID)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Accessing state after tentacle devouring...");
PlayerControllerB playerController = StartOfRound.Instance.allPlayerScripts[playerID];
Plugin.Instance.PluginLogger.LogDebug((object)"Player is dying! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(playerController, AdvancedCauseOfDeath.Other_DepositItemsDesk);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in DepositItemsDeskAnimationGrabPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(JesterAI))]
[HarmonyPatch("killPlayerAnimation")]
internal class JesterAIKillPlayerAnimationPatch
{
public static void Postfix(int playerId)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Accessing state after Jester mauling...");
PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId];
if ((Object)(object)val == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
return;
}
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(val, AdvancedCauseOfDeath.Enemy_Jester);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in JesterAIKillPlayerAnimationPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(SandWormAI))]
[HarmonyPatch("EatPlayer")]
internal class SandWormAIEatPlayerPatch
{
public static void Postfix(PlayerControllerB playerScript)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Accessing state after Sand Worm devouring...");
if ((Object)(object)playerScript == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
return;
}
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(playerScript, AdvancedCauseOfDeath.Enemy_EarthLeviathan);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in SandWormAIEatPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(RedLocustBees))]
[HarmonyPatch("BeeKillPlayerOnLocalClient")]
internal class RedLocustBeesBeeKillPlayerOnLocalClientPatch
{
public static void Postfix(int playerId)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Accessing state after Circuit Bee electrocution...");
PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId];
if ((Object)(object)val == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (val.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(val, AdvancedCauseOfDeath.Enemy_CircuitBees);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in RedLocustBeesBeeKillPlayerOnLocalClientPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(DressGirlAI))]
[HarmonyPatch("OnCollideWithPlayer")]
internal class DressGirlAIOnCollideWithPlayerPatch
{
public static void Postfix(DressGirlAI __instance)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Processing Ghost Girl player collision...");
if ((Object)(object)__instance.hauntingPlayer == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after collision!");
}
else if (__instance.hauntingPlayer.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__instance.hauntingPlayer, AdvancedCauseOfDeath.Enemy_GhostGirl);
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in DressGirlAIOnCollideWithPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(FlowermanAI))]
[HarmonyPatch("killAnimation")]
internal class FlowermanAIKillAnimationPatch
{
public static void Postfix(FlowermanAI __instance)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Accessing state after Bracken snapping neck...");
if ((Object)(object)((EnemyAI)__instance).inSpecialAnimationWithPlayer == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after snapping neck!");
return;
}
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(((EnemyAI)__instance).inSpecialAnimationWithPlayer, AdvancedCauseOfDeath.Enemy_Bracken);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in FlowermanAIKillAnimationPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(ForestGiantAI))]
[HarmonyPatch("EatPlayerAnimation")]
internal class ForestGiantAIEatPlayerAnimationPatch
{
public static void Postfix(PlayerControllerB playerBeingEaten)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Accessing state after Forest Giant devouring...");
if ((Object)(object)playerBeingEaten == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
return;
}
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(playerBeingEaten, AdvancedCauseOfDeath.Enemy_ForestGiant);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in ForestGiantAIEatPlayerAnimationPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(MouthDogAI))]
[HarmonyPatch("KillPlayer")]
internal class MouthDogAIKillPlayerPatch
{
public static void Postfix(int playerId)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Accessing state after dog devouring...");
PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId];
if ((Object)(object)val == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
return;
}
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(val, AdvancedCauseOfDeath.Enemy_EyelessDog);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in MouthDogAIKillPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(CentipedeAI))]
[HarmonyPatch("DamagePlayerOnIntervals")]
internal class CentipedeAIDamagePlayerOnIntervalsPatch
{
public static void Postfix(CentipedeAI __instance)
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Invalid comparison between Unknown and I4
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling Snare Flea damage...");
if ((Object)(object)__instance.clingingToPlayer == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player being clung to!");
}
else if (__instance.clingingToPlayer.isPlayerDead && (int)__instance.clingingToPlayer.causeOfDeath == 5)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__instance.clingingToPlayer, AdvancedCauseOfDeath.Enemy_SnareFlea);
}
else if (__instance.clingingToPlayer.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player somehow died while attacked by Snare Flea! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in CentipedeAIDamagePlayerOnIntervalsPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(BaboonBirdAI))]
[HarmonyPatch("OnCollideWithPlayer")]
internal class BaboonBirdAIOnCollideWithPlayerPatch
{
public static void Postfix(Collider other)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling Baboon Hawk damage...");
PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
if ((Object)(object)component == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (component.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_BaboonHawk);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in BaboonBirdAIOnCollideWithPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
[HarmonyPatch("DamagePlayerFromOtherClientClientRpc")]
internal class PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch
{
public static void Postfix(PlayerControllerB __instance)
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Invalid comparison between Unknown and I4
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Invalid comparison between Unknown and I4
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Invalid comparison between Unknown and I4
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling friendly fire damage...");
if ((Object)(object)__instance == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access victim after death!");
}
else if (__instance.isPlayerDead)
{
if ((int)__instance.causeOfDeath == 1)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Melee);
}
else if ((int)__instance.causeOfDeath == 6)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Melee);
}
else if ((int)__instance.causeOfDeath == 7)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Shotgun);
}
else
{
Plugin.Instance.PluginLogger.LogWarning((object)("Player was killed by someone else but we don't know how! " + ((object)(CauseOfDeath)(ref __instance.causeOfDeath)).ToString()));
}
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(PufferAI))]
[HarmonyPatch("OnCollideWithPlayer")]
internal class PufferAIOnCollideWithPlayerPatch
{
public static void Postfix(Collider other)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling Spore Lizard damage...");
PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
if ((Object)(object)component == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (component.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_SporeLizard);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in PufferAIOnCollideWithPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(SpringManAI))]
[HarmonyPatch("OnCollideWithPlayer")]
internal class SpringManAIOnCollideWithPlayerPatch
{
public static void Postfix(Collider other)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling Coil Head damage...");
PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
if ((Object)(object)component == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (component.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_CoilHead);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in SpringManAIOnCollideWithPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(BlobAI))]
[HarmonyPatch("SlimeKillPlayerEffectServerRpc")]
internal class BlobAISlimeKillPlayerEffectServerRpcPatch
{
public static void Postfix(int playerKilled)
{
try
{
PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerKilled];
if ((Object)(object)val == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (val.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(val, AdvancedCauseOfDeath.Enemy_Hygrodere);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in BlobAISlimeKillPlayerEffectServerRpcPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(HoarderBugAI))]
[HarmonyPatch("OnCollideWithPlayer")]
internal class HoarderBugAIOnCollideWithPlayerPatch
{
public static void Postfix(Collider other)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling Hoarder Bug damage...");
PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
if ((Object)(object)component == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (component.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_HoarderBug);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in HoarderBugAIOnCollideWithPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(CrawlerAI))]
[HarmonyPatch("OnCollideWithPlayer")]
internal class CrawlerAIOnCollideWithPlayerPatch
{
public static void Postfix(Collider other)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling Thumper damage...");
PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
if ((Object)(object)component == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (component.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_Thumper);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in CrawlerAIOnCollideWithPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(SandSpiderAI))]
[HarmonyPatch("OnCollideWithPlayer")]
internal class SandSpiderAIOnCollideWithPlayerPatch
{
public static void Postfix(Collider other)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling Bunker Spider damage...");
PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
if ((Object)(object)component == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (component.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_BunkerSpider);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in SandSpiderAIOnCollideWithPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(NutcrackerEnemyAI))]
[HarmonyPatch("LegKickPlayer")]
internal class NutcrackerEnemyAILegKickPlayerPatch
{
public static void Postfix(int playerId)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Nutcracker kicked a player to death!");
PlayerControllerB playerController = StartOfRound.Instance.allPlayerScripts[playerId];
Plugin.Instance.PluginLogger.LogDebug((object)"Player is dying! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(playerController, AdvancedCauseOfDeath.Enemy_Nutcracker_Kicked);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in NutcrackerEnemyAILegKickPlayerPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(ShotgunItem))]
[HarmonyPatch("ShootGun")]
internal class ShotgunItemShootGunPatch
{
public static void Postfix(ShotgunItem __instance)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Invalid comparison between Unknown and I4
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Handling shotgun shot...");
PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
if ((Object)(object)localPlayerController == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access local player after shotgun shot!");
}
else if (localPlayerController.isPlayerDead && (int)localPlayerController.causeOfDeath == 7)
{
if (((GrabbableObject)__instance).isHeldByEnemy)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Enemy_Nutcracker_Shot);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Player_Murder_Shotgun);
}
}
else if (localPlayerController.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogWarning((object)("Player died while attacked by shotgun? Skipping... " + ((object)(CauseOfDeath)(ref localPlayerController.causeOfDeath)).ToString()));
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in ShotgunItemShootGunPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(MaskedPlayerEnemy))]
[HarmonyPatch("killAnimation")]
internal class MaskedPlayerEnemykillAnimationPatch
{
public static void Postfix(MaskedPlayerEnemy __instance)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Masked Player killed someone...");
PlayerControllerB inSpecialAnimationWithPlayer = ((EnemyAI)__instance).inSpecialAnimationWithPlayer;
if ((Object)(object)inSpecialAnimationWithPlayer == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
return;
}
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(inSpecialAnimationWithPlayer, AdvancedCauseOfDeath.Enemy_MaskedPlayer_Victim);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in MaskedPlayerEnemykillAnimationPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(HauntedMaskItem))]
[HarmonyPatch("FinishAttaching")]
internal class HauntedMaskItemFinishAttachingPatch
{
public static void Postfix(HauntedMaskItem __instance)
{
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Masked Player killed someone...");
PlayerControllerB value = Traverse.Create((object)__instance).Field("previousPlayerHeldBy").GetValue<PlayerControllerB>();
if ((Object)(object)value == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning((object)"Could not access player after death!");
}
else if (value.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(value, AdvancedCauseOfDeath.Enemy_MaskedPlayer_Wear);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is somehow still alive! Skipping...");
}
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in HauntedMaskItemFinishAttachingPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(ExtensionLadderItem))]
[HarmonyPatch("StartLadderAnimation")]
internal class ExtensionLadderItemStartLadderAnimationPatch
{
public static void Postfix(ExtensionLadderItem __instance)
{
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Extension ladder started animation! Modifying kill trigger...");
GameObject gameObject = ((Component)__instance).gameObject;
if ((Object)(object)gameObject == (Object)null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not fetch GameObject from ExtensionLadderItem.");
}
Transform val = gameObject.transform.Find("AnimContainer/MeshContainer/LadderMeshContainer/BaseLadder/LadderSecondPart/KillTrigger");
if ((Object)(object)val == (Object)null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not fetch KillTrigger Transform from ExtensionLadderItem.");
}
GameObject gameObject2 = ((Component)val).gameObject;
if ((Object)(object)gameObject2 == (Object)null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not fetch KillTrigger GameObject from ExtensionLadderItem.");
}
KillLocalPlayer component = gameObject2.GetComponent<KillLocalPlayer>();
if ((Object)(object)component == (Object)null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not fetch KillLocalPlayer from KillTrigger GameObject.");
}
component.causeOfDeath = (CauseOfDeath)8;
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in ExtensionLadderItemStartLadderAnimationPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(ItemDropship))]
[HarmonyPatch("Start")]
internal class ItemDropshipStartPatch
{
public static void Postfix(ItemDropship __instance)
{
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
try
{
Plugin.Instance.PluginLogger.LogDebug((object)"Item dropship spawned! Modifying kill trigger...");
GameObject gameObject = ((Component)__instance).gameObject;
if ((Object)(object)gameObject == (Object)null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not fetch GameObject from ItemDropship.");
}
Transform val = gameObject.transform.Find("ItemShip/KillTrigger");
if ((Object)(object)val == (Object)null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not fetch KillTrigger Transform from ItemDropship.");
}
GameObject gameObject2 = ((Component)val).gameObject;
if ((Object)(object)gameObject2 == (Object)null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not fetch KillTrigger GameObject from ItemDropship.");
}
KillLocalPlayer component = gameObject2.GetComponent<KillLocalPlayer>();
if ((Object)(object)component == (Object)null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not fetch KillLocalPlayer from KillTrigger GameObject.");
}
component.causeOfDeath = (CauseOfDeath)300;
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in ItemDropshipStartPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
}
[HarmonyPatch(typeof(Turret))]
[HarmonyPatch("Update")]
public class TurretUpdatePatch
{
public static void Postfix(Turret __instance)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Invalid comparison between Unknown and I4
if ((int)__instance.turretMode == 2)
{
PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
if (localPlayerController.isPlayerDead && (int)localPlayerController.causeOfDeath == 7)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Player is now dead! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Other_Turret);
}
}
}
}
[HarmonyPatch(typeof(Landmine))]
[HarmonyPatch("SpawnExplosion")]
public class LandmineSpawnExplosionPatch
{
private const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32)";
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method)
{
List<CodeInstruction> list = new List<CodeInstruction>(instructions);
List<CodeInstruction> list2 = BuildInstructionsToInsert(method);
if (list2 == null)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not build instructions to insert in LandmineSpawnExplosionPatch! Safely aborting...");
return instructions;
}
int num = -1;
for (int i = 0; i < list.Count; i++)
{
CodeInstruction val = list[i];
if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32)")
{
num = i;
break;
}
}
if (num == -1)
{
Plugin.Instance.PluginLogger.LogError((object)"Could not find PlayerControllerB.KillPlayer call in LandmineSpawnExplosionPatch! Safely aborting...");
return instructions;
}
Plugin.Instance.PluginLogger.LogInfo((object)"Injecting patch into Landmine.SpawnExplosion...");
list.InsertRange(num, list2);
Plugin.Instance.PluginLogger.LogInfo((object)"Done.");
return list;
}
private static List<CodeInstruction> BuildInstructionsToInsert(MethodBase method)
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Expected O, but got Unknown
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>();
int num = 2;
IList<LocalVariableInfo> localVariables = method.GetMethodBody().LocalVariables;
LocalVariableInfo localVariableInfo = null;
for (int i = 0; i < localVariables.Count; i++)
{
LocalVariableInfo localVariableInfo2 = localVariables[i];
if (localVariableInfo2.LocalType == typeof(PlayerControllerB))
{
if (localVariableInfo != null)
{
Plugin.Instance.PluginLogger.LogError((object)"Found multiple PlayerControllerB local variables in LandmineSpawnExplosionPatch!");
return null;
}
localVariableInfo = localVariableInfo2;
break;
}
}
list.Add(new CodeInstruction(OpCodes.Ldloc_S, (object)localVariableInfo.LocalIndex));
list.Add(new CodeInstruction(OpCodes.Ldarg, (object)num));
list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(LandmineSpawnExplosionPatch).GetMethod("RewriteCauseOfDeath")));
return list;
}
public static void RewriteCauseOfDeath(PlayerControllerB targetPlayer, float killRange)
{
AdvancedCauseOfDeath causeOfDeath = AdvancedCauseOfDeath.Blast;
if (killRange == 5f)
{
causeOfDeath = AdvancedCauseOfDeath.Player_Jetpack_Blast;
}
else if (killRange == 5.7f)
{
causeOfDeath = AdvancedCauseOfDeath.Other_Landmine;
}
else if (killRange == 2.4f)
{
causeOfDeath = AdvancedCauseOfDeath.Other_Lightning;
}
AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, causeOfDeath);
}
}
[HarmonyPatch(typeof(HUDManager))]
[HarmonyPatch("FillEndGameStats")]
internal class HUDManagerFillEndGameStatsPatch
{
public static void Postfix(HUDManager __instance)
{
try
{
OverridePerformanceReport(__instance);
}
catch (Exception ex)
{
Plugin.Instance.PluginLogger.LogError((object)("Error in HUDManagerFillEndGameStatsPatch.Postfix: " + ex));
Plugin.Instance.PluginLogger.LogError((object)ex.StackTrace);
}
}
private static Random BuildSyncedRandom(HUDManager __instance)
{
int randomMapSeed = StartOfRound.Instance.randomMapSeed;
Plugin.Instance.PluginLogger.LogDebug((object)("Syncing randomization to map seed: '" + randomMapSeed + "'"));
return new Random(randomMapSeed);
}
private static void OverridePerformanceReport(HUDManager __instance)
{
Plugin.Instance.PluginLogger.LogDebug((object)"Applying Coroner patches to player notes...");
Random random = BuildSyncedRandom(__instance);
for (int i = 0; i < __instance.statsUIElements.playerNotesText.Length; i++)
{
PlayerControllerB val = __instance.playersManager.allPlayerScripts[i];
if (!val.disconnectedMidGame && !val.isPlayerDead && !val.isPlayerControlled)
{
Plugin.Instance.PluginLogger.LogInfo((object)("Player " + i + " is not controlled by a player. Skipping..."));
continue;
}
TextMeshProUGUI val2 = __instance.statsUIElements.playerNotesText[i];
if (val.isPlayerDead)
{
if (Plugin.Instance.PluginConfig.ShouldDisplayCauseOfDeath())
{
if (Plugin.Instance.PluginConfig.ShouldDeathReplaceNotes())
{
Plugin.Instance.PluginLogger.LogInfo((object)("[REPORT] Player " + i + " is dead! Replacing notes with Cause of Death..."));
((TMP_Text)val2).text = "Cause of Death: \n";
}
else
{
Plugin.Instance.PluginLogger.LogInfo((object)("[REPORT] Player " + i + " is dead! Appending notes with Cause of Death..."));
}
AdvancedCauseOfDeath causeOfDeath = AdvancedDeathTracker.GetCauseOfDeath(val);
string text = "* " + AdvancedDeathTracker.StringifyCauseOfDeath(causeOfDeath, random) + "\n";
((TMP_Text)val2).text = ((TMP_Text)val2).text + text;
}
else
{
Plugin.Instance.PluginLogger.LogInfo((object)("[REPORT] Player " + i + " is dead, but Config says leave it be..."));
}
}
else if (Plugin.Instance.PluginConfig.ShouldDisplayFunnyNotes())
{
Plugin.Instance.PluginLogger.LogInfo((object)("[REPORT] Player " + i + " has no notes! Injecting something funny..."));
string text2 = "* " + AdvancedDeathTracker.StringifyCauseOfDeath(null, random) + "\n";
((TMP_Text)val2).text = ((TMP_Text)val2).text + text2;
((TMP_Text)val2).text = "Notes: \n";
((TMP_Text)val2).text = ((TMP_Text)val2).text + text2;
}
else
{
Plugin.Instance.PluginLogger.LogInfo((object)("[REPORT] Player " + i + " has no notes, but Config says leave it be..."));
}
}
AdvancedDeathTracker.ClearDeathTracker();
}
}
}
namespace Coroner.LCAPI
{
internal class DeathBroadcasterLCAPI
{
private const string SIGNATURE_DEATH = "com.elitemastereric.coroner.death";
public static void Initialize()
{
Plugin.Instance.PluginLogger.LogDebug((object)"Initializing DeathBroadcaster...");
if (Plugin.Instance.IsLCAPIPresent)
{
Plugin.Instance.PluginLogger.LogDebug((object)"LC_API is present! Registering signature...");
Networking.GetString = (Action<string, string>)Delegate.Combine(Networking.GetString, new Action<string, string>(OnBroadcastString));
}
else
{
Plugin.Instance.PluginLogger.LogError((object)"LC_API is not present! Why did you try to register the DeathBroadcaster?");
}
}
private static void OnBroadcastString(string data, string signature)
{
if (signature == "com.elitemastereric.coroner.death")
{
Plugin.Instance.PluginLogger.LogDebug((object)"Broadcast has been received from LC_API!");
string[] array = data.Split('|');
int playerIndex = int.Parse(array[0]);
int num = int.Parse(array[1]);
AdvancedCauseOfDeath advancedCauseOfDeath = (AdvancedCauseOfDeath)num;
Plugin.Instance.PluginLogger.LogDebug((object)("Player " + playerIndex + " died of " + AdvancedDeathTracker.StringifyCauseOfDeath((AdvancedCauseOfDeath?)advancedCauseOfDeath)));
AdvancedDeathTracker.SetCauseOfDeath(playerIndex, advancedCauseOfDeath, broadcast: false);
}
}
public static void AttemptBroadcast(string data, string signature)
{
if (Plugin.Instance.IsLCAPIPresent)
{
Plugin.Instance.PluginLogger.LogDebug((object)"LC_API is present! Broadcasting...");
Networking.Broadcast(data, signature);
}
else
{
Plugin.Instance.PluginLogger.LogDebug((object)"LC_API is not present! Skipping broadcast...");
}
}
}
}