kour.io mod menu

Kour.io mod menu

安裝腳本?
作者推薦腳本

您可能也會喜歡 Kour.rip

安裝腳本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         kour.io mod menu 
// @match        *://kour.io/*
// @version      1.7.0
// @author       rexmine-code
// @description  Kour.io mod menu
// @run-at       document-start
// @grant        unsafeWindow
// @namespace https://greasyfork.org/users/1369586
// @license MIT
// ==/UserScript==

const Signatures = {
    ping:              "f3 07 01 00 00", // Filter
    pong:              "f3 06 01 01 01", // Filter
    anotherPing:       "f3 04 e2 03 e3", // Filter

    createGame:        "f3 02 e3 03 ff 07 06", // Create Game / Party (Can be used to change partyId)
    updateState:       "f3 02 fd 02 f4 03 c8", // Insta-kill
    damageTaken:       "f3 04 c8 02 f5 15 04", // Invisibility

    connectStarts:     "f3 02 e", // Connect (start)
    connectEnds:       "f1 1c e8 1c bf 0b 23" // Connect (end)
}

class Kour {
    constructor() {
        this.sockets = [];
        this.config = {
            Invisible: true,
            InstantKill: false
        }
        this.packets = 0;
        unsafeWindow.WebSocket = class extends WebSocket {
            constructor() {
                super(...arguments);
                this.addEventListener("open", event => {
                    kourInstance.sockets.push(this);
                    kourInstance.hook(this);
                });
            }
        }
    }

    hexArrayToString(hexArray) {
        let str = '';
        for (let i = 0; i < hexArray.length; i++) {
            let hex = hexArray[i];
            let decimalValue = parseInt(hex, 16);
            str += String.fromCharCode(decimalValue);
        }
        return str;
    }

    hook(socket) {
        console.debug("%c !! ", "background:#7aadff;color:#000", `Intercepted WebSocket (${socket.url})`);
        const send = socket.send;
        const onmessage = socket.onmessage;

        socket.onmessage = (event) => {
            if (event.data == null) {
                return onmessage.call(socket, event);
            }

            let hexArray = Array.from(new Uint8Array(event.data)).map(byte => byte.toString(16).padStart(2, '0'));
            let stringHexArray = hexArray.join(" ");

            if (stringHexArray.startsWith(Signatures.damageTaken) && this.config.Invisible) {
                return;
            }

            return onmessage.call(socket, event);
        };

        socket.send = (data) => {
            let hexArray = Array.from(new Uint8Array(data)).map(byte => byte.toString(16).padStart(2, '0'));
            let stringHexArray = hexArray.join(" ");

            if (stringHexArray.startsWith(Signatures.createGame)) {
                let partyId = this.hexArrayToString(hexArray.slice(7, 13));
                console.debug("%c => ", "background:#7F7;color:#000", "Creating game:", partyId);
                return send.call(socket, data);
            } else if (stringHexArray.startsWith(Signatures.updateState) && this.config.InstantKill) {
                for (let i = 0; i < 40; i++) {
                    send.call(socket, data);
                }
                return send.call(socket, data);
            }
            return send.call(socket, data);
        };
    }

    watermark() {
        let overlayCanvas = document.createElement("canvas");
        let unityContainer = document.getElementById("unity-container");
        overlayCanvas.width = unityContainer.clientWidth;
        overlayCanvas.height = unityContainer.clientHeight;
        overlayCanvas.style.position = "absolute";
        overlayCanvas.style.top = "50%";
        overlayCanvas.style.left = "50%";
        overlayCanvas.style.transform = "translate(-50%, -50%)";
        overlayCanvas.style.pointerEvents = "none";
        unityContainer.appendChild(overlayCanvas);

        let ctx = overlayCanvas.getContext("2d");
        ctx.font = "15px monospace";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";

        function animate() {
            let lines = [`kour.rip (${kourInstance.packets})`];
            lines.push(kourInstance.config.Invisible ? "<c>✔ Invisible" : "<c>✖ Invisible");
            lines.push(kourInstance.config.InstantKill ? "<c>✔ Instant-Kill" : "<c>✖ Instant-Kill");

            let lineHeight = 20;
            let startY = overlayCanvas.height / 2 - ((lines.length - 1) * lineHeight) / 2 + 60;
            let centerX = overlayCanvas.width / 2;

            ctx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
            ctx.globalAlpha = 1;

            lines.forEach((line, index) => {
                ctx.fillStyle = line.includes("<c>") ? "#F8CEFF" : "white";
                ctx.fillText(line.replace("<c>", ""), centerX, startY + index * lineHeight);
            });

            requestAnimationFrame(animate);
        }

        animate();
    }

    toggleInvisible() {
        this.config.Invisible = !this.config.Invisible;
    }

    toggleInstantKill() {
        this.config.InstantKill = !this.config.InstantKill;
    }

    openModMenu() {
        let menu = document.createElement('div');
        menu.style.position = 'fixed';
        menu.style.top = '10px';
        menu.style.left = '10px';
        menu.style.backgroundColor = 'rgba(0, 0, 0, 0.9)';  // Increase opacity
        menu.style.color = 'white';
        menu.style.padding = '20px';  // Increase padding for better visibility
        menu.style.borderRadius = '5px';
        menu.style.zIndex = '9999';
        menu.style.boxShadow = '0 0 20px rgba(0, 0, 0, 0.7)';  // Add more shadow for better contrast

        let invBtn = this.createStyledButton('Invisible', () => {
            this.toggleInvisible();
            invBtn.innerText = this.config.Invisible ? 'Disable Invisible' : 'Enable Invisible';
        });

        let killBtn = this.createStyledButton('Instant Kill', () => {
            this.toggleInstantKill();
            killBtn.innerText = this.config.InstantKill ? 'Disable Instant-Kill' : 'Enable Instant-Kill';
        });

        menu.appendChild(invBtn);
        menu.appendChild(document.createElement('br'));
        menu.appendChild(killBtn);

        // RGB border effect using CSS animation
        menu.style.border = '5px solid';
        menu.style.borderImage = 'linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet)';
        menu.style.borderImageSlice = 1;

        // Ensure the menu is always visible for debugging
        document.body.appendChild(menu);
        this.menu = menu;
    }

    createStyledButton(text, onClick) {
        let button = document.createElement('button');
        button.innerText = text;
        button.style.backgroundColor = 'transparent';
        button.style.color = 'white';
        button.style.border = '3px solid transparent';
        button.style.padding = '10px';
        button.style.margin = '5px';
        button.style.borderRadius = '5px';
        button.style.fontSize = '14px';
        button.style.cursor = 'pointer';
        button.style.transition = 'all 0.3s ease';

        // RGB border effect for buttons
        button.style.borderImage = 'linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet)';
        button.style.borderImageSlice = 1;

        // Add hover effect
        button.onmouseover = () => {
            button.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
        };
        button.onmouseout = () => {
            button.style.backgroundColor = 'transparent';
        };

        button.onclick = onClick;
        return button;
    }

    toggleMenu() {
        if (this.menu.style.display === 'none') {
            this.menu.style.display = 'block';
        } else {
            this.menu.style.display = 'none';
        }
    }
}

const kourInstance = new Kour();

unsafeWindow.kourInstance = kourInstance;

window.addEventListener("load", () => {
    kourInstance.openModMenu();
    window.addEventListener("keydown", (e) => {
        if (e.key === 'm') {  // Press 'm' to toggle the mod menu
            kourInstance.toggleMenu();
        }
    });
});