// ==UserScript== // @name MooMoo.io Auto Triple Mill // @namespace https://greasyfork.org/users/1064285-vcrazy-gaming // @version 0.2 // @description Automatically place Triple Mill in MooMoo.io when the [M] key is pressed. // @match *://moomoo.io/* // @match *://*.moomoo.io/* // @author _VcrazY_ // @require https://cdn.jsdelivr.net/npm/msgpack-lite@0.1.26/dist/msgpack.min.js // @grant none // @icon https://moomoo.io/img/favicon.png?v=1 // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/473948/MooMooio%20Auto%20Triple%20Mill.user.js // @updateURL https://update.greasyfork.icu/scripts/473948/MooMooio%20Auto%20Triple%20Mill.meta.js // ==/UserScript== (() => { // Constants and Variables let ws = null; let x = 0; let y = 0; let msgpack5 = window.msgpack; let scale = 45; let placeOffset = 5; let autoMill = false; const inventory = { primary: null, secondary: null, food: null, wall: null, spike: null, mill: null, mine: null, boostPad: null, trap: null, turret: null, spawnpad: null }; const vars = { camX: 0, camY: 0 }; const myPlayer = { sid: null, x: null, y: null, dir: null, buildIndex: null, weaponIndex: null, weaponVariant: null, team: null, isLeader: null, skinIndex: null, tailIndex: null, iconIndex: null }; // Helper Functions /** * Utility function to join arrays * @param {Array} message - The array to join * @returns {Array} - Joined array */ const join = message => Array.isArray(message) ? [...message] : [...message]; /** * Hook function for WebSocket * @param {object} ms - WebSocket message */ const hookWS = ms => { let tmpData = msgpack5.decode(new Uint8Array(ms.data)); if ((ms = undefined) || (tmpData = (ms = tmpData.length > 1 ? [tmpData[0], ...join(tmpData[1])] : tmpData)[0]) || ms) { if ("C" == tmpData && null === myPlayer.sid && (myPlayer.sid = ms[1]) || "a" == tmpData) { for (tmpData = 0; tmpData < ms[1].length / 13; tmpData++) { let data = ms[1].slice(13 * tmpData, 13 * (tmpData + 1)); if (data[0] == myPlayer.sid) { Object.assign(myPlayer, { x: data[1], y: data[2], dir: data[3], buildIndex: data[4], weaponIndex: data[5], weaponVariant: data[6], team: data[7], isLeader: data[8], skinIndex: data[9], tailIndex: data[10], iconIndex: data[11] }); } } } vars.camX || (vars.camX = myPlayer.x); vars.camY || (vars.camY = myPlayer.y); if (y !== myPlayer.y || x !== myPlayer.x) { // AUTO MILL CODE: if (Math.atan2(y - myPlayer.y, x - myPlayer.x) < (scale + placeOffset) * 2) { if (autoMill) { let angle = Math.atan2(y - myPlayer.y, x - myPlayer.x); place(inventory.mill, angle + Math.PI / 2.5); place(inventory.mill, angle); place(inventory.mill, angle - Math.PI / 2.5); } x = myPlayer.x; y = myPlayer.y; } } cacheItems(); } }; /** * Function to emit a packet * @param {string} event - Event type * @param {*} a - Parameter a * @param {*} b - Parameter b * @param {*} c - Parameter c * @param {*} m - Parameter m * @param {*} r - Parameter r */ const emit = (event, a, b, c, m, r) => ws.send(Uint8Array.from([...msgpack5.encode([event, [a, b, c, m, r]])])); /** * Function to place an item * @param {number} event - Event type * @param {number} l - Angle */ const place = (event, l) => { emit("G", event, false); emit("d", 1, l); emit("d", 0, l); emit("G", myPlayer.weaponIndex, true); }; /** * Function to send a chat message * @param {string} event - The chat message */ const chat = event => emit("6", event); /** * Cache the player's items */ const cacheItems = () => { for (let c = 0; c < 9; c++) { var _document$getElementB; if (((_document$getElementB = document.getElementById(`actionBarItem${c}`)) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.offsetParent) !== null) { inventory.primary = c; } } for (let s = 9; s < 16; s++) { var _document$getElementB2; if (((_document$getElementB2 = document.getElementById(`actionBarItem${s}`)) === null || _document$getElementB2 === void 0 ? void 0 : _document$getElementB2.offsetParent) !== null) { inventory.secondary = s; } } for (let P = 16; P < 19; P++) { var _document$getElementB3; if (((_document$getElementB3 = document.getElementById(`actionBarItem${P}`)) === null || _document$getElementB3 === void 0 ? void 0 : _document$getElementB3.offsetParent) !== null) { inventory.food = P - 16; } } for (let f = 19; f < 22; f++) { var _document$getElementB4; if (((_document$getElementB4 = document.getElementById(`actionBarItem${f}`)) === null || _document$getElementB4 === void 0 ? void 0 : _document$getElementB4.offsetParent) !== null) { inventory.wall = f - 16; } } for (let _ = 22; _ < 26; _++) { var _document$getElementB5; if (((_document$getElementB5 = document.getElementById(`actionBarItem${_}`)) === null || _document$getElementB5 === void 0 ? void 0 : _document$getElementB5.offsetParent) !== null) { inventory.spike = _ - 16; } } for (let u = 26; u < 29; u++) { var _document$getElementB6; if (((_document$getElementB6 = document.getElementById(`actionBarItem${u}`)) === null || _document$getElementB6 === void 0 ? void 0 : _document$getElementB6.offsetParent) !== null) { inventory.mill = u - 16; } } for (let I = 29; I < 31; I++) { var _document$getElementB7; if (((_document$getElementB7 = document.getElementById(`actionBarItem${I}`)) === null || _document$getElementB7 === void 0 ? void 0 : _document$getElementB7.offsetParent) !== null) { inventory.mine = I - 16; } } for (let p = 31; p < 33; p++) { var _document$getElementB8; if (((_document$getElementB8 = document.getElementById(`actionBarItem${p}`)) === null || _document$getElementB8 === void 0 ? void 0 : _document$getElementB8.offsetParent) !== null) { inventory.boostPad = p - 16; } } for (let x = 31; x < 33; x++) { var _document$getElementB9; if (((_document$getElementB9 = document.getElementById(`actionBarItem${x}`)) === null || _document$getElementB9 === void 0 ? void 0 : _document$getElementB9.offsetParent) !== null) { inventory.trap = x - 16; } } for (let g = 29; g < 31; g++) { var _document$getElementB10; if (((_document$getElementB10 = document.getElementById(`actionBarItem${g}`)) === null || _document$getElementB10 === void 0 ? void 0 : _document$getElementB10.offsetParent) !== null && g !== 36) { inventory.turret = g - 16; } } inventory.spawnpad = 36; }; // Override WebSocket's send method document.msgpack = window.msgpack; WebSocket.prototype.oldSend = WebSocket.prototype.send; WebSocket.prototype.send = function (event) { ws || (document.ws = this, ws = this, document.ws.addEventListener("message", hookWS)); this.oldSend(event); }; // Event listener for [M] key to toggle autoMill document.addEventListener("keydown", event => { if (event.keyCode === 77 && document.activeElement.id.toLowerCase() !== 'chatbox') { autoMill = !autoMill; chat(`Auto Triple Mill : ${autoMill ? 'enabled' : 'disabled'}`); } }); })();