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 Useful Asset CO v1.1.1
Coroner.dll
Decompiled 2 years agousing 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.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Coroner.LCAPI; using GameNetcodeStuff; using HarmonyLib; using LC_API.ServerAPI; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EliteMasterEric")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Rework the Performance Report with new info, including cause of death.")] [assembly: AssemblyFileVersion("1.5.0.0")] [assembly: AssemblyInformationalVersion("1.5.0+e51a33f7a42a8bdfa9720d596f52ba030032dd38")] [assembly: AssemblyProduct("Coroner")] [assembly: AssemblyTitle("Coroner")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Coroner { internal class AdvancedDeathTracker { public const int PLAYER_CAUSE_OF_DEATH_DROPSHIP = 300; private static readonly Dictionary<int, AdvancedCauseOfDeath> PlayerCauseOfDeath = new Dictionary<int, AdvancedCauseOfDeath>(); private static readonly Dictionary<int, string> PlayerNotes = new Dictionary<int, string>(); public static void ClearDeathTracker() { PlayerCauseOfDeath.Clear(); PlayerNotes.Clear(); } public static void SetCauseOfDeath(int playerIndex, AdvancedCauseOfDeath causeOfDeath, bool broadcast = true) { PlayerCauseOfDeath[playerIndex] = causeOfDeath; if (broadcast) { DeathBroadcaster.BroadcastCauseOfDeath(playerIndex, causeOfDeath); } } public static void SetCauseOfDeath(int playerIndex, CauseOfDeath causeOfDeath, bool broadcast = true) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SetCauseOfDeath(playerIndex, ConvertCauseOfDeath(causeOfDeath), broadcast); } public static void SetCauseOfDeath(PlayerControllerB playerController, CauseOfDeath causeOfDeath, bool broadcast = true) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) SetCauseOfDeath((int)playerController.playerClientId, ConvertCauseOfDeath(causeOfDeath), broadcast); } public static void SetCauseOfDeath(PlayerControllerB playerController, AdvancedCauseOfDeath causeOfDeath, bool broadcast = true) { SetCauseOfDeath((int)playerController.playerClientId, causeOfDeath, broadcast); } public static AdvancedCauseOfDeath GetCauseOfDeath(int playerIndex) { PlayerControllerB playerController = StartOfRound.Instance.allPlayerScripts[playerIndex]; return GetCauseOfDeath(playerController); } public static AdvancedCauseOfDeath GetCauseOfDeath(PlayerControllerB playerController) { if (!PlayerCauseOfDeath.ContainsKey((int)playerController.playerClientId)) { Plugin.Instance.PluginLogger.LogDebug($"Player {playerController.playerClientId} has no custom cause of death stored! Using fallback..."); return GuessCauseOfDeath(playerController); } Plugin.Instance.PluginLogger.LogDebug($"Player {playerController.playerClientId} has custom cause of death stored! {PlayerCauseOfDeath[(int)playerController.playerClientId]}"); return PlayerCauseOfDeath[(int)playerController.playerClientId]; } public static AdvancedCauseOfDeath GuessCauseOfDeath(PlayerControllerB playerController) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if (playerController.isPlayerDead) { if (IsHoldingJetpack(playerController)) { if ((int)playerController.causeOfDeath == 2) { return AdvancedCauseOfDeath.Player_Jetpack_Gravity; } if ((int)playerController.causeOfDeath == 3) { return AdvancedCauseOfDeath.Player_Jetpack_Blast; } } return ConvertCauseOfDeath(playerController.causeOfDeath); } return AdvancedCauseOfDeath.Unknown; } public static bool IsHoldingJetpack(PlayerControllerB playerController) { GrabbableObject currentlyHeldObjectServer = playerController.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer == (Object)null) { return false; } GameObject gameObject = ((Component)currentlyHeldObjectServer).gameObject; if ((Object)(object)gameObject == (Object)null) { return false; } GrabbableObject component = gameObject.GetComponent<GrabbableObject>(); if ((Object)(object)component == (Object)null) { return false; } if (component is JetpackItem) { return true; } return false; } public static AdvancedCauseOfDeath ConvertCauseOfDeath(CauseOfDeath causeOfDeath) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected I4, but got Unknown return (int)causeOfDeath switch { 0 => AdvancedCauseOfDeath.Unknown, 1 => AdvancedCauseOfDeath.Bludgeoning, 2 => AdvancedCauseOfDeath.Gravity, 3 => AdvancedCauseOfDeath.Blast, 4 => AdvancedCauseOfDeath.Strangulation, 5 => AdvancedCauseOfDeath.Suffocation, 6 => AdvancedCauseOfDeath.Mauling, 7 => AdvancedCauseOfDeath.Gunshots, 8 => AdvancedCauseOfDeath.Crushing, 9 => AdvancedCauseOfDeath.Drowning, 10 => AdvancedCauseOfDeath.Abandoned, 11 => AdvancedCauseOfDeath.Electrocution, _ => AdvancedCauseOfDeath.Unknown, }; } public static string StringifyCauseOfDeath(CauseOfDeath causeOfDeath) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return StringifyCauseOfDeath(ConvertCauseOfDeath(causeOfDeath), Plugin.RANDOM); } public static string StringifyCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) { return StringifyCauseOfDeath(causeOfDeath, Plugin.RANDOM); } public static string StringifyCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath, Random random) { string[] array = SelectCauseOfDeath(causeOfDeath); if (array.Length > 1 && (!causeOfDeath.HasValue || !Plugin.Instance.PluginConfig.ShouldUseSeriousDeathMessages())) { return array[random.Next(array.Length)]; } return array[0]; } public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) { if (!causeOfDeath.HasValue) { return LanguageHandler.GetValuesByTag("FunnyNote"); } return causeOfDeath switch { AdvancedCauseOfDeath.Bludgeoning => LanguageHandler.GetValuesByTag("DeathBludgeoning"), AdvancedCauseOfDeath.Gravity => LanguageHandler.GetValuesByTag("DeathGravity"), AdvancedCauseOfDeath.Blast => LanguageHandler.GetValuesByTag("DeathBlast"), AdvancedCauseOfDeath.Strangulation => LanguageHandler.GetValuesByTag("DeathStrangulation"), AdvancedCauseOfDeath.Suffocation => LanguageHandler.GetValuesByTag("DeathSuffocation"), AdvancedCauseOfDeath.Mauling => LanguageHandler.GetValuesByTag("DeathMauling"), AdvancedCauseOfDeath.Gunshots => LanguageHandler.GetValuesByTag("DeathGunshots"), AdvancedCauseOfDeath.Crushing => LanguageHandler.GetValuesByTag("DeathCrushing"), AdvancedCauseOfDeath.Drowning => LanguageHandler.GetValuesByTag("DeathDrowning"), AdvancedCauseOfDeath.Abandoned => LanguageHandler.GetValuesByTag("DeathAbandoned"), AdvancedCauseOfDeath.Electrocution => LanguageHandler.GetValuesByTag("DeathElectrocution"), AdvancedCauseOfDeath.Kicking => LanguageHandler.GetValuesByTag("DeathKicking"), AdvancedCauseOfDeath.Enemy_Bracken => LanguageHandler.GetValuesByTag("DeathEnemyBracken"), AdvancedCauseOfDeath.Enemy_EyelessDog => LanguageHandler.GetValuesByTag("DeathEnemyEyelessDog"), AdvancedCauseOfDeath.Enemy_ForestGiant => LanguageHandler.GetValuesByTag("DeathEnemyForestGiant"), AdvancedCauseOfDeath.Enemy_CircuitBees => LanguageHandler.GetValuesByTag("DeathEnemyCircuitBees"), AdvancedCauseOfDeath.Enemy_GhostGirl => LanguageHandler.GetValuesByTag("DeathEnemyGhostGirl"), AdvancedCauseOfDeath.Enemy_EarthLeviathan => LanguageHandler.GetValuesByTag("DeathEnemyEarthLeviathan"), AdvancedCauseOfDeath.Enemy_BaboonHawk => LanguageHandler.GetValuesByTag("DeathEnemyBaboonHawk"), AdvancedCauseOfDeath.Enemy_Jester => LanguageHandler.GetValuesByTag("DeathEnemyJester"), AdvancedCauseOfDeath.Enemy_CoilHead => LanguageHandler.GetValuesByTag("DeathEnemyCoilHead"), AdvancedCauseOfDeath.Enemy_SnareFlea => LanguageHandler.GetValuesByTag("DeathEnemySnareFlea"), AdvancedCauseOfDeath.Enemy_Hygrodere => LanguageHandler.GetValuesByTag("DeathEnemyHygrodere"), AdvancedCauseOfDeath.Enemy_HoarderBug => LanguageHandler.GetValuesByTag("DeathEnemyHoarderBug"), AdvancedCauseOfDeath.Enemy_SporeLizard => LanguageHandler.GetValuesByTag("DeathEnemySporeLizard"), AdvancedCauseOfDeath.Enemy_BunkerSpider => LanguageHandler.GetValuesByTag("DeathEnemyBunkerSpider"), AdvancedCauseOfDeath.Enemy_Thumper => LanguageHandler.GetValuesByTag("DeathEnemyThumper"), AdvancedCauseOfDeath.Enemy_MaskedPlayer_Wear => LanguageHandler.GetValuesByTag("DeathEnemyMaskedPlayerWear"), AdvancedCauseOfDeath.Enemy_MaskedPlayer_Victim => LanguageHandler.GetValuesByTag("DeathEnemyMaskedPlayerVictim"), AdvancedCauseOfDeath.Enemy_Nutcracker_Kicked => LanguageHandler.GetValuesByTag("DeathEnemyNutcrackerKicked"), AdvancedCauseOfDeath.Enemy_Nutcracker_Shot => LanguageHandler.GetValuesByTag("DeathEnemyNutcrackerShot"), AdvancedCauseOfDeath.Player_Jetpack_Gravity => LanguageHandler.GetValuesByTag("DeathPlayerJetpackGravity"), AdvancedCauseOfDeath.Player_Jetpack_Blast => LanguageHandler.GetValuesByTag("DeathPlayerJetpackBlast"), AdvancedCauseOfDeath.Player_Murder_Melee => LanguageHandler.GetValuesByTag("DeathPlayerMurderMelee"), AdvancedCauseOfDeath.Player_Murder_Shotgun => LanguageHandler.GetValuesByTag("DeathPlayerMurderShotgun"), AdvancedCauseOfDeath.Player_Quicksand => LanguageHandler.GetValuesByTag("DeathPlayerQuicksand"), AdvancedCauseOfDeath.Player_StunGrenade => LanguageHandler.GetValuesByTag("DeathPlayerStunGrenade"), AdvancedCauseOfDeath.Other_DepositItemsDesk => LanguageHandler.GetValuesByTag("DeathOtherDepositItemsDesk"), AdvancedCauseOfDeath.Other_Dropship => LanguageHandler.GetValuesByTag("DeathOtherItemDropship"), AdvancedCauseOfDeath.Other_Landmine => LanguageHandler.GetValuesByTag("DeathOtherLandmine"), AdvancedCauseOfDeath.Other_Turret => LanguageHandler.GetValuesByTag("DeathOtherTurret"), AdvancedCauseOfDeath.Other_Lightning => LanguageHandler.GetValuesByTag("DeathOtherLightning"), _ => LanguageHandler.GetValuesByTag("DeathUnknown"), }; } internal static void SetCauseOfDeath(PlayerControllerB playerControllerB, object enemy_BaboonHawk) { throw new NotImplementedException(); } } internal enum AdvancedCauseOfDeath { Unknown, Bludgeoning, Gravity, Blast, Strangulation, Suffocation, Mauling, Gunshots, Crushing, Drowning, Abandoned, Electrocution, Kicking, Enemy_BaboonHawk, Enemy_Bracken, Enemy_CircuitBees, Enemy_CoilHead, Enemy_EarthLeviathan, Enemy_EyelessDog, Enemy_ForestGiant, Enemy_GhostGirl, Enemy_Hygrodere, Enemy_Jester, Enemy_SnareFlea, Enemy_SporeLizard, Enemy_HoarderBug, Enemy_Thumper, Enemy_BunkerSpider, Enemy_MaskedPlayer_Wear, Enemy_MaskedPlayer_Victim, Enemy_Nutcracker_Kicked, Enemy_Nutcracker_Shot, Player_Jetpack_Gravity, Player_Jetpack_Blast, Player_Quicksand, Player_Murder_Melee, Player_Murder_Shotgun, Player_StunGrenade, Other_Landmine, Other_Turret, Other_Lightning, Other_DepositItemsDesk, Other_Dropship } internal class DeathBroadcaster { private const string SIGNATURE_DEATH = "com.elitemastereric.coroner.death"; public static void Initialize() { if (Plugin.Instance.IsLCAPIPresent) { DeathBroadcasterLCAPI.Initialize(); } else { Plugin.Instance.PluginLogger.LogInfo("LC_API is not present! Skipping registration..."); } } public static void BroadcastCauseOfDeath(int playerId, AdvancedCauseOfDeath causeOfDeath) { AttemptBroadcast(BuildDataCauseOfDeath(playerId, causeOfDeath), "com.elitemastereric.coroner.death"); } private static string BuildDataCauseOfDeath(int playerId, AdvancedCauseOfDeath causeOfDeath) { string text = playerId.ToString(); int num = (int)causeOfDeath; return text + "|" + num; } private static void AttemptBroadcast(string data, string signature) { if (Plugin.Instance.IsLCAPIPresent) { DeathBroadcasterLCAPI.AttemptBroadcast(data, signature); } else { Plugin.Instance.PluginLogger.LogInfo("LC_API is not present! Skipping broadcast..."); } } } internal class LanguageHandler { public const string DEFAULT_LANGUAGE = "en"; public static readonly string[] AVAILABLE_LANGUAGES = new string[3] { "en", "ru", "nl" }; 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_ENEMY_BRACKEN = "DeathEnemyBracken"; public const string TAG_DEATH_ENEMY_EYELESS_DOG = "DeathEnemyEyelessDog"; public const string TAG_DEATH_ENEMY_FOREST_GIANT = "DeathEnemyForestGiant"; public const string TAG_DEATH_ENEMY_CIRCUIT_BEES = "DeathEnemyCircuitBees"; public const string TAG_DEATH_ENEMY_GHOST_GIRL = "DeathEnemyGhostGirl"; public const string TAG_DEATH_ENEMY_EARTH_LEVIATHAN = "DeathEnemyEarthLeviathan"; public const string TAG_DEATH_ENEMY_BABOON_HAWK = "DeathEnemyBaboonHawk"; public const string TAG_DEATH_ENEMY_JESTER = "DeathEnemyJester"; public const string TAG_DEATH_ENEMY_COILHEAD = "DeathEnemyCoilHead"; public const string TAG_DEATH_ENEMY_SNARE_FLEA = "DeathEnemySnareFlea"; public const string TAG_DEATH_ENEMY_HYGRODERE = "DeathEnemyHygrodere"; public const string TAG_DEATH_ENEMY_HOARDER_BUG = "DeathEnemyHoarderBug"; public const string TAG_DEATH_ENEMY_SPORE_LIZARD = "DeathEnemySporeLizard"; public const string TAG_DEATH_ENEMY_BUNKER_SPIDER = "DeathEnemyBunkerSpider"; public const string TAG_DEATH_ENEMY_THUMPER = "DeathEnemyThumper"; 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_PLAYER_JETPACK_GRAVITY = "DeathPlayerJetpackGravity"; public const string TAG_DEATH_PLAYER_JETPACK_BLAST = "DeathPlayerJetpackBlast"; public const string TAG_DEATH_PLAYER_MURDER_MELEE = "DeathPlayerMurderMelee"; 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_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_UNKNOWN = "DeathUnknown"; private static XDocument languageData; public static void Initialize() { Plugin.Instance.PluginLogger.LogInfo("Coroner Language Support: " + Plugin.Instance.PluginConfig.GetSelectedLanguage()); ValidateLanguage(Plugin.Instance.PluginConfig.GetSelectedLanguage()); LoadLanguageData(Plugin.Instance.PluginConfig.GetSelectedLanguage()); } private static void ValidateLanguage(string languageCode) { if (!AVAILABLE_LANGUAGES.Contains(languageCode)) { Plugin.Instance.PluginLogger.LogWarning("Coroner Unknown language code: " + languageCode); Plugin.Instance.PluginLogger.LogWarning("Coroner There may be issues loading language data."); } } private static void LoadLanguageData(string languageCode) { try { languageData = XDocument.Load(Plugin.AssemblyDirectory + "/Strings_" + languageCode + ".xml"); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Coroner Error loading language data: " + ex.Message); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); if (languageCode != "en") { LoadLanguageData("en"); } } } public static string GetLanguageList() { return "(" + string.Join(", ", AVAILABLE_LANGUAGES) + ")"; } public static string GetValueByTag(string tag) { return languageData.Descendants(tag).FirstOrDefault()?.Attribute("text")?.Value; } public static string[] GetValuesByTag(string tag) { IEnumerable<XElement> source = languageData.Descendants(tag); IEnumerable<string> source2 = source.Select((XElement item) => item.Attribute("text")?.Value); IEnumerable<string> source3 = source2.Where((string item) => item != null); return source3.ToArray(); } } 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 = "1.5.0"; public const string PLUGIN_GUID = "com.elitemastereric.coroner"; } [BepInPlugin("com.elitemastereric.coroner", "Coroner", "1.5.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public static readonly Random RANDOM = new Random(); public PluginLogger PluginLogger; public PluginConfig PluginConfig; public bool IsLCAPIPresent = false; 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Instance = this; PluginLogger = new PluginLogger(((BaseUnityPlugin)this).Logger, (LogLevel)16); Harmony val = new Harmony("com.elitemastereric.coroner"); val.PatchAll(); PluginLogger.LogInfo("Plugin Coroner (com.elitemastereric.coroner) is loaded!"); LoadConfig(); LanguageHandler.Initialize(); QueryLCAPI(); DeathBroadcaster.Initialize(); } private void QueryLCAPI() { PluginLogger.LogInfo("Checking for LC_API..."); if (Chainloader.PluginInfos.ContainsKey("LC_API")) { Chainloader.PluginInfos.TryGetValue("LC_API", out var value); if (value == null) { PluginLogger.LogError("Detected LC_API, but could not get plugin info!"); IsLCAPIPresent = false; } else { PluginLogger.LogInfo("LCAPI is present! " + value.Metadata.GUID + ":" + value.Metadata.Version); IsLCAPIPresent = true; } } else { PluginLogger.LogInfo("LCAPI is not present."); IsLCAPIPresent = false; } } private void LoadConfig() { PluginConfig = new PluginConfig(); PluginConfig.BindConfig(((BaseUnityPlugin)this).Config); } } public class PluginLogger { private ManualLogSource manualLogSource; private LogLevel logLevel; public PluginLogger(ManualLogSource manualLogSource, LogLevel logLevel = 16) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) this.manualLogSource = manualLogSource; this.logLevel = logLevel; } public void LogFatal(object data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)logLevel >= 1) { manualLogSource.LogFatal(data); } } public void LogError(object data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)logLevel >= 2) { manualLogSource.LogError(data); } } public void LogWarning(object data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)logLevel >= 4) { manualLogSource.LogWarning(data); } } public void LogMessage(object data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)logLevel >= 8) { manualLogSource.LogMessage(data); } } public void LogInfo(object data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if ((int)logLevel >= 16) { manualLogSource.LogInfo(data); } } public void LogDebug(object data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if ((int)logLevel >= 32) { manualLogSource.LogDebug(data); } } } public class PluginConfig { private ConfigEntry<bool> DisplayCauseOfDeath; private ConfigEntry<bool> SeriousDeathMessages; private ConfigEntry<bool> DisplayFunnyNotes; private ConfigEntry<bool> DeathReplacesNotes; private ConfigEntry<string> LanguagePicker; 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", "Select a language to use " + LanguageHandler.GetLanguageList()); } public bool ShouldDisplayCauseOfDeath() { return DisplayCauseOfDeath.Value; } public bool ShouldUseSeriousDeathMessages() { return SeriousDeathMessages.Value; } public bool ShouldDisplayFunnyNotes() { return DisplayFunnyNotes.Value; } public bool ShouldDeathReplaceNotes() { return DeathReplacesNotes.Value; } public string GetSelectedLanguage() { return LanguagePicker.Value; } } } namespace Coroner.Patch { [HarmonyPatch(typeof(PlayerControllerB))] [HarmonyPatch("KillPlayer")] internal class PlayerControllerBKillPlayerPatch { public static void Prefix(PlayerControllerB __instance, ref CauseOfDeath causeOfDeath) { try { if ((int)causeOfDeath == 300) { Plugin.Instance.PluginLogger.LogDebug("Player died from item dropship! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Other_Dropship); causeOfDeath = (CauseOfDeath)8; } else if (__instance.isSinking && (int)causeOfDeath == 5) { Plugin.Instance.PluginLogger.LogDebug("Player died of suffociation while sinking in quicksand! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Quicksand); } else if ((int)causeOfDeath != 3) { Plugin.Instance.PluginLogger.LogDebug("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(DepositItemsDesk))] [HarmonyPatch("AnimationGrabPlayer")] internal class DepositItemsDeskAnimationGrabPlayerPatch { public static void Postfix(int playerID) { try { Plugin.Instance.PluginLogger.LogDebug("Accessing state after tentacle devouring..."); PlayerControllerB playerController = StartOfRound.Instance.allPlayerScripts[playerID]; Plugin.Instance.PluginLogger.LogDebug("Player is dying! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerController, AdvancedCauseOfDeath.Other_DepositItemsDesk); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in DepositItemsDeskAnimationGrabPlayerPatch.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 is now dead! 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(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 is now dead! 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(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 is now dead! 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(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 is now dead! 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(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 is now dead! 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(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 is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerBeingEaten, AdvancedCauseOfDeath.Enemy_ForestGiant); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in ForestGiantAIEatPlayerAnimationPatch.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 is now dead! 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(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 is now dead! 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(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(PlayerControllerB))] [HarmonyPatch("DamagePlayerFromOtherClientClientRpc")] internal class PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch { public static void Postfix(PlayerControllerB __instance) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Invalid comparison between Unknown and I4 //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Invalid comparison between Unknown and I4 try { Plugin.Instance.PluginLogger.LogDebug("Handling friendly fire damage..."); if ((Object)(object)__instance == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access victim after death!"); } else if (__instance.isPlayerDead) { if ((int)__instance.causeOfDeath == 1) { Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Melee); } else if ((int)__instance.causeOfDeath == 6) { Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Melee); } else if ((int)__instance.causeOfDeath == 7) { Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Shotgun); } else { Plugin.Instance.PluginLogger.LogWarning("Player was killed by someone else but we don't know how! " + ((object)(CauseOfDeath)(ref __instance.causeOfDeath)).ToString()); } } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch.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 is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_SporeLizard); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in PufferAIOnCollideWithPlayerPatch.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 is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_CoilHead); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in SpringManAIOnCollideWithPlayerPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(BlobAI))] [HarmonyPatch("SlimeKillPlayerEffectServerRpc")] internal class BlobAISlimeKillPlayerEffectServerRpcPatch { public static void Postfix(int playerKilled) { try { PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerKilled]; if ((Object)(object)val == (Object)null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player after death!"); } else if (val.isPlayerDead) { Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(val, AdvancedCauseOfDeath.Enemy_Hygrodere); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in BlobAISlimeKillPlayerEffectServerRpcPatch.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 is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_HoarderBug); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in HoarderBugAIOnCollideWithPlayerPatch.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 is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_Thumper); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in CrawlerAIOnCollideWithPlayerPatch.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 is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(component, AdvancedCauseOfDeath.Enemy_BunkerSpider); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in SandSpiderAIOnCollideWithPlayerPatch.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 is dying! 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 is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Enemy_Nutcracker_Shot); } else { Plugin.Instance.PluginLogger.LogDebug("Player is now dead! 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(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 is now dead! 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(HauntedMaskItem))] [HarmonyPatch("FinishAttaching")] internal class HauntedMaskItemFinishAttachingPatch { public static void Postfix(HauntedMaskItem __instance) { try { Plugin.Instance.PluginLogger.LogDebug("Masked Player killed 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 is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(value, AdvancedCauseOfDeath.Enemy_MaskedPlayer_Wear); } else { Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); } } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in HauntedMaskItemFinishAttachingPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(ExtensionLadderItem))] [HarmonyPatch("StartLadderAnimation")] internal class ExtensionLadderItemStartLadderAnimationPatch { public static void Postfix(ExtensionLadderItem __instance) { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) try { Plugin.Instance.PluginLogger.LogDebug("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."); } 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."); } GameObject gameObject2 = ((Component)val).gameObject; if ((Object)(object)gameObject2 == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch KillTrigger GameObject from ExtensionLadderItem."); } KillLocalPlayer component = gameObject2.GetComponent<KillLocalPlayer>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch KillLocalPlayer from KillTrigger GameObject."); } component.causeOfDeath = (CauseOfDeath)8; } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in ExtensionLadderItemStartLadderAnimationPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(ItemDropship))] [HarmonyPatch("Start")] internal class ItemDropshipStartPatch { public static void Postfix(ItemDropship __instance) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) try { Plugin.Instance.PluginLogger.LogDebug("Item dropship spawned! Modifying kill trigger..."); GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)gameObject == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch GameObject from ItemDropship."); } Transform val = gameObject.transform.Find("ItemShip/KillTrigger"); if ((Object)(object)val == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch KillTrigger Transform from ItemDropship."); } GameObject gameObject2 = ((Component)val).gameObject; if ((Object)(object)gameObject2 == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch KillTrigger GameObject from ItemDropship."); } KillLocalPlayer component = gameObject2.GetComponent<KillLocalPlayer>(); if ((Object)(object)component == (Object)null) { Plugin.Instance.PluginLogger.LogError("Could not fetch KillLocalPlayer from KillTrigger GameObject."); } component.causeOfDeath = (CauseOfDeath)300; } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in ItemDropshipStartPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } } [HarmonyPatch(typeof(Turret))] [HarmonyPatch("Update")] public class TurretUpdatePatch { public static void Postfix(Turret __instance) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 if ((int)__instance.turretMode == 2) { PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (localPlayerController.isPlayerDead && (int)localPlayerController.causeOfDeath == 7) { Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Other_Turret); } } } } [HarmonyPatch(typeof(Landmine))] [HarmonyPatch("SpawnExplosion")] public class LandmineSpawnExplosionPatch { private const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32)"; private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator, MethodBase method) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); List<CodeInstruction> list2 = BuildInstructionsToInsert(method); if (list2 == null) { Plugin.Instance.PluginLogger.LogError("Could not build instructions to insert in LandmineSpawnExplosionPatch! Safely aborting..."); return instructions; } int num = -1; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (val.opcode == OpCodes.Callvirt && val.operand.ToString() == "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32)") { num = i; break; } } if (num == -1) { Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.KillPlayer call in LandmineSpawnExplosionPatch! Safely aborting..."); return instructions; } Plugin.Instance.PluginLogger.LogInfo("Injecting patch into Landmine.SpawnExplosion..."); list.InsertRange(num, list2); Plugin.Instance.PluginLogger.LogInfo("Done."); return list; } private static List<CodeInstruction> BuildInstructionsToInsert(MethodBase method) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(); int num = 2; IList<LocalVariableInfo> localVariables = method.GetMethodBody().LocalVariables; LocalVariableInfo localVariableInfo = null; for (int i = 0; i < localVariables.Count; i++) { LocalVariableInfo localVariableInfo2 = localVariables[i]; if (localVariableInfo2.LocalType == typeof(PlayerControllerB)) { if (localVariableInfo != null) { Plugin.Instance.PluginLogger.LogError("Found multiple PlayerControllerB local variables in LandmineSpawnExplosionPatch!"); return null; } localVariableInfo = localVariableInfo2; break; } } list.Add(new CodeInstruction(OpCodes.Ldloc_S, (object)localVariableInfo.LocalIndex)); list.Add(new CodeInstruction(OpCodes.Ldarg, (object)num)); list.Add(new CodeInstruction(OpCodes.Call, (object)typeof(LandmineSpawnExplosionPatch).GetMethod("RewriteCauseOfDeath"))); return list; } public static void RewriteCauseOfDeath(PlayerControllerB targetPlayer, float killRange) { AdvancedCauseOfDeath causeOfDeath = AdvancedCauseOfDeath.Blast; if (killRange == 5f) { causeOfDeath = AdvancedCauseOfDeath.Player_Jetpack_Blast; } else if (killRange == 5.7f) { causeOfDeath = AdvancedCauseOfDeath.Other_Landmine; } else if (killRange == 2.4f) { causeOfDeath = AdvancedCauseOfDeath.Other_Lightning; } AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, causeOfDeath); } } [HarmonyPatch(typeof(HUDManager))] [HarmonyPatch("FillEndGameStats")] internal class HUDManagerFillEndGameStatsPatch { private const string EMPTY_NOTES = "Notes: \n"; public static void Postfix(HUDManager __instance) { try { OverridePerformanceReport(__instance); } catch (Exception ex) { Plugin.Instance.PluginLogger.LogError("Error in HUDManagerFillEndGameStatsPatch.Postfix: " + ex); Plugin.Instance.PluginLogger.LogError(ex.StackTrace); } } private static Random BuildSyncedRandom() { int randomMapSeed = StartOfRound.Instance.randomMapSeed; Plugin.Instance.PluginLogger.LogDebug("Syncing randomization to map seed: '" + randomMapSeed + "'"); return new Random(randomMapSeed); } private static void OverridePerformanceReport(HUDManager __instance) { Plugin.Instance.PluginLogger.LogDebug("Applying Coroner patches to player notes..."); Random random = BuildSyncedRandom(); for (int i = 0; i < __instance.statsUIElements.playerNotesText.Length; i++) { PlayerControllerB val = __instance.playersManager.allPlayerScripts[i]; if (!val.disconnectedMidGame && !val.isPlayerDead && !val.isPlayerControlled) { Plugin.Instance.PluginLogger.LogInfo("Player " + i + " is not controlled by a player. Skipping..."); continue; } TextMeshProUGUI val2 = __instance.statsUIElements.playerNotesText[i]; if (val.isPlayerDead) { if (Plugin.Instance.PluginConfig.ShouldDisplayCauseOfDeath()) { if (Plugin.Instance.PluginConfig.ShouldDeathReplaceNotes()) { Plugin.Instance.PluginLogger.LogInfo("[REPORT] Player " + i + " is dead! Replacing notes with Cause of Death..."); ((TMP_Text)val2).text = LanguageHandler.GetValueByTag("UICauseOfDeath") + "\n"; } else { Plugin.Instance.PluginLogger.LogInfo("[REPORT] Player " + i + " is dead! Appending notes with Cause of Death..."); } AdvancedCauseOfDeath causeOfDeath = AdvancedDeathTracker.GetCauseOfDeath(val); ((TMP_Text)val2).text = ((TMP_Text)val2).text + "* " + AdvancedDeathTracker.StringifyCauseOfDeath(causeOfDeath, random) + "\n"; } else { Plugin.Instance.PluginLogger.LogInfo("[REPORT] Player " + i + " is dead, but Config says leave it be..."); } } else if (((TMP_Text)val2).text == "Notes: \n") { if (Plugin.Instance.PluginConfig.ShouldDisplayFunnyNotes()) { Plugin.Instance.PluginLogger.LogInfo("[REPORT] Player " + i + " has no notes! Injecting something funny..."); ((TMP_Text)val2).text = LanguageHandler.GetValueByTag("UINotes") + "\n"; ((TMP_Text)val2).text = ((TMP_Text)val2).text + "* " + AdvancedDeathTracker.StringifyCauseOfDeath(null, random) + "\n"; } else { Plugin.Instance.PluginLogger.LogInfo("[REPORT] Player " + i + " has no notes, but Config says leave it be..."); } } else { Plugin.Instance.PluginLogger.LogInfo("[REPORT] Player " + i + " has notes, don't override them..."); } } AdvancedDeathTracker.ClearDeathTracker(); } } } namespace Coroner.LCAPI { internal class DeathBroadcasterLCAPI { private const string SIGNATURE_DEATH = "com.elitemastereric.coroner.death"; public static void Initialize() { Plugin.Instance.PluginLogger.LogDebug("Initializing DeathBroadcaster..."); if (Plugin.Instance.IsLCAPIPresent) { Plugin.Instance.PluginLogger.LogDebug("LC_API is present! Registering signature..."); Networking.GetString = (Action<string, string>)Delegate.Combine(Networking.GetString, new Action<string, string>(OnBroadcastString)); } else { Plugin.Instance.PluginLogger.LogError("LC_API is not present! Why did you try to register the DeathBroadcaster?"); } } private static void OnBroadcastString(string data, string signature) { if (signature == "com.elitemastereric.coroner.death") { Plugin.Instance.PluginLogger.LogDebug("Broadcast has been received from LC_API!"); string[] array = data.Split('|'); int playerIndex = int.Parse(array[0]); int num = int.Parse(array[1]); AdvancedCauseOfDeath advancedCauseOfDeath = (AdvancedCauseOfDeath)num; Plugin.Instance.PluginLogger.LogDebug("Player " + playerIndex + " died of " + AdvancedDeathTracker.StringifyCauseOfDeath((AdvancedCauseOfDeath?)advancedCauseOfDeath)); AdvancedDeathTracker.SetCauseOfDeath(playerIndex, advancedCauseOfDeath, broadcast: false); } } public static void AttemptBroadcast(string data, string signature) { if (Plugin.Instance.IsLCAPIPresent) { Plugin.Instance.PluginLogger.LogDebug("LC_API is present! Broadcasting..."); Networking.Broadcast(data, signature); } else { Plugin.Instance.PluginLogger.LogDebug("LC_API is not present! Skipping broadcast..."); } } } }