From 78379726f53e5ecdf2e7609112bee1a26e1f2f70 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 17 Dec 2023 17:25:38 -0500 Subject: [PATCH] Version 1.4.0 --- CHANGELOG.md | 12 ++ Coroner/AdvancedCauseOfDeath.cs | 83 +++++--- Coroner/LCAPI/DeathBroadcasterLCAPI.cs | 12 +- Coroner/Patch/CauseOfDeathPatch.cs | 264 ++++++++++++++++++------- Coroner/Patch/HUDManagerPatch.cs | 6 +- Coroner/PluginConfig.cs | 7 + 6 files changed, 278 insertions(+), 106 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7596f6f..e87e23f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +# 1.4.0 +## Additions +- Added custom death messages for specific types of explosions: + - Landmines + - Jetpack + - Lightning +- Added custom death message for Turrets. +- Added a `SeriousDeathMessages` config option to display only more to-the-point death messages. Defaults to `false`. +## Changed +- The death report now says "Cause of Death" instead of "Notes" when a player dies. +- Decreased log verbosity to improve performance. + # 1.3.1 ## Fixed - Fixed an issue where an exception in one of the cause-of-death patches would cause the player to not die. diff --git a/Coroner/AdvancedCauseOfDeath.cs b/Coroner/AdvancedCauseOfDeath.cs index 50a316c..a1a0b58 100644 --- a/Coroner/AdvancedCauseOfDeath.cs +++ b/Coroner/AdvancedCauseOfDeath.cs @@ -72,12 +72,12 @@ public static AdvancedCauseOfDeath GetCauseOfDeath(PlayerControllerB playerContr { if (!PlayerCauseOfDeath.ContainsKey((int)playerController.playerClientId)) { - Plugin.Instance.PluginLogger.LogInfo($"Player {playerController.playerClientId} has no custom cause of death stored! Using fallback..."); + Plugin.Instance.PluginLogger.LogDebug($"Player {playerController.playerClientId} has no custom cause of death stored! Using fallback..."); return GuessCauseOfDeath(playerController); } else { - Plugin.Instance.PluginLogger.LogInfo($"Player {playerController.playerClientId} has custom cause of death stored! {PlayerCauseOfDeath[(int)playerController.playerClientId]}"); + Plugin.Instance.PluginLogger.LogDebug($"Player {playerController.playerClientId} has custom cause of death stored! {PlayerCauseOfDeath[(int)playerController.playerClientId]}"); return PlayerCauseOfDeath[(int)playerController.playerClientId]; } } @@ -171,7 +171,7 @@ public static string StringifyCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) public static string StringifyCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath, Random random) { var result = SelectCauseOfDeath(causeOfDeath); - if (result.Length == 1) return result[0]; + if (result.Length == 1 || Plugin.Instance.PluginConfig.ShouldUseSeriousDeathMessages()) return result[0]; else return result[random.Next(result.Length)]; } @@ -179,6 +179,8 @@ public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) { if (causeOfDeath == null) return FUNNY_NOTES; + // NOTE: First cause of death in the list should be the "serious" entry. + switch (causeOfDeath) { case AdvancedCauseOfDeath.Bludgeoning: @@ -192,8 +194,8 @@ public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) }; case AdvancedCauseOfDeath.Blast: return new[] { - "Went out with a bang.", "Exploded.", + "Went out with a bang.", "Was blown to smithereens." }; case AdvancedCauseOfDeath.Strangulation: @@ -241,10 +243,8 @@ public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) }; case AdvancedCauseOfDeath.Enemy_EyelessDog: return new[] { - "Got caught using a mechanical keyboard.", - "Was eaten by an Eyeless Dog.", - "Was eaten by an Eyeless Dog.", "Was eaten by an Eyeless Dog.", + "Got caught using a mechanical keyboard.", "Wasn't quiet around an Eyeless Dog.", }; case AdvancedCauseOfDeath.Enemy_ForestGiant: @@ -258,6 +258,8 @@ public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) case AdvancedCauseOfDeath.Enemy_GhostGirl: return new[] { "Died a mysterious death.", + "Lost their mind.", + "Got a real bad headache.", "???", }; case AdvancedCauseOfDeath.Enemy_EarthLeviathan: @@ -271,12 +273,14 @@ public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) }; case AdvancedCauseOfDeath.Enemy_Jester: return new[] { + "Mauled to death by a Jester.", "Was the butt of the Jester's joke.", "Got pranked by the Jester.", "Got popped like a weasel.", }; case AdvancedCauseOfDeath.Enemy_CoilHead: return new[] { + "Mauled to death by a Coil Head.", "Got in a staring contest with a Coil Head.", "Lost a staring contest with a Coil Head.", }; @@ -288,13 +292,18 @@ public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) return new[] { "Was absorbed by a Hygrodere.", "Got lost in the sauce.", + "Had an oopsie with a Hygrodere.", }; case AdvancedCauseOfDeath.Enemy_HoarderBug: return new[] { + "Was mauled by a Hoarder Bug.", + "Was swarmed by a Hoarder Bug.", "Was hoarded by a Hoarder Bug.", + "Tried to steal from a Hoarder Bug.", }; case AdvancedCauseOfDeath.Enemy_SporeLizard: return new[] { + "Was bitten by a Spore Lizard.", "Was puffed by a Spore Lizard.", }; case AdvancedCauseOfDeath.Enemy_BunkerSpider: @@ -309,47 +318,49 @@ public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) case AdvancedCauseOfDeath.Enemy_MaskedPlayer_Wear: return new[] { - "Nobody cared who they were until they put on the Mask.", "Donned the Mask.", + "Nobody cared who they were until they put on the Mask.", }; case AdvancedCauseOfDeath.Enemy_MaskedPlayer_Victim: return new[] { - "Became a tragedy at the hands of the Mask.", "Was killed by a Masked coworker.", + "Became a tragedy at the hands of the Mask.", }; case AdvancedCauseOfDeath.Enemy_Nutcracker_Kicked: return new[] { - "Got their nuts cracked by a Nutcracker.", "Was kicked to death by a Nutcracker.", + "Got their nuts cracked by a Nutcracker.", }; case AdvancedCauseOfDeath.Enemy_Nutcracker_Shot: return new[] { - "Was at the wrong end of a 21-gun salute.", "Got shot by a Nutcracker.", + "Was at the wrong end of a 21-gun salute.", }; case AdvancedCauseOfDeath.Player_Jetpack_Gravity: return new[] { + "Fell while using a jetpack.", "Flew too close to the sun.", "Ran out of fuel.", }; case AdvancedCauseOfDeath.Player_Jetpack_Blast: return new[] { + "Blew up while using a Jetpack.", "Turned into a firework.", - "Got blown up by bad piloting.", }; case AdvancedCauseOfDeath.Player_Murder_Melee: return new[] { + "Was bludgeoned to death by a coworker.", "Was the victim of a murder.", "Got murdered.", - "Was bludgeoned to death by a coworker.", + "Got backstabbed by a coworker." }; case AdvancedCauseOfDeath.Player_Murder_Shotgun: return new[] { - // "Was the victim of a murder.", - // "Got murdered.", - // "Was shot to death by a coworker.", - // "Got one-pumped by a coworker.", + "Was shot to death by a coworker.", + "Was the victim of a murder.", + "Got murdered.", + "Got one-pumped by a coworker.", "Got 360-noscoped by a coworker.", }; case AdvancedCauseOfDeath.Player_Quicksand: @@ -357,26 +368,42 @@ public static string[] SelectCauseOfDeath(AdvancedCauseOfDeath? causeOfDeath) "Got stuck in quicksand.", "Drowned in quicksand", }; - case AdvancedCauseOfDeath.Player_DepositItemsDesk: + case AdvancedCauseOfDeath.Player_StunGrenade: + return new[] { + "Got flashbanged by a coworker.", + "Was the victim of a murder.", + }; + + case AdvancedCauseOfDeath.Other_DepositItemsDesk: + // NOTE: Since there's no performance report on Gordion this never shows. return new[] { "Received a demotion.", "Was put on disciplinary leave.", }; - case AdvancedCauseOfDeath.Player_Dropship: + case AdvancedCauseOfDeath.Other_Dropship: return new[] { + "Was crushed by the Item Dropship.", "Couldn't wait for their items.", "Got too impatient for their items.", }; - case AdvancedCauseOfDeath.Player_StunGrenade: - return new[] { - "Was the victim of a murder.", + case AdvancedCauseOfDeath.Other_Landmine: + return new [] { + "Stepped on a landmine." + }; + case AdvancedCauseOfDeath.Other_Turret: + return new [] { + "Got shot by a turret." + }; + case AdvancedCauseOfDeath.Other_Lightning: + return new [] { + "Was struck by lightning." }; - // case AdvancedCauseOfDeath.Unknown: default: return new[] { - "Most sincerely dead.", "Died somehow.", + "Most sincerely dead.", + "Expired in an inexplicable manner." }; } } @@ -433,8 +460,12 @@ enum AdvancedCauseOfDeath Player_Quicksand, Player_Murder_Melee, Player_Murder_Shotgun, - Player_DepositItemsDesk, - Player_Dropship, Player_StunGrenade, // TODO: Implement this. + + Other_Landmine, + Other_Turret, + Other_Lightning, + Other_DepositItemsDesk, + Other_Dropship, } } \ No newline at end of file diff --git a/Coroner/LCAPI/DeathBroadcasterLCAPI.cs b/Coroner/LCAPI/DeathBroadcasterLCAPI.cs index be182c2..cd53760 100644 --- a/Coroner/LCAPI/DeathBroadcasterLCAPI.cs +++ b/Coroner/LCAPI/DeathBroadcasterLCAPI.cs @@ -5,9 +5,9 @@ class DeathBroadcasterLCAPI { const string SIGNATURE_DEATH = PluginInfo.PLUGIN_GUID + ".death"; public static void Initialize() { - Plugin.Instance.PluginLogger.LogInfo("Initializing DeathBroadcaster..."); + Plugin.Instance.PluginLogger.LogDebug("Initializing DeathBroadcaster..."); if (Plugin.Instance.IsLCAPIPresent) { - Plugin.Instance.PluginLogger.LogInfo("LC_API is present! Registering signature..."); + Plugin.Instance.PluginLogger.LogDebug("LC_API is present! Registering signature..."); LC_API.ServerAPI.Networking.GetString += OnBroadcastString; } else { Plugin.Instance.PluginLogger.LogError("LC_API is not present! Why did you try to register the DeathBroadcaster?"); @@ -16,22 +16,22 @@ public static void Initialize() { static void OnBroadcastString(string data, string signature) { if (signature == SIGNATURE_DEATH) { - Plugin.Instance.PluginLogger.LogInfo("Broadcast has been received from LC_API!"); + Plugin.Instance.PluginLogger.LogDebug("Broadcast has been received from LC_API!"); string[] split = data.Split('|'); int playerId = int.Parse(split[0]); int causeOfDeathInt = int.Parse(split[1]); AdvancedCauseOfDeath causeOfDeath = (AdvancedCauseOfDeath) causeOfDeathInt; - Plugin.Instance.PluginLogger.LogInfo("Player " + playerId + " died of " + AdvancedDeathTracker.StringifyCauseOfDeath(causeOfDeath)); + Plugin.Instance.PluginLogger.LogDebug("Player " + playerId + " died of " + AdvancedDeathTracker.StringifyCauseOfDeath(causeOfDeath)); AdvancedDeathTracker.SetCauseOfDeath(playerId, causeOfDeath, false); } } public static void AttemptBroadcast(string data, string signature) { if (Plugin.Instance.IsLCAPIPresent) { - Plugin.Instance.PluginLogger.LogInfo("LC_API is present! Broadcasting..."); + Plugin.Instance.PluginLogger.LogDebug("LC_API is present! Broadcasting..."); LC_API.ServerAPI.Networking.Broadcast(data, signature); } else { - Plugin.Instance.PluginLogger.LogInfo("LC_API is not present! Skipping broadcast..."); + Plugin.Instance.PluginLogger.LogDebug("LC_API is not present! Skipping broadcast..."); } } } diff --git a/Coroner/Patch/CauseOfDeathPatch.cs b/Coroner/Patch/CauseOfDeathPatch.cs index def06df..a951366 100644 --- a/Coroner/Patch/CauseOfDeathPatch.cs +++ b/Coroner/Patch/CauseOfDeathPatch.cs @@ -1,3 +1,7 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Reflection.Emit; using GameNetcodeStuff; using HarmonyLib; using UnityEngine; @@ -18,11 +22,10 @@ public static void Prefix(PlayerControllerB __instance, ref CauseOfDeath causeOf try { // NOTE: Only called on the client of the player who died. - if ((int)causeOfDeath == AdvancedDeathTracker.PLAYER_CAUSE_OF_DEATH_DROPSHIP) { - Plugin.Instance.PluginLogger.LogInfo("Player died from item dropship! Setting special cause of death..."); - AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Dropship); + Plugin.Instance.PluginLogger.LogDebug("Player died from item dropship! Setting special cause of death..."); + AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Other_Dropship); // Now to fix the jank by adding a normal value! causeOfDeath = CauseOfDeath.Crushing; return; @@ -30,12 +33,16 @@ public static void Prefix(PlayerControllerB __instance, ref CauseOfDeath causeOf if (__instance.isSinking && causeOfDeath == CauseOfDeath.Suffocation) { - Plugin.Instance.PluginLogger.LogInfo("Player died of suffociation while sinking in quicksand! Setting special cause of death..."); + 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 (causeOfDeath == CauseOfDeath.Blast) { + // Determine what caused the blast. + // WARNING: This code is very janky and may cause mental damage to anyone who reads it. + } else { - Plugin.Instance.PluginLogger.LogInfo("Player is dying! No cause of death registered in hook..."); + Plugin.Instance.PluginLogger.LogDebug("Player is dying! No cause of death registered in hook..."); } } catch (System.Exception e) @@ -54,11 +61,11 @@ public static void Postfix(int playerID) { try { - Plugin.Instance.PluginLogger.LogInfo("Accessing state after tentacle devouring..."); + Plugin.Instance.PluginLogger.LogDebug("Accessing state after tentacle devouring..."); PlayerControllerB playerDying = StartOfRound.Instance.allPlayerScripts[playerID]; - Plugin.Instance.PluginLogger.LogInfo("Player is dying! Setting special cause of death..."); - AdvancedDeathTracker.SetCauseOfDeath(playerDying, AdvancedCauseOfDeath.Player_DepositItemsDesk); + Plugin.Instance.PluginLogger.LogDebug("Player is dying! Setting special cause of death..."); + AdvancedDeathTracker.SetCauseOfDeath(playerDying, AdvancedCauseOfDeath.Other_DepositItemsDesk); } catch (System.Exception e) { @@ -76,7 +83,7 @@ public static void Postfix(int playerId) { try { - Plugin.Instance.PluginLogger.LogInfo("Accessing state after Jester mauling..."); + Plugin.Instance.PluginLogger.LogDebug("Accessing state after Jester mauling..."); PlayerControllerB playerControllerB = StartOfRound.Instance.allPlayerScripts[playerId]; if (playerControllerB == null) @@ -85,7 +92,7 @@ public static void Postfix(int playerId) return; } - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerControllerB, AdvancedCauseOfDeath.Enemy_Jester); } catch (System.Exception e) @@ -104,7 +111,7 @@ public static void Postfix(PlayerControllerB playerScript) { try { - Plugin.Instance.PluginLogger.LogInfo("Accessing state after Sand Worm devouring..."); + Plugin.Instance.PluginLogger.LogDebug("Accessing state after Sand Worm devouring..."); if (playerScript == null) { @@ -112,7 +119,7 @@ public static void Postfix(PlayerControllerB playerScript) return; } - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerScript, AdvancedCauseOfDeath.Enemy_EarthLeviathan); } catch (System.Exception e) @@ -131,7 +138,7 @@ public static void Postfix(int playerId) { try { - Plugin.Instance.PluginLogger.LogInfo("Accessing state after Circuit Bee electrocution..."); + Plugin.Instance.PluginLogger.LogDebug("Accessing state after Circuit Bee electrocution..."); PlayerControllerB playerDying = StartOfRound.Instance.allPlayerScripts[playerId]; if (playerDying == null) @@ -142,12 +149,12 @@ public static void Postfix(int playerId) if (playerDying.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerDying, AdvancedCauseOfDeath.Enemy_CircuitBees); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -167,7 +174,7 @@ public static void Postfix(DressGirlAI __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Processing Ghost Girl player collision..."); + Plugin.Instance.PluginLogger.LogDebug("Processing Ghost Girl player collision..."); if (__instance.hauntingPlayer == null) { @@ -176,7 +183,7 @@ public static void Postfix(DressGirlAI __instance) } if (__instance.hauntingPlayer.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance.hauntingPlayer, AdvancedCauseOfDeath.Enemy_GhostGirl); } } @@ -196,7 +203,7 @@ public static void Postfix(FlowermanAI __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Accessing state after Bracken snapping neck..."); + Plugin.Instance.PluginLogger.LogDebug("Accessing state after Bracken snapping neck..."); if (__instance.inSpecialAnimationWithPlayer == null) { @@ -204,7 +211,7 @@ public static void Postfix(FlowermanAI __instance) return; } - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance.inSpecialAnimationWithPlayer, AdvancedCauseOfDeath.Enemy_Bracken); } catch (System.Exception e) @@ -223,7 +230,7 @@ public static void Postfix(PlayerControllerB playerBeingEaten) { try { - Plugin.Instance.PluginLogger.LogInfo("Accessing state after Forest Giant devouring..."); + Plugin.Instance.PluginLogger.LogDebug("Accessing state after Forest Giant devouring..."); if (playerBeingEaten == null) { @@ -231,7 +238,7 @@ public static void Postfix(PlayerControllerB playerBeingEaten) return; } - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerBeingEaten, AdvancedCauseOfDeath.Enemy_ForestGiant); } catch (System.Exception e) @@ -250,7 +257,7 @@ public static void Postfix(int playerId) { try { - Plugin.Instance.PluginLogger.LogInfo("Accessing state after dog devouring..."); + Plugin.Instance.PluginLogger.LogDebug("Accessing state after dog devouring..."); PlayerControllerB playerDying = StartOfRound.Instance.allPlayerScripts[playerId]; if (playerDying == null) @@ -259,7 +266,7 @@ public static void Postfix(int playerId) return; } - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerDying, AdvancedCauseOfDeath.Enemy_EyelessDog); } catch (System.Exception e) @@ -278,7 +285,7 @@ public static void Postfix(CentipedeAI __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling Snare Flea damage..."); + Plugin.Instance.PluginLogger.LogDebug("Handling Snare Flea damage..."); if (__instance.clingingToPlayer == null) { Plugin.Instance.PluginLogger.LogWarning("Could not access player being clung to!"); @@ -287,12 +294,12 @@ public static void Postfix(CentipedeAI __instance) if (__instance.clingingToPlayer.isPlayerDead && __instance.clingingToPlayer.causeOfDeath == CauseOfDeath.Suffocation) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + 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.LogWarning("Player somehow died while attacked by Snare Flea! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player somehow died while attacked by Snare Flea! Skipping..."); return; } else @@ -312,11 +319,11 @@ public static void Postfix(CentipedeAI __instance) [HarmonyPatch("OnCollideWithPlayer")] class BaboonBirdAIOnCollideWithPlayerPatch { - public static void Postfix(BaboonBirdAI __instance, Collider other) + public static void Postfix(Collider other) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling Baboon Hawk damage..."); + Plugin.Instance.PluginLogger.LogDebug("Handling Baboon Hawk damage..."); PlayerControllerB playerControllerB = other.gameObject.GetComponent(); if (playerControllerB == null) @@ -327,12 +334,12 @@ public static void Postfix(BaboonBirdAI __instance, Collider other) if (playerControllerB.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerControllerB, AdvancedCauseOfDeath.Enemy_BaboonHawk); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -348,11 +355,11 @@ public static void Postfix(BaboonBirdAI __instance, Collider other) [HarmonyPatch("DamagePlayerFromOtherClientClientRpc")] class PlayerControllerBDamagePlayerFromOtherClientClientRpcPatch { - public static void Postfix(PlayerControllerB __instance, int playerWhoHit) + public static void Postfix(PlayerControllerB __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling friendly fire damage..."); + Plugin.Instance.PluginLogger.LogDebug("Handling friendly fire damage..."); if (__instance == null) { Plugin.Instance.PluginLogger.LogWarning("Could not access victim after death!"); @@ -364,17 +371,17 @@ public static void Postfix(PlayerControllerB __instance, int playerWhoHit) { if (__instance.causeOfDeath == CauseOfDeath.Bludgeoning) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Melee); } else if (__instance.causeOfDeath == CauseOfDeath.Mauling) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Melee); } else if (__instance.causeOfDeath == CauseOfDeath.Gunshots) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(__instance, AdvancedCauseOfDeath.Player_Murder_Shotgun); } else @@ -384,7 +391,7 @@ public static void Postfix(PlayerControllerB __instance, int playerWhoHit) } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -400,11 +407,11 @@ public static void Postfix(PlayerControllerB __instance, int playerWhoHit) [HarmonyPatch("OnCollideWithPlayer")] class PufferAIOnCollideWithPlayerPatch { - public static void Postfix(PufferAI __instance, Collider other) + public static void Postfix(Collider other) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling Spore Lizard damage..."); + Plugin.Instance.PluginLogger.LogDebug("Handling Spore Lizard damage..."); PlayerControllerB playerControllerB = other.gameObject.GetComponent(); if (playerControllerB == null) @@ -415,12 +422,12 @@ public static void Postfix(PufferAI __instance, Collider other) if (playerControllerB.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerControllerB, AdvancedCauseOfDeath.Enemy_SporeLizard); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -436,11 +443,11 @@ public static void Postfix(PufferAI __instance, Collider other) [HarmonyPatch("OnCollideWithPlayer")] class SpringManAIOnCollideWithPlayerPatch { - public static void Postfix(PufferAI __instance, Collider other) + public static void Postfix(Collider other) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling Coil Head damage..."); + Plugin.Instance.PluginLogger.LogDebug("Handling Coil Head damage..."); PlayerControllerB playerControllerB = other.gameObject.GetComponent(); if (playerControllerB == null) @@ -451,12 +458,12 @@ public static void Postfix(PufferAI __instance, Collider other) if (playerControllerB.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerControllerB, AdvancedCauseOfDeath.Enemy_CoilHead); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -486,12 +493,12 @@ public static void Postfix(int playerKilled) if (playerDying.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerDying, AdvancedCauseOfDeath.Enemy_Hygrodere); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -511,7 +518,7 @@ public static void Postfix(Collider other) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling Hoarder Bug damage..."); + Plugin.Instance.PluginLogger.LogDebug("Handling Hoarder Bug damage..."); PlayerControllerB playerControllerB = other.gameObject.GetComponent(); if (playerControllerB == null) @@ -522,12 +529,12 @@ public static void Postfix(Collider other) if (playerControllerB.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerControllerB, AdvancedCauseOfDeath.Enemy_HoarderBug); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -543,11 +550,11 @@ public static void Postfix(Collider other) [HarmonyPatch("OnCollideWithPlayer")] class CrawlerAIOnCollideWithPlayerPatch { - public static void Postfix(CrawlerAI __instance, Collider other) + public static void Postfix(Collider other) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling Thumper damage..."); + Plugin.Instance.PluginLogger.LogDebug("Handling Thumper damage..."); PlayerControllerB playerControllerB = other.gameObject.GetComponent(); if (playerControllerB == null) @@ -558,12 +565,12 @@ public static void Postfix(CrawlerAI __instance, Collider other) if (playerControllerB.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerControllerB, AdvancedCauseOfDeath.Enemy_Thumper); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -579,11 +586,11 @@ public static void Postfix(CrawlerAI __instance, Collider other) [HarmonyPatch("OnCollideWithPlayer")] class SandSpiderAIOnCollideWithPlayerPatch { - public static void Postfix(SandSpiderAI __instance, Collider other) + public static void Postfix(Collider other) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling Bunker Spider damage..."); + Plugin.Instance.PluginLogger.LogDebug("Handling Bunker Spider damage..."); PlayerControllerB playerControllerB = other.gameObject.GetComponent(); if (playerControllerB == null) @@ -594,12 +601,12 @@ public static void Postfix(SandSpiderAI __instance, Collider other) if (playerControllerB.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerControllerB, AdvancedCauseOfDeath.Enemy_BunkerSpider); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -615,14 +622,14 @@ public static void Postfix(SandSpiderAI __instance, Collider other) [HarmonyPatch("LegKickPlayer")] class NutcrackerEnemyAILegKickPlayerPatch { - public static void Postfix(NutcrackerEnemyAI __instance, int playerId) + public static void Postfix(int playerId) { try { - Plugin.Instance.PluginLogger.LogInfo("Nutcracker kicked a player to death!"); + Plugin.Instance.PluginLogger.LogDebug("Nutcracker kicked a player to death!"); PlayerControllerB playerDying = StartOfRound.Instance.allPlayerScripts[playerId]; - Plugin.Instance.PluginLogger.LogInfo("Player is dying! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is dying! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerDying, AdvancedCauseOfDeath.Enemy_Nutcracker_Kicked); } catch (System.Exception e) @@ -637,11 +644,11 @@ public static void Postfix(NutcrackerEnemyAI __instance, int playerId) [HarmonyPatch("ShootGun")] class ShotgunItemShootGunPatch { - public static void Postfix(ShotgunItem __instance, Vector3 shotgunPosition, Vector3 shotgunForward) + public static void Postfix(ShotgunItem __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Handling shotgun shot..."); + Plugin.Instance.PluginLogger.LogDebug("Handling shotgun shot..."); PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (localPlayerController == null) @@ -654,13 +661,13 @@ public static void Postfix(ShotgunItem __instance, Vector3 shotgunPosition, Vect if (__instance.isHeldByEnemy) { // Enemy Nutcracker fired the shotgun. - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Enemy_Nutcracker_Shot); } else { // Player fired the shotgun. - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(localPlayerController, AdvancedCauseOfDeath.Player_Murder_Shotgun); } } @@ -686,7 +693,7 @@ public static void Postfix(MaskedPlayerEnemy __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Masked Player killed someone..."); + Plugin.Instance.PluginLogger.LogDebug("Masked Player killed someone..."); PlayerControllerB playerControllerB = __instance.inSpecialAnimationWithPlayer; if (playerControllerB == null) @@ -696,7 +703,7 @@ public static void Postfix(MaskedPlayerEnemy __instance) } // playerControllerB.isPlayerDead is false here but we just assume they will die here. - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(playerControllerB, AdvancedCauseOfDeath.Enemy_MaskedPlayer_Victim); } catch (System.Exception e) @@ -715,7 +722,7 @@ public static void Postfix(HauntedMaskItem __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Masked Player killed someone..."); + Plugin.Instance.PluginLogger.LogDebug("Masked Player killed someone..."); PlayerControllerB previousPlayerHeldBy = Traverse.Create(__instance).Field("previousPlayerHeldBy").GetValue(); if (previousPlayerHeldBy == null) @@ -726,12 +733,12 @@ public static void Postfix(HauntedMaskItem __instance) if (previousPlayerHeldBy.isPlayerDead) { - Plugin.Instance.PluginLogger.LogInfo("Player is now dead! Setting special cause of death..."); + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); AdvancedDeathTracker.SetCauseOfDeath(previousPlayerHeldBy, AdvancedCauseOfDeath.Enemy_MaskedPlayer_Wear); } else { - Plugin.Instance.PluginLogger.LogWarning("Player is somehow still alive! Skipping..."); + Plugin.Instance.PluginLogger.LogDebug("Player is somehow still alive! Skipping..."); return; } } @@ -751,7 +758,7 @@ public static void Postfix(ExtensionLadderItem __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Extension ladder started animation! Modifying kill trigger..."); + Plugin.Instance.PluginLogger.LogDebug("Extension ladder started animation! Modifying kill trigger..."); GameObject extensionLadderGameObject = __instance.gameObject; if (extensionLadderGameObject == null) @@ -798,7 +805,7 @@ public static void Postfix(ItemDropship __instance) { try { - Plugin.Instance.PluginLogger.LogInfo("Item dropship spawned! Modifying kill trigger..."); + Plugin.Instance.PluginLogger.LogDebug("Item dropship spawned! Modifying kill trigger..."); GameObject itemDropshipGameObject = __instance.gameObject; if (itemDropshipGameObject == null) @@ -836,4 +843,119 @@ public static void Postfix(ItemDropship __instance) } } } + + [HarmonyPatch(typeof(Turret))] + [HarmonyPatch("Update")] + public class TurretUpdatePatch + { + public static void Postfix(Turret __instance) { + if (__instance.turretMode != TurretMode.Firing) return; + + // TODO: This might conflict with other Gunshots causes of death? + + var targetPlayer = GameNetworkManager.Instance.localPlayerController; + if (targetPlayer.isPlayerDead && targetPlayer.causeOfDeath == CauseOfDeath.Gunshots) { + Plugin.Instance.PluginLogger.LogDebug("Player is now dead! Setting special cause of death..."); + AdvancedDeathTracker.SetCauseOfDeath(targetPlayer, AdvancedCauseOfDeath.Other_Turret); + } + } + } + + [HarmonyPatch(typeof(Landmine))] + [HarmonyPatch("SpawnExplosion")] + public class LandmineSpawnExplosionPatch + { + // IL_0177: callvirt instance void GameNetcodeStuff.PlayerControllerB::KillPlayer(valuetype [UnityEngine.CoreModule]UnityEngine.Vector3, bool, valuetype CauseOfDeath, int32) + const string KILL_PLAYER_SIGNATURE = "Void KillPlayer(UnityEngine.Vector3, Boolean, CauseOfDeath, Int32)"; + + static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator, MethodBase method) + { + var code = new List(instructions); + + // We'll need to modify code here. + var codeToInject = BuildInstructionsToInsert(method); + if (codeToInject == null) { + Plugin.Instance.PluginLogger.LogError("Could not build instructions to insert in LandmineSpawnExplosionPatch! Safely aborting..."); + return instructions; + } + + // Search for where PlayerControllerB.KillPlayer is called. + int insertionIndex = -1; + for (int i = 0; i < code.Count; i++) + { + CodeInstruction instruction = code[i]; + if (instruction.opcode == OpCodes.Callvirt && instruction.operand.ToString() == KILL_PLAYER_SIGNATURE) + { + insertionIndex = i; + break; + } + } + + if (insertionIndex == -1) + { + Plugin.Instance.PluginLogger.LogError("Could not find PlayerControllerB.KillPlayer call in LandmineSpawnExplosionPatch! Safely aborting..."); + return instructions; + } else { + // Moment of truth. + Plugin.Instance.PluginLogger.LogInfo("Injecting patch into Landmine.SpawnExplosion..."); + code.InsertRange(insertionIndex, codeToInject); + Plugin.Instance.PluginLogger.LogInfo("Done."); + + return code; + } + } + + static List BuildInstructionsToInsert(MethodBase method) { + var result = new List(); + + // var argumentIndex_explosionPosition = 0; + // var argumentIndex_spawnExplosionEffect = 1; + var argumentIndex_killRange = 2; + // var argumentIndex_damageRange = 3; + + IList localVars = method.GetMethodBody().LocalVariables; + LocalVariableInfo localVar_component = null; + + for (int i = 0; i < localVars.Count; i++) { + var currentLocalVar = localVars[i]; + + if (currentLocalVar.LocalType == typeof(PlayerControllerB)) { + if (localVar_component != null) { + Plugin.Instance.PluginLogger.LogError("Found multiple PlayerControllerB local variables in LandmineSpawnExplosionPatch!"); + return null; + } + localVar_component = currentLocalVar; + break; + } + } + + + // IL_017D: ldloc.s component + result.Add(new CodeInstruction(OpCodes.Ldloc_S, localVar_component.LocalIndex)); + + // IL_017F: ldarg.2 + result.Add(new CodeInstruction(OpCodes.Ldarg, argumentIndex_killRange)); + + // IL_0180: call void [Coroner]Coroner.Patch.LandmineSpawnExplosionPatch::RewriteCauseOfDeath(class GameNetcodeStuff.PlayerControllerB, float32) + result.Add(new CodeInstruction(OpCodes.Call, typeof(LandmineSpawnExplosionPatch).GetMethod(nameof(RewriteCauseOfDeath)))); + + return result; + } + + public static void RewriteCauseOfDeath(PlayerControllerB targetPlayer, float killRange) { + // This function sets different causes of death for the player based on the kill range of the explosion. + // This works because different explosion types have different kill ranges. + + AdvancedCauseOfDeath causeOfDeath = AdvancedCauseOfDeath.Blast; + if (killRange == 5.0f) { + 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); + } + } } \ No newline at end of file diff --git a/Coroner/Patch/HUDManagerPatch.cs b/Coroner/Patch/HUDManagerPatch.cs index 9a482ce..3b1b003 100644 --- a/Coroner/Patch/HUDManagerPatch.cs +++ b/Coroner/Patch/HUDManagerPatch.cs @@ -17,7 +17,7 @@ public static void Postfix(HUDManager __instance) { static Random BuildSyncedRandom(HUDManager __instance) { var seed = StartOfRound.Instance.randomMapSeed; - Plugin.Instance.PluginLogger.LogInfo("Syncing randomization to map seed: '" + seed + "'"); + Plugin.Instance.PluginLogger.LogDebug("Syncing randomization to map seed: '" + seed + "'"); return new Random(seed); } @@ -25,7 +25,7 @@ static Random BuildSyncedRandom(HUDManager __instance) { * Override the performance report to display our notes. */ static void OverridePerformanceReport(HUDManager __instance) { - Plugin.Instance.PluginLogger.LogInfo("Applying Coroner patches to player notes..."); + Plugin.Instance.PluginLogger.LogDebug("Applying Coroner patches to player notes..."); var syncedRandom = BuildSyncedRandom(__instance); @@ -42,7 +42,7 @@ static void OverridePerformanceReport(HUDManager __instance) { if (Plugin.Instance.PluginConfig.ShouldDeathReplaceNotes()) { Plugin.Instance.PluginLogger.LogInfo("[REPORT] Player " + playerIndex + " is dead! Replacing notes with Cause of Death..."); // Reset the notes. - textMesh.text = "Notes: \n"; + textMesh.text = "Cause of Death: \n"; } else { Plugin.Instance.PluginLogger.LogInfo("[REPORT] Player " + playerIndex + " is dead! Appending notes with Cause of Death..."); } diff --git a/Coroner/PluginConfig.cs b/Coroner/PluginConfig.cs index 17107b9..d39bf7e 100644 --- a/Coroner/PluginConfig.cs +++ b/Coroner/PluginConfig.cs @@ -5,6 +5,7 @@ namespace Coroner public class PluginConfig { ConfigEntry DisplayCauseOfDeath; + ConfigEntry SeriousDeathMessages; ConfigEntry DisplayFunnyNotes; ConfigEntry DeathReplacesNotes; @@ -17,6 +18,7 @@ public PluginConfig() public void BindConfig(ConfigFile _config) { DisplayCauseOfDeath = _config.Bind("General", "DisplayCauseOfDeath", true, "Display the cause of death in the player notes."); + SeriousDeathMessages = _config.Bind("General", "SeriousDeathMessages", false, "Cause of death messages are more to-the-point."); DisplayFunnyNotes = _config.Bind("General", "DisplayFunnyNotes", true, "Display a random note when the player has no notes."); DeathReplacesNotes = _config.Bind("General", "DeathReplacesNotes", true, "True to replace notes when the player dies, false to append."); } @@ -26,6 +28,11 @@ public bool ShouldDisplayCauseOfDeath() return DisplayCauseOfDeath.Value; } + public bool ShouldUseSeriousDeathMessages() + { + return SeriousDeathMessages.Value; + } + public bool ShouldDisplayFunnyNotes() { return DisplayFunnyNotes.Value;