using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using Coroner; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("KilledByAFake")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+04bce0e8de24626ef291cfe421c154d3821978f7")] [assembly: AssemblyProduct("KilledByAFake")] [assembly: AssemblyTitle("KilledByAFake")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 KilledByAFake { [BepInPlugin("com.ztm.killedbyafake", "KilledByAFake", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.ztm.killedbyafake"; public const string PluginName = "KilledByAFake"; public const string PluginVersion = "1.0.1"; internal static ManualLogSource Log; internal static readonly Dictionary FakeNames = new Dictionary(); private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; new Harmony("com.ztm.killedbyafake").PatchAll(Assembly.GetExecutingAssembly()); Log.LogInfo((object)"KilledByAFake 1.0.1 loaded. Masked kills will now snitch on their disguise."); } } [HarmonyPatch(typeof(MaskedPlayerEnemy), "FinishKillAnimation")] internal static class MaskedFinishKillAnimationPatch { [HarmonyPostfix] [HarmonyAfter(new string[] { "com.elitemastereric.coroner" })] private static void Postfix(MaskedPlayerEnemy __instance, bool killedPlayer) { try { if (!killedPlayer) { return; } PlayerControllerB inSpecialAnimationWithPlayer = ((EnemyAI)__instance).inSpecialAnimationWithPlayer; if (!((Object)(object)inSpecialAnimationWithPlayer == (Object)null)) { PlayerControllerB mimickedPlayer = GetMimickedPlayer(__instance); if (!((Object)(object)mimickedPlayer == (Object)null)) { Plugin.FakeNames[(int)inSpecialAnimationWithPlayer.playerClientId] = mimickedPlayer.playerUsername; Plugin.Log.LogDebug((object)("Masked imitating '" + mimickedPlayer.playerUsername + "' killed '" + inSpecialAnimationWithPlayer.playerUsername + "'.")); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedFinishKillAnimationPatch: {arg}"); } } private static PlayerControllerB GetMimickedPlayer(MaskedPlayerEnemy masked) { Component[] components = ((Component)masked).GetComponents(); foreach (Component val in components) { if (!((Object)(object)val == (Object)null) && !(((object)val).GetType().Name != "MimicPlayer")) { object? obj = ((object)val).GetType().GetProperty("MimickingPlayer")?.GetValue(val); PlayerControllerB val2 = (PlayerControllerB)((obj is PlayerControllerB) ? obj : null); if (val2 != null && (Object)(object)val2 != (Object)null) { return val2; } } } return masked.mimickingPlayer; } } [HarmonyPatch(typeof(HUDManager), "FillEndGameStats")] internal static class FillEndGameStatsPatch { private static readonly HashSet maskedVictims = new HashSet(); [HarmonyPrefix] private static void Prefix() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) maskedVictims.Clear(); try { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && val.isPlayerDead) { AdvancedCauseOfDeath? causeOfDeath = API.GetCauseOfDeath(val); AdvancedCauseOfDeath enemy_MaskedPlayer_Victim = AdvancedCauseOfDeath.Enemy_MaskedPlayer_Victim; if (causeOfDeath.HasValue && causeOfDeath.GetValueOrDefault() == enemy_MaskedPlayer_Victim) { maskedVictims.Add((int)val.playerClientId); } } } } catch (Exception arg) { Plugin.Log.LogError((object)$"FillEndGameStatsPatch.Prefix: {arg}"); } } [HarmonyPostfix] [HarmonyAfter(new string[] { "com.elitemastereric.coroner" })] private static void Postfix(HUDManager __instance) { try { for (int i = 0; i < __instance.statsUIElements.playerNotesText.Length; i++) { PlayerControllerB val = __instance.playersManager.allPlayerScripts[i]; if ((Object)(object)val == (Object)null || !val.isPlayerDead) { continue; } int num = (int)val.playerClientId; if (maskedVictims.Contains(num) && Plugin.FakeNames.TryGetValue(num, out var value)) { TextMeshProUGUI val2 = __instance.statsUIElements.playerNotesText[i]; string text = ((TMP_Text)val2).text; int num2 = text.LastIndexOf("* ", StringComparison.Ordinal); if (num2 >= 0) { int num3 = text.IndexOf('\n', num2); string text2 = ((num3 >= 0) ? text.Substring(num3) : "\n"); ((TMP_Text)val2).text = text.Substring(0, num2) + "* Was killed by a fake " + value + "." + text2; } } } } catch (Exception arg) { Plugin.Log.LogError((object)$"FillEndGameStatsPatch.Postfix: {arg}"); } finally { maskedVictims.Clear(); Plugin.FakeNames.Clear(); } } } }