Please disclose if your mod was created primarily 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 IyeQs Coroner Edit v1.0.0
Coroner.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; 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.2.0.0")] [assembly: AssemblyInformationalVersion("2.2.0+15b48f9fe2f9dd06a65afc16f50ee79252cbf332")] [assembly: AssemblyProduct("Coroner")] [assembly: AssemblyTitle("Coroner")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Coroner { internal class AdvancedDeathTracker { public static Dictionary<int, AdvancedCauseOfDeath?> causeOfDeathDictionary = new Dictionary<int, AdvancedCauseOfDeath?>(); public static void ClearDeathTracker() { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { StoreLocalCauseOfDeath((int)val.playerClientId, null, overrideExisting: true); } } public static void SetCauseOfDeath(int playerIndex, AdvancedCauseOfDeath? causeOfDeath, bool forceOverride = false) { if (!causeOfDeath.HasValue) { NetworkRPC.ReportCauseOfDeathServerRpc(playerIndex, null, forceOverride); return; } AdvancedCauseOfDeath value = causeOfDeath.Value; Plugin.Instance.PluginLogger.LogDebug(string.Format("Serializing {0} to {1}{2}", value, value.GetLanguageTag(), forceOverride ? " (FORCED)" : "")); NetworkRPC.ReportCauseOfDeathServerRpc(playerIndex, value.GetLanguageTag(), forceOverride); } 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) { PlayerControllerB playerController = StartOfRound.Instance.allPlayerScripts[playerIndex]; return GetCauseOfDeath(playerController, shouldGuess); } public static bool HasCauseOfDeath(int playerIndex) { 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 Snipped = 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 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_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) { AdvancedDeathTracker.SetCauseOfDeath(player, causeOfDeath); } public static void SetCauseOfDeath(int playerId, AdvancedCauseOfDeath? causeOfDeath) { AdvancedDeathTracker.SetCauseOfDeath(playerId, causeOfDeath); } 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 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_SNIPPED = "DeathSnipped"; 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_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_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] 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.2.0"; public const string PLUGIN_GUID = "com.elitemastereric.coroner"; } [BepInPlugin("com.elitemastereric.coroner", "Coroner", "2.2.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 { [HarmonyPatch(typeof(BaboonBirdAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class BaboonBirdAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Baboon Hawk damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_BaboonHawk); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in BaboonBirdAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(FlowermanAI))] [HarmonyPatch("killAnimation")] internal class FlowermanAIKillAnimationPatch { public static void Postfix(FlowermanAI __instance) { try { Plugin.Instance.PluginLogger.LogDebug("Accessing state after Bracken snapping neck..."); if ((Object)(object)((EnemyAI)__instance).inSpecialAnimationWithPlayer == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after snapping neck!"); return; } Plugin.Instance.PluginLogger.LogDebug("Player killed by Bracken! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(((EnemyAI)__instance).inSpecialAnimationWithPlayer, AdvancedCauseOfDeath.Enemy_Bracken); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in FlowermanAIKillAnimationPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(SandSpiderAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class SandSpiderAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Bunker Spider damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player killed by Bunker Spider! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_BunkerSpider); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive after hit by Forest Spider! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in SandSpiderAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(RedLocustBees))] [HarmonyPatch("BeeKillPlayerOnLocalClient")] internal class RedLocustBeesBeeKillPlayerOnLocalClientPatch { public static void Postfix(int playerId) { try { Plugin.Instance.PluginLogger.LogDebug("Accessing state after Circuit Bee electrocution..."); PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; if ((Object)(object)val == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (val.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player killed by Circuit Bees! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(val, AdvancedCauseOfDeath.Enemy_CircuitBees); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in RedLocustBeesBeeKillPlayerOnLocalClientPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(SpringManAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class SpringManAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Coil Head damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player killed by Coil Head! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_CoilHead); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive after hit by Coil Head! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in SpringManAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(SandWormAI))] [HarmonyPatch("EatPlayer")] internal class SandWormAIEatPlayerPatch { public static void Postfix(PlayerControllerB playerScript) { try { Plugin.Instance.PluginLogger.LogDebug("Accessing state after Sand Worm devouring..."); if ((Object)(object)playerScript == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); return; } Plugin.Instance.PluginLogger.LogDebug("Player was eaten by Earth Leviathan! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerScript, AdvancedCauseOfDeath.Enemy_EarthLeviathan); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in SandWormAIEatPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(MouthDogAI))] [HarmonyPatch("KillPlayer")] internal class MouthDogAIKillPlayerPatch { public static void Postfix(int playerId) { try { Plugin.Instance.PluginLogger.LogDebug("Accessing state after dog devouring..."); PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; if ((Object)(object)val == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); return; } Plugin.Instance.PluginLogger.LogDebug("Player was killed by Eyeless Dog! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(val, AdvancedCauseOfDeath.Enemy_EyelessDog); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in MouthDogAIKillPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(ForestGiantAI))] [HarmonyPatch("EatPlayerAnimation")] internal class ForestGiantAIEatPlayerAnimationPatch { public static void Postfix(PlayerControllerB playerBeingEaten) { try { Plugin.Instance.PluginLogger.LogDebug("Accessing state after Forest Giant devouring..."); if ((Object)(object)playerBeingEaten == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); return; } Plugin.Instance.PluginLogger.LogDebug("Player was eaten by Forest Giant! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerBeingEaten, AdvancedCauseOfDeath.Enemy_ForestGiant_Eaten); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in ForestGiantAIEatPlayerAnimationPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(ForestGiantAI))] [HarmonyPatch("AnimationEventA")] internal class ForestGiantAIAnimationEventAPatch { private const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)"; 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 ForestGiantAIAnimationEventAPatch! Safely aborting..."); return instructions; } int num = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)") { num = i; break; } } if (num == -1) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.KillPlayer call in ForestGiantAIAnimationEventAPatch! Safely aborting..."); return instructions; } Plugin.Instance.PluginLogger.LogDebug("Injecting patch into ForestGiantAI.AnimationEventA..."); list.InsertRange(num + 1, list2); Plugin.Instance.PluginLogger.LogDebug("Done."); return list; } private static List<CodeInstruction>? BuildInstructionsToInsert(MethodBase method) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); IList<LocalVariableInfo> localVariables = method.GetMethodBody().LocalVariables; LocalVariableInfo localVariableInfo = null; for (int i = 0; i < localVariables.Count; i++) { LocalVariableInfo localVariableInfo2 = localVariables[i]; if (localVariableInfo2.LocalType == typeof(PlayerControllerB)) { if (localVariableInfo != null) { Plugin.Instance.PluginLogger.LogError("Found multiple PlayerControllerB local variables in ForestGiantAIAnimationEventAPatch!"); return null; } localVariableInfo = localVariableInfo2; break; } } if (localVariableInfo == null) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB local variable in ForestGiantAIAnimationEventAPatch!"); return null; } list.Add(new CodeInstruction(OpCodes.Ldloc_S, (object)localVariableInfo.LocalIndex)); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(ForestGiantAIAnimationEventAPatch).GetMethod("RewriteCauseOfDeath"))); return list; } public static void RewriteCauseOfDeath(PlayerControllerB targetPlayer) { Plugin.Instance.PluginLogger.LogDebug("Player was crushed by dying Forest Giant! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, AdvancedCauseOfDeath.Enemy_ForestGiant_Death, forceOverride: true); } } [HarmonyPatch(typeof(DressGirlAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class DressGirlAIOnCollideWithPlayerPatch { public static void Postfix(DressGirlAI __instance) { try { Plugin.Instance.PluginLogger.LogDebug("Processing Ghost Girl player collision..."); if ((Object)(object)__instance.hauntingPlayer == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after collision!"); } else if (__instance.hauntingPlayer.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Ghost Girl! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance.hauntingPlayer, AdvancedCauseOfDeath.Enemy_GhostGirl); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in DressGirlAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(HoarderBugAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class HoarderBugAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Hoarder Bug damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Hoarder Bug! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_HoarderBug); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive after hit by Hoarder Bug! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in HoarderBugAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(BlobAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class BlobAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Hygrodere damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Hygrodere! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_Hygrodere); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive after hit by Hygrodere! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in BlobAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(JesterAI))] [HarmonyPatch("killPlayerAnimation")] internal class JesterAIKillPlayerAnimationPatch { public static void Postfix(int playerId) { try { Plugin.Instance.PluginLogger.LogDebug("Accessing state after Jester mauling..."); PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; if ((Object)(object)val == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); return; } Plugin.Instance.PluginLogger.LogDebug("Player was killed by Jester! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(val, AdvancedCauseOfDeath.Enemy_Jester); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in JesterAIKillPlayerAnimationPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(CaveDwellerAI))] [HarmonyPatch("killAnimation")] internal class CaveDwellerAIKillAnimationPatch { public static void Postfix(CaveDwellerAI __instance, PlayerControllerB killingPlayer) { try { Plugin.Instance.PluginLogger.LogDebug("Accessing state after Maneater mauling..."); if ((Object)(object)killingPlayer == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); return; } Plugin.Instance.PluginLogger.LogDebug("Player was killed by Maneater! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(killingPlayer, AdvancedCauseOfDeath.Enemy_Maneater); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in CaveDwellerAIKillAnimationPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(CentipedeAI))] [HarmonyPatch("DamagePlayerOnIntervals")] internal class CentipedeAIDamagePlayerOnIntervalsPatch { public static void Postfix(CentipedeAI __instance) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 try { Plugin.Instance.PluginLogger.LogDebug("Handling Snare Flea damage..."); if ((Object)(object)__instance.clingingToPlayer == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player being clung to!"); } else if (__instance.clingingToPlayer.isPlayerDead && (int)__instance.clingingToPlayer.causeOfDeath == 5) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Snare Flea! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance.clingingToPlayer, AdvancedCauseOfDeath.Enemy_SnareFlea); } else if (__instance.clingingToPlayer.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player somehow died while attacked by Snare Flea! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in CentipedeAIDamagePlayerOnIntervalsPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(PufferAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class PufferAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Spore Lizard damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Spore Lizard! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_SporeLizard); } else { Plugin.Instance.PluginLogger.LogDebug("Player is alive after being hit by Spore Lizard! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in PufferAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(CrawlerAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class CrawlerAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Thumper damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Thumper! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_Thumper); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive after being hit by Thumper! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in CrawlerAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(HauntedMaskItem))] [HarmonyPatch("FinishAttaching")] internal class HauntedMaskItemFinishAttachingPatch { public static void Postfix(HauntedMaskItem __instance) { try { Plugin.Instance.PluginLogger.LogDebug("Mask attached to someone..."); PlayerControllerB value = Traverse.Create((object)__instance).Field("previousPlayerHeldBy").GetValue<PlayerControllerB>(); if ((Object)(object)value == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (value.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by putting on a Mask! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(value, AdvancedCauseOfDeath.Enemy_MaskedPlayer_Wear); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive after putting on a Mask! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in HauntedMaskItemFinishAttachingPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(MaskedPlayerEnemy))] [HarmonyPatch("killAnimation")] internal class MaskedPlayerEnemykillAnimationPatch { public static void Postfix(MaskedPlayerEnemy __instance) { try { Plugin.Instance.PluginLogger.LogDebug("Masked Player killed someone..."); PlayerControllerB inSpecialAnimationWithPlayer = ((EnemyAI)__instance).inSpecialAnimationWithPlayer; if ((Object)(object)inSpecialAnimationWithPlayer == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); return; } Plugin.Instance.PluginLogger.LogDebug("Player was killed by Masked Player! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(inSpecialAnimationWithPlayer, AdvancedCauseOfDeath.Enemy_MaskedPlayer_Victim); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in MaskedPlayerEnemykillAnimationPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(NutcrackerEnemyAI))] [HarmonyPatch("LegKickPlayer")] internal class NutcrackerEnemyAILegKickPlayerPatch { public static void Postfix(int playerId) { try { Plugin.Instance.PluginLogger.LogDebug("Nutcracker kicked a player to death!"); PlayerControllerB playerController = StartOfRound.Instance.allPlayerScripts[playerId]; Plugin.Instance.PluginLogger.LogDebug("Player was kicked by Nutcracker! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerController, AdvancedCauseOfDeath.Enemy_Nutcracker_Kicked); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in NutcrackerEnemyAILegKickPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(ShotgunItem))] [HarmonyPatch("ShootGun")] internal class ShotgunItemShootGunPatch { public static void Postfix(ShotgunItem __instance) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 try { Plugin.Instance.PluginLogger.LogDebug("Handling shotgun shot..."); PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access local player after shotgun shot!"); } else if (localPlayerController.isPlayerDead && (int)localPlayerController.causeOfDeath == 7) { if (((GrabbableObject)__instance).isHeldByEnemy) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Shotgun (Nutcracker)! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Enemy_Nutcracker_Shot); } else { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Shotgun (Player)! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Player_Murder_Shotgun); } } else if (localPlayerController.isPlayerDead) { Plugin.Instance.PluginLogger.LogWarning("Player died while attacked by shotgun? Skipping... " + ((object)(CauseOfDeath)(ref localPlayerController.causeOfDeath)).ToString()); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in ShotgunItemShootGunPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(ButlerEnemyAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class ButlerEnemyAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Butler stab damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Butler (Stabbing)! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_Butler_Stab); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in ButlerEnemyAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(ButlerBeesEnemyAI))] [HarmonyPatch("OnCollideWithPlayer")] internal class ButlerBeesEnemyAIOnCollideWithPlayerPatch { public static void Postfix(Collider other) { try { Plugin.Instance.PluginLogger.LogDebug("Handling Mask Hornet stab damage..."); PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (component.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player was killed by Mask Hornets! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_MaskHornets); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in ButlerBeesEnemyAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(FlowerSnakeEnemy))] [HarmonyPatch("StopClingingOnLocalClient")] internal class FlowerSnakeEnemyStopClingingOnLocalClientPatch { public static void Prefix(FlowerSnakeEnemy __instance) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance.clingingToPlayer != (Object)null)) { return; } Plugin.Instance.PluginLogger.LogDebug("Tulip Snake let go of player..."); if (__instance.clingingToPlayer.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Tulip Snake let go of player because they died..."); if (__instance.clingingToPlayer.causeOfDeath == AdvancedCauseOfDeath.Gravity) { Plugin.Instance.PluginLogger.LogDebug("Tulip Snake let go of player because they died of gravity! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance.clingingToPlayer, AdvancedCauseOfDeath.Enemy_TulipSnake_Drop); } } } } [HarmonyPatch(typeof(RadMechAI))] [HarmonyPatch("CancelTorchPlayerAnimation")] internal class RadMechAICancelTorchPlayerAnimationPatch { public static void Prefix(RadMechAI __instance) { if ((Object)(object)((EnemyAI)__instance).inSpecialAnimationWithPlayer != (Object)null) { Plugin.Instance.PluginLogger.LogDebug("Player was torched to death by Old Bird, setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(((EnemyAI)__instance).inSpecialAnimationWithPlayer, AdvancedCauseOfDeath.Enemy_Old_Bird_Torch); } } } [HarmonyPatch(typeof(RadMechAI))] [HarmonyPatch("Stomp")] internal class RadMechAIStompPatch { public static void Postfix(RadMechAI __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (localPlayerController.isPlayerDead && !AdvancedDeathTracker.HasCauseOfDeath(localPlayerController) && localPlayerController.causeOfDeath == AdvancedCauseOfDeath.Crushing) { Plugin.Instance.PluginLogger.LogDebug("Player was crushed to death by Old Bird, setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Enemy_Old_Bird_Stomp); } } } [HarmonyPatch(typeof(BushWolfEnemy))] [HarmonyPatch("OnCollideWithPlayer")] internal class BushWolfOnCollideWithPlayerPatch { private const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)"; 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 BushWolfOnCollideWithPlayerPatch! Safely aborting..."); return instructions; } int num = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)") { num = i; break; } } if (num == -1) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.KillPlayer call in BushWolfOnCollideWithPlayerPatch! Safely aborting..."); return instructions; } Plugin.Instance.PluginLogger.LogDebug("Injecting patch into BushWolf.OnCollideWithPlayer..."); list.InsertRange(num + 1, list2); Plugin.Instance.PluginLogger.LogDebug("Done."); return list; } private static List<CodeInstruction>? BuildInstructionsToInsert(MethodBase method) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(BushWolfOnCollideWithPlayerPatch).GetMethod("RewriteCauseOfDeath"))); return list; } public static void RewriteCauseOfDeath() { Plugin.Instance.PluginLogger.LogDebug("Player died to Kidnapper Wolf! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Enemy_KidnapperFox); } } [HarmonyPatch(typeof(PlayerControllerB))] [HarmonyPatch("KillPlayer")] internal class PlayerControllerBKillPlayerPatch { public static void Prefix(PlayerControllerB __instance, ref CauseOfDeath causeOfDeath) { try { if (AdvancedDeathTracker.HasCauseOfDeath(__instance)) { Plugin.Instance.PluginLogger.LogDebug("Player already has a known specific cause of death! Skipping advanced processing..."); } else if (causeOfDeath == AdvancedCauseOfDeath.Other_Dropship) { Plugin.Instance.PluginLogger.LogDebug("Player died from item dropship! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Other_Dropship); causeOfDeath = (CauseOfDeath)8; } else if (causeOfDeath == AdvancedCauseOfDeath.Player_Ladder) { Plugin.Instance.PluginLogger.LogDebug("Player died from ladder! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Ladder); causeOfDeath = (CauseOfDeath)8; } else if (__instance.isSinking && (int)causeOfDeath == 5) { Plugin.Instance.PluginLogger.LogDebug("Player died of suffociation while sinking in quicksand! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Quicksand); } else if ((int)causeOfDeath == 3) { GrabbableObject currentlyHeldObjectServer = __instance.currentlyHeldObjectServer; if (!((Object)(object)currentlyHeldObjectServer != (Object)null)) { return; } GameObject gameObject = ((Component)currentlyHeldObjectServer).gameObject; if ((Object)(object)gameObject != (Object)null) { GrabbableObject component = gameObject.GetComponent<GrabbableObject>(); if ((Object)(object)component != (Object)null && component is StunGrenadeItem) { Plugin.Instance.PluginLogger.LogDebug("Player died from stun grenade explosion! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_StunGrenade); } } } else if ((int)causeOfDeath == 17) { Plugin.Instance.PluginLogger.LogDebug("Player died to Snipped! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Enemy_Barber); } else { Plugin.Instance.PluginLogger.LogDebug("Player is dying! No cause of death registered in hook..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in PlayerControllerBKillPlayerPatch.Prefix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(PlayerControllerB))] [HarmonyPatch("DamagePlayerFromOtherClientClientRpc")] internal class PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch { private const string DAMAGE_PLAYER_SIGNATURE = "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)"; 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(ExtensionLadderItem))] [HarmonyPatch("StartLadderAnimation")] internal class ExtensionLadderItemStartLadderAnimationPatch { public static void Postfix(ExtensionLadderItem __instance) { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) try { Plugin.Instance.PluginLogger.LogDebug("Extension ladder started animation! Modifying kill trigger..."); GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)gameObject == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch GameObject from ExtensionLadderItem."); return; } Transform val = gameObject.transform.Find("AnimContainer/MeshContainer/LadderMeshContainer/BaseLadder/LadderSecondPart/KillTrigger"); if ((Object)(object)val == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch KillTrigger Transform from ExtensionLadderItem."); return; } GameObject gameObject2 = ((Component)val).gameObject; if ((Object)(object)gameObject2 == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch KillTrigger GameObject from ExtensionLadderItem."); return; } KillLocalPlayer component = gameObject2.GetComponent<KillLocalPlayer>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch KillLocalPlayer from KillTrigger GameObject."); } else { component.causeOfDeath = AdvancedCauseOfDeath.Player_Ladder; } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in ExtensionLadderItemStartLadderAnimationPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(VehicleController))] [HarmonyPatch("DestroyCar")] internal class VehicleControllerDestroyCarPatch { private const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)"; 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 VehicleControllerDestroyCarPatch! Safely aborting..."); return instructions; } int num = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)") { num = i; break; } } if (num == -1) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.KillPlayer call in VehicleControllerDestroyCarPatch! Safely aborting..."); return instructions; } Plugin.Instance.PluginLogger.LogDebug("Injecting patch into VehicleController.DestroyCar..."); list.InsertRange(num, list2); Plugin.Instance.PluginLogger.LogDebug("Done."); return list; } private static List<CodeInstruction>? BuildInstructionsToInsert(MethodBase method) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(VehicleControllerDestroyCarPatch).GetMethod("RewriteCauseOfDeath"))); return list; } public static void RewriteCauseOfDeath(VehicleController vehicle) { Plugin.Instance.PluginLogger.LogDebug("Player died to Cruiser Explosion! Setting special cause of death..."); if ((Object)(object)vehicle == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not get reference to vehicle..."); AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Explode_Bystander); return; } Plugin.Instance.PluginLogger.LogDebug($"Got vehicle controller. ({vehicle.localPlayerInControl}, {vehicle.localPlayerInPassengerSeat})"); if (vehicle.localPlayerInControl) { AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Driver); return; } if (vehicle.localPlayerInPassengerSeat) { AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Passenger); return; } Plugin.Instance.PluginLogger.LogWarning("Could not get reference to local player in control or passenger seat..."); AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Explode_Bystander); } } [HarmonyPatch(typeof(VehicleController))] [HarmonyPatch("RemovePlayerControlOfVehicleClientRpc")] internal class VehicleControllerRemovePlayerControlOfVehicleClientRpcPatch { private static void Postfix(VehicleController __instance, int playerId, bool setIgnitionStarted) { Plugin.Instance.PluginLogger.LogDebug($"Removed player control of vehicle: {playerId} ({setIgnitionStarted})"); } } [HarmonyPatch(typeof(VehicleController))] [HarmonyPatch("DamagePlayerInVehicle")] internal class VehicleControllerDamagePlayerInVehiclePatch { private const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)"; private const string DAMAGE_PLAYER_SIGNATURE = "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)"; private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<CodeInstruction> list2 = BuildInstructionsToInsertKill(method); if (list2 == null) { Plugin.Instance.PluginLogger.LogError("Could not build instructions (kill) to insert in VehicleControllerDamagePlayerInVehiclePatch! Safely aborting..."); return instructions; } List<CodeInstruction> list3 = BuildInstructionsToInsertDamage(method); if (list3 == null) { Plugin.Instance.PluginLogger.LogError("Could not build instructions (damage) to insert in VehicleControllerDamagePlayerInVehiclePatch! Safely aborting..."); return instructions; } int num = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)") { num = i; } } if (num == -1) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.KillPlayer call in VehicleControllerDamagePlayerInVehiclePatch! Safely aborting..."); return instructions; } Plugin.Instance.PluginLogger.LogDebug("Injecting kill patches into VehicleController.DamagePlayer..."); list.InsertRange(num + 1, list2); Plugin.Instance.PluginLogger.LogDebug("Done."); int num2 = -1; for (int j = 0; j < list.Count; j++) { CodeInstruction val2 = list[j]; if (val2.opcode == OpCodes.Callvirt && val2.operand.ToString() == "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)") { num2 = j; } } if (num2 == -1) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.DamagePlayer call in VehicleControllerDamagePlayerInVehiclePatch! Safely aborting..."); return instructions; } Plugin.Instance.PluginLogger.LogDebug("Injecting damage patches into VehicleController.DamagePlayerInVehicle..."); list.InsertRange(num2 + 1, list3); Plugin.Instance.PluginLogger.LogDebug("Done."); Plugin.Instance.PluginLogger.LogDebug("VehicleController.DamagePlayerInVehicle patch done."); return list; } private static List<CodeInstruction>? BuildInstructionsToInsertKill(MethodBase method) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(VehicleControllerDamagePlayerInVehiclePatch).GetMethod("RewriteCauseOfDeath"))); return list; } private static List<CodeInstruction>? BuildInstructionsToInsertDamage(MethodBase method) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(VehicleControllerDamagePlayerInVehiclePatch).GetMethod("MaybeRewriteCauseOfDeath"))); return list; } public static void MaybeRewriteCauseOfDeath(VehicleController vehicle) { PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (localPlayerController.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player died from car accident damage"); RewriteCauseOfDeath(vehicle); } else { Plugin.Instance.PluginLogger.LogDebug($"Player did not die from car accident (left at ${localPlayerController.health} health)"); } } public static void RewriteCauseOfDeath(VehicleController vehicle) { Plugin.Instance.PluginLogger.LogDebug("Player died to Cruiser Explosion! Setting special cause of death..."); if ((Object)(object)vehicle == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not get reference to vehicle..."); AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Ran_Over); return; } Plugin.Instance.PluginLogger.LogDebug($"Got vehicle controller. ({vehicle.localPlayerInControl}, {vehicle.localPlayerInPassengerSeat})"); if (vehicle.localPlayerInControl) { AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Driver); return; } if (vehicle.localPlayerInPassengerSeat) { AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Passenger); return; } Plugin.Instance.PluginLogger.LogWarning("Could not get reference to local player in control or passenger seat..."); AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Ran_Over); } } [HarmonyPatch(typeof(VehicleCollisionTrigger))] [HarmonyPatch("OnTriggerEnter")] internal class VehicleCollisionTriggerOnTriggerEnterPatch { private const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)"; private const string DAMAGE_PLAYER_SIGNATURE = "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)"; private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<CodeInstruction> list2 = BuildInstructionsToInsertKill(method); if (list2 == null) { Plugin.Instance.PluginLogger.LogError("Could not build instructions (kill) to insert in VehicleCollisionTriggerOnTriggerEnterPatch! Safely aborting..."); return instructions; } List<CodeInstruction> list3 = BuildInstructionsToInsertDamage(method); if (list3 == null) { Plugin.Instance.PluginLogger.LogError("Could not build instructions (damage) to insert in VehicleCollisionTriggerOnTriggerEnterPatch! Safely aborting..."); return instructions; } int num = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)") { num = i; } } if (num == -1) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.KillPlayer call in VehicleCollisionTriggerOnTriggerEnterPatch! Safely aborting..."); return instructions; } Plugin.Instance.PluginLogger.LogDebug("Injecting patch #1 into VehicleCollisionTrigger.OnTriggerEnter..."); list.InsertRange(num + 1, list2); Plugin.Instance.PluginLogger.LogDebug("Done."); int num2 = -1; for (int j = 0; j < list.Count; j++) { CodeInstruction val2 = list[j]; if (val2.opcode == OpCodes.Callvirt && val2.operand.ToString() == "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)") { num2 = j; } } if (num2 == -1) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.DamagePlayer call in VehicleCollisionTriggerOnTriggerEnterPatch! Safely aborting..."); return instructions; } Plugin.Instance.PluginLogger.LogDebug("Injecting patch #2 into VehicleCollisionTrigger.OnTriggerEnter..."); list.InsertRange(num2 + 1, list3); Plugin.Instance.PluginLogger.LogDebug("Done."); Plugin.Instance.PluginLogger.LogDebug("Done with all VehicleCollisionTriggerOnTriggerEnterPatch patches."); return list; } private static List<CodeInstruction>? BuildInstructionsToInsertKill(MethodBase method) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(VehicleControllerDamagePlayerInVehiclePatch).GetMethod("RewriteCauseOfDeath"))); return list; } private static List<CodeInstruction>? BuildInstructionsToInsertDamage(MethodBase method) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(VehicleControllerDamagePlayerInVehiclePatch).GetMethod("MaybeRewriteCauseOfDeath"))); return list; } public static void MaybeRewriteCauseOfDeath() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0054: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (localPlayerController.isPlayerDead) { if ((int)localPlayerController.causeOfDeath == 8) { Plugin.Instance.PluginLogger.LogDebug("Player died from car accident damage"); RewriteCauseOfDeath(); } else { Plugin.Instance.PluginLogger.LogWarning($"Player was hit by a car but died of something else? {localPlayerController.causeOfDeath}"); } } else { Plugin.Instance.PluginLogger.LogDebug($"Player did not die from car accident (left at ${localPlayerController.health} health)"); } } public static void RewriteCauseOfDeath() { Plugin.Instance.PluginLogger.LogDebug("Player died to run over by Cruiser! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(GameNetworkManager.Instance.localPlayerController, AdvancedCauseOfDeath.Player_Cruiser_Ran_Over); } } [HarmonyPatch(typeof(Landmine))] [HarmonyPatch("SpawnExplosion")] internal class LandmineSpawnExplosionPatch { private const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)"; private const string DAMAGE_PLAYER_SIGNATURE = "Void DamagePlayer(Int32, Boolean, Boolean, CauseOfDeath, Int32, Boolean, UnityEngine.Vector3)"; private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<CodeInstruction> list2 = BuildInstructionsToInsertKill(method); if (list2 == null) { Plugin.Instance.PluginLogger.LogError("Could not build instructions (kill) to insert in LandmineSpawnExplosionPatch! Safely aborting..."); return instructions; } List<CodeInstruction> list3 = BuildInstructionsToInsertDamage(method); if (list3 == null) { Plugin.Instance.PluginLogger.LogError("Could not build instructions (damage) to insert in LandmineSpawnExplosionPatch! Safely aborting..."); return instructions; } int num = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32, UnityEngine.Vector3)") { num = i;