SoundBoard

Play sounds when specific chat messages are received

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         SoundBoard
// @version      1.4.0
// @description  Play sounds when specific chat messages are received
// @author       FeiFei
// @match        https://bonk.io/gameframe-release.html
// @run-at       document-end
// @grant        none
// @namespace    https://greasyfork.org/users/1366475
// ==/UserScript==

"use strict";

let soundBoard = {};

soundBoard.windowConfigs = {
    windowName: "SoundBoard",
    windowId: "soundBoard_window",
    modVersion: "1.4.0",
    bonkLIBVersion: "1.1.3",
    bonkVersion: "49",
    windowContent: null,
    settingsContent: null,
};

// Initialize global mute state
soundBoard.globalMute = false;
soundBoard.modIndex = null;
soundBoard.windowContentElement = null;
soundBoard.settingsContentElement = null;

// Define the sounds and their corresponding messages and audio URLs
soundBoard.sounds = [
    {
        name: "a",
        triggerMessage: "a",
        audioUrl: "https://www.myinstants.com/media/sounds/gawr-gura-a.mp3",
        enabled: true, // default enabled
    },
    // *Add more sounds here if needed
];

soundBoard.setWindowContent = function () {
    let windowHTML = document.createElement("div");
    // !Maybe dont need this
    windowHTML.id = soundBoard.windowConfigs.windowId; // Unique ID for scoping
    windowHTML.classList.add("bonkhud-background-color");
    
    // Create the global mute toggle button
    let muteButton = document.createElement("button");
    muteButton.id = "muteButton";
    muteButton.textContent = this.globalMute ? "🔇" : "🔊";
    muteButton.title = this.globalMute ? "Unmute" : "Mute";
    muteButton.classList.add("bonkhud-text-color"); // Apply text color
    muteButton.addEventListener("click", () => {
        this.globalMute = !this.globalMute;
        muteButton.textContent = this.globalMute ? "🔇" : "🔊";
        muteButton.title = this.globalMute ? "Unmute" : "Mute";
        // Save the global mute setting
        this.saveSettings();
    });
    windowHTML.appendChild(muteButton);

    // Create the list of sounds
    let soundList = document.createElement("div");
    soundList.id = "soundList";

    this.sounds.forEach((sound, index) => {
        let soundDiv = document.createElement("div");
        soundDiv.className = "sound-item bonkhud-border-color"; // Apply border color

        let soundName = document.createElement("span");
        soundName.className = "sound-name bonkhud-text-color"; // Apply text color
        soundName.textContent = sound.name;
        soundName.title = sound.triggerMessage;

        // Create the checkbox input
        let checkbox = document.createElement("input");
        checkbox.type = "checkbox";
        checkbox.id = `checkbox_${index}`;
        checkbox.checked = sound.enabled;

        // Create the label for the checkbox
        let label = document.createElement("label");
        label.htmlFor = `checkbox_${index}`;
        label.className = "soundBoardToggle bonkhud-button-color"; // Apply button color

        // Event listener to update the sound enabled state
        checkbox.addEventListener("change", () => {
            sound.enabled = checkbox.checked;
            // Save the settings
            this.saveSettings();
        });

        // Create a container for the toggle switch
        let toggleContainer = document.createElement("div");
        toggleContainer.style.display = "flex";
        toggleContainer.style.alignItems = "center";

        toggleContainer.appendChild(checkbox);
        toggleContainer.appendChild(label);

        soundDiv.appendChild(soundName);
        soundDiv.appendChild(toggleContainer);

        soundList.appendChild(soundDiv);
    });

    windowHTML.appendChild(soundList);

    // Add to windowContent
    this.windowConfigs.windowContent = windowHTML;

    // Store a reference to the window content element
    this.windowContentElement = windowHTML;
};

