using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyTitle("K.Y.S")]
[assembly: AssemblyDescription("Toggleable instant death hotkey for PEAK.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("tony4twenty")]
[assembly: AssemblyProduct("K.Y.S")]
[assembly: AssemblyCopyright("Copyright © tony4twenty 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("361d37ad-d43b-4908-bdd2-02729cf3904d")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}
namespace KYS
{
[BepInPlugin("tony4twentys.kys", "K.Y.S", "1.1.0")]
[BepInProcess("PEAK.exe")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "tony4twentys.kys";
public const string PluginName = "K.Y.S";
public const string PluginVersion = "1.1.0";
internal static ConfigEntry<KeyCode> KysKey;
internal static ConfigEntry<KeyCode> KysModifier;
internal static ConfigEntry<bool> KysModifierToggle;
internal static ConfigEntry<KeyCode> ToggleKey;
internal static ConfigEntry<KeyCode> ToggleModifier;
internal static ConfigEntry<bool> ToggleModifierRequired;
internal static ConfigEntry<bool> HideAllNotifications;
internal static ConfigEntry<bool> KeepOnNotifierUntilOff;
internal static ConfigEntry<bool> PreviewBothNotifiers;
internal static ConfigEntry<float> PopupSeconds;
internal static ConfigEntry<string> OnColor;
internal static ConfigEntry<string> OffColor;
internal static ConfigEntry<int> OnSize;
internal static ConfigEntry<int> OffSize;
internal static ConfigEntry<float> OnPosX;
internal static ConfigEntry<float> OnPosY;
internal static ConfigEntry<float> OffPosX;
internal static ConfigEntry<float> OffPosY;
private bool _loggedDieFailure;
internal static Plugin Instance { get; private set; }
internal static ManualLogSource Log { get; private set; }
internal static bool SuicideEnabled { get; private set; }
private void Awake()
{
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
KysModifierToggle = ((BaseUnityPlugin)this).Config.Bind<bool>("Hotkey", "kysModifierToggle", true, "Require modifier to be held with kysKey to trigger death.");
KysModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkey", "kysModifier", (KeyCode)308, "Modifier key for death.");
KysKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkey", "kysKey", (KeyCode)100, "Key that triggers death.");
ToggleModifierRequired = ((BaseUnityPlugin)this).Config.Bind<bool>("Toggle", "kysToggleModifierToggle", true, "Require modifier to toggle the suicide system.");
ToggleModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Toggle", "kysToggleModifier", (KeyCode)308, "Modifier key for toggling.");
ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Toggle", "kysToggleKey", (KeyCode)115, "Key to toggle suicide system.");
HideAllNotifications = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "HideAllNotifications", false, "Hide on-screen K.Y.S alerts.");
KeepOnNotifierUntilOff = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "KeepOnNotifierUntilOff", true, "If on, the K.Y.S ON text stays on screen until suicide is toggled off. If off, ON fades like OFF.");
PreviewBothNotifiers = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "PreviewBothNotifiers", false, "Show K.Y.S ON and K.Y.S OFF together so you can place, size, and recolor them. Edits apply immediately. Turn off when finished.");
PopupSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "PopupSeconds", 5f, "How long timed ON/OFF alerts stay on screen.");
OnColor = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "OnColor", "#FF0000", "K.Y.S ON alert color.");
OffColor = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "OffColor", "#00FF00", "K.Y.S OFF alert color.");
OnSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "OnSize", 80, "K.Y.S ON text size.");
OffSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "OffSize", 80, "K.Y.S OFF text size.");
OnPosX = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "OnPosX", 0f, "K.Y.S ON anchored X.");
OnPosY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "OnPosY", -200f, "K.Y.S ON anchored Y.");
OffPosX = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "OffPosX", 0f, "K.Y.S OFF anchored X.");
OffPosY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "OffPosY", -200f, "K.Y.S OFF anchored Y.");
BindLiveUi<bool>(HideAllNotifications);
BindLiveUi<bool>(KeepOnNotifierUntilOff);
BindLiveUi<bool>(PreviewBothNotifiers);
BindLiveUi<float>(PopupSeconds);
BindLiveUi<string>(OnColor);
BindLiveUi<string>(OffColor);
BindLiveUi<int>(OnSize);
BindLiveUi<int>(OffSize);
BindLiveUi<float>(OnPosX);
BindLiveUi<float>(OnPosY);
BindLiveUi<float>(OffPosX);
BindLiveUi<float>(OffPosY);
KysHud.Initialize(((Component)this).transform);
KysHud.ApplyLiveSettings();
((BaseUnityPlugin)this).Logger.LogInfo((object)"K.Y.S v1.1.0 loaded.");
}
private void OnDestroy()
{
KysHud.Shutdown();
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
}
private void Update()
{
KysHud.Tick();
if (!IsGameplayInputBlocked())
{
if (WasPressed(ToggleKey, ToggleModifier, ToggleModifierRequired))
{
ToggleSuicide();
}
if (SuicideEnabled && WasPressed(KysKey, KysModifier, KysModifierToggle))
{
KillYourself();
}
}
}
private void ToggleSuicide()
{
SuicideEnabled = !SuicideEnabled;
((BaseUnityPlugin)this).Logger.LogInfo((object)("KYS: Suicide ability toggled " + (SuicideEnabled ? "ON" : "OFF")));
if (!KysHud.Previewing)
{
if (SuicideEnabled)
{
KysHud.ShowOn();
}
else
{
KysHud.ShowOff();
}
}
}
private static void BindLiveUi<T>(ConfigEntry<T> entry)
{
if (entry != null)
{
entry.SettingChanged += delegate
{
KysHud.ApplyLiveSettings();
};
}
}
private void KillYourself()
{
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || localCharacter.data.dead || (Object)(object)localCharacter.view == (Object)null)
{
return;
}
try
{
Character.Die();
((BaseUnityPlugin)this).Logger.LogInfo((object)"KYS: Suicide triggered.");
}
catch (Exception ex)
{
if (!_loggedDieFailure)
{
_loggedDieFailure = true;
((BaseUnityPlugin)this).Logger.LogError((object)("KYS: Die failed once: " + ex));
}
}
}
private static bool WasPressed(ConfigEntry<KeyCode> key, ConfigEntry<KeyCode> modifier, ConfigEntry<bool> requireModifier)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
if (key == null || (int)key.Value == 0)
{
return false;
}
if (!Input.GetKeyDown(key.Value))
{
return false;
}
if (requireModifier != null && requireModifier.Value)
{
if (modifier != null && (int)modifier.Value != 0)
{
return Input.GetKey(modifier.Value);
}
return false;
}
return true;
}
private static bool IsGameplayInputBlocked()
{
try
{
if (GUIManager.InPauseMenu)
{
return true;
}
GUIManager instance = GUIManager.instance;
return (Object)(object)instance != (Object)null && instance.windowBlockingInput;
}
catch
{
return false;
}
}
internal static Color ParseColor(ConfigEntry<string> entry, Color fallback)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
if (entry == null || string.IsNullOrWhiteSpace(entry.Value))
{
return fallback;
}
string text = entry.Value.Trim();
if (text.Length == 0 || text[0] != '#')
{
text = "#" + text;
}
Color result = default(Color);
if (ColorUtility.TryParseHtmlString(text, ref result))
{
return result;
}
return fallback;
}
}
internal static class KysHud
{
private sealed class AlertLabel
{
internal GameObject Root;
internal RectTransform Rect;
internal TextMeshProUGUI Label;
internal float HideAt;
}
private static readonly Color OnFallback = Color.red;
private static readonly Color OffFallback = Color.green;
private static GameObject _canvasObject;
private static AlertLabel _onAlert;
private static AlertLabel _offAlert;
private static TMP_FontAsset _cachedFont;
private static int _cachedSceneHandle = -1;
private static bool _previewing;
internal static bool Previewing => _previewing;
internal static void Initialize(Transform parent)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_canvasObject != (Object)null))
{
_canvasObject = new GameObject("KYSAlertCanvas");
if ((Object)(object)parent != (Object)null)
{
_canvasObject.transform.SetParent(parent, false);
}
Canvas obj = _canvasObject.AddComponent<Canvas>();
obj.renderMode = (RenderMode)0;
obj.sortingOrder = 9400;
obj.additionalShaderChannels = (AdditionalCanvasShaderChannels)25;
CanvasScaler obj2 = _canvasObject.AddComponent<CanvasScaler>();
obj2.uiScaleMode = (ScaleMode)1;
obj2.referenceResolution = new Vector2(1920f, 1080f);
obj2.matchWidthOrHeight = 1f;
_onAlert = CreateAlert("OnAlert");
_offAlert = CreateAlert("OffAlert");
HideAll();
}
}
internal static void Shutdown()
{
if ((Object)(object)_canvasObject != (Object)null)
{
Object.Destroy((Object)(object)_canvasObject);
}
_canvasObject = null;
_onAlert = null;
_offAlert = null;
_cachedFont = null;
_cachedSceneHandle = -1;
_previewing = false;
}
internal static void Tick()
{
if (_onAlert == null)
{
return;
}
if (WantPreview())
{
if (!_previewing)
{
ApplyLiveSettings();
}
ApplyFont(_onAlert.Label);
ApplyFont(_offAlert.Label);
return;
}
if (_previewing)
{
_previewing = false;
RestoreFromSuicideState();
return;
}
if (Plugin.SuicideEnabled && PersistOn())
{
if (NotificationsHidden())
{
Hide(_onAlert);
}
else if (!_onAlert.Root.activeSelf)
{
ShowOn();
}
else
{
ApplyFont(_onAlert.Label);
}
}
else
{
HideIfExpired(_onAlert);
}
HideIfExpired(_offAlert);
}
internal static void ApplyLiveSettings()
{
if (_onAlert == null)
{
return;
}
if (WantPreview())
{
ShowPreviewBoth();
return;
}
if (_previewing)
{
_previewing = false;
RestoreFromSuicideState();
return;
}
if (NotificationsHidden())
{
HideAll();
return;
}
if (_onAlert.Root.activeSelf)
{
ApplyAppearance(_onAlert, on: true);
if (Plugin.SuicideEnabled && PersistOn())
{
_onAlert.HideAt = float.PositiveInfinity;
}
else if (Plugin.SuicideEnabled)
{
_onAlert.HideAt = Time.unscaledTime + PopupDuration();
}
}
else if (Plugin.SuicideEnabled && PersistOn())
{
ShowOn();
}
if (_offAlert.Root.activeSelf)
{
ApplyAppearance(_offAlert, on: false);
}
}
internal static void ShowOn()
{
if (WantPreview())
{
ShowPreviewBoth();
return;
}
if (NotificationsHidden())
{
HideAll();
return;
}
Hide(_offAlert);
ForceShow(_onAlert, on: true, PersistOn());
}
internal static void ShowOff()
{
if (WantPreview())
{
ShowPreviewBoth();
return;
}
Hide(_onAlert);
if (!NotificationsHidden())
{
ForceShow(_offAlert, on: false, persist: false);
}
}
private static bool PersistOn()
{
if (Plugin.KeepOnNotifierUntilOff != null)
{
return Plugin.KeepOnNotifierUntilOff.Value;
}
return true;
}
private static bool NotificationsHidden()
{
if (Plugin.HideAllNotifications != null)
{
return Plugin.HideAllNotifications.Value;
}
return false;
}
private static bool WantPreview()
{
if (Plugin.PreviewBothNotifiers != null)
{
return Plugin.PreviewBothNotifiers.Value;
}
return false;
}
private static void ShowPreviewBoth()
{
_previewing = true;
ForceShow(_onAlert, on: true, persist: true);
ForceShow(_offAlert, on: false, persist: true);
}
private static void RestoreFromSuicideState()
{
if (NotificationsHidden())
{
HideAll();
}
else if (Plugin.SuicideEnabled)
{
ShowOn();
}
else
{
HideAll();
}
}
private static void ForceShow(AlertLabel alert, bool on, bool persist)
{
if (alert != null && !((Object)(object)alert.Label == (Object)null))
{
ApplyAppearance(alert, on);
alert.Root.SetActive(true);
alert.HideAt = (persist ? float.PositiveInfinity : (Time.unscaledTime + PopupDuration()));
}
}
private static void ApplyAppearance(AlertLabel alert, bool on)
{
//IL_0086: 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)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
if (alert != null && !((Object)(object)alert.Label == (Object)null))
{
((TMP_Text)alert.Label).text = (on ? "K.Y.S ON" : "K.Y.S OFF");
((TMP_Text)alert.Label).fontSize = ((!on) ? ((Plugin.OffSize != null) ? Plugin.OffSize.Value : 80) : ((Plugin.OnSize != null) ? Plugin.OnSize.Value : 80));
((Graphic)alert.Label).color = (on ? Plugin.ParseColor(Plugin.OnColor, OnFallback) : Plugin.ParseColor(Plugin.OffColor, OffFallback));
ApplyFont(alert.Label);
alert.Rect.anchoredPosition = (on ? Pos(Plugin.OnPosX, Plugin.OnPosY, 0f, -200f) : Pos(Plugin.OffPosX, Plugin.OffPosY, 0f, -200f));
}
}
private static float PopupDuration()
{
if (Plugin.PopupSeconds == null)
{
return 5f;
}
return Mathf.Max(0.25f, Plugin.PopupSeconds.Value);
}
private static Vector2 Pos(ConfigEntry<float> x, ConfigEntry<float> y, float fallbackX, float fallbackY)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
return new Vector2(x?.Value ?? fallbackX, y?.Value ?? fallbackY);
}
private static void HideIfExpired(AlertLabel alert)
{
if (alert != null && alert.Root.activeSelf && Time.unscaledTime >= alert.HideAt)
{
Hide(alert);
}
}
private static void Hide(AlertLabel alert)
{
if (alert != null && (Object)(object)alert.Root != (Object)null)
{
alert.Root.SetActive(false);
}
}
private static void HideAll()
{
Hide(_onAlert);
Hide(_offAlert);
}
private static AlertLabel CreateAlert(string name)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject(name, new Type[2]
{
typeof(RectTransform),
typeof(CanvasRenderer)
});
val.transform.SetParent(_canvasObject.transform, false);
RectTransform component = val.GetComponent<RectTransform>();
component.anchorMin = new Vector2(0.5f, 0.5f);
component.anchorMax = new Vector2(0.5f, 0.5f);
component.pivot = new Vector2(0.5f, 0.5f);
component.sizeDelta = new Vector2(900f, 120f);
TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
((TMP_Text)val2).fontStyle = (FontStyles)0;
((Graphic)val2).raycastTarget = false;
((TMP_Text)val2).enableWordWrapping = false;
((TMP_Text)val2).overflowMode = (TextOverflowModes)0;
ApplyFont(val2);
val.SetActive(false);
return new AlertLabel
{
Root = val,
Rect = component,
Label = val2
};
}
private static void ApplyFont(TextMeshProUGUI text)
{
if (!((Object)(object)text == (Object)null))
{
TMP_FontAsset gameFont = GetGameFont();
if ((Object)(object)gameFont != (Object)null)
{
((TMP_Text)text).font = gameFont;
}
((TMP_Text)text).fontStyle = (FontStyles)0;
}
}
private static TMP_FontAsset GetGameFont()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
int num = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle);
if ((Object)(object)_cachedFont != (Object)null && _cachedSceneHandle == num)
{
return _cachedFont;
}
try
{
if ((Object)(object)GUIManager.instance != (Object)null)
{
TextMeshProUGUI componentInChildren = ((Component)GUIManager.instance).GetComponentInChildren<TextMeshProUGUI>(true);
if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((TMP_Text)componentInChildren).font != (Object)null)
{
_cachedFont = ((TMP_Text)componentInChildren).font;
_cachedSceneHandle = num;
return _cachedFont;
}
}
}
catch
{
}
try
{
TextMeshProUGUI val = Object.FindFirstObjectByType<TextMeshProUGUI>((FindObjectsInactive)1);
if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null)
{
_cachedFont = ((TMP_Text)val).font;
_cachedSceneHandle = num;
return _cachedFont;
}
}
catch
{
}
return _cachedFont;
}
}
}