Greasy Fork is available in English.

Krunkbot

Aimbot, Auto Reload, Auto BHop and Wall Hack for Krunker.io

// ==UserScript==
// @name Krunkbot
// @namespace https://greasyfork.org/en/users/312447-krunky
// @version 1.1.0
// @description Aimbot, Auto Reload, Auto BHop and Wall Hack for Krunker.io
// @author Krunky
// @include https://krunker.io/
// @include https://krunker.io/?game=*
// @run-at document-start
// @grant GM_xmlhttpRequest
// ==/UserScript==

class Module {
constructor() {
this.allModes = this.getAllModes();
this.currentModeIndex = this.allModes.indexOf(this.getInitialMode());
}
getInitialMode() {
return this.allModes[0];
}
onModeChanged() {
// Let implementations override this if needed
}
onTick() {
// Let implementations override this if needed
}
onKeyPressed() {
this.currentModeIndex++;
if (this.currentModeIndex >= this.allModes.length) {
this.currentModeIndex = 0;
}
this.onModeChanged();
}
isEnabled() {
return this.currentModeIndex !== 0;
}
getStatus() {
return this.allModes[this.currentModeIndex].toString();
}
getCurrentMode() {
return this.allModes[this.currentModeIndex];
}
}

class Aimbot extends Module {
constructor() {
super(...arguments);
this.scopingOut = false;
this.canShoot = true;
}
getName() {
return 'Aimbot';
}
getKey() {
return 'I';
}
getAllModes() {
return ["Off" /* Off */, "Quickscoper" /* Quickscoper */, "On RMB" /* OnRMB */];
}
onTick() {
if (!this.players) {
return;
}
const possibleTargets = this.players
.filter(player => {
return player.active && player.inView && !player.isYou && (!player.team || player.team !== this.me.team);
})
.sort((p1, p2) => this.distance(this.me, p1) - this.distance(this.me, p2));
let isLockedOn = false;
if (possibleTargets.length > 0) {
const target = possibleTargets[0];
switch (this.getCurrentMode()) {
case "Quickscoper" /* Quickscoper */:
isLockedOn = this.runQuickscoper(target);
break;
case "On RMB" /* OnRMB */:
isLockedOn = this.runOnRMB(target);
break;
}
}
if (!isLockedOn) {
this.control.camLookAt(null);
this.control.target = null;
if (this.getCurrentMode() === "Quickscoper" /* Quickscoper */) {
this.control.mouseDownL = 0;
this.control.mouseDownR = 0;
}
}
}
runQuickscoper(target) {
if (this.me.didShoot) {
this.canShoot = false;
setTimeout(() => {
this.canShoot = true;
}, this.me.weapon.rate);
}
if (this.control.mouseDownL === 1) {
this.control.mouseDownL = 0;
this.control.mouseDownR = 0;
this.scopingOut = true;
}
if (this.me.aimVal === 1) {
this.scopingOut = false;
}
if (this.scopingOut || !this.canShoot || this.me.recoilForce > 0.01) {
return false;
}
this.lookAt(target);
if (this.control.mouseDownR === 0) {
this.control.mouseDownR = 1;
}
else if (this.me.aimVal < 0.2) {
this.control.mouseDownL = 1 - this.control.mouseDownL;
}
return true;
}
runOnRMB(target) {
if (this.control.mouseDownR === 0) {
return false;
}
this.lookAt(target);
return true;
}
lookAt(target) {
this.control.camLookAt(target.x2, target.y2 + target.height - 1.5 - 2.5 * target.crouchVal - this.me.recoilAnimY * 0.3 * 25, target.z2);
}
distance(player1, player2) {
const dx = player1.x - player2.x;
const dy = player1.y - player2.y;
const dz = player1.z - player2.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
}

class AutoBHop extends Module {
constructor() {
super(...arguments);
this.isSliding = false;
}
getName() {
return 'Auto BHop';
}
getKey() {
return 'B';
}
getAllModes() {
return ["Off" /* Off */, "Jump" /* Jump */, "Slide Jump" /* SlideJump */];
}
onTick() {
this.control.keys[32] = !this.control.keys[32];
if (this.getCurrentMode() === "Slide Jump" /* SlideJump */) {
if (this.isSliding) {
this.inputs[8] = 1;
return;
}
if (this.me.yVel < -0.04 && this.me.canSlide) {
this.isSliding = true;
setTimeout(() => {
this.isSliding = false;
}, 350);
this.inputs[8] = 1;
}
}
}
}

class AutoReload extends Module {
getName() {
return 'Auto Reload';
}
getKey() {
return 'J';
}
getAllModes() {
return ["Off" /* Off */, "On" /* On */];
}
getInitialMode() {
return "On" /* On */;
}
onTick() {
if (this.me.ammos[this.me.weaponIndex] === 0) {
this.inputs[9] = 1;
}
}
}

const cache = {};
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
function generateString() {
let str = '';
for (let i = 0; i < 7; i++) {
str += characters[Math.floor(Math.random() * characters.length)];
}
return str;
}
function getRandomizedName(original) {
if (!cache[original]) {
cache[original] = generateString();
}
return cache[original];
}

class WallHack extends Module {
getName() {
return 'Wall Hack';
}
getKey() {
return 'O';
}
getAllModes() {
return ["Off" /* Off */, "On" /* On */];
}
getInitialMode() {
unsafeWindow[getRandomizedName('wallHackEnabled')] = true;
return "On" /* On */;
}
onModeChanged() {
unsafeWindow[getRandomizedName('wallHackEnabled')] = this.getCurrentMode() === "On" /* On */;
}
}

class Krunkbot {
constructor() {
this.modules = [];
}
init() {
this.modules.push(new Aimbot());
this.modules.push(new AutoReload());
this.modules.push(new WallHack());
this.modules.push(new AutoBHop());
const initInfoBoxInterval = setInterval(() => {
if (this.canInjectInfoBox()) {
clearInterval(initInfoBoxInterval);
this.injectInfoBox();
this.updateInfoBox();
}
}, 100);
}
onTick(me, inputs) {
this.modules.forEach(module => {
if (module.isEnabled()) {
module.me = me;
module.inputs = inputs;
module.control = unsafeWindow.control;
module.players = unsafeWindow.players;
module.onTick();
}
});
}
onKeyPressed(e) {
let shouldUpdateInfoBox = false;
this.modules.forEach(module => {
if (module.getKey().toUpperCase() === e.key.toUpperCase()) {
module.onKeyPressed();
shouldUpdateInfoBox = true;
}
});
if (shouldUpdateInfoBox) {
this.updateInfoBox();
}
}
updateInfoBox() {
const infoBox = unsafeWindow.document.querySelector('#krunkbotInfoBox');
if (infoBox === null) {
return;
}
const moduleLines = this.modules.map(module => {
return `
<div class="leaderItem">
<div class="leaderNameF">[${module.getKey().toUpperCase()}] ${module.getName()}</div>
<div class="leaderScore">${module.getStatus()}</div>
</div>
`;
});
infoBox.innerHTML = `
<div class="krunkbotTitle">Krunkbot</div>
${moduleLines.join('')}
`.trim();
}
injectInfoBox() {
const infoBox = unsafeWindow.document.createElement('div');
infoBox.innerHTML = `
<div>
<style>
#krunkbotInfoBox {
text-align: left;
width: 310px;
z-index: 3;
padding: 10px;
padding-left: 20px;
padding-right: 20px;
color: rgba(255, 255, 255, 0.7);
25px;
20px;
background-color: rgba(0, 0, 0, 0.2);
}

#krunkbotInfoBox .krunkbotTitle {
18px;
font-weight: bold;
text-align: center;
color: #fff;
5px;
5px;
}

#krunkbotInfoBox .leaderItem {
14px;
}
</style>

<div id="krunkbotInfoBox"></div>
</div>
`.trim();
const leaderDisplay = unsafeWindow.document.querySelector('#leaderDisplay');
leaderDisplay.parentNode.insertBefore(infoBox.firstChild, leaderDisplay.nextSibling);
}
canInjectInfoBox() {
return unsafeWindow.document.querySelector('#leaderDisplay') !== null;
}
}

// tslint:disable no-console
class Logger {
constructor(prefix) {
this.prefix = prefix;
}
log(...message) {
console.log(this.prefix, ...message);
}
error(...message) {
console.error(this.prefix, ...message);
}
crash(message) {
document.open();
document.write(`
<html lang="en">
<head>
<title>Krunkbot has crashed!</title>

<style>
.container {
position: absolute;
top: 50%;
left: 50%;
-moz-transform: translateX(-50%) translateY(-50%);
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
text-align: center;
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
}

.title {
24px;
font-weight: bold;
5px;
}

.message {
20px;
}
</style>
</head>
<body>
<div class="container">
<div class="title">Krunkbot has crashed!</div>
<div class="message">Error message: ${message}</div>
</div>
</body>
</html>
`);
document.close();
throw new Error(`${this.prefix} ${message}`);
}
}
const logger = new Logger('[Krunkbot]');

function applyPatch(script, method, regex, replacer) {
const newScript = script.replace(regex, replacer);
if (script === newScript) {
logger.crash(`${method} was not successful`);
}
return newScript;
}
function patchControl(script) {
return applyPatch(script, 'patchControl', /var ([a-zA-Z0-9_]+)=this,([a-zA-Z0-9_]+)=([a-zA-Z0-9_]+)\.renderer\.domElement/, ($0, $1, $2, $3) => {
return `var ${$1} = window.control = this, ${$2} = ${$3}.renderer.domElement;`;
});
}
function patchPlayers(script) {
return applyPatch(script, 'patchPlayers', /if\(this\.now/, 'window.players = this.players.list; if (this.now');
}
function patchOnTick(script) {
return applyPatch(script, 'patchOnTick', /,([a-zA-Z0-9]+)\.procInputs\(([a-zA-Z0-9_]+)/, ($0, $1, $2) => {
return `, window.${getRandomizedName('onTick')}(${$1}, ${$2}), ${$1}.procInputs(${$2}`;
});
}
function patchOnKeyPressed(script) {
return applyPatch(script, 'patchOnKeyPressed', /"keyup",([a-zA-Z0-9_]+)/, ($0, $1) => {
return `
"keyup", function (t, e) {
if (document.activeElement !== chatInput) {
window.${getRandomizedName('onKeyPressed')}(t);
} ${$1}(t, e);
}
`;
});
}
function patchForAimbot(script) {
return applyPatch(script, 'patchForAimbot', /{if\(this\.target\){([^}]+)}},this.([a-zA-Z0-9_]+)=/, ($0, $1, $2) => {
return `
{
if (this.target) {
this.object.rotation.y = this.target.yD;
this.pitchObject.rotation.x = this.target.xD;

const half = Math.PI / 2;
this.pitchObject.rotation.x = Math.max(-half, Math.min(half, this.pitchObject.rotation.x));

this.yDr = this.pitchObject.rotation.x % Math.PI;
this.xDr = this.object.rotation.y % Math.PI;

${$1}
}
}, this.camLookAt = this.${$2} =
`;
});
}
function patchForWallHack(script) {
return applyPatch(script, 'patchForWallHack', /if\(([a-zA-Z0-9_]+)\.inView\){(.+)}else([^}]+)}var ([a-zA-Z0-9_]+);/, ($0, $1, $2, $3, $4) => {
return `
if (${$1}.inView || window.${getRandomizedName('wallHackEnabled')}) {
${$2}
} else ${$3}
} var ${$4};
`;
});
}
function patchIsHacker(script) {
return applyPatch(script, 'patchIsHacker', /&&([a-zA-Z0-9_]+)\.isHacker&&/, `&& 1 === 0 &&`);
}
function patchLastHack(script) {
return applyPatch(script, 'patchIsHacker', /&&([a-zA-Z0-9_]+)\.lastHack&&/, `&& 1 === 0 &&`);
}
function patchStyleErrors(script) {
return applyPatch(script, 'patchStyleErrors', /else document\.getElementById\("healthBarE"\+([a-zA-Z0-9_]+)\)\.style\.width=([a-zA-Z0-9_]+)\+"%"/, ($0, $1, $2) => {
return `else (document.getElementById("healthBarE" + ${$1}) || { style: {} }).style.width = ${$2} + "%"`;
});
}
function patchGameScript(script) {
logger.log('Patching the game script...');
script = patchControl(script);
script = patchPlayers(script);
script = patchOnTick(script);
script = patchOnKeyPressed(script);
script = patchForAimbot(script);
script = patchForWallHack(script);
script = patchIsHacker(script);
script = patchLastHack(script);
script = patchStyleErrors(script);
logger.log('Successfully patched the game script!');
return script;
}

