using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using com.github.luckofthelefty.LethalHUDMessages.Messages;
using com.github.luckofthelefty.LethalHUDMessages.Patches;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("EasyTextEffects")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LuckOfTheLefty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Custom on-screen overlay for deaths, monster encounters, and game events in Lethal Company. Displays messages as a subtitle bar instead of chat.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+9b4ff8272daac681726eb765a1fa110348d7e4b4")]
[assembly: AssemblyProduct("LethalHUDMessages")]
[assembly: AssemblyTitle("com.github.luckofthelefty.LethalHUDMessages")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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 com.github.luckofthelefty.LethalHUDMessages
{
internal enum DisplayStyle
{
Tip,
GlobalNotification
}
internal static class ConfigManager
{
private static HashSet<string> _blacklistCache;
internal static ConfigEntry<DisplayStyle> NotificationStyle { get; private set; }
internal static ConfigEntry<bool> CriticalDamageMessages { get; private set; }
internal static ConfigEntry<bool> ShipLeavingMessages { get; private set; }
internal static ConfigEntry<bool> VoteToLeaveMessages { get; private set; }
internal static ConfigEntry<bool> TeleporterMessages { get; private set; }
internal static ConfigEntry<bool> QuotaFulfilledMessages { get; private set; }
internal static ConfigEntry<bool> EnableTestMode { get; private set; }
internal static ConfigEntry<bool> MonsterEncounterMessages { get; private set; }
internal static ConfigEntry<bool> CustomEnemyEncounterMessages { get; private set; }
internal static ConfigEntry<string> EnemyBlacklist { get; private set; }
internal static bool IsEnemyBlacklisted(string enemyName)
{
if (_blacklistCache == null)
{
RebuildBlacklistCache();
}
return _blacklistCache.Contains(enemyName.ToLowerInvariant());
}
private static void RebuildBlacklistCache()
{
_blacklistCache = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (EnemyBlacklist?.Value == null)
{
return;
}
string[] array = EnemyBlacklist.Value.Split(',');
foreach (string text in array)
{
string text2 = text.Trim();
if (text2.Length > 0)
{
_blacklistCache.Add(text2.ToLowerInvariant());
}
}
}
internal static void Initialize(ConfigFile config)
{
NotificationStyle = config.Bind<DisplayStyle>("Display", "NotificationStyle", DisplayStyle.Tip, "How to display messages. Tip = bottom-right popup with header. GlobalNotification = blue banner at bottom-center.");
EnableTestMode = config.Bind<bool>("Debug", "EnableTestMode", false, "Enable test mode. F8=Death, F9=Monster Kill, F10=Monster Encounter, F11=Events.");
CriticalDamageMessages = config.Bind<bool>("Player Events", "CriticalDamageMessages", false, "Show a message when a player takes critical damage.");
ShipLeavingMessages = config.Bind<bool>("Ship Events", "ShipLeavingMessages", false, "Show a message when the ship is leaving.");
VoteToLeaveMessages = config.Bind<bool>("Ship Events", "VoteToLeaveMessages", false, "Show a message when someone votes to leave.");
TeleporterMessages = config.Bind<bool>("Ship Events", "TeleporterMessages", false, "Show a message when the teleporter is used.");
QuotaFulfilledMessages = config.Bind<bool>("Ship Events", "QuotaFulfilledMessages", false, "Show a message when the profit quota is met.");
MonsterEncounterMessages = config.Bind<bool>("Monster Encounters", "MonsterEncounterMessages", true, "Show messages when players encounter monsters.");
CustomEnemyEncounterMessages = config.Bind<bool>("Monster Encounters", "CustomEnemyEncounterMessages", true, "Show generic encounter messages for modded/unknown enemies.");
EnemyBlacklist = config.Bind<string>("Monster Encounters", "EnemyBlacklist", "", "Comma-separated list of enemy names to suppress messages for.");
}
}
internal class DebugTester : MonoBehaviour
{
private static readonly CauseOfDeath[] DeathCauses;
private static readonly string[] MonsterNames;
private int _deathIndex;
private int _monsterDeathIndex;
private int _monsterEncounterIndex;
private int _eventIndex;
private const int EventTypeCount = 7;
private InputAction _f8Action;
private InputAction _f9Action;
private InputAction _f10Action;
private InputAction _f11Action;
private string TestName
{
get
{
PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
if (!((Object)(object)val != (Object)null))
{
return "TestPlayer";
}
return val.playerUsername;
}
}
private void Awake()
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Expected O, but got Unknown
_f8Action = new InputAction("DebugDeath", (InputActionType)1, "<Keyboard>/f8", (string)null, (string)null, (string)null);
_f9Action = new InputAction("DebugMonsterKill", (InputActionType)1, "<Keyboard>/f9", (string)null, (string)null, (string)null);
_f10Action = new InputAction("DebugEncounter", (InputActionType)1, "<Keyboard>/f10", (string)null, (string)null, (string)null);
_f11Action = new InputAction("DebugEvent", (InputActionType)1, "<Keyboard>/f11", (string)null, (string)null, (string)null);
_f8Action.Enable();
_f9Action.Enable();
_f10Action.Enable();
_f11Action.Enable();
Plugin.Log.LogInfo((object)"[DebugTester] Awake — InputActions created and enabled.");
}
private void OnDestroy()
{
InputAction f8Action = _f8Action;
if (f8Action != null)
{
f8Action.Disable();
}
InputAction f8Action2 = _f8Action;
if (f8Action2 != null)
{
f8Action2.Dispose();
}
InputAction f9Action = _f9Action;
if (f9Action != null)
{
f9Action.Disable();
}
InputAction f9Action2 = _f9Action;
if (f9Action2 != null)
{
f9Action2.Dispose();
}
InputAction f10Action = _f10Action;
if (f10Action != null)
{
f10Action.Disable();
}
InputAction f10Action2 = _f10Action;
if (f10Action2 != null)
{
f10Action2.Dispose();
}
InputAction f11Action = _f11Action;
if (f11Action != null)
{
f11Action.Disable();
}
InputAction f11Action2 = _f11Action;
if (f11Action2 != null)
{
f11Action2.Dispose();
}
}
private void Update()
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
if (!ConfigManager.EnableTestMode.Value)
{
return;
}
if (_f8Action.WasPressedThisFrame())
{
CauseOfDeath val = DeathCauses[_deathIndex % DeathCauses.Length];
string text = DeathMessages.Get(val, TestName);
Plugin.Log.LogInfo((object)$"[TEST] Death ({val}): {text}");
MessageSender.ShowTip(text);
_deathIndex++;
}
if (_f9Action.WasPressedThisFrame())
{
string text2 = MonsterNames[_monsterDeathIndex % MonsterNames.Length];
string deathMessage = MonsterMessages.GetDeathMessage(text2, TestName);
Plugin.Log.LogInfo((object)("[TEST] Monster Kill (" + text2 + "): " + deathMessage));
MessageSender.ShowTip(deathMessage);
_monsterDeathIndex++;
}
if (_f10Action.WasPressedThisFrame())
{
string text3 = MonsterNames[_monsterEncounterIndex % MonsterNames.Length];
string encounterMessage = MonsterMessages.GetEncounterMessage(text3, TestName);
if (encounterMessage != null)
{
Plugin.Log.LogInfo((object)("[TEST] Encounter (" + text3 + "): " + encounterMessage));
MessageSender.ShowTip(encounterMessage, MessageTier.Event);
}
_monsterEncounterIndex++;
}
if (_f11Action.WasPressedThisFrame())
{
string text4;
string text5;
switch (_eventIndex % 7)
{
default:
return;
case 0:
text4 = EventMessages.GetCriticalDamage(TestName);
text5 = "CriticalDamage";
break;
case 1:
text4 = EventMessages.GetShipLeaving();
text5 = "ShipLeaving";
break;
case 2:
text4 = EventMessages.GetVoteToLeave();
text5 = "VoteToLeave";
break;
case 3:
text4 = EventMessages.GetTeleporter(isInverse: false);
text5 = "Teleporter";
break;
case 4:
text4 = EventMessages.GetTeleporter(isInverse: true);
text5 = "InverseTeleporter";
break;
case 5:
text4 = EventMessages.GetQuotaFulfilled();
text5 = "QuotaFulfilled";
break;
case 6:
text4 = EventMessages.GetTurretFiring();
text5 = "TurretFiring";
break;
}
Plugin.Log.LogInfo((object)("[TEST] Event (" + text5 + "): " + text4));
MessageSender.ShowTip(text4, MessageTier.Event);
_eventIndex++;
}
}
static DebugTester()
{
CauseOfDeath[] array = new CauseOfDeath[16];
RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
DeathCauses = (CauseOfDeath[])(object)array;
MonsterNames = new string[21]
{
"Flowerman", "Jester", "ForestGiant", "MouthDog", "Crawler", "Blob", "Centipede", "SandSpider", "BaboonHawk", "NutcrackerEnemy",
"SpringMan", "MaskedPlayerEnemy", "DressGirl", "Butler", "ClaySurgeon", "CaveDweller", "HoarderBug", "SandWorm", "RadMech", "RedLocustBees",
"ButlerBees"
};
}
}
internal static class DiscoveryTracker
{
private static readonly HashSet<ulong> _discoveredEnemies = new HashSet<ulong>();
internal static void MarkDiscovered(ulong networkObjectId)
{
_discoveredEnemies.Add(networkObjectId);
}
internal static bool IsDiscovered(ulong networkObjectId)
{
return _discoveredEnemies.Contains(networkObjectId);
}
internal static void Reset()
{
_discoveredEnemies.Clear();
}
}
internal enum MessageTier
{
Death,
Event
}
internal class NotifColorOverride : MonoBehaviour
{
internal Image bgImage;
internal TMP_Text tmpText;
internal Color bgColor;
internal Color textColor;
internal float remainingTime;
private void LateUpdate()
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
if (remainingTime <= 0f)
{
Object.Destroy((Object)(object)this);
return;
}
remainingTime -= Time.deltaTime;
if ((Object)(object)bgImage != (Object)null)
{
((Graphic)bgImage).color = bgColor;
}
if ((Object)(object)tmpText != (Object)null)
{
((Graphic)tmpText).color = textColor;
}
}
}
internal static class MessageSender
{
private struct QueuedMessage
{
internal string text;
internal MessageTier tier;
}
[CompilerGenerated]
private sealed class <DrainQueue>d__10 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DrainQueue>d__10(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
int num = <>1__state;
if (num != 0)
{
if (num != 1)
{
return false;
}
<>1__state = -1;
goto IL_004f;
}
<>1__state = -1;
goto IL_0078;
IL_004f:
if (_queue.Count > 0)
{
QueuedMessage queuedMessage = _queue.Dequeue();
DisplayNow(queuedMessage.text, queuedMessage.tier);
}
goto IL_0078;
IL_0078:
if (_queue.Count > 0)
{
float num2 = 4f - (Time.time - _lastShowTime);
if (num2 > 0f)
{
<>2__current = (object)new WaitForSeconds(num2);
<>1__state = 1;
return true;
}
goto IL_004f;
}
_drainCoroutine = null;
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static readonly Color DeathBg = new Color(0.7f, 0.1f, 0.1f, 1f);
private static readonly Color EventBg = new Color(0.85f, 0.7f, 0f, 1f);
private const float MinDisplayTime = 4f;
private static readonly Queue<QueuedMessage> _queue = new Queue<QueuedMessage>();
private static float _lastShowTime = -999f;
private static Coroutine _drainCoroutine;
internal static void Send(string message, MessageTier tier = MessageTier.Death)
{
if (!((Object)(object)NetworkManager.Singleton == (Object)null) && (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer))
{
ShowTip(message, tier);
}
}
internal static void ShowTip(string message, MessageTier tier = MessageTier.Death)
{
if ((Object)(object)HUDManager.Instance == (Object)null)
{
return;
}
float num = Time.time - _lastShowTime;
if (num >= 4f && _queue.Count == 0)
{
DisplayNow(message, tier);
return;
}
_queue.Enqueue(new QueuedMessage
{
text = message,
tier = tier
});
if (_drainCoroutine == null)
{
_drainCoroutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(DrainQueue());
}
}
private static void DisplayNow(string message, MessageTier tier)
{
_lastShowTime = Time.time;
if (ConfigManager.NotificationStyle.Value == DisplayStyle.GlobalNotification)
{
HUDManager.Instance.DisplayGlobalNotification(message);
ApplyColorOverride(tier);
}
else
{
string text = ((tier == MessageTier.Death) ? "DEATH" : "EVENT");
bool flag = tier == MessageTier.Death;
HUDManager.Instance.DisplayTip(text, message, flag, false, "LC_Tip1");
}
}
[IteratorStateMachine(typeof(<DrainQueue>d__10))]
private static IEnumerator DrainQueue()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DrainQueue>d__10(0);
}
private static void ApplyColorOverride(MessageTier tier)
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
Animator globalNotificationAnimator = HUDManager.Instance.globalNotificationAnimator;
if (!((Object)(object)globalNotificationAnimator == (Object)null))
{
Image val = ((Component)globalNotificationAnimator).GetComponent<Image>();
if ((Object)(object)val == (Object)null)
{
val = ((Component)globalNotificationAnimator).GetComponentInChildren<Image>();
}
TextMeshProUGUI globalNotificationText = HUDManager.Instance.globalNotificationText;
NotifColorOverride notifColorOverride = ((Component)globalNotificationAnimator).gameObject.GetComponent<NotifColorOverride>();
if ((Object)(object)notifColorOverride == (Object)null)
{
notifColorOverride = ((Component)globalNotificationAnimator).gameObject.AddComponent<NotifColorOverride>();
}
notifColorOverride.bgImage = val;
notifColorOverride.tmpText = (TMP_Text)(object)globalNotificationText;
notifColorOverride.bgColor = ((tier == MessageTier.Death) ? DeathBg : EventBg);
notifColorOverride.textColor = ((tier == MessageTier.Death) ? Color.white : Color.black);
notifColorOverride.remainingTime = 8f;
if ((Object)(object)val != (Object)null)
{
Plugin.Log.LogInfo((object)("[GlobalNotif] Color override attached on '" + ((Object)((Component)val).gameObject).name + "'"));
}
else
{
Plugin.Log.LogWarning((object)("[GlobalNotif] No Image found on animator or children. Animator GO: '" + ((Object)((Component)globalNotificationAnimator).gameObject).name + "'"));
}
}
}
}
internal static class NetworkUtils
{
private static readonly Dictionary<string, int> _lastProcessedFrame = new Dictionary<string, int>();
public static bool ShouldProcess(string eventKey)
{
int frameCount = Time.frameCount;
if (_lastProcessedFrame.TryGetValue(eventKey, out var value) && value == frameCount)
{
return false;
}
_lastProcessedFrame[eventKey] = frameCount;
return true;
}
}
[BepInPlugin("com.github.luckofthelefty.LethalHUDMessages", "LethalHUDMessages", "1.0.0")]
internal class Plugin : BaseUnityPlugin
{
private readonly Harmony _harmony = new Harmony("com.github.luckofthelefty.LethalHUDMessages");
internal static Plugin Instance { get; private set; }
internal static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger;
private void Awake()
{
Instance = this;
ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
((Component)this).gameObject.AddComponent<DebugTester>();
((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalHUDMessages v1.0.0 loaded!");
_harmony.PatchAll(typeof(DeathPatch));
_harmony.PatchAll(typeof(MonsterKillPatch));
_harmony.PatchAll(typeof(MonsterEncounterPatch));
_harmony.PatchAll(typeof(DiscoveryPatch));
_harmony.PatchAll(typeof(EventPatch));
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "com.github.luckofthelefty.LethalHUDMessages";
public const string PLUGIN_NAME = "LethalHUDMessages";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace com.github.luckofthelefty.LethalHUDMessages.Patches
{
[HarmonyPatch(typeof(PlayerControllerB))]
internal static class DeathPatch
{
[HarmonyPatch("KillPlayerClientRpc")]
[HarmonyPostfix]
private static void KillPlayerClientRpcPatch(PlayerControllerB __instance, int playerId, int causeOfDeath)
{
if (!NetworkUtils.ShouldProcess($"death_{playerId}"))
{
return;
}
PlayerControllerB val = ((StartOfRound.Instance?.allPlayerScripts != null && playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length) ? StartOfRound.Instance.allPlayerScripts[playerId] : __instance);
if ((Object)(object)val == (Object)null || !val.isPlayerDead)
{
return;
}
string username = val.playerUsername ?? "Unknown";
if (MonsterKillPatch.TryConsumeMonsterKill(playerId, out var enemyName) && !ConfigManager.IsEnemyBlacklisted(enemyName))
{
string deathMessage = MonsterMessages.GetDeathMessage(enemyName, username);
MessageSender.Send(deathMessage);
return;
}
string text = FindAttackingEnemy(val);
if (text != null && !ConfigManager.IsEnemyBlacklisted(text))
{
string deathMessage2 = MonsterMessages.GetDeathMessage(text, username);
MessageSender.Send(deathMessage2);
}
else
{
string message = DeathMessages.Get((CauseOfDeath)causeOfDeath, username);
MessageSender.Send(message);
}
}
private static string FindAttackingEnemy(PlayerControllerB playerScript)
{
if ((Object)(object)playerScript.inAnimationWithEnemy != (Object)null)
{
return GetEnemyName(playerScript.inAnimationWithEnemy);
}
EnemyAI[] array = Object.FindObjectsOfType<EnemyAI>();
if (array == null)
{
return null;
}
EnemyAI[] array2 = array;
foreach (EnemyAI val in array2)
{
if (!((Object)(object)val?.enemyType == (Object)null))
{
if ((Object)(object)val.inSpecialAnimationWithPlayer == (Object)(object)playerScript)
{
return GetEnemyName(val);
}
if ((Object)(object)val.targetPlayer == (Object)(object)playerScript && val.movingTowardsTargetPlayer)
{
return GetEnemyName(val);
}
}
}
return null;
}
private static string GetEnemyName(EnemyAI enemy)
{
if ((Object)(object)enemy?.enemyType == (Object)null)
{
return null;
}
return enemy.enemyType.enemyName ?? ((object)enemy).GetType().Name;
}
}
[HarmonyPatch]
internal static class DiscoveryPatch
{
[HarmonyPatch(typeof(EnemyAI), "SwitchToBehaviourClientRpc")]
[HarmonyPostfix]
private static void EnemyBehaviorChanged(EnemyAI __instance, int stateIndex)
{
if ((Object)(object)__instance == (Object)null || !NetworkUtils.ShouldProcess($"discovery_{((Object)__instance).GetInstanceID()}_{stateIndex}"))
{
return;
}
NetworkObject component = ((Component)__instance).GetComponent<NetworkObject>();
if ((Object)(object)component == (Object)null)
{
return;
}
ulong networkObjectId = component.NetworkObjectId;
if (stateIndex < 1)
{
return;
}
bool flag = DiscoveryTracker.IsDiscovered(networkObjectId);
DiscoveryTracker.MarkDiscovered(networkObjectId);
if (flag || !ConfigManager.MonsterEncounterMessages.Value || !ConfigManager.CustomEnemyEncounterMessages.Value)
{
return;
}
string enemyName = __instance.enemyType?.enemyName ?? ((object)__instance).GetType().Name;
if (!ConfigManager.IsEnemyBlacklisted(enemyName) && !MonsterMessages.HasEncounterPool(enemyName))
{
string nearestPlayerName = GetNearestPlayerName(__instance);
string encounterMessage = MonsterMessages.GetEncounterMessage(enemyName, nearestPlayerName);
if (encounterMessage != null)
{
MessageSender.Send(encounterMessage, MessageTier.Event);
}
}
}
private static string GetNearestPlayerName(EnemyAI enemy)
{
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)enemy.targetPlayer != (Object)null)
{
return enemy.targetPlayer.playerUsername ?? "Unknown";
}
if ((Object)(object)enemy.inSpecialAnimationWithPlayer != (Object)null)
{
return enemy.inSpecialAnimationWithPlayer.playerUsername ?? "Unknown";
}
if (StartOfRound.Instance?.allPlayerScripts != null)
{
float num = float.MaxValue;
PlayerControllerB val = null;
PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
foreach (PlayerControllerB val2 in allPlayerScripts)
{
if (!((Object)(object)val2 == (Object)null) && !val2.isPlayerDead && val2.isPlayerControlled)
{
float num2 = Vector3.Distance(((Component)enemy).transform.position, ((Component)val2).transform.position);
if (num2 < num)
{
num = num2;
val = val2;
}
}
}
if ((Object)(object)val != (Object)null)
{
return val.playerUsername ?? "Unknown";
}
}
return "someone";
}
[HarmonyPatch(typeof(StartOfRound), "ReviveDeadPlayers")]
[HarmonyPostfix]
private static void ResetOnNewRound()
{
DiscoveryTracker.Reset();
MonsterEncounterPatch.ResetCooldowns();
}
}
internal static class EventPatch
{
[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayerClientRpc")]
[HarmonyPostfix]
private static void DamagePlayer(PlayerControllerB __instance, int damageNumber)
{
if (NetworkUtils.ShouldProcess($"damage_{((Object)__instance).GetInstanceID()}") && ConfigManager.CriticalDamageMessages.Value && !((Object)(object)__instance == (Object)null) && !__instance.isPlayerDead && __instance.health <= 20)
{
string username = __instance.playerUsername ?? "Unknown";
string criticalDamage = EventMessages.GetCriticalDamage(username);
MessageSender.Send(criticalDamage, MessageTier.Event);
}
}
[HarmonyPatch(typeof(StartOfRound), "ShipLeaveAutomatically")]
[HarmonyPostfix]
private static void ShipLeaving()
{
if (ConfigManager.ShipLeavingMessages.Value)
{
string shipLeaving = EventMessages.GetShipLeaving();
MessageSender.Send(shipLeaving, MessageTier.Event);
}
}
[HarmonyPatch(typeof(TimeOfDay), "VoteShipToLeaveEarly")]
[HarmonyPostfix]
private static void VoteToLeave()
{
if (ConfigManager.VoteToLeaveMessages.Value)
{
string voteToLeave = EventMessages.GetVoteToLeave();
MessageSender.Send(voteToLeave, MessageTier.Event);
}
}
[HarmonyPatch(typeof(ShipTeleporter), "PressTeleportButtonClientRpc")]
[HarmonyPostfix]
private static void TeleporterUsed(ShipTeleporter __instance)
{
if (NetworkUtils.ShouldProcess($"teleporter_{((Object)__instance).GetInstanceID()}") && ConfigManager.TeleporterMessages.Value)
{
string teleporter = EventMessages.GetTeleporter(__instance.isInverseTeleporter);
MessageSender.Send(teleporter, MessageTier.Event);
}
}
[HarmonyPatch(typeof(TimeOfDay), "SyncNewProfitQuotaClientRpc")]
[HarmonyPostfix]
private static void QuotaFulfilled()
{
if (ConfigManager.QuotaFulfilledMessages.Value)
{
string quotaFulfilled = EventMessages.GetQuotaFulfilled();
MessageSender.Send(quotaFulfilled, MessageTier.Event);
}
}
}
internal static class MonsterEncounterPatch
{
private static readonly Dictionary<ulong, float> _cooldowns = new Dictionary<ulong, float>();
private const float CooldownSeconds = 15f;
private static bool IsOnCooldown(ulong networkObjectId)
{
if (_cooldowns.TryGetValue(networkObjectId, out var value) && Time.time - value < 15f)
{
return true;
}
return false;
}
private static void SetCooldown(ulong networkObjectId)
{
_cooldowns[networkObjectId] = Time.time;
}
internal static void ResetCooldowns()
{
_cooldowns.Clear();
}
private static bool CanSendEncounter(EnemyAI enemy)
{
if (!ConfigManager.MonsterEncounterMessages.Value)
{
return false;
}
if ((Object)(object)enemy == (Object)null)
{
return false;
}
if (!NetworkUtils.ShouldProcess($"encounter_{((Object)enemy).GetInstanceID()}"))
{
return false;
}
NetworkObject component = ((Component)enemy).GetComponent<NetworkObject>();
if ((Object)(object)component == (Object)null)
{
return false;
}
ulong networkObjectId = component.NetworkObjectId;
if (!DiscoveryTracker.IsDiscovered(networkObjectId))
{
return false;
}
if (IsOnCooldown(networkObjectId))
{
return false;
}
return true;
}
private static void SendEncounter(EnemyAI enemy, string playerName)
{
string enemyName = enemy.enemyType?.enemyName ?? ((object)enemy).GetType().Name;
string encounterMessage = MonsterMessages.GetEncounterMessage(enemyName, playerName);
if (encounterMessage != null)
{
NetworkObject component = ((Component)enemy).GetComponent<NetworkObject>();
if ((Object)(object)component != (Object)null)
{
SetCooldown(component.NetworkObjectId);
}
MessageSender.Send(encounterMessage, MessageTier.Event);
}
}
private static string GetPlayerName(int playerObjectIndex)
{
if (StartOfRound.Instance?.allPlayerScripts == null || playerObjectIndex < 0 || playerObjectIndex >= StartOfRound.Instance.allPlayerScripts.Length)
{
return "Unknown";
}
return StartOfRound.Instance.allPlayerScripts[playerObjectIndex]?.playerUsername ?? "Unknown";
}
private static string GetPlayerName(PlayerControllerB playerScript)
{
return playerScript?.playerUsername ?? "Unknown";
}
private static string GetTargetPlayerName(EnemyAI enemy)
{
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)enemy.targetPlayer != (Object)null)
{
return enemy.targetPlayer.playerUsername ?? "Unknown";
}
if ((Object)(object)enemy.inSpecialAnimationWithPlayer != (Object)null)
{
return enemy.inSpecialAnimationWithPlayer.playerUsername ?? "Unknown";
}
if (StartOfRound.Instance?.allPlayerScripts != null)
{
float num = float.MaxValue;
PlayerControllerB val = null;
PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
foreach (PlayerControllerB val2 in allPlayerScripts)
{
if (!((Object)(object)val2 == (Object)null) && !val2.isPlayerDead && val2.isPlayerControlled)
{
float num2 = Vector3.Distance(((Component)enemy).transform.position, ((Component)val2).transform.position);
if (num2 < num)
{
num = num2;
val = val2;
}
}
}
if ((Object)(object)val != (Object)null)
{
return val.playerUsername ?? "Unknown";
}
}
return "someone";
}
[HarmonyPatch(typeof(FlowermanAI), "KillPlayerAnimationClientRpc")]
[HarmonyPostfix]
private static void BrackenGrab(FlowermanAI __instance, int playerObjectId)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerObjectId));
}
}
[HarmonyPatch(typeof(JesterAI), "SetJesterInitialValues")]
[HarmonyPostfix]
private static void JesterCranking(JesterAI __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetTargetPlayerName((EnemyAI)(object)__instance));
}
}
[HarmonyPatch(typeof(SpringManAI), "SetAnimationGoClientRpc")]
[HarmonyPostfix]
private static void CoilheadMoving(SpringManAI __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetTargetPlayerName((EnemyAI)(object)__instance));
}
}
[HarmonyPatch(typeof(MaskedPlayerEnemy), "CreateMimicClientRpc")]
[HarmonyPostfix]
private static void MaskedMimic(MaskedPlayerEnemy __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
string playerName = (((Object)(object)__instance.mimickingPlayer != (Object)null) ? GetPlayerName(__instance.mimickingPlayer) : GetTargetPlayerName((EnemyAI)(object)__instance));
SendEncounter((EnemyAI)(object)__instance, playerName);
}
}
[HarmonyPatch(typeof(CentipedeAI), "ClingToPlayerClientRpc")]
[HarmonyPostfix]
private static void SnareFleaCling(CentipedeAI __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
string playerName = (((Object)(object)__instance.clingingToPlayer != (Object)null) ? GetPlayerName(__instance.clingingToPlayer) : GetTargetPlayerName((EnemyAI)(object)__instance));
SendEncounter((EnemyAI)(object)__instance, playerName);
}
}
[HarmonyPatch(typeof(SandSpiderAI), "PlayerTripWebClientRpc")]
[HarmonyPostfix]
private static void SpiderWebTrip(SandSpiderAI __instance, int playerNum)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerNum));
}
}
[HarmonyPatch(typeof(ForestGiantAI), "GrabPlayerClientRpc")]
[HarmonyPostfix]
private static void GiantGrab(ForestGiantAI __instance, int playerId)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerId));
}
}
[HarmonyPatch(typeof(CrawlerAI), "HitPlayerClientRpc")]
[HarmonyPostfix]
private static void ThumperHit(CrawlerAI __instance, int playerId)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerId));
}
}
[HarmonyPatch(typeof(BaboonBirdAI), "StabPlayerDeathAnimClientRpc")]
[HarmonyPostfix]
private static void BaboonHawkStab(BaboonBirdAI __instance, int playerObject)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerObject));
}
}
[HarmonyPatch(typeof(DressGirlAI), "ChooseNewHauntingPlayerClientRpc")]
[HarmonyPostfix]
private static void GhostGirlHaunt(DressGirlAI __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
string playerName = (((Object)(object)__instance.hauntingPlayer != (Object)null) ? GetPlayerName(__instance.hauntingPlayer) : GetTargetPlayerName((EnemyAI)(object)__instance));
SendEncounter((EnemyAI)(object)__instance, playerName);
}
}
[HarmonyPatch(typeof(MouthDogAI), "KillPlayerClientRpc")]
[HarmonyPostfix]
private static void EyelessDogEncounter(MouthDogAI __instance, int playerId)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerId));
}
}
[HarmonyPatch(typeof(BlobAI), "SlimeKillPlayerEffectClientRpc")]
[HarmonyPostfix]
private static void BlobContact(BlobAI __instance, int playerKilled)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerKilled));
}
}
[HarmonyPatch(typeof(NutcrackerEnemyAI), "FireGunClientRpc")]
[HarmonyPostfix]
private static void NutcrackerShot(NutcrackerEnemyAI __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetTargetPlayerName((EnemyAI)(object)__instance));
}
}
[HarmonyPatch(typeof(ButlerEnemyAI), "StabPlayerClientRpc")]
[HarmonyPostfix]
private static void ButlerStab(ButlerEnemyAI __instance, int playerId)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerId));
}
}
[HarmonyPatch(typeof(ClaySurgeonAI), "KillPlayerClientRpc")]
[HarmonyPostfix]
private static void BarberEncounter(ClaySurgeonAI __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetTargetPlayerName((EnemyAI)(object)__instance));
}
}
[HarmonyPatch(typeof(EnemyAI), "SwitchToBehaviourClientRpc")]
[HarmonyPostfix]
private static void BehaviourStateEncounter(EnemyAI __instance, int stateIndex)
{
if (__instance is CaveDwellerAI && stateIndex >= 1)
{
if (CanSendEncounter(__instance))
{
SendEncounter(__instance, GetTargetPlayerName(__instance));
}
}
else if (__instance is HoarderBugAI && stateIndex >= 2)
{
if (CanSendEncounter(__instance))
{
SendEncounter(__instance, GetTargetPlayerName(__instance));
}
}
else if (__instance is RedLocustBees && stateIndex >= 1)
{
if (CanSendEncounter(__instance))
{
SendEncounter(__instance, GetTargetPlayerName(__instance));
}
}
else if (__instance is ButlerBeesEnemyAI && stateIndex >= 1 && CanSendEncounter(__instance))
{
SendEncounter(__instance, GetTargetPlayerName(__instance));
}
}
[HarmonyPatch(typeof(SandWormAI), "EmergeClientRpc")]
[HarmonyPostfix]
private static void SandWormEmerge(SandWormAI __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetTargetPlayerName((EnemyAI)(object)__instance));
}
}
[HarmonyPatch(typeof(RadMechAI), "GrabPlayerClientRpc")]
[HarmonyPostfix]
private static void OldBirdGrab(RadMechAI __instance, int playerId)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetPlayerName(playerId));
}
}
[HarmonyPatch(typeof(RadMechAI), "ShootGunClientRpc")]
[HarmonyPostfix]
private static void OldBirdShoot(RadMechAI __instance)
{
if (CanSendEncounter((EnemyAI)(object)__instance))
{
SendEncounter((EnemyAI)(object)__instance, GetTargetPlayerName((EnemyAI)(object)__instance));
}
}
[HarmonyPatch(typeof(Turret), "SetToModeClientRpc")]
[HarmonyPostfix]
private static void TurretMode(Turret __instance, int mode)
{
if (NetworkUtils.ShouldProcess($"turret_{((Object)__instance).GetInstanceID()}") && ConfigManager.MonsterEncounterMessages.Value && mode >= 2)
{
string turretFiring = EventMessages.GetTurretFiring();
MessageSender.Send(turretFiring, MessageTier.Event);
}
}
}
internal static class MonsterKillPatch
{
private static readonly Dictionary<int, string> _recentMonsterKills = new Dictionary<int, string>();
internal static void RegisterMonsterKill(int playerId, string enemyName)
{
_recentMonsterKills[playerId] = enemyName;
}
internal static bool TryConsumeMonsterKill(int playerId, out string enemyName)
{
if (_recentMonsterKills.TryGetValue(playerId, out enemyName))
{
_recentMonsterKills.Remove(playerId);
return true;
}
enemyName = null;
return false;
}
[HarmonyPatch(typeof(FlowermanAI), "KillPlayerAnimationClientRpc")]
[HarmonyPostfix]
private static void BrackenKill(int playerObjectId)
{
RegisterMonsterKill(playerObjectId, "Flowerman");
}
[HarmonyPatch(typeof(JesterAI), "KillPlayerClientRpc")]
[HarmonyPostfix]
private static void JesterKill(int playerId)
{
RegisterMonsterKill(playerId, "Jester");
}
[HarmonyPatch(typeof(ForestGiantAI), "GrabPlayerClientRpc")]
[HarmonyPostfix]
private static void GiantKill(int playerId)
{
RegisterMonsterKill(playerId, "ForestGiant");
}
[HarmonyPatch(typeof(MouthDogAI), "KillPlayerClientRpc")]
[HarmonyPostfix]
private static void EyelessDogKill(int playerId)
{
RegisterMonsterKill(playerId, "MouthDog");
}
[HarmonyPatch(typeof(BlobAI), "SlimeKillPlayerEffectClientRpc")]
[HarmonyPostfix]
private static void BlobKill(int playerKilled)
{
RegisterMonsterKill(playerKilled, "Blob");
}
[HarmonyPatch(typeof(BaboonBirdAI), "StabPlayerDeathAnimClientRpc")]
[HarmonyPostfix]
private static void BaboonHawkKill(int playerObject)
{
RegisterMonsterKill(playerObject, "BaboonHawk");
}
[HarmonyPatch(typeof(ButlerEnemyAI), "StabPlayerClientRpc")]
[HarmonyPostfix]
private static void ButlerKill(int playerId)
{
RegisterMonsterKill(playerId, "Butler");
}
[HarmonyPatch(typeof(ClaySurgeonAI), "KillPlayerClientRpc")]
[HarmonyPostfix]
private static void BarberKill(ClaySurgeonAI __instance)
{
PlayerControllerB targetPlayer = ((EnemyAI)__instance).targetPlayer;
if (!((Object)(object)targetPlayer == (Object)null))
{
int playerId = (int)targetPlayer.playerClientId;
RegisterMonsterKill(playerId, "ClaySurgeon");
}
}
[HarmonyPatch(typeof(RadMechAI), "GrabPlayerClientRpc")]
[HarmonyPostfix]
private static void OldBirdKill(int playerId)
{
RegisterMonsterKill(playerId, "RadMech");
}
}
}
namespace com.github.luckofthelefty.LethalHUDMessages.Messages
{
internal static class DeathMessages
{
private static readonly Random _rng = new Random();
private static readonly List<string> Unknown = new List<string> { "$$ just... died. Nobody knows how.", "$$'s cause of death: \u00af\\_(ツ)_/\u00af", "$$ has left the mortal plane.", "$$ spontaneously stopped living.", "The Company sends its condolences to $$'s family.", "$$ died of mysterious circumstances. Totally not suspicious.", "$$ died and nobody saw it happen.", "$$ was claimed by the moon itself." };
private static readonly List<string> Bludgeoning = new List<string> { "$$ got absolutely rocked.", "$$'s skull made an interesting sound.", "$$ caught something heavy with their face.", "$$ was bludgeoned into next week.", "$$ was on the wrong end of blunt force trauma.", "$$ brought a face to a blunt object fight.", "$$'s head was used as a stress ball.", "Something gave $$ a permanent headache." };
private static readonly List<string> Gravity = new List<string> { "$$'s last words were 'I can make that jump.'", "$$ achieved terminal velocity.", "$$ forgot their parachute at home.", "$$ tested gravity. Gravity won.", "$$ left a $$ shaped crater.", "$$ believed they could fly. They were wrong.", "$$ hit the ground at terminal velocity.", "$$ took the express elevator down.", "$$ discovered that fall damage is real.", "$$ speedran the gravity simulator." };
private static readonly List<string> Blast = new List<string> { "$$ was blown to bits across the facility.", "$$ went out with a bang. Literally.", "$$ was scattered across several zip codes.", "$$ became confetti.", "$$ stepped on a mine and exploded. Spectacularly.", "$$ found the landmine. With their feet.", "$$ is now a fine mist.", "$$ was vaporized. At least it was quick." };
private static readonly List<string> Strangulation = new List<string> { "$$ was strangled. That's not a great way to go.", "$$'s neck got a very unwanted massage.", "$$ forgot how to breathe (with help).", "$$ was choked out like a UFC fighter.", "Something really wanted $$ to shut up.", "$$'s airway was permanently closed for business.", "$$ received a complimentary neck massage.", "$$ was strangled into the afterlife." };
private static readonly List<string> Suffocation = new List<string> { "$$ ran out of oxygen. Classic mistake.", "$$'s lungs gave out. No air left.", "$$ tried to breathe and couldn't.", "$$ found out air is actually important.", "Air was evicted from $$'s lungs.", "$$'s last breath was... their last breath.", "$$ suffocated. Should've brought a spare lung.", "$$ forgot that breathing is not optional.", "$$ experienced a permanent air shortage." };
private static readonly List<string> Mauling = new List<string> { "$$ was mauled beyond recognition.", "$$'s insurance doesn't cover mauling.", "$$ was torn apart like wrapping paper.", "$$ became an all-you-can-eat buffet.", "Something used $$ as a chew toy.", "$$ was ferociously disassembled, limb from limb.", "$$'s insides are now on the outside.", "$$ found out they're made of meat. The hard way." };
private static readonly List<string> Gunshots = new List<string> { "$$ brought a body to a gunfight.", "$$ now has more holes than swiss cheese.", "$$ caught a bullet. With their everything.", "$$ was shot. Who gave these things guns?!", "$$ now has more holes than they started with.", "$$ found out they weren't bulletproof.", "$$ was used for target practice.", "$$ learned that bullets are not friends." };
private static readonly List<string> Crushing = new List<string> { "$$ became two-dimensional.", "$$ was compacted for easy storage.", "$$ found out they're not load-bearing.", "$$ was crushed like a soda can.", "$$ was crushed flat. Very flat.", "$$ is now a pancake.", "$$'s bones were turned into gravel.", "$$ was flattened. Permanently." };
private static readonly List<string> Drowning = new List<string> { "$$ forgot how to swim.", "$$ is sleeping with the fishes.", "$$ tried to drink the entire ocean.", "$$'s lungs were not designed for water.", "$$ went for a swim. Didn't come back.", "$$ discovered they're not a fish.", "$$ drowned. Turns out water is wet AND deadly.", "$$ sank like a rock. Because they're not a boat." };
private static readonly List<string> Abandoned = new List<string> { "$$ was left behind. Oops.", "The ship left without $$. That's rough.", "$$ was voted off the moon.", "Nobody waited for $$. Cold.", "$$ learned the ship waits for no one.", "$$'s coworkers chose profits over friendship.", "$$ was sacrificed for the quota.", "The Company doesn't do rescue missions for $$." };
private static readonly List<string> Electrocution = new List<string> { "$$ became a lightning rod.", "$$'s hair is standing up. Forever.", "$$ found out watt happens when you touch that.", "$$ was deep fried.", "$$ got a shocking surprise.", "$$ conducted electricity. Poorly.", "$$'s entire body just short-circuited.", "$$ was electrocuted into the shadow realm." };
private static readonly List<string> Kicking = new List<string> { "$$ was kicked into next week.", "$$ got booted. Literally.", "$$ caught a foot to the everything.", "$$ was punted like a football.", "$$ found out legs are weapons too.", "Somebody dropkicked $$ into orbit.", "$$ was on the receiving end of a boot.", "$$ was kicked so hard they ragdolled." };
private static readonly List<string> Burning = new List<string> { "$$ is extra crispy.", "$$ was roasted. Not the funny kind.", "$$ achieved a nice golden brown.", "$$ discovered they're flammable.", "$$'s marshmallow impression was too convincing.", "$$ was cooked to perfection. Medium well.", "$$ spontaneously combusted. Probably.", "$$ was flame-broiled." };
private static readonly List<string> Stabbing = new List<string> { "$$ was turned into a pincushion.", "$$ got the point. Several points actually.", "Something sharp disagreed with $$.", "$$ was perforated.", "$$ brought their torso to a knife fight.", "$$ was skewered like a kebab.", "$$ discovered a new hole in their body.", "$$ was impaled. Ouch doesn't cover it." };
private static readonly List<string> Fan = new List<string> { "$$ became a smoothie.", "$$ was blended on the 'puree' setting.", "$$ walked into a fan. A big one.", "$$ was diced, sliced, and julienned.", "$$ tried to high-five a giant fan blade.", "$$ was turned into confetti by a fan.", "$$ found the industrial fan. It found them back.", "$$ was shredded. Not the cool guitar kind." };
internal static string Get(CauseOfDeath cause, string username)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected I4, but got Unknown
List<string> list = (int)cause switch
{
0 => Unknown,
1 => Bludgeoning,
2 => Gravity,
3 => Blast,
4 => Strangulation,
5 => Suffocation,
6 => Mauling,
7 => Gunshots,
8 => Crushing,
9 => Drowning,
10 => Abandoned,
11 => Electrocution,
12 => Kicking,
13 => Burning,
14 => Stabbing,
15 => Fan,
_ => Unknown,
};
return list[_rng.Next(list.Count)].Replace("$$", username);
}
}
internal static class EventMessages
{
private static readonly Random _rng = new Random();
private static readonly List<string> CriticalDamage = new List<string> { "$$ is critically injured!", "$$ is barely hanging on!", "$$ is one hit from death!", "$$'s health is critical!", "$$ needs help. NOW.", "$$ is clinging to life!" };
private static readonly List<string> ShipLeaving = new List<string> { "The ship is leaving! Run!", "Ship's departing! Move it or lose it!", "Last call! The ship is out of here!", "The autopilot doesn't wait. The ship is leaving!", "Ship is leaving! Every employee for themselves!", "LEAVE. NOW. SHIP. GOING." };
private static readonly List<string> VoteToLeave = new List<string> { "Someone wants out. Can't blame them.", "A vote to leave has been cast. Coward or genius?", "Someone's had enough of this moon.", "Vote to leave! Someone chose life.", "An employee has requested immediate departure.", "Someone would like to leave. Understandable." };
private static readonly List<string> Teleporter = new List<string> { "The teleporter was activated!", "Someone just got beamed up!", "Teleporter fired! Hope they made it.", "Beam me up! The teleporter was used.", "The teleporter just went off!", "Someone's taking the express route back." };
private static readonly List<string> InverseTeleporter = new List<string> { "The inverse teleporter was used! Good luck in there.", "Someone just got sent into the facility blind!", "Inverse teleporter activated! Hope they packed lunch.", "The inverse teleporter fired! Godspeed.", "Someone volunteered for a random drop. Brave.", "Inverse teleporter! Destination: probably death." };
private static readonly List<string> QuotaFulfilled = new List<string> { "Quota met! The Company is pleased... for now.", "Profit quota fulfilled! You live another cycle.", "The Company acknowledges your adequate performance.", "Quota complete! The Company demands more next time.", "You met the quota! Don't celebrate. There's always more.", "The shareholders are satisfied. Temporarily." };
private static readonly List<string> TurretFiring = new List<string> { "Turret locked on! Take cover!", "The turret is firing! Duck!", "Someone's in the turret's crosshairs!", "Turret going berserk!", "The turret has chosen violence!", "TURRET! EVERYONE DOWN!" };
internal static string GetCriticalDamage(string username)
{
return CriticalDamage[_rng.Next(CriticalDamage.Count)].Replace("$$", username);
}
internal static string GetShipLeaving()
{
return ShipLeaving[_rng.Next(ShipLeaving.Count)];
}
internal static string GetVoteToLeave()
{
return VoteToLeave[_rng.Next(VoteToLeave.Count)];
}
internal static string GetTeleporter(bool isInverse)
{
if (!isInverse)
{
return Teleporter[_rng.Next(Teleporter.Count)];
}
return InverseTeleporter[_rng.Next(InverseTeleporter.Count)];
}
internal static string GetQuotaFulfilled()
{
return QuotaFulfilled[_rng.Next(QuotaFulfilled.Count)];
}
internal static string GetTurretFiring()
{
return TurretFiring[_rng.Next(TurretFiring.Count)];
}
}
internal static class MonsterMessages
{
private static readonly Random _rng = new Random();
private static readonly Dictionary<string, List<string>> DeathPools = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase)
{
["Flowerman"] = new List<string> { "$$ went on a one-way date with the Bracken.", "$$ was added to the Bracken's private collection.", "The Bracken just wanted a hug. $$ didn't survive it.", "$$ shouldn't have looked at the Bracken.", "$$ was dragged into the darkness. Bye $$!", "$$ found out the Bracken doesn't like eye contact.", "The Bracken snapped $$'s neck like a glow stick.", "$$ was invited to the Bracken's room. No one comes back." },
["Jester"] = new List<string> { "Pop goes $$!", "$$ found out what's in the box.", "The Jester wasn't joking around with $$.", "$$ didn't laugh at the Jester's joke. Fatal mistake.", "The music stopped. So did $$.", "$$ was the punchline to a very bad joke.", "Jack popped out of the box. $$ popped out of existence.", "The Jester cranked $$'s life away." },
["ForestGiant"] = new List<string> { "$$ was a light snack for the Forest Giant.", "The Giant added $$ to their meal plan.", "$$ found out they're bite-sized.", "$$ was eaten alive. Yikes.", "The Forest Giant didn't even chew. Just swallowed $$.", "$$ was picked up like a chicken nugget.", "The Giant used $$ as a toothpick. Then ate the toothpick.", "$$ was the Giant's appetizer." },
["MouthDog"] = new List<string> { "$$ was too loud.", "The dog didn't need eyes to find $$.", "$$ learned that 'be quiet' wasn't a suggestion.", "An Eyeless Dog heard $$'s last breath.", "$$ forgot the number one rule: shut up.", "The Eyeless Dog ate $$ in one bite.", "$$'s footsteps were a dinner bell.", "$$ whispered. It wasn't quiet enough." },
["Crawler"] = new List<string> { "A Thumper ran $$ over like a freight train.", "$$ was steamrolled by a Thumper.", "The Thumper didn't even slow down for $$.", "$$ zigged when they should've zagged. Thumper didn't care.", "$$ was in the Thumper's lane. Bad idea.", "$$ heard the thumping. Then felt it.", "The Thumper used $$ as a speed bump.", "$$ was roadkill." },
["Blob"] = new List<string> { "$$ was dissolved like a bath bomb.", "The Blob absorbed $$. Delicious.", "$$ melted into the Hygrodere.", "$$ became one with the slime.", "The Blob didn't have a mouth, but it ate $$ anyway.", "$$ was digested alive. Slowly.", "$$ walked into the Blob. Didn't walk out.", "The slime claimed $$. Gross." },
["Centipede"] = new List<string> { "A Snare Flea suffocated $$ with love.", "$$ got a face full of Snare Flea.", "The Snare Flea wore $$ like a hat. $$ didn't make it.", "$$ was smothered by a ceiling bug.", "The Snare Flea hugged $$'s face. Permanently.", "$$ looked up. Shouldn't have.", "A Snare Flea dropped on $$'s head. Game over.", "$$ was facefhugged. Alien style." },
["SandSpider"] = new List<string> { "$$ was wrapped up like a burrito by a Spider.", "The Spider turned $$ into a cocoon.", "$$ walked into a web and never walked out.", "$$ became Spider food.", "The Spider gift-wrapped $$ for later.", "$$ was caught in the Spider's pantry.", "$$ got webbed up and chomped.", "A Spider made $$ its next meal." },
["BaboonHawk"] = new List<string> { "A Baboon Hawk shanked $$.", "$$ was jumped by a Baboon Hawk. In broad daylight.", "The Baboon Hawk chose violence. $$ was the victim.", "$$ got pecked to death. Embarrassing.", "A Baboon Hawk stabbed $$ in the back. Literally.", "$$ was mugged by a bird monkey.", "The Baboon Hawk said 'your scrap or your life.' $$ had scrap.", "$$ underestimated the murder bird." },
["NutcrackerEnemy"] = new List<string> { "The Nutcracker shot $$ point blank.", "$$ caught a shotgun blast from the Nutcracker.", "The Nutcracker's aim was true. $$ is dead.", "$$ was executed by a toy soldier.", "The Nutcracker cracked more than nuts.", "$$ was gunned down by a Christmas decoration.", "The Nutcracker gave $$ a lead present.", "$$ found out the Nutcracker's gun is real." },
["SpringMan"] = new List<string> { "$$ blinked. The Coilhead didn't.", "The Coilhead caught $$ slipping.", "$$ forgot the one rule about Coilheads.", "Don't blink. $$ blinked.", "The Coilhead spring-loaded $$ into the afterlife.", "$$ looked away for one second. One.", "The Coilhead was patient. $$ was not.", "$$ lost the staring contest with the Coilhead." },
["MaskedPlayerEnemy"] = new List<string> { "$$ was killed by their own doppelganger.", "The Masked got $$ from behind.", "$$ trusted the wrong teammate. It was a Mimic.", "A Mimic wearing a friend's face killed $$.", "$$ was backstabbed by a copycat.", "The Masked fooled everyone. Especially $$.", "$$ didn't notice their friend had no personality.", "The imposter killed $$. That's pretty sus." },
["DressGirl"] = new List<string> { "The Ghost Girl finally caught $$.", "$$ couldn't escape the Ghost Girl.", "She got $$. It was only a matter of time.", "$$ was haunted to death. Literally.", "The little girl wasn't so little. $$ is dead.", "$$ heard giggling. Then nothing. Forever.", "The Ghost Girl played with $$ until they broke.", "$$ was the Ghost Girl's favorite toy." },
["Butler"] = new List<string> { "The Butler served $$ their last meal.", "$$ was stabbed by the help.", "The Butler did it. In the facility. With a knife.", "$$ got a five-star stabbing from the Butler.", "The Butler took $$'s order. It was death.", "$$ tipped the Butler. The Butler tipped them over.", "The Butler's service was killer. Literally.", "$$ found out the Butler doesn't take 'no' for an answer." },
["ClaySurgeon"] = new List<string> { "The Barber gave $$ a little off the top. And the middle. And the bottom.", "$$ got the closest shave of their life. Their last, too.", "The Barber snipped $$ in half. Clean cut.", "$$ walked into the Barber's shop. Didn't walk out in one piece.", "The Barber performed surgery on $$. Without anesthesia.", "$$ was trimmed down to size by the Barber.", "The Barber's scissors found $$. Snip snip.", "$$ was the Barber's latest masterpiece." },
["CaveDweller"] = new List<string> { "The Maneater ate $$. Shocker.", "$$ thought the baby was cute. It wasn't a baby.", "The Maneater grew up fast. $$ didn't.", "$$ adopted a baby. The baby ate them.", "The cute little creature devoured $$.", "$$ learned that not all babies are innocent.", "The Maneater baited $$. Hook, line, and sinker.", "$$ was consumed by what they tried to protect." },
["HoarderBug"] = new List<string> { "A Hoarding Bug killed $$ over a piece of junk.", "$$ touched the Hoarding Bug's stuff. Fatal mistake.", "The Hoarding Bug chose violence to protect its hoard.", "$$ was murdered by a bug over a lightbulb.", "Don't mess with a Hoarding Bug's collection. $$ learned that.", "$$ died fighting a bug over loot. Embarrassing.", "The Hoarding Bug wasn't sharing with $$.", "$$ was killed by the world's angriest hoarder." },
["SandWorm"] = new List<string> { "$$ was swallowed whole by an Earth Leviathan.", "The ground opened up and ate $$.", "$$ didn't hear the rumbling. Now they're underground.", "An Earth Leviathan had $$ for lunch.", "$$ was consumed by a giant worm. That's a sentence.", "The Earth Leviathan came from below. $$ went below.", "$$ was in the wrong place when the worm surfaced.", "The Leviathan emerged. $$ did not." },
["RadMech"] = new List<string> { "An Old Bird stepped on $$. Crunch.", "$$ was incinerated by an Old Bird's rockets.", "The Old Bird turned $$ into a scorch mark.", "$$ was stomped flat by a robot apocalypse.", "An Old Bird locked onto $$. $$ is now dust.", "$$ picked a fight with a giant mech. It went poorly.", "The Old Bird blasted $$ into next week.", "$$ was terminated. Old Bird style." },
["RedLocustBees"] = new List<string> { "$$ disturbed the hive. The bees disturbed $$'s life.", "The Circuit Bees swarmed $$. Buzz buzz, bye bye.", "$$ tried to steal honey. Got stung to death.", "A swarm of angry bees ended $$'s career.", "$$ found out those bees aren't just for show.", "The Circuit Bees chose $$ as their target. Ouch.", "$$ was stung approximately one million times.", "Don't touch the beehive. $$ touched the beehive." },
["ButlerBees"] = new List<string> { "The Butler's hornets finished what the Butler started on $$.", "$$ was swarmed by Mask Hornets.", "The Mask Hornets stung $$ to death.", "$$ killed the Butler. The hornets killed $$.", "Mask Hornets avenged the Butler by killing $$.", "$$ thought killing the Butler was the hard part.", "The hornets came for $$. Revenge is sweet.", "The Butler's bees made sure $$ didn't celebrate." }
};
private static readonly Dictionary<string, List<string>> EncounterPools = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase)
{
["Flowerman"] = new List<string> { "The Bracken has its eyes on $$.", "$$ made eye contact with the Bracken. Bold.", "The Bracken is stalking $$. Act natural.", "$$ felt something breathing on their neck...", "The Bracken is watching $$. Don't turn around.", "$$ glimpsed something tall in the shadows." },
["Jester"] = new List<string> { "The Jester's music box is winding down...", "Do you hear that music? $$ does.", "Pop goes the... oh no.", "The Jester is cranking up. Time to leave.", "That music box sounds closer...", "The Jester is getting ready for a show." },
["SpringMan"] = new List<string> { "$$ looked away from the Coilhead. Bold move.", "Don't. Blink.", "The Coilhead moved. Someone wasn't watching.", "$$ heard a spring. Keep your eyes open.", "The Coilhead is closer than it was a second ago.", "Nobody blink. NOBODY BLINK." },
["MaskedPlayerEnemy"] = new List<string> { "Something is wearing $$'s face...", "Wait... there are two $$s?", "That doesn't look like the real $$.", "A Mimic is impersonating $$. Don't trust anyone.", "$$'s evil twin just showed up.", "Who's the real $$? Good luck." },
["Centipede"] = new List<string> { "A Snare Flea latched onto $$'s head!", "$$ has an unwanted hat.", "Something dropped from the ceiling onto $$!", "$$ is being suffocated by a ceiling bug!", "A Snare Flea is hugging $$'s face!", "$$ can't see. Or breathe. Snare Flea." },
["SandSpider"] = new List<string> { "$$ walked right into a spider's web.", "$$ triggered a trip wire. The Spider knows.", "The Spider felt something in its web...", "$$ just rang the Spider's doorbell.", "$$ is tangled in webs. The Spider is coming.", "A web just caught $$. Dinner is served." },
["ForestGiant"] = new List<string> { "A Forest Giant snatched up $$!", "$$ was picked up like an action figure!", "The Giant grabbed $$! This is bad!", "$$ is in the Giant's hand. Pray.", "A Forest Giant has $$! Someone do something!", "The Giant is holding $$ like a snack. Because they are one." },
["Crawler"] = new List<string> { "$$ just got bodied by a Thumper.", "A Thumper clipped $$!", "$$ took a hit from a Thumper. Walk it off.", "The Thumper charged $$! They're still standing... barely.", "$$ was sideswiped by a Thumper.", "A Thumper just freight-trained $$." },
["BaboonHawk"] = new List<string> { "A Baboon Hawk chose violence against $$.", "The Baboon Hawks are getting aggressive with $$.", "$$ is being targeted by Baboon Hawks.", "A Baboon Hawk stabbed at $$!", "$$ caught the attention of the murder birds.", "The Baboon Hawks don't like $$." },
["DressGirl"] = new List<string> { "Something has taken an interest in $$...", "$$ is being haunted. Good luck with that.", "The Ghost Girl chose $$. F.", "$$ hears giggling. No one else does.", "She's following $$. Don't look behind you.", "$$ feels a presence. It's not friendly." },
["MouthDog"] = new List<string> { "Something heard $$...", "An Eyeless Dog perked up near $$. Shhhh.", "$$ made a noise. The Dog noticed.", "An Eyeless Dog is sniffing around $$.", "Shhh! The Dog is near $$!", "$$ needs to be very, very quiet right now." },
["Blob"] = new List<string> { "$$ is getting slimed!", "The Blob touched $$. Gross.", "$$ stepped in the Hygrodere.", "The slime is on $$. Move!", "$$ is being slowly consumed. Move faster!", "A Blob is dissolving $$'s shoes." },
["NutcrackerEnemy"] = new List<string> { "The Nutcracker opened fire!", "Shots fired! The Nutcracker is shooting!", "The Nutcracker has $$ in its sights!", "Duck! The Nutcracker is locked and loaded!", "The toy soldier is shooting! Take cover!", "The Nutcracker's shotgun just went off!" },
["Butler"] = new List<string> { "The Butler is following $$. Politely. Menacingly.", "$$ has the Butler's full attention.", "The Butler is getting closer to $$...", "The Butler offered $$ a drink. $$ should run.", "$$ noticed the Butler's knife. Time to go.", "The Butler is serving $$ a death stare." },
["ClaySurgeon"] = new List<string> { "The Barber is eyeing $$...", "$$ is next in the Barber's chair.", "Snip snip. The Barber found $$.", "The Barber's scissors are getting closer to $$.", "$$ can hear scissors behind them...", "The Barber wants to give $$ a trim." },
["CaveDweller"] = new List<string> { "$$ picked up something... alive.", "That baby $$ found looks hungry.", "The Maneater is growing. $$ should drop it.", "$$ adopted something they shouldn't have.", "The cute baby near $$ is getting bigger...", "The Maneater is near $$. Don't feed it." },
["HoarderBug"] = new List<string> { "A Hoarding Bug is upset with $$!", "$$ got too close to the Hoarding Bug's stuff.", "The Hoarding Bug is angry at $$!", "$$ touched the bug's loot. Bad move.", "A Hoarding Bug is defending its hoard from $$!", "$$ angered the world's most territorial bug." },
["SandWorm"] = new List<string> { "The ground is shaking near $$...", "Something massive is moving underground near $$!", "$$ felt the earth rumble. That's not good.", "An Earth Leviathan is surfacing near $$!", "RUN! The ground is opening near $$!", "$$ is standing on very dangerous ground." },
["RadMech"] = new List<string> { "An Old Bird spotted $$!", "The Old Bird is targeting $$!", "$$ has a giant robot problem.", "An Old Bird is charging at $$!", "The mech locked onto $$. Run!", "$$ is in an Old Bird's crosshairs." },
["RedLocustBees"] = new List<string> { "$$ got too close to the beehive!", "The Circuit Bees are angry at $$!", "$$ disturbed the hive! Bees incoming!", "A swarm of bees is chasing $$!", "The Circuit Bees don't want $$ near their hive!", "$$ poked the bee's nest. Classic." },
["ButlerBees"] = new List<string> { "Mask Hornets are swarming $$!", "The Butler's hornets are after $$!", "A swarm of Mask Hornets appeared near $$!", "$$ is being chased by angry hornets!", "The Mask Hornets have targeted $$!", "Hornets everywhere! $$ is in trouble!" }
};
private static readonly List<string> GenericMonsterDeath = new List<string> { "$$ was killed by a ##.", "## claimed another victim: $$.", "$$ had an unfortunate encounter with a ##.", "A ## ended $$'s career.", "$$ was no match for the ##.", "## destroyed $$. Completely.", "$$ was eliminated by a ##.", "The ## made short work of $$." };
private static readonly List<string> GenericMonsterEncounter = new List<string> { "A ## has been disturbed...", "$$ caught the attention of a ##.", "A ## noticed $$. That can't be good.", "The ## is agitated. $$ is nearby.", "$$ is being targeted by a ##.", "A ## has its sights on $$." };
internal static string GetDeathMessage(string enemyName, string username)
{
if (DeathPools.TryGetValue(enemyName, out var value))
{
return value[_rng.Next(value.Count)].Replace("$$", username);
}
string text = GenericMonsterDeath[_rng.Next(GenericMonsterDeath.Count)];
return text.Replace("$$", username).Replace("##", enemyName);
}
internal static string GetEncounterMessage(string enemyName, string username)
{
if (EncounterPools.TryGetValue(enemyName, out var value))
{
return value[_rng.Next(value.Count)].Replace("$$", username);
}
if (!ConfigManager.CustomEnemyEncounterMessages.Value)
{
return null;
}
string text = GenericMonsterEncounter[_rng.Next(GenericMonsterEncounter.Count)];
return text.Replace("$$", username).Replace("##", enemyName);
}
internal static bool HasDeathPool(string enemyName)
{
return DeathPools.ContainsKey(enemyName);
}
internal static bool HasEncounterPool(string enemyName)
{
return EncounterPools.ContainsKey(enemyName);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}