// ==UserScript==
// @name MooMoo.io - 1.8.0 Reload Timer
// @author KOOKY WARRIOR
// @description Assists in calculating your weapon(s) reload time.
// @version 1
// @match *://*.moomoo.io/*
// @namespace https://gf.qytechs.cn/users/999838
// @icon https://cdn.glitch.com/82ae8945-dcc6-4276-98a9-665381b4cd2b/cursor12.png
// @require https://cdnjs.cloudflare.com/ajax/libs/msgpack-lite/0.1.26/msgpack.min.js
// @run-at document-start
// @grant unsafeWindow
// @license MIT
// ==/UserScript==
;(async () => {
unsafeWindow.reloadTimer = true
let weaponSpeed = [
300, 400, 400, 300, 300, 700, 300, 100, 400, 600, 400, 0, 700, 230, 700, 1500
]
let weaponSrc = [
"hammer_1",
"axe_1",
"great_axe_1",
"sword_1",
"samurai_1",
"spear_1",
"bat_1",
"dagger_1",
"stick_1",
"bow_1",
"great_hammer_1",
"shield_1",
"crossbow_1",
"crossbow_2",
"grab_1",
"musket_1"
]
var myPlayer,
mySID,
inGame = false,
reloads = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
var now, delta, lastUpdate
const reloadTimer1 = document.createElement("div")
reloadTimer1.id = "reloadTimer1"
reloadTimer1.className = "resourceDisplay"
reloadTimer1.innerText = "0"
const reloadTimer2 = document.createElement("div")
reloadTimer2.id = "reloadTimer2"
reloadTimer2.className = "resourceDisplay"
reloadTimer2.innerText = "-"
await new Promise(async (resolve) => {
let { send } = WebSocket.prototype
WebSocket.prototype.send = function (...x) {
send.apply(this, x)
this.send = send
this.addEventListener("message", (e) => {
if (!e.origin.includes("moomoo.io") && unsafeWindow.privateServer) return
const [packet, data] = msgpack.decode(new Uint8Array(e.data))
switch (packet) {
case "C":
inGame = true
mySID = data[0]
break
case "P":
inGame = false
reloads = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
break
case "K":
if (data[0] == mySID) reloads[data[2]] = weaponSpeed[data[2]]
break
case "X":
if ([1000, 1200, 1400].includes(data[3])) {
let projectileID
switch (data[5]) {
case 0:
projectileID = 9
break
case 2:
projectileID = 12
break
case 3:
projectileID = 13
break
case 5:
projectileID = 15
break
default:
projectileID = null
}
let x = data[0] - Math.cos(data[2]) * 35
let y = data[1] - Math.sin(data[2]) * 35
if (Math.sqrt((x -= myPlayer.x) * x + (y -= myPlayer.y) * y) <= 70)
reloads[projectileID] = weaponSpeed[projectileID]
}
break
}
})
resolve(this)
}
})
function updateReload() {
now = Date.now()
delta = now - lastUpdate
lastUpdate = now
if (inGame && myPlayer) {
if (myPlayer.buildIndex == -1) {
reloads[myPlayer.weaponIndex] = Math.max(
0,
reloads[myPlayer.weaponIndex] - delta
)
}
if (myPlayer.weapons[0] != null) {
reloadTimer1.style.backgroundImage = `url(../img/weapons/${
weaponSrc[myPlayer.weapons[0]]
}.png)`;
reloadTimer1.innerText = reloads[myPlayer.weapons[0]];
reloadTimer1.style.transition = 'background-color 0.1s';
reloadTimer1.style.backgroundColor = reloads[myPlayer.weapons[0]] > 0 ? 'rgba(0, 0, 0, 0.3)' : 'rgba(0, 0, 0, 0.15)';
}
if (myPlayer.weapons[1] != null) {
reloadTimer2.style.backgroundImage = `url(../img/weapons/${
weaponSrc[myPlayer.weapons[1]]
}.png)`;
reloadTimer2.innerText = reloads[myPlayer.weapons[1]];
reloadTimer2.style.transition = 'background-color 0.1s';
reloadTimer2.style.backgroundColor = reloads[myPlayer.weapons[1]] > 0 ? 'rgba(0, 0, 0, 0.3)' : 'rgba(0, 0, 0, 0.15)';
} else {
reloadTimer2.style.backgroundImage = 'none';
reloadTimer2.innerText = '';
reloadTimer2.style.transition = 'background-color 0.1s';
reloadTimer2.style.backgroundColor = 'transparent';
}
}
unsafeWindow.requestAnimationFrame(updateReload)
}
lastUpdate = Date.now()
unsafeWindow.requestAnimationFrame(updateReload)
function waitForElm(selector) {
return new Promise((resolve) => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector))
}
const observer = new MutationObserver((mutations) => {
if (document.querySelector(selector)) {
resolve(document.querySelector(selector))
observer.disconnect()
}
})
observer.observe(document.body, {
childList: true,
subtree: true
})
})
}
const symbol = Symbol("minimapCounter")
Object.defineProperty(Object.prototype, "minimapCounter", {
get() {
return this[symbol]
},
set(value) {
this[symbol] = value
if (this.isPlayer === true && this.sid === mySID) {
myPlayer = this
}
},
configurable: true
})
waitForElm("#topInfoHolder").then((topInfoHolder) => {
const style = document.createElement("style")
style.innerHTML = `
#reloadTimer1 {
right: 0px;
margin-top: 65px;
color: #fff;
font-size: 28px;
background-color: rgba(0, 0, 0, 0.25);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
#reloadTimer2 {
right: 0px;
margin-top: 120px;
color: #fff;
font-size: 28px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
`
document.head.appendChild(style)
topInfoHolder.appendChild(reloadTimer1)
topInfoHolder.appendChild(reloadTimer2)
})
})()