Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Coroner v2.4.1
Coroner.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
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.1.0")] [assembly: AssemblyInformationalVersion("2.4.1+8626d7985f5122271a270e3ab7373ebd9dfa5235")] [assembly: AssemblyProduct("Coroner")] [assembly: AssemblyTitle("Coroner")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.4.1.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(bool verbose = true) { if (!wasPlayerQueried) { return false; } PlayerControllerB val = FetchPlayer(); if ((Object)(object)val == (Object)null) { return false; } if (!val.isPlayerDead) { if (verbose) { 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 { if (__state.ValidateIsPlayerDead(verbose: false) && __state.ValidateWasntAlreadyDead() && __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_01e8: 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 { CauseOfDeath