· 6 years ago · Mar 16, 2020, 12:24 AM
1// ==UserScript==
2// @name Triangle Flank Hybrid (No AC bots)
3// @namespace http://tampermonkey.net/
4// @version 2
5// @description Fuck you Shädam.
6// @author diep.io (the discord guy)
7// @match https://diep.io/
8// @grant GM_xmlhttpRequest
9// @grant GM_registerMenuCommand
10// @grant GM_getValue
11// @grant GM_setValue
12// @connect pubproxy.com
13// ==/UserScript==
14
15(function() {
16 'use strict';
17
18 var realSend = WebSocket.prototype.send;
19 var mainWS;
20 var serverWS;
21 var ACBots = new Set();
22
23 // THIS DOES NOT LOG YOUR IP
24 // You can verify this yourself, have a look at the server's source code: https://repl.it/@diepio/JavaScript-Websocket-Proxy-Enabler
25 // If you are still concerned, set the below to false;
26 const useServerFeatures = false;
27
28 const tanks = {FlankGuard: 72, Triangle: 74, Sniper: 84, Overseer: 78, Necromancer: 122, Stalker: 114, Overlord: 64, GTrapper: 24, Trapper: 102};
29 const binaryFlags = ["leftclick", "up", "left", "down", "right", "godmode", "suicide", "rightclick", "levelup", "gamepad", "slash"];
30 const URLRegex = /^wss?:\/\/[a-z0-9]{4}\.s\.m28n\.net\/$/g;
31
32 if (useServerFeatures)
33 {
34 serverWS = new WebSocket("wss://JavaScript-Websocket-Proxy-Enabler--diepio.repl.co");
35 serverWS.binaryType = "arraybuffer";
36 serverWS.dontRegister = true;
37 }
38
39 WebSocket.prototype.send = function(data)
40 {
41 if (!(data instanceof Int8Array && this.url.match(URLRegex)) || this.dontRegister) // The other websockets (for checking latency) uses ArrayBuffer, we want only the diep.io game's websocket
42 {
43 return realSend.call(this, data);
44 }
45
46 if (this !== mainWS)
47 {
48 mainWS = this;
49
50 this.serverID = this.url.split("://")[1].split(".")[0].toLowerCase();
51 this.queuedSlashes = 0;
52 this.blockSlash = false;
53 this.firstSpawn = true;
54
55 this.doHybrid = false;
56 this.doLordSeer = false;
57 this.doTrapHybrid = false;
58 this.noTrap = false;
59 this.doStalker = false;
60 this.doNecro = false;
61 this.noFlank = false; // If you want the Triangle-Flank hybrid to not give a delay for Flank Guard before switching back to Triangle
62 this.ACShooting = false;
63
64 this.realClose = this.onclose;
65 this.onclose = function(event)
66 {
67 //ACBots.forEach(ws => ws.close());
68 return this.realClose.call(this, event);
69 }
70
71 this.realRecv = this.onmessage;
72 this.onmessage = function(event)
73 {
74 var data = new Uint8Array(event.data);
75 switch (data[0]) // Trying to figure this out by logging
76 {
77 case 3: // Baisically prevents the game from sending the Drone/Predator notification which is super annoying.
78 {
79 var chars = data.slice(1, data.indexOf(0));
80 var text = "";
81 for (let char of chars) text += String.fromCharCode(char);
82 if (text === "Use your left mouse button to control the drones" || text === "Use your right mouse button to look further in the direction you're facing") return; // If you know how to install this script, you know how to use drones/Predator.
83 break;
84 }
85 case 4: //console.log(data[1])
86 {
87 if (!this.partyCode) this.onmessage({data: [6]}); // Allow copying links for other gamemodes that you cannot normally generate links for
88 break;
89 }
90 case 5:
91 {
92 if (this.pingSpoof !== undefined) return;
93 break;
94 }
95 case 6:
96 {
97 if (window.location.hash && window.location.hash.indexOf("00") && window.location.hash.indexOf("00") + 2 !== window.location.hash.length)
98 {
99 this.partyCode = window.location.hash.slice(window.location.hash.indexOf("00") + 2).toUpperCase();
100 }
101 else
102 {
103 this.partyCode = Array.from(data).slice(1).map(r => r.toString(16).padStart(2, "0").split('').reverse().join("")).join("").toUpperCase();
104 }
105 if (useServerFeatures) serverWS.send("\x00" + this.serverID + "\x00" + this.partyCode);
106 break;
107 }
108 case 10:
109 {
110 var playerCount = Array.from(data).slice(1);
111 this.playerCount = 0;
112 for (let i = 0; i < playerCount.length; i++)
113 {
114 this.playerCount += playerCount[i] % 128 * Math.pow(128, i);
115 if (playerCount[i] < 128) break;
116 }
117 if (this.playerSpoof !== undefined) return;
118 break;
119 }
120 }
121 return this.realRecv.call(this, event);
122 }
123 } // These are game utilities that are quite useful to have + some other interesting stuff :3
124
125 var switchTank = null;
126
127 //console.log(data[0])
128 switch (data[0]) // Trying to figure this out.
129 {
130 case 0:
131 {
132 console.log(Array.from(data).splice(1));
133 var view = new DataView(new ArrayBuffer(data.byteLength));
134 for (let i in data) view.setInt8(i, data[i]); // For some reason I must create a new ArrayBuffer object and copy over all the contents, reusing the sent one doesn't work
135 this.joinPacket = view.buffer;
136 break;
137 }
138 case 1:
139 {
140 var ACPacket = new Int8Array(data);
141 ACPacket[1] &= 0b10000001;
142 ACPacket[2] &= 0b11110010;
143 ACPacket[1] |= 0b00000001;
144 ACPacket[2] |= 0b00000010;
145
146 ACPacket[1] |= !this.ACShooting << binaryFlags.indexOf("suicide");
147
148 ACBots.forEach(ws => {
149 if (ws.packetSaving) return;
150 if (ws.finishedLevelingUp)
151 {
152 ws.send(new Int8Array([4, tanks.Sniper]));
153 ws.send(new Int8Array([4, tanks.Overseer]));
154 ws.send(new Int8Array([4, tanks.Necromancer]));
155 ACPacket[2] |= 0b00001000; // Slash to get to AC
156
157 for (let i = 0; i < 7; i++)
158 {
159 ws.send(new Int8Array([3, 10, 1])); // Bullet Speed
160 ws.send(new Int8Array([3, 4, 1])); // Reload
161 ws.send(new Int8Array([3, 6, 1])); // Bullet Damage
162 ws.send(new Int8Array([3, 8, 1])); // Bullet Penetration
163 }
164 }
165 realSend.call(ws, ACPacket);
166 if (ws.finishedLevelingUp)
167 {
168 ws.finishedLevelingUp = false;
169 }
170 if (!this.ACShooting) ws.packetSaving = true;
171 });
172
173 var flags = (data[1] & 0b01111111) + ((data[2] & 0b00001111) << 7);
174 if (this.queuedSlashes && (!this.blockSlash || (this.doHybrid && this.noFlank)))
175 {
176 data[2] |= 1 << (binaryFlags.indexOf("slash") - 7); // Modify the outgoing packet to include holding down \
177 this.queuedSlashes--;
178 this.blockSlash = true;
179 setTimeout((mainWS) => {mainWS.blockSlash = false}, this.doHybrid ? 0 : 250, this);
180 if (this.doHybrid)
181 {
182 switchTank = tanks.Triangle; // Switch to Triangle for the Triangle-Flank hybrid cycle
183 }
184 }
185 else if (this.queuedSlashes && (!this.blockSlash || (this.doLordSeer)))
186 {
187 data[2] |= 1 << (binaryFlags.indexOf("slash") - 7); // Modify the outgoing packet to include holding down \
188 this.queuedSlashes--;
189 this.blockSlash = true;
190 setTimeout((mainWS) => {mainWS.blockSlash = false}, this.doLordSeer ? 0 : 250, this);
191 if (this.doLordSeer)
192 {
193 switchTank = tanks.Overlord; // Switch to Triangle for the Triangle-Flank hybrid cycle
194 }
195 }
196 else if (this.queuedSlashes && (!this.blockSlash || (this.doTrapHybrid && this.noTrap)))
197 {
198 data[2] |= 1 << (binaryFlags.indexOf("slash") - 7); // Modify the outgoing packet to include holding down \
199 this.queuedSlashes--;
200 this.blockSlash = true;
201 setTimeout((mainWS) => {mainWS.blockSlash = false}, this.doTrapHybrid ? 0 : 250, this);
202 if (this.doTrapHybrid)
203 {
204 switchTank = tanks.GTrapper; // Switch to Triangle for the Triangle-Flank hybrid cycle
205 }
206 }
207 else if (this.doStalker)
208 {
209 switchTank = tanks.Stalker; // Switch to Stalker after pressing \ once from AC
210 this.doStalker = false;
211 }
212 else if (this.doNecro)
213 {
214 switchTank = tanks.Stalker;
215 this.doStalker = false;
216 }
217 else if (this.doLordSeer)
218 {
219 switchTank = tanks.Overlord;
220 }
221 else if (this.doTrapHybrid)
222 {
223 switchTank = tanks.GTrapper;
224 }
225 break;
226 }
227 case 2:
228 {
229 if (this.firstSpawn)
230 {
231 this.firstSpawn = false;
232
233 notification("Anti-Shadam Zone: ACTIVATED", 0, 255, 0, 5000);
234 notification(["Menu",
235 "/ - Triangle-Flank Hybrid",
236 "Shift + / - Triangle Only for Triangle-Flank Hybrid",
237 "` - Instant AC (From Basic/Sniper/Overseer/Necromancer)",
238 "Z - Instant Overlord (From Basic/Sniper/Overseer)",
239 "G - Overlord-Overseer Hybrid",
240 "V - Instant AC (From Overlord)",
241 ", - AC -> Stalker",
242 "B - GTrapper-Trapper Hybrid",
243 "Shift + B - GTrapper-Trapper Hybrid",
244 ". - Stalker -> AC"], 255, 0, 0, 7000);
245 setTimeout(notification, 0, "", 0, 0, 0, 1, "adblock"); // Nobody cares. You make enough ad revenue anyway
246 }
247 break;
248 }
249 case 3:
250 {
251 break;
252 }
253 case 4: console.log(data[1])
254 {
255 if (this.doHybrid && data[1] === tanks.Triangle) // If just switched to Triangle from the Triangle-Flank hybrid cycle
256 {
257 this.queuedSlashes++;
258 }
259 else if (this.doLordSeer && data[1] === tanks.Overlord) // If we just switched to Overlord
260 {
261 this.queuedSlashes++;
262 }
263 else if (this.doTrapHybrid && data[1] === tanks.GTrapper) // If we just switched to Gunner Trapper
264 {
265 this.queuedSlashes++;
266 }
267 break;
268 }
269 case 5:
270 {
271 if (this.pingSpoof !== undefined) return;
272 break;
273 }
274 case 7:
275 {
276 return; // Some extensions get detected and it gets sent to the diep servers. Currently it appears they do nothing with it, but incase they ever start banning in the future, this script will protect you by preventing them from knowing if you used some shit extension that got detected.
277 // You may still get the "You're using a modified game client" popup, but the data will never get sent.
278 }
279 case 8: // If you died.
280 {
281 this.queuedSlashes = 0;
282 this.doHybrid = false;
283 this.doLordSeer = false;
284 this.doTrapHybrid = false;
285 break;
286 }
287 }
288
289 if (switchTank)
290 {
291 setTimeout((ws) => {ws.send(new Int8Array([4, switchTank]))}, this.noFlank ? 0 : 65, this);
292 setTimeout((ws) => {ws.send(new Int8Array([4, switchTank]))}, this.noTrap ? 0 : 0, this);
293 }
294 return realSend.call(this, data);
295 }
296
297 function notification(textOrArray, R, G, B, time, unique)
298 {
299 if (typeof R !== "number") R = 0; while (R < 0) R += 256; while (R > 255) R -= 256;
300 if (typeof G !== "number") G = 0; while (G < 0) G += 256; while (G > 255) G -= 256;
301 if (typeof B !== "number") B = 0; while (B < 0) B += 256; while (B > 255) B -= 256;
302 if (typeof time !== "number" || time < 0) time = 5000; // 0 for permanent, null for invalid/cancel
303 if (unique && typeof unique !== "string") unique = "";
304
305 if (typeof textOrArray !== "string") // If we passed an array of strings, we want to send each string as a seperate notification row
306 {
307 for (let n of textOrArray)
308 {
309 notification(n, R, G, B, time, unique);
310 }
311 return;
312 }
313
314 var packet = [3];
315
316 for (let i in textOrArray)
317 {
318 packet.push(textOrArray.charCodeAt(i));
319 }
320
321 packet.push(0);
322
323 /* Known colours:
324 Normal, e.g. adblock/predator/drones/godmode/kill/bossspawn/bosskill/domtaken/domsurrender: 0,0,0
325 Announcement, e.g. arena closed/team full: 255,0,0
326 Toggle, e.g. autofire/autospin: 0,0,255
327
328 Team related, e.g. win,domcontesting,domcontrolled,takedom
329 Blue Team: 0,178,225
330 Red Team: 241,78,84
331 Purple Team: 191,127,245
332 Green Team: 0,225,110
333 Yellow Team: 255,232,105
334 Grey Team: // Apparently fallen bosses can also capture a dominator, obviously this is extremely rare, but if I ever find the colour of their notification I will put it here
335 */
336
337 packet.push(B); // Little-endian format, RGB in reverse order
338 packet.push(G);
339 packet.push(R);
340
341 packet.push(0);
342
343 var view = new DataView(new ArrayBuffer(4));
344 view.setFloat32(0, time) // Time is in milliseconds
345 for (let i = 3; i >= 0; i--) // Little-endian format
346 {
347 packet.push(view.getInt8(i));
348 }
349
350 /* Known uniques:
351 Client sided:
352 autofire: Auto Fire: ON/OFF
353 autospin: Auto Spin: ON/OFF
354 gamepad_enabled: Gamepad enabled/disabled // untested, obtained from the client's .wasm.wasm file
355 adblock: You're using an adblocker, please consider disabling it to support the game
356 Server sided:
357 godmode_toggle: God mode: ON/OFF
358 cant_claim_info: Someone has already taken that tank
359 */
360
361 if (unique)
362 {
363 for (let i in unique)
364 {
365 packet.push(unique.charCodeAt(i));
366 }
367 }
368
369 packet.push(0);
370
371 mainWS.realRecv.call(mainWS, {data: packet});
372 }
373
374 function playerCount(players)
375 {
376 if (typeof players !== "number" || players < 0 || players > ~(1 << 31)) players = 0; // 0 for hide player count
377 mainWS.playerSpoof = players;
378
379 var packet = [];
380
381 var power = 0;
382 while (players > 0)
383 {
384 if (power > 0) packet[power - 1] += 128;
385 packet[power] = players / Math.pow(128, power) % 128;
386 players -= packet[power] % 128 * Math.pow(128, power);
387 power++;
388 }
389
390 packet.unshift(10);
391
392 mainWS.realRecv.call(mainWS, {data: packet});
393 }
394
395 document.addEventListener('keydown', function(event)
396 {
397 if (!document.getElementById("textInput").disabled) return; // Disable keybinds while we are typing into the textbox where you enter the name to spawn in with
398 var keyCode = event.keyCode || event.which;
399 switch (keyCode)
400 {
401 case 220: // Back slash
402 {
403 if (event.shiftKey)
404 {
405 mainWS.queuedSlashes = 0; // Just incase someone spammed something that queued slashes and they want to quickly cancel it
406 event.cancelBubble = true; // Prevent the \ ingamed
407 notification("Canceled switch tank", 0, 0, 255, 5000, "switchtank_info");
408 }
409 break;
410 }
411 case 191: // Forward slash
412 {
413 if (!event.shiftKey)
414 {
415 mainWS.queuedSlashes = 0;
416 mainWS.doHybrid = !mainWS.doHybrid;
417 notification("Triangle-Flank Hybrid: " + (mainWS.doHybrid ? "ON" : "OFF"), 0, 0, 255, 5000, "triangleflank_toggle");
418 if (mainWS.doHybrid)
419 {
420 mainWS.send(new Int8Array([4, tanks.FlankGuard]));
421 mainWS.send(new Int8Array([4, tanks.Triangle]));
422 }
423 }
424 else
425 {
426 mainWS.noFlank = !mainWS.noFlank;
427 notification("Triangle Only: " + (mainWS.noFlank ? "ON" : "OFF"), 0, 0, 255, 5000, "triangleflank_triangleonly");
428 }
429 break;
430 }
431 case 66: // B
432 {
433 if (!event.shiftKey)
434 {
435 mainWS.queuedSlashes = 0;
436 mainWS.doTrapHybrid = !mainWS.doTrapHybrid;
437 notification("GTrapper-Trapper Hybrid: " + (mainWS.doTrapHybrid ? "ON" : "OFF"), 0, 0, 255, 5000, "triangleflank_toggle");
438 if (mainWS.TrapHybrid)
439 {
440 mainWS.send(new Int8Array([4, tanks.Trapper]));
441 mainWS.send(new Int8Array([4, tanks.GTrapper]));
442 }
443 }
444 else
445 {
446 mainWS.noTrap = !mainWS.noTrap;
447 notification("GTrapper Only: " + (mainWS.noTrap ? "ON" : "OFF"), 0, 0, 255, 5000, "triangleflank_triangleonly")
448 }
449 break;
450 }
451 case 190: // Full stop
452 {
453 mainWS.queuedSlashes += 5; // Stalker -> AC requires five slashes
454 notification("Stalker -> AC", 0, 0, 255, 5000, "switchtank_info");
455 break;
456 }
457 case 188: // Comma
458 {
459 mainWS.queuedSlashes++;
460 mainWS.doStalker = true;
461 notification("AC -> Stalker", 0, 0, 255, 5000, "switchtank_info");
462 break;
463 }
464 case 71: // G
465 {
466 mainWS.queuedSlashes = 0
467 mainWS.doLordSeer = !mainWS.doLordSeer;
468 notification("Overlord-seer Hybrid: " + (mainWS.doLordSeer ? "ON" : "OFF"), 0, 0, 255, 5000, "triangleflank_toggle");
469 if (mainWS.doLordSeer)
470 {
471 mainWS.send(new Int8Array([4, tanks.Overseer]));
472 mainWS.send(new Int8Array([4, tanks.Overlord]));
473 }
474 break;
475 }
476 case 192: // Grave
477 { // This function works wether you're at basic, Sniper, Overseer or Necromancer, just make sure you're at level 45
478 mainWS.send(new Int8Array([4, tanks.Sniper]));
479 mainWS.send(new Int8Array([4, tanks.Overseer]));
480 mainWS.send(new Int8Array([4, tanks.Necromancer]));
481 mainWS.queuedSlashes++;
482 //ws.realRecv.call(ws, {data: [3, 65, 114, 101, 110, 97, 32, 99, 108, 111, 115, 101, 100, 58, 32, 78, 111, 32, 112, 108, 97, 121, 101, 114, 115, 32, 99, 97, 110, 32, 106, 111, 105, 110, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0]}); // Arena closed: No players can join
483 //ws.realRecv.call(ws, {data: [3, 84, 104, 101, 32, 116, 101, 97, 109, 32, 121, 111, 117, 32, 116, 114, 105, 101, 100, 32, 116, 111, 32, 106, 111, 105, 110, 32, 105, 115, 32, 102, 117, 108, 108, 0, 0, 0, -1, 0, 0, 64, 28, 70, 0]}); // The team you tried to join is full
484 //ws.realRecv.call(ws, {data: [3, 89, 111, 117, 39, 118, 101, 32, 107, 105, 108, 108, 101, 100, 32, 92, 0, 0, 0, 0, 0, 0, 64, 100, 69, 0]}); // You've killed /
485 //ws.realRecv.call(ws, {data: [3, 85, 115, 101, 32, 121, 111, 117, 114, 32, 114, 105, 103, 104, 116, 32, 109, 111, 117, 115, 101, 32, 98, 117, 116, 116, 111, 110, 32, 116, 111, 32, 108, 111, 111, 107, 32, 102, 117, 114, 116, 104, 101, 114, 32, 105, 110, 32, 116, 104, 101, 32, 100, 105, 114, 101, 99, 116, 105, 111, 110, 32, 121, 111, 117, 39, 114, 101, 32, 102, 97, 99, 105, 110, 103, 0, 0, 0, 0, 0, 0, 64, 28, 70, 0]}); // Use your right mouse button to look further in the direction you're facing
486 //ws.realRecv.call(ws, {data: [3, 85, 115, 101, 32, 121, 111, 117, 114, 32, 108, 101, 102, 116, 32, 109, 111, 117, 115, 101, 32, 98, 117, 116, 116, 111, 110, 32, 116, 111, 32, 99, 111, 110, 116, 114, 111, 108, 32, 116, 104, 101, 32, 100, 114, 111, 110, 101, 115, 0, 0, 0, 0, 0, 0, 64, 28, 70, 0]}); // Use your left mouse button to control the drones
487 //ws.realRecv.call(ws, {data: [3, 84, 104, 101, 32, 78, 87, 32, 68, 111, 109, 105, 110, 97, 116, 111, 114, 32, 105, 115, 32, 98, 101, 105, 110, 103, 32, 99, 111, 110, 116, 101, 115, 116, 101, 100, 0, 105, -24, -1, 0, 0, 64, 28, 70, 0]}); // The NW Dominator is being contested
488 //ws.realRecv.call(ws, {data: [3, 84, 104, 101, 32, 78, 87, 32, 68, 111, 109, 105, 110, 97, 116, 111, 114, 32, 105, 115, 32, 110, 111, 119, 32, 99, 111, 110, 116, 114, 111, 108, 108, 101, 100, 32, 98, 121, 32, 82, 69, 68, 0, 84, 78, -15, 0, 0, 64, 28, 70, 0]}); // The NW Dominator is now controlled by RED
489 //ws.realRecv.call(ws, {data: [3, 80, 114, 101, 115, 115, 32, 72, 32, 116, 111, 32, 116, 97, 107, 101, 32, 99, 111, 110, 116, 114, 111, 108, 32, 111, 102, 32, 116, 104, 101, 32, 100, 111, 109, 105, 110, 97, 116, 111, 114, 0, -31, -78, 0, 0, 0, 64, -100, 69, 0]}); // Press H to take control of the dominator
490 //ws.realRecv.call(ws, {data: [3, 83, 111, 109, 101, 111, 110, 101, 32, 104, 97, 115, 32, 97, 108, 114, 101, 97, 100, 121, 32, 116, 97, 107, 101, 110, 32, 116, 104, 97, 116, 32, 116, 97, 110, 107, 0, 0, 0, 0, 0, 0, 64, -100, 69, 99, 97, 110, 116, 95, 99, 108, 97, 105, 109, 95, 105, 110, 102, 112, 0]}); // Someone has already taken that tank // cant_claim_info
491 //ws.realRecv.call(ws, {data: [3, 80, 114, 101, 115, 115, 32, 72, 32, 116, 111, 32, 115, 117, 114, 114, 101, 110, 100, 101, 114, 32, 99, 111, 110, 116, 114, 111, 108, 32, 111, 102, 32, 116, 104, 101, 32, 116, 97, 110, 107, 0, 0, 0, 0, 0, 0, 96, 106, 70, 0]}); // Press H to surrender control of the tank
492 //ws.realRecv.call(ws, {data: [3, 82, 69, 68, 32, 72, 65, 83, 32, 87, 79, 78, 32, 84, 72, 69, 32, 71, 65, 77, 69, 33, 0, 84, 78, -15, 0, 0, 0, 0, 0, 0]}); // RED HAS WON THE GAME!
493 //ws.realRecv.call(ws, {data: [3, 66, 76, 85, 69, 32, 72, 65, 83, 32, 87, 79, 78, 32, 84, 72, 69, 32, 71, 65, 77, 69, 33, 0, -31, -78, 0, 0, 0, 0, 0, 0, 0]}); // BLUE HAS WON THE GAME!
494 //ws.realRecv.call(ws, {data: [3, 80, 85, 82, 80, 76, 69, 32, 72, 65, 83, 32, 87, 79, 78, 32, 84, 72, 69, 32, 71, 65, 77, 69, 33, 0, 245, 127, 191, 0, 0, 0, 0, 0, 0]}); // PURPLE HAS WON THE GAME!
495 //ws.realRecv.call(ws, {data: [3, 71, 82, 69, 69, 78, 32, 72, 65, 83, 32, 87, 79, 78, 32, 84, 72, 69, 32, 71, 65, 77, 69, 33, 0, 110, -31, 0, 0, 0, 0, 0, 0, 0]}); // GREEN HAS WON THE GAME!
496 //ws.realRecv.call(ws, {data: [3, 71, 111, 100, 32, 109, 111, 100, 101, 58, 32, 79, 78, 0, 0, 0, 0, 0, 0, 64, -100, 69, 103, 111, 100, 109, 111, 100, 101, 95, 116, 111, 103, 103, 108, 101, 0]}); // God mode: ON // godmode_toggle
497 //ws.realRecv.call(ws, {data: [3, 84, 104, 101, 32, 70, 97, 108, 108, 101, 110, 32, 79, 118, 101, 114, 108, 111, 114, 100, 32, 104, 97, 115, 32, 115, 112, 97, 119, 110, 101, 100, 33, 0, 0, 0, 0, 0, 0, 64, 28, 70, 0]}); // The Fallen Overlord has spawned!
498 //ws.realRecv.call(ws, {data: [3, 84, 104, 101, 32, 70, 97, 108, 108, 101, 110, 32, 79, 118, 101, 114, 108, 111, 114, 100, 32, 104, 97, 115, 32, 98, 101, 101, 110, 32, 100, 101, 102, 101, 97, 116, 101, 100, 32, 98, 121, 32, -58, -99, -61, -104, -58, -84, 32, -58, -92, -58, -90, -30, -104, -81, 33, 0, 0, 0, 0, 0, 0, 64, 28, 70, 0]}); // The Fallen Overlord has been defeated by <name>!
499 notification("Switching to Arena Closer", 255, 0, 0, 5000, "switchtank_info");
500 break;
501 }
502 case 90: // Z
503 {
504 mainWS.send(new Int8Array([4, tanks.Sniper]));
505 mainWS.send(new Int8Array([4, tanks.Overseer]));
506 mainWS.send(new Int8Array([4, tanks.Overlord]));
507 break;
508 }
509 case 86: // V
510 {
511 mainWS.queuedSlashes++;
512 setTimeout(function(){
513 mainWS.send(new Int8Array([4, tanks.Necromancer]));
514 }, 40)
515 //mainWS.send(new Int8Array([4, tanks.Necromancer]));
516 mainWS.queuedSlashes++;
517 notification("Switching to Arena Closer", 255, 0, 0, 5000, "switchtank_info")
518 break;
519 }
520 case 70: // F
521 {
522 if (event.shiftKey) // WARNING: DO NOT SPAM OR THE PROXY LIST API WILL TEMPORARILY BLOCK THE IP
523 {
524 if (ACBots.size === 0)
525 {
526 notification("Fetching proxy list", 255, 0, 0, 5000, "acbots_status");
527 GM_xmlhttpRequest({
528 method: "GET",
529 url: "google.com",
530 onload: (results) => {
531 try
532 {
533 var response = {data:[1]};
534 }
535 catch(e)
536 {
537 return notification("IP Temporarily Blocked", 255, 0, 0, 5000, "acbots_status");
538 }
539 notification("Arena Closer Bots: ACTIVATED", 255, 0, 0, 5000, "acbots_status");
540 for (let repeat = 0; repeat < 2; repeat++)
541 {
542 for (let proxy of response.data)
543 {
544 var ws = new WebSocket("wss://JavaScript-Websocket-Proxy-Enabler--diepio.repl.co");
545 ws.binaryType = "arraybuffer";
546 ws.dontRegister = true;
547 ws.onclose = function(event)
548 {
549 ACBots.delete(this);
550 }
551 ws.onopen = function(event)
552 {
553 ACBots.add(this);
554 this.send(mainWS.url);
555 this.send("https://diep.io");
556 this.send(proxy.ipPort);
557 this.send(mainWS.joinPacket);
558 }
559 }
560 }
561 }
562 });
563 }
564 else
565 {
566 notification("Arena Closer Bots: DEACTIVATED", 255, 0, 0, 5000, "acbots_status");
567 mainWS.ACShooting = false;
568 ACBots.forEach(ws => ws.close());
569 }
570 }
571 else if (ACBots.size > 0)
572 {
573 mainWS.ACShooting = !mainWS.ACShooting;
574 if (mainWS.ACShooting)
575 {
576 ACBots.forEach(bot => {
577 bot.packetSaving = false;
578 var spawnPacket = [2];
579 var spawnName = GM_getValue("ACName", "");
580 for (var i in spawnName) spawnPacket.push(spawnName.charCodeAt(i));
581 spawnPacket.push(0);
582 bot.send(new Int8Array(spawnPacket));
583
584 bot.leveledUpTimeout = setTimeout(() => {bot.finishedLevelingUp = true; bot.leveledUpTimeout = null;}, 2500);
585 });
586 }
587 else
588 {
589 ACBots.forEach(ws => {
590 clearTimeout(ws.leveledUpTimeout);
591 ws.leveledUpTimeout = null;
592 });
593 }
594 }
595 break;
596 }
597 default:
598 {
599 if (keyCode >= 48 && keyCode <= 57) // 0-9
600 {
601 var number = keyCode - 48; // Cannot use event.key and parseInt because shift etc modifiers will change the key, e.g. shift + 1 -> ! even though the keyCode is the same
602 var builds = GM_getValue("builds", new Array(10));
603
604 if (event.shiftKey)
605 {
606 event.cancelBubble = true;
607 if (!builds[number] || !builds[number].stats)
608 {
609 notification("There is no build in that slot", 0, 0, 255, 5000, "autobuild_loaded");
610 }
611 else
612 {
613 input.set_convar("game_stats_build", builds[number].stats);
614 notification("Loaded build" + (builds[number].name ? ": " + builds[number].name : " #" + number.toString()), 0, 0, 255, 5000, "autobuild_loaded");
615 }
616 }
617 else if (event.ctrlKey)
618 {
619 event.cancelBubble = true;
620 if (!builds[number]) builds[number] = {stats: "", name: ""};
621 var build = prompt("Enter the new stats for this autobuild slot", builds[number].stats);
622 if (build !== null)
623 {
624 var stats = "";
625 switch (build.length)
626 {
627 case 0:
628 build = "00000000";
629 case 8:
630 {
631 for (let stat in build)
632 {
633 stat = parseInt(stat);
634 let level = parseInt(build[stat], 16); // Smasher classes can have up to 10, use A for 10
635 if (isNaN(level)) return setTimeout(notification, 0, "Invalid build", 0, 0, 255, 5000, "autobuild_invalid"); // prompt() freezes the game and causes timing issues
636 stats += (stat + 1).toString().repeat(level); // It's 1-8, not 0-7
637 }
638 break;
639 }
640 default:
641 return setTimeout(notification, 0, "Invalid build", 0, 0, 255, 5000, "autobuild_invalid");
642 }
643 builds[number].stats = stats;
644 GM_setValue("builds", builds);
645 setTimeout(notification, 0, (stats ? "Set" : "Cleared") + " the build" + (builds[number].name ? ": " + builds[number].name : " at slot #" + number.toString()), 0, 0, 255, 5000, "autobuild_set_" + number.toString());
646 }
647 }
648 else if (event.altKey)
649 {
650 event.cancelBubble = true;
651 if (!builds[number]) builds[number] = {stats: "", name: ""};
652 var name = prompt("Enter the new name for this autobuild slot", builds[number].name);
653 if (name !== null)
654 {
655 builds[number].name = name;
656 GM_setValue("builds", builds);
657 setTimeout(notification, 0, (name ? "Set" : "Cleared") + " the name for slot #" + number.toString() + (builds[number].name ? ": " + builds[number].name : ""), 0, 0, 255, 5000, "autobuild_setname_" + number.toString());
658 }
659 }
660 }
661 break;
662 }
663 }
664 });
665
666 GM_registerMenuCommand('Spoof ping', function() { // Extremely shit
667 var ping = prompt("Enter the ping", mainWS.pingSpoof);
668 if (typeof ping === "string")
669 {
670 if (ping.length === 0)
671 {
672 clearInterval(mainWS.pingSpoofInterval);
673 if (mainWS.pingSpoof !== undefined) mainWS.send("\x05"); // Restart the loop
674 delete mainWS.pingSpoof;
675 delete mainWS.pingSpoofInterval;
676 setTimeout(notification, 0, "Ping Spoof: OFF", 0, 0, 255, 5000, "pingspoof_ping");
677 }
678 else
679 {
680 ping = parseFloat(ping);
681 if (typeof ping === "number")
682 {
683 clearInterval(mainWS.pingSpoofInterval);
684 mainWS.pingSpoof = ping;
685 mainWS.pingSpoofInterval = setInterval((mainWS) => {mainWS.realRecv.call(mainWS, {data: [5]}); realSend.call(mainWS, "\x05")}, mainWS.pingSpoof, mainWS);
686 setTimeout(notification, 0, "Ping Spoof: " + mainWS.pingSpoof.toString(), 0, 0, 255, 5000, "pingspoof_ping");
687 }
688 else
689 {
690 setTimeout(notification, 0, "Invalid number", 0, 0, 255, 5000, "pingspoof_invalid");
691 }
692 }
693 }
694 });
695
696 GM_registerMenuCommand('Spoof player count', function() {
697 var players = prompt("Enter the player count", mainWS.playerSpoof || mainWS.playerCount);
698 if (typeof players === "string")
699 {
700 if (players.length === 0)
701 {
702 playerCount(mainWS.playerCount);
703 delete mainWS.playerSpoof;
704 setTimeout(notification, 0, "Player Count Spoof: OFF", 0, 0, 255, 5000, "playercountspoof_players");
705 }
706 else
707 {
708 players = parseInt(players, 10);
709 if (typeof players === "number")
710 {
711 playerCount(players);
712 setTimeout(notification, 0, "Player Count Spoof: " + mainWS.playerSpoof.toString(), 0, 0, 255, 5000, "playercountspoof_players");
713 }
714 else
715 {
716 setTimeout(notification, 0, "Invalid number", 0, 0, 255, 5000, "playercountspoof_invalid");
717 }
718 }
719 }
720 });
721
722 GM_registerMenuCommand('Set AC bots name', function() {
723 var name = prompt("Enter the name for the AC bots to spawn in with", GM_getValue("ACName", ""));
724 if (typeof name === "string")
725 {
726 GM_setValue("ACName", name);
727 setTimeout(notification, 0, name === "" ? "Emptied name" : "Set name to: " + name, 0, 0, 255, 5000, "acbots_name"); // prompt() freezes the game and causes timing issues
728 if ((new TextEncoder('utf-8').encode(name)).length > 15) setTimeout(notification, 0, "Warning: Name is too long", 255, 128, 0, 5000, "acbots_name_warning"); // The script won't stop you from trying, but the server automatically truncates the name to 15 bytes
729 }
730 });
731})();