// ==UserScript==
// @name Neon's Hitbox mod
// @namespace http://tampermonkey.net/
// @version 1.0.3-Reworkv1
// @description A Mod menu for hitbox.io. press shift+a to open the menu or click the white square on the corner.
// @author iNeonz
// @match https://heav.io/game.html
// @match https://hitbox.io/game.html
// @match https://heav.io/game2.html
// @match https://hitbox.io/game2.html
// @match https://hitbox.io/game-beta.html
// @icon https://www.google.com/s2/favicons?sz=64&domain=heav.io
// @grant none
// @run-at document-idle
// ==/UserScript==
let modmenu = document.createElement('div');
document.body.appendChild(modmenu);
let style = document.createElement('style');
style.innerHTML = `
.styled-check {
border-radius: 7px;
vertical-align: middle;
border: 1px solid black;
appearance: none;
-webkit-appearance: none;
outline: none;
background-color: #3b4353;
cursor: pointer;
}
.styled-check:checked {
appearance: none;
background-color: #537aff;
}
.styled-button:hover {
background-color: #23262d !important;
cursor: pointer;
}
.styled-text {
border: none;
outline: none;
background-color: #595b65;
color: white;
border-radius: 7px;
}
`;
document.head.appendChild(style);
let botEnabled = false;
let quickplayEnabled = false;
let settings = {};
let echoList = [];
function addElementToList(list,element,elements) {
let divider = document.createElement('div');
let content = list.querySelector('.content');
content.appendChild(divider);
divider.outerHTML = ` <div class="createWindow option divider lol" style="background-color: #17171c; width: calc(100% - 40px); font-size: 15px; height: 20px; margin: 5px; border-radius: 7px;">
${element}
<div class="removeElement" style="cursor: pointer; top: 3px; display: inline-block; position: relative; left: 20px; width: 15px; height: 15px; border-radius: 7px; background-color: red;"></div>
</div>`
divider = document.querySelector('.lol');
divider.classList.remove('lol');
return divider;
}
function addList(tab,title,list,change) {
let listTop = document.createElement('div');
tab.appendChild(listTop);
listTop.outerHTML = ` <div class="createWindow option list lol" style="width: calc(100% - 10px); font-size: 25px; min-height: 30px; height: calc(fit-content + 20px); margin: 15px; border-radius: 7px;">
${title}
<input placeholder="add element" type="text" class="createWindow option styled-text" style="position: relative; top: 10px; width: calc(100% - 20px); height: 20px;"></input>
<div class="content" style="overflow-y: scroll; max-height: 200px; position: relative; top: 10px; background-color: #292d31; width: calc(100% - 10px); font-size: 20px; height: fit-content; margin: 5px; border-radius: 7px;"></div>
</div>`
listTop = document.querySelector('.lol');
listTop.classList.remove('lol');
let input = listTop.querySelector('.styled-text');
input.onkeydown = (e) => {
if (e.which == 13) {
if (!list.includes(input.value)) {
let value = input.value;
list.push(value);
let element = addElementToList(listTop,value,list);
input.value = '';
change(list);
element.children[0].onclick = () => {
list.splice(list.indexOf(value),1);
change(list);
element.remove();
}
setTimeout(() => {
document.activeElement.blur();
},1);
}
}
}
for (let i of list) {
let element = addElementToList(listTop,i,list);
input.value = '';
element.children[0].onclick = () => {
list.splice(list.indexOf(i),1);
change(list);
element.remove();
}
}
return listTop;
}
window.addEventListener('keydown', (e) => {
if (document.activeElement.tagName == "INPUT" && e.which != 13) {
console.log('ha');
e.stopImmediatePropagation()
return;
}
if (e.which == 65 && e.shiftKey) {
modmenu.style.display = modmenu.style.display == 'none'? 'block' : 'none';
window.selectTab(lastTabSelected);
}
},true)
function addDivider(tab,title) {
let divider = document.createElement('div');
tab.appendChild(divider);
divider.outerHTML = ` <div class="createWindow option divider" style="text-align: center; width: calc(100% - 10px); font-size: 30px; height: 30px; margin: 5px; border-radius: 7px;">${title}</div>`
}
function addDetail(tab,title) {
let divider = document.createElement('div');
tab.appendChild(divider);
divider.outerHTML = ` <div class="createWindow option detail" style="width: calc(100% - 10px); font-size: 13px; height: 13px; margin: 5px; border-radius: 7px;">${title}</div>`
}
function addButton(tab,title) {
let btn = document.createElement('div');
tab.appendChild(btn);
btn.outerHTML = ` <div class="createWindow option styled-button lol" style="background-color: #3d424d; width: calc(100% - 30px); font-size: 20px; height: 30px; margin-left: 20px; margin-top: 5px; border-radius: 7px;">${title}</div>`
btn = document.querySelector('.lol');
btn.classList.remove('lol');
return btn;
}
function addCheckButton(tab,title,checked) {
let check = document.createElement('div');
tab.appendChild(check);
check.outerHTML = ` <div class="createWindow option check lol" style="background-color: #25262a; width: calc(100% - 10px); font-size: 25px; height: 30px; margin: 5px; border-radius: 7px;">${title}</div>`
check = document.querySelector('.lol');
check.classList.remove('lol');
let input = document.createElement('input');
check.appendChild(input);
input.outerHTML = ` <input type="checkbox" style="accent-color: #454755; top: -5px; position: relative; width: 20px;height: 20px;" class="styled-check tab input lol"></input>`
input = document.querySelector('.lol');
input.classList.remove('lol');
input.checked = checked;
return input;
}
let highestMapId = 0;
let bwLIST = JSON.parse(localStorage.getItem('bannedwords') || '[]');
let kickAFK = false;
let levels = localStorage.getItem('levels') || false;
let kickLaggy = false;
fetch("https://hitbox.io/scripts/map_get_newest_spice.php", {
"headers": {
"accept": "*/*",
"content-type": "application/x-www-form-urlencoded",
"priority": "u=1, i",
},
"body": "startingfrom=0",
"method": "POST",
})
.then(r => r.json())
.then(r => {
highestMapId = r.maps[0].id-602;
});
const render = window.PIXI.Text.prototype._render;
window.PIXI.Text.prototype._render = function(...args){
render.call(this,...args)
if (this.parent && this._text) {
let user = findUser(this._text);
if (levels && user) {
if (!this._text.includes(' (')) {
this.text += ' ('+user.lvl+(myid == user.id? '🔺)' : '🔹)');
this.width /= 1.6;
this.height /= 1.6;
}
}
}
}
let lastTabSelected = 'Hosting & Utils';
const modMenuTabs = {
"Hosting & Utils": function (tab) {
if (myid != hostId) {
tab.style.opacity = .3;
tab.style.pointerEvents = 'none';
addDivider(tab,"You need to be host to use this tab.");
}
addDetail(tab,"Press shift+a to open the menu");
addDivider(tab,"Teams");
addButton(tab,'Move all Blue').onclick = () => {
for (let i of users) {
WSS.send(`42[1,[47,{"i":${i.id},"t":3}]]`)
}
};
addButton(tab,'Move all Red').onclick = () => {
for (let i of users) {
WSS.send(`42[1,[47,{"i":${i.id},"t":2}]]`)
}
};
addButton(tab,'Shuffle teams').onclick = () => {
let teams = [2,3].sort(() => .5 - Math.random());
let score = [0,0,0,0,0];
for (let i of users.sort(() => .5 - Math.random())) {
let team = -1;
let lowest = 1/0;
for (let x of teams) {
if (score[x] < lowest) {
lowest = score[x];
team = x;
}
}
score[team] += 1;
WSS.send(`42[1,[47,{"i":${i.id},"t":${team}}]]`)
}
};
addButton(tab,'Move all Spec').onclick = () => {
for (let i of users) {
WSS.send(`42[1,[47,{"i":${i.id},"t":0}]]`)
}
};
addButton(tab,'Move all FFA').onclick = () => {
for (let i of users) {
WSS.send(`42[1,[47,{"i":${i.id},"t":1}]]`)
}
};
addDivider(tab,"Auto hosting");
let qpb = addCheckButton(tab,"Quickplay enabled? | ",quickplayEnabled);
addDetail(tab,"Idle hosting. automatically starts a new map after round end.");
qpb.onchange = () => {
quickplayEnabled = qpb.checked;
};
let rngMap = addButton(tab,'Random Map');
addDetail(tab,"Chooses a random map (includes private maps)");
rngMap.onclick = () => {
modmenu.style.display = 'none';
WSS.send(`42[1,[42,${Math.floor(Math.random()*highestMapId)+602}]]`);
}
let kkp = addCheckButton(tab,"Auto kick Laggy? (600+ ms) | ",kickLaggy);
kkp.onchange = () => {
kickLaggy = kkp.checked;
};
let kka = addCheckButton(tab,"Auto kick AFK? (afk for 2 minutes) | ",kickAFK);
kka.onchange = () => {
kickAFK = kka.checked;
};
addList(tab,"Banned words",bwLIST,(e) => {
bwLIST = e;
localStorage.setItem('bannedwords',JSON.stringify(bwLIST));
});
addDivider(tab,"Settings");
addButton(tab,'Download Settings').onclick = () => {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(settings)));
element.setAttribute('download', 'game_settings.json');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
};
addDetail(tab,"Download current game settings as a file to import later");
addButton(tab,'Import Settings').onclick = () => {
let input = document.createElement('input');
input.setAttribute('accept','.json');
input.type = 'file';
input.click();
input.onchange = (e) => {
let a = e.target.files[0];
const reader = new FileReader();
reader.onload = () => {
WSS.send('42'+JSON.stringify([1,[62,JSON.parse(reader.result)]]));
WSS.onmessage({data:'42'+JSON.stringify([63,JSON.parse(reader.result)])})
modmenu.style.display = 'none';
}
reader.readAsText(a);
}
}
},
"Fun & Misc": function (tab,tabName) {
addDivider(tab,"Bot");
let bbn = addCheckButton(tab,"Bot enabled? | ",botEnabled);
bbn.onchange = () => {
botEnabled = bbn.checked;
};
addDivider(tab,"Chat");
addList(tab,"Copy players",echoList,(e) => {
echoList = e;
});
addButton(tab,'Clear List').onclick = () => {
echoList = [];
window.selectTab(tabName);
};
addDetail(tab,"Echo list | Copy any message a player included in the list sends.");
},
"Visual": function (tab,tabName) {
let bbn = addCheckButton(tab,"Show player levels ingame | ",levels);
bbn.onchange = () => {
levels = bbn.checked;
localStorage.setItem('levels',levels);
};
}
}
let modMenuButton = document.createElement('div');
document.body.appendChild(modMenuButton);
modMenuButton.outerHTML = `<div class="modmenubutton" style="position: absolute; right: 15px; top: 50px; width: 30px; height: 30px; border-radius: 10px; background-color: #ffffff;"></div>`
modmenu.outerHTML = `<div style="opacity: .95; display: none; z-index: 9999999; right: 90px; top: 90px; position: absolute; width: calc(100% - 170px); height: calc(100% - 180px); background-color: #25262a; border-radius: 7px;" class="createWindow modMenu">
<div class="createWindow modMenuTabs" style="background-color: #131616; position: absolute; top: 20px; left: 20px; width: 200px; height: calc(100% - 40px); border-radius: 7px;"></div>
<div class="createWindow openTab" style="overflow-x: hidden; background-color: #131616; overflow-y: scroll; position: absolute; top: 20; left: 240px; width: calc(100% - 280px); height: calc(100% - 40px); border-radius: 7px;"></div>
</div>`
modmenu = document.querySelector('.modMenu');
modMenuButton = document.querySelector(".modmenubutton");
modMenuButton.onclick = () => {
modmenu.style.display = modmenu.style.display == 'none'? 'block' : 'none';
window.selectTab(lastTabSelected);
}
const tabs = document.querySelector('.createWindow .modMenuTabs');
const openTab = document.querySelector('.createWindow .openTab');
window.selectTab = (tab) => {
openTab.style.opacity = '1';
openTab.style.pointerEvents = 'all';
openTab.replaceChildren();
modMenuTabs[tab](openTab,tab);
}
for (let i in modMenuTabs) {
let tabButton = document.createElement('div');
tabs.appendChild(tabButton);
tabButton.outerHTML = `<div onclick="javascript:window.selectTab('${i}');" class="createWindow tab" style="cursor: pointer; background-color: #25262a; width: calc(100% - 10px); font-size: 25px; height: 30px; margin: 5px; border-radius: 7px;">${i}</div>`
}
const codeNames = {};
const codeNamesRegex = {
"simulation": {
reg: /\];\}.{0,2}\(.{0,3}\) {var .{0,3},.{0,3},.{0,3},.{0,3},.{0,3},.{0,3};(.*?)\{throw new Error\("Failed to simulate(.*?)\);\}(.*?)\.step\((.*?)\);(.*?).{0,2}\(\);(.*?)\}.{0,2}\(\)/ig,
verify: function(match)
{
//console.log(match);
let world = match[0].match(/this\..{2,2}\.step\(/ig)[0];
let sim = match[0].split(";}")[1].split("(")[0];
//console.log(sim);
let thisses = match[0].split("this.");
//console.log(thisses);
for (let i of thisses){
if (i.match("=")){
i = i.split("=")[0];
}else{
i = null;
}
}
thisses.filter(a => a != null);
//console.log(thisses);
//console.log([sim,thisses[1].split(".")[0],thisses[1].split(".")[1].split("(")[0]]);
return [sim,thisses[1].split(".")[0],thisses[1].split(".")[1].split("(")[0],world.split("this.")[1].split(".")[0]];
}
},
}
//funny
setInterval(() => {
if (hostId == myid && kickAFK) {
for (let i of users) {
if (Date.now() > i.act+120000) {
WSS.send(`42[1,[32,{"id":${i.id},"ban":0}]]`);
}
}
}
},1000);
parent.document.getElementById("adboxverticalright").style.top = "-200%";
parent.document.getElementById("adboxverticalleft").style.top = "-200%";
const lerpNumber = function(a, b, weight) {
return ((1 - weight) * a + weight * b);
};
let bot = false;
let myid = -1;
let quickplay = false;
let qpdelay = 0;
let hostId = -2;
let DN = [
"gsFightersCollide",
"recordMode",
"o",
"l",
"u",
"m",
"g",
"v",
"k",
"N",
"S",
"M",
"C",
"_",
"T",
"P",
"B",
"I",
"F",
"R",
"O",
"A",
"D",
"L",
"U",
"H",
"J",
"W",
"G",
"Y", // ss
"V",
"q",
"K",
"X",
"Z",
"$",
"tt",
"it",
"st",
"ht",
"et",
"nt",
"ot",
"rt",
"at",
"lt",
"ut",
"ct",
"dt",
"wt",
"ft",
"gt",
"bt"
]
let stateMaker;
let mostScore = -1;
for (let a1 in window.multiplayerSession){
let a = window.multiplayerSession[a1];
if (typeof a == "object")
{
let score = 0;
for (let x1 in a){
let x = a[x1];
if (typeof x == "object")
{
if (x.constructor.name == "Array"){
}
else
{
let length = 0;
for (let y1 in x){
let y = x[y1];
length++
if (length > 2){
break;
}
}
if (length == 1){
for (let y1 in x){
let y = x[y1];
if (y.constructor.name == "Map"){
score++
}
break;
}
}else{
let isDN = true;
for (let i of DN){
if (!i in x){
isDN = false;
break;
}
}
if (isDN){
score+=5;
}
}
}
}
}
if (score > mostScore && score < 52){
mostScore = score;
stateMaker = a;
}
}
}
let users = [];
window.requestAnimationFrame = new Proxy( window.requestAnimationFrame, {
apply( target, thisArgs, args ) {
Reflect.apply(...arguments);
}
})
const originalSend = window.WebSocket.prototype.send;
const excludewss = [];
let WSS = 0;
function findUser(id){
for (let t in users) {
let o = users[t];
if (o.id == id || o.name == id){
o.index = t;
return o;
break;
}
}
}
window.WebSocket.prototype.send = function(args) {
if(this.url.includes("/socket.io/?EIO=3&transport=websocket&sid=")){
if(typeof(args) == "string" && !excludewss.includes(this)){
if (!WSS){
WSS = this;
}
if (WSS == this){
if (args.startsWith('42[1,[')) {
try{
let packet = JSON.parse(args.slice(5,-1))
if (packet[0] == 62) {
settings = packet[1];
}
if (quickplayEnabled) {
if (packet[0] == 68 && myid == hostId) {
WSS.send(`42[1,[42,${Math.floor(Math.random()*highestMapId)+602}]]`);
setTimeout(() => {document.querySelector("#appContainer > div.lobbyContainer > div.settingsBox > div.startButton.settingsButton").click();},500);
}
}
}catch(error){}
}else if (args.startsWith('42[2,')) {
myid = 0;
hostId = 0;
}
}else{
excludewss.push(this);
}
//console.log('SENT',args);
}
if (!this.injected){
this.injected = true;
const originalClose = this.onclose;
this.onclose = (...args) => {
if (WSS == this){
WSS = 0;
users = [];
hostId = -2;
quickplay = false;
}
originalClose.call(this,...args);
}
this.onmessage2 = this.onmessage;
this.onmessage = function(event){
if(!excludewss.includes(this) && typeof(event.data) == 'string'){
if (event.data.startsWith('42[')){
let packet = JSON.parse(event.data.slice(2,event.data.length));
if (packet[0] == 16) {
settings = packet[1][0];
}
if (packet[0] == 63) {
settings = packet[1];
}
if (packet[0] == 35 && kickLaggy) {
for (let i of packet[1]) {
let user = findUser(i.i);
if (user.id != hostId && hostId == myid) {
if (!user.LagStrikes) {
user.LagStrikes = 0;
}
if (i.p > 600) {
user.LagStrikes += 1;
if (user.LagStrikes > 6) {
WSS.send(`42[1,[32,{"id":${user.id},"ban":0}]]`);
}
}else{
if (user.LagStrikes > 0) {
user.LagStrikes -= .5;
}
}
}
}
}
if (packet[0] == 12) {
let user = findUser(packet[1][3]);
if (user) {
user.act = Date.now();
}
}
if (packet[0] == 7){
myid = packet[1][0]
hostId = packet[1][1];
for (let i of packet[1][3]){
users.push({"act": Date.now(),"team": i[2],"color":(i[7][0] || i[7][1]),"name":i[0],"id":i[4],"lvl":i[6]});
}
}
if (packet[0] == 29) {
let user = findUser(packet[1]);
user.act = Date.now();
if (echoList.includes(user.name)) {
WSS.send('42'+JSON.stringify([1,[28,packet[2]]]));
}
if (hostId == myid) {
for (let i of bwLIST) {
if (packet[2].toLowerCase().includes(i.toLowerCase())) {
WSS.send(`42[1,[32,{"id":${user.id},"ban":0}]]`);
}
}
}
}
if (packet[0] == 25){
let plr = findUser(packet[1]);
if (plr){
plr.team = packet[2];
}
}
if (packet[0] == 9){
hostId = packet[2];
let user = findUser(packet[1]);
if (user){
if (user.pet){
user.pet.destroy();
user.pet = null;
}
users.splice(user.index,1);
}
}
if (packet[0] == 45){
hostId = packet[1];
if (hostId != myid){
quickplay = false;
}
}
if (packet[0] == 8){
users.push({"act": Date.now(),"name":packet[1][0],"color":(packet[7]? (packet[7][1] || packet[7][0]):undefined),"team":packet[1][2],"id":packet[1][4],"lvl":packet[1][6]});
}
}
}
this.onmessage2(event);
}
}
}
return originalSend.call(this, args);
}
let chats = document.getElementsByClassName('content');
let inputs = document.getElementsByClassName('input');
let chatI = [];
for (let c of inputs){
if (c.parentElement.classList.contains('inGameChat') || c.parentElement.classList.contains('chatBox')){
chatI.push(c);
}
}
window.hescape = (s) => {
let lookup = {'$':'$','%':'%','.':'.','+':'+','-':'-','&':"&",'"': """,'\'': "'",'<': "<",'*':'*','=':'=','>': ">",'#':'#',':':':',';':';','`':'`'};
return s.replace( /[\*=%#\-+&"'<>]/g, c => lookup[c] );
}
function getRGBFromNUM(colorID,offset,max){
const red = (colorID >> 16) & 0xFF;
const green = (colorID >> 8) & 0xFF;
const blue = colorID & 0xFF;
// Construct the RGB color representation
return `rgb(${Math.max(max || 0,red-(offset || 0))}, ${Math.max(max || 0,green-(offset || 0))}, ${Math.max(max || 0,blue-(offset || 0))})`;
}
function display(text,ingamecolor,lobbycolor,sanitize){
if (WSS){
let div = document.createElement('div');
div.classList.add('statusContainer');
let span = document.createElement('span');
span.classList.add('status');
span.style.color = lobbycolor || "#ffffff";
if (sanitize != false){
span.textContent = text;
}else{
span.innerHTML = text;
}
span.style.backgroundColor = 'rgba(37, 38, 42, 0.768627451)';
div.style.borderRadius = '7px';
div.appendChild(span);
let clone = div.cloneNode(true);
clone.children[0].style.color = ingamecolor || '#ffffff';
setTimeout(() => {
clone.remove();
},11500);
for (let i of chats){
if (i.parentElement.classList.contains('chatBox')){
i.appendChild(div);
i.scrollTop = Number.MAX_SAFE_INTEGER;
}else{
i.appendChild(clone);
}
}
}
}