// ==UserScript==
// @name 9mm [MooMoo.io]
// @name:ru 9mm [MooMoo.io]
// @namespace https://github.com/Nudo-o
// @version 1.0.0b
// @description It's a good script for the game, 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! You don't need to buy anything in the store, the script will buy everything by itself!
// @description:ru Это хороший сценарий для игры, не самый лучший, но я постараюсь сделать его как можно лучше. 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://update.greasyfork.org/scripts/480301/1320686/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/1320686/CowJS.js
/*
- 02.02.2024 (v1.0.0):
1. RELEASE.
*/
(function() {
"use strict"
const { Cow, CowUtils } = window
const { packets, items } = Cow.config.designations
const _placeItem = Cow.placeItem
const _roundRect = CanvasRenderingContext2D.prototype.roundRect
let nearEnemy = null
let preplaceObjects = []
let lastPreplaceClear = 0
class AutoHeal {
constructor() {
this.checkIsHealed = false
this.lastHeal = 0
}
doFullHeal() {
const { player } = Cow
if (player.health === player.maxHealth) return
const amount = player.items[0] === 0 ? 20 : player.items[0] === 1 ? 30 : 25
for (let i = player.health; i < player.maxHealth; i += amount) {
this.doHeal()
}
}
doHeal() {
const { player } = Cow
if (player.health === player.maxHealth) return
const timeSinceHeal = Cow.ticker.ticks - (this.lastHeal || 0)
if (timeSinceHeal >= 0) {
Cow.delayedPlaceItem(() => Cow.placeItem(items.FOOD))
this.lastHeal = Cow.ticker.ticks
}
}
update() {
const { player } = Cow
if (!player?.alive || player?.skinIndex === 45) return
if (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 = 35
this.lastHeal = 0
}
doFullHeal() {
const { player } = Cow
if (player.health === player.maxHealth) return
const amount = player.items[0] === 0 ? 20 : player.items[0] === 1 ? 30 : 25
for (let i = player.health; i < player.maxHealth; i += amount) {
this.doHeal()
}
}
doHeal() {
const { player } = Cow
if (player.health === player.maxHealth) return
const timeSinceHeal = Cow.ticker.ticks - (this.lastHeal || 0)
if (timeSinceHeal >= 0) {
Cow.placeItem(items.FOOD)
this.lastHeal = Cow.ticker.ticks
}
}
update() {
const { player } = Cow
if (!player?.alive || player?.skinIndex === 45) return
if (player.health > this.targetHealth || !nearEnemy) return
const 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 = 0
this.lastHatID = null
this.lastAccID = null
this.autoEmpCD = null
this.attackHatsCD = null
this.autoEmpSoldier = false
this.autoSoldierEmp = false
this.autoEmpHat = false
this.autoBullTick = false
this.autoTankHat = false
this.autoBullTickTimeout = null
Cow.onPacket(packets.ADD_PLAYER, (_, isYou) => {
if (!isYou) return
this.attackHatActive = false
this.autoAttackState = false
this.autoAttackHatTick = 0
})
}
isHasTick(key) {
return Boolean(this.hatTicks.filter((tick) => tick.key == key).length)
}
equipHat(id) {
const { player } = Cow
if (!this.hasHats.includes(id) && id !== 0) {
if (player.points >= Cow.items.hats.searchById(id).price) {
Cow.sendPacket(packets.STORE_EQUIP, 1, id, 0)
return this.hasHats.push(id)
}
}
if (this.hasHats.includes(id) && player.skinIndex !== id) {
Cow.sendPacket(packets.STORE_EQUIP, 0, id, 0)
this.lastHatID = id
}
}
equipAcc(id) {
const { player } = Cow
if (!this.hasAccs.includes(id) && id !== 0) {
if (player.points >= Cow.items.accessories.searchById(id).price) {
Cow.sendPacket(packets.STORE_EQUIP, 1, id, 1)
return this.hasAccs.push(id)
}
}
if (this.hasAccs.includes(id) && player.tailIndex !== id) {
Cow.sendPacket(packets.STORE_EQUIP, 0, id, 1)
this.lastAccID = id
}
}
equipBiomeHat() {
const { player } = Cow
let hatID = 0
if (player.y2 > 6850 && player.y2 < 7550) {
hatID = 31
} else if (player.y2 < 2400) {
hatID = 15
} else {
hatID = 12
}
if (!this.isHasTick("auto-biome")) {
this.hatTicks.push({
key: "auto-biome",
callback: () => {
this.equipHat(hatID)
this.equipAcc(11)
}
})
}
}
unknownTicks(amount) {
while (amount--) {
this.hatTicks.push({
key: "unknown",
callback: () => {}
})
}
}
autoHats() {
const { player } = Cow
const dangerBuildings = calculator.getDangerBuildings(player)
if (nearEnemy && player.health < player.maxHealth) {
const isPolearm = nearEnemy.weaponIndex === 4
const isSword = nearEnemy.weaponIndex === 3
const isKatana = nearEnemy.weaponIndex === 4
if (isPolearm || isSword || isKatana) {
if (nearEnemy.weapons[1] === 10) {
if (this.autoEmpSoldier) return
this.autoEmpSoldier = true
this.hatTicks = []
this.equipHat(22)
setTimeout(() => {
this.equipHat(6)
setTimeout(() => {
this.autoEmpSoldier = false
}, 25)
}, 90)
} else {
if (this.autoSoldierEmp) return
this.autoSoldierEmp = true
this.hatTicks = []
this.equipHat(6)
setTimeout(() => {
this.equipHat(22)
setTimeout(() => {
this.autoEmpSoldier = false
}, 25)
}, 90)
}
return
}
}
/*if (this.autoBullTick) {
this.hatTicks = []
this.equipHat(7)
if (!this.autoBullTickTimeout) {
this.autoBullTickTimeout = setTimeout(() => {
this.autoBullTick = false
this.autoBullTickTimeout = null
}, 111.111)
}
return
}*/
if (this.autoEmpHat && (!this.autoEmpCD || Date.now() - this.autoEmpCD >= 500)) {
this.equipHat(22)
if (!this.isHasTick("uneqip-hats")) {
this.unknownTicks(1)
this.hatTicks.push({
key: "uneqip-hats",
callback: () => {
this.autoEmpHat = false
this.autoEmpCD = null
}
})
}
this.autoEmpCD = Date.now()
} else if (this.autoTankHat) {
this.equipHat(40)
if (!this.isHasTick("uneqip-hats")) {
this.unknownTicks(4)
this.hatTicks.push({
key: "uneqip-hats",
callback: () => {
this.autoTankHat = false
}
})
}
this.attackHatsCD = Date.now()
} else if (dangerBuildings.length || nearEnemy) {
if (dangerBuildings.length) {
this.equipHat(6)
} else if (nearEnemy) {
const weaponIndex = nearEnemy.weaponIndex
const angle = CowUtils.getDirection(nearEnemy, player)
const distance = CowUtils.getDistance(nearEnemy, player) - player.scale
const isMeInAngle = true//getAngleDist(angle, tmpValues.nearEnemy.dir) <= Math.PI / 1.25
const weapon = Cow.items.weapons[weaponIndex]
if (!weapon) return
const isMeInRange = distance <= weapon.range * 3.25
if (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 {
return this.equipBiomeHat()
}
}
} else {
return this.equipBiomeHat()
}
}
update() {
this.autoHats()
const { player } = Cow
const timeSinceHatTick = Cow.ticker.ticks - (this.lastHatTick || 0)
if (timeSinceHatTick >= 0 && this.hatTicks.length) {
const hatTick = this.hatTicks[0]
typeof hatTick?.callback === 'function' && hatTick.callback()
this.hatTicks.shift()
this.lastHatTick = Cow.ticker.ticks
}
}
}
class AutoPlacer {
constructor() {
this.delay = 0
this.lastUpdate = null
}
update() {
const { player } = Cow
if (!player?.alive || !nearEnemy?.visible) return
if (Date.now() - this.lastUpdate < this.delay) return
const trapConfig = Cow.items.list[player.items[items.TRAP]]
const spikeConfig = Cow.items.list[player.items[items.SPIKE]]
if (!trapConfig || !spikeConfig) return
const visibleObjects = Cow.objectsManager.list.filter((gameObject) => gameObject.visible && gameObject.active)
const angle = CowUtils.getDistance(nearEnemy, player)
const placeSpikeDistance = player.scale + spikeConfig.scale * 1.4
const distance = CowUtils.getDistance(player, nearEnemy)
let distanceToPlace = distance
nearEnemy.inTrap = false
for (let i = 0; i < visibleObjects.length; i++) {
const gameObject = visibleObjects[i]
if (!gameObject.isItem || gameObject.id !== 15 || gameObject.owner?.sid === nearEnemy.sid) continue
const scale = gameObject.scale || gameObject.getScale()
const enemyDistanceToTrap = CowUtils.getDistance(nearEnemy, gameObject) - scale + window.config.collisionDepth
const angleTrapToEnemy = CowUtils.getDirection(nearEnemy, gameObject)
if (enemyDistanceToTrap > 0) continue
nearEnemy.inTrap = true
const offset = scale - Math.abs(enemyDistanceToTrap) + nearEnemy.scale / 2 + spikeConfig.scale
const 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.scale
const placeDistance = trapConfig.scale * 1.2 + player.scale
if (!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 = null
this.assistPlaceY = null
this.lastAssistActive = null
this.keys = {
FOOD: "KeyQ",
TRAP: "KeyF",
SPIKE: "KeyV",
MILL: "KeyN",
TURRET: "KeyH"
}
}
resetAssist() {
this.assistPlaceX = null
this.assistPlaceY = null
this.lastAssistActive = Date.now()
}
update() {
const { player } = Cow
if (!player?.alive || isInputFocused()) return
if (Date.now() - this.lastAssistActive >= 500) this.resetAssist()
for (const key in this.keys) {
if (!Cow.input.keyboard.activeKeys.get(this.keys[key])) continue
const placeItemIndex = items[key.replace(/wind/, "").toUpperCase()]
const placeItem = Cow.items.list[player.items[placeItemIndex]]
if (!placeItem) continue
let placeAngle = player.lookAngle
if (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 = placeX
let newPlaceY = placeY
for (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.25
const _x = newPlaceX + offsetScale
const _y = newPlaceY + offsetScale
newPlaceX = _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) break
nearObjects = 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 = newPlaceX
this.assistPlaceY = newPlaceY
this.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 = null
this.isActive = false
Cow.onKeyboard("KeyM", () => {
if (isInputFocused()) return
this.isActive = !this.isActive
if (!this.isActive) this.lastPlace = null
}, {
repeat: false
})
}
get gap() {
const { player } = Cow
return this.gaps[Number(player.items[items.MILL] !== 10)]
}
update() {
const { player } = Cow
if (!player?.alive || !this.isActive) return
if (this.lastPlace) {
const millConfig = Cow.items.list[player.items[items.MILL]]
const distance = CowUtils.getDistance(player, this.lastPlace) - player.scale
const placeDistance = millConfig.scale * 1.6
if (distance < placeDistance) return
}
//Cow.delayedPlaceItem(() => {
Cow.placeItem(items.MILL, {
angle: player.moveDir + this.gap
})
Cow.placeItem(items.MILL, {
angle: player.moveDir
})
Cow.placeItem(items.MILL, {
angle: player.moveDir - this.gap
})
this.lastPlace = {
x: player.x,
y: player.y
}
//})
}
}
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.config
const { context } = Cow.renderer
const width = _width || (healthBarWidth / 2 - healthBarPad / 2)
const height = 17
context._roundRect = _roundRect
context.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 = color
context.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.isAlly
const { healthBarWidth, healthBarPad } = window.config
const width = (healthBarWidth / 2 - healthBarPad / 2)
const addWidth = 0
const color = this.getColor(primaryReload, isAlly)
const offset = -width * 1.19 + addWidth
const radius = 8
const 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.isAlly
const { healthBarWidth, healthBarPad } = window.config
const width = (healthBarWidth / 2 - healthBarPad / 2)
const addWidth = 0
const color = this.getColor(secondaryReload, isAlly)
const offset = width * 1.19 - addWidth
const radius = 8
const 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.isAlly
const { healthBarWidth } = window.config
const color = this.getColor(turretReload, isAlly)
const radius = 8
this.drawBar(turretReload, color, entity, 0, entity.scale + window.config.nameY * 1.75 - 3, healthBarWidth, radius)
}
update() {
const { player } = Cow
if (!player?.alive) return
Cow.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.x
const dy = target.y - other.y
const 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 } = Cow
if (!player?.alive || !target?.visible) return []
const predictor = this.getPredictor(target)
return Cow.objectsManager.list.filter((gameObject) => {
if (!gameObject.visible || !gameObject.isItem || !gameObject.visible) return
const isSpike = [6, 7, 8, 9].includes(gameObject.id)
return isSpike && !Cow.isAllianceMember(gameObject.owner?.sid) && this.findBuildingOnPosition(predictor, gameObject)
})
}
}
class AutoBreak {
constructor() {
this.isBreaking = false
}
stopBreaking() {
if (!this.isBreaking) return
this.isBreaking = false
tailor.autoTankHat = false
aimControl.stopAiming()
}
async update() {
const { player } = Cow
player.inTrap = false
const 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.collisionDepth
player.inTrap = distance <= 0
if (!player.inTrap) return this.stopBreaking()
this.isBreaking = true
tailor.autoTankHat = true
const breakWeapon = player.weapons[1] === 10 ? player.weapons[1] : player.weapons[0]
if (player.weaponIndex !== breakWeapon) Cow.sendPacket(packets.SELECT_BUILD, breakWeapon, true)
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 = null
this.isAiming = false
this._aimAngle = null
this.isSent = false
}
get aimAngle() {
this.updateAimToTarget()
return this._aimAngle
}
set aimAngle(_angle) {
this._aimAngle = _angle
}
onSent() {
this.isSent = true
}
updateAimToTarget() {
if (!this.isAiming) return
const { player } = Cow
const angle = typeof this.aimTarget === 'number' ? this.aimTarget : CowUtils.getDirection(this.aimTarget, player)
this.aimAngle = angle
}
startAiming(point) {
this.aimTarget = point
this.isAiming = true
this.isSent = false
this.updateAimToTarget()
}
stopAiming() {
this.aimTarget = null
this.isAiming = false
this.aimAngle = null
}
}
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 ??= 0
if (this.lastPlaceItem && (this.ticker.ticks - this.lastPlaceItem) < 1) return
callback()
this.lastPlaceItem = this.ticker.ticks
}
Cow.isAllianceMember = function(sid) {
const { player } = Cow
if (player && player.sid == sid) return true
if (!player.team || sid < 0) return false
for (var i = 0; i < Cow.alliancePlayers.length; i += 2) {
if (sid !== Cow.alliancePlayers[i]) continue
return true
}
return false
}
Cow.isCanGather = function(doer, other) {
const distance = CowUtils.getDistance(doer, other) - other.scale
const angle = CowUtils.getDirection(other, doer)
const angleDistance = CowUtils.getAngleDist(angle, doer.dir2)
const isInAngle = angleDistance <= window.config.gatherAngle
const isInRange = distance <= doer.weapon.range
return {
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) continue
Cow.alliances.splice(i, 1)
}
})
Cow.onPacket(packets.SET_ALLIANCE_PLAYERS, (players) => {
Cow.alliancePlayers = players
})
Cow.onPacket(packets.UPDATE_PLAYERS, () => {
const { player } = Cow
if (Cow.ticker.ticks - lastPreplaceClear >= 1) {
preplaceObjects = []
lastPreplaceClear = Cow.ticker.ticks
}
})
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()
Cow.addRender("global", () => {
const { context } = Cow.renderer
const { player } = Cow
nearEnemy = Cow.getNearEnemy()
for (const preplaceObject of preplaceObjects) {
renderPreplace(preplaceObject, context)
}
macro.update()
autoPlacer.update()
tailor.update()
autoHeal.update()
antiInsta.update()
autoMills.update()
reloadBars.update()
antiTrap.update()
})
const oldSend = WebSocket.prototype.send
WebSocket.prototype.send = function(data) {
const binary = new Uint8Array(data)
const decoded = Cow.codec.decoder.decode(binary)
if (decoded[0] === packets.SPAWN) {
decoded[1][0].moofoll = true
decoded[1][0].name = "9-".concat(decoded[1][0].name)
return oldSend.call(this, Cow.codec.encoder.encode(decoded))
}
if (decoded[0] === packets.LOOK_DIR && aimControl.isAiming) {
aimControl.updateAimToTarget()
decoded[1][0] = aimControl.aimAngle
oldSend.call(this, Cow.codec.encoder.encode(decoded))
return aimControl.onSent()
}
oldSend.apply(this, arguments)
}
function isInputFocused() {
return document.activeElement.tagName === "INPUT"
}
function renderPreplace(preplaceObject, context) {
const { player } = Cow
const 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) return
context.save()
context.globalAlpha = .3
context.translate(player.renderX + x, player.renderY + y)
context.rotate(preplaceObject.angle)
context.drawImage(sprite, -(sprite.width / 2), -(sprite.height / 2))
context.restore()
}
const itemSprites = {}
function renderStar(ctxt, spikes, outer, inner) {
const step = Math.PI / spikes
let rot = Math.PI / 2 * 3
let x = 0
let y = 0
ctxt.beginPath()
ctxt.moveTo(0, -outer)
for (let i = 0; i < spikes; i++) {
x = Math.cos(rot) * outer
y = Math.sin(rot) * outer
ctxt.lineTo(x, y)
rot += step
x = Math.cos(rot) * inner
y = Math.sin(rot) * inner
ctxt.lineTo(x, y)
rot += step
}
ctxt.lineTo(0, -outer)
ctxt.closePath()
}
function renderCircle(x, y, scale, tmpContext, dontStroke, dontFill) {
tmpContext = tmpContext || Cow.renderer.context
tmpContext.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.context
const 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 tmpSprite
const tmpCanvas = document.createElement("canvas")
const tmpContext = tmpCanvas.getContext("2d")
const outlineWidth = 5.5
const outlineColor = "#525252"
tmpCanvas.width = tmpCanvas.height = (obj.scale * 2.5) + outlineWidth + (Cow.items.list[obj.id].spritePadding || 0)
tmpContext.strokeStyle = outlineColor
tmpContext.lineWidth = outlineWidth
tmpContext.translate((tmpCanvas.width / 2), (tmpCanvas.height / 2))
tmpContext.rotate(Math.PI / 2)
if (/wall/.test(obj.name)) {
const sides = (obj.name == "castle wall") ? 4 : 3
tmpContext.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 = outlineColor
renderStar(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 = 50
tmpContext.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 * 2
const tmpW = tmpS / tmpCount
let 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 = tmpCanvas
itemSprites[obj.id] = tmpSprite
return tmpSprite
}
function removeButton(buttonId) {
const button = document.querySelector(buttonId)
button.style.visibility = "hidden"
}
const checkButtons = setInterval(() => {
const storeButton = document.getElementById("storeButton")
if (!storeButton?.style) return
createCustomHtmlAndCss()
removeButton("#storeButton")
removeButton("#chatButton")
clearInterval(checkButtons)
})
function createCustomHtmlAndCss() {
const style = document.createElement("style")
style.insertAdjacentHTML("beforeend", `
#gameName::after {
content: "9mm";
display: inline-block;
position: absolute;
font-size: 40px;
transform: rotate(45deg) translate(-10px, 60px) scale(1);
text-shadow: 0 1px 0 #c4c4c4, 0 2px 0 #c4c4c4, 0 3px 0 #c4c4c4;
animation: scale-anim 3s infinite ease-in-out;
}
@keyframes scale-anim {
0% {
transform: rotate(45deg) translate(-10px, 60px) scale(1);
}
50% {
transform: rotate(45deg) translate(-10px, 60px) scale(1.1);
}
100% {
transform: rotate(45deg) translate(-10px, 60px) scale(1);
}
}
`)
document.head.appendChild(style)
}
})()