Chimkens weapon variant Progress!🐓

View when your weapon is about to change variant!

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         Chimkens weapon variant Progress!🐓
// @description  View when your weapon is about to change variant!
// @author       Mr-Chimken_Lord
// @match        *://*.moomoo.io/*
// @match        *://*.sandbox.moomoo.io/*
// @icon         none
// @require      https://cdnjs.cloudflare.com/ajax/libs/msgpack-lite/0.1.26/msgpack.min.js
// @require 	 https://greasyfork.org/scripts/478839-moomoo-io-packet-code/code/MooMooio%20Packet%20Code.js?version=1274028
// @run-at       document-start
// @grant        unsafeWindow
// @license      MIT
// @version      3
// @namespace    Hehe
// ==/UserScript==

;(async () => {
	unsafeWindow.weaponVariantProgress = true

	document.addEventListener("DOMContentLoaded", () => {
		const style = document.createElement("style")
		style.innerText = `
		.weaponVariantBar {
			margin-top: 63px;
			height: 3px;
			border-radius: 4px;
		}

		@media only screen and (max-width: 896px) {
			.weaponVariantBar {
				margin-top: 41px;
			}
		}
		`

		document.head.appendChild(style)
	})

	let init = false,
		playerSID,
		weaponXP = {},
		weaponIndex,
		resources = {},
		pps = {},
		PPS = 0,
		lastPPSTime = 0
	await new Promise(async (resolve) => {
		let { send } = WebSocket.prototype

		WebSocket.prototype.send = function (...x) {
			send.apply(this, x)
			this.send = send
			this.iosend = function (...datas) {
				const [packet, ...data] = datas
				this.send(new Uint8Array(Array.from(msgpack.encode([packet, data]))))
			}
			if (!init) {
				init = true
				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 OLDPACKETCODE.RECEIVE["1"]:
							playerSID = data[0]
							break
						case OLDPACKETCODE.RECEIVE["2"]:
							if (data[1]) {
								weaponXP = {}
								const moofoll = localStorage.getItem("moofoll")
								resources = {
									food: moofoll ? 100 : 0,
									stone: moofoll ? 100 : 0,
									wood: moofoll ? 100 : 0,
									points: moofoll ? 100 : 0
								}
								for (let i = 0; i < 16; i++) {
									waitForElm("#variantBar" + i).then((element) => {
										element.style.width = "0%"
									})
								}
							}
						case OLDPACKETCODE.RECEIVE["6"]:
							for (var i = 0; i < data[0].length; i += 8) {
								if (data[0][i + 7] === playerSID) {
									if (data[0][i + 6] === 10) {
										PPS += 1
										pps[data[0][i]] = 1
									} else if (data[0][i + 6] === 11) {
										PPS += 1.5
										pps[data[0][i]] = 1.5
									} else if (data[0][i + 6] === 12) {
										PPS += 2
										pps[data[0][i]] = 2
									}
								}
							}
							break
						case OLDPACKETCODE.RECEIVE["12"]:
							if (pps[data[0]] != null) {
								PPS -= pps[data[0]]
								delete pps[data[0]]
							}
							break
						case OLDPACKETCODE.RECEIVE["33"]:
							for (let i = 0; i < data[0].length; i += 13) {
								if (data[0][i] === playerSID) {
									weaponIndex = data[0][i + 5]
									if (weaponXP[weaponIndex] < unsafeWindow.config.weaponVariants[data[0][i + 6]].xp) {
										weaponXP[weaponIndex] = unsafeWindow.config.weaponVariants[data[0][i + 6]].xp
										updateStyleWidth(weaponIndex)
									} else if (weaponXP[weaponIndex] >= unsafeWindow.config.weaponVariants[data[0][i + 6] + 1]?.xp) {
										weaponXP[weaponIndex] -= weaponXP[weaponIndex] - unsafeWindow.config.weaponVariants[data[0][i + 6] + 1].xp + 100
										updateStyleWidth(weaponIndex)
									}
									break
								}
							}
							break
						case OLDPACKETCODE.RECEIVE["9"]:
							if (data[0] === "kills") break
							const tmpIndex = weaponIndex
							if (weaponXP[tmpIndex] == null) weaponXP[tmpIndex] = 0
							const resDiff = data[1] - resources[data[0]]
							if (resDiff > 0) {
								if (data[0] === "points" && [Math.ceil(PPS), Math.floor(PPS)].includes(resDiff) && Date.now() - lastPPSTime > 800) {
									lastPPSTime = Date.now()
									resources[data[0]] = data[1]
									updateStyleWidth(tmpIndex)
									break
								} else if (data[0] === "points" && resDiff >= 100) {
									resources[data[0]] = data[1]
									updateStyleWidth(tmpIndex)
									break
								}
								weaponXP[tmpIndex] += resDiff
							}
							resources[data[0]] = data[1]
							updateStyleWidth(tmpIndex)
							break
					}
				})
			}
			resolve(this)
		}
	})

	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
			})
		})
	}

	for (let i = 0; i < 16; i++) {
		waitForElm("#actionBarItem" + i).then((parent) => {
			const element = document.createElement("div")
			element.id = "variantBar" + i
			element.className = "weaponVariantBar"
			parent.appendChild(element)
		})
	}

	function updateStyleWidth(tmpIndex) {
		let tmpStyle
		let tmpWidth
		if (weaponXP[tmpIndex] >= 12000) {
			tmpStyle = "none"
			tmpWidth = 0
		} else if (weaponXP[tmpIndex] >= 7000) {
			tmpStyle = "rgb(255, 113, 111)"
			tmpWidth = ((weaponXP[tmpIndex] - 7000) / 5000) * 100
		} else if (weaponXP[tmpIndex] >= 3000) {
			tmpStyle = "rgb(134, 181, 255)"
			tmpWidth = ((weaponXP[tmpIndex] - 3000) / 4000) * 100
		} else if (weaponXP[tmpIndex] >= 0) {
			tmpStyle = "rgb(247, 207, 69)"
			tmpWidth = (weaponXP[tmpIndex] / 3000) * 100
		}
		document.getElementById("variantBar" + tmpIndex).style.width = tmpWidth + "%"
		document.getElementById("variantBar" + tmpIndex).style.backgroundColor = tmpStyle
	}
})()