返回首頁 

Greasy Fork is available in English.

9mm [MooMoo.io] [v1.0.1]

Это хороший скрипт для moomoo.io, не самый лучший, но я постараюсь сделать его как можно лучше. M - Автоматические мельницы. Q/F/V/N/H - Макросы. Всё остальное работает автоматически! Если какие-то шапки не купились сами, то вы можете купить их в магазине.

// ==UserScript==// @name            9mm [MooMoo.io] [v1.0.1]// @name:ru         9mm [MooMoo.io] [v1.0.1]// @namespace       https://github.com/Nudo-o// @version         1.0.1// @description     It's a good script for moomoo.io, it's not the best, but I'll try to make it as good as possible. M - Auto mills. Q/F/V/N/H - Macro placers. Everything else works automatically! If some hats were not bought by yourself, then you can buy them in the store.// @description:ru  Это хороший скрипт для moomoo.io, не самый лучший, но я постараюсь сделать его как можно лучше. M - Автоматические мельницы. Q/F/V/N/H - Макросы. Всё остальное работает автоматически! Если какие-то шапки не купились сами, то вы можете купить их в магазине.// @author          @nudoo// @match           *://moomoo.io/*// @match           *://*.moomoo.io/*// @icon            https://www.google.com/s2/favicons?sz=64&domain=moomoo.io// @require         https://greasyfork.org/scripts/423602-msgpack/code/msgpack.js// @require         https://update.greasyfork.org/scripts/480301/1322984/CowJS.js// @license         MIT// @grant           none// @run-at          document-start// ==/UserScript==// LICENSE (MIT): https://www.tldrlegal.com/license/mit-license// The creation uses my library designed to simplify the work in creating scripts on MooMoo.io. You can get acquainted with it by following the link.// Cow.js - https://update.greasyfork.org/scripts/480301/1322984/CowJS.js(function() {"use strict"const { Cow, CowUtils, msgpack } = windowconst { packets, items } = Cow.config.designationsconst _placeItem = Cow.placeItemconst _roundRect = CanvasRenderingContext2D.prototype.roundRectCow.setCodec(msgpack)let nearEnemy = nulllet preplaceObjects = []let lastPreplaceClear = 0class AutoHeal {constructor() {this.checkIsHealed = falsethis.lastHeal = 0}doFullHeal() {const { player } = Cowif (player.health === player.maxHealth) returnconst amount = player.items[0] === 0 ? 20 : player.items[0] === 1 ? 30 : 25for (let i = player.health; i < player.maxHealth; i += amount) {this.doHeal()}}doHeal() {const { player } = Cowif (player.health === player.maxHealth) returnconst timeSinceHeal = Cow.ticker.ticks - (this.lastHeal || 0)if (timeSinceHeal >= 1) {/*Cow.delayedPlaceItem(() => Cow.placeItem(items.FOOD))*/Cow.placeItem(items.FOOD)this.lastHeal = Cow.ticker.ticks}}update() {const { player } = Cowif (!player?.alive || player?.skinIndex === 45) returnif (player.health === player.maxHealth) {if (player.shameCount >= 2) {tailor.autoBullTick = true}return}if (player.health <= 85 && nearEnemy) {const distance = CowUtils.getDistance(nearEnemy, player)if (distance <= 500) {tailor.autoEmpHat = true}}const timeSinceHit = Cow.ticker.ticks - (player.hitTime || 0)const timeSinceHeal = Cow.ticker.ticks - (this.lastHeal || 0)if (player.shameCount < 5) {if (timeSinceHeal >= 8) {this.doHeal()} else {if (timeSinceHit >= ((player.health <= 30) ? 0 : 2)) {if (player.health <= 40) {this.doFullHeal()} else if (timeSinceHit >= 1 && timeSinceHit >= 1) {this.doHeal()}if (player.health >= 65) {this.doHeal()} else if (player.health > 40 && player.health < 65) {this.doFullHeal()}} else if (timeSinceHit === 1) {if (player.health <= 30) {this.doHeal()this.doFullHeal()}}}} else {if (player.health < 40 && timeSinceHit >= 2) {this.doHeal()this.doHeal()} else if (player.health >= 40 && timeSinceHit >= 3 && timeSinceHeal >= 2) {this.doFullHeal()this.doHeal()}}}}class AntiInsta {constructor() {this.targetHealth = 35this.lastHeal = 0}doFullHeal() {const { player } = Cowif (player.health === player.maxHealth) returnconst amount = player.items[0] === 0 ? 20 : player.items[0] === 1 ? 30 : 25for (let i = player.health; i < player.maxHealth; i += amount) {this.doHeal()}}doHeal() {const { player } = Cowif (player.health === player.maxHealth) returnconst timeSinceHeal = Cow.ticker.ticks - (this.lastHeal || 0)if (timeSinceHeal >= 0) {Cow.placeItem(items.FOOD)this.lastHeal = Cow.ticker.ticks}}update() {const { player } = Cowif (!player?.alive || player?.skinIndex === 45) returnif (player.health > this.targetHealth || !nearEnemy) returnconst timeSinceHit = Cow.ticker.ticks - (player.hitTime || 0)const timeSinceHeal = Cow.ticker.ticks - (this.lastHeal || 0)if (player.shameCount <= 4) {if (timeSinceHeal >= 8) {this.doHeal()if (player.health <= 20) {this.doFullHeal()}this.doHeal()} else {if (timeSinceHit >= ((player.health <= 20) ? 0 : 1)) {if (player.health <= (this.targetHealth - 10)) {this.doHeal()this.doHeal()} else if (timeSinceHit >= 1 && timeSinceHit >= 1) {this.doHeal()this.doFullHeal()}if (player.health >= (this.targetHealth - 10)) {this.doHeal()this.doHeal()} else if (player.health > 5 && player.health < 15) {this.doFullHeal()this.doHeal()}} else if (timeSinceHit === 1) {this.doHeal()this.doHeal()}}if (player.health <= Math.max(this.targetHealth - 15, 10)) {this.doFullHeal()} else if (timeSinceHit >= 1 && timeSinceHeal >= 1) {this.doHeal()this.doHeal()} else {this.doHeal()}} else {if (player.health < (this.targetHealth - 5) && timeSinceHit >= 1) {this.doHeal()this.doHeal()} else if (player.health >= (this.targetHealth - 5) && timeSinceHit >= 2 && timeSinceHeal >= 1) {this.doHeal()}}}}class Tailor {constructor() {this.hatTicks = []this.hasHats = [ 0 ]this.hasAccs = [ 0 ]this.lastHatTick = 0this.autoEmpCD = nullthis.autoEmpSoldier = falsethis.autoSoldierEmp = falsethis.autoEmpHat = falsethis.autoBullTick = falsethis.auto####Hat = false}get canEquip() {return !autoSpikeSync.isActive && !autoClickHats.isActive}isHasTick(key) {return Boolean(this.hatTicks.filter((tick) => tick.key == key).length)}reset() {this.autoEmpSoldier = falsethis.autoSoldierEmp = falsethis.autoEmpHat = falsethis.autoBullTick = falsethis.auto####Hat = false}equipHat(id, onlyBuy) {const { player } = Cowif (!this.hasHats.includes(id) && id !== 0) {if (player.points >= Cow.items.hats.searchById(id).price) {Cow.sendPacket(packets.STORE_EQUIP, 1, id, 0, "by 9mm")return this.hasHats.push(id)}}if (onlyBuy) returnif (this.hasHats.includes(id) && player.skinIndex !== id) {Cow.sendPacket(packets.STORE_EQUIP, 0, id, 0)this.lastHatID = id}}equipAcc(id, onlyBuy) {const { player } = Cowif (!this.hasAccs.includes(id) && id !== 0) {if (player.points >= Cow.items.accessories.searchById(id).price) {Cow.sendPacket(packets.STORE_EQUIP, 1, id, 1, "by 9mm")return this.hasAccs.push(id)}}if (onlyBuy) returnif (this.hasAccs.includes(id) && player.tailIndex !== id) {Cow.sendPacket(packets.STORE_EQUIP, 0, id, 1)this.lastAccID = id}}equipBiomeHat() {if (!this.canEquip) returnconst { player } = Cowlet hatID = 0if (player.y2 > 6850 && player.y2 < 7550) {hatID = 31} else if (player.y2 < 2400) {hatID = 15} else {hatID = 12}this.equipHat(hatID)if (!this.isHasTick("uneqip-tail")) {this.hatTicks.push({key: "unknown",callback: () => {this.equipAcc(11)}})}}unknownTicks(amount) {while (amount--) {this.hatTicks.push({key: "unknown",callback: () => {}})}}autoHats() {const { player } = Cowconst dangerBuildings = calculator.getDangerBuildings(player)if (nearEnemy && player.health < player.maxHealth && this.canEquip) {const isPolearm = nearEnemy.weaponIndex === 4const isSword = nearEnemy.weaponIndex === 3const isKatana = nearEnemy.weaponIndex === 4if (isPolearm || isSword || isKatana) {if (nearEnemy.weapons[1] === 10) {if (this.autoEmpSoldier) returnthis.autoEmpSoldier = truethis.hatTicks = []this.equipHat(22)setTimeout(() => {this.equipHat(6)setTimeout(() => {this.autoEmpSoldier = false}, 25)}, 90)} else {if (this.autoSoldierEmp) returnthis.autoSoldierEmp = truethis.hatTicks = []this.equipHat(6)setTimeout(() => {this.equipHat(22)setTimeout(() => {this.autoEmpSoldier = false}, 25)}, 90)}return}}if (this.autoEmpHat && (!this.autoEmpCD || Date.now() - this.autoEmpCD >= 500) && this.canEquip) {this.equipHat(22)if (!this.isHasTick("uneqip-hats")) {this.unknownTicks(1)this.hatTicks.push({key: "uneqip-hats",callback: () => {this.autoEmpHat = falsethis.autoEmpCD = null}})}this.autoEmpCD = Date.now()} else if (this.auto####Hat) {this.equipHat(40)if (!this.isHasTick("uneqip-hats")) {this.unknownTicks(3)this.hatTicks.push({key: "uneqip-hats",callback: () => {this.auto####Hat = false}})}} else if (dangerBuildings.length || nearEnemy && this.canEquip) {if (dangerBuildings.length) {this.equipHat(6)} else if (nearEnemy) {const weaponIndex = nearEnemy.weaponIndexconst angle = CowUtils.getDirection(nearEnemy, player)const distance = CowUtils.getDistance(nearEnemy, player) - player.scaleconst isMeInAngle = true//getAngleDist(angle, tmpValues.nearEnemy.dir) <= Math.PI / 1.25const weapon = Cow.items.weapons[weaponIndex]if (!weapon) returnconst isMeInRange = distance <= weapon.range * 3.25if (isMeInRange && isMeInAngle) {if (nearEnemy.skinIndex === 7 && nearEnemy.tailIndex !== 11) {if (!this.isHasTick("auto-spike")) {this.equipHat(6)this.unknownTicks(2)this.hatTicks.push({key: "auto-spike",callback: () => {this.equipHat(11)}})}return} else {this.equipHat(6)return}} else {if (this.canEquip) return this.equipBiomeHat()}}} else {if (this.canEquip) this.equipBiomeHat()}}update() {this.autoHats()const { player } = Cowconst timeSinceHatTick = Cow.ticker.ticks - (this.lastHatTick || 0)if (timeSinceHatTick >= 20 && !this.hatTicks.length && this.canEquip) {this.equipAcc(11, true)this.equipHat(6, true)this.equipHat(7, true)this.equipHat(22, true)this.equipHat(40, true)this.equipHat(53, true)this.lastHatTick = Cow.ticker.ticks}if (!this.canEquip) return (this.hatTicks = [])const hatTick = this.hatTicks[0]typeof hatTick?.callback === 'function' && hatTick.callback()this.hatTicks.shift()}}class AutoPlacer {constructor() {this.delay = 10this.lastUpdate = null}update() {const { player } = Cowif (!player?.alive || !nearEnemy?.visible || autoSpikeSync.isActive) returnif (Date.now() - this.lastUpdate < this.delay) returnconst trapConfig = Cow.items.list[player.items[items.TRAP]]const spikeConfig = Cow.items.list[player.items[items.SPIKE]]if (!trapConfig || !spikeConfig) returnconst visibleObjects = Cow.objectsManager.list.filter((gameObject) => gameObject.visible && gameObject.active && CowUtils.getDistance(gameObject, player) <= 300)const angle = CowUtils.getDistance(nearEnemy, player)const placeSpikeDistance = player.scale + spikeConfig.scale * 1.4const distance = CowUtils.getDistance(player, nearEnemy)let distanceToPlace = distancenearEnemy.inTrap = falsefor (let i = 0; i < visibleObjects.length; i++) {const gameObject = visibleObjects[i]if (!gameObject.isItem || gameObject.id !== 15 || gameObject.owner?.sid === nearEnemy.sid) continueconst scale = gameObject.scale || gameObject.getScale()const enemyDistanceToTrap = CowUtils.getDistance(nearEnemy, gameObject) - scale + window.config.collisionDepthconst angleTrapToEnemy = CowUtils.getDirection(nearEnemy, gameObject)if (enemyDistanceToTrap > 0) continuenearEnemy.inTrap = trueconst offset = scale - Math.abs(enemyDistanceToTrap) + nearEnemy.scale / 2 + spikeConfig.scaleconst placeX = gameObject.x + offset * Math.cos(angleTrapToEnemy)const placeY = gameObject.y + offset * Math.sin(angleTrapToEnemy)distanceToPlace = CowUtils.getDistance(placeX, placeY, player.x, player.y)if (distanceToPlace <= placeSpikeDistance) {const angleToPlace = CowUtils.getDirection(placeX, placeY, player.x, player.y)Cow.placeItem(items.SPIKE, {angle: angleToPlace})}break}const distanceToEnemy = CowUtils.getDistance(player, nearEnemy) - nearEnemy.scaleconst placeDistance = trapConfig.scale * 1.2 + player.scaleif (!nearEnemy.inTrap) {if (trapConfig) {if (distanceToEnemy <= placeDistance && player.items[items.TRAP] === 15) {const angle = CowUtils.getDirection(nearEnemy, player)Cow.placeItem(items.TRAP, { angle })}}} else if (distanceToPlace > placeSpikeDistance && distanceToEnemy <= 275) {if (player.items[items.TRAP] === 15) {Cow.placeItem(items.TRAP, {angle: angle})}Cow.placeItem(items.SPIKE, {angle: -angle})}this.lastUpdate = Date.now()}}class Macro {constructor() {this.assistPlaceX = nullthis.assistPlaceY = nullthis.lastAssistActive = nullthis.keys = {FOOD: 81,TRAP: 70,SPIKE: 86,MILL: 78,TURRET: 72}}resetAssist() {this.assistPlaceX = nullthis.assistPlaceY = nullthis.lastAssistActive = Date.now()}update() {const { player } = Cowif (!player?.alive || isInputFocused()) returnif (Date.now() - this.lastAssistActive >= 500) this.resetAssist()for (const key in this.keys) {if (!Cow.input.keyboard.activeKeys.get(this.keys[key])) continueconst placeItemIndex = items[key.replace(/wind/, "").toUpperCase()]const placeItem = Cow.items.list[player.items[placeItemIndex]]if (!placeItem) continuelet placeAngle = player.lookAngleif (placeItem?.scale) {const generalScale = (player.scale + placeItem.scale + (placeItem.placeOffset || 0))const placeX = player.x + (generalScale * Math.cos(placeAngle))const placeY = player.y + (generalScale * Math.sin(placeAngle))const placePosition = { x: placeX, y: placeY }const interferingObject = Cow.objectsManager.checkItemLocation(placeX, placeY, placeItem.scale, 0.6, placeItem.id, false, true)if (interferingObject) {let nearObjects = Cow.objectsManager.list.filter((gameObject) => {const generalScale = placeItem.scale + (gameObject.isItem ? gameObject.scale : gameObject.getScale(0.6, false))const inPlace = CowUtils.getDistance(gameObject, player) <= generalScale + player.scale * 2 + (placeItem.placeOffset || 0)return gameObject.visible && gameObject.active && inPlace})nearObjects = nearObjects.sort((a, b) => {a = CowUtils.getDistance(a, placePosition)b = CowUtils.getDistance(b, placePosition)return a - b})if (nearObjects.length) {let newPlaceX = placeXlet newPlaceY = placeYfor (const nearObject of nearObjects) {const angle = CowUtils.getDirection(player, nearObject)const scale = nearObject.isItem ? nearObject.scale : nearObject.getScale(.6, false)const offsetScale = scale / 2 + placeItem.scale / 2 * 1.25const _x = newPlaceX + offsetScaleconst _y = newPlaceY + offsetScalenewPlaceX = _x * Math.cos(angle - Math.atan(player.x - _x))newPlaceY = _y * Math.sin(angle - Math.atan(player.y - _y))const isCanPlace = Cow.objectsManager.checkItemLocation(newPlaceX, newPlaceY, placeItem.scale, 0.6, placeItem.id, false)if (isCanPlace) breaknearObjects = nearObjects.sort((a, b) => {const newPlacePosition = { x: newPlaceX, y: newPlaceY }a = CowUtils.getDistance(a, newPlacePosition)b = CowUtils.getDistance(b, newPlacePosition)return a - b})}this.assistPlaceX = newPlaceXthis.assistPlaceY = newPlaceYthis.lastAssistActive = Date.now()placeAngle = CowUtils.getDirection(player.x, player.y, newPlaceX, newPlaceY)}}}//Cow.delayedPlaceItem(() => {Cow.placeItem(placeItemIndex, {angle: placeAngle})//})}}}class AutoMills {constructor() {this.gaps = [ 1.115820407, 1.141422642 ]this.lastPlace = nullthis.isActive = falsethis.expectedMills = 0this.autoResetTime = nullconst onKeyboard = () => {if (isInputFocused()) returnthis.isActive = !this.isActivethis.expectedMills = 0if (!this.isActive) this.lastPlace = null}Cow.onKeyboard(77, onKeyboard, {repeat: false})}get gap() {const { player } = Cowreturn this.gaps[Number(player.items[items.MILL] !== 10)]}update() {const { player } = Cowif (!player?.alive || !this.isActive) returnif (Date.now() - this.autoResetTime >= 500) {this.autoResetTime = null} else if (this.autoResetTime) {return}if (this.lastPlace && Date.now() - this.lastPlace < 100) returnconst millConfig = Cow.items.list[player.items[items.MILL]]const checkCanBuild = (angle) => {const scale = player.scale + millConfig.scale + (millConfig.placeOffset || 0)const placeX = player.x2 + scale * Math.cos(angle)const placeY = player.y2 + scale * Math.sin(angle)return Cow.objectsManager.checkItemLocation(placeX, placeY, millConfig.scale, .6, millConfig.id, false)}if (checkCanBuild(player.moveDir + this.gap)) {Cow.placeItem(items.MILL, {angle: player.moveDir + this.gap})this.expectedMills += 1}if (checkCanBuild(player.moveDir)) {Cow.placeItem(items.MILL, {angle: player.moveDir})this.expectedMills += 1}if (checkCanBuild(player.moveDir)) {Cow.placeItem(items.MILL, {angle: player.moveDir - this.gap})this.expectedMills += 1}if (this.expectedMills === 1) {this.autoResetTime = Date.now()}this.lastPlace = Date.now()}}class ReloadBars {constructor() {this.colors = {1: [ "#cc5151", "#8ecc51" ],2: "#accd51",3: "#c4cd51",4: "#cdae51",5: "#cd8251",6: "#cd5d51"}}getColor(reloadValue, isAlly) {let color = ""if (reloadValue >= 0.8 && reloadValue < 1) {color = this.colors[2]} else if (reloadValue >= 0.6 && reloadValue < 0.8) {color = this.colors[3]} else if (reloadValue >= 0.4 && reloadValue < 0.6) {color = this.colors[4]} else if (reloadValue >= 0.2 && reloadValue < 0.4) {color = this.colors[5]} else if (reloadValue < 0.2) {color = this.colors[6]} else {color = this.colors[1][Number(isAlly)]}return color}drawBar(widthMult, color, object, offsetX, offsetY, _width, radii) {const { healthBarWidth, healthBarPad } = window.configconst { context } = Cow.rendererconst width = _width || (healthBarWidth / 2 - healthBarPad / 2)const height = 17context._roundRect = _roundRectcontext.save()context.fillStyle = "#3d3f42"context.translate(object.renderX + offsetX, object.renderY + offsetY)context.beginPath()context._roundRect(-width - healthBarPad, -height / 2, 2 * width + 2 * healthBarPad, height, Array.isArray(radii) ? radii[0] : radii)context.fill()context.restore()context.save()context.fillStyle = colorcontext.translate(object.renderX + offsetX, object.renderY + offsetY)context.beginPath()context._roundRect(-width, -height / 2 + healthBarPad, 2 * width * widthMult, height - 2 * healthBarPad, Array.isArray(radii) ? radii[1] : radii - 1)context.fill()context.restore()}drawPrimaryBar(entity) {const primaryReload = Math.min(Math.max(entity.reloads.primary.count / entity.reloads.primary.max, 0), 1)const isAlly = entity.isMe || entity.isAllyconst { healthBarWidth, healthBarPad } = window.configconst width = (healthBarWidth / 2 - healthBarPad / 2)const addWidth = 0const color = this.getColor(primaryReload, isAlly)const offset = -width * 1.19 + addWidthconst radius = 8const radii = [[ radius, 0, 0, radius ], [ radius - 1, 0, 0, radius - 1 ]]this.drawBar(primaryReload, color, entity, offset, entity.scale + window.config.nameY - 5, width + addWidth, radii)}drawSecondaryBar(entity) {const secondaryReload = Math.min(Math.max(entity.reloads.secondary.count / entity.reloads.secondary.max, 0), 1)const isAlly = entity.isMe || entity.isAllyconst { healthBarWidth, healthBarPad } = window.configconst width = (healthBarWidth / 2 - healthBarPad / 2)const addWidth = 0const color = this.getColor(secondaryReload, isAlly)const offset = width * 1.19 - addWidthconst radius = 8const radii = [[ 0, radius, radius, 0 ], [ 0, radius - 1, radius - 1, 0 ]]this.drawBar(secondaryReload, color, entity, offset, entity.scale + window.config.nameY - 5, width + addWidth, radii)}drawTurretHatBar(entity) {const turretReload = Math.min(Math.max(entity.reloads.turret.count / entity.reloads.turret.max, 0), 1)const isAlly = entity.isMe || entity.isAllyconst { healthBarWidth } = window.configconst color = this.getColor(turretReload, isAlly)const radius = 8this.drawBar(turretReload, color, entity, 0, entity.scale + window.config.nameY * 1.75 - 3, healthBarWidth, radius)}update() {const { player } = Cowif (!player?.alive) returnCow.playersManager.eachVisible((player) => {this.drawPrimaryBar(player)this.drawSecondaryBar(player)this.drawTurretHatBar(player)})}}class Calculator {constructor() {}getLength(x, y) {const math = (Math.pow, Math.sqrt)return math(x * x + y * y)}findBuildingOnPosition(target, other) {const dx = target.x - other.xconst dy = target.y - other.yconst scale = target.scale + (other.getScale ? other.getScale() : other.scale)const length = this.getLength(dx, dy)return length - scale < 0}getPredictor(target) {return {x: target.x2 + target.speed * Math.cos(target.moveDir - Math.PI),y: target.y2 + target.speed * Math.sin(target.moveDir - Math.PI),scale: target.scale}}getDangerBuildings(target) {const { player } = Cowif (!player?.alive || !target?.visible) return []const predictor = this.getPredictor(target)return Cow.objectsManager.list.filter((gameObject) => {if (!gameObject.visible || !gameObject.isItem || !gameObject.visible) returnconst isSpike = [6, 7, 8, 9].includes(gameObject.id)return isSpike && !Cow.isAllianceMember(gameObject.owner?.sid) && this.findBuildingOnPosition(predictor, gameObject)})}}class AutoBreak {constructor() {this.isBreaking = falsethis.weaponBeforeStart = null}stopBreaking() {if (!this.isBreaking) returnconst { player } = Cowthis.isBreaking = falsetailor.auto####Hat = falseaimControl.stopAiming()Cow.sendPacket(packets.SELECT_BUILD, player.weapons[this.weaponBeforeStart], true)this.weaponBeforeStart = null}async update() {const { player } = Cowplayer.inTrap = falseconst nearTrap = Cow.objectsManager.list.filter((gameObject) => gameObject.visible && gameObject.active && gameObject.id === 15 && !Cow.isAllianceMember(gameObject.owner?.sid)).sort((a, b) => {a = CowUtils.getDistance(a, player)b = CowUtils.getDistance(b, player)return a - b})[0]if (!nearTrap) return this.stopBreaking()const distance = CowUtils.getDistance(nearTrap, player) - nearTrap.scale + window.config.collisionDepthplayer.inTrap = distance <= 10if (!player.inTrap) return this.stopBreaking()this.isBreaking = truetailor.auto####Hat = trueif (!this.weaponBeforeStart) {this.weaponBeforeStart = Number(player.weaponIndex > 8)}const breakWeapon = player.weapons[1] === 10 ? player.weapons[1] : player.weapons[0]const equipWeapon = (id) => {if (player.weaponIndex !== breakWeapon) Cow.sendPacket(packets.SELECT_BUILD, breakWeapon, true)}if (nearEnemy) {const weapon = Cow.items.weapons[player.weaponIndex]const angle = CowUtils.getDirection(nearEnemy, player)const distance = CowUtils.getDistance(nearEnemy, player) - player.scale * 2const isInAngle = CowUtils.getAngleDist(angle, player.dir) <= window.config.gatherAngleconst isInRange = distance <= weapon.rangeif (isInAngle && isInRange && player.weapons[0] !== 8) {equipWeapon(player.weapons[0])} else {equipWeapon(breakWeapon)}} else {equipWeapon(breakWeapon)}aimControl.startAiming(nearTrap)Cow.sendPacket(packets.ATTACK_STATE, 1, aimControl.aimAngle)Cow.sendPacket(packets.ATTACK_STATE, 0, aimControl.aimAngle)}}class AntiTrap extends AutoBreak {constructor() {super()}update() {super.update()}}class AimControl {constructor() {this.aimTarget = nullthis.isAiming = falsethis._aimAngle = nullthis.isSent = false}get aimAngle() {this.updateAimToTarget()return this._aimAngle}set aimAngle(_angle) {this._aimAngle = _angle}onSent() {this.isSent = true}updateAimToTarget() {if (!this.isAiming) returnconst { player } = Cowconst angle = typeof this.aimTarget === 'number' ? this.aimTarget : CowUtils.getDirection(this.aimTarget, player)this.aimAngle = angle}startAiming(point) {this.aimTarget = pointthis.isAiming = truethis.isSent = falsethis.updateAimToTarget()}stopAiming() {this.aimTarget = nullthis.isAiming = falsethis.aimAngle = null}}class AutoClickHats {constructor() {this.isActive = falsethis.isGathering = falsethis.isAutoAttacking = falsethis.timeout = null}onStartGather(isAutoAttack) {if (isAutoAttack) {this.isAutoAttacking = true}this.isGathering = truethis.reset()}onStopGather(isAutoAttack) {if (isAutoAttack) {this.isAutoAttacking = false}if (!isAutoAttack && this.isAutoAttacking) returnthis.isGathering = falsethis.reset()}fullReset() {this.isGathering = falsethis.isAutoAttacking = falsethis.reset()}reset() {this.isActive = falsethis.clearTimeout()}clearTimeout() {clearTimeout(this.timeout)this.timeout = null}update() {if (autoSpikeSync.isActive) return this.reset()if (!this.isGathering || this.isActive || this.timeout) returnconst { player } = Cowconst weapon = Cow.items.weapons[player.weaponIndex]let isTargetEnemy = falseif (nearEnemy) {const angle = CowUtils.getDirection(nearEnemy, player)const distance = CowUtils.getDistance(nearEnemy, player) - player.scale * 2const isInAngle = CowUtils.getAngleDist(angle, player.dir) <= window.config.gatherAngleconst isInRange = distance <= weapon.rangeif (isInRange && isInAngle) {isTargetEnemy = nearEnemythis.isActive = truethis.clearTimeout()player.tailIndex === 11 && tailor.equipAcc(0)tailor.equipHat(7)this.timeout = setTimeout(() => {tailor.equipHat(6)this.reset()}, weapon.speed / 1.5)}}if (isTargetEnemy) returnconst gameObjects = Cow.objectsManager.list.filter((gameObject) => gameObject.isItem && gameObject.visible && gameObject.active && CowUtils.getDistance(player, gameObject) <= 300)const nearGameObject = gameObjects.sort((a, b) => {a = CowUtils.getDistance(player, a)b = CowUtils.getDistance(player, b)return a - b})[0]if (nearGameObject) {const angle = CowUtils.getDirection(nearGameObject, player)const distance = CowUtils.getDistance(nearGameObject, player) - nearGameObject.scale - weapon.rangeif (distance > 0) returnthis.isActive = truethis.clearTimeout()tailor.equipHat(40)this.timeout = setTimeout(() => {tailor.equipHat(6)this.reset()}, weapon.speed / 1.5)}}}class AutoSpikeSync {constructor() {this.isActive = falsethis.lastActive = null}getSpikes() {return Cow.objectsManager.list.filter((gameObject) => gameObject.visible && gameObject.active && gameObject.group?.name === "spikes")}async doSpikeSync(angle) {if (this.lastActive && Date.now() - this.lastActive < 1000) returnconst { player } = Cowthis.isActive = trueif (player.weapons[0] === 7) {this.isActive = falsereturn Cow.placeItem(items.SPIKE, { angle })}aimControl.stopAiming()aimControl.startAiming(angle)await CowUtils.delay(10)player.weaponIndex !== player.weapons[0] && Cow.sendPacket(packets.SELECT_BUILD, player.weapons[0], true)await CowUtils.delay(10)tailor.equipAcc(0)await CowUtils.delay(10)tailor.equipHat(7)await CowUtils.delay(25)Cow.sendPacket(packets.ATTACK_STATE, 1, angle, "by 9mm")Cow.sendPacket(packets.ATTACK_STATE, 0, null, "by 9mm")await CowUtils.delay(25)Cow.placeItem(items.SPIKE, { angle })aimControl.stopAiming()this.isActive = falsethis.lastActive = Date.now()}update() {const { player, camera } = Cowconst { context } = Cow.rendererif (!player?.alive || this.isActive || !nearEnemy) returnconst spikeObjects = this.getSpikes()if (!spikeObjects.length) returnconst nearSpikesToEnemy = spikeObjects.filter((spikeObject) => spikeObject.owner.sid !== nearEnemy.sid && CowUtils.getDistance(nearEnemy, spikeObject) <= 90 + nearEnemy.scale)if (!nearSpikesToEnemy.length || nearSpikesToEnemy.length > 3) returnconst midX = nearSpikesToEnemy.reduce((acc, spikeObject) => acc + spikeObject.x, 0) / nearSpikesToEnemy.lengthconst midY = nearSpikesToEnemy.reduce((acc, spikeObject) => acc + spikeObject.y, 0) / nearSpikesToEnemy.lengthconst angleMeToMid = CowUtils.getDirection(midX, midY, player.x, player.y)const angleEnemyToMid = CowUtils.getDirection(midX, midY, nearEnemy.x, nearEnemy.y)const angleMeToEnemy = CowUtils.getDirection(nearEnemy, player)const targetAngle = window.config.gatherAngle * (nearSpikesToEnemy.length === 2 ? 2 : 1)const distanceToEnemy = CowUtils.getDistance(nearEnemy, player) - player.scale * 2if (CowUtils.getAngleDist(-angleEnemyToMid, angleMeToEnemy) > targetAngle) returnrenderGameObjectMark({renderX: midX - camera.xOffset,renderY: midY - camera.yOffset,}, context, 1, distanceToEnemy > player.weapon.range ? "#941492" : "#941414", true)if (distanceToEnemy > player.weapon.range) returnthis.doSpikeSync(angleMeToMid)}}CowUtils.delay = function(ms) {return new Promise((resolve) => setTimeout(resolve, ms))}Cow.placeItem = function() {const lastWeapon = Number(this.player.weaponIndex > 8)if (arguments[0] !== 0) {preplaceObjects.push({id: arguments[0],angle: arguments[1]?.angle || this.player.dir})}_placeItem.apply(this, arguments)const weaponId = this.player.weapons[lastWeapon]if (this.player.weaponIndex !== weaponId) this.sendPacket(packets.SELECT_BUILD, weaponId, true)}Cow.delayedPlaceItem = function(callback) {this.lastPlaceItem ??= 0if (this.lastPlaceItem && (this.ticker.ticks - this.lastPlaceItem) < 1) returncallback()this.lastPlaceItem = this.ticker.ticks}Cow.isAllianceMember = function(sid) {const { player } = Cowif (player && player.sid == sid) return trueif (!player.team || sid < 0) return falsefor (var i = 0; i < Cow.alliancePlayers.length; i += 2) {if (sid !== Cow.alliancePlayers[i]) continuereturn true}return false}Cow.isCanGather = function(doer, other) {const distance = CowUtils.getDistance(doer, other) - other.scaleconst angle = CowUtils.getDirection(other, doer)const angleDistance = CowUtils.getAngleDist(angle, doer.dir2)const isInAngle = angleDistance <= window.config.gatherAngleconst isInRange = distance <= doer.weapon.rangereturn {range: isInRange,angle: isInAngle,both: isInRange && isInAngle}}Cow.onPacket(packets.INIT_DATA, (initData) => {Cow.alliances = initData.teams})Cow.onPacket(packets.ADD_ALLIANCE, (alliance) => {Cow.alliances.push(alliance)})Cow.onPacket(packets.DELETE_ALLIANCE, (sid) => {for (let i = Cow.alliances.length - 1; i >= 0; i--) {if (Cow.alliances[i].sid !== sid) continueCow.alliances.splice(i, 1)}})Cow.onPacket(packets.SET_ALLIANCE_PLAYERS, (players) => {Cow.alliancePlayers = players})Cow.onPacket(packets.UPDATE_PLAYERS, () => {const { player } = Cowif (Cow.ticker.ticks - lastPreplaceClear >= 1) {preplaceObjects = []lastPreplaceClear = Cow.ticker.ticks}})Cow.onPacket(packets.ADD_PLAYER, (_, isYou) => {if (!isYou) returntailor.reset()autoClickHats.fullReset()toggleLoadingMenu(false)setTimeout(() => {updateItemsCount(true)}, 500)if (!Cow.isFirstEnterGame) {const firstClanInput = document.querySelector("#first_clan_input")Cow.isFirstEnterGame = truefirstClanInput.value && Cow.sendPacket(packets.CREATE_ALLIANCE, firstClanInput.value)}})Cow.onPacket(packets.UPDATE_ITEM_COUNTS, (index, value) => {const { player } = Cowplayer.itemCounts[index] = valueupdateItemsCount(false, index)})Cow.onPacket(packets.UPDATE_UPGRADES, (index, value) => {updateItemsCount()})const macro = new Macro()const calculator = new Calculator()const autoPlacer = new AutoPlacer()const tailor = new Tailor()const autoHeal = new AutoHeal()const antiInsta = new AntiInsta()const autoMills = new AutoMills()const reloadBars = new ReloadBars()const antiTrap = new AntiTrap()const aimControl = new AimControl()const autoClickHats = new AutoClickHats()const autoSpikeSync = new AutoSpikeSync()let lastRenderUpdate = 0let fps = 0let lastPingUpdate = nullCow.addRender("global", () => {fps += (1000 / Math.max(Date.now() - lastRenderUpdate, 1) - fps) / 10lastRenderUpdate = Date.now()const { context } = Cow.rendererconst { player } = CownearEnemy = Cow.getNearEnemy()for (const preplaceObject of preplaceObjects) {renderPreplace(preplaceObject, context)}Cow.objectsManager.eachVisible((gameObject) => {if (!gameObject.isItem || !gameObject.active) returnconst distance = CowUtils.getDistance(player, gameObject) - player.scaleif (distance > 600) returnconst alpha = Math.min(1, Math.max(0, 1 - (distance / 600)))renderGameObjectMark(gameObject, context, alpha)})macro.update()autoPlacer.update()autoClickHats.update()tailor.update()autoHeal.update()antiInsta.update()autoMills.update()reloadBars.update()antiTrap.update()autoSpikeSync.update()const pingDisplay = document.querySelector("#pingDisplay")if (pingDisplay && player?.alive) {if (!lastPingUpdate || (Date.now() - lastPingUpdate) >= 750 || !/FPS/.test(pingDisplay.innerHTML)) {pingDisplay.innerHTML = `Ping: ${window.pingTime}ms, FPS: ${fps.toFixed(0) || 0}`lastPingUpdate = Date.now()}}})const oldSend = WebSocket.prototype.sendWebSocket.prototype.send = function(data) {const binary = new Uint8Array(data)const decoded = msgpack.decode(binary)const { player } = Cowif (decoded[0] === packets.STORE_EQUIP && decoded[1][0] === 1 && decoded[1][1] !== 0) {if (decoded[1][3] !== "by 9mm" && player.points >= Cow.items.hats.searchById(decoded[1][1])?.price) {if (decoded[1][2] === 0) {tailor.hasHats.push(decoded[1][1])} else {tailor.hasAccs.push(decoded[1][1])}}}if (![9, 12, 13, 15].includes(player?.weaponIndex)) {if (decoded[0] === packets.ATTACK_STATE) {if (decoded[1][2] !== "by cowjs" && decoded[1][2] !== "by 9mm") {if (decoded[1][0] === 1) {autoClickHats.onStartGather()} else {autoClickHats.onStopGather()}}}if (decoded[0] === packets.AUTO_ATTACK) {if (!autoClickHats.isAutoAttacking) {autoClickHats.onStartGather(true)} else {autoClickHats.onStopGather(true)}}}if (decoded[0] === packets.SPAWN) {const nicknameInput = document.querySelector("#nickname_input")decoded[1][0] = {name: "9-".concat(nicknameInput.value.slice(0, 13)),moofoll: true,skin: decoded[1][0].skin}return oldSend.call(this, msgpack.encode(decoded))}if (decoded[0] === packets.LOOK_DIR && aimControl.isAiming) {aimControl.updateAimToTarget()decoded[1][0] = aimControl.aimAngleoldSend.call(this, msgpack.encode(decoded))return aimControl.onSent()}oldSend.apply(this, arguments)}function isInputFocused() {return document.activeElement.tagName === "INPUT"}function renderGameObjectMark(gameObject, context, alpha, color, isDebug) {const { player } = Cowconst radius = 12const innerRadius = !gameObject.maxHealth ? radius : (gameObject.health / gameObject.maxHealth) * radiuscolor = color ? color : gameObject.owner.sid === player.sid ? "#8ecc51" : Cow.isAllianceMember(gameObject.owner.sid) ? "#cdaa51" : "#cc5151"context.save()context.globalAlpha = alphacontext.fillStyle = colorcontext.translate(gameObject.renderX, gameObject.renderY)context.beginPath()context.arc(0, 0, isDebug ? radius : Math.min(radius, Math.max(0, innerRadius)), 0, Math.PI * 2)context.fill()context.closePath()context.restore()context.save()context.globalAlpha = alphacontext.strokeStyle = "#3d3f42"context.lineWidth = 5.5context.translate(gameObject.renderX, gameObject.renderY)context.beginPath()context.arc(0, 0, radius, 0, Math.PI * 2)context.stroke()context.closePath()context.restore()}function renderPreplace(preplaceObject, context) {const { player } = Cowconst item = Cow.items.list[Cow.player.items[preplaceObject.id]]const sprite = getItemSprite(item)const x = (player.scale + item.scale) * Math.cos(preplaceObject.angle)const y = (player.scale + item.scale) * Math.sin(preplaceObject.angle)const isCanPlace = Cow.objectsManager.checkItemLocation(player.x + x, player.y + y, item.scale, 0.6, item.id, false)if (!isCanPlace) returncontext.save()context.globalAlpha = .3context.translate(player.renderX + x, player.renderY + y)context.rotate(preplaceObject.angle)context.drawImage(sprite, -(sprite.width / 2), -(sprite.height / 2))context.restore()}function updateItemsCount(isFirst, itemIndex) {const { player } = Cowconst allActionBarItems = [ ...document.querySelectorAll(".actionBarItem") ]allActionBarItems.forEach((actionBarItem) => {const id = parseInt(actionBarItem.id.replace(/\D/g, "")) - 16const itemConfig = Cow.items.list[id]if (!itemConfig?.group) returnconst { group } = itemConfigif (!group.place) returnactionBarItem.innerHTML = `<span class="item-count${!isFirst && group.id === itemIndex ? " scale-anim" : ""}">${player.itemCounts[group.id] || 0}</span>`})}const itemSprites = {}function renderStar(ctxt, spikes, outer, inner) {const step = Math.PI / spikeslet rot = Math.PI / 2 * 3let x = 0let y = 0ctxt.beginPath()ctxt.moveTo(0, -outer)for (let i = 0; i < spikes; i++) {x = Math.cos(rot) * outery = Math.sin(rot) * outerctxt.lineTo(x, y)rot += stepx = Math.cos(rot) * innery = Math.sin(rot) * innerctxt.lineTo(x, y)rot += step}ctxt.lineTo(0, -outer)ctxt.closePath()}function renderCircle(x, y, scale, tmpContext, dontStroke, dontFill) {tmpContext = tmpContext || Cow.renderer.contexttmpContext.beginPath()tmpContext.arc(x, y, scale, 0, 2 * Math.PI)if (!dontFill) tmpContext.fill()if (!dontStroke) tmpContext.stroke()}function renderRect(x, y, w, h, ctxt, stroke) {ctxt.fillRect(x - (w / 2), y - (h / 2), w, h)if (!stroke) ctxt.strokeRect(x - (w / 2), y - (h / 2), w, h)}function renderRectCircle(x, y, s, sw, seg, ctxt, stroke) {ctxt.save()ctxt.translate(x, y)seg = Math.ceil(seg / 2)for (var i = 0; i < seg; i++) {renderRect(0, 0, s * 2, sw, ctxt, stroke)ctxt.rotate(Math.PI / seg)}ctxt.restore()}function renderTriangle(s, ctx) {ctx = ctx || Cow.renderer.contextconst h = s * (Math.sqrt(3) / 2)ctx.beginPath()ctx.moveTo(0, -h / 2)ctx.lineTo(-s / 2, h / 2)ctx.lineTo(s / 2, h / 2)ctx.lineTo(0, -h / 2)ctx.fill()ctx.closePath()}function getItemSprite(obj) {let tmpSprite = itemSprites[obj.id];if (tmpSprite) return tmpSpriteconst tmpCanvas = document.createElement("canvas")const tmpContext = tmpCanvas.getContext("2d")const outlineWidth = 5.5const outlineColor = "#525252"tmpCanvas.width = tmpCanvas.height = (obj.scale * 2.5) + outlineWidth + (Cow.items.list[obj.id].spritePadding || 0)tmpContext.strokeStyle = outlineColortmpContext.lineWidth = outlineWidthtmpContext.translate((tmpCanvas.width / 2), (tmpCanvas.height / 2))tmpContext.rotate(Math.PI / 2)if (/wall/.test(obj.name)) {const sides = (obj.name == "castle wall") ? 4 : 3tmpContext.fillStyle = obj.name == "castle wall" ? "#83898e" : obj.name == "wood wall" ? "#a5974c" : "#939393"renderStar(tmpContext, sides, obj.scale * 1.1, obj.scale * 1.1)tmpContext.fill()tmpContext.stroke()tmpContext.fillStyle = obj.name == "castle wall" ? "#9da4aa" : obj.name == "wood wall" ? "#c9b758" : "#bcbcbc"renderStar(tmpContext, sides, obj.scale * 0.65, obj.scale * 0.65)tmpContext.fill()} else if (/spikes/.test(obj.name)) {const tmpScale = (obj.scale * 0.6)tmpContext.fillStyle = obj.name == "poison spikes" ? "#7b935d" : "#939393"renderStar(tmpContext, (obj.name == "spikes") ? 5 : 6, obj.scale, tmpScale)tmpContext.fill()tmpContext.stroke()tmpContext.fillStyle = "#a5974c"renderCircle(0, 0, tmpScale, tmpContext)tmpContext.fillStyle = "#c9b758"renderCircle(0, 0, tmpScale / 2, tmpContext, true)} else if (/mill/.test(obj.name)) {tmpContext.fillStyle = "#a5974c"renderCircle(0, 0, obj.scale, tmpContext)tmpContext.fillStyle = "#c9b758"renderRectCircle(0, 0, obj.scale * 1.5, 29, 4, tmpContext)tmpContext.fillStyle = "#a5974c"renderCircle(0, 0, obj.scale * 0.5, tmpContext)} else if (/mine/.test(obj.name)) {tmpContext.fillStyle = "#939393"renderStar(tmpContext, 3, obj.scale, obj.scale)tmpContext.fill()tmpContext.stroke()tmpContext.fillStyle = "#bcbcbc"renderStar(tmpContext, 3, obj.scale * 0.55, obj.scale * 0.65)tmpContext.fill()} else if (/sapling/.test(obj.name)) {for (let i = 0; i < 2; ++i) {const tmpScale = obj.scale * (!i ? 1 : 0.5)renderStar(tmpContext, 7, tmpScale, tmpScale * 0.7)tmpContext.fillStyle = (!i ? "#9ebf57" : "#b4db62")tmpContext.fill()!i && tmpContext.stroke()}} else if (/trap/.test(obj.name)) {tmpContext.fillStyle = "#a5974c"renderStar(tmpContext, 3, obj.scale * 1.1, obj.scale * 1.1)tmpContext.fill()tmpContext.stroke()tmpContext.fillStyle = outlineColorrenderStar(tmpContext, 3, obj.scale * 0.65, obj.scale * 0.65)tmpContext.fill()} else if (/boost/.test(obj.name)) {tmpContext.fillStyle = "#7e7f82"renderRect(0, 0, obj.scale * 2, obj.scale * 2, tmpContext)tmpContext.fill()tmpContext.stroke()tmpContext.fillStyle = "#dbd97d"renderTriangle(obj.scale * 1, tmpContext)} else if (/turret/.test(obj.name)) {const tmpLen = 50tmpContext.fillStyle = "#a5974c"renderCircle(0, 0, obj.scale, tmpContext)tmpContext.fill()tmpContext.stroke()tmpContext.fillStyle = "#939393"renderRect(0, -tmpLen / 2, obj.scale * 0.9, tmpLen, tmpContext)renderCircle(0, 0, obj.scale * 0.6, tmpContext)tmpContext.fill()tmpContext.stroke()} else if (/platform/.test(obj.name)) {const tmpCount = 4;const tmpS = obj.scale * 2const tmpW = tmpS / tmpCountlet tmpX = -(obj.scale / 2)tmpContext.fillStyle = "#cebd5f"for (let i = 0; i < tmpCount; ++i) {renderRect(tmpX - (tmpW / 2), 0, tmpW, obj.scale * 2, tmpContext)tmpContext.fill()tmpContext.stroke()tmpX += tmpS / tmpCount}} else if (/spawn/.test(obj.name)) {tmpContext.fillStyle = "#7e7f82"renderRect(0, 0, obj.scale * 2, obj.scale * 2, tmpContext)tmpContext.fill()tmpContext.stroke()tmpContext.fillStyle = "#71aad6"renderCircle(0, 0, obj.scale * 0.6, tmpContext)} else if (/blocker/.test(obj.name)) {tmpContext.fillStyle = "#7e7f82"renderCircle(0, 0, obj.scale, tmpContext)tmpContext.fill()tmpContext.stroke()tmpContext.rotate(Math.PI / 4)tmpContext.fillStyle = "#db6e6e"renderRectCircle(0, 0, obj.scale * 0.65, 20, 4, tmpContext, true)} else if (/teleport/.test(obj.name)) {tmpContext.fillStyle = "#7e7f82"renderCircle(0, 0, obj.scale, tmpContext)tmpContext.fill()tmpContext.stroke()tmpContext.rotate(Math.PI / 4)tmpContext.fillStyle = "#d76edb"renderCircle(0, 0, obj.scale * 0.5, tmpContext, true)}tmpSprite = tmpCanvasitemSprites[obj.id] = tmpSpritereturn tmpSprite}function waitForInterval(selector, callback) {const checker = setInterval(() => {const node = document.querySelector(selector)if (!node?.style) returncallback()clearInterval(checker)})setTimeout(() => {clearInterval(checker)}, 30000)return checker}waitForInterval("#gameUI", () => {createCustomHtmlAndCss()})waitForInterval("#mainMenu", createCustomMainMenu)waitForInterval("#enterGame", () => {const enterGameBtn = document.querySelector("#enterGame")enterGameBtn.addEventListener = new Proxy(enterGameBtn.addEventListener, {apply(target, _this, args) {_this = document.querySelector("#play_button")return target.apply(_this, args)}})})Object.defineProperty(HTMLElement.prototype, "onclick", {set(callback) {this.addEventListener("click", arguments[0])if (!/enterGame/.test(this.id)) returnconst playButton = document.querySelector("#play_button")playButton.addEventListener("click", arguments[0])}})function createCustomMainMenu() {const mainMenu = document.querySelector("#mainMenu")const style = document.createElement("style")style.insertAdjacentHTML("beforeend", `.better-mm-holder {display: block;position: absolute;top: 0;z-index: 999999999;width: 100%;height: 100%;background: rgba(0, 0, 0, .75);overflow: hidden;pointer-events: all;}.better-mm-holder * {box-sizing: border-box;}.better-mm-holder ul, .better-mm-holder li {margin: 0;padding: 0;list-style: none;text-decoration: none;}.better-mm-wrapper {display: flex;flex-direction: column;justify-content: space-between;height: 100%;}.better-mm-header {display: flex;align-items: center;justify-content: center;width: 100%;height: 105px;min-height: 105px;background: #101010;border-bottom: 4px solid #1f0f29;}.mod-title {background: #1f0f29;color: #7575757a;font-size: 50px;transform: skewX(10deg);padding: 5px 30px;border-radius: 50% 20% 35% / 70%;box-shadow: 0px 0px 3px 1px #020002;animation: blob-anim 20s infinite ease-in-out;}@keyframes blob-anim {0% {border-radius: 50% 20% 35% / 70%;}25% {border-radius: 50% 20% 35% / 30% 30% 20%;}50% {border-radius: 50% 20% 35% / 50% 50% 40%;}100% {border-radius: 50% 20% 35% / 70%;}}.better-mm-container {display: flex;align-items: center;justify-content: center;gap: 20px;width: 100%;height: 100%;padding: 40px;}.bmm-container-box {display: flex;flex-direction: column;background: #101010;border: 4px solid #1f0f29;border-radius: 12px;padding: 5px;overflow-y: auto;}.bmm-container-box::-webkit-scrollbar {width: 8px;}.bmm-container-box::-webkit-scrollbar-track {width: 8px;}.bmm-container-box::-webkit-scrollbar-thumb {background: rgba(0, 0, 0, .35);border-radius: 4px 30px 30px 4px;}.game-servers-box, .mod-changelog-box, .game-settings-box {min-height: 375px;max-height: 375px;width: 325px;}.items-list {display: flex;flex-direction: column;align-items: center;gap: 5px;padding: 5px !important;}.items-list .item {display: flex;flex-direction: column;gap: 4px;background: #252525b8;width: 100%;min-height: max-content;border-radius: 6px;padding: 5px !important;}.items-list .item.light-background {background: #474747bd;}.changelog-item-header, .server-data-header {font-size: 16px;color: #d0d0d0;}.changelog-updates {display: flex;flex-direction: column;gap: 4px;padding: 0 4px;}.changelog-update-value {font-size: 14px;color: #a3a2a2;}.changelog-version-info {display: flex;flex-direction: column;gap: 2px;padding-left: 4px;border-left: 2px solid #a3a2a2;}.player-body-figure {stroke-width: 4;stroke: #3d3f42;transition: .3s fill;}.game-settings-box, .game-servers-box {overflow-y: hidden;}.game-servers-box .items-list {overflow-y: auto;}.game-servers-box .items-list::-webkit-scrollbar {width: 8px;}.game-servers-box .items-list::-webkit-scrollbar-track {width: 8px;}.game-servers-box .items-list::-webkit-scrollbar-thumb {background-color: rgba(0, 0, 0, .35);border-radius: 20px;}.game-settings-box {display: flex;align-items: center;justify-content: space-between;}.player-settings {display: flex;align-items: center;justify-content: center;gap: 5px;padding: 10px;}.player-preview-wrapper {min-width: 50px;min-height: 50px;border-radius: 12px;background: #252525b8;cursor: pointer;}.player-data-wrapper {display: flex;flex-direction: column;gap: 8px;}.player-data-input {background: none;outline: 0;border: none;color: #d0d0d0;font-size: 14px;border-bottom: 2px solid #1f0f29;transition: .3s border-bottom;}.player-data-input:hover, .player-data-input:focus {border-bottom: 2px solid #2d143d;}.game-servers-update {display: flex;align-items: center;justify-content: center;color: #a3a2a2;font-size: 16px;width: 100%;min-height: 30px;background: #252525b8;border-radius: 6px;cursor: pointer;margin-bottom: 5px;transition: .3s color;}.game-servers-update:hover {color: #d0d0d0;}.server-data-wrapper {display: flex;align-items: center;justify-content: space-between;}.server-data-header, .server-data-ping {font-size: 14px;user-select: text;cursor: default;}.server-data-ping.red {color: #750d0d;}.server-data-ping.low-red {color: #852323;}.server-data-ping.yellow {color: #b3af0c;}.server-data-ping.green {color: #4bb30c;}.server-data-ping.low-green {color: #6c9f2b;}.server-data-actions {display: flex;align-items: center;gap: 4px;}.server-data-players {display: inline-block;user-select: none;color: #a3a2a2;width: 55px;}.server-open-btn {display: flex;align-items: center;justify-content: center;color: #d0d0d0;font-size: 14px;cursor: pointer;padding: 0 4px;background: #1f0f29;border-radius: 4px;}.loading-text, .disconnect-text {color: #d0d0d0;font-size: 35px;}.info-link {cursor: pointer;text-decoration: underline;}.link-logo {width: 25px;height: 25px;}.info-footer {display: flex;align-items: center;justify-content: center;gap: 10px;padding: 8px;border-radius: 8px;}.info-footer-item {display: flex;align-items: center;}.info-footer-item.discord-item {user-select: text;}.info-footer-item.discord-item img {transform: scale(1.35);}.info-footer-item.discord-item::after {content: "nudoo";position: fixed;color: #5a75ce;font-size: 14px;width: 0px;transform: scaleX(0) translateX(30px);text-decoration: none;opacity: 0;user-select: text;transition: transform .3s, width .3s, opacity .3s;}.info-footer-item.discord-item:hover::after {margin-left: 4px;transform: scaleX(1) translateX(30px);width: 40px;opacity: 1;}.game-settings {display: flex;flex-direction: column;}.player-settings-wrapper {display: flex;flex-direction: column;align-items: center;}.play-button, .game-setting-btn {display: flex;align-items: center;justify-content: center;font-size: 18px;padding: 0 4px;width: 100%;height: 30px;color: #7575757a;background: #1f0f29;border-radius: 6px;letter-spacing: 4px;cursor: pointer;transition: .3s background, .3s color;}.play-button:hover {background: #2d143d;color: #75757599;}.play-button:active, .game-setting-btn:active {transform: scale(.975);}.game-settings {display: grid;grid-template-columns: repeat(2, max-content);justify-items: center;justify-content: center;grid-gap: 5px;width: 100%;height: 100%;}.game-setting-btn {font-size: 14px;width: 140px;padding: 0 6px;letter-spacing: 0px;background: #1f0f29;}.game-setting-btn.enabled {background: #2d143d;color: #d0d0d0;}.select-skin-panel {position: absolute;padding: 4px;display: grid;grid-template-columns: repeat(5, max-content);gap: 4px;background: #252525b8;border: 4px solid #1f0f29;border-radius: 6px;z-index: 99999999999;}.skin-circle {cursor: pointer;width: 20px;height: 20px;border-radius: 6px;border: 3px solid #525252;transition: .3s border-radius;}.skin-circle:hover {border-radius: 50%;}.skin-circle.selected {border-radius: 50% !important;}.global-notification {position: absolute;top: 0;width: 100%;height: 100%;z-index: 9999999999999999999;display: flex;align-items: center;justify-content: center;}.global-notification-box {width: 400px;height: 400px;overflow: hidden;}`)document.head.appendChild(style)mainMenu.insertAdjacentHTML("beforeend", `<div class="better-mm-holder" id="menuCardHolder"><main class="better-mm-wrapper"><header class="better-mm-header"><span class="mod-title">9mm</span></header><container class="better-mm-container" id="better_mm_loading"><span class="loading-text">Loading...</span></container><container class="better-mm-container hidden" id="better_mm_disconnect"><span class="disconnect-text">Disconnected...</span></container><container class="better-mm-container hidden" id="better_mm_container"><box class="bmm-container-box game-servers-box"><div class="game-servers-update" id="game_servers_update">UPDATE</div><ul class="items-list" id="game_servers"></ul></box><box class="bmm-container-box game-settings-box"><div class="player-settings-wrapper"><div class="player-settings"><div class="player-preview-wrapper" id="player_preview"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="eIZvJ0eqgt61" viewBox="0 0 100 100" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"><ellipse class="player-body-figure" rx="10" ry="10" transform="translate(80 32.942071)" fill="#bf8f54"/><ellipse class="player-body-figure" rx="10" ry="10" transform="translate(20 32.942071)" fill="#bf8f54"/><ellipse class="player-body-figure" rx="30" ry="30" transform="translate(50 57)" fill="#bf8f54"/></svg></div><div class="player-data-wrapper"><input class="player-data-input" id="nickname_input" placeholder="Enter nickname..." maxlength="13"><input class="player-data-input" id="first_clan_input" placeholder="Enter clan name..." maxlength="7"></div></div><div class="play-button" id="play_button">PLAY</div></div><div class="game-settings"><div class="game-setting-btn${localStorage.show_ping == "true" ? " enabled" : ""}" id="show_ping">Show ping/fps</div><div class="game-setting-btn${localStorage.native_resolution == "true" ? " enabled" : ""}" id="native_resolution">Native resolution</div><div class="game-setting-btn${localStorage.mill_rotate == "true" ? " enabled" : ""}" id="mill_rotate">Mill rotate</div><div class="game-setting-btn${localStorage.remove_grid == "true" ? " enabled" : ""}" id="remove_grid">Remove grid</div></div><footer class="info-footer"><a class="info-footer-item info-link" href="https://www.youtube.com/channel/UCpBgMEb1vFQnMcSz-kJ6i0Q" target="_blank"><img class="link-logo" src="https://cdn.glitch.global/26ec0d7f-01b9-40b1-aff5-8aa4412693c4/youtube.png?v=1700800235511"></a><a class="info-footer-item info-link" href="https://github.com/Nudo-o/" target="_blank"><img class="link-logo" src="https://cdn.glitch.global/26ec0d7f-01b9-40b1-aff5-8aa4412693c4/github-mark-white.png?v=1700800770200"></a><a class="info-footer-item info-link" href="https://greasyfork.org/ru/users/759782-nudo" target="_blank"><img class="link-logo" src="https://cdn.glitch.global/26ec0d7f-01b9-40b1-aff5-8aa4412693c4/greasyfork.png?v=1700800851140"></a><div class="info-footer-item discord-item"><img class="link-logo" src="https://cdn.glitch.global/26ec0d7f-01b9-40b1-aff5-8aa4412693c4/discord.png?v=1700801396017"></div></footer></box><box class="bmm-container-box mod-changelog-box"><ul class="items-list" id="mod_changelog"></ul></box></container></main></div><div class="select-skin-panel hidden" id="select_skin_panel"><div class="skin-circle selected" activeSkin" style="background: #bf8f54;" skin_index="0"></div><div class="skin-circle" style="background: #cbb091;" skin_index="1"></div><div class="skin-circle" style="background: #896c4b;" skin_index="2"></div><div class="skin-circle" style="background: #fadadc;" skin_index="3"></div><div class="skin-circle" style="background: #ececec;" skin_index="4"></div><div class="skin-circle" style="background: #c37373;" skin_index="5"></div><div class="skin-circle" style="background: #4c4c4c;" skin_index="6"></div><div class="skin-circle" style="background: #ecaff7;" skin_index="7"></div><div class="skin-circle" style="background: #738cc3;" skin_index="8"></div><div class="skin-circle" style="background: #8bc373;" skin_index="9"></div></div>`)updateChangelog(getModVersions(), "#mod_changelog")const gameServersUpdateBtn = document.querySelector("#game_servers_update")const nicknameInput = document.querySelector("#nickname_input")const firstClanInput = document.querySelector("#first_clan_input")const playButton = document.querySelector("#play_button")const showPing = document.querySelector("#show_ping")const millRotate = document.querySelector("#mill_rotate")const nativeResolution = document.querySelector("#native_resolution")const removeGrid = document.querySelector("#remove_grid")const playerPreview = document.querySelector("#player_preview")const allSelectSkinElements = [ ...document.querySelectorAll(".skin-circle") ]const setNodeVisibility = (selector, key) => {const node = document.querySelector(selector)if (!node) returnconst state = JSON.parse(localStorage.getItem(key))if (!node.hiddenInterval) {node.hiddenInterval = setInterval(() => {node.hidden = false})}if (state) return node.classList.remove("hidden")node.classList.add("hidden")}const toggleGameSettingBtn = (toggler, key) => {if (!toggler) returntoggler.classList.toggle("enabled")const state = toggler.classList.contains("enabled")localStorage.setItem(key, state.toString())if (key === "show_ping") {setNodeVisibility("#pingDisplay", key)}}const setGameSettingBtnState = (toggler, key) => {if (!toggler) returnconst state = JSON.parse(localStorage.getItem(key))if (key === "show_ping") {setNodeVisibility("#pingDisplay", key)}if (state) return toggler.classList.add("enabled")toggler.classList.remove("enabled")}setGameSettingBtnState(showPing, "show_ping")setGameSettingBtnState(millRotate, "mill_rotate")setGameSettingBtnState(nativeResolution, "native_resolution")setGameSettingBtnState(removeGrid, "remove_grid")nicknameInput.value = localStorage.getItem("9mm_name") || ""firstClanInput.value = localStorage.getItem("moo_first_clan") || ""nicknameInput.addEventListener("input", () => {localStorage.setItem("9mm_name", nicknameInput.value)})firstClanInput.addEventListener("input", () => {localStorage.setItem("moo_first_clan", firstClanInput.value)})showPing.addEventListener("click", toggleGameSettingBtn.bind(null, showPing, "show_ping"))millRotate.addEventListener("click", toggleGameSettingBtn.bind(null, millRotate, "mill_rotate"))nativeResolution.addEventListener("click", toggleGameSettingBtn.bind(null, nativeResolution, "native_resolution"))removeGrid.addEventListener("click", toggleGameSettingBtn.bind(null, removeGrid, "remove_grid"))playButton.addEventListener("click", enterGame)gameServersUpdateBtn.addEventListener("click", updateGameServers)playerPreview.addEventListener("click", toggleSelectSkin)window.addEventListener("resize", () => {toggleSelectSkin(null, true)})allSelectSkinElements.forEach((selectSkinElement) => {selectSkinElement.addEventListener("mousedown", selectSkin)})const checkGameLoading = setInterval(() => {const loadingText = document.querySelector("#loadingText")if (loadingText?.style.display !== "none") returnif (localStorage.moo_skin) {selectSkin({ target: allSelectSkinElements[+localStorage.moo_skin] })}toggleLoadingMenu(false)clearInterval(checkGameLoading)})const checkGameDisconnect = setInterval(() => {const loadingText = document.querySelector("#loadingText")if (loadingText?.style.display === "none" || !/disconnect/.test(loadingText?.innerHTML)) returntoggleDisconnectMenu(true)clearInterval(checkGameLoading)})Cow.socket.onEvent("close", toggleDisconnectMenu.bind(null, true))}function selectSkin(event) {const allSelectSkinElements = [ ...document.querySelectorAll(".skin-circle") ]allSelectSkinElements.forEach((selectSkinElement) => {selectSkinElement.classList.remove("selected")})const skinIndex = parseInt(event.target.getAttribute("skin_index"))const playerBodyFigures = [ ...document.querySelectorAll(".player-body-figure") ]playerBodyFigures.forEach((playerBodyFigure) => {playerBodyFigure.style.fill = window.config.skinColors[skinIndex]})event.target.classList.add("selected")window.selectSkinColor(skinIndex)localStorage.setItem("moo_skin", skinIndex)}function toggleSelectSkin(_, isResize, forceHide) {const playerPreview = document.querySelector("#player_preview")const selectSkinPanel = document.querySelector("#select_skin_panel")const boundings = playerPreview.getBoundingClientRect()const width = 162const height = 72if (forceHide) return selectSkinPanel.classList.add("hidden")!isResize && selectSkinPanel.classList.toggle("hidden")selectSkinPanel.style.left = `${boundings.x - width / 2 + boundings.width / 2}px`selectSkinPanel.style.top = `${boundings.y - height - 5}px`}function enterGame() {const enterGameBtn = document.querySelector("#enterGame")toggleSelectSkin(null, false, true)toggleLoadingMenu(true)setLoadingText("Connecting...")}function setLoadingText(text) {const bettermmLoading = document.querySelector("#better_mm_loading")const loadingText = bettermmLoading.querySelector(".loading-text")loadingText.innerHTML = text}function toggleDisconnectMenu(visibility) {const bettermmDisconnect = document.querySelector("#better_mm_disconnect")if (visibility) {bettermmDisconnect.classList.remove("hidden")toggleLoadingMenu(false)toggleSelectSkin(null, false, true)return toggleBettermmContainer(false)}bettermmDisconnect.classList.add("hidden")toggleBettermmContainer(true)toggleLoadingMenu(false)}function toggleLoadingMenu(visibility) {const bettermmLoading = document.querySelector("#better_mm_loading")if (visibility) {bettermmLoading.classList.remove("hidden")toggleSelectSkin(null, false, true)return toggleBettermmContainer(false)}bettermmLoading.classList.add("hidden")toggleBettermmContainer(true)}function toggleBettermmContainer(visibility) {const bettermmContainer = document.querySelector("#better_mm_container")if (visibility) {return bettermmContainer.classList.remove("hidden")}bettermmContainer.classList.add("hidden")}function getGameServers() {const currentMode = location.host.replace(/\.moomoo\.io/, "")const getRequestUrl = () => {if (/(sandbox|dev)/.test(currentMode)) {return `https://api-${currentMode}.moomoo.io/servers?v=1.22`}return "https://api.moomoo.io/servers"}return new Promise((resolve) => {fetch(getRequestUrl()).then((res) => res.text()).then((servers) => resolve(JSON.parse(servers)))})}async function updateGameServers() {let servers = await getGameServers()const [ currentServerRegion, currentServerName ] = location.href.replace(/.+\=/, "").split(":")const gameServers = document.querySelector("#game_servers")const serversByRegions = {}gameServers.innerHTML = ""for (const server of servers) {if (!serversByRegions[server.region]) {serversByRegions[server.region] = []}serversByRegions[server.region].push(server)}servers = Object.values(serversByRegions)for (let serversRegion of servers) {serversRegion = serversRegion.sort((a, b) => b.playerCount - a.playerCount)for (let i = 0; i < serversRegion.length; i++) {const server = serversRegion[i]const requestPingUrl = `https://${server.key}.${server.region}.moomoo.io/ping/9mm`const sentTime = Date.now()const currentMode = location.host.replace(/\.moomoo\.io/, "")const id = `${server.region}_${server.name}`const isCurrentServer = server.region === currentServerRegion && server.name === currentServerNamegameServers.insertAdjacentHTML(isCurrentServer ? "afterbegin" : "beforeend", `<li class="item${isCurrentServer ? " light-background" : ""}"><div class="server-data-wrapper"><header class="server-data-header"><span class="server-data-players">(${server.playerCount}/${server.playerCapacity})</span>${window.regionsName[server.region]} ${server.name}</header><div class="server-data-actions"><span class="server-data-ping" id="${id}_ping"></span>${!isCurrentServer ? `<div class="server-open-btn" id="${id}_open">GO!</div>` : ""}</div></div></li>`)const serverOpenBtn = document.querySelector(`#${id}_open`)if (serverOpenBtn) {serverOpenBtn.addEventListener("click", () => {window.open(`https://${currentMode !== "" ? currentMode + "." : ""}moomoo.io/?server=${server.region}:${server.name}`)})}fetch(requestPingUrl).then(() => {const ping = Date.now() - sentTimeconst serverDataPing = document.querySelector(`#${server.region}_${server.name}_ping`)if (ping >= 500) {serverDataPing.classList.add("red")} else if (ping >= 350 && ping < 500) {serverDataPing.classList.add("low-red")} else if (ping >= 200 && ping < 350) {serverDataPing.classList.add("yellow")} else if (ping >= 100 && ping < 200) {serverDataPing.classList.add("low-green")} else {serverDataPing.classList.add("green")}serverDataPing.innerHTML = ping})}}}function getModVersions() {return `1.0.1 (5/02/2024):> Added auto spike sync.> Added distance check for building markers.> Optimization for any keyboard.> Fixed a bug with infinite loading.1.0.0 (4/02/2024):> Release.> Mini update auto mills.> Added custom main menu.> Added auto #### and bull hats.> Added building markers/hp.> Added items count.> Store was returned.1.0.0b (2/02/2024):> Beta release.`}async function updateChangelog(versions, appendNodeSelector, linesSlice = 0) {const changelog = document.querySelector(appendNodeSelector)const versionsList = versions.split(/\n/).slice(linesSlice).filter((line) => line !== "" && !/\s\s\-\s/.test(line))for (let i = 0; i < versionsList.length; i++) {const versionsLine = versionsList[i]if (!/^\d/.test(versionsLine)) continueconst currentVersion = versionsLine.replace(/\:.+$/, ":").replace(/\)\s.+\:/, ":")const parsedVersion = currentVersion.replace(/\(.+/, "").replace(/\s\-/, "")const versionDate = currentVersion.replace(/^.+\(/, "(").replace(/(\(|\)|\:)/g, "").split("/")const date = `${versionDate[1]}/${versionDate[0]}/${versionDate[2]}`const month = new Date(date).toLocaleString('en-GB', { month: 'long' })const nextGameVersionIndex = versionsList.slice(i + 1).findIndex((line) => /^\d+\./.test(line))const updatesList = versionsList.slice(i + 1, (i + 1) + nextGameVersionIndex)if (/0\.10/.test(parsedVersion) && linesSlice !== 0) {updatesList.push("> Initial Release")}if (/1\.0\.0b/.test(parsedVersion) && linesSlice === 0) {updatesList.push("> Beta release.")}changelog.insertAdjacentHTML("beforeend", `<li class="item"><header class="changelog-item-header">${parsedVersion} (${month} ${versionDate[0]}, ${versionDate[2]})</header><div class="changelog-updates">${updatesList.map((update) => `<div class="changelog-version-info"><span class="changelog-update-value">${update.replace(/\>\s/, "")}</span></div>`).join("")}</div></li>`)}}function createCustomHtmlAndCss() {const style = document.createElement("style")style.insertAdjacentHTML("beforeend", `.hidden {display: none !important;}.item-count {position: absolute;display: block;color: #fff;font-size: 16px;margin: 2px 5px;}.item-count.scale-anim {transform: scale(1);animation: item-count-scale-anim 1s;}@keyframes item-count-scale-anim {0% {transform: scale(1);}50% {transform: scale(1.1);}100% {transform: scale(1);}}.actionBarItem {text-align: end;}#actionBar {display: flex !important;justify-content: center;margin-bottom: 5px;}#menuContainer, #settingsButton, #partyButton, #linksContainer2, #joinPartyButton {display: none !important;}`)document.head.appendChild(style)}const maxScreenWidth = 1920const maxScreenHeight = 1080const { lineTo, moveTo } = CanvasRenderingContext2D.prototypeconst gridAlpha = 0.06CanvasRenderingContext2D.prototype.moveTo = function(x, y) {if (localStorage.remove_grid == "false") return moveTo.apply(this, arguments)if (this.globalAlpha === gridAlpha) returnreturn moveTo.apply(this, arguments)}CanvasRenderingContext2D.prototype.lineTo = function(x, y) {if (localStorage.remove_grid == "false") return lineTo.apply(this, arguments)if (this.globalAlpha === gridAlpha && (y === maxScreenHeight || x === maxScreenWidth)) returnreturn lineTo.apply(this, arguments)}const turnSpeeds = {9: .003,10: .0016,11: .0025,12: .005,}Object.defineProperty(Object.prototype, "turnSpeed", {get() {if (![10, 11, 12].includes(this.id)) return turnSpeeds[this.id]return localStorage.mill_rotate == "true" ? turnSpeeds[this.id] : 0},set(value) {this[Symbol("turnSpeed")] = value}})window.fetch = new Proxy(fetch, {apply(target, _this, args) {if (/\/ping/.test(args[0]) && !/\/9mm/.test(args[0])) {return target.apply(_this)}if (/\/9mm/.test(args[0])) {args[0] = args[0].replace(/\/9mm/, "")}return target.apply(_this, args)}})console._error = console.errorconsole.error = function(error) {// FK THIS FKING ERROR!!! FK U FAILED TO LOAD. I'VE BEEN FIXING YOU FOR 4 ####ING HOURS.if (error === "Failed to load.") {setInterval(() => {setLoadingText("Failed to load -___-")toggleBettermmContainer(false)toggleLoadingMenu(true)})}this._error(error)}window.regionsName = {"us-east": "Miami","us-west": "Silicon Valley","gb": "London","eu-west": "Frankfurt","au": "Sydney","sg": "Singapore"}})()