Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DeathTunes v1.1.2
DeathTunes/DeathTunes.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalNetworkAPI; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("DeathTunes")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DeathTunes")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3bc8e91e-4245-4e07-9d3d-f9b30954ac9d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] internal class EmptyMonoBehaviour : MonoBehaviour { } namespace DeathTunes; public static class DeathCustomizationManager { private class ButtonHoverHandler : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { public Image Background; public TextMeshProUGUI Text; public bool IsArrow; public Color NormalBackgroundColor; public Color HoverBackgroundColor; public Color NormalTextColor; public Color HoverTextColor; public void OnPointerEnter(PointerEventData eventData) { //IL_0024: 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 (!IsArrow) { if ((Object)(object)Background != (Object)null) { ((Graphic)Background).color = HoverBackgroundColor; } if ((Object)(object)Text != (Object)null) { ((Graphic)Text).color = HoverTextColor; } } } public void OnPointerExit(PointerEventData eventData) { //IL_0018: 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) if ((Object)(object)Background != (Object)null) { ((Graphic)Background).color = NormalBackgroundColor; } if ((Object)(object)Text != (Object)null) { ((Graphic)Text).color = NormalTextColor; } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__28_0; public static UnityAction <>9__28_1; internal void <CreateMenu>b__28_0() { PreviousSound(); UpdateMenuDisplay(); } internal void <CreateMenu>b__28_1() { NextSound(); UpdateMenuDisplay(); } } public static Dictionary<string, AudioClip> Sounds = new Dictionary<string, AudioClip>(); public static List<string> SoundIDs = new List<string>(); public static string SelectedSound = ""; private static int soundIndex = 0; public static string PendingSoundSelection = null; private static GameObject menu; private static TextMeshProUGUI soundNameText; private static TextMeshProUGUI soundCounterText; private static Button previousButton; private static Button nextButton; private static Button previewButton; private static Button saveButton; private static Button closeButton; private static bool menuCreated = false; private static TMP_FontAsset gameFont; private static readonly Color BackgroundColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)235)); private static readonly Color PanelColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue)); private static readonly Color RedColor = Color32.op_Implicit(new Color32((byte)247, (byte)0, (byte)7, byte.MaxValue)); private static readonly Color SecondaryRedColor = Color32.op_Implicit(new Color32((byte)240, (byte)0, (byte)7, (byte)250)); private static readonly Color BlackColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue)); private static readonly Color WhiteColor = Color32.op_Implicit(new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)); private static readonly Color DisabledColor = Color32.op_Implicit(new Color32((byte)45, (byte)45, (byte)45, (byte)180)); public static int CurrentSoundIndex => soundIndex; private static void LoadGameFont() { if ((Object)(object)gameFont != (Object)null) { return; } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); TMP_FontAsset[] array2 = array; foreach (TMP_FontAsset val in array2) { if (!((Object)(object)val == (Object)null) && ((Object)val).name.Equals("3270-Regular", StringComparison.OrdinalIgnoreCase)) { gameFont = val; break; } } if ((Object)(object)gameFont == (Object)null) { TMP_FontAsset[] array3 = array; foreach (TMP_FontAsset val2 in array3) { if (!((Object)(object)val2 == (Object)null) && ((Object)val2).name.IndexOf("3270", StringComparison.OrdinalIgnoreCase) >= 0) { gameFont = val2; break; } } } if ((Object)(object)gameFont != (Object)null) { DeathTunesPlugin.Log.LogInfo((object)("DeathTunes using game font: " + ((Object)gameFont).name)); } else { DeathTunesPlugin.Log.LogWarning((object)"3270-Regular font could not be found. Using default TMP font."); } } private static void SendPlayerSound(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { ulong playerSteamId = player.playerSteamId; DeathTunesPlugin.Log.LogInfo((object)("Sending sound '" + SelectedSound + "' for SteamID " + playerSteamId)); DeathSoundNetworking.SendSelection(playerSteamId, SelectedSound); } } public static void LoadSounds() { LoadGameFont(); string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); List<string> list = new List<string>(); DeathTunesPlugin.Log.LogInfo((object)"Searching for death sounds..."); string path = Path.Combine(directoryName, "Sounds"); if (Directory.Exists(path)) { list.AddRange(Directory.GetFiles(path, "*.wav", SearchOption.AllDirectories)); } list.AddRange(Directory.GetFiles(directoryName, "*.wav", SearchOption.TopDirectoryOnly)); list = list.Distinct().ToList(); foreach (string item in list) { AudioClip val = DeathTunesPlugin.Instance.LoadWav(item); if ((Object)(object)val != (Object)null) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item); if (!Sounds.ContainsKey(fileNameWithoutExtension)) { Sounds.Add(fileNameWithoutExtension, val); SoundIDs.Add(fileNameWithoutExtension); DeathTunesPlugin.Log.LogInfo((object)("Loaded death sound: " + fileNameWithoutExtension)); } } } if (SoundIDs.Count > 0) { string value = DeathTunesPlugin.SavedDeathSound.Value; if (!string.IsNullOrEmpty(value) && Sounds.ContainsKey(value)) { SelectedSound = value; soundIndex = SoundIDs.IndexOf(value); if (soundIndex < 0) { soundIndex = 0; } } else { SelectedSound = SoundIDs[0]; soundIndex = 0; } } DeathTunesPlugin.Log.LogInfo((object)("Total death sounds loaded: " + Sounds.Count)); } public static void OpenMenu() { if ((Object)(object)menu != (Object)null) { menu.SetActive(true); UpdateMenuDisplay(); } else { CreateMenu(); menu.SetActive(true); UpdateMenuDisplay(); } } private static void CreateMenu() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Expected O, but got Unknown //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Expected O, but got Unknown //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Expected O, but got Unknown //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Expected O, but got Unknown //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Expected O, but got Unknown if (menuCreated) { return; } menuCreated = true; LoadGameFont(); menu = new GameObject("DeathTunesMenu"); Canvas val = menu.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 5000; CanvasScaler val2 = menu.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); val2.screenMatchMode = (ScreenMatchMode)0; val2.matchWidthOrHeight = 0.5f; menu.AddComponent<GraphicRaycaster>(); Object.DontDestroyOnLoad((Object)(object)menu); GameObject val3 = CreatePanel(menu.transform, Vector2.zero, Vector2.zero, BackgroundColor); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; GameObject val4 = CreatePanel(menu.transform, new Vector2(760f, 570f), Vector2.zero, PanelColor); AddBorder(val4, RedColor, 2f); GameObject val5 = CreateText(val4.transform, "DEATHTUNES", 44, new Vector2(0f, 215f), RedColor); TextMeshProUGUI component2 = val5.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component2).fontStyle = (FontStyles)1; ((TMP_Text)component2).characterSpacing = 3f; GameObject val6 = CreateText(val4.transform, "DEATH SOUND CUSTOMIZATION", 20, new Vector2(0f, 175f), RedColor); ((TMP_Text)val6.GetComponent<TextMeshProUGUI>()).fontStyle = (FontStyles)1; CreateDivider(val4.transform, new Vector2(0f, 145f)); GameObject val7 = CreateText(val4.transform, "SELECT SOUND", 21, new Vector2(0f, 112f), RedColor); ((TMP_Text)val7.GetComponent<TextMeshProUGUI>()).fontStyle = (FontStyles)1; GameObject val8 = CreatePanel(val4.transform, new Vector2(500f, 100f), new Vector2(0f, 48f), BlackColor); AddBorder(val8, RedColor, 1f); GameObject val9 = CreateText(val8.transform, "", 30, Vector2.zero, RedColor); soundNameText = val9.GetComponent<TextMeshProUGUI>(); ((TMP_Text)soundNameText).fontStyle = (FontStyles)1; ((TMP_Text)soundNameText).enableWordWrapping = false; ((TMP_Text)soundNameText).overflowMode = (TextOverflowModes)1; previousButton = CreateStyledButton(val4.transform, "‹", new Vector2(-315f, 48f), new Vector2(70f, 70f)); ButtonClickedEvent onClick = previousButton.onClick; object obj = <>c.<>9__28_0; if (obj == null) { UnityAction val10 = delegate { PreviousSound(); UpdateMenuDisplay(); }; <>c.<>9__28_0 = val10; obj = (object)val10; } ((UnityEvent)onClick).AddListener((UnityAction)obj); nextButton = CreateStyledButton(val4.transform, "›", new Vector2(315f, 48f), new Vector2(70f, 70f)); ButtonClickedEvent onClick2 = nextButton.onClick; object obj2 = <>c.<>9__28_1; if (obj2 == null) { UnityAction val11 = delegate { NextSound(); UpdateMenuDisplay(); }; <>c.<>9__28_1 = val11; obj2 = (object)val11; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); GameObject val12 = CreateText(val4.transform, "", 17, new Vector2(0f, -18f), SecondaryRedColor); soundCounterText = val12.GetComponent<TextMeshProUGUI>(); ((TMP_Text)soundCounterText).fontStyle = (FontStyles)1; previewButton = CreateStyledButton(val4.transform, "> PREVIEW SOUND", new Vector2(0f, -72f), new Vector2(300f, 48f)); ((UnityEvent)previewButton.onClick).AddListener(new UnityAction(PlaySelectedSound)); CreateDivider(val4.transform, new Vector2(0f, -115f)); saveButton = CreateStyledButton(val4.transform, "> SAVE", new Vector2(-125f, -165f), new Vector2(190f, 50f)); ((UnityEvent)saveButton.onClick).AddListener(new UnityAction(SaveSelection)); closeButton = CreateStyledButton(val4.transform, "> CLOSE", new Vector2(125f, -165f), new Vector2(190f, 50f)); ((UnityEvent)closeButton.onClick).AddListener(new UnityAction(CloseMenu)); menu.SetActive(false); } private static void UpdateMenuDisplay() { if ((Object)(object)soundNameText == (Object)null) { return; } if (SoundIDs.Count == 0) { ((TMP_Text)soundNameText).text = "NO SOUNDS FOUND"; if ((Object)(object)soundCounterText != (Object)null) { ((TMP_Text)soundCounterText).text = "0 / 0"; } SetButtonInteractable(previousButton, interactable: false); SetButtonInteractable(nextButton, interactable: false); SetButtonInteractable(previewButton, interactable: false); SetButtonInteractable(saveButton, interactable: false); return; } if (soundIndex < 0) { soundIndex = 0; } if (soundIndex >= SoundIDs.Count) { soundIndex = 0; } SelectedSound = SoundIDs[soundIndex]; ((TMP_Text)soundNameText).text = FormatSoundName(SelectedSound); if ((Object)(object)soundCounterText != (Object)null) { ((TMP_Text)soundCounterText).text = "SOUND " + (soundIndex + 1) + " / " + SoundIDs.Count; } SetButtonInteractable(previousButton, SoundIDs.Count > 1); SetButtonInteractable(nextButton, SoundIDs.Count > 1); SetButtonInteractable(previewButton, interactable: true); SetButtonInteractable(saveButton, interactable: true); } private static void SaveSelection() { DeathTunesPlugin.Log.LogInfo((object)"Saving death sound..."); DeathTunesPlugin.Log.LogInfo((object)("Selected sound: " + SelectedSound)); DeathTunesPlugin.SavedDeathSound.Value = SelectedSound; if ((Object)(object)GameNetworkManager.Instance == (Object)null) { DeathTunesPlugin.Log.LogWarning((object)"GameNetworkManager not initialized yet."); PendingSoundSelection = SelectedSound; return; } PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { DeathTunesPlugin.Log.LogWarning((object)"Local player controller not available. Saving locally for later."); PendingSoundSelection = SelectedSound; } else { SendPlayerSound(localPlayerController); } } public static void CloseMenu() { DeathTunesPlugin.Log.LogInfo((object)"Closing DeathTunes customization menu."); if ((Object)(object)menu != (Object)null) { menu.SetActive(false); } } public static void NextSound() { if (SoundIDs.Count != 0) { soundIndex++; if (soundIndex >= SoundIDs.Count) { soundIndex = 0; } SelectedSound = SoundIDs[soundIndex]; DeathTunesPlugin.Log.LogInfo((object)("Changed selected sound to: " + SelectedSound)); } } public static void PreviousSound() { if (SoundIDs.Count != 0) { soundIndex--; if (soundIndex < 0) { soundIndex = SoundIDs.Count - 1; } SelectedSound = SoundIDs[soundIndex]; DeathTunesPlugin.Log.LogInfo((object)("Changed selected sound to: " + SelectedSound)); } } private static void PlaySelectedSound() { DeathTunesPlugin.Log.LogInfo((object)("Previewing death sound: " + SelectedSound)); if (Sounds.ContainsKey(SelectedSound)) { DeathTunesPlugin.PlayClip(Sounds[SelectedSound]); } else { DeathTunesPlugin.Log.LogWarning((object)("Cannot preview sound. Sound not found: " + SelectedSound)); } } private static GameObject CreatePanel(Transform parent, Vector2 size, Vector2 position, Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Panel"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = size; val2.anchoredPosition = position; Image val3 = val.AddComponent<Image>(); ((Graphic)val3).color = color; return val; } private static GameObject CreateText(Transform parent, string value, int size, Vector2 position, Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_009a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Text"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = new Vector2(600f, 50f); val2.anchoredPosition = position; TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val3).text = value; ((TMP_Text)val3).fontSize = size; ((Graphic)val3).color = color; ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; ((TMP_Text)val3).enableWordWrapping = true; ((Graphic)val3).raycastTarget = false; if ((Object)(object)gameFont != (Object)null) { ((TMP_Text)val3).font = gameFont; } return val; } private static Button CreateStyledButton(Transform parent, string value, Vector2 position, Vector2 size) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Button"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = size; val2.anchoredPosition = position; GameObject val3 = new GameObject("Border"); val3.transform.SetParent(val.transform, false); RectTransform val4 = val3.AddComponent<RectTransform>(); val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; Image val5 = val3.AddComponent<Image>(); ((Graphic)val5).color = RedColor; ((Graphic)val5).raycastTarget = false; GameObject val6 = new GameObject("Background"); val6.transform.SetParent(val.transform, false); RectTransform val7 = val6.AddComponent<RectTransform>(); val7.anchorMin = Vector2.zero; val7.anchorMax = Vector2.one; val7.offsetMin = new Vector2(2f, 2f); val7.offsetMax = new Vector2(-2f, -2f); Image val8 = val6.AddComponent<Image>(); ((Graphic)val8).color = BlackColor; Button val9 = val.AddComponent<Button>(); ((Selectable)val9).transition = (Transition)0; ((Selectable)val9).targetGraphic = (Graphic)(object)val8; bool flag = value == "‹" || value == "›"; Color color = (flag ? WhiteColor : RedColor); GameObject val10 = CreateText(val6.transform, value, flag ? 38 : 18, Vector2.zero, color); TextMeshProUGUI component = val10.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).fontStyle = (FontStyles)1; ((Graphic)component).raycastTarget = false; ButtonHoverHandler buttonHoverHandler = val.AddComponent<ButtonHoverHandler>(); buttonHoverHandler.Background = val8; buttonHoverHandler.Text = component; buttonHoverHandler.IsArrow = flag; buttonHoverHandler.NormalBackgroundColor = BlackColor; buttonHoverHandler.HoverBackgroundColor = RedColor; buttonHoverHandler.NormalTextColor = (flag ? WhiteColor : RedColor); buttonHoverHandler.HoverTextColor = (flag ? WhiteColor : BlackColor); return val9; } private static void AddBorder(GameObject target, Color color, float thickness) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Outline val = target.AddComponent<Outline>(); ((Shadow)val).effectColor = color; ((Shadow)val).effectDistance = new Vector2(thickness, thickness); ((Shadow)val).useGraphicAlpha = true; } private static void CreateDivider(Transform parent, Vector2 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Divider"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = new Vector2(600f, 1f); val2.anchoredPosition = position; Image val3 = val.AddComponent<Image>(); ((Graphic)val3).color = Color32.op_Implicit(new Color32((byte)247, (byte)0, (byte)7, (byte)180)); } private static void SetButtonInteractable(Button button, bool interactable) { if (!((Object)(object)button == (Object)null)) { ((Selectable)button).interactable = interactable; } } private static string FormatSoundName(string id) { if (string.IsNullOrEmpty(id)) { return "UNKNOWN SOUND"; } string text = id.Replace("_", " ").Replace("-", " "); string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (array[i].Length != 0) { array[i] = char.ToUpper(array[i][0]) + ((array[i].Length > 1) ? array[i].Substring(1).ToLower() : ""); } } return string.Join(" ", array).ToUpper(); } } public static class DeathCustomizationMenuUtils { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__0_0; public static Func<Button, GameObject> <>9__0_1; public static Func<GameObject, float> <>9__0_3; public static Func<float, float, float> <>9__0_4; internal void <InjectMenu>b__0_0() { DeathCustomizationManager.OpenMenu(); } internal GameObject <InjectMenu>b__0_1(Button b) { return ((Component)b).gameObject; } internal float <InjectMenu>b__0_3(GameObject b) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return b.GetComponent<RectTransform>().anchoredPosition.y; } internal float <InjectMenu>b__0_4(float a, float b) { return Mathf.Abs(b - a); } } public static void InjectMenu(Transform mainButtonsTransform, GameObject quitButton) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) DeathTunesPlugin.Log.LogInfo((object)"Injecting DeathTunes button..."); DeathCustomizationManager.OpenMenu(); DeathCustomizationManager.CloseMenu(); GameObject deathButton = Object.Instantiate<GameObject>(quitButton, mainButtonsTransform); ((Object)deathButton).name = "DeathTunesButton"; Button component = deathButton.GetComponent<Button>(); ((UnityEventBase)component.onClick).RemoveAllListeners(); component.onClick = new ButtonClickedEvent(); ButtonClickedEvent onClick = component.onClick; object obj = <>c.<>9__0_0; if (obj == null) { UnityAction val = delegate { DeathCustomizationManager.OpenMenu(); }; <>c.<>9__0_0 = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); TextMeshProUGUI componentInChildren = deathButton.GetComponentInChildren<TextMeshProUGUI>(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).text = "> Death Sounds"; } List<GameObject> source = (from b in ((Component)mainButtonsTransform).GetComponentsInChildren<Button>() select ((Component)b).gameObject).ToList(); List<float> list = (from b in source where (Object)(object)b != (Object)(object)deathButton select b.GetComponent<RectTransform>().anchoredPosition.y).ToList(); float num = 55f; if (list.Count >= 2) { num = list.Zip(list.Skip(1), (float a, float b) => Mathf.Abs(b - a)).Min(); } foreach (GameObject item in source.Where((GameObject g) => (Object)(object)g != (Object)(object)quitButton)) { RectTransform component2 = item.GetComponent<RectTransform>(); component2.anchoredPosition += new Vector2(0f, num); } RectTransform component3 = quitButton.GetComponent<RectTransform>(); RectTransform component4 = deathButton.GetComponent<RectTransform>(); component4.anchoredPosition = component3.anchoredPosition + new Vector2(0f, num); DeathTunesPlugin.Log.LogInfo((object)"DeathTunes button positioned successfully."); } } [HarmonyPatch(typeof(PlayerControllerB))] public class DeathPatch { [HarmonyPatch("Update")] [HarmonyPostfix] private static void CheckDeath(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { ulong playerSteamId = __instance.playerSteamId; bool isPlayerDead = __instance.isPlayerDead; bool value = false; DeathTunesPlugin.LastDeathState.TryGetValue(playerSteamId, out value); if (isPlayerDead && !value) { DeathTunesPlugin.Log.LogInfo((object)("DEATH DETECTED: Player " + playerSteamId)); PlayerDeathSoundManager.PlayPlayerDeathSound(__instance); } DeathTunesPlugin.LastDeathState[playerSteamId] = isPlayerDead; } } } public class SoundSelectionData { public ulong SteamID; public string SoundName; } public static class DeathSoundNetworking { public static readonly Dictionary<ulong, string> PlayerSounds = new Dictionary<ulong, string>(); public static LNetworkMessage<SoundSelectionData> SoundMessage; public static LNetworkMessage<string> RequestMessage; public static void Initialize() { SoundMessage = LNetworkMessage<SoundSelectionData>.Create("DeathSoundSelection", (Action<SoundSelectionData, ulong>)OnServerReceived, (Action<SoundSelectionData>)OnClientReceived, (Action<SoundSelectionData, ulong>)null); RequestMessage = LNetworkMessage<string>.Create("DeathSoundRequest", (Action<string, ulong>)OnRequestReceived, (Action<string>)null, (Action<string, ulong>)null); DeathTunesPlugin.Log.LogInfo((object)"Death sound networking initialized."); } public static void SendSelection(ulong steamID, string sound) { SoundSelectionData soundSelectionData = new SoundSelectionData { SteamID = steamID, SoundName = sound }; PlayerSounds[steamID] = sound; DeathTunesPlugin.Log.LogInfo((object)$"Sending sound selection: {steamID} -> {sound}"); SoundMessage.SendServer(soundSelectionData); } private static void OnServerReceived(SoundSelectionData data, ulong sender) { PlayerSounds[data.SteamID] = data.SoundName; DeathTunesPlugin.Log.LogInfo((object)$"Host stored sound: {data.SteamID} -> {data.SoundName}"); SoundMessage.SendClients(data); } private static void OnClientReceived(SoundSelectionData data) { PlayerSounds[data.SteamID] = data.SoundName; DeathTunesPlugin.Log.LogInfo((object)$"Client stored sound: {data.SteamID} -> {data.SoundName}"); } public static void RequestAllSounds() { DeathTunesPlugin.Log.LogInfo((object)"Requesting all death sounds..."); RequestMessage.SendServer(""); } private static void OnRequestReceived(string unused, ulong sender) { DeathTunesPlugin.Log.LogInfo((object)$"Sending all sounds to client {sender}"); Dictionary<ulong, string> dictionary = new Dictionary<ulong, string>(PlayerSounds); foreach (KeyValuePair<ulong, string> item in dictionary) { SoundSelectionData soundSelectionData = new SoundSelectionData { SteamID = item.Key, SoundName = item.Value }; SoundMessage.SendClient(soundSelectionData, sender); } DeathTunesPlugin.Log.LogInfo((object)$"Finished sending {dictionary.Count} sounds to client {sender}"); } public static void PrintDatabase() { DeathTunesPlugin.Log.LogInfo((object)"===== DEATH SOUND DATABASE ====="); foreach (KeyValuePair<ulong, string> playerSound in PlayerSounds) { DeathTunesPlugin.Log.LogInfo((object)$"{playerSound.Key} -> {playerSound.Value}"); } } } [BepInPlugin("ryang.deathtunes", "DeathTunes", "0.1.0")] public class DeathTunesPlugin : BaseUnityPlugin { public static DeathTunesPlugin Instance; public static ManualLogSource Log; public static AudioSource AudioSource; public static ConfigEntry<string> SavedDeathSound; public static Dictionary<ulong, bool> LastDeathState = new Dictionary<ulong, bool>(); private void Awake() { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; SavedDeathSound = ((BaseUnityPlugin)this).Config.Bind<string>("DeathTunes", "SelectedDeathSound", "", "The selected death sound for this player."); Log.LogInfo((object)"DeathTunes starting..."); Log.LogInfo((object)("DLL location: " + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))); DeathCustomizationManager.LoadSounds(); DeathSoundNetworking.Initialize(); Harmony val = new Harmony("ryang.deathtunes"); val.PatchAll(); ((MonoBehaviour)this).StartCoroutine(CreateAudioSource()); Log.LogInfo((object)"DeathTunes loaded!"); } private void Update() { if (DeathCustomizationManager.PendingSoundSelection == null) { return; } Log.LogInfo((object)("DeathTunes pending sound: " + DeathCustomizationManager.PendingSoundSelection)); if ((Object)(object)StartOfRound.Instance == (Object)null) { Log.LogInfo((object)"Waiting for StartOfRound..."); return; } Log.LogInfo((object)"StartOfRound exists"); PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { Log.LogInfo((object)"Waiting for local player..."); return; } Log.LogInfo((object)"Local player found!"); ulong playerSteamId = localPlayerController.playerSteamId; DeathSoundNetworking.SendSelection(playerSteamId, DeathCustomizationManager.PendingSoundSelection); Log.LogInfo((object)("Sent sound " + DeathCustomizationManager.PendingSoundSelection + " for SteamID " + playerSteamId)); DeathCustomizationManager.PendingSoundSelection = null; } private IEnumerator CreateAudioSource() { yield return (object)new WaitForSeconds(3f); CreateAudioObject(); Log.LogInfo((object)"DeathTunes AudioSource created"); } public static void CreateAudioObject() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)AudioSource != (Object)null)) { GameObject val = new GameObject("DeathTunesAudio"); Object.DontDestroyOnLoad((Object)(object)val); AudioSource = val.AddComponent<AudioSource>(); AudioSource.playOnAwake = false; AudioSource.loop = false; AudioSource.spatialBlend = 0f; AudioSource.volume = 1f; AudioSource.ignoreListenerVolume = true; AudioSource.priority = 0; } } public static AudioClip LoadWavPublic(string path) { return Instance.LoadWav(path); } public AudioClip LoadWav(string path) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 try { UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip("file:///" + path, (AudioType)20); UnityWebRequestAsyncOperation val = audioClip.SendWebRequest(); while (!((AsyncOperation)val).isDone) { Thread.Sleep(10); } if ((int)audioClip.result != 1) { Log.LogError((object)audioClip.error); return null; } AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip); ((Object)content).name = Path.GetFileNameWithoutExtension(path); return content; } catch (Exception ex) { Log.LogError((object)ex.Message); return null; } } public static void PlayClip(AudioClip clip) { if ((Object)(object)clip == (Object)null) { Log.LogError((object)"Tried to play NULL clip"); return; } if ((Object)(object)AudioSource == (Object)null) { CreateAudioObject(); } AudioSource.Stop(); AudioSource.clip = clip; AudioSource.volume = 1f; AudioSource.Play(); Log.LogInfo((object)("Playing death sound: " + ((Object)clip).name)); } } [HarmonyPatch(typeof(MenuManager))] public class MainMenuPatch { [HarmonyPatch("Start")] [HarmonyPostfix] public static void Start(MenuManager __instance) { if (!__instance.isInitScene) { DeathTunesPlugin.Log.LogInfo((object)"DeathTunes injecting menu..."); ((MonoBehaviour)__instance).StartCoroutine(DelayedInjection()); } } private static IEnumerator DelayedInjection() { yield return (object)new WaitForSeconds(1f); InjectMenu(); } private static void InjectMenu() { GameObject val = GameObject.Find("MenuContainer"); if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.transform.Find("MainButtons"); if (!((Object)(object)val2 == (Object)null)) { Transform val3 = val2.Find("QuitButton"); if ((Object)(object)val3 == (Object)null) { DeathTunesPlugin.Log.LogError((object)"QuitButton missing!"); } else { DeathCustomizationMenuUtils.InjectMenu(val2, ((Component)val3).gameObject); } } } } [HarmonyPatch(typeof(StartOfRound))] public class PlayerConnectionPatch { private static bool hasSynced; [HarmonyPatch("Start")] [HarmonyPostfix] public static void OnGameStart(StartOfRound __instance) { if (!hasSynced) { hasSynced = true; DeathTunesPlugin.Log.LogInfo((object)"DeathTunes player connection sync started."); ((MonoBehaviour)__instance).StartCoroutine(DelayedSync()); } } private static IEnumerator DelayedSync() { yield return (object)new WaitForSeconds(3f); PlayerControllerB player = StartOfRound.Instance.localPlayerController; if ((Object)(object)player == (Object)null) { DeathTunesPlugin.Log.LogWarning((object)"Cannot sync death sound. Local player missing."); yield break; } ulong steamID = player.playerSteamId; DeathTunesPlugin.Log.LogInfo((object)$"Local player found. SteamID: {steamID}"); if (!string.IsNullOrEmpty(DeathTunesPlugin.SavedDeathSound.Value)) { DeathSoundNetworking.SendSelection(steamID, DeathTunesPlugin.SavedDeathSound.Value); DeathTunesPlugin.Log.LogInfo((object)"Sent saved death sound."); } else { DeathTunesPlugin.Log.LogInfo((object)"No saved death sound found."); } DeathSoundNetworking.RequestAllSounds(); DeathTunesPlugin.Log.LogInfo((object)"Requested all player death sounds."); } [HarmonyPatch("OnDestroy")] [HarmonyPostfix] public static void OnDestroy() { hasSynced = false; DeathTunesPlugin.Log.LogInfo((object)"DeathTunes player sync reset."); } } public static class PlayerDeathSoundManager { public static void PlayPlayerDeathSound(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return; } ulong playerSteamId = player.playerSteamId; DeathTunesPlugin.Log.LogInfo((object)$"Looking up death sound for SteamID: {playerSteamId}"); AudioClip val = null; if (DeathSoundNetworking.PlayerSounds.TryGetValue(playerSteamId, out var value)) { DeathTunesPlugin.Log.LogInfo((object)$"Found sound entry: {playerSteamId} -> {value}"); if (DeathCustomizationManager.Sounds.ContainsKey(value)) { val = DeathCustomizationManager.Sounds[value]; } else { DeathTunesPlugin.Log.LogWarning((object)("Sound file does not exist: " + value)); } } else { DeathTunesPlugin.Log.LogWarning((object)$"No sound registered for SteamID: {playerSteamId}"); } if ((Object)(object)val == (Object)null && (Object)(object)player == (Object)(object)StartOfRound.Instance.localPlayerController) { string value2 = DeathTunesPlugin.SavedDeathSound.Value; if (!string.IsNullOrEmpty(value2) && DeathCustomizationManager.Sounds.ContainsKey(value2)) { DeathTunesPlugin.Log.LogInfo((object)("Using local saved fallback sound: " + value2)); val = DeathCustomizationManager.Sounds[value2]; } } if ((Object)(object)val == (Object)null) { DeathTunesPlugin.Log.LogWarning((object)$"Could not find death sound for {playerSteamId}"); return; } DeathTunesPlugin.Log.LogInfo((object)$"Playing death sound for {playerSteamId}: {((Object)val).name}"); DeathTunesPlugin.PlayClip(val); } }