Wolf_ Ultimate menu

Scripts for Kour.io (have fun)

Terá de instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Terá de instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Terá de instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Terá de instalar uma extensão como Tampermonkey para instalar este script.

Terá de instalar uma extensão de gestão de scripts de utilizador para instalar este script.

(Já tenho um gestor de scripts de utilizador, deixe-me instalá-lo!)

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

(Já tenho um gestor de estilos de utilizador, deixe-me instalá-lo!)

// ==UserScript==
// @name         Wolf_ Ultimate menu
// @match        *://kour.io/*
// @version      1.3
// @author       wolf_
// @description  Scripts for Kour.io (have fun)
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// @namespace https://greasyfork.org/users/1598070
// ==/UserScript==

(function() {
    'use strict';

    let settings = GM_getValue("kourPlusConfigs", {
        userPhrases: ["GG!", "well played", "xD", "𝐄𝐀𝐒𝐘"],
        lastColor: "#ff0000"
    });

    const ui = document.createElement('div');
    ui.id = "kour-rgb-ui";
    document.body.appendChild(ui);

    const style = document.createElement('style');
    style.innerHTML = `
        @keyframes smoothRainbow {
            0% { border-color: #ff0000; color: #ff0000; }
            33% { border-color: #00ff00; color: #00ff00; }
            66% { border-color: #0000ff; color: #0000ff; }
            100% { border-color: #ff0000; color: #ff0000; }
        }

        #kour-rgb-ui {
            position: fixed; top: 20px; right: 20px;
            background: rgba(10, 10, 10, 0.98);
            border: 2px solid #ff0000;
            padding: 15px; z-index: 9999999;
            border-radius: 12px; width: 270px;
            font-family: 'Segoe UI', Tahoma, sans-serif;
            animation: smoothRainbow 10s linear infinite;
            box-shadow: 0 10px 30px rgba(0,0,0,0.6);
            user-select: none;
        }

        .title-rgb {
            text-align: center; font-weight: 900; font-size: 15px;
            margin-bottom: 12px;
            text-transform: uppercase; letter-spacing: 2px;
            cursor: move;
            padding: 8px;
            background: rgba(255,255,255,0.03);
            border-radius: 6px;
            animation: smoothRainbow 10s linear infinite;
        }

        .section-label { font-size: 10px; color: #666; text-transform: uppercase; margin-bottom: 5px; display: block; font-weight: bold; }

        .btn-style {
            width: 100%; background: #1a1a1a; color: #fff; border: 1px solid #333;
            padding: 10px; cursor: pointer; font-weight: bold; border-radius: 6px;
            text-transform: uppercase; margin-bottom: 6px; font-size: 12px; transition: 0.2s;
        }
        .btn-style:hover { background: #333; border-color: #777; }

        .fast-red { background: #400 !important; color: #ff4444 !important; border: 1px solid #600 !important; }
        .clear-btn { background: #222 !important; color: #888 !important; font-size: 9px !important; margin-top: 5px !important; }

        .color-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; background: #111; padding: 8px; border-radius: 6px; border: 1px solid #222; }
        #nickColorPicker { border: none; width: 35px; height: 25px; cursor: pointer; background: none; }

        .phrase-row { display: flex; gap: 5px; margin-bottom: 5px; }
        .del-btn { background: #300; color: #f44; border: 1px solid #500; padding: 5px 10px; cursor: pointer; border-radius: 5px; font-weight: bold; }

        #phrase-container { max-height: 160px; overflow-y: auto; margin-top: 10px; border-top: 1px solid #222; padding-top: 10px; }

        .footer-rainbow {
            font-size: 13px;
            text-align: center;
            margin-top: 15px;
            font-weight: 900;
            font-style: italic;
            animation: smoothRainbow 10s linear infinite;
        }

        ::-webkit-scrollbar { width: 4px; }
        ::-webkit-scrollbar-thumb { background: #333; border-radius: 10px; }
    `;
    document.head.appendChild(style);

    function render() {
        const savedPos = JSON.parse(localStorage.getItem("kourMenuPos") || '{"top":"20px","left":"auto","right":"20px"}');
        ui.style.top = savedPos.top;
        ui.style.left = savedPos.left;
        ui.style.right = savedPos.right;

        ui.innerHTML = `
            <div class="title-rgb" id="kour-header">KOUR Ultimate Menu</div>
            <span class="section-label">Quick Actions</span>
            <button id="fastRedBtn" class="btn-style fast-red">🔴 Fast Red No-Name</button>
            <span class="section-label" style="margin-top:10px;">Nickname</span>
            <div class="color-row">
                <input type="color" id="nickColorPicker" value="${settings.lastColor}">
                <span style="font-size:11px; color:#888;">Custom Color</span>
            </div>
            <button id="setNickBtn" class="btn-style">Apply Nickname</button>
            <span class="section-label" style="margin-top:10px;">Phrases</span>
            <button id="addPhraseBtn" class="btn-style" style="color:#4f4; border-color:#262;">+ Add Phrase</button>
            <div id="phrase-container"></div>
            <button id="clearPhrasesBtn" class="btn-style clear-btn">Clear All</button>
            <div class="footer-rainbow">Made by Wolf_</div>
            <div style="font-size:9px; color:#333; text-align:center; margin-top:5px;">[O] Hide/Show | Drag title to move</div>
        `;

        const list = ui.querySelector('#phrase-container');
        settings.userPhrases.forEach((p, index) => {
            const row = document.createElement('div');
            row.className = "phrase-row";
            const b = document.createElement('button');
            b.className = "btn-style"; b.style.marginBottom = "0"; b.innerText = p;
            b.onclick = () => {
                navigator.clipboard.writeText("ㅤ" + p);
                const original = b.innerText;
                b.innerText = "COPIED!"; setTimeout(() => b.innerText = original, 800);
            };
            const d = document.createElement('button');
            d.className = "del-btn"; d.innerText = "X";
            d.onclick = () => {
                settings.userPhrases.splice(index, 1);
                GM_setValue("kourPlusConfigs", settings); render();
            };
            row.appendChild(b); row.appendChild(d); list.appendChild(row);
        });

        document.getElementById('clearPhrasesBtn').onclick = () => {
            if (confirm("Delete all phrases?")) {
                settings.userPhrases = []; GM_setValue("kourPlusConfigs", settings); render();
            }
        };

        document.getElementById('fastRedBtn').onclick = () => {
            const fastName = "<color=#FF0000>ㅤ</color>";
            localStorage.setItem("playerNickname", fastName);
            window.unityInstance?.SendMessage("MapScripts", "SetNickname", fastName);
        };

        document.getElementById('setNickBtn').onclick = () => {
            const name = prompt("Nickname:");
            if (!name) return;
            const color = document.getElementById('nickColorPicker').value;
            settings.lastColor = color;
            GM_setValue("kourPlusConfigs", settings);
            const finalName = `<color=${color}>${name.trim()}</color>`;
            localStorage.setItem("playerNickname", finalName);
            window.unityInstance?.SendMessage("MapScripts", "SetNickname", finalName);
        };

        document.getElementById('addPhraseBtn').onclick = () => {
            const newPhrase = prompt("New phrase:");
            if (newPhrase) {
                settings.userPhrases.push(newPhrase.trim());
                GM_setValue("kourPlusConfigs", settings); render();
            }
        };

        makeDraggable(ui, document.getElementById("kour-header"));
    }

    function makeDraggable(element, handle) {
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        handle.onmousedown = (e) => {
            e.preventDefault();
            pos3 = e.clientX; pos4 = e.clientY;
            document.onmouseup = () => {
                document.onmouseup = null;
                document.onmousemove = null;
                localStorage.setItem("kourMenuPos", JSON.stringify({
                    top: element.style.top,
                    left: element.style.left,
                    right: "auto"
                }));
            };
            document.onmousemove = (e) => {
                e.preventDefault();
                pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY;
                pos3 = e.clientX; pos4 = e.clientY;

                let newTop = element.offsetTop - pos2;
                let newLeft = element.offsetLeft - pos1;

                const padding = 1;
                const maxLeft = window.innerWidth - element.offsetWidth - padding;
                const maxTop = window.innerHeight - element.offsetHeight - padding;

                newTop = Math.max(padding, Math.min(newTop, maxTop));
                newLeft = Math.max(padding, Math.min(newLeft, maxLeft));

                element.style.top = newTop + "px";
                element.style.left = newLeft + "px";
                element.style.right = "auto";
            };
        };
    }

    render();

    setInterval(() => {
        const saved = localStorage.getItem("playerNickname");
        if (saved && typeof unityInstance !== 'undefined') {
            unityInstance.SendMessage("MapScripts", "SetNickname", saved);
        }
    }, 5000);

    document.addEventListener('keydown', (e) => {
        if (e.key.toLowerCase() === 'o') ui.style.display = (ui.style.display === 'none') ? 'block' : 'none';
    });

})();