using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Xml.Linq;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using StaticNetcodeLib;
using TMPro;
using Unity.Netcode;
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("A Lethal Company plugin which overhauls the end-of-mission performance report with new information, including cause of death for any deceased players with some fun easter eggs thrown in too.")]
[assembly: AssemblyFileVersion("2.4.0.0")]
[assembly: AssemblyInformationalVersion("2.4.0+6c0de7becd0367a9aad95d2702c27cfc04d0c47b")]
[assembly: AssemblyProduct("Coroner")]
[assembly: AssemblyTitle("Coroner")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 static Dictionary<int, AdvancedCauseOfDeath?> causeOfDeathDictionary = new Dictionary<int, AdvancedCauseOfDeath?>();
public static void ClearDeathTracker()
{
PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
foreach (PlayerControllerB val in allPlayerScripts)
{
StoreLocalCauseOfDeath((int)val.playerClientId, null, overrideExisting: true);
}
}
public static void SetCauseOfDeath(int playerIndex, AdvancedCauseOfDeath? causeOfDeath, bool forceOverride = false)
{
if (!causeOfDeath.HasValue)
{
NetworkRPC.ReportCauseOfDeathServerRpc(playerIndex, null, forceOverride);
return;
}
AdvancedCauseOfDeath value = causeOfDeath.Value;
Plugin.Instance.PluginLogger.LogDebug(string.Format("Serializing {0} to {1}{2}", value, value.GetLanguageTag(), forceOverride ? " (FORCED)" : ""));
NetworkRPC.ReportCauseOfDeathServerRpc(playerIndex, value.GetLanguageTag(), forceOverride);
StoreLocalCauseOfDeath(playerIndex, causeOfDeath, forceOverride);
}
public static void SetCauseOfDeath(PlayerControllerB playerController, AdvancedCauseOfDeath? causeOfDeath, bool forceOverride = false)
{
SetCauseOfDeath((int)playerController.playerClientId, causeOfDeath, forceOverride);
}
public static void StoreLocalCauseOfDeath(int playerId, AdvancedCauseOfDeath? causeOfDeath, bool overrideExisting)
{
if (!overrideExisting && (!causeOfDeath.HasValue || HasCauseOfDeath(playerId)))
{
if (!causeOfDeath.HasValue)
{
Plugin.Instance.PluginLogger.LogDebug($"Ignoring null cause of death for player {playerId}");
return;
}
string languageTag = causeOfDeath.Value.GetLanguageTag();
AdvancedCauseOfDeath? causeOfDeath2 = GetCauseOfDeath(playerId, shouldGuess: false);
string arg = ((!causeOfDeath2.HasValue) ? "null" : causeOfDeath2.Value.GetLanguageTag());
Plugin.Instance.PluginLogger.LogWarning($"Player {playerId} already has a cause of death set ({arg}), not overwriting it with {languageTag}.");
}
else if (!causeOfDeath.HasValue)
{
Plugin.Instance.PluginLogger.LogDebug($"Clearing cause of death for player {playerId}");
causeOfDeathDictionary[playerId] = null;
}
else
{
AdvancedCauseOfDeath? causeOfDeath3 = GetCauseOfDeath(playerId, shouldGuess: false);
string arg2 = ((!causeOfDeath3.HasValue) ? "null" : causeOfDeath3.Value.GetLanguageTag());
string languageTag2 = causeOfDeath.Value.GetLanguageTag();
Plugin.Instance.PluginLogger.LogDebug($"Storing cause of death {languageTag2} (overriding {arg2}) for player {playerId}!");
causeOfDeathDictionary[playerId] = causeOfDeath;
}
}
private static AdvancedCauseOfDeath? FetchCauseOfDeathVariable(PlayerControllerB playerController)
{
if (!HasCauseOfDeath(playerController))
{
return null;
}
return causeOfDeathDictionary[(int)playerController.playerClientId];
}
public static AdvancedCauseOfDeath? GetCauseOfDeath(int playerIndex, bool shouldGuess = true)
{
if (playerIndex < 0 || playerIndex >= StartOfRound.Instance.allPlayerScripts.Length)
{
return null;
}
PlayerControllerB playerController = StartOfRound.Instance.allPlayerScripts[playerIndex];
return GetCauseOfDeath(playerController, shouldGuess);
}
public static bool HasCauseOfDeath(int playerIndex)
{
if (playerIndex < 0 || playerIndex >= StartOfRound.Instance.allPlayerScripts.Length)
{
return false;
}
return HasCauseOfDeath(StartOfRound.Instance.allPlayerScripts[playerIndex]);
}
public static bool HasCauseOfDeath(PlayerControllerB playerController)
{
return causeOfDeathDictionary.ContainsKey((int)playerController.playerClientId) && causeOfDeathDictionary[(int)playerController.playerClientId].HasValue;
}
public static AdvancedCauseOfDeath? GetCauseOfDeath(PlayerControllerB playerController, bool shouldGuess = true)
{
AdvancedCauseOfDeath? advancedCauseOfDeath = FetchCauseOfDeathVariable(playerController);
if (advancedCauseOfDeath.HasValue)
{
AdvancedCauseOfDeath value = advancedCauseOfDeath.Value;
Plugin.Instance.PluginLogger.LogDebug($"Player {playerController.playerClientId} has custom cause of death stored! {value.GetLanguageTag()}");
return value;
}
if (!shouldGuess)
{
Plugin.Instance.PluginLogger.LogDebug($"Player {playerController.playerClientId} has no custom cause of death stored! Returning null...");
return null;
}
Plugin.Instance.PluginLogger.LogDebug($"Player {playerController.playerClientId} has no custom cause of death stored! Using fallback...");
return GuessCauseOfDeath(playerController);
}
public static AdvancedCauseOfDeath GuessCauseOfDeath(PlayerControllerB playerController)
{
//IL_0047: 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_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: 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 playerController.causeOfDeath;
}
return AdvancedCauseOfDeath.Unknown;
}
public static GrabbableObject? GetHeldObject(PlayerControllerB playerController)
{
GrabbableObject currentlyHeldObjectServer = playerController.currentlyHeldObjectServer;
if ((Object)(object)currentlyHeldObjectServer == (Object)null)
{
return null;
}
GameObject gameObject = ((Component)currentlyHeldObjectServer).gameObject;
if ((Object)(object)gameObject == (Object)null)
{
return null;
}
return gameObject.GetComponent<GrabbableObject>();
}
public static bool IsHoldingJetpack(PlayerControllerB playerController)
{
GrabbableObject heldObject = GetHeldObject(playerController);
if ((Object)(object)heldObject == (Object)null)
{
return false;
}
if (heldObject is JetpackItem)
{
return true;
}
return false;
}
public static bool IsHoldingShovel(PlayerControllerB playerController)
{
GrabbableObject heldObject = GetHeldObject(playerController);
if ((Object)(object)heldObject == (Object)null)
{
return false;
}
if (heldObject is Shovel && ((Object)((Component)heldObject).gameObject).name.StartsWith("Shovel"))
{
return true;
}
return false;
}
public static bool IsHoldingStopSign(PlayerControllerB playerController)
{
GrabbableObject heldObject = GetHeldObject(playerController);
if ((Object)(object)heldObject == (Object)null)
{
return false;
}
if (heldObject is Shovel && ((Object)((Component)heldObject).gameObject).name.StartsWith("StopSign"))
{
return true;
}
return false;
}
public static bool IsHoldingYieldSign(PlayerControllerB playerController)
{
GrabbableObject heldObject = GetHeldObject(playerController);
if ((Object)(object)heldObject == (Object)null)
{
return false;
}
if (heldObject is Shovel && ((Object)((Component)heldObject).gameObject).name.StartsWith("YieldSign"))
{
return true;
}
return false;
}
public static bool IsHoldingShotgun(PlayerControllerB playerController)
{
GrabbableObject heldObject = GetHeldObject(playerController);
if ((Object)(object)heldObject == (Object)null)
{
return false;
}
if (heldObject is ShotgunItem)
{
return true;
}
return false;
}
public static bool IsHoldingKnife(PlayerControllerB playerController)
{
GrabbableObject heldObject = GetHeldObject(playerController);
if ((Object)(object)heldObject == (Object)null)
{
return false;
}
if (heldObject is KnifeItem)
{
return true;
}
return false;
}
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 && (!causeOfDeath.HasValue || !Plugin.Instance.PluginConfig.ShouldUseSeriousDeathMessages()))
{
int num = random.Next(array.Length);
return array[num];
}
return array[0];
}
public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath)
{
if (!causeOfDeath.HasValue)
{
return Plugin.Instance.LanguageHandler.GetValuesByTag("FunnyNote");
}
if (AdvancedCauseOfDeath.IsCauseOfDeathRegistered(causeOfDeath))
{
return causeOfDeath.Value.GetLanguageValues();
}
return Plugin.Instance.LanguageHandler.GetValuesByTag("DeathUnknown");
}
}
public struct AdvancedCauseOfDeath
{
public static readonly Dictionary<string, AdvancedCauseOfDeath> Registry = new Dictionary<string, AdvancedCauseOfDeath>();
private static int NextId = 100;
public static AdvancedCauseOfDeath Unknown = BuildFromExisting("DeathUnknown", (CauseOfDeath)0);
public static AdvancedCauseOfDeath Bludgeoning = BuildFromExisting("DeathBludgeoning", (CauseOfDeath)1);
public static AdvancedCauseOfDeath Gravity = BuildFromExisting("DeathGravity", (CauseOfDeath)2);
public static AdvancedCauseOfDeath Blast = BuildFromExisting("DeathBlast", (CauseOfDeath)3);
public static AdvancedCauseOfDeath Strangulation = BuildFromExisting("DeathStrangulation", (CauseOfDeath)4);
public static AdvancedCauseOfDeath Suffocation = BuildFromExisting("DeathSuffocation", (CauseOfDeath)5);
public static AdvancedCauseOfDeath Mauling = BuildFromExisting("DeathMauling", (CauseOfDeath)6);
public static AdvancedCauseOfDeath Gunshots = BuildFromExisting("DeathGunshots", (CauseOfDeath)7);
public static AdvancedCauseOfDeath Crushing = BuildFromExisting("DeathCrushing", (CauseOfDeath)8);
public static AdvancedCauseOfDeath Drowning = BuildFromExisting("DeathDrowning", (CauseOfDeath)9);
public static AdvancedCauseOfDeath Abandoned = BuildFromExisting("DeathAbandoned", (CauseOfDeath)10);
public static AdvancedCauseOfDeath Electrocution = BuildFromExisting("DeathElectrocution", (CauseOfDeath)11);
public static AdvancedCauseOfDeath Kicking = BuildFromExisting("DeathKicking", (CauseOfDeath)12);
public static AdvancedCauseOfDeath Burning = BuildFromExisting("DeathBurning", (CauseOfDeath)13);
public static AdvancedCauseOfDeath Stabbing = BuildFromExisting("DeathStabbing", (CauseOfDeath)14);
public static AdvancedCauseOfDeath Fan = BuildFromExisting("DeathFan", (CauseOfDeath)15);
public static AdvancedCauseOfDeath Inertia = BuildFromExisting("DeathInertia", (CauseOfDeath)16);
public static AdvancedCauseOfDeath Scratching = BuildFromExisting("DeathScratching", (CauseOfDeath)18);
public static AdvancedCauseOfDeath Snipping = BuildFromExisting("DeathSnipped", (CauseOfDeath)17);
public static AdvancedCauseOfDeath Enemy_BaboonHawk = Build("DeathEnemyBaboonHawk");
public static AdvancedCauseOfDeath Enemy_Bracken = Build("DeathEnemyBracken");
public static AdvancedCauseOfDeath Enemy_BunkerSpider = Build("DeathEnemyBunkerSpider");
public static AdvancedCauseOfDeath Enemy_CircuitBees = Build("DeathEnemyCircuitBees");
public static AdvancedCauseOfDeath Enemy_CoilHead = Build("DeathEnemyCoilHead");
public static AdvancedCauseOfDeath Enemy_EarthLeviathan = Build("DeathEnemyEarthLeviathan");
public static AdvancedCauseOfDeath Enemy_EyelessDog = Build("DeathEnemyEyelessDog");
public static AdvancedCauseOfDeath Enemy_GhostGirl = Build("DeathEnemyGhostGirl");
public static AdvancedCauseOfDeath Enemy_HoarderBug = Build("DeathEnemyHoarderBug");
public static AdvancedCauseOfDeath Enemy_Hygrodere = Build("DeathEnemyHygrodere");
public static AdvancedCauseOfDeath Enemy_Jester = Build("DeathEnemyJester");
public static AdvancedCauseOfDeath Enemy_LassoMan = Build("DeathEnemyLassoMan");
public static AdvancedCauseOfDeath Enemy_SnareFlea = Build("DeathEnemySnareFlea");
public static AdvancedCauseOfDeath Enemy_SporeLizard = Build("DeathEnemySporeLizard");
public static AdvancedCauseOfDeath Enemy_Thumper = Build("DeathEnemyThumper");
public static AdvancedCauseOfDeath Enemy_ForestGiant_Eaten = Build("DeathEnemyForestGiantEaten");
public static AdvancedCauseOfDeath Enemy_ForestGiant_Death = Build("DeathEnemyForestGiantDeath");
public static AdvancedCauseOfDeath Enemy_MaskedPlayer_Wear = Build("DeathEnemyMaskedPlayerWear");
public static AdvancedCauseOfDeath Enemy_MaskedPlayer_Victim = Build("DeathEnemyMaskedPlayerVictim");
public static AdvancedCauseOfDeath Enemy_Nutcracker_Kicked = Build("DeathEnemyNutcrackerKicked");
public static AdvancedCauseOfDeath Enemy_Nutcracker_Shot = Build("DeathEnemyNutcrackerShot");
public static AdvancedCauseOfDeath Enemy_Butler_Stab = Build("DeathEnemyButlerStab");
public static AdvancedCauseOfDeath Enemy_Butler_Explode = Build("DeathEnemyButlerExplode");
public static AdvancedCauseOfDeath Enemy_MaskHornets = Build("DeathEnemyMaskHornets");
public static AdvancedCauseOfDeath Enemy_TulipSnake_Drop = Build("DeathEnemyTulipSnakeDrop");
public static AdvancedCauseOfDeath Enemy_Old_Bird_Rocket = Build("DeathEnemyOldBirdRocket");
public static AdvancedCauseOfDeath Enemy_Old_Bird_Charge = Build("DeathEnemyOldBirdCharge");
public static AdvancedCauseOfDeath Enemy_Old_Bird_Stomp = Build("DeathEnemyOldBirdStomp");
public static AdvancedCauseOfDeath Enemy_Old_Bird_Torch = Build("DeathEnemyOldBirdTorch");
public static AdvancedCauseOfDeath Enemy_KidnapperFox = Build("DeathEnemyKidnapperFox");
public static AdvancedCauseOfDeath Enemy_Barber = Build("DeathEnemyBarber");
public static AdvancedCauseOfDeath Enemy_Maneater = Build("DeathEnemyManeater");
public static AdvancedCauseOfDeath Enemy_Giant_Sapsucker = Build("DeathEnemyGiantSapsucker");
public static AdvancedCauseOfDeath Enemy_Cadaver_Growth = Build("DeathEnemyCadaverGrowth");
public static AdvancedCauseOfDeath Enemy_Cadaver_Bloom = Build("DeathEnemyCadaverBloom");
public static AdvancedCauseOfDeath Enemy_Feiopar = Build("DeathEnemyFeiopar");
public static AdvancedCauseOfDeath Player_Jetpack_Gravity = Build("DeathPlayerJetpackGravity");
public static AdvancedCauseOfDeath Player_Jetpack_Blast = Build("DeathPlayerJetpackBlast");
public static AdvancedCauseOfDeath Player_Quicksand = Build("DeathPlayerQuicksand");
public static AdvancedCauseOfDeath Player_Ladder = Build("DeathPlayerLadder");
public static AdvancedCauseOfDeath Player_Murder_Shovel = Build("DeathPlayerMurderShovel");
public static AdvancedCauseOfDeath Player_Murder_Stop_Sign = Build("DeathPlayerMurderStopSign");
public static AdvancedCauseOfDeath Player_Murder_Yield_Sign = Build("DeathPlayerMurderYieldSign");
public static AdvancedCauseOfDeath Player_Murder_Shotgun = Build("DeathPlayerMurderShotgun");
public static AdvancedCauseOfDeath Player_Murder_Knife = Build("DeathPlayerMurderKnife");
public static AdvancedCauseOfDeath Player_StunGrenade = Build("DeathPlayerStunGrenade");
public static AdvancedCauseOfDeath Player_EasterEgg = Build("DeathPlayerEasterEgg");
public static AdvancedCauseOfDeath Player_Electric_Chair = Build("DeathPlayerElectricChair");
public static AdvancedCauseOfDeath Player_Vomiting = Build("DeathPlayerVomiting");
public static AdvancedCauseOfDeath Player_Cruiser_Driver = Build("DeathPlayerCruiserDriver");
public static AdvancedCauseOfDeath Player_Cruiser_Passenger = Build("DeathPlayerCruiserPassenger");
public static AdvancedCauseOfDeath Player_Cruiser_Explode_Bystander = Build("DeathPlayerCruiserExplodeBystander");
public static AdvancedCauseOfDeath Player_Cruiser_Ran_Over = Build("DeathPlayerCruiserRanOver");
public static AdvancedCauseOfDeath Pit_Generic = Build("DeathPitGeneric");
public static AdvancedCauseOfDeath Pit_Facility_Pit = Build("DeathPitFacilityPit");
public static AdvancedCauseOfDeath Pit_Facility_Catwalk_Jump = Build("DeathPitFacilityCatwalkJump");
public static AdvancedCauseOfDeath Pit_Mine_Pit = Build("DeathPitMinePit");
public static AdvancedCauseOfDeath Pit_Mine_Cave = Build("DeathPitMineCave");
public static AdvancedCauseOfDeath Pit_Mine_Elevator = Build("DeathPitMineElevator");
public static AdvancedCauseOfDeath Other_Landmine = Build("DeathOtherLandmine");
public static AdvancedCauseOfDeath Other_Turret = Build("DeathOtherTurret");
public static AdvancedCauseOfDeath Other_Lightning = Build("DeathOtherLightning");
public static AdvancedCauseOfDeath Other_Meteor = Build("DeathOtherMeteor");
public static AdvancedCauseOfDeath Other_DepositItemsDesk = Build("DeathOtherDepositItemsDesk");
public static AdvancedCauseOfDeath Other_Dropship = Build("DeathOtherItemDropship");
public static AdvancedCauseOfDeath Other_Spike_Trap = Build("DeathOtherSpikeTrap");
public static AdvancedCauseOfDeath Other_OutOfBounds = Build("DeathOtherOutOfBounds");
private int statusCode;
private string languageTag;
public static AdvancedCauseOfDeath Build(string languageTag)
{
int nextId = NextId;
NextId++;
AdvancedCauseOfDeath advancedCauseOfDeath = default(AdvancedCauseOfDeath);
advancedCauseOfDeath.statusCode = nextId;
advancedCauseOfDeath.languageTag = languageTag;
AdvancedCauseOfDeath advancedCauseOfDeath2 = advancedCauseOfDeath;
Register(languageTag, advancedCauseOfDeath2);
return advancedCauseOfDeath2;
}
public static AdvancedCauseOfDeath BuildFromExisting(string languageTag, CauseOfDeath statusCode)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Expected I4, but got Unknown
AdvancedCauseOfDeath advancedCauseOfDeath = default(AdvancedCauseOfDeath);
advancedCauseOfDeath.statusCode = (int)statusCode;
advancedCauseOfDeath.languageTag = languageTag;
AdvancedCauseOfDeath advancedCauseOfDeath2 = advancedCauseOfDeath;
Register(languageTag, advancedCauseOfDeath2);
return advancedCauseOfDeath2;
}
private static void Register(string key, AdvancedCauseOfDeath value)
{
if (IsTagRegistered(key))
{
Plugin.Instance.PluginLogger.LogError("Tried to register duplicate Cause of Death key (" + key + ")!");
}
else if (IsCauseOfDeathRegistered(value))
{
Plugin.Instance.PluginLogger.LogError($"Tried to register Cause of Death twice ({value})!");
}
else
{
Registry.Add(key, value);
}
}
public static AdvancedCauseOfDeath? Fetch(string? key)
{
if (key == null)
{
return null;
}
if (!Registry.ContainsKey(key))
{
return null;
}
return Registry[key];
}
public static bool IsTagRegistered(string key)
{
return Registry.ContainsKey(key);
}
public static bool IsCauseOfDeathRegistered(AdvancedCauseOfDeath? value)
{
if (!value.HasValue)
{
return false;
}
return Registry.ContainsValue(value.Value);
}
private 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_004b: Expected I4, but got Unknown
return (int)causeOfDeath switch
{
0 => Unknown,
1 => Bludgeoning,
2 => Gravity,
3 => Blast,
4 => Strangulation,
5 => Suffocation,
6 => Mauling,
7 => Gunshots,
8 => Crushing,
9 => Drowning,
10 => Abandoned,
11 => Electrocution,
13 => Burning,
15 => Fan,
14 => Stabbing,
_ => Unknown,
};
}
public string GetLanguageTag()
{
return languageTag;
}
public string[] GetLanguageValues()
{
return Plugin.Instance.LanguageHandler.GetValuesByTag(languageTag);
}
public override bool Equals(object obj)
{
return obj is AdvancedCauseOfDeath advancedCauseOfDeath && statusCode == advancedCauseOfDeath.statusCode;
}
public override int GetHashCode()
{
return HashCode.Combine(statusCode, languageTag);
}
public static bool operator ==(AdvancedCauseOfDeath left, AdvancedCauseOfDeath right)
{
return left.statusCode == right.statusCode;
}
public static bool operator !=(AdvancedCauseOfDeath left, AdvancedCauseOfDeath right)
{
return left.statusCode != right.statusCode;
}
public static bool operator ==(CauseOfDeath left, AdvancedCauseOfDeath right)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
return (int)left == right.statusCode;
}
public static bool operator !=(CauseOfDeath left, AdvancedCauseOfDeath right)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
return (int)left != right.statusCode;
}
public static bool operator ==(AdvancedCauseOfDeath left, CauseOfDeath right)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between I4 and Unknown
return left.statusCode == (int)right;
}
public static bool operator !=(AdvancedCauseOfDeath left, CauseOfDeath right)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between I4 and Unknown
return left.statusCode != (int)right;
}
public static implicit operator AdvancedCauseOfDeath(CauseOfDeath value)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return ConvertCauseOfDeath(value);
}
public static implicit operator CauseOfDeath(AdvancedCauseOfDeath value)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
return (CauseOfDeath)value.statusCode;
}
public override string ToString()
{
return "AdvancedCauseOfDeath(" + languageTag + ")";
}
}
public class API
{
public static void SetCauseOfDeath(PlayerControllerB player, AdvancedCauseOfDeath causeOfDeath)
{
bool flag = false;
AdvancedDeathTracker.SetCauseOfDeath(player, causeOfDeath);
}
public static void SetCauseOfDeath(int playerId, AdvancedCauseOfDeath causeOfDeath)
{
bool flag = false;
AdvancedDeathTracker.SetCauseOfDeath(playerId, causeOfDeath);
}
public static void ClearCauseOfDeath(PlayerControllerB player)
{
ClearCauseOfDeath((int)player.playerClientId);
}
public static void ClearCauseOfDeath(int playerId)
{
AdvancedDeathTracker.StoreLocalCauseOfDeath(playerId, null, overrideExisting: true);
}
public static AdvancedCauseOfDeath? GetCauseOfDeath(PlayerControllerB player)
{
return AdvancedDeathTracker.GetCauseOfDeath(player);
}
public static AdvancedCauseOfDeath? GetCauseOfDeath(int playerId)
{
return AdvancedDeathTracker.GetCauseOfDeath(playerId);
}
public static AdvancedCauseOfDeath Register(string key)
{
return AdvancedCauseOfDeath.Build(key);
}
public static bool IsRegistered(string key)
{
return AdvancedCauseOfDeath.IsTagRegistered(key);
}
public static string StringifyCauseOfDeath(AdvancedCauseOfDeath causeOfDeath, Random? random)
{
return AdvancedDeathTracker.StringifyCauseOfDeath(causeOfDeath, (random != null) ? random : Plugin.RANDOM);
}
}
internal class EnumeratorPatch : IEnumerable
{
public IEnumerator targetEnumerator;
public Action? prefixAction;
public Action? postfixAction;
public Action<object?>? preStepAction;
public Action<object?>? postStepAction;
public Func<object?, object?>? stepAction;
public EnumeratorPatch(IEnumerator targetEnumerator)
{
this.targetEnumerator = targetEnumerator;
}
public IEnumerator GetEnumerator()
{
if (prefixAction != null)
{
prefixAction();
}
while (targetEnumerator.MoveNext())
{
object value = targetEnumerator.Current;
if (preStepAction != null)
{
preStepAction(value);
}
yield return (stepAction != null) ? stepAction(value) : value;
if (postStepAction != null)
{
postStepAction(value);
}
}
if (postfixAction != null)
{
postfixAction();
}
}
}
internal class LanguageHandler
{
public const string DEFAULT_LANGUAGE = "en-us";
public const string TAG_FUNNY_NOTES = "FunnyNote";
public const string TAG_UI_NOTES = "UINotes";
public const string TAG_UI_DEATH = "UICauseOfDeath";
public const string TAG_DEATH_GENERIC_BLUDGEONING = "DeathBludgeoning";
public const string TAG_DEATH_GENERIC_GRAVITY = "DeathGravity";
public const string TAG_DEATH_GENERIC_BLAST = "DeathBlast";
public const string TAG_DEATH_GENERIC_STRANGULATION = "DeathStrangulation";
public const string TAG_DEATH_GENERIC_SUFFOCATION = "DeathSuffocation";
public const string TAG_DEATH_GENERIC_MAULING = "DeathMauling";
public const string TAG_DEATH_GENERIC_GUNSHOTS = "DeathGunshots";
public const string TAG_DEATH_GENERIC_CRUSHING = "DeathCrushing";
public const string TAG_DEATH_GENERIC_DROWNING = "DeathDrowning";
public const string TAG_DEATH_GENERIC_ABANDONED = "DeathAbandoned";
public const string TAG_DEATH_GENERIC_ELECTROCUTION = "DeathElectrocution";
public const string TAG_DEATH_GENERIC_KICKING = "DeathKicking";
public const string TAG_DEATH_GENERIC_BURNING = "DeathBurning";
public const string TAG_DEATH_GENERIC_STABBING = "DeathStabbing";
public const string TAG_DEATH_GENERIC_FAN = "DeathFan";
public const string TAG_DEATH_GENERIC_INERTIA = "DeathInertia";
public const string TAG_DEATH_GENERIC_SNIPPING = "DeathSnipped";
public const string TAG_DEATH_GENERIC_SCRATCHING = "DeathScratching";
public const string TAG_DEATH_ENEMY_BABOON_HAWK = "DeathEnemyBaboonHawk";
public const string TAG_DEATH_ENEMY_BRACKEN = "DeathEnemyBracken";
public const string TAG_DEATH_ENEMY_BUNKER_SPIDER = "DeathEnemyBunkerSpider";
public const string TAG_DEATH_ENEMY_CIRCUIT_BEES = "DeathEnemyCircuitBees";
public const string TAG_DEATH_ENEMY_COILHEAD = "DeathEnemyCoilHead";
public const string TAG_DEATH_ENEMY_EARTH_LEVIATHAN = "DeathEnemyEarthLeviathan";
public const string TAG_DEATH_ENEMY_EYELESS_DOG = "DeathEnemyEyelessDog";
public const string TAG_DEATH_ENEMY_GHOST_GIRL = "DeathEnemyGhostGirl";
public const string TAG_DEATH_ENEMY_HOARDER_BUG = "DeathEnemyHoarderBug";
public const string TAG_DEATH_ENEMY_HYGRODERE = "DeathEnemyHygrodere";
public const string TAG_DEATH_ENEMY_JESTER = "DeathEnemyJester";
public const string TAG_DEATH_ENEMY_LASSO_MAN = "DeathEnemyLassoMan";
public const string TAG_DEATH_ENEMY_SNARE_FLEA = "DeathEnemySnareFlea";
public const string TAG_DEATH_ENEMY_SPORE_LIZARD = "DeathEnemySporeLizard";
public const string TAG_DEATH_ENEMY_THUMPER = "DeathEnemyThumper";
public const string TAG_DEATH_ENEMY_FOREST_GIANT_EATEN = "DeathEnemyForestGiantEaten";
public const string TAG_DEATH_ENEMY_FOREST_GIANT_DEATH = "DeathEnemyForestGiantDeath";
public const string TAG_DEATH_ENEMY_MASKED_PLAYER_WEAR = "DeathEnemyMaskedPlayerWear";
public const string TAG_DEATH_ENEMY_MASKED_PLAYER_VICTIM = "DeathEnemyMaskedPlayerVictim";
public const string TAG_DEATH_ENEMY_NUTCRACKER_KICKED = "DeathEnemyNutcrackerKicked";
public const string TAG_DEATH_ENEMY_NUTCRACKER_SHOT = "DeathEnemyNutcrackerShot";
public const string TAG_DEATH_ENEMY_BUTLER_STAB = "DeathEnemyButlerStab";
public const string TAG_DEATH_ENEMY_BUTLER_EXPLODE = "DeathEnemyButlerExplode";
public const string TAG_DEATH_ENEMY_MASK_HORNETS = "DeathEnemyMaskHornets";
public const string TAG_DEATH_ENEMY_TULIP_SNAKE_DROP = "DeathEnemyTulipSnakeDrop";
public const string TAG_DEATH_ENEMY_OLD_BIRD_ROCKET = "DeathEnemyOldBirdRocket";
public const string TAG_DEATH_ENEMY_OLD_BIRD_STOMP = "DeathEnemyOldBirdStomp";
public const string TAG_DEATH_ENEMY_OLD_BIRD_CHARGE = "DeathEnemyOldBirdCharge";
public const string TAG_DEATH_ENEMY_OLD_BIRD_TORCH = "DeathEnemyOldBirdTorch";
public const string TAG_DEATH_ENEMY_KIDNAPPER_FOX = "DeathEnemyKidnapperFox";
public const string TAG_DEATH_ENEMY_BARBER = "DeathEnemyBarber";
public const string TAG_DEATH_ENEMY_MANEATER = "DeathEnemyManeater";
public const string TAG_DEATH_ENEMY_GIANT_SAPSUCKER = "DeathEnemyGiantSapsucker";
public const string TAG_DEATH_ENEMY_CADAVER_GROWTH = "DeathEnemyCadaverGrowth";
public const string TAG_DEATH_ENEMY_CADAVER_BLOOM = "DeathEnemyCadaverBloom";
public const string TAG_DEATH_ENEMY_FEIOPAR = "DeathEnemyFeiopar";
public const string TAG_DEATH_PLAYER_JETPACK_GRAVITY = "DeathPlayerJetpackGravity";
public const string TAG_DEATH_PLAYER_JETPACK_BLAST = "DeathPlayerJetpackBlast";
public const string TAG_DEATH_PLAYER_LADDER = "DeathPlayerLadder";
public const string TAG_DEATH_PLAYER_MURDER_SHOVEL = "DeathPlayerMurderShovel";
public const string TAG_DEATH_PLAYER_MURDER_STOP_SIGN = "DeathPlayerMurderStopSign";
public const string TAG_DEATH_PLAYER_MURDER_YIELD_SIGN = "DeathPlayerMurderYieldSign";
public const string TAG_DEATH_PLAYER_MURDER_KNIFE = "DeathPlayerMurderKnife";
public const string TAG_DEATH_PLAYER_EASTER_EGG = "DeathPlayerEasterEgg";
public const string TAG_DEATH_PLAYER_MURDER_SHOTGUN = "DeathPlayerMurderShotgun";
public const string TAG_DEATH_PLAYER_QUICKSAND = "DeathPlayerQuicksand";
public const string TAG_DEATH_PLAYER_STUN_GRENADE = "DeathPlayerStunGrenade";
public const string TAG_DEATH_PLAYER_ELECTRIC_CHAIR = "DeathPlayerElectricChair";
public const string TAG_DEATH_PLAYER_VOMITING = "DeathPlayerVomiting";
public const string TAG_DEATH_PLAYER_CRUISER_DRIVER = "DeathPlayerCruiserDriver";
public const string TAG_DEATH_PLAYER_CRUISER_PASSENGER = "DeathPlayerCruiserPassenger";
public const string TAG_DEATH_PLAYER_CRUISER_EXPLODE_BYSTANDER = "DeathPlayerCruiserExplodeBystander";
public const string TAG_DEATH_PLAYER_CRUISER_RAN_OVER = "DeathPlayerCruiserRanOver";
public const string TAG_DEATH_PIT_GENERIC = "DeathPitGeneric";
public const string TAG_DEATH_PIT_FACILITY_PIT = "DeathPitFacilityPit";
public const string TAG_DEATH_PIT_FACILITY_CATWALK_JUMP = "DeathPitFacilityCatwalkJump";
public const string TAG_DEATH_PIT_MINE_PIT = "DeathPitMinePit";
public const string TAG_DEATH_PIT_MINE_CAVE = "DeathPitMineCave";
public const string TAG_DEATH_PIT_MINE_ELEVATOR = "DeathPitMineElevator";
public const string TAG_DEATH_OTHER_DEPOSIT_ITEMS_DESK = "DeathOtherDepositItemsDesk";
public const string TAG_DEATH_OTHER_ITEM_DROPSHIP = "DeathOtherItemDropship";
public const string TAG_DEATH_OTHER_LANDMINE = "DeathOtherLandmine";
public const string TAG_DEATH_OTHER_TURRET = "DeathOtherTurret";
public const string TAG_DEATH_OTHER_LIGHTNING = "DeathOtherLightning";
public const string TAG_DEATH_OTHER_METEOR = "DeathOtherMeteor";
public const string TAG_DEATH_OTHER_SPIKE_TRAP = "DeathOtherSpikeTrap";
public const string TAG_DEATH_OTHER_OUT_OF_BOUNDS = "DeathOtherOutOfBounds";
public const string TAG_DEATH_UNKNOWN = "DeathUnknown";
public string languageCode;
private Dictionary<string, List<string>> languageData;
private bool fallback;
public LanguageHandler(string languageCode, bool fallback = false)
{
Plugin.Instance.PluginLogger.LogInfo("Coroner loading " + (fallback ? "fallback " : "") + "language support: " + languageCode);
this.languageCode = languageCode;
this.fallback = fallback;
languageData = new Dictionary<string, List<string>>();
LoadLanguageData(languageCode);
}
private void LoadLanguageData(string languageCode)
{
if (!Directory.Exists(Plugin.Instance.GetConfigPath()))
{
Plugin.Instance.PluginLogger.LogError("Config folder not found at: " + Plugin.Instance.GetConfigPath());
string path = Plugin.AssemblyDirectory + "/BepInEx/config/EliteMasterEric-Coroner/Strings_" + languageCode + ".xml";
if (File.Exists(path))
{
Plugin.Instance.PluginLogger.LogError("IMPORTANT: You didn't install the mod correctly! Move the BepInEx/config folder to the right spot!");
}
else
{
Plugin.Instance.PluginLogger.LogError("Try reinstalling the mod from scratch.");
}
return;
}
if (!File.Exists(Plugin.Instance.GetConfigPath() + "/Strings_" + languageCode + ".xml"))
{
Plugin.Instance.PluginLogger.LogError("Localization File not found at: " + Plugin.Instance.GetConfigPath());
return;
}
Plugin.Instance.PluginLogger.LogInfo("Loading language data from config folder: " + Plugin.Instance.GetConfigPath());
XDocument xDocument = XDocument.Load(Plugin.Instance.GetConfigPath() + "/Strings_" + languageCode + ".xml");
if (xDocument == null)
{
Plugin.Instance.PluginLogger.LogError("Localization could not be parsed at: " + Plugin.Instance.GetConfigPath() + "/Strings_" + languageCode + ".xml");
return;
}
PopulateLanguageData(xDocument);
string[] array = Directory.GetFiles(Plugin.Instance.GetConfigPath(), "Strings_" + languageCode + "_*.xml").ToArray();
Plugin.Instance.PluginLogger.LogInfo($"Loading {array.Length} additional language data files from config folder");
for (int i = 0; i < array.Length; i++)
{
Plugin.Instance.PluginLogger.LogInfo("Loading additional language data file: " + array[i]);
XDocument languageDoc = XDocument.Load(array[i]);
PopulateLanguageData(languageDoc, append: true);
}
Plugin.Instance.PluginLogger.LogInfo($"Success, loaded {languageData.Count()} types of language tags with {CountLanguageEntries()} total entries.");
}
public void PopulateLanguageData(XDocument languageDoc, bool append = false)
{
if (!append)
{
languageData.Clear();
}
XElement xElement = languageDoc.Descendants("strings").First();
foreach (XElement item in xElement.Descendants())
{
string text = item.Name.ToString();
string value = item.Attribute("text").Value;
if (!languageData.ContainsKey(text))
{
languageData[text] = new List<string>();
}
List<string> list = languageData[text];
if (list != null)
{
list.Add(value);
languageData[text] = list;
}
else
{
Plugin.Instance.PluginLogger.LogError("Current values for key '" + text + "' is null!");
}
}
}
public int CountLanguageEntries()
{
return languageData.Sum<KeyValuePair<string, List<string>>>((KeyValuePair<string, List<string>> x) => x.Value.Count);
}
public string GetFirstValueByTag(string tag)
{
return GetValuesByTag(tag)[0];
}
public string[] GetValuesByTag(string tag)
{
if (languageData.Count == 0 && languageCode != "en-us")
{
Plugin.Instance.PluginLogger.LogWarning("No language data loaded for '" + languageCode + "', displaying fallback language en-us...");
return Plugin.Instance.FallbackLanguageHandler.GetValuesByTag(tag);
}
if (languageData.Count == 0)
{
Plugin.Instance.PluginLogger.LogWarning("No language data loaded for default language, displaying error text...");
return new string[1] { "{'" + tag + "'}" };
}
if (!languageData.ContainsKey(tag) && languageCode != "en-us")
{
Plugin.Instance.PluginLogger.LogWarning("No values found for tag '" + tag + "' in language '" + languageCode + "', displaying fallback language en-us...");
return Plugin.Instance.FallbackLanguageHandler.GetValuesByTag(tag);
}
if (!languageData.ContainsKey(tag))
{
Plugin.Instance.PluginLogger.LogWarning("No values found for tag '" + tag + "' in language '" + languageCode + "', displaying error text...");
return new string[1] { "{'" + tag + "'}" };
}
List<string> list = languageData[tag];
if ((list == null || list.Count == 0) && languageCode != "en-us")
{
Plugin.Instance.PluginLogger.LogWarning("No values found for tag '" + tag + "' in language '" + languageCode + "', displaying fallback language en-us...");
return Plugin.Instance.FallbackLanguageHandler.GetValuesByTag(tag);
}
if (list == null || list.Count == 0)
{
Plugin.Instance.PluginLogger.LogWarning("No values found for tag '" + tag + "' in language '" + languageCode + "', displaying error text...");
return new string[1] { "{'" + tag + "'}" };
}
return list.ToArray();
}
}
[StaticNetcode]
internal class NetworkRPC
{
[ServerRpc(RequireOwnership = false)]
public static void ReportCauseOfDeathServerRpc(int playerClientId, string? codLanguageTag, bool forceOverride)
{
Plugin.Instance.PluginLogger.LogDebug(string.Format("Server received cause of death via RPC: ({0}, {1})", playerClientId, (codLanguageTag == null) ? "null" : codLanguageTag));
BroadcastCauseOfDeathClientRpc(playerClientId, codLanguageTag, forceOverride);
}
[ClientRpc(/*Could not decode attribute arguments.*/)]
public static void BroadcastCauseOfDeathClientRpc(int playerClientId, string? codLanguageTag, bool forceOverride)
{
Plugin.Instance.PluginLogger.LogDebug(string.Format("Client received cause of death via RPC: ({0}, {1})", playerClientId, (codLanguageTag == null) ? "null" : codLanguageTag));
if (codLanguageTag == null || !AdvancedCauseOfDeath.IsTagRegistered(codLanguageTag))
{
Plugin.Instance.PluginLogger.LogError("Could not deserialize cause of death (" + codLanguageTag + ")");
return;
}
AdvancedCauseOfDeath? advancedCauseOfDeath = AdvancedCauseOfDeath.Fetch(codLanguageTag);
Plugin.Instance.PluginLogger.LogDebug($"Deserialized cause of death to {advancedCauseOfDeath}");
AdvancedDeathTracker.StoreLocalCauseOfDeath(playerClientId, advancedCauseOfDeath, forceOverride);
}
}
public static class PluginInfo
{
public const string PLUGIN_ID = "Coroner";
public const string PLUGIN_NAME = "Coroner";
public const string PLUGIN_AUTHOR = "EliteMasterEric";
public const string PLUGIN_VERSION = "2.3.0";
public const string PLUGIN_GUID = "com.elitemastereric.coroner";
}
[BepInPlugin("com.elitemastereric.coroner", "Coroner", "2.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
public static readonly Random RANDOM = new Random();
public PluginLogger PluginLogger;
internal PluginConfig PluginConfig;
internal LanguageHandler LanguageHandler;
internal LanguageHandler FallbackLanguageHandler;
public static Plugin Instance { get; private set; }
public static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uriBuilder = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uriBuilder.Path);
return Path.GetDirectoryName(path);
}
}
private void Awake()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
Instance = this;
PluginLogger = new PluginLogger(((BaseUnityPlugin)this).Logger);
Harmony val = new Harmony("com.elitemastereric.coroner");
val.PatchAll();
PluginLogger.LogInfo("Plugin Coroner (com.elitemastereric.coroner) is loaded!");
LoadConfig();
LoadLanguageHandlers();
}
public string GetConfigPath()
{
return Paths.ConfigPath + "/EliteMasterEric-Coroner";
}
public void LoadLanguageHandlers()
{
LanguageHandler = new LanguageHandler(PluginConfig.GetSelectedLanguage());
FallbackLanguageHandler = new LanguageHandler("en-us", fallback: true);
}
private void LoadConfig()
{
PluginConfig = new PluginConfig();
PluginConfig.BindConfig(((BaseUnityPlugin)this).Config);
}
}
public class PluginLogger
{
private ManualLogSource manualLogSource;
public PluginLogger(ManualLogSource manualLogSource)
{
this.manualLogSource = manualLogSource;
}
public void LogFatal(object data)
{
manualLogSource.LogFatal(data);
}
public void LogError(object data)
{
manualLogSource.LogError(data);
}
public void LogWarning(object data)
{
manualLogSource.LogWarning(data);
}
public void LogMessage(object data)
{
manualLogSource.LogMessage(data);
}
public void LogInfo(object data)
{
manualLogSource.LogInfo(data);
}
public void LogDebug(object data)
{
manualLogSource.LogDebug(data);
}
}
internal class PluginConfig
{
private ConfigEntry<bool>? DisplayCauseOfDeath = null;
private ConfigEntry<bool>? SeriousDeathMessages = null;
private ConfigEntry<bool>? DisplayFunnyNotes = null;
private ConfigEntry<bool>? DeathReplacesNotes = null;
private ConfigEntry<string>? LanguagePicker = null;
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.");
LanguagePicker = _config.Bind<string>("Language", "LanguagePicker", "en-us", "Select a language to use.");
}
public bool ShouldDisplayCauseOfDeath()
{
if (DisplayCauseOfDeath == null)
{
Plugin.Instance.PluginLogger.LogWarning("Invalid access to uninstantiated config value DisplayCauseOfDeath");
return true;
}
return DisplayCauseOfDeath.Value;
}
public bool ShouldUseSeriousDeathMessages()
{
if (SeriousDeathMessages == null)
{
Plugin.Instance.PluginLogger.LogWarning("Invalid access to uninstantiated config value SeriousDeathMessages");
return false;
}
return SeriousDeathMessages.Value;
}
public bool ShouldDisplayFunnyNotes()
{
if (DisplayFunnyNotes == null)
{
Plugin.Instance.PluginLogger.LogWarning("Invalid access to uninstantiated config value DisplayFunnyNotes");
return true;
}
return DisplayFunnyNotes.Value;
}
public bool ShouldDeathReplaceNotes()
{
if (DeathReplacesNotes == null)
{
Plugin.Instance.PluginLogger.LogWarning("Invalid access to uninstantiated config value DeathReplacesNotes");
return true;
}
return DeathReplacesNotes.Value;
}
public string GetSelectedLanguage()
{
if (LanguagePicker == null)
{
Plugin.Instance.PluginLogger.LogWarning("Invalid access to uninstantiated config value LanguagePicker");
return "en-us";
}
return LanguagePicker.Value.Replace('_', '-');
}
}
}
namespace Coroner.Patch
{
internal class CauseOfDeathPatch
{
public const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3, Boolean)";
public const string DAMAGE_PLAYER_SIGNATURE = "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)";
public static void LogException(Exception e, string location)
{
Plugin.Instance.PluginLogger.LogError("Caught exception in " + location + ": " + e.Message);
Plugin.Instance.PluginLogger.LogError(e.StackTrace);
}
public static bool IsPlayer(Collider collider)
{
if ((Object)(object)collider == (Object)null)
{
return false;
}
return (Object)(object)((Component)collider).gameObject.GetComponent<PlayerControllerB>() != (Object)null;
}
public static int LocateKillPlayerCall(List<CodeInstruction> instructions)
{
for (int i = 0; i < instructions.Count; i++)
{
CodeInstruction val = instructions[i];
if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3, Boolean)")
{
return i;
}
}
return -1;
}
public static int LocateDamagePlayerCall(List<CodeInstruction> instructions)
{
for (int i = 0; i < instructions.Count; i++)
{
CodeInstruction val = instructions[i];
if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)")
{
return i;
}
}
return -1;
}
public static void OverrideKillLocalPlayer(KillLocalPlayer target, AdvancedCauseOfDeath causeOfDeath)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)target == (Object)null))
{
target.causeOfDeath = causeOfDeath;
}
}
public static void OverrideKillLocalPlayer(GameObject target, AdvancedCauseOfDeath causeOfDeath)
{
if (!((Object)(object)target == (Object)null))
{
OverrideKillLocalPlayer(target.GetComponent<KillLocalPlayer>(), causeOfDeath);
}
}
public static void OverrideKillLocalPlayer(Transform target, AdvancedCauseOfDeath causeOfDeath)
{
if (!((Object)(object)target == (Object)null))
{
OverrideKillLocalPlayer(((Component)target).gameObject, causeOfDeath);
}
}
}
internal class CauseOfDeathPatchState
{
private int targetPlayerIndex;
private bool wasPlayerQueried;
public bool previousIsPlayerDead;
public CauseOfDeath? previousCauseOfDeath = null;
public bool wasHoldingJetpack;
public CauseOfDeathPatchState()
{
targetPlayerIndex = -1;
wasPlayerQueried = false;
}
public void TrySetPlayer(int targetPlayerIndex)
{
if (targetPlayerIndex < 0)
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Invalid player index! " + targetPlayerIndex);
}
else
{
this.targetPlayerIndex = targetPlayerIndex;
}
}
public void TrySetPlayer(PlayerControllerB playerControllerB)
{
if ((Object)(object)playerControllerB == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: PlayerController was null");
}
else
{
TrySetPlayer((int)playerControllerB.playerClientId);
}
}
public void TrySetPlayer(Collider collider)
{
if ((Object)(object)collider == (Object)null)
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Collider was null!");
return;
}
if (!CauseOfDeathPatch.IsPlayer(collider))
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Collider was not a player!");
return;
}
PlayerControllerB component = ((Component)collider).gameObject.GetComponent<PlayerControllerB>();
TrySetPlayer(component);
}
public void QueryPlayerState()
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
if (wasPlayerQueried)
{
Plugin.Instance.PluginLogger.LogWarning("Tried to query player state, but we already did that? " + ToString());
return;
}
PlayerControllerB val = FetchPlayer();
if (!((Object)(object)val == (Object)null))
{
Plugin.Instance.PluginLogger.LogDebug("Querying target player parameters pre-death...");
wasPlayerQueried = true;
previousIsPlayerDead = val.isPlayerDead;
previousCauseOfDeath = val.causeOfDeath;
wasHoldingJetpack = AdvancedDeathTracker.IsHoldingJetpack(val);
Plugin.Instance.PluginLogger.LogDebug("Query successful!" + wasPlayerQueried);
}
}
public int FetchPlayerIndex()
{
if (targetPlayerIndex == -1)
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Index not assigned!");
return -1;
}
return targetPlayerIndex;
}
public PlayerControllerB? FetchPlayer()
{
if (targetPlayerIndex == -1)
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Index not assigned!");
return null;
}
if (targetPlayerIndex >= StartOfRound.Instance.allPlayerScripts.Length)
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Index out of bounds! " + targetPlayerIndex);
return null;
}
return StartOfRound.Instance.allPlayerScripts[targetPlayerIndex];
}
public PlayerControllerB GetPlayer()
{
PlayerControllerB val = FetchPlayer();
if ((Object)(object)val == (Object)null)
{
throw new Exception("Could not retrieve player from state!");
}
return val;
}
public bool ValidateWasntAlreadyDead()
{
if (!wasPlayerQueried)
{
return false;
}
PlayerControllerB val = FetchPlayer();
if ((Object)(object)val == (Object)null)
{
return false;
}
if (previousIsPlayerDead)
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Player was already dead!");
return false;
}
return true;
}
public bool ValidateIsPlayerDead()
{
if (!wasPlayerQueried)
{
return false;
}
PlayerControllerB val = FetchPlayer();
if ((Object)(object)val == (Object)null)
{
return false;
}
if (!val.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Player is still alive!");
return false;
}
return true;
}
public bool ValidateHasNoCauseOfDeath()
{
if (!wasPlayerQueried)
{
return false;
}
if (AdvancedDeathTracker.HasCauseOfDeath(FetchPlayerIndex()))
{
Plugin.Instance.PluginLogger.LogWarning("Could not access dying player: Player already had a precise cause of death!");
return false;
}
return true;
}
public override string ToString()
{
return $"CauseOfDeathPatchState({targetPlayerIndex}:{wasPlayerQueried}, {previousIsPlayerDead}==false?)";
}
}
internal class CauseOfDeathEnumerator : EnumeratorPatch
{
public Action<CauseOfDeathPatchState>? preDeathAction;
public Action<CauseOfDeathPatchState>? postDeathAction;
public Action<CauseOfDeathPatchState>? postDeathStepAction;
public CauseOfDeathEnumerator(IEnumerator targetEnumerator)
: base(targetEnumerator)
{
CauseOfDeathPatchState state = new CauseOfDeathPatchState();
prefixAction = delegate
{
preDeathAction?.Invoke(state);
Plugin.Instance.PluginLogger.LogDebug("Post step action done: " + state.ToString());
};
postfixAction = delegate
{
postDeathAction?.Invoke(state);
Plugin.Instance.PluginLogger.LogDebug("Post step action done: " + state.ToString());
};
postStepAction = delegate
{
postDeathStepAction?.Invoke(state);
Plugin.Instance.PluginLogger.LogDebug("Post step action done: " + state.ToString());
};
}
}
[HarmonyPatch(typeof(BaboonBirdAI), "OnCollideWithPlayer")]
internal class BaboonBirdAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "BaboonBirdAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Baboon Hawk damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Baboon Hawk killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_BaboonHawk);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "BaboonBirdAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(ButlerBeesEnemyAI), "OnCollideWithPlayer")]
internal class ButlerBeesEnemyAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "ButlerBeesEnemyAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Mask Hornet damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Mask Hornet killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_MaskHornets);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "ButlerBeesEnemyAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(ButlerEnemyAI), "OnCollideWithPlayer")]
internal class ButlerEnemyAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "ButlerEnemyAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Butler damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Butler killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Butler_Stab);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "ButlerEnemyAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(CadaverBloomAI), "OnCollideWithPlayer")]
internal class CadaverBloomAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CadaverBloomAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Cadaver Bloom damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Cadaver Bloom killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Cadaver_Bloom);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CadaverBloomAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(GiantKiwiAI), "AnimationEventB")]
internal class GiantKiwiAIAnimationEventBPatch
{
public static void Prefix(ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(GameNetworkManager.Instance.localPlayerController);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "GiantKiwiAI.AnimationEventB:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Giant Sapsucker damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Giant Sapsucker killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Giant_Sapsucker);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "GiantKiwiAI.AnimationEventB:Postfix");
}
}
}
[HarmonyPatch(typeof(LassoManAI), "OnCollideWithPlayer")]
internal class LassoManAIOnCollideWithPlayer
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "LassoManAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Lasso Man damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Lasso Man killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_LassoMan);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "LassoManAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(MoveToExitSpecialAnimation), "shockChair")]
internal class MoveToExitSpecialAnimationShockChairPatch
{
public static void Prefix(MoveToExitSpecialAnimation __instance, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(((Component)__instance.interactTrigger.lockedPlayer).GetComponent<PlayerControllerB>());
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "MoveToExitSpecialAnimation.shockChair:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Lasso Man damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Electric Chair killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Player_Electric_Chair);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "MoveToExitSpecialAnimation.shockChair:Postfix");
}
}
}
[HarmonyPatch(typeof(PufferAI), "OnCollideWithPlayer")]
internal class PufferAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "PufferAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Spore Lizard damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Spore Lizard killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_SporeLizard);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "PufferAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(PumaAI), "OnCollideWithPlayer")]
internal class PumaAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "PumaAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Feiopar damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Feiopar killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Feiopar);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "PumaAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(RadMechAI), "Stomp")]
internal class RadMechAIStompPatch
{
public static void Prefix(ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(GameNetworkManager.Instance.localPlayerController);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "RadMechAI.Stomp:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Old Bird (Stomp) damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Old Bird killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Old_Bird_Stomp);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "RadMechAI.Stomp:Postfix");
}
}
}
[HarmonyPatch(typeof(RadMechAI), "TorchPlayerAnimation")]
internal class RadMechAITorchPlayerAnimationPatch
{
public static void Postfix(RadMechAI __instance, ref IEnumerator __result)
{
RadMechAI __instance2 = __instance;
try
{
CauseOfDeathEnumerator causeOfDeathEnumerator = new CauseOfDeathEnumerator(__result)
{
preDeathAction = delegate(CauseOfDeathPatchState __state)
{
EnumeratorPrefix(__instance2, __state);
},
postDeathStepAction = delegate(CauseOfDeathPatchState __state)
{
EnumeratorStepPostfix(__instance2, __state);
},
postDeathAction = delegate(CauseOfDeathPatchState __state)
{
EnumeratorStepPostfix(__instance2, __state);
}
};
__result = causeOfDeathEnumerator.GetEnumerator();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "RadMechAI.TorchPlayerAnimation:Postfix");
}
}
private static void EnumeratorPrefix(RadMechAI __instance, CauseOfDeathPatchState __state)
{
try
{
__state.TrySetPlayer(((EnemyAI)__instance).inSpecialAnimationWithPlayer);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "RadMechAI.TorchPlayerAnimation:EnumeratorPrefix");
}
}
private static void EnumeratorStepPostfix(RadMechAI __instance, CauseOfDeathPatchState __state)
{
try
{
PlayerControllerB player = __state.GetPlayer();
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Old Bird killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Old_Bird_Torch);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "RadMechAI.TorchPlayerAnimation:EnumeratorStepPostfix");
}
}
}
[HarmonyPatch(typeof(SandSpiderAI), "OnCollideWithPlayer")]
internal class SandSpiderAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "SandSpiderAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Bunker Spider damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Bunker Spider killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_BunkerSpider);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "SandSpiderAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(BlobAI), "OnCollideWithPlayer")]
internal class BlobAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "BlobAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Bunker Spider damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Bunker Spider killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Hygrodere);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "BlobAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(CentipedeAI), "DamagePlayerOnIntervals")]
internal class CentipedeAIDamagePlayerOnIntervalsPatch
{
public static void Prefix(CentipedeAI __instance, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(__instance.clingingToPlayer);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CentipedeAI.DamagePlayerOnIntervals:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Centipede damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Centipede killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_SnareFlea);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CentipedeAI.DamagePlayerOnIntervals:Postfix");
}
}
}
[HarmonyPatch(typeof(CrawlerAI), "OnCollideWithPlayer")]
internal class CrawlerAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CrawlerAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Thumper damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Thumper killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Thumper);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CrawlerAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(RedLocustBees), "BeeKillPlayerOnLocalClient")]
internal class RedLocustBeesBeeKillPlayerOnLocalClientPatch
{
public static void Prefix(int playerId, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(playerId);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "RedLocustBees.BeeKillPlayerOnLocalClient:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Circuit Bees damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Circuit Bees killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_CircuitBees);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "RedLocustBees.BeeKillPlayerOnLocalClient:Postfix");
}
}
}
[HarmonyPatch(typeof(HoarderBugAI), "OnCollideWithPlayer")]
internal class HoarderBugAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "HoarderBugAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Hoarder Bug damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Hoarder Bug killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_HoarderBug);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "HoarderBugAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(SpringManAI), "OnCollideWithPlayer")]
internal class SpringManAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "SpringManAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Coil-Head damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Coil-Head killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_CoilHead);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "SpringManAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(ShotgunItem), "ShootGun")]
internal class ShotgunItemShootGunPatch
{
public static void Prefix(ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(GameNetworkManager.Instance.localPlayerController);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "ShotgunItem.ShootGun:Prefix");
}
}
public static void Postfix(ShotgunItem __instance, ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Shotgun damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Shotgun killed Player! Checking wielder...");
if (((GrabbableObject)__instance).isHeldByEnemy)
{
Plugin.Instance.PluginLogger.LogDebug("Shotgun (Nutcracker) killed player! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Nutcracker_Shot);
}
else
{
Plugin.Instance.PluginLogger.LogDebug("Shotgun (Player) killed player! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Player_Murder_Shotgun);
}
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "ShotgunItem.ShootGun:Postfix");
}
}
}
[HarmonyPatch(typeof(SprayPaintItem), "HealPlayerInfection")]
internal class SprayPaintItemHealPlayerInfectionPatch
{
public static void Prefix(ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(GameNetworkManager.Instance.localPlayerController);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "SprayPaintItem.HealPlayerInfection:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling vomiting damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Vomiting killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Player_Vomiting);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "SprayPaintItem.HealPlayerInfection:Postfix");
}
}
}
[HarmonyPatch(typeof(StunGrenadeItem), "StunExplosion")]
internal class StunGrenadeItemStunExplosionPatch
{
public static void Prefix(StunGrenadeItem __instance, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(((GrabbableObject)__instance).playerHeldBy);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "StunGrenadeItem.StunExplosion:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Stun Grenade damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Stun Grenade killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Player_StunGrenade);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "StunGrenadeItem.StunExplosion:Postfix");
}
}
}
[HarmonyPatch(typeof(VehicleCollisionTrigger), "OnTriggerEnter")]
internal class VehicleCollisionTriggerOnTriggerEnterPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
if (!((Component)other).gameObject.CompareTag("Player"))
{
Plugin.Instance.PluginLogger.LogDebug("Vehicle collision with non-player...");
return;
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "VehicleCollisionTrigger.OnTriggerEnter:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Vehicle damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Vehicle (Collision) killed Player (Pedestrian)! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Player_Cruiser_Ran_Over);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "VehicleCollisionTrigger.OnTriggerEnter:Postfix");
}
}
}
[HarmonyPatch(typeof(VehicleController), "DamagePlayerInVehicle")]
internal class VehicleControllerDamagePlayerInVehiclePatch
{
public static void Prefix(VehicleController __instance, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
if (__instance.localPlayerInControl || __instance.localPlayerInPassengerSeat)
{
__state.TrySetPlayer(GameNetworkManager.Instance.localPlayerController);
__state.QueryPlayerState();
}
else
{
Plugin.Instance.PluginLogger.LogDebug("Couldn't determine player in vehicle...");
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "VehicleController.DamagePlayerInVehicle:Prefix");
}
}
public static void Postfix(VehicleController __instance, ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Vehicle damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
if (__instance.localPlayerInControl)
{
Plugin.Instance.PluginLogger.LogDebug("Vehicle (Collision) killed Player (Driver)! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Driver);
}
else if (__instance.localPlayerInPassengerSeat)
{
Plugin.Instance.PluginLogger.LogDebug("Vehicle (Collision) killed Player (Passenger)! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Passenger);
}
else
{
Plugin.Instance.PluginLogger.LogDebug("Couldn't determine player in vehicle...");
}
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "VehicleController.DamagePlayerInVehicle:Postfix");
}
}
}
[HarmonyPatch(typeof(PlayerControllerB), "PlayerHitGroundEffects")]
internal class PlayerControllerBPlayerHitGroundEffectsPatch
{
public static void Prefix(PlayerControllerB __instance, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(__instance);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "PlayerControllerB.PlayerHitGroundEffects:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling generic fall damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
PlayerControllerB player = __state.GetPlayer();
FootstepSurface val = StartOfRound.Instance.footstepSurfaces[player.currentFootstepSurfaceIndex];
if (val != null)
{
Plugin.Instance.PluginLogger.LogDebug("Fall damage (surface tag: $" + val.surfaceTag + ") killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(player, AdvancedCauseOfDeath.Gravity);
}
else
{
Plugin.Instance.PluginLogger.LogDebug("Fall damage (unknown surface) killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(player, AdvancedCauseOfDeath.Gravity);
}
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "PlayerControllerB.PlayerHitGroundEffects:Postfix");
}
}
}
[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayerFromOtherClientClientRpc")]
internal class PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch
{
private const string DAMAGE_PLAYER_SIGNATURE = "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)";
public static void Prefix(PlayerControllerB __instance, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(__instance);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "PlayerControllerB.DamagePlayerFromOtherClientClientRpc:Prefix");
}
}
public static void Postfix(int playerWhoHit, ref CauseOfDeathPatchState __state)
{
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling friendly fire damage...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
PlayerControllerB player = __state.GetPlayer();
PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerWhoHit];
if ((Object)(object)val == (Object)null)
{
Plugin.Instance.PluginLogger.LogError("Damage from other player: attacker is null!");
}
else if (AdvancedDeathTracker.IsHoldingShotgun(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Shotgun! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(player, AdvancedCauseOfDeath.Player_Murder_Shotgun);
}
else if (AdvancedDeathTracker.IsHoldingKnife(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Knife! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(player, AdvancedCauseOfDeath.Player_Murder_Knife);
}
else if (AdvancedDeathTracker.IsHoldingShovel(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Shovel! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(player, AdvancedCauseOfDeath.Player_Murder_Shovel);
}
else if (AdvancedDeathTracker.IsHoldingStopSign(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Stop Sign! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(player, AdvancedCauseOfDeath.Player_Murder_Stop_Sign);
}
else if (AdvancedDeathTracker.IsHoldingYieldSign(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Yield Sign! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(player, AdvancedCauseOfDeath.Player_Murder_Yield_Sign);
}
else
{
Plugin.Instance.PluginLogger.LogWarning($"Player was murdered, by an unknown item {AdvancedDeathTracker.GetHeldObject(val)}! Setting cause of death to: " + ((object)(CauseOfDeath)(ref player.causeOfDeath)).ToString());
AdvancedDeathTracker.SetCauseOfDeath(player, player.causeOfDeath);
}
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch:Postfix");
}
}
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("Could not build instructions to insert in PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch! Safely aborting...");
return instructions;
}
int num = -1;
for (int i = 0; i < list.Count; i++)
{
CodeInstruction val = list[i];
if (val.opcode == OpCodes.Call && val.operand.ToString() == "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)")
{
num = i;
}
}
if (num == -1)
{
Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.DamagePlayer call in PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch! Safely aborting...");
return instructions;
}
Plugin.Instance.PluginLogger.LogDebug("Injecting patch into PlayerControllerB.DamagePlayerFromOtherClientClientRpc...");
list.InsertRange(num + 1, list2);
Plugin.Instance.PluginLogger.LogDebug("Done.");
Plugin.Instance.PluginLogger.LogDebug("Done with all PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch patches.");
return list;
}
private static List<CodeInstruction>? BuildInstructionsToInsert(MethodBase method)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Expected O, but got Unknown
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>();
int num = 0;
int num2 = 1;
int num3 = 2;
int num4 = 3;
int num5 = 4;
list.Add(new CodeInstruction(OpCodes.Ldarg, (object)num));
list.Add(new CodeInstruction(OpCodes.Ldarg, (object)num2));
list.Add(new CodeInstruction(OpCodes.Ldarg, (object)num3));
list.Add(new CodeInstruction(OpCodes.Ldarg, (object)num4));
list.Add(new CodeInstruction(OpCodes.Ldarg, (object)num5));
list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch).GetMethod("MaybeRewriteCauseOfDeath")));
return list;
}
public static void MaybeRewriteCauseOfDeath(PlayerControllerB targetPlayer, int damageAmount, Vector3 hitDirection, int playerWhoHit, int newHealthAmount)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
Plugin.Instance.PluginLogger.LogDebug($"Player damaged another player ${targetPlayer}({damageAmount}, {hitDirection}, {playerWhoHit}, {newHealthAmount})");
if (targetPlayer.isPlayerDead)
{
Plugin.Instance.PluginLogger.LogDebug("Player died from friendly fire damage");
RewriteCauseOfDeath(targetPlayer, playerWhoHit);
}
else
{
Plugin.Instance.PluginLogger.LogDebug($"Player did not die from friendly fire (left at ${targetPlayer.health} health)");
}
}
public static void RewriteCauseOfDeath(PlayerControllerB targetPlayer, int playerWhoHitIndex)
{
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerWhoHitIndex];
if ((Object)(object)targetPlayer == (Object)null)
{
Plugin.Instance.PluginLogger.LogError("Damage from other client: victim is null!");
return;
}
if ((Object)(object)val == (Object)null)
{
Plugin.Instance.PluginLogger.LogError("Damage from other client: attacker is null!");
return;
}
Plugin.Instance.PluginLogger.LogDebug($"Player died from murder ({targetPlayer.causeOfDeath}), determining special cause of death...");
if (AdvancedDeathTracker.IsHoldingShotgun(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Shotgun! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, AdvancedCauseOfDeath.Player_Murder_Shotgun);
}
else if (AdvancedDeathTracker.IsHoldingKnife(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Knife! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, AdvancedCauseOfDeath.Player_Murder_Knife);
}
else if (AdvancedDeathTracker.IsHoldingShovel(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Shovel! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, AdvancedCauseOfDeath.Player_Murder_Shovel);
}
else if (AdvancedDeathTracker.IsHoldingStopSign(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Stop Sign! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, AdvancedCauseOfDeath.Player_Murder_Stop_Sign);
}
else if (AdvancedDeathTracker.IsHoldingYieldSign(val))
{
Plugin.Instance.PluginLogger.LogDebug("Player was murdered by Yield Sign! Setting special cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, AdvancedCauseOfDeath.Player_Murder_Yield_Sign);
}
else
{
Plugin.Instance.PluginLogger.LogWarning($"Player was killed by someone else, holding an unknown item {AdvancedDeathTracker.GetHeldObject(val)}! " + ((object)(CauseOfDeath)(ref targetPlayer.causeOfDeath)).ToString());
AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, targetPlayer.causeOfDeath);
}
}
}
[HarmonyPatch(typeof(AnimatedObjectFloatSetter), "KillPlayerAtPoint")]
internal class AnimatedObjectFloatSetterKillPlayerAtPointPatch
{
public static void Prefix(ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(GameNetworkManager.Instance.localPlayerController);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "AnimatedObjectFloatSetter.KillPlayerAtPoint:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling AnimatedObjectFloatSetter death...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogWarning("AnimatedObjectFloatSetter killed Player! Unknown cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Unknown);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "AnimatedObjectFloatSetter.KillPlayerAtPoint:Postfix");
}
}
}
[HarmonyPatch(typeof(BushWolfEnemy), "OnCollideWithPlayer")]
internal class BushWolfOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "BushWolf.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Kidnapper Fox death...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogWarning("Kidnapper Fox killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_KidnapperFox);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "BushWolf.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(CadaverBloomAI), "BurstForth")]
internal class CadaverBloomAIBurstForthPatch
{
public static void Prefix(PlayerControllerB player, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(player);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CadaverBloomAI.BurstForth:Prefix");
}
}
public static void Postfix(bool kill, ref CauseOfDeathPatchState __state)
{
try
{
if (kill)
{
Plugin.Instance.PluginLogger.LogDebug("Handling Cadaver Growth death...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogWarning("Cadaver Growth killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Cadaver_Growth);
}
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CadaverBloomAI.BurstForth:Postfix");
}
}
}
[HarmonyPatch(typeof(CaveDwellerAI), "KillPlayerAnimationClientRpc")]
internal class CaveDwellerAIKillPlayerAnimationClientRpcPatch
{
public static void Prefix(int playerObjectId, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(playerObjectId);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CaveDwellerAI.KillPlayerAnimationClientRpc:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Maneater death...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogWarning("Maneater killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Maneater);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "CaveDwellerAI.KillPlayerAnimationClientRpc:Postfix");
}
}
}
[HarmonyPatch(typeof(ClaySurgeonAI), "OnCollideWithPlayer")]
internal class ClaySurgeonAIOnCollideWithPlayerPatch
{
public static void Prefix(Collider other, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
__state.TrySetPlayer(other);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "ClaySurgeonAI.OnCollideWithPlayer:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Barber death...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Barber killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_Barber);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "ClaySurgeonAI.OnCollideWithPlayer:Postfix");
}
}
}
[HarmonyPatch(typeof(DepositItemsDesk), "AnimationGrabPlayer")]
internal class DepositItemsDeskAnimationGrabPlayerPatch
{
public static void Postfix(DepositItemsDesk __instance, int playerID, ref IEnumerator __result)
{
DepositItemsDesk __instance2 = __instance;
try
{
CauseOfDeathEnumerator causeOfDeathEnumerator = new CauseOfDeathEnumerator(__result)
{
preDeathAction = delegate(CauseOfDeathPatchState __state)
{
EnumeratorPrefix(__instance2, playerID, __state);
},
postDeathStepAction = delegate(CauseOfDeathPatchState __state)
{
EnumeratorStepPostfix(__instance2, __state);
},
postDeathAction = delegate(CauseOfDeathPatchState __state)
{
EnumeratorStepPostfix(__instance2, __state);
}
};
__result = causeOfDeathEnumerator.GetEnumerator();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "DepositItemsDesk.AnimationGrabPlayer:Postfix");
}
}
private static void EnumeratorPrefix(DepositItemsDesk __instance, int playerID, CauseOfDeathPatchState __state)
{
try
{
__state.TrySetPlayer(playerID);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "DepositItemsDesk.AnimationGrabPlayer:EnumeratorPrefix");
}
}
private static void EnumeratorStepPostfix(DepositItemsDesk __instance, CauseOfDeathPatchState __state)
{
try
{
PlayerControllerB player = __state.GetPlayer();
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Deposit Desk killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Other_DepositItemsDesk);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "DepositItemsDesk.AnimationGrabPlayer:EnumeratorStepPostfix");
}
}
}
[HarmonyPatch(typeof(HauntedMaskItem), "FinishAttaching")]
internal class HauntedMaskItemFinishAttachingPatch
{
public static void Prefix(HauntedMaskItem __instance, ref CauseOfDeathPatchState __state)
{
try
{
if (__state == null)
{
__state = new CauseOfDeathPatchState();
}
PlayerControllerB value = Traverse.Create((object)__instance).Field("previousPlayerHeldBy").GetValue<PlayerControllerB>();
__state.TrySetPlayer(value);
__state.QueryPlayerState();
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "HauntedMaskItem.FinishAttaching:Prefix");
}
}
public static void Postfix(ref CauseOfDeathPatchState __state)
{
try
{
Plugin.Instance.PluginLogger.LogDebug("Handling Haunted Mask death...");
if (__state.ValidateWasntAlreadyDead() && __state.ValidateIsPlayerDead() && __state.ValidateHasNoCauseOfDeath())
{
Plugin.Instance.PluginLogger.LogDebug("Haunted Mask killed Player! Setting cause of death...");
AdvancedDeathTracker.SetCauseOfDeath(__state.GetPlayer(), AdvancedCauseOfDeath.Enemy_MaskedPlayer_Wear);
}
}
catch (Exception e)
{
CauseOfDeathPatch.LogException(e, "HauntedMaskItem.FinishAttaching:Postfix");
}
}
}
[HarmonyPatch(typeof(JesterAI), "killPlayerAnimation")]
internal class JesterAIKillPlayerAnimationPatch
{
public static void Postfix(JesterAI __instance, int playerId, ref IEnumerator __result)
{
JesterAI __instance2 = __instance;
try
{