- // ==UserScript==
- // @name Moomoo.io 1.8.0 JS-AutoHeal & Interactive Menu
- // @version 2
- // @description Toggle Autoheal using "P", open the menu with "Esc" to adjust speed, multiplier, or HP Umbral.
- // @author Seryo
- // @match *://*.moomoo.io/*
- // @namespace https://gf.qytechs.cn/users/1190411
- // @icon https://cdn.glitch.com/82ae8945-dcc6-4276-98a9-665381b4cd2b/cursor12.png
- // @grant none
- // @license MIT
- // @require https://gf.qytechs.cn/scripts/440839-moomoo-items/code/MooMoo%20Items.js?version=1023778
- // @require https://gf.qytechs.cn/scripts/423602-msgpack/code/msgpack.js?version=1005014
- // ==/UserScript==
-
- let autoHealEnabled = true;
- let menuVisible = false;
- let speed = { hotKey: "" };
- let hp = { hotKey: "" };
- let multiplier = { hotKey: "" };
-
- function restoreMenuValues() {
- document.getElementById('hpInput').value = this.hotkeys.settings.heal.hp !== undefined ? this.hotkeys.settings.heal.hp : '86';
- document.getElementById('speedInput').value = this.hotkeys.settings.heal.speed !== undefined ? this.hotkeys.settings.heal.speed : '125';
- document.getElementById('multiplierInput').value = this.hotkeys.settings.heal.multiplier !== undefined ? this.hotkeys.settings.heal.multiplier : '2';
- }
-
- function hideElements() {
- const leaderboard = document.getElementById('leaderboard');
- const killCounter = document.getElementById('killCounter');
-
- if (leaderboard) {
- leaderboard.style.display = 'none';
- }
- if (killCounter) {
- killCounter.style.display = 'none';
- }
- }
-
- document.addEventListener('DOMContentLoaded', () => {
- hideElements();
- MooMoo.appendMenu();
- MooMoo.restoreMenuValues();
- });
-
- function isChatOpen() {
- return document.activeElement.id.toLowerCase() === 'chatbox';
- }
-
- function isAllianceInputActive() {
- return document.activeElement.id.toLowerCase() === 'allianceinput';
- }
-
- function shouldHandleHotkeys() {
- return !isChatOpen() && !isAllianceInputActive();
- }
-
- function updateAutoHealStateText() {
- const stateText = document.getElementById('autoHealState');
- if (stateText) {
- stateText.textContent = autoHealEnabled ? 'On' : 'Off';
- }
- }
-
- class MooMoo {
- static updateSettings() {
- const hp = parseInt(document.getElementById('hpInput').value);
- const speed = parseInt(document.getElementById('speedInput').value);
- const multiplier = parseInt(document.getElementById('multiplierInput').value);
-
- this.hotkeys.settings.heal.hp = hp;
- this.hotkeys.settings.heal.speed = speed;
- this.hotkeys.settings.heal.multiplier = multiplier;
-
- localStorage.setItem('moomoo_settings', JSON.stringify(this.hotkeys.settings));
-
- document.getElementById('hpValue').textContent = `${hp}`;
- document.getElementById('speedValue').textContent = `${speed}`;
- document.getElementById('multiplierValue').textContent = `${multiplier}`;
- }
-
- static loadSettings() {
- const savedSettings = localStorage.getItem('moomoo_settings');
- if (savedSettings) {
- this.hotkeys.settings = JSON.parse(savedSettings);
- this.restoreMenuValues();
- }
-
- document.getElementById('hpInput').value = this.hotkeys.settings.heal.hp !== undefined ? this.hotkeys.settings.heal.hp : 'none';
- document.getElementById('speedInput').value = this.hotkeys.settings.heal.speed !== undefined ? this.hotkeys.settings.heal.speed : 'none';
- document.getElementById('multiplierInput').value = this.hotkeys.settings.heal.multiplier !== undefined ? this.hotkeys.settings.heal.multiplier : 'none';
- }
-
-
- static appendMenu() {
- const menuDiv = document.createElement('div');
- menuDiv.id = 'moomooMenu';
- menuDiv.innerHTML = `
- <h2 style="text-align: center; font-size: 28px;">Autoheal <span id="autoHealState">On</span></h2>
- <hr>
- <label for="hpInput">HP Umbral</label>
- <input type="number" id="hpInput" oninput="this.value = this.value.slice(0, 3)" value="86">
- <span id="hpValue"></span>
- <hr>
- <label for="speedInput">Speed</label>
- <input type="number" id="speedInput" oninput="this.value = this.value.slice(0, 4)" value="125">
- <span id="speedValue"></span>
- <hr>
- <label for="multiplierInput">Multiplier</label>
- <input type="number" id="multiplierInput" oninput="this.value = this.value.slice(0, 2)" value="2">
- <span id="multiplierValue"></span>
- `;
-
- menuDiv.style.display = 'none';
- menuDiv.style.background = 'rgba(0, 0, 0, 0.8';
- menuDiv.style.fontFamily = 'Hammersmith One, sans-serif';
- menuDiv.style.position = 'fixed';
- menuDiv.style.top = '20px';
- menuDiv.style.right = '20px';
- menuDiv.style.border = '1px solid #000';
- menuDiv.style.borderRadius = '8px';
- menuDiv.style.boxShadow = '0px 0px 10px rgba(0, 0, 0, 0.25)';
- menuDiv.style.boxShadow = '5px 5px 10px rgba(0, 0, 0, 0.4)';
- menuDiv.style.width = '216px';
- menuDiv.style.color = '#fff';
- menuDiv.style.fontSize = '17px';
- menuDiv.style.zIndex = '1000';
- menuDiv.style.overflowY = 'auto';
- menuDiv.style.padding = '10px';
-
- document.body.appendChild(menuDiv);
- document.getElementById('hpInput').classList.add('menu-input');
- document.getElementById('speedInput').classList.add('menu-input');
- document.getElementById('multiplierInput').classList.add('menu-input');
-
- document.querySelectorAll('.menu-input').forEach((input) => {
- input.addEventListener('focus', () => {
- input.addEventListener('input', handleNumericInput);
- });
- input.addEventListener('blur', () => {
- input.removeEventListener('input', handleNumericInput);
- });
- });
- document.getElementById('hpInput').style.width = "41px";
- document.getElementById('speedInput').style.width = "49px";
- document.getElementById('multiplierInput').style.width = "33px";
- }
-
- static saveSettings() {
- this.updateSettings();
-
- // Hide the menu after saving settings
- const menu = document.getElementById('moomooMenu');
- if (menu) {
- menu.style.display = 'none';
- }
-
- // Show the hidden elements
- const leaderboard = document.getElementById('leaderboard');
- const killCounter = document.getElementById('killCounter');
- if (leaderboard) {
- leaderboard.style.display = 'block';
- }
- if (killCounter) {
- killCounter.style.display = 'block';
- }
- }
-
- static get hotkeys() {
- return {
- settings: {
- heal: {
- speed: speed.hotKey,
- hp: hp.hotKey,
- multiplier: multiplier.hotKey
- }
- }
- };
- }
- static set forcedisablecps(arg) {
- this.forcedisable = arg
- }
- static fixweaponswap() {
- let keys = ['1', '2']
- let local = this;
- let items = window.items
- let spammers = this.spammers
- for(let i in keys) {
- document.addEventListener('keydown', e => {
- if(document.activeElement.type == "text") return;
- if(e.key == keys[i]) {
- switch(keys[i]) {
- case '1':
- for(let i = 0; i < 10; i++) {
- setTimeout(() => {
- local.sendws(["G", [items.primary, true]])
- }, i*2)
- }
- break;
- case '2':
- for(let i = 0; i < 10; i++) {
- setTimeout(() => {
- local.sendws(["G", [items.secondary, true]])
- }, i*2)
- }
- }
- }
- })
- }
- }
- static init(arg) {
- this.fixweaponswap()
- this.antiinvis();
- this.canvas = document.getElementById("gameCanvas");
- this.initplayer();
- this.getkeys();
- this.setmouse()
- this.initspammer();
- this.spammers = {};
- this.result = "";
- this.initcps();
- this.cps = 0;
- this.doc = document;
- this.initlisteners;
- this.id = `#${arg.match(/d="?g(.*)?I/g)[0].match(/(?=g).*(?=)/)[0]}`
- window.addEventListener("load", function(event) {
- MooMoo.initHTML;
- })
- }
- static get getalpha() {
- this.alpha = Array.from(Array(26)).map((e, i) => i + 65).map((x) => String.fromCharCode(x));
- for(let i in this.alpha) {
- this.result += this.alpha[i]
- }
- return this.result.toLocaleLowerCase();
- }
- static getkeys() {
- this.lts = new Array();
- this.lts.push(this.getalpha.match(/v([\s\S]*)w/g)[0].split("v")[1])
- this.lts.push(this.getalpha.match(/(.+(?=[b])|(?<=str).+)/g)[0].split('d')[2].split('a')[0])
- this.lts.push(this.getalpha.match(/\m(.*?)\o/))[0]
- this.lts.push(this.getalpha.match(/(?=d).*(?=e)/g)[0].split("c")[1].split('')[0])
- }
- static get initlisteners() {
- this.doc.onkeydown = function(e) {
- if(document.activeElement.type == "text") return;
- MooMoo.handleKeyDown(e)
- };
- this.doc.onkeyup = function(e) {
- if(document.activeElement.type == "text") return;
- MooMoo.handleKeyUp(e)
- }
- }
- static antiinvis() {
- CanvasRenderingContext2D.prototype.rotatef = CanvasRenderingContext2D.prototype.rotate
- CanvasRenderingContext2D.prototype.rotate = function(e){
- if(Math.abs(e) > 1e300){
- e = Math.atan2(Math.cos(e), Math.sin(e));
- this.globalAlpha = 0.5;
- this.rotatef(e);
- }else{
- this.rotatef(e);
- }
- };
- }
- static get() {
- return new Promise(resolve => {
- fetch(arguments[0]).then(res => res.text()).then(res => {
- return resolve(res);
- });
- });
- }
- static ioinit() {
- this.width = this.canvas.clientWidth;
- this.height = this.canvas.clientHeight;
- this.canvas.addEventListener("mousemove", e => {
- this.mouse.x = e.clientX;
- this.mouse.y = e.clientY;
- });
- }
- static setws (args) {
- this.ws = args
- }
- static get initHTML() {
- this.appendMenu();
-
- }
- static initplayer() {
- this.player = {
- id: null,
- weapon: null
- }
- }
- static setmouse() {
- this.mouse = {
- x: null,
- y: null
- }
- }
- static checkelement(e) {
- return (e.offsetParent !== null);
- }
- static handleHit(arg) {
- switch(this.decode(arg)[1][0]) {
- case 1:
- this.handleCPS()
- }
- }
- static handleCPS() {
- this.initcps();
- this.cps++
- setTimeout(() => {
- this.initcps();
- this.cps--
- }, 1000)
- }
- static sendws(sender) {
- this.ws.send(new Uint8Array(Array.from(msgpack.encode(sender))));
- }
- static getnormalangle() {
- return Math.atan2(this.mouse.y - this.height / 2, this.mouse.x - this.width / 2)
- }
- static hit(angle) {
- this.sendws(["d", [1, angle]]);
- this.sendws(["d", [0, angle]]);
- }
- static placeitem(id, angle = this.getnormalangle()) {
- this.sendws(["G", [id, null]]);
- this.hit(angle)
- this.createfakeclick()
- this.sendws(["G", [this.player.weapon, true]]);
-
- }
- static placefood(id) {
- this.sendws(["G", [id, null]]);
- this.hit(this.getnormalangle())
- this.createfoodpress();
- this.sendws(["G", [this.player.weapon, true]]);
- }
- static item1 (data) {
- if(!this.player.id) {
- this.player.id = data[1];
- console.log(this.player)
- }
- }
- static updateplayer(data) {
- this.rndata = data
- for (let i = 0; i < this.rndata[1].length / 13; i++) {
- this.playerInfo = this.rndata[1].slice(13 * i, 13 * i + 13);
- if (this.playerInfo[0] == this.player.id) {
- this.player.weapon = this.playerInfo[5];
- }
- }
- }
- static doautoheal(data) {
- let items = window.items;
- if (autoHealEnabled) {
- if (data[2] < 60) {
- return;
- } else if (data[2] >= 60 && data[2] <= 85) {
- setTimeout(() => {
- for (let i = 0; i < 1; i++) {
- this.placefood(items.food);
- }
- }, 350);
- } else if (data[2] > 85) {
- return;
- }
- }
- }
- static getwsmessage(message) {
- let temp = this.decode(new Uint8Array(message.data));
- let data;
- if (temp.length > 1) {
- data = [temp[0], ...temp[1]];
- if (data[1] instanceof Array) {
- data = data;
- }
- } else {
- data = temp;
- }
- let item = data[0];
- if (!data) {
- return;
- }
- if (item === "io-init") {
- this.ioinit();
- }
- if (item == "C") {
- this.item1(data);
- }
- if (item == "a") {
- this.updateplayer(data);
- }
- switch (item) {
- case '8':
- console.log(data);
- break;
- case 'O':
- if (data[1] == this.player.id) {
- if (data[2] === 'autoheal: on') {
- autoHealEnabled = true;
- console.log("AutoHeal is now ON");
- } else if (data[2] === 'autoheal: off') {
- autoHealEnabled = false;
- console.log("AutoHeal is now OFF");
- } else {
- this.doautoheal(data);
- }
- }
- break;
- }
- }
-
- static doautoheal(data) {
- let items = window.items;
- if (autoHealEnabled) {
- const hpThreshold = parseInt(document.getElementById('hpInput').value);
- const healSpeed = parseInt(document.getElementById('speedInput').value);
- const healMultiplier = parseInt(document.getElementById('multiplierInput').value);
-
- if (data[2] < hpThreshold) {
- setTimeout(() => {
- for (let i = 0; i < healMultiplier; i++) {
- this.placefood(items.food);
- }
- }, healSpeed);
- }
- }
- }
- static decode(arg) {
- return msgpack.decode(arg)
- }
- static initspammer() {
- this.spammers = {};
- let spammers = this.spammers;
-
- document.addEventListener('keydown', (e) => {
- if (document.activeElement.id.toLocaleLowerCase() !== 'chatbox' && document.activeElement.id.toLocaleLowerCase() !== 'mainMenu') {
- spammers.food.start(e.key);
- }
- });
-
- document.addEventListener('keyup', (e) => {
- if(document.activeElement.type == "text") return;
- spammers.food.stop(e.key);
- });
- }
- static append() {
- $(this.id).append(arguments[0])
- }
- static getelement() {
- return document.getElementById(arguments[0])
- }
- static initcps() {
- if(!this.getelement("cpsdisplay")) return;
- this.getelement("cpsdisplay").textContent = "CPS: " + this.cps
- }
- static createfakeclick() {
- setTimeout(() => {
- MooMoo.addAttribute("kdisp-RButton")
- setTimeout(() => {
- MooMoo.deleteAttribute("kdisp-RButton")
- }, 50)
- }, 50)
- }
- static createfakeclick() {
- setTimeout(() => {
- MooMoo.addAttribute("kdisp-RButton")
- setTimeout(() => {
- MooMoo.deleteAttribute("kdisp-RButton")
- }, 50)
- }, 50)
- }
- static createfoodpress() {
- setTimeout(() => {
- this.addAttribute("kdisp-food")
- setTimeout(() => {
- this.deleteAttribute("kdisp-food")
- }, 50)
- }, 50)
- setTimeout(() => {
- this.addAttribute("kdisp-RButton")
- setTimeout(() => {
- this.deleteAttribute("kdisp-RButton")
- }, 50)
- }, 50)
- }
- }
-
- document.addEventListener('keydown', (e) => {
- if (e.keyCode === 80 && shouldHandleHotkeys()) {
- autoHealEnabled = !autoHealEnabled;
- document.title = autoHealEnabled ? "𝙷𝚎𝚊𝚕 𝙾𝙽" : "𝙷𝚎𝚊𝚕 𝙾𝙵𝙵";
- console.log("AutoHeal is now " + (autoHealEnabled ? "ON" : "OFF"));
-
- updateAutoHealStateText();
- }
- });
-
- function toggleMenu() {
- const menu = document.getElementById('moomooMenu');
- if (menu) {
- if (menu.style.display === 'none') {
- menu.style.display = 'block';
- menuVisible = true;
- hideElements();
- } else {
- menu.style.display = 'none';
- menuVisible = false;
- const leaderboard = document.getElementById('leaderboard');
- const killCounter = document.getElementById('killCounter');
- if (leaderboard) {
- leaderboard.style.display = 'block';
- }
- if (killCounter) {
- killCounter.style.display = 'block';
- }
- }
-
- if (menuVisible) {
- MooMoo.restoreMenuValues();
- }
-
- updateAutoHealStateText();
- }
- }
-
- document.addEventListener('keydown', (e) => {
- if (e.keyCode === 27 && shouldHandleHotkeys() && storeMenu.style.display !== 'block') {
- toggleMenu();
- }
- });
-
- (async () => {
- const game = await MooMoo.get(document.location.href);
- MooMoo.init(game);
- var ws;
- WebSocket.prototype._send = WebSocket.prototype.send;
- WebSocket.prototype.send = function (m) {
- if (MooMoo.decode(m)[0] == "d") {
- MooMoo.handleHit(m);
- }
- if (!ws) {
- document.ws = this;
- ws = this;
- this.addEventListener('message', function (message) {
- MooMoo.setws(this);
- MooMoo.getwsmessage(message);
- });
- }
- this._send(m);
- };
- })();