// ==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();
}
});
});