soundBoard.setSettingsContent = function () {
    let settingsHTML = document.createElement("div");
    settingsHTML.className = "settings-container bonkhud-background-color"; // Apply background color
    
    // Create the list of sounds with delete buttons
    let soundList = document.createElement("div");
    soundList.id = "settingsSoundList";

    this.sounds.forEach((sound, index) => {
        let soundDiv = document.createElement("div");
        soundDiv.className = "settings-sound-item bonkhud-border-color"; // Apply border color

        let soundInfo = document.createElement("span");
        soundInfo.className = "settings-sound-info bonkhud-text-color"; // Apply text color
        soundInfo.textContent = `${sound.name} | Trigger: "${sound.triggerMessage}" | URL: ${sound.audioUrl}`;

        let deleteButton = document.createElement("button");
        deleteButton.className = "delete-button bonkhud-button-color"; // Apply button color
        deleteButton.textContent = "Delete";
        deleteButton.addEventListener("mouseover", () => {
            deleteButton.classList.add("bonkhud-button-color-hover");
        });
        deleteButton.addEventListener("mouseout", () => {
            deleteButton.classList.remove("bonkhud-button-color-hover");
        });
        deleteButton.addEventListener("click", () => {
            // Remove the sound from the list
            this.sounds.splice(index, 1);
            // Save settings
            this.saveSettings();
            // Update the settings content
            this.updateSettingsContent();
            // Update the window content
            this.updateWindowContent();
        });

        soundDiv.appendChild(soundInfo);
        soundDiv.appendChild(deleteButton);

        soundList.appendChild(soundDiv);
    });

    settingsHTML.appendChild(soundList);

    // Create GUI for importing new sounds
    let importDiv = document.createElement("div");
    importDiv.className = "import-div";
    importDiv.style.marginTop = "10px";

    let nameInput = document.createElement("input");
    nameInput.type = "text";
    nameInput.placeholder = "Sound Name";
    nameInput.classList.add("bonkhud-text-color", "bonkhud-background-color"); // Apply text and background color

    let triggerInput = document.createElement("input");
    triggerInput.type = "text";
    triggerInput.placeholder = "Trigger Message";
    triggerInput.classList.add("bonkhud-text-color", "bonkhud-background-color");

    let urlInput = document.createElement("input");
    urlInput.type = "text";
    urlInput.placeholder = "Audio URL";
    urlInput.classList.add("bonkhud-text-color", "bonkhud-background-color");

    let addButton = document.createElement("button");
    addButton.className = "add-button bonkhud-button-color"; // Apply button color
    addButton.textContent = "Add Sound";
    addButton.addEventListener("click", () => {
        let name = nameInput.value.trim();
        let triggerMessage = triggerInput.value.trim();
        let audioUrl = urlInput.value.trim();

        if (name && triggerMessage && audioUrl) {
            this.sounds.push({
                name: name,
                triggerMessage: triggerMessage,
                audioUrl: audioUrl,
                enabled: true
            });
            // Save settings
            this.saveSettings();
            // Update the settings content
            this.updateSettingsContent();
            // Update the window content
            this.updateWindowContent();
            // Clear inputs
            nameInput.value = '';
            triggerInput.value = '';
            urlInput.value = '';
        } else {
            alert("Please fill in all fields.");
        }
    });

    importDiv.appendChild(nameInput);
    importDiv.appendChild(triggerInput);
    importDiv.appendChild(urlInput);
    importDiv.appendChild(addButton);

    settingsHTML.appendChild(importDiv);

    // Add to settingsContent
    this.windowConfigs.settingsContent = settingsHTML;

    // Store a reference to the settings content element
    this.settingsContentElement = settingsHTML;
};

// Create the mod window using BonkHUD
soundBoard.createWindow = function () {
    // Create the window using BonkHUD
    const modIndex = bonkHUD.createMod(this.windowConfigs.windowName, this.windowConfigs);
    this.modIndex = modIndex; // Store the mod index just in case
    
    // Load UI settings if available
    bonkHUD.loadUISetting(modIndex);
};

// Function to add custom styles
soundBoard.addStyles = function() {
    const css = `
    /* Scoped Styles for SoundBoard Mod */
    #soundBoard_window {
        font-family: Poppins;
        padding: 10px;
    }
    #soundBoard_window #muteButton {
        background-color: transparent;
        border: none;
        font-size: 24px;
        cursor: pointer;
        margin-bottom: 10px;
    }
    
    #soundBoard_window .sound-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 5px 0;
        border-bottom: 1px solid;
    }
    #soundBoard_window .sound-item:last-child {
        border-bottom: none;
    }
    #soundBoard_window .sound-name {
        flex-grow: 1;
        font-size: 16px;
    }
    
    #soundBoard_window .soundBoardToggle {
        position: relative;
        width: 40px;
        height: 20px;
        border-radius: 20px;
        cursor: pointer;
        transition: background-color 0.2s;
    }
    #soundBoard_window .soundBoardToggle::before {
        content: '';
        position: absolute;
        width: 18px;
        height: 18px;
        left: 1px;
        top: 1px;
        background-color: #fff;
        border-radius: 18px;
        transition: transform 0.2s;
    }
    #soundBoard_window input[type="checkbox"]:checked + .soundBoardToggle::before {
        transform: translateX(20px);
    }
    #soundBoard_window input[type="checkbox"] {
        display: none;
    }
    
    /* Style the Settings Content */
    #soundBoardModContainer .settings-container {
        margin-top: 15px;
    }
    #soundBoardModContainer .settings-sound-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 5px 0;
        border-bottom: 1px solid;
    }
    #soundBoardModContainer .settings-sound-item:last-child {
        border-bottom: none;
    }
    #soundBoardModContainer .settings-sound-info {
        flex-grow: 1;
        font-size: 14px;
    }
        
    /* Style the Input Fields and Add Button */
    #soundBoardModContainer .import-div {
        margin-top: 15px;
    }
    #soundBoardModContainer .import-div input[type="text"] {
        width: calc(33% - 10px);
        padding: 5px;
        margin-right: 5px;
        border-radius: 4px;
    }
    #soundBoardModContainer .import-div input[type="text"]:last-of-type {
        margin-right: 0;
    }
    `;
    let style = document.createElement('style');
    style.innerHTML = css;
    document.head.appendChild(style);
};

