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: 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.
Pada tanggal
// ==UserScript==
// @name kitty klient
// @version 3.11.8
// @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: 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 HUD_DEFAULTS = Object.freeze({
autoHeal: true,
soldierAuto: true,
movementGear: true,
trapEscape: true,
antiBoost: true,
threatTrap: true,
reloadSpike: true,
shieldDefense: true,
musketRecharge: true,
autoPurchase: false,
esp: true,
predictionGhost: true,
bullHelmet: true,
tankRightClick: true,
instaKill: false,
boostBreak: true,
boostChat: true,
syncLeader: false,
syncFollower: false,
soldierRange: 400,
combatRange: 400,
antiBoostRange: 200,
killMessageEnabled: true,
killMessage: "gg"
});
const HUD_BOOLEAN_KEYS = Object.freeze([
"autoHeal",
"soldierAuto",
"movementGear",
"trapEscape",
"antiBoost",
"threatTrap",
"reloadSpike",
"shieldDefense",
"musketRecharge",
"autoPurchase",
"esp",
"predictionGhost",
"bullHelmet",
"tankRightClick",
"instaKill",
"boostBreak",
"boostChat",
"syncLeader",
"syncFollower",
"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 }),
antiBoostRange: Object.freeze({ min: 80, max: 500, step: 10 })
});
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(";
// __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 hudMounted = false;
let hudSettingsSent = false;
let hudState = { ...HUD_DEFAULTS };
const hudControls = new Map();
window.__MooMooScrollZoomMultiplier = viewMultiplier;
// 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);
}
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 status = document.querySelector("#" + HUD_ID + " [data-hud-status]");
if (!status) return;
const enabled = [
hudState.autoHeal && "heal",
hudState.soldierAuto && "soldier",
hudState.movementGear && "speed",
hudState.antiBoost && "spikes",
hudState.syncLeader && "sync leader",
hudState.syncFollower && "sync follower"
].filter(Boolean);
status.textContent = enabled.length ? "Active: " + enabled.join(" · ") : "Automation paused";
}
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(15,19,29,.94);--mm-surface:rgba(255,255,255,.07);--mm-line:rgba(255,255,255,.13);--mm-text:#f5f7ff;--mm-muted:#aab4ca;--mm-accent:#71e6ab;position:fixed;z-index:2147483646;top:72px;left:16px;width:min(336px,calc(100vw - 32px));font:13px/1.25 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:var(--mm-text);pointer-events:auto}",
"#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-launcher{width:100%;border:1px solid var(--mm-line);border-radius:10px;background:var(--mm-bg);color:var(--mm-text);padding:10px 12px;display:flex;justify-content:space-between;align-items:center;font-weight:800;letter-spacing:.02em;cursor:pointer;box-shadow:0 8px 30px rgba(0,0,0,.28)}#moomoo-op-hud .mm-hud-launcher b{color:var(--mm-accent);font-size:11px}",
"#moomoo-op-hud .mm-hud-panel{margin-top:7px;max-height:calc(100vh - 140px);overflow:auto;border:1px solid var(--mm-line);border-radius:12px;background:var(--mm-bg);box-shadow:0 14px 44px rgba(0,0,0,.34);padding:12px}#moomoo-op-hud.mm-hud-collapsed .mm-hud-panel{display:none}",
"#moomoo-op-hud .mm-hud-status{margin:0 0 10px;color:var(--mm-accent);font-size:11px;font-weight:700}#moomoo-op-hud .mm-hud-section{border-top:1px solid var(--mm-line);padding:10px 0 2px}#moomoo-op-hud .mm-hud-section:first-of-type{border-top:0;padding-top:0}#moomoo-op-hud h3{margin:0 0 7px;font-size:11px;text-transform:uppercase;letter-spacing:.09em;color:var(--mm-muted)}",
"#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}#moomoo-op-hud small{color:var(--mm-muted);font-size:10px}",
"#moomoo-op-hud input[type='checkbox']{appearance:none;width:34px;height:19px;margin:0;border:1px solid var(--mm-line);border-radius:999px;background:#465068;position:relative;flex:0 0 auto;cursor:pointer}#moomoo-op-hud input[type='checkbox']:after{content:'';position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;background:white;transition:transform .14s ease}#moomoo-op-hud input[type='checkbox']:checked{background:#198f60}#moomoo-op-hud input[type='checkbox']:checked:after{transform:translateX(15px)}",
"#moomoo-op-hud input[type='number']{width:62px;border:1px solid var(--mm-line);border-radius:6px;background:var(--mm-surface);color:var(--mm-text);padding:5px 6px;text-align:right}#moomoo-op-hud .mm-hud-message{width:100%;border:1px solid var(--mm-line);border-radius:7px;background:var(--mm-surface);color:var(--mm-text);padding:7px 8px;margin:3px 0 7px}",
"#moomoo-op-hud .mm-hud-actions{display:grid;grid-template-columns:1fr;gap:6px}#moomoo-op-hud .mm-hud-actions button,#moomoo-op-hud .mm-hud-reset{border:1px solid var(--mm-line);border-radius:7px;background:var(--mm-surface);color:var(--mm-text);padding:7px;cursor:pointer}#moomoo-op-hud .mm-hud-actions button:hover,#moomoo-op-hud .mm-hud-reset:hover{border-color:var(--mm-accent)}#moomoo-op-hud .mm-hud-keys{margin:0;padding-left:16px;color:var(--mm-muted);font-size:11px;display:grid;gap:3px}",
"@media (max-width:600px){#moomoo-op-hud{top:12px;left:10px;width:min(320px,calc(100vw - 20px))}#moomoo-op-hud .mm-hud-panel{max-height:calc(100vh - 82px)}}"
].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 launcher = document.createElement("button");
launcher.className = "mm-hud-launcher";
launcher.type = "button";
launcher.textContent = "kitty klient";
const launcherState = document.createElement("b");
launcherState.textContent = "OPEN HUD";
launcher.appendChild(launcherState);
launcher.addEventListener("click", () => {
root.classList.toggle("mm-hud-collapsed");
launcherState.textContent = root.classList.contains("mm-hud-collapsed") ? "OPEN HUD" : "HIDE HUD";
});
const panel = document.createElement("div");
panel.className = "mm-hud-panel";
panel.addEventListener("keydown", (event) => event.stopPropagation(), true);
panel.addEventListener("keyup", (event) => event.stopPropagation(), true);
const status = document.createElement("p");
status.className = "mm-hud-status";
status.dataset.hudStatus = "";
panel.appendChild(status);
const automation = addHudSection(panel, "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 hat and adaptive tail");
addHudToggle(automation, "trapEscape", "Trap escape", "Build behind you while continuously breaking the locking trap");
addHudToggle(automation, "antiBoost", "Anti-boost spikes", "React to a boosted enemy");
addHudToggle(automation, "threatTrap", "Threat trap", "Place one pit trap between you and a nearby enemy or hostile animal");
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", "Musket recharge", "Selects a reloading Musket unless another action needs control");
addHudToggle(automation, "autoPurchase", "Auto purchase", "Monkey Tail → Soldier → Stick/Bull path → gear → wings");
const tabSync = addHudSection(panel, "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(panel, "Visuals");
addHudToggle(visuals, "esp", "Player & animal markers", "Blue friends, red foes, green animals, and player lines");
addHudToggle(visuals, "predictionGhost", "Prediction ghost", "A translucent copy projects ahead by half your live ping");
const actions = addHudSection(panel, "Gear & boost controls");
addHudToggle(actions, "bullHelmet", "Bull helmet", "Tick-paced primary attack; swaps Monkey Tail for Corrupt X Wings");
addHudToggle(actions, "tankRightClick", "Tank right-click", "Tick-paced Tank swap for the right-click weapon");
addHudToggle(actions, "instaKill", "R insta", "Bull primary + Turret Gear secondary combo");
addHudToggle(actions, "boostBreak", "Shift + F boost-break", "Place, break, and move on cooldown");
addHudToggle(actions, "boostChat", "Shift + F chat", "Send shuffled speed messages");
const tuning = addHudSection(panel, "Distance tuning");
addHudNumber(tuning, "soldierRange", "Soldier radius", "Pixels");
addHudNumber(tuning, "combatRange", "Combat radius", "Tail behavior cutoff");
addHudNumber(tuning, "antiBoostRange", "Spike radius", "Pixels");
const messages = addHudSection(panel, "Death message");
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(panel, "Hotkeys");
const keyList = document.createElement("ul");
keyList.className = "mm-hud-keys";
["P autoheal", "Q food · F trap · V spikes · Z 3 windmills behind · H selected build", "Shift + F boost-break · 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.append(launcher, panel);
document.body.appendChild(root);
renderHud();
}
function scheduleHudMount() {
if (document.body) mountHud();
else document.addEventListener("DOMContentLoaded", mountHud, { once: true });
}
window.addEventListener("MooMooOPHudState", (event) => {
if (!event.detail || typeof event.detail !== "object") return;
hudState = normalizeHudSettings({ ...hudState, ...event.detail });
if (!hudSettingsSent) {
hudSettingsSent = true;
sendHudCommand({ type: "hydrate", settings: readHudSettings() });
}
saveHudSettings();
renderHud();
});
scheduleHudMount();
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,
__mmAntiBoostRange = 200,
__mmSoldierAutoEnabled = !0,
__mmMovementGearEnabled = !0,
__mmTrapEscapeEnabled = !0,
__mmAntiBoostEnabled = !0,
__mmThreatTrapEnabled = !0,
__mmReloadSpikeEnabled = !0,
__mmShieldDefenseEnabled = !0,
__mmMusketRechargeEnabled = !0,
__mmAutoPurchaseEnabled = !1,
__mmEspEnabled = !0,
__mmPredictionGhostEnabled = !0,
__mmBullHelmetEnabled = !0,
__mmTankRightClickEnabled = !0,
__mmInstaUiEnabled = !1,
__mmBoostBreakEnabled = !0,
__mmBoostChatEnabled = !0,
__mmSyncLeaderEnabled = !1,
__mmSyncFollowerEnabled = !1,
__mmKillMessageEnabled = !0,
__mmKillMessage = "gg";
const __mmShieldWeapon = 11,
__mmShortSword = 3,
__mmPolearmWeapon = 5,
__mmTurretGear = 53,
__mmTurretGearRange = 700,
__mmThreatTrapRange = 450,
__mmThreatTrapCooldownMs = 650,
__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 __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 }),
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,
__mmAutoHealLastSendAt = 0,
__mmAutoHealLastDamageAt = 0,
__mmAutoHealLastObservedHealth = null,
__mmLastWeapon = null,
__mmLastBuildItem = null,
__mmAutoHealWeapon = null;
let __mmAutoPurchaseTimer = 0,
__mmAutoPurchasePending = null;
let __mmMovementGearTimer = 0,
__mmMovementGearPreviousHat = null,
__mmMovementGearPreviousTail = null,
__mmProximityTailPrevious = 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;
let __mmThreatTrapTimer = 0,
__mmThreatTrapLastAt = 0,
__mmThreatTrapLastKey = 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,
__mmSyncStatus = "off";
let __mmBuildSpamTimer = 0,
__mmBuildSpamKey = 0;
let __mmWindmillRowTimer = 0,
__mmWindmillHoldTimer = 0,
__mmWindmillHeld = !1,
__mmWindmillRowWeapon = null;
let __mmMusketRechargeTimer = 0,
__mmMusketRechargePreviousWeapon = null;
let __mmPredictionLastX = null,
__mmPredictionLastY = null,
__mmPredictionLastAt = 0;
let __mmPrimaryHeld = !1,
__mmSecondaryHeld = !1,
__mmHeldAttackTimer = 0,
__mmPrimaryBullArmTimer = 0,
__mmPrimaryBullSwingPending = !1,
__mmSecondaryTankArmTimer = 0,
__mmSecondaryTankSwingPending = !1,
__mmPrimaryClickHat = null,
__mmPrimaryClickTail = null,
__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,
__mmTrapWeapon = null,
__mmTrapHat = null,
__mmTrapLastSwingAt = 0,
__mmTrapBuildTimer = 0,
__mmTrapBuildAttemptKey = null,
__mmTrapBuildWeapon = null;
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);
};
const __mmOriginalSocketSend = O.send;
O.send = function () {
const __mmResult = __mmOriginalSocketSend.apply(this, arguments);
return (__mmSyncObserveSocketSend(arguments), __mmResult);
};
const __mmOriginalPlayerAttack = Pl;
const __mmOriginalHealthUpdate = $l;
const __mmOriginalPlayerStatUpdate = Kl;
const __mmOriginalRender = Cl;
// 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,
snapshot: null,
primaryWeapon: null,
followupIndex: 0,
attackHeld: !1,
cooldowns: Object.create(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() {
return !!(
!v ||
!v.alive ||
v.lockMove ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
this.isEmergencyHealth()
);
},
capture() {
this.snapshot = {
weapon: __mmSelectedWeapon(),
hat: v.skinIndex,
tail: v.tailIndex,
primaryHeld: __mmPrimaryHeld,
secondaryHeld: __mmSecondaryHeld,
heldPulse: !!__mmHeldAttackTimer,
movementGear: __mmMovementGearEnabled,
soldierAuto: __mmSoldierAutoEnabled,
autoHeal: __mmAutoHealEnabled,
};
},
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) &&
Number.isFinite(Number(__mmTarget.x)) &&
Number.isFinite(Number(__mmTarget.y))
? __mmTarget
: null;
},
weaponData(__mmWeapon) {
return b && b.weapons && __mmWeapon != null ? b.weapons[__mmWeapon] : null;
},
weaponCooldown(__mmWeapon) {
const __mmData = this.weaponData(__mmWeapon);
const __mmSpeed = __mmData && Number(__mmData.speed);
return Math.max(this.tick(), Number.isFinite(__mmSpeed) && __mmSpeed > 0 ? __mmSpeed : this.tick());
},
weaponReady(__mmWeapon) {
return !!(
v &&
v.alive &&
v.weapons &&
v.weapons.includes(__mmWeapon) &&
this.weaponData(__mmWeapon) &&
__mmWeaponReady(__mmWeapon) &&
Date.now() >= (this.cooldowns[__mmWeapon] || 0)
);
},
markWeaponCooldown(__mmWeapon) {
this.cooldowns[__mmWeapon] = Date.now() + this.weaponCooldown(__mmWeapon);
},
supportedPrimary(__mmRequireReady = !0) {
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 &&
(!__mmRequireReady || this.weaponReady(__mmWeapon))
? __mmWeapon
: null;
},
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);
return Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) <= __mmReach;
},
aim(__mmTarget) {
return __mmTarget
? Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x)
: Ci();
},
context(__mmRequireRange, __mmRequirePrimaryReady = !0) {
if (
!__mmInstaUiEnabled ||
!this.runtimeReady() ||
this.isPriorityConflict()
)
return null;
const __mmPrimary = this.supportedPrimary(__mmRequirePrimaryReady);
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;
// Both selections are independently ownership-checked by the helpers.
v.skins && v.skins[7] && __mmEquipHatNow(7);
v.tails && v.tails[__mmCorruptXWings] &&
__mmEquipTailNow(__mmCorruptXWings);
},
selectSecondaryDamageGear() {
// The second strike uses Turret Gear when it is owned. It is sent before
// the secondary selection/attack, preserving the ordered tick sequence.
v && v.alive && v.skins && v.skins[__mmTurretGear] &&
__mmEquipHatNow(__mmTurretGear);
},
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() || !this.turretInRange(__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) {}
// Keep the hat through two server ticks: one to apply the equip packet and
// one for the loaded turret shot, then cleanup restores the snapshot.
this.schedule(() => {
this.state === "turretPoke" &&
this.schedule(() => this.finishTurretPoke());
});
return !0;
},
start(__mmOptions = {}) {
if (this.state !== "idle") return !1;
this.state = "validate";
this.targetOptional = !!__mmOptions.targetOptional;
this.followupIndex = 0;
this.cooldowns = Object.create(null);
if (!this.runtimeReady()) return (this.cleanup("runtime-unavailable"), !1);
this.capture();
const __mmTarget = this.nearestEnemy();
if (__mmTarget) this.targetSid = __mmTarget.sid;
const __mmContext = this.context(!1, !1);
if (!__mmContext) return (this.cleanup("validation-failed"), !1);
this.primaryWeapon = __mmContext.primary;
this.state = "arm";
this.arm();
return !0;
},
arm() {
const __mmContext = this.context(!1, !1);
if (!__mmContext) return void this.cleanup("arm-invalid");
this.primaryWeapon = __mmContext.primary;
// Do not put on Bull gear merely because an enemy is nearby. Arming only
// snapshots state; gear is selected after the target is truly in reach.
this.state = "waitForRange";
this.waitForRange();
},
waitForRange() {
if (this.state !== "waitForRange") return;
const __mmContext = this.context(!1, !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")
);
if (!this.weaponReady(__mmContext.primary))
return void this.schedule(() => this.waitForRange());
this.selectDamageGear();
// Socket messages are ordered, so send Bull gear, selection, and the
// attack-down state as one sequence. The attack stays down until the next
// server tick; releasing it in this same turn only showed Bull Helmet.
this.state = "executeBurst";
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 || !this.weaponReady(__mmContext.primary))
return void this.cleanup("primary-unavailable");
if (!this.sendAttack(__mmContext.primary, !0, __mmContext.target))
return void this.cleanup("primary-send-failed");
this.markWeaponCooldown(__mmContext.primary);
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 &&
this.weaponReady(__mmWeapon)
? __mmWeapon
: null;
},
spikeFollowup() {
const __mmSpike = __mmSpikeItem();
return __mmSpike != null &&
v &&
v.items &&
v.items.includes(__mmSpike) &&
__mmCanUseBuildItem(__mmSpike)
? __mmSpike
: null;
},
nextFollowup() {
const __mmSteps = ["secondary", "spike"];
while (this.followupIndex < __mmSteps.length) {
const __mmStep = __mmSteps[this.followupIndex++];
if (__mmStep === "secondary") {
const __mmSecondary = this.secondaryFollowup();
if (__mmSecondary != null)
return { type: "weapon", item: __mmSecondary };
} else {
const __mmSpike = this.spikeFollowup();
if (__mmSpike != null) return { type: "item", item: __mmSpike };
}
}
return 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, !1);
if (!__mmContext) return void this.cleanup("followup-invalid");
const __mmFollowup = this.nextFollowup();
if (!__mmFollowup) return void this.cleanup("complete");
if (
(__mmFollowup.type === "weapon" && !this.weaponReady(__mmFollowup.item)) ||
(__mmFollowup.type === "item" && !this.spikeFollowup())
)
return void this.schedule(() => this.executeFollowup());
__mmFollowup.type === "weapon" && this.selectSecondaryDamageGear();
if (!this.sendAttack(
__mmFollowup.item,
__mmFollowup.type === "weapon",
__mmContext.target,
))
return void this.cleanup("followup-send-failed");
__mmFollowup.type === "weapon" && this.markWeaponCooldown(__mmFollowup.item);
this.schedule(() => this.executeFollowup());
},
cleanup(__mmReason) {
const __mmSnapshot = this.snapshot;
this.state = "cleanup";
this.timer && clearTimeout(this.timer);
this.timer = 0;
this.releaseAttack();
if (v && v.alive && __mmSnapshot) {
__mmSnapshot.tail != null && __mmEquipTailNow(__mmSnapshot.tail);
__mmSnapshot.hat != null && __mmEquipHatNow(__mmSnapshot.hat);
__mmSnapshot.weapon != null && __mmRestoreWeapon(__mmSnapshot.weapon);
(__mmSnapshot.primaryHeld || __mmSnapshot.secondaryHeld) &&
(__mmPrimaryHeld || __mmSecondaryHeld) &&
__mmResumeHeldAttack();
}
this.snapshot = null;
this.targetSid = null;
this.targetOptional = !1;
this.primaryWeapon = null;
this.followupIndex = 0;
this.cooldowns = Object.create(null);
this.reason = __mmReason || "cancelled";
this.state = "idle";
// 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) {
__mmUpdateMovementGear();
__mmUpdateSoldier();
__mmUpdateMusketRecharge();
__mmAutoHeal();
}
},
cancel(__mmReason) {
this.cleanup(__mmReason || "cancelled");
},
};
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 __mmSameTeam(__mmPlayer) {
const __mmOwnTeam = __mmTeamKey(v),
__mmOtherTeam = __mmTeamKey(__mmPlayer);
return (
__mmOwnTeam != null &&
__mmOtherTeam != null &&
__mmOwnTeam === __mmOtherTeam
);
}
function __mmIsEnemyPlayer(__mmPlayer) {
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!v ||
!v.alive ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid ||
__mmSameTeam(__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 !== "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 __mmSyncObserveSocketSend(__mmArguments) {
if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
if (__mmArguments[0] === "c") {
__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, __mmServerTickMs())));
}
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 || !Array.isArray(E) || !Array.isArray(N)) return;
const __mmOwnX = v.x - __mmLeft,
__mmOwnY = v.y - __mmTop;
(k.save(), (k.lineWidth = 1.5), (k.globalAlpha = 0.72));
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 = __mmSameTeam(__mmPlayer) ? "#43a5ff" : "#ff4d5d",
__mmX = __mmPlayer.x - __mmLeft,
__mmY = __mmPlayer.y - __mmTop;
((k.strokeStyle = __mmColor),
k.beginPath(),
k.moveTo(__mmOwnX, __mmOwnY),
k.lineTo(__mmX, __mmY),
k.stroke());
}
((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 = __mmSameTeam(__mmPlayer) ? "#43a5ff" : "#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) {}
}
}
Cl = function () {
const __mmResult = __mmOriginalRender.apply(this, arguments);
return (__mmDrawEsp(), __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.turret,
__mmEntries.tank,
__mmEntries.shadow,
__mmEntries.angel,
__mmEntries.blood,
__mmEntries.corrupt,
]
: [
__mmEntries.monkeyTail,
__mmEntries.soldier,
__mmEntries.bull,
__mmEntries.booster,
__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,
__mmServerTickMs(),
));
}
function __mmStopAutoPurchase() {
(__mmAutoPurchaseTimer && clearInterval(__mmAutoPurchaseTimer),
(__mmAutoPurchaseTimer = 0),
(__mmAutoPurchasePending = null));
}
function __mmEnemyWithinCombatRange() {
if (!v || !v.alive) return !1;
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;
}
function __mmHudState() {
return {
autoHeal: __mmAutoHealEnabled,
soldierAuto: __mmSoldierAutoEnabled,
movementGear: __mmMovementGearEnabled,
trapEscape: __mmTrapEscapeEnabled,
antiBoost: __mmAntiBoostEnabled,
threatTrap: __mmThreatTrapEnabled,
reloadSpike: __mmReloadSpikeEnabled,
shieldDefense: __mmShieldDefenseEnabled,
musketRecharge: __mmMusketRechargeEnabled,
autoPurchase: __mmAutoPurchaseEnabled,
esp: __mmEspEnabled,
predictionGhost: __mmPredictionGhostEnabled,
bullHelmet: __mmBullHelmetEnabled,
tankRightClick: __mmTankRightClickEnabled,
instaKill: __mmInstaUiEnabled,
boostBreak: __mmBoostBreakEnabled,
boostChat: __mmBoostChatEnabled,
syncLeader: __mmSyncLeaderEnabled,
syncFollower: __mmSyncFollowerEnabled,
soldierRange: __mmSoldierRange,
combatRange: __mmCombatRange,
antiBoostRange: __mmAntiBoostRange,
killMessageEnabled: __mmKillMessageEnabled,
killMessage: __mmKillMessage,
};
}
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 === "antiBoostRange" &&
(__mmAntiBoostRange = Math.max(80, Math.min(500, __mmNumber))),
__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 === "trapEscape")
((__mmTrapEscapeEnabled = __mmEnabled),
__mmEnabled ? __mmStartTrapEscape() : __mmStopTrapEscape());
else if (__mmKey === "antiBoost") __mmAntiBoostEnabled = __mmEnabled;
else if (__mmKey === "threatTrap") __mmThreatTrapEnabled = __mmEnabled;
else if (__mmKey === "reloadSpike") __mmReloadSpikeEnabled = __mmEnabled;
else if (__mmKey === "shieldDefense") __mmShieldDefenseEnabled = __mmEnabled;
else if (__mmKey === "musketRecharge")
((__mmMusketRechargeEnabled = __mmEnabled),
!__mmEnabled && (__mmMusketRechargePreviousWeapon = null));
else if (__mmKey === "autoPurchase")
((__mmAutoPurchaseEnabled = __mmEnabled),
__mmEnabled ? (__mmStartAutoPurchase(), __mmUpdateAutoPurchase()) : __mmStopAutoPurchase());
else if (__mmKey === "esp") __mmEspEnabled = __mmEnabled;
else if (__mmKey === "predictionGhost")
__mmPredictionGhostEnabled = __mmEnabled;
else if (__mmKey === "bullHelmet") {
__mmBullHelmetEnabled = __mmEnabled;
if (!__mmEnabled && v && __mmPrimaryClickHat != null) {
const __mmHat = __mmPrimaryClickHat;
((__mmPrimaryClickHat = null),
v.skinIndex === 7 && __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat));
}
} else if (__mmKey === "tankRightClick")
((__mmTankRightClickEnabled = __mmEnabled),
!__mmEnabled && __mmStopSecondary());
else if (__mmKey === "instaKill") {
((__mmInstaUiEnabled = __mmEnabled),
!__mmEnabled && __mmInsta.cancel("hud-disabled"));
}
else if (__mmKey === "boostBreak") {
((__mmBoostBreakEnabled = __mmEnabled),
!__mmEnabled && __mmStopBoostBreak());
} else if (__mmKey === "boostChat") {
((__mmBoostChatEnabled = __mmEnabled), !__mmEnabled && __mmStopBoostChat());
} else if (__mmKey === "syncLeader") {
__mmSetSyncLeader(__mmEnabled);
return;
} else if (__mmKey === "syncFollower") {
__mmSetSyncFollower(__mmEnabled);
return;
} 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 === "antiBoostRange"
? __mmSetHudNumber(__mmKey, __mmValue)
: __mmSetHudToggle(__mmKey, __mmValue);
}
function __mmApplyHudSettings(__mmSettings) {
if (!__mmSettings || typeof __mmSettings !== "object") return;
const __mmKeys = [
"autoHeal",
"soldierAuto",
"movementGear",
"trapEscape",
"antiBoost",
"threatTrap",
"reloadSpike",
"shieldDefense",
"musketRecharge",
"autoPurchase",
"esp",
"predictionGhost",
"bullHelmet",
"tankRightClick",
"instaKill",
"boostBreak",
"boostChat",
"syncLeader",
"syncFollower",
"killMessageEnabled",
"killMessage",
"soldierRange",
"combatRange",
"antiBoostRange",
];
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);
__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) {
if (
!v ||
!v.alive ||
__mmHat == null ||
(__mmHat !== 0 && !(v.skins && v.skins[__mmHat]))
)
return !1;
if (v.skinIndex === __mmHat) {
__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) {
if (
!v ||
!v.alive ||
__mmTail == null ||
(__mmTail !== 0 && !(v.tails && v.tails[__mmTail]))
)
return !1;
if (v.tailIndex === __mmTail) {
__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) {
if (!v || !v.alive) return;
(__mmHat != null && __mmEquipHatNow(__mmHat),
__mmTail != null && __mmEquipTailNow(__mmTail));
}
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() {
__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 __mmWeapon = __mmSelectedWeapon();
(je(v.items[0]),
O.send("F", 1, Ci()),
O.send("F", 0, Ci()),
__mmWeapon != null && __mmRestoreWeapon(__mmWeapon),
__mmResumeHeldAttack());
}
function __mmUseFoodBurst(__mmCount) {
const __mmBites = Math.min(Math.max(0, __mmCount | 0), __mmFoodCharges());
if (!__mmBites) return;
const __mmFood = v.items[0],
__mmAngle = Ci(),
__mmWeapon = __mmSelectedWeapon();
for (let __mmBite = 0; __mmBite < __mmBites; __mmBite++)
(je(__mmFood), O.send("F", 1, __mmAngle), O.send("F", 0, __mmAngle));
(__mmWeapon != null && __mmRestoreWeapon(__mmWeapon), __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 __mmRestoreWeapon(__mmWeapon) {
v && v.alive && v.weapons.includes(__mmWeapon) && je(__mmWeapon, !0);
}
function __mmMusketIsReloading() {
if (!v || !v.alive || !v.weapons || !v.weapons.includes(__mmMusket))
return !1;
const __mmReload = v.reloads && Number(v.reloads[__mmMusket]);
return Number.isFinite(__mmReload) && __mmReload > 0;
}
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 __mmMusketRechargeOverridden() {
return (
!v ||
!v.alive ||
__mmInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmAutoHealWasHealing ||
__mmShieldDefenseTimer ||
__mmTankGearActive() ||
__mmPrimaryClickHat != null ||
__mmRightClickHat != null ||
__mmTrapHat != null
);
}
function __mmUpdateMusketRecharge() {
if (
!__mmMusketRechargeEnabled ||
__mmSyncFollowerEnabled ||
!v ||
!v.alive ||
!v.weapons ||
!v.weapons.includes(__mmMusket)
)
return void (__mmMusketRechargePreviousWeapon = null);
if (!__mmMusketIsReloading()) {
const __mmPreviousWeapon = __mmMusketRechargePreviousWeapon;
return (
(__mmMusketRechargePreviousWeapon = null),
void (
__mmPreviousWeapon != null &&
!__mmMusketRechargeOverridden() &&
__mmSelectedWeapon() === __mmMusket &&
__mmRestoreWeapon(__mmPreviousWeapon)
)
);
}
if (__mmMusketRechargeOverridden()) return;
const __mmSelected = __mmSelectedWeapon();
__mmSelected !== __mmMusket &&
(__mmMusketRechargePreviousWeapon == null &&
(__mmMusketRechargePreviousWeapon = __mmSelected),
je(__mmMusket, !0));
}
function __mmStartMusketRecharge() {
__mmMusketRechargeTimer ||
(__mmMusketRechargeTimer = setInterval(
__mmUpdateMusketRecharge,
__mmServerTickMs(),
));
}
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 __mmAutoHealCooldown() {
// Send the first food immediately on a health update, then pace follow-up
// food to the server tick with only a small ping allowance.
const __mmPing = Number(window.pingTime);
return Math.max(
75,
Math.min(
135,
__mmServerTickMs() - 12 +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing) * 0.12 : 0),
),
);
}
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;
if (
__mmAutoHealLastObservedHealth != null &&
__mmCurrentHealth < __mmAutoHealLastObservedHealth
)
__mmAutoHealLastDamageAt = Date.now();
__mmAutoHealLastObservedHealth = __mmCurrentHealth;
}
function __mmResetAutoHeal() {
((__mmAutoHealWasHealing = !1),
(__mmAutoHealLastSendAt = 0),
(__mmAutoHealLastDamageAt = 0),
(__mmAutoHealLastObservedHealth = v && v.alive ? Number(v.health) : null),
__mmRestoreAutoHealWeapon());
}
function __mmAutoHealIsEmergency() {
if (!v || !v.alive) return !1;
const __mmCriticalHealth = Math.max(20, v.maxHealth * 0.2);
const __mmFoodValue = __mmAutoHealFoodValue();
const __mmMissingHealth = Math.max(0, v.maxHealth - v.health);
return (
v.health <= __mmCriticalHealth ||
((__mmEnemyWithinCombatRange() || v.lockMove || __mmTrapAttackActive) &&
__mmMissingHealth >= __mmFoodValue)
);
}
function __mmAutoHeal() {
if (!__mmAutoHealEnabled || !v || !v.alive)
return void __mmResetAutoHeal();
__mmObserveAutoHealHealth(v.health);
if (v.health >= v.maxHealth || !__mmCanEat()) return void __mmResetAutoHeal();
const __mmNow = Date.now();
const __mmCooldown = __mmAutoHealCooldown();
// A health update can call this immediately. Every later food use waits for
// the short server-tick cadence, rather than adding a second post-hit wait.
if (__mmNow - __mmAutoHealLastSendAt < __mmCooldown) return;
((__mmAutoHealWasHealing = !0),
(__mmAutoHealLastSendAt = __mmNow),
__mmUseFood());
}
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));
if (__mmShiftPreviousTail != null) {
const __mmTail = __mmShiftPreviousTail;
((__mmShiftPreviousTail = null),
v.tailIndex !== __mmTail &&
(__mmTail === 0 || (v.tails && v.tails[__mmTail])) &&
__mmEquipTailNow(__mmTail));
}
if (__mmTemporaryHatOverlay())
return void (
__mmShiftRestoreTimer ||
(__mmShiftRestoreTimer = setTimeout(function () {
((__mmShiftRestoreTimer = 0), __mmRestoreShiftSpeed());
}, __mmServerTickMs()))
);
const __mmHat = __mmShiftPreviousHat;
((__mmShiftPreviousHat = null),
__mmHat != null &&
v.skinIndex !== __mmHat &&
__mmCanEquipHat(__mmHat) &&
__mmEquipHatNow(__mmHat));
}
function __mmStartShiftSpeedGear() {
if (!v || !v.alive || !__mmShiftHasSpeedGear()) return;
((__mmShiftMode = 1),
(__mmShiftPreviousHat = __mmShiftBaseHat()),
(__mmShiftPreviousTail = v.tailIndex),
__mmShiftSpeedTimer ||
(__mmShiftSpeedTimer = setInterval(
__mmUpdateShiftSpeed,
__mmServerTickMs(),
)),
__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",
}),
));
}, __mmServerTickMs());
}
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 (__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) {
__mmRestoreMovementGear();
if (v.tails && v.tails[__mmAngelWings])
return void __mmEquipTailNow(__mmAngelWings);
return void __mmClearIdleMonkeyTail();
}
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,
__mmServerTickMs(),
)),
__mmUpdateMovementGear());
}
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;
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;
}
return null;
}
function __mmThreatTrapAnimalAllowed(__mmAnimal) {
if (
!__mmAnimal ||
!__mmAnimal.active ||
!__mmAnimal.alive ||
!__mmAnimal.visible ||
!__mmAnimal.hostile
)
return !1;
const __mmName = String(__mmAnimal.name || "").trim().toLowerCase();
return __mmName !== "moostafa" && __mmName !== "moofie";
}
function __mmThreatTrapTarget() {
if (!v || !v.alive) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmConsider = function (__mmTarget, __mmType) {
if (
!__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 > __mmThreatTrapRange || __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,
distance: __mmDistance,
}),
(__mmClosestDistance = __mmDistance));
};
if (Array.isArray(E))
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
__mmIsEnemyPlayer(__mmPlayer) && __mmConsider(__mmPlayer, "player");
}
if (Array.isArray(N))
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
const __mmAnimal = N[__mmIndex];
__mmThreatTrapAnimalAllowed(__mmAnimal) &&
__mmConsider(__mmAnimal, "animal");
}
return __mmClosest;
}
function __mmPlaceThreatTrap() {
if (
!__mmThreatTrapEnabled ||
!v ||
!v.alive ||
v.lockMove ||
__mmInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer
)
return !1;
const __mmTrap = __mmThreatTrapItem(),
__mmThreat = __mmThreatTrapTarget(),
__mmNow = Date.now();
if (
__mmTrap == null ||
!__mmThreat ||
(__mmThreat.key === __mmThreatTrapLastKey &&
__mmNow - __mmThreatTrapLastAt < __mmThreatTrapCooldownMs)
)
return !1;
// Build placement is angle-based and always occurs at the player's placement
// radius, so aiming at the threat puts the pit trap directly between us.
const __mmAngle = Math.atan2(
__mmThreat.target.y - v.y,
__mmThreat.target.x - v.x,
),
__mmWeapon = __mmSelectedWeapon();
try {
(je(__mmTrap),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmWeapon != null && __mmRestoreWeapon(__mmWeapon),
(__mmThreatTrapLastAt = __mmNow),
(__mmThreatTrapLastKey = __mmThreat.key));
return !0;
} catch (__mmThreatTrapError) {
return !1;
}
}
function __mmStartThreatTrap() {
__mmThreatTrapTimer ||
(__mmThreatTrapTimer = setInterval(
__mmPlaceThreatTrap,
__mmServerTickMs(),
));
}
function __mmNearestEnemy() {
if (!v || !v.alive) return null;
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));
}
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();
(!__mmEnemyNearby &&
v.tails &&
v.tails[11] &&
v.tailIndex !== 11 &&
__mmEquipTailNow(11),
__mmEnemyNearby && !__mmHasStick() && v.tailIndex === 11 && __mmEquipTailNow(0));
const __mmHat = __mmSpeedHat();
if (!__mmEnemyNearby && v.skins && v.skins[__mmHat]) __mmEquipHatNow(__mmHat);
else if (
__mmBoostTankPreviousHat != null &&
v.skinIndex === 40 &&
__mmCanEquipHat(__mmBoostTankPreviousHat)
)
__mmEquipHatNow(__mmBoostTankPreviousHat);
else if (
__mmInSnowBiome() &&
v.skins &&
v.skins[__mmBoosterHat] &&
v.skinIndex !== __mmBoosterHat
)
__mmEquipHatNow(__mmBoosterHat);
}
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();
(__mmPauseSoldierForBreaking(),
!__mmEnemyWithinCombatRange() &&
v.tails &&
v.tails[11] &&
v.tailIndex !== 11 &&
__mmEquipTailNow(11),
je(__mmPad),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmStartBoostForward(__mmAngle),
__mmBoostTankPreviousHat == null &&
(__mmBoostTankPreviousHat = v.skinIndex),
__mmEquipHatNow(40),
(__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;
((__mmBoostBreakHeld = !0),
__mmBoostBreakTimer ||
(__mmBoostBreakTimer = setInterval(
__mmBoostBreakTick,
__mmServerTickMs(),
)),
__mmStartBoostChat(),
__mmBoostBreakTick());
}
function __mmStopBoostBreak() {
((__mmBoostBreakHeld = !1),
__mmBoostBreakTimer &&
(clearInterval(__mmBoostBreakTimer), (__mmBoostBreakTimer = 0)),
__mmBoostBreakStrikeTimer &&
(clearTimeout(__mmBoostBreakStrikeTimer),
(__mmBoostBreakStrikeTimer = 0)),
(__mmBoostBreakStriking = !1),
__mmBoostBreakPreviousWeapon != null &&
__mmRestoreWeapon(__mmBoostBreakPreviousWeapon),
(__mmBoostBreakPreviousWeapon = null),
__mmStopBoostChat(),
(__mmBoostBreakCooldownWeapon = null),
(__mmBoostBreakReadyAt = 0));
if (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)),
__mmUpdateMovementGear());
}
function __mmStartAutoHeal() {
__mmAutoHealTimer || (__mmAutoHealTimer = setInterval(__mmAutoHeal, 10));
}
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 __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];
if (__mmCount === 2) return [__mmAngle - 0.48, __mmAngle + 0.48];
if (__mmCount === 3)
return [__mmAngle - 0.48, __mmAngle + 0.48, __mmAngle + Math.PI];
return [
__mmAngle - 0.48,
__mmAngle + 0.48,
__mmAngle + Math.PI - 0.48,
__mmAngle + Math.PI + 0.48,
];
}
function __mmPlaceAntiBoostSpikes(__mmAngle) {
const __mmSpike = __mmSpikeItem(),
__mmCount = Math.min(4, __mmMaxBuildCount(__mmSpike));
if (__mmSpike == null || __mmCount < 1) return;
const __mmWeapon = __mmSelectedWeapon(),
__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]));
__mmRestoreWeapon(__mmWeapon);
}
function __mmUpdateAntiBoostSpikes() {
if (__mmInsta.isActive()) return void __mmInsta.cancel("anti-boost");
if (
!__mmAntiBoostEnabled ||
!v ||
!v.alive ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld
)
return;
const __mmNow = Date.now();
if (__mmNow - __mmAntiBoostLast < 350) return;
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
) {
(__mmPlaceAntiBoostSpikes(Math.atan2(__mmToPlayerY, __mmToPlayerX)),
(__mmAntiBoostLast = __mmNow),
(__mmTrail.boostAt = 0));
return;
}
}
}
function __mmStartAntiBoostSpikes() {
__mmAntiBoostTimer ||
(__mmAntiBoostTimer = setInterval(__mmUpdateAntiBoostSpikes, 50));
}
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) {
const __mmSpike = __mmSpikeItem();
if (
!__mmTarget ||
__mmSpike == null ||
!__mmCanUseBuildItem(__mmSpike)
)
return !1;
const __mmWeapon = __mmSelectedWeapon();
const __mmAngle = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x);
(je(__mmSpike),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmRestoreWeapon(__mmWeapon));
return !0;
}
function __mmUpdateReloadSpike() {
const __mmReloading = __mmMusketIsReloading() || __mmTurretGearIsReloading();
if (!__mmReloading) return void (__mmReloadSpikePlaced = !1);
if (
!__mmReloadSpikeEnabled ||
__mmReloadSpikePlaced ||
!v ||
!v.alive ||
__mmInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmFoodSpamTimer ||
__mmAutoHealWasHealing ||
__mmBuildSpamTimer
)
return;
const __mmTarget = __mmReloadSpikeTarget();
__mmTarget && __mmPlaceReloadSpike(__mmTarget) && (__mmReloadSpikePlaced = !0);
}
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 __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;
const __mmGrids = X.getGridArrays(v.x, v.y, Math.max(140, v.scale * 4));
let __mmClosest = null,
__mmClosestDistance = Infinity;
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.trap) continue;
const __mmDistance =
(__mmObject.x - v.x) ** 2 + (__mmObject.y - v.y) ** 2;
__mmDistance < __mmClosestDistance &&
((__mmClosestDistance = __mmDistance), (__mmClosest = __mmObject));
}
return __mmClosest;
}
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 __mmFacing = Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x),
__mmBehind = __mmFacing + Math.PI,
__mmSpike = __mmSpikeItem(),
__mmSpikeCount = 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 = __mmTrapBuildWeapon;
((__mmTrapBuildTimer && clearTimeout(__mmTrapBuildTimer),
(__mmTrapBuildTimer = 0),
(__mmTrapBuildWeapon = null),
__mmClearAttempt && (__mmTrapBuildAttemptKey = null),
__mmWeapon != null && __mmRestoreWeapon(__mmWeapon)));
}
function __mmStartTrapBuildEscape(__mmTrap) {
if (!v || !v.alive || !v.lockMove || !__mmTrap || __mmTrapBuildTimer) return;
const __mmTrapKey = __mmTrapBuildKey(__mmTrap);
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 ||
!v.lockMove ||
__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));
if (__mmIndex < __mmPlan.length) {
__mmTrapBuildTimer = setTimeout(__mmPlaceNext, __mmServerTickMs());
return;
}
__mmStopTrapBuildEscape(!1);
};
__mmTrapBuildTimer = setTimeout(__mmPlaceNext, __mmServerTickMs());
}
function __mmEquipTankForTrap() {
if (!v || !v.alive || !v.skins || !v.skins[40] || __mmRightClickHat != null)
return;
(__mmTrapHat == null && (__mmTrapHat = v.skinIndex),
v.skinIndex !== 40 && __mmEquipHatNow(40));
}
function __mmRestoreTrapHat() {
if (__mmTrapHat == null) return;
if (!v || !v.alive) return void (__mmTrapHat = null);
if (__mmPrimaryHeld || __mmSecondaryHeld || __mmRightClickHat != null) return;
const __mmHat = __mmTrapHat;
((__mmTrapHat = null),
v.skinIndex !== __mmHat &&
__mmCanEquipHat(__mmHat) &&
__mmEquipHatNow(__mmHat));
}
function __mmStopTrapAttack() {
(__mmStopTrapBuildEscape(),
__mmTrapAttackActive &&
(O.send("F", 0, Ci()),
(__mmTrapAttackActive = !1),
__mmRestoreWeapon(__mmTrapWeapon),
(__mmTrapWeapon = null)),
(__mmTrapLastSwingAt = 0),
__mmRestoreTrapHat());
}
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) ||
!__mmWeaponReady(__mmWeapon) ||
__mmDistance > __mmTrapWeaponRange(__mmWeapon, __mmTrap)
)
continue;
return __mmWeapon;
}
return null;
}
function __mmBreakTrap() {
if (__mmInsta.isActive()) return void __mmInsta.cancel("trap-escape");
if (
!__mmTrapEscapeEnabled ||
!v ||
!v.alive ||
!v.lockMove
)
return void __mmStopTrapAttack();
__mmAutoHeal();
const __mmTrap = __mmNearestLockingTrap();
if (__mmTrap == null) return void __mmStopTrapAttack();
__mmStartTrapBuildEscape(__mmTrap);
(__mmTrapAttackActive ||
(__mmPauseSoldierForBreaking(),
(__mmTrapAttackActive = !0),
(__mmTrapWeapon = __mmSelectedWeapon()),
__mmEquipTankForTrap()));
const __mmWeapon = __mmTrapBreakWeapon(__mmTrap);
if (__mmWeapon == null) return;
const __mmNow = Date.now();
const __mmWeaponData = b.weapons[__mmWeapon];
const __mmDelay = Math.max(50, Number(__mmWeaponData.speed) || 400);
if (__mmNow - __mmTrapLastSwingAt < __mmDelay) return;
const __mmAngle = Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x);
(je(__mmWeapon, !0),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
(__mmTrapLastSwingAt = __mmNow));
}
function __mmStartTrapEscape() {
__mmTrapAttackTimer ||
(__mmTrapAttackTimer = setInterval(__mmBreakTrap, __mmServerTickMs()));
}
function __mmStopTrapEscape() {
(__mmTrapAttackTimer &&
(clearInterval(__mmTrapAttackTimer), (__mmTrapAttackTimer = 0)),
__mmStopTrapAttack());
}
function __mmCanAutoSoldier() {
return (
__mmSoldierAutoEnabled &&
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;
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, __mmServerTickMs()));
}
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 ||
(__mmPlayer.team && v.team && __mmPlayer.team === v.team)
)
continue;
__mmEnemies.push(__mmAiEnemySnapshot(__mmPlayer));
}
__mmEnemies.sort(function (__mmFirst, __mmSecond) {
return __mmFirst.distance - __mmSecond.distance;
});
const __mmAngle = __mmTrapAngle();
return {
available: !0,
modVersion: "3.8.4",
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: !!v.lockMove,
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 &&
v &&
v.alive &&
v.weapons.includes(__mmShieldWeapon) &&
!__mmInsta.isActive() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive
);
}
function __mmUseShieldDefense(__mmPlayer) {
if (!__mmCanUseShieldDefense()) return;
const __mmDistance = (__mmPlayer.x - v.x) ** 2 + (__mmPlayer.y - v.y) ** 2;
if (__mmDistance > __mmShieldDefenseRange * __mmShieldDefenseRange) 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 () {
const __mmWeaponToRestore = __mmShieldDefenseWeapon;
((__mmShieldDefenseTimer = 0),
(__mmShieldDefenseWeapon = null),
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
__mmWeaponToRestore != null &&
__mmWeaponToRestore !== __mmShieldWeapon &&
__mmRestoreWeapon(__mmWeaponToRestore));
}, __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 !Number.isFinite(__mmReload) || __mmReload <= 0;
}
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 __mmEquipBullTailForPrimary() {
if (!v || !v.alive) return;
if (v.tails && v.tails[__mmCorruptXWings]) {
(__mmPrimaryClickTail == null && (__mmPrimaryClickTail = v.tailIndex),
__mmEquipTailNow(__mmCorruptXWings));
} else
v.tailIndex === 11 &&
((__mmPrimaryClickTail = v.tailIndex), __mmEquipTailNow(0));
}
function __mmEquipBullForPrimary() {
if (!__mmBullPrimaryAvailable() || !__mmPrimaryWeaponReady()) return;
(__mmPrimaryClickHat == null && (__mmPrimaryClickHat = v.skinIndex),
__mmEquipHatNow(7),
__mmEquipBullTailForPrimary());
}
function __mmRestoreBullForPrimary() {
if (__mmSecondaryHeld || __mmRightClickHat != null) return;
if (!v || !v.alive)
return void ((__mmPrimaryClickHat = null), (__mmPrimaryClickTail = null));
const __mmHat = __mmPrimaryClickHat,
__mmTail = __mmPrimaryClickTail;
((__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
__mmTail != null &&
v.tailIndex !== __mmTail &&
(__mmTail === 0 || (v.tails && v.tails[__mmTail])) &&
__mmEquipTailNow(__mmTail),
__mmHat != null &&
v.skinIndex !== __mmHat &&
(__mmHat === 0 || (v.skins && v.skins[__mmHat])) &&
__mmEquipHatNow(__mmHat));
}
function __mmFirePrimaryBullWeapon() {
__mmPrimaryBullArmTimer = 0;
const __mmWeapon = v && v.weapons ? v.weapons[0] : null;
if (!__mmPrimaryHeld || !__mmBullPrimaryAvailable() || __mmWeapon == null)
return (
(__mmPrimaryBullSwingPending = !1),
void __mmRestoreBullForPrimary()
);
(je(__mmWeapon, !0),
__mmSendWeaponAttack(1),
// Hold Bull Helmet across the full left-click for a stable tick macro.
(__mmPrimaryBullSwingPending = !1));
}
function __mmPulsePrimaryBullWeapon() {
if (
!__mmPrimaryHeld ||
!__mmBullPrimaryAvailable() ||
!__mmPrimaryWeaponReady() ||
__mmPrimaryBullSwingPending
)
return;
const __mmWasBull = v.skinIndex === 7;
__mmEquipBullForPrimary();
if (__mmPrimaryClickHat == null) return void __mmSendWeaponAttack(1);
if (__mmWasBull) return (je(v.weapons[0], !0), 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;
((__mmPrimaryHeld = !0),
__mmStartHeldAttackPulse(),
__mmAtFullHealth() && __mmStopFoodSpam());
}
function __mmStopPrimaryInput() {
((__mmPrimaryHeld = !1),
__mmPrimaryBullArmTimer &&
(clearTimeout(__mmPrimaryBullArmTimer), (__mmPrimaryBullArmTimer = 0)),
(__mmPrimaryBullSwingPending = !1),
__mmStopHeldAttackPulse(),
__mmSecondaryHeld && __mmPulseHeldAttack(),
__mmRestoreBullForPrimary(),
__mmRestoreTrapHat());
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (!__mmIsGameClick(__mmEvent) || __mmEvent.button !== 0) return;
// 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");
(__mmEvent.preventDefault(),
__mmEvent.stopImmediatePropagation(),
__mmStartPrimaryInput());
},
!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 __mmSecondary = __mmSecondaryWeapon(),
__mmData =
__mmSecondary == null ? null : b && b.weapons && b.weapons[__mmSecondary];
return __mmSecondary == null
? null
: __mmData && __mmData.projectile != null && v.weapons[0] != null
? v.weapons[0]
: __mmSecondary;
}
function __mmRightClickWeaponReady() {
const __mmWeapon = __mmRightClickWeapon();
return __mmWeapon != null && __mmWeaponReady(__mmWeapon);
}
function __mmServerTickMs() {
return Math.max(
60,
Math.ceil(1e3 / Math.max(1, Number(y && y.serverUpdateRate) || 9)),
);
}
function __mmEquipTankForSecondary() {
if (
!__mmTankRightClickEnabled ||
!v ||
!v.alive ||
!__mmRightClickWeaponReady() ||
!v.skins ||
!v.skins[40]
)
return;
(__mmRememberNormalHat(),
__mmRightClickHat == null &&
(__mmRightClickHat =
v.skinIndex === 40 ? __mmLastNormalHat : v.skinIndex),
__mmEquipHatNow(40));
}
function __mmRestoreRightClickHat() {
if (__mmRightClickHat == null) return;
if (!v || !v.alive) return void (__mmRightClickHat = null);
const __mmHat =
__mmRightClickHat === 40 ? __mmLastNormalHat : __mmRightClickHat;
((__mmRightClickHat = null), __mmEquipHatNow(__mmHat));
}
function __mmFireSecondaryTankWeapon() {
__mmSecondaryTankArmTimer = 0;
if (!__mmSecondaryHeld || !__mmRightClickWeaponReady())
return (
(__mmSecondaryTankSwingPending = !1),
void __mmRestoreRightClickHat()
);
const __mmWeapon = __mmRightClickWeapon();
if (__mmWeapon == null)
return (
(__mmSecondaryTankSwingPending = !1),
void __mmRestoreRightClickHat()
);
(je(__mmWeapon, !0),
__mmSendWeaponAttack(1),
// Keep Tank Gear on for the held right-click. Restoring it after every
// swing caused a tick-by-tick Tank/normal-hat flicker.
(__mmSecondaryTankSwingPending = !1));
}
function __mmPulseSecondaryWeapon() {
if (
!__mmSecondaryHeld ||
!__mmRightClickWeaponReady() ||
__mmSecondaryTankSwingPending
)
return;
const __mmWeapon = __mmRightClickWeapon(),
__mmUseTank = !!(__mmTankRightClickEnabled && v && v.skins && v.skins[40]),
__mmWasTank = __mmTankGearActive();
if (__mmWeapon == null) return;
if (!__mmUseTank)
return (je(__mmWeapon, !0), void __mmSendWeaponAttack(1));
__mmEquipTankForSecondary();
if (__mmRightClickHat == null)
return (je(__mmWeapon, !0), void __mmSendWeaponAttack(1));
if (__mmWasTank) 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());
}
function __mmFinishSecondaryInput() {
(__mmStopSecondary(), __mmRestoreBullForPrimary());
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (__mmEvent.button !== 2 || !__mmIsGameClick(__mmEvent))
return void __mmRestoreRightClickHat();
__mmInsta.isActive() && __mmInsta.cancel("manual-secondary");
if (!__mmTankRightClickEnabled || __mmRightClickWeapon() == null)
return void __mmRestoreRightClickHat();
(__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) {
__mmEvent.button === 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(),
__mmStopWindmillHold(),
__mmInsta.cancel("window-blur"),
__mmRestoreBullForPrimary(),
__mmStopShiftSpeed(),
__mmRestoreMovementGear());
});
document.addEventListener("visibilitychange", function () {
document.hidden &&
(__mmStopPrimaryInput(),
__mmStopSecondary(),
__mmStopWindmillHold(),
__mmInsta.cancel("document-hidden"),
__mmStopShiftSpeed(),
__mmRestoreMovementGear());
});
function __mmSendKillMessage() {
if (!__mmKillMessageEnabled || !__mmKillMessage || !v || !v.alive) return;
__mmSendChat(__mmKillMessage);
}
__mmStartAutoHeal();
__mmStartTrapEscape();
__mmStartSoldierAuto();
__mmStartMovementGear();
__mmStartMusketRecharge();
__mmStartAutoPurchase();
__mmStartAntiBoostSpikes();
__mmStartThreatTrap();
__mmStartReloadSpike();
$l = function (__mmPlayerSid, __mmHealth) {
const __mmResult = __mmOriginalHealthUpdate.apply(this, arguments);
if (v && __mmPlayerSid === v.sid) {
__mmObserveAutoHealHealth(__mmHealth);
// R owns a very short attack window. Routine food changes selection and
// can erase the queued strike, so defer it until cleanup. Critical health
// still wins and immediately cancels the burst.
if (__mmInsta.isActive()) {
__mmInsta.isEmergencyHealth() &&
__mmInsta.cancel("health-emergency");
} else __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
);
};
Pl = function (__mmPlayerSid, __mmAngle, __mmWeapon) {
__mmTrackTurretGearReload(__mmPlayerSid);
__mmHandleEnemyPolearmSwing(__mmPlayerSid, __mmWeapon);
return __mmOriginalPlayerAttack.apply(this, arguments);
};
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 "t==67?void 0: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 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 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],
["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(/from"\.\/vendor-[^"]+\.js"/, (specifier) => {
const path = specifier.slice(5, -1);
return `from"${new URL(path, bundleUrl).href}"`;
});
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 interceptGameBundle(script) {
if (gameScriptHijacked || !script.src || !GAME_BUNDLE.test(new URL(script.src, location.href).pathname)) return;
gameScriptHijacked = true;
const originalUrl = script.src;
script.type = "application/x-moomoo-scroll-zoom-blocked";
script.removeAttribute("src");
script.remove();
loadPatchedBundle(originalUrl);
}
const observer = 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);
}
}
}
});
observer.observe(document, { childList: true, subtree: true });
document.querySelectorAll("script[src]").forEach(interceptGameBundle);
document.addEventListener("readystatechange", () => {
if (!gameScriptHijacked && document.readyState === "interactive") {
document.querySelectorAll("script[src]").forEach(interceptGameBundle);
}
}, { once: true });
})();