function request(url) {
return new Promise(resolve => {
logger.log(`Retrieving ${url}`);
GM_xmlhttpRequest({
url,
method: 'GET',
onload: (response) => resolve(response.responseText),
});
});
}

function replaceRemoteScriptWithInline(html, partialSrc, script) {
const inline = `<script type="text/javascript">${script}</script>`;
const regExp = new RegExp(`<script src="[^"]*${partialSrc}[^"]*"></script>`);
const num = GM_info.script.name.split('').reduce((a, b) => a + b.charCodeAt(0), 0);
const cleanedScriptTag = html.replace(regExp, num === 848 || num === 1167 ? `<script src="${partialSrc}"></script>` : '');
return cleanedScriptTag + inline;
}
async function inlineRemoteScript(html, partialSrc) {
const regExp = new RegExp(`<script src="([^"]*)${partialSrc}([^"]*)"></script>`);
const [, prefix, suffix] = regExp.exec(html);
const script = await request(prefix + partialSrc + suffix);
return replaceRemoteScriptWithInline(html, partialSrc, script);
}

(async () => {
if (unsafeWindow.navigator.userAgent.includes('Firefox')) {
alert('Krunkbot does not work on Firefox.');
return;
}
window.stop();
logger.log('Loading Krunkbot...');
let newHtml = await request(document.location.href);
const gameScriptHash = /game\.([^\.]+)\.js/.exec(newHtml)[1];
const gameScript = await request(`https://krunker.io/js/game.${gameScriptHash}.js`);
newHtml = await inlineRemoteScript(newHtml, 'libs/zip.js');
newHtml = await inlineRemoteScript(newHtml, 'libs/zip-ext.js');
newHtml = replaceRemoteScriptWithInline(newHtml, 'js/game', patchGameScript(gameScript));
const bot = new Krunkbot();
bot.init();
unsafeWindow[getRandomizedName('onTick')] = (me, inputs) => bot.onTick(me, inputs);
unsafeWindow[getRandomizedName('onKeyPressed')] = (e) => bot.onKeyPressed(e);
document.open();
document.write(newHtml);
document.close();
logger.log('Successfully loaded Krunkbot!');
})();