### Initialize Plugin with Automatic Music Pack Download in CSharp Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Implements the Main plugin class that handles lifecycle management, creates audio directories, automatically downloads and extracts the music pack from GitHub releases on first run, registers settings, and initializes event handlers. Uses WebClient to download a ZIP file, extracts it to the configured audio directory, and cleans up temporary files upon completion. ```csharp using Exiled.API.Features; using System.IO; using System.Net; using System.IO.Compression; namespace MVPMusic { public class Main : Plugin { public override string Name => "MVPMusic"; public static Main Instance { get; private set; } public static string AudioDirectoryPath { get; } = Path.Combine(Paths.Configs, "audio"); public override void OnEnabled() { Instance = this; // Create audio directory if it doesn't exist if (!Directory.Exists(AudioDirectoryPath)) { Log.Warn("Audio directory does not exist. Creating..."); Directory.CreateDirectory(AudioDirectoryPath); } // Download music pack on first run string MVPMusicDirectory = Path.Combine(AudioDirectoryPath, "MVPMusic"); if (!Directory.Exists(MVPMusicDirectory)) DownloadMVPMusic(MVPMusicDirectory); // Register settings and events SettingBase.Register(new[] { SettingsHeader }); MVPMusic.RegisterEvents(); base.OnEnabled(); } private void DownloadMVPMusic(string MVPMusicDirectory) { string MVPMusicZip = MVPMusicDirectory + ".zip"; string MVPMusicTemp = MVPMusicDirectory + "_Temp"; using WebClient client = new(); Log.Warn("Downloading MVPMusic.zip..."); client.DownloadFile( $"https://github.com/Vretu-Dev/MVPMusic/releases/download/{Version}/MVPMusic.zip", MVPMusicZip); Log.Info("MVPMusic.zip has been downloaded!"); ZipFile.ExtractToDirectory(MVPMusicZip, MVPMusicTemp); Directory.Move(Path.Combine(MVPMusicTemp, "MVPMusic"), MVPMusicDirectory); Directory.Delete(MVPMusicTemp); File.Delete(MVPMusicZip); Log.Info("Done!"); } } } ``` -------------------------------- ### Configure MVP Selection and Music Tracks in CSharp Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Defines the Config class implementing IConfig interface with properties for enabling/disabling the plugin, MVP selection method (FirstEscaper, TopKiller, etc.), hint message formatting with placeholders, music dropdown menu ID, and a dictionary mapping track names to audio file paths. This allows server administrators to customize MVP determination criteria and available music selections. ```csharp using Exiled.API.Interfaces; using System.Collections.Generic; namespace MVPMusic { public class Config : IConfig { public bool IsEnabled { get; set; } = true; public bool Debug { get; set; } = false; public string Mvp { get; set; } = "FirstEscaper"; public string Mvphint { get; set; } = "Round MVP:{Nickname} as {Scenario}"; public int MusicDropdownId { get; set; } = 101; public Dictionary MusicList { get; set; } = new Dictionary { { "Example Music", "MVPMusic/example" }, { "Another Example Music", "MVPMusic/example2" } }; } } ``` -------------------------------- ### Configure MVP Settings in YAML Format Source: https://context7.com/vretu-dev/mvpmusic/llms.txt YAML configuration file format for MVPMusic plugin settings including enabled status, debug mode, MVP selection method (TopKiller), hint message with HTML formatting, music dropdown menu ID, and music list mapping track names to audio file paths. This format is parsed by the plugin's configuration system to apply server-wide settings. ```yaml MVPMusic: is_enabled: true debug: false mvp: 'TopKiller' mvphint: 'Round MVP:{Nickname} as {Scenario}' music_dropdown_id: 101 music_list: 'Custom Track 1': 'MVPMusic/custom1' 'Epic Victory': 'MVPMusic/epicvictory' ``` -------------------------------- ### Define Default Music Mapping Dictionary in C# Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Creates a static readonly dictionary containing 70+ pre-mapped music tracks from CS:GO music kits for the MVPMusic plugin. Each entry maps a display-friendly track name (key) to its corresponding resource path (value) in the MVPMusic directory. This dictionary serves as the foundation for the music selection system available to players achieving MVP status on the server. ```csharp public static readonly Dictionary MusicMapping = new Dictionary { { "All for Dust", "MVPMusic/All-for-Dust" }, { "Bachram", "MVPMusic/Bachram" }, { "Desert Fire", "MVPMusic/Desert-Fire" }, { "Mocha Petal", "MVPMusic/Mocha-Petal" }, { "I Am By AWOLNATION", "MVPMusic/I-Am-By-AWOLNATION" }, { "u mad!", "MVPMusic/u-mad" }, { "Aggressive", "MVPMusic/Aggressive" }, { "The Good Youth", "MVPMusic/The-Good-Youth" }, { "Yellow Magic", "MVPMusic/Yellow-Magic" }, { "Crimson Assault", "MVPMusic/Crimson-Assault" }, { "Eye of the Dragon", "MVPMusic/Eye-of-the-Dragon" }, { "Total Domination", "MVPMusic/Total-Domination" }, { "Moments CSGO", "MVPMusic/Moments-CSGO" }, { "ULTIMATE", "MVPMusic/ULTIMATE" }, { "Gunman Taco", "MVPMusic/Gunman-Taco" }, { "Feel The Power", "MVPMusic/Feel-ThePower" }, { "High Noon", "MVPMusic/High-Noon" }, { "Vici", "MVPMusic/Vici" }, { "Void", "MVPMusic/Void" }, { "FREE", "MVPMusic/FREE" }, { "inhuman", "MVPMusic/inhuman" }, { "Astro Bellum", "MVPMusic/Astro-Bellum" }, { "Shooters", "MVPMusic/Shooters" }, { "Hazardous Environments", "MVPMusic/Hazardous-Environments" }, { "All Night", "MVPMusic/All-Night" }, { "MOLOTOV", "MVPMusic/MOLOTOV" }, { "dashstar", "MVPMusic/dashstar" }, { "Work Hard, Play Hard", "MVPMusic/Work-Hard" }, { "Java Havana", "MVPMusic/Java-Havana" }, { "For No Mankind", "MVPMusic/For-No-Mankind" }, { "IsoRhythm", "MVPMusic/IsoRhythm" }, { "Drifter", "MVPMusic/Drifter" }, { "Gothic Luxury", "MVPMusic/Gothic-Luxury" }, { "Invasion!", "MVPMusic/Invasion" }, { "All I Want for Christmas", "MVPMusic/All-I-Want-for-Christmas" }, { "Diamonds", "MVPMusic/Diamonds" }, { "Sharpened", "MVPMusic/Sharpened" }, { "Battlepack", "MVPMusic/Battlepack" }, { "Reason", "MVPMusic/Reason" }, { "Backbone", "MVPMusic/Backbone" }, { "Insurgency", "MVPMusic/Insurgency" }, { "Bodacious", "MVPMusic/Bodacious" }, { "KOLIBRI", "MVPMusic/KOLIBRI" }, { "King, Scar", "MVPMusic/King-Scar" }, { "A*D*8", "MVPMusic/AD8" }, { "Metal", "MVPMusic/Metal" }, { "II-Headshot", "MVPMusic/II-Headshot" }, { "III-Arena", "MVPMusic/III-Arena" }, { "Lock Me Up", "MVPMusic/Lock-Me-Up" }, { "EZ4ENCE", "MVPMusic/EZ4ENCE" }, { "Flashbang Dance", "MVPMusic/Flashbang-Dance" }, { "Neo Noir", "MVPMusic/Neo-Noir" }, { "M.U.D.D. FORCE", "MVPMusic/MUDD-FORCE" }, { "Uber Blasto Phone", "MVPMusic/Uber-Blasto-Phone" }, { "Under Bright Lights", "MVPMusic/Under-Bright-Lights" }, { "GLA", "MVPMusic/GLA" }, { "Hotline Miami", "MVPMusic/Hotline-Miami" }, { "Hades", "MVPMusic/Hades" }, { "Anti-Citizen", "MVPMusic/Anti-Citizen" }, { "The Master Chief", "MVPMusic/The-Master-Chief" }, { "Default CS:GO First", "MVPMusic/Default-CSGO" }, { "Default CS:GO Second", "MVPMusic/Default2-CSGO" }, { "Default CS:GO 2", "MVPMusic/Default-CSGO2" } }; ``` -------------------------------- ### Register Music Dropdown Setting (C#) Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Registers a dropdown setting for players to select their preferred MVP music. It builds a complete music list from defaults and custom additions, then creates a DropdownSetting that persists across rounds and updates player session variables on change. ```csharp using Exiled.API.Features.Core.UserSettings; using System.Linq; public static DropdownSetting MusicDropdownSetting { get; private set; } public static void RegisterEvents() { // Build complete music list from defaults + custom additions Dictionary completeMusicList = new Dictionary(MusicMapping); if (Main.Instance.Config.MusicList != null) { foreach (var kv in Main.Instance.Config.MusicList) { if (!kv.Key.Contains("Example Music")) { if (!completeMusicList.ContainsKey(kv.Key)) { completeMusicList.Add(kv.Key, kv.Value); } } } } // Create dropdown setting MusicDropdownSetting = new DropdownSetting( id: Main.Instance.Config.MusicDropdownId, label: Main.Instance.Translation.SettingLabel, options: completeMusicList.Keys.Cast().ToArray(), defaultOptionIndex: 0, dropdownEntryType: SSDropdownSetting.DropdownEntryType.Regular, hintDescription: Main.Instance.Translation.HintDescription, onChanged: (player, setting) => { string friendlyName = (setting as DropdownSetting)?.SelectedOption; if (completeMusicList.TryGetValue(friendlyName, out string url)) { player.SessionVariables["SelectedMusicUrl"] = url; } }); SettingBase.Register(new[] { MusicDropdownSetting }); } ``` -------------------------------- ### Define Translation Labels for Music Selection Interface in CSharp Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Implements the Translation class with ITranslation interface to customize player-facing text strings for the music selection dropdown menu. Provides localized labels for the setting prompt and descriptive hints explaining the music selection functionality to end users. ```csharp using Exiled.API.Interfaces; namespace MVPMusic { public class Translation : ITranslation { public string SettingLabel { get; set; } = "Choose music"; public string HintDescription { get; set; } = "Select the song that will be played at the end of the round."; } } ``` -------------------------------- ### Track Player Kills for MVP (C#) Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Tracks player kills throughout the round to determine the top killers. It maintains separate dictionaries for SCP and human kills, updating counts when a player dies. Includes a method to combine these counts and identify the overall top killer. ```csharp using Exiled.Events.EventArgs.Player; using System.Collections.Generic; private static Dictionary scpKills = new Dictionary(); private static Dictionary humanKills = new Dictionary(); private static void OnPlayerDied(DiedEventArgs ev) { Player attacker = ev.Attacker; if (attacker != null && attacker != ev.Player) { if (attacker.Role.Team == Team.SCPs) { if (!scpKills.ContainsKey(attacker)) scpKills[attacker] = 0; scpKills[attacker]++; } else { if (!humanKills.ContainsKey(attacker)) humanKills[attacker] = 0; humanKills[attacker]++; } } } // Get overall top killer combining SCP and human kills private static Player GetOverallTopKiller() { Dictionary combinedKills = new Dictionary(); foreach (var kv in humanKills) { if (!combinedKills.ContainsKey(kv.Key)) combinedKills[kv.Key] = 0; combinedKills[kv.Key] += kv.Value; } foreach (var kv in scpKills) { if (!combinedKills.ContainsKey(kv.Key)) combinedKills[kv.Key] = 0; combinedKills[kv.Key] += kv.Value; } return GetTopKiller(combinedKills); } private static Player GetTopKiller(Dictionary kills) { Player topKiller = null; int maxKills = 0; foreach (var entry in kills) { if (entry.Value > maxKills) { topKiller = entry.Key; maxKills = entry.Value; } } return topKiller; } ``` -------------------------------- ### Track SCP Damage for TopDamageDealer MVP in C# Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Tracks damage dealt by human players to SCPs. It stores damage amounts in a dictionary, keyed by the attacking player. This is used for the 'TopDamageDealer' MVP selection mode. Dependencies include Exiled.Events.EventArgs.Player and System.Collections.Generic. ```csharp using Exiled.Events.EventArgs.Player; using System; using System.Collections.Generic; private static Dictionary humanDamage = new Dictionary(); private static void OnPlayerHurting(HurtingEventArgs ev) { Player attacker = ev.Attacker; Player victim = ev.Player; // Track damage only from humans to SCPs if (attacker != null && attacker != victim && attacker.Role.Team != Team.SCPs && victim.Role.Team == Team.SCPs) { if (!humanDamage.ContainsKey(attacker)) humanDamage[attacker] = 0; humanDamage[attacker] += (int)Math.Round(ev.Amount); } } private static Player GetTopDamageDealer(Dictionary damage) { Player topDealer = null; float maxDamage = 0; foreach (var entry in damage) { if (entry.Value > maxDamage) { topDealer = entry.Key; maxDamage = entry.Value; } } return topDealer; } // Example usage in round end: // Player mvpPlayer = GetTopDamageDealer(humanDamage); ``` -------------------------------- ### Retrieve Player Music URL (C#) Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Retrieves the selected music URL from a player's settings. It attempts to find the DropdownSetting by its ID and then looks up the corresponding music URL from the internal mapping. Returns an empty string if the setting is not found or the URL cannot be determined. ```csharp private static string GetMusicUrlFromPlayer(Player player) { int dropdownId = Main.Instance.Config.MusicDropdownId; if (SettingBase.TryGetSetting(player, dropdownId, out DropdownSetting setting)) { if (setting.OriginalDefinition == null) return string.Empty; string friendlyName = setting.SelectedOption; if (MusicMapping.TryGetValue(friendlyName, out string actualUrl)) return actualUrl; } return string.Empty; } // Usage example when MVP is determined: Player mvpPlayer = GetOverallTopKiller(); if (mvpPlayer != null) { string musicUrl = GetMusicUrlFromPlayer(mvpPlayer); string command = $"/audio play {musicUrl}"; Server.ExecuteCommand(command); } ``` -------------------------------- ### Round End MVP Determination and Music Playback in C# Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Determines the MVP based on configuration (FirstEscaper, FirstScpKiller, TopKiller, TopDamageDealer) and plays their selected music. It displays an MVP hint to all players and resets tracking data for the next round. Dependencies include Exiled.Events.EventArgs.Server and Player. ```csharp using Exiled.Events.EventArgs.Server; // Assuming GetOverallTopKiller() and GetMusicUrlFromPlayer() are defined elsewhere. // Also assuming Main.Instance.Config.Mvp, Main.Instance.Config.Mvphint are accessible. private static void OnRoundEnded(RoundEndedEventArgs ev) { Player mvpPlayer = null; // Determine MVP based on configuration switch (Main.Instance.Config.Mvp) { case "FirstEscaper": mvpPlayer = firstEscaper; break; case "FirstScpKiller": mvpPlayer = firstScpKiller; break; case "TopKiller": // mvpPlayer = GetOverallTopKiller(); // Assumed to be defined break; case "TopDamageDealer": // mvpPlayer = GetTopDamageDealer(humanDamage); // Assumed to be defined break; default: mvpPlayer = firstScpKiller; break; } if (mvpPlayer != null) { // Display MVP hint to all players string hint = new string('\n', 4) + Main.Instance.Config.Mvphint .Replace("{Nickname}", mvpPlayer.Nickname) .Replace("{Scenario}", Main.Instance.Config.Mvp); foreach (var player in Player.List) { if (!player.IsHost) player.ShowHint(hint, 10); } // Play MVP's selected music string musicUrl = GetMusicUrlFromPlayer(mvpPlayer); // Assumed to be defined string command = $"/audio play {musicUrl}"; Server.ExecuteCommand(command); } } // Reset tracking data for next round private static void OnRestartingRound() { // Assuming scpKills and humanKills are also tracked and need clearing // scpKills.Clear(); // humanKills.Clear(); humanDamage.Clear(); firstEscaper = null; firstScpKiller = null; } ``` -------------------------------- ### Track First Escaper and SCP Killer for MVP in C# Source: https://context7.com/vretu-dev/mvpmusic/llms.txt Tracks the first player to escape and the first player to kill an SCP (excluding SCP-049-2). This data is used for alternative MVP selection modes. It relies on Exiled.Events.EventArgs.Player and PlayerRoles. It does not handle cases where no one escapes or kills an SCP. ```csharp using Exiled.Events.EventArgs.Player; using PlayerRoles; private static Player firstEscaper = null; private static Player firstScpKiller = null; private static void OnPlayerEscaping(EscapingEventArgs ev) { if (firstEscaper == null && ev.IsAllowed) { firstEscaper = ev.Player; } } private static void OnPlayerDying(DyingEventArgs ev) { Player attacker = ev.Attacker; Player victim = ev.Player; // Track first SCP kill (excluding zombies) if (victim.Role.Team == Team.SCPs && victim.Role.Type != RoleTypeId.Scp0492) { if (firstScpKiller == null) { firstScpKiller = attacker; } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.