kitty klient — a MooMoo.io client with adaptive zoom, fast autoheal, gear automation, combat tools, visual markers, position prediction, quick builds, anti-boost spikes, and an in-game controls HUD. Hotkeys: U friend-pick, I enemy-pick, C cleanup, P autoheal, R insta, Q food, F trap/Shift+F boost-break, V spike, Z three windmills behind, H selected deployable; hold Q/F/V/Z/H to spam.
// ==UserScript==
// @name kitty klient
// @version 3.57.1
// @icon https://static.wikia.nocookie.net/belugacinematicuniversefanon/images/6/6a/Beluga.jpg/revision/latest?cb=20231226224904
// @description kitty klient — a MooMoo.io client with adaptive zoom, fast autoheal, gear automation, combat tools, visual markers, position prediction, quick builds, anti-boost spikes, and an in-game controls HUD. Hotkeys: U friend-pick, I enemy-pick, C cleanup, P autoheal, R insta, Q food, F trap/Shift+F boost-break, V spike, Z three windmills behind, H selected deployable; hold Q/F/V/Z/H to spam.
// @match *://moomoo.io/*
// @match *://*.moomoo.io/*
// @grant none
// @run-at document-start
// @namespace thisisirrelevandandidontknowwhygreasyforkneedsthisanyways
// @license MIT
// ==/UserScript==
(() => {
"use strict";
const MIN_VIEW_MULTIPLIER = 0.5;
const MAX_VIEW_MULTIPLIER = 1 / 0.15;
const ZOOM_STEP = 1.1;
const TRACKPAD_PIXELS_PER_ZOOM_STEP = 360;
const INDICATOR_ID = "moomoo-scroll-zoom-indicator";
const HUD_ID = "moomoo-op-hud";
const HUD_STORAGE_KEY = "moomoo-op-hud-settings-v1";
const KILL_MESSAGE_AUTO_MIGRATION_KEY = "kitty-klient-kill-message-auto-v1";
const TAB_SYNC_BRIDGE_KEY = "kitty-klient-tab-sync-bridge-v1";
const KITTY_KLIENT_VERSION = "3.57.1";
const KITTY_UPDATE_POPUP_ID = "kitty-klient-update-popup";
const KITTY_UPDATE_DISMISS_KEY = "kitty-klient-dismissed-update-v1";
const KITTY_UPDATE_API = "https://api.greasyfork.org/en/scripts/592072.json";
const KITTY_UPDATE_FALLBACK_URL = "https://update.greasyfork.org/scripts/592072/kitty%20klient.user.js";
const HUD_DEFAULTS = Object.freeze({
autoHeal: true,
soldierAuto: true,
movementGear: true,
passiveSpikeAvoidance: true,
trapEscape: true,
antiBoost: true,
antiBoostInsta: true,
threatTrap: true,
autoCloseSpike: true,
reloadSpike: true,
shieldDefense: true,
musketRecharge: true,
autoPurchase: false,
matThief: false,
mobSteal: false,
spinningWindmills: false,
esp: true,
espLines: true,
predictionGhost: true,
cooldownBars: true,
bullHelmet: true,
tankRightClick: true,
allItemsUnlock: true,
instaKill: false,
autoInsta: true,
autoSpikeInsta: true,
autoSpikeSpam: true,
antiInsta: true,
instaSync: true,
boostBreak: true,
boostChat: true,
materialReply: true,
syncLeader: false,
syncFollower: false,
soldierRange: 400,
combatRange: 400,
gearHoldTicks: 3,
passiveSpikeEnemyRange: 400,
antiBoostRange: 200,
reactionMs: 25,
debugPanel: false,
killMessageEnabled: true,
killMessage: "gg",
friendNames: []
});
const HUD_BOOLEAN_KEYS = Object.freeze([
"autoHeal",
"soldierAuto",
"movementGear",
"passiveSpikeAvoidance",
"trapEscape",
"antiBoost",
"antiBoostInsta",
"threatTrap",
"autoCloseSpike",
"reloadSpike",
"shieldDefense",
"musketRecharge",
"autoPurchase",
"matThief",
"mobSteal",
"spinningWindmills",
"esp",
"espLines",
"predictionGhost",
"cooldownBars",
"bullHelmet",
"tankRightClick",
"allItemsUnlock",
"instaKill",
"autoInsta",
"autoSpikeInsta",
"autoSpikeSpam",
"antiInsta",
"instaSync",
"boostBreak",
"boostChat",
"materialReply",
"syncLeader",
"syncFollower",
"debugPanel",
"killMessageEnabled"
]);
const HUD_NUMERIC_BOUNDS = Object.freeze({
soldierRange: Object.freeze({ min: 100, max: 1000, step: 10 }),
combatRange: Object.freeze({ min: 100, max: 1000, step: 10 }),
gearHoldTicks: Object.freeze({ min: 1, max: 8, step: 1 }),
passiveSpikeEnemyRange: Object.freeze({ min: 0, max: 1200, step: 25 }),
antiBoostRange: Object.freeze({ min: 80, max: 500, step: 10 }),
reactionMs: Object.freeze({ min: 10, max: 100, step: 5 })
});
const GAME_BUNDLE = /\/assets\/index-[\w-]+\.js(?:\?.*)?$/;
const VIEWPORT_MARKER = "const _=y.maxScreenWidth,L=y.maxScreenHeight;";
const HOTKEY_MARKER = "t==69?wl():t==67?tl():t==88?gl():";
const FOOD_HOTKEY_MARKER = "t==81?je(v.items[0]):";
const FOOD_KEYUP_MARKER = "function pl(e){if(v&&v.alive){const t=e.which||e.keyCode||0;";
const MOVEMENT_KEYDOWN_MARKER = "bt[t]?Tt():t==32&&(U=1,ke())";
const MOVEMENT_KEYUP_MARKER = "bt[t]?Tt():t==32&&(U=0,ke())";
const BACKDROP_GRID_MARKER = "k.globalAlpha=.06,k.beginPath();for(var i=-oe;i<_;i+=L/18)i>0&&(k.moveTo(i,0),k.lineTo(i,L));for(let c=-ae;c<L;c+=L/18)i>0&&(k.moveTo(0,c),k.lineTo(_,c));k.stroke(),k.globalAlpha=1,";
// The HUD kill-message hook wraps this local game function. Validate it before
// injecting so a renamed game bundle falls back cleanly instead of half-loading.
const PLAYER_STAT_UPDATE_MARKER = "function Kl(";
const CHAT_DISPLAY_MARKER = "function dl(";
// __mmInsta depends on both functions below to bind a target by SID and
// to coexist with the game's normal attack dispatch. Missing either means
// the complete patched bundle is abandoned in favor of the original.
const INSTA_PLAYER_LOOKUP_MARKER = "function Rt(";
const INSTA_PLAYER_ATTACK_MARKER = "function Pl(";
const BUNDLE_RETRY_LIMIT = 8;
const BUNDLE_RETRY_DELAY_MS = 250;
const PATCHED_MODULE_RETRY_LIMIT = 3;
let viewMultiplier = 1 / 0.75;
let hideIndicatorTimer = 0;
let gameScriptHijacked = false;
let originalBundleLoaded = false;
let restoreBundleInsertionGuards = () => {};
let hudMounted = false;
let hudSettingsSent = false;
let hudState = { ...HUD_DEFAULTS };
let hudOpen = false;
const hudControls = new Map();
window.__MooMooScrollZoomMultiplier = viewMultiplier;
// Arm the game-bundle interception before theme installation, HUD work, or
// any optional network request. This userscript is intentionally large;
// waiting until its final lines left a first-navigation race where the
// outer UI loaded but MooMoo's original module escaped unpatched.
installSynchronousBundleGuards();
const gameBundleObserver = new MutationObserver((records) => {
for (const record of records) {
for (const node of record.addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE && node.tagName === "SCRIPT") {
interceptGameBundle(node);
} else if (node.nodeType === Node.ELEMENT_NODE && node.querySelectorAll) {
node.querySelectorAll("script[src]").forEach(interceptGameBundle);
}
}
}
});
gameBundleObserver.observe(document, { childList: true, subtree: true });
document.querySelectorAll("script[src]").forEach(interceptGameBundle);
// Firefox exposes a cancellable last-chance event for parser-inserted
// scripts. Chromium simply ignores this listener and uses the synchronous
// DOM guards plus the observer above.
document.addEventListener("beforescriptexecute", (event) => {
const script = event.target;
if (script instanceof HTMLScriptElement && interceptGameBundle(script)) {
event.preventDefault();
event.stopImmediatePropagation();
}
}, true);
document.addEventListener("readystatechange", () => {
if (!gameScriptHijacked && document.readyState === "interactive") {
document.querySelectorAll("script[src]").forEach(interceptGameBundle);
}
}, { once: true });
window.addEventListener("load", () => {
// If the page never produced the MooMoo module, stop wrapping DOM APIs.
// Normal successful interception restores them immediately in claimGameBundle.
if (!gameScriptHijacked) restoreBundleInsertionGuards();
}, { once: true });
function installCanvasTextTheme() {
const prototype = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
if (!prototype || prototype.__kittyKlientTextTheme) return;
Object.defineProperty(prototype, "__kittyKlientTextTheme", { value: true });
["fillText", "strokeText"].forEach((method) => {
const original = prototype[method];
if (typeof original !== "function") return;
prototype[method] = function (...args) {
const previousShadowColor = this.shadowColor;
const previousShadowBlur = this.shadowBlur;
const previousFillStyle = this.fillStyle;
try {
this.shadowColor = "#8b5cf6";
this.shadowBlur = Math.max(8, Number(this.shadowBlur) || 0);
if (method === "fillText") {
const current = String(previousFillStyle || "").replace(/\s+/g, "").toLowerCase();
const dark = current === "#000" || current === "#000000" || current === "black" ||
/^rgba?\((?:0,){2}0(?:,|\))/.test(current);
this.fillStyle = dark ? "#050505" : "#ffffff";
}
return original.apply(this, args);
} finally {
this.shadowColor = previousShadowColor;
this.shadowBlur = previousShadowBlur;
this.fillStyle = previousFillStyle;
}
};
});
}
function applyKittyNameTrademark() {
const input = document.getElementById("nameInput");
if (!input) return;
const storedOriginal = Number(input.dataset.kittyOriginalNameMax);
const originalMax = Number.isFinite(storedOriginal) && storedOriginal > 2
? storedOriginal
: Math.max(3, Number(input.maxLength) || 15);
const nameLimit = Math.max(1, originalMax - 2);
input.dataset.kittyOriginalNameMax = String(originalMax);
input.dataset.kittyNameLimit = String(nameLimit);
input.maxLength = nameLimit;
input.setAttribute("maxlength", String(nameLimit));
input.placeholder = "Enter Name (k- added)";
const normalize = () => {
const normalized = String(input.value || "")
.replace(/^(?:k-)+/i, "")
.slice(0, nameLimit);
if (input.value !== normalized) input.value = normalized;
};
normalize();
if (!input.dataset.kittyNameTrademarkBound) {
input.dataset.kittyNameTrademarkBound = "1";
input.addEventListener("input", normalize);
input.addEventListener("change", normalize);
input.addEventListener("focus", normalize);
}
}
function applyKittyBrand() {
applyKittyNameTrademark();
if (document.title !== "kitty klient") document.title = "kitty klient";
const menu = document.getElementById("mainMenu") || document.body;
if (!menu) return;
const candidates = menu.querySelectorAll("#gameName,.gameName,h1,h2,[class*='title'],[id*='title']");
candidates.forEach((element) => {
const text = (element.textContent || "").trim();
if (text.length <= 32 && /moo\s*moo(?:\.io)?/i.test(text)) {
element.textContent = "kitty klient";
element.dataset.kittyBrand = "";
}
});
}
function installKittyTheme() {
if (!document.documentElement || document.getElementById("kitty-klient-theme")) return;
const style = document.createElement("style");
style.id = "kitty-klient-theme";
style.textContent = [
":root{--kitty-purple:#a855f7;--kitty-purple-deep:#6d28d9;--kitty-black:#08050d}",
"body,button,input,select,textarea,label,#gameUI,#mainMenu,#menuCardHolder,.menuCard,.menuButton,.settingRadio,.leaderboardItem,.leaderScore,.notificationText,.allianceItem,.storeItem,#itemInfoHolder,#loadingText,#diedText{color:#fff!important;text-shadow:0 0 4px #8b5cf6,0 0 11px rgba(168,85,247,.9)!important}",
".menuCard,#guideCard,#serverBrowser,#storeHolder,#allianceHolder,#allianceManager,#chatBox{background-color:rgba(5,3,9,.82)!important;border-color:rgba(168,85,247,.7)!important;box-shadow:0 0 18px rgba(139,92,246,.4)!important}",
"#mainMenu{background:rgba(5,3,9,.5)!important;border:0!important;box-shadow:none!important}#menuCardHolder,#storeMenu,#allianceMenu,#chatHolder{background:transparent!important;border:0!important;box-shadow:none!important;backdrop-filter:none!important}",
"#menuContainer{width:min(1100px,calc(100vw - 28px))!important;left:50%!important;transform:translate(-50%,-50%)!important}#storeHolder{width:min(400px,calc(100vw - 40px))!important;box-sizing:border-box!important}#storeMenu>div:first-child{width:min(400px,calc(100vw - 40px));margin-inline:auto}#storeMenu .storeTab{width:calc(50% - 7px)!important;box-sizing:border-box!important}#allianceHolder,#allianceManager{width:min(370px,calc(100vw - 40px))!important;box-sizing:border-box!important;margin-inline:auto!important}#chatBox{width:min(420px,calc(100vw - 40px))!important;box-sizing:border-box!important}",
"#mainMenu button,#mainMenu input,#mainMenu select,#enterGame,.menuButton,.allianceButtonM,.joinAlBtn{background:rgba(8,5,13,.82)!important;border:1px solid rgba(168,85,247,.72)!important;color:#fff!important;box-shadow:0 0 10px rgba(139,92,246,.28)!important}",
"#mainMenu button:hover,#enterGame:hover,.menuButton:hover,.allianceButtonM:hover,.joinAlBtn:hover{border-color:#c084fc!important;box-shadow:0 0 16px rgba(168,85,247,.72)!important}",
"[data-kitty-brand],#gameName.kitty-klient-brand{font-family:'Segoe Print','Bradley Hand','Brush Script MT',cursive!important;font-style:italic!important;font-weight:900!important;letter-spacing:.045em!important;text-transform:lowercase!important;color:#07030b!important;-webkit-text-stroke:1px #17101f;text-shadow:-2px 1px 0 #a855f7,2px -1px 0 #6d28d9,0 0 8px #c084fc,0 0 22px #7c3aed!important;transform:skewX(-9deg) rotate(-1deg)!important}",
"#kitty-klient-metrics{position:fixed;z-index:2147483645;right:14px;top:62%;transform:translateY(-50%);display:grid;gap:5px;padding:9px 10px;border:1px solid rgba(168,85,247,.68);border-radius:10px;background:rgba(5,3,9,.68);box-shadow:0 0 18px rgba(139,92,246,.38);backdrop-filter:blur(7px);pointer-events:none;color:#fff;font:800 11px/1.15 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 7px #8b5cf6}",
"#kitty-klient-metrics span{display:flex;justify-content:space-between;gap:10px;min-width:92px}#kitty-klient-metrics b{color:#c084fc;font-weight:900}",
"#kitty-klient-update-popup{position:fixed;z-index:2147483647;top:18px;right:18px;width:min(330px,calc(100vw - 36px));box-sizing:border-box;padding:17px 17px 16px;border:1px solid rgba(192,132,252,.82);border-radius:14px;background:linear-gradient(145deg,rgba(8,5,13,.94),rgba(30,12,48,.88));box-shadow:0 0 28px rgba(139,92,246,.5),inset 0 0 22px rgba(168,85,247,.08);backdrop-filter:blur(12px);color:#fff;font:600 13px/1.45 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;text-shadow:0 0 7px rgba(168,85,247,.8);animation:kitty-update-enter .22s ease-out both}",
"#kitty-klient-update-popup .kitty-update-title{margin:0 30px 5px 0;color:#fff;font-size:18px;font-weight:900;letter-spacing:.01em}#kitty-klient-update-popup .kitty-update-copy{margin:0 0 12px;color:#eee}#kitty-klient-update-popup .kitty-update-versions{display:flex;align-items:center;gap:7px;margin:0 0 14px;color:#d8b4fe;font:800 11px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 8px #7c3aed}",
"#kitty-klient-update-popup .kitty-update-download{display:flex;align-items:center;justify-content:center;min-height:38px;padding:0 14px;border:1px solid #c084fc;border-radius:9px;background:linear-gradient(135deg,#7c3aed,#a855f7);color:#fff!important;font-size:13px;font-weight:900;text-decoration:none;box-shadow:0 0 15px rgba(168,85,247,.46);text-shadow:0 0 7px #4c1d95!important;transition:transform .12s ease,filter .12s ease}#kitty-klient-update-popup .kitty-update-download:hover{filter:brightness(1.13);transform:translateY(-1px)}",
"#kitty-klient-update-popup .kitty-update-close{position:absolute;top:8px;right:9px;width:30px;height:30px;padding:0;border:0;border-radius:8px;background:transparent;color:#e9d5ff!important;font:900 23px/28px Arial,sans-serif;cursor:pointer;text-shadow:0 0 9px #a855f7!important}#kitty-klient-update-popup .kitty-update-close:hover{background:rgba(168,85,247,.2);color:#fff!important}@keyframes kitty-update-enter{from{opacity:0;transform:translateY(-9px) scale(.98)}to{opacity:1;transform:none}}",
"@media(max-width:700px){#kitty-klient-metrics{right:8px;top:60%;font-size:9px;padding:7px}#menuContainer{width:calc(100vw - 16px)!important;white-space:normal!important}}"
].join("");
(document.head || document.documentElement).appendChild(style);
applyKittyBrand();
const observer = new MutationObserver(applyKittyBrand);
observer.observe(document.documentElement, { childList: true, subtree: true });
}
function mountMetrics() {
if (!document.body || document.getElementById("kitty-klient-metrics")) return;
const metrics = document.createElement("div");
metrics.id = "kitty-klient-metrics";
metrics.setAttribute("aria-label", "kitty klient performance");
metrics.innerHTML = "<span>PING <b data-metric='ping'>--</b></span>" +
"<span>FPS <b data-metric='fps'>--</b></span>" +
"<span>PACKETS <b data-metric='packets'>0</b></span>";
document.body.appendChild(metrics);
}
installCanvasTextTheme();
// Firefox can place a patched blob module in a messaging context that is
// separate from the userscript's normal page context. Bridge tab-sync
// traffic through the page-level storage event as a reliable fallback.
window.addEventListener("MooMooTabSyncOutbound", (event) => {
const payload = typeof event.detail === "string" ? event.detail : "";
if (!payload || payload.length > 1200) return;
try {
localStorage.setItem(TAB_SYNC_BRIDGE_KEY, payload);
} catch {
// BroadcastChannel remains available when storage is blocked.
}
});
window.addEventListener("storage", (event) => {
if (!event || event.key !== TAB_SYNC_BRIDGE_KEY || !event.newValue) return;
window.dispatchEvent(new CustomEvent("MooMooTabSyncInbound", { detail: event.newValue }));
});
function showZoomIndicator(message) {
if (!document.body) return;
let indicator = document.getElementById(INDICATOR_ID);
if (!indicator) {
indicator = document.createElement("div");
indicator.id = INDICATOR_ID;
indicator.style.cssText = [
"position:fixed",
"top:16px",
"left:50%",
"z-index:2147483647",
"transform:translateX(-50%)",
"padding:6px 10px",
"border-radius:6px",
"background:rgba(0,0,0,.65)",
"color:#fff",
"font:700 14px Arial,sans-serif",
"pointer-events:none",
"transition:opacity .2s"
].join(";");
document.body.appendChild(indicator);
}
// A larger viewport multiplier means more of the map is visible.
indicator.textContent = message || `Zoom: ${Math.round((1 / viewMultiplier) * 100)}%`;
indicator.style.opacity = "1";
clearTimeout(hideIndicatorTimer);
hideIndicatorTimer = window.setTimeout(() => {
indicator.style.opacity = "0";
}, 900);
}
function applyViewportSize() {
window.__MooMooScrollZoomMultiplier = viewMultiplier;
if (typeof window.__MooMooScrollZoomSetViewport === "function") {
window.__MooMooScrollZoomSetViewport(viewMultiplier);
}
}
function isGameSurface(target) {
return target instanceof Element && Boolean(target.closest("#gameCanvas, #touch-controls-fullscreen"));
}
function isLikelyTrackpadScroll(event) {
// Physical mouse wheels normally report line-mode or a large pixel delta.
// Trackpads emit frequent, small pixel-mode deltas.
return event.deltaMode === WheelEvent.DOM_DELTA_PIXEL && Math.abs(event.deltaY) < 50;
}
document.addEventListener("wheel", (event) => {
if (!isGameSurface(event.target) || event.ctrlKey || event.deltaY === 0) return;
event.preventDefault();
event.stopImmediatePropagation();
const zoomStep = isLikelyTrackpadScroll(event)
? Math.pow(ZOOM_STEP, Math.abs(event.deltaY) / TRACKPAD_PIXELS_PER_ZOOM_STEP)
: ZOOM_STEP;
viewMultiplier = Math.min(
MAX_VIEW_MULTIPLIER,
Math.max(MIN_VIEW_MULTIPLIER, viewMultiplier * (event.deltaY > 0 ? zoomStep : 1 / zoomStep))
);
applyViewportSize();
showZoomIndicator();
}, { capture: true, passive: false });
window.addEventListener("MooMooScrollZoomAutoheal", (event) => {
showZoomIndicator(`Autoheal: ${event.detail ? "On" : "Off"}`);
});
window.addEventListener("MooMooScrollZoomMonkeyTail", (event) => {
showZoomIndicator(event.detail);
});
window.addEventListener("MooMooScrollZoomShiftSpeed", (event) => {
showZoomIndicator(event.detail);
});
window.addEventListener("MooMooScrollZoomStatus", (event) => {
showZoomIndicator(event.detail);
});
function clampHudNumber(key, value) {
const bounds = HUD_NUMERIC_BOUNDS[key];
if (!bounds || !Number.isFinite(value)) return HUD_DEFAULTS[key];
return Math.min(bounds.max, Math.max(bounds.min, value));
}
function normalizeHudSettings(candidate) {
const settings = { ...HUD_DEFAULTS };
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) return settings;
HUD_BOOLEAN_KEYS.forEach((key) => {
if (typeof candidate[key] === "boolean") settings[key] = candidate[key];
});
Object.keys(HUD_NUMERIC_BOUNDS).forEach((key) => {
if (Number.isFinite(candidate[key])) settings[key] = clampHudNumber(key, candidate[key]);
});
if (typeof candidate.killMessage === "string") {
settings.killMessage = candidate.killMessage.slice(0, 30);
}
if (Array.isArray(candidate.friendNames)) {
const seen = new Set();
settings.friendNames = candidate.friendNames.reduce((names, value) => {
const name = typeof value === "string" ? value.trim().slice(0, 15) : "";
const key = name.toLowerCase();
if (name && !seen.has(key) && names.length < 30) {
seen.add(key);
names.push(name);
}
return names;
}, []);
}
return settings;
}
function readHudSettings() {
try {
const settings = normalizeHudSettings(JSON.parse(localStorage.getItem(HUD_STORAGE_KEY) || "{}"));
// Apply the requested auto death-message default once without
// discarding the rest of the player's saved HUD configuration.
if (localStorage.getItem(KILL_MESSAGE_AUTO_MIGRATION_KEY) !== "1") {
settings.killMessageEnabled = true;
if (!settings.killMessage.trim()) settings.killMessage = HUD_DEFAULTS.killMessage;
localStorage.setItem(KILL_MESSAGE_AUTO_MIGRATION_KEY, "1");
}
return settings;
} catch {
return { ...HUD_DEFAULTS };
}
}
function saveHudSettings() {
try {
// A tab role is intentionally per-tab. Persisting it would make a
// freshly opened tab unexpectedly become another leader/follower.
const settings = normalizeHudSettings(hudState);
settings.syncLeader = false;
settings.syncFollower = false;
localStorage.setItem(HUD_STORAGE_KEY, JSON.stringify(settings));
} catch {
// Saved settings are optional; the mod still works when storage is unavailable.
}
}
function sendHudCommand(detail) {
window.dispatchEvent(new CustomEvent("MooMooOPHudCommand", { detail }));
}
function setHudControlValue(key, value) {
const control = hudControls.get(key);
if (!control) return;
if (control.type === "checkbox") control.checked = Boolean(value);
else control.value = value == null ? "" : String(value);
}
function renderHud() {
Object.entries(hudState).forEach(([key, value]) => setHudControlValue(key, value));
const friendList = document.querySelector("#" + HUD_ID + " [data-hud-friends]");
if (friendList) {
friendList.textContent = "";
const names = Array.isArray(hudState.friendNames) ? hudState.friendNames : [];
if (!names.length) {
const empty = document.createElement("small");
empty.textContent = "No friends yet — every non-teammate starts as an enemy.";
friendList.appendChild(empty);
} else {
names.forEach((name) => {
const chip = document.createElement("span");
chip.className = "mm-hud-friend-chip";
chip.textContent = name;
friendList.appendChild(chip);
});
}
}
const status = document.querySelector("#" + HUD_ID + " [data-hud-status]");
if (!status) return;
const enabled = [
hudState.autoHeal && "heal",
hudState.soldierAuto && "soldier",
hudState.movementGear && "speed",
hudState.matThief && "mat thief",
hudState.mobSteal && "mob steal",
hudState.antiBoost && "spikes",
hudState.antiBoostInsta && "boost insta",
hudState.syncLeader && "sync leader",
hudState.syncFollower && "sync follower"
].filter(Boolean);
status.textContent = enabled.length ? "Active: " + enabled.join(" · ") : "Automation paused";
const debug = document.querySelector("#" + HUD_ID + " [data-hud-debug]");
if (debug) {
debug.hidden = !hudState.debugPanel;
debug.textContent = hudState.debugPanel
? (typeof hudState.debugText === "string" && hudState.debugText) || "Waiting for live game state…"
: "";
}
}
function addHudToggle(container, key, label, subtitle) {
const row = document.createElement("label");
row.className = "mm-hud-row";
const text = document.createElement("span");
const title = document.createElement("strong");
title.textContent = label;
const hint = document.createElement("small");
hint.textContent = subtitle;
text.append(title, hint);
const input = document.createElement("input");
input.type = "checkbox";
input.checked = Boolean(hudState[key]);
input.addEventListener("change", () => {
hudState[key] = input.checked;
saveHudSettings();
sendHudCommand({ type: "set", key, value: input.checked });
renderHud();
});
row.append(text, input);
container.appendChild(row);
hudControls.set(key, input);
}
function addHudNumber(container, key, label, subtitle) {
const bounds = HUD_NUMERIC_BOUNDS[key];
const row = document.createElement("label");
row.className = "mm-hud-number";
const text = document.createElement("span");
const title = document.createElement("strong");
title.textContent = label;
const hint = document.createElement("small");
hint.textContent = subtitle;
text.append(title, hint);
const input = document.createElement("input");
input.type = "number";
input.min = String(bounds.min);
input.max = String(bounds.max);
input.step = String(bounds.step);
input.value = String(hudState[key]);
input.addEventListener("change", () => {
const value = clampHudNumber(key, Number(input.value));
hudState[key] = value;
saveHudSettings();
sendHudCommand({ type: "set", key, value });
renderHud();
});
row.append(text, input);
container.appendChild(row);
hudControls.set(key, input);
}
function addHudSection(panel, heading) {
const section = document.createElement("section");
section.className = "mm-hud-section";
const title = document.createElement("h3");
title.textContent = heading;
section.appendChild(title);
panel.appendChild(section);
return section;
}
function mountHud() {
if (hudMounted || !document.body) return;
if (document.getElementById(HUD_ID)) {
hudMounted = true;
return;
}
hudMounted = true;
hudState = { ...hudState, ...readHudSettings() };
const style = document.createElement("style");
style.id = HUD_ID + "-style";
style.textContent = [
"#moomoo-op-hud{--mm-bg:rgba(5,3,9,.78);--mm-surface:rgba(20,12,30,.72);--mm-line:rgba(168,85,247,.4);--mm-text:#fff;--mm-muted:#d8b4fe;--mm-accent:#a855f7;position:fixed;z-index:2147483646;inset:0;display:grid;place-items:center;padding:28px;font:13px/1.3 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:var(--mm-text);pointer-events:none;background:rgba(0,0,0,.08);backdrop-filter:blur(2px)}",
"#moomoo-op-hud.mm-hud-collapsed{display:none}#moomoo-op-hud *,#moomoo-op-hud *:before,#moomoo-op-hud *:after{box-sizing:border-box}#moomoo-op-hud button,#moomoo-op-hud input{font:inherit}",
"#moomoo-op-hud .mm-hud-panel{pointer-events:auto;width:min(1040px,calc(100vw - 56px));height:min(720px,calc(100vh - 56px));display:grid;grid-template-rows:auto auto minmax(0,1fr);overflow:hidden;border:1px solid rgba(192,132,252,.7);border-radius:18px;background:var(--mm-bg);box-shadow:0 0 24px rgba(139,92,246,.38),0 22px 70px rgba(0,0,0,.7);backdrop-filter:blur(16px)}",
"#moomoo-op-hud .mm-hud-head{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:18px 20px 12px;border-bottom:1px solid var(--mm-line)}#moomoo-op-hud .mm-hud-brand{margin:0;font-family:'Segoe Print','Bradley Hand','Brush Script MT',cursive;font-style:italic;font-size:29px;line-height:1;color:#050208!important;-webkit-text-stroke:1px #17101f;text-shadow:-2px 1px 0 #a855f7,2px -1px 0 #6d28d9,0 0 13px #c084fc!important;transform:skewX(-8deg)}",
"#moomoo-op-hud .mm-hud-status{margin:0;color:#fff;font-size:11px;font-weight:800;text-align:right;text-shadow:0 0 8px #8b5cf6}#moomoo-op-hud .mm-hud-escape{color:var(--mm-muted);font-size:10px;white-space:nowrap}",
"#moomoo-op-hud .mm-hud-nav{display:flex;gap:6px;padding:10px 14px;border-bottom:1px solid var(--mm-line);overflow-x:auto}#moomoo-op-hud .mm-hud-nav button{border:1px solid transparent;border-radius:9px;background:transparent;color:#fff;padding:8px 13px;cursor:pointer;font-weight:800;text-shadow:0 0 7px #8b5cf6}#moomoo-op-hud .mm-hud-nav button:hover,#moomoo-op-hud .mm-hud-nav button.mm-active{border-color:#a855f7;background:rgba(109,40,217,.28);box-shadow:0 0 12px rgba(168,85,247,.35)}",
"#moomoo-op-hud .mm-hud-pages{min-height:0;overflow:auto;padding:14px}#moomoo-op-hud .mm-hud-page{display:none;grid-template-columns:repeat(2,minmax(0,1fr));align-content:start;gap:12px}#moomoo-op-hud .mm-hud-page.mm-active{display:grid}",
"#moomoo-op-hud .mm-hud-section{padding:13px 14px;border:1px solid var(--mm-line);border-radius:12px;background:var(--mm-surface);box-shadow:inset 0 0 18px rgba(109,40,217,.08)}#moomoo-op-hud h3{margin:0 0 8px;font-size:11px;text-transform:uppercase;letter-spacing:.11em;color:#d8b4fe;text-shadow:0 0 7px #7c3aed}",
"#moomoo-op-hud .mm-hud-row,#moomoo-op-hud .mm-hud-number{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:6px 0;cursor:pointer}#moomoo-op-hud .mm-hud-row span,#moomoo-op-hud .mm-hud-number span{display:grid;gap:2px}#moomoo-op-hud strong{font-size:13px;color:#fff;text-shadow:0 0 6px #7c3aed}#moomoo-op-hud small{color:var(--mm-muted);font-size:10px}",
"#moomoo-op-hud input[type='checkbox']{appearance:none;width:36px;height:20px;margin:0;border:1px solid var(--mm-line);border-radius:999px;background:#21172b;position:relative;flex:0 0 auto;cursor:pointer}#moomoo-op-hud input[type='checkbox']:after{content:'';position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#fff;box-shadow:0 0 7px #c084fc;transition:transform .14s ease}#moomoo-op-hud input[type='checkbox']:checked{background:#7c3aed;border-color:#c084fc;box-shadow:0 0 10px rgba(168,85,247,.65)}#moomoo-op-hud input[type='checkbox']:checked:after{transform:translateX(16px)}",
"#moomoo-op-hud input[type='number']{width:68px;border:1px solid var(--mm-line);border-radius:7px;background:#09050e;color:#fff;padding:6px;text-align:right}#moomoo-op-hud .mm-hud-message{width:100%;border:1px solid var(--mm-line);border-radius:8px;background:#09050e;color:#fff;padding:8px;margin:3px 0 7px}",
"#moomoo-op-hud .mm-hud-reset{border:1px solid var(--mm-line);border-radius:8px;background:#0b0711;color:#fff;padding:8px;cursor:pointer}#moomoo-op-hud .mm-hud-reset:hover{border-color:var(--mm-accent);box-shadow:0 0 11px rgba(168,85,247,.45)}#moomoo-op-hud .mm-hud-keys{margin:0;padding-left:16px;color:var(--mm-muted);font-size:11px;display:grid;gap:4px}",
"#moomoo-op-hud .mm-hud-friend-actions{display:grid;grid-template-columns:1fr auto auto;gap:6px;align-items:center}#moomoo-op-hud .mm-hud-friend-actions .mm-hud-message{margin:3px 0 7px}#moomoo-op-hud .mm-hud-friend-list{display:flex;flex-wrap:wrap;gap:6px;min-height:24px;align-items:center}#moomoo-op-hud .mm-hud-friend-chip{border:1px solid rgba(250,204,21,.68);border-radius:999px;background:rgba(250,204,21,.12);color:#fff;padding:4px 8px;box-shadow:0 0 8px rgba(250,204,21,.28);text-shadow:0 0 6px #eab308}",
"#moomoo-op-hud .mm-hud-debug{margin:4px 0 7px;white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid var(--mm-line);border-radius:8px;background:rgba(0,0,0,.45);color:#fff;padding:8px;font:10px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 6px #7c3aed}",
"@media(max-width:720px){#moomoo-op-hud{padding:10px}#moomoo-op-hud .mm-hud-panel{width:calc(100vw - 20px);height:calc(100vh - 20px)}#moomoo-op-hud .mm-hud-page{grid-template-columns:1fr}#moomoo-op-hud .mm-hud-head{padding:14px}#moomoo-op-hud .mm-hud-brand{font-size:23px}}"
].join("");
(document.head || document.documentElement).appendChild(style);
const root = document.createElement("aside");
root.id = HUD_ID;
root.className = "mm-hud-collapsed";
root.setAttribute("aria-label", "kitty klient controls");
const panel = document.createElement("div");
panel.className = "mm-hud-panel";
panel.addEventListener("mousedown", (event) => event.stopPropagation());
panel.addEventListener("click", (event) => event.stopPropagation());
const head = document.createElement("header");
head.className = "mm-hud-head";
const brand = document.createElement("h2");
brand.className = "mm-hud-brand";
brand.textContent = "kitty klient";
const headInfo = document.createElement("div");
const status = document.createElement("p");
status.className = "mm-hud-status";
status.dataset.hudStatus = "";
const escapeHint = document.createElement("span");
escapeHint.className = "mm-hud-escape";
escapeHint.textContent = "ESC toggles · WASDFVR returns straight to the game";
headInfo.append(status, escapeHint);
head.append(brand, headInfo);
const nav = document.createElement("nav");
nav.className = "mm-hud-nav";
const pages = document.createElement("div");
pages.className = "mm-hud-pages";
const pageMap = new Map();
const activatePage = (name) => {
nav.querySelectorAll("button").forEach((button) => button.classList.toggle("mm-active", button.dataset.page === name));
pages.querySelectorAll(".mm-hud-page").forEach((page) => page.classList.toggle("mm-active", page.dataset.page === name));
};
const addPage = (name, label) => {
const button = document.createElement("button");
button.type = "button";
button.dataset.page = name;
button.textContent = label;
button.addEventListener("click", () => activatePage(name));
nav.appendChild(button);
const page = document.createElement("div");
page.className = "mm-hud-page";
page.dataset.page = name;
pages.appendChild(page);
pageMap.set(name, page);
return page;
};
const automationPage = addPage("automation", "Automation");
const combatPage = addPage("combat", "Combat");
const visualsPage = addPage("visuals", "Visuals");
const syncPage = addPage("sync", "Sync");
const configPage = addPage("config", "Config");
panel.append(head, nav, pages);
const automation = addHudSection(automationPage, "Automation");
addHudToggle(automation, "autoHeal", "Autoheal", "Immediate first food, then tick-paced recovery");
addHudToggle(automation, "soldierAuto", "Soldier helmet", "Idle protection and combat range");
addHudToggle(automation, "movementGear", "Movement gear", "Speed gear while moving, EMP Helmet while idle and safe, plus adaptive tails");
addHudToggle(automation, "passiveSpikeAvoidance", "Passive spike avoidance", "After movement release, counter residual velocity that would carry you into a damaging spike");
addHudToggle(automation, "trapEscape", "Trap escape", "Build behind you while continuously breaking the locking trap");
addHudToggle(automation, "antiBoost", "Auto boost block", "Two-spike wall, short retreat, and temporary shield against rushers");
addHudToggle(automation, "antiBoostInsta", "Anti-boost insta", "Full-insta an enemy boost-rushing into range");
addHudToggle(automation, "threatTrap", "Auto close trap", "Place a pit trap between you and nearby enemies or hostile animals");
addHudToggle(automation, "autoCloseSpike", "Auto close spike", "Place a spike near close threats when no enabled pit trap is available");
addHudToggle(automation, "reloadSpike", "Reload spike", "Defend with one spike while Musket or Turret Gear reloads");
addHudToggle(automation, "shieldDefense", "Shield defense", "Face polearm and turret attacks");
addHudToggle(automation, "musketRecharge", "Weapon recharge", "Main-first resumable queue for every cooling weapon");
addHudToggle(automation, "autoPurchase", "Auto purchase", "Monkey Tail → Soldier → Stick/Bull path → gear → wings");
addHudToggle(automation, "matThief", "Mat thief", "Last-hit nearby mills, turrets, and teleporters; starts disabled");
addHudToggle(automation, "mobSteal", "Mob steal", "Predictively last-hit one-swing animals in range; starts disabled");
addHudToggle(automation, "spinningWindmills", "Spinning windmills", "Continuously place mills in rotating collision-free slots; starts disabled");
const tabSync = addHudSection(syncPage, "Tab sync (same game)");
addHudToggle(tabSync, "syncLeader", "Sync leader", "Share this tab’s position, equipment, selections, and attacks");
addHudToggle(tabSync, "syncFollower", "Sync follower", "Follow the leader in a tight orbit and replay its actions with positional aim");
const visuals = addHudSection(visualsPage, "Visuals");
addHudToggle(visuals, "esp", "Player & animal markers", "Colored circles around players and animals");
addHudToggle(visuals, "espLines", "Player connection lines", "Lines to friends, teammates, and enemies; hostile lines are thicker");
addHudToggle(visuals, "predictionGhost", "Prediction ghost", "A translucent copy projects ahead by half your live ping");
addHudToggle(visuals, "cooldownBars", "Tool cooldown bars", "Small refill bars beneath players show both tool cooldowns");
const actions = addHudSection(combatPage, "Gear & boost controls");
addHudToggle(actions, "bullHelmet", "Bull helmet", "Bull through the configured swing window, Soldier during reload, then restores your hat");
addHudToggle(actions, "tankRightClick", "Tank right-click", "Tank uses the configured hold, then Soldier; falls back to any primary when slot two is empty");
addHudToggle(actions, "allItemsUnlock", "Preview every upgrade", "Shows every same-age choice but disables selections the server would reject");
addHudToggle(actions, "instaKill", "R insta", "Bull primary + Turret Gear secondary combo");
addHudToggle(actions, "autoInsta", "Click insta", "Left-click starts the ready full combo when an enemy is close");
addHudToggle(actions, "autoSpikeInsta", "Spike-tick strike", "Turret Gear + insta-primary swing on predicted allied-spike contact");
addHudToggle(actions, "autoSpikeSpam", "Trapped-player spikes", "Predictive tangent solver auto-places against exposed trapped enemies");
addHudToggle(actions, "antiInsta", "Anti insta", "Places a spike against a lethal incoming projectile volley");
addHudToggle(actions, "instaSync", "Insta sync", "Predictively matches allied-player and allied-turret projectile arrivals");
addHudToggle(actions, "boostBreak", "Shift + F boost-break", "Place, break, and move on cooldown");
addHudToggle(actions, "boostChat", "Shift + F chat", "Send shuffled speed messages");
const friends = addHudSection(combatPage, "Friends");
const friendHint = document.createElement("small");
friendHint.textContent = "Press U, then click a player to add them. Press I, then click a player to mark them as an enemy. Friends stay ignored unless they betray you.";
const friendList = document.createElement("div");
friendList.className = "mm-hud-friend-list";
friendList.dataset.hudFriends = "";
friends.append(friendHint, friendList);
const tuning = addHudSection(configPage, "Distance tuning");
addHudNumber(tuning, "soldierRange", "Soldier radius", "Pixels");
addHudNumber(tuning, "combatRange", "Combat radius", "Tail behavior cutoff");
addHudNumber(tuning, "gearHoldTicks", "Gear hold", "Minimum server ticks for Bull, Soldier, right-click Tank, and trap-breaking Tank stages");
addHudNumber(tuning, "passiveSpikeEnemyRange", "Avoidance enemy cutoff", "Passive spike avoidance pauses when an enemy is within this many pixels");
addHudNumber(tuning, "antiBoostRange", "Spike radius", "Pixels");
addHudNumber(tuning, "reactionMs", "Reaction scan", "Milliseconds between live-state checks");
const diagnostics = addHudSection(configPage, "Diagnostics");
addHudToggle(diagnostics, "debugPanel", "Runtime debug", "Show live owner, target, trap, and cooldown reasons");
const debugReadout = document.createElement("pre");
debugReadout.className = "mm-hud-debug";
debugReadout.dataset.hudDebug = "";
debugReadout.hidden = !hudState.debugPanel;
diagnostics.appendChild(debugReadout);
const messages = addHudSection(configPage, "Chat automation");
addHudToggle(messages, "materialReply", "Material request reply", "Tell teammates and friends your current wood and stone when they ask for materials");
addHudToggle(messages, "killMessageEnabled", "Auto send on kill", "Posts a chat line when your kill count rises");
const message = document.createElement("input");
message.className = "mm-hud-message";
message.type = "text";
message.maxLength = 30;
message.placeholder = "Example: gg!";
message.value = hudState.killMessage;
message.addEventListener("input", () => {
hudState.killMessage = message.value.slice(0, 30);
saveHudSettings();
sendHudCommand({ type: "set", key: "killMessage", value: hudState.killMessage });
});
messages.appendChild(message);
hudControls.set("killMessage", message);
const hotkeys = addHudSection(configPage, "Hotkeys");
const keyList = document.createElement("ul");
keyList.className = "mm-hud-keys";
["U + click add friend · I + click mark enemy", "C cleanup (W/A/S/D/F/V/R/H/Z or click cancels)", "P autoheal", "Q food · F trap · V spikes · Z 3 windmills behind · H selected build", "Shift + F boost-break · Shift + T betrayal insta", "Left-click Bull · Right-click Tank"].forEach((line) => {
const item = document.createElement("li");
item.textContent = line;
keyList.appendChild(item);
});
const reset = document.createElement("button");
reset.className = "mm-hud-reset";
reset.type = "button";
reset.textContent = "Reset saved settings";
reset.addEventListener("click", () => {
hudState = { ...HUD_DEFAULTS };
saveHudSettings();
sendHudCommand({ type: "hydrate", settings: { ...HUD_DEFAULTS } });
renderHud();
});
hotkeys.append(keyList, reset);
root.appendChild(panel);
document.body.appendChild(root);
activatePage("automation");
renderHud();
}
function scheduleHudMount() {
const mountAll = () => {
installKittyTheme();
mountMetrics();
mountHud();
};
if (document.body) mountAll();
else document.addEventListener("DOMContentLoaded", mountAll, { once: true });
}
function compareKittyVersions(left, right) {
const leftParts = String(left || "").match(/\d+/g) || [];
const rightParts = String(right || "").match(/\d+/g) || [];
const length = Math.max(leftParts.length, rightParts.length);
for (let index = 0; index < length; index += 1) {
const difference = Number(leftParts[index] || 0) - Number(rightParts[index] || 0);
if (difference) return difference > 0 ? 1 : -1;
}
return 0;
}
function safeKittyDownloadUrl(candidate) {
try {
const url = new URL(candidate || KITTY_UPDATE_FALLBACK_URL);
if (
url.protocol === "https:" &&
url.hostname === "update.greasyfork.org" &&
/^\/scripts\/592072(?:\/|$)/.test(url.pathname)
) return url.href;
} catch {
// The fixed GreasyFork installer remains the safe fallback.
}
return KITTY_UPDATE_FALLBACK_URL;
}
function mountKittyUpdatePopup(latestVersion, downloadUrl) {
if (!document.body || document.getElementById(KITTY_UPDATE_POPUP_ID)) return;
try {
if (sessionStorage.getItem(KITTY_UPDATE_DISMISS_KEY) === latestVersion) return;
} catch {
// A blocked session store should not prevent an update notice.
}
const popup = document.createElement("aside");
popup.id = KITTY_UPDATE_POPUP_ID;
popup.setAttribute("role", "dialog");
popup.setAttribute("aria-labelledby", "kitty-update-title");
popup.setAttribute("aria-describedby", "kitty-update-copy");
const title = document.createElement("h2");
title.id = "kitty-update-title";
title.className = "kitty-update-title";
title.textContent = "Update available";
const copy = document.createElement("p");
copy.id = "kitty-update-copy";
copy.className = "kitty-update-copy";
copy.textContent = "A newer Kitty Klient build is ready.";
const versions = document.createElement("div");
versions.className = "kitty-update-versions";
versions.textContent = KITTY_KLIENT_VERSION + " → " + latestVersion;
const download = document.createElement("a");
download.className = "kitty-update-download";
download.href = safeKittyDownloadUrl(downloadUrl);
download.target = "_blank";
download.rel = "noopener noreferrer";
download.textContent = "Download update";
const close = document.createElement("button");
close.className = "kitty-update-close";
close.type = "button";
close.setAttribute("aria-label", "Dismiss update notice");
close.textContent = "×";
close.addEventListener("click", () => {
try {
sessionStorage.setItem(KITTY_UPDATE_DISMISS_KEY, latestVersion);
} catch {
// Closing still works when storage is unavailable.
}
popup.remove();
});
popup.append(title, copy, versions, download, close);
document.body.appendChild(popup);
}
async function checkForKittyUpdate() {
const controller = typeof AbortController === "function" ? new AbortController() : null;
const timeout = window.setTimeout(() => controller && controller.abort(), 5000);
try {
const response = await fetch(KITTY_UPDATE_API, {
cache: "no-store",
credentials: "omit",
signal: controller ? controller.signal : undefined
});
if (!response.ok) return;
const release = await response.json();
const latestVersion = typeof release.version === "string" ? release.version.trim() : "";
if (!latestVersion || compareKittyVersions(latestVersion, KITTY_KLIENT_VERSION) <= 0) return;
const showPopup = () => mountKittyUpdatePopup(latestVersion, release.code_url);
if (document.body) showPopup();
else document.addEventListener("DOMContentLoaded", showPopup, { once: true });
} catch {
// Update checks are optional and must never interfere with the client.
} finally {
window.clearTimeout(timeout);
}
}
let escapeClaimedByGameMenu = false;
function isGameSubmenuOpen() {
return ["allianceMenu", "storeMenu", "chatHolder"].some((id) => {
const menu = document.getElementById(id);
if (!menu) return false;
return menu.style.display === "block" || window.getComputedStyle(menu).display !== "none";
});
}
function closeHud(root) {
hudOpen = false;
root.classList.add("mm-hud-collapsed");
root.setAttribute("aria-hidden", "true");
}
document.addEventListener("keydown", (event) => {
const root = document.getElementById(HUD_ID);
if (event.key === "Escape") {
if (!root) return;
if (escapeClaimedByGameMenu) {
// Do not let a held Escape key close the game menu and then
// toggle Kitty Klient open on the first repeat event.
event.preventDefault();
event.stopImmediatePropagation();
return;
}
if (isGameSubmenuOpen()) {
escapeClaimedByGameMenu = true;
closeHud(root);
const active = document.activeElement;
if (active && active.matches("input,textarea,[contenteditable='true']")) active.blur();
// Keep the trusted Escape event flowing. The game's own close
// handler dismisses store, alliance, and the chat text box.
return;
}
hudOpen = root.classList.contains("mm-hud-collapsed");
root.classList.toggle("mm-hud-collapsed", !hudOpen);
root.setAttribute("aria-hidden", String(!hudOpen));
event.preventDefault();
event.stopImmediatePropagation();
return;
}
if (!root) return;
if (hudOpen && /^[wasdfvrui]$/i.test(event.key)) {
closeHud(root);
// Keep the real trusted key event flowing into the game so movement
// and held actions begin immediately after the menu disappears.
}
}, true);
document.addEventListener("keyup", (event) => {
if (event.key === "Escape") escapeClaimedByGameMenu = false;
}, true);
window.addEventListener("MooMooKittyMetrics", (event) => {
if (!event.detail || typeof event.detail !== "object") return;
mountMetrics();
const metrics = document.getElementById("kitty-klient-metrics");
if (!metrics) return;
const setMetric = (name, value) => {
const field = metrics.querySelector("[data-metric='" + name + "']");
if (field) field.textContent = value;
};
setMetric("ping", Number.isFinite(event.detail.ping) ? Math.round(event.detail.ping) + "ms" : "--");
setMetric("fps", Number.isFinite(event.detail.fps) ? String(Math.round(event.detail.fps)) : "--");
const packetText = String(Math.max(0, Number(event.detail.packets) || 0)) +
(Number.isFinite(event.detail.pps) ? " · " + Math.round(event.detail.pps) + "/s" : "");
setMetric("packets", packetText);
});
window.addEventListener("MooMooFriendPickNotice", (event) => {
if (typeof event.detail === "string" && event.detail) {
showZoomIndicator(event.detail);
}
});
window.addEventListener("MooMooOPHudState", (event) => {
if (!event.detail || typeof event.detail !== "object") return;
const debugText = typeof event.detail.debugText === "string" ? event.detail.debugText : hudState.debugText;
hudState = { ...normalizeHudSettings({ ...hudState, ...event.detail }), debugText };
if (!hudSettingsSent) {
hudSettingsSent = true;
sendHudCommand({ type: "hydrate", settings: readHudSettings() });
}
saveHudSettings();
renderHud();
});
window.addEventListener("MooMooFriendState", (event) => {
const detail = event.detail;
if (!detail || typeof detail.name !== "string") return;
const name = detail.name.trim().slice(0, 15);
if (!name) return;
const key = name.toLowerCase();
const names = Array.isArray(hudState.friendNames) ? hudState.friendNames.slice() : [];
const existing = names.findIndex((entry) => entry.toLowerCase() === key);
if (detail.type === "remove" && existing >= 0) names.splice(existing, 1);
else if (detail.type === "add" && existing < 0) names.push(name);
else return;
hudState.friendNames = normalizeHudSettings({ friendNames: names }).friendNames;
saveHudSettings();
renderHud();
});
scheduleHudMount();
void checkForKittyUpdate();
function patchedViewportCode() {
// This string replaces a matching section of the game bundle at runtime.
return `
const __mmZoomBaseWidth = y.maxScreenWidth,
__mmZoomBaseHeight = y.maxScreenHeight;
let __mmSoldierRange = 400,
__mmCombatRange = 400,
__mmGearHoldTicks = 3,
__mmPassiveSpikeEnemyRange = 400,
__mmAntiBoostRange = 200,
__mmSoldierAutoEnabled = !0,
__mmMovementGearEnabled = !0,
__mmPassiveSpikeAvoidanceEnabled = !0,
__mmTrapEscapeEnabled = !0,
__mmAntiBoostEnabled = !0,
__mmAntiBoostInstaEnabled = !0,
__mmThreatTrapEnabled = !0,
__mmAutoCloseSpikeEnabled = !0,
__mmReloadSpikeEnabled = !0,
__mmShieldDefenseEnabled = !0,
__mmMusketRechargeEnabled = !0,
__mmAutoPurchaseEnabled = !1,
__mmMatThiefEnabled = !1,
__mmMobStealEnabled = !1,
__mmSpinningWindmillsEnabled = !1,
__mmEspEnabled = !0,
__mmEspLinesEnabled = !0,
__mmPredictionGhostEnabled = !0,
__mmCooldownBarsEnabled = !0,
__mmBullHelmetEnabled = !0,
__mmTankRightClickEnabled = !0,
__mmAllItemsUnlockEnabled = !0,
__mmInstaUiEnabled = !1,
__mmAutoInstaEnabled = !0,
__mmAutoSpikeInstaEnabled = !0,
__mmAutoSpikeSpamEnabled = !0,
__mmAntiInstaEnabled = !0,
__mmInstaSyncEnabled = !0,
__mmBoostBreakEnabled = !0,
__mmBoostChatEnabled = !0,
__mmMaterialReplyEnabled = !0,
__mmSyncLeaderEnabled = !1,
__mmSyncFollowerEnabled = !1,
__mmDebugPanelEnabled = !1,
__mmKillMessageEnabled = !0,
__mmKillMessage = "gg",
__mmReactionMs = 25;
const __mmShieldWeapon = 11,
__mmToolHammer = 0,
__mmMcGrabby = 14,
__mmShortSword = 3,
__mmPolearmWeapon = 5,
__mmTurretGear = 53,
__mmTurretGearRange = 700,
__mmEmpHelmet = 22,
__mmFullInstaRangeMultiplier = 1.5,
__mmThreatTrapRange = 300,
__mmThreatAnimalRange = 200,
__mmThreatTrapCooldownMs = 650,
__mmTrapCollisionPadding = 14,
__mmTrapAlertRangeReduction = 10,
__mmShieldDefenseRange = 240,
__mmShieldDefenseMs = 750,
__mmBoosterHat = 12,
__mmSnowHat = 15,
__mmSnowHatPrice = 600,
__mmFlipperHat = 31,
__mmFlipperHatPrice = 2500,
__mmGreatHammer = 10,
__mmKatana = 4,
__mmMusket = 15,
__mmAngelWings = 13,
__mmShadowWings = 19,
__mmBloodWings = 18,
__mmCorruptXWings = 21;
const __mmOriginalWeaponPrerequisites =
b && Array.isArray(b.weapons)
? b.weapons.map(function (__mmWeapon) {
return __mmWeapon && __mmWeapon.pre;
})
: [],
__mmOriginalItemPrerequisites =
b && Array.isArray(b.list)
? b.list.map(function (__mmItem) {
return __mmItem && __mmItem.pre;
})
: [];
const __mmAutoPurchaseEntries = Object.freeze({
monkeyTail: Object.freeze({ id: 11, tail: !0, price: 2e3 }),
soldier: Object.freeze({ id: 6, tail: !1, price: 4e3 }),
bull: Object.freeze({ id: 7, tail: !1, price: 6e3 }),
booster: Object.freeze({ id: 12, tail: !1, price: 6e3 }),
emp: Object.freeze({ id: 22, tail: !1, price: 6e3 }),
turret: Object.freeze({ id: 53, tail: !1, price: 1e4 }),
tank: Object.freeze({ id: 40, tail: !1, price: 15e3 }),
shadow: Object.freeze({ id: 19, tail: !0, price: 15e3 }),
angel: Object.freeze({ id: 13, tail: !0, price: 15e3 }),
blood: Object.freeze({ id: 18, tail: !0, price: 2e4 }),
corrupt: Object.freeze({ id: 21, tail: !0, price: 2e4 }),
});
let _ = y.maxScreenWidth,
L = y.maxScreenHeight;
let __mmFoodSpamTimer = 0;
let __mmAutoHealTimer = 0,
__mmAutoHealEnabled = !0,
__mmAutoHealWasHealing = !1,
__mmAutoHealPending = !1,
__mmAutoHealBitesRemaining = 0,
__mmAutoHealNextBiteAt = 0,
__mmAutoHealLastObservedHealth = null,
__mmAutoHealLastDamageAt = 0,
__mmAutoHealShameCount = 0,
__mmLastWeapon = null,
__mmLastBuildItem = null,
__mmAutoHealWeapon = null;
let __mmAutoPurchaseTimer = 0,
__mmAutoPurchasePending = null;
let __mmMatThiefTimer = 0,
__mmMatThiefReleaseTimer = 0,
__mmMatThiefAimAngle = null,
__mmMatThiefReturnAngle = null,
__mmMatThiefRestoreTool = null,
__mmMatThiefAttackHeld = !1;
const __mmMatThiefReservations = new WeakMap();
let __mmCleanupActive = !1,
__mmCleanupTimer = 0,
__mmCleanupProgressTimer = 0,
__mmCleanupOriginX = 0,
__mmCleanupOriginY = 0,
__mmCleanupTarget = null,
__mmCleanupSavedTool = null,
__mmCleanupWeapon = null,
__mmCleanupAttackHeld = !1,
__mmCleanupAimAngle = null,
__mmCleanupMoveAngle = null,
__mmCleanupTargetHealth = null,
__mmCleanupProgressAt = 0,
__mmCleanupEmptySince = 0,
__mmCleanupChatStep = 0;
const __mmCleanupReservations = new WeakMap();
let __mmMobStealTimer = 0,
__mmMobStealReleaseTimer = 0,
__mmMobStealAimAngle = null,
__mmMobStealRestoreTool = null,
__mmMobStealRestoreHat = null,
__mmMobStealRestoreTail = null,
__mmMobStealAttackHeld = !1;
const __mmMobStealMotion = Object.create(null),
__mmMobStealReservations = Object.create(null);
let __mmAutoInstaTimer = 0;
let __mmAutoSpikeInstaTimer = 0,
__mmAutoSpikeInstaLastAt = 0,
__mmSpikeTickStrikeTimer = 0,
__mmSpikeTickStrikeTool = null,
__mmSpikeTickStrikeHat = null,
__mmSpikeTickStrikeAimAngle = null,
__mmSpikeTickStrikeHeld = !1;
const __mmAutoSpikeInstaMotion = Object.create(null);
let __mmAutoSpikeSpamTimer = 0,
__mmAutoSpikeSpamLastAt = 0,
__mmAutoSpikeSpamGhost = null,
__mmAutoSpikeSpamCandidateKey = null,
__mmAutoSpikeSpamCandidateSince = 0,
__mmAutoSpikeSpamAimAngle = null,
__mmAutoSpikeSpamAimUntil = 0;
const __mmAutoSpikeSpamReservations = [];
const __mmAutoSpikeSpamMotion = Object.create(null);
let __mmAntiInstaTimer = 0,
__mmAntiInstaLastAt = 0,
__mmAntiInstaUntil = 0,
__mmAntiInstaActionTimer = 0;
let __mmInstaSyncLoopTimer = 0,
__mmInstaSyncTimer = 0,
__mmInstaSyncReleaseTimer = 0,
__mmInstaSyncPending = !1,
__mmInstaSyncFiring = !1,
__mmInstaSyncLastAt = 0,
__mmInstaSyncRestoreTool = null,
__mmInstaSyncRestoreHat = null,
__mmInstaSyncWeaponHeld = !1;
const __mmInstaSyncProjectileStates = new WeakMap();
let __mmMovementGearTimer = 0,
__mmMovementGearPreviousHat = null,
__mmMovementGearPreviousTail = null,
__mmProximityTailPrevious = null;
let __mmPassiveSpikeMotionTimer = 0,
__mmPassiveSpikePendingTimer = 0,
__mmPassiveSpikeCorrectionTimer = 0,
__mmPassiveSpikeCorrecting = !1,
__mmPassiveSpikeMotion = null;
let __mmFlipperPurchaseAt = 0,
__mmSnowPurchaseAt = 0;
let __mmShiftSpeedActive = !1,
__mmShiftMode = 0,
__mmShiftPreviousHat = null,
__mmShiftPreviousTail = null,
__mmShiftRestoreTimer = 0,
__mmShiftSpeedTimer = 0,
__mmShiftGearPurchaseTimer = 0;
let __mmBoostBreakTimer = 0,
__mmBoostBreakHeld = !1,
__mmBoostBreakCooldownWeapon = null,
__mmBoostBreakReadyAt = 0,
__mmBoostBreakStrikeTimer = 0,
__mmBoostBreakStriking = !1,
__mmBoostBreakPreviousWeapon = null,
__mmBoostMoveDirection = null,
__mmBoostTankPreviousHat = null,
__mmBoostChatTimer = 0,
__mmBoostChatOrder = [],
__mmBoostChatIndex = 0;
let __mmSoldierAutoTimer = 0,
__mmSoldierRestoreTimer = 0,
__mmSoldierPreviousHat = null;
let __mmShieldDefenseTimer = 0,
__mmShieldDefenseWeapon = null;
let __mmAntiBoostTimer = 0,
__mmAntiBoostLast = 0,
__mmAntiBoostBlockTimer = 0,
__mmAntiBoostMoveTimer = 0,
__mmAntiBoostBlockTool = null,
__mmAntiBoostBlockAimAngle = null,
__mmAntiBoostBackingUp = !1;
let __mmThreatTrapTimer = 0,
__mmThreatTrapLastAt = 0,
__mmThreatTrapLastKey = null;
const __mmThreatTrapPlacements = Object.create(null);
let __mmTrapAlertTimer = 0,
__mmTrapAlertUntil = 0,
__mmTrapChatIncidentActive = !1;
let __mmFriendlyTrapChatTimer = 0,
__mmFriendlyTrapChatLastAt = 0;
const __mmFriendlyTrapChatIncidents = Object.create(null);
let __mmReloadSpikeTimer = 0,
__mmReloadSpikePlaced = !1,
__mmTurretReloadUntil = 0;
const __mmEnemyBoostTrail = {};
const __mmSyncProtocol = "kitty-klient-tab-sync-v1";
const __mmSyncStorageKey = "kitty-klient-tab-sync-state-v1";
let __mmSyncChannel = null;
try {
typeof BroadcastChannel === "function" &&
(__mmSyncChannel = new BroadcastChannel(__mmSyncProtocol));
} catch (__mmSyncChannelError) {}
const __mmSyncTabId = (function () {
try {
const __mmStored = sessionStorage.getItem("kitty-klient-tab-sync-id");
if (__mmStored) return __mmStored;
const __mmId =
Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 10);
return (sessionStorage.setItem("kitty-klient-tab-sync-id", __mmId), __mmId);
} catch (__mmStorageError) {
return Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 10);
}
})();
let __mmSyncTimer = 0,
__mmSyncMoveActive = !1,
__mmSyncLeaderState = null,
__mmSyncSelectionBlockedUntil = 0,
__mmSyncGearPairDispatch = !1,
__mmSyncStatus = "off";
let __mmBuildSpamTimer = 0,
__mmBuildSpamKey = 0;
let __mmWindmillRowTimer = 0,
__mmWindmillHoldTimer = 0,
__mmWindmillHeld = !1,
__mmWindmillRowWeapon = null;
let __mmSpinningWindmillTimer = 0,
__mmSpinningWindmillAngle = 0,
__mmSpinningWindmillLastAt = 0;
const __mmSpinningWindmillReservations = [];
let __mmWeaponRechargeTimer = 0,
__mmWeaponRechargePreviousTool = null,
__mmWeaponRechargeActiveWeapon = null,
__mmWeaponRechargeSelectAt = 0;
let __mmPredictionLastX = null,
__mmPredictionLastY = null,
__mmPredictionLastAt = 0;
let __mmPrimaryHeld = !1,
__mmSecondaryHeld = !1,
__mmHeldAttackTimer = 0,
__mmPrimaryBullArmTimer = 0,
__mmPrimaryBullSwingPending = !1,
__mmPrimaryManualReadyAt = 0,
__mmSecondaryTankArmTimer = 0,
__mmSecondaryTankSwingPending = !1,
__mmSecondaryManualReadyAt = 0,
__mmSecondaryGearStage = null,
__mmSecondaryGearTimer = 0,
__mmSecondaryTankHoldUntil = 0,
__mmSecondarySoldierHoldUntil = 0,
__mmPrimaryClickHat = null,
__mmPrimaryClickTail = null,
__mmPrimaryGearStage = null,
__mmPrimaryGearTimer = 0,
__mmPrimaryBullHoldUntil = 0,
__mmPrimarySoldierHoldUntil = 0,
__mmRightClickHat = null,
__mmLastNormalHat = 0;
// Equipment packets are acknowledged by the game state. Keep local rendering
// authoritative and merely debounce duplicate requests while that update is in
// flight; directly rewriting skinIndex/tailIndex caused visible frame flicker.
let __mmPendingHat = null,
__mmPendingHatAt = 0,
__mmPendingTail = null,
__mmPendingTailAt = 0;
let __mmTrapAttackTimer = 0,
__mmTrapAttackActive = !1,
__mmTrapAimAngle = null,
__mmTrapWeapon = null,
__mmTrapHat = null,
__mmTrapAttackHeld = !1,
__mmTrapAttackHeldWeapon = null,
__mmTrapTankHoldUntil = 0,
__mmTrapWeaponSelectAt = 0,
__mmTrapHatRestoreTimer = 0,
__mmTrapHatRestoreAttempts = 0,
__mmTrapBuildTimer = 0,
__mmTrapBuildAttemptKey = null,
__mmTrapBuildWeapon = null;
let __mmLiveStateTimer = 0,
__mmDebugHudTimer = 0;
let __mmMetricFrames = 0,
__mmMetricPackets = 0,
__mmMetricPacketWindow = 0,
__mmMetricFps = 0,
__mmMetricPps = 0,
__mmMetricUpdatedAt = performance.now();
let __mmMouseAimReturnTimer = 0,
__mmSendingMouseAimReturn = !1;
const __mmBreakableHealth = new WeakMap(),
__mmRecentPlayerSwings = Object.create(null),
__mmPlayerToolCooldowns = Object.create(null);
const __mmFriendNames = new Map(),
__mmFriendEnemies = new Set(),
__mmFriendAttackWindows = Object.create(null);
let __mmFriendPickMode = null;
const __mmLiveState = {
updatedAt: 0,
alive: !1,
enemies: [],
animals: [],
nearestEnemy: null,
nearestEnemyDistance: Infinity,
nearbyTrap: null,
trapped: !1,
health: 0,
maxHealth: 0,
primaryReady: !1,
secondaryReady: !1,
};
const __mmActionPriorities = Object.freeze({
trapEscape: 100,
antiInsta: 95,
autoHeal: 90,
insta: 80,
spikeTickStrike: 82,
instaSync: 75,
shieldDefense: 85,
antiBoostBlock: 88,
boostBreak: 65,
manualAttack: 60,
cleanup: 55,
spikeSpam: 93,
threatTrap: 45,
reloadSpike: 40,
mobSteal: 38,
matThief: 35,
spinningWindmills: 15,
weaponRecharge: 20,
movementGear: 10,
soldierGear: 10,
});
let __mmActionOwner = "idle",
__mmActionReason = "waiting",
__mmActionSince = 0,
__mmActionLastDecision = "waiting";
function __mmActionPriority(__mmOwner) {
return Number(__mmActionPriorities[__mmOwner]) || 0;
}
function __mmActionAvailable(__mmOwner) {
return __mmActionOwner === "idle" || __mmActionOwner === __mmOwner;
}
function __mmActionCanPreempt(__mmOwner) {
return (
__mmActionAvailable(__mmOwner) ||
__mmActionPriority(__mmOwner) > __mmActionPriority(__mmActionOwner)
);
}
function __mmActionClaim(__mmOwner, __mmReason) {
if (
__mmActionOwner === "cleanup" &&
__mmOwner !== "cleanup" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("cleanup")
)
__mmStopCleanup("preempted by " + __mmOwner, !1);
if (
__mmActionOwner === "spikeTickStrike" &&
__mmOwner !== "spikeTickStrike" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("spikeTickStrike")
)
__mmStopSpikeTickStrike("preempted by " + __mmOwner);
if (
__mmActionOwner === "antiBoostBlock" &&
__mmOwner !== "antiBoostBlock" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("antiBoostBlock")
)
__mmStopAntiBoostBlock("preempted by " + __mmOwner);
if (
__mmActionOwner === "weaponRecharge" &&
__mmOwner !== "weaponRecharge" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("weaponRecharge")
)
__mmPauseWeaponRecharge(!0);
if (
__mmActionOwner === "matThief" &&
__mmOwner !== "matThief" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("matThief")
)
__mmFinishMatThief("preempted by " + __mmOwner);
if (
__mmActionOwner === "mobSteal" &&
__mmOwner !== "mobSteal" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("mobSteal")
)
__mmFinishMobSteal("preempted by " + __mmOwner);
if (!__mmActionAvailable(__mmOwner)) {
__mmActionLastDecision =
__mmOwner +
" blocked by " +
__mmActionOwner +
" (requested " +
__mmActionPriority(__mmOwner) +
", active " +
__mmActionPriority(__mmActionOwner) +
"): " +
(__mmReason || "busy");
return !1;
}
if (__mmActionOwner === __mmOwner) {
((__mmActionReason = __mmReason || __mmActionReason),
(__mmActionLastDecision = __mmOwner + ": " + __mmActionReason));
return !0;
}
((__mmActionOwner = __mmOwner),
(__mmActionReason = __mmReason || "active"),
(__mmActionSince = Date.now()),
(__mmActionLastDecision = __mmOwner + ": " + __mmActionReason));
return !0;
}
function __mmActionRelease(__mmOwner, __mmReason) {
if (__mmActionOwner !== __mmOwner) return !1;
((__mmActionOwner = "idle"),
(__mmActionReason = "idle"),
(__mmActionSince = 0),
(__mmActionLastDecision = __mmOwner + ": " + (__mmReason || "complete")));
return !0;
}
function __mmActionMayRestore(__mmOwner) {
return __mmActionOwner === __mmOwner || __mmActionOwner === "idle";
}
function __mmUpdateLiveState() {
const __mmNow = Date.now(),
__mmEnemies = [],
__mmAnimals = [],
__mmSeenEntities = Object.create(null);
let __mmNearest = null,
__mmNearestDistance = Infinity;
if (!v || !v.alive) {
((__mmLiveState.updatedAt = __mmNow),
(__mmLiveState.alive = !1),
(__mmLiveState.enemies = __mmEnemies),
(__mmLiveState.animals = __mmAnimals),
(__mmLiveState.nearestEnemy = null),
(__mmLiveState.nearestEnemyDistance = Infinity),
(__mmLiveState.nearbyTrap = null),
(__mmLiveState.trapped = !1));
return __mmLiveState;
}
if (typeof E !== "undefined" && Array.isArray(E))
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
const __mmPlayer = E[__mmIndex];
const __mmKey = __mmThreatTargetKey(__mmPlayer);
__mmKey != null && (__mmSeenEntities[__mmKey] = !0);
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
const __mmDistance = Math.hypot(__mmPlayer.x - v.x, __mmPlayer.y - v.y);
if (!Number.isFinite(__mmDistance)) continue;
__mmEnemies.push(__mmPlayer);
if (__mmDistance < __mmNearestDistance) {
((__mmNearest = __mmPlayer), (__mmNearestDistance = __mmDistance));
}
}
if (typeof N !== "undefined" && Array.isArray(N))
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex += 1) {
const __mmAnimal = N[__mmIndex];
const __mmKey = __mmThreatTargetKey(__mmAnimal);
__mmKey != null && (__mmSeenEntities[__mmKey] = !0);
__mmAnimal && __mmAnimal.active !== !1 && __mmAnimals.push(__mmAnimal);
}
for (const __mmKey in __mmThreatTrapPlacements)
__mmSeenEntities[__mmKey] || delete __mmThreatTrapPlacements[__mmKey];
for (const __mmKey in __mmUnknownTeamSeen)
__mmSeenEntities[__mmKey] || delete __mmUnknownTeamSeen[__mmKey];
const __mmTrap = __mmNearestLockingTrap();
((__mmLiveState.updatedAt = __mmNow),
(__mmLiveState.alive = !0),
(__mmLiveState.enemies = __mmEnemies),
(__mmLiveState.animals = __mmAnimals),
(__mmLiveState.nearestEnemy = __mmNearest),
(__mmLiveState.nearestEnemyDistance = __mmNearestDistance),
(__mmLiveState.nearbyTrap = __mmTrap),
(__mmLiveState.trapped = !!(v.lockMove || __mmTrap)),
(__mmLiveState.health = Number(v.health) || 0),
(__mmLiveState.maxHealth = Number(v.maxHealth) || 0),
(__mmLiveState.primaryReady = !!__mmWeaponReady(v.weapons && v.weapons[0])),
(__mmLiveState.secondaryReady = !!__mmWeaponReady(v.weapons && v.weapons[1])));
return __mmLiveState;
}
function __mmLiveStateFresh() {
return Date.now() - __mmLiveState.updatedAt <= 2 * __mmFastCheckMs();
}
function __mmCurrentNearbyTrap() {
return __mmLiveStateFresh() ? __mmLiveState.nearbyTrap : __mmNearestLockingTrap();
}
function __mmIsTrapped() {
return !!(v && v.alive && (v.lockMove || __mmCurrentNearbyTrap()));
}
function __mmRuntimeDebugText() {
const __mmState = __mmLiveState,
__mmEnemy = __mmState.nearestEnemy,
__mmReload = v && v.weapons
? "main " + (__mmState.primaryReady ? "ready" : "reload") +
" · secondary " + (__mmState.secondaryReady ? "ready" : "reload")
: "weapons unavailable",
__mmOwnerAge = __mmActionSince ? Date.now() - __mmActionSince : 0;
return [
"owner: " + __mmActionOwner + (__mmActionSince ? " (" + __mmOwnerAge + "ms)" : ""),
"reason: " + __mmActionReason,
"last: " + __mmActionLastDecision,
"enemy: " +
(__mmEnemy
? String(__mmEnemy.sid) + " at " + Math.round(__mmState.nearestEnemyDistance)
: "none"),
"trap: " + (__mmState.trapped ? "locked/collision" : "clear"),
"reload: " + __mmReload,
"scan: " + __mmReactionMs + "ms · state age " +
(Date.now() - __mmState.updatedAt) + "ms",
].join("\\n");
}
function __mmStartLiveState() {
if (__mmLiveStateTimer) return;
(__mmUpdateLiveState(),
(__mmLiveStateTimer = setInterval(__mmUpdateLiveState, __mmFastCheckMs())));
}
function __mmStartDebugHud() {
__mmDebugHudTimer ||
(__mmDebugHudTimer = setInterval(function () {
__mmDebugPanelEnabled && __mmPublishHudState();
}, 200));
}
const __mmUnknownTeamSeen = {},
__mmUnknownTeamGraceMs = 1500;
const __mmBoostChatLines = [
"WHEEEEEE!",
"Wooo-hooo!",
"ZOOOOOM!",
"Can't catch me!",
"I AM SPEEEEED!",
"I'M COMING FOR YOU!",
"AAAHHHHH!",
];
const __mmOriginalSelect = je;
je = function (__mmItem, __mmIsWeapon) {
__mmIsWeapon
? (__mmLastWeapon = __mmItem)
: __mmIsPlaceableItem(__mmItem) && (__mmLastBuildItem = __mmItem);
const __mmResult = __mmOriginalSelect(__mmItem, __mmIsWeapon);
return (__mmSyncPublishSelection(__mmItem, __mmIsWeapon), __mmResult);
};
function __mmPrepareTrademarkNameInput() {
// Do not touch MooMoo's minified name-input binding here. This patch block is
// inserted before that top-level const is initialized in the current bundle,
// so even testing the binding aborts the whole module through the TDZ.
const __mmNameInput = document.getElementById("nameInput");
if (!__mmNameInput) return 13;
const __mmStoredOriginal = Number(__mmNameInput.dataset.kittyOriginalNameMax),
__mmOriginalMax =
Number.isFinite(__mmStoredOriginal) && __mmStoredOriginal > 2
? __mmStoredOriginal
: Math.max(3, Number(__mmNameInput.maxLength) || 15),
__mmLimit = Math.max(1, __mmOriginalMax - 2),
__mmRaw = String(__mmNameInput.value || "")
.replace(/^(?:k-)+/i, "")
.slice(0, __mmLimit);
(__mmNameInput.dataset.kittyOriginalNameMax = String(__mmOriginalMax),
__mmNameInput.dataset.kittyNameLimit = String(__mmLimit),
(__mmNameInput.maxLength = __mmLimit),
__mmNameInput.setAttribute("maxlength", String(__mmLimit)),
(__mmNameInput.placeholder = "Enter Name (k- added)"),
__mmNameInput.value !== __mmRaw && (__mmNameInput.value = __mmRaw));
return __mmLimit;
}
function __mmTrademarkPlayerName(__mmName) {
const __mmLimit = __mmPrepareTrademarkNameInput(),
__mmRaw = String(__mmName || "")
.replace(/^(?:k-)+/i, "")
.slice(0, __mmLimit);
return "k-" + __mmRaw;
}
__mmPrepareTrademarkNameInput();
const __mmOriginalSocketSend = O.send;
O.send = function () {
if (arguments[0] === "H" && !__mmAllowUpgradePacket(arguments[1]))
return;
if (
arguments[0] === "M" &&
arguments[1] &&
typeof arguments[1] === "object"
)
arguments[1] = {
...arguments[1],
name: __mmTrademarkPlayerName(arguments[1].name),
};
const __mmResult = __mmOriginalSocketSend.apply(this, arguments);
return (
(__mmMetricPackets += 1),
(__mmMetricPacketWindow += 1),
__mmSyncObserveSocketSend(arguments),
__mmObserveForcedDirectionPacket(arguments),
__mmResult
);
};
const __mmOriginalPlayerAttack = Pl;
const __mmOriginalHealthUpdate = $l;
const __mmOriginalAnimalUpdate = Xl;
const __mmOriginalPlayerStatUpdate = Kl;
const __mmOriginalChatDisplay = dl;
const __mmOriginalUpgradeDisplay = Un;
const __mmOriginalObjectRender = Ge;
const __mmOriginalObjectHit = Wl;
const __mmOriginalAimDirection = Ci;
const __mmOriginalRender = Cl;
Ci = function () {
return __mmTrapAttackActive && Number.isFinite(__mmTrapAimAngle)
? __mmTrapAimAngle
: Number.isFinite(__mmMatThiefAimAngle)
? __mmMatThiefAimAngle
: Number.isFinite(__mmMobStealAimAngle)
? __mmMobStealAimAngle
: Number.isFinite(__mmAntiBoostBlockAimAngle)
? __mmAntiBoostBlockAimAngle
: Number.isFinite(__mmSpikeTickStrikeAimAngle)
? __mmSpikeTickStrikeAimAngle
: __mmCleanupActive && Number.isFinite(__mmCleanupAimAngle)
? __mmCleanupAimAngle
: Date.now() < __mmAutoSpikeSpamAimUntil &&
Number.isFinite(__mmAutoSpikeSpamAimAngle)
? __mmAutoSpikeSpamAimAngle
: __mmOriginalAimDirection.apply(this, arguments);
};
function __mmRawMouseAimDirection() {
// Read the cursor coordinates directly so X/lockDir cannot freeze this at
// the pre-automation angle. The normal Ci helper intentionally preserves
// its old angle while X is enabled.
const __mmMouseX = Number(On) - Number(De) / 2,
__mmMouseY = Number(Hn) - Number(Ae) / 2;
if (Number.isFinite(__mmMouseX) && Number.isFinite(__mmMouseY)) {
const __mmDirectAngle = Math.atan2(__mmMouseY, __mmMouseX);
return typeof M.fixTo === "function"
? M.fixTo(__mmDirectAngle, 2)
: __mmDirectAngle;
}
let __mmAngle = 0;
try {
__mmAngle = Number(__mmOriginalAimDirection());
} catch (__mmMouseAimError) {}
// Zero is a valid direction (cursor directly on the positive X axis), so
// never use a truthiness fallback here.
return Number.isFinite(__mmAngle) ? __mmAngle : 0;
}
function __mmForcedDirectionStillActive() {
return !!(
(__mmTrapAttackActive && Number.isFinite(__mmTrapAimAngle)) ||
Number.isFinite(__mmMatThiefAimAngle) ||
Number.isFinite(__mmMobStealAimAngle) ||
Number.isFinite(__mmAntiBoostBlockAimAngle) ||
Number.isFinite(__mmSpikeTickStrikeAimAngle) ||
(__mmCleanupActive && Number.isFinite(__mmCleanupAimAngle)) ||
(Date.now() < __mmAutoSpikeSpamAimUntil &&
Number.isFinite(__mmAutoSpikeSpamAimAngle)) ||
__mmInsta.isActive() ||
__mmInstaSyncPending ||
__mmInstaSyncFiring
);
}
function __mmReturnDirectionToMouse() {
__mmMouseAimReturnTimer = 0;
if (!v || !v.alive) return;
if (__mmForcedDirectionStillActive()) {
__mmMouseAimReturnTimer = setTimeout(
__mmReturnDirectionToMouse,
__mmFastCheckMs(),
);
return;
}
const __mmAngle = __mmRawMouseAimDirection();
try {
// Update the game's cached aim as well as the server. When X is active,
// Ci returns this cache instead of sampling the cursor on the next frame.
((It = __mmAngle),
(__mmSendingMouseAimReturn = !0),
O.send("D", __mmAngle));
} finally {
__mmSendingMouseAimReturn = !1;
}
}
function __mmScheduleMouseAimReturn() {
if (__mmSendingMouseAimReturn) return;
__mmMouseAimReturnTimer && clearTimeout(__mmMouseAimReturnTimer);
__mmMouseAimReturnTimer = setTimeout(
__mmReturnDirectionToMouse,
__mmServerTickMs(),
);
}
function __mmObserveForcedDirectionPacket(__mmArgs) {
if (__mmSendingMouseAimReturn || !__mmArgs) return;
const __mmPacket = __mmArgs[0];
if (
__mmPacket === "F" &&
__mmArgs[2] != null &&
Number.isFinite(Number(__mmArgs[2]))
) {
__mmScheduleMouseAimReturn();
return;
}
if (
__mmPacket !== "D" ||
__mmArgs[1] == null ||
!Number.isFinite(Number(__mmArgs[1]))
)
return;
const __mmSent = Number(__mmArgs[1]),
__mmMouse = __mmRawMouseAimDirection(),
__mmDifference = Math.abs(
Math.atan2(
Math.sin(__mmSent - __mmMouse),
Math.cos(__mmSent - __mmMouse),
),
);
__mmDifference > 0.001 && __mmScheduleMouseAimReturn();
}
// R insta owns one short-lived interaction at a time. It deliberately uses the
// same client actions as normal input and yields to safety/manual automation.
// State transitions are intentionally limited to:
// idle -> validate -> arm -> waitForRange -> executeBurst -> cleanup -> idle.
const __mmInsta = {
state: "idle",
timer: 0,
targetSid: null,
targetOptional: !1,
automatic: !1,
betrayal: !1,
snapshot: null,
primaryWeapon: null,
pendingSecondaryWeapon: null,
attackHeld: !1,
trapHandoff: null,
isActive() {
return this.state !== "idle" && this.state !== "cleanup";
},
isEmergencyHealth() {
return !!(
v &&
v.alive &&
Number(v.health) <= Math.max(20, Number(v.maxHealth) * 0.2)
);
},
runtimeReady() {
return !!(
typeof v !== "undefined" &&
v &&
typeof b !== "undefined" &&
b &&
b.weapons &&
b.list &&
typeof E !== "undefined" &&
Array.isArray(E) &&
typeof Rt === "function" &&
typeof je === "function" &&
typeof O !== "undefined" &&
O &&
typeof O.send === "function" &&
typeof Ci === "function" &&
typeof y !== "undefined" &&
y
);
},
tick() {
return __mmServerTickMs();
},
schedule(__mmCallback) {
this.timer && clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.timer = 0;
__mmCallback();
}, this.tick());
},
isPriorityConflict() {
const __mmTrapHandoffAvailable = !!(
__mmIsTrapped() &&
(__mmActionOwner === "trapEscape" || __mmTrapAttackActive)
);
return !!(
!v ||
!v.alive ||
(!__mmActionCanPreempt("insta") && !__mmTrapHandoffAvailable) ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
(__mmTrapAttackActive && !__mmTrapHandoffAvailable) ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
Date.now() < __mmAntiInstaUntil ||
__mmInstaSyncPending ||
__mmInstaSyncFiring ||
(this.isEmergencyHealth() && !__mmIsTrapped())
);
},
suspendTrapEscape() {
if (!__mmIsTrapped() || !__mmTrapEscapeEnabled) return;
this.trapHandoff = {
resume: !0,
weapon:
__mmTrapWeapon != null ? __mmTrapWeapon : __mmSelectedWeapon(),
hat: __mmTrapHat != null ? __mmTrapHat : v.skinIndex,
};
(__mmTrapAttackActive || __mmActionOwner === "trapEscape") &&
__mmStopTrapAttack();
},
capture() {
this.snapshot = {
weapon:
this.trapHandoff && this.trapHandoff.weapon != null
? this.trapHandoff.weapon
: __mmSelectedWeapon(),
hat:
this.trapHandoff && this.trapHandoff.hat != null
? this.trapHandoff.hat
: v.skinIndex,
tail: v.tailIndex,
primaryHeld: __mmPrimaryHeld,
secondaryHeld: __mmSecondaryHeld,
heldPulse: !!__mmHeldAttackTimer,
movementGear: __mmMovementGearEnabled,
soldierAuto: __mmSoldierAutoEnabled,
autoHeal: __mmAutoHealEnabled,
};
},
nearestEnemy() {
if (__mmLiveStateFresh()) return __mmLiveState.nearestEnemy;
if (!v || !v.alive || !Array.isArray(E)) return null;
let __mmClosest = null;
let __mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
const __mmPlayer = E[__mmIndex];
if (
!__mmIsEnemyPlayer(__mmPlayer) ||
!Number.isFinite(Number(__mmPlayer.x)) ||
!Number.isFinite(Number(__mmPlayer.y))
)
continue;
const __mmDx = __mmPlayer.x - v.x;
const __mmDy = __mmPlayer.y - v.y;
const __mmDistance = __mmDx * __mmDx + __mmDy * __mmDy;
if (__mmDistance < __mmClosestDistance) {
__mmClosest = __mmPlayer;
__mmClosestDistance = __mmDistance;
}
}
return __mmClosest;
},
target() {
if (this.targetSid == null) return null;
let __mmTarget = null;
try {
__mmTarget = Rt(this.targetSid);
} catch (__mmLookupError) {}
if (!__mmTarget && Array.isArray(E)) {
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
const __mmPlayer = E[__mmIndex];
if (__mmPlayer && String(__mmPlayer.sid) === String(this.targetSid)) {
__mmTarget = __mmPlayer;
break;
}
}
}
return __mmTarget &&
String(__mmTarget.sid) === String(this.targetSid) &&
(__mmIsEnemyPlayer(__mmTarget) ||
(this.betrayal &&
__mmTarget !== v &&
__mmTarget.alive &&
__mmTarget.visible)) &&
Number.isFinite(Number(__mmTarget.x)) &&
Number.isFinite(Number(__mmTarget.y))
? __mmTarget
: null;
},
weaponData(__mmWeapon) {
return b && b.weapons && __mmWeapon != null ? b.weapons[__mmWeapon] : null;
},
supportedPrimary() {
if (!v || !v.alive || !v.weapons) return null;
const __mmWeapon = v.weapons[0];
if (
__mmWeapon !== __mmShortSword &&
__mmWeapon !== __mmKatana &&
__mmWeapon !== __mmPolearmWeapon
)
return null;
const __mmData = this.weaponData(__mmWeapon);
return __mmData &&
__mmData.projectile == null &&
__mmWeapon;
},
inRange(__mmWeapon, __mmTarget) {
const __mmData = this.weaponData(__mmWeapon);
const __mmRange = __mmData && Number(__mmData.range);
if (
!v ||
!__mmTarget ||
!Number.isFinite(__mmRange) ||
__mmRange <= 0
)
return !1;
const __mmReach =
(__mmRange +
(Number(v.scale) || 0) +
(Number(__mmTarget.scale) || 0)) *
__mmFullInstaRangeMultiplier;
return Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) <= __mmReach;
},
canFullBurst(__mmTarget) {
const __mmPrimary = this.supportedPrimary(),
__mmSecondary = v && v.weapons && v.weapons[1],
__mmSecondaryData = this.weaponData(__mmSecondary);
return !!(
__mmPrimary != null &&
__mmTarget &&
this.inRange(__mmPrimary, __mmTarget) &&
__mmSecondary != null &&
__mmSecondary !== __mmPrimary &&
__mmSecondary !== __mmShieldWeapon &&
__mmSecondaryData &&
!__mmSecondaryData.shield
);
},
aim(__mmTarget) {
return __mmTarget
? Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x)
: Ci();
},
damageTail() {
if (!v || !v.alive) return null;
if (v.tails && v.tails[__mmCorruptXWings]) return __mmCorruptXWings;
return (this.snapshot && this.snapshot.tail === 11) || v.tailIndex === 11
? 0
: null;
},
context(__mmRequireRange) {
if (
(!__mmInstaUiEnabled && !this.automatic) ||
!this.runtimeReady() ||
this.isPriorityConflict()
)
return null;
const __mmPrimary = this.supportedPrimary();
if (__mmPrimary == null) return null;
const __mmTarget = this.target();
if (!__mmTarget && !this.targetOptional) return null;
if (__mmRequireRange && __mmTarget && !this.inRange(__mmPrimary, __mmTarget))
return null;
return { primary: __mmPrimary, target: __mmTarget };
},
selectDamageGear() {
if (!v || !v.alive) return;
// Dispatch both equipment packets from this same local/server-tick phase.
__mmEquipGearPair(
v.skins && v.skins[7] ? 7 : null,
this.damageTail(),
!0,
);
},
selectSecondaryDamageGear() {
if (!v || !v.alive) return;
// Re-send the damage tail in the exact Turret packet phase too. This keeps
// the secondary stage paired even if the Bull-stage acknowledgement has
// not reached the client yet.
__mmEquipGearPair(
v.skins && v.skins[__mmTurretGear] ? __mmTurretGear : null,
this.damageTail(),
!0,
);
},
turretReady() {
return !!(
v &&
v.alive &&
v.skins &&
v.skins[__mmTurretGear] &&
Date.now() >= __mmTurretReloadUntil
);
},
turretInRange(__mmTarget) {
if (!v || !__mmTarget) return !1;
const __mmReach =
__mmTurretGearRange +
(Number(v.scale) || 0) +
(Number(__mmTarget.scale) || 0);
return Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) <= __mmReach;
},
finishTurretPoke() {
this.state === "turretPoke" && this.cleanup("turret-poke-complete");
},
startTurretPoke(__mmTarget) {
if (!this.turretReady() || !__mmTarget) return !1;
this.state = "turretPoke";
__mmEquipHatNow(__mmTurretGear);
// Keep the game's aim direction on the distant target while Turret Gear
// is active. Turret Gear fires on its own cooldown; no normal attack is
// sent in this out-of-melee-range branch.
try {
O.send("D", this.aim(__mmTarget));
} catch (__mmTurretAimError) {}
// This is a best-effort troll shot: no weapon/loadout or distance gate and
// no server acknowledgement wait. Restore on the next local server tick.
this.schedule(() => this.finishTurretPoke());
return !0;
},
start(__mmOptions = {}) {
if (this.state !== "idle") return !1;
// A real R burst has priority over a scheduled friendly-shot sync and idle
// reloading, but never steals selection from an emergency action.
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
this.suspendTrapEscape();
if (
!__mmActionClaim(
"insta",
__mmOptions.betrayal
? "betrayal combo"
: __mmOptions.automatic
? "auto target"
: "R combo",
)
) {
const __mmResumeTrap = !!(
this.trapHandoff &&
this.trapHandoff.resume &&
v &&
v.alive &&
__mmIsTrapped()
);
this.trapHandoff = null;
__mmResumeTrap && __mmBreakTrap();
return !1;
}
this.state = "validate";
this.targetOptional = !!__mmOptions.targetOptional;
this.automatic = !!__mmOptions.automatic;
this.betrayal = !!__mmOptions.betrayal;
if (!this.runtimeReady()) return (this.cleanup("runtime-unavailable"), !1);
this.capture();
const __mmRequestedTarget =
__mmOptions.targetSid == null ? null : Rt(__mmOptions.targetSid),
__mmTarget =
__mmRequestedTarget &&
(__mmIsEnemyPlayer(__mmRequestedTarget) ||
(this.betrayal &&
__mmRequestedTarget !== v &&
__mmRequestedTarget.alive &&
__mmRequestedTarget.visible))
? __mmRequestedTarget
: this.betrayal
? null
: this.nearestEnemy();
if (__mmTarget) this.targetSid = __mmTarget.sid;
if (
!this.automatic &&
!this.betrayal &&
__mmInstaUiEnabled &&
__mmTarget &&
!this.canFullBurst(__mmTarget) &&
this.startTurretPoke(__mmTarget)
)
return !0;
const __mmContext = this.context(!1);
if (!__mmContext) return (this.cleanup("validation-failed"), !1);
this.primaryWeapon = __mmContext.primary;
this.state = "arm";
this.arm();
return !0;
},
canAutoStart() {
if (
!__mmAutoInstaEnabled ||
this.state !== "idle" ||
!this.runtimeReady() ||
this.isPriorityConflict()
)
return !1;
const __mmPrimary = this.supportedPrimary(),
__mmTarget = this.nearestEnemy();
if (
__mmPrimary == null ||
!__mmTarget ||
!this.inRange(__mmPrimary, __mmTarget) ||
!__mmWeaponReady(__mmPrimary)
)
return !1;
const __mmSecondary = v.weapons && v.weapons[1],
__mmSecondaryData = this.weaponData(__mmSecondary);
if (
__mmSecondary == null ||
__mmSecondary === __mmPrimary ||
__mmSecondary === __mmShieldWeapon ||
!__mmSecondaryData ||
__mmSecondaryData.shield ||
!__mmWeaponReady(__mmSecondary)
)
return !1;
return !(
v.skins &&
v.skins[__mmTurretGear] &&
!this.turretReady()
);
},
arm() {
const __mmContext = this.context(!1);
if (!__mmContext) return void this.cleanup("arm-invalid");
this.primaryWeapon = __mmContext.primary;
// Do not change gear until the target is actually in reach.
this.state = "waitForRange";
this.waitForRange();
},
waitForRange() {
if (this.state !== "waitForRange") return;
const __mmContext = this.context(!1);
if (!__mmContext) return void this.cleanup("target-or-state-lost");
this.primaryWeapon = __mmContext.primary;
if (__mmContext.target && !this.inRange(__mmContext.primary, __mmContext.target))
return void (
this.startTurretPoke(__mmContext.target) ||
this.cleanup("out-of-range")
);
// Bull and the primary are sent together. Keep the attack held for one
// tick, then send Turret Gear and aim before the secondary.
this.state = "executeBurst";
this.selectDamageGear();
this.executeBurst();
},
releaseAttack() {
if (!this.attackHeld) return;
try {
O && O.send && O.send("F", 0, null);
} catch (__mmReleaseError) {}
this.attackHeld = !1;
},
sendAttack(__mmItem, __mmIsWeapon, __mmTarget) {
if (!v || !v.alive || __mmItem == null) return !1;
this.releaseAttack();
try {
const __mmAngle = this.aim(__mmTarget);
je(__mmItem, !!__mmIsWeapon);
O.send("F", 1, __mmAngle);
this.attackHeld = !0;
return !0;
} catch (__mmAttackError) {
this.attackHeld = !1;
return !1;
}
},
executeBurst() {
if (this.state !== "executeBurst") return;
const __mmContext = this.context(!0);
if (!__mmContext)
return void this.cleanup("primary-unavailable");
if (!this.sendAttack(__mmContext.primary, !0, __mmContext.target))
return void this.cleanup("primary-send-failed");
this.schedule(() => this.executeFollowup());
},
secondaryFollowup() {
if (!v || !v.weapons) return null;
const __mmWeapon = v.weapons[1],
__mmData = this.weaponData(__mmWeapon);
return __mmWeapon != null &&
__mmWeapon !== this.primaryWeapon &&
__mmWeapon !== __mmShieldWeapon &&
__mmData &&
!__mmData.shield
? __mmWeapon
: null;
},
executeFollowup() {
if (this.state !== "executeBurst") return;
// Every swing remains down for a full authoritative tick. Release it just
// before choosing the next combo step so the following press is a fresh
// attack rather than an ignored held state.
this.releaseAttack();
// The opening hit may knock the target out of primary melee range. Keep
// the confirmed target but let the equipped secondary make its own shot.
const __mmContext = this.context(!1);
if (!__mmContext) return void this.cleanup("followup-invalid");
const __mmSecondary = this.secondaryFollowup();
if (__mmSecondary == null) return void this.cleanup("secondary-unavailable");
// Turret Gear and aim go out now; the secondary follows one fixed tick
// later, without waiting on reload or server-confirmation state.
this.pendingSecondaryWeapon = __mmSecondary;
this.selectSecondaryDamageGear();
try {
O.send("D", this.aim(__mmContext.target));
} catch (__mmSecondaryAimError) {}
return void this.schedule(() => this.fireSecondaryFollowup());
},
fireSecondaryFollowup() {
if (this.state !== "executeBurst") return;
const __mmWeapon = this.pendingSecondaryWeapon,
__mmContext = this.context(!1);
if (__mmWeapon == null || !__mmContext)
return void this.cleanup("secondary-context-lost");
if (!this.sendAttack(__mmWeapon, !0, __mmContext.target))
return void this.cleanup("secondary-send-failed");
// Hold the secondary swing for one game tick, then restore the pre-R
// weapon and gear. No reload-state polling or extra build follow-up.
((this.pendingSecondaryWeapon = null),
this.schedule(() => this.cleanup("complete")));
},
cleanup(__mmReason) {
const __mmSnapshot = this.snapshot,
__mmCompletedFullInsta = __mmReason === "complete",
__mmRestore = __mmActionMayRestore("insta"),
__mmResumeTrap = !!(
this.trapHandoff &&
this.trapHandoff.resume &&
__mmTrapEscapeEnabled &&
v &&
v.alive &&
__mmIsTrapped()
);
this.state = "cleanup";
this.timer && clearTimeout(this.timer);
this.timer = 0;
this.releaseAttack();
if (v && v.alive && __mmSnapshot && __mmRestore) {
__mmEquipGearPair(__mmSnapshot.hat, __mmSnapshot.tail, !0);
__mmSnapshot.weapon != null && __mmRestoreWeapon(__mmSnapshot.weapon);
(__mmSnapshot.primaryHeld || __mmSnapshot.secondaryHeld) &&
(__mmPrimaryHeld || __mmSecondaryHeld) &&
__mmResumeHeldAttack();
}
this.snapshot = null;
this.targetSid = null;
this.targetOptional = !1;
this.automatic = !1;
this.betrayal = !1;
this.primaryWeapon = null;
this.pendingSecondaryWeapon = null;
this.trapHandoff = null;
this.reason = __mmReason || "cancelled";
this.state = "idle";
__mmActionRelease("insta", this.reason);
__mmCompletedFullInsta && __mmSendChat("Meow!");
// These loops were gated while the burst owned gear/selection. Run their
// normal updates now instead of changing their user-configured toggles.
if (v && v.alive) {
__mmResumeTrap && __mmBreakTrap();
__mmUpdateMovementGear();
__mmUpdateSoldier();
__mmUpdateWeaponRecharge();
__mmAutoHeal();
}
},
cancel(__mmReason) {
this.cleanup(__mmReason || "cancelled");
},
};
function __mmNearestBetrayalTarget() {
if (!v || !v.alive || !Array.isArray(E) || __mmTeamKey(v) == null)
return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
String(__mmPlayer.sid) === String(v.sid) ||
!__mmSameTeam(__mmPlayer) ||
__mmIsFriendPlayer(__mmPlayer) ||
!Number.isFinite(Number(__mmPlayer.x)) ||
!Number.isFinite(Number(__mmPlayer.y))
)
continue;
const __mmDistance =
(__mmPlayer.x - v.x) ** 2 + (__mmPlayer.y - v.y) ** 2;
if (__mmDistance < __mmClosestDistance)
((__mmClosest = __mmPlayer), (__mmClosestDistance = __mmDistance));
}
return __mmClosest;
}
function __mmBetrayalInstaReady(__mmTarget) {
if (
!__mmInstaUiEnabled ||
!__mmTarget ||
__mmInsta.state !== "idle" ||
!__mmInsta.runtimeReady() ||
__mmIsTrapped() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
Date.now() < __mmAntiInstaUntil ||
__mmInsta.isEmergencyHealth() ||
!__mmActionAvailable("insta")
)
return !1;
const __mmPrimary = __mmInsta.supportedPrimary();
if (
__mmPrimary == null ||
!__mmWeaponReady(__mmPrimary) ||
!__mmInsta.inRange(__mmPrimary, __mmTarget)
)
return !1;
const __mmSecondary = v.weapons && v.weapons[1],
__mmSecondaryData = __mmInsta.weaponData(__mmSecondary);
if (
__mmSecondary == null ||
__mmSecondary === __mmPrimary ||
__mmSecondary === __mmShieldWeapon ||
!__mmSecondaryData ||
__mmSecondaryData.shield ||
!__mmWeaponReady(__mmSecondary)
)
return !1;
return !(
v.skins &&
v.skins[__mmTurretGear] &&
!__mmInsta.turretReady()
);
}
function __mmStartBetrayalInsta() {
const __mmTarget = __mmNearestBetrayalTarget();
if (!__mmTarget) return !1;
__mmActionOwner === "matThief" &&
__mmFinishMatThief("betrayal insta");
__mmActionOwner === "mobSteal" &&
__mmFinishMobSteal("betrayal insta");
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmBetrayalInstaReady(__mmTarget)) return !1;
// Send leave first and deliberately assume success. The betrayal target flag
// keeps this exact former teammate valid until the combo finishes, avoiding
// any wait for the server's team-state acknowledgement.
O.send("N");
return __mmInsta.start({ targetSid: __mmTarget.sid, betrayal: !0 });
}
function __mmTeamKey(__mmPlayer) {
if (!__mmPlayer) return null;
const __mmTeam = __mmPlayer.team;
return typeof __mmTeam === "number"
? __mmTeam > 0
? "n:" + __mmTeam
: null
: typeof __mmTeam === "string" && __mmTeam.trim()
? "s:" + __mmTeam
: null;
}
function __mmNormalizeFriendName(__mmName) {
return typeof __mmName === "string"
? __mmName.trim().slice(0, 15).toLowerCase()
: "";
}
function __mmFriendDisplayName(__mmName) {
return typeof __mmName === "string" ? __mmName.trim().slice(0, 15) : "";
}
function __mmIsFriendPlayer(__mmPlayer) {
const __mmKey = __mmNormalizeFriendName(__mmPlayer && __mmPlayer.name);
return !!(
__mmKey &&
__mmFriendNames.has(__mmKey) &&
!__mmFriendEnemies.has(__mmKey)
);
}
function __mmDispatchFriendState(__mmType, __mmName) {
window.dispatchEvent(
new CustomEvent("MooMooFriendState", {
detail: { type: __mmType, name: __mmName },
}),
);
}
function __mmAddFriend(__mmName, __mmAnnounce) {
const __mmDisplay = __mmFriendDisplayName(__mmName),
__mmKey = __mmNormalizeFriendName(__mmDisplay);
if (!__mmKey) return !1;
(__mmFriendNames.set(__mmKey, __mmDisplay),
__mmFriendEnemies.delete(__mmKey),
__mmDispatchFriendState("add", __mmDisplay),
__mmAnnounce && __mmSendChat("Added friend, " + __mmDisplay + "!"),
__mmPublishHudState());
return !0;
}
function __mmRemoveFriend(__mmName, __mmAnnounce) {
const __mmKey = __mmNormalizeFriendName(__mmName),
__mmDisplay =
__mmFriendNames.get(__mmKey) || __mmFriendDisplayName(__mmName);
if (!__mmKey || !__mmDisplay) return !1;
(__mmFriendNames.delete(__mmKey),
__mmFriendEnemies.add(__mmKey),
delete __mmFriendAttackWindows[__mmKey],
__mmDispatchFriendState("remove", __mmDisplay),
__mmAnnounce && __mmSendChat(__mmDisplay + " is an enemy!"),
__mmPublishHudState());
return !0;
}
function __mmFriendPickNotice(__mmMessage) {
window.dispatchEvent(
new CustomEvent("MooMooFriendPickNotice", {
detail: String(__mmMessage || ""),
}),
);
}
function __mmArmFriendPick(__mmMode) {
if (!v || !v.alive) return !1;
const __mmNext =
__mmMode === "friend" || __mmMode === "enemy" ? __mmMode : null;
if (__mmFriendPickMode === __mmNext) {
(__mmFriendPickMode = null,
__mmFriendPickNotice("Player selection cancelled"));
return !1;
}
__mmFriendPickMode = __mmNext;
__mmFriendPickNotice(
__mmNext === "friend"
? "Click a player to add friend"
: "Click a player to mark enemy",
);
return !0;
}
function __mmPlayerAtFriendPick(__mmEvent) {
if (!v || !v.alive || !Array.isArray(E) || !__mmEvent) return null;
const __mmSurface =
document.getElementById("gameCanvas") ||
(__mmEvent.target instanceof Element
? __mmEvent.target.closest("#gameCanvas,#touch-controls-fullscreen")
: null),
__mmRect =
__mmSurface && typeof __mmSurface.getBoundingClientRect === "function"
? __mmSurface.getBoundingClientRect()
: null;
if (!__mmRect || __mmRect.width <= 0 || __mmRect.height <= 0) return null;
const __mmViewportWidth = Math.max(1, Number(_) || Number(De) || __mmRect.width),
__mmViewportHeight = Math.max(1, Number(L) || Number(Ae) || __mmRect.height),
__mmLeft = Number(oe) - __mmViewportWidth / 2,
__mmTop = Number(ae) - __mmViewportHeight / 2;
let __mmBest = null,
__mmBestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
String(__mmPlayer.sid) === String(v.sid)
)
continue;
const __mmScreenX =
__mmRect.left +
((Number(__mmPlayer.x) - __mmLeft) / __mmViewportWidth) *
__mmRect.width,
__mmScreenY =
__mmRect.top +
((Number(__mmPlayer.y) - __mmTop) / __mmViewportHeight) *
__mmRect.height,
__mmDistance = Math.hypot(
Number(__mmEvent.clientX) - __mmScreenX,
Number(__mmEvent.clientY) - __mmScreenY,
),
__mmHitRadius = Math.max(
24,
((Number(__mmPlayer.scale) || 35) / __mmViewportWidth) *
__mmRect.width +
16,
);
if (__mmDistance <= __mmHitRadius && __mmDistance < __mmBestDistance)
((__mmBest = __mmPlayer), (__mmBestDistance = __mmDistance));
}
return __mmBest;
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (!__mmFriendPickMode || !__mmIsGameClick(__mmEvent)) return;
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
__mmCleanupActive && __mmStopCleanup("friend selection click", !1);
const __mmPlayer = __mmPlayerAtFriendPick(__mmEvent);
if (!__mmPlayer) {
__mmFriendPickNotice("No player there - click again");
return;
}
const __mmMode = __mmFriendPickMode;
__mmFriendPickMode = null;
if (__mmMode === "friend") {
(__mmAddFriend(__mmPlayer.name, !0),
__mmFriendPickNotice("Friend: " + __mmPlayer.name));
} else {
(__mmRemoveFriend(__mmPlayer.name, !0),
__mmFriendPickNotice("Enemy: " + __mmPlayer.name));
}
},
!0,
);
window.addEventListener("blur", function () {
__mmFriendPickMode = null;
});
function __mmReplaceFriends(__mmNames) {
const __mmPrevious = Array.from(__mmFriendNames.keys()),
__mmNext = new Map();
if (Array.isArray(__mmNames)) {
for (let __mmIndex = 0; __mmIndex < __mmNames.length; __mmIndex++) {
const __mmDisplay = __mmFriendDisplayName(__mmNames[__mmIndex]),
__mmKey = __mmNormalizeFriendName(__mmDisplay);
__mmKey && !__mmNext.has(__mmKey) && __mmNext.set(__mmKey, __mmDisplay);
if (__mmNext.size >= 30) break;
}
}
__mmFriendNames.clear();
__mmNext.forEach(function (__mmDisplay, __mmKey) {
(__mmFriendNames.set(__mmKey, __mmDisplay),
__mmFriendEnemies.delete(__mmKey));
});
for (let __mmIndex = 0; __mmIndex < __mmPrevious.length; __mmIndex++)
__mmNext.has(__mmPrevious[__mmIndex]) ||
__mmFriendEnemies.add(__mmPrevious[__mmIndex]);
}
function __mmFriendAttackAimedAtUs(__mmPlayer, __mmWeapon) {
if (!v || !v.alive || !__mmPlayer || !__mmPlayer.alive) return !1;
const __mmWeaponId =
__mmWeapon == null ? __mmPlayer.weaponIndex : Number(__mmWeapon),
__mmWeaponData = b.weapons && b.weapons[__mmWeaponId],
__mmAttackAngle = Number(__mmPlayer.dir),
__mmTargetAngle = Math.atan2(v.y - __mmPlayer.y, v.x - __mmPlayer.x),
__mmAngleDifference = Math.abs(
Math.atan2(
Math.sin(__mmAttackAngle - __mmTargetAngle),
Math.cos(__mmAttackAngle - __mmTargetAngle),
),
),
__mmDistance = Math.hypot(v.x - __mmPlayer.x, v.y - __mmPlayer.y),
__mmReach = __mmWeaponData
? __mmWeaponData.projectile != null
? 900
: (Number(__mmWeaponData.range) || 0) +
(Number(__mmPlayer.scale) || 35) +
(Number(v.scale) || 35) +
45
: 220;
return __mmAngleDifference <= 0.72 && __mmDistance <= __mmReach;
}
function __mmObserveFriendAttack(__mmPlayerSid, __mmDidHit, __mmWeapon) {
const __mmPlayer = Rt(__mmPlayerSid);
if (!__mmIsFriendPlayer(__mmPlayer)) return;
const __mmKey = __mmNormalizeFriendName(__mmPlayer.name);
if (!__mmFriendAttackAimedAtUs(__mmPlayer, __mmWeapon)) return;
const __mmNow = Date.now(),
__mmWeaponId =
__mmWeapon == null ? Number(__mmPlayer.weaponIndex) : Number(__mmWeapon),
__mmWindow =
__mmFriendAttackWindows[__mmKey] ||
(__mmFriendAttackWindows[__mmKey] = {
lastAt: 0,
lastWeapon: null,
lastAimedAt: 0,
damageStartedAt: 0,
damage: 0,
}),
__mmRapidDistinct =
__mmWindow.lastAt > 0 &&
__mmNow - __mmWindow.lastAt <= Math.max(300, __mmServerTickMs() * 3) &&
__mmWindow.lastWeapon != null &&
__mmWindow.lastWeapon !== __mmWeaponId &&
([__mmShortSword, __mmKatana, __mmPolearmWeapon].includes(__mmWeaponId) ||
[__mmShortSword, __mmKatana, __mmPolearmWeapon].includes(
__mmWindow.lastWeapon,
)),
__mmInstaPrimary = [
__mmShortSword,
__mmKatana,
__mmPolearmWeapon,
].includes(__mmWeaponId),
__mmInstaGear =
Number(__mmPlayer.skinIndex) === 7 ||
Number(__mmPlayer.skinIndex) === __mmTurretGear;
((__mmWindow.lastAt = __mmNow),
(__mmWindow.lastWeapon = __mmWeaponId),
(__mmWindow.lastAimedAt = __mmNow));
(__mmRapidDistinct || (__mmInstaPrimary && __mmInstaGear)) &&
__mmRemoveFriend(__mmPlayer.name, !0);
}
function __mmObserveFriendDamage(__mmDamage) {
if (!(Number(__mmDamage) > 0) || !v || !v.alive) return;
const __mmNow = Date.now();
let __mmBestKey = "",
__mmBestAt = 0;
__mmFriendNames.forEach(function (__mmDisplay, __mmKey) {
const __mmWindow = __mmFriendAttackWindows[__mmKey];
if (
__mmWindow &&
__mmNow - __mmWindow.lastAimedAt <= 850 &&
__mmWindow.lastAimedAt > __mmBestAt
)
((__mmBestKey = __mmKey), (__mmBestAt = __mmWindow.lastAimedAt));
});
if (!__mmBestKey) return;
const __mmWindow = __mmFriendAttackWindows[__mmBestKey];
if (
!__mmWindow.damageStartedAt ||
__mmNow - __mmWindow.damageStartedAt > 1200
)
((__mmWindow.damageStartedAt = __mmNow), (__mmWindow.damage = 0));
__mmWindow.damage += Number(__mmDamage);
__mmWindow.damage > 20 &&
__mmRemoveFriend(__mmFriendNames.get(__mmBestKey), !0);
}
function __mmSameTeam(__mmPlayer) {
const __mmOwnTeam = __mmTeamKey(v),
__mmOtherTeam = __mmTeamKey(__mmPlayer);
return (
__mmOwnTeam != null &&
__mmOtherTeam != null &&
__mmOwnTeam === __mmOtherTeam
);
}
function __mmIsEnemyPlayer(__mmPlayer) {
const __mmFriendKey = __mmNormalizeFriendName(
__mmPlayer && __mmPlayer.name,
),
__mmBetrayedFriend =
!!__mmFriendKey && __mmFriendEnemies.has(__mmFriendKey);
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
(Number.isFinite(Number(__mmPlayer.health)) &&
Number(__mmPlayer.health) <= 0) ||
!v ||
!v.alive ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid
)
return !1;
if (
!__mmBetrayedFriend &&
(__mmSameTeam(__mmPlayer) || __mmIsFriendPlayer(__mmPlayer))
)
return !1;
const __mmOwnTeam = __mmTeamKey(v),
__mmOtherTeam = __mmTeamKey(__mmPlayer);
if (__mmOwnTeam != null && __mmOtherTeam == null) {
const __mmSid = String(__mmPlayer.sid),
__mmNow = Date.now(),
__mmSeen =
__mmUnknownTeamSeen[__mmSid] ||
(__mmUnknownTeamSeen[__mmSid] = __mmNow);
return __mmNow - __mmSeen >= __mmUnknownTeamGraceMs;
}
return !0;
}
function __mmSyncPost(__mmMessage) {
if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
const __mmPacket = {
...__mmMessage,
sender: __mmSyncTabId,
leaderSid: v.sid,
sentAt: Date.now(),
};
try {
__mmSyncChannel && __mmSyncChannel.postMessage(__mmPacket);
} catch (__mmSyncPostError) {}
try {
window.dispatchEvent(
new CustomEvent("MooMooTabSyncOutbound", {
detail: JSON.stringify(__mmPacket),
}),
);
} catch (__mmSyncBridgeError) {}
}
function __mmSetSyncStatus(__mmStatus) {
if (__mmSyncStatus === __mmStatus) return;
((__mmSyncStatus = __mmStatus),
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomStatus", {
detail: "Sync: " + __mmStatus,
}),
));
}
function __mmSyncBroadcastState() {
if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
const __mmAim = Ci(),
__mmAimDistance = 1800,
__mmState = {
type: "state",
x: v.x,
y: v.y,
aimX: v.x + Math.cos(__mmAim) * __mmAimDistance,
aimY: v.y + Math.sin(__mmAim) * __mmAimDistance,
};
(__mmSyncPost(__mmState),
// BroadcastChannel is the fast path. This small storage-event fallback
// still lets a second same-origin tab acquire the leader when a browser
// has isolated the injected bundle's BroadcastChannel context.
(() => {
try {
localStorage.setItem(
__mmSyncStorageKey,
JSON.stringify({
...__mmState,
sender: __mmSyncTabId,
leaderSid: v.sid,
sentAt: Date.now(),
}),
);
} catch (__mmSyncStorageWriteError) {}
})());
}
function __mmSyncLeaderPlayer(__mmMessage) {
const __mmState = __mmSyncLeaderState;
if (
!__mmSyncFollowerEnabled ||
!v ||
!v.alive ||
!__mmState ||
Date.now() - __mmState.receivedAt > 800 ||
(__mmMessage &&
(__mmMessage.sender !== __mmState.sender ||
String(__mmMessage.leaderSid) !== String(__mmState.leaderSid)))
)
return null;
const __mmLeader = Rt(__mmState.leaderSid);
if (
__mmLeader &&
__mmLeader.alive &&
__mmLeader !== v &&
String(__mmLeader.sid) === String(__mmState.leaderSid)
)
return __mmLeader;
// The player list only includes players the local client currently knows
// about. Keep following the explicitly enabled local leader while they are
// off-screen, then switch to their authoritative in-match position as soon
// as the follower can see them.
return Number.isFinite(Number(__mmState.x)) &&
Number.isFinite(Number(__mmState.y))
? __mmState
: null;
}
function __mmSyncStopFollowMovement() {
if (!__mmSyncMoveActive) return;
((__mmSyncMoveActive = !1), (Kt = null), Tt());
}
function __mmSyncFollowTick() {
if (!__mmSyncFollowerEnabled || !v || !v.alive)
return void __mmSyncStopFollowMovement();
const __mmLeader = __mmSyncLeaderPlayer();
if (!__mmLeader)
return (__mmSetSyncStatus("waiting for leader"), void __mmSyncStopFollowMovement());
__mmSetSyncStatus("following");
// Target a small rotating offset around the leader instead of their exact
// center. That keeps the companion close without colliding or pushing them.
const __mmOrbitRadius = (v.scale || 35) + (__mmLeader.scale || 35) + 30,
__mmOrbit = (Date.now() / 680 + 0.85) % (Math.PI * 2),
__mmTargetX = __mmLeader.x + Math.cos(__mmOrbit) * __mmOrbitRadius,
__mmTargetY = __mmLeader.y + Math.sin(__mmOrbit) * __mmOrbitRadius,
__mmDx = __mmTargetX - v.x,
__mmDy = __mmTargetY - v.y;
if (__mmDx * __mmDx + __mmDy * __mmDy < 64)
return void __mmSyncStopFollowMovement();
const __mmDirection = Math.atan2(__mmDy, __mmDx);
(O.send("9", __mmDirection),
(Kt = __mmDirection),
(__mmSyncMoveActive = !0));
}
function __mmSyncOwnsSelection(__mmItem, __mmIsWeapon) {
return !!(
v &&
v.alive &&
Number.isFinite(Number(__mmItem)) &&
(__mmIsWeapon
? v.weapons && v.weapons.includes(__mmItem)
: v.items && v.items.includes(__mmItem))
);
}
function __mmSyncHandleMessage(__mmEvent) {
const __mmMessage = __mmEvent && __mmEvent.data;
if (
!__mmSyncFollowerEnabled ||
!__mmMessage ||
__mmMessage.sender === __mmSyncTabId ||
typeof __mmMessage !== "object"
)
return;
if (__mmMessage.type === "state") {
const __mmLeader = Rt(__mmMessage.leaderSid);
if (
v &&
String(__mmMessage.leaderSid) !== String(v.sid) &&
Number.isFinite(Number(__mmMessage.x)) &&
Number.isFinite(Number(__mmMessage.y))
) {
// The role is explicitly enabled in both local tabs. Do not require the
// leader to be visible before following, otherwise two far-apart spawns
// can never meet. When visible, the live player object is preferred.
__mmSyncLeaderState = {
...__mmMessage,
x:
__mmLeader && __mmLeader.alive ? __mmLeader.x : Number(__mmMessage.x),
y:
__mmLeader && __mmLeader.alive ? __mmLeader.y : Number(__mmMessage.y),
receivedAt: Date.now(),
};
__mmSyncFollowTick();
}
return;
}
const __mmLeader = __mmSyncLeaderPlayer(__mmMessage);
if (!__mmLeader) return;
if (__mmMessage.type === "selection") {
if (!__mmSyncOwnsSelection(__mmMessage.item, !!__mmMessage.isWeapon)) {
__mmSyncSelectionBlockedUntil = Date.now() + 900;
return;
}
((__mmSyncSelectionBlockedUntil = 0),
je(__mmMessage.item, !!__mmMessage.isWeapon));
return;
}
if (__mmMessage.type === "gear") {
__mmMessage.tail
? __mmEquipTailNow(__mmMessage.item)
: __mmEquipHatNow(__mmMessage.item);
return;
}
if (__mmMessage.type === "gearPair") {
__mmEquipGearPair(__mmMessage.hat, __mmMessage.tail, !0);
return;
}
if (
__mmMessage.type !== "attack" ||
Date.now() < __mmSyncSelectionBlockedUntil
)
return;
const __mmAimX = Number(__mmMessage.aimX),
__mmAimY = Number(__mmMessage.aimY),
__mmAngle =
Number.isFinite(__mmAimX) && Number.isFinite(__mmAimY)
? Math.atan2(__mmAimY - v.y, __mmAimX - v.x)
: Ci();
O.send("F", __mmMessage.state ? 1 : 0, __mmAngle);
}
function __mmSyncPublishSelection(__mmItem, __mmIsWeapon) {
__mmSyncPost({
type: "selection",
item: __mmItem,
isWeapon: !!__mmIsWeapon,
});
}
function __mmSyncPublishGear(__mmItem, __mmTail) {
__mmSyncPost({ type: "gear", item: __mmItem, tail: !!__mmTail });
}
function __mmSyncPublishGearPair(__mmHat, __mmTail) {
__mmSyncPost({ type: "gearPair", hat: __mmHat, tail: __mmTail });
}
function __mmSyncObserveSocketSend(__mmArguments) {
if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
if (__mmArguments[0] === "c") {
if (__mmSyncGearPairDispatch) return;
__mmSyncPublishGear(__mmArguments[2], !!__mmArguments[3]);
return;
}
if (__mmArguments[0] !== "F") return;
const __mmAngle = Number(__mmArguments[2]),
__mmDirection = Number.isFinite(__mmAngle) ? __mmAngle : Ci(),
__mmAimDistance = 1800;
__mmSyncPost({
type: "attack",
state: __mmArguments[1] ? 1 : 0,
aimX: v.x + Math.cos(__mmDirection) * __mmAimDistance,
aimY: v.y + Math.sin(__mmDirection) * __mmAimDistance,
});
}
function __mmUpdateTabSync() {
__mmSyncLeaderEnabled && __mmSyncBroadcastState();
__mmSyncFollowerEnabled && __mmSyncFollowTick();
}
function __mmStartTabSync() {
(__mmUpdateTabSync(),
__mmSyncTimer ||
(__mmSyncTimer = setInterval(__mmUpdateTabSync, __mmFastCheckMs())));
}
function __mmStopTabSync() {
if (__mmSyncLeaderEnabled || __mmSyncFollowerEnabled) return;
(__mmSyncTimer && clearInterval(__mmSyncTimer),
(__mmSyncTimer = 0),
(__mmSyncLeaderState = null),
(__mmSyncSelectionBlockedUntil = 0),
__mmSyncStopFollowMovement());
}
function __mmSetSyncLeader(__mmEnabled) {
((__mmSyncLeaderEnabled = !!__mmEnabled),
__mmSyncLeaderEnabled && (__mmSyncFollowerEnabled = !1),
__mmSyncLeaderEnabled ? __mmStartTabSync() : __mmStopTabSync(),
__mmSetSyncStatus(__mmSyncLeaderEnabled ? "broadcasting" : "off"),
__mmPublishHudState());
}
function __mmSetSyncFollower(__mmEnabled) {
((__mmSyncFollowerEnabled = !!__mmEnabled),
__mmSyncFollowerEnabled && (__mmSyncLeaderEnabled = !1),
__mmSyncFollowerEnabled ? __mmStartTabSync() : __mmStopTabSync(),
__mmSetSyncStatus(__mmSyncFollowerEnabled ? "waiting for leader" : "off"),
__mmPublishHudState());
}
__mmSyncChannel && __mmSyncChannel.addEventListener("message", __mmSyncHandleMessage);
window.addEventListener("storage", function (__mmStorageEvent) {
if (!__mmStorageEvent || __mmStorageEvent.key !== __mmSyncStorageKey) return;
try {
__mmStorageEvent.newValue &&
__mmSyncHandleMessage({ data: JSON.parse(__mmStorageEvent.newValue) });
} catch (__mmSyncStorageReadError) {}
});
window.addEventListener("MooMooTabSyncInbound", function (__mmSyncBridgeEvent) {
try {
typeof __mmSyncBridgeEvent.detail === "string" &&
__mmSyncHandleMessage({ data: JSON.parse(__mmSyncBridgeEvent.detail) });
} catch (__mmSyncBridgeReadError) {}
});
function __mmDrawPredictionGhost(__mmLeft, __mmTop) {
if (!__mmPredictionGhostEnabled || !v || !v.alive) return;
const __mmNow = Date.now();
if (__mmPredictionLastX == null || __mmPredictionLastY == null) {
((__mmPredictionLastX = v.x),
(__mmPredictionLastY = v.y),
(__mmPredictionLastAt = __mmNow));
return;
}
const __mmElapsed = Math.max(
1,
Math.min(120, __mmNow - __mmPredictionLastAt),
),
__mmPing = Number(window.pingTime),
__mmLeadMs = Number.isFinite(__mmPing)
? Math.max(0, Math.min(1e3, __mmPing * 0.5))
: 0,
__mmPredictedX = Math.max(
0,
Math.min(
y.mapScale,
v.x + ((v.x - __mmPredictionLastX) / __mmElapsed) * __mmLeadMs,
),
),
__mmPredictedY = Math.max(
0,
Math.min(
y.mapScale,
v.y + ((v.y - __mmPredictionLastY) / __mmElapsed) * __mmLeadMs,
),
);
((__mmPredictionLastX = v.x),
(__mmPredictionLastY = v.y),
(__mmPredictionLastAt = __mmNow));
const __mmScreenX = __mmPredictedX - __mmLeft,
__mmScreenY = __mmPredictedY - __mmTop;
if (
__mmScreenX < -(v.scale || 35) ||
__mmScreenX > _ + (v.scale || 35) ||
__mmScreenY < -(v.scale || 35) ||
__mmScreenY > L + (v.scale || 35)
)
return;
(k.save(),
(k.globalAlpha = 0.3),
k.translate(__mmScreenX, __mmScreenY),
k.rotate(Ci() + v.dirPlus),
Dl(v, k),
k.restore());
}
function __mmDrawEsp() {
if (!v || !v.alive || !k) return;
try {
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2;
__mmDrawPredictionGhost(__mmLeft, __mmTop);
if (
(!__mmEspEnabled && !__mmEspLinesEnabled) ||
!Array.isArray(E) ||
!Array.isArray(N)
)
return;
const __mmOwnX = v.x - __mmLeft,
__mmOwnY = v.y - __mmTop;
(k.save(), (k.globalAlpha = 0.72));
if (__mmEspLinesEnabled) {
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid
)
continue;
const __mmFriendly =
__mmIsFriendPlayer(__mmPlayer) || __mmSameTeam(__mmPlayer),
__mmColor = __mmIsFriendPlayer(__mmPlayer)
? "#facc15"
: __mmSameTeam(__mmPlayer)
? "#a855f7"
: "#ff4d5d",
__mmX = __mmPlayer.x - __mmLeft,
__mmY = __mmPlayer.y - __mmTop;
((k.lineWidth = __mmFriendly ? 1.5 : 3.5),
(k.strokeStyle = __mmColor),
k.beginPath(),
k.moveTo(__mmOwnX, __mmOwnY),
k.lineTo(__mmX, __mmY),
k.stroke());
}
}
if (__mmEspEnabled) {
((k.lineWidth = 2), (k.globalAlpha = 0.9));
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid
)
continue;
const __mmColor = __mmIsFriendPlayer(__mmPlayer)
? "#facc15"
: __mmSameTeam(__mmPlayer)
? "#a855f7"
: "#ff4d5d";
((k.strokeStyle = __mmColor),
k.beginPath(),
k.arc(
__mmPlayer.x - __mmLeft,
__mmPlayer.y - __mmTop,
Math.max(10, (__mmPlayer.scale || 35) + 5),
0,
Math.PI * 2,
),
k.stroke());
}
k.strokeStyle = "#48df79";
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
const __mmAnimal = N[__mmIndex];
if (!__mmAnimal || !__mmAnimal.active || !__mmAnimal.visible) continue;
(k.beginPath(),
k.arc(
__mmAnimal.x - __mmLeft,
__mmAnimal.y - __mmTop,
Math.max(9, (__mmAnimal.scale || 35) + 4),
0,
Math.PI * 2,
),
k.stroke());
}
}
k.restore();
} catch (__mmError) {
try {
k && k.restore();
} catch (__mmIgnore) {}
}
}
const __mmStructureTintCache = Object.create(null);
function __mmOwnStructure(__mmObject) {
if (!v || !__mmObject || !__mmObject.owner) return !1;
const __mmOwner = __mmObject.owner,
__mmOwnerSid = __mmOwner.sid;
return !!(
__mmOwner === v ||
(__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
);
}
function __mmTintableStructure(__mmObject) {
const __mmItem = __mmObject && b && b.list && b.list[__mmObject.id],
__mmName = String(__mmItem && __mmItem.name || "").toLowerCase();
return !!(
__mmObject &&
__mmObject.isItem &&
(__mmOwnStructure(__mmObject) ||
__mmName.includes("spikes") ||
__mmName === "turret" ||
__mmName === "pit trap")
);
}
function __mmFriendlyStructure(__mmObject) {
if (!v || !__mmObject || !__mmObject.owner) return !1;
const __mmOwner = __mmObject.owner,
__mmOwnerSid = __mmOwner.sid;
if (__mmOwnStructure(__mmObject)) return !0;
if (__mmSameTeam(__mmOwner)) return !0;
const __mmOwnerPlayer = typeof Rt === "function" ? Rt(__mmOwnerSid) : null;
return !!(__mmOwnerPlayer && __mmSameTeam(__mmOwnerPlayer));
}
function __mmTintedStructureSprite(__mmObject, __mmRelationship) {
const __mmBase = Di(__mmObject),
__mmKind =
__mmRelationship === "own"
? "own"
: __mmRelationship === "friendly" || __mmRelationship === !0
? "friendly"
: "enemy",
__mmColor =
__mmKind === "own"
? "#d8b4fe"
: __mmKind === "friendly"
? "#a855f7"
: "#ef233c",
__mmKey = String(__mmObject.id) + ":" + __mmColor + ":" +
__mmBase.width + "x" + __mmBase.height;
let __mmTinted = __mmStructureTintCache[__mmKey];
if (__mmTinted) return __mmTinted;
__mmTinted = document.createElement("canvas");
__mmTinted.width = __mmBase.width;
__mmTinted.height = __mmBase.height;
const __mmContext = __mmTinted.getContext("2d");
(__mmContext.drawImage(__mmBase, 0, 0),
(__mmContext.globalCompositeOperation = "source-atop"),
(__mmContext.globalAlpha = __mmKind === "own" ? 0.7 : 0.8),
(__mmContext.fillStyle = __mmColor),
__mmContext.fillRect(0, 0, __mmTinted.width, __mmTinted.height),
(__mmContext.globalCompositeOperation = "source-over"),
(__mmContext.globalAlpha = 0.34),
__mmContext.drawImage(__mmBase, 0, 0));
__mmStructureTintCache[__mmKey] = __mmTinted;
return __mmTinted;
}
function __mmDrawStructureTints(__mmLayer, __mmLeft, __mmTop) {
if (!v || !v.alive || !Array.isArray(ge)) return;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmObject = ge[__mmIndex];
if (
!__mmObject ||
!__mmObject.active ||
__mmObject.layer !== __mmLayer ||
!__mmTintableStructure(__mmObject)
)
continue;
const __mmX = __mmObject.x + __mmObject.xWiggle - __mmLeft,
__mmY = __mmObject.y + __mmObject.yWiggle - __mmTop;
if (!ts(__mmX, __mmY, __mmObject.scale + (__mmObject.blocker || 0))) continue;
const __mmRelationship = __mmOwnStructure(__mmObject)
? "own"
: __mmFriendlyStructure(__mmObject)
? "friendly"
: "enemy",
__mmSprite = __mmTintedStructureSprite(
__mmObject,
__mmRelationship,
);
(k.save(),
(k.globalAlpha = __mmObject.hideFromEnemy ? 0.76 : 0.9),
k.translate(__mmX, __mmY),
k.rotate(__mmObject.dir),
k.drawImage(__mmSprite, -__mmSprite.width / 2, -__mmSprite.height / 2),
k.restore());
}
}
function __mmDrawAutoSpikeSpamGhost() {
const __mmGhost = __mmAutoSpikeSpamGhost,
__mmData = __mmGhost && b && b.list && b.list[__mmGhost.item];
if (!v || !v.alive || !__mmGhost || !__mmData || !k) return;
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2,
__mmX = __mmGhost.x - __mmLeft,
__mmY = __mmGhost.y - __mmTop;
if (!ts(__mmX, __mmY, __mmGhost.scale + 12)) return;
const __mmSprite = __mmTintedStructureSprite(__mmData, "friendly");
(k.save(),
(k.globalAlpha = 0.42),
k.translate(__mmX, __mmY),
k.rotate(__mmGhost.angle),
k.drawImage(
__mmSprite,
-__mmSprite.width / 2,
-__mmSprite.height / 2,
),
k.rotate(-__mmGhost.angle),
(k.globalAlpha = 0.9),
(k.strokeStyle = "#c084fc"),
(k.lineWidth = 2),
k.setLineDash([5, 4]),
k.beginPath(),
k.arc(0, 0, __mmGhost.scale + 3, 0, Math.PI * 2),
k.stroke(),
k.restore());
}
function __mmBreakableState(__mmObject) {
if (!__mmObject || !Number.isFinite(Number(__mmObject.health))) return null;
const __mmBaseHealth = Number(__mmObject.health);
if (__mmBaseHealth <= 0) return null;
let __mmState = __mmBreakableHealth.get(__mmObject);
if (
!__mmState ||
String(__mmState.sid) !== String(__mmObject.sid) ||
__mmState.baseHealth !== __mmBaseHealth
) {
__mmState = {
sid: __mmObject.sid,
baseHealth: __mmBaseHealth,
health: __mmBaseHealth,
};
__mmBreakableHealth.set(__mmObject, __mmState);
}
return __mmState;
}
function __mmPlayerHatData(__mmPlayer) {
if (!__mmPlayer || !Array.isArray(Ze)) return null;
for (let __mmIndex = 0; __mmIndex < Ze.length; __mmIndex++)
if (Ze[__mmIndex].id === __mmPlayer.skinIndex) return Ze[__mmIndex];
return null;
}
function __mmToolCooldownDuration(__mmPlayer, __mmWeaponId) {
const __mmWeapon = b && b.weapons && b.weapons[__mmWeaponId];
if (!__mmWeapon) return 0;
const __mmBaseSpeed = Number(__mmWeapon.speed),
__mmHat = __mmPlayerHatData(__mmPlayer),
__mmHatSpeed = Number(__mmHat && __mmHat.atkSpd),
__mmMultiplier = Number.isFinite(__mmHatSpeed) && __mmHatSpeed > 0
? __mmHatSpeed
: 1;
return Number.isFinite(__mmBaseSpeed) && __mmBaseSpeed > 0
? Math.max(1, __mmBaseSpeed * __mmMultiplier)
: 0;
}
function __mmTrackPlayerToolCooldown(__mmPlayerSid, __mmWeaponId) {
if (__mmPlayerSid == null) return;
let __mmPlayer = null;
try {
__mmPlayer = Rt(__mmPlayerSid);
} catch (__mmLookupError) {}
if (
!__mmPlayer &&
v &&
v.sid != null &&
String(v.sid) === String(__mmPlayerSid)
)
__mmPlayer = v;
const __mmResolvedWeapon = Number(
__mmWeaponId == null && __mmPlayer
? __mmPlayer.weaponIndex
: __mmWeaponId,
),
__mmDuration = __mmToolCooldownDuration(
__mmPlayer,
__mmResolvedWeapon,
);
if (!Number.isInteger(__mmResolvedWeapon) || !__mmDuration) return;
const __mmKey = String(__mmPlayerSid),
__mmNow = Date.now(),
__mmState =
__mmPlayerToolCooldowns[__mmKey] ||
(__mmPlayerToolCooldowns[__mmKey] = {
weapons: Object.create(null),
updatedAt: __mmNow,
});
((__mmState.weapons[String(__mmResolvedWeapon)] = {
weapon: __mmResolvedWeapon,
duration: __mmDuration,
startedAt: __mmNow,
readyAt: __mmNow + __mmDuration,
}),
(__mmState.updatedAt = __mmNow));
}
function __mmPlayerCooldownRows(__mmPlayer, __mmNow) {
if (!__mmPlayer || __mmPlayer.sid == null) return [];
const __mmIsLocal = !!(
v && String(__mmPlayer.sid) === String(v.sid)
),
__mmState = __mmPlayerToolCooldowns[String(__mmPlayer.sid)],
__mmIds = [];
function __mmAddWeapon(__mmWeaponId) {
if (__mmWeaponId == null) return;
const __mmId = Number(__mmWeaponId);
Number.isInteger(__mmId) &&
b &&
b.weapons &&
b.weapons[__mmId] &&
!__mmIds.includes(__mmId) &&
__mmIds.push(__mmId);
}
if (__mmIsLocal && Array.isArray(v.weapons)) {
__mmAddWeapon(v.weapons[0]);
__mmAddWeapon(v.weapons[1]);
} else {
__mmAddWeapon(__mmPlayer.weaponIndex);
if (__mmState && __mmState.weapons) {
Object.keys(__mmState.weapons)
.map(function (__mmKey) {
return __mmState.weapons[__mmKey];
})
.sort(function (__mmA, __mmB) {
return (__mmB.startedAt || 0) - (__mmA.startedAt || 0);
})
.forEach(function (__mmEntry) {
__mmAddWeapon(__mmEntry.weapon);
});
}
}
return __mmIds.slice(0, 2).map(function (__mmWeaponId) {
const __mmTracked =
__mmState && __mmState.weapons
? __mmState.weapons[String(__mmWeaponId)]
: null,
__mmDuration = Math.max(
1,
Number(__mmTracked && __mmTracked.duration) ||
__mmToolCooldownDuration(__mmPlayer, __mmWeaponId) ||
1,
),
__mmRemaining = __mmIsLocal
? Math.max(
0,
Number(v.reloads && v.reloads[__mmWeaponId]) || 0,
)
: Math.max(
0,
Number(__mmTracked && __mmTracked.readyAt) - __mmNow || 0,
);
return {
weapon: __mmWeaponId,
ratio: Math.max(0, Math.min(1, 1 - __mmRemaining / Math.max(__mmDuration, __mmRemaining))),
};
});
}
function __mmDrawPlayerCooldownBars() {
if (
!__mmCooldownBarsEnabled ||
!v ||
!v.alive ||
!k ||
!Array.isArray(E)
)
return;
try {
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2,
__mmNow = Date.now(),
__mmPlayers = E.slice();
!__mmPlayers.some(function (__mmPlayer) {
return __mmPlayer === v ||
(__mmPlayer && String(__mmPlayer.sid) === String(v.sid));
}) && __mmPlayers.push(v);
k.save();
for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
const __mmPlayer = __mmPlayers[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
(__mmPlayer !== v && !__mmPlayer.visible)
)
continue;
const __mmRows = __mmPlayerCooldownRows(__mmPlayer, __mmNow);
if (!__mmRows.length) continue;
const __mmX = __mmPlayer.x - __mmLeft,
__mmY = __mmPlayer.y - __mmTop,
__mmScale = Number(__mmPlayer.scale) || 35,
__mmNameOffset = Number(y && y.nameY) || 0,
__mmWidth = 46,
__mmHeight = 5,
__mmGap = 3,
__mmStartX = Math.round(__mmX - __mmWidth / 2),
__mmStartY = Math.round(__mmY + __mmScale + __mmNameOffset + 21);
if (
__mmStartX > _ + __mmWidth ||
__mmStartX < -__mmWidth ||
__mmStartY > L + 20 ||
__mmStartY < -20
)
continue;
for (let __mmRow = 0; __mmRow < __mmRows.length; __mmRow++) {
const __mmBarY = __mmStartY + __mmRow * (__mmHeight + __mmGap),
__mmRatio = __mmRows[__mmRow].ratio,
__mmFill = __mmRow === 0 ? "#a855f7" : "#d8b4fe";
((k.fillStyle = "rgba(5, 3, 9, 0.82)"),
k.fillRect(__mmStartX, __mmBarY, __mmWidth, __mmHeight),
(k.fillStyle = __mmFill),
(k.shadowColor = __mmFill),
(k.shadowBlur = __mmRatio >= 1 ? 5 : 2),
k.fillRect(
__mmStartX + 1,
__mmBarY + 1,
Math.max(0, (__mmWidth - 2) * __mmRatio),
__mmHeight - 2,
),
(k.shadowBlur = 0),
(k.strokeStyle = "rgba(216, 180, 254, 0.72)"),
(k.lineWidth = 1),
k.strokeRect(__mmStartX + 0.5, __mmBarY + 0.5, __mmWidth - 1, __mmHeight - 1));
}
}
k.restore();
} catch (__mmCooldownDrawError) {
try {
k && k.restore();
} catch (__mmIgnore) {}
}
}
function __mmWeaponStructureDamage(__mmPlayer, __mmWeaponId, __mmObject) {
if (!__mmPlayer || !b || !b.weapons || !__mmObject) return 0;
const __mmWeapon = b.weapons[__mmWeaponId];
if (!__mmWeapon) return 0;
if (__mmWeapon.projectile != null) {
const __mmProjectile = b.projectiles && b.projectiles[__mmWeapon.projectile];
return __mmObject.projDmg && __mmProjectile
? Math.max(0, Number(__mmProjectile.dmg) || 0)
: 0;
}
const __mmVariant =
y && y.weaponVariants && y.weaponVariants[__mmPlayer.weaponVariant],
__mmVariantMultiplier = Number(__mmVariant && __mmVariant.val) || 1,
__mmStructureMultiplier = Number(__mmWeapon.sDmg) || 1,
__mmHat = __mmPlayerHatData(__mmPlayer),
__mmHatMultiplier = Number(__mmHat && __mmHat.bDmg) || 1;
return Math.max(
0,
(Number(__mmWeapon.dmg) || 0) *
__mmVariantMultiplier *
__mmStructureMultiplier *
__mmHatMultiplier,
);
}
function __mmCurrentStructureDamage(__mmObject) {
if (!v || !v.alive || Number(v.buildIndex) >= 0) return 0;
return __mmWeaponStructureDamage(v, v.weaponIndex, __mmObject);
}
function __mmMatThiefStructureAllowed(__mmObject) {
if (
!v ||
!v.alive ||
!__mmObject ||
!__mmObject.active ||
!__mmObject.isItem ||
!__mmObject.owner
)
return !1;
const __mmOwnerSid = __mmObject.owner.sid;
// Teammate structures are intentional targets too, but the local player's
// own placed structures must never be selected.
if (
__mmObject.owner === v ||
(__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
)
return !1;
const __mmOwnerPlayer =
__mmOwnerSid != null && typeof Rt === "function"
? Rt(__mmOwnerSid)
: __mmObject.owner;
if (__mmIsFriendPlayer(__mmOwnerPlayer)) return !1;
const __mmItem = b && b.list && b.list[__mmObject.id],
__mmName = String((__mmItem && __mmItem.name) || "").toLowerCase();
return (
__mmName === "windmill" ||
__mmName === "faster windmill" ||
__mmName === "power mill" ||
__mmName === "turret" ||
__mmName === "teleporter"
);
}
function __mmMatThiefWeaponCandidates() {
if (!v || !v.alive || !Array.isArray(v.weapons)) return [];
const __mmWeapons = [],
__mmSeen = new Set();
for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
const __mmWeapon = v.weapons[__mmIndex],
__mmData = b && b.weapons && b.weapons[__mmWeapon];
if (
__mmWeapon == null ||
__mmSeen.has(__mmWeapon) ||
!__mmData ||
__mmData.projectile != null ||
!__mmWeaponReady(__mmWeapon)
)
continue;
(__mmSeen.add(__mmWeapon), __mmWeapons.push(__mmWeapon));
}
return __mmWeapons;
}
function __mmMatThiefTargetsForWeapon(__mmWeapon, __mmNow) {
if (!v || !v.alive || !Array.isArray(ge)) return [];
const __mmWeaponData = b && b.weapons && b.weapons[__mmWeapon],
__mmRange = Number(__mmWeaponData && __mmWeaponData.range);
if (!Number.isFinite(__mmRange) || __mmRange <= 0) return [];
const __mmTargets = [];
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmObject = ge[__mmIndex];
if (!__mmMatThiefStructureAllowed(__mmObject)) continue;
const __mmReservedUntil = Number(__mmMatThiefReservations.get(__mmObject));
if (Number.isFinite(__mmReservedUntil) && __mmReservedUntil > __mmNow)
continue;
const __mmState = __mmBreakableState(__mmObject),
__mmDamage = __mmWeaponStructureDamage(v, __mmWeapon, __mmObject);
if (!__mmState || __mmDamage <= 0 || __mmState.health > __mmDamage + 0.001)
continue;
const __mmDx = __mmObject.x - v.x,
__mmDy = __mmObject.y - v.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
// Match the server gather check: center distance minus structure scale
// must fit inside the selected weapon's range.
__mmReach = __mmRange + (Number(__mmObject.scale) || 0);
if (__mmDistance > __mmReach) continue;
__mmTargets.push({
object: __mmObject,
angle: Math.atan2(__mmDy, __mmDx),
distance: __mmDistance,
});
}
return __mmTargets;
}
function __mmMatThiefAngleDifference(__mmFirst, __mmSecond) {
return Math.atan2(
Math.sin(__mmSecond - __mmFirst),
Math.cos(__mmSecond - __mmFirst),
);
}
function __mmMatThiefAimPlan(__mmTargets) {
if (!__mmTargets.length) return null;
const __mmGatherAngle = Math.max(0.05, Number(y && y.gatherAngle) || 0.35),
__mmCandidateAngles = [];
for (let __mmIndex = 0; __mmIndex < __mmTargets.length; __mmIndex++)
__mmCandidateAngles.push(__mmTargets[__mmIndex].angle);
for (let __mmFirst = 0; __mmFirst < __mmTargets.length; __mmFirst++)
for (
let __mmSecond = __mmFirst + 1;
__mmSecond < __mmTargets.length;
__mmSecond++
) {
const __mmDifference = __mmMatThiefAngleDifference(
__mmTargets[__mmFirst].angle,
__mmTargets[__mmSecond].angle,
);
Math.abs(__mmDifference) <= 2 * __mmGatherAngle + 0.0001 &&
__mmCandidateAngles.push(
__mmTargets[__mmFirst].angle + __mmDifference / 2,
);
}
let __mmBest = null;
for (
let __mmAngleIndex = 0;
__mmAngleIndex < __mmCandidateAngles.length;
__mmAngleIndex++
) {
const __mmAim = __mmCandidateAngles[__mmAngleIndex],
__mmCovered = __mmTargets.filter(
(__mmTarget) =>
Math.abs(__mmMatThiefAngleDifference(__mmAim, __mmTarget.angle)) <=
__mmGatherAngle + 0.0001,
),
__mmDistanceScore = __mmCovered.reduce(
(__mmTotal, __mmTarget) => __mmTotal + __mmTarget.distance,
0,
);
if (
!__mmBest ||
__mmCovered.length > __mmBest.targets.length ||
(__mmCovered.length === __mmBest.targets.length &&
__mmDistanceScore < __mmBest.distanceScore)
)
__mmBest = {
angle: __mmAim,
targets: __mmCovered,
distanceScore: __mmDistanceScore,
};
}
return __mmBest;
}
function __mmMatThiefPlan() {
const __mmNow = Date.now(),
__mmWeapons = __mmMatThiefWeaponCandidates(),
__mmSelected = __mmSelectedWeapon();
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < __mmWeapons.length; __mmIndex++) {
const __mmWeapon = __mmWeapons[__mmIndex],
__mmTargets = __mmMatThiefTargetsForWeapon(__mmWeapon, __mmNow),
__mmAim = __mmMatThiefAimPlan(__mmTargets);
if (!__mmAim || !__mmAim.targets.length) continue;
const __mmData = b.weapons[__mmWeapon],
__mmDamage = __mmWeaponStructureDamage(
v,
__mmWeapon,
__mmAim.targets[0].object,
),
__mmPlan = {
weapon: __mmWeapon,
angle: __mmAim.angle,
targets: __mmAim.targets,
distanceScore: __mmAim.distanceScore,
damage: __mmDamage,
speed: Math.max(50, Number(__mmData.speed) || 400),
},
__mmPlanUsesSelected = __mmWeapon === __mmSelected,
__mmBestUsesSelected = __mmBest && __mmBest.weapon === __mmSelected;
if (
!__mmBest ||
__mmPlan.targets.length > __mmBest.targets.length ||
(__mmPlan.targets.length === __mmBest.targets.length &&
__mmPlanUsesSelected &&
!__mmBestUsesSelected) ||
(__mmPlan.targets.length === __mmBest.targets.length &&
__mmPlanUsesSelected === __mmBestUsesSelected &&
(__mmPlan.distanceScore < __mmBest.distanceScore ||
(__mmPlan.distanceScore === __mmBest.distanceScore &&
__mmPlan.damage > __mmBest.damage)))
)
__mmBest = __mmPlan;
}
return __mmBest;
}
function __mmFinishMatThief(__mmReason) {
const __mmAim = __mmMatThiefAimAngle,
__mmReturnAngle = __mmMatThiefReturnAngle,
__mmTool = __mmMatThiefRestoreTool,
__mmRestore = __mmActionMayRestore("matThief");
(__mmMatThiefReleaseTimer && clearTimeout(__mmMatThiefReleaseTimer),
(__mmMatThiefReleaseTimer = 0),
__mmMatThiefAttackHeld && O.send("F", 0, __mmAim),
(__mmMatThiefAttackHeld = !1),
(__mmMatThiefAimAngle = null),
(__mmMatThiefReturnAngle = null),
(__mmMatThiefRestoreTool = null),
__mmRestore && __mmRestoreTool(__mmTool),
__mmRestore &&
Number.isFinite(__mmReturnAngle) &&
O.send("D", __mmReturnAngle),
__mmActionRelease("matThief", __mmReason || "last hit complete"));
}
function __mmUpdateMatThief() {
if (
!__mmMatThiefEnabled ||
document.hidden ||
!v ||
!v.alive ||
v.lockMove ||
__mmMatThiefReleaseTimer ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmInsta.isActive() ||
__mmSyncFollowerEnabled ||
(__mmActionOwner !== "idle" && __mmActionOwner !== "weaponRecharge")
)
return;
const __mmPlan = __mmMatThiefPlan();
if (!__mmPlan) return;
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmActionClaim("matThief", "one-hit structure")) return;
let __mmReturnAngle;
try {
__mmReturnAngle = __mmOriginalAimDirection();
} catch (__mmAimError) {
__mmReturnAngle = 0;
}
const __mmNow = Date.now(),
__mmReservationUntil =
__mmNow + Math.max(__mmPlan.speed, 2 * __mmServerTickMs());
for (let __mmIndex = 0; __mmIndex < __mmPlan.targets.length; __mmIndex++)
__mmMatThiefReservations.set(
__mmPlan.targets[__mmIndex].object,
__mmReservationUntil,
);
((__mmMatThiefReturnAngle = __mmReturnAngle),
(__mmMatThiefRestoreTool = __mmSelectedTool()),
(__mmMatThiefAimAngle = __mmPlan.angle),
O.send("D", __mmPlan.angle),
je(__mmPlan.weapon, !0),
O.send("F", 1, __mmPlan.angle),
(__mmMatThiefAttackHeld = !0),
(__mmMatThiefReleaseTimer = setTimeout(function () {
__mmFinishMatThief("last hit sent");
}, __mmServerTickMs())));
}
function __mmStartMatThief() {
__mmMatThiefEnabled &&
!__mmMatThiefTimer &&
(__mmMatThiefTimer = setInterval(__mmUpdateMatThief, __mmFastCheckMs()));
}
function __mmStopMatThief() {
(__mmMatThiefTimer && clearInterval(__mmMatThiefTimer),
(__mmMatThiefTimer = 0),
__mmFinishMatThief("mode disabled"));
}
function __mmMobStealEntityKey(__mmAnimal) {
if (!__mmAnimal) return null;
const __mmId =
__mmAnimal.sid != null
? __mmAnimal.sid
: __mmAnimal.id != null
? __mmAnimal.id
: __mmAnimal.index;
return __mmId == null ? null : "mob:" + String(__mmId);
}
function __mmMobStealVariantMultiplier(__mmWeapon) {
const __mmVariants = y && y.weaponVariants,
__mmXp = Number(v && v.weaponXP && v.weaponXP[__mmWeapon]) || 0;
if (!Array.isArray(__mmVariants)) return 1;
for (let __mmIndex = __mmVariants.length - 1; __mmIndex >= 0; __mmIndex--)
if (__mmXp >= (Number(__mmVariants[__mmIndex].xp) || 0))
return Number(__mmVariants[__mmIndex].val) || 1;
return 1;
}
function __mmMobStealTailData(__mmTail) {
if (typeof pa === "undefined" || !Array.isArray(pa)) return null;
for (let __mmIndex = 0; __mmIndex < pa.length; __mmIndex++)
if (Number(pa[__mmIndex].id) === Number(__mmTail)) return pa[__mmIndex];
return null;
}
function __mmMobStealDamage(__mmWeapon, __mmUseBull, __mmStripMonkeyTail) {
const __mmData = b && b.weapons && b.weapons[__mmWeapon];
if (!__mmData || __mmData.projectile != null) return 0;
const __mmHat = __mmUseBull
? __mmPlayerHatData({ skinIndex: 7 })
: __mmPlayerHatData(v),
__mmTail = __mmStripMonkeyTail
? null
: __mmMobStealTailData(v && v.tailIndex),
__mmHatMultiplier = Number(__mmHat && __mmHat.dmgMultO) || 1,
__mmTailMultiplier = Number(__mmTail && __mmTail.dmgMultO) || 1;
return Math.max(
0,
(Number(__mmData.dmg) || 0) *
__mmMobStealVariantMultiplier(__mmWeapon) *
__mmHatMultiplier *
__mmTailMultiplier,
);
}
function __mmMobStealWeaponCandidates() {
if (!v || !v.alive || !Array.isArray(v.weapons)) return [];
const __mmUseBull = !!(
__mmBullHelmetEnabled && __mmCanEquipHat(7)
),
__mmStripMonkeyTail = Number(v.tailIndex) === 11,
__mmSelected = __mmSelectedWeapon(),
__mmCandidates = [],
__mmSeen = new Set();
for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
const __mmWeapon = v.weapons[__mmIndex],
__mmData = b && b.weapons && b.weapons[__mmWeapon],
__mmRange = Number(__mmData && __mmData.range),
__mmDamage = __mmMobStealDamage(
__mmWeapon,
__mmUseBull,
__mmStripMonkeyTail,
);
if (
__mmWeapon == null ||
__mmSeen.has(__mmWeapon) ||
!__mmData ||
__mmData.projectile != null ||
__mmData.shield ||
!Number.isFinite(__mmRange) ||
__mmRange <= 0 ||
__mmDamage <= 0 ||
!__mmWeaponReady(__mmWeapon)
)
continue;
(__mmSeen.add(__mmWeapon),
__mmCandidates.push({
weapon: __mmWeapon,
range: __mmRange,
damage: __mmDamage,
speed: Math.max(50, Number(__mmData.speed) || 400),
selected: __mmWeapon === __mmSelected,
useBull: __mmUseBull,
stripMonkeyTail: __mmStripMonkeyTail,
}));
}
return __mmCandidates;
}
function __mmMobStealPredictPoint(
__mmEntity,
__mmKey,
__mmNow,
__mmLeadMs,
) {
const __mmX = Number(__mmEntity && __mmEntity.x),
__mmY = Number(__mmEntity && __mmEntity.y);
if (!Number.isFinite(__mmX) || !Number.isFinite(__mmY)) return null;
const __mmPrevious = __mmMobStealMotion[__mmKey],
__mmElapsed = __mmPrevious
? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
: 0;
let __mmVelocityX = __mmPrevious
? (__mmX - __mmPrevious.x) / __mmElapsed
: 0,
__mmVelocityY = __mmPrevious
? (__mmY - __mmPrevious.y) / __mmElapsed
: 0;
const __mmServerElapsed = Number(__mmEntity.t2) - Number(__mmEntity.t1),
__mmServerVelocityX =
(Number(__mmEntity.x2) - Number(__mmEntity.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(__mmEntity.y2) - Number(__mmEntity.y1)) / __mmServerElapsed;
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
) {
((__mmVelocityX = __mmPrevious
? __mmServerVelocityX * 0.75 + __mmVelocityX * 0.25
: __mmServerVelocityX),
(__mmVelocityY = __mmPrevious
? __mmServerVelocityY * 0.75 + __mmVelocityY * 0.25
: __mmServerVelocityY));
}
__mmMobStealMotion[__mmKey] = { x: __mmX, y: __mmY, at: __mmNow };
return {
x: Math.max(0, Math.min(y.mapScale, __mmX + __mmVelocityX * __mmLeadMs)),
y: Math.max(0, Math.min(y.mapScale, __mmY + __mmVelocityY * __mmLeadMs)),
};
}
function __mmMobStealPlan() {
if (!v || !v.alive || !Array.isArray(N)) return null;
const __mmWeapons = __mmMobStealWeaponCandidates();
if (!__mmWeapons.length) return null;
const __mmNow = Date.now(),
__mmPing = Number(window.pingTime),
__mmLeadMs = Math.min(
300,
__mmServerTickMs() +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0),
),
__mmSelf = __mmMobStealPredictPoint(
v,
"self",
__mmNow,
__mmLeadMs,
),
__mmSeen = Object.create(null);
if (!__mmSelf) return null;
__mmSeen.self = !0;
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
const __mmAnimal = N[__mmIndex],
__mmKey = __mmMobStealEntityKey(__mmAnimal);
if (__mmKey == null) continue;
__mmSeen[__mmKey] = !0;
const __mmPrediction = __mmMobStealPredictPoint(
__mmAnimal,
__mmKey,
__mmNow,
__mmLeadMs,
);
if (
!__mmPrediction ||
!__mmAnimal ||
__mmAnimal.active === !1 ||
__mmAnimal.alive === !1 ||
!__mmAnimal.visible ||
!(Number(__mmAnimal.health) > 0) ||
Number(__mmMobStealReservations[__mmKey]) > __mmNow
)
continue;
for (
let __mmWeaponIndex = 0;
__mmWeaponIndex < __mmWeapons.length;
__mmWeaponIndex++
) {
const __mmWeapon = __mmWeapons[__mmWeaponIndex];
if (Number(__mmAnimal.health) > __mmWeapon.damage + 0.001) continue;
const __mmDx = __mmPrediction.x - __mmSelf.x,
__mmDy = __mmPrediction.y - __mmSelf.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
// Match the server gather hitbox for players and AI targets.
__mmReach =
__mmWeapon.range + (Number(__mmAnimal.scale) || 35) * 1.8;
if (__mmDistance > __mmReach) continue;
const __mmScore =
__mmDistance / Math.max(1, __mmReach) +
(__mmWeapon.selected ? 0 : 0.08);
if (!__mmBest || __mmScore < __mmBest.score)
__mmBest = {
animal: __mmAnimal,
key: __mmKey,
weapon: __mmWeapon.weapon,
damage: __mmWeapon.damage,
speed: __mmWeapon.speed,
useBull: __mmWeapon.useBull,
stripMonkeyTail: __mmWeapon.stripMonkeyTail,
x: __mmPrediction.x,
y: __mmPrediction.y,
angle: Math.atan2(__mmDy, __mmDx),
score: __mmScore,
};
}
}
for (const __mmKey in __mmMobStealMotion)
__mmSeen[__mmKey] || delete __mmMobStealMotion[__mmKey];
for (const __mmKey in __mmMobStealReservations)
Number(__mmMobStealReservations[__mmKey]) <= __mmNow &&
delete __mmMobStealReservations[__mmKey];
return __mmBest;
}
function __mmFinishMobSteal(__mmReason) {
const __mmAim = __mmMobStealAimAngle,
__mmHadAim = Number.isFinite(__mmMobStealAimAngle),
__mmTool = __mmMobStealRestoreTool,
__mmHat = __mmMobStealRestoreHat,
__mmTail = __mmMobStealRestoreTail,
__mmRestore = __mmActionMayRestore("mobSteal");
(__mmMobStealReleaseTimer && clearTimeout(__mmMobStealReleaseTimer),
(__mmMobStealReleaseTimer = 0),
__mmMobStealAttackHeld && O.send("F", 0, __mmAim),
(__mmMobStealAttackHeld = !1),
(__mmMobStealAimAngle = null),
(__mmMobStealRestoreTool = null),
(__mmMobStealRestoreHat = null),
(__mmMobStealRestoreTail = null),
__mmRestore && __mmRestoreTool(__mmTool),
__mmRestore && __mmEquipGearPair(__mmHat, __mmTail, !0),
__mmActionRelease("mobSteal", __mmReason || "predicted last hit complete"),
__mmHadAim && __mmScheduleMouseAimReturn(),
v && v.alive && __mmUpdateWeaponRecharge());
}
function __mmStartMobStealAttack(__mmPlan) {
if (!__mmPlan || !v || !v.alive) return !1;
(__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmActionOwner === "matThief" &&
__mmFinishMatThief("mob steal last hit"));
if (!__mmActionClaim("mobSteal", "predicted one-hit mob")) return !1;
const __mmNow = Date.now();
(__mmMobStealReservations[__mmPlan.key] =
__mmNow + Math.max(__mmPlan.speed, 2 * __mmServerTickMs()),
(__mmMobStealRestoreTool = __mmSelectedTool()),
(__mmMobStealRestoreHat = __mmPlan.useBull ? v.skinIndex : null),
(__mmMobStealRestoreTail = __mmPlan.stripMonkeyTail ? v.tailIndex : null),
__mmEquipGearPair(
__mmPlan.useBull ? 7 : null,
__mmPlan.stripMonkeyTail ? 0 : null,
!0,
),
(__mmMobStealAimAngle = __mmPlan.angle),
O.send("D", __mmPlan.angle),
je(__mmPlan.weapon, !0),
O.send("F", 1, __mmPlan.angle),
(__mmMobStealAttackHeld = !0),
(__mmMobStealReleaseTimer = setTimeout(function () {
__mmFinishMobSteal("predicted last hit sent");
}, __mmServerTickMs())));
return !0;
}
function __mmUpdateMobSteal() {
if (
!__mmMobStealEnabled ||
document.hidden ||
!v ||
!v.alive ||
v.lockMove ||
__mmMobStealReleaseTimer ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmInsta.isActive() ||
__mmSyncFollowerEnabled ||
!(
__mmActionOwner === "idle" ||
__mmActionOwner === "weaponRecharge" ||
__mmActionOwner === "matThief"
)
)
return;
const __mmPlan = __mmMobStealPlan();
__mmPlan && __mmStartMobStealAttack(__mmPlan);
}
function __mmStartMobSteal() {
__mmMobStealEnabled &&
!__mmMobStealTimer &&
(__mmMobStealTimer = setInterval(__mmUpdateMobSteal, 5));
}
function __mmStopMobSteal() {
(__mmMobStealTimer && clearInterval(__mmMobStealTimer),
(__mmMobStealTimer = 0),
__mmFinishMobSteal("mode disabled"));
}
function __mmRecordPlayerSwing(__mmPlayerSid, __mmWeapon) {
if (__mmPlayerSid == null) return;
__mmTrackPlayerToolCooldown(__mmPlayerSid, __mmWeapon);
__mmRecentPlayerSwings[String(__mmPlayerSid)] = {
at: Date.now(),
weapon: __mmWeapon,
};
}
function __mmObservedObjectHitDamage(__mmObject, __mmHitAngle) {
if (!__mmObject || !Array.isArray(E)) return 0;
const __mmNow = Date.now();
let __mmBestDamage = 0,
__mmBestScore = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex],
__mmRecent =
__mmPlayer && __mmRecentPlayerSwings[String(__mmPlayer.sid)];
if (!__mmPlayer || !__mmPlayer.alive || !__mmRecent) continue;
const __mmAge = __mmNow - __mmRecent.at,
__mmWeaponId =
__mmRecent.weapon == null ? __mmPlayer.weaponIndex : __mmRecent.weapon,
__mmWeapon = b.weapons && b.weapons[__mmWeaponId];
if (__mmAge < 0 || __mmAge > 900 || !__mmWeapon) continue;
const __mmDx = __mmObject.x - __mmPlayer.x,
__mmDy = __mmObject.y - __mmPlayer.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmDirection = Math.atan2(__mmDy, __mmDx),
__mmAngleDifference = M.getAngleDist(__mmDirection, __mmHitAngle),
__mmMeleeReach =
(Number(__mmWeapon.range) || 0) + (Number(__mmObject.scale) || 0) + 16;
if (
__mmWeapon.projectile == null &&
(__mmDistance > __mmMeleeReach || __mmAngleDifference > 0.32)
)
continue;
const __mmDamage = __mmWeaponStructureDamage(
__mmPlayer,
__mmWeaponId,
__mmObject,
);
if (!__mmDamage) continue;
const __mmScore = __mmAge +
(__mmWeapon.projectile == null ? __mmDistance : 300);
if (__mmScore < __mmBestScore) {
((__mmBestScore = __mmScore), (__mmBestDamage = __mmDamage));
}
}
return __mmBestDamage || __mmCurrentStructureDamage(__mmObject);
}
function __mmObserveObjectHit(__mmAngle, __mmObjectSid) {
const __mmObject = typeof ns === "function" ? ns(__mmObjectSid) : null,
__mmState = __mmBreakableState(__mmObject);
if (!__mmObject || !__mmState) return;
const __mmDamage = __mmObservedObjectHitDamage(
__mmObject,
Number(__mmAngle) || 0,
);
if (__mmDamage > 0)
__mmState.health = Math.max(0, __mmState.health - __mmDamage);
}
function __mmDrawBreakableHitCounts() {
if (!v || !v.alive || !k || !Array.isArray(ge)) return;
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2;
(k.save(),
(k.textAlign = "center"),
(k.textBaseline = "middle"));
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmObject = ge[__mmIndex],
__mmState = __mmBreakableState(__mmObject);
if (!__mmObject || !__mmObject.active || !__mmState) continue;
const __mmX = __mmObject.x + __mmObject.xWiggle - __mmLeft,
__mmY = __mmObject.y + __mmObject.yWiggle - __mmTop;
if (!ts(__mmX, __mmY, (Number(__mmObject.scale) || 35) + 10)) continue;
const __mmDamage = __mmCurrentStructureDamage(__mmObject),
__mmHits = __mmDamage > 0
? String(Math.max(0, Math.ceil(__mmState.health / __mmDamage)))
: "∞";
((k.globalAlpha = 0.96),
(k.shadowColor = "#a855f7"),
(k.shadowBlur = 8),
(k.strokeStyle = "rgba(5,3,9,.92)"),
(k.lineWidth = 4),
(k.font = "900 20px Hammersmith One, Arial, sans-serif"),
k.strokeText(__mmHits, __mmX, __mmY),
(k.fillStyle = "#ffffff"),
k.fillText(__mmHits, __mmX, __mmY));
}
k.restore();
}
Ge = function (__mmLayer, __mmLeft, __mmTop) {
const __mmResult = __mmOriginalObjectRender.apply(this, arguments);
return (__mmDrawStructureTints(__mmLayer, __mmLeft, __mmTop), __mmResult);
};
Wl = function (__mmAngle, __mmObjectSid) {
__mmObserveObjectHit(__mmAngle, __mmObjectSid);
return __mmOriginalObjectHit.apply(this, arguments);
};
function __mmUpdateMetrics() {
__mmMetricFrames += 1;
const __mmNow = performance.now(),
__mmElapsed = __mmNow - __mmMetricUpdatedAt;
if (__mmElapsed < 500) return;
((__mmMetricFps = __mmMetricFrames * 1000 / __mmElapsed),
(__mmMetricPps = __mmMetricPacketWindow * 1000 / __mmElapsed),
(__mmMetricFrames = 0),
(__mmMetricPacketWindow = 0),
(__mmMetricUpdatedAt = __mmNow),
window.dispatchEvent(
new CustomEvent("MooMooKittyMetrics", {
detail: {
ping: Number.isFinite(Number(window.pingTime)) ? Number(window.pingTime) : null,
fps: __mmMetricFps,
packets: __mmMetricPackets,
pps: __mmMetricPps,
},
}),
));
}
Cl = function () {
const __mmResult = __mmOriginalRender.apply(this, arguments);
return (
__mmUpdateMetrics(),
__mmDrawEsp(),
__mmDrawPlayerCooldownBars(),
__mmDrawAutoSpikeSpamGhost(),
__mmDrawBreakableHitCounts(),
__mmResult
);
};
function __mmIsPlaceableItem(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
return !!(__mmData && __mmData.group && __mmData.group.place);
}
function __mmSelectedPlaceableItem() {
if (!v) return null;
return __mmIsPlaceableItem(__mmLastBuildItem)
? __mmLastBuildItem
: __mmIsPlaceableItem(v.buildIndex)
? v.buildIndex
: null;
}
function __mmCanEquipHat(__mmHat) {
return __mmHat === 0 || !!(v && v.skins && v.skins[__mmHat]);
}
function __mmShiftHeld() {
return typeof ne !== "undefined" && !!ne[16];
}
function __mmPlayerMoving() {
return (
typeof ne !== "undefined" &&
!!(
ne[87] ||
ne[38] ||
ne[83] ||
ne[40] ||
ne[65] ||
ne[37] ||
ne[68] ||
ne[39]
)
);
}
function __mmHasStick() {
return !!(v && v.weapons && v.weapons.includes(8));
}
function __mmAutoPurchaseQueue() {
const __mmEntries = __mmAutoPurchaseEntries;
return __mmHasStick()
? [
__mmEntries.monkeyTail,
__mmEntries.soldier,
__mmEntries.booster,
__mmEntries.emp,
__mmEntries.turret,
__mmEntries.tank,
__mmEntries.shadow,
__mmEntries.angel,
__mmEntries.blood,
__mmEntries.corrupt,
]
: [
__mmEntries.monkeyTail,
__mmEntries.soldier,
__mmEntries.bull,
__mmEntries.booster,
__mmEntries.emp,
__mmEntries.turret,
__mmEntries.tank,
__mmEntries.shadow,
__mmEntries.angel,
__mmEntries.blood,
__mmEntries.corrupt,
];
}
function __mmOwnsAutoPurchaseEntry(__mmEntry) {
return !!(
v &&
__mmEntry &&
( __mmEntry.tail
? v.tails && v.tails[__mmEntry.id]
: v.skins && v.skins[__mmEntry.id])
);
}
function __mmUpdateAutoPurchase() {
if (
!__mmAutoPurchaseEnabled ||
__mmSyncFollowerEnabled ||
__mmInsta.isActive() ||
!v ||
!v.alive
)
return;
if (
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld
)
return;
const __mmNow = Date.now(),
__mmPending = __mmAutoPurchasePending;
if (__mmPending) {
if (__mmOwnsAutoPurchaseEntry(__mmPending))
__mmAutoPurchasePending = null;
else if (__mmNow - __mmPending.at < Math.max(350, __mmServerTickMs() * 3))
return;
else __mmAutoPurchasePending = null;
}
const __mmQueue = __mmAutoPurchaseQueue();
for (let __mmIndex = 0; __mmIndex < __mmQueue.length; __mmIndex++) {
const __mmEntry = __mmQueue[__mmIndex];
if (__mmOwnsAutoPurchaseEntry(__mmEntry)) continue;
// Preserve the requested order: do not spend on a later item until the
// next missing purchase is affordable.
if ((Number(v.points) || 0) < __mmEntry.price) return;
((__mmAutoPurchasePending = { ...__mmEntry, at: __mmNow }),
Xn(__mmEntry.id, __mmEntry.tail));
return;
}
}
function __mmStartAutoPurchase() {
__mmAutoPurchaseTimer ||
(__mmAutoPurchaseTimer = setInterval(
__mmUpdateAutoPurchase,
__mmFastCheckMs(),
));
}
function __mmStopAutoPurchase() {
(__mmAutoPurchaseTimer && clearInterval(__mmAutoPurchaseTimer),
(__mmAutoPurchaseTimer = 0),
(__mmAutoPurchasePending = null));
}
function __mmEnemyWithinCombatRange() {
if (!v || !v.alive) return !1;
if (__mmLiveStateFresh())
return __mmLiveState.nearestEnemyDistance <= __mmCombatRange;
for (let __mmEnemyIndex = 0; __mmEnemyIndex < E.length; __mmEnemyIndex++) {
const __mmEnemy = E[__mmEnemyIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmDx = __mmEnemy.x - v.x,
__mmDy = __mmEnemy.y - v.y;
if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmCombatRange * __mmCombatRange)
return !0;
}
return !1;
}
let __mmLastUpgradePacketAt = 0;
function __mmUpgradeSelection(__mmSelection) {
const __mmIndex = Number(__mmSelection),
__mmWeaponCount = b && Array.isArray(b.weapons) ? b.weapons.length : 0;
if (!Number.isInteger(__mmIndex) || __mmIndex < 0) return null;
if (__mmIndex < __mmWeaponCount)
return {
entry: b.weapons[__mmIndex],
prerequisite: __mmOriginalWeaponPrerequisites[__mmIndex],
owned: v && v.weapons,
};
const __mmItemIndex = __mmIndex - __mmWeaponCount;
return {
entry: b && b.list && b.list[__mmItemIndex],
prerequisite: __mmOriginalItemPrerequisites[__mmItemIndex],
owned: v && v.items,
};
}
function __mmUpgradeServerSafe(__mmSelection) {
const __mmChoice = __mmUpgradeSelection(__mmSelection);
if (
!v ||
!v.alive ||
!__mmChoice ||
!__mmChoice.entry ||
!(Number(v.upgradePoints) > 0)
)
return !1;
const __mmRequiredAge = Number(__mmChoice.entry.age),
__mmCurrentUpgradeAge = Number(v.upgrAge);
if (
Number.isFinite(__mmRequiredAge) &&
Number.isFinite(__mmCurrentUpgradeAge) &&
__mmRequiredAge !== __mmCurrentUpgradeAge
)
return !1;
return (
__mmChoice.prerequisite == null ||
(Array.isArray(__mmChoice.owned) &&
__mmChoice.owned.includes(__mmChoice.prerequisite))
);
}
function __mmUpgradeBlockedNotice() {
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomStatus", {
detail: "Upgrade blocked: wrong weapon path",
}),
);
}
function __mmAllowUpgradePacket(__mmSelection) {
if (!__mmUpgradeServerSafe(__mmSelection))
return (__mmUpgradeBlockedNotice(), !1);
const __mmNow = Date.now();
if (__mmNow - __mmLastUpgradePacketAt < 350) return !1;
return ((__mmLastUpgradePacketAt = __mmNow), !0);
}
function __mmMarkUnsafeUpgradeChoices() {
if (!b || !Array.isArray(b.weapons) || !Array.isArray(b.list)) return;
const __mmTotal = b.weapons.length + b.list.length;
for (let __mmIndex = 0; __mmIndex < __mmTotal; __mmIndex++) {
const __mmElement = document.getElementById("upgradeItem" + __mmIndex);
if (!__mmElement || __mmUpgradeServerSafe(__mmIndex)) continue;
((__mmElement.style.opacity = "0.28"),
(__mmElement.style.filter = "grayscale(1)"),
(__mmElement.style.cursor = "not-allowed"),
(__mmElement.title = "Blocked: server prerequisite not met"),
__mmElement.setAttribute("aria-disabled", "true"),
(__mmElement.onclick = function () {
__mmUpgradeBlockedNotice();
}));
}
}
function __mmApplyAllItemsUnlock() {
const __mmApply = function (__mmEntries, __mmOriginal) {
if (!Array.isArray(__mmEntries)) return;
for (let __mmIndex = 0; __mmIndex < __mmEntries.length; __mmIndex++) {
const __mmEntry = __mmEntries[__mmIndex],
__mmPrerequisite = __mmOriginal[__mmIndex];
if (!__mmEntry || __mmPrerequisite == null) continue;
__mmEntry.pre = __mmAllItemsUnlockEnabled
? null
: __mmPrerequisite;
}
};
// This mode is a preview only: same-age choices are rendered, while the
// original prerequisites remain available to the packet guard below.
(__mmApply(b && b.weapons, __mmOriginalWeaponPrerequisites),
__mmApply(b && b.list, __mmOriginalItemPrerequisites));
}
function __mmHudState() {
return {
autoHeal: __mmAutoHealEnabled,
soldierAuto: __mmSoldierAutoEnabled,
movementGear: __mmMovementGearEnabled,
passiveSpikeAvoidance: __mmPassiveSpikeAvoidanceEnabled,
trapEscape: __mmTrapEscapeEnabled,
antiBoost: __mmAntiBoostEnabled,
antiBoostInsta: __mmAntiBoostInstaEnabled,
threatTrap: __mmThreatTrapEnabled,
autoCloseSpike: __mmAutoCloseSpikeEnabled,
reloadSpike: __mmReloadSpikeEnabled,
shieldDefense: __mmShieldDefenseEnabled,
musketRecharge: __mmMusketRechargeEnabled,
autoPurchase: __mmAutoPurchaseEnabled,
matThief: __mmMatThiefEnabled,
mobSteal: __mmMobStealEnabled,
spinningWindmills: __mmSpinningWindmillsEnabled,
esp: __mmEspEnabled,
espLines: __mmEspLinesEnabled,
predictionGhost: __mmPredictionGhostEnabled,
cooldownBars: __mmCooldownBarsEnabled,
bullHelmet: __mmBullHelmetEnabled,
tankRightClick: __mmTankRightClickEnabled,
allItemsUnlock: __mmAllItemsUnlockEnabled,
instaKill: __mmInstaUiEnabled,
autoInsta: __mmAutoInstaEnabled,
autoSpikeInsta: __mmAutoSpikeInstaEnabled,
autoSpikeSpam: __mmAutoSpikeSpamEnabled,
antiInsta: __mmAntiInstaEnabled,
instaSync: __mmInstaSyncEnabled,
boostBreak: __mmBoostBreakEnabled,
boostChat: __mmBoostChatEnabled,
materialReply: __mmMaterialReplyEnabled,
syncLeader: __mmSyncLeaderEnabled,
syncFollower: __mmSyncFollowerEnabled,
soldierRange: __mmSoldierRange,
combatRange: __mmCombatRange,
gearHoldTicks: __mmGearHoldTicks,
passiveSpikeEnemyRange: __mmPassiveSpikeEnemyRange,
antiBoostRange: __mmAntiBoostRange,
reactionMs: __mmReactionMs,
debugPanel: __mmDebugPanelEnabled,
debugText: __mmRuntimeDebugText(),
killMessageEnabled: __mmKillMessageEnabled,
killMessage: __mmKillMessage,
friendNames: Array.from(__mmFriendNames.values()),
};
}
function __mmPublishHudState() {
window.dispatchEvent(
new CustomEvent("MooMooOPHudState", { detail: __mmHudState() }),
);
}
function __mmSetAutoHeal(__mmEnabled) {
((__mmAutoHealEnabled = !!__mmEnabled),
!__mmAutoHealEnabled &&
__mmAutoHealWasHealing &&
((__mmAutoHealWasHealing = !1), __mmRestoreAutoHealWeapon()),
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomAutoheal", {
detail: __mmAutoHealEnabled,
}),
),
__mmPublishHudState());
}
function __mmSetSoldierAuto(__mmEnabled) {
__mmSoldierAutoEnabled = !!__mmEnabled;
if (
!__mmSoldierAutoEnabled &&
v &&
v.alive &&
__mmSoldierPreviousHat != null
) {
const __mmHat = __mmSoldierPreviousHat;
((__mmSoldierPreviousHat = null),
v.skinIndex === 6 && __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat));
}
__mmPublishHudState();
}
function __mmSetMovementGear(__mmEnabled) {
((__mmMovementGearEnabled = !!__mmEnabled),
!__mmMovementGearEnabled &&
(__mmRestoreMovementGear(), __mmRestoreProximityTail()),
__mmPublishHudState());
}
function __mmSetHudNumber(__mmKey, __mmValue) {
const __mmNumber = Number(__mmValue);
if (!Number.isFinite(__mmNumber)) return;
(__mmKey === "soldierRange"
? (__mmSoldierRange = Math.max(100, Math.min(1000, __mmNumber)))
: __mmKey === "combatRange"
? (__mmCombatRange = Math.max(100, Math.min(1000, __mmNumber)))
: __mmKey === "gearHoldTicks"
? (__mmGearHoldTicks = Math.max(1, Math.min(8, Math.round(__mmNumber))))
: __mmKey === "passiveSpikeEnemyRange"
? (__mmPassiveSpikeEnemyRange = Math.max(0, Math.min(1200, __mmNumber)))
: __mmKey === "antiBoostRange"
? (__mmAntiBoostRange = Math.max(80, Math.min(500, __mmNumber)))
: __mmKey === "reactionMs" &&
((__mmReactionMs = Math.max(10, Math.min(100, __mmNumber))),
__mmLiveStateTimer &&
(clearInterval(__mmLiveStateTimer),
(__mmLiveStateTimer = 0),
__mmStartLiveState())),
__mmPublishHudState());
}
function __mmSetHudToggle(__mmKey, __mmValue) {
const __mmEnabled = !!__mmValue;
if (__mmKey === "autoHeal") return void __mmSetAutoHeal(__mmEnabled);
if (__mmKey === "soldierAuto") return void __mmSetSoldierAuto(__mmEnabled);
if (__mmKey === "movementGear") return void __mmSetMovementGear(__mmEnabled);
if (__mmKey === "passiveSpikeAvoidance")
((__mmPassiveSpikeAvoidanceEnabled = __mmEnabled),
__mmEnabled
? __mmStartPassiveSpikeAvoidance()
: __mmStopPassiveSpikeAvoidance());
else if (__mmKey === "trapEscape")
((__mmTrapEscapeEnabled = __mmEnabled),
__mmEnabled ? __mmStartTrapEscape() : __mmStopTrapEscape());
else if (__mmKey === "antiBoost")
((__mmAntiBoostEnabled = __mmEnabled),
!__mmEnabled && __mmStopAntiBoostBlock("hud disabled"));
else if (__mmKey === "antiBoostInsta")
__mmAntiBoostInstaEnabled = __mmEnabled;
else if (__mmKey === "threatTrap") __mmThreatTrapEnabled = __mmEnabled;
else if (__mmKey === "autoCloseSpike")
__mmAutoCloseSpikeEnabled = __mmEnabled;
else if (__mmKey === "reloadSpike") __mmReloadSpikeEnabled = __mmEnabled;
else if (__mmKey === "shieldDefense")
((__mmShieldDefenseEnabled = __mmEnabled),
!__mmEnabled && __mmStopShieldDefense("hud disabled"));
else if (__mmKey === "musketRecharge")
((__mmMusketRechargeEnabled = __mmEnabled),
!__mmEnabled && __mmStopWeaponRecharge(!1));
else if (__mmKey === "autoPurchase")
((__mmAutoPurchaseEnabled = __mmEnabled),
__mmEnabled ? (__mmStartAutoPurchase(), __mmUpdateAutoPurchase()) : __mmStopAutoPurchase());
else if (__mmKey === "matThief")
((__mmMatThiefEnabled = __mmEnabled),
__mmEnabled ? (__mmStartMatThief(), __mmUpdateMatThief()) : __mmStopMatThief());
else if (__mmKey === "mobSteal")
((__mmMobStealEnabled = __mmEnabled),
__mmEnabled ? (__mmStartMobSteal(), __mmUpdateMobSteal()) : __mmStopMobSteal());
else if (__mmKey === "spinningWindmills")
((__mmSpinningWindmillsEnabled = __mmEnabled),
__mmEnabled
? (__mmStartSpinningWindmills(), __mmUpdateSpinningWindmills())
: __mmStopSpinningWindmills());
else if (__mmKey === "esp") __mmEspEnabled = __mmEnabled;
else if (__mmKey === "espLines") __mmEspLinesEnabled = __mmEnabled;
else if (__mmKey === "predictionGhost")
__mmPredictionGhostEnabled = __mmEnabled;
else if (__mmKey === "cooldownBars")
__mmCooldownBarsEnabled = __mmEnabled;
else if (__mmKey === "bullHelmet") {
__mmBullHelmetEnabled = __mmEnabled;
if (
!__mmEnabled &&
v &&
(__mmPrimaryClickHat != null || __mmPrimaryClickTail != null)
)
__mmForceRestoreBullForPrimary();
} else if (__mmKey === "tankRightClick")
((__mmTankRightClickEnabled = __mmEnabled),
!__mmEnabled &&
(__mmStopSecondary(), __mmForceRestoreRightClickHat()));
else if (__mmKey === "allItemsUnlock")
((__mmAllItemsUnlockEnabled = __mmEnabled),
__mmApplyAllItemsUnlock());
else if (__mmKey === "instaKill") {
((__mmInstaUiEnabled = __mmEnabled),
!__mmEnabled && __mmInsta.cancel("hud-disabled"));
}
else if (__mmKey === "autoInsta") {
((__mmAutoInstaEnabled = __mmEnabled),
!__mmEnabled &&
__mmInsta.automatic &&
__mmInsta.cancel("auto-insta-disabled"));
}
else if (__mmKey === "autoSpikeInsta")
((__mmAutoSpikeInstaEnabled = __mmEnabled),
!__mmEnabled && __mmStopSpikeTickStrike("hud disabled"));
else if (__mmKey === "autoSpikeSpam") {
__mmAutoSpikeSpamEnabled = __mmEnabled;
if (!__mmEnabled) {
((__mmAutoSpikeSpamGhost = null),
(__mmAutoSpikeSpamCandidateKey = null),
(__mmAutoSpikeSpamCandidateSince = 0));
}
}
else if (__mmKey === "antiInsta") {
__mmAntiInstaEnabled = __mmEnabled;
if (!__mmEnabled && __mmActionOwner === "antiInsta") {
(__mmAntiInstaActionTimer && clearTimeout(__mmAntiInstaActionTimer),
(__mmAntiInstaActionTimer = 0),
__mmActionRelease("antiInsta", "hud disabled"));
}
}
else if (__mmKey === "instaSync") {
__mmInstaSyncEnabled = __mmEnabled;
!__mmEnabled && __mmStopInstaSync();
}
else if (__mmKey === "boostBreak") {
((__mmBoostBreakEnabled = __mmEnabled),
!__mmEnabled && __mmStopBoostBreak());
} else if (__mmKey === "boostChat") {
((__mmBoostChatEnabled = __mmEnabled), !__mmEnabled && __mmStopBoostChat());
} else if (__mmKey === "materialReply") {
__mmMaterialReplyEnabled = __mmEnabled;
} else if (__mmKey === "syncLeader") {
__mmSetSyncLeader(__mmEnabled);
return;
} else if (__mmKey === "syncFollower") {
__mmSetSyncFollower(__mmEnabled);
return;
} else if (__mmKey === "debugPanel")
__mmDebugPanelEnabled = __mmEnabled;
else if (__mmKey === "killMessageEnabled")
__mmKillMessageEnabled = __mmEnabled;
else return;
__mmPublishHudState();
}
function __mmSetHudValue(__mmKey, __mmValue) {
if (__mmKey === "killMessage")
return (
(__mmKillMessage = String(__mmValue || "").slice(0, 30)),
void __mmPublishHudState()
);
__mmKey === "soldierRange" ||
__mmKey === "combatRange" ||
__mmKey === "gearHoldTicks" ||
__mmKey === "passiveSpikeEnemyRange" ||
__mmKey === "antiBoostRange" ||
__mmKey === "reactionMs"
? __mmSetHudNumber(__mmKey, __mmValue)
: __mmSetHudToggle(__mmKey, __mmValue);
}
function __mmApplyHudSettings(__mmSettings) {
if (!__mmSettings || typeof __mmSettings !== "object") return;
Object.prototype.hasOwnProperty.call(__mmSettings, "friendNames") &&
__mmReplaceFriends(__mmSettings.friendNames);
const __mmKeys = [
"autoHeal",
"soldierAuto",
"movementGear",
"passiveSpikeAvoidance",
"trapEscape",
"antiBoost",
"antiBoostInsta",
"threatTrap",
"autoCloseSpike",
"reloadSpike",
"shieldDefense",
"musketRecharge",
"autoPurchase",
"matThief",
"mobSteal",
"spinningWindmills",
"esp",
"espLines",
"predictionGhost",
"cooldownBars",
"bullHelmet",
"tankRightClick",
"allItemsUnlock",
"instaKill",
"autoInsta",
"autoSpikeInsta",
"autoSpikeSpam",
"antiInsta",
"instaSync",
"boostBreak",
"boostChat",
"materialReply",
"syncLeader",
"syncFollower",
"debugPanel",
"killMessageEnabled",
"killMessage",
"soldierRange",
"combatRange",
"gearHoldTicks",
"passiveSpikeEnemyRange",
"antiBoostRange",
"reactionMs",
];
for (let __mmIndex = 0; __mmIndex < __mmKeys.length; __mmIndex++) {
const __mmKey = __mmKeys[__mmIndex];
Object.prototype.hasOwnProperty.call(__mmSettings, __mmKey) &&
__mmSetHudValue(__mmKey, __mmSettings[__mmKey]);
}
__mmPublishHudState();
}
function __mmHandleHudCommand(__mmEvent) {
const __mmCommand = __mmEvent.detail || {};
if (__mmCommand.type === "hydrate")
return void __mmApplyHudSettings(__mmCommand.settings);
if (__mmCommand.type === "set")
return void __mmSetHudValue(__mmCommand.key, __mmCommand.value);
if (__mmCommand.type === "friend-add")
return void __mmAddFriend(__mmCommand.name, !0);
if (__mmCommand.type === "friend-remove")
return void __mmRemoveFriend(__mmCommand.name, !0);
__mmPublishHudState();
}
window.addEventListener("MooMooOPHudCommand", __mmHandleHudCommand);
function __mmTankGearActive() {
return !!(v && v.skinIndex === 40);
}
function __mmMovementGearActive() {
return (
__mmMovementGearPreviousHat != null || __mmMovementGearPreviousTail != null
);
}
function __mmRememberNormalHat() {
v && v.alive && v.skinIndex !== 40 && (__mmLastNormalHat = v.skinIndex);
}
function __mmEquipHatNow(__mmHat, __mmOverridePending) {
if (
!v ||
!v.alive ||
__mmHat == null ||
(__mmHat !== 0 && !(v.skins && v.skins[__mmHat]))
)
return !1;
const __mmHasConflictingPendingEquip = !!(
__mmOverridePending &&
__mmPendingHat != null &&
__mmPendingHat !== __mmHat
);
if (v.skinIndex === __mmHat && !__mmHasConflictingPendingEquip) {
__mmPendingHat === __mmHat &&
((__mmPendingHat = null), (__mmPendingHatAt = 0));
return !0;
}
const __mmNow = Date.now();
if (
__mmPendingHat === __mmHat &&
__mmNow - __mmPendingHatAt < __mmServerTickMs()
)
return !0;
return (
O.send("c", 0, __mmHat, !1),
(__mmPendingHat = __mmHat),
(__mmPendingHatAt = __mmNow),
__mmHat !== 40 && (__mmLastNormalHat = __mmHat),
!0
);
}
function __mmEquipTailNow(__mmTail, __mmOverridePending) {
if (
!v ||
!v.alive ||
__mmTail == null ||
(__mmTail !== 0 && !(v.tails && v.tails[__mmTail]))
)
return !1;
const __mmHasConflictingPendingEquip = !!(
__mmOverridePending &&
__mmPendingTail != null &&
__mmPendingTail !== __mmTail
);
if (v.tailIndex === __mmTail && !__mmHasConflictingPendingEquip) {
__mmPendingTail === __mmTail &&
((__mmPendingTail = null), (__mmPendingTailAt = 0));
return !0;
}
const __mmNow = Date.now();
if (
__mmPendingTail === __mmTail &&
__mmNow - __mmPendingTailAt < __mmServerTickMs()
)
return !0;
return (
O.send("c", 0, __mmTail, !0),
(__mmPendingTail = __mmTail),
(__mmPendingTailAt = __mmNow),
!0
);
}
function __mmEquipGearPair(__mmHat, __mmTail, __mmOverridePending) {
if (!v || !v.alive) return !1;
const __mmHatValid = !!(
__mmHat != null &&
(__mmHat === 0 || (v.skins && v.skins[__mmHat]))
),
__mmTailValid = !!(
__mmTail != null &&
(__mmTail === 0 || (v.tails && v.tails[__mmTail]))
),
__mmNow = Date.now(),
__mmTick = __mmServerTickMs(),
// Combat/restore pairs must remain pairs even if one side is already the
// visible value or has an identical request awaiting acknowledgement.
__mmForcePair = !!(
__mmOverridePending &&
__mmHatValid &&
__mmTailValid
),
__mmHatConflict = !!(
__mmOverridePending &&
__mmPendingHat != null &&
__mmPendingHat !== __mmHat
),
__mmTailConflict = !!(
__mmOverridePending &&
__mmPendingTail != null &&
__mmPendingTail !== __mmTail
),
__mmSendHat = !!(
__mmHatValid &&
(__mmForcePair ||
v.skinIndex !== __mmHat ||
__mmHatConflict) &&
(__mmForcePair ||
__mmPendingHat !== __mmHat ||
__mmNow - __mmPendingHatAt >= __mmTick)
),
__mmSendTail = !!(
__mmTailValid &&
(__mmForcePair ||
v.tailIndex !== __mmTail ||
__mmTailConflict) &&
(__mmForcePair ||
__mmPendingTail !== __mmTail ||
__mmNow - __mmPendingTailAt >= __mmTick)
);
// Decide both slots first, then emit both socket packets synchronously with
// the same timestamp. No timer, microtask, acknowledgement, or helper call
// is allowed between the paired packets.
const __mmWasPairing = __mmSyncGearPairDispatch;
__mmSyncGearPairDispatch = !0;
try {
(__mmSendHat &&
(O.send("c", 0, __mmHat, !1),
(__mmPendingHat = __mmHat),
(__mmPendingHatAt = __mmNow),
__mmHat !== 40 && (__mmLastNormalHat = __mmHat)),
__mmSendTail &&
(O.send("c", 0, __mmTail, !0),
(__mmPendingTail = __mmTail),
(__mmPendingTailAt = __mmNow)));
} finally {
__mmSyncGearPairDispatch = __mmWasPairing;
}
!__mmWasPairing &&
(__mmHat != null || __mmTail != null) &&
__mmSyncPublishGearPair(__mmHat, __mmTail);
return __mmSendHat || __mmSendTail;
}
function __mmSetProximityTail(__mmTail) {
if (!v || __mmTail == null) return;
(__mmProximityTailPrevious == null &&
(__mmProximityTailPrevious = v.tailIndex),
__mmEquipTailNow(__mmTail));
}
function __mmRestoreProximityTail() {
if (__mmProximityTailPrevious == null) return;
if (!v || !v.alive) return void (__mmProximityTailPrevious = null);
const __mmTail = __mmProximityTailPrevious;
((__mmProximityTailPrevious = null), __mmEquipTailNow(__mmTail));
}
function __mmClearIdleMonkeyTail() {
if (
!v ||
!v.alive ||
__mmPlayerMoving() ||
__mmBoostBreakHeld ||
v.tailIndex !== 11
)
return;
const __mmTail = __mmMovementGearPreviousTail;
__mmMovementGearPreviousTail = null;
const __mmRestoreTail =
__mmTail === 0 || (__mmTail != null && v.tails && v.tails[__mmTail])
? __mmTail
: 0;
__mmEquipTailNow(__mmRestoreTail);
}
function __mmHeldAttackWeapon() {
return !v || !v.alive || !v.weapons
? null
: __mmSecondaryHeld
? __mmRightClickWeapon()
: __mmPrimaryHeld
? v.weapons[0]
: null;
}
function __mmSendWeaponAttack(__mmState) {
O.send("F", __mmState, null);
}
function __mmPulseHeldAttack() {
const __mmWeapon = __mmHeldAttackWeapon();
if (__mmWeapon == null) return;
if (__mmSecondaryHeld) return void __mmPulseSecondaryWeapon();
if (__mmPrimaryHeld && __mmBullPrimaryAvailable())
return void __mmPulsePrimaryBullWeapon();
(je(__mmWeapon, !0), __mmSendWeaponAttack(1));
}
function __mmStartHeldAttackPulse() {
__mmPulseHeldAttack();
if (__mmHeldAttackTimer) return;
__mmHeldAttackTimer = setInterval(function () {
__mmHeldAttackWeapon() != null
? __mmPulseHeldAttack()
: __mmStopHeldAttackPulse();
}, __mmServerTickMs());
}
function __mmStopHeldAttackPulse() {
if (__mmPrimaryHeld || __mmSecondaryHeld) return;
(__mmHeldAttackTimer &&
(clearInterval(__mmHeldAttackTimer), (__mmHeldAttackTimer = 0)),
v && v.alive && __mmSendWeaponAttack(0));
}
function __mmResumeHeldAttack() {
if (
__mmTrapAttackActive &&
__mmTrapAttackHeld &&
__mmTrapAttackHeldWeapon != null
) {
const __mmAngle = Number.isFinite(__mmTrapAimAngle)
? __mmTrapAimAngle
: Ci();
(je(__mmTrapAttackHeldWeapon, !0),
O.send("D", __mmAngle),
O.send("F", 1, __mmAngle));
return;
}
__mmPulseHeldAttack();
}
function __mmCanEat() {
if (!v || !v.alive || v.items[0] == null) return !1;
const __mmFood = b.list[v.items[0]];
if (!__mmFood || !__mmFood.consume || !__mmFood.req) return !1;
for (
let __mmReqIndex = 0;
__mmReqIndex < __mmFood.req.length;
__mmReqIndex += 2
)
if ((v[__mmFood.req[__mmReqIndex]] || 0) < __mmFood.req[__mmReqIndex + 1])
return !1;
return !0;
}
function __mmFoodCharges() {
if (!__mmCanEat()) return 0;
const __mmFood = b.list[v.items[0]];
let __mmCharges = Infinity;
for (
let __mmReqIndex = 0;
__mmReqIndex < __mmFood.req.length;
__mmReqIndex += 2
)
__mmCharges = Math.min(
__mmCharges,
Math.floor(
(v[__mmFood.req[__mmReqIndex]] || 0) / __mmFood.req[__mmReqIndex + 1],
),
);
return Number.isFinite(__mmCharges) ? Math.max(0, __mmCharges) : 0;
}
function __mmUseFood() {
if (!__mmCanEat()) return;
const __mmTool = __mmSelectedTool();
(je(v.items[0]),
O.send("F", 1, Ci()),
O.send("F", 0, Ci()),
__mmRestoreTool(__mmTool),
__mmResumeHeldAttack());
}
function __mmUseFoodBurst(__mmCount) {
const __mmBites = Math.min(Math.max(0, __mmCount | 0), __mmFoodCharges());
if (!__mmBites) return;
const __mmFood = v.items[0],
__mmAngle = Ci(),
__mmTool = __mmSelectedTool();
for (let __mmBite = 0; __mmBite < __mmBites; __mmBite++)
(je(__mmFood), O.send("F", 1, __mmAngle), O.send("F", 0, __mmAngle));
(__mmRestoreTool(__mmTool), __mmResumeHeldAttack());
}
function __mmAtFullHealth() {
return v && v.alive && v.health >= v.maxHealth;
}
function __mmSelectedWeapon() {
return !v || !v.alive
? null
: v.weapons.includes(__mmLastWeapon)
? __mmLastWeapon
: v.weapons.includes(v.weaponIndex)
? v.weaponIndex
: v.weapons[0];
}
function __mmHoldingMcGrabby() {
return !!(
v &&
v.alive &&
Number(v.buildIndex) < 0 &&
Number(__mmSelectedWeapon()) === __mmMcGrabby
);
}
function __mmRestoreWeapon(__mmWeapon) {
v && v.alive && v.weapons.includes(__mmWeapon) && je(__mmWeapon, !0);
}
function __mmSelectedTool() {
if (!v || !v.alive) return null;
const __mmBuild = Number(v.buildIndex);
if (
Number.isInteger(__mmBuild) &&
__mmBuild >= 0 &&
v.items &&
v.items.includes(__mmBuild)
)
return { item: __mmBuild, weapon: !1 };
const __mmWeapon = __mmSelectedWeapon();
return __mmWeapon == null ? null : { item: __mmWeapon, weapon: !0 };
}
function __mmRestoreTool(__mmTool) {
if (!v || !v.alive || !__mmTool) return;
__mmTool.weapon
? __mmRestoreWeapon(__mmTool.item)
: v.items && v.items.includes(__mmTool.item) && je(__mmTool.item);
}
const __mmCleanupRadius = 1000,
__mmCleanupInputKeys = Object.freeze({
87: !0,
65: !0,
83: !0,
68: !0,
70: !0,
86: !0,
82: !0,
72: !0,
90: !0,
});
function __mmCleanupObjectScale(__mmObject) {
if (!__mmObject) return 0;
if (typeof __mmObject.getScale === "function") {
const __mmScale = Number(__mmObject.getScale(0.6, !!__mmObject.isItem));
if (Number.isFinite(__mmScale) && __mmScale > 0) return __mmScale;
}
return Math.max(
1,
Number(__mmObject.blocker) ||
Number(__mmObject.scale) ||
Number(b && b.list && b.list[__mmObject.id] && b.list[__mmObject.id].scale) ||
35,
);
}
function __mmCleanupIsSpike(__mmObject) {
const __mmItem = __mmObject && b && b.list && b.list[__mmObject.id],
__mmName = String((__mmItem && __mmItem.name) || "").toLowerCase();
return __mmName.includes("spikes");
}
function __mmCleanupStructureAllowed(__mmObject) {
const __mmData = __mmObject && b && b.list && b.list[__mmObject.id];
if (
!__mmCleanupActive ||
!__mmObject ||
!__mmObject.active ||
!__mmObject.isItem ||
!__mmData ||
!__mmData.group ||
!__mmData.group.place
)
return !1;
const __mmState = __mmBreakableState(__mmObject),
__mmLiveHealth = Number(__mmObject.health),
__mmHealth = __mmState
? Number(__mmState.health)
: Number.isFinite(__mmLiveHealth)
? __mmLiveHealth
: Number(__mmData.health);
if (!Number.isFinite(__mmHealth) || __mmHealth <= 0.001) return !1;
const __mmDx = Number(__mmObject.x) - __mmCleanupOriginX,
__mmDy = Number(__mmObject.y) - __mmCleanupOriginY;
return (
Number.isFinite(__mmDx) &&
Number.isFinite(__mmDy) &&
__mmDx * __mmDx + __mmDy * __mmDy <=
__mmCleanupRadius * __mmCleanupRadius
);
}
function __mmCleanupSafeDistance(__mmObject) {
return (
(Number(v && v.scale) || 35) +
__mmCleanupObjectScale(__mmObject) +
(__mmCleanupIsSpike(__mmObject) ? 18 : 8)
);
}
function __mmCleanupWeaponPlan(__mmObject) {
if (!v || !v.alive || !Array.isArray(v.weapons)) return null;
const __mmSafe = __mmCleanupSafeDistance(__mmObject),
__mmScale = __mmCleanupObjectScale(__mmObject);
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
const __mmWeapon = v.weapons[__mmIndex],
__mmData = b && b.weapons && b.weapons[__mmWeapon];
if (!__mmData || __mmData.projectile != null) continue;
const __mmDamage = __mmWeaponStructureDamage(v, __mmWeapon, __mmObject),
__mmRange = Number(__mmData.range) || 0,
__mmReach = __mmRange + __mmScale - 5,
__mmSpeed = Math.max(50, Number(__mmData.speed) || 400);
if (__mmDamage <= 0 || __mmReach < __mmSafe + 2) continue;
const __mmScore = __mmDamage / __mmSpeed + __mmRange / 1e6;
if (
!__mmBest ||
__mmScore > __mmBest.score ||
(__mmScore === __mmBest.score && __mmReach > __mmBest.reach)
)
__mmBest = {
weapon: __mmWeapon,
damage: __mmDamage,
speed: __mmSpeed,
reach: __mmReach,
safe: __mmSafe,
score: __mmScore,
};
}
return __mmBest;
}
function __mmCleanupHasRemaining() {
if (!Array.isArray(ge)) return !1;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++)
if (__mmCleanupStructureAllowed(ge[__mmIndex])) return !0;
return !1;
}
function __mmCleanupNearestTarget(__mmNow) {
if (!v || !v.alive || !Array.isArray(ge)) return null;
let __mmBest = null,
__mmBestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmObject = ge[__mmIndex];
if (!__mmCleanupStructureAllowed(__mmObject)) continue;
const __mmReservedUntil = Number(__mmCleanupReservations.get(__mmObject));
if (Number.isFinite(__mmReservedUntil) && __mmReservedUntil > __mmNow)
continue;
const __mmPlan = __mmCleanupWeaponPlan(__mmObject);
if (!__mmPlan) {
__mmCleanupReservations.set(__mmObject, __mmNow + 750);
continue;
}
const __mmDistance = Math.hypot(
Number(__mmObject.x) - Number(v.x),
Number(__mmObject.y) - Number(v.y),
);
if (Number.isFinite(__mmDistance) && __mmDistance < __mmBestDistance)
((__mmBestDistance = __mmDistance),
(__mmBest = { object: __mmObject, plan: __mmPlan }));
}
return __mmBest;
}
function __mmCleanupSetMovement(__mmAngle) {
if (!v || !v.alive) {
((__mmCleanupMoveAngle = null), (Kt = null));
return;
}
if (!Number.isFinite(__mmAngle)) {
if (__mmCleanupMoveAngle == null) return;
((__mmCleanupMoveAngle = null), (Kt = null), O.send("9", null));
return;
}
const __mmFixed =
typeof M.fixTo === "function" ? M.fixTo(__mmAngle, 2) : __mmAngle,
__mmDifference =
__mmCleanupMoveAngle == null
? Infinity
: Math.abs(
Math.atan2(
Math.sin(__mmFixed - __mmCleanupMoveAngle),
Math.cos(__mmFixed - __mmCleanupMoveAngle),
),
);
if (__mmDifference < 0.04) return;
((__mmCleanupMoveAngle = __mmFixed),
(Kt = __mmFixed),
O.send("9", __mmFixed));
}
function __mmCleanupReleaseAttack() {
if (!__mmCleanupAttackHeld) return;
(O.send(
"F",
0,
Number.isFinite(__mmCleanupAimAngle) ? __mmCleanupAimAngle : null,
),
(__mmCleanupAttackHeld = !1),
(__mmCleanupAimAngle = null),
(__mmCleanupWeapon = null));
}
function __mmCleanupSteeringAngle(__mmDesired, __mmTarget) {
if (!v || !v.alive || !Array.isArray(ge)) return __mmDesired;
const __mmOffsets = [0, 0.24, -0.24, 0.48, -0.48, 0.78, -0.78, 1.08, -1.08, 1.57, -1.57],
__mmPlayerScale = Number(v.scale) || 35,
__mmStep = 90;
let __mmBestAngle = __mmDesired,
__mmBestScore = Infinity;
for (let __mmOffsetIndex = 0; __mmOffsetIndex < __mmOffsets.length; __mmOffsetIndex++) {
const __mmAngle = __mmDesired + __mmOffsets[__mmOffsetIndex],
__mmEndX = Number(v.x) + Math.cos(__mmAngle) * __mmStep,
__mmEndY = Number(v.y) + Math.sin(__mmAngle) * __mmStep;
let __mmScore = Math.abs(__mmOffsets[__mmOffsetIndex]) * 15;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmObject = ge[__mmIndex];
if (
!__mmObject ||
__mmObject === __mmTarget ||
!__mmObject.active
)
continue;
const __mmClearance =
__mmPlayerScale +
__mmCleanupObjectScale(__mmObject) +
(__mmCleanupIsSpike(__mmObject) ? 20 : 6),
__mmDistanceSquared = __mmSegmentDistanceSquared(
Number(v.x),
Number(v.y),
__mmEndX,
__mmEndY,
Number(__mmObject.x),
Number(__mmObject.y),
);
if (__mmDistanceSquared < __mmClearance * __mmClearance) {
const __mmDistance = Math.sqrt(Math.max(0, __mmDistanceSquared));
__mmScore +=
1e4 + (__mmClearance - __mmDistance) *
(__mmCleanupIsSpike(__mmObject) ? 100 : 25);
}
}
if (__mmScore < __mmBestScore)
((__mmBestScore = __mmScore), (__mmBestAngle = __mmAngle));
}
return __mmBestAngle;
}
function __mmCleanupAttackTarget(__mmEntry, __mmAngle, __mmNow) {
const __mmObject = __mmEntry.object,
__mmPlan = __mmEntry.plan,
__mmState = __mmBreakableState(__mmObject),
__mmData = b && b.list && b.list[__mmObject.id],
__mmLiveHealth = Number(__mmObject.health),
__mmHealth = __mmState
? Number(__mmState.health)
: Number.isFinite(__mmLiveHealth)
? __mmLiveHealth
: Number(__mmData && __mmData.health) || 1;
__mmCleanupSetMovement(null);
__mmCleanupAimAngle = __mmAngle;
if (__mmCleanupWeapon !== __mmPlan.weapon) {
(__mmCleanupReleaseAttack(),
(__mmCleanupWeapon = __mmPlan.weapon),
je(__mmPlan.weapon, !0));
}
if (!__mmCleanupAttackHeld)
(O.send("D", __mmAngle),
O.send("F", 1, __mmAngle),
(__mmCleanupAttackHeld = !0));
else O.send("D", __mmAngle);
if (
__mmCleanupTargetHealth == null ||
__mmHealth < __mmCleanupTargetHealth - 0.001
)
((__mmCleanupTargetHealth = __mmHealth),
(__mmCleanupProgressAt = __mmNow));
const __mmStallMs = Math.max(
2200,
__mmPlan.speed *
(Math.max(1, Math.ceil(__mmHealth / Math.max(1, __mmPlan.damage))) + 2) +
__mmServerTickMs() * 2,
);
if (__mmNow - __mmCleanupProgressAt > __mmStallMs) {
(__mmCleanupReleaseAttack(),
__mmCleanupReservations.set(__mmObject, __mmNow + 900),
(__mmCleanupTarget = null),
(__mmCleanupTargetHealth = null));
}
}
function __mmUpdateCleanup() {
if (!__mmCleanupActive) return;
if (document.hidden || !v || !v.alive)
return void __mmStopCleanup("runtime unavailable", !1);
if (__mmActionOwner !== "cleanup")
return void __mmStopCleanup("action ownership lost", !1);
const __mmNow = Date.now();
let __mmEntry = __mmCleanupTarget;
if (!__mmEntry || !__mmCleanupStructureAllowed(__mmEntry.object)) {
(__mmCleanupReleaseAttack(),
(__mmCleanupTarget = null),
(__mmCleanupTargetHealth = null),
(__mmEntry = __mmCleanupNearestTarget(__mmNow)));
if (__mmEntry) {
((__mmCleanupTarget = __mmEntry),
(__mmCleanupTargetHealth = null),
(__mmCleanupProgressAt = __mmNow),
(__mmCleanupEmptySince = 0));
}
}
if (!__mmEntry) {
(__mmCleanupSetMovement(null), __mmCleanupReleaseAttack());
if (__mmCleanupHasRemaining()) {
__mmCleanupEmptySince = 0;
return;
}
__mmCleanupEmptySince || (__mmCleanupEmptySince = __mmNow);
if (__mmNow - __mmCleanupEmptySince >= Math.max(650, Number(y && y.chatCooldown) + 100 || 650))
__mmStopCleanup("radius complete", !0);
return;
}
const __mmObject = __mmEntry.object,
__mmDx = Number(__mmObject.x) - Number(v.x),
__mmDy = Number(__mmObject.y) - Number(v.y),
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmAngle = Math.atan2(__mmDy, __mmDx),
__mmSafe = __mmEntry.plan.safe,
__mmReach = __mmEntry.plan.reach,
__mmStopDistance = Math.max(
__mmSafe + 2,
Math.min(__mmReach - 4, __mmSafe + 14),
);
if (!Number.isFinite(__mmDistance)) {
__mmCleanupTarget = null;
return;
}
if (__mmDistance < __mmSafe) {
(__mmCleanupReleaseAttack(),
__mmCleanupSetMovement(
__mmCleanupSteeringAngle(__mmAngle + Math.PI, __mmObject),
));
return;
}
if (__mmDistance > __mmStopDistance) {
(__mmCleanupReleaseAttack(),
__mmCleanupSetMovement(
__mmCleanupSteeringAngle(__mmAngle, __mmObject),
));
return;
}
if (__mmDistance <= __mmReach)
return void __mmCleanupAttackTarget(__mmEntry, __mmAngle, __mmNow);
__mmCleanupSetMovement(__mmCleanupSteeringAngle(__mmAngle, __mmObject));
}
function __mmCleanupProgressChat() {
if (!__mmCleanupActive) return;
const __mmLines = ["Cleaning.", "Cleaning..", "Cleaning..."];
(__mmSendChat(__mmLines[__mmCleanupChatStep % __mmLines.length]),
(__mmCleanupChatStep += 1));
}
function __mmStartCleanup() {
if (__mmCleanupActive || document.hidden || !v || !v.alive) return !1;
(__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmActionOwner === "matThief" && __mmFinishMatThief("cleanup started"),
__mmActionOwner === "mobSteal" && __mmFinishMobSteal("cleanup started"));
if (!__mmActionClaim("cleanup", "clearing 1000px radius")) return !1;
(__mmRestoreMovementGear(),
(__mmCleanupActive = !0),
(__mmCleanupOriginX = Number(v.x) || 0),
(__mmCleanupOriginY = Number(v.y) || 0),
(__mmCleanupTarget = null),
(__mmCleanupSavedTool = __mmSelectedTool()),
(__mmCleanupWeapon = null),
(__mmCleanupAttackHeld = !1),
(__mmCleanupAimAngle = null),
(__mmCleanupMoveAngle = null),
(__mmCleanupTargetHealth = null),
(__mmCleanupProgressAt = Date.now()),
(__mmCleanupEmptySince = 0),
(__mmCleanupChatStep = 0),
__mmCleanupProgressChat(),
(__mmCleanupProgressTimer = setInterval(
__mmCleanupProgressChat,
Math.max(750, (Number(y && y.chatCooldown) || 500) + 150),
)),
(__mmCleanupTimer = setInterval(__mmUpdateCleanup, __mmFastCheckMs())),
__mmUpdateCleanup());
return !0;
}
function __mmStopCleanup(__mmReason, __mmCompleted) {
if (!__mmCleanupActive && __mmActionOwner !== "cleanup") return;
const __mmTool = __mmCleanupSavedTool,
__mmCanRestore = __mmActionMayRestore("cleanup");
((__mmCleanupActive = !1),
__mmCleanupTimer && clearInterval(__mmCleanupTimer),
(__mmCleanupTimer = 0),
__mmCleanupProgressTimer && clearInterval(__mmCleanupProgressTimer),
(__mmCleanupProgressTimer = 0),
__mmCleanupSetMovement(null),
__mmCleanupReleaseAttack(),
(__mmCleanupTarget = null),
(__mmCleanupSavedTool = null),
(__mmCleanupWeapon = null),
(__mmCleanupAimAngle = null),
(__mmCleanupTargetHealth = null),
(__mmCleanupEmptySince = 0),
__mmCanRestore && __mmRestoreTool(__mmTool),
__mmActionRelease("cleanup", __mmReason || "stopped"),
__mmScheduleMouseAimReturn(),
__mmCompleted && __mmSendChat("Nice and tidy!"));
}
function __mmToggleCleanup() {
return __mmCleanupActive
? (__mmStopCleanup("C toggled off", !1), !1)
: __mmStartCleanup();
}
function __mmCleanupInputKey(__mmKey) {
__mmCleanupActive &&
__mmCleanupInputKeys[Number(__mmKey)] &&
__mmStopCleanup("manual key", !1);
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
__mmCleanupActive &&
__mmEvent.isTrusted &&
__mmStopCleanup("manual click", !1);
},
!0,
);
function __mmWeaponIsReloading(__mmWeapon) {
if (
!v ||
!v.alive ||
!v.weapons ||
__mmWeapon == null ||
!v.weapons.includes(__mmWeapon)
)
return !1;
const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]);
return Number.isFinite(__mmReload) && __mmReload > 0;
}
function __mmMusketIsReloading() {
return __mmWeaponIsReloading(__mmMusket);
}
function __mmTurretGearIsReloading() {
return !!(
v &&
v.alive &&
v.skinIndex === __mmTurretGear &&
Date.now() < __mmTurretReloadUntil
);
}
function __mmTrackTurretGearReload(__mmPlayerSid) {
if (
!v ||
!v.alive ||
__mmPlayerSid !== v.sid ||
v.skinIndex !== __mmTurretGear
)
return;
// Turret Gear fires once every 2.5 seconds. The client does not expose a
// reload entry for hats, so keep a local cooldown from its attack event.
__mmTurretReloadUntil = Math.max(__mmTurretReloadUntil, Date.now() + 2500);
}
function __mmWeaponRechargeOverridden() {
return (
!v ||
!v.alive ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmInsta.attackHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmAutoHealWasHealing ||
__mmShieldDefenseTimer ||
!__mmActionAvailable("weaponRecharge")
);
}
function __mmNextWeaponToRecharge() {
if (!v || !v.alive || !v.weapons) return null;
const __mmSeen = new Set();
// Inventory order is main first, then secondary/any additional weapons.
// Checking every slot makes the queue survive weapon upgrades and swaps.
for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
const __mmWeapon = v.weapons[__mmIndex];
if (__mmWeapon == null || __mmSeen.has(__mmWeapon)) continue;
__mmSeen.add(__mmWeapon);
if (__mmWeaponIsReloading(__mmWeapon)) return __mmWeapon;
}
return null;
}
function __mmWeaponRechargeSelected(__mmWeapon) {
return !!(
v &&
v.alive &&
Number(v.buildIndex) < 0 &&
Number(v.weaponIndex) === Number(__mmWeapon)
);
}
function __mmWeaponRechargeCurrentTool() {
if (!v || !v.alive) return null;
const __mmBuild = Number(v.buildIndex);
if (
Number.isInteger(__mmBuild) &&
__mmBuild >= 0 &&
v.items &&
v.items.includes(__mmBuild)
)
return { item: __mmBuild, weapon: !1 };
const __mmWeapon = Number(v.weaponIndex);
return v.weapons && v.weapons.includes(__mmWeapon)
? { item: __mmWeapon, weapon: !0 }
: __mmSelectedTool();
}
function __mmSelectWeaponForRecharge(__mmWeapon) {
if (__mmWeaponRechargeSelected(__mmWeapon)) return !0;
const __mmNow = Date.now();
if (__mmNow - __mmWeaponRechargeSelectAt >= 25) {
((__mmWeaponRechargeSelectAt = __mmNow), je(__mmWeapon, !0));
}
return __mmWeaponRechargeSelected(__mmWeapon);
}
function __mmPauseWeaponRecharge(__mmRestore) {
const __mmActive = __mmWeaponRechargeActiveWeapon,
__mmPrevious = __mmWeaponRechargePreviousTool;
(__mmRestore &&
__mmActionMayRestore("weaponRecharge") &&
__mmActive != null &&
__mmPrevious != null &&
__mmWeaponRechargeSelected(__mmActive) &&
__mmRestoreTool(__mmPrevious),
(__mmWeaponRechargeActiveWeapon = null),
(__mmWeaponRechargeSelectAt = 0),
__mmActionRelease("weaponRecharge", "reload paused"));
}
function __mmStopWeaponRecharge(__mmRestore) {
const __mmPrevious = __mmWeaponRechargePreviousTool;
((__mmWeaponRechargeActiveWeapon = null),
(__mmWeaponRechargePreviousTool = null),
(__mmWeaponRechargeSelectAt = 0),
__mmRestore &&
__mmPrevious != null &&
__mmActionMayRestore("weaponRecharge") &&
__mmRestoreTool(__mmPrevious),
__mmActionRelease("weaponRecharge", "reload queue complete"));
}
function __mmUpdateWeaponRecharge() {
if (
!__mmMusketRechargeEnabled ||
__mmSyncFollowerEnabled ||
!v ||
!v.alive ||
!v.weapons
)
return void __mmStopWeaponRecharge(!1);
const __mmTarget = __mmNextWeaponToRecharge(),
__mmActive = __mmWeaponRechargeActiveWeapon;
// Manual clicks and higher-priority actions pause selection but retain both
// the original tool and the server-reported cooldown queue. If a reload
// finishes during the override, restoration waits until input is released.
if (__mmWeaponRechargeOverridden()) {
__mmActive != null && __mmPauseWeaponRecharge(!1);
return;
}
if (__mmTarget == null) return void __mmStopWeaponRecharge(!0);
if (__mmActive === __mmTarget) {
__mmSelectWeaponForRecharge(__mmTarget);
return;
}
// A newly cooling main preempts the secondary. A completed main advances to
// the secondary immediately in this same scan without clearing queue state.
if (__mmActive != null) {
((__mmWeaponRechargeActiveWeapon = __mmTarget),
(__mmWeaponRechargeSelectAt = 0),
__mmSelectWeaponForRecharge(__mmTarget));
return;
}
if (!__mmActionClaim("weaponRecharge", "idle reload")) return;
((__mmWeaponRechargeActiveWeapon = __mmTarget),
__mmWeaponRechargePreviousTool == null &&
(__mmWeaponRechargePreviousTool = __mmWeaponRechargeCurrentTool()),
(__mmWeaponRechargeSelectAt = 0),
__mmSelectWeaponForRecharge(__mmTarget));
}
function __mmStartWeaponRecharge() {
__mmWeaponRechargeTimer ||
(__mmWeaponRechargeTimer = setInterval(__mmUpdateWeaponRecharge, 5));
}
function __mmRestoreAutoHealWeapon() {
// __mmUseFood restores the selected weapon after each safe food use. Keep
// this cleanup hook for the HUD toggle and for older event paths.
__mmAutoHealWeapon = null;
}
function __mmAutoHealFoodValue() {
if (!v || v.items[0] == null) return 20;
const __mmFood = b.list[v.items[0]];
const __mmDescription = String((__mmFood && __mmFood.desc) || "");
const __mmMatch = __mmDescription.match(/restores\\s+(\\d+)\\s+health/i);
return __mmMatch ? Math.max(1, Number(__mmMatch[1])) : 20;
}
function __mmObserveAutoHealHealth(__mmHealth) {
const __mmCurrentHealth = Number(__mmHealth);
if (!Number.isFinite(__mmCurrentHealth)) return !1;
const __mmNow = Date.now(),
__mmHadHealth = __mmAutoHealLastObservedHealth != null,
__mmTookDamage =
__mmHadHealth &&
__mmCurrentHealth < __mmAutoHealLastObservedHealth,
__mmHealed =
__mmHadHealth &&
__mmCurrentHealth > __mmAutoHealLastObservedHealth;
if (__mmTookDamage)
((__mmAutoHealPending = !0),
(__mmAutoHealBitesRemaining = 0),
(__mmAutoHealNextBiteAt = 0),
(__mmAutoHealLastDamageAt = __mmNow));
// Track manual healing too. Autoheal predicts its own result at send time
// and clears LastDamageAt there, so its later health packet is not counted
// twice. This mirrors the server's <=120ms increment / late-heal -2 rule.
if (__mmHealed && __mmAutoHealLastDamageAt) {
const __mmElapsed = __mmNow - __mmAutoHealLastDamageAt;
((__mmAutoHealShameCount =
__mmElapsed <= 120
? Math.min(8, __mmAutoHealShameCount + 1)
: Math.max(0, __mmAutoHealShameCount - 2)),
(__mmAutoHealLastDamageAt = 0));
}
// Queue one catch-up heal if the script begins while already injured. Later
// heals are queued only by actual damage packets, so the 10ms backup loop
// cannot resend the same burst while the server is processing it.
if (
!__mmTookDamage &&
__mmAutoHealLastObservedHealth == null &&
v &&
v.alive &&
__mmCurrentHealth < v.maxHealth
)
((__mmAutoHealPending = !0),
(__mmAutoHealBitesRemaining = 0),
(__mmAutoHealNextBiteAt = 0));
__mmAutoHealLastObservedHealth = __mmCurrentHealth;
return __mmTookDamage;
}
function __mmAutoHealRecordFoodAttempt(__mmNow) {
if (!__mmAutoHealLastDamageAt) return;
const __mmElapsed = __mmNow - __mmAutoHealLastDamageAt;
((__mmAutoHealShameCount =
__mmElapsed <= 120
? Math.min(8, __mmAutoHealShameCount + 1)
: Math.max(0, __mmAutoHealShameCount - 2)),
// The server consumes the saved hit timestamp on this food attempt. Clear
// ours immediately as well; no acknowledgement retry is involved.
(__mmAutoHealLastDamageAt = 0));
}
function __mmAutoHealSafeAt(__mmEmergency, __mmFoodValue) {
if (!__mmAutoHealLastDamageAt || __mmAutoHealShameCount < 5)
return 0;
const __mmLowHealth =
v.health <= Math.max(35, Number(__mmFoodValue) || 20);
// Survival wins over Shame prevention. At non-critical health, 135ms from
// the received damage packet is deliberately beyond the server's 120ms
// comparison and turns this heal into a two-point counter reduction.
return __mmEmergency || __mmLowHealth
? 0
: __mmAutoHealLastDamageAt + 135;
}
function __mmResetAutoHeal() {
((__mmAutoHealWasHealing = !1),
(__mmAutoHealPending = !1),
(__mmAutoHealBitesRemaining = 0),
(__mmAutoHealNextBiteAt = 0),
(__mmAutoHealLastObservedHealth = v && v.alive ? Number(v.health) : null),
__mmRestoreAutoHealWeapon());
}
function __mmAutoHeal(__mmEmergency) {
if (!__mmAutoHealEnabled || !v || !v.alive)
return void __mmResetAutoHeal();
__mmObserveAutoHealHealth(v.health);
// Shame! (hat 45) means the server is rejecting food for its 30-second
// penalty. Do not burn resources or flood selection/attack packets during it.
if (Number(v.skinIndex) === 45) {
((__mmAutoHealShameCount = 8),
(__mmAutoHealPending = !1),
(__mmAutoHealBitesRemaining = 0),
(__mmAutoHealNextBiteAt = 0));
return;
}
if (v.health >= v.maxHealth || !__mmCanEat()) return void __mmResetAutoHeal();
if (__mmAutoHealPending) {
// Calculate the whole refill from the hit packet, then keep sending it on
// the server tick. This is optimistic (it never waits for a heal reply),
// but avoids the current server dropping a pile of same-frame F packets.
const __mmMissingHealth = Math.max(0, v.maxHealth - v.health),
__mmFoodValue = __mmAutoHealFoodValue(),
__mmNow = Date.now(),
__mmSafeAt = __mmAutoHealSafeAt(__mmEmergency, __mmFoodValue);
((__mmAutoHealBitesRemaining = Math.min(
Math.ceil(__mmMissingHealth / __mmFoodValue),
__mmFoodCharges(),
)),
(__mmAutoHealPending = !1),
(__mmAutoHealNextBiteAt = Math.max(__mmNow, __mmSafeAt || 0)));
}
if (!__mmAutoHealBitesRemaining || Date.now() < __mmAutoHealNextBiteAt)
return;
// A held mouse attack remains the action owner while food is pulsed between
// swings. __mmUseFood restores the selected tool and resumes the live held
// attack immediately, so healing does not require releasing either button.
const __mmHealingDuringHeldAttack = !!(
__mmActionOwner === "manualAttack" &&
(__mmPrimaryHeld || __mmSecondaryHeld)
),
__mmOwnsAction = __mmHealingDuringHeldAttack
? !1
: __mmActionClaim("autoHeal", "food recovery");
if (
!__mmOwnsAction &&
!__mmHealingDuringHeldAttack &&
!(__mmEmergency && __mmActionOwner === "trapEscape")
)
return;
const __mmFoodSentAt = Date.now();
((__mmAutoHealWasHealing = !0),
__mmAutoHealRecordFoodAttempt(__mmFoodSentAt),
__mmUseFood(),
(__mmAutoHealWasHealing = !1),
(__mmAutoHealBitesRemaining -= 1),
(__mmAutoHealNextBiteAt =
Date.now() + Math.max(1, __mmServerTickMs())),
__mmOwnsAction && __mmActionRelease("autoHeal", "food sent"));
}
function __mmToggleAutoHeal() {
__mmSetAutoHeal(!__mmAutoHealEnabled);
}
function __mmTemporaryHatOverlay() {
return (
!v ||
!v.alive ||
__mmSyncFollowerEnabled ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmTankGearActive() ||
__mmPrimaryClickHat != null ||
__mmRightClickHat != null ||
__mmTrapHat != null ||
(__mmSoldierPreviousHat != null &&
!(__mmShiftSpeedActive && __mmShiftMode === 1))
);
}
function __mmInSnowBiome() {
return !!(
v &&
Number.isFinite(Number(v.y)) &&
y &&
Number.isFinite(Number(y.snowBiomeTop)) &&
v.y <= y.snowBiomeTop
);
}
function __mmInWater() {
if (
!v ||
!y ||
!Number.isFinite(Number(v.y)) ||
!Number.isFinite(Number(y.mapScale)) ||
!Number.isFinite(Number(y.riverWidth))
)
return !1;
const __mmRiverMiddle = y.mapScale / 2,
__mmRiverHalf = y.riverWidth / 2;
return (
v.y >= __mmRiverMiddle - __mmRiverHalf &&
v.y <= __mmRiverMiddle + __mmRiverHalf
);
}
function __mmBuyFlipperHat() {
if (
!__mmInWater() ||
!v ||
!v.alive ||
(v.skins && v.skins[__mmFlipperHat]) ||
(v.points || 0) < __mmFlipperHatPrice ||
Date.now() - __mmFlipperPurchaseAt < 500
)
return !1;
return ((__mmFlipperPurchaseAt = Date.now()), Xn(__mmFlipperHat, !1), !0);
}
function __mmBuySnowHat() {
if (
!__mmInSnowBiome() ||
!v ||
!v.alive ||
(v.skins && v.skins[__mmSnowHat]) ||
(v.points || 0) < __mmSnowHatPrice ||
Date.now() - __mmSnowPurchaseAt < 500
)
return !1;
return ((__mmSnowPurchaseAt = Date.now()), Xn(__mmSnowHat, !1), !0);
}
function __mmSpeedHat() {
return __mmInWater()
? __mmFlipperHat
: __mmInSnowBiome()
? v && v.skins && v.skins[__mmSnowHat]
? __mmSnowHat
: __mmBoosterHat
: __mmBoosterHat;
}
function __mmShiftHasSpeedGear() {
const __mmHat = __mmSpeedHat();
return !!(v && v.skins && v.skins[__mmHat] && v.tails && v.tails[11]);
}
function __mmShiftBaseHat() {
return __mmTrapHat != null
? __mmTrapHat
: __mmRightClickHat != null
? __mmRightClickHat
: __mmPrimaryClickHat != null
? __mmPrimaryClickHat
: __mmSoldierPreviousHat != null
? __mmSoldierPreviousHat
: v
? v.skinIndex
: null;
}
function __mmUpdateShiftSpeed() {
if (
!__mmShiftSpeedActive ||
__mmShiftMode !== 1 ||
__mmInsta.isActive()
)
return;
(__mmInWater() && __mmBuyFlipperHat(),
__mmInSnowBiome() && __mmBuySnowHat(),
__mmSoldierPreviousHat != null && __mmPauseSoldierForBreaking());
if (__mmTemporaryHatOverlay()) return;
const __mmHat = __mmSpeedHat();
if (!v.skins || !v.skins[__mmHat]) return;
__mmEquipGearPair(__mmHat, 11);
}
function __mmRestoreShiftSpeed() {
if (__mmShiftPreviousHat == null && __mmShiftPreviousTail == null) return;
if (!v || !v.alive)
return void ((__mmShiftPreviousHat = null), (__mmShiftPreviousTail = null));
// Do not restore the tail early while a temporary combat hat still owns the
// gear tick. Wait, then restore both saved slots in the same callback.
if (__mmTemporaryHatOverlay())
return void (
__mmShiftRestoreTimer ||
(__mmShiftRestoreTimer = setTimeout(function () {
((__mmShiftRestoreTimer = 0), __mmRestoreShiftSpeed());
}, __mmServerTickMs()))
);
const __mmHat = __mmShiftPreviousHat,
__mmTail = __mmShiftPreviousTail;
((__mmShiftPreviousHat = null),
(__mmShiftPreviousTail = null),
__mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmStartShiftSpeedGear() {
if (!v || !v.alive || !__mmShiftHasSpeedGear()) return;
((__mmShiftMode = 1),
(__mmShiftPreviousHat = __mmShiftBaseHat()),
(__mmShiftPreviousTail = v.tailIndex),
__mmShiftSpeedTimer ||
(__mmShiftSpeedTimer = setInterval(
__mmUpdateShiftSpeed,
__mmFastCheckMs(),
)),
__mmUpdateShiftSpeed());
}
function __mmWatchShiftGearPurchase() {
if (__mmShiftGearPurchaseTimer) return;
__mmShiftGearPurchaseTimer = setInterval(function () {
if (!__mmShiftSpeedActive)
return (
clearInterval(__mmShiftGearPurchaseTimer),
void (__mmShiftGearPurchaseTimer = 0)
);
if (!__mmShiftHasSpeedGear()) return;
(clearInterval(__mmShiftGearPurchaseTimer),
(__mmShiftGearPurchaseTimer = 0),
__mmStartShiftSpeedGear(),
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomShiftSpeed", {
detail: "Shift speed: On",
}),
));
}, __mmFastCheckMs());
}
function __mmBuySnowHatOnShift() {
return __mmBuySnowHat()
? (__mmWatchShiftGearPurchase(), !0)
: !1;
}
function __mmBuyMonkeyTailOnShift() {
if (
__mmInSnowBiome() ||
!v ||
!v.alive ||
(v.tails && v.tails[11]) ||
(v.points || 0) < 2e3
)
return !1;
return (Xn(11, !0), __mmWatchShiftGearPurchase(), !0);
}
function __mmStartShiftSpeed() {
if (__mmShiftSpeedActive) return;
((__mmShiftSpeedActive = !0),
__mmBuySnowHatOnShift(),
__mmBuyMonkeyTailOnShift());
if (__mmShiftHasSpeedGear()) {
(__mmStartShiftSpeedGear(),
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomShiftSpeed", {
detail: "Shift speed: On",
}),
));
return;
}
((__mmShiftMode = 2),
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomShiftSpeed", {
detail: "Shift speed gear unavailable",
}),
));
}
function __mmStopShiftSpeed() {
if (!__mmShiftSpeedActive) return;
const __mmMode = __mmShiftMode;
((__mmShiftSpeedActive = !1),
(__mmShiftMode = 0),
__mmShiftSpeedTimer &&
(clearInterval(__mmShiftSpeedTimer), (__mmShiftSpeedTimer = 0)),
__mmShiftGearPurchaseTimer &&
(clearInterval(__mmShiftGearPurchaseTimer),
(__mmShiftGearPurchaseTimer = 0)),
__mmStopBoostBreak(),
__mmMode === 1 && __mmRestoreShiftSpeed(),
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomShiftSpeed", {
detail: "Shift speed: Off",
}),
));
}
function __mmRestoreMovementGear(__mmForceNoMonkey) {
if (!__mmMovementGearActive()) return;
if (!v || !v.alive)
return void ((__mmMovementGearPreviousHat = null),
(__mmMovementGearPreviousTail = null));
if (
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmTankGearActive()
)
return;
const __mmHat = __mmMovementGearPreviousHat,
__mmTail =
__mmForceNoMonkey && !__mmHasStick() ? 0 : __mmMovementGearPreviousTail;
((__mmMovementGearPreviousHat = null),
(__mmMovementGearPreviousTail = null),
__mmEquipGearPair(__mmHat, __mmTail));
}
function __mmUpdateMovementGear() {
if (!__mmMovementGearEnabled)
return void (__mmRestoreMovementGear(),
__mmRestoreProximityTail(),
__mmClearIdleMonkeyTail());
if (!v || !v.alive)
return void (__mmRestoreMovementGear(), __mmRestoreProximityTail());
if (!__mmActionAvailable("movementGear")) return;
if (__mmInsta.isActive()) return;
// Existing combat actions own their hat and tail until they finish, avoiding
// tick-by-tick flicker between movement and combat gear.
if (
__mmSyncFollowerEnabled ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmTankGearActive()
)
return;
__mmInSnowBiome() && __mmBuySnowHat();
__mmRememberNormalHat();
const __mmEnemyNearby = __mmEnemyWithinCombatRange(),
__mmMoving = __mmPlayerMoving();
if (__mmEnemyNearby) {
__mmRestoreMovementGear(!0);
const __mmTail =
__mmMoving && v.tails && v.tails[__mmShadowWings]
? __mmShadowWings
: !__mmMoving && v.tails && v.tails[__mmBloodWings]
? __mmBloodWings
: __mmMoving
? null
: 0;
return __mmTail == null
? void __mmRestoreProximityTail()
: void __mmSetProximityTail(__mmTail);
}
__mmRestoreProximityTail();
if (!__mmMoving && !__mmBoostBreakHeld) {
if (!(v.skins && v.skins[__mmEmpHelmet])) {
__mmRestoreMovementGear();
if (v.tails && v.tails[__mmAngelWings])
return void __mmEquipTailNow(__mmAngelWings);
return void __mmClearIdleMonkeyTail();
}
if (!__mmMovementGearActive()) {
((__mmMovementGearPreviousHat = __mmShiftBaseHat()),
(__mmMovementGearPreviousTail = v.tailIndex),
__mmPauseSoldierForBreaking());
}
const __mmIdleTail =
v.tails && v.tails[__mmAngelWings]
? __mmAngelWings
: __mmMovementGearPreviousTail;
// EMP Helmet's anti-turret protection is the stationary, out-of-combat
// phase of this gear loop. Its paired tail leaves in the same packet tick.
return void __mmEquipGearPair(__mmEmpHelmet, __mmIdleTail);
}
if (__mmTankGearActive()) return;
if (
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld
)
return void __mmRestoreMovementGear();
__mmInWater() && __mmBuyFlipperHat();
const __mmHat = __mmSpeedHat(),
__mmHasHat = !!(v.skins && v.skins[__mmHat]),
__mmHasTail = !!(v.tails && v.tails[11]);
if (!__mmMovementGearActive()) {
((__mmMovementGearPreviousHat = __mmShiftBaseHat()),
(__mmMovementGearPreviousTail = v.tailIndex),
__mmPauseSoldierForBreaking());
}
// Snow uses owned Snow Hat first and Booster Hat while the snow purchase is
// unavailable or still being acknowledged; do not go bald in that gap.
__mmEquipGearPair(__mmHasHat ? __mmHat : 0, __mmHasTail ? 11 : null);
}
function __mmStartMovementGear() {
__mmMovementGearTimer ||
((__mmMovementGearTimer = setInterval(
__mmUpdateMovementGear,
__mmFastCheckMs(),
)),
__mmUpdateMovementGear());
}
function __mmUpdatePassiveSpikeMotion() {
if (!v || !v.alive) {
__mmPassiveSpikeMotion = null;
return;
}
const __mmNow = Date.now(),
__mmPrevious = __mmPassiveSpikeMotion,
__mmElapsed = __mmPrevious
? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
: 0,
__mmSampleVelocityX = __mmElapsed
? (Number(v.x) - __mmPrevious.x) / __mmElapsed
: 0,
__mmSampleVelocityY = __mmElapsed
? (Number(v.y) - __mmPrevious.y) / __mmElapsed
: 0,
__mmVelocityX = __mmPrevious && __mmElapsed < 250
? __mmSampleVelocityX * 0.72 + __mmPrevious.velocityX * 0.28
: __mmSampleVelocityX,
__mmVelocityY = __mmPrevious && __mmElapsed < 250
? __mmSampleVelocityY * 0.72 + __mmPrevious.velocityY * 0.28
: __mmSampleVelocityY;
__mmPassiveSpikeMotion = {
x: Number(v.x) || 0,
y: Number(v.y) || 0,
at: __mmNow,
velocityX: Number.isFinite(__mmVelocityX) ? __mmVelocityX : 0,
velocityY: Number.isFinite(__mmVelocityY) ? __mmVelocityY : 0,
};
}
function __mmPassiveSpikeVelocity() {
let __mmVelocityX = Number(
__mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityX,
) || 0,
__mmVelocityY = Number(
__mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityY,
) || 0;
const __mmServerElapsed = Number(v && v.t2) - Number(v && v.t1),
__mmServerVelocityX =
(Number(v && v.x2) - Number(v && v.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(v && v.y2) - Number(v && v.y1)) / __mmServerElapsed,
__mmTrackedSpeed = Math.hypot(__mmVelocityX, __mmVelocityY),
__mmServerSpeed = Math.hypot(__mmServerVelocityX, __mmServerVelocityY);
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500 &&
__mmServerSpeed > __mmTrackedSpeed
)
((__mmVelocityX = __mmServerVelocityX),
(__mmVelocityY = __mmServerVelocityY));
return { x: __mmVelocityX, y: __mmVelocityY };
}
function __mmPassiveSpikeEnemyNearby() {
if (
!v ||
!v.alive ||
!Array.isArray(E) ||
__mmPassiveSpikeEnemyRange <= 0
)
return !1;
const __mmRangeSquared =
__mmPassiveSpikeEnemyRange * __mmPassiveSpikeEnemyRange;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
const __mmDx = __mmPlayer.x - v.x,
__mmDy = __mmPlayer.y - v.y;
if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmRangeSquared) return !0;
}
return !1;
}
function __mmPassiveSpikeThreat() {
if (!v || !v.alive || !Array.isArray(ge)) return null;
const __mmVelocity = __mmPassiveSpikeVelocity(),
__mmSpeed = Math.hypot(__mmVelocity.x, __mmVelocity.y);
if (!Number.isFinite(__mmSpeed) || __mmSpeed < 0.01) return null;
const __mmLeadMs = Math.max(
150,
Math.min(280, __mmServerTickMs() * 1.8),
),
__mmCoastDistance = Math.min(95, __mmSpeed * __mmLeadMs),
__mmEndX = v.x + (__mmVelocity.x / __mmSpeed) * __mmCoastDistance,
__mmEndY = v.y + (__mmVelocity.y / __mmSpeed) * __mmCoastDistance;
let __mmBest = null,
__mmBestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmSpike = ge[__mmIndex],
__mmData = __mmSpike && b && b.list && b.list[__mmSpike.id],
__mmName = String(__mmData && __mmData.name || "").toLowerCase();
if (
!__mmSpike ||
!__mmSpike.active ||
!__mmSpike.isItem ||
!__mmName.includes("spikes") ||
__mmSpikeOwnedByUsOrAlly(__mmSpike)
)
continue;
const __mmToSpikeX = __mmSpike.x - v.x,
__mmToSpikeY = __mmSpike.y - v.y,
__mmToward =
__mmToSpikeX * __mmVelocity.x +
__mmToSpikeY * __mmVelocity.y;
if (__mmToward <= 0) continue;
const __mmRadius =
(Number(v.scale) || 35) +
(Number(__mmSpike.scale) || Number(__mmData.scale) || 45) +
4,
__mmPathDistanceSquared = __mmSegmentDistanceSquared(
v.x,
v.y,
__mmEndX,
__mmEndY,
__mmSpike.x,
__mmSpike.y,
),
__mmCenterDistanceSquared =
__mmToSpikeX * __mmToSpikeX + __mmToSpikeY * __mmToSpikeY;
if (
__mmPathDistanceSquared <= __mmRadius * __mmRadius &&
__mmCenterDistanceSquared < __mmBestDistance
)
((__mmBest = __mmSpike),
(__mmBestDistance = __mmCenterDistanceSquared));
}
return __mmBest;
}
function __mmStopPassiveSpikeCorrection(__mmUserMovementTakingOver) {
(__mmPassiveSpikePendingTimer &&
clearTimeout(__mmPassiveSpikePendingTimer),
(__mmPassiveSpikePendingTimer = 0),
__mmPassiveSpikeCorrectionTimer &&
clearTimeout(__mmPassiveSpikeCorrectionTimer),
(__mmPassiveSpikeCorrectionTimer = 0));
if (!__mmPassiveSpikeCorrecting) return;
((__mmPassiveSpikeCorrecting = !1), (Kt = null));
__mmUserMovementTakingOver || Tt();
}
function __mmRunPassiveSpikeCorrection() {
__mmPassiveSpikePendingTimer = 0;
if (
!__mmPassiveSpikeAvoidanceEnabled ||
!v ||
!v.alive ||
(typeof ul === "function" && ul() != null) ||
__mmPassiveSpikeEnemyNearby() ||
__mmSyncFollowerEnabled ||
__mmBoostBackingUp ||
__mmBoostBreakHeld ||
__mmTrapAttackActive ||
__mmInsta.isActive() ||
__mmIsTrapped()
)
return;
const __mmSpike = __mmPassiveSpikeThreat();
if (!__mmSpike) return;
const __mmAway = Math.atan2(v.y - __mmSpike.y, v.x - __mmSpike.x),
__mmDuration = Math.max(75, Math.min(140, __mmServerTickMs()));
((__mmPassiveSpikeCorrecting = !0),
(Kt = __mmAway),
O.send("9", __mmAway),
(__mmPassiveSpikeCorrectionTimer = setTimeout(function () {
__mmStopPassiveSpikeCorrection(!1);
}, __mmDuration)));
}
function __mmPassiveSpikeMovementPressed() {
__mmStopPassiveSpikeCorrection(!0);
}
function __mmPassiveSpikeMovementReleased() {
if (
!__mmPassiveSpikeAvoidanceEnabled ||
(typeof ul === "function" && ul() != null)
)
return;
__mmPassiveSpikePendingTimer && clearTimeout(__mmPassiveSpikePendingTimer);
__mmPassiveSpikePendingTimer = setTimeout(__mmRunPassiveSpikeCorrection, 0);
}
function __mmStartPassiveSpikeAvoidance() {
if (!__mmPassiveSpikeAvoidanceEnabled || __mmPassiveSpikeMotionTimer) return;
(__mmUpdatePassiveSpikeMotion(),
(__mmPassiveSpikeMotionTimer = setInterval(
__mmUpdatePassiveSpikeMotion,
Math.max(8, __mmFastCheckMs()),
)));
}
function __mmStopPassiveSpikeAvoidance() {
(__mmPassiveSpikeMotionTimer && clearInterval(__mmPassiveSpikeMotionTimer),
(__mmPassiveSpikeMotionTimer = 0),
(__mmPassiveSpikeMotion = null),
__mmStopPassiveSpikeCorrection(!1));
}
function __mmBoostPadItem() {
if (!v || !v.items) return null;
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmItem = v.items[__mmItemIndex],
__mmData = b.list[__mmItem];
if (__mmData && __mmData.boostSpeed) return __mmItem;
}
return null;
}
function __mmHasPitTrap() {
if (!v || !v.items) return !1;
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmData = b.list[v.items[__mmItemIndex]];
if (__mmData && __mmData.trap) return !0;
}
return !1;
}
function __mmCanUseBuildItem(__mmItem) {
const __mmData = b.list[__mmItem];
if (!v || !__mmData || !__mmData.req) return !1;
for (
let __mmReqIndex = 0;
__mmReqIndex < __mmData.req.length;
__mmReqIndex += 2
)
if ((v[__mmData.req[__mmReqIndex]] || 0) < __mmData.req[__mmReqIndex + 1])
return !1;
return !0;
}
function __mmThreatTrapItem() {
if (!v || !v.items || !b || !b.list) return null;
if (__mmThreatTrapEnabled)
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmItem = v.items[__mmItemIndex],
__mmData = b.list[__mmItem];
if (__mmData && __mmData.trap && __mmCanUseBuildItem(__mmItem))
return __mmItem;
}
// Pit traps keep priority when both controls are enabled. Spikes have their
// own switch and remain blocked while Mc Grabby is actively selected.
if (!__mmAutoCloseSpikeEnabled || __mmHoldingMcGrabby()) return null;
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmItem = v.items[__mmItemIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
typeof __mmData.name === "string" &&
__mmData.name.indexOf("spikes") !== -1 &&
__mmCanUseBuildItem(__mmItem)
)
return __mmItem;
}
return null;
}
function __mmThreatTeleporterItem() {
if (!v || !v.items || !b || !b.list) return null;
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmItem = v.items[__mmItemIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
String(__mmData.name || "").toLowerCase() === "teleporter" &&
__mmCanUseBuildItem(__mmItem)
)
return __mmItem;
}
return null;
}
function __mmThreatTrapAnimalName(__mmAnimal) {
return String((__mmAnimal && __mmAnimal.name) || "").trim().toLowerCase();
}
function __mmThreatAnimalIsWolf(__mmAnimal) {
return __mmThreatTrapAnimalName(__mmAnimal) === "wolf";
}
function __mmThreatItemIsPitTrap(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
return !!(__mmData && __mmData.trap);
}
function __mmThreatTeleporterAnimalAllowed(__mmAnimal) {
const __mmName = __mmThreatTrapAnimalName(__mmAnimal);
return !!(
__mmAnimal &&
__mmAnimal.active &&
__mmAnimal.alive &&
__mmAnimal.visible &&
(__mmName === "moostafa" || __mmName === "moofie")
);
}
function __mmThreatTrapAnimalAllowed(__mmAnimal) {
if (
!__mmAnimal ||
!__mmAnimal.active ||
!__mmAnimal.alive ||
!__mmAnimal.visible ||
!__mmAnimal.hostile
)
return !1;
const __mmName = __mmThreatTrapAnimalName(__mmAnimal);
return __mmName !== "moostafa" && __mmName !== "moofie";
}
function __mmThreatTargetKey(__mmTarget) {
if (!__mmTarget) return null;
const __mmId =
__mmTarget.sid != null
? __mmTarget.sid
: __mmTarget.id != null
? __mmTarget.id
: __mmTarget.index != null
? __mmTarget.index
: null;
return __mmId == null ? null : String(__mmId);
}
function __mmRememberThreatTrap(__mmTarget, __mmItem, __mmAngle) {
const __mmKey = __mmThreatTargetKey(__mmTarget),
__mmData = b && b.list && b.list[__mmItem];
if (!__mmKey || !__mmData || !__mmData.trap || !v) return;
const __mmPlaceDistance =
(Number(v.scale) || 35) +
(Number(__mmData.scale) || 50) +
(Number(__mmData.placeOffset) || 0),
__mmCollisionScale = Math.max(
10,
(Number(__mmData.scale) || 50) * (Number(__mmData.colDiv) || 1),
);
__mmThreatTrapPlacements[__mmKey] = {
x: v.x + Math.cos(__mmAngle) * __mmPlaceDistance,
y: v.y + Math.sin(__mmAngle) * __mmPlaceDistance,
scale: __mmCollisionScale,
// Keep only a brief acknowledgement bridge; never retain a stale target
// position after a death or despawn.
expiresAt: Date.now() + 2500,
};
}
function __mmThreatAlreadyTrapped(__mmTarget) {
if (
!__mmTarget ||
!X ||
typeof X.getGridArrays !== "function" ||
!Number.isFinite(Number(__mmTarget.x)) ||
!Number.isFinite(Number(__mmTarget.y))
)
return !1;
const __mmTargetScale = Number(__mmTarget.scale) || 35;
if (__mmTarget.lockMove) return !0;
const __mmTargetKey = __mmThreatTargetKey(__mmTarget),
__mmRememberedTrap =
__mmTargetKey && __mmThreatTrapPlacements[__mmTargetKey];
if (__mmRememberedTrap) {
if (__mmRememberedTrap.expiresAt <= Date.now())
delete __mmThreatTrapPlacements[__mmTargetKey];
else if (
Math.hypot(
__mmRememberedTrap.x - __mmTarget.x,
__mmRememberedTrap.y - __mmTarget.y,
) <=
__mmTargetScale + __mmRememberedTrap.scale + 10
)
return !0;
}
let __mmGrids;
try {
__mmGrids = X.getGridArrays(
__mmTarget.x,
__mmTarget.y,
__mmTargetScale + 60,
);
} catch (__mmGridError) {
return !1;
}
if (!Array.isArray(__mmGrids)) return !1;
for (let __mmGridIndex = 0; __mmGridIndex < __mmGrids.length; __mmGridIndex++)
for (
let __mmObjectIndex = 0;
__mmObjectIndex < __mmGrids[__mmGridIndex].length;
__mmObjectIndex++
) {
const __mmObject = __mmGrids[__mmGridIndex][__mmObjectIndex];
if (!__mmObject || !__mmObject.active || !__mmObject.trap) continue;
const __mmTrapScale =
typeof __mmObject.getScale === "function"
? __mmObject.getScale()
: Number(__mmObject.scale) || 50;
if (
Math.hypot(
__mmObject.x - __mmTarget.x,
__mmObject.y - __mmTarget.y,
) <=
__mmTargetScale +
Math.max(__mmTrapScale, Number(__mmObject.scale) || 0) +
10
)
return !0;
}
return !1;
}
function __mmThreatTrapTarget(__mmTrap, __mmTeleporter) {
if (!v || !v.alive) return null;
const __mmPlayers = __mmLiveStateFresh() ? __mmLiveState.enemies : E,
__mmAnimals = __mmLiveStateFresh() ? __mmLiveState.animals : N;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmConsider = function (
__mmTarget,
__mmType,
__mmItem,
__mmRange,
) {
if (
!__mmTarget ||
__mmThreatAlreadyTrapped(__mmTarget) ||
!Number.isFinite(Number(__mmTarget.x)) ||
!Number.isFinite(Number(__mmTarget.y))
)
return;
const __mmDistance = Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y);
if (__mmDistance > __mmRange || __mmDistance >= __mmClosestDistance)
return;
const __mmId =
__mmTarget.sid != null
? __mmTarget.sid
: __mmTarget.id != null
? __mmTarget.id
: __mmTarget.index != null
? __mmTarget.index
: Math.round(__mmTarget.x) + ":" + Math.round(__mmTarget.y);
((__mmClosest = {
target: __mmTarget,
key: __mmType + ":" + __mmId,
item: __mmItem,
distance: __mmDistance,
}),
(__mmClosestDistance = __mmDistance));
};
if (__mmTrap != null && Array.isArray(__mmPlayers))
for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
const __mmPlayer = __mmPlayers[__mmIndex];
__mmIsEnemyPlayer(__mmPlayer) &&
__mmConsider(__mmPlayer, "player", __mmTrap, __mmThreatTrapRange);
}
if (Array.isArray(__mmAnimals))
for (let __mmIndex = 0; __mmIndex < __mmAnimals.length; __mmIndex++) {
const __mmAnimal = __mmAnimals[__mmIndex];
__mmTrap != null &&
__mmThreatTrapAnimalAllowed(__mmAnimal) &&
// Wolves are easy melee kills and flee after spike damage. They are
// still trapped normally whenever the chosen item is a real pit trap.
(!__mmThreatAnimalIsWolf(__mmAnimal) ||
__mmThreatItemIsPitTrap(__mmTrap)) &&
__mmConsider(
__mmAnimal,
"animal",
__mmTrap,
__mmThreatAnimalRange,
);
__mmTeleporter != null &&
__mmThreatTeleporterAnimalAllowed(__mmAnimal) &&
__mmConsider(
__mmAnimal,
"teleporter",
__mmTeleporter,
__mmThreatAnimalRange,
);
}
return __mmClosest;
}
function __mmPlaceThreatTrap() {
if (
(!__mmThreatTrapEnabled && !__mmAutoCloseSpikeEnabled) ||
!v ||
!v.alive ||
v.lockMove ||
__mmInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer
)
return !1;
const __mmTrap = __mmThreatTrapItem(),
__mmTeleporter = __mmThreatTrapEnabled
? __mmThreatTeleporterItem()
: null,
__mmThreat = __mmThreatTrapTarget(__mmTrap, __mmTeleporter),
__mmNow = Date.now();
if (
!__mmThreat ||
(__mmThreat.key === __mmThreatTrapLastKey &&
__mmNow - __mmThreatTrapLastAt < __mmThreatTrapCooldownMs)
)
return !1;
// Only take action ownership after a real, non-cooled-down threat exists.
// Claiming first used to cancel Cleanup on every empty 25ms scan.
if (!__mmActionClaim("threatTrap", "nearby hostile")) return !1;
// Build placement is angle-based and always occurs at the player's placement
// radius, so aiming at the threat puts the defensive item between us.
const __mmAngle = Math.atan2(
__mmThreat.target.y - v.y,
__mmThreat.target.x - v.x,
),
__mmWeapon = __mmSelectedWeapon();
try {
(je(__mmThreat.item),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmRememberThreatTrap(__mmThreat.target, __mmThreat.item, __mmAngle),
__mmWeapon != null && __mmRestoreWeapon(__mmWeapon),
(__mmThreatTrapLastAt = __mmNow),
(__mmThreatTrapLastKey = __mmThreat.key),
__mmActionRelease("threatTrap", "placed"));
return !0;
} catch (__mmThreatTrapError) {
return (__mmActionRelease("threatTrap", "placement failed"), !1);
}
}
function __mmStartThreatTrap() {
__mmThreatTrapTimer ||
(__mmThreatTrapTimer = setInterval(
__mmPlaceThreatTrap,
__mmFastCheckMs(),
));
}
function __mmNearestEnemy() {
if (!v || !v.alive) return null;
if (__mmLiveStateFresh()) return __mmLiveState.nearestEnemy;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
const __mmPlayer = E[__mmPlayerIndex];
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
const __mmDx = __mmPlayer.x - v.x,
__mmDy = __mmPlayer.y - v.y,
__mmDistance = __mmDx * __mmDx + __mmDy * __mmDy;
if (__mmDistance < __mmClosestDistance) {
((__mmClosestDistance = __mmDistance), (__mmClosest = __mmPlayer));
}
}
return __mmClosest;
}
function __mmWeaponReady(__mmWeapon) {
if (!v || !v.alive || __mmWeapon == null) return !1;
const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]);
return !Number.isFinite(__mmReload) || __mmReload <= 0;
}
function __mmBoostBreakWeapon() {
if (!v || !v.weapons) return null;
if (v.weapons.includes(__mmGreatHammer)) return __mmGreatHammer;
const __mmMainWeapon = v.weapons[0];
return __mmMainWeapon === __mmKatana || __mmMainWeapon === __mmPolearmWeapon
? __mmMainWeapon
: null;
}
function __mmCanBoostBreak() {
const __mmPad = __mmBoostPadItem();
return !!(
v &&
v.alive &&
v.skins &&
v.skins[40] &&
__mmPad != null &&
!__mmHasPitTrap() &&
__mmCanUseBuildItem(__mmPad) &&
__mmBoostBreakWeapon() != null &&
!__mmInsta.isActive() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive
);
}
function __mmBoostBreakWeaponReady() {
const __mmWeapon = __mmBoostBreakWeapon(),
__mmReload = v && v.reloads && Number(v.reloads[__mmWeapon]);
if (__mmWeapon == null || (Number.isFinite(__mmReload) && __mmReload > 0))
return !1;
return !(
__mmBoostBreakCooldownWeapon === __mmWeapon &&
Date.now() < __mmBoostBreakReadyAt
);
}
function __mmShuffleBoostChat() {
__mmBoostChatOrder = __mmBoostChatLines.slice();
for (
let __mmIndex = __mmBoostChatOrder.length - 1;
__mmIndex > 0;
__mmIndex--
) {
const __mmRandom = Math.floor(Math.random() * (__mmIndex + 1)),
__mmSwap = __mmBoostChatOrder[__mmIndex];
((__mmBoostChatOrder[__mmIndex] = __mmBoostChatOrder[__mmRandom]),
(__mmBoostChatOrder[__mmRandom] = __mmSwap));
}
__mmBoostChatIndex = 0;
}
function __mmSendChat(__mmMessage) {
typeof on === "function" &&
typeof __mmMessage === "string" &&
on(__mmMessage.slice(0, 30));
}
let __mmMaterialReplyLastAt = 0;
function __mmChatMentionsMaterials(__mmMessage) {
if (typeof __mmMessage !== "string") return !1;
const __mmWords = __mmMessage
.toLowerCase()
.replace(/[@4]/g, "a")
.replace(/1/g, "i")
.replace(/3/g, "e")
.replace(/0/g, "o")
.replace(/5/g, "s")
.replace(/7/g, "t")
.replace(/[^a-z]+/g, " ")
.trim();
return /(?:^|\s)(?:mats?|materials?|resources?|res|supplies|wood|stone)(?:\s|$)/.test(
__mmWords,
);
}
function __mmReplyToMaterialRequest(__mmPlayerSid, __mmMessage) {
if (
!__mmMaterialReplyEnabled ||
!v ||
!v.alive ||
__mmPlayerSid == null ||
String(__mmPlayerSid) === String(v.sid) ||
!__mmChatMentionsMaterials(__mmMessage)
)
return;
let __mmPlayer = null;
try {
__mmPlayer = Rt(__mmPlayerSid);
} catch (__mmLookupError) {}
if (
!__mmPlayer ||
(!__mmSameTeam(__mmPlayer) && !__mmIsFriendPlayer(__mmPlayer))
)
return;
const __mmNow = Date.now(),
__mmCooldown = Math.max(2500, (Number(y && y.chatCooldown) || 500) * 2);
if (__mmNow - __mmMaterialReplyLastAt < __mmCooldown) return;
const __mmWood = Math.max(0, Math.floor(Number(v.wood) || 0)),
__mmStone = Math.max(0, Math.floor(Number(v.stone) || 0));
((__mmMaterialReplyLastAt = __mmNow),
__mmSendChat("Wood " + __mmWood + " Stone " + __mmStone));
}
let __mmModReplyLastAt = 0;
const __mmModReplyText = "kitty klient",
__mmModReplyCooldownMs = 5000;
function __mmChatMentionsMod(__mmMessage) {
if (typeof __mmMessage !== "string") return !1;
const __mmNormalized = __mmMessage
.toLowerCase()
.replace(/[@4]/g, "a")
.replace(/1/g, "i")
.replace(/3/g, "e")
.replace(/0/g, "o")
.replace(/5/g, "s")
.replace(/7/g, "t"),
__mmWords = __mmNormalized.replace(/[^a-z]+/g, " ").trim(),
__mmCompact = __mmNormalized.replace(/[^a-z]+/g, "");
// Match direct questions and casual accusations without depending on exact
// phrasing or punctuation. Distinctive compact forms also catch "h a c k"
// and similarly spaced-out attempts.
return !!(
/(?:^|\s)(?:mod(?:s|ded)?|hack(?:s|er|ing|ed)?|hax|client|klient|macro(?:s)?|script(?:s|ed)?|userscript|cheat(?:s|er|ing|ed)?|tampermonkey)(?:\s|$)/.test(
__mmWords,
) ||
/(?:hack|hax|client|klient|macro|userscript|tampermonkey)/.test(
__mmCompact,
)
);
}
function __mmReplyToModQuestion(__mmPlayerSid, __mmMessage) {
if (
!v ||
!v.alive ||
__mmPlayerSid === v.sid ||
!__mmChatMentionsMod(__mmMessage)
)
return;
const __mmNow = Date.now();
if (__mmNow - __mmModReplyLastAt < __mmModReplyCooldownMs) return;
((__mmModReplyLastAt = __mmNow), __mmSendChat(__mmModReplyText));
}
function __mmSendBoostChat() {
if (!__mmBoostBreakHeld || !__mmShiftHeld() || !v || !v.alive) return;
if (!__mmBoostChatOrder.length) __mmShuffleBoostChat();
__mmSendChat(
__mmBoostChatOrder[__mmBoostChatIndex++ % __mmBoostChatOrder.length],
);
}
function __mmStartBoostChat() {
if (!__mmBoostChatEnabled || __mmBoostChatTimer) return;
(__mmShuffleBoostChat(),
__mmSendBoostChat(),
(__mmBoostChatTimer = setInterval(
__mmSendBoostChat,
Math.max(550, Number(y.chatCooldown) || 500),
)));
}
function __mmStopBoostChat() {
(__mmBoostChatTimer &&
(clearInterval(__mmBoostChatTimer), (__mmBoostChatTimer = 0)),
__mmShuffleBoostChat());
}
function __mmStartBoostForward(__mmAngle) {
((__mmBoostMoveDirection = __mmAngle),
O.send("9", __mmAngle),
(Kt = __mmAngle));
}
function __mmFinishBoostBreakGear() {
if (!v || !v.alive) return;
const __mmEnemyNearby = __mmEnemyWithinCombatRange(),
__mmTail =
!__mmEnemyNearby && v.tails && v.tails[11] && v.tailIndex !== 11
? 11
: __mmEnemyNearby && !__mmHasStick() && v.tailIndex === 11
? 0
: null,
__mmSpeed = __mmSpeedHat();
let __mmHat = null;
if (!__mmEnemyNearby && v.skins && v.skins[__mmSpeed]) __mmHat = __mmSpeed;
else if (
__mmBoostTankPreviousHat != null &&
v.skinIndex === 40 &&
__mmCanEquipHat(__mmBoostTankPreviousHat)
)
__mmHat = __mmBoostTankPreviousHat;
else if (
__mmInSnowBiome() &&
v.skins &&
v.skins[__mmBoosterHat] &&
v.skinIndex !== __mmBoosterHat
)
__mmHat = __mmBoosterHat;
__mmEquipGearPair(__mmHat, __mmTail, !0);
}
function __mmSelectBoostBreakWeapon(__mmWeapon) {
if (!v || !v.weapons || !v.weapons.includes(__mmWeapon)) return !1;
return ((__mmLastWeapon = __mmWeapon), je(__mmWeapon, !0), !0);
}
function __mmFinishBoostBreakStrike(__mmWeapon, __mmAngle) {
__mmBoostBreakStrikeTimer = 0;
const __mmPreviousWeapon = __mmBoostBreakPreviousWeapon;
__mmBoostBreakPreviousWeapon = null;
if (!__mmBoostBreakHeld || !v || !v.alive)
return void (__mmBoostBreakStriking = !1);
(__mmSelectBoostBreakWeapon(__mmWeapon) &&
(O.send("F", 1, __mmAngle), O.send("F", 0, __mmAngle)),
__mmRestoreWeapon(__mmPreviousWeapon),
__mmFinishBoostBreakGear(),
(__mmBoostBreakCooldownWeapon = __mmWeapon),
(__mmBoostBreakReadyAt =
Date.now() + Math.max(1, Number(b.weapons[__mmWeapon].speed) || 400)),
(__mmBoostBreakStriking = !1));
}
function __mmBoostBreakTick() {
if (__mmBoostBreakStriking) return;
if (!__mmBoostBreakHeld || !__mmShiftHeld() || !__mmCanBoostBreak())
return void __mmStopBoostBreak();
if (!__mmBoostBreakWeaponReady()) return;
const __mmPad = __mmBoostPadItem();
if (__mmPad == null || !__mmCanUseBuildItem(__mmPad))
return void __mmStopBoostBreak();
const __mmWeapon = __mmBoostBreakWeapon();
if (__mmWeapon == null) return void __mmStopBoostBreak();
const __mmAngle = Ci(),
__mmTail =
!__mmEnemyWithinCombatRange() &&
v.tails &&
v.tails[11] &&
v.tailIndex !== 11
? 11
: null;
(__mmPauseSoldierForBreaking(),
__mmBoostTankPreviousHat == null &&
(__mmBoostTankPreviousHat = v.skinIndex),
__mmEquipGearPair(40, __mmTail, !0),
je(__mmPad),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmStartBoostForward(__mmAngle),
(__mmBoostBreakPreviousWeapon = __mmSelectedWeapon()),
(__mmBoostBreakStriking = !0),
__mmSelectBoostBreakWeapon(__mmWeapon),
(__mmBoostBreakStrikeTimer = setTimeout(function () {
__mmFinishBoostBreakStrike(__mmWeapon, __mmAngle);
}, __mmServerTickMs())));
}
function __mmStartBoostBreak() {
__mmInsta.isActive() && __mmInsta.cancel("boost-break");
if (!__mmBoostBreakEnabled || !__mmShiftHeld() || !__mmCanBoostBreak())
return;
if (!__mmActionClaim("boostBreak", "shift boost-break")) return;
((__mmBoostBreakHeld = !0),
__mmBoostBreakTimer ||
(__mmBoostBreakTimer = setInterval(
__mmBoostBreakTick,
__mmServerTickMs(),
)),
__mmStartBoostChat(),
__mmBoostBreakTick());
}
function __mmStopBoostBreak() {
const __mmRestore = __mmActionMayRestore("boostBreak");
((__mmBoostBreakHeld = !1),
__mmBoostBreakTimer &&
(clearInterval(__mmBoostBreakTimer), (__mmBoostBreakTimer = 0)),
__mmBoostBreakStrikeTimer &&
(clearTimeout(__mmBoostBreakStrikeTimer),
(__mmBoostBreakStrikeTimer = 0)),
(__mmBoostBreakStriking = !1),
__mmRestore &&
__mmBoostBreakPreviousWeapon != null &&
__mmRestoreWeapon(__mmBoostBreakPreviousWeapon),
(__mmBoostBreakPreviousWeapon = null),
__mmStopBoostChat(),
(__mmBoostBreakCooldownWeapon = null),
(__mmBoostBreakReadyAt = 0));
if (__mmRestore && v && v.alive && __mmBoostTankPreviousHat != null) {
const __mmHat = __mmBoostTankPreviousHat;
((__mmBoostTankPreviousHat = null),
v.skinIndex === 40 && __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat));
} else __mmBoostTankPreviousHat = null;
(__mmBoostMoveDirection != null &&
((Kt = null), Tt(), (__mmBoostMoveDirection = null)),
__mmActionRelease("boostBreak", "boost-break complete"),
__mmUpdateMovementGear());
}
function __mmStartAutoHeal() {
__mmAutoHealTimer || (__mmAutoHealTimer = setInterval(__mmAutoHeal, 10));
}
function __mmUpdateAutoInsta() {
return !!(
__mmInsta.canAutoStart() &&
__mmInsta.start({ automatic: !0 })
);
}
function __mmStartAutoInsta() {
// Auto Insta is intentionally input-assisted. The primary mousedown path
// calls __mmUpdateAutoInsta; proximity by itself never starts a combo.
__mmAutoInstaTimer && clearInterval(__mmAutoInstaTimer);
__mmAutoInstaTimer = 0;
}
function __mmSpikeHostileToEnemy(__mmSpike, __mmEnemy) {
if (!__mmSpike || !__mmEnemy || !__mmSpike.owner) return !0;
const __mmOwner = __mmSpike.owner,
__mmOwnerSid = __mmOwner.sid;
if (
__mmOwner === __mmEnemy ||
String(__mmOwnerSid) === String(__mmEnemy.sid)
)
return !1;
const __mmOwnerPlayer = typeof Rt === "function" ? Rt(__mmOwnerSid) : null,
__mmOwnerTeam = __mmTeamKey(__mmOwnerPlayer || __mmOwner),
__mmEnemyTeam = __mmTeamKey(__mmEnemy);
return !(
__mmOwnerTeam != null &&
__mmEnemyTeam != null &&
__mmOwnerTeam === __mmEnemyTeam
);
}
function __mmPredictEnemyNextTick(__mmEnemy, __mmNow) {
const __mmSid = String(__mmEnemy.sid),
__mmPrevious = __mmAutoSpikeInstaMotion[__mmSid],
__mmSampleElapsed = __mmPrevious
? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
: 0;
let __mmVelocityX = __mmPrevious
? (__mmEnemy.x - __mmPrevious.x) / __mmSampleElapsed
: 0,
__mmVelocityY = __mmPrevious
? (__mmEnemy.y - __mmPrevious.y) / __mmSampleElapsed
: 0;
const __mmServerElapsed = Number(__mmEnemy.t2) - Number(__mmEnemy.t1),
__mmServerVelocityX =
(Number(__mmEnemy.x2) - Number(__mmEnemy.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(__mmEnemy.y2) - Number(__mmEnemy.y1)) / __mmServerElapsed;
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
) {
((__mmVelocityX = __mmPrevious
? __mmServerVelocityX * 0.75 + __mmVelocityX * 0.25
: __mmServerVelocityX),
(__mmVelocityY = __mmPrevious
? __mmServerVelocityY * 0.75 + __mmVelocityY * 0.25
: __mmServerVelocityY));
}
__mmAutoSpikeInstaMotion[__mmSid] = {
x: __mmEnemy.x,
y: __mmEnemy.y,
at: __mmNow,
};
const __mmLeadMs = __mmServerTickMs();
return {
x: __mmEnemy.x + __mmVelocityX * __mmLeadMs,
y: __mmEnemy.y + __mmVelocityY * __mmLeadMs,
velocityX: __mmVelocityX,
velocityY: __mmVelocityY,
};
}
function __mmSegmentDistanceSquared(
__mmStartX,
__mmStartY,
__mmEndX,
__mmEndY,
__mmPointX,
__mmPointY,
) {
const __mmPathX = __mmEndX - __mmStartX,
__mmPathY = __mmEndY - __mmStartY,
__mmLengthSquared = __mmPathX * __mmPathX + __mmPathY * __mmPathY;
if (__mmLengthSquared <= 1e-6)
return (
(__mmPointX - __mmStartX) ** 2 + (__mmPointY - __mmStartY) ** 2
);
const __mmProgress = Math.max(
0,
Math.min(
1,
((__mmPointX - __mmStartX) * __mmPathX +
(__mmPointY - __mmStartY) * __mmPathY) /
__mmLengthSquared,
),
),
__mmClosestX = __mmStartX + __mmPathX * __mmProgress,
__mmClosestY = __mmStartY + __mmPathY * __mmProgress;
return (
(__mmPointX - __mmClosestX) ** 2 +
(__mmPointY - __mmClosestY) ** 2
);
}
function __mmSpikeOwnedByUsOrAlly(__mmSpike) {
if (!v || !v.alive || !__mmSpike || !__mmSpike.owner) return !1;
const __mmOwner = __mmSpike.owner,
__mmOwnerSid = __mmOwner.sid;
if (
__mmOwner === v ||
(__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
)
return !0;
const __mmOwnerPlayer =
__mmOwnerSid != null && typeof Rt === "function" ? Rt(__mmOwnerSid) : null;
return __mmSameTeam(__mmOwnerPlayer || __mmOwner);
}
function __mmEnemyWillHitSpikeNextTick(__mmEnemy, __mmPrediction) {
if (!Array.isArray(ge)) return !1;
const __mmSpeedSquared =
__mmPrediction.velocityX * __mmPrediction.velocityX +
__mmPrediction.velocityY * __mmPrediction.velocityY;
if (__mmSpeedSquared <= 1e-6) return !1;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmSpike = ge[__mmIndex],
__mmData = __mmSpike && b.list && b.list[__mmSpike.id],
__mmName = String(__mmData && __mmData.name || "").toLowerCase();
if (
!__mmSpike ||
!__mmSpike.active ||
!__mmSpike.isItem ||
!__mmName.includes("spikes") ||
!__mmSpikeOwnedByUsOrAlly(__mmSpike) ||
!__mmSpikeHostileToEnemy(__mmSpike, __mmEnemy)
)
continue;
const __mmCollisionRadius =
(Number(__mmEnemy.scale) || 35) +
(Number(__mmSpike.scale) || Number(__mmData.scale) || 45),
__mmCurrentDistanceSquared =
(__mmEnemy.x - __mmSpike.x) ** 2 +
(__mmEnemy.y - __mmSpike.y) ** 2,
__mmPredictedDistanceSquared =
(__mmPrediction.x - __mmSpike.x) ** 2 +
(__mmPrediction.y - __mmSpike.y) ** 2,
__mmPathDistanceSquared = __mmSegmentDistanceSquared(
__mmEnemy.x,
__mmEnemy.y,
__mmPrediction.x,
__mmPrediction.y,
__mmSpike.x,
__mmSpike.y,
);
if (
__mmPredictedDistanceSquared < __mmCurrentDistanceSquared &&
__mmPathDistanceSquared <= __mmCollisionRadius * __mmCollisionRadius
)
return !0;
}
return !1;
}
function __mmFullInstaReadyFor(__mmEnemy) {
if (
!v ||
!v.alive ||
!__mmEnemy ||
__mmInsta.state !== "idle" ||
!__mmInsta.runtimeReady() ||
__mmInsta.isPriorityConflict() ||
!v.skins ||
!v.skins[7] ||
!v.skins[__mmTurretGear] ||
!__mmInsta.turretReady()
)
return !1;
const __mmPrimary = __mmInsta.supportedPrimary(),
__mmSecondary = v.weapons && v.weapons[1],
__mmSecondaryData = __mmInsta.weaponData(__mmSecondary);
return !!(
__mmPrimary != null &&
__mmIsEnemyPlayer(__mmEnemy) &&
__mmInsta.inRange(__mmPrimary, __mmEnemy) &&
__mmWeaponReady(__mmPrimary) &&
__mmSecondary != null &&
__mmSecondary !== __mmPrimary &&
__mmSecondary !== __mmShieldWeapon &&
__mmSecondaryData &&
!__mmSecondaryData.shield &&
__mmWeaponReady(__mmSecondary)
);
}
function __mmSpikeTickStrikeReady(__mmEnemy, __mmPrediction) {
if (
!__mmAutoSpikeInstaEnabled ||
!v ||
!v.alive ||
!__mmEnemy ||
!__mmPrediction ||
__mmSpikeTickStrikeTimer ||
__mmInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmShieldDefenseTimer ||
__mmIsTrapped() ||
!(
__mmActionAvailable("spikeTickStrike") ||
__mmActionOwner === "weaponRecharge" ||
__mmActionOwner === "matThief" ||
__mmActionOwner === "mobSteal" ||
__mmActionOwner === "instaSync"
)
)
return !1;
const __mmPrimary = __mmInsta.supportedPrimary(),
__mmPredictedTarget = {
x: __mmPrediction.x,
y: __mmPrediction.y,
scale: __mmEnemy.scale,
};
return !!(
__mmPrimary != null &&
__mmWeaponReady(__mmPrimary) &&
__mmInsta.inRange(__mmPrimary, __mmPredictedTarget)
);
}
function __mmStopSpikeTickStrike(__mmReason) {
const __mmTool = __mmSpikeTickStrikeTool,
__mmHat = __mmSpikeTickStrikeHat,
__mmRestore = __mmActionMayRestore("spikeTickStrike");
(__mmSpikeTickStrikeTimer && clearTimeout(__mmSpikeTickStrikeTimer),
(__mmSpikeTickStrikeTimer = 0),
__mmSpikeTickStrikeHeld && O.send("F", 0, __mmSpikeTickStrikeAimAngle),
(__mmSpikeTickStrikeHeld = !1),
(__mmSpikeTickStrikeTool = null),
(__mmSpikeTickStrikeHat = null),
(__mmSpikeTickStrikeAimAngle = null),
__mmRestore && __mmHat != null && __mmEquipHatNow(__mmHat, !0),
__mmRestore && __mmRestoreTool(__mmTool),
__mmActionRelease(
"spikeTickStrike",
__mmReason || "predicted spike strike complete",
),
v && v.alive && __mmUpdateWeaponRecharge());
}
function __mmStartSpikeTickStrike(__mmEnemy, __mmPrediction) {
if (!__mmSpikeTickStrikeReady(__mmEnemy, __mmPrediction)) return !1;
(__mmActionOwner === "instaSync" && __mmStopInstaSync(),
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmActionOwner === "matThief" &&
__mmFinishMatThief("predicted spike strike"),
__mmActionOwner === "mobSteal" &&
__mmFinishMobSteal("predicted spike strike"));
if (!__mmActionClaim("spikeTickStrike", "predicted allied-spike contact"))
return !1;
const __mmPrimary = __mmInsta.supportedPrimary(),
__mmAngle = Math.atan2(__mmPrediction.y - v.y, __mmPrediction.x - v.x);
if (__mmPrimary == null)
return (__mmActionRelease("spikeTickStrike", "primary unavailable"), !1);
((__mmSpikeTickStrikeTool = __mmSelectedTool()),
(__mmSpikeTickStrikeHat = v.skinIndex),
(__mmSpikeTickStrikeAimAngle = __mmAngle),
__mmInsta.turretReady() && __mmEquipHatNow(__mmTurretGear),
O.send("D", __mmAngle),
je(__mmPrimary, !0),
O.send("F", 1, __mmAngle),
(__mmSpikeTickStrikeHeld = !0),
(__mmSpikeTickStrikeTimer = setTimeout(function () {
__mmStopSpikeTickStrike("predicted spike strike complete");
}, __mmServerTickMs())));
return !0;
}
function __mmUpdateAutoSpikeInsta() {
const __mmNow = Date.now(),
__mmSeen = Object.create(null);
if (!__mmAutoSpikeInstaEnabled || !v || !v.alive || !Array.isArray(E)) return;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmEnemy = E[__mmIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmSid = String(__mmEnemy.sid),
__mmPrediction = __mmPredictEnemyNextTick(__mmEnemy, __mmNow);
__mmSeen[__mmSid] = !0;
if (
__mmNow - __mmAutoSpikeInstaLastAt >= __mmServerTickMs() &&
__mmEnemyWillHitSpikeNextTick(__mmEnemy, __mmPrediction) &&
__mmStartSpikeTickStrike(__mmEnemy, __mmPrediction)
) {
__mmAutoSpikeInstaLastAt = __mmNow;
return;
}
}
for (const __mmSid in __mmAutoSpikeInstaMotion)
__mmSeen[__mmSid] || delete __mmAutoSpikeInstaMotion[__mmSid];
}
function __mmStartAutoSpikeInsta() {
__mmAutoSpikeInstaTimer ||
(__mmAutoSpikeInstaTimer = setInterval(__mmUpdateAutoSpikeInsta, 5));
}
function __mmAutoSpikeSpamGhostStillRelevant() {
const __mmGhost = __mmAutoSpikeSpamGhost;
if (!__mmGhost || __mmGhost.targetSid == null || !v || !v.alive)
return !1;
let __mmEnemy = null;
try {
__mmEnemy = Rt(__mmGhost.targetSid);
} catch (__mmLookupError) {}
return !!(
__mmIsEnemyPlayer(__mmEnemy) &&
__mmAutoSpikeSpamTrapForEnemy(__mmEnemy)
);
}
function __mmAutoSpikeSpamResetCandidate(__mmForceGhostClear) {
((__mmForceGhostClear || !__mmAutoSpikeSpamGhostStillRelevant()) &&
(__mmAutoSpikeSpamGhost = null),
(__mmAutoSpikeSpamCandidateKey = null),
(__mmAutoSpikeSpamCandidateSince = 0));
}
function __mmAutoSpikeSpamCleanReservations(__mmNow) {
for (let __mmIndex = __mmAutoSpikeSpamReservations.length - 1; __mmIndex >= 0; __mmIndex--)
__mmAutoSpikeSpamReservations[__mmIndex].expiresAt <= __mmNow &&
__mmAutoSpikeSpamReservations.splice(__mmIndex, 1);
}
function __mmAutoSpikeSpamHasCapacity(__mmSpike) {
const __mmData = b && b.list && b.list[__mmSpike];
if (
__mmSpike == null ||
!__mmData ||
!__mmData.group ||
!__mmCanUseBuildItem(__mmSpike) ||
__mmMaxBuildCount(__mmSpike) < 1
)
return !1;
const __mmLimit = y.inSandbox
? __mmData.group.sandboxLimit || Math.max(__mmData.group.limit * 3, 99)
: __mmData.group.limit,
__mmPlaced = Number(v.itemCounts && v.itemCounts[__mmData.group.id]) || 0;
return !__mmLimit ||
__mmPlaced + __mmAutoSpikeSpamReservations.length < __mmLimit;
}
function __mmAutoSpikeSpamTrapForEnemy(__mmEnemy) {
if (!__mmEnemy || !Array.isArray(ge)) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmTrap = ge[__mmIndex];
if (
!__mmTrap ||
!__mmTrap.active ||
!__mmTrap.trap ||
!__mmSpikeHostileToEnemy(__mmTrap, __mmEnemy)
)
continue;
const __mmTrapCollisionScale =
typeof __mmTrap.getScale === "function"
? Number(__mmTrap.getScale()) || 0
: (Number(__mmTrap.scale) || 50) * (Number(__mmTrap.colDiv) || 1),
__mmDistance = Math.hypot(
__mmEnemy.x - __mmTrap.x,
__mmEnemy.y - __mmTrap.y,
),
// Allow for a little dangling/jitter around the trap edge. Hostility and
// active-trap checks still prevent unrelated structures from qualifying.
__mmLockRange =
(Number(__mmEnemy.scale) || 35) + __mmTrapCollisionScale + 14;
if (__mmDistance <= __mmLockRange && __mmDistance < __mmClosestDistance) {
((__mmClosest = __mmTrap), (__mmClosestDistance = __mmDistance));
}
}
return __mmClosest;
}
function __mmAutoSpikeSpamTarget() {
if (!v || !v.alive || !Array.isArray(E)) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmEnemy = E[__mmIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmTrap = __mmAutoSpikeSpamTrapForEnemy(__mmEnemy);
if (!__mmTrap) continue;
const __mmDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y);
if (__mmDistance < __mmClosestDistance) {
((__mmClosest = { enemy: __mmEnemy, trap: __mmTrap }),
(__mmClosestDistance = __mmDistance));
}
}
return __mmClosest;
}
function __mmAutoSpikeSpamObjectScale(__mmObject) {
if (!__mmObject) return 0;
if (Number(__mmObject.blocker) > 0) return Number(__mmObject.blocker);
if (typeof __mmObject.getScale === "function") {
// Match the server's checkItemLocation scale arguments for a normal build.
const __mmScale = Number(__mmObject.getScale(0.6, !!__mmObject.isItem));
if (Number.isFinite(__mmScale) && __mmScale > 0) return __mmScale;
}
return Number(__mmObject.scale) || 0;
}
function __mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale) {
if (
__mmX - __mmSpikeScale < 0 ||
__mmY - __mmSpikeScale < 0 ||
__mmX + __mmSpikeScale > y.mapScale ||
__mmY + __mmSpikeScale > y.mapScale ||
(__mmY >= y.mapScale / 2 - y.riverWidth / 2 &&
__mmY <= y.mapScale / 2 + y.riverWidth / 2)
)
return !1;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmObject = ge[__mmIndex];
if (!__mmObject || !__mmObject.active) continue;
const __mmObjectScale = __mmAutoSpikeSpamObjectScale(__mmObject),
// Match the game's collision boundary instead of adding a stricter
// two-pixel buffer around every nearby structure.
__mmMinimum = __mmSpikeScale + __mmObjectScale;
if (
(__mmObject.x - __mmX) ** 2 + (__mmObject.y - __mmY) ** 2 <
__mmMinimum * __mmMinimum
)
return !1;
}
for (let __mmIndex = 0; __mmIndex < __mmAutoSpikeSpamReservations.length; __mmIndex++) {
const __mmReservation = __mmAutoSpikeSpamReservations[__mmIndex],
__mmMinimum = __mmSpikeScale + __mmReservation.scale;
if (
(__mmReservation.x - __mmX) ** 2 +
(__mmReservation.y - __mmY) ** 2 <
__mmMinimum * __mmMinimum
)
return !1;
}
return !0;
}
function __mmAutoSpikeSpamPredictionLead() {
const __mmPing = Number(window.pingTime);
return Math.max(
10,
Math.min(
65,
__mmServerTickMs() * 0.16 +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing) * 0.5 : 0),
),
);
}
function __mmAutoSpikeSpamPredictedEnemy(__mmTarget, __mmNow) {
const __mmEnemy = __mmTarget && __mmTarget.enemy,
__mmTrap = __mmTarget && __mmTarget.trap;
if (!__mmEnemy) return null;
const __mmKey = String(__mmEnemy.sid),
__mmPrevious = __mmAutoSpikeSpamMotion[__mmKey],
__mmMoved = !!(
__mmPrevious &&
Math.hypot(
__mmEnemy.x - __mmPrevious.x,
__mmEnemy.y - __mmPrevious.y,
) > 0.001
),
// Only advance the sample clock when the coordinates actually change.
// The solver runs every 5 ms, while player coordinates commonly update
// once per render/server step; advancing it on identical scans creates a
// false, extremely high velocity on the next real update.
__mmSampleElapsed = __mmMoved
? Math.max(1, Math.min(250, __mmNow - __mmPrevious.sampleAt))
: 0,
__mmSampleFresh = !!(
__mmPrevious &&
__mmNow - __mmPrevious.sampleAt <= 250
),
__mmSampleVelocityX = __mmMoved
? (__mmEnemy.x - __mmPrevious.x) / __mmSampleElapsed
: __mmSampleFresh
? __mmPrevious.sampleVelocityX
: 0,
__mmSampleVelocityY = __mmMoved
? (__mmEnemy.y - __mmPrevious.y) / __mmSampleElapsed
: __mmSampleFresh
? __mmPrevious.sampleVelocityY
: 0,
__mmServerElapsed = Number(__mmEnemy.t2) - Number(__mmEnemy.t1),
__mmServerVelocityX =
(Number(__mmEnemy.x2) - Number(__mmEnemy.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(__mmEnemy.y2) - Number(__mmEnemy.y1)) / __mmServerElapsed,
__mmHasServerVelocity = !!(
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
);
let __mmVelocityX = __mmHasServerVelocity
? __mmServerVelocityX * 0.68 + __mmSampleVelocityX * 0.32
: __mmSampleVelocityX,
__mmVelocityY = __mmHasServerVelocity
? __mmServerVelocityY * 0.68 + __mmSampleVelocityY * 0.32
: __mmSampleVelocityY;
if (__mmPrevious) {
((__mmVelocityX = __mmVelocityX * 0.72 + __mmPrevious.velocityX * 0.28),
(__mmVelocityY = __mmVelocityY * 0.72 + __mmPrevious.velocityY * 0.28));
}
__mmAutoSpikeSpamMotion[__mmKey] = {
x: __mmMoved || !__mmPrevious ? __mmEnemy.x : __mmPrevious.x,
y: __mmMoved || !__mmPrevious ? __mmEnemy.y : __mmPrevious.y,
sampleAt:
__mmMoved || !__mmPrevious ? __mmNow : __mmPrevious.sampleAt,
sampleVelocityX: __mmSampleVelocityX,
sampleVelocityY: __mmSampleVelocityY,
velocityX: __mmVelocityX,
velocityY: __mmVelocityY,
};
const __mmLeadMs = __mmAutoSpikeSpamPredictionLead(),
__mmRawLeadX = __mmVelocityX * __mmLeadMs,
__mmRawLeadY = __mmVelocityY * __mmLeadMs,
__mmLeadDistance = Math.hypot(__mmRawLeadX, __mmRawLeadY),
__mmLeadScale = __mmLeadDistance > 14 ? 14 / __mmLeadDistance : 1;
let __mmX = __mmEnemy.x + __mmRawLeadX * __mmLeadScale,
__mmY = __mmEnemy.y + __mmRawLeadY * __mmLeadScale;
if (__mmTrap) {
const __mmTrapScale =
typeof __mmTrap.getScale === "function"
? Number(__mmTrap.getScale()) || Number(__mmTrap.scale) || 50
: Number(__mmTrap.scale) || 50,
__mmLockRadius = (Number(__mmEnemy.scale) || 35) + __mmTrapScale + 14,
__mmTrapDx = __mmX - __mmTrap.x,
__mmTrapDy = __mmY - __mmTrap.y,
__mmTrapDistance = Math.hypot(__mmTrapDx, __mmTrapDy);
if (__mmTrapDistance > __mmLockRadius && __mmTrapDistance > 0) {
((__mmX = __mmTrap.x + (__mmTrapDx / __mmTrapDistance) * __mmLockRadius),
(__mmY = __mmTrap.y + (__mmTrapDy / __mmTrapDistance) * __mmLockRadius));
}
}
return {
x: __mmX,
y: __mmY,
scale: __mmEnemy.scale,
sid: __mmEnemy.sid,
};
}
function __mmAutoSpikeSpamPredictedOrigin() {
if (!v || !v.alive) return null;
let __mmVelocityX = Number(
__mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityX,
) || 0,
__mmVelocityY = Number(
__mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityY,
) || 0;
const __mmServerElapsed = Number(v.t2) - Number(v.t1),
__mmServerVelocityX = (Number(v.x2) - Number(v.x1)) / __mmServerElapsed,
__mmServerVelocityY = (Number(v.y2) - Number(v.y1)) / __mmServerElapsed;
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
) {
((__mmVelocityX = __mmVelocityX * 0.35 + __mmServerVelocityX * 0.65),
(__mmVelocityY = __mmVelocityY * 0.35 + __mmServerVelocityY * 0.65));
}
const __mmLeadMs = __mmAutoSpikeSpamPredictionLead(),
__mmLeadX = __mmVelocityX * __mmLeadMs,
__mmLeadY = __mmVelocityY * __mmLeadMs,
__mmDistance = Math.hypot(__mmLeadX, __mmLeadY),
__mmScale = __mmDistance > 10 ? 10 / __mmDistance : 1;
return {
x: v.x + __mmLeadX * __mmScale,
y: v.y + __mmLeadY * __mmScale,
};
}
function __mmAutoSpikeSpamCandidate(__mmTarget, __mmSpike) {
if (!__mmTarget || !v) return null;
const __mmNow = Date.now(),
__mmEnemy = __mmAutoSpikeSpamPredictedEnemy(__mmTarget, __mmNow),
__mmOrigin = __mmAutoSpikeSpamPredictedOrigin(),
__mmData = b.list[__mmSpike],
__mmSpikeScale = Number(__mmData.scale) || 49,
__mmPlacementRadius =
(Number(v.scale) || 35) +
__mmSpikeScale +
(Number(__mmData.placeOffset) || 0),
__mmTouchRadius =
(Number(__mmEnemy.scale) || 35) + __mmSpikeScale - 2,
__mmTargetDx = __mmEnemy.x - __mmOrigin.x,
__mmTargetDy = __mmEnemy.y - __mmOrigin.y,
__mmTargetDistance = Math.hypot(__mmTargetDx, __mmTargetDy);
if (
__mmTargetDistance <= 1e-6 ||
__mmTargetDistance > __mmPlacementRadius + __mmTouchRadius + 10 ||
__mmTargetDistance < Math.abs(__mmPlacementRadius - __mmTouchRadius) - 10
)
return null;
const __mmBaseAngle = Math.atan2(__mmTargetDy, __mmTargetDx),
__mmCosOffset = Math.max(
-1,
Math.min(
1,
(__mmPlacementRadius * __mmPlacementRadius +
__mmTargetDistance * __mmTargetDistance -
__mmTouchRadius * __mmTouchRadius) /
(2 * __mmPlacementRadius * __mmTargetDistance),
),
),
__mmIntersectionOffset = Math.acos(__mmCosOffset),
__mmSeeds = [
__mmBaseAngle - __mmIntersectionOffset,
__mmBaseAngle + __mmIntersectionOffset,
];
let __mmBest = null,
__mmBestScore = Infinity;
for (let __mmSeedIndex = 0; __mmSeedIndex < __mmSeeds.length; __mmSeedIndex++) {
let __mmSeedFound = !1;
for (let __mmStep = 0; __mmStep <= 140 && !__mmSeedFound; __mmStep++) {
const __mmOffset = __mmStep * 0.0025,
__mmSigns = __mmStep === 0 ? [0] : [-1, 1];
for (
let __mmSignIndex = 0;
__mmSignIndex < __mmSigns.length;
__mmSignIndex++
) {
const __mmSignedOffset = __mmOffset * __mmSigns[__mmSignIndex],
__mmAngle = __mmSeeds[__mmSeedIndex] + __mmSignedOffset,
__mmX = __mmOrigin.x + Math.cos(__mmAngle) * __mmPlacementRadius,
__mmY = __mmOrigin.y + Math.sin(__mmAngle) * __mmPlacementRadius,
__mmEnemyDistance = Math.hypot(
__mmX - __mmEnemy.x,
__mmY - __mmEnemy.y,
),
__mmTouchError = Math.abs(__mmEnemyDistance - __mmTouchRadius);
if (
__mmEnemyDistance > __mmTouchRadius + 4 ||
__mmEnemyDistance < __mmTouchRadius - 9 ||
!__mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale)
)
continue;
const __mmScore =
__mmTouchError * 12 + Math.abs(__mmSignedOffset) * 2;
if (__mmScore < __mmBestScore) {
((__mmBestScore = __mmScore),
(__mmBest = {
item: __mmSpike,
x: __mmX,
y: __mmY,
angle: __mmAngle,
scale: __mmSpikeScale,
targetSid: __mmEnemy.sid,
}));
}
__mmSeedFound = !0;
}
}
}
return __mmBest;
}
function __mmPlaceAutoSpikeSpam(__mmCandidate, __mmNow) {
if (
!__mmCandidate ||
__mmHoldingMcGrabby() ||
!__mmAutoSpikeSpamHasCapacity(__mmCandidate.item) ||
!__mmActionClaim("spikeSpam", "trapped enemy edge")
)
return !1;
const __mmTool = __mmSelectedTool();
try {
((__mmAutoSpikeSpamAimAngle = __mmCandidate.angle),
(__mmAutoSpikeSpamAimUntil = __mmNow + __mmServerTickMs()),
O.send("D", __mmCandidate.angle),
je(__mmCandidate.item),
O.send("F", 1, __mmCandidate.angle),
O.send("F", 0, __mmCandidate.angle),
__mmRestoreTool(__mmTool),
__mmAutoSpikeSpamReservations.push({
x: __mmCandidate.x,
y: __mmCandidate.y,
scale: __mmCandidate.scale,
expiresAt: __mmNow + 650,
}),
(__mmAutoSpikeSpamLastAt = __mmNow),
__mmActionRelease("spikeSpam", "spike placed"),
__mmAutoSpikeSpamResetCandidate());
return !0;
} catch (__mmSpikeSpamError) {
(__mmActionRelease("spikeSpam", "placement failed"),
__mmAutoSpikeSpamResetCandidate());
return !1;
}
}
function __mmAutoSpikeSpamCanPlaceNow() {
return !!(
v &&
v.alive &&
!v.lockMove &&
!__mmInsta.isActive() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
!__mmBuildSpamTimer &&
!__mmFoodSpamTimer &&
(__mmActionAvailable("spikeSpam") ||
__mmActionOwner === "weaponRecharge" ||
__mmActionOwner === "matThief" ||
__mmActionOwner === "mobSteal")
);
}
function __mmUpdateAutoSpikeSpam() {
const __mmNow = Date.now();
__mmAutoSpikeSpamCleanReservations(__mmNow);
if (
!__mmAutoSpikeSpamEnabled ||
!v ||
!v.alive
)
return void __mmAutoSpikeSpamResetCandidate(!0);
const __mmSpike = __mmSpikeItem();
if (!__mmAutoSpikeSpamHasCapacity(__mmSpike))
return void __mmAutoSpikeSpamResetCandidate();
const __mmTarget = __mmAutoSpikeSpamTarget(),
__mmCandidate = __mmAutoSpikeSpamCandidate(__mmTarget, __mmSpike);
if (!__mmCandidate) return void __mmAutoSpikeSpamResetCandidate();
__mmAutoSpikeSpamGhost = __mmCandidate;
const __mmKey =
String(__mmCandidate.targetSid) + ":" +
Math.round(__mmCandidate.x / 3) + ":" +
Math.round(__mmCandidate.y / 3);
if (__mmKey !== __mmAutoSpikeSpamCandidateKey) {
((__mmAutoSpikeSpamCandidateKey = __mmKey),
(__mmAutoSpikeSpamCandidateSince = __mmNow));
}
// Previewing is independent from action ownership. Keep drawing the legal
// non-colliding position while a click, insta, or reload temporarily blocks
// placement instead of erasing the ghost every 10ms. After placement, the
// last valid ghost remains pinned until this target is no longer trapped.
if (!__mmAutoSpikeSpamCanPlaceNow()) return;
if (
__mmNow - __mmAutoSpikeSpamLastAt >=
Math.max(5, Math.min(10, __mmServerTickMs() * 0.08))
) {
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
__mmActionOwner === "matThief" &&
__mmFinishMatThief("trapped-player spike priority");
__mmActionOwner === "mobSteal" &&
__mmFinishMobSteal("trapped-player spike priority");
__mmPlaceAutoSpikeSpam(__mmCandidate, __mmNow);
}
}
function __mmStartAutoSpikeSpam() {
__mmAutoSpikeSpamTimer ||
(__mmAutoSpikeSpamTimer = setInterval(__mmUpdateAutoSpikeSpam, 5));
}
function __mmStartFoodSpam() {
__mmInsta.isActive() && __mmInsta.cancel("food-input");
if (__mmFoodSpamTimer) return;
(__mmUseFood(),
(__mmFoodSpamTimer = setInterval(__mmUseFood, 1e3 / y.serverUpdateRate)));
}
function __mmStopFoodSpam() {
__mmFoodSpamTimer &&
(clearInterval(__mmFoodSpamTimer), (__mmFoodSpamTimer = 0));
}
function __mmUseBuild(__mmItemSlot) {
if (!v || !v.alive) return;
const __mmWeapon = __mmSelectedWeapon(),
__mmItem = __mmItemSlot < 0 ? v.buildIndex : v.items[__mmItemSlot];
if (__mmItem == null || __mmItem <= 0) return;
(__mmItemSlot >= 0 && je(__mmItem),
O.send("F", 1, Ci()),
O.send("F", 0, Ci()),
__mmRestoreWeapon(__mmWeapon));
}
function __mmUseBuildItem(__mmItem) {
if (
!v ||
!v.alive ||
__mmItem == null ||
__mmItem <= 0 ||
!__mmCanUseBuildItem(__mmItem)
)
return;
const __mmWeapon = __mmSelectedWeapon();
(je(__mmItem),
O.send("F", 1, Ci()),
O.send("F", 0, Ci()),
__mmRestoreWeapon(__mmWeapon));
}
function __mmSpikeItem() {
if (!v || !v.items) return null;
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmItem = v.items[__mmItemIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
typeof __mmData.name === "string" &&
__mmData.name.indexOf("spikes") !== -1
)
return __mmItem;
}
return null;
}
function __mmLethalProjectileVolley() {
if (!v || !v.alive || !Array.isArray(Ve)) return null;
const __mmPlayerRadius = Number(v.scale) || 35,
__mmHorizonMs = 650;
let __mmDamage = 0,
__mmFirstThreat = null,
__mmFirstImpactMs = Infinity;
for (
let __mmProjectileIndex = 0;
__mmProjectileIndex < Ve.length;
__mmProjectileIndex++
) {
const __mmProjectile = Ve[__mmProjectileIndex];
if (!__mmProjectile || !__mmProjectile.active) continue;
const __mmX = Number(__mmProjectile.x),
__mmY = Number(__mmProjectile.y),
__mmDirection = Number(__mmProjectile.dir),
__mmSpeed = Number(__mmProjectile.speed),
__mmDamageValue = Number(__mmProjectile.dmg);
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmDirection) ||
!Number.isFinite(__mmSpeed) ||
__mmSpeed <= 0 ||
!Number.isFinite(__mmDamageValue) ||
__mmDamageValue <= 0
)
continue;
const __mmToPlayerX = v.x - __mmX,
__mmToPlayerY = v.y - __mmY,
__mmForward =
__mmToPlayerX * Math.cos(__mmDirection) +
__mmToPlayerY * Math.sin(__mmDirection),
__mmSide = Math.abs(
__mmToPlayerX * Math.sin(__mmDirection) -
__mmToPlayerY * Math.cos(__mmDirection),
),
__mmHitRadius = __mmPlayerRadius + (Number(__mmProjectile.scale) || 0),
__mmImpactMs = __mmForward / __mmSpeed,
__mmRemainingRange = Number(__mmProjectile.range);
if (
__mmForward < 0 ||
__mmSide > __mmHitRadius ||
__mmImpactMs > __mmHorizonMs ||
(Number.isFinite(__mmRemainingRange) &&
__mmForward > __mmRemainingRange + __mmHitRadius)
)
continue;
(__mmDamage += __mmDamageValue,
__mmImpactMs < __mmFirstImpactMs &&
((__mmFirstImpactMs = __mmImpactMs),
(__mmFirstThreat = __mmProjectile)));
}
return __mmFirstThreat && __mmDamage >= Number(v.health)
? {
damage: __mmDamage,
angle: Math.atan2(__mmFirstThreat.y - v.y, __mmFirstThreat.x - v.x),
}
: null;
}
function __mmCanUseAntiInsta() {
return !!(
__mmAntiInstaEnabled &&
!__mmHoldingMcGrabby() &&
__mmActionAvailable("antiInsta") &&
v &&
v.alive &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
!__mmBuildSpamTimer &&
!__mmFoodSpamTimer &&
!__mmShieldDefenseTimer
);
}
function __mmPlaceAntiInstaSpike(__mmAngle) {
if (__mmHoldingMcGrabby()) return !1;
const __mmSpike = __mmSpikeItem();
if (__mmSpike == null || !__mmCanUseBuildItem(__mmSpike)) return !1;
const __mmTool = __mmSelectedTool();
(je(__mmSpike),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmRestoreTool(__mmTool));
return !0;
}
function __mmUpdateAntiInsta() {
if (
!__mmAntiInstaEnabled ||
!v ||
!v.alive ||
__mmHoldingMcGrabby()
)
return;
const __mmNow = Date.now();
if (__mmNow - __mmAntiInstaLastAt < 450) return;
const __mmThreat = __mmLethalProjectileVolley();
if (!__mmThreat) return;
// A lethal volley takes priority over a queued combo, but we never switch
// selection out from underneath a real held attack or another build action.
__mmInsta.isActive() && __mmInsta.cancel("lethal-projectile");
__mmInstaSyncPending || __mmInstaSyncFiring ? __mmStopInstaSync() : null;
if (!__mmActionCanPreempt("antiInsta")) return;
__mmActionOwner === "shieldDefense" &&
__mmStopShieldDefense("lethal projectile priority");
__mmBoostBreakHeld && __mmStopBoostBreak();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmActionClaim("antiInsta", "lethal projectile")) return;
if (!__mmCanUseAntiInsta())
return void __mmActionRelease("antiInsta", "unsafe to place");
if (!__mmPlaceAntiInstaSpike(__mmThreat.angle))
return void __mmActionRelease("antiInsta", "no spike");
((__mmAntiInstaLastAt = __mmNow),
(__mmAntiInstaUntil = __mmNow + Math.max(140, __mmServerTickMs())),
__mmAntiInstaActionTimer && clearTimeout(__mmAntiInstaActionTimer),
(__mmAntiInstaActionTimer = setTimeout(function () {
((__mmAntiInstaActionTimer = 0),
__mmActionRelease("antiInsta", "threat window complete"));
}, Math.max(140, __mmServerTickMs()))));
}
function __mmStartAntiInsta() {
__mmAntiInstaTimer ||
(__mmAntiInstaTimer = setInterval(__mmUpdateAntiInsta, 25));
}
function __mmProjectileTravelDistance(__mmFrom, __mmTarget) {
return Math.max(
0,
Math.hypot(__mmTarget.x - __mmFrom.x, __mmTarget.y - __mmFrom.y) -
(Number(__mmFrom.scale) || 35) -
(Number(__mmTarget.scale) || 35),
);
}
function __mmDirectFriendlyProjectileSource(__mmProjectile) {
if (!v || !v.alive || !__mmProjectile || !__mmProjectile.owner) return null;
const __mmOwner = __mmProjectile.owner,
__mmOwnerSid = __mmOwner.sid;
// A normal shot from this player should not recursively trigger another
// sync shot. Personal structures are allowed through the nested owner path.
if (
__mmOwner === v ||
(__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
)
return null;
let __mmOwnerPlayer =
__mmOwnerSid != null && typeof Rt === "function" ? Rt(__mmOwnerSid) : null;
if (__mmSameTeam(__mmOwnerPlayer || __mmOwner))
return __mmOwnerPlayer || __mmOwner;
const __mmStructureOwner = __mmOwner.owner,
__mmStructureOwnerSid = __mmStructureOwner && __mmStructureOwner.sid;
if (!__mmStructureOwner) return null;
if (String(__mmStructureOwnerSid) === String(v.sid)) return __mmOwner;
__mmOwnerPlayer =
__mmStructureOwnerSid != null && typeof Rt === "function"
? Rt(__mmStructureOwnerSid)
: null;
return __mmSameTeam(__mmOwnerPlayer || __mmStructureOwner)
? __mmOwner
: null;
}
function __mmFriendlyProjectileSource(__mmProjectile) {
if (!__mmProjectile || !Array.isArray(E)) return null;
const __mmX = Number(__mmProjectile.x),
__mmY = Number(__mmProjectile.y),
__mmDirection = Number(__mmProjectile.dir);
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmDirection)
)
return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
!__mmSameTeam(__mmPlayer)
)
continue;
const __mmDx = __mmX - __mmPlayer.x,
__mmDy = __mmY - __mmPlayer.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmForward =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection),
__mmSide = Math.abs(
__mmDx * Math.sin(__mmDirection) -
__mmDy * Math.cos(__mmDirection),
);
if (
__mmForward < -35 ||
__mmSide > 125 ||
__mmDistance > Math.max(320, (Number(__mmPlayer.scale) || 35) + 180) ||
__mmDistance >= __mmClosestDistance
)
continue;
((__mmClosest = __mmPlayer), (__mmClosestDistance = __mmDistance));
}
return __mmClosest;
}
function __mmPersonalTurretProjectileSource(__mmProjectile) {
if (!v || !v.alive || !__mmProjectile || !Array.isArray(ge)) return null;
const __mmX = Number(__mmProjectile.x),
__mmY = Number(__mmProjectile.y),
__mmDirection = Number(__mmProjectile.dir);
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmDirection)
)
return null;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmObject = ge[__mmIndex],
__mmItem = __mmObject && b.list[__mmObject.id];
if (
!__mmObject ||
!__mmObject.active ||
!__mmItem ||
String(__mmItem.name || "").toLowerCase() !== "turret" ||
!__mmObject.owner
)
continue;
const __mmOwnerSid = __mmObject.owner.sid,
__mmOwnerPlayer =
String(__mmOwnerSid) === String(v.sid)
? v
: typeof Rt === "function"
? Rt(__mmOwnerSid)
: null;
if (
String(__mmOwnerSid) !== String(v.sid) &&
!__mmSameTeam(__mmOwnerPlayer || __mmObject.owner)
)
continue;
const __mmDx = __mmX - __mmObject.x,
__mmDy = __mmY - __mmObject.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmForward =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection),
__mmSide = Math.abs(
__mmDx * Math.sin(__mmDirection) -
__mmDy * Math.cos(__mmDirection),
);
if (
__mmForward >= -35 &&
__mmSide <= Math.max(150, Number(__mmObject.scale) || 0) &&
__mmDistance <= Math.max(340, (Number(__mmObject.scale) || 45) + 200)
)
return __mmObject;
}
return null;
}
function __mmSyncPlayerVelocity(__mmPlayer) {
if (!__mmPlayer) return { x: 0, y: 0 };
const __mmElapsed = Number(__mmPlayer.t2) - Number(__mmPlayer.t1),
__mmX =
(Number(__mmPlayer.x2) - Number(__mmPlayer.x1)) / __mmElapsed,
__mmY =
(Number(__mmPlayer.y2) - Number(__mmPlayer.y1)) / __mmElapsed;
return __mmElapsed > 0 &&
__mmElapsed <= 500 &&
Number.isFinite(__mmX) &&
Number.isFinite(__mmY)
? { x: Math.max(-1.5, Math.min(1.5, __mmX)), y: Math.max(-1.5, Math.min(1.5, __mmY)) }
: { x: 0, y: 0 };
}
function __mmProjectileEnemyTarget(__mmProjectile) {
const __mmPlayers = __mmLiveStateFresh() ? __mmLiveState.enemies : E;
if (!__mmProjectile || !Array.isArray(__mmPlayers)) return null;
const __mmX = Number(__mmProjectile.x),
__mmY = Number(__mmProjectile.y),
__mmDirection = Number(__mmProjectile.dir),
__mmSpeed = Number(__mmProjectile.speed),
__mmRange = Number(__mmProjectile.range);
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmDirection) ||
!Number.isFinite(__mmSpeed) ||
__mmSpeed <= 0
)
return null;
let __mmTarget = null,
__mmForwardBest = Infinity;
for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
const __mmPlayer = __mmPlayers[__mmIndex];
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
let __mmDx = __mmPlayer.x - __mmX,
__mmDy = __mmPlayer.y - __mmY,
__mmForward =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection);
const __mmVelocity = __mmSyncPlayerVelocity(__mmPlayer),
__mmInitialArrival = Math.max(0, __mmForward) / __mmSpeed,
__mmLead = Math.min(400, __mmInitialArrival);
(__mmDx += __mmVelocity.x * __mmLead,
__mmDy += __mmVelocity.y * __mmLead,
(__mmForward =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection)));
const __mmSide = Math.abs(
__mmDx * Math.sin(__mmDirection) -
__mmDy * Math.cos(__mmDirection),
),
__mmHitRadius =
(Number(__mmPlayer.scale) || 35) +
(Number(__mmProjectile.scale) || 0) +
18;
if (
__mmForward < 0 ||
__mmSide > __mmHitRadius ||
(Number.isFinite(__mmRange) && __mmForward > __mmRange + __mmHitRadius) ||
__mmForward >= __mmForwardBest
)
continue;
((__mmTarget = __mmPlayer), (__mmForwardBest = __mmForward));
}
return __mmTarget
? {
target: __mmTarget,
arrivalMs: __mmForwardBest / __mmSpeed,
}
: null;
}
function __mmSyncProjectileWeapons(__mmTarget) {
if (!v || !v.alive || !v.weapons || !__mmTarget) return [];
const __mmDistance = __mmProjectileTravelDistance(v, __mmTarget);
const __mmShots = [],
__mmSeen = new Set();
for (const __mmWeapon of [v.weapons[1], v.weapons[0]]) {
if (__mmWeapon == null || __mmSeen.has(__mmWeapon)) continue;
__mmSeen.add(__mmWeapon);
const __mmWeaponData =
b.weapons[__mmWeapon],
__mmProjectile =
__mmWeaponData && __mmWeaponData.projectile != null
? b.projectiles[__mmWeaponData.projectile]
: null,
__mmSpeed = __mmProjectile && Number(__mmProjectile.speed),
__mmRange = __mmProjectile && Number(__mmProjectile.range);
if (
!__mmWeaponData ||
!__mmProjectile ||
!__mmWeaponReady(__mmWeapon) ||
!Number.isFinite(__mmSpeed) ||
__mmSpeed <= 0 ||
!Number.isFinite(__mmRange) ||
__mmDistance > __mmRange
)
continue;
__mmShots.push({
type: "projectile",
weapon: __mmWeapon,
// A weapon packet normally lands between server updates. Include half a
// tick of launch latency so the arrival scheduler does not fire late.
travelMs:
Math.min(55, __mmServerTickMs() * 0.5) +
__mmDistance / __mmSpeed,
});
}
return __mmShots;
}
function __mmSyncTurretShot(__mmTarget) {
if (
!v ||
!v.alive ||
!__mmTarget ||
!v.skins ||
!v.skins[__mmTurretGear] ||
!__mmInsta.turretReady()
)
return null;
const __mmDistance = __mmProjectileTravelDistance(v, __mmTarget);
if (__mmDistance > __mmTurretGearRange) return null;
// Turret shots use the bullet travel profile. Account for one gear-apply
// tick before its shot can leave the player.
return {
type: "turret",
travelMs: __mmServerTickMs() + __mmDistance / 3.6,
};
}
function __mmSyncShotsForTarget(__mmTarget) {
const __mmTurret = __mmSyncTurretShot(__mmTarget);
return (__mmTurret ? [__mmTurret] : []).concat(
__mmSyncProjectileWeapons(__mmTarget),
);
}
function __mmSyncAimAngle(__mmTarget, __mmTravelMs) {
const __mmVelocity = __mmSyncPlayerVelocity(__mmTarget),
__mmPing = Number(window.pingTime),
__mmLead = Math.min(
450,
Math.max(0, Number(__mmTravelMs) || 0) +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0),
),
__mmTargetX = __mmTarget.x + __mmVelocity.x * __mmLead,
__mmTargetY = __mmTarget.y + __mmVelocity.y * __mmLead;
return Math.atan2(__mmTargetY - v.y, __mmTargetX - v.x);
}
function __mmCanFireInstaSync() {
return !!(
__mmInstaSyncEnabled &&
(__mmActionAvailable("instaSync") ||
__mmActionOwner === "weaponRecharge" ||
__mmActionOwner === "matThief" ||
__mmActionOwner === "mobSteal") &&
v &&
v.alive &&
!__mmInsta.isActive() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
!__mmBuildSpamTimer &&
!__mmFoodSpamTimer &&
!__mmShieldDefenseTimer &&
!__mmInstaSyncFiring
);
}
function __mmFinishInstaSync() {
const __mmTool = __mmInstaSyncRestoreTool,
__mmHat = __mmInstaSyncRestoreHat,
__mmRestore = __mmActionMayRestore("instaSync");
(__mmInstaSyncReleaseTimer && clearTimeout(__mmInstaSyncReleaseTimer),
(__mmInstaSyncReleaseTimer = 0),
__mmInstaSyncWeaponHeld && O.send("F", 0, null),
(__mmInstaSyncWeaponHeld = !1),
(__mmInstaSyncRestoreTool = null),
(__mmInstaSyncRestoreHat = null),
(__mmInstaSyncFiring = !1),
__mmRestore && __mmHat != null && __mmEquipHatNow(__mmHat),
__mmRestore && __mmRestoreTool(__mmTool),
__mmActionRelease("instaSync", "sync shot complete"));
}
function __mmStopInstaSync() {
(__mmInstaSyncTimer && clearTimeout(__mmInstaSyncTimer),
(__mmInstaSyncTimer = 0),
(__mmInstaSyncPending = !1),
__mmFinishInstaSync());
}
function __mmFireInstaSync(__mmShot, __mmTargetSid) {
((__mmInstaSyncTimer = 0), (__mmInstaSyncPending = !1));
let __mmTarget = null;
try {
__mmTarget = Rt(__mmTargetSid);
} catch (__mmLookupError) {}
if (!__mmCanFireInstaSync() || !__mmIsEnemyPlayer(__mmTarget))
return void __mmFinishInstaSync();
const __mmAngle = __mmSyncAimAngle(__mmTarget, __mmShot.travelMs);
((__mmInstaSyncFiring = !0), (__mmInstaSyncLastAt = Date.now()));
if (__mmShot.type === "turret") {
((__mmInstaSyncRestoreHat = v.skinIndex),
__mmEquipHatNow(__mmTurretGear),
O.send("D", __mmAngle),
(__mmInstaSyncReleaseTimer = setTimeout(
__mmFinishInstaSync,
__mmServerTickMs(),
)));
return;
}
if (
__mmShot.weapon == null ||
!__mmWeaponReady(__mmShot.weapon) ||
!v.weapons.includes(__mmShot.weapon)
)
return void __mmFinishInstaSync();
((__mmInstaSyncRestoreTool = __mmSelectedTool()),
je(__mmShot.weapon, !0),
O.send("D", __mmAngle),
O.send("F", 1, __mmAngle),
(__mmInstaSyncWeaponHeld = !0),
(__mmInstaSyncReleaseTimer = setTimeout(
__mmFinishInstaSync,
__mmServerTickMs(),
)));
}
function __mmScheduleInstaSync(__mmProjectile, __mmTargetInfo) {
if (
!__mmCanFireInstaSync() ||
__mmInstaSyncPending ||
Date.now() - __mmInstaSyncLastAt < 45
)
return !1;
const __mmShots = __mmSyncShotsForTarget(__mmTargetInfo.target),
__mmPing = Number(window.pingTime),
__mmOneWayPing = Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0;
let __mmChoice = null;
for (let __mmIndex = 0; __mmIndex < __mmShots.length; __mmIndex++) {
const __mmShot = __mmShots[__mmIndex],
__mmRawDelay =
__mmTargetInfo.arrivalMs - __mmShot.travelMs - __mmOneWayPing;
// Do not schedule a shot that is already meaningfully too late. Among
// viable shots, prefer the one that can leave soonest for less aim drift.
if (__mmRawDelay < -35 || __mmRawDelay > 900) continue;
const __mmDelay = Math.max(0, Math.round(__mmRawDelay));
if (!__mmChoice || __mmDelay < __mmChoice.delay)
__mmChoice = { shot: __mmShot, delay: __mmDelay };
}
if (!__mmChoice) return !1;
if (!__mmActionClaim("instaSync", "friendly projectile")) return !1;
((__mmInstaSyncPending = !0),
__mmChoice.delay <= 1
? __mmFireInstaSync(__mmChoice.shot, __mmTargetInfo.target.sid)
: (__mmInstaSyncTimer = setTimeout(function () {
__mmFireInstaSync(__mmChoice.shot, __mmTargetInfo.target.sid);
}, __mmChoice.delay)));
return !0;
}
function __mmUpdateInstaSync() {
if (
!__mmInstaSyncEnabled ||
__mmInstaSyncPending ||
__mmInstaSyncFiring ||
!Array.isArray(Ve)
)
return;
for (let __mmIndex = 0; __mmIndex < Ve.length; __mmIndex++) {
const __mmProjectile = Ve[__mmIndex];
if (!__mmProjectile) continue;
const __mmSid = __mmProjectile.sid,
__mmRange = Number(__mmProjectile.range),
__mmPreviousState = __mmInstaSyncProjectileStates.get(__mmProjectile),
__mmNewGeneration = !!(
__mmProjectile.active &&
(!__mmPreviousState ||
!__mmPreviousState.active ||
(__mmSid != null && String(__mmSid) !== __mmPreviousState.sid) ||
(Number.isFinite(__mmRange) &&
Number.isFinite(__mmPreviousState.range) &&
__mmRange > __mmPreviousState.range + 20))
),
__mmState = __mmNewGeneration
? {
active: !0,
handled: !1,
sid: __mmSid == null ? "" : String(__mmSid),
range: __mmRange,
}
: __mmPreviousState || {
active: !!__mmProjectile.active,
handled: !1,
sid: __mmSid == null ? "" : String(__mmSid),
range: __mmRange,
};
((__mmState.active = !!__mmProjectile.active),
(__mmState.range = __mmRange),
__mmInstaSyncProjectileStates.set(__mmProjectile, __mmState));
if (!__mmProjectile.active || __mmState.handled) continue;
if (
!__mmDirectFriendlyProjectileSource(__mmProjectile) &&
!__mmFriendlyProjectileSource(__mmProjectile) &&
!__mmPersonalTurretProjectileSource(__mmProjectile)
)
continue;
const __mmTargetInfo = __mmProjectileEnemyTarget(__mmProjectile);
if (!__mmTargetInfo) continue;
if (__mmScheduleInstaSync(__mmProjectile, __mmTargetInfo)) {
__mmState.handled = !0;
return;
}
}
}
function __mmStartInstaSync() {
__mmInstaSyncLoopTimer ||
(__mmInstaSyncLoopTimer = setInterval(__mmUpdateInstaSync, 5));
}
function __mmMaxBuildCount(__mmItem) {
const __mmData = b.list[__mmItem];
if (!v || !__mmData || !__mmData.req) return 0;
let __mmCount = Infinity;
for (
let __mmReqIndex = 0;
__mmReqIndex < __mmData.req.length;
__mmReqIndex += 2
)
__mmCount = Math.min(
__mmCount,
Math.floor(
(v[__mmData.req[__mmReqIndex]] || 0) / __mmData.req[__mmReqIndex + 1],
),
);
return Number.isFinite(__mmCount) ? Math.max(0, __mmCount) : 0;
}
function __mmEnemyNearBoostPad(__mmPlayer) {
if (!__mmPlayer || !__mmPlayer.alive) return !1;
const __mmGrids = X.getGridArrays(__mmPlayer.x, __mmPlayer.y, 180);
for (let __mmGridIndex = 0; __mmGridIndex < __mmGrids.length; __mmGridIndex++)
for (
let __mmItemIndex = 0;
__mmItemIndex < __mmGrids[__mmGridIndex].length;
__mmItemIndex++
) {
const __mmObject = __mmGrids[__mmGridIndex][__mmItemIndex];
if (!__mmObject.active || !__mmObject.boostSpeed) continue;
const __mmRange = __mmPlayer.scale + __mmObject.scale + 80,
__mmDx = __mmPlayer.x - __mmObject.x,
__mmDy = __mmPlayer.y - __mmObject.y;
if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmRange * __mmRange) return !0;
}
return !1;
}
function __mmAntiBoostAngles(__mmAngle, __mmCount) {
if (__mmCount <= 1) return [__mmAngle];
return [__mmAngle - 0.46, __mmAngle + 0.46];
}
function __mmPlaceAntiBoostSpikes(__mmAngle) {
// Boost-rush defense is the one automatic spike exception while Mc Grabby
// is selected, matching the anti-boost insta safety path.
if (__mmHoldingMcGrabby() && !__mmAntiBoostInstaEnabled) return 0;
const __mmSpike = __mmSpikeItem(),
__mmCount = Math.min(2, __mmMaxBuildCount(__mmSpike));
if (__mmSpike == null || __mmCount < 1) return 0;
const __mmTool = __mmSelectedTool(),
__mmAngles = __mmAntiBoostAngles(__mmAngle, __mmCount);
je(__mmSpike);
for (let __mmIndex = 0; __mmIndex < __mmAngles.length; __mmIndex++)
(O.send("F", 1, __mmAngles[__mmIndex]),
O.send("F", 0, __mmAngles[__mmIndex]));
(__mmRestoreTool(__mmTool), __mmResumeHeldAttack());
return __mmAngles.length;
}
function __mmStopAntiBoostRetreat() {
(__mmAntiBoostMoveTimer && clearTimeout(__mmAntiBoostMoveTimer),
(__mmAntiBoostMoveTimer = 0));
if (!__mmAntiBoostBackingUp) return;
((__mmAntiBoostBackingUp = !1), (Kt = null), Tt());
}
function __mmStopAntiBoostBlock(__mmReason) {
const __mmTool = __mmAntiBoostBlockTool,
__mmRestore = __mmActionMayRestore("antiBoostBlock");
(__mmAntiBoostBlockTimer && clearTimeout(__mmAntiBoostBlockTimer),
(__mmAntiBoostBlockTimer = 0),
__mmStopAntiBoostRetreat(),
(__mmAntiBoostBlockTool = null),
(__mmAntiBoostBlockAimAngle = null),
__mmRestore && __mmRestoreTool(__mmTool),
__mmActionRelease(
"antiBoostBlock",
__mmReason || "boost block complete",
));
}
function __mmStartAntiBoostBlock(__mmEnemy) {
if (
!__mmAntiBoostEnabled ||
!v ||
!v.alive ||
!__mmEnemy ||
__mmAntiBoostBlockTimer
)
return !1;
__mmActionOwner === "shieldDefense" &&
__mmStopShieldDefense("boost block priority");
if (!__mmActionClaim("antiBoostBlock", "boost-pad rush")) return !1;
const __mmToward = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
__mmAway = __mmToward + Math.PI,
__mmWindow = Math.max(180, 3 * __mmServerTickMs());
((__mmAntiBoostBlockTool = __mmSelectedTool()),
(__mmAntiBoostBlockAimAngle = __mmToward),
__mmPlaceAntiBoostSpikes(__mmToward),
O.send("D", __mmToward),
O.send("9", __mmAway),
(Kt = __mmAway),
(__mmAntiBoostBackingUp = !0),
v.weapons &&
v.weapons.includes(__mmShieldWeapon) &&
je(__mmShieldWeapon, !0),
(__mmAntiBoostMoveTimer = setTimeout(
__mmStopAntiBoostRetreat,
Math.max(120, 2 * __mmServerTickMs()),
)),
(__mmAntiBoostBlockTimer = setTimeout(function () {
__mmStopAntiBoostBlock("boost block complete");
}, __mmWindow)));
return !0;
}
function __mmUpdateAntiBoostSpikes() {
// An active burst owns its complete primary -> turret -> secondary window.
if (__mmInsta.isActive()) return;
if (
(!__mmAntiBoostEnabled && !__mmAntiBoostInstaEnabled) ||
!v ||
!v.alive ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld
)
return;
const __mmNow = Date.now();
for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
const __mmEnemy = E[__mmPlayerIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmSid = String(__mmEnemy.sid),
__mmTrail =
__mmEnemyBoostTrail[__mmSid] ||
(__mmEnemyBoostTrail[__mmSid] = {
x: __mmEnemy.x,
y: __mmEnemy.y,
time: __mmNow,
boostAt: 0,
}),
__mmDx = __mmEnemy.x - __mmTrail.x,
__mmDy = __mmEnemy.y - __mmTrail.y,
__mmToPlayerX = v.x - __mmEnemy.x,
__mmToPlayerY = v.y - __mmEnemy.y,
__mmDistance =
__mmToPlayerX * __mmToPlayerX + __mmToPlayerY * __mmToPlayerY;
if (__mmEnemyNearBoostPad(__mmEnemy)) __mmTrail.boostAt = __mmNow;
const __mmFreshBoost = __mmNow - __mmTrail.boostAt <= 700,
__mmMovingToward =
__mmDx * __mmDx + __mmDy * __mmDy > 0.25 &&
__mmDx * __mmToPlayerX + __mmDy * __mmToPlayerY > 0;
((__mmTrail.x = __mmEnemy.x),
(__mmTrail.y = __mmEnemy.y),
(__mmTrail.time = __mmNow));
if (
__mmFreshBoost &&
__mmDistance <= __mmAntiBoostRange * __mmAntiBoostRange &&
__mmMovingToward
) {
if (
__mmAntiBoostInstaEnabled &&
__mmFullInstaReadyFor(__mmEnemy) &&
__mmInsta.start({ automatic: !0, targetSid: __mmEnemy.sid })
) {
((__mmAntiBoostLast = __mmNow), (__mmTrail.boostAt = 0));
return;
}
if (
__mmAntiBoostEnabled &&
__mmNow - __mmAntiBoostLast >= 350 &&
__mmStartAntiBoostBlock(__mmEnemy)
) {
((__mmAntiBoostLast = __mmNow),
(__mmTrail.boostAt = 0));
return;
}
}
}
}
function __mmStartAntiBoostSpikes() {
__mmAntiBoostTimer ||
(__mmAntiBoostTimer = setInterval(
__mmUpdateAntiBoostSpikes,
__mmFastCheckMs(),
));
}
function __mmReloadSpikeTarget() {
if (!v || !v.alive) return null;
if (!__mmMusketIsReloading() && !__mmTurretGearIsReloading()) return null;
const __mmEnemy = __mmNearestEnemy();
if (!__mmEnemy) return null;
const __mmDx = __mmEnemy.x - v.x;
const __mmDy = __mmEnemy.y - v.y;
const __mmRange = Math.min(220, Math.max(120, __mmCombatRange));
return __mmDx * __mmDx + __mmDy * __mmDy <= __mmRange * __mmRange
? __mmEnemy
: null;
}
function __mmPlaceReloadSpike(__mmTarget) {
if (__mmHoldingMcGrabby()) return !1;
const __mmSpike = __mmSpikeItem();
if (
!__mmTarget ||
__mmSpike == null ||
!__mmCanUseBuildItem(__mmSpike)
)
return !1;
const __mmTool = __mmSelectedTool();
const __mmAngle = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x);
(je(__mmSpike),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmRestoreTool(__mmTool));
return !0;
}
function __mmUpdateReloadSpike() {
const __mmReloading = __mmMusketIsReloading() || __mmTurretGearIsReloading();
if (!__mmReloading) return void (__mmReloadSpikePlaced = !1);
if (
!__mmReloadSpikeEnabled ||
__mmReloadSpikePlaced ||
__mmHoldingMcGrabby() ||
!v ||
!v.alive ||
__mmInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmFoodSpamTimer ||
__mmAutoHealWasHealing ||
__mmBuildSpamTimer
)
return;
const __mmTarget = __mmReloadSpikeTarget();
if (!__mmTarget || !__mmActionClaim("reloadSpike", "reload defense")) return;
(__mmPlaceReloadSpike(__mmTarget) && (__mmReloadSpikePlaced = !0),
__mmActionRelease("reloadSpike", "reload defense sent"));
}
function __mmStartReloadSpike() {
__mmReloadSpikeTimer ||
(__mmReloadSpikeTimer = setInterval(__mmUpdateReloadSpike, 25));
}
function __mmStopBuildSpam(__mmKey) {
(!__mmKey || __mmKey == __mmBuildSpamKey) &&
(__mmBuildSpamTimer && clearInterval(__mmBuildSpamTimer),
(__mmBuildSpamTimer = 0),
(__mmBuildSpamKey = 0));
}
function __mmStartBuildSpam(__mmItemSlot, __mmKey) {
__mmInsta.isActive() && __mmInsta.cancel("build-input");
if (__mmBuildSpamTimer && __mmBuildSpamKey == __mmKey) return;
(__mmStopBuildSpam(),
(__mmBuildSpamKey = __mmKey),
__mmUseBuild(__mmItemSlot),
(__mmBuildSpamTimer = setInterval(function () {
__mmUseBuild(__mmItemSlot);
}, 1e3 / y.serverUpdateRate)));
}
function __mmStartBuildItemSpam(__mmItem, __mmKey) {
__mmInsta.isActive() && __mmInsta.cancel("build-input");
if (__mmBuildSpamTimer && __mmBuildSpamKey == __mmKey) return;
(__mmStopBuildSpam(),
(__mmBuildSpamKey = __mmKey),
__mmUseBuildItem(__mmItem),
(__mmBuildSpamTimer = setInterval(
function () {
__mmUseBuildItem(__mmItem);
},
1e3 / Math.max(1, Number(y.serverUpdateRate) || 9),
)));
}
function __mmStartSelectedBuildSpam(__mmKey) {
const __mmItem = __mmSelectedPlaceableItem();
__mmItem != null && __mmStartBuildItemSpam(__mmItem, __mmKey);
}
function __mmWindmillItem() {
if (!v || !v.items) return null;
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmItem = v.items[__mmItemIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
typeof __mmData.name === "string" &&
__mmData.name.indexOf("mill") !== -1
)
return __mmItem;
}
return null;
}
function __mmCleanSpinningWindmillReservations(__mmNow) {
for (
let __mmIndex = __mmSpinningWindmillReservations.length - 1;
__mmIndex >= 0;
__mmIndex--
)
__mmSpinningWindmillReservations[__mmIndex].expiresAt <= __mmNow &&
__mmSpinningWindmillReservations.splice(__mmIndex, 1);
}
function __mmSpinningWindmillCapacity(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
if (
!v ||
!__mmData ||
!__mmData.group ||
!__mmCanUseBuildItem(__mmItem)
)
return 0;
const __mmResourceCount = __mmMaxBuildCount(__mmItem),
__mmLimit = y.inSandbox
? __mmData.group.sandboxLimit || Math.max(__mmData.group.limit * 3, 99)
: __mmData.group.limit,
__mmPlaced = Number(v.itemCounts && v.itemCounts[__mmData.group.id]) || 0,
__mmSlots = __mmLimit
? Math.max(
0,
__mmLimit - __mmPlaced - __mmSpinningWindmillReservations.length,
)
: __mmResourceCount;
return Math.max(0, Math.min(__mmResourceCount, __mmSlots));
}
function __mmSpinningWindmillPositionClear(
__mmX,
__mmY,
__mmScale,
) {
if (
__mmX - __mmScale < 0 ||
__mmY - __mmScale < 0 ||
__mmX + __mmScale > y.mapScale ||
__mmY + __mmScale > y.mapScale ||
(__mmY >= y.mapScale / 2 - y.riverWidth / 2 &&
__mmY <= y.mapScale / 2 + y.riverWidth / 2)
)
return !1;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmObject = ge[__mmIndex];
if (!__mmObject || !__mmObject.active) continue;
const __mmMinimum =
__mmScale + __mmAutoSpikeSpamObjectScale(__mmObject);
if (
(__mmObject.x - __mmX) ** 2 + (__mmObject.y - __mmY) ** 2 <
__mmMinimum * __mmMinimum
)
return !1;
}
for (
let __mmIndex = 0;
__mmIndex < __mmSpinningWindmillReservations.length;
__mmIndex++
) {
const __mmReservation = __mmSpinningWindmillReservations[__mmIndex],
__mmMinimum = __mmScale + __mmReservation.scale;
if (
(__mmReservation.x - __mmX) ** 2 +
(__mmReservation.y - __mmY) ** 2 <
__mmMinimum * __mmMinimum
)
return !1;
}
return !0;
}
function __mmSpinningWindmillCandidate(__mmItem) {
if (!v || !v.alive) return null;
const __mmData = b.list[__mmItem],
__mmScale = Number(__mmData.scale) || 45,
__mmDistance =
(Number(v.scale) || 35) +
__mmScale +
(Number(__mmData.placeOffset) || 0),
__mmStep = Math.PI / 24,
__mmStart = __mmSpinningWindmillAngle;
// Search center-out from the rotating phase so a nearby obstacle moves the
// mill to the closest legal slot instead of stopping the spinner entirely.
for (let __mmOffset = 0; __mmOffset < 48; __mmOffset++) {
const __mmRingStep = Math.ceil(__mmOffset / 2),
__mmSign = __mmOffset === 0 || __mmOffset % 2 ? 1 : -1,
__mmAngle = __mmStart + __mmRingStep * __mmStep * __mmSign,
__mmX = v.x + Math.cos(__mmAngle) * __mmDistance,
__mmY = v.y + Math.sin(__mmAngle) * __mmDistance;
if (!__mmSpinningWindmillPositionClear(__mmX, __mmY, __mmScale))
continue;
return {
item: __mmItem,
angle: __mmAngle,
x: __mmX,
y: __mmY,
scale: __mmScale,
nextAngle: __mmAngle + __mmStep,
};
}
return null;
}
function __mmUpdateSpinningWindmills() {
const __mmNow = Date.now();
__mmCleanSpinningWindmillReservations(__mmNow);
if (
!__mmSpinningWindmillsEnabled ||
!v ||
!v.alive ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmInsta.isActive() ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmWindmillHeld ||
__mmFoodSpamTimer ||
__mmAutoHealWasHealing ||
!__mmActionAvailable("spinningWindmills") ||
__mmNow - __mmSpinningWindmillLastAt < __mmServerTickMs()
)
return;
const __mmItem = __mmWindmillItem();
if (__mmItem == null || !__mmSpinningWindmillCapacity(__mmItem)) return;
const __mmCandidate = __mmSpinningWindmillCandidate(__mmItem);
if (!__mmCandidate) {
__mmSpinningWindmillAngle += Math.PI / 24;
return;
}
if (!__mmActionClaim("spinningWindmills", "rotating mill placement")) return;
const __mmTool = __mmSelectedTool();
try {
(je(__mmCandidate.item),
O.send("F", 1, __mmCandidate.angle),
O.send("F", 0, __mmCandidate.angle),
__mmRestoreTool(__mmTool),
(__mmSpinningWindmillAngle = __mmCandidate.nextAngle),
(__mmSpinningWindmillLastAt = __mmNow),
__mmSpinningWindmillReservations.push({
x: __mmCandidate.x,
y: __mmCandidate.y,
scale: __mmCandidate.scale,
expiresAt: __mmNow + 650,
}),
__mmScheduleMouseAimReturn());
} finally {
__mmActionRelease("spinningWindmills", "mill sent");
}
}
function __mmStartSpinningWindmills() {
if (!__mmSpinningWindmillsEnabled || __mmSpinningWindmillTimer) return;
((__mmSpinningWindmillAngle = Ci() + Math.PI),
(__mmSpinningWindmillTimer = setInterval(
__mmUpdateSpinningWindmills,
10,
)));
}
function __mmStopSpinningWindmills() {
(__mmSpinningWindmillTimer && clearInterval(__mmSpinningWindmillTimer),
(__mmSpinningWindmillTimer = 0),
(__mmSpinningWindmillLastAt = 0),
(__mmSpinningWindmillReservations.length = 0),
__mmActionRelease("spinningWindmills", "spinner disabled"));
}
function __mmStopWindmillRow() {
const __mmWeapon = __mmWindmillRowWeapon;
((__mmWindmillRowTimer && clearTimeout(__mmWindmillRowTimer),
(__mmWindmillRowTimer = 0),
(__mmWindmillRowWeapon = null),
__mmWeapon != null && __mmRestoreWeapon(__mmWeapon)));
}
function __mmStartWindmillHold() {
if (__mmWindmillHeld) return;
((__mmWindmillHeld = !0),
__mmPlaceWindmillRow(),
(__mmWindmillHoldTimer = setInterval(
__mmPlaceWindmillRow,
__mmServerTickMs(),
)));
}
function __mmStopWindmillHold() {
((__mmWindmillHeld = !1),
__mmWindmillHoldTimer && clearInterval(__mmWindmillHoldTimer),
(__mmWindmillHoldTimer = 0),
__mmStopWindmillRow());
}
function __mmPlaceWindmillRow() {
if (__mmWindmillRowTimer || !v || !v.alive) return;
const __mmWindmill = __mmWindmillItem();
if (__mmWindmill == null || !__mmCanUseBuildItem(__mmWindmill)) return;
const __mmWeapon = __mmSelectedWeapon(),
__mmBehind = Ci() + Math.PI,
__mmData = b.list[__mmWindmill],
__mmPlaceDistance =
(v.scale || 35) +
(__mmData.scale || 45) +
(Number(__mmData.placeOffset) || 0),
// The angular separation is derived from the mill diameter and its true
// placement distance, so the three mills touch side-to-side instead of
// overlapping behind the player.
__mmSideOffset =
2 *
Math.asin(
Math.min(
0.999,
(2 * (__mmData.scale || 45)) / (2 * __mmPlaceDistance),
),
),
__mmCount = Math.min(3, __mmMaxBuildCount(__mmWindmill)),
__mmAngles =
__mmCount === 1
? [__mmBehind]
: __mmCount === 2
? [__mmBehind - __mmSideOffset / 2, __mmBehind + __mmSideOffset / 2]
: [__mmBehind, __mmBehind - __mmSideOffset, __mmBehind + __mmSideOffset];
if (!__mmCount) return;
__mmWindmillRowWeapon = __mmWeapon;
je(__mmWindmill);
for (let __mmIndex = 0; __mmIndex < __mmAngles.length; __mmIndex++)
(O.send("F", 1, __mmAngles[__mmIndex]),
O.send("F", 0, __mmAngles[__mmIndex]));
// Keep a one-tick key-repeat guard, but do not make the row wait three ticks.
__mmWindmillRowTimer = setTimeout(__mmStopWindmillRow, __mmServerTickMs());
}
function __mmNearestLockingTrap() {
if (!v || !v.alive) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmSeen = new Set(),
__mmConsider = function (__mmObject) {
if (
!__mmObject ||
__mmSeen.has(__mmObject) ||
!__mmObject.active ||
!__mmObject.trap ||
__mmFriendlyStructure(__mmObject)
)
return;
__mmSeen.add(__mmObject);
const __mmRange =
(Number(v.scale) || 35) +
(Number(__mmObject.scale) || 45) +
__mmTrapCollisionPadding,
__mmDistance =
(__mmObject.x - v.x) ** 2 + (__mmObject.y - v.y) ** 2;
if (__mmDistance > __mmRange * __mmRange) return;
__mmDistance < __mmClosestDistance &&
((__mmClosestDistance = __mmDistance), (__mmClosest = __mmObject));
};
try {
const __mmGrids = X.getGridArrays(v.x, v.y, Math.max(180, v.scale * 5));
for (let __mmGridIndex = 0; __mmGridIndex < __mmGrids.length; __mmGridIndex++)
for (
let __mmItemIndex = 0;
__mmItemIndex < __mmGrids[__mmGridIndex].length;
__mmItemIndex++
)
__mmConsider(__mmGrids[__mmGridIndex][__mmItemIndex]);
} catch (__mmTrapGridError) {}
// Item-grid visibility can lag a trap collision by one update. Scan the
// render object list too, so the escape routine starts on the first lock tick.
if (typeof ge !== "undefined" && Array.isArray(ge))
for (let __mmItemIndex = 0; __mmItemIndex < ge.length; __mmItemIndex++)
__mmConsider(ge[__mmItemIndex]);
return __mmClosest;
}
function __mmFriendlyTrapForPlayer(__mmPlayer) {
if (!v || !v.alive || !__mmPlayer || !Array.isArray(ge)) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < ge.length; __mmIndex++) {
const __mmTrap = ge[__mmIndex];
if (
!__mmTrap ||
!__mmTrap.active ||
!__mmTrap.trap ||
!__mmFriendlyStructure(__mmTrap)
)
continue;
const __mmTrapScale =
typeof __mmTrap.getScale === "function"
? Number(__mmTrap.getScale()) || Number(__mmTrap.scale) || 50
: Number(__mmTrap.scale) || 50,
__mmLockRange =
(Number(__mmPlayer.scale) || 35) +
Math.max(__mmTrapScale, Number(__mmTrap.scale) || 0) +
12,
__mmDistance = Math.hypot(
Number(__mmPlayer.x) - Number(__mmTrap.x),
Number(__mmPlayer.y) - Number(__mmTrap.y),
),
__mmCaught =
__mmDistance <= __mmLockRange &&
(!!__mmPlayer.lockMove || __mmDistance <= __mmLockRange - 5);
if (__mmCaught && __mmDistance < __mmClosestDistance)
((__mmClosest = __mmTrap), (__mmClosestDistance = __mmDistance));
}
return __mmClosest;
}
function __mmUpdateFriendlyTrapChat() {
const __mmNow = Date.now(),
__mmSeen = Object.create(null);
let __mmFriendIncident = null,
__mmEnemyIncident = null;
if (v && v.alive && Array.isArray(E)) {
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
__mmPlayer === v ||
String(__mmPlayer.sid) === String(v.sid) ||
(Number.isFinite(Number(__mmPlayer.health)) &&
Number(__mmPlayer.health) <= 0) ||
Math.hypot(
Number(__mmPlayer.x) - Number(v.x),
Number(__mmPlayer.y) - Number(v.y),
) > 1500
)
continue;
const __mmFriend = __mmIsFriendPlayer(__mmPlayer),
__mmFriendKey = __mmNormalizeFriendName(__mmPlayer.name),
__mmBetrayed =
!!__mmFriendKey && __mmFriendEnemies.has(__mmFriendKey),
__mmEnemy = !__mmFriend &&
(__mmBetrayed || !__mmSameTeam(__mmPlayer));
if (!__mmFriend && !__mmEnemy) continue;
const __mmTrap = __mmFriendlyTrapForPlayer(__mmPlayer);
if (!__mmTrap) continue;
const __mmKind = __mmFriend ? "friend" : "enemy",
__mmKey = __mmKind + ":" + String(__mmPlayer.sid),
__mmIncident =
__mmFriendlyTrapChatIncidents[__mmKey] ||
(__mmFriendlyTrapChatIncidents[__mmKey] = {
announced: !1,
lastSeen: __mmNow,
});
((__mmIncident.lastSeen = __mmNow), (__mmSeen[__mmKey] = !0));
if (!__mmIncident.announced) {
const __mmCandidate = {
key: __mmKey,
player: __mmPlayer,
trap: __mmTrap,
};
__mmFriend
? (__mmFriendIncident || (__mmFriendIncident = __mmCandidate))
: (__mmEnemyIncident || (__mmEnemyIncident = __mmCandidate));
}
}
}
for (const __mmKey in __mmFriendlyTrapChatIncidents) {
const __mmIncident = __mmFriendlyTrapChatIncidents[__mmKey];
if (!__mmSeen[__mmKey] && __mmNow - __mmIncident.lastSeen > 450)
delete __mmFriendlyTrapChatIncidents[__mmKey];
}
const __mmCandidate = __mmFriendIncident || __mmEnemyIncident,
__mmCooldown = Math.max(
750,
(Number(y && y.chatCooldown) || 500) + 150,
);
if (
!__mmCandidate ||
__mmNow - __mmFriendlyTrapChatLastAt < __mmCooldown
)
return;
const __mmIncident = __mmFriendlyTrapChatIncidents[__mmCandidate.key];
if (!__mmIncident || __mmIncident.announced) return;
((__mmIncident.announced = !0),
(__mmFriendlyTrapChatLastAt = __mmNow),
__mmSendChat(
__mmCandidate.key.startsWith("friend:")
? "Uh oh! let me free you!"
: "Ha, I have you in my trap!",
));
}
function __mmStartFriendlyTrapChat() {
__mmFriendlyTrapChatTimer ||
((__mmFriendlyTrapChatTimer = setInterval(
__mmUpdateFriendlyTrapChat,
__mmFastCheckMs(),
)),
__mmUpdateFriendlyTrapChat());
}
function __mmTrapAngle() {
const __mmTrap = __mmNearestLockingTrap();
return __mmTrap == null
? null
: Math.round(100 * Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x)) / 100;
}
function __mmTrapBuildKey(__mmTrap) {
if (!__mmTrap) return null;
const __mmId =
__mmTrap.sid != null
? __mmTrap.sid
: __mmTrap.id != null
? __mmTrap.id
: null;
return __mmId != null
? "id:" + __mmId
: "pos:" + Math.round(__mmTrap.x) + ":" + Math.round(__mmTrap.y);
}
function __mmAffordableBuildItem(__mmMatches) {
if (!v || !v.items || !b || !b.list) return null;
for (let __mmIndex = 0; __mmIndex < v.items.length; __mmIndex++) {
const __mmItem = v.items[__mmIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
__mmMatches(__mmData, __mmItem) &&
__mmCanUseBuildItem(__mmItem)
)
return __mmItem;
}
return null;
}
function __mmTrapEmergencyFallbackItem() {
const __mmTrap = __mmAffordableBuildItem((__mmData) => !!__mmData.trap);
if (__mmTrap != null) return __mmTrap;
const __mmWindmill = __mmAffordableBuildItem(
(__mmData) =>
typeof __mmData.name === "string" && __mmData.name.indexOf("mill") !== -1,
);
if (__mmWindmill != null) return __mmWindmill;
const __mmWall = __mmAffordableBuildItem(
(__mmData) =>
typeof __mmData.name === "string" && __mmData.name.indexOf("wall") !== -1,
);
if (__mmWall != null) return __mmWall;
const __mmUtilityNames = [
"turret",
"teleporter",
"boost pad",
"platform",
"healing pad",
"blocker",
"spawn pad",
"sapling",
"mine",
];
for (
let __mmNameIndex = 0;
__mmNameIndex < __mmUtilityNames.length;
__mmNameIndex++
) {
const __mmName = __mmUtilityNames[__mmNameIndex],
__mmItem = __mmAffordableBuildItem(
(__mmData) => __mmData.name === __mmName,
);
if (__mmItem != null) return __mmItem;
}
return null;
}
function __mmTrapEmergencyBuildPlan(__mmTrap) {
const __mmBehind = Ci() + Math.PI,
__mmSpike = __mmSpikeItem(),
__mmSpikeCount = __mmHoldingMcGrabby()
? 0
: Math.min(2, __mmMaxBuildCount(__mmSpike));
if (__mmSpike != null && __mmSpikeCount > 0)
return __mmSpikeCount === 1
? [{ item: __mmSpike, angle: __mmBehind }]
: [
{ item: __mmSpike, angle: __mmBehind - 0.42 },
{ item: __mmSpike, angle: __mmBehind + 0.42 },
];
const __mmFallback = __mmTrapEmergencyFallbackItem();
return __mmFallback == null
? []
: [{ item: __mmFallback, angle: __mmBehind }];
}
function __mmStopTrapBuildEscape(__mmClearAttempt = !0) {
const __mmWeapon = __mmTrapAttackActive
? __mmTrapAttackHeldWeapon || __mmTrapBreakWeapon(__mmCurrentNearbyTrap())
: __mmTrapBuildWeapon;
((__mmTrapBuildTimer && clearTimeout(__mmTrapBuildTimer),
(__mmTrapBuildTimer = 0),
(__mmTrapBuildWeapon = null),
__mmClearAttempt && (__mmTrapBuildAttemptKey = null),
__mmWeapon != null && __mmRestoreWeapon(__mmWeapon)));
}
function __mmStartTrapBuildEscape(__mmTrap) {
if (!v || !v.alive || !__mmIsTrapped() || __mmTrapBuildTimer) return;
const __mmTrapKey = __mmTrap ? __mmTrapBuildKey(__mmTrap) : "locked";
if (__mmTrapKey == null || __mmTrapBuildAttemptKey === __mmTrapKey) return;
// Mark before sending. If a collision or packet rejection prevents placement,
// this exact trap is not retried until it is gone or a new trap catches us.
__mmTrapBuildAttemptKey = __mmTrapKey;
const __mmPlan = __mmTrapEmergencyBuildPlan(__mmTrap);
if (!__mmPlan.length) return;
let __mmIndex = 0;
__mmTrapBuildWeapon = __mmSelectedWeapon();
const __mmPlaceNext = function () {
const __mmCurrentTrap = __mmNearestLockingTrap();
if (
!v ||
!v.alive ||
!__mmIsTrapped() ||
(__mmTrap && __mmTrapBuildKey(__mmCurrentTrap) !== __mmTrapKey)
)
return void __mmStopTrapBuildEscape();
const __mmEntry = __mmPlan[__mmIndex++];
if (!__mmEntry || !__mmCanUseBuildItem(__mmEntry.item))
return void __mmStopTrapBuildEscape(!1);
(je(__mmEntry.item),
O.send("F", 1, __mmEntry.angle),
O.send("F", 0, __mmEntry.angle),
__mmResumeHeldAttack());
if (__mmIndex < __mmPlan.length) {
__mmTrapBuildTimer = setTimeout(__mmPlaceNext, __mmServerTickMs());
return;
}
__mmStopTrapBuildEscape(!1);
};
__mmPlaceNext();
}
function __mmEquipTankForTrap() {
if (!v || !v.alive || !v.skins || !v.skins[40] || __mmRightClickHat != null)
return;
(__mmTrapHat == null && (__mmTrapHat = v.skinIndex),
v.skinIndex !== 40 && __mmEquipHatNow(40, !0));
}
function __mmEquipTrapDowntimeHat() {
if (!v || !v.alive || __mmTrapHat == null || __mmRightClickHat != null)
return;
const __mmHat = v.skins && v.skins[6] ? 6 : __mmTrapHat;
__mmEquipHatNow(__mmHat, !0);
}
function __mmUpdateTrapEscapeGear(__mmWeapon) {
if (!__mmTrapAttackActive || !v || !v.alive || __mmWeapon == null) return;
__mmTrapHat == null && (__mmTrapHat = v.skinIndex);
if (!v.skins || !v.skins[40] || __mmRightClickHat != null) return;
const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]),
__mmTankWindow =
Date.now() < __mmTrapTankHoldUntil ||
!Number.isFinite(__mmReload) ||
__mmReload <= __mmServerTickMs();
__mmTankWindow
? __mmEquipTankForTrap()
: __mmEquipTrapDowntimeHat();
}
function __mmObserveTrapEscapeSwing(__mmPlayerSid, __mmWeapon) {
const __mmResolvedWeapon =
__mmWeapon == null ? Number(v && v.weaponIndex) : Number(__mmWeapon);
if (
!v ||
!v.alive ||
!__mmTrapAttackActive ||
String(__mmPlayerSid) !== String(v.sid) ||
(__mmTrapAttackHeldWeapon != null &&
__mmResolvedWeapon !== Number(__mmTrapAttackHeldWeapon))
)
return;
((__mmTrapTankHoldUntil = Date.now() + __mmGearHoldMs()),
__mmEquipTankForTrap());
}
function __mmCancelTrapHatRestoreTimer() {
(__mmTrapHatRestoreTimer && clearTimeout(__mmTrapHatRestoreTimer),
(__mmTrapHatRestoreTimer = 0));
}
function __mmScheduleTrapHatRestore() {
__mmCancelTrapHatRestoreTimer();
__mmTrapHatRestoreTimer = setTimeout(function () {
((__mmTrapHatRestoreTimer = 0), __mmRestoreTrapHat());
}, __mmServerTickMs());
}
function __mmRestoreTrapHat() {
__mmCancelTrapHatRestoreTimer();
if (__mmTrapHat == null) return;
if (!v || !v.alive) {
((__mmTrapHat = null), (__mmTrapHatRestoreAttempts = 0));
return;
}
if (
__mmTrapAttackActive ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmRightClickHat != null ||
__mmInsta.isActive() ||
__mmInstaSyncPending ||
__mmInstaSyncFiring ||
__mmBoostBreakHeld ||
(__mmActionOwner !== "idle" && __mmActionOwner !== "trapEscape")
)
return void __mmScheduleTrapHatRestore();
const __mmHat = __mmTrapHat,
__mmPendingConflict = !!(
__mmPendingHat != null &&
__mmPendingHat !== __mmHat &&
Date.now() - __mmPendingHatAt < __mmGearHoldMs()
);
if (v.skinIndex === __mmHat && !__mmPendingConflict) {
((__mmPendingHat === __mmHat &&
((__mmPendingHat = null), (__mmPendingHatAt = 0))),
(__mmTrapHat = null),
(__mmTrapHatRestoreAttempts = 0));
return;
}
(__mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat, !0),
(__mmTrapHatRestoreAttempts += 1));
if (__mmTrapHatRestoreAttempts < 6)
return void __mmScheduleTrapHatRestore();
((__mmTrapHat = null), (__mmTrapHatRestoreAttempts = 0));
}
function __mmStopTrapAttack() {
const __mmRestore = __mmActionMayRestore("trapEscape"),
__mmReleaseAngle = Number.isFinite(__mmTrapAimAngle)
? __mmTrapAimAngle
: Ci();
(__mmStopTrapBuildEscape(),
__mmTrapAttackHeld && O.send("F", 0, __mmReleaseAngle),
(__mmTrapAttackHeld = !1),
(__mmTrapAttackHeldWeapon = null),
(__mmTrapTankHoldUntil = 0),
(__mmTrapWeaponSelectAt = 0),
__mmTrapAttackActive &&
((__mmTrapAttackActive = !1),
__mmRestore && __mmRestoreWeapon(__mmTrapWeapon),
(__mmTrapWeapon = null)),
(__mmTrapAimAngle = null),
__mmRestoreTrapHat(),
__mmActionRelease("trapEscape", "trap clear"));
}
function __mmPauseSoldierForBreaking() {
__mmCancelSoldierRestore();
if (__mmSoldierPreviousHat == null || !v || !v.alive || v.skinIndex !== 6)
return;
const __mmPreviousHat = __mmSoldierPreviousHat;
((__mmSoldierPreviousHat = null),
__mmCanEquipHat(__mmPreviousHat) && __mmEquipHatNow(__mmPreviousHat));
}
function __mmTrapWeaponRange(__mmWeapon, __mmTrap) {
const __mmData = b && b.weapons && b.weapons[__mmWeapon];
if (!__mmData || __mmData.projectile != null) return 0;
return (
(Number(__mmData.range) || 0) +
(v.scale || 35) +
(__mmTrap.scale || 35) +
8
);
}
function __mmTrapBreakWeapon(__mmTrap) {
if (!v || !v.weapons || !__mmTrap) return null;
const __mmCandidates = [
__mmGreatHammer,
v.weapons[0],
v.weapons[1],
];
const __mmDistance = Math.hypot(__mmTrap.x - v.x, __mmTrap.y - v.y);
for (
let __mmIndex = 0;
__mmIndex < __mmCandidates.length;
__mmIndex += 1
) {
const __mmWeapon = __mmCandidates[__mmIndex];
if (
__mmWeapon == null ||
!v.weapons.includes(__mmWeapon) ||
__mmDistance > __mmTrapWeaponRange(__mmWeapon, __mmTrap)
)
continue;
return __mmWeapon;
}
return null;
}
function __mmBreakTrap() {
if (
!__mmTrapEscapeEnabled ||
!v ||
!v.alive ||
!__mmIsTrapped()
)
return void __mmStopTrapAttack();
// The insta owns the same weapon, hat, and aim channels for only a few
// ticks. Leave the trap interval alive but idle until cleanup hands control
// back, instead of cancelling the combo on its next fast scan.
if (__mmInsta.isActive()) return;
// Being genuinely trapped is still a safety priority; an idle trap-escape
// interval must not otherwise terminate every R insta burst.
if (!__mmActionCanPreempt("trapEscape")) return;
const __mmTrapRestoreHat =
__mmPrimaryClickHat != null
? __mmPrimaryClickHat
: __mmRightClickHat != null
? __mmRightClickHat
: __mmSoldierPreviousHat != null
? __mmSoldierPreviousHat
: v.skinIndex;
if (__mmInsta.isActive()) __mmInsta.cancel("trap-escape");
(__mmInstaSyncPending || __mmInstaSyncFiring) && __mmStopInstaSync();
__mmBoostBreakHeld && __mmStopBoostBreak();
__mmActionOwner === "shieldDefense" && __mmStopShieldDefense("trap priority");
__mmPrimaryHeld && __mmStopPrimaryInput();
(__mmPrimaryClickHat != null || __mmPrimaryClickTail != null) &&
__mmForceRestoreBullForPrimary();
__mmSecondaryHeld && __mmStopSecondary();
__mmRightClickHat != null && __mmForceRestoreRightClickHat();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (__mmActionOwner === "antiInsta") {
(__mmAntiInstaActionTimer && clearTimeout(__mmAntiInstaActionTimer),
(__mmAntiInstaActionTimer = 0),
__mmActionRelease("antiInsta", "trap priority"));
}
if (!__mmActionClaim("trapEscape", "locked pit trap")) return;
__mmAutoHeal(!0);
const __mmTrap = __mmCurrentNearbyTrap();
if (__mmTrap == null)
return void __mmStartTrapBuildEscape(null);
const __mmAngle = Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x);
(__mmTrapAttackActive ||
(__mmCancelTrapHatRestoreTimer(),
(__mmTrapHatRestoreAttempts = 0),
__mmPauseSoldierForBreaking(),
(__mmTrapAttackActive = !0),
(__mmTrapWeapon = __mmSelectedWeapon()),
(__mmTrapHat == null && (__mmTrapHat = __mmTrapRestoreHat))));
// Lock the normal client aim source onto the trap. Cl reads Ci every render,
// so this turns the player toward the structure immediately and keeps every
// break swing pointed at it until the trap is gone.
(__mmTrapAimAngle = __mmAngle,
__mmStartTrapBuildEscape(__mmTrap));
const __mmWeapon = __mmTrapBreakWeapon(__mmTrap);
if (__mmWeapon == null) return;
__mmUpdateTrapEscapeGear(__mmWeapon);
if (
!__mmTrapAttackHeld ||
__mmTrapAttackHeldWeapon !== __mmWeapon
) {
(__mmTrapAttackHeld && O.send("F", 0, __mmAngle),
je(__mmWeapon, !0),
O.send("D", __mmAngle),
O.send("F", 1, __mmAngle),
(__mmTrapAttackHeld = !0),
(__mmTrapAttackHeldWeapon = __mmWeapon),
(__mmTrapWeaponSelectAt = Date.now()));
} else if (
(Number(v.buildIndex) >= 0 || Number(v.weaponIndex) !== Number(__mmWeapon)) &&
Date.now() - __mmTrapWeaponSelectAt >= 25
)
((__mmTrapWeaponSelectAt = Date.now()), je(__mmWeapon, !0));
}
function __mmStartTrapEscape() {
__mmTrapAttackTimer ||
(__mmTrapAttackTimer = setInterval(__mmBreakTrap, __mmFastCheckMs()));
}
function __mmWithinTrapAlertRange(__mmTrap) {
if (!v || !__mmTrap) return !1;
const __mmRange = Math.max(
0,
(Number(v.scale) || 35) +
(Number(__mmTrap.scale) || 45) +
__mmTrapCollisionPadding -
__mmTrapAlertRangeReduction,
),
__mmDistance = (__mmTrap.x - v.x) ** 2 + (__mmTrap.y - v.y) ** 2;
return Number.isFinite(__mmDistance) && __mmDistance <= __mmRange ** 2;
}
function __mmUpdateTrapAlert() {
const __mmNow = Date.now(),
__mmNearbyTrap = v && v.alive ? __mmCurrentNearbyTrap() : null;
// The movement lock can arrive a tick late. Check the actual pit-trap collision
// too, using a slightly tighter alert radius to avoid premature warnings.
const __mmIncident = !!(
v &&
v.alive &&
(v.lockMove || __mmWithinTrapAlertRange(__mmNearbyTrap))
);
if (__mmIncident) {
__mmTrapAlertUntil = __mmNow + 400;
if (!__mmTrapChatIncidentActive) {
(__mmTrapChatIncidentActive = !0,
__mmSendChat("Oh no! A trap!"));
}
} else if (__mmNow >= __mmTrapAlertUntil) {
__mmTrapChatIncidentActive = !1;
}
const __mmTrapped = !!(v && v.alive && (__mmIncident || __mmNow < __mmTrapAlertUntil));
let __mmAlert = document.getElementById("kitty-klient-trap-alert");
if (!__mmAlert && !__mmTrapped) return;
if (!__mmAlert) {
if (!document.body) return;
((__mmAlert = document.createElement("div")),
(__mmAlert.id = "kitty-klient-trap-alert"),
(__mmAlert.setAttribute("role", "status")),
(__mmAlert.setAttribute("aria-live", "assertive")),
(__mmAlert.style.cssText =
"position:fixed;top:18%;left:50%;z-index:2147483647;transform:translate(-50%,-8px);padding:7px 11px;border:1px solid #ffb4b4;border-radius:7px;background:rgba(127,20,28,.92);color:#fff;font:700 14px Arial,sans-serif;letter-spacing:.01em;box-shadow:0 5px 18px rgba(0,0,0,.36);pointer-events:none;opacity:0;transition:opacity .12s ease,transform .12s ease;"),
document.body.appendChild(__mmAlert));
}
(__mmAlert.textContent = "Oh no! A trap!"),
(__mmAlert.style.opacity = __mmTrapped ? "1" : "0"),
(__mmAlert.style.transform = __mmTrapped
? "translate(-50%,0)"
: "translate(-50%,-8px)");
}
function __mmStartTrapAlert() {
__mmTrapAlertTimer ||
(__mmTrapAlertTimer = setInterval(__mmUpdateTrapAlert, __mmFastCheckMs()));
}
function __mmStopTrapEscape() {
(__mmTrapAttackTimer &&
(clearInterval(__mmTrapAttackTimer), (__mmTrapAttackTimer = 0)),
__mmStopTrapAttack());
}
function __mmCanAutoSoldier() {
return (
__mmSoldierAutoEnabled &&
__mmActionAvailable("soldierGear") &&
v &&
v.alive &&
v.skinIndex !== 40 &&
v.skins &&
v.skins[6] &&
!__mmSyncFollowerEnabled &&
!__mmInsta.isActive() &&
!__mmMovementGearActive() &&
!__mmPlayerMoving() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
__mmPrimaryClickHat == null &&
__mmRightClickHat == null
);
}
function __mmEnemyWithinSoldierRange() {
if (!v || !v.alive) return !1;
if (__mmLiveStateFresh())
return __mmLiveState.nearestEnemyDistance <= __mmSoldierRange;
for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
const __mmPlayer = E[__mmPlayerIndex];
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
const __mmDx = __mmPlayer.x - v.x,
__mmDy = __mmPlayer.y - v.y;
if (
__mmDx * __mmDx + __mmDy * __mmDy <=
__mmSoldierRange * __mmSoldierRange
)
return !0;
}
return !1;
}
function __mmCancelSoldierRestore() {
__mmSoldierRestoreTimer &&
(clearTimeout(__mmSoldierRestoreTimer), (__mmSoldierRestoreTimer = 0));
}
function __mmEquipSoldier() {
if (!__mmCanAutoSoldier()) return;
__mmCancelSoldierRestore();
if (v.skinIndex !== 6) {
(__mmSoldierPreviousHat == null && (__mmSoldierPreviousHat = v.skinIndex),
__mmEquipHatNow(6));
}
}
function __mmRestoreSoldier() {
if (!__mmCanAutoSoldier() || __mmSoldierPreviousHat == null) return;
const __mmPreviousHat = __mmSoldierPreviousHat;
__mmSoldierPreviousHat = null;
v.skinIndex === 6 &&
__mmPreviousHat !== 6 &&
__mmCanEquipHat(__mmPreviousHat) &&
__mmEquipHatNow(__mmPreviousHat);
}
function __mmUpdateSoldier() {
__mmCanAutoSoldier() && __mmEquipSoldier();
}
function __mmStartSoldierAuto() {
__mmSoldierAutoTimer ||
(__mmSoldierAutoTimer = setInterval(
__mmUpdateSoldier,
__mmFastCheckMs(),
));
}
function __mmTurretGearCanFire(__mmPlayer) {
return __mmPlayer.skinIndex === __mmTurretGear;
}
function __mmAiEnemySnapshot(__mmPlayer) {
const __mmDx = __mmPlayer.x - v.x,
__mmDy = __mmPlayer.y - v.y;
return {
distance: Math.round(Math.sqrt(__mmDx * __mmDx + __mmDy * __mmDy)),
health: Number(__mmPlayer.health) || 0,
maxHealth: Number(__mmPlayer.maxHealth) || 0,
weapon: Number(__mmPlayer.weaponIndex) || 0,
hat: Number(__mmPlayer.skinIndex) || 0,
tail: Number(__mmPlayer.tailIndex) || 0,
turretGear: __mmPlayer.skinIndex === __mmTurretGear,
};
}
function __mmAiContext() {
if (!v) return { available: !1 };
const __mmEnemies = [];
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid ||
!__mmIsEnemyPlayer(__mmPlayer)
)
continue;
__mmEnemies.push(__mmAiEnemySnapshot(__mmPlayer));
}
__mmEnemies.sort(function (__mmFirst, __mmSecond) {
return __mmFirst.distance - __mmSecond.distance;
});
const __mmAngle = __mmTrapAngle();
return {
available: !0,
modVersion: "3.15.0",
player: {
alive: !!v.alive,
health: Number(v.health) || 0,
maxHealth: Number(v.maxHealth) || 0,
gold: Number(v.points) || 0,
wood: Number(v.wood) || 0,
food: Number(v.food) || 0,
stone: Number(v.stone) || 0,
weapons: Array.isArray(v.weapons) ? v.weapons.slice(0, 4) : [],
selectedWeapon: __mmSelectedWeapon(),
hat: Number(v.skinIndex) || 0,
tail: Number(v.tailIndex) || 0,
trapped: __mmIsTrapped(),
foodItem: v.items ? v.items[0] : null,
},
nearbyEnemies: __mmEnemies.slice(0, 8),
nearbyTrap: { detected: __mmAngle != null, angle: __mmAngle },
features: { autoHeal: __mmAutoHealEnabled, soldierRange: __mmSoldierRange },
};
}
function __mmPublishAiContext() {
window.dispatchEvent(
new CustomEvent("MooMooAIContext", { detail: __mmAiContext() }),
);
}
window.addEventListener("MooMooAIRequestContext", __mmPublishAiContext);
function __mmCanUseShieldDefense() {
return (
__mmShieldDefenseEnabled &&
__mmActionAvailable("shieldDefense") &&
v &&
v.alive &&
v.weapons.includes(__mmShieldWeapon) &&
!__mmInsta.isActive() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive
);
}
function __mmStopShieldDefense(__mmReason) {
const __mmWeapon = __mmShieldDefenseWeapon,
__mmRestore = __mmActionMayRestore("shieldDefense");
((__mmShieldDefenseTimer && clearTimeout(__mmShieldDefenseTimer),
(__mmShieldDefenseTimer = 0),
(__mmShieldDefenseWeapon = null),
__mmRestore &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
__mmWeapon != null &&
__mmWeapon !== __mmShieldWeapon &&
__mmRestoreWeapon(__mmWeapon),
__mmActionRelease("shieldDefense", __mmReason || "defense complete")));
}
function __mmUseShieldDefense(__mmPlayer) {
if (!__mmCanUseShieldDefense()) return;
const __mmDistance = (__mmPlayer.x - v.x) ** 2 + (__mmPlayer.y - v.y) ** 2;
if (__mmDistance > __mmShieldDefenseRange * __mmShieldDefenseRange) return;
if (!__mmActionClaim("shieldDefense", "polearm defense")) return;
const __mmWeapon = __mmSelectedWeapon();
(__mmShieldDefenseTimer && clearTimeout(__mmShieldDefenseTimer),
__mmShieldDefenseWeapon == null && (__mmShieldDefenseWeapon = __mmWeapon),
je(__mmShieldWeapon, !0),
O.send("9", Math.atan2(__mmPlayer.y - v.y, __mmPlayer.x - v.x)),
(__mmShieldDefenseTimer = setTimeout(function () {
__mmStopShieldDefense("defense complete");
}, __mmShieldDefenseMs)));
}
function __mmHandleEnemyPolearmSwing(__mmPlayerSid, __mmWeapon) {
const __mmPlayer = Rt(__mmPlayerSid);
if (
!__mmIsEnemyPlayer(__mmPlayer) ||
(__mmPlayer.weaponIndex !== __mmPolearmWeapon &&
__mmWeapon !== __mmPolearmWeapon) ||
!__mmTurretGearCanFire(__mmPlayer)
)
return;
__mmUseShieldDefense(__mmPlayer);
}
window.addEventListener("blur", __mmStopFoodSpam);
window.addEventListener("blur", function () {
__mmStopBuildSpam();
});
function __mmIsGameClick(__mmEvent) {
return (
__mmEvent.target instanceof Element &&
__mmEvent.target.closest("#gameCanvas,#touch-controls-fullscreen")
);
}
function __mmPrimaryWeaponReady() {
if (!v || !v.alive || !v.weapons || v.weapons[0] == null) return !1;
const __mmReload = v.reloads && Number(v.reloads[v.weapons[0]]);
return (
Date.now() >= __mmPrimaryManualReadyAt &&
(!Number.isFinite(__mmReload) || __mmReload <= 0)
);
}
function __mmManualWeaponCooldown(__mmWeapon) {
const __mmData = b && b.weapons && b.weapons[__mmWeapon];
return Math.max(
__mmServerTickMs(),
Number(__mmData && __mmData.speed) || __mmServerTickMs(),
);
}
function __mmGearHoldMs() {
return __mmServerTickMs() * Math.max(
1,
Math.min(8, Math.round(Number(__mmGearHoldTicks) || 3)),
);
}
function __mmBullPrimaryAvailable() {
return !!(
__mmBullHelmetEnabled &&
v &&
v.alive &&
v.weapons &&
v.weapons[0] != null &&
v.weapons[0] !== 8 &&
v.skins &&
v.skins[7] &&
!__mmSecondaryHeld &&
__mmRightClickHat == null
);
}
function __mmPrimaryDamageTail() {
if (!v || !v.alive) return null;
if (v.tails && v.tails[__mmCorruptXWings]) {
__mmPrimaryClickTail == null && (__mmPrimaryClickTail = v.tailIndex);
return __mmCorruptXWings;
}
if (v.tailIndex === 11) {
__mmPrimaryClickTail == null && (__mmPrimaryClickTail = v.tailIndex);
return 0;
}
return null;
}
function __mmClearPrimaryGearTimer() {
(__mmPrimaryGearTimer && clearTimeout(__mmPrimaryGearTimer),
(__mmPrimaryGearTimer = 0));
}
function __mmSchedulePrimaryGear(__mmCallback, __mmAt) {
__mmClearPrimaryGearTimer();
__mmPrimaryGearTimer = setTimeout(function () {
(__mmPrimaryGearTimer = 0, __mmCallback());
}, Math.max(1, Number(__mmAt) - Date.now()));
}
function __mmEquipBullForPrimary() {
if (!__mmBullPrimaryAvailable() || !__mmPrimaryWeaponReady()) return;
(__mmClearPrimaryGearTimer(),
(__mmPrimaryGearStage = "bull"),
(__mmPrimarySoldierHoldUntil = 0),
__mmPrimaryClickHat == null && (__mmPrimaryClickHat = v.skinIndex),
// Force Bull past the Soldier packet from the previous cooldown window.
__mmEquipGearPair(7, __mmPrimaryDamageTail(), !0));
}
function __mmEquipPrimaryDowntimeHat() {
if (!v || !v.alive || __mmPrimaryClickHat == null) return;
const __mmNow = Date.now();
if (
__mmPrimaryGearStage === "bull" &&
__mmNow < __mmPrimaryBullHoldUntil
)
return void __mmSchedulePrimaryGear(
__mmEquipPrimaryDowntimeHat,
__mmPrimaryBullHoldUntil,
);
const __mmHat = v.skins && v.skins[6] ? 6 : __mmPrimaryClickHat;
(__mmClearPrimaryGearTimer(),
__mmPrimaryGearStage !== "soldier" &&
((__mmPrimaryGearStage = "soldier"),
(__mmPrimarySoldierHoldUntil = __mmNow + __mmGearHoldMs())),
// Soldier and the saved non-damage tail replace Bull/damage-tail as one
// pair; otherwise the tail visibly and functionally trails the hat phase.
__mmEquipGearPair(__mmHat, __mmPrimaryClickTail, !0));
!__mmPrimaryHeld &&
__mmSchedulePrimaryGear(
__mmRestoreBullForPrimary,
__mmPrimarySoldierHoldUntil,
);
}
function __mmRestoreBullForPrimary() {
if (__mmPrimaryHeld || __mmSecondaryHeld || __mmRightClickHat != null) return;
if (!v || !v.alive) {
(__mmClearPrimaryGearTimer(),
(__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
(__mmPrimaryGearStage = null),
(__mmPrimaryBullHoldUntil = 0),
(__mmPrimarySoldierHoldUntil = 0));
return;
}
const __mmNow = Date.now();
if (
__mmPrimaryGearStage === "bull" &&
__mmNow < __mmPrimaryBullHoldUntil
)
return void __mmSchedulePrimaryGear(
__mmEquipPrimaryDowntimeHat,
__mmPrimaryBullHoldUntil,
);
if (__mmPrimaryGearStage === "bull")
return void __mmEquipPrimaryDowntimeHat();
if (
__mmPrimaryGearStage === "soldier" &&
__mmNow < __mmPrimarySoldierHoldUntil
)
return void __mmSchedulePrimaryGear(
__mmRestoreBullForPrimary,
__mmPrimarySoldierHoldUntil,
);
const __mmHat = __mmPrimaryClickHat,
__mmTail = __mmPrimaryClickTail;
(__mmClearPrimaryGearTimer(),
(__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
(__mmPrimaryGearStage = null),
(__mmPrimaryBullHoldUntil = 0),
(__mmPrimarySoldierHoldUntil = 0),
// Override both still-pending damage-gear packets together. A quick release
// can arrive before either acknowledgement, so the restore must be paired.
__mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmForceRestoreBullForPrimary() {
if (__mmPrimaryClickHat == null && __mmPrimaryClickTail == null) return;
const __mmHat = __mmPrimaryClickHat,
__mmTail = __mmPrimaryClickTail;
(__mmClearPrimaryGearTimer(),
(__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
(__mmPrimaryGearStage = null),
(__mmPrimaryBullHoldUntil = 0),
(__mmPrimarySoldierHoldUntil = 0),
v && v.alive && __mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmFirePrimaryBullWeapon() {
__mmPrimaryBullArmTimer = 0;
const __mmWeapon = v && v.weapons ? v.weapons[0] : null;
if (!__mmPrimaryHeld || !__mmBullPrimaryAvailable() || __mmWeapon == null)
return (
(__mmPrimaryBullSwingPending = !1),
void (__mmPrimaryHeld
? __mmEquipPrimaryDowntimeHat()
: __mmRestoreBullForPrimary())
);
(je(__mmWeapon, !0),
__mmSendWeaponAttack(1),
__mmSendWeaponAttack(0),
(__mmPrimaryManualReadyAt =
Date.now() + __mmManualWeaponCooldown(__mmWeapon)),
(__mmPrimaryBullSwingPending = !1),
// Keep Bull through the configured post-swing window, then give Soldier
// its own minimum window before any restore or next Bull cycle.
(__mmPrimaryGearStage = "bull"),
(__mmPrimaryBullHoldUntil = Date.now() + __mmGearHoldMs()),
__mmEquipPrimaryDowntimeHat());
}
function __mmPulsePrimaryBullWeapon() {
if (!__mmPrimaryHeld || !__mmBullPrimaryAvailable()) return;
__mmPrimaryClickHat == null && (__mmPrimaryClickHat = v.skinIndex);
if (__mmPrimaryBullSwingPending) return;
if (
__mmPrimaryGearStage === "soldier" &&
Date.now() < __mmPrimarySoldierHoldUntil
)
return;
if (!__mmPrimaryWeaponReady()) return void __mmEquipPrimaryDowntimeHat();
__mmEquipBullForPrimary();
if (__mmPrimaryClickHat == null) return void __mmSendWeaponAttack(1);
(je(v.weapons[0], !0),
(__mmPrimaryBullSwingPending = !0),
(__mmPrimaryBullArmTimer = setTimeout(
__mmFirePrimaryBullWeapon,
__mmServerTickMs(),
)));
}
function __mmStartPrimaryInput() {
if (__mmPrimaryHeld || !v || !v.alive || v.weapons[0] == null) return !1;
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmActionClaim("manualAttack", "left click")) return !1;
((__mmPrimaryHeld = !0),
__mmStartHeldAttackPulse(),
__mmAtFullHealth() && __mmStopFoodSpam());
return !0;
}
function __mmStopPrimaryInput() {
((__mmPrimaryHeld = !1),
__mmPrimaryBullArmTimer &&
(clearTimeout(__mmPrimaryBullArmTimer), (__mmPrimaryBullArmTimer = 0)),
(__mmPrimaryBullSwingPending = !1),
__mmStopHeldAttackPulse(),
__mmSecondaryHeld && __mmPulseHeldAttack(),
__mmRestoreBullForPrimary(),
__mmRestoreTrapHat(),
!__mmSecondaryHeld && __mmActionRelease("manualAttack", "left click released"));
__mmUpdateWeaponRecharge();
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (!__mmIsGameClick(__mmEvent) || __mmEvent.button !== 0) return;
// Mouse modes are exclusive. Cancel every right-click state and its pending
// Tank timer before the new left-click becomes authoritative.
(__mmSecondaryHeld ||
__mmSecondaryTankArmTimer ||
__mmSecondaryTankSwingPending ||
__mmRightClickHat != null) &&
(__mmFinishSecondaryInput(), __mmForceRestoreRightClickHat());
// A real click always wins over the queued R burst; cancel first, then
// allow this existing input path to proceed normally.
__mmInsta.isActive() && __mmInsta.cancel("manual-primary");
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (__mmUpdateAutoInsta()) {
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
return;
}
if (!__mmStartPrimaryInput()) return;
(__mmEvent.preventDefault(),
__mmEvent.stopImmediatePropagation(),
null);
},
!0,
);
document.addEventListener(
"mouseup",
function (__mmEvent) {
if (__mmEvent.button !== 0 || !__mmPrimaryHeld) return;
(__mmEvent.preventDefault(),
__mmEvent.stopImmediatePropagation(),
__mmStopPrimaryInput());
},
!0,
);
function __mmSecondaryWeapon() {
return v && v.alive && v.weapons && v.weapons[1] != null
? v.weapons[1]
: null;
}
function __mmSecondaryWeaponReady() {
const __mmWeapon = __mmSecondaryWeapon();
if (__mmWeapon == null) return !1;
const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]);
return !Number.isFinite(__mmReload) || __mmReload <= 0;
}
function __mmRightClickWeapon() {
const __mmPrimary = v && v.alive && v.weapons ? v.weapons[0] : null,
__mmSecondary = __mmSecondaryWeapon(),
__mmData =
__mmSecondary == null ? null : b && b.weapons && b.weapons[__mmSecondary];
return __mmSecondary == null
? __mmPrimary
: __mmData && __mmData.projectile != null && __mmPrimary != null
? __mmPrimary
: __mmSecondary;
}
function __mmRightClickWeaponReady() {
const __mmWeapon = __mmRightClickWeapon();
return (
__mmWeapon != null &&
Date.now() >= __mmSecondaryManualReadyAt &&
__mmWeaponReady(__mmWeapon)
);
}
function __mmServerTickMs() {
return Math.max(
60,
Math.ceil(1e3 / Math.max(1, Number(y && y.serverUpdateRate) || 9)),
);
}
function __mmFastCheckMs() {
// State detection should react between server updates; action paths retain
// their separate server-tick rate limits before sending packets.
return Math.min(
Math.max(10, Number(__mmReactionMs) || 25),
__mmServerTickMs(),
);
}
function __mmEquipTankForSecondary() {
if (
!__mmTankRightClickEnabled ||
!v ||
!v.alive ||
!__mmRightClickWeaponReady() ||
!v.skins ||
!v.skins[40]
)
return;
(__mmSecondaryGearTimer && clearTimeout(__mmSecondaryGearTimer),
(__mmSecondaryGearTimer = 0),
(__mmSecondaryGearStage = "tank"),
(__mmSecondarySoldierHoldUntil = 0),
__mmRightClickHat == null && (__mmRightClickHat = v.skinIndex),
// Override the Soldier cooldown packet before arming the Tank swing.
__mmEquipHatNow(40, !0));
}
function __mmClearSecondaryGearTimer() {
(__mmSecondaryGearTimer && clearTimeout(__mmSecondaryGearTimer),
(__mmSecondaryGearTimer = 0));
}
function __mmScheduleSecondaryGear(__mmCallback, __mmAt) {
__mmClearSecondaryGearTimer();
__mmSecondaryGearTimer = setTimeout(function () {
((__mmSecondaryGearTimer = 0), __mmCallback());
}, Math.max(1, Number(__mmAt) - Date.now()));
}
function __mmEquipSecondaryDowntimeHat() {
if (!v || !v.alive || __mmRightClickHat == null) return;
const __mmNow = Date.now();
if (
__mmSecondaryGearStage === "tank" &&
__mmNow < __mmSecondaryTankHoldUntil
)
return void __mmScheduleSecondaryGear(
__mmEquipSecondaryDowntimeHat,
__mmSecondaryTankHoldUntil,
);
const __mmHat = v.skins && v.skins[6] ? 6 : __mmRightClickHat;
(__mmClearSecondaryGearTimer(),
__mmSecondaryGearStage !== "soldier" &&
((__mmSecondaryGearStage = "soldier"),
(__mmSecondarySoldierHoldUntil = __mmNow + __mmGearHoldMs())),
__mmEquipHatNow(__mmHat, !0));
!__mmSecondaryHeld &&
__mmScheduleSecondaryGear(
__mmRestoreRightClickHat,
__mmSecondarySoldierHoldUntil,
);
}
function __mmRestoreRightClickHat() {
if (__mmRightClickHat == null) return void __mmClearSecondaryGearTimer();
if (__mmSecondaryHeld) return;
if (!v || !v.alive) {
(__mmClearSecondaryGearTimer(),
(__mmRightClickHat = null),
(__mmSecondaryGearStage = null),
(__mmSecondaryTankHoldUntil = 0),
(__mmSecondarySoldierHoldUntil = 0));
return;
}
const __mmNow = Date.now();
if (
__mmSecondaryGearStage === "tank" &&
__mmNow < __mmSecondaryTankHoldUntil
)
return void __mmScheduleSecondaryGear(
__mmEquipSecondaryDowntimeHat,
__mmSecondaryTankHoldUntil,
);
if (__mmSecondaryGearStage === "tank")
return void __mmEquipSecondaryDowntimeHat();
if (
__mmSecondaryGearStage === "soldier" &&
__mmNow < __mmSecondarySoldierHoldUntil
)
return void __mmScheduleSecondaryGear(
__mmRestoreRightClickHat,
__mmSecondarySoldierHoldUntil,
);
const __mmHat = __mmRightClickHat;
// Force the saved hat past a pending Tank Gear equip. Without this override,
// a release received before the equip acknowledgement could leave Tank on.
(__mmClearSecondaryGearTimer(),
(__mmRightClickHat = null),
(__mmSecondaryGearStage = null),
(__mmSecondaryTankHoldUntil = 0),
(__mmSecondarySoldierHoldUntil = 0),
__mmEquipHatNow(__mmHat, !0));
}
function __mmForceRestoreRightClickHat() {
if (__mmRightClickHat == null) return void __mmClearSecondaryGearTimer();
const __mmHat = __mmRightClickHat;
(__mmClearSecondaryGearTimer(),
(__mmRightClickHat = null),
(__mmSecondaryGearStage = null),
(__mmSecondaryTankHoldUntil = 0),
(__mmSecondarySoldierHoldUntil = 0),
v && v.alive && __mmEquipHatNow(__mmHat, !0));
}
function __mmFireSecondaryTankWeapon() {
__mmSecondaryTankArmTimer = 0;
if (!__mmSecondaryHeld || !__mmRightClickWeaponReady())
return (
(__mmSecondaryTankSwingPending = !1),
void (__mmSecondaryHeld
? __mmEquipSecondaryDowntimeHat()
: __mmRestoreRightClickHat())
);
const __mmWeapon = __mmRightClickWeapon();
if (__mmWeapon == null)
return (
(__mmSecondaryTankSwingPending = !1),
void __mmRestoreRightClickHat()
);
(je(__mmWeapon, !0),
__mmSendWeaponAttack(1),
__mmSendWeaponAttack(0),
(__mmSecondaryManualReadyAt =
Date.now() + __mmManualWeaponCooldown(__mmWeapon)),
(__mmSecondaryTankSwingPending = !1),
(__mmSecondaryGearStage = "tank"),
(__mmSecondaryTankHoldUntil = Date.now() + __mmGearHoldMs()),
__mmEquipSecondaryDowntimeHat());
}
function __mmPulseSecondaryWeapon() {
if (!__mmSecondaryHeld || __mmSecondaryTankSwingPending) return;
const __mmWeapon = __mmRightClickWeapon(),
__mmUseTank = !!(__mmTankRightClickEnabled && v && v.skins && v.skins[40]);
if (__mmWeapon == null) return;
if (!__mmUseTank)
return (je(__mmWeapon, !0), void __mmSendWeaponAttack(1));
__mmRightClickHat == null && (__mmRightClickHat = v.skinIndex);
if (
__mmSecondaryGearStage === "soldier" &&
Date.now() < __mmSecondarySoldierHoldUntil
)
return;
if (!__mmRightClickWeaponReady())
return void __mmEquipSecondaryDowntimeHat();
__mmEquipTankForSecondary();
if (__mmRightClickHat == null)
return (je(__mmWeapon, !0), void __mmSendWeaponAttack(1));
((__mmSecondaryTankSwingPending = !0),
(__mmSecondaryTankArmTimer = setTimeout(
__mmFireSecondaryTankWeapon,
__mmServerTickMs(),
)));
}
function __mmStopSecondary() {
((__mmSecondaryHeld = !1),
__mmSecondaryTankArmTimer &&
(clearTimeout(__mmSecondaryTankArmTimer),
(__mmSecondaryTankArmTimer = 0)),
(__mmSecondaryTankSwingPending = !1),
__mmStopHeldAttackPulse(),
__mmPrimaryHeld && __mmPulseHeldAttack(),
__mmRestoreRightClickHat(),
__mmRestoreTrapHat(),
!__mmPrimaryHeld && __mmActionRelease("manualAttack", "right click released"));
__mmUpdateWeaponRecharge();
}
function __mmFinishSecondaryInput() {
(__mmStopSecondary(), __mmRestoreBullForPrimary());
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (__mmEvent.button !== 2 || !__mmIsGameClick(__mmEvent))
return void __mmRestoreRightClickHat();
__mmInsta.isActive() && __mmInsta.cancel("manual-secondary");
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmTankRightClickEnabled || __mmRightClickWeapon() == null)
return void __mmRestoreRightClickHat();
// A right-click handoff must fully release the left attack first. This
// clears the Bull arm timer and prevents a late primary pulse from winning
// after the secondary has already started.
(__mmPrimaryHeld ||
__mmPrimaryBullArmTimer ||
__mmPrimaryBullSwingPending ||
__mmPrimaryClickHat != null) &&
(__mmStopPrimaryInput(), __mmForceRestoreBullForPrimary());
if (!__mmActionClaim("manualAttack", "right click")) return;
(__mmEvent.preventDefault(),
__mmEvent.stopImmediatePropagation(),
(__mmSecondaryHeld = !0),
__mmStartHeldAttackPulse());
},
!0,
);
document.addEventListener(
"mouseup",
function (__mmEvent) {
if (
__mmEvent.button !== 2 ||
(!__mmSecondaryHeld && __mmRightClickHat == null)
)
return;
(__mmEvent.preventDefault(),
__mmEvent.stopImmediatePropagation(),
__mmFinishSecondaryInput());
},
!0,
);
document.addEventListener(
"pointerup",
function (__mmEvent) {
if (__mmEvent.button === 0 && __mmPrimaryHeld) __mmStopPrimaryInput();
if (
__mmEvent.button === 2 &&
(__mmSecondaryHeld ||
__mmSecondaryTankArmTimer ||
__mmSecondaryTankSwingPending ||
__mmRightClickHat != null)
)
__mmFinishSecondaryInput();
},
!0,
);
document.addEventListener(
"pointermove",
function (__mmEvent) {
if (__mmEvent.pointerType && __mmEvent.pointerType !== "mouse") return;
__mmPrimaryHeld && !(__mmEvent.buttons & 1) && __mmStopPrimaryInput();
__mmSecondaryHeld && !(__mmEvent.buttons & 2) && __mmFinishSecondaryInput();
},
!0,
);
document.addEventListener(
"pointercancel",
function () {
(__mmStopPrimaryInput(), __mmFinishSecondaryInput());
},
!0,
);
document.addEventListener(
"contextmenu",
function (__mmEvent) {
__mmIsGameClick(__mmEvent) && __mmEvent.preventDefault();
},
!0,
);
window.addEventListener("blur", function () {
(__mmStopPrimaryInput(),
__mmStopSecondary(),
__mmStopCleanup("window blur", !1),
__mmFinishMatThief("window blur"),
__mmFinishMobSteal("window blur"),
__mmStopWindmillHold(),
__mmStopInstaSync(),
__mmStopSpikeTickStrike("window blur"),
__mmStopAntiBoostBlock("window blur"),
__mmInsta.cancel("window-blur"),
__mmRestoreBullForPrimary(),
__mmStopShiftSpeed(),
__mmRestoreMovementGear());
});
document.addEventListener("visibilitychange", function () {
document.hidden &&
(__mmStopPrimaryInput(),
__mmStopSecondary(),
__mmStopCleanup("document hidden", !1),
__mmFinishMatThief("document hidden"),
__mmFinishMobSteal("document hidden"),
__mmStopWindmillHold(),
__mmStopInstaSync(),
__mmStopSpikeTickStrike("document hidden"),
__mmStopAntiBoostBlock("document hidden"),
__mmInsta.cancel("document-hidden"),
__mmStopShiftSpeed(),
__mmRestoreMovementGear());
});
function __mmSendKillMessage() {
if (!__mmKillMessageEnabled || !__mmKillMessage || !v || !v.alive) return;
__mmSendChat(__mmKillMessage);
}
__mmApplyAllItemsUnlock();
__mmStartLiveState();
__mmStartDebugHud();
__mmStartAutoHeal();
__mmStartAutoSpikeSpam();
__mmStartAutoInsta();
__mmStartAutoSpikeInsta();
__mmStartTrapAlert();
__mmStartFriendlyTrapChat();
__mmStartTrapEscape();
__mmStartSoldierAuto();
__mmStartMovementGear();
__mmStartPassiveSpikeAvoidance();
__mmStartWeaponRecharge();
__mmStartAutoPurchase();
__mmStartMobSteal();
__mmStartSpinningWindmills();
__mmStartAntiInsta();
__mmStartInstaSync();
__mmStartAntiBoostSpikes();
__mmStartThreatTrap();
__mmStartReloadSpike();
Xl = function () {
const __mmResult = __mmOriginalAnimalUpdate.apply(this, arguments);
__mmMobStealEnabled && __mmUpdateMobSteal();
return __mmResult;
};
$l = function (__mmPlayerSid, __mmHealth) {
const __mmPreviousHealth =
v && __mmPlayerSid === v.sid ? Number(v.health) : null;
const __mmResult = __mmOriginalHealthUpdate.apply(this, arguments);
if (v && __mmPlayerSid === v.sid) {
Number.isFinite(__mmPreviousHealth) &&
Number.isFinite(Number(__mmHealth)) &&
__mmObserveFriendDamage(
Math.max(0, __mmPreviousHealth - Number(__mmHealth)),
);
const __mmTookDamage = __mmObserveAutoHealHealth(__mmHealth);
// A confirmed hit always takes priority over a queued insta. Healing is
// packet-driven, so do it now rather than deferring for combat cleanup.
__mmInsta.isActive() && __mmTookDamage &&
__mmInsta.cancel("health-damage");
__mmAutoHeal();
}
return __mmResult;
};
Kl = function (__mmKey, __mmValue, __mmRefresh) {
const __mmPreviousKills =
v && __mmKey === "kills" ? Number(v.kills) || 0 : null,
__mmResult = __mmOriginalPlayerStatUpdate.apply(this, arguments);
return (
__mmPreviousKills != null &&
Number(__mmValue) > __mmPreviousKills &&
__mmSendKillMessage(),
__mmResult
);
};
Un = function () {
const __mmResult = __mmOriginalUpgradeDisplay.apply(this, arguments);
(__mmMarkUnsafeUpgradeChoices(), __mmResult);
return __mmResult;
};
Pl = function (__mmPlayerSid, __mmDidHit, __mmWeapon) {
__mmRecordPlayerSwing(__mmPlayerSid, __mmWeapon);
__mmObserveTrapEscapeSwing(__mmPlayerSid, __mmWeapon);
__mmObserveFriendAttack(__mmPlayerSid, __mmDidHit, __mmWeapon);
__mmTrackTurretGearReload(__mmPlayerSid);
__mmHandleEnemyPolearmSwing(__mmPlayerSid, __mmWeapon);
return __mmOriginalPlayerAttack.apply(this, arguments);
};
dl = function (__mmPlayerSid, __mmMessage) {
const __mmResult = __mmOriginalChatDisplay.apply(this, arguments);
(__mmReplyToMaterialRequest(__mmPlayerSid, __mmMessage),
__mmReplyToModQuestion(__mmPlayerSid, __mmMessage),
__mmResult);
return __mmResult;
};
window.addEventListener("blur", __mmStopTrapAttack);
__mmPublishHudState();
window.__MooMooScrollZoomSetViewport = function (__mmZoomMultiplier) {
const __mmMultiplier = Math.max(
0.5,
Math.min(6.666666666666667, Number(__mmZoomMultiplier) || 1),
);
_ = y.maxScreenWidth = __mmZoomBaseWidth * __mmMultiplier;
L = y.maxScreenHeight = __mmZoomBaseHeight * __mmMultiplier;
bi();
};
setTimeout(function () {
window.__MooMooScrollZoomSetViewport(
window.__MooMooScrollZoomMultiplier || 1,
);
}, 0);
`;
}
function patchedHotkeyCode() {
// Item slots 2 and 4 are the current spike and pit-trap upgrades.
return "__mmCleanupInputKey(t),t==85?__mmArmFriendPick('friend'):t==73?__mmArmFriendPick('enemy'):t==67?__mmToggleCleanup():t==84&&__mmShiftHeld()?__mmStartBetrayalInsta():t==82?__mmInsta.start():t==80?__mmToggleAutoHeal():t==90?__mmStartWindmillHold():t==72?__mmStartSelectedBuildSpam(72):t==70&&__mmShiftHeld()?__mmStartBoostBreak():t==70&&v.items[4]!=null?__mmStartBuildSpam(4,70):t==86&&v.items[2]!=null?__mmStartBuildSpam(2,86):" + HOTKEY_MARKER;
}
function patchedFoodHotkeyCode() {
return "t==81?__mmStartFoodSpam():";
}
function patchedFoodKeyupCode() {
// R is deliberately absent: one keydown starts a burst, repeat keydowns are
// ignored by __mmInsta, and keyup must not cancel an armed range wait.
return "function pl(e){const __mmFoodKey=e.which||e.keyCode||0;__mmFoodKey==16&&__mmStopBoostBreak();__mmFoodKey==70&&__mmStopBoostBreak();__mmFoodKey==81&&__mmStopFoodSpam();__mmFoodKey==90&&__mmStopWindmillHold();(__mmFoodKey==70||__mmFoodKey==72||__mmFoodKey==86)&&__mmStopBuildSpam(__mmFoodKey);if(v&&v.alive){const t=e.which||e.keyCode||0;";
}
function patchedMovementKeydownCode() {
return "bt[t]?(__mmPassiveSpikeMovementPressed(),Tt()):t==32&&(U=1,ke())";
}
function patchedMovementKeyupCode() {
return "bt[t]?(__mmPassiveSpikeMovementReleased(),Tt()):t==32&&(U=0,ke())";
}
function wait(milliseconds) {
return new Promise((resolve) => window.setTimeout(resolve, milliseconds));
}
function loadOriginalBundle(originalUrl) {
if (originalBundleLoaded) return;
originalBundleLoaded = true;
const fallbackScript = document.createElement("script");
fallbackScript.type = "module";
fallbackScript.src = originalUrl;
(document.head || document.documentElement).appendChild(fallbackScript);
}
async function fetchBundleSource(originalUrl) {
let lastError;
for (let attempt = 1; attempt <= BUNDLE_RETRY_LIMIT; attempt += 1) {
try {
const response = await fetch(originalUrl, { cache: "force-cache" });
if (!response.ok) throw new Error(`bundle request failed (${response.status})`);
return await response.text();
} catch (error) {
lastError = error;
if (attempt < BUNDLE_RETRY_LIMIT) {
console.warn(`[MooMoo Scroll Zoom] bundle attempt ${attempt} failed; retrying.`);
await wait(BUNDLE_RETRY_DELAY_MS * attempt);
}
}
}
throw lastError || new Error("bundle request failed");
}
function loadPatchedModule(patchedSource) {
return new Promise((resolve, reject) => {
const blobUrl = URL.createObjectURL(new Blob([patchedSource], { type: "text/javascript" }));
const patchedScript = document.createElement("script");
patchedScript.type = "module";
patchedScript.src = blobUrl;
patchedScript.onload = () => {
URL.revokeObjectURL(blobUrl);
resolve();
};
patchedScript.onerror = () => {
URL.revokeObjectURL(blobUrl);
patchedScript.remove();
reject(new Error("patched game bundle could not load"));
};
(document.head || document.documentElement).appendChild(patchedScript);
});
}
function waitForDocumentParsed() {
if (document.readyState !== "loading") return Promise.resolve();
return new Promise((resolve) => {
document.addEventListener("DOMContentLoaded", resolve, { once: true });
});
}
function findMissingPatchMarkers(source) {
const markers = [
["viewport", VIEWPORT_MARKER],
["hotkeys", HOTKEY_MARKER],
["food hotkey", FOOD_HOTKEY_MARKER],
["food keyup", FOOD_KEYUP_MARKER],
["movement keydown", MOVEMENT_KEYDOWN_MARKER],
["movement keyup", MOVEMENT_KEYUP_MARKER],
["backdrop", BACKDROP_GRID_MARKER],
["player-stat update", PLAYER_STAT_UPDATE_MARKER],
["chat display", CHAT_DISPLAY_MARKER],
["insta player lookup", INSTA_PLAYER_LOOKUP_MARKER],
["insta player attack", INSTA_PLAYER_ATTACK_MARKER]
];
return markers
.filter(([, marker]) => !source.includes(marker))
.map(([name]) => name);
}
async function loadPatchedBundle(originalUrl) {
try {
const originalSource = await fetchBundleSource(originalUrl);
const missingMarkers = findMissingPatchMarkers(originalSource);
if (missingMarkers.length) {
throw new Error("the game client changed; missing patch markers: " + missingMarkers.join(", "));
}
const bundleUrl = new URL(originalUrl, location.href);
const patchedSource = originalSource
.replace(BACKDROP_GRID_MARKER, "k.globalAlpha=1,")
.replace(VIEWPORT_MARKER, patchedViewportCode())
.replace(HOTKEY_MARKER, patchedHotkeyCode())
.replace(FOOD_HOTKEY_MARKER, patchedFoodHotkeyCode())
.replace(FOOD_KEYUP_MARKER, patchedFoodKeyupCode())
.replace(MOVEMENT_KEYDOWN_MARKER, patchedMovementKeydownCode())
.replace(MOVEMENT_KEYUP_MARKER, patchedMovementKeyupCode())
.replace(/from"\.\/vendor-[^"]+\.js"/, (specifier) => {
const path = specifier.slice(5, -1);
return `from"${new URL(path, bundleUrl).href}"`;
});
// The site's original module is parser-deferred. Our replacement is
// dynamically appended, so preserve the same ordering explicitly;
// otherwise a cached bundle can run before MooMoo's body exists.
await waitForDocumentParsed();
let lastError;
for (let attempt = 1; attempt <= PATCHED_MODULE_RETRY_LIMIT; attempt += 1) {
try {
await loadPatchedModule(patchedSource);
return;
} catch (error) {
lastError = error;
if (attempt < PATCHED_MODULE_RETRY_LIMIT) {
console.warn(`[MooMoo Scroll Zoom] patched bundle attempt ${attempt} failed; retrying.`);
await wait(BUNDLE_RETRY_DELAY_MS * attempt);
}
}
}
throw lastError || new Error("patched game bundle could not load");
} catch (error) {
console.error("[MooMoo Scroll Zoom] could not patch the game bundle; loading the original bundle.", error);
loadOriginalBundle(originalUrl);
}
}
function gameBundleUrl(value) {
if (!value) return null;
try {
const url = new URL(String(value), location.href);
return GAME_BUNDLE.test(url.pathname) ? url.href : null;
} catch {
return null;
}
}
function claimGameBundle(script, originalUrl, removeConnected = true) {
if (gameScriptHijacked || !script || !originalUrl) return false;
gameScriptHijacked = true;
restoreBundleInsertionGuards();
script.type = "application/x-kitty-klient-blocked";
script.removeAttribute("src");
if (removeConnected && script.isConnected) script.remove();
// Start the replacement fetch during the same turn that blocked the
// original module. No observer/microtask gap is left for it to execute.
loadPatchedBundle(originalUrl);
return true;
}
function interceptGameBundle(script, removeConnected = true) {
if (gameScriptHijacked || !script || script.tagName !== "SCRIPT") return false;
const originalUrl = gameBundleUrl(script.src || script.getAttribute("src"));
return claimGameBundle(script, originalUrl, removeConnected);
}
function installSynchronousBundleGuards() {
const nodePrototype = Node.prototype;
const elementPrototype = Element.prototype;
const scriptPrototype = HTMLScriptElement.prototype;
const originalAppendChild = nodePrototype.appendChild;
const originalInsertBefore = nodePrototype.insertBefore;
const originalReplaceChild = nodePrototype.replaceChild;
const originalAppend = elementPrototype.append;
const originalPrepend = elementPrototype.prepend;
const originalSetAttribute = elementPrototype.setAttribute;
const originalSrc = Object.getOwnPropertyDescriptor(scriptPrototype, "src");
let restored = false;
const restore = () => {
if (restored) return;
restored = true;
nodePrototype.appendChild = originalAppendChild;
nodePrototype.insertBefore = originalInsertBefore;
nodePrototype.replaceChild = originalReplaceChild;
if (originalAppend) elementPrototype.append = originalAppend;
if (originalPrepend) elementPrototype.prepend = originalPrepend;
elementPrototype.setAttribute = originalSetAttribute;
if (originalSrc) Object.defineProperty(scriptPrototype, "src", originalSrc);
};
restoreBundleInsertionGuards = restore;
const captureNode = (node) => {
if (
gameScriptHijacked ||
!node ||
node.nodeType !== Node.ELEMENT_NODE ||
node.tagName !== "SCRIPT"
) return false;
const originalUrl = gameBundleUrl(node.src || node.getAttribute("src"));
return claimGameBundle(node, originalUrl, false);
};
nodePrototype.appendChild = function (node) {
if (captureNode(node)) return node;
return originalAppendChild.call(this, node);
};
nodePrototype.insertBefore = function (node, reference) {
if (captureNode(node)) return node;
return originalInsertBefore.call(this, node, reference);
};
nodePrototype.replaceChild = function (node, previous) {
if (captureNode(node)) return previous;
return originalReplaceChild.call(this, node, previous);
};
if (originalAppend) {
elementPrototype.append = function (...nodes) {
const remaining = nodes.filter((node) => !captureNode(node));
if (remaining.length) return originalAppend.apply(this, remaining);
};
}
if (originalPrepend) {
elementPrototype.prepend = function (...nodes) {
const remaining = nodes.filter((node) => !captureNode(node));
if (remaining.length) return originalPrepend.apply(this, remaining);
};
}
elementPrototype.setAttribute = function (name, value) {
if (
!gameScriptHijacked &&
this instanceof HTMLScriptElement &&
String(name).toLowerCase() === "src"
) {
const originalUrl = gameBundleUrl(value);
if (claimGameBundle(this, originalUrl, false)) return;
}
return originalSetAttribute.call(this, name, value);
};
if (originalSrc && originalSrc.get && originalSrc.set) {
Object.defineProperty(scriptPrototype, "src", {
configurable: originalSrc.configurable,
enumerable: originalSrc.enumerable,
get: originalSrc.get,
set(value) {
if (!gameScriptHijacked) {
const originalUrl = gameBundleUrl(value);
if (claimGameBundle(this, originalUrl, false)) return;
}
return originalSrc.set.call(this, value);
}
});
}
}
})();