soundBoard.updateWindowContent = function () {
    let soundList = this.windowContentElement.querySelector('#soundList');
    if (soundList) {
        // Clear existing content
        soundList.innerHTML = '';

        // Re-create the list of sounds
        this.sounds.forEach((sound, index) => {
            let soundDiv = document.createElement("div");
            soundDiv.className = "sound-item bonkhud-border-color"; // Apply border color

            let soundName = document.createElement("span");
            soundName.className = "sound-name bonkhud-text-color"; // Apply text color
            soundName.textContent = sound.name;
            soundName.title = sound.triggerMessage;

            // Create the checkbox input
            let checkbox = document.createElement("input");
            checkbox.type = "checkbox";
            checkbox.id = `checkbox_${index}`;
            checkbox.checked = sound.enabled;

            // Create the label for the checkbox
            let label = document.createElement("label");
            label.htmlFor = `checkbox_${index}`;
            label.className = "soundBoardToggle bonkhud-button-color"; // Apply button color

            // Event listener to update the sound enabled state
            checkbox.addEventListener("change", () => {
                sound.enabled = checkbox.checked;
                // Save the settings
                this.saveSettings();
            });

            // Create a container for the toggle switch
            let toggleContainer = document.createElement("div");
            toggleContainer.style.display = "flex";
            toggleContainer.style.alignItems = "center";

            toggleContainer.appendChild(checkbox);
            toggleContainer.appendChild(label);

            soundDiv.appendChild(soundName);
            soundDiv.appendChild(toggleContainer);

            soundList.appendChild(soundDiv);
        });
        
        bonkHUD.updateStyleSettings();
    }
};

soundBoard.updateSettingsContent = function () {
    let soundList = this.settingsContentElement.querySelector('#settingsSoundList');
    if (soundList) {
        // Clear existing content
        soundList.innerHTML = '';

        // Re-create the list of sounds with delete buttons
        this.sounds.forEach((sound, index) => {
            let soundDiv = document.createElement("div");
            soundDiv.className = "settings-sound-item bonkhud-border-color"; // Apply border color

            let soundInfo = document.createElement("span");
            soundInfo.className = "settings-sound-info bonkhud-text-color"; // Apply text color
            soundInfo.textContent = `${sound.name} | Trigger: "${sound.triggerMessage}" | URL: ${sound.audioUrl}`;

            let deleteButton = document.createElement("button");
            deleteButton.className = "delete-button bonkhud-button-color"; // Apply button color
            deleteButton.textContent = "Delete";
            deleteButton.addEventListener("mouseover", () => {
                deleteButton.classList.add("bonkhud-button-color-hover");
            });
            deleteButton.addEventListener("mouseout", () => {
                deleteButton.classList.remove("bonkhud-button-color-hover");
            });
            deleteButton.addEventListener("click", () => {
                // Remove the sound from the list
                this.sounds.splice(index, 1);
                // Save settings
                this.saveSettings();
                // Update the settings content
                this.updateSettingsContent();
                // Update the window content
                this.updateWindowContent();
            });

            soundDiv.appendChild(soundInfo);
            soundDiv.appendChild(deleteButton);

            soundList.appendChild(soundDiv);
        });
        
        bonkHUD.updateStyleSettings();
    }
};

// Function to save settings to localStorage
soundBoard.saveSettings = function () {
    let settings = {
        globalMute: this.globalMute,
        sounds: this.sounds,
    };
    localStorage.setItem('bonkHUD_Mod_Setting_SoundBoard', JSON.stringify(settings));
};

// Function to load settings from localStorage
soundBoard.loadSettings = function () {
    let savedSettings = JSON.parse(localStorage.getItem('bonkHUD_Mod_Setting_SoundBoard') || '{}');
    if (typeof savedSettings.globalMute !== "undefined") {
        this.globalMute = savedSettings.globalMute;
    }
    if (Array.isArray(savedSettings.sounds)) {
        this.sounds = savedSettings.sounds;
    }
};

// Initialize the mod (run when document is ready)
soundBoard.initMod = function () {
    // Ensure BonkHUD is available
    if (!window.bonkHUD) {
        console.error("BonkHUD is not loaded. Please make sure BonkHUD is installed.");
        return;
    }
    
    this.loadSettings();
    this.setWindowContent();
    this.setSettingsContent();
    this.createWindow();
    this.addStyles();

    // Add event listener for chat messages
    bonkAPI.addEventListener("chatIn", (e) => {
        if (this.globalMute) return;
        
        this.sounds.forEach((sound) => {
            if (sound.enabled && e.message === sound.triggerMessage) {
                this.playSound(sound.audioUrl);
            }
        });
    });

    console.log(this.windowConfigs.windowName + " initialized");
};

// Function to play audio
soundBoard.playSound = function (url) {
    let audio = new Audio(url);
    audio.play();
};

// Function to handle document readiness and initialize the mod
soundBoard.onDocumentReady = function () {
    if (document.readyState === "complete" || document.readyState === "interactive") {
        this.initMod();
    } else {
        document.addEventListener("DOMContentLoaded", () => {
            this.initMod();
        });
    }
};

// Call the function to check document readiness and initialize the mod
soundBoard.onDocumentReady();