kitty klient — a MooMoo.io client with adaptive zoom, fast autoheal, gear automation, combat tools, predictive placement, visual markers, manual quick builds, and a fully rebindable keyboard/mouse controls HUD.
// ==UserScript==
// @name kitty klient
// @author Coder Guy
// @version 4.2.4
// @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, predictive placement, visual markers, manual quick builds, and a fully rebindable keyboard/mouse controls HUD.
// @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 CHAT_HISTORY_ID = "kitty-klient-chat-history";
const CHAT_HISTORY_COLLAPSED_KEY = "kitty-klient-chat-history-collapsed-v1";
const HUD_STORAGE_KEY = "moomoo-op-hud-settings-v1";
const KILL_MESSAGE_AUTO_MIGRATION_KEY = "kitty-klient-kill-message-auto-v1";
const PLACEMENT_CORE_AUTO_MIGRATION_KEY = "kitty-klient-placement-core-auto-v3";
const INSTA_HOTKEY_AUTO_MIGRATION_KEY = "kitty-klient-r-insta-auto-v1";
const TAB_SYNC_BRIDGE_KEY = "kitty-klient-tab-sync-bridge-v1";
const KITTY_KLIENT_VERSION = "4.2.4";
const KITTY_AUX_PANELS_VISIBLE = true;
const KITTY_TUTORIAL_ID = "kitty-klient-tutorial";
const KITTY_TUTORIAL_COMPLETE_KEY = "kitty-klient-tutorial-complete-v1";
const KITTY_HUD_LAUNCHER_ID = "kitty-klient-hud-launcher";
const KITTY_UPDATE_POPUP_ID = "kitty-klient-update-popup";
const KITTY_UPDATE_DISMISS_KEY = "kitty-klient-dismissed-update-v1";
const KITTY_UPDATE_API = "https://api.greasyfork.org/en/scripts/592072.json";
const KITTY_UPDATE_FALLBACK_URL = "https://update.greasyfork.org/scripts/592072/kitty%20klient.user.js";
function installKittyUpgradeModuleUnlock() {
if (window.__KittyUpgradeModuleUnlockInstalled) return;
window.__KittyUpgradeModuleUnlockInstalled = true;
const nativeCall = Function.prototype.call;
let callProxy = null;
const restoreCall = () => {
if (Function.prototype.call === callProxy) Function.prototype.call = nativeCall;
if (!window.__KittyUpgradeModuleData)
window.__KittyUpgradeModuleUnlockInstalled = false;
};
const unlockData = (data) => {
if (!data || !Array.isArray(data.weapons) || !Array.isArray(data.list)) return false;
if (!window.__KittyVanillaUpgradePrerequisites) {
window.__KittyVanillaUpgradePrerequisites = {
weapons: data.weapons.map((entry) => entry && entry.pre),
items: data.list.map((entry) => entry && entry.pre)
};
}
data.weapons.forEach((entry) => {
if (entry && entry.pre != null) entry.pre = null;
});
data.list.forEach((entry) => {
if (entry && entry.pre != null) entry.pre = null;
});
window.__KittyUpgradeModuleData = data;
return true;
};
callProxy = new Proxy(nativeCall, {
apply(target, thisArg, args) {
try {
// Intercept the MooMoo item-data module loader here. Keep
// the interception narrow and restore the
// native prototype immediately after item module 45 loads.
if (args[1] && Number(args[1].i) === 21 && typeof args[3] === "function") {
const moduleGetter = args[3];
args[3] = function (id) {
const data = Reflect.apply(moduleGetter, this, arguments);
if (Number(id) === 45 && unlockData(data)) {
args[3] = moduleGetter;
restoreCall();
}
return data;
};
}
} catch (_) {
// The injected runtime has a direct data-module fallback.
}
return Reflect.apply(target, thisArg, args);
}
});
Function.prototype.call = callProxy;
window.setTimeout(restoreCall, 12000);
}
const KITTY_BINDING_ACTIONS = Object.freeze([
Object.freeze({ id: "toggleHud", group: "Menu & view", binding: "Escape", action: "Toggle Kitty HUD", note: "Closes MooMoo shop, clan, or chat first when one is open." }),
Object.freeze({ id: "primaryAttack", group: "Combat & gear", binding: "Mouse0", action: "Primary attack", note: "Held attack with Kitty's Bull and tail timing.", hold: true }),
Object.freeze({ id: "secondaryAttack", group: "Combat & gear", binding: "Mouse2", action: "Secondary attack / Tank", note: "Held secondary or situational Shield/Tank path.", hold: true }),
Object.freeze({ id: "clickBoostInsta", group: "Combat & gear", binding: "Shift+Mouse0", action: "Click Boost Insta", note: "Starts Boost Insta when ready; otherwise continues as a primary hold.", hold: true }),
Object.freeze({ id: "normalInsta", group: "Combat & gear", binding: "KeyR", action: "Normal Insta", note: "Runs the selected full Insta profile or Bush manual ambush." }),
Object.freeze({ id: "boostInsta", group: "Combat & gear", binding: "Shift+KeyR", action: "Boost Insta", note: "Requires the Crossbow Insta kit." }),
Object.freeze({ id: "oneTickInsta", group: "Combat & gear", binding: "Shift+KeyP", action: "Toggle One-Tick Insta", note: "Toggles the secondary-first one-tick profile." }),
Object.freeze({ id: "velTickInsta", group: "Combat & gear", binding: "KeyT", action: "Toggle VelTick Insta", note: "Toggles predictive spacing and Turret/Polearm timing." }),
Object.freeze({ id: "boostSpike", group: "Combat & gear", binding: "KeyG", action: "Boost + Spike", note: "Continuously solves legal contact spikes while held.", hold: true }),
Object.freeze({ id: "quadTrap", group: "Combat & gear", binding: "Shift+KeyB", action: "Manual Quad Trap", note: "Forces one legal four-slot trap solve." }),
Object.freeze({ id: "quadSpike", group: "Combat & gear", binding: "Shift+KeyC", action: "Manual Quad Spike", note: "Forces one legal four-slot spike solve." }),
Object.freeze({ id: "betrayalInsta", group: "Combat & gear", binding: "Shift+KeyT", action: "Betrayal Insta", note: "Leaves the team and attacks the nearest eligible player." }),
Object.freeze({ id: "toggleAutoHeal", group: "Combat & gear", binding: "KeyP", action: "Toggle Autoheal", note: "Changes Autoheal without opening the HUD." }),
Object.freeze({ id: "food", group: "Building & supplies", binding: "KeyQ", action: "Food", note: "Repeatedly uses the current food while held.", hold: true }),
Object.freeze({ id: "trapBuild", group: "Building & supplies", binding: "KeyF", action: "Pit trap", note: "Repeatedly places the current trap while held.", hold: true }),
Object.freeze({ id: "spikeBuild", group: "Building & supplies", binding: "KeyV", action: "Spike", note: "Repeatedly places the current spike while held.", hold: true }),
Object.freeze({ id: "specialBuild", group: "Building & supplies", binding: "KeyH", action: "Special deployable", note: "Repeats the active turret, teleporter, pad, platform, or blocker.", hold: true }),
Object.freeze({ id: "boostBreak", group: "Building & supplies", binding: "Shift+KeyF", action: "Boost-break", note: "Boosts forward and destroys each pad behind you while held.", hold: true }),
Object.freeze({ id: "movingMills", group: "Modes & automation", binding: "KeyZ", action: "Toggle moving three-mill", note: "Primary Automill toggle." }),
Object.freeze({ id: "movingMillsAlt", group: "Modes & automation", binding: "KeyN", action: "Toggle moving three-mill (alternate)", note: "Second independently editable Automill shortcut." }),
Object.freeze({ id: "bushMode", group: "Modes & automation", binding: "KeyB", action: "Toggle Bush ambush", note: "Purchases and holds Bush Gear when possible." }),
Object.freeze({ id: "cleanup", group: "Modes & automation", binding: "KeyC", action: "Toggle Cleanup", note: "Starts or stops automatic nearby breakable cleanup." }),
Object.freeze({ id: "friendPick", group: "Friends & teammate sync", binding: "KeyU", action: "Add friend", note: "Arms click-to-friend selection for a non-teammate." }),
Object.freeze({ id: "enemyPick", group: "Friends & teammate sync", binding: "KeyI", action: "Mark enemy", note: "Arms click-to-enemy selection." }),
Object.freeze({ id: "syncPick", group: "Friends & teammate sync", binding: "KeyY", action: "Select sync teammate", note: "Arms click-to-sync selection for a teammate." })
]);
const KITTY_DEFAULT_KEYBINDS = Object.freeze(Object.fromEntries(
KITTY_BINDING_ACTIONS.map((entry) => [entry.id, entry.binding])
));
const HUD_DEFAULTS = Object.freeze({
autoHeal: true,
soldierAuto: true,
movementGear: true,
trapEscape: true,
automaticStateRepair: true,
autoAcceptTeamRequests: false,
autoDeclineTeamRequests: false,
autoRespawn: false,
antiBoostInsta: true,
antiInsta: true,
antiCollision: true,
antiCollisionPauseCombat: true,
shieldDefense: true,
placementDefense: true,
antiRetrapPush: true,
teammateTrapRescue: true,
turretSteal: true,
spikeGearCounter: true,
dashMovement: true,
musketRecharge: true,
autoPurchase: false,
matThief: false,
multiTargetBreak: true,
mobSteal: false,
assassinAutomation: false,
spinningWindmills: false,
forceFullServers: true,
bushMode: false,
fpsBoost: true,
smoothVisuals: true,
reloadArcs: true,
entityDanger: true,
notificationTracers: true,
groundGrid: false,
esp: true,
espLines: true,
predictionGhost: true,
placementVisuals: true,
cooldownBars: true,
weaponXpBar: true,
chatHistory: true,
combatTelemetry: false,
telemetryProjectileHits: true,
telemetrySpikeKnockback: true,
telemetryActualAim: true,
telemetryBuildingOwners: true,
telemetryShameCount: true,
telemetryDamageHealing: true,
enemyColor: "#ff4d5d",
allyColor: "#a855f7",
friendColor: "#facc15",
ownColor: "#d8b4fe",
bullHelmet: true,
tankRightClick: true,
instaKill: true,
autoInsta: true,
autoBowUpgradeInsta: false,
reverseInsta: false,
oneTickInsta: false,
appleInsta: false,
bleedInsta: false,
knockbackInsta: false,
velTickInsta: false,
polearmAids: false,
autoPushInsta: false,
boostSpikeKill: true,
autoTrapInsta: true,
autoSpikeInsta: true,
autoSpikeSpam: false,
autoSpikeKill: false,
animalTrap: false,
passiveMobTrap: false,
bossTeleporter: false,
smartAutoPlace: true,
smartPreplace: true,
smartMultiPlace: true,
smartQuadTraps: true,
smartQuadSpikes: true,
smartSpikeContact: true,
smartTrapContact: true,
smartKnockbackChain: true,
smartTrapSurround: true,
smartAngleDenial: true,
smartAutoPushWeight: true,
smartAutoReplace: false,
smartSpikeSyncPlace: false,
smartAntiBoostPlace: false,
smartMovingMills: false,
smartInstaUtilityPlace: false,
instaSync: true,
boostBreak: true,
boostChat: true,
materialReply: true,
meowChainInsta: true,
instaChat: true,
bushChat: true,
friendAddedChat: true,
enemyMarkedChat: true,
cleanupProgressChat: true,
cleanupCompleteChat: true,
modReplyChat: true,
enemyTrapChat: true,
friendTrapChat: true,
trapAlertChat: true,
deathHistoryChat: true,
syncStatusChat: true,
syncMovement: true,
syncCopyWeapons: true,
syncCopyBuilds: true,
syncCopyGear: true,
syncCopyAim: true,
syncCopyAttacks: true,
syncCatchupGear: true,
syncPauseInCombat: false,
syncWasdCombatOnly: true,
syncTickCombat: true,
syncFollowGap: 12,
syncStopTolerance: 4,
syncResumeTolerance: 9,
syncPredictionMs: 130,
syncCatchupDistance: 420,
syncCatchupReleaseDistance: 190,
syncMoveRefreshMs: 50,
syncRelayUrl: "",
syncRoom: "",
syncStatus: "Sync off",
syncTargetName: "",
soldierRange: 400,
combatRange: 400,
gearHoldTicks: 3,
antiBoostRange: 200,
antiCollisionRange: 260,
reactionMs: 25,
adaptiveSmartness: true,
smartDepth: 5,
smartPlaceAccuracy: 50,
smartMaxPlacements: 4,
smartPlaceDelay: 111,
assassinSafeMs: 2000,
assassinMinHealth: 80,
assassinDangerRange: 650,
debugPanel: false,
killMessageEnabled: true,
killMessage: "gg",
friendNames: [],
keybinds: KITTY_DEFAULT_KEYBINDS
});
const HUD_BOOLEAN_KEYS = Object.freeze([
"autoHeal",
"soldierAuto",
"movementGear",
"trapEscape",
"automaticStateRepair",
"autoAcceptTeamRequests",
"autoDeclineTeamRequests",
"autoRespawn",
"antiBoostInsta",
"antiInsta",
"antiCollision",
"antiCollisionPauseCombat",
"shieldDefense",
"placementDefense",
"antiRetrapPush",
"teammateTrapRescue",
"turretSteal",
"spikeGearCounter",
"dashMovement",
"musketRecharge",
"autoPurchase",
"matThief",
"multiTargetBreak",
"mobSteal",
"assassinAutomation",
"spinningWindmills",
"forceFullServers",
"bushMode",
"fpsBoost",
"smoothVisuals",
"reloadArcs",
"entityDanger",
"notificationTracers",
"groundGrid",
"esp",
"espLines",
"predictionGhost",
"placementVisuals",
"cooldownBars",
"weaponXpBar",
"chatHistory",
"combatTelemetry",
"telemetryProjectileHits",
"telemetrySpikeKnockback",
"telemetryActualAim",
"telemetryBuildingOwners",
"telemetryShameCount",
"telemetryDamageHealing",
"bullHelmet",
"tankRightClick",
"instaKill",
"autoInsta",
"autoBowUpgradeInsta",
"reverseInsta",
"oneTickInsta",
"appleInsta",
"bleedInsta",
"knockbackInsta",
"velTickInsta",
"polearmAids",
"autoPushInsta",
"boostSpikeKill",
"autoTrapInsta",
"autoSpikeInsta",
"autoSpikeSpam",
"autoSpikeKill",
"animalTrap",
"passiveMobTrap",
"bossTeleporter",
"smartAutoPlace",
"smartPreplace",
"smartMultiPlace",
"smartQuadTraps",
"smartQuadSpikes",
"smartSpikeContact",
"smartTrapContact",
"smartKnockbackChain",
"smartTrapSurround",
"smartAngleDenial",
"smartAutoPushWeight",
"smartAutoReplace",
"smartSpikeSyncPlace",
"smartAntiBoostPlace",
"smartMovingMills",
"smartInstaUtilityPlace",
"adaptiveSmartness",
"instaSync",
"boostBreak",
"boostChat",
"materialReply",
"meowChainInsta",
"instaChat",
"bushChat",
"friendAddedChat",
"enemyMarkedChat",
"cleanupProgressChat",
"cleanupCompleteChat",
"modReplyChat",
"enemyTrapChat",
"friendTrapChat",
"trapAlertChat",
"deathHistoryChat",
"syncStatusChat",
"syncMovement",
"syncCopyWeapons",
"syncCopyBuilds",
"syncCopyGear",
"syncCopyAim",
"syncCopyAttacks",
"syncCatchupGear",
"syncPauseInCombat",
"syncWasdCombatOnly",
"syncTickCombat",
"debugPanel",
"killMessageEnabled"
]);
const HUD_NUMERIC_BOUNDS = Object.freeze({
soldierRange: Object.freeze({ min: 100, max: 1000, step: 10 }),
combatRange: Object.freeze({ min: 100, max: 1000, step: 10 }),
gearHoldTicks: Object.freeze({ min: 1, max: 8, step: 1 }),
antiBoostRange: Object.freeze({ min: 80, max: 500, step: 10 }),
antiCollisionRange: Object.freeze({ min: 120, max: 500, step: 10 }),
reactionMs: Object.freeze({ min: 10, max: 100, step: 5 }),
smartDepth: Object.freeze({ min: 1, max: 10, step: 1 }),
smartPlaceAccuracy: Object.freeze({ min: 20, max: 180, step: 5 }),
smartMaxPlacements: Object.freeze({ min: 1, max: 4, step: 1 }),
smartPlaceDelay: Object.freeze({ min: 0, max: 222, step: 1 }),
assassinSafeMs: Object.freeze({ min: 500, max: 5000, step: 100 }),
assassinMinHealth: Object.freeze({ min: 20, max: 100, step: 5 }),
assassinDangerRange: Object.freeze({ min: 250, max: 1200, step: 25 }),
syncFollowGap: Object.freeze({ min: 2, max: 120, step: 1 }),
syncStopTolerance: Object.freeze({ min: 1, max: 30, step: 1 }),
syncResumeTolerance: Object.freeze({ min: 2, max: 60, step: 1 }),
syncPredictionMs: Object.freeze({ min: 0, max: 300, step: 5 }),
syncCatchupDistance: Object.freeze({ min: 100, max: 1200, step: 10 }),
syncCatchupReleaseDistance: Object.freeze({ min: 50, max: 800, step: 10 }),
syncMoveRefreshMs: Object.freeze({ min: 16, max: 250, step: 1 })
});
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 NATIVE_GROUND_GRID_MARKER = 'k.lineWidth=4,k.strokeStyle="#000",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(),';
// The HUD kill-message hook wraps this local game function. Validate it before
// injecting so a renamed game bundle falls back cleanly instead of half-loading.
const PLAYER_STAT_UPDATE_MARKER = "function Kl(";
const CHAT_DISPLAY_MARKER = "function dl(";
// __mmInsta depends on both functions below to bind a target by SID and
// to coexist with the game's normal attack dispatch. Missing either means
// the complete patched bundle is abandoned in favor of the original.
const INSTA_PLAYER_LOOKUP_MARKER = "function Rt(";
const INSTA_PLAYER_ATTACK_MARKER = "function Pl(";
const FORCE_FULL_DIRECT_MARKER = 's.playerCount>=s.playerCapacity){this.errorCallback("Server is already full.");return}';
const FORCE_FULL_FILTER_MARKER = ".filter(function(h){return h.playerCount<n})";
const FORCE_FULL_AUTO_MARKER = "e=e.filter(n=>n.playerCount!==n.playerCapacity)";
const FORCE_FULL_SPAWN_MARKER = "moofoll:xt";
const BUNDLE_RETRY_LIMIT = 8;
const BUNDLE_RETRY_DELAY_MS = 250;
const PATCHED_MODULE_RETRY_LIMIT = 3;
let viewMultiplier = 1 / 0.75;
let hideIndicatorTimer = 0;
let gameScriptHijacked = false;
let originalBundleLoaded = false;
let restoreBundleInsertionGuards = () => {};
let hudMounted = false;
let hudSettingsSent = false;
let hudState = readHudSettings();
let hudOpen = false;
let kittyTutorialIndex = 0;
let kittyTutorialActive = false;
let kittyTutorialHudWasOpen = false;
let hotkeyCaptureAction = null;
let hotkeyCaptureButton = null;
const chatHistoryEntries = [];
const hudControls = new Map();
window.__MooMooScrollZoomMultiplier = viewMultiplier;
window.__KittySmartAutoPlace = hudState.smartAutoPlace !== false;
applyForceFullServersPreference(hudState.forceFullServers);
document.documentElement &&
!document.documentElement.hasAttribute("data-kitty-spinning-windmills") &&
document.documentElement.setAttribute("data-kitty-spinning-windmills", "0");
installKittyClanPingSocketObserver();
// Arm the game-bundle interception before theme installation, HUD work, or
// any optional network request. This userscript is intentionally large;
// waiting until its final lines left a first-navigation race where the
// outer UI loaded but MooMoo's original module escaped unpatched.
installSynchronousBundleGuards();
const gameBundleObserver = new MutationObserver((records) => {
for (const record of records) {
for (const node of record.addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE && node.tagName === "SCRIPT") {
interceptGameBundle(node);
} else if (node.nodeType === Node.ELEMENT_NODE && node.querySelectorAll) {
node.querySelectorAll("script[src]").forEach(interceptGameBundle);
}
}
}
});
gameBundleObserver.observe(document, { childList: true, subtree: true });
document.querySelectorAll("script[src]").forEach(interceptGameBundle);
// Firefox exposes a cancellable last-chance event for parser-inserted
// scripts. Chromium simply ignores this listener and uses the synchronous
// DOM guards plus the observer above.
document.addEventListener("beforescriptexecute", (event) => {
const script = event.target;
if (script instanceof HTMLScriptElement && interceptGameBundle(script)) {
event.preventDefault();
event.stopImmediatePropagation();
}
}, true);
document.addEventListener("readystatechange", () => {
if (!gameScriptHijacked && document.readyState === "interactive") {
document.querySelectorAll("script[src]").forEach(interceptGameBundle);
}
}, { once: true });
window.addEventListener("load", () => {
// If the page never produced the MooMoo module, stop wrapping DOM APIs.
// Normal successful interception restores them immediately in claimGameBundle.
if (!gameScriptHijacked) restoreBundleInsertionGuards();
}, { once: true });
function decodeKittyMessagePack(input) {
const bytes = input instanceof Uint8Array
? input
: new Uint8Array(input.buffer || input, input.byteOffset || 0, input.byteLength);
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
const decoder = new TextDecoder();
let offset = 0;
const take = (length) => {
if (offset + length > bytes.length) throw new RangeError("short packet");
const start = offset;
offset += length;
return start;
};
const text = (length) => {
const start = take(length);
return decoder.decode(bytes.subarray(start, start + length));
};
const array = (length) => {
const value = new Array(length);
for (let index = 0; index < length; index += 1) value[index] = read();
return value;
};
const map = (length) => {
const value = {};
for (let index = 0; index < length; index += 1) value[String(read())] = read();
return value;
};
const read = () => {
const code = view.getUint8(take(1));
if (code <= 0x7f) return code;
if (code >= 0xe0) return code - 0x100;
if (code >= 0xa0 && code <= 0xbf) return text(code & 0x1f);
if (code >= 0x90 && code <= 0x9f) return array(code & 0x0f);
if (code >= 0x80 && code <= 0x8f) return map(code & 0x0f);
let start;
switch (code) {
case 0xc0: return null;
case 0xc2: return false;
case 0xc3: return true;
case 0xca: start = take(4); return view.getFloat32(start);
case 0xcb: start = take(8); return view.getFloat64(start);
case 0xcc: return view.getUint8(take(1));
case 0xcd: start = take(2); return view.getUint16(start);
case 0xce: start = take(4); return view.getUint32(start);
case 0xcf:
start = take(8);
return Number(view.getBigUint64(start));
case 0xd0: return view.getInt8(take(1));
case 0xd1: start = take(2); return view.getInt16(start);
case 0xd2: start = take(4); return view.getInt32(start);
case 0xd3:
start = take(8);
return Number(view.getBigInt64(start));
case 0xd9: return text(view.getUint8(take(1)));
case 0xda: start = take(2); return text(view.getUint16(start));
case 0xdb: start = take(4); return text(view.getUint32(start));
case 0xdc: start = take(2); return array(view.getUint16(start));
case 0xdd: start = take(4); return array(view.getUint32(start));
case 0xde: start = take(2); return map(view.getUint16(start));
case 0xdf: start = take(4); return map(view.getUint32(start));
default: throw new TypeError("unsupported packet value " + code);
}
};
return read();
}
function observeKittyClanPingPacket(rawData) {
if (typeof rawData === "string") return;
if (typeof Blob === "function" && rawData instanceof Blob) {
rawData.arrayBuffer().then(observeKittyClanPingPacket).catch(() => {});
return;
}
if (!(rawData instanceof ArrayBuffer) && !ArrayBuffer.isView(rawData)) return;
try {
const packet = decodeKittyMessagePack(rawData);
// Incoming packet 9 is MooMoo's teammate minimap distress ping.
// Packet p is unrelated and previously produced false top-left
// alerts when its payload happened to resemble two coordinates.
if (!Array.isArray(packet) || String(packet[0]) !== "9") return;
const payload = packet.length === 2 && Array.isArray(packet[1])
? packet[1]
: packet.slice(1);
const coordinates = payload.length === 1 && payload[0] &&
typeof payload[0] === "object" && !Array.isArray(payload[0])
? payload[0]
: payload;
const x = Number(coordinates.x ?? coordinates[0]);
const y = Number(coordinates.y ?? coordinates[1]);
if (!Number.isFinite(x) || !Number.isFinite(y)) return;
window.dispatchEvent(new CustomEvent("MooMooKittyClanPing", {
detail: { x, y, at: Date.now() }
}));
} catch (_) {}
}
function installKittyClanPingSocketObserver() {
if (window.__KittyClanPingSocketObserver || typeof WebSocket !== "function") return;
const NativeWebSocket = window.WebSocket;
function KittyObservedWebSocket(...args) {
const socket = Reflect.construct(NativeWebSocket, args, NativeWebSocket);
socket.addEventListener("message", (event) => observeKittyClanPingPacket(event.data));
return socket;
}
Object.setPrototypeOf(KittyObservedWebSocket, NativeWebSocket);
KittyObservedWebSocket.prototype = NativeWebSocket.prototype;
try {
window.WebSocket = KittyObservedWebSocket;
window.__KittyClanPingSocketObserver = true;
} catch (_) {}
}
function installCanvasTextTheme() {
const prototype = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
if (!prototype || prototype.__kittyKlientTextTheme) return;
Object.defineProperty(prototype, "__kittyKlientTextTheme", { value: true });
["fillText", "strokeText"].forEach((method) => {
const original = prototype[method];
if (typeof original !== "function") return;
prototype[method] = function (...args) {
const previousShadowColor = this.shadowColor;
const previousShadowBlur = this.shadowBlur;
const previousFillStyle = this.fillStyle;
try {
this.shadowColor = "#8b5cf6";
this.shadowBlur = Math.max(8, Number(this.shadowBlur) || 0);
if (method === "fillText") {
const current = String(previousFillStyle || "").replace(/\s+/g, "").toLowerCase();
const dark = current === "#000" || current === "#000000" || current === "black" ||
/^rgba?\((?:0,){2}0(?:,|\))/.test(current);
this.fillStyle = dark ? "#050505" : "#ffffff";
}
return original.apply(this, args);
} finally {
this.shadowColor = previousShadowColor;
this.shadowBlur = previousShadowBlur;
this.fillStyle = previousFillStyle;
}
};
});
}
function applyKittyNameTrademark() {
const input = document.getElementById("nameInput");
if (!input) return;
const prefix = "k-";
const storedOriginal = Number(input.dataset.kittyOriginalNameMax);
const originalMax = Number.isFinite(storedOriginal) && storedOriginal > 2
? storedOriginal
: Math.max(3, Number(input.maxLength) || 15);
const nameLimit = Math.max(1, originalMax - 2);
input.dataset.kittyOriginalNameMax = String(originalMax);
input.dataset.kittyNameLimit = String(nameLimit);
input.maxLength = originalMax;
input.setAttribute("maxlength", String(originalMax));
input.placeholder = "k-Your Name";
const normalize = () => {
const normalized = prefix + String(input.value || "")
.replace(/^(?:k-)+/i, "")
.slice(0, nameLimit);
if (input.value !== normalized) input.value = normalized;
if (
document.activeElement === input &&
input.selectionStart != null &&
input.selectionEnd != null &&
input.selectionStart < prefix.length &&
input.selectionEnd < prefix.length
)
input.setSelectionRange(prefix.length, prefix.length);
};
normalize();
if (!input.dataset.kittyNameTrademarkBound) {
input.dataset.kittyNameTrademarkBound = "1";
input.addEventListener("input", normalize);
input.addEventListener("change", normalize);
const protectPrefix = (event) => {
const start = Number(input.selectionStart),
end = Number(input.selectionEnd),
inputType = String(event.inputType || ""),
touchesPrefix = start < prefix.length ||
(inputType === "deleteContentBackward" &&
start === prefix.length && end === start);
if (!Number.isFinite(start) || !Number.isFinite(end) || !touchesPrefix)
return;
if (!inputType.startsWith("delete") && !inputType.startsWith("insert"))
return;
event.preventDefault();
const insertion = inputType.startsWith("insert")
? String(event.data || (event.dataTransfer && event.dataTransfer.getData("text/plain")) || "")
: "";
input.setRangeText(insertion, prefix.length, Math.max(prefix.length, end), "end");
normalize();
input.dispatchEvent(new Event("input", { bubbles: true }));
};
const clampCaret = () => {
normalize();
if (
input.selectionStart != null &&
input.selectionEnd != null &&
input.selectionStart === input.selectionEnd &&
input.selectionStart < prefix.length
)
input.setSelectionRange(prefix.length, prefix.length);
};
input.addEventListener("beforeinput", protectPrefix);
input.addEventListener("focus", clampCaret);
input.addEventListener("click", clampCaret);
input.addEventListener("keyup", clampCaret);
}
}
const KITTY_TUTORIAL_STEPS = Object.freeze([
Object.freeze({
phase: "menu",
target: "#gameName,[data-kitty-brand]",
eyebrow: "Welcome",
title: "Meet kitty klient",
copy: "Kitty adds automation, combat helpers, visual tools, teammate sync, and a full control HUD while keeping MooMoo's normal menu available."
}),
Object.freeze({
phase: "menu",
target: "#nameInput",
eyebrow: "Your name",
title: "The k- tag is automatic",
copy: "Type the part of your name after k-. The prefix is shown in the box, cannot be deleted, and is included when you enter the game."
}),
Object.freeze({
phase: "menu",
target: "#enterGame",
eyebrow: "Start playing",
title: "Play normally from here",
copy: "Pick a server and press Play when ready. Starting the game closes this guide; you can replay it from the Tutorial button at any time."
}),
Object.freeze({
phase: "menu",
target: "#kitty-klient-home-tutorial",
eyebrow: "Replay",
title: "Tutorial stays available",
copy: "The automatic tour only appears for first-time users. This button always starts it again without resetting any of your settings."
}),
Object.freeze({
phase: "hud",
page: "automation",
target: "#moomoo-op-hud .mm-hud-panel",
eyebrow: "Esc HUD",
title: "Escape opens the control center",
copy: "Esc or the in-game Menu button opens Kitty's HUD. Use Esc or × to close it. If shop, clan, or chat is open, Esc closes that first."
}),
Object.freeze({
phase: "hud",
page: "automation",
target: "#moomoo-op-hud [data-page='automation'].mm-hud-page",
eyebrow: "Automation",
title: "Survival and utility controls",
copy: "Configure healing, gear, trap escape, threat placement, weapon recharge, purchases, cleanup helpers, and other background behavior here."
}),
Object.freeze({
phase: "hud",
page: "combat",
target: "#moomoo-op-hud [data-page='combat'].mm-hud-page",
eyebrow: "Combat",
title: "Combos, defense, and friends",
copy: "This page controls Insta paths, spike prediction, anti-insta, boost tools, and friend targeting. Hover any option for a more exact explanation."
}),
Object.freeze({
phase: "hud",
page: "visuals",
target: "#moomoo-op-hud [data-page='visuals'].mm-hud-page",
eyebrow: "Visuals",
title: "Choose what Kitty draws",
copy: "Player markers, connection lines, prediction ghosts, stacked chat bubbles, and primary, secondary, and Turret Gear cooldown bars can be enabled independently."
}),
Object.freeze({
phase: "hud",
page: "sync",
target: "#moomoo-op-hud [data-page='sync'].mm-hud-page",
eyebrow: "Sync",
title: "Follow and fight with a teammate",
copy: "Press Y and click a teammate for a one-way follow. They only follow you back if they also press Y and click you; exact cross-client combat timing requires matching Kitty relay settings."
}),
Object.freeze({
phase: "hud",
page: "config",
target: "#moomoo-op-hud [data-page='config'].mm-hud-page",
eyebrow: "Config",
title: "Tune behavior and messages",
copy: "Adjust ranges and reaction speed, inspect diagnostics, choose each automated chat message, and reset saved settings from this page."
}),
Object.freeze({
phase: "hud",
page: "hotkeys",
target: "#moomoo-op-hud [data-page='hotkeys'].mm-hud-page",
eyebrow: "Hotkey library",
title: "Every shortcut is editable",
copy: "Click a Kitty keycap, then press any keyboard key or mouse button with the modifiers you want. Conflicts swap safely, and each action can be reset independently."
}),
Object.freeze({
phase: "hud",
page: "hotkeys",
target: "#moomoo-op-hud .mm-hud-brand",
eyebrow: "Ready",
title: "You're ready to play",
copy: "Use Back to revisit anything, Finish to complete onboarding, or Stop for now. The guide only opens when you press a Tutorial button."
})
]);
function kittyTutorialIsComplete() {
try {
return localStorage.getItem(KITTY_TUTORIAL_COMPLETE_KEY) === "1";
} catch {
return false;
}
}
function setKittyTutorialComplete() {
try {
localStorage.setItem(KITTY_TUTORIAL_COMPLETE_KEY, "1");
} catch {
// Completion remains valid for this page when storage is blocked.
}
}
function setKittyHudOpen(open) {
hudOpen = Boolean(open);
if (document.documentElement)
document.documentElement.setAttribute("data-kitty-hud-open", hudOpen ? "1" : "0");
window.dispatchEvent(new CustomEvent("MooMooKittyHudVisibility", { detail: hudOpen }));
const root = document.getElementById(HUD_ID);
if (!root) return;
root.classList.toggle("mm-hud-collapsed", !hudOpen);
root.setAttribute("aria-hidden", String(!hudOpen));
const launcher = document.getElementById(KITTY_HUD_LAUNCHER_ID);
if (launcher) {
launcher.setAttribute("aria-expanded", String(hudOpen));
launcher.classList.toggle("kitty-hud-open", hudOpen);
}
}
function positionKittyTutorial() {
const root = document.getElementById(KITTY_TUTORIAL_ID);
if (!root || !kittyTutorialActive) return;
const step = KITTY_TUTORIAL_STEPS[kittyTutorialIndex];
const spotlight = root.querySelector(".kitty-tutorial-spotlight");
const card = root.querySelector(".kitty-tutorial-card");
const target = step && step.target ? document.querySelector(step.target) : null;
if (!spotlight || !card) return;
if (!target || !target.getClientRects().length) {
spotlight.hidden = true;
card.style.left = "50%";
card.style.top = "50%";
card.style.transform = "translate(-50%,-50%)";
return;
}
const bounds = target.getBoundingClientRect();
spotlight.hidden = false;
spotlight.style.left = Math.max(6, bounds.left - 8) + "px";
spotlight.style.top = Math.max(6, bounds.top - 8) + "px";
spotlight.style.width = Math.max(24, Math.min(window.innerWidth - 12, bounds.width + 16)) + "px";
spotlight.style.height = Math.max(24, Math.min(window.innerHeight - 12, bounds.height + 16)) + "px";
card.style.transform = "none";
const cardBounds = card.getBoundingClientRect();
let left = bounds.left + bounds.width / 2 - cardBounds.width / 2;
left = Math.max(12, Math.min(window.innerWidth - cardBounds.width - 12, left));
let top = bounds.bottom + 18;
if (top + cardBounds.height > window.innerHeight - 12)
top = bounds.top - cardBounds.height - 18;
if (top < 12) top = window.innerHeight - cardBounds.height - 18;
card.style.left = left + "px";
card.style.top = Math.max(12, top) + "px";
}
function showKittyTutorialStep() {
const root = document.getElementById(KITTY_TUTORIAL_ID);
const step = KITTY_TUTORIAL_STEPS[kittyTutorialIndex];
if (!root || !step) return;
if (step.phase === "hud") {
setKittyHudOpen(true);
if (step.page) {
const button = document.querySelector("#" + HUD_ID + " .mm-hud-nav button[data-page='" + step.page + "']");
if (button) button.click();
const pages = document.querySelector("#" + HUD_ID + " .mm-hud-pages");
if (pages) pages.scrollTop = 0;
}
} else setKittyHudOpen(false);
root.querySelector("[data-tutorial-eyebrow]").textContent = step.eyebrow;
root.querySelector("[data-tutorial-title]").textContent = step.title;
root.querySelector("[data-tutorial-copy]").textContent = step.copy;
root.querySelector("[data-tutorial-progress]").textContent =
String(kittyTutorialIndex + 1) + " / " + String(KITTY_TUTORIAL_STEPS.length);
const back = root.querySelector("[data-tutorial-back]");
const next = root.querySelector("[data-tutorial-next]");
back.disabled = kittyTutorialIndex === 0;
next.textContent = kittyTutorialIndex === KITTY_TUTORIAL_STEPS.length - 1
? "Finish"
: "Next";
requestAnimationFrame(() => requestAnimationFrame(positionKittyTutorial));
}
function stopKittyTutorial(completed) {
if (completed) setKittyTutorialComplete();
kittyTutorialActive = false;
document.getElementById(KITTY_TUTORIAL_ID)?.remove();
setKittyHudOpen(kittyTutorialHudWasOpen);
}
function startKittyTutorial() {
if (!document.body) return;
document.getElementById(KITTY_TUTORIAL_ID)?.remove();
kittyTutorialHudWasOpen = hudOpen;
kittyTutorialIndex = 0;
kittyTutorialActive = true;
const root = document.createElement("aside");
root.id = KITTY_TUTORIAL_ID;
root.setAttribute("role", "dialog");
root.setAttribute("aria-modal", "true");
root.setAttribute("aria-label", "Kitty Klient tutorial");
const spotlight = document.createElement("div");
spotlight.className = "kitty-tutorial-spotlight";
const card = document.createElement("section");
card.className = "kitty-tutorial-card";
card.innerHTML =
"<div class='kitty-tutorial-top'><span data-tutorial-eyebrow></span><b data-tutorial-progress></b></div>" +
"<h2 data-tutorial-title></h2><p data-tutorial-copy></p>" +
"<div class='kitty-tutorial-actions'>" +
"<button type='button' data-tutorial-stop>Stop for now</button>" +
"<button type='button' data-tutorial-skip>Skip tutorial</button>" +
"<span></span><button type='button' data-tutorial-back>Back</button>" +
"<button type='button' data-tutorial-next>Next</button></div>";
root.append(spotlight, card);
document.body.appendChild(root);
card.querySelector("[data-tutorial-stop]").addEventListener("click", () => stopKittyTutorial(false));
card.querySelector("[data-tutorial-skip]").addEventListener("click", () => stopKittyTutorial(true));
card.querySelector("[data-tutorial-back]").addEventListener("click", () => {
kittyTutorialIndex = Math.max(0, kittyTutorialIndex - 1);
showKittyTutorialStep();
});
card.querySelector("[data-tutorial-next]").addEventListener("click", () => {
if (kittyTutorialIndex >= KITTY_TUTORIAL_STEPS.length - 1)
return stopKittyTutorial(true);
kittyTutorialIndex += 1;
showKittyTutorialStep();
});
showKittyTutorialStep();
}
function kittyHomeActions() {
const mainMenu = document.getElementById("mainMenu");
if (!mainMenu) return null;
let actions = document.getElementById("kitty-klient-home-actions");
if (actions) return actions;
const enterGame = document.getElementById("enterGame");
const container = enterGame && enterGame.parentElement
? enterGame.parentElement
: mainMenu.querySelector("#menuContainer,.menuCard") || mainMenu;
actions = document.createElement("div");
actions.id = "kitty-klient-home-actions";
if (enterGame && enterGame.parentElement === container)
enterGame.insertAdjacentElement("afterend", actions);
else container.appendChild(actions);
if (enterGame && !enterGame.dataset.kittyTutorialPlayBound) {
enterGame.dataset.kittyTutorialPlayBound = "1";
enterGame.addEventListener("click", () => {
if (kittyTutorialActive) stopKittyTutorial(true);
});
}
return actions;
}
function mountKittyHomeTutorial() {
const actions = kittyHomeActions();
if (!actions) return;
let tutorial = document.getElementById("kitty-klient-home-tutorial");
if (!tutorial) {
tutorial = document.createElement("button");
tutorial.id = "kitty-klient-home-tutorial";
tutorial.type = "button";
tutorial.textContent = "Tutorial";
tutorial.addEventListener("click", startKittyTutorial);
}
if (tutorial.parentElement !== actions) actions.appendChild(tutorial);
}
function mountKittyHomeDiscord() {
const actions = kittyHomeActions();
if (!actions) return;
let discord = document.getElementById("kitty-klient-home-discord");
if (!discord) {
discord = document.createElement("a");
discord.id = "kitty-klient-home-discord";
discord.href = "https://discord.gg/mHvC2kJSH";
discord.target = "_blank";
discord.rel = "noopener noreferrer";
discord.textContent = "Official Discord";
}
if (discord.parentElement !== actions) actions.appendChild(discord);
}
function applyKittyBrand() {
applyKittyNameTrademark();
if (document.title !== "kitty klient") document.title = "kitty klient";
const menu = document.getElementById("mainMenu") || document.body;
if (!menu) return;
const candidates = menu.querySelectorAll("#gameName,.gameName,h1,h2,[class*='title'],[id*='title']");
candidates.forEach((element) => {
const text = (element.textContent || "").trim();
if (text.length <= 32 && /moo\s*moo(?:\.io)?/i.test(text)) {
element.textContent = "kitty klient";
element.dataset.kittyBrand = "";
}
});
mountKittyHomeTutorial();
mountKittyHomeDiscord();
watchKittyAuxPanelVisibility();
}
function installKittyTheme() {
if (!document.documentElement || document.getElementById("kitty-klient-theme")) return;
const style = document.createElement("style");
style.id = "kitty-klient-theme";
style.textContent = [
":root{--kitty-purple:#a855f7;--kitty-purple-deep:#6d28d9;--kitty-black:#08050d}",
"#kitty-klient-metrics.kitty-main-menu-hidden,#kitty-klient-chat-history.kitty-main-menu-hidden,#kitty-klient-hud-launcher.kitty-main-menu-hidden{display:none!important}",
"#upgradeHolder[data-kitty-no-upgrades='1'],#upgradeCounter[data-kitty-no-upgrades='1']{display:none!important}",
"body,button,input,select,textarea,label,#gameUI,#mainMenu,#menuCardHolder,.menuCard,.menuButton,.settingRadio,.leaderboardItem,.leaderScore,.notificationText,.allianceItem,.storeItem,#itemInfoHolder,#loadingText,#diedText{color:#fff!important;text-shadow:0 0 4px #8b5cf6,0 0 11px rgba(168,85,247,.9)!important}",
".menuCard,#guideCard,#serverBrowser,#storeHolder,#allianceHolder,#allianceManager,#chatBox{background-color:rgba(5,3,9,.82)!important;border-color:rgba(168,85,247,.7)!important;box-shadow:0 0 18px rgba(139,92,246,.4)!important}",
"#mainMenu{background:rgba(5,3,9,.5)!important;border:0!important;box-shadow:none!important}#menuCardHolder,#storeMenu,#allianceMenu,#chatHolder{background:transparent!important;border:0!important;box-shadow:none!important;backdrop-filter:none!important}",
"#menuContainer{position:fixed!important;top:50%!important;right:auto!important;bottom:auto!important;left:50%!important;width:min(1100px,calc(100vw - 28px))!important;box-sizing:border-box!important;margin:0!important;text-align:center!important;scale:none!important;transform:translate(-50%,-50%) scale(var(--kitty-native-ui-scale,.82))!important;transform-origin:center center!important}#menuContainer>#menuCardHolder{margin-inline:auto!important}#storeHolder{width:min(400px,calc(100vw - 40px))!important;box-sizing:border-box!important}#storeMenu>div:first-child{width:min(400px,calc(100vw - 40px));margin-inline:auto}#storeMenu .storeTab{width:calc(50% - 7px)!important;box-sizing:border-box!important}#allianceHolder,#allianceManager{width:min(370px,calc(100vw - 40px))!important;box-sizing:border-box!important;margin-inline:auto!important}#chatBox{width:min(420px,calc(100vw - 40px))!important;box-sizing:border-box!important}",
"#chatBox,#chatBox input,#chatBox textarea,#chatHolder input,#chatHolder textarea{font-size:16px!important;line-height:1.35!important}",
":root{--kitty-native-ui-scale:.82}#gameUI>:is(.uiElement,#topInfoHolder,#itemInfoHolder,#upgradeHolder,#upgradeCounter,#leaderboard,#killCounter,#mapDisplay,#actionBar,#storeButton,#allianceButton,#chatButton,#chatHolder,#storeMenu,#allianceMenu,#notificationDisplay,#diedText,#disconnectDisplay){scale:var(--kitty-native-ui-scale)!important}",
"#gameUI>:is(#topInfoHolder,#itemInfoHolder,#notificationDisplay){transform-origin:top center!important}#gameUI>:is(#leaderboard,#killCounter){transform-origin:top right!important}#gameUI>:is(#mapDisplay,#storeButton,#allianceButton,#chatButton){transform-origin:bottom right!important}#gameUI>:is(#actionBar,#chatHolder){transform-origin:bottom center!important}#gameUI>:is(#upgradeHolder,#upgradeCounter,#storeMenu,#allianceMenu,#diedText,#disconnectDisplay){transform-origin:center center!important}#kitty-klient-home-actions{scale:1.2195122!important}",
"#mainMenu button,#mainMenu input,#mainMenu select,#enterGame,.menuButton,.allianceButtonM,.joinAlBtn{background:rgba(8,5,13,.82)!important;border:1px solid rgba(168,85,247,.72)!important;color:#fff!important;box-shadow:0 0 10px rgba(139,92,246,.28)!important}",
"#mainMenu button:hover,#enterGame:hover,.menuButton:hover,.allianceButtonM:hover,.joinAlBtn:hover{border-color:#c084fc!important;box-shadow:0 0 16px rgba(168,85,247,.72)!important}",
"#gameUI>#itemInfoHolder{position:fixed!important;top:var(--kitty-item-info-top,110px)!important;right:auto!important;left:14px!important;transform-origin:top left!important}@media(max-width:700px){#gameUI>#itemInfoHolder{left:8px!important;right:auto!important}}",
"#kitty-klient-home-actions{display:grid!important;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);gap:8px;width:min(340px,calc(100% - 24px));margin:10px auto 0;box-sizing:border-box;transform-origin:top center!important;position:relative;z-index:3}#kitty-klient-home-actions>*{display:flex!important;align-items:center;justify-content:center;min-width:0;min-height:38px;box-sizing:border-box;margin:0!important;padding:0 12px;border:1px solid #c084fc!important;border-radius:9px;color:#fff!important;font:900 12px/1.2 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;text-decoration:none!important;text-shadow:0 0 8px #2e1065!important;transition:transform .12s ease,filter .12s ease}#kitty-klient-home-tutorial{background:rgba(8,5,13,.9)!important;cursor:pointer}#kitty-klient-home-discord{background:linear-gradient(135deg,rgba(76,29,149,.94),rgba(124,58,237,.94))!important;box-shadow:0 0 15px rgba(168,85,247,.5)!important}#kitty-klient-home-actions>*:hover{filter:brightness(1.14);transform:translateY(-1px);box-shadow:0 0 21px rgba(192,132,252,.72)!important}",
"[data-kitty-brand],#gameName.kitty-klient-brand{font-family:'Segoe Print','Bradley Hand','Brush Script MT',cursive!important;font-style:italic!important;font-weight:900!important;letter-spacing:.045em!important;text-transform:lowercase!important;color:#07030b!important;-webkit-text-stroke:1px #17101f;text-shadow:-2px 1px 0 #a855f7,2px -1px 0 #6d28d9,0 0 8px #c084fc,0 0 22px #7c3aed!important;transform:skewX(-9deg) rotate(-1deg)!important}",
"#mainMenu #gameName[data-kitty-brand]{display:block!important;width:max-content!important;max-width:100%!important;position:relative!important;left:50%!important;right:auto!important;margin-left:0!important;margin-right:0!important;text-align:center!important;transform-origin:center center!important;transform:translateX(-50%) skewX(-9deg) rotate(-1deg)!important}",
"#kitty-klient-metrics{position:fixed;z-index:2147483645;right:14px;top:62%;transform:translateY(-50%);display:grid;gap:5px;padding:9px 10px;border:1px solid rgba(168,85,247,.68);border-radius:10px;background:rgba(5,3,9,.68);box-shadow:0 0 18px rgba(139,92,246,.38);backdrop-filter:blur(7px);pointer-events:none;color:#fff;font:800 11px/1.15 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 7px #8b5cf6}",
"#kitty-klient-metrics span{display:flex;justify-content:space-between;gap:10px;min-width:92px}#kitty-klient-metrics b{color:#c084fc;font-weight:900}",
"#kitty-klient-tutorial{position:fixed;z-index:2147483647;inset:0;pointer-events:none;color:#fff;font:600 13px/1.45 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;text-shadow:0 0 7px rgba(168,85,247,.8)}#kitty-klient-tutorial *{box-sizing:border-box}#kitty-klient-tutorial .kitty-tutorial-spotlight{position:fixed;border:2px solid #c084fc;border-radius:13px;box-shadow:0 0 0 9999px rgba(2,1,4,.72),0 0 25px rgba(192,132,252,.95),inset 0 0 18px rgba(168,85,247,.18);transition:left .18s ease,top .18s ease,width .18s ease,height .18s ease;pointer-events:none}#kitty-klient-tutorial .kitty-tutorial-spotlight[hidden]{display:none}",
"#kitty-klient-tutorial .kitty-tutorial-card{position:fixed;width:min(410px,calc(100vw - 24px));padding:18px;border:1px solid rgba(192,132,252,.88);border-radius:15px;background:linear-gradient(145deg,rgba(7,4,12,.98),rgba(37,15,57,.96));box-shadow:0 0 30px rgba(139,92,246,.58),0 18px 60px rgba(0,0,0,.72);backdrop-filter:blur(14px);pointer-events:auto}#kitty-klient-tutorial .kitty-tutorial-top{display:flex;align-items:center;justify-content:space-between;gap:12px;color:#d8b4fe;font-size:10px;font-weight:900;letter-spacing:.12em;text-transform:uppercase}#kitty-klient-tutorial h2{margin:7px 0 7px;color:#fff!important;font-size:21px;line-height:1.12;text-shadow:0 0 11px #8b5cf6!important}#kitty-klient-tutorial p{margin:0;color:#f5f3ff;font-size:12px}#kitty-klient-tutorial .kitty-tutorial-actions{display:grid;grid-template-columns:auto auto 1fr auto auto;gap:7px;align-items:center;margin-top:16px}#kitty-klient-tutorial button{min-height:34px;padding:0 10px;border:1px solid rgba(192,132,252,.6);border-radius:8px;background:rgba(10,6,16,.88);color:#fff!important;font:800 11px/1 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;cursor:pointer;text-shadow:0 0 7px #7c3aed!important}#kitty-klient-tutorial button:hover{border-color:#e9d5ff;box-shadow:0 0 13px rgba(168,85,247,.58)}#kitty-klient-tutorial button:disabled{opacity:.35;cursor:default;box-shadow:none}#kitty-klient-tutorial [data-tutorial-next]{background:linear-gradient(135deg,#6d28d9,#a855f7);border-color:#d8b4fe}#kitty-klient-tutorial [data-tutorial-stop]{border-color:rgba(248,113,113,.56)}@media(max-width:620px){#kitty-klient-tutorial .kitty-tutorial-actions{grid-template-columns:1fr 1fr}#kitty-klient-tutorial .kitty-tutorial-actions>span{display:none}#kitty-klient-tutorial .kitty-tutorial-card{padding:14px}}",
"#kitty-klient-update-popup{position:fixed;z-index:2147483647;top:18px;right:18px;width:min(330px,calc(100vw - 36px));box-sizing:border-box;padding:17px 17px 16px;border:1px solid rgba(192,132,252,.82);border-radius:14px;background:linear-gradient(145deg,rgba(8,5,13,.94),rgba(30,12,48,.88));box-shadow:0 0 28px rgba(139,92,246,.5),inset 0 0 22px rgba(168,85,247,.08);backdrop-filter:blur(12px);color:#fff;font:600 13px/1.45 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;text-shadow:0 0 7px rgba(168,85,247,.8);animation:kitty-update-enter .22s ease-out both}",
"#kitty-klient-update-popup .kitty-update-title{margin:0 30px 5px 0;color:#fff;font-size:18px;font-weight:900;letter-spacing:.01em}#kitty-klient-update-popup .kitty-update-copy{margin:0 0 12px;color:#eee}#kitty-klient-update-popup .kitty-update-versions{display:flex;align-items:center;gap:7px;margin:0 0 14px;color:#d8b4fe;font:800 11px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 8px #7c3aed}",
"#kitty-klient-update-popup .kitty-update-download{display:flex;align-items:center;justify-content:center;min-height:38px;padding:0 14px;border:1px solid #c084fc;border-radius:9px;background:linear-gradient(135deg,#7c3aed,#a855f7);color:#fff!important;font-size:13px;font-weight:900;text-decoration:none;box-shadow:0 0 15px rgba(168,85,247,.46);text-shadow:0 0 7px #4c1d95!important;transition:transform .12s ease,filter .12s ease}#kitty-klient-update-popup .kitty-update-download:hover{filter:brightness(1.13);transform:translateY(-1px)}",
"#kitty-klient-update-popup .kitty-update-close{position:absolute;top:8px;right:9px;width:30px;height:30px;padding:0;border:0;border-radius:8px;background:transparent;color:#e9d5ff!important;font:900 23px/28px Arial,sans-serif;cursor:pointer;text-shadow:0 0 9px #a855f7!important}#kitty-klient-update-popup .kitty-update-close:hover{background:rgba(168,85,247,.2);color:#fff!important}@keyframes kitty-update-enter{from{opacity:0;transform:translateY(-9px) scale(.98)}to{opacity:1;transform:none}}",
"html[data-kitty-fps-boost='1'] :is(#gameUI,#mainMenu,#moomoo-op-hud),html[data-kitty-fps-boost='1'] :is(#gameUI,#mainMenu,#moomoo-op-hud) *{backdrop-filter:none!important;animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}",
"@media(max-width:700px){#kitty-klient-metrics{right:8px;top:60%;font-size:9px;padding:7px}#menuContainer{width:calc(100vw - 16px)!important;white-space:normal!important}}"
].join("");
(document.head || document.documentElement).appendChild(style);
applyKittyBrand();
// The game mutates its DOM constantly. Running the full branding query
// for every mutation can consume an entire frame on the main menu, so
// observe only until MooMoo's menu has finished mounting.
if (!document.getElementById("kitty-klient-home-actions")) {
let brandRefreshTimer = 0;
const observer = new MutationObserver(() => {
if (brandRefreshTimer) return;
brandRefreshTimer = window.setTimeout(() => {
brandRefreshTimer = 0;
applyKittyBrand();
if (
document.getElementById("mainMenu") &&
document.getElementById("enterGame") &&
document.getElementById("kitty-klient-home-actions")
) observer.disconnect();
}, 80);
});
observer.observe(document.documentElement, { childList: true, subtree: true });
}
}
function mountMetrics() {
if (!KITTY_AUX_PANELS_VISIBLE) {
document.getElementById("kitty-klient-metrics")?.remove();
return;
}
if (!document.body || document.getElementById("kitty-klient-metrics")) return;
const metrics = document.createElement("div");
metrics.id = "kitty-klient-metrics";
metrics.setAttribute("aria-label", "kitty klient performance");
metrics.innerHTML = "<span>PING <b data-metric='ping'>--</b></span>" +
"<span>FPS <b data-metric='fps'>--</b></span>" +
"<span>PACKETS <b data-metric='packets'>0</b></span>";
document.body.appendChild(metrics);
syncKittyAuxPanelVisibility();
}
function syncKittyAuxPanelVisibility() {
const mainMenu = document.getElementById("mainMenu");
const mainMenuVisible = !mainMenu || window.getComputedStyle(mainMenu).display !== "none";
if (document.documentElement) {
const nextValue = mainMenuVisible ? "1" : "0";
if (document.documentElement.getAttribute("data-kitty-main-menu-open") !== nextValue) {
document.documentElement.setAttribute("data-kitty-main-menu-open", nextValue);
window.dispatchEvent(new CustomEvent("MooMooKittyMainMenuVisibility", {
detail: mainMenuVisible
}));
}
}
["kitty-klient-metrics", CHAT_HISTORY_ID, KITTY_HUD_LAUNCHER_ID].forEach((id) => {
document.getElementById(id)?.classList.toggle("kitty-main-menu-hidden", mainMenuVisible);
});
positionKittyHudLauncher();
}
function watchKittyAuxPanelVisibility() {
const mainMenu = document.getElementById("mainMenu");
if (!mainMenu || mainMenu.hasAttribute("data-kitty-aux-visibility-watch")) {
syncKittyAuxPanelVisibility();
return;
}
mainMenu.setAttribute("data-kitty-aux-visibility-watch", "");
new MutationObserver(syncKittyAuxPanelVisibility).observe(mainMenu, {
attributes: true,
attributeFilter: ["style", "class", "hidden"]
});
syncKittyAuxPanelVisibility();
}
let kittyChatHistoryCollapsed = false;
try {
kittyChatHistoryCollapsed = localStorage.getItem(CHAT_HISTORY_COLLAPSED_KEY) === "1";
} catch {
// Collapsing remains available for this page when storage is blocked.
}
function setKittyChatHistoryCollapsed(collapsed, panel = document.getElementById(CHAT_HISTORY_ID)) {
kittyChatHistoryCollapsed = !!collapsed;
if (panel) {
panel.classList.toggle("kitty-chat-collapsed", kittyChatHistoryCollapsed);
const toggle = panel.querySelector("[data-kitty-chat-toggle]");
if (toggle) {
toggle.textContent = kittyChatHistoryCollapsed ? "Show chat" : "Hide chat";
toggle.setAttribute("aria-expanded", String(!kittyChatHistoryCollapsed));
toggle.setAttribute(
"aria-label",
kittyChatHistoryCollapsed ? "Show chat history" : "Hide chat history"
);
}
}
try {
localStorage.setItem(CHAT_HISTORY_COLLAPSED_KEY, kittyChatHistoryCollapsed ? "1" : "0");
} catch {
// Persistence is optional.
}
requestAnimationFrame(() => {
positionKittyChatHistory();
positionKittyNativeTooltip();
});
}
function positionKittyChatHistory() {
const panel = document.getElementById(CHAT_HISTORY_ID);
if (!panel) return;
panel.style.top = window.innerWidth <= 700 ? "8px" : "14px";
panel.style.bottom = "auto";
requestAnimationFrame(positionKittyNativeTooltip);
}
function positionKittyNativeTooltip() {
const panel = document.getElementById(CHAT_HISTORY_ID);
const panelVisible = panel && panel.getClientRects().length > 0;
const top = panelVisible
? Math.ceil(panel.getBoundingClientRect().bottom + 8)
: window.innerWidth <= 700 ? 8 : 14;
document.documentElement.style.setProperty("--kitty-item-info-top", top + "px");
}
function kittyChatIsNearBottom(log) {
return !!log && log.scrollHeight - log.scrollTop - log.clientHeight <= 14;
}
function updateKittyChatScrollLock(log) {
const panel = log && log.closest("#" + CHAT_HISTORY_ID);
const jump = panel && panel.querySelector("[data-kitty-chat-jump]");
if (!panel || !jump) return;
const locked = !kittyChatIsNearBottom(log);
panel.classList.toggle("kitty-chat-scroll-locked", locked);
jump.hidden = !locked;
}
function appendKittyChatHistoryEntry(entry) {
const panel = document.getElementById(CHAT_HISTORY_ID);
const log = panel && panel.querySelector("[data-kitty-chat-log]");
if (!panel || !log) return;
const followLatest = kittyChatIsNearBottom(log);
const empty = panel.querySelector("[data-kitty-chat-empty]");
if (empty) empty.hidden = true;
const row = document.createElement("article");
row.className = "kitty-chat-entry";
row.dataset.relation = entry.relation || "enemy";
const meta = document.createElement("div");
meta.className = "kitty-chat-meta";
const name = document.createElement("strong");
name.textContent = entry.name;
const time = document.createElement("time");
time.dateTime = new Date(entry.at).toISOString();
time.textContent = new Date(entry.at).toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit"
});
meta.append(name, time);
const message = document.createElement("p");
message.textContent = entry.message;
row.append(meta, message);
log.appendChild(row);
while (log.querySelectorAll(".kitty-chat-entry").length > 120)
log.querySelector(".kitty-chat-entry")?.remove();
const count = panel.querySelector("[data-kitty-chat-count]");
if (count) count.textContent = String(Math.min(120, chatHistoryEntries.length));
requestAnimationFrame(() => {
if (followLatest)
log.scrollTo({ top: log.scrollHeight, behavior: "smooth" });
updateKittyChatScrollLock(log);
});
positionKittyChatHistory();
}
function mountKittyChatHistory() {
if (!KITTY_AUX_PANELS_VISIBLE) {
document.getElementById(CHAT_HISTORY_ID)?.remove();
return;
}
if (!document.body || document.getElementById(CHAT_HISTORY_ID)) return;
const style = document.createElement("style");
style.id = CHAT_HISTORY_ID + "-style";
style.textContent = [
"#kitty-klient-chat-history{position:fixed;z-index:2147483644;top:14px;bottom:auto;left:14px;width:min(350px,calc(100vw - 28px));max-height:min(270px,36vh);display:grid;grid-template-rows:auto minmax(0,1fr);overflow:hidden;border:1px solid rgba(192,132,252,.62);border-radius:13px;background:linear-gradient(145deg,rgba(5,3,9,.58),rgba(25,10,40,.44));box-shadow:0 0 20px rgba(139,92,246,.3),0 12px 35px rgba(0,0,0,.28);backdrop-filter:blur(8px) saturate(1.12);color:#fff;font:13px/1.42 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;text-shadow:0 0 6px rgba(168,85,247,.65);pointer-events:auto;transition:top .2s ease,opacity .2s ease,max-height .18s ease}#kitty-klient-chat-history.kitty-chat-disabled{display:none!important}#kitty-klient-chat-history.kitty-chat-collapsed{grid-template-rows:auto;width:auto;max-height:48px}#kitty-klient-chat-history.kitty-chat-collapsed .kitty-chat-title,#kitty-klient-chat-history.kitty-chat-collapsed .kitty-chat-count{display:none!important}",
"#kitty-klient-chat-history:hover{border-color:rgba(216,180,254,.82);box-shadow:0 0 24px rgba(168,85,247,.42),0 14px 38px rgba(0,0,0,.32)}#kitty-klient-chat-history .kitty-chat-head{display:flex;align-items:center;justify-content:space-between;gap:9px;padding:9px 11px 8px;border-bottom:1px solid rgba(168,85,247,.25);background:rgba(10,5,17,.25)}#kitty-klient-chat-history.kitty-chat-collapsed .kitty-chat-head{border-bottom-color:transparent}",
"#kitty-klient-chat-history .kitty-chat-title{display:flex;align-items:center;gap:7px;min-width:0;font-weight:900;letter-spacing:.1em;text-transform:uppercase}#kitty-klient-chat-history .kitty-chat-title:before{content:'';flex:0 0 auto;width:7px;height:7px;border-radius:50%;background:#a855f7;box-shadow:0 0 9px #c084fc}#kitty-klient-chat-history .kitty-chat-actions{display:flex;align-items:center;gap:6px;flex:0 0 auto}#kitty-klient-chat-history .kitty-chat-count{min-width:21px;padding:2px 6px;border:1px solid rgba(192,132,252,.42);border-radius:999px;background:rgba(109,40,217,.2);color:#e9d5ff;text-align:center;font:800 9px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace}#kitty-klient-chat-history .kitty-chat-toggle{min-height:25px;padding:3px 8px;border:1px solid rgba(216,180,254,.58);border-radius:7px;background:rgba(76,29,149,.3);color:#fff;font:800 10px/1 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;cursor:pointer;text-shadow:0 0 6px #7c3aed}#kitty-klient-chat-history .kitty-chat-toggle:hover{border-color:#d8b4fe;background:rgba(109,40,217,.46);box-shadow:0 0 10px rgba(168,85,247,.38)}",
"#kitty-klient-chat-history .kitty-chat-log{min-height:54px;overflow-y:auto;overscroll-behavior:contain;scroll-behavior:smooth;padding:7px;scrollbar-width:thin;scrollbar-color:#7c3aed rgba(8,5,13,.42)}#kitty-klient-chat-history .kitty-chat-log::-webkit-scrollbar{width:6px}#kitty-klient-chat-history .kitty-chat-log::-webkit-scrollbar-track{background:rgba(8,5,13,.42)}#kitty-klient-chat-history .kitty-chat-log::-webkit-scrollbar-thumb{border-radius:999px;background:linear-gradient(#a855f7,#6d28d9)}",
"#kitty-klient-chat-history .kitty-chat-empty{display:grid;place-items:center;min-height:42px;color:#c4b5fd;font-style:italic;opacity:.72}#kitty-klient-chat-history .kitty-chat-entry{margin:0 0 6px;padding:7px 8px;border:1px solid rgba(168,85,247,.17);border-left:3px solid var(--kitty-enemy,#ff4d5d);border-radius:8px;background:rgba(8,5,13,.29);animation:kitty-chat-enter .2s cubic-bezier(.2,.8,.2,1) both}#kitty-klient-chat-history .kitty-chat-entry:last-child{margin-bottom:0}#kitty-klient-chat-history .kitty-chat-entry[data-relation='self']{border-left-color:var(--kitty-own,#d8b4fe)}#kitty-klient-chat-history .kitty-chat-entry[data-relation='ally']{border-left-color:var(--kitty-ally,#a855f7)}#kitty-klient-chat-history .kitty-chat-entry[data-relation='friend']{border-left-color:var(--kitty-friend,#facc15)}#kitty-klient-chat-history.kitty-chat-collapsed .kitty-chat-log,#kitty-klient-chat-history.kitty-chat-collapsed .kitty-chat-jump{display:none!important}",
"#kitty-klient-chat-history .kitty-chat-jump{position:absolute;right:11px;bottom:10px;min-height:28px;padding:0 10px;border:1px solid rgba(216,180,254,.82);border-radius:999px;background:rgba(76,29,149,.94);color:#fff;font:900 10px/1 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;cursor:pointer;box-shadow:0 0 14px rgba(168,85,247,.55);text-shadow:0 0 7px #7c3aed}#kitty-klient-chat-history .kitty-chat-jump[hidden]{display:none}#kitty-klient-chat-history.kitty-chat-scroll-locked .kitty-chat-log{padding-bottom:44px}",
"#kitty-klient-chat-history .kitty-chat-meta{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:3px}#kitty-klient-chat-history .kitty-chat-meta strong{overflow:hidden;color:#fff;font-size:12px;text-overflow:ellipsis;white-space:nowrap}#kitty-klient-chat-history .kitty-chat-meta time{flex:0 0 auto;color:#c4b5fd;font:700 10px/1 ui-monospace,SFMono-Regular,Menlo,monospace}#kitty-klient-chat-history .kitty-chat-entry p{margin:0;color:#f5f3ff;font-size:14px;line-height:1.42;overflow-wrap:anywhere} @keyframes kitty-chat-enter{from{opacity:0;transform:translateX(9px) scale(.98)}to{opacity:1;transform:none}}",
"@media(max-width:700px){#kitty-klient-chat-history{top:8px;bottom:auto;left:8px;width:min(310px,calc(100vw - 16px));max-height:29vh;font-size:12px}#kitty-klient-chat-history .kitty-chat-entry p{font-size:13px}}"
].join("");
(document.head || document.documentElement).appendChild(style);
const panel = document.createElement("aside");
panel.id = CHAT_HISTORY_ID;
panel.classList.toggle("kitty-chat-disabled", !hudState.chatHistory);
panel.setAttribute("aria-label", "Chat history");
panel.setAttribute("aria-hidden", String(!hudState.chatHistory));
const head = document.createElement("header");
head.className = "kitty-chat-head";
const title = document.createElement("span");
title.className = "kitty-chat-title";
title.textContent = "Chat history";
const count = document.createElement("span");
count.className = "kitty-chat-count";
count.dataset.kittyChatCount = "";
count.textContent = "0";
const actions = document.createElement("div");
actions.className = "kitty-chat-actions";
const toggle = document.createElement("button");
toggle.className = "kitty-chat-toggle";
toggle.type = "button";
toggle.dataset.kittyChatToggle = "";
toggle.setAttribute("aria-controls", CHAT_HISTORY_ID + "-log");
toggle.addEventListener("click", () => {
setKittyChatHistoryCollapsed(!kittyChatHistoryCollapsed, panel);
});
actions.append(count, toggle);
head.append(title, actions);
const log = document.createElement("div");
log.id = CHAT_HISTORY_ID + "-log";
log.className = "kitty-chat-log";
log.dataset.kittyChatLog = "";
log.setAttribute("role", "log");
log.setAttribute("aria-live", "polite");
const empty = document.createElement("div");
empty.className = "kitty-chat-empty";
empty.dataset.kittyChatEmpty = "";
empty.textContent = "Messages will appear here";
log.appendChild(empty);
const jump = document.createElement("button");
jump.className = "kitty-chat-jump";
jump.type = "button";
jump.dataset.kittyChatJump = "";
jump.textContent = "Latest ↓";
jump.hidden = true;
jump.addEventListener("click", () => {
log.scrollTo({ top: log.scrollHeight, behavior: "smooth" });
requestAnimationFrame(() => updateKittyChatScrollLock(log));
});
log.addEventListener("scroll", () => updateKittyChatScrollLock(log), { passive: true });
panel.append(head, log, jump);
document.body.appendChild(panel);
setKittyChatHistoryCollapsed(kittyChatHistoryCollapsed, panel);
if (typeof ResizeObserver === "function")
new ResizeObserver(positionKittyNativeTooltip).observe(panel);
chatHistoryEntries.forEach(appendKittyChatHistoryEntry);
positionKittyChatHistory();
syncKittyAuxPanelVisibility();
}
window.addEventListener("MooMooKittyChatMessage", (event) => {
const detail = event.detail && typeof event.detail === "object" ? event.detail : {};
const message = String(detail.message || "").trim().slice(0, 120);
if (!message) return;
const entry = {
name: String(detail.name || "Player").slice(0, 32),
message,
relation: ["self", "ally", "friend", "enemy"].includes(detail.relation)
? detail.relation
: "enemy",
at: Number.isFinite(Number(detail.at)) ? Number(detail.at) : Date.now()
};
chatHistoryEntries.push(entry);
if (chatHistoryEntries.length > 120) chatHistoryEntries.shift();
const alreadyMounted = !!document.getElementById(CHAT_HISTORY_ID);
mountKittyChatHistory();
alreadyMounted && appendKittyChatHistoryEntry(entry);
});
window.addEventListener("resize", () => {
positionKittyChatHistory();
positionKittyHudLauncher();
}, { passive: true });
installCanvasTextTheme();
// Firefox can place a patched blob module in a messaging context that is
// separate from the userscript's normal page context. Bridge tab-sync
// traffic through the page-level storage event as a reliable fallback.
window.addEventListener("MooMooTabSyncOutbound", (event) => {
const payload = typeof event.detail === "string" ? event.detail : "";
if (!payload || payload.length > 1200) return;
try {
localStorage.setItem(TAB_SYNC_BRIDGE_KEY, payload);
} catch {
// BroadcastChannel remains available when storage is blocked.
}
});
window.addEventListener("storage", (event) => {
if (!event || event.key !== TAB_SYNC_BRIDGE_KEY || !event.newValue) return;
window.dispatchEvent(new CustomEvent("MooMooTabSyncInbound", { detail: event.newValue }));
});
function showZoomIndicator(message) {
if (!document.body) return;
let indicator = document.getElementById(INDICATOR_ID);
if (!indicator) {
indicator = document.createElement("div");
indicator.id = INDICATOR_ID;
indicator.style.cssText = [
"position:fixed",
"top:16px",
"left:50%",
"z-index:2147483647",
"transform:translateX(-50%)",
"max-width:min(560px,calc(100vw - 30px))",
"box-sizing:border-box",
"padding:10px 17px",
"border:1px solid rgba(192,132,252,.78)",
"border-radius:11px",
"background:linear-gradient(145deg,rgba(5,3,9,.9),rgba(34,12,52,.86))",
"color:#fff",
"font:800 18px/1.3 Arial,sans-serif",
"text-align:center",
"text-shadow:0 0 8px rgba(168,85,247,.9)",
"box-shadow:0 0 22px rgba(139,92,246,.44),0 8px 24px rgba(0,0,0,.3)",
"backdrop-filter:blur(9px)",
"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("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 normalizeHudColor(value, fallback) {
const color = typeof value === "string" ? value.trim().toLowerCase() : "";
return /^#[0-9a-f]{6}$/.test(color) ? color : fallback;
}
function normalizeKittyBinding(value, fallback) {
const pieces = typeof value === "string"
? value.split("+").map((piece) => piece.trim()).filter(Boolean)
: [];
const modifiers = new Set();
let trigger = "";
pieces.forEach((piece) => {
const token = piece.toLowerCase();
if (token === "ctrl" || token === "control") modifiers.add("Ctrl");
else if (token === "alt" || token === "option") modifiers.add("Alt");
else if (token === "shift") modifiers.add("Shift");
else if (token === "meta" || token === "command" || token === "cmd") modifiers.add("Meta");
else trigger = piece;
});
const validTrigger = /^(?:Mouse[0-4]|Key[A-Z]|Digit[0-9]|F(?:[1-9]|1[0-2])|Escape|Space|Enter|Tab|Backquote|Minus|Equal|BracketLeft|BracketRight|Backslash|Semicolon|Quote|Comma|Period|Slash|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Home|End|PageUp|PageDown|Insert|Delete)$/i.test(trigger);
if (!validTrigger) return fallback;
if (/^mouse/i.test(trigger)) trigger = "Mouse" + trigger.replace(/\D/g, "");
else if (/^key/i.test(trigger)) trigger = "Key" + trigger.slice(3).toUpperCase();
else if (/^digit/i.test(trigger)) trigger = "Digit" + trigger.slice(5);
else if (/^f\d+$/i.test(trigger)) trigger = trigger.toUpperCase();
else {
const canonical = ["Escape", "Space", "Enter", "Tab", "Backquote", "Minus", "Equal", "BracketLeft", "BracketRight", "Backslash", "Semicolon", "Quote", "Comma", "Period", "Slash", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown", "Insert", "Delete"];
trigger = canonical.find((entry) => entry.toLowerCase() === trigger.toLowerCase()) || trigger;
}
return ["Ctrl", "Alt", "Shift", "Meta"].filter((modifier) => modifiers.has(modifier)).concat(trigger).join("+");
}
function kittyBindingLabelPart(part) {
if (part === "Ctrl") return "Ctrl";
if (part === "Alt") return "Alt";
if (part === "Shift") return "Shift";
if (part === "Meta") return "Cmd";
if (part === "Mouse0") return "Left click";
if (part === "Mouse1") return "Middle click";
if (part === "Mouse2") return "Right click";
if (part === "Mouse3") return "Mouse 4";
if (part === "Mouse4") return "Mouse 5";
if (/^Key[A-Z]$/.test(part)) return part.slice(3);
if (/^Digit[0-9]$/.test(part)) return part.slice(5);
if (part === "Space") return "Space";
return part.replace(/([a-z])([A-Z])/g, "$1 $2");
}
function kittyBindingFromEvent(event, mouse) {
if (!event) return null;
const trigger = mouse
? "Mouse" + Math.max(0, Math.min(4, Number(event.button) || 0))
: String(event.code || "");
if (!trigger || /^(?:Shift|Control|Alt|Meta)(?:Left|Right)$/.test(trigger)) return null;
return normalizeKittyBinding([
event.ctrlKey && "Ctrl",
event.altKey && "Alt",
event.shiftKey && "Shift",
event.metaKey && "Meta",
trigger
].filter(Boolean).join("+"), null);
}
function kittyBindingMatchesEvent(binding, event, mouse) {
const actual = kittyBindingFromEvent(event, mouse);
return Boolean(actual && normalizeKittyBinding(binding, "") === actual);
}
function normalizeHudSettings(candidate) {
const settings = { ...HUD_DEFAULTS };
settings.keybinds = { ...KITTY_DEFAULT_KEYBINDS };
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]);
});
["enemyColor", "allyColor", "friendColor", "ownColor"].forEach((key) => {
settings[key] = normalizeHudColor(candidate[key], HUD_DEFAULTS[key]);
});
if (typeof candidate.killMessage === "string") {
settings.killMessage = candidate.killMessage.slice(0, 30);
}
if (typeof candidate.syncRelayUrl === "string") {
settings.syncRelayUrl = candidate.syncRelayUrl.trim().slice(0, 200);
}
if (typeof candidate.syncRoom === "string") {
settings.syncRoom = candidate.syncRoom.trim().slice(0, 64);
}
if (typeof candidate.syncStatus === "string") {
settings.syncStatus = candidate.syncStatus.trim().slice(0, 100) || "Sync off";
}
if (typeof candidate.syncTargetName === "string") {
settings.syncTargetName = candidate.syncTargetName.trim().slice(0, 15);
}
if (Array.isArray(candidate.friendNames)) {
const seen = new Set();
settings.friendNames = candidate.friendNames.reduce((names, value) => {
const name = typeof value === "string" ? value.trim().slice(0, 15) : "";
const key = name.toLowerCase();
if (name && !seen.has(key) && names.length < 30) {
seen.add(key);
names.push(name);
}
return names;
}, []);
}
if (candidate.keybinds && typeof candidate.keybinds === "object" && !Array.isArray(candidate.keybinds)) {
KITTY_BINDING_ACTIONS.forEach((entry) => {
settings.keybinds[entry.id] = normalizeKittyBinding(
candidate.keybinds[entry.id],
KITTY_DEFAULT_KEYBINDS[entry.id]
);
});
}
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");
}
// Older Kitty builds persisted the smart-placement master as false
// because it was originally an opt-in preview. Enable the repaired
// core once, persist that migration immediately, and leave the HUD
// toggle fully user-controllable from then on.
if (localStorage.getItem(PLACEMENT_CORE_AUTO_MIGRATION_KEY) !== "1") {
settings.smartAutoPlace = true;
settings.smartMultiPlace = true;
settings.smartQuadTraps = true;
settings.smartQuadSpikes = true;
settings.smartSpikeContact = true;
settings.smartTrapContact = true;
settings.smartTrapSurround = true;
settings.smartMaxPlacements = 4;
settings.placementVisuals = true;
localStorage.setItem(HUD_STORAGE_KEY, JSON.stringify(settings));
localStorage.setItem(PLACEMENT_CORE_AUTO_MIGRATION_KEY, "1");
}
// R is a direct action key, so old installs must not silently keep
// the master R-Insta switch in the historical false default.
if (localStorage.getItem(INSTA_HOTKEY_AUTO_MIGRATION_KEY) !== "1") {
settings.instaKill = true;
localStorage.setItem(HUD_STORAGE_KEY, JSON.stringify(settings));
localStorage.setItem(INSTA_HOTKEY_AUTO_MIGRATION_KEY, "1");
}
return settings;
} catch {
return { ...HUD_DEFAULTS };
}
}
function saveHudSettings() {
try {
const settings = normalizeHudSettings(hudState);
delete settings.syncStatus;
delete settings.syncTargetName;
localStorage.setItem(HUD_STORAGE_KEY, JSON.stringify(settings));
} catch {
// Saved settings are optional; the mod still works when storage is unavailable.
}
}
function applyHudSettings(nextSettings) {
hudState = {
...normalizeHudSettings({ ...hudState, ...nextSettings }),
debugText: hudState.debugText
};
saveHudSettings();
sendHudCommand({ type: "hydrate", settings: { ...hudState } });
renderHud();
}
function applyHudPreset(name) {
const presets = {
performance: {
fpsBoost: true,
smoothVisuals: false,
reloadArcs: false,
entityDanger: true,
notificationTracers: true,
groundGrid: false,
espLines: false,
predictionGhost: false,
placementVisuals: false,
cooldownBars: false,
weaponXpBar: false,
chatHistory: false,
combatTelemetry: false,
debugPanel: false
},
combat: {
fpsBoost: true,
smoothVisuals: true,
reloadArcs: true,
entityDanger: true,
notificationTracers: true,
groundGrid: false,
esp: true,
espLines: true,
predictionGhost: true,
placementVisuals: true,
cooldownBars: true,
weaponXpBar: true,
chatHistory: true,
combatTelemetry: true,
telemetryProjectileHits: true,
telemetrySpikeKnockback: true,
telemetryActualAim: true,
telemetryDamageHealing: true,
reactionMs: 20
},
visual: {
fpsBoost: false,
groundGrid: true,
esp: true,
espLines: true,
predictionGhost: true,
placementVisuals: true,
cooldownBars: true,
weaponXpBar: true,
chatHistory: true,
combatTelemetry: true,
telemetryProjectileHits: true,
telemetrySpikeKnockback: true,
telemetryActualAim: true,
telemetryBuildingOwners: true,
telemetryShameCount: true,
telemetryDamageHealing: true
}
};
if (presets[name]) applyHudSettings(presets[name]);
}
function applyForceFullServersPreference(value) {
const enabled = value !== false;
window.__KittyForceFullServers = enabled;
try {
if (enabled) localStorage.setItem("moofoll", "1");
else localStorage.removeItem("moofoll");
} catch {
// The bundle patches still honor the in-memory flag when storage is blocked.
}
}
function sendHudCommand(detail) {
if (detail && typeof detail === "object") {
const forceFullValue = detail.type === "set" && detail.key === "forceFullServers"
? detail.value
: detail.type === "hydrate" && detail.settings &&
Object.prototype.hasOwnProperty.call(detail.settings, "forceFullServers")
? detail.settings.forceFullServers
: null;
if (forceFullValue != null) applyForceFullServersPreference(forceFullValue);
const placementValue = detail.type === "set" && detail.key === "smartAutoPlace"
? detail.value
: detail.type === "hydrate" && detail.settings &&
Object.prototype.hasOwnProperty.call(detail.settings, "smartAutoPlace")
? detail.settings.smartAutoPlace
: null;
if (placementValue != null) window.__KittySmartAutoPlace = placementValue !== false;
}
if (document.documentElement && detail && typeof detail === "object") {
const __kittySpinningValue = detail.type === "set" && detail.key === "spinningWindmills"
? detail.value
: detail.type === "hydrate" && detail.settings &&
Object.prototype.hasOwnProperty.call(detail.settings, "spinningWindmills")
? detail.settings.spinningWindmills
: null;
if (__kittySpinningValue != null) {
document.documentElement.setAttribute(
"data-kitty-spinning-windmills",
__kittySpinningValue ? "1" : "0"
);
}
const __kittyFpsBoostValue = detail.type === "set" && detail.key === "fpsBoost"
? detail.value
: detail.type === "hydrate" && detail.settings &&
Object.prototype.hasOwnProperty.call(detail.settings, "fpsBoost")
? detail.settings.fpsBoost
: null;
if (__kittyFpsBoostValue != null) {
document.documentElement.setAttribute(
"data-kitty-fps-boost",
__kittyFpsBoostValue ? "1" : "0"
);
}
const __kittyGroundGridValue = detail.type === "set" && detail.key === "groundGrid"
? detail.value
: detail.type === "hydrate" && detail.settings &&
Object.prototype.hasOwnProperty.call(detail.settings, "groundGrid")
? detail.settings.groundGrid
: null;
if (__kittyGroundGridValue != null) {
document.documentElement.setAttribute(
"data-kitty-ground-grid",
__kittyGroundGridValue ? "1" : "0"
);
}
}
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);
if (control._kittyValueOutput)
control._kittyValueOutput.textContent = control.value;
}
}
function renderKittyBindingButton(button, binding) {
if (!button) return;
button.textContent = "";
const parts = String(binding || "").split("+").filter(Boolean);
parts.forEach((part, index) => {
if (index) {
const plus = document.createElement("span");
plus.className = "mm-hotkey-plus";
plus.textContent = "+";
button.appendChild(plus);
}
const keycap = document.createElement("kbd");
keycap.textContent = kittyBindingLabelPart(part);
button.appendChild(keycap);
});
button.setAttribute("aria-label", "Rebind " + (button.dataset.kittyBindingLabel || "Kitty action") + ", currently " + parts.map(kittyBindingLabelPart).join(" plus "));
}
function refreshKittyBindingButtons() {
document.querySelectorAll("#" + HUD_ID + " [data-kitty-binding-action]").forEach((button) => {
const action = button.dataset.kittyBindingAction;
if (action === hotkeyCaptureAction) return;
button.classList.remove("mm-capturing");
renderKittyBindingButton(button, hudState.keybinds && hudState.keybinds[action]);
});
}
function finishKittyBindingCapture() {
if (hotkeyCaptureButton) hotkeyCaptureButton.classList.remove("mm-capturing");
hotkeyCaptureAction = null;
hotkeyCaptureButton = null;
refreshKittyBindingButtons();
}
function beginKittyBindingCapture(action, button) {
finishKittyBindingCapture();
hotkeyCaptureAction = action;
hotkeyCaptureButton = button;
button.classList.add("mm-capturing");
button.textContent = "Press input… · Backspace cancels";
button.setAttribute("aria-label", "Waiting for a new key or mouse button");
}
function setKittyBinding(action, binding) {
const entry = KITTY_BINDING_ACTIONS.find((candidate) => candidate.id === action);
if (!entry) return false;
const normalized = normalizeKittyBinding(binding, KITTY_DEFAULT_KEYBINDS[action]);
const next = { ...KITTY_DEFAULT_KEYBINDS, ...(hudState.keybinds || {}) };
const previous = next[action];
const conflict = KITTY_BINDING_ACTIONS.find((candidate) =>
candidate.id !== action && next[candidate.id] === normalized
);
next[action] = normalized;
if (conflict) next[conflict.id] = previous;
hudState.keybinds = next;
saveHudSettings();
sendHudCommand({ type: "set", key: "keybinds", value: { ...next } });
refreshKittyBindingButtons();
showZoomIndicator(conflict
? entry.action + " rebound · swapped with " + conflict.action
: entry.action + " rebound");
return true;
}
function captureKittyBindingEvent(event, mouse) {
if (!hotkeyCaptureAction) return false;
if (!mouse && event.code === "Backspace") {
event.preventDefault();
event.stopImmediatePropagation();
finishKittyBindingCapture();
showZoomIndicator("Keybind change cancelled");
return true;
}
const binding = kittyBindingFromEvent(event, mouse);
event.preventDefault();
event.stopImmediatePropagation();
if (!binding) return true;
const action = hotkeyCaptureAction;
finishKittyBindingCapture();
setKittyBinding(action, binding);
return true;
}
function renderHud() {
if (document.documentElement) {
document.documentElement.setAttribute("data-kitty-fps-boost", hudState.fpsBoost ? "1" : "0");
document.documentElement.setAttribute("data-kitty-ground-grid", hudState.groundGrid ? "1" : "0");
document.documentElement.style.setProperty("--kitty-enemy", hudState.enemyColor);
document.documentElement.style.setProperty("--kitty-ally", hudState.allyColor);
document.documentElement.style.setProperty("--kitty-friend", hudState.friendColor);
document.documentElement.style.setProperty("--kitty-own", hudState.ownColor);
}
Object.entries(hudState).forEach(([key, value]) => setHudControlValue(key, value));
refreshKittyBindingButtons();
const chatHistory = document.getElementById(CHAT_HISTORY_ID);
if (chatHistory) {
chatHistory.classList.toggle("kitty-chat-disabled", !hudState.chatHistory);
chatHistory.setAttribute("aria-hidden", String(!hudState.chatHistory));
requestAnimationFrame(positionKittyNativeTooltip);
}
const friendList = document.querySelector("#" + HUD_ID + " [data-hud-friends]");
if (friendList) {
friendList.textContent = "";
const names = Array.isArray(hudState.friendNames) ? hudState.friendNames : [];
if (!names.length) {
const empty = document.createElement("small");
empty.textContent = "No friends yet — every non-teammate starts as an enemy.";
friendList.appendChild(empty);
} else {
names.forEach((name) => {
const chip = document.createElement("span");
chip.className = "mm-hud-friend-chip";
chip.textContent = name;
friendList.appendChild(chip);
});
}
}
const status = document.querySelector("#" + HUD_ID + " [data-hud-status]");
const syncStatus = document.querySelector("#" + HUD_ID + " [data-hud-sync-status]");
if (syncStatus) {
const syncText = String(hudState.syncStatus || "Sync off");
syncStatus.textContent = syncText;
syncStatus.dataset.syncPhase = /^Synced\b/i.test(syncText)
? "synced"
: /^(?:Syncing|Reconnecting)/i.test(syncText)
? "syncing"
: /(?:failed|error|blocked)/i.test(syncText)
? "error"
: "off";
}
if (!status) return;
const enabled = [
hudState.autoHeal && "heal",
hudState.antiInsta && "anti-insta",
hudState.soldierAuto && "soldier",
hudState.movementGear && "speed",
hudState.matThief && "mat thief",
hudState.multiTargetBreak && "multi-break",
hudState.mobSteal && "mob steal",
hudState.placementDefense && "placement defense",
hudState.antiRetrapPush && "anti-retrap",
hudState.teammateTrapRescue && "trap rescue",
hudState.turretSteal && "turret finisher",
hudState.spikeGearCounter && "spike counter",
hudState.dashMovement && "dash break",
hudState.assassinAutomation && "assassin",
hudState.autoRespawn && "auto respawn",
hudState.bushMode && "bush ambush",
hudState.animalTrap && "animal trap",
hudState.passiveMobTrap && "passive mob trap",
hudState.bossTeleporter && "boss TP",
hudState.smartAutoPlace && "smart auto place",
hudState.smartQuadTraps && "auto quad traps",
hudState.smartQuadSpikes && "auto quad spikes",
hudState.autoSpikeSpam && "trap spike fill",
hudState.autoSpikeKill && "lethal spike push",
hudState.smartAutoReplace && "smart replace",
hudState.smartAntiBoostPlace && "smart anti-boost",
hudState.smartMovingMills && "moving mills",
hudState.antiBoostInsta && "boost insta",
hudState.boostSpikeKill && "boost + spike",
hudState.antiCollision && "collision guard",
hudState.combatTelemetry && "telemetry",
hudState.syncTargetName && "sync: " + hudState.syncTargetName
].filter(Boolean);
status.textContent = enabled.length ? "Active: " + enabled.join(" · ") : "Automation paused";
const debug = document.querySelector("#" + HUD_ID + " [data-hud-debug]");
if (debug) {
debug.hidden = !hudState.debugPanel;
debug.textContent = hudState.debugPanel
? (typeof hudState.debugText === "string" && hudState.debugText) || "Waiting for live game state…"
: "";
}
}
function setHudTooltip(element, message) {
if (!element || typeof message !== "string" || !message.trim()) return element;
element.dataset.hudTooltip = message.trim();
return element;
}
function addHudToggle(container, key, label, subtitle) {
const row = document.createElement("label");
row.className = "mm-hud-row";
setHudTooltip(row, label + ": " + subtitle);
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";
setHudTooltip(
row,
label + ": " + subtitle + ". Allowed " + bounds.min + "–" + bounds.max + ", step " + bounds.step + "."
);
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 addHudSlider(container, key, label, subtitle) {
const bounds = HUD_NUMERIC_BOUNDS[key];
const row = document.createElement("label");
row.className = "mm-hud-slider";
setHudTooltip(
row,
label + ": " + subtitle + ". Allowed " + bounds.min + "–" + bounds.max + "."
);
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 control = document.createElement("span");
control.className = "mm-hud-slider-control";
const input = document.createElement("input");
input.type = "range";
input.min = String(bounds.min);
input.max = String(bounds.max);
input.step = String(bounds.step);
input.value = String(hudState[key]);
const value = document.createElement("output");
value.textContent = input.value;
input._kittyValueOutput = value;
input.addEventListener("input", () => {
value.textContent = String(clampHudNumber(key, Number(input.value)));
});
input.addEventListener("change", () => {
const next = clampHudNumber(key, Number(input.value));
hudState[key] = next;
value.textContent = String(next);
saveHudSettings();
sendHudCommand({ type: "set", key, value: next });
renderHud();
});
control.append(input, value);
row.append(text, control);
container.appendChild(row);
hudControls.set(key, input);
}
function addHudText(container, key, label, subtitle, options = {}) {
const row = document.createElement("label");
row.className = "mm-hud-text";
setHudTooltip(row, label + ": " + subtitle);
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.className = "mm-hud-message";
input.type = options.password ? "password" : "text";
input.maxLength = options.maxLength || 120;
input.placeholder = options.placeholder || "";
input.value = String(hudState[key] || "");
input.addEventListener("input", () => {
hudState[key] = input.value.slice(0, input.maxLength);
saveHudSettings();
});
input.addEventListener("change", () => {
hudState[key] = input.value.trim().slice(0, input.maxLength);
saveHudSettings();
sendHudCommand({ type: "set", key, value: hudState[key] });
renderHud();
});
row.append(text, input);
container.appendChild(row);
hudControls.set(key, input);
}
function addHudColor(container, key, label, subtitle) {
const row = document.createElement("label");
row.className = "mm-hud-color";
setHudTooltip(row, label + ": " + subtitle);
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 = "color";
input.value = normalizeHudColor(hudState[key], HUD_DEFAULTS[key]);
input.setAttribute("aria-label", label);
input.addEventListener("input", () => {
hudState[key] = normalizeHudColor(input.value, HUD_DEFAULTS[key]);
saveHudSettings();
sendHudCommand({ type: "set", key, value: hudState[key] });
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;
setHudTooltip(title, heading + " settings");
section.appendChild(title);
panel.appendChild(section);
return section;
}
function attachHudTooltipController(root, tooltip) {
let activeTarget = null;
const position = (clientX, clientY) => {
if (!activeTarget || tooltip.hidden) return;
const margin = 10;
let left = clientX + 14;
let top = clientY + 18;
const width = tooltip.offsetWidth;
const height = tooltip.offsetHeight;
if (left + width > window.innerWidth - margin)
left = Math.max(margin, clientX - width - 14);
if (top + height > window.innerHeight - margin)
top = Math.max(margin, clientY - height - 14);
tooltip.style.left = left + "px";
tooltip.style.top = top + "px";
};
const show = (target, clientX, clientY) => {
const message = target && target.dataset && target.dataset.hudTooltip;
if (!message) return;
activeTarget = target;
tooltip.textContent = message;
tooltip.hidden = false;
position(clientX, clientY);
};
const hide = () => {
activeTarget = null;
tooltip.hidden = true;
};
root.addEventListener("pointerover", (event) => {
const target = event.target.closest && event.target.closest("[data-hud-tooltip]");
if (!target || !root.contains(target)) return;
show(target, event.clientX, event.clientY);
});
root.addEventListener("pointermove", (event) => {
activeTarget && position(event.clientX, event.clientY);
});
root.addEventListener("pointerout", (event) => {
if (
activeTarget &&
!activeTarget.contains(event.relatedTarget)
)
hide();
});
root.addEventListener("focusin", (event) => {
const target = event.target.closest && event.target.closest("[data-hud-tooltip]");
if (!target) return;
const bounds = target.getBoundingClientRect();
show(target, bounds.left + bounds.width / 2, bounds.top);
});
root.addEventListener("focusout", hide);
root.addEventListener("mouseleave", hide);
}
let kittyHudLauncherPositionFrame = 0;
function positionKittyHudLauncher() {
kittyHudLauncherPositionFrame && cancelAnimationFrame(kittyHudLauncherPositionFrame);
kittyHudLauncherPositionFrame = requestAnimationFrame(() => {
kittyHudLauncherPositionFrame = 0;
const launcher = document.getElementById(KITTY_HUD_LAUNCHER_ID);
if (!launcher) return;
const edge = window.innerWidth <= 700 ? 8 : 14;
let bottom = edge;
const minimap = document.getElementById("mapDisplay");
if (minimap && window.getComputedStyle(minimap).display !== "none") {
const mapBounds = minimap.getBoundingClientRect();
const launcherWidth = launcher.offsetWidth || 72;
const launcherHeight = launcher.offsetHeight || 36;
const launcherLeft = edge;
const launcherRight = launcherLeft + launcherWidth;
const launcherTop = window.innerHeight - edge - launcherHeight;
const margin = 10;
const overlapsMap =
launcherRight > mapBounds.left - margin &&
launcherLeft < mapBounds.right + margin &&
launcherTop < mapBounds.bottom + margin &&
window.innerHeight - edge > mapBounds.top - margin;
if (overlapsMap)
bottom = Math.ceil(window.innerHeight - mapBounds.top + margin);
}
launcher.style.left = edge + "px";
launcher.style.bottom = Math.min(
Math.max(edge, bottom),
Math.max(edge, window.innerHeight - (launcher.offsetHeight || 36) - edge),
) + "px";
});
}
function mountKittyHudLauncher() {
if (!document.body) return;
let launcher = document.getElementById(KITTY_HUD_LAUNCHER_ID);
if (!launcher) {
launcher = document.createElement("button");
launcher.id = KITTY_HUD_LAUNCHER_ID;
launcher.type = "button";
launcher.textContent = "Menu";
launcher.setAttribute("aria-controls", HUD_ID);
launcher.setAttribute("aria-label", "Open Kitty Klient menu");
launcher.addEventListener("click", (event) => {
event.preventDefault();
event.stopPropagation();
setKittyHudOpen(true);
});
document.body.appendChild(launcher);
}
launcher.setAttribute("aria-expanded", String(hudOpen));
launcher.classList.toggle("kitty-hud-open", hudOpen);
syncKittyAuxPanelVisibility();
positionKittyHudLauncher();
setTimeout(positionKittyHudLauncher, 250);
setTimeout(positionKittyHudLauncher, 1000);
}
function mountHud() {
if (hudMounted || !document.body) return;
if (document.getElementById(HUD_ID)) {
hudMounted = true;
mountKittyHudLauncher();
return;
}
hudMounted = true;
hudState = { ...hudState, ...readHudSettings() };
const style = document.createElement("style");
style.id = HUD_ID + "-style";
style.textContent = [
"#moomoo-op-hud{--mm-bg:rgba(8,5,13,.95);--mm-surface:rgba(20,12,30,.88);--mm-line:rgba(168,85,247,.4);--mm-text:#fff;--mm-muted:#d8b4fe;--mm-accent:#a855f7;position:fixed;z-index:2147483646;inset:0;display:grid;place-items:center;padding:28px;font:13px/1.3 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:var(--mm-text);pointer-events:none;background:rgba(0,0,0,.42);backdrop-filter:none;contain:strict}",
"#moomoo-op-hud.mm-hud-collapsed{display:none}#moomoo-op-hud *,#moomoo-op-hud *:before,#moomoo-op-hud *:after{box-sizing:border-box}#moomoo-op-hud button,#moomoo-op-hud input{font:inherit}",
"#kitty-klient-hud-launcher{position:fixed;z-index:2147483645;left:14px;bottom:14px;min-width:72px;min-height:36px;padding:0 14px;border:1px solid rgba(192,132,252,.8);border-radius:10px;background:linear-gradient(135deg,rgba(8,5,13,.9),rgba(76,29,149,.88));color:#fff;font:900 12px/1 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;cursor:pointer;box-shadow:0 0 14px rgba(139,92,246,.48);text-shadow:0 0 8px #8b5cf6;transition:transform .12s ease,opacity .12s ease,box-shadow .12s ease}#kitty-klient-hud-launcher:hover{transform:translateY(-1px);box-shadow:0 0 21px rgba(192,132,252,.72)}#kitty-klient-hud-launcher.kitty-hud-open{opacity:0;pointer-events:none}",
"#moomoo-op-hud .mm-hud-panel{pointer-events:auto;width:min(1040px,calc(100vw - 56px));height:min(720px,calc(100vh - 56px));display:grid;grid-template-rows:auto auto minmax(0,1fr);overflow:hidden;border:1px solid rgba(192,132,252,.7);border-radius:18px;background:var(--mm-bg);box-shadow:0 0 24px rgba(139,92,246,.38),0 22px 70px rgba(0,0,0,.7);backdrop-filter:none;contain:layout paint style}",
"#moomoo-op-hud .mm-hud-panel{background-image:radial-gradient(circle at 15% 0%,rgba(168,85,247,.16),transparent 34%),radial-gradient(circle at 92% 100%,rgba(109,40,217,.12),transparent 38%)}#moomoo-op-hud .mm-hud-section{transition:transform .14s ease,border-color .14s ease;content-visibility:auto;contain-intrinsic-size:170px;contain:layout paint style}#moomoo-op-hud .mm-hud-section:hover{transform:translateY(-1px);border-color:rgba(192,132,252,.58)}#moomoo-op-hud .mm-hud-nav button{position:relative}#moomoo-op-hud .mm-hud-nav button.mm-active:after{content:'';position:absolute;left:22%;right:22%;bottom:2px;height:2px;border-radius:99px;background:linear-gradient(90deg,#7c3aed,#e9d5ff,#7c3aed);box-shadow:0 0 8px #a855f7}",
"#moomoo-op-hud .mm-hud-head{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:18px 20px 12px;border-bottom:1px solid var(--mm-line)}#moomoo-op-hud .mm-hud-brand{margin:0;font-family:'Segoe Print','Bradley Hand','Brush Script MT',cursive;font-style:italic;font-size:29px;line-height:1;color:#050208!important;-webkit-text-stroke:1px #17101f;text-shadow:-2px 1px 0 #a855f7,2px -1px 0 #6d28d9,0 0 13px #c084fc!important;transform:skewX(-8deg)}#moomoo-op-hud .mm-hud-head-info{margin-left:auto}#moomoo-op-hud .mm-hud-close{display:grid;place-items:center;flex:0 0 auto;width:34px;height:34px;padding:0;border:1px solid rgba(192,132,252,.55);border-radius:9px;background:rgba(9,5,14,.76);color:#fff;font:900 24px/1 Arial,sans-serif;cursor:pointer;text-shadow:0 0 9px #a855f7}#moomoo-op-hud .mm-hud-close:hover{border-color:#e9d5ff;background:rgba(109,40,217,.3);box-shadow:0 0 13px rgba(168,85,247,.55)}",
"#moomoo-op-hud .mm-hud-status{margin:0;color:#fff;font-size:11px;font-weight:800;text-align:right;text-shadow:0 0 8px #8b5cf6}#moomoo-op-hud .mm-hud-escape{color:var(--mm-muted);font-size:10px;white-space:nowrap}",
"#moomoo-op-hud .mm-hud-nav{display:flex;gap:6px;padding:10px 14px;border-bottom:1px solid var(--mm-line);overflow-x:auto}#moomoo-op-hud .mm-hud-nav button{border:1px solid transparent;border-radius:9px;background:transparent;color:#fff;padding:8px 13px;cursor:pointer;font-weight:800;text-shadow:0 0 7px #8b5cf6}#moomoo-op-hud .mm-hud-nav button:hover,#moomoo-op-hud .mm-hud-nav button.mm-active{border-color:#a855f7;background:rgba(109,40,217,.28);box-shadow:0 0 12px rgba(168,85,247,.35)}",
"#moomoo-op-hud .mm-hud-pages{min-height:0;overflow:auto;padding:14px}#moomoo-op-hud .mm-hud-page{display:none;grid-template-columns:repeat(2,minmax(0,1fr));align-content:start;gap:12px}#moomoo-op-hud .mm-hud-page.mm-active{display:grid}",
"#moomoo-op-hud .mm-hud-section{padding:13px 14px;border:1px solid var(--mm-line);border-radius:12px;background:var(--mm-surface);box-shadow:inset 0 0 18px rgba(109,40,217,.08)}#moomoo-op-hud h3{margin:0 0 8px;font-size:11px;text-transform:uppercase;letter-spacing:.11em;color:#d8b4fe;text-shadow:0 0 7px #7c3aed}",
"#moomoo-op-hud .mm-hud-row,#moomoo-op-hud .mm-hud-number,#moomoo-op-hud .mm-hud-color{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:6px 0;cursor:pointer}#moomoo-op-hud .mm-hud-text{display:grid;gap:5px;padding:6px 0}#moomoo-op-hud .mm-hud-row span,#moomoo-op-hud .mm-hud-number span,#moomoo-op-hud .mm-hud-color span,#moomoo-op-hud .mm-hud-text>span{display:grid;gap:2px}#moomoo-op-hud strong{font-size:13px;color:#fff;text-shadow:0 0 6px #7c3aed}#moomoo-op-hud small{color:var(--mm-muted);font-size:10px}",
"#moomoo-op-hud input[type='checkbox']{appearance:none;width:36px;height:20px;margin:0;border:1px solid var(--mm-line);border-radius:999px;background:#21172b;position:relative;flex:0 0 auto;cursor:pointer}#moomoo-op-hud input[type='checkbox']:after{content:'';position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#fff;box-shadow:0 0 7px #c084fc;transition:transform .14s ease}#moomoo-op-hud input[type='checkbox']:checked{background:#7c3aed;border-color:#c084fc;box-shadow:0 0 10px rgba(168,85,247,.65)}#moomoo-op-hud input[type='checkbox']:checked:after{transform:translateX(16px)}",
"#moomoo-op-hud input[type='number']{width:68px;border:1px solid var(--mm-line);border-radius:7px;background:#09050e;color:#fff;padding:6px;text-align:right}#moomoo-op-hud input[type='color']{width:42px;height:30px;padding:3px;border:1px solid var(--mm-line);border-radius:8px;background:#09050e;cursor:pointer}#moomoo-op-hud input[type='color']::-webkit-color-swatch{border:0;border-radius:5px}#moomoo-op-hud .mm-hud-message{width:100%;border:1px solid var(--mm-line);border-radius:8px;background:#09050e;color:#fff;padding:8px;margin:3px 0 7px}",
"#moomoo-op-hud .mm-hud-slider{display:grid;grid-template-columns:minmax(0,1fr) minmax(150px,42%);align-items:center;gap:12px;padding:8px 0;cursor:pointer}#moomoo-op-hud .mm-hud-slider>span:first-child{display:grid;gap:2px}#moomoo-op-hud .mm-hud-slider-control{display:grid;grid-template-columns:minmax(0,1fr) 25px;align-items:center;gap:8px}#moomoo-op-hud .mm-hud-slider output{color:#fff;font:900 12px/1 ui-monospace,SFMono-Regular,Menlo,monospace;text-align:right;text-shadow:0 0 8px #a855f7}#moomoo-op-hud input[type='range']{appearance:none;width:100%;height:5px;border-radius:999px;background:linear-gradient(90deg,#6d28d9,#c084fc);box-shadow:0 0 9px rgba(168,85,247,.5);cursor:pointer}#moomoo-op-hud input[type='range']::-webkit-slider-thumb{appearance:none;width:16px;height:16px;border:2px solid #e9d5ff;border-radius:50%;background:#7c3aed;box-shadow:0 0 10px #c084fc}",
"#moomoo-op-hud .mm-hud-adaptive-status{display:block;margin:1px 0 7px;padding:6px 8px;border:1px solid rgba(168,85,247,.28);border-radius:7px;background:rgba(9,5,14,.5);color:#fff;font:800 10px/1.25 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 7px #7c3aed}",
"#moomoo-op-hud .mm-hud-reset{border:1px solid var(--mm-line);border-radius:8px;background:#0b0711;color:#fff;padding:8px;cursor:pointer}#moomoo-op-hud .mm-hud-reset:hover{border-color:var(--mm-accent);box-shadow:0 0 11px rgba(168,85,247,.45)}#moomoo-op-hud .mm-hud-preset-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px;margin-bottom:8px}#moomoo-op-hud .mm-hotkey-list{display:grid;gap:4px}#moomoo-op-hud .mm-hotkey-entry{display:grid;grid-template-columns:minmax(150px,.88fr) minmax(0,1.6fr) auto;gap:10px;align-items:center;padding:7px 0;border-bottom:1px solid rgba(168,85,247,.16)}#moomoo-op-hud .mm-hotkey-entry:last-child{border-bottom:0}#moomoo-op-hud .mm-hotkey-combo{display:flex;flex-wrap:wrap;gap:4px;align-items:center}#moomoo-op-hud kbd{display:inline-flex;align-items:center;justify-content:center;min-width:24px;min-height:23px;padding:2px 7px;border:1px solid rgba(216,180,254,.72);border-bottom-width:2px;border-radius:6px;background:linear-gradient(#1f142b,#0a0610);color:#fff;font:900 10px/1 ui-monospace,SFMono-Regular,Menlo,monospace;box-shadow:0 0 8px rgba(168,85,247,.24);text-shadow:0 0 6px #7c3aed}#moomoo-op-hud .mm-hotkey-plus{color:#c4b5fd;font-size:9px;font-weight:900}#moomoo-op-hud .mm-hotkey-action{display:grid;gap:2px}#moomoo-op-hud .mm-hotkey-action small{line-height:1.3}#moomoo-op-hud .mm-hotkey-intro{display:grid;grid-column:1/-1;gap:9px}#moomoo-op-hud .mm-hotkey-intro-actions{display:flex;gap:7px;flex-wrap:wrap}#moomoo-op-hud .mm-hotkey-bind{min-height:32px;padding:4px 7px;border:1px solid rgba(168,85,247,.42);border-radius:8px;background:rgba(9,5,14,.78);cursor:pointer;text-align:left}#moomoo-op-hud .mm-hotkey-bind:hover{border-color:#c084fc;box-shadow:0 0 12px rgba(168,85,247,.36)}#moomoo-op-hud .mm-hotkey-bind.mm-capturing{border-color:#facc15;box-shadow:0 0 16px rgba(250,204,21,.4);animation:mm-hotkey-capture 1s ease-in-out infinite alternate}#moomoo-op-hud .mm-hotkey-row-reset{width:29px;height:29px;padding:0;border:1px solid rgba(168,85,247,.32);border-radius:7px;background:transparent;color:#d8b4fe;cursor:pointer}#moomoo-op-hud .mm-hotkey-row-reset:hover{border-color:#c084fc;color:#fff}@keyframes mm-hotkey-capture{to{filter:brightness(1.35)}}@media(max-width:720px){#moomoo-op-hud .mm-hotkey-entry{grid-template-columns:1fr auto}#moomoo-op-hud .mm-hotkey-action{grid-column:1/-1;grid-row:2}}",
"#moomoo-op-hud .mm-hud-discord{display:flex;align-items:center;justify-content:center;min-height:38px;padding:0 14px;border:1px solid #c084fc;border-radius:9px;background:linear-gradient(135deg,#4c1d95,#7c3aed);color:#fff!important;font-size:12px;font-weight:900;text-decoration:none;box-shadow:0 0 14px rgba(168,85,247,.4);text-shadow:0 0 7px #2e1065!important;transition:transform .12s ease,filter .12s ease}#moomoo-op-hud .mm-hud-discord:hover{filter:brightness(1.14);transform:translateY(-1px);box-shadow:0 0 18px rgba(192,132,252,.62)}",
"#moomoo-op-hud .mm-hud-friend-actions{display:grid;grid-template-columns:1fr auto auto;gap:6px;align-items:center}#moomoo-op-hud .mm-hud-friend-actions .mm-hud-message{margin:3px 0 7px}#moomoo-op-hud .mm-hud-friend-list{display:flex;flex-wrap:wrap;gap:6px;min-height:24px;align-items:center}#moomoo-op-hud .mm-hud-friend-chip{border:1px solid rgba(250,204,21,.68);border-radius:999px;background:rgba(250,204,21,.12);color:#fff;padding:4px 8px;box-shadow:0 0 8px rgba(250,204,21,.28);text-shadow:0 0 6px #eab308}",
"#moomoo-op-hud .mm-hud-debug{margin:4px 0 7px;white-space:pre-wrap;overflow-wrap:anywhere;border:1px solid var(--mm-line);border-radius:8px;background:rgba(0,0,0,.45);color:#fff;padding:8px;font:10px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;text-shadow:0 0 6px #7c3aed}",
"#moomoo-op-hud [data-hud-sync-status][data-sync-phase='synced']{border-color:rgba(74,222,128,.72);box-shadow:0 0 11px rgba(74,222,128,.25);color:#dcfce7}#moomoo-op-hud [data-hud-sync-status][data-sync-phase='syncing']{border-color:rgba(192,132,252,.82);animation:mm-hud-sync-pulse .8s ease-in-out infinite alternate}#moomoo-op-hud [data-hud-sync-status][data-sync-phase='error']{border-color:rgba(248,113,113,.8);color:#fee2e2}@keyframes mm-hud-sync-pulse{from{box-shadow:0 0 4px rgba(168,85,247,.2)}to{box-shadow:0 0 14px rgba(192,132,252,.55)}}",
"#moomoo-op-hud .mm-hud-tooltip{position:fixed;z-index:2147483647;max-width:min(320px,calc(100vw - 20px));padding:7px 9px;border:1px solid rgba(192,132,252,.72);border-radius:8px;background:rgba(7,3,12,.96);color:#fff;box-shadow:0 0 15px rgba(139,92,246,.5),0 8px 24px rgba(0,0,0,.55);font:700 11px/1.35 system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;text-shadow:0 0 7px #7c3aed;pointer-events:none;white-space:normal;overflow-wrap:anywhere}#moomoo-op-hud .mm-hud-tooltip[hidden]{display:none}",
"@media(max-width:720px){#moomoo-op-hud{padding:10px}#moomoo-op-hud .mm-hud-panel{width:calc(100vw - 20px);height:calc(100vh - 20px)}#moomoo-op-hud .mm-hud-page{grid-template-columns:1fr}#moomoo-op-hud .mm-hud-head{padding:14px}#moomoo-op-hud .mm-hud-brand{font-size:23px}}"
].join("");
(document.head || document.documentElement).appendChild(style);
const root = document.createElement("aside");
root.id = HUD_ID;
root.className = "mm-hud-collapsed";
root.setAttribute("aria-label", "kitty klient controls");
const panel = document.createElement("div");
panel.className = "mm-hud-panel";
panel.addEventListener("mousedown", (event) => event.stopPropagation());
panel.addEventListener("click", (event) => event.stopPropagation());
const head = document.createElement("header");
head.className = "mm-hud-head";
const brand = document.createElement("h2");
brand.className = "mm-hud-brand";
brand.textContent = "kitty klient";
setHudTooltip(brand, "kitty klient v" + KITTY_KLIENT_VERSION);
const headInfo = document.createElement("div");
headInfo.className = "mm-hud-head-info";
const status = document.createElement("p");
status.className = "mm-hud-status";
status.dataset.hudStatus = "";
setHudTooltip(status, "Currently enabled Kitty automation and combat features");
const escapeHint = document.createElement("span");
escapeHint.className = "mm-hud-escape";
escapeHint.textContent = "ESC toggles · WASDFVR returns straight to the game";
setHudTooltip(escapeHint, "Escape closes Kitty. Gameplay keys close it and continue directly into the game.");
headInfo.append(status, escapeHint);
const closeButton = document.createElement("button");
closeButton.className = "mm-hud-close";
closeButton.type = "button";
closeButton.setAttribute("aria-label", "Close Kitty Klient menu");
closeButton.textContent = "×";
setHudTooltip(closeButton, "Close the Kitty HUD and return to the game");
closeButton.addEventListener("click", () => {
if (kittyTutorialActive) stopKittyTutorial(false);
setKittyHudOpen(false);
});
head.append(brand, headInfo, closeButton);
const nav = document.createElement("nav");
nav.className = "mm-hud-nav";
const pages = document.createElement("div");
pages.className = "mm-hud-pages";
const pageMap = new Map();
const activatePage = (name) => {
nav.querySelectorAll("button").forEach((button) => button.classList.toggle("mm-active", button.dataset.page === name));
pages.querySelectorAll(".mm-hud-page").forEach((page) => page.classList.toggle("mm-active", page.dataset.page === name));
};
const addPage = (name, label, tooltip) => {
const button = document.createElement("button");
button.type = "button";
button.dataset.page = name;
button.textContent = label;
setHudTooltip(button, tooltip);
button.addEventListener("click", () => activatePage(name));
nav.appendChild(button);
const page = document.createElement("div");
page.className = "mm-hud-page";
page.dataset.page = name;
pages.appendChild(page);
pageMap.set(name, page);
return page;
};
const automationPage = addPage("automation", "Automation", "Automatic survival, equipment, gathering, and cleanup features");
const combatPage = addPage("combat", "Combat", "Combat combos, defenses, boosts, and friend targeting controls");
const placementPage = addPage("placement", "Placement", "Kitty predictive placement controllers and scoring methods");
const visualsPage = addPage("visuals", "Visuals", "Player markers, connection lines, predictions, cooldowns, and chat visuals");
const syncPage = addPage("sync", "Sync", "Copy movement or synchronize combat with another Kitty teammate");
const configPage = addPage("config", "Config", "Ranges, diagnostics, chat messages, saved settings, and community links");
const hotkeysPage = addPage("hotkeys", "Hotkeys", "Complete Kitty and core MooMoo keyboard and mouse shortcut library");
panel.append(head, nav, pages);
const survivalAutomation = addHudSection(automationPage, "Survival & defense");
addHudToggle(survivalAutomation, "autoHeal", "Autoheal", "Immediate first food, then tick-paced recovery");
addHudToggle(survivalAutomation, "soldierAuto", "Soldier helmet", "Idle protection and combat range");
addHudToggle(survivalAutomation, "movementGear", "Movement gear", "Speed gear while moving, Soldier around enemies, and EMP Helmet only while idle and out of combat, plus adaptive tails");
addHudToggle(survivalAutomation, "trapEscape", "Trap escape", "Face and continuously break the locking trap; pulse Tank only for a real break swing, use the best normal hat between hits, and place up to two smart rear defenses");
addHudToggle(survivalAutomation, "automaticStateRepair", "Automatic state repair", "Recover orphaned Bull, Tank, Turret, held-attack, forced-aim, and borrowed-tool state after an interrupted packet or timer");
addHudToggle(survivalAutomation, "antiBoostInsta", "Anti-boost insta", "Full-insta an enemy boost-rushing into range");
addHudToggle(survivalAutomation, "antiInsta", "Lethal anti-insta", "Use unified melee/projectile/turret/spike prediction to place one defensive spike before otherwise lethal incoming damage");
addHudToggle(survivalAutomation, "antiCollision", "Anti TP / spike collision", "Predictive braking: always stop before Teleporters, avoid hostile spikes while safe, quick-right-click toward TPs, then allow one deliberate release/re-press bypass");
addHudToggle(survivalAutomation, "antiCollisionPauseCombat", "Spike guard combat auto-pause", "Keep Teleporter protection active but temporarily ignore hostile-spike stopping while combat is active");
addHudToggle(survivalAutomation, "shieldDefense", "Shield defense", "Face polearm and turret attacks");
addHudToggle(survivalAutomation, "placementDefense", "Projectile placement defense", "Place one legal wall, blocker, platform, or mill toward an obstruction-aware incoming projectile that is imminent or lethal");
addHudToggle(survivalAutomation, "antiRetrapPush", "Anti-retrap push", "If your locking trap is already a one-hit Hammer break, briefly push a close enemy away with your ready primary before resuming escape");
addHudToggle(survivalAutomation, "teammateTrapRescue", "Teammate trap rescue", "Great Hammer a trap holding a reachable teammate or friend, using Tank when owned, then restore immediately");
const utilityAutomation = addHudSection(automationPage, "Equipment & utility");
addHudToggle(utilityAutomation, "autoAcceptTeamRequests", "Auto accept team requests", "Immediately accept incoming requests to join your team");
addHudToggle(utilityAutomation, "autoDeclineTeamRequests", "Auto decline team requests", "Immediately decline incoming requests to join your team");
addHudToggle(utilityAutomation, "autoRespawn", "Auto respawn", "Re-enter after the local death screen appears; disabled by default");
addHudToggle(utilityAutomation, "musketRecharge", "Weapon recharge", "Main-first queue that briefly borrows held attacks to reload the other weapon");
addHudToggle(utilityAutomation, "autoPurchase", "Auto purchase", "Monkey Tail → Soldier → Stick/Bull path → gear → wings");
addHudToggle(utilityAutomation, "matThief", "Mat thief", "Last-hit nearby mills, turrets, and teleporters; starts disabled");
addHudToggle(utilityAutomation, "multiTargetBreak", "Multi-target breaking", "While holding an attack or cleaning, choose a nearby legal swing angle that hits the most breakables");
addHudToggle(utilityAutomation, "mobSteal", "Mob steal", "Predictive last hit: Monkey Tail off three ticks early, Bull on two ticks early, then revalidates and swings");
addHudToggle(utilityAutomation, "turretSteal", "Turret finisher", "Use a ready Turret Gear shot on a visible enemy or animal at 25 health or less without stealing another combat action");
addHudToggle(utilityAutomation, "dashMovement", "Boost-pad dash break", "When H is held on a boost pad, Tank + a ready one-hit weapon destroys each manual pad on the same local phase");
addHudToggle(utilityAutomation, "assassinAutomation", "Assassin automation", "When stationary and safe, buy Assassin Gear if affordable, wait out concealment safety, then equip it; starts disabled");
addHudNumber(utilityAutomation, "assassinSafeMs", "Assassin safe delay", "Stationary and invisibility-cooldown milliseconds required after movement, damage, combat, or turret danger");
addHudNumber(utilityAutomation, "assassinMinHealth", "Assassin minimum health", "Minimum health percentage required before concealment");
addHudNumber(utilityAutomation, "assassinDangerRange", "Assassin danger radius", "Enemy-player and hostile-turret exclusion distance");
addHudToggle(utilityAutomation, "spinningWindmills", "Spinning windmills", "Allow native mill rotation; off freezes every mill without a background placement scanner");
addHudToggle(utilityAutomation, "forceFullServers", "Force full servers", "Show, select, and attempt to join servers the normal browser marks full; the server can still reject a truly full shard");
addHudToggle(utilityAutomation, "bushMode", "Bush ambush", "B toggles concealment; automatic ambush says SURPRISE, while R manually runs the same boost-first combo and says Meow; empty clicks stay concealed and incoming damage turns it off");
const tabSync = addHudSection(syncPage, "Connection & target");
const syncHint = document.createElement("small");
syncHint.textContent = "Press Y, then click a teammate for a one-way link. They only follow you back if they independently press Y and click you. Click your target again to disconnect.";
setHudTooltip(syncHint, "Visible movement works with any teammate; exact off-screen action and tick timing requires Kitty on both clients");
tabSync.appendChild(syncHint);
addHudToggle(tabSync, "syncStatusChat", "Sync status chat", "Announce Syncing..., Synced!, and Sync stopped. once per link-state transition");
addHudText(tabSync, "syncRelayUrl", "Relay WebSocket", "Optional Kitty-to-Kitty exact sync across browsers; visible teammate following works without it", {
maxLength: 200,
placeholder: "wss://sync.example.com"
});
addHudText(tabSync, "syncRoom", "Private sync room", "Kitty users need the same case-sensitive phrase for exact cross-browser timing", {
maxLength: 64,
placeholder: "team room phrase",
password: true
});
const syncReadout = document.createElement("pre");
syncReadout.className = "mm-hud-debug";
syncReadout.dataset.hudSyncStatus = "";
syncReadout.textContent = "Sync off";
setHudTooltip(syncReadout, "Selected teammate and available sync precision");
tabSync.appendChild(syncReadout);
const syncMovement = addHudSection(syncPage, "Follow movement");
addHudToggle(syncMovement, "syncMovement", "Movement follow", "Walk to the selected teammate's predicted side position");
addHudNumber(syncMovement, "syncFollowGap", "Hitbox gap", "Minimum pixels kept between the edges of both player hitboxes");
addHudNumber(syncMovement, "syncStopTolerance", "Stop tolerance", "Extra arrival buffer so momentum stops before violating the hitbox gap");
addHudNumber(syncMovement, "syncResumeTolerance", "Resume tolerance", "How far the side target may drift before following resumes");
addHudNumber(syncMovement, "syncPredictionMs", "Position prediction", "Milliseconds of velocity lead used to hide visible follow delay");
addHudNumber(syncMovement, "syncMoveRefreshMs", "Direction refresh", "Maximum milliseconds between movement-direction updates");
addHudToggle(syncMovement, "syncPauseInCombat", "Pause follow in combat", "Stop automatic movement while either linked player is fighting");
addHudToggle(syncMovement, "syncWasdCombatOnly", "WASD keeps combat link", "Manual WASD disables movement follow but preserves combat synchronization");
const syncCatchup = addHudSection(syncPage, "Catch-up behavior");
addHudToggle(syncCatchup, "syncCatchupGear", "Fast catch-up gear", "Use the fastest owned hat, tail, and compatible tool while far behind and out of combat");
addHudNumber(syncCatchup, "syncCatchupDistance", "Catch-up starts", "Side-target distance that activates fast equipment");
addHudNumber(syncCatchup, "syncCatchupReleaseDistance", "Catch-up ends", "Side-target distance that restores copied or previous equipment");
const syncActions = addHudSection(syncPage, "Copied actions");
addHudToggle(syncActions, "syncCopyWeapons", "Copy weapons", "Mirror compatible weapon selections from the selected teammate");
addHudToggle(syncActions, "syncCopyBuilds", "Copy build items", "Mirror compatible placeable selections from the selected teammate");
addHudToggle(syncActions, "syncCopyGear", "Copy hats & tails", "Mirror compatible gear pairs, including same-tick hat and tail updates");
addHudToggle(syncActions, "syncCopyAim", "Copy aim", "Mirror exact aim packets when a Kitty or compatible mod bridge provides them");
addHudToggle(syncActions, "syncCopyAttacks", "Copy attacks", "Mirror press-and-release swings from the selected teammate");
addHudToggle(syncActions, "syncTickCombat", "Combat tick sync", "Queue full instas on one shared relay timestamp so Turret, weapons, and projectiles start together");
const visuals = addHudSection(visualsPage, "Visuals");
addHudToggle(visuals, "fpsBoost", "FPS boost", "Uses cheaper Kitty visual effects and bounded overlay budgets without slowing combat checks");
addHudToggle(visuals, "smoothVisuals", "Polished entity styling", "Layered translucent markers, soft outlines, and relation-colored depth without covering the playfield");
addHudToggle(visuals, "reloadArcs", "Smooth reload arcs", "Primary, secondary, and Turret refill arcs around you and the selected enemy");
addHudToggle(visuals, "entityDanger", "Entity danger aura", "Pulse a restrained danger field around close hostile players and hostile animals");
addHudToggle(visuals, "notificationTracers", "Clan alert tracers", "While you are on a team, place a directional ! marker halfway from your player toward a teammate's distress ping");
addHudToggle(visuals, "groundGrid", "Ground grid", "Draws a camera-aligned purple world grid beneath players, animals, and placeables");
addHudToggle(visuals, "esp", "Player & animal markers", "Colored circles plus a rotating red target reticle on the nearest enemy");
addHudToggle(visuals, "espLines", "Player direction arrows", "Large high-contrast relationship-colored arrows sit midway between you and each player; enemies use the thickest style");
addHudToggle(visuals, "predictionGhost", "Prediction ghost", "A translucent copy projects ahead by half your live ping");
addHudToggle(visuals, "placementVisuals", "Placement previews", "Shows blocked sample slots, scored legal candidates, predicted pre-places, and the exact slots Kitty selects");
addHudToggle(visuals, "cooldownBars", "Tool cooldown bars", "Three refill bars track primary, secondary, and Turret Gear cooldowns independently");
addHudToggle(visuals, "weaponXpBar", "Weapon XP bar", "Compact local progress bar uses the live weapon XP and next upgrade threshold");
addHudToggle(visuals, "chatHistory", "Stacked chat bubbles", "Shows up to three unexpired messages above each player plus the in-game chat-history panel");
const relationshipColors = addHudSection(visualsPage, "Relationship colors");
addHudColor(relationshipColors, "enemyColor", "Enemies", "Player markers, target reticle, chat, and hostile placeables");
addHudColor(relationshipColors, "allyColor", "Teammates", "Team player markers, chat, and allied placeables");
addHudColor(relationshipColors, "friendColor", "Friends", "Saved friend markers and chat-history entries");
addHudColor(relationshipColors, "ownColor", "Your placeables", "Tint used for structures that you own");
const combatTelemetry = addHudSection(visualsPage, "Combat telemetry");
addHudToggle(combatTelemetry, "combatTelemetry", "Telemetry master", "Enable the bounded canvas telemetry layer; individual rows below remain independently configurable");
addHudToggle(combatTelemetry, "telemetryProjectileHits", "Predicted projectile hits", "Draw obstruction-aware hostile projectile paths, impact times, and damage");
addHudToggle(combatTelemetry, "telemetrySpikeKnockback", "Spike knockback", "Mark predicted hostile spike follow-up damage from incoming attacks");
addHudToggle(combatTelemetry, "telemetryActualAim", "Actual aim", "Draw the server-facing weapon direction and reach for visible players");
addHudToggle(combatTelemetry, "telemetryBuildingOwners", "Building owners", "Label nearby breakables with their resolved owner name or server id");
addHudToggle(combatTelemetry, "telemetryShameCount", "Shame count", "Show Kitty's locally tracked rapid-heal shame value beside your player");
addHudToggle(combatTelemetry, "telemetryDamageHealing", "Damage & healing values", "Stack recent health losses and gains above affected visible players");
const actions = addHudSection(combatPage, "Gear & boost controls");
addHudToggle(actions, "bullHelmet", "Bull helmet", "Equip Bull and the damage tail in the exact ready primary-swing phase, then restore on the next server tick");
addHudToggle(actions, "tankRightClick", "Smart right-click", "With Shield: block close or ranged pressure; otherwise use Tank + main on its exact swing phase");
addHudToggle(actions, "instaKill", "R insta", "Bull primary, then Turret secondary, then Soldier restore");
addHudToggle(actions, "autoInsta", "Click insta", "Left-click starts the full combo; Shift+click starts Crossbow boost insta");
addHudToggle(actions, "autoTrapInsta", "Owned-trap insta", "Full-insta a nearby caught enemy; every Great Hammer Insta attempts a legal spike after the combo, preferring target contact");
addHudToggle(actions, "spikeGearCounter", "Spike Gear counter", "With Spike Gear + Corrupt X Wings owned, pre-arm both in one phase against a close Bull-primary swing, then answer with Bull + your ready primary");
addHudToggle(actions, "autoSpikeInsta", "Spike-tick strike", "Ping-timed Turret lead-in, then Bull + Polearm/Katana on predicted allied-spike contact");
addHudToggle(actions, "instaSync", "Insta sync", "Predictively matches allied-player and allied-turret projectile arrivals");
addHudToggle(actions, "boostBreak", "Shift + F boost-break", "Place and boost forward, snap 180° for each destroy swing, then instantly face forward again");
const kittyInstas = addHudSection(combatPage, "Kitty Insta library");
addHudToggle(kittyInstas, "autoBowUpgradeInsta", "Bow Upgrade Insta", "Any primary works: with Bow, a special placeable, Turret Gear, and two saved upgrades, R fires Bow → Crossbow → Musket; an in-range Short Sword, Katana, or Polearm runs the normal Insta first and hands its Bow shot straight into the upgrades. Friendly and personal-turret shots can trigger it too");
addHudToggle(kittyInstas, "reverseInsta", "Reverse R order", "R uses Turret + secondary first, then Bull + primary; Shift+R remains Kitty's Crossbow boost Insta");
addHudToggle(kittyInstas, "oneTickInsta", "One-Tick Insta", "Shift+P toggles the secondary-first one-server-tick combo; projectile timing is prediction-adjusted");
addHudToggle(kittyInstas, "appleInsta", "Apple Insta", "Automatically uses Turret + Great Hammer, then Bull + Polearm against a nearby Soldier-helmet target");
addHudToggle(kittyInstas, "bleedInsta", "Bleed Insta", "Automatically runs the variant-damage secondary-first combo against a vulnerable non-Soldier target");
addHudToggle(kittyInstas, "knockbackInsta", "Knockback Insta", "Predicts whether the opening hit pushes a target into an allied spike, then commits the Polearm finisher");
addHudToggle(kittyInstas, "velTickInsta", "VelTick Insta", "T toggles predictive 170–245px spacing, Turret lead-in, and Bull + Polearm finish");
addHudToggle(kittyInstas, "polearmAids", "Polearm Aids", "Against a target in your or an ally's trap: Tank + Great Hammer, then Bull + Polearm and a legal contact spike");
addHudToggle(kittyInstas, "autoPushInsta", "Auto-Push Insta", "Aligns behind a trapped enemy to push it into an allied spike, and upgrades predicted spike contact to a full Insta");
addHudToggle(kittyInstas, "boostSpikeKill", "Boost + Spike", "G predicts the nearest enemy, sends legal side/contact spikes first, then boosts through the open lane");
const smartPlacementCore = addHudSection(placementPage, "Kitty smart auto place");
addHudToggle(smartPlacementCore, "smartAutoPlace", "General smart placement", "Generic scored spike-and-pit-trap scanner; automatic quad trap and spike toggles continue independently when this is off");
addHudToggle(smartPlacementCore, "smartPreplace", "Predictive pre-place", "Lead enemy velocity by ping plus one tick and place before contact");
addHudToggle(smartPlacementCore, "smartMultiPlace", "Multi-place", "Choose several high-scoring non-overlapping slots in one placement phase");
addHudToggle(smartPlacementCore, "smartQuadTraps", "Automatic quad traps", "Without a hotkey, fill up to four legal non-overlapping trap-pressure angles when an enemy enters the automatic placement radius");
addHudToggle(smartPlacementCore, "smartQuadSpikes", "Automatic quad spikes", "Without a hotkey, prefer up to four legal contact, trapped-surround, or knockback-chain spikes around a close enemy");
addHudToggle(smartPlacementCore, "smartSpikeContact", "Spike contact", "Score legal spikes that touch or intercept an enemy");
addHudToggle(smartPlacementCore, "smartTrapContact", "Trap and retrap", "Score pit traps that catch, retrap, or block an enemy's route");
addHudToggle(smartPlacementCore, "smartKnockbackChain", "Knockback chaining", "Prefer spikes that push an enemy into allied traps, spikes, or map hazards");
addHudToggle(smartPlacementCore, "smartTrapSurround", "Trapped surround", "Fill legal escape-side slots around an enemy already held by an allied trap");
addHudToggle(smartPlacementCore, "smartAngleDenial", "Placement denial", "Score slots that intercept the enemy's own useful placement angles");
addHudToggle(smartPlacementCore, "smartAutoPushWeight", "Auto-push weighting", "Raise candidates that support pushing a trapped enemy into allied spikes");
const placementReadout = document.createElement("pre");
placementReadout.className = "mm-hud-debug";
placementReadout.dataset.hudPlacementStatus = "";
placementReadout.textContent = "STARTING — waiting for live game state";
setHudTooltip(placementReadout, "Live placement state, legal/scored slot counts, sent packet count, and equipped item readiness");
smartPlacementCore.appendChild(placementReadout);
const smartPlacementEvents = addHudSection(placementPage, "Event placement");
addHudToggle(smartPlacementEvents, "autoSpikeSpam", "Trapped-player spike fill", "Continuously finds and places a legal contact spike around a trapped enemy when your movement shows attack intent");
addHudToggle(smartPlacementEvents, "autoSpikeKill", "Lethal spike push", "Predictively place a spike that keeps contact while pushing a killable enemy into allied spikes");
addHudToggle(smartPlacementEvents, "smartAutoReplace", "Destroyed-object replace", "Immediately rescan and refill useful legal slots when a nearby structure disappears");
addHudToggle(smartPlacementEvents, "smartSpikeSyncPlace", "Spike-sync replace", "Prioritize a contact spike when a nearby enemy's allied trap is broken");
addHudToggle(smartPlacementEvents, "smartAntiBoostPlace", "Anti-boost fallback", "Blocker ring → side/rear spikes → trap ring → wall ring against a predicted boost rush");
addHudToggle(smartPlacementEvents, "smartMovingMills", "Moving three-mill", "Probe every movement tick and place a geometry-spaced three-mill row as soon as every slot is clear");
addHudToggle(smartPlacementEvents, "smartInstaUtilityPlace", "Projectile utility place", "Place an equipped Platform before compatible projectile-sync and boost-projectile stages");
const wildlifePlacement = addHudSection(placementPage, "Wildlife placement");
addHudToggle(wildlifePlacement, "animalTrap", "Animal trap", "Trap a nearby hostile animal; fall back to a spike when no usable pit trap exists, except against wolves");
addHudToggle(wildlifePlacement, "passiveMobTrap", "Passive mob trap", "Predictively place a pit trap on a nearby passive mob's path; hostile animals and bosses keep priority, and already trapped mobs are ignored");
addHudToggle(wildlifePlacement, "bossTeleporter", "Boss teleporter", "Place a Teleporter between you and nearby Moostafa or Moofie when it is owned, affordable, and the boss is not already trapped");
const smartPlacementTuning = addHudSection(placementPage, "Placement tuning");
addHudToggle(smartPlacementTuning, "adaptiveSmartness", "Adaptive smartness", "Lower effective placement depth during sustained FPS pressure, then recover it gradually when frames are stable—faster during combat");
addHudSlider(smartPlacementTuning, "smartDepth", "Smartness depth ceiling", "1 is lightweight and reactive; 10 searches more angles, enemy branches, and future movement at a higher CPU cost");
const adaptiveSmartnessReadout = document.createElement("small");
adaptiveSmartnessReadout.className = "mm-hud-adaptive-status";
adaptiveSmartnessReadout.dataset.hudAdaptiveSmartness = "";
adaptiveSmartnessReadout.textContent = "Effective depth 5/5 · sampling FPS";
setHudTooltip(adaptiveSmartnessReadout, "The first number is the depth currently used by placement searches; the second is your selected ceiling");
smartPlacementTuning.appendChild(adaptiveSmartnessReadout);
addHudNumber(smartPlacementTuning, "smartPlaceAccuracy", "Angle accuracy", "Placement samples per half-ring");
addHudNumber(smartPlacementTuning, "smartMaxPlacements", "Maximum placements", "Legal non-overlapping items per phase");
addHudNumber(smartPlacementTuning, "smartPlaceDelay", "Pre-place delay", "Milliseconds before a predictive pre-place; ping is subtracted");
const friends = addHudSection(combatPage, "Friends");
const friendHint = document.createElement("small");
friendHint.textContent = "Press U to friend or I to mark an enemy, then click a non-teammate. Teammates are always allies and cannot be added as friends or enemies.";
setHudTooltip(friendHint, "Friend rules apply to automatic targeting, traps, instas, and player markers");
const friendList = document.createElement("div");
friendList.className = "mm-hud-friend-list";
friendList.dataset.hudFriends = "";
setHudTooltip(friendList, "Saved non-teammate friends; use U + click to add and I + click to remove");
friends.append(friendHint, friendList);
const tuning = addHudSection(configPage, "Distance tuning");
addHudNumber(tuning, "soldierRange", "Soldier radius", "Pixels");
addHudNumber(tuning, "combatRange", "Combat radius", "Tail behavior cutoff");
addHudNumber(tuning, "gearHoldTicks", "Gear restore grace", "Ticks allowed for delayed equipment-state reconciliation");
addHudNumber(tuning, "antiBoostRange", "Boost-insta radius", "Pixels");
addHudNumber(tuning, "antiCollisionRange", "Collision guard radius", "Maximum distance for Teleporter and hostile-spike prediction");
addHudNumber(tuning, "reactionMs", "Reaction scan", "Milliseconds between live-state checks");
const diagnostics = addHudSection(configPage, "Diagnostics");
addHudToggle(diagnostics, "debugPanel", "Runtime debug", "Show live owner, target, trap, and cooldown reasons");
const debugReadout = document.createElement("pre");
debugReadout.className = "mm-hud-debug";
debugReadout.dataset.hudDebug = "";
debugReadout.hidden = !hudState.debugPanel;
setHudTooltip(debugReadout, "Live action owner, target distance, trap state, reload state, and scan age");
diagnostics.appendChild(debugReadout);
const messages = addHudSection(configPage, "Chat automation");
addHudToggle(messages, "instaChat", "Insta complete · Meow!", "Send Meow! after a completed normal or boost insta");
addHudToggle(messages, "bushChat", "Bush ambush · SURPRISE!!!", "Send SURPRISE!!! when a bush ambush begins");
addHudToggle(messages, "friendAddedChat", "Friend-added message", "Announce Added friend, [name]! after U + click");
addHudToggle(messages, "enemyMarkedChat", "Enemy-marked message", "Announce [name] is an enemy! after I + click or betrayal detection");
addHudToggle(messages, "cleanupProgressChat", "Cleanup progress", "Send the animated Cleaning messages while cleanup runs");
addHudToggle(messages, "cleanupCompleteChat", "Cleanup completion", "Send Nice and tidy! when cleanup finishes");
addHudToggle(messages, "boostChat", "Shift + F chat", "Send shuffled speed messages during boost-break");
addHudToggle(messages, "materialReply", "Material request reply", "Tell teammates and friends your current wood and stone when they ask for materials");
addHudToggle(messages, "meowChainInsta", "Meow chain insta", "If a recently attacking Kitty teammate says Meow!, start your own ready in-range insta; completion uses the Insta Meow toggle");
addHudToggle(messages, "modReplyChat", "Mod-question reply", "Reply with the Kitty Klient version when another player asks about mods or clients");
addHudToggle(messages, "enemyTrapChat", "Enemy trapped message", "Send Ha, I have you in my trap! for trapped enemies");
addHudToggle(messages, "friendTrapChat", "Friend trapped message", "Send Uh oh! let me free you! for trapped friends");
addHudToggle(messages, "trapAlertChat", "Self trapped message", "Send Oh no! A trap! once per trapping incident");
addHudToggle(messages, "deathHistoryChat", "Death history entries", "Add [name] died notices to Kitty's local chat-history panel");
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;
setHudTooltip(message, "Message sent after your kill count increases; maximum 30 characters");
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 community = addHudSection(configPage, "Community");
const discord = document.createElement("a");
discord.className = "mm-hud-discord";
discord.href = "https://discord.gg/mHvC2kJSH";
discord.target = "_blank";
discord.rel = "noopener noreferrer";
discord.textContent = "Join official Discord server";
setHudTooltip(discord, "Open the official Kitty Klient Discord invite in a new tab");
community.appendChild(discord);
const savedSettings = addHudSection(configPage, "Saved settings");
const presetGrid = document.createElement("div");
presetGrid.className = "mm-hud-preset-grid";
[
["performance", "Performance", "Reduce optional drawing while leaving gameplay settings alone"],
["combat", "Combat", "Enable useful combat feedback with a faster reaction scan"],
["visual", "Visual", "Enable the full visual toolset and ground grid"]
].forEach(([name, label, tooltip]) => {
const button = document.createElement("button");
button.className = "mm-hud-reset";
button.type = "button";
button.textContent = label;
setHudTooltip(button, tooltip);
button.addEventListener("click", () => applyHudPreset(name));
presetGrid.appendChild(button);
});
const reset = document.createElement("button");
reset.className = "mm-hud-reset";
reset.type = "button";
reset.textContent = "Reset saved settings";
setHudTooltip(reset, "Restore every saved Kitty setting to its default value");
reset.addEventListener("click", () => {
applyHudSettings({ ...HUD_DEFAULTS });
});
savedSettings.append(presetGrid, reset);
const hotkeyIntro = addHudSection(hotkeysPage, "Hotkey library");
hotkeyIntro.classList.add("mm-hotkey-intro");
const hotkeyIntroText = document.createElement("small");
hotkeyIntroText.textContent = "Click any binding, then press a keyboard key or mouse button with the modifiers you want. Conflicts swap bindings so no action becomes unreachable. Hold actions stop when their trigger or required modifier is released.";
const hotkeyIntroActions = document.createElement("div");
hotkeyIntroActions.className = "mm-hotkey-intro-actions";
const replayTutorial = document.createElement("button");
replayTutorial.className = "mm-hud-reset";
replayTutorial.type = "button";
replayTutorial.textContent = "Replay tutorial";
replayTutorial.addEventListener("click", startKittyTutorial);
const resetBindings = document.createElement("button");
resetBindings.className = "mm-hud-reset";
resetBindings.type = "button";
resetBindings.textContent = "Reset keybinds";
resetBindings.addEventListener("click", () => {
hudState.keybinds = { ...KITTY_DEFAULT_KEYBINDS };
saveHudSettings();
sendHudCommand({ type: "set", key: "keybinds", value: { ...hudState.keybinds } });
finishKittyBindingCapture();
showZoomIndicator("Kitty keybinds reset");
});
hotkeyIntroActions.append(replayTutorial, resetBindings);
hotkeyIntro.append(hotkeyIntroText, hotkeyIntroActions);
const addHotkeyGroup = (heading, entries) => {
const section = addHudSection(hotkeysPage, heading);
const list = document.createElement("div");
list.className = "mm-hotkey-list";
entries.forEach((entry) => {
const row = document.createElement("div");
row.className = "mm-hotkey-entry";
const combo = document.createElement("div");
combo.className = "mm-hotkey-combo";
if (entry.id) {
const bind = document.createElement("button");
bind.type = "button";
bind.className = "mm-hotkey-bind mm-hotkey-combo";
bind.dataset.kittyBindingAction = entry.id;
bind.dataset.kittyBindingLabel = entry.action;
bind.addEventListener("click", () => beginKittyBindingCapture(entry.id, bind));
bind.addEventListener("contextmenu", (event) => event.preventDefault());
renderKittyBindingButton(bind, hudState.keybinds[entry.id]);
combo.appendChild(bind);
} else {
entry.keys.forEach((key, index) => {
if (index) {
const plus = document.createElement("span");
plus.className = "mm-hotkey-plus";
plus.textContent = "+";
combo.appendChild(plus);
}
const keycap = document.createElement("kbd");
keycap.textContent = key;
combo.appendChild(keycap);
});
}
const action = document.createElement("span");
action.className = "mm-hotkey-action";
const label = document.createElement("strong");
label.textContent = entry.action;
const note = document.createElement("small");
note.textContent = entry.note;
action.append(label, note);
row.append(combo, action);
if (entry.id) {
const resetOne = document.createElement("button");
resetOne.type = "button";
resetOne.className = "mm-hotkey-row-reset";
resetOne.textContent = "↺";
resetOne.setAttribute("aria-label", "Reset " + entry.action);
setHudTooltip(resetOne, "Reset this action to " + KITTY_DEFAULT_KEYBINDS[entry.id]);
resetOne.addEventListener("click", () => setKittyBinding(entry.id, KITTY_DEFAULT_KEYBINDS[entry.id]));
row.appendChild(resetOne);
}
list.appendChild(row);
});
section.appendChild(list);
return section;
};
addHotkeyGroup("Menu & view", [
...KITTY_BINDING_ACTIONS.filter((entry) => entry.group === "Menu & view"),
{ keys: ["Menu", "or ×"], action: "Open or close by hand", note: "Menu appears at the lower-left during gameplay; × closes the HUD from its header." },
{ keys: ["Any bound action"], action: "Leave HUD into gameplay", note: "A bound gameplay action closes the HUD and continues into the game." },
{ keys: ["Mouse wheel"], action: "Zoom map view", note: "Scroll on the game canvas; trackpads use smooth smaller steps." },
{ keys: ["Tutorial"], action: "Replay onboarding", note: "Use the button beside Play or the button at the top of this page." }
]);
addHotkeyGroup("Combat & gear", KITTY_BINDING_ACTIONS.filter((entry) => entry.group === "Combat & gear"));
addHotkeyGroup("Building & supplies", KITTY_BINDING_ACTIONS.filter((entry) => entry.group === "Building & supplies"));
addHotkeyGroup("Modes & automation", KITTY_BINDING_ACTIONS.filter((entry) => entry.group === "Modes & automation"));
addHotkeyGroup("Friends & teammate sync", KITTY_BINDING_ACTIONS.filter((entry) => entry.group === "Friends & teammate sync"));
addHotkeyGroup("Core MooMoo controls", [
{ keys: ["W/A/S/D"], action: "Move", note: "Normal movement stays active unless an automation currently owns movement." },
{ keys: ["Mouse"], action: "Aim", note: "Forced build and combat rotations restore to the current mouse direction afterward." },
{ keys: ["Left click", "or Space"], action: "Attack / gather", note: "Standard MooMoo held attack input." },
{ keys: ["1–9"], action: "Select hotbar slot", note: "Standard MooMoo weapon, food, and placeable selection." },
{ keys: ["Enter"], action: "Open chat", note: "Normal MooMoo chat remains available; Esc closes the text box." },
{ keys: ["E"], action: "Toggle native auto-attack", note: "Standard MooMoo automatic gathering and attack toggle." },
{ keys: ["X"], action: "Lock rotation", note: "Kitty automation restores the locked or mouse-facing direction after temporary forced aim." }
]);
const tooltip = document.createElement("div");
tooltip.className = "mm-hud-tooltip";
tooltip.id = HUD_ID + "-tooltip";
tooltip.setAttribute("role", "tooltip");
tooltip.hidden = true;
root.append(panel, tooltip);
document.body.appendChild(root);
mountKittyHudLauncher();
setKittyHudOpen(false);
attachHudTooltipController(root, tooltip);
activatePage("automation");
renderHud();
}
function scheduleHudMount() {
const mountAll = () => {
installKittyTheme();
mountMetrics();
mountKittyChatHistory();
watchKittyAuxPanelVisibility();
mountHud();
};
if (document.body) mountAll();
else document.addEventListener("DOMContentLoaded", mountAll, { once: true });
}
function compareKittyVersions(left, right) {
const leftParts = String(left || "").match(/\d+/g) || [];
const rightParts = String(right || "").match(/\d+/g) || [];
const length = Math.max(leftParts.length, rightParts.length);
for (let index = 0; index < length; index += 1) {
const difference = Number(leftParts[index] || 0) - Number(rightParts[index] || 0);
if (difference) return difference > 0 ? 1 : -1;
}
return 0;
}
function safeKittyDownloadUrl(candidate) {
try {
const url = new URL(candidate || KITTY_UPDATE_FALLBACK_URL);
if (
url.protocol === "https:" &&
url.hostname === "update.greasyfork.org" &&
/^\/scripts\/592072(?:\/|$)/.test(url.pathname)
) return url.href;
} catch {
// The fixed GreasyFork installer remains the safe fallback.
}
return KITTY_UPDATE_FALLBACK_URL;
}
function mountKittyUpdatePopup(latestVersion, downloadUrl) {
if (!document.body || document.getElementById(KITTY_UPDATE_POPUP_ID)) return;
try {
if (sessionStorage.getItem(KITTY_UPDATE_DISMISS_KEY) === latestVersion) return;
} catch {
// A blocked session store should not prevent an update notice.
}
const popup = document.createElement("aside");
popup.id = KITTY_UPDATE_POPUP_ID;
popup.setAttribute("role", "dialog");
popup.setAttribute("aria-labelledby", "kitty-update-title");
popup.setAttribute("aria-describedby", "kitty-update-copy");
const title = document.createElement("h2");
title.id = "kitty-update-title";
title.className = "kitty-update-title";
title.textContent = "Update available";
const copy = document.createElement("p");
copy.id = "kitty-update-copy";
copy.className = "kitty-update-copy";
copy.textContent = "A newer Kitty Klient build is ready.";
const versions = document.createElement("div");
versions.className = "kitty-update-versions";
versions.textContent = KITTY_KLIENT_VERSION + " → " + latestVersion;
const download = document.createElement("a");
download.className = "kitty-update-download";
download.href = safeKittyDownloadUrl(downloadUrl);
download.target = "_blank";
download.rel = "noopener noreferrer";
download.textContent = "Download update";
const close = document.createElement("button");
close.className = "kitty-update-close";
close.type = "button";
close.setAttribute("aria-label", "Dismiss update notice");
close.textContent = "×";
close.addEventListener("click", () => {
try {
sessionStorage.setItem(KITTY_UPDATE_DISMISS_KEY, latestVersion);
} catch {
// Closing still works when storage is unavailable.
}
popup.remove();
});
popup.append(title, copy, versions, download, close);
document.body.appendChild(popup);
}
async function checkForKittyUpdate() {
const controller = typeof AbortController === "function" ? new AbortController() : null;
const timeout = window.setTimeout(() => controller && controller.abort(), 5000);
try {
const response = await fetch(KITTY_UPDATE_API, {
cache: "no-store",
credentials: "omit",
signal: controller ? controller.signal : undefined
});
if (!response.ok) return;
const release = await response.json();
const latestVersion = typeof release.version === "string" ? release.version.trim() : "";
if (!latestVersion || compareKittyVersions(latestVersion, KITTY_KLIENT_VERSION) <= 0) return;
const showPopup = () => mountKittyUpdatePopup(latestVersion, release.code_url);
if (document.body) showPopup();
else document.addEventListener("DOMContentLoaded", showPopup, { once: true });
} catch {
// Update checks are optional and must never interfere with the client.
} finally {
window.clearTimeout(timeout);
}
}
let escapeClaimedByGameMenu = false;
function isGameSubmenuOpen() {
return ["allianceMenu", "storeMenu", "chatHolder"].some((id) => {
const menu = document.getElementById(id);
if (!menu) return false;
return menu.style.display === "block" || window.getComputedStyle(menu).display !== "none";
});
}
function closeHud(root) {
if (root) setKittyHudOpen(false);
}
function isKittyHudTextInput(target, root) {
if (!root || !target || typeof target.closest !== "function") return false;
const editable = target.closest([
"textarea",
"[contenteditable='true']",
"[contenteditable='plaintext-only']",
"input:not([type])",
"input[type='text']",
"input[type='search']",
"input[type='url']",
"input[type='email']",
"input[type='tel']",
"input[type='password']",
"input[type='number']"
].join(","));
return Boolean(editable && root.contains(editable));
}
document.addEventListener("keydown", (event) => {
if (!kittyTutorialActive || event.key !== "Escape") return;
const root = document.getElementById(HUD_ID);
if (isKittyHudTextInput(event.target, root)) {
// Do not cancel the browser's normal text-field behavior, but keep
// this Escape press away from every menu/game shortcut listener.
event.stopImmediatePropagation();
return;
}
stopKittyTutorial(false);
event.preventDefault();
event.stopImmediatePropagation();
}, true);
window.addEventListener("resize", () => {
if (kittyTutorialActive) positionKittyTutorial();
});
document.addEventListener("scroll", () => {
if (kittyTutorialActive) positionKittyTutorial();
}, true);
document.addEventListener("keydown", (event) => {
const root = document.getElementById(HUD_ID);
// Text editing inside Kitty owns these keystrokes. In particular,
// WASDFVR must type normally and Escape must not close the HUD.
if (isKittyHudTextInput(event.target, root)) {
event.stopImmediatePropagation();
return;
}
if (captureKittyBindingEvent(event, false)) return;
const toggleHudBinding = hudState.keybinds && hudState.keybinds.toggleHud;
if (kittyBindingMatchesEvent(toggleHudBinding, event, false)) {
if (!root) return;
if (escapeClaimedByGameMenu) {
// Do not let a held Escape key close the game menu and then
// toggle Kitty Klient open on the first repeat event.
event.preventDefault();
event.stopImmediatePropagation();
return;
}
if (isGameSubmenuOpen()) {
escapeClaimedByGameMenu = true;
closeHud(root);
const active = document.activeElement;
if (active && active.matches("input,textarea,[contenteditable='true']")) active.blur();
// Keep the trusted Escape event flowing. The game's own close
// handler dismisses store, alliance, and the chat text box.
return;
}
setKittyHudOpen(root.classList.contains("mm-hud-collapsed"));
event.preventDefault();
event.stopImmediatePropagation();
return;
}
if (!root) return;
const boundGameplayAction = KITTY_BINDING_ACTIONS.some((entry) =>
entry.id !== "toggleHud" && kittyBindingMatchesEvent(hudState.keybinds[entry.id], event, false)
);
if (hudOpen && (/^[wasdfvrui]$/i.test(event.key) || boundGameplayAction)) {
closeHud(root);
// Keep the real trusted key event flowing into the game so movement
// and held actions begin immediately after the menu disappears.
}
}, true);
document.addEventListener("mousedown", (event) => {
if (captureKittyBindingEvent(event, true)) return;
if (!isGameSurface(event.target)) return;
const toggleHudBinding = hudState.keybinds && hudState.keybinds.toggleHud;
if (kittyBindingMatchesEvent(toggleHudBinding, event, true)) {
const root = document.getElementById(HUD_ID);
if (!root) return;
setKittyHudOpen(root.classList.contains("mm-hud-collapsed"));
event.preventDefault();
event.stopImmediatePropagation();
return;
}
if (
hudOpen &&
KITTY_BINDING_ACTIONS.some((entry) =>
entry.id !== "toggleHud" && kittyBindingMatchesEvent(hudState.keybinds[entry.id], event, true)
)
)
closeHud(document.getElementById(HUD_ID));
}, true);
document.addEventListener("keyup", (event) => {
if (event.key === "Escape") escapeClaimedByGameMenu = false;
}, true);
window.addEventListener("MooMooKittyMetrics", (event) => {
if (!event.detail || typeof event.detail !== "object") return;
mountMetrics();
const metrics = document.getElementById("kitty-klient-metrics");
if (!metrics) return;
const setMetric = (name, value) => {
const field = metrics.querySelector("[data-metric='" + name + "']");
if (field) field.textContent = value;
};
setMetric("ping", Number.isFinite(event.detail.ping) ? Math.round(event.detail.ping) + "ms" : "--");
setMetric("fps", Number.isFinite(event.detail.fps) ? String(Math.round(event.detail.fps)) : "--");
const packetText = String(Math.max(0, Number(event.detail.packets) || 0)) +
(Number.isFinite(event.detail.pps) ? " · " + Math.round(event.detail.pps) + "/s" : "");
setMetric("packets", packetText);
});
window.addEventListener("MooMooKittyAdaptiveSmartness", (event) => {
if (!event.detail || typeof event.detail !== "object") return;
const readout = document.querySelector("#" + HUD_ID + " [data-hud-adaptive-smartness]");
if (!readout) return;
const effective = Math.max(1, Math.round(Number(event.detail.effective) || 1));
const ceiling = Math.max(effective, Math.round(Number(event.detail.ceiling) || effective));
const fpsValue = Number(event.detail.fps);
const fps = event.detail.fps != null && Number.isFinite(fpsValue) && fpsValue > 0
? Math.round(fpsValue) + " FPS"
: "sampling FPS";
const reason = String(event.detail.reason || "holding");
readout.textContent = "Effective depth " + effective + "/" + ceiling + " · " + fps + " · " + reason;
readout.dataset.adaptiveState = event.detail.enabled ? "adaptive" : "manual";
});
window.addEventListener("MooMooKittyPlacementStatus", (event) => {
if (!event.detail || typeof event.detail !== "object") return;
const readout = document.querySelector("#" + HUD_ID + " [data-hud-placement-status]");
if (!readout) return;
const state = String(event.detail.state || "idle").toUpperCase();
const reason = String(event.detail.reason || "waiting");
const legal = Math.max(0, Number(event.detail.legal) || 0);
const scored = Math.max(0, Number(event.detail.scored) || 0);
const sent = Math.max(0, Number(event.detail.sent) || 0);
const items = String(event.detail.itemSummary || "none");
readout.textContent = state + " — " + reason + "\nlegal " + legal + " · scored " + scored + " · sent " + sent + "\n" + items;
readout.dataset.placementState = state.toLowerCase();
});
window.addEventListener("MooMooFriendPickNotice", (event) => {
if (typeof event.detail === "string" && event.detail) {
showZoomIndicator(event.detail);
}
});
let kittyRespawnTimer = 0;
window.addEventListener("MooMooKittyLocalDeath", () => {
if (!hudState.autoRespawn) return;
kittyRespawnTimer && clearTimeout(kittyRespawnTimer);
let attempts = 0;
const tryRespawn = () => {
kittyRespawnTimer = 0;
if (!hudState.autoRespawn || ++attempts > 10) return;
const enterGame = document.getElementById("enterGame");
const diedText = document.getElementById("diedText");
const deathScreenVisible = !!(
diedText &&
diedText.getClientRects().length &&
window.getComputedStyle(diedText).display !== "none"
);
if (enterGame && deathScreenVisible) {
enterGame.click();
return;
}
kittyRespawnTimer = window.setTimeout(tryRespawn, 250);
};
kittyRespawnTimer = window.setTimeout(tryRespawn, 450);
});
window.addEventListener("MooMooOPHudState", (event) => {
if (!event.detail || typeof event.detail !== "object") return;
const debugText = typeof event.detail.debugText === "string" ? event.detail.debugText : hudState.debugText;
hudState = { ...normalizeHudSettings({ ...hudState, ...event.detail }), debugText };
if (!hudSettingsSent) {
hudSettingsSent = true;
sendHudCommand({ type: "hydrate", settings: readHudSettings() });
}
saveHudSettings();
renderHud();
});
window.addEventListener("MooMooFriendState", (event) => {
const detail = event.detail;
if (!detail || typeof detail.name !== "string") return;
const name = detail.name.trim().slice(0, 15);
if (!name) return;
const key = name.toLowerCase();
const names = Array.isArray(hudState.friendNames) ? hudState.friendNames.slice() : [];
const existing = names.findIndex((entry) => entry.toLowerCase() === key);
if (detail.type === "remove" && existing >= 0) names.splice(existing, 1);
else if (detail.type === "add" && existing < 0) names.push(name);
else return;
hudState.friendNames = normalizeHudSettings({ friendNames: names }).friendNames;
saveHudSettings();
renderHud();
});
scheduleHudMount();
void checkForKittyUpdate();
function patchedViewportCode() {
// This string replaces a matching section of the game bundle at runtime.
return `
const __mmZoomBaseWidth = y.maxScreenWidth,
__mmZoomBaseHeight = y.maxScreenHeight;
let __mmSoldierRange = 400,
__mmCombatRange = 400,
__mmGearHoldTicks = 3,
__mmPassiveSpikeEnemyRange = 400,
__mmAntiBoostRange = 200,
__mmAntiCollisionRange = 260,
__mmSoldierAutoEnabled = !0,
__mmMovementGearEnabled = !0,
__mmPassiveSpikeAvoidanceEnabled = !1,
__mmTrapEscapeEnabled = !0,
__mmAutomaticStateRepairEnabled = !0,
__mmAutoSpikeReplaceEnabled = !1,
__mmAutoAcceptTeamRequestsEnabled = !1,
__mmAutoDeclineTeamRequestsEnabled = !1,
__mmAntiBoostEnabled = !1,
__mmAntiBoostInstaEnabled = !0,
__mmAntiTrollEnabled = !1,
__mmAntiCollisionEnabled = !0,
__mmAntiCollisionPauseCombatEnabled = !0,
__mmThreatTrapEnabled = !1,
__mmPassiveMobTrapEnabled = !1,
__mmBossTeleporterEnabled = !1,
__mmAutoCloseSpikeEnabled = !1,
__mmReloadSpikeEnabled = !1,
__mmShieldDefenseEnabled = !0,
__mmPlacementDefenseEnabled = !0,
__mmAntiRetrapPushEnabled = !0,
__mmTeammateTrapRescueEnabled = !0,
__mmTurretStealEnabled = !0,
__mmSpikeGearCounterEnabled = !0,
__mmDashMovementEnabled = !0,
__mmMusketRechargeEnabled = !0,
__mmAutoPurchaseEnabled = !1,
__mmMatThiefEnabled = !1,
__mmMultiTargetBreakEnabled = !0,
__mmMobStealEnabled = !1,
__mmAssassinAutomationEnabled = !1,
__mmSpinningWindmillsEnabled = !1,
__mmForceFullServersEnabled = !0,
__mmWeaponGrindEnabled = !1,
__mmBushModeEnabled = !1,
__mmFpsBoostEnabled = !0,
__mmSmoothVisualsEnabled = !0,
__mmReloadArcsEnabled = !0,
__mmEntityDangerEnabled = !0,
__mmNotificationTracersEnabled = !0,
__mmGroundGridEnabled = !1,
__mmEspEnabled = !0,
__mmEspLinesEnabled = !0,
__mmPredictionGhostEnabled = !0,
__mmPlacementVisualsEnabled = !0,
__mmCooldownBarsEnabled = !0,
__mmWeaponXpBarEnabled = !0,
__mmChatHistoryEnabled = !0,
__mmCombatTelemetryEnabled = !1,
__mmTelemetryProjectileHitsEnabled = !0,
__mmTelemetrySpikeKnockbackEnabled = !0,
__mmTelemetryActualAimEnabled = !0,
__mmTelemetryBuildingOwnersEnabled = !0,
__mmTelemetryShameCountEnabled = !0,
__mmTelemetryDamageHealingEnabled = !0,
__mmEnemyColor = "#ff4d5d",
__mmAllyColor = "#a855f7",
__mmFriendColor = "#facc15",
__mmOwnColor = "#d8b4fe",
__mmBullHelmetEnabled = !0,
__mmTankRightClickEnabled = !0,
__mmAllItemsUnlockEnabled = !0,
__mmInstaUiEnabled = !0,
__mmAutoInstaEnabled = !0,
__mmAutoBowUpgradeInstaEnabled = !1,
__mmReverseInstaEnabled = !1,
__mmOneTickInstaEnabled = !1,
__mmAppleInstaEnabled = !1,
__mmBleedInstaEnabled = !1,
__mmKnockbackInstaEnabled = !1,
__mmVelTickInstaEnabled = !1,
__mmPolearmAidsEnabled = !1,
__mmAutoPushInstaEnabled = !1,
__mmBoostSpikeEnabled = !0,
__mmAutoTrapInstaEnabled = !0,
__mmAutoSpikeInstaEnabled = !0,
__mmSmartAutoPlaceEnabled = window.__KittySmartAutoPlace !== !1,
__mmSmartPreplaceEnabled = !0,
__mmSmartMultiPlaceEnabled = !0,
__mmSmartQuadTrapsEnabled = !0,
__mmSmartQuadSpikesEnabled = !0,
__mmSmartSpikeContactEnabled = !0,
__mmSmartTrapContactEnabled = !0,
__mmSmartKnockbackChainEnabled = !0,
__mmSmartTrapSurroundEnabled = !0,
__mmSmartAngleDenialEnabled = !0,
__mmSmartAutoPushWeightEnabled = !0,
__mmSmartAutoReplaceEnabled = !1,
__mmSmartSpikeSyncPlaceEnabled = !1,
__mmSmartAntiBoostPlaceEnabled = !1,
__mmSmartMovingMillsEnabled = !1,
__mmSmartInstaUtilityPlaceEnabled = !1,
__mmAutoSpikeSpamEnabled = !1,
__mmAutoSpikeKillEnabled = !1,
__mmAntiInstaEnabled = !0,
__mmInstaSyncEnabled = !0,
__mmBoostBreakEnabled = !0,
__mmBoostChatEnabled = !0,
__mmMaterialReplyEnabled = !0,
__mmMeowChainInstaEnabled = !0,
__mmInstaChatEnabled = !0,
__mmBushChatEnabled = !0,
__mmFriendAddedChatEnabled = !0,
__mmEnemyMarkedChatEnabled = !0,
__mmCleanupProgressChatEnabled = !0,
__mmCleanupCompleteChatEnabled = !0,
__mmModReplyChatEnabled = !0,
__mmEnemyTrapChatEnabled = !0,
__mmFriendTrapChatEnabled = !0,
__mmTrapAlertChatEnabled = !0,
__mmDeathHistoryChatEnabled = !0,
__mmSyncStatusChatEnabled = !0,
__mmSyncLeaderEnabled = !1,
__mmSyncFollowerEnabled = !1,
__mmSyncCombatOnlyEnabled = !1,
__mmSyncMovementEnabled = !0,
__mmSyncCopyWeaponsEnabled = !0,
__mmSyncCopyBuildsEnabled = !0,
__mmSyncCopyGearEnabled = !0,
__mmSyncCopyAimEnabled = !0,
__mmSyncCopyAttacksEnabled = !0,
__mmSyncCatchupGearEnabled = !0,
__mmSyncPauseInCombatEnabled = !1,
__mmSyncWasdCombatOnlyEnabled = !0,
__mmSyncTickCombatEnabled = !0,
__mmSyncFollowGap = 12,
__mmSyncStopTolerance = 4,
__mmSyncResumeTolerance = 9,
__mmSyncPredictionMs = 130,
__mmSyncCatchupDistance = 420,
__mmSyncCatchupReleaseDistance = 190,
__mmSyncMoveRefreshMs = 50,
__mmSyncRelayUrl = "",
__mmSyncRoom = "",
__mmDebugPanelEnabled = !1,
__mmKillMessageEnabled = !0,
__mmKillMessage = "gg",
__mmReactionMs = 25,
__mmAdaptiveSmartnessEnabled = !0,
__mmSmartDepth = 5,
__mmSmartPlaceAccuracy = 50,
__mmSmartMaxPlacements = 4,
__mmSmartPlaceDelay = 111,
__mmAssassinSafeMs = 2000,
__mmAssassinMinHealth = 80,
__mmAssassinDangerRange = 650;
const __mmDefaultKeybinds = JSON.parse('${JSON.stringify(KITTY_DEFAULT_KEYBINDS)}');
let __mmKeybinds = Object.assign({}, __mmDefaultKeybinds);
const __mmBindingActions = Object.freeze(Object.keys(__mmDefaultKeybinds)),
__mmBindingHoldActions = new Set([
"primaryAttack",
"secondaryAttack",
"clickBoostInsta",
"boostSpike",
"food",
"trapBuild",
"spikeBuild",
"specialBuild",
"boostBreak",
"movingMills",
"movingMillsAlt",
"bushMode",
]),
__mmActiveBindingActions = new Map(),
__mmConsumedBindingInputs = new Map();
const __mmShieldWeapon = 11,
__mmToolHammer = 0,
__mmMcGrabby = 14,
__mmShortSword = 3,
__mmPolearmWeapon = 5,
__mmTurretGear = 53,
__mmTurretGearRange = 700,
__mmEmpHelmet = 22,
__mmAssassinGear = 56,
__mmFullInstaRangeMultiplier = 1.5,
__mmThreatTrapRange = 300,
__mmThreatAnimalRange = 200,
__mmPassiveMobTrapRange = 190,
__mmThreatTrapCooldownMs = 650,
__mmEnemyTrapChatRange = 1500,
__mmFriendTrapChatRange = 1500,
__mmShieldDefenseRange = 240,
__mmShieldDefenseMs = 750,
__mmBoosterHat = 12,
__mmBushGear = 10,
__mmBushGearPrice = 3e3,
__mmSnowHat = 15,
__mmSnowHatPrice = 600,
__mmFlipperHat = 31,
__mmFlipperHatPrice = 2500,
__mmGreatHammer = 10,
__mmBow = 9,
__mmKatana = 4,
__mmCrossbow = 12,
__mmMusket = 15,
__mmAngelWings = 13,
__mmShadowWings = 19,
__mmBloodWings = 18,
__mmCorruptXWings = 21;
const __mmUpgradePrerequisiteSnapshot =
window.__KittyVanillaUpgradePrerequisites || null,
__mmOriginalWeaponPrerequisites =
__mmUpgradePrerequisiteSnapshot &&
Array.isArray(__mmUpgradePrerequisiteSnapshot.weapons)
? __mmUpgradePrerequisiteSnapshot.weapons.slice()
: b && Array.isArray(b.weapons)
? b.weapons.map(function (__mmWeapon) {
return __mmWeapon && __mmWeapon.pre;
})
: [],
__mmOriginalItemPrerequisites =
__mmUpgradePrerequisiteSnapshot &&
Array.isArray(__mmUpgradePrerequisiteSnapshot.items)
? __mmUpgradePrerequisiteSnapshot.items.slice()
: b && Array.isArray(b.list)
? b.list.map(function (__mmItem) {
return __mmItem && __mmItem.pre;
})
: [];
const __mmAutoPurchaseEntries = Object.freeze({
monkeyTail: Object.freeze({ id: 11, tail: !0, price: 2e3 }),
soldier: Object.freeze({ id: 6, tail: !1, price: 4e3 }),
bull: Object.freeze({ id: 7, tail: !1, price: 6e3 }),
booster: Object.freeze({ id: 12, tail: !1, price: 6e3 }),
emp: Object.freeze({ id: 22, tail: !1, price: 6e3 }),
turret: Object.freeze({ id: 53, tail: !1, price: 1e4 }),
tank: Object.freeze({ id: 40, tail: !1, price: 15e3 }),
shadow: Object.freeze({ id: 19, tail: !0, price: 15e3 }),
angel: Object.freeze({ id: 13, tail: !0, price: 15e3 }),
blood: Object.freeze({ id: 18, tail: !0, price: 2e4 }),
corrupt: Object.freeze({ id: 21, tail: !0, price: 2e4 }),
});
let _ = y.maxScreenWidth,
L = y.maxScreenHeight;
let __mmFoodSpamTimer = 0;
let __mmAutoHealTimer = 0,
__mmAutoHealEnabled = !0,
__mmAutoHealWasHealing = !1,
__mmAutoHealPending = !1,
__mmAutoHealBitesRemaining = 0,
__mmAutoHealNextBiteAt = 0,
__mmAutoHealLastObservedHealth = null,
__mmAutoHealLastDamageAt = 0,
__mmAutoHealShameCount = 0,
__mmLastWeapon = null,
__mmAutoHealWeapon = null;
let __mmAutoPurchaseTimer = 0,
__mmAutoPurchasePending = null;
let __mmBushModeRequested = !1,
__mmBushModeTimer = 0,
__mmBushExitRestoreTimer = 0,
__mmBushPurchaseTimer = 0,
__mmBushPurchaseAt = 0,
__mmBushHotkeyDown = !1,
__mmBushPreviousHat = null,
__mmBushPreviousTail = null,
__mmBushRestoreOverrideHat = null,
__mmBushRestoreOverrideTail = null,
__mmBushRestoreOverrideUntil = 0;
let __mmMatThiefTimer = 0,
__mmMatThiefReleaseTimer = 0,
__mmMatThiefAimAngle = null,
__mmMatThiefReturnAngle = null,
__mmMatThiefRestoreTool = null,
__mmMatThiefAttackHeld = !1;
const __mmMatThiefReservations = new WeakMap();
let __mmMultiBreakTimer = 0,
__mmMultiBreakAimAngle = null,
__mmMultiBreakTargetCount = 0;
let __mmAssassinTimer = 0,
__mmAssassinPreviousHat = null,
__mmAssassinSafeSince = 0,
__mmAssassinLastUnsafeAt = 0,
__mmAssassinLastDamageAt = 0,
__mmAssassinPurchaseAt = 0,
__mmAssassinCooldownUntil = 0,
__mmAssassinConcealed = !1;
let __mmCleanupActive = !1,
__mmCleanupTimer = 0,
__mmCleanupProgressTimer = 0,
__mmCleanupOriginX = 0,
__mmCleanupOriginY = 0,
__mmCleanupTarget = null,
__mmCleanupSavedTool = null,
__mmCleanupWeapon = null,
__mmCleanupAttackHeld = !1,
__mmCleanupMouseButton = null,
__mmCleanupAimAngle = null,
__mmCleanupMoveAngle = null,
__mmCleanupApproachStopped = !1,
__mmCleanupTargetHealth = null,
__mmCleanupProgressAt = 0,
__mmCleanupEmptySince = 0,
__mmCleanupChatStep = 0;
const __mmCleanupReservations = new WeakMap();
let __mmMobStealTimer = 0,
__mmMobStealStageTimer = 0,
__mmMobStealReleaseTimer = 0,
__mmMobStealPendingPlan = null,
__mmMobStealAimAngle = null,
__mmMobStealRestoreTool = null,
__mmMobStealRestoreHat = null,
__mmMobStealRestoreTail = null,
__mmMobStealAttackHeld = !1;
const __mmMobStealMotion = Object.create(null),
__mmMobStealReservations = Object.create(null);
let __mmAutoInstaTimer = 0;
let __mmKittyInstaTimer = 0,
__mmKittyInstaLastAt = 0,
__mmVelTickMoveAngle = null,
__mmVelTickTargetSid = null,
__mmVelTickStartedAt = 0,
__mmVelTickManualUntil = 0,
__mmAutoPushMoveAngle = null,
__mmAutoPushTargetSid = null,
__mmAutoPushManualUntil = 0,
__mmAutoPushRoute = [],
__mmAutoPushRouteAt = 0,
__mmAutoPushRouteGoalX = null,
__mmAutoPushRouteGoalY = null,
__mmAutoPushRouteTargetSid = null;
let __mmAutoTrapInstaTimer = 0;
const __mmAutoTrapInstaIncidents = Object.create(null);
let __mmAutoSpikeInstaTimer = 0,
__mmAutoSpikeInstaLastAt = 0,
__mmSpikeTickStrikeTimer = 0,
__mmSpikeTickStrikeTool = null,
__mmSpikeTickStrikeHat = null,
__mmSpikeTickStrikeTail = null,
__mmSpikeTickStrikeAimAngle = null,
__mmSpikeTickStrikeHeld = !1;
const __mmAutoSpikeInstaMotion = Object.create(null);
let __mmAutoSpikeSpamTimer = 0,
__mmAutoSpikeSpamLastAt = 0,
__mmAutoSpikeSpamGhost = null,
__mmAutoSpikeSpamCandidateKey = null,
__mmAutoSpikeSpamCandidateSince = 0,
__mmAutoSpikeSpamAimAngle = null,
__mmAutoSpikeSpamAimUntil = 0;
const __mmAutoSpikeSpamReservations = [];
const __mmAutoSpikeSpamMotion = Object.create(null),
__mmAutoSpikeKillAssumedUntil = Object.create(null);
const __mmAutoSpikeSpamIntent = {
targetSid: null,
lastX: null,
lastY: null,
lastAt: 0,
score: 0,
armed: !1,
};
let __mmSmartPlacementTimer = 0,
__mmSmartPlacementLastAt = 0,
__mmSmartPlacementCalculatedAt = 0,
__mmSmartObjectScanAt = 0,
__mmSmartReplaceUntil = 0,
__mmSmartReplacePoint = null,
__mmSmartMillX = null,
__mmSmartMillY = null,
__mmSmartMillLastAt = 0,
__mmSmartUtilityLastAt = 0;
let __mmBoostSpikeTimer = 0,
__mmBoostSpikeLastAt = 0,
__mmBoostSpikeMoveAngle = null;
const __mmSmartPlacementStats = {
state: "starting",
reason: "waiting for game state",
scans: 0,
legal: 0,
scored: 0,
sent: 0,
failed: 0,
blocked: 0,
itemSummary: "none",
updatedAt: 0,
broadcastAt: 0,
signature: "",
};
const __mmSmartPreplaceTimers = new Set(),
__mmSmartPreplaceKeys = new Set(),
__mmSmartKnownObjects = new Map(),
__mmSmartPlacementMotion = Object.create(null);
const __mmSmartPreviewSamples = [];
let __mmSmartPlacementPreview = {
samples: [],
ranked: [],
selected: [],
reason: "idle",
updatedAt: 0,
};
let __mmAntiInstaTimer = 0,
__mmAntiInstaLastAt = 0,
__mmAntiInstaUntil = 0,
__mmAntiInstaActionTimer = 0;
let __mmCombatThreatCalculatedAt = 0,
__mmCombatThreatCache = null;
let __mmInstaSyncLoopTimer = 0,
__mmInstaSyncTimer = 0,
__mmInstaSyncReleaseTimer = 0,
__mmInstaSyncPending = !1,
__mmInstaSyncFiring = !1,
__mmInstaSyncLastAt = 0,
__mmInstaSyncRestoreTool = null,
__mmInstaSyncRestoreHat = null,
__mmInstaSyncWeaponHeld = !1;
const __mmInstaSyncProjectileStates = new WeakMap();
let __mmMovementGearTimer = 0,
__mmMovementGearPreviousHat = null,
__mmMovementGearPreviousTail = null,
__mmProximityTailPrevious = null;
let __mmPassiveSpikeMotionTimer = 0,
__mmPassiveSpikePendingTimer = 0,
__mmPassiveSpikeCorrectionTimer = 0,
__mmPassiveSpikeCorrecting = !1,
__mmPassiveSpikeMotion = null;
let __mmAntiCollisionTimer = 0,
__mmAntiCollisionBlocked = !1,
__mmAntiCollisionBlockedObject = null,
__mmAntiCollisionBlockedKey = null,
__mmAntiCollisionBypassArmedKey = null,
__mmAntiCollisionBypassArmedUntil = 0,
__mmAntiCollisionBypassActiveKey = null,
__mmAntiCollisionLastPopupKey = null,
__mmAntiCollisionLastPopupAt = 0,
__mmAntiCollisionRightClickTimer = 0;
const __mmAntiCollisionPopups = [];
const __mmInstaTypePopups = [];
const __mmClanPingAlerts = [];
window.addEventListener("MooMooKittyClanPing", function (__mmEvent) {
const __mmDetail = (__mmEvent && __mmEvent.detail) || {},
__mmX = Number(__mmDetail.x),
__mmY = Number(__mmDetail.y),
__mmOwnTeam = __mmTeamKey(v),
__mmMapScale = Number(y && y.mapScale);
if (
!v ||
!v.alive ||
__mmOwnTeam == null ||
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmMapScale) ||
__mmX < 0 ||
__mmY < 0 ||
__mmX > __mmMapScale ||
__mmY > __mmMapScale ||
// Do not turn our own echoed native ping into a teammate alert.
Math.hypot(__mmX - Number(v.x), __mmY - Number(v.y)) < 45
)
return;
let __mmVisiblePlayerAtPing = !1,
__mmVisibleTeammateAtPing = !1;
if (Array.isArray(E))
for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
const __mmPlayer = E[__mmPlayerIndex];
if (!__mmPlayer || __mmPlayer === v || !__mmPlayer.alive) continue;
const __mmPlayerX = Number(__mmPlayer.x),
__mmPlayerY = Number(__mmPlayer.y);
if (
!Number.isFinite(__mmPlayerX) ||
!Number.isFinite(__mmPlayerY) ||
Math.hypot(__mmPlayerX - __mmX, __mmPlayerY - __mmY) > 170
)
continue;
__mmVisiblePlayerAtPing = !0;
if (__mmSameTeam(__mmPlayer)) {
__mmVisibleTeammateAtPing = !0;
break;
}
}
// Across-map teammates may not exist in the visible-player list, so trust
// the team-only server packet when nobody is rendered at its coordinates.
// If someone is visible there, require that player to be our teammate.
if (__mmVisiblePlayerAtPing && !__mmVisibleTeammateAtPing) return;
const __mmNow = performance.now(),
__mmDuplicate = __mmClanPingAlerts.find(
(__mmAlert) =>
__mmNow - __mmAlert.startedAt < 180 &&
Math.hypot(__mmAlert.x - __mmX, __mmAlert.y - __mmY) < 10,
);
if (__mmDuplicate) {
__mmDuplicate.startedAt = __mmNow;
__mmDuplicate.expiresAt = __mmNow + 5000;
} else {
__mmClanPingAlerts.push({
x: __mmX,
y: __mmY,
startedAt: __mmNow,
expiresAt: __mmNow + 5000,
});
__mmClanPingAlerts.length > 8 && __mmClanPingAlerts.shift();
}
});
let __mmMinimapRegionTimer = 0,
__mmMinimapRegionElement = null,
__mmMinimapRegionBaseImage = "";
let __mmFlipperPurchaseAt = 0,
__mmSnowPurchaseAt = 0;
let __mmBoostBreakTimer = 0,
__mmBoostBreakHeld = !1,
__mmBoostBreakCooldownWeapon = null,
__mmBoostBreakReadyAt = 0,
__mmBoostBreakStrikeTimer = 0,
__mmBoostBreakStriking = !1,
__mmBoostBreakPreviousWeapon = null,
__mmBoostMoveDirection = null,
__mmBoostTankPreviousHat = null,
__mmBoostChatTimer = 0,
__mmBoostChatOrder = [],
__mmBoostChatIndex = 0;
let __mmSoldierAutoTimer = 0,
__mmSoldierRestoreTimer = 0,
__mmSoldierPreviousHat = null;
let __mmShieldDefenseTimer = 0,
__mmShieldDefenseWeapon = null;
let __mmAntiBoostTimer = 0,
__mmAntiBoostLast = 0,
__mmAntiBoostBlockTimer = 0,
__mmAntiBoostMoveTimer = 0,
__mmAntiBoostBlockTool = null,
__mmAntiBoostBlockAimAngle = null,
__mmAntiBoostBackingUp = !1;
let __mmAntiTrollTimer = 0,
__mmAntiTrollLastAt = 0,
__mmAntiTrollLatchedSid = null;
const __mmAntiTrollMotion = Object.create(null);
let __mmThreatTrapTimer = 0,
__mmThreatTrapLastAt = 0,
__mmThreatTrapLastKey = null;
const __mmThreatTrapPlacements = Object.create(null);
let __mmTrapAlertTimer = 0,
__mmTrapChatIncidentActive = !1;
let __mmFriendlyTrapChatTimer = 0,
__mmFriendlyTrapChatLastAt = 0;
const __mmFriendlyTrapChatIncidents = Object.create(null);
let __mmReloadSpikeTimer = 0,
__mmReloadSpikePlaced = !1,
__mmTurretReloadUntil = 0;
const __mmEnemyBoostTrail = {};
const __mmSyncProtocol = "kitty-klient-tab-sync-v1";
const __mmSyncStorageKey = "kitty-klient-tab-sync-state-v1";
const __mmOpenSyncProtocol = "kitty-klient-open-sync-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,
__mmSyncFollowFrame = 0,
__mmSyncMoveActive = !1,
__mmSyncLastMoveDirection = null,
__mmSyncLastMoveAt = 0,
__mmSyncTargetSid = null,
__mmSyncTargetName = "",
__mmSyncTargetExplicit = !1,
__mmSyncLeaderState = null,
__mmSyncStandLeaderKey = "",
__mmSyncStandAngle = null,
__mmSyncArrivedBeside = !1,
__mmSyncCatchupActive = !1,
__mmSyncCatchupPreviousHat = null,
__mmSyncCatchupPreviousTail = null,
__mmSyncLeaderCombatUntil = 0,
__mmSyncSelectionBlockedUntil = 0,
__mmSyncGearPairDispatch = !1,
__mmSyncReplayDepth = 0,
__mmSyncDirectAttackAt = 0,
__mmSyncDirectAttackActive = !1,
__mmSyncObservedAttackHeld = !1,
__mmSyncObservedAttackReleaseTimer = 0,
__mmOpenSyncSequence = 0,
__mmSyncRequestLastAt = 0,
__mmSyncSequence = 0,
__mmSyncStatus = "Sync off";
let __mmSyncStatusChatPhase = "off",
__mmSyncStatusChatTimer = 0,
__mmSyncStatusChatLastAt = 0;
const __mmSyncStatusChatQueue = [];
const __mmSyncSeenPackets = Object.create(null);
let __mmSyncRelaySocket = null,
__mmSyncRelayReconnectTimer = 0,
__mmSyncRelayPingTimer = 0,
__mmSyncRelayAttemptAt = 0,
__mmSyncRelayClockOffset = 0,
__mmSyncRelayRtt = 0,
__mmSyncRelayRoomKey = "",
__mmSyncScheduledInstaTimer = 0,
__mmSyncScheduledInstaAt = 0;
let __mmBuildSpamTimer = 0,
__mmBuildSpamKey = 0;
let __mmWindmillHotkeyDown = !1;
const __mmWindmillDataTurnSpeeds = Object.create(null),
__mmWindmillObjectTurnSpeeds = new WeakMap();
let __mmWeaponGrindTimer = 0,
__mmWeaponGrindWeapon = null,
__mmWeaponGrindHold = !1,
__mmWeaponGrindLayoutAngle = null,
__mmWeaponGrindAimAngle = null,
__mmWeaponGrindTargetIndex = 0,
__mmWeaponGrindNextAimAt = 0,
__mmWeaponGrindLastPlaceAt = 0,
__mmWeaponGrindLifeSid = null;
const __mmWeaponGrindPlaced = { turret: 0, teleporter: 0 },
__mmWeaponGrindReservations = [],
__mmWeaponGrindSlots = { turret: [], teleporter: [] };
let __mmWeaponRechargeTimer = 0,
__mmWeaponRechargePreviousTool = null,
__mmWeaponRechargeActiveWeapon = null,
__mmWeaponRechargeSelectAt = 0,
__mmWeaponRechargeHeldLoan = null;
let __mmPredictionLastX = null,
__mmPredictionLastY = null,
__mmPredictionLastAt = 0;
let __mmPrimaryHeld = !1,
__mmSecondaryHeld = !1,
__mmPhysicalPrimaryDown = !1,
__mmPhysicalSecondaryDown = !1,
__mmPhysicalInputAt = 0,
__mmHeldAttackTimer = 0,
__mmPrimaryAttackDown = !1,
__mmPrimaryManualReadyAt = 0,
__mmPrimaryManualWeapon = null,
__mmSecondaryAttackDown = !1,
__mmSecondaryManualReadyAt = 0,
__mmSecondaryManualWeapon = null,
__mmSecondaryGearStage = null,
__mmSecondaryGearTimer = 0,
__mmSecondaryGearEpoch = 0,
__mmSecondaryReleaseRestoreTimer = 0,
__mmSecondaryReleaseRestoreHat = null,
__mmSecondaryReleaseRestoreAttempts = 0,
__mmSecondaryShieldActive = !1,
__mmSecondaryShieldAngle = null,
__mmSecondaryShieldUsed = !1,
__mmSecondaryShieldAimAt = 0,
__mmSecondaryRestoreWeapon = null,
__mmRightClickShieldPlanAt = 0,
__mmRightClickShieldPlanCache = null,
__mmPrimaryClickHat = null,
__mmPrimaryClickTail = null,
__mmPrimaryGearStage = null,
__mmPrimaryGearTimer = 0,
__mmRightClickHat = null,
__mmHeldHatPrevious = null,
__mmHeldTailPrevious = null,
__mmLastNormalHat = 0;
let __mmCombatHatLockHat = null,
__mmCombatHatLockUntil = 0,
__mmCombatHatLockTimer = 0,
__mmCombatHatLockEpoch = 0,
__mmCombatHatLockWriting = !1;
// Equipment packets are acknowledged by the game state. Keep local rendering
// authoritative and merely debounce duplicate requests while that update is in
// flight; directly rewriting skinIndex/tailIndex caused visible frame flicker.
let __mmPendingHat = null,
__mmPendingHatAt = 0,
__mmPendingTail = null,
__mmPendingTailAt = 0;
let __mmTrapAttackTimer = 0,
__mmTrapAttackActive = !1,
__mmTrapAimAngle = null,
__mmTrapAttackTargetKey = null,
__mmTrapWeapon = null,
__mmTrapHat = null,
__mmTrapAttackHeld = !1,
__mmTrapAttackHeldWeapon = null,
__mmTrapManualReadyAt = 0,
__mmTrapWeaponSelectAt = 0,
__mmTrapHatRestoreTimer = 0,
__mmTrapHatRestoreAttempts = 0,
__mmTrapBuildTimer = 0,
__mmTrapBuildAttemptKey = null,
__mmTrapBuildLastAt = 0,
__mmTrapBuildWeapon = null,
__mmTrapBuildPreferredItem = null,
__mmTrapBuildPlacedKey = null,
__mmTrapBuildPlacedCount = 0,
__mmTrapResumeTimer = 0,
__mmTrapSpikeReplaceSlot = null,
__mmTrapSpikeReplaceLastAt = 0;
let __mmAntiRetrapReleaseTimer = 0,
__mmAntiRetrapLastAt = 0,
__mmPlacementDefenseTimer = 0,
__mmPlacementDefenseLastAt = 0,
__mmTeammateRescueTimer = 0,
__mmTeammateRescueReleaseTimer = 0,
__mmTeammateRescueAngle = null,
__mmTeammateRescueRestoreTool = null,
__mmTeammateRescueLastAt = 0,
__mmTurretStealTimer = 0,
__mmTurretStealRestoreTimer = 0,
__mmSpikeGearCounterTimer = 0,
__mmSpikeGearCounterTargetSid = null,
__mmSpikeGearCounterArmedAt = 0,
__mmSpikeGearCounterPreviousTail = null,
__mmSpikeGearCounterRestoreTimer = 0,
__mmDashMovementReleaseTimer = 0,
__mmDashMovementAngle = null,
__mmDashMovementRestoreTool = null;
const __mmPlacementDefenseHandled = new WeakMap();
let __mmTeamRequestObserver = null,
__mmTeamRequestTimer = 0;
const __mmHandledTeamRequestButtons = new WeakSet();
let __mmLiveStateTimer = 0,
__mmDebugHudTimer = 0;
let __mmOperationPipelineTimer = 0,
__mmOperationPipelineRunning = !1,
__mmOperationPipelineCycle = 0,
__mmOperationPipelineStage = "boot",
__mmOperationPipelineLastAt = 0;
const __mmOperationPipelineOrder = Object.freeze([
"snapshot",
"housekeeping",
"trap",
"defense",
"combat-sync",
"combat-insta",
"heal",
"placement",
"utility",
"gear",
"restore",
]),
__mmOperationPipelineErrors = Object.create(null);
let __mmMetricFrames = 0,
__mmMetricPackets = 0,
__mmMetricPacketWindow = 0,
__mmMetricFps = 0,
__mmMetricPps = 0,
__mmMetricUpdatedAt = performance.now();
let __mmHudMenuOpen = !!(
document.documentElement &&
document.documentElement.getAttribute("data-kitty-hud-open") === "1"
),
__mmNativeMenuOpen = !!(
document.documentElement &&
document.documentElement.getAttribute("data-kitty-main-menu-open") === "1"
);
window.addEventListener("MooMooKittyHudVisibility", (__mmEvent) => {
__mmHudMenuOpen = !!__mmEvent.detail;
});
window.addEventListener("MooMooKittyMainMenuVisibility", (__mmEvent) => {
__mmNativeMenuOpen = !!__mmEvent.detail;
});
let __mmAdaptiveSmartDepth = __mmSmartDepth,
__mmAdaptiveFpsEma = 60,
__mmAdaptiveLowSince = 0,
__mmAdaptiveStableSince = 0,
__mmAdaptiveLastChangeAt = 0,
__mmAdaptiveReason = "sampling",
__mmAdaptiveCombat = !1;
const __mmChatBubbleStacks = Object.create(null),
__mmChatBubbleWidthCache = new Map();
let __mmChatBubbleCleanupAt = 0;
let __mmMouseAimReturnTimer = 0,
__mmSendingMouseAimReturn = !1,
__mmLastForcedDirectionAt = 0,
__mmStateRepairLastAt = 0,
__mmStateRepairLastReason = "watching",
__mmStateRepairCount = 0;
const __mmBreakableHealth = new WeakMap(),
__mmBreakableLabelCache = new WeakMap(),
__mmRecentPlayerSwings = Object.create(null),
__mmPlayerToolCooldowns = Object.create(null);
const __mmProjectileCooldownStates = new WeakMap();
let __mmProjectileCooldownLastScanAt = 0;
const __mmCombatDeltaStacks = Object.create(null);
const __mmFriendNames = new Map(),
__mmFriendEnemies = new Set(),
__mmFriendAttackWindows = Object.create(null);
let __mmFriendPickMode = null,
__mmSyncPickArmed = !1;
const __mmLiveState = {
updatedAt: 0,
alive: !1,
enemies: [],
animals: [],
nearestEnemy: null,
nearestEnemyDistance: Infinity,
nearbyTrap: null,
trapped: !1,
health: 0,
maxHealth: 0,
primaryReady: !1,
secondaryReady: !1,
};
const __mmActionPriorities = Object.freeze({
trapEscape: 100,
antiInsta: 95,
autoHeal: 90,
insta: 80,
bowUpgradeInsta: 86,
velTickSetup: 79,
autoPushSetup: 78,
boostInsta: 84,
boostSpike: 77,
spikeTickStrike: 82,
instaSync: 75,
shieldDefense: 85,
placementDefense: 93,
teammateRescue: 87,
spikeGearCounter: 83,
turretSteal: 43,
dashMovement: 66,
antiBoostBlock: 88,
antiTroll: 92,
boostBreak: 65,
manualAttack: 60,
cleanup: 55,
weaponGrind: 50,
// Placement sits above ordinary clicks/cleanup, but all defensive and Insta
// owners still win. Held attacks loan one placement phase without being
// cancelled by this priority.
smartAutoPlace: 64,
spikeSpam: 94,
threatTrap: 45,
reloadSpike: 40,
mobSteal: 38,
matThief: 35,
weaponRecharge: 20,
movementGear: 10,
soldierGear: 10,
});
let __mmActionOwner = "idle",
__mmActionReason = "waiting",
__mmActionSince = 0,
__mmActionLastDecision = "waiting";
function __mmActionPriority(__mmOwner) {
return Number(__mmActionPriorities[__mmOwner]) || 0;
}
function __mmHeldAttackMayLoan(__mmOwner) {
return !!(
__mmActionOwner === "manualAttack" &&
(__mmPrimaryHeld || __mmSecondaryHeld) &&
(
__mmOwner === "antiTroll" ||
__mmOwner === "antiInsta" ||
__mmOwner === "antiBoostBlock" ||
__mmOwner === "placementDefense" ||
__mmOwner === "teammateRescue" ||
__mmOwner === "spikeSpam" ||
__mmOwner === "smartAutoPlace" ||
__mmOwner === "threatTrap" ||
__mmOwner === "reloadSpike" ||
__mmOwner === "weaponRecharge"
)
);
}
function __mmActionAvailable(__mmOwner) {
return (
__mmActionOwner === "idle" ||
__mmActionOwner === __mmOwner ||
__mmHeldAttackMayLoan(__mmOwner) ||
(__mmActionOwner === "weaponGrind" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("weaponGrind"))
);
}
function __mmActionCanPreempt(__mmOwner) {
return (
__mmActionAvailable(__mmOwner) ||
__mmActionPriority(__mmOwner) > __mmActionPriority(__mmActionOwner)
);
}
function __mmActionClaim(__mmOwner, __mmReason) {
const __mmIncomingHigher =
__mmOwner !== __mmActionOwner &&
__mmActionPriority(__mmOwner) > __mmActionPriority(__mmActionOwner);
if (__mmIncomingHigher && __mmActionOwner === "insta")
__mmInsta.cancel("preempted by " + __mmOwner);
if (__mmIncomingHigher && __mmActionOwner === "bowUpgradeInsta")
__mmBowUpgradeInsta.cancel("preempted by " + __mmOwner);
if (__mmIncomingHigher && __mmActionOwner === "instaSync")
__mmStopInstaSync();
if (__mmIncomingHigher && __mmActionOwner === "shieldDefense")
__mmStopShieldDefense("preempted by " + __mmOwner);
if (__mmIncomingHigher && __mmActionOwner === "spikeGearCounter")
__mmResetSpikeGearCounter(!0);
if (__mmIncomingHigher && __mmActionOwner === "turretSteal") {
(__mmTurretStealRestoreTimer &&
clearTimeout(__mmTurretStealRestoreTimer),
(__mmTurretStealRestoreTimer = 0),
v && v.alive && __mmEquipHatNow(__mmBestPostCombatHat(), !0),
__mmActionRelease("turretSteal", "preempted by " + __mmOwner));
}
if (__mmIncomingHigher && __mmActionOwner === "boostBreak")
__mmStopBoostBreak();
if (__mmIncomingHigher && __mmActionOwner === "teammateRescue")
__mmStopTeammateRescue("preempted by " + __mmOwner);
if (__mmIncomingHigher && __mmActionOwner === "dashMovement")
__mmStopDashMovement("preempted by " + __mmOwner);
if (
__mmActionOwner === "autoPushSetup" &&
__mmOwner !== "autoPushSetup" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("autoPushSetup")
)
__mmStopAutoPushSetup("preempted by " + __mmOwner);
if (
__mmActionOwner === "velTickSetup" &&
__mmOwner !== "velTickSetup" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("velTickSetup")
)
__mmStopVelTickInsta("preempted by " + __mmOwner);
if (
__mmActionOwner === "boostInsta" &&
__mmOwner !== "boostInsta" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("boostInsta")
)
__mmBoostInsta.cancel("preempted by " + __mmOwner);
if (
__mmActionOwner === "weaponGrind" &&
__mmOwner !== "weaponGrind" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("weaponGrind")
)
__mmPauseWeaponGrind("preempted by " + __mmOwner);
if (
__mmActionOwner === "cleanup" &&
__mmOwner !== "cleanup" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("cleanup")
)
__mmStopCleanup("preempted by " + __mmOwner, !1);
if (
__mmActionOwner === "spikeTickStrike" &&
__mmOwner !== "spikeTickStrike" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("spikeTickStrike")
)
__mmStopSpikeTickStrike("preempted by " + __mmOwner);
if (
__mmActionOwner === "antiBoostBlock" &&
__mmOwner !== "antiBoostBlock" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("antiBoostBlock")
)
__mmStopAntiBoostBlock("preempted by " + __mmOwner);
if (
__mmActionOwner === "weaponRecharge" &&
__mmOwner !== "weaponRecharge" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("weaponRecharge")
)
__mmPauseWeaponRecharge(!0);
if (
__mmActionOwner === "matThief" &&
__mmOwner !== "matThief" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("matThief")
)
__mmFinishMatThief("preempted by " + __mmOwner);
if (
__mmActionOwner === "mobSteal" &&
__mmOwner !== "mobSteal" &&
__mmActionPriority(__mmOwner) > __mmActionPriority("mobSteal")
)
__mmFinishMobSteal("preempted by " + __mmOwner);
if (!__mmActionAvailable(__mmOwner)) {
__mmActionLastDecision =
__mmOwner +
" blocked by " +
__mmActionOwner +
" (requested " +
__mmActionPriority(__mmOwner) +
", active " +
__mmActionPriority(__mmActionOwner) +
"): " +
(__mmReason || "busy");
return !1;
}
if (__mmHeldAttackMayLoan(__mmOwner)) {
__mmActionLastDecision =
__mmOwner + ": borrowed held attack · " + (__mmReason || "active");
return !0;
}
if (__mmActionOwner === __mmOwner) {
((__mmActionReason = __mmReason || __mmActionReason),
(__mmActionLastDecision = __mmOwner + ": " + __mmActionReason));
return !0;
}
((__mmActionOwner = __mmOwner),
(__mmActionReason = __mmReason || "active"),
(__mmActionSince = Date.now()),
(__mmActionLastDecision = __mmOwner + ": " + __mmActionReason));
return !0;
}
function __mmActionRelease(__mmOwner, __mmReason) {
if (__mmActionOwner !== __mmOwner) return !1;
((__mmActionOwner = "idle"),
(__mmActionReason = "idle"),
(__mmActionSince = 0),
(__mmActionLastDecision = __mmOwner + ": " + (__mmReason || "complete")));
return !0;
}
function __mmActionMayRestore(__mmOwner) {
return (
__mmActionOwner === __mmOwner ||
__mmActionOwner === "idle" ||
__mmHeldAttackMayLoan(__mmOwner)
);
}
function __mmNormalizeRuntimeBindings(__mmCandidate) {
const __mmNext = Object.assign({}, __mmDefaultKeybinds);
if (!__mmCandidate || typeof __mmCandidate !== "object") return __mmNext;
for (let __mmIndex = 0; __mmIndex < __mmBindingActions.length; __mmIndex++) {
const __mmAction = __mmBindingActions[__mmIndex],
__mmValue = __mmCandidate[__mmAction];
if (typeof __mmValue === "string" && __mmValue.length <= 80)
__mmNext[__mmAction] = __mmValue;
}
return __mmNext;
}
function __mmSetRuntimeBindings(__mmCandidate) {
__mmReleaseAllConfiguredBindings();
__mmKeybinds = __mmNormalizeRuntimeBindings(__mmCandidate);
}
function __mmRuntimeBindingParts(__mmBinding) {
const __mmPieces = String(__mmBinding || "").split("+");
return {
ctrl: __mmPieces.includes("Ctrl"),
alt: __mmPieces.includes("Alt"),
shift: __mmPieces.includes("Shift"),
meta: __mmPieces.includes("Meta"),
trigger:
__mmPieces.find(function (__mmPiece) {
return !["Ctrl", "Alt", "Shift", "Meta"].includes(__mmPiece);
}) || "",
};
}
function __mmRuntimeInputTrigger(__mmEvent, __mmMouse) {
return __mmMouse
? "Mouse" + Math.max(0, Math.min(4, Number(__mmEvent.button) || 0))
: String(__mmEvent.code || "");
}
function __mmRuntimeBindingMatches(__mmBinding, __mmEvent, __mmMouse) {
const __mmParts = __mmRuntimeBindingParts(__mmBinding);
return !!(
__mmParts.trigger === __mmRuntimeInputTrigger(__mmEvent, __mmMouse) &&
__mmParts.ctrl === !!__mmEvent.ctrlKey &&
__mmParts.alt === !!__mmEvent.altKey &&
__mmParts.shift === !!__mmEvent.shiftKey &&
__mmParts.meta === !!__mmEvent.metaKey
);
}
function __mmConfiguredActionForEvent(__mmEvent, __mmMouse) {
for (let __mmIndex = 0; __mmIndex < __mmBindingActions.length; __mmIndex++) {
const __mmAction = __mmBindingActions[__mmIndex];
if (
__mmAction !== "toggleHud" &&
__mmRuntimeBindingMatches(__mmKeybinds[__mmAction], __mmEvent, __mmMouse)
)
return __mmAction;
}
return null;
}
function __mmBindingActionHeld(__mmAction) {
return __mmActiveBindingActions.has(__mmAction);
}
function __mmBindingTypingTarget(__mmTarget) {
return !!(
__mmTarget &&
__mmTarget.closest &&
__mmTarget.closest("input,textarea,[contenteditable='true']")
);
}
function __mmBindingGameSubmenuOpen() {
const __mmIds = ["allianceMenu", "storeMenu", "chatHolder"];
for (let __mmIndex = 0; __mmIndex < __mmIds.length; __mmIndex++) {
const __mmMenu = document.getElementById(__mmIds[__mmIndex]);
if (
__mmMenu &&
(__mmMenu.style.display === "block" ||
window.getComputedStyle(__mmMenu).display !== "none")
)
return !0;
}
return !1;
}
function __mmStartConfiguredPrimary(__mmEvent, __mmBoostClick) {
if (!v || !v.alive || v.weapons[0] == null) return !1;
if (__mmHandleBushCombatClick(__mmEvent)) return !0;
if (__mmBoostInsta.isActive()) return !0;
(__mmSecondaryHeld || __mmRightClickHat != null) &&
(__mmFinishSecondaryInput(), __mmForceRestoreRightClickHat());
__mmInsta.isActive() && __mmInsta.cancel("configured-primary");
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (__mmBoostClick) {
if (
__mmAutoInstaEnabled &&
__mmBoostInsta.start({ automatic: !0 })
)
return !0;
} else if (
__mmInsta.canAutoStart() &&
__mmInsta.start({ automatic: !0 })
)
return !0;
return __mmStartPrimaryInput();
}
function __mmPressConfiguredAction(__mmAction, __mmEvent) {
__mmCleanupActive &&
__mmAction !== "cleanup" &&
__mmStopCleanup("configured input", !1);
if (__mmAction === "primaryAttack")
return __mmStartConfiguredPrimary(__mmEvent, !1);
if (__mmAction === "clickBoostInsta")
return __mmStartConfiguredPrimary(__mmEvent, !0);
if (__mmAction === "secondaryAttack")
return __mmStartConfiguredSecondary(__mmEvent);
if (__mmAction === "normalInsta") return __mmHandleInstaHotkey();
if (__mmAction === "boostInsta") return __mmBoostInsta.start();
if (__mmAction === "oneTickInsta") return (__mmToggleOneTickInsta(), !0);
if (__mmAction === "velTickInsta") return (__mmToggleVelTickInsta(), !0);
if (__mmAction === "boostSpike") return (__mmStartBoostSpike(), !0);
if (__mmAction === "quadTrap")
return (__mmManualQuadPlacement("trap"), !0);
if (__mmAction === "quadSpike")
return (__mmManualQuadPlacement("spike"), !0);
if (__mmAction === "betrayalInsta") return __mmStartBetrayalInsta();
if (__mmAction === "toggleAutoHeal") return (__mmToggleAutoHeal(), !0);
if (__mmAction === "food") return (__mmStartFoodSpam(), !0);
if (__mmAction === "trapBuild")
return (v && v.items && v.items[4] != null &&
__mmStartBuildSpam(4, __mmAction), !0);
if (__mmAction === "spikeBuild")
return (v && v.items && v.items[2] != null &&
__mmStartBuildSpam(2, __mmAction), !0);
if (__mmAction === "specialBuild")
return (__mmStartSelectedBuildSpam(__mmAction), !0);
if (__mmAction === "boostBreak") return (__mmStartBoostBreak(), !0);
if (__mmAction === "movingMills" || __mmAction === "movingMillsAlt")
return (__mmStartWindmillHold(), !0);
if (__mmAction === "bushMode") return (__mmHandleBushHotkey(), !0);
if (__mmAction === "cleanup") return (__mmToggleCleanup(), !0);
if (__mmAction === "friendPick")
return (__mmArmFriendPick("friend"), !0);
if (__mmAction === "enemyPick")
return (__mmArmFriendPick("enemy"), !0);
if (__mmAction === "syncPick") return (__mmArmSyncPick(), !0);
return !1;
}
function __mmReleaseConfiguredAction(__mmAction) {
if (__mmAction === "primaryAttack" || __mmAction === "clickBoostInsta")
return void (__mmPrimaryHeld && __mmStopPrimaryInput());
if (__mmAction === "secondaryAttack")
return void ((__mmSecondaryHeld || __mmRightClickHat != null) &&
__mmFinishSecondaryInput());
if (__mmAction === "boostSpike") return void __mmStopBoostSpike();
if (__mmAction === "food") return void __mmStopFoodSpam();
if (["trapBuild", "spikeBuild", "specialBuild"].includes(__mmAction))
return void __mmStopBuildSpam(__mmAction);
if (__mmAction === "boostBreak") return void __mmStopBoostBreak();
if (__mmAction === "movingMills" || __mmAction === "movingMillsAlt")
return void __mmStopWindmillHold();
if (__mmAction === "bushMode") __mmBushHotkeyDown = !1;
}
function __mmReleaseAllConfiguredBindings() {
const __mmActions = Array.from(__mmActiveBindingActions.keys());
for (let __mmIndex = 0; __mmIndex < __mmActions.length; __mmIndex++)
__mmReleaseConfiguredAction(__mmActions[__mmIndex]);
(__mmActiveBindingActions.clear(), __mmConsumedBindingInputs.clear());
}
function __mmConfiguredModifierReleased(__mmCode, __mmParts) {
return !!(
(__mmParts.shift && /^Shift/.test(__mmCode)) ||
(__mmParts.ctrl && /^Control/.test(__mmCode)) ||
(__mmParts.alt && /^Alt/.test(__mmCode)) ||
(__mmParts.meta && /^Meta/.test(__mmCode))
);
}
function __mmHandleConfiguredInput(__mmEvent, __mmPressed, __mmMouse) {
if (
!__mmEvent ||
(__mmPressed && __mmBindingTypingTarget(__mmEvent.target))
)
return !1;
if (__mmPressed && __mmBindingGameSubmenuOpen()) return !1;
if (__mmMouse) {
if (!__mmIsGameClick(__mmEvent)) return !1;
if (__mmFriendPickMode || __mmSyncPickArmed) return !1;
}
const __mmTrigger = __mmRuntimeInputTrigger(__mmEvent, __mmMouse);
if (__mmPressed) {
const __mmAction = __mmConfiguredActionForEvent(__mmEvent, __mmMouse);
if (!__mmAction) return !1;
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
if (__mmEvent.repeat || __mmConsumedBindingInputs.has(__mmTrigger)) return !0;
if (__mmBindingHoldActions.has(__mmAction))
__mmActiveBindingActions.set(__mmAction, {
trigger: __mmTrigger,
binding: __mmKeybinds[__mmAction],
});
(__mmConsumedBindingInputs.set(__mmTrigger, __mmAction),
__mmPressConfiguredAction(__mmAction, __mmEvent));
return !0;
}
let __mmConsumed = !1;
const __mmDirectAction = __mmConsumedBindingInputs.get(__mmTrigger);
if (__mmDirectAction) {
(__mmConsumedBindingInputs.delete(__mmTrigger), (__mmConsumed = !0));
if (__mmActiveBindingActions.has(__mmDirectAction)) {
(__mmReleaseConfiguredAction(__mmDirectAction),
__mmActiveBindingActions.delete(__mmDirectAction));
}
}
if (!__mmMouse) {
for (const [__mmAction, __mmActive] of __mmActiveBindingActions) {
if (
__mmConfiguredModifierReleased(
String(__mmEvent.code || ""),
__mmRuntimeBindingParts(__mmActive.binding),
)
)
(__mmReleaseConfiguredAction(__mmAction),
__mmActiveBindingActions.delete(__mmAction));
}
}
if (__mmConsumed)
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
return __mmConsumed;
}
document.addEventListener(
"keydown",
function (__mmEvent) {
__mmHandleConfiguredInput(__mmEvent, !0, !1);
},
!0,
);
document.addEventListener(
"keyup",
function (__mmEvent) {
__mmHandleConfiguredInput(__mmEvent, !1, !1);
},
!0,
);
document.addEventListener(
"mousedown",
function (__mmEvent) {
__mmHandleConfiguredInput(__mmEvent, !0, !0);
},
!0,
);
document.addEventListener(
"mouseup",
function (__mmEvent) {
__mmHandleConfiguredInput(__mmEvent, !1, !0);
},
!0,
);
window.addEventListener("blur", __mmReleaseAllConfiguredBindings);
function __mmSuspendHeldAttackForManualInsta() {
const __mmHadHeldAttack = !!(__mmPrimaryHeld || __mmSecondaryHeld),
__mmCanTakeHeldAttack =
__mmActionOwner === "manualAttack" || __mmActionOwner === "idle";
// A direct R press may borrow the player's current mouse hold. Keep the
// logical held flags intact so mouseup can still cancel it, but stop the
// native attack stream before the combo emits its own precisely timed taps.
if (__mmHadHeldAttack && !__mmCanTakeHeldAttack) return !1;
if (__mmHadHeldAttack) {
(__mmHeldAttackTimer && clearInterval(__mmHeldAttackTimer),
(__mmHeldAttackTimer = 0));
if (v && v.alive)
try {
__mmSendWeaponAttack(0);
} catch (__mmManualInstaReleaseError) {}
((__mmPrimaryAttackDown = !1), (__mmSecondaryAttackDown = !1));
}
// A missed mouseup can leave manualAttack owned even though neither button
// is down. R should repair that stale owner instead of being swallowed.
__mmActionOwner === "manualAttack" &&
__mmActionRelease("manualAttack", "loaned to manual R Insta");
return !0;
}
function __mmUpdateLiveState() {
const __mmNow = Date.now(),
__mmEnemies = [],
__mmAnimals = [],
__mmSeenEntities = Object.create(null);
let __mmNearest = null,
__mmNearestDistance = Infinity;
if (!v || !v.alive) {
((__mmLiveState.updatedAt = __mmNow),
(__mmLiveState.alive = !1),
(__mmLiveState.enemies = __mmEnemies),
(__mmLiveState.animals = __mmAnimals),
(__mmLiveState.nearestEnemy = null),
(__mmLiveState.nearestEnemyDistance = Infinity),
(__mmLiveState.nearbyTrap = null),
(__mmLiveState.trapped = !1));
return __mmLiveState;
}
if (typeof E !== "undefined" && Array.isArray(E))
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
const __mmPlayer = E[__mmIndex];
const __mmKey = __mmThreatTargetKey(__mmPlayer);
__mmKey != null && (__mmSeenEntities[__mmKey] = !0);
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
const __mmDistance = Math.hypot(__mmPlayer.x - v.x, __mmPlayer.y - v.y);
if (!Number.isFinite(__mmDistance)) continue;
__mmEnemies.push(__mmPlayer);
if (__mmDistance < __mmNearestDistance) {
((__mmNearest = __mmPlayer), (__mmNearestDistance = __mmDistance));
}
}
if (typeof N !== "undefined" && Array.isArray(N))
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex += 1) {
const __mmAnimal = N[__mmIndex];
const __mmKey = __mmThreatTargetKey(__mmAnimal);
__mmKey != null && (__mmSeenEntities[__mmKey] = !0);
__mmAnimal && __mmAnimal.active !== !1 && __mmAnimals.push(__mmAnimal);
}
for (const __mmKey in __mmThreatTrapPlacements)
__mmSeenEntities[__mmKey] || delete __mmThreatTrapPlacements[__mmKey];
for (const __mmKey in __mmUnknownTeamSeen)
__mmSeenEntities[__mmKey] || delete __mmUnknownTeamSeen[__mmKey];
const __mmTrap = __mmNearestLockingTrap();
((__mmLiveState.updatedAt = __mmNow),
(__mmLiveState.alive = !0),
(__mmLiveState.enemies = __mmEnemies),
(__mmLiveState.animals = __mmAnimals),
(__mmLiveState.nearestEnemy = __mmNearest),
(__mmLiveState.nearestEnemyDistance = __mmNearestDistance),
(__mmLiveState.nearbyTrap = __mmTrap),
(__mmLiveState.trapped = !!__mmTrap),
(__mmLiveState.health = Number(v.health) || 0),
(__mmLiveState.maxHealth = Number(v.maxHealth) || 0),
(__mmLiveState.primaryReady = !!__mmWeaponReady(v.weapons && v.weapons[0])),
(__mmLiveState.secondaryReady = !!__mmWeaponReady(v.weapons && v.weapons[1])));
return __mmLiveState;
}
function __mmLiveStateFresh() {
return Date.now() - __mmLiveState.updatedAt <= 2 * __mmFastCheckMs();
}
function __mmCurrentNearbyTrap() {
if (
__mmLiveStateFresh() &&
__mmPlayerCenterTouchesEnemyTrap(__mmLiveState.nearbyTrap)
)
return __mmLiveState.nearbyTrap;
return __mmNearestLockingTrap();
}
function __mmIsTrapped() {
return !!(v && v.alive && __mmCurrentNearbyTrap());
}
function __mmRuntimeDebugText() {
const __mmState = __mmLiveState,
__mmThreat = __mmCombatThreatSnapshot(),
__mmEnemy = __mmState.nearestEnemy,
__mmReload = v && v.weapons
? "main " + (__mmState.primaryReady ? "ready" : "reload") +
" · secondary " + (__mmState.secondaryReady ? "ready" : "reload")
: "weapons unavailable",
__mmOwnerAge = __mmActionSince ? Date.now() - __mmActionSince : 0;
return [
"pipeline: " +
__mmOperationPipelineStage +
" · cycle " +
__mmOperationPipelineCycle +
" · " +
__mmOperationPipelineOrder.join(" > "),
"owner: " + __mmActionOwner + (__mmActionSince ? " (" + __mmOwnerAge + "ms)" : ""),
"reason: " + __mmActionReason,
"last: " + __mmActionLastDecision,
"repair: " +
(__mmStateRepairCount
? __mmStateRepairLastReason +
" (" +
(Date.now() - __mmStateRepairLastAt) +
"ms ago · " +
__mmStateRepairCount +
")"
: "watching"),
"insta: " +
(__mmInsta && __mmInsta.isActive()
? __mmInsta.profile + " · " + __mmInsta.profileSource
: "idle"),
"enemy: " +
(__mmEnemy
? String(__mmEnemy.sid) + " at " + Math.round(__mmState.nearestEnemyDistance)
: "none"),
"trap: " + (__mmState.trapped ? "locked/collision" : "clear"),
"threat: " +
Math.round(__mmThreat.damage) +
" dmg (proj " +
Math.round(__mmThreat.projectileDamage) +
" · melee " +
Math.round(__mmThreat.meleeDamage) +
" · spike " +
Math.round(__mmThreat.spikeDamage) +
") · heal " +
Math.round(__mmThreat.healPotential) +
(__mmThreat.lethal ? " · LETHAL" : ""),
"reload: " + __mmReload,
"smartness: " +
__mmEffectiveSmartDepth() +
"/" +
__mmSmartDepthCeiling() +
" · " +
(__mmAdaptiveSmartnessEnabled ? __mmAdaptiveReason : "manual ceiling") +
" · " +
(Number.isFinite(__mmMetricFps) && __mmMetricFps > 0
? Math.round(__mmMetricFps) + " FPS"
: "sampling FPS"),
"placement: " +
__mmSmartPlacementStats.state + " · " +
__mmSmartPlacementStats.reason + " · legal " +
__mmSmartPlacementStats.legal + " / scored " +
__mmSmartPlacementStats.scored + " / sent " +
__mmSmartPlacementStats.sent + " · items " +
__mmSmartPlacementStats.itemSummary,
"scan: " + __mmReactionMs + "ms · state age " +
(Date.now() - __mmState.updatedAt) + "ms",
].join("\\n");
}
function __mmStartLiveState() {
__mmEnsureOperationPipeline();
}
function __mmOperationStage(__mmStage, __mmCallback) {
__mmOperationPipelineStage = __mmStage;
try {
__mmCallback();
} catch (__mmPipelineStageError) {
const __mmNow = Date.now(),
__mmLastError = Number(__mmOperationPipelineErrors[__mmStage]) || 0;
__mmOperationPipelineErrors[__mmStage] = __mmNow;
__mmNow - __mmLastError >= 1000 &&
console.warn(
"[kitty klient] operation stage failed:",
__mmStage,
__mmPipelineStageError,
);
}
}
function __mmRunOperationPipeline() {
if (__mmOperationPipelineRunning) return;
(__mmOperationPipelineRunning = !0,
(__mmOperationPipelineCycle += 1),
(__mmOperationPipelineLastAt = Date.now()));
try {
__mmOperationStage("snapshot", function () {
(__mmUpdateLiveState(),
(__mmCombatThreatCalculatedAt = 0),
__mmCombatThreatSnapshot(!0),
__mmObserveProjectileCooldowns());
});
__mmOperationStage("housekeeping", function () {
__mmUpdateAutoPurchase();
});
// A real lock owns the weapon/aim channels before every other module.
__mmOperationStage("trap", function () {
(__mmTrapEscapeEnabled || __mmTrapAttackActive) && __mmBreakTrap();
});
// Lethal prevention is evaluated before optional damage combos, with one
// latency-sensitive combat module owning a server tick at a time.
__mmOperationStage("defense", function () {
(__mmUpdateAntiInsta(),
__mmUpdateAntiTroll(),
__mmUpdatePlacementDefense(),
__mmUpdateTeammateTrapRescue(),
__mmUpdateAntiCollision());
});
// Resolve allied projectile/turret sync and spike timing before
// self-started Insta variants.
__mmOperationStage("combat-sync", function () {
(__mmUpdateInstaSync(), __mmUpdateAutoSpikeInsta());
});
__mmOperationStage("combat-insta", function () {
(__mmUpdateKittyInstas(),
__mmUpdateAutoTrapInsta(),
__mmUpdateAntiBoostInsta(),
__mmUpdateSpikeGearCounter(),
__mmUpdateBushMode());
});
// Health events still call Autoheal synchronously; this ordered pass is
// the between-packets fallback.
__mmOperationStage("heal", function () {
__mmAutoHeal();
});
__mmOperationStage("placement", function () {
(__mmUpdateAutoSpikeSpam(),
(__mmSmartAutoPlaceEnabled ||
__mmAutomaticQuadPlacementEnabled() ||
__mmSmartAutoReplaceEnabled ||
__mmSmartSpikeSyncPlaceEnabled ||
__mmSmartAntiBoostPlaceEnabled ||
__mmSmartMovingMillsEnabled ||
__mmSmartReplacePoint) &&
__mmUpdateSmartPlacement(),
__mmPlaceThreatTrap(),
__mmUpdateReloadSpike());
});
__mmOperationStage("utility", function () {
(__mmCleanupActive && __mmUpdateCleanup(),
__mmWeaponGrindEnabled && __mmUpdateWeaponGrind(),
__mmUpdateTurretSteal(),
__mmUpdateMobSteal(),
__mmUpdateMatThief(),
__mmMusketRechargeEnabled && __mmUpdateWeaponRecharge(),
__mmUpdateMultiBreakAim());
});
__mmOperationStage("gear", function () {
(__mmUpdateAssassinAutomation(),
__mmUpdateMovementGear(),
__mmUpdateSoldier());
});
__mmOperationStage("restore", function () {
(__mmUpdateAutomaticStateRepair(), __mmRecoverStrayCombatHat());
});
} finally {
((__mmOperationPipelineStage = "idle"),
(__mmOperationPipelineRunning = !1));
}
}
function __mmScheduleOperationPipeline() {
if (__mmOperationPipelineTimer) return;
__mmOperationPipelineTimer = setTimeout(function __mmOperationPipelineStep() {
((__mmOperationPipelineTimer = 0), __mmRunOperationPipeline());
__mmOperationPipelineTimer = setTimeout(
__mmOperationPipelineStep,
Math.min(10, __mmFastCheckMs()),
);
}, 0);
}
function __mmEnsureOperationPipeline() {
(__mmLiveStateTimer && clearInterval(__mmLiveStateTimer),
(__mmLiveStateTimer = 0),
__mmScheduleOperationPipeline());
}
function __mmStartDebugHud() {
__mmDebugHudTimer ||
(__mmDebugHudTimer = setInterval(function () {
__mmDebugPanelEnabled && __mmPublishHudState();
}, 200));
}
const __mmUnknownTeamSeen = {},
__mmUnknownTeamGraceMs = 1500;
const __mmBoostChatLines = [
"WHEEEEEE!",
"Wooo-hooo!",
"ZOOOOOM!",
"Can't catch me!",
"I AM SPEEEEED!",
"I'M COMING FOR YOU!",
"AAAHHHHH!",
];
const __mmOriginalSelect = je;
let __mmLastSelectionItem = null,
__mmLastSelectionWasWeapon = !1,
__mmLastSelectionAt = 0;
je = function (__mmItem, __mmIsWeapon) {
((__mmLastSelectionItem = __mmItem),
(__mmLastSelectionWasWeapon = !!__mmIsWeapon),
(__mmLastSelectionAt = Date.now()));
__mmIsWeapon && (__mmLastWeapon = __mmItem);
const __mmResult = __mmOriginalSelect(__mmItem, __mmIsWeapon);
return (__mmSyncPublishSelection(__mmItem, __mmIsWeapon), __mmResult);
};
function __mmPrepareTrademarkNameInput() {
// Do not touch MooMoo's minified name-input binding here. This patch block is
// inserted before that top-level const is initialized in the current bundle,
// so even testing the binding aborts the whole module through the TDZ.
const __mmNameInput = document.getElementById("nameInput");
if (!__mmNameInput) return 13;
const __mmStoredOriginal = Number(__mmNameInput.dataset.kittyOriginalNameMax),
__mmOriginalMax =
Number.isFinite(__mmStoredOriginal) && __mmStoredOriginal > 2
? __mmStoredOriginal
: Math.max(3, Number(__mmNameInput.maxLength) || 15),
__mmLimit = Math.max(1, __mmOriginalMax - 2),
__mmRaw = String(__mmNameInput.value || "")
.replace(/^(?:k-)+/i, "")
.slice(0, __mmLimit),
__mmVisible = "k-" + __mmRaw;
(__mmNameInput.dataset.kittyOriginalNameMax = String(__mmOriginalMax),
__mmNameInput.dataset.kittyNameLimit = String(__mmLimit),
(__mmNameInput.maxLength = __mmOriginalMax),
__mmNameInput.setAttribute("maxlength", String(__mmOriginalMax)),
(__mmNameInput.placeholder = "k-Your Name"),
__mmNameInput.value !== __mmVisible &&
(__mmNameInput.value = __mmVisible));
return __mmLimit;
}
function __mmTrademarkPlayerName(__mmName) {
const __mmLimit = __mmPrepareTrademarkNameInput(),
__mmRaw = String(__mmName || "")
.replace(/^(?:k-)+/i, "")
.slice(0, __mmLimit);
return "k-" + __mmRaw;
}
__mmPrepareTrademarkNameInput();
const __mmOriginalSocketSend = O.send;
let __mmKatanaMusketUpgradeTimer = 0,
__mmKatanaMusketUpgradeActive = !1;
function __mmTryKatanaMusketUpgrade(__mmSelection) {
if (Number(__mmSelection) !== Number(__mmMusket)) return !1;
// Consume repeated Musket clicks while the fixed two-packet sequence owns
// the upgrade channel. There are no confirmation retries.
if (__mmKatanaMusketUpgradeActive) return !0;
const __mmUpgradePoints = Number(v && v.upgradePoints);
if (
!v ||
!v.alive ||
!Array.isArray(v.weapons) ||
!v.weapons.includes(__mmShortSword) ||
v.weapons.includes(__mmKatana) ||
(Number.isFinite(__mmUpgradePoints) && __mmUpgradePoints <= 0) ||
!__mmUpgradeServerSafe(__mmMusket)
)
return !1;
// Both choices must enter the same server update window. A full-tick delay
// lets Katana consume/advance the upgrade phase before Musket arrives; zero
// delay can be coalesced by some transports. Keep only a tiny ordering gap,
// with no acknowledgement wait or retry loop.
const __mmDelay = Math.max(4, Math.min(12, __mmFastCheckMs()));
((__mmKatanaMusketUpgradeActive = !0),
(__mmLastUpgradePacketAt = Date.now()),
__mmOriginalSocketSend.call(O, "H", __mmKatana),
(__mmKatanaMusketUpgradeTimer = setTimeout(function () {
__mmKatanaMusketUpgradeTimer = 0;
if (v && v.alive) {
((__mmLastUpgradePacketAt = Date.now()),
__mmOriginalSocketSend.call(O, "H", __mmMusket));
}
__mmKatanaMusketUpgradeActive = !1;
}, __mmDelay)));
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomStatus", {
detail: "Katana + Musket",
}),
);
return !0;
}
O.send = function () {
const __mmUpgradePacket = arguments[0] === "H";
if (__mmUpgradePacket && __mmTryKatanaMusketUpgrade(arguments[1])) return;
if (__mmUpgradePacket && !__mmAllowUpgradePacket(arguments[1])) return;
if (
arguments[0] === "c" &&
!arguments[3] &&
Number(arguments[2]) === Number(__mmEmpHelmet) &&
__mmEnemyWithinCombatRange()
)
arguments[2] = v && v.skins && v.skins[6] ? 6 : 0;
if (
arguments[0] === "c" &&
!arguments[3] &&
!__mmCombatHatPacketAllowed(arguments[2])
)
return;
if (
arguments[0] === "M" &&
arguments[1] &&
typeof arguments[1] === "object"
)
arguments[1] = {
...arguments[1],
name: __mmTrademarkPlayerName(arguments[1].name),
};
const __mmResult = __mmOriginalSocketSend.apply(this, arguments);
((__mmMetricPackets += 1),
(__mmMetricPacketWindow += 1),
__mmObserveOutgoingProjectileAttack(arguments),
__mmSyncObserveSocketSend(arguments),
__mmObserveForcedDirectionPacket(arguments));
return __mmResult;
};
const __mmOriginalPlayerAttack = Pl;
const __mmOriginalDeath = Sl;
const __mmOriginalHealthUpdate = $l;
const __mmOriginalAnimalUpdate = Xl;
const __mmOriginalPlayerStatUpdate = Kl;
const __mmOriginalChatDisplay = dl;
const __mmOriginalUpgradeDisplay = Un;
const __mmOriginalObjectRender = Ge;
const __mmOriginalObjectHit = Wl;
const __mmOriginalAimDirection = Ci;
const __mmOriginalRender = Cl;
Ci = function () {
return __mmTrapAttackActive && Number.isFinite(__mmTrapAimAngle)
? __mmTrapAimAngle
: __mmSecondaryShieldActive && Number.isFinite(__mmSecondaryShieldAngle)
? __mmSecondaryShieldAngle
: Number.isFinite(__mmMatThiefAimAngle)
? __mmMatThiefAimAngle
: Number.isFinite(__mmMobStealAimAngle)
? __mmMobStealAimAngle
: Number.isFinite(__mmAntiBoostBlockAimAngle)
? __mmAntiBoostBlockAimAngle
: Number.isFinite(__mmSpikeTickStrikeAimAngle)
? __mmSpikeTickStrikeAimAngle
: Number.isFinite(__mmMultiBreakAimAngle)
? __mmMultiBreakAimAngle
: __mmCleanupActive && Number.isFinite(__mmCleanupAimAngle)
? __mmCleanupAimAngle
: __mmWeaponGrindEnabled &&
(__mmWeaponGrindHold || __mmActionOwner === "weaponGrind") &&
Number.isFinite(__mmWeaponGrindAimAngle)
? __mmWeaponGrindAimAngle
: Date.now() < __mmAutoSpikeSpamAimUntil &&
Number.isFinite(__mmAutoSpikeSpamAimAngle)
? __mmAutoSpikeSpamAimAngle
: __mmOriginalAimDirection.apply(this, arguments);
};
function __mmRawMouseAimDirection() {
// Read the cursor coordinates directly so X/lockDir cannot freeze this at
// the pre-automation angle. The normal Ci helper intentionally preserves
// its old angle while X is enabled.
const __mmMouseX = Number(On) - Number(De) / 2,
__mmMouseY = Number(Hn) - Number(Ae) / 2;
if (Number.isFinite(__mmMouseX) && Number.isFinite(__mmMouseY)) {
const __mmDirectAngle = Math.atan2(__mmMouseY, __mmMouseX);
return typeof M.fixTo === "function"
? M.fixTo(__mmDirectAngle, 2)
: __mmDirectAngle;
}
let __mmAngle = 0;
try {
__mmAngle = Number(__mmOriginalAimDirection());
} catch (__mmMouseAimError) {}
// Zero is a valid direction (cursor directly on the positive X axis), so
// never use a truthiness fallback here.
return Number.isFinite(__mmAngle) ? __mmAngle : 0;
}
function __mmForcedDirectionStillActive() {
return !!(
(__mmTrapAttackActive && Number.isFinite(__mmTrapAimAngle)) ||
(__mmSecondaryShieldActive && Number.isFinite(__mmSecondaryShieldAngle)) ||
Number.isFinite(__mmMatThiefAimAngle) ||
Number.isFinite(__mmMobStealAimAngle) ||
Number.isFinite(__mmAntiBoostBlockAimAngle) ||
Number.isFinite(__mmSpikeTickStrikeAimAngle) ||
Number.isFinite(__mmMultiBreakAimAngle) ||
(__mmCleanupActive && Number.isFinite(__mmCleanupAimAngle)) ||
(__mmWeaponGrindEnabled &&
(__mmWeaponGrindHold || __mmActionOwner === "weaponGrind") &&
Number.isFinite(__mmWeaponGrindAimAngle)) ||
(Date.now() < __mmAutoSpikeSpamAimUntil &&
Number.isFinite(__mmAutoSpikeSpamAimAngle)) ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
Number.isFinite(__mmBoostSpikeMoveAngle) ||
__mmInstaSyncPending ||
__mmInstaSyncFiring
);
}
function __mmReturnDirectionToMouse() {
__mmMouseAimReturnTimer = 0;
if (!v || !v.alive) return;
if (__mmForcedDirectionStillActive()) {
__mmMouseAimReturnTimer = setTimeout(
__mmReturnDirectionToMouse,
__mmFastCheckMs(),
);
return;
}
const __mmAngle = __mmRawMouseAimDirection();
let __mmReturned = !1;
try {
// Update the game's cached aim as well as the server. When X is active,
// Ci returns this cache instead of sampling the cursor on the next frame.
((It = __mmAngle),
(__mmSendingMouseAimReturn = !0),
O.send("D", __mmAngle),
(__mmReturned = !0));
} catch (__mmMouseAimReturnError) {
// The watchdog will retry after the transport resumes.
__mmLastForcedDirectionAt = Date.now();
} finally {
__mmSendingMouseAimReturn = !1;
}
__mmReturned && (__mmLastForcedDirectionAt = 0);
}
function __mmScheduleMouseAimReturn() {
if (__mmSendingMouseAimReturn) return;
__mmMouseAimReturnTimer && clearTimeout(__mmMouseAimReturnTimer);
__mmMouseAimReturnTimer = setTimeout(
__mmReturnDirectionToMouse,
__mmServerTickMs(),
);
}
function __mmObserveForcedDirectionPacket(__mmArgs) {
if (__mmSendingMouseAimReturn || !__mmArgs) return;
const __mmPacket = __mmArgs[0];
if (
__mmPacket === "F" &&
__mmArgs[2] != null &&
Number.isFinite(Number(__mmArgs[2]))
) {
((__mmLastForcedDirectionAt = Date.now()), __mmScheduleMouseAimReturn());
return;
}
if (
__mmPacket !== "D" ||
__mmArgs[1] == null ||
!Number.isFinite(Number(__mmArgs[1]))
)
return;
const __mmSent = Number(__mmArgs[1]),
__mmMouse = __mmRawMouseAimDirection(),
__mmDifference = Math.abs(
Math.atan2(
Math.sin(__mmSent - __mmMouse),
Math.cos(__mmSent - __mmMouse),
),
);
__mmDifference > 0.001 &&
((__mmLastForcedDirectionAt = Date.now()), __mmScheduleMouseAimReturn());
}
// R insta owns one short-lived interaction at a time. It deliberately uses the
// same client actions as normal input and yields to safety/manual automation.
// State transitions are intentionally limited to:
// idle -> validate -> arm -> waitForRange -> executeBurst -> soldier -> cleanup -> idle.
function __mmInstaSafeRestoreHat(__mmFallback) {
// Bull, Tank and Turret are packet-phase combat hats, never stable restore
// targets. A late acknowledgement from any of them must not poison the next
// Insta snapshot and keep that temporary hat equipped after cleanup.
const __mmCandidates = [
__mmFallback,
__mmPendingHat,
__mmPrimaryClickHat,
__mmRightClickHat,
__mmTrapHat,
__mmMovementGearPreviousHat,
__mmSoldierPreviousHat,
__mmLastNormalHat,
];
for (let __mmIndex = 0; __mmIndex < __mmCandidates.length; __mmIndex++) {
const __mmHat = __mmCandidates[__mmIndex];
if (!__mmTemporaryCombatHat(__mmHat) && __mmCanEquipHat(__mmHat))
return __mmHat;
}
return 0;
}
// Insta placement validates locally, selects the placeable, and sends one
// placement packet at the solved angle, then immediately put the combo weapon
// back in hand. There is deliberately no acknowledgement wait or F=0 gap.
function __mmInstaPlaceAndReselect(__mmItem, __mmAngle, __mmWeapon) {
if (
!v ||
!v.alive ||
__mmItem == null ||
!Number.isFinite(Number(__mmAngle)) ||
!__mmCanUseBuildItem(__mmItem)
)
return !1;
try {
const __mmPreviewCandidate = __mmSmartCandidateForAngle(
__mmItem,
__mmAngle,
!0,
);
if (__mmPreviewCandidate) {
((__mmPreviewCandidate.points = 10),
(__mmPreviewCandidate.priority = !0),
__mmSmartSetPlacementPreview(
[__mmPreviewCandidate],
[__mmPreviewCandidate],
"insta placement",
));
}
(je(__mmItem),
O.send("F", 1, __mmAngle),
__mmWeapon != null && je(__mmWeapon, !0));
return !0;
} catch (__mmInstaPlacementError) {
return !1;
}
}
function __mmInstaPopupLabel(__mmProfile, __mmAutomatic, __mmBetrayal) {
if (__mmBetrayal) return "Betrayal Insta";
const __mmLabels = {
normal: __mmAutomatic ? "Auto Insta" : "Normal Insta",
reverse: "Reverse Insta",
oneTick: "One-Tick Insta",
apple: "Apple Insta",
bleed: "Bleed Insta",
knockback: "Knockback Insta",
trapCatch: "Trap Insta",
polearmAids: "Polearm Insta",
velTick: "VelTick Insta",
autoPush: "Auto-Push Insta",
};
return __mmLabels[String(__mmProfile || "normal")] || "Insta";
}
function __mmTargetShieldActive(__mmTarget) {
if (!__mmTarget || !b || !b.weapons) return !1;
const __mmWeapon = b.weapons[Number(__mmTarget.weaponIndex)];
return !!(__mmWeapon && Number(__mmWeapon.shield) > 0);
}
function __mmShieldBypass(__mmAttacker, __mmTarget, __mmOrigin) {
if (!__mmTargetShieldActive(__mmTarget)) return !0;
const __mmAttackerX = Number(
__mmOrigin && __mmOrigin.x != null
? __mmOrigin.x
: __mmAttacker && __mmAttacker.x,
),
__mmAttackerY = Number(
__mmOrigin && __mmOrigin.y != null
? __mmOrigin.y
: __mmAttacker && __mmAttacker.y,
),
__mmTargetX = Number(__mmTarget.x),
__mmTargetY = Number(__mmTarget.y),
__mmFacing = Number(__mmTarget.dir);
if (
!Number.isFinite(__mmAttackerX) ||
!Number.isFinite(__mmAttackerY) ||
!Number.isFinite(__mmTargetX) ||
!Number.isFinite(__mmTargetY) ||
!Number.isFinite(__mmFacing)
)
return !1;
const __mmTowardAttacker = Math.atan2(
__mmAttackerY - __mmTargetY,
__mmAttackerX - __mmTargetX,
),
__mmDifference = Math.abs(
Math.atan2(
Math.sin(__mmTowardAttacker - __mmFacing),
Math.cos(__mmTowardAttacker - __mmFacing),
),
),
__mmShieldAngle = Math.max(
0.1,
Number(y && y.shieldAngle) || Math.PI / 3,
);
return __mmDifference > __mmShieldAngle;
}
const __mmInsta = {
state: "idle",
timer: 0,
releaseTimer: 0,
hatRestoreTimer: 0,
hatRestoreEpoch: 0,
targetSid: null,
targetOptional: !1,
automatic: !1,
betrayal: !1,
snapshot: null,
primaryWeapon: null,
pendingSecondaryWeapon: null,
attackHeld: !1,
trapHandoff: null,
postSpikeEnabled: !1,
postSpikeCandidate: null,
postSpikeCalculatedAt: 0,
postSpikeTarget: null,
profile: "normal",
profileSource: "R",
manualHotkey: !1,
bowUpgradeFollowup: !1,
popupShown: !1,
automaticRetryUntil: 0,
shieldWaitStartedAt: 0,
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, __mmDelay = this.tick()) {
this.timer && clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.timer = 0;
__mmCallback();
}, Math.max(1, Number(__mmDelay) || this.tick()));
},
normalStageMs() {
// Keep fixed 120 ms stages from becoming shorter than the actual server
// update when a slower server rate is reported.
return Math.max(120, this.tick());
},
reverseProfile() {
return [
"reverse",
"oneTick",
"apple",
"bleed",
"knockback",
"polearmAids",
].includes(this.profile);
},
openingDelay() {
return this.profile === "normal" ? this.normalStageMs() : 1;
},
profileStep(__mmTarget, __mmWeapon) {
if (this.profile !== "oneTick") return this.tick();
const __mmData = this.weaponData(__mmWeapon),
__mmProjectile =
__mmData && __mmData.projectile != null && b.projectiles
? b.projectiles[__mmData.projectile]
: null,
__mmSpeed = Number(__mmProjectile && __mmProjectile.speed),
__mmDistance = __mmTarget
? Math.max(
0,
Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) -
(Number(__mmTarget.scale) || 35),
)
: 0,
__mmTravel =
Number.isFinite(__mmSpeed) && __mmSpeed > 0
? __mmDistance / __mmSpeed
: this.tick();
// Launch the secondary first, then put the melee hit in the following
// server window. Projectile travel can shorten that window, never extend
// it beyond one tick where the target could leave melee range.
return Math.max(8, Math.min(this.tick(), __mmTravel || this.tick()));
},
scheduleRelease() {
this.releaseTimer && clearTimeout(this.releaseTimer);
this.releaseTimer = setTimeout(() => {
this.releaseTimer = 0;
this.releaseAttack();
}, 25);
},
cancelHatRestore() {
this.hatRestoreTimer && clearTimeout(this.hatRestoreTimer);
this.hatRestoreTimer = 0;
this.hatRestoreEpoch += 1;
},
scheduleHatRestore(__mmHat) {
this.cancelHatRestore();
__mmHat = __mmInstaSafeRestoreHat(__mmHat);
if (!__mmCanEquipHat(__mmHat)) return;
const __mmEpoch = this.hatRestoreEpoch,
__mmSelf = this;
let __mmAttempts = 0;
const __mmReassert = function () {
__mmSelf.hatRestoreTimer = 0;
if (
__mmEpoch !== __mmSelf.hatRestoreEpoch ||
__mmSelf.isActive() ||
!v ||
!v.alive
)
return;
if (
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmPrimaryClickHat != null ||
__mmRightClickHat != null ||
__mmTrapAttackActive ||
(__mmActionOwner !== "idle" &&
__mmActionOwner !== "movementGear" &&
__mmActionOwner !== "soldierGear" &&
__mmActionOwner !== "weaponRecharge")
) {
__mmAttempts += 1;
if (__mmAttempts < 12)
__mmSelf.hatRestoreTimer = setTimeout(
__mmReassert,
__mmSelf.tick(),
);
return;
}
const __mmPendingRestore =
__mmPendingHat != null &&
!__mmTemporaryCombatHat(__mmPendingHat) &&
__mmCanEquipHat(__mmPendingHat)
? __mmPendingHat
: __mmHat,
__mmTemporaryStillOwned =
__mmTemporaryCombatHat(v.skinIndex) ||
__mmTemporaryCombatHat(__mmPendingHat);
__mmTemporaryStillOwned && __mmEquipHatNow(__mmPendingRestore, !0);
__mmAttempts += 1;
if (__mmAttempts < 6)
__mmSelf.hatRestoreTimer = setTimeout(
__mmReassert,
__mmSelf.tick(),
);
};
this.hatRestoreTimer = setTimeout(__mmReassert, this.tick());
},
isPriorityConflict() {
const __mmTrapHandoffAvailable = !!(
__mmIsTrapped() &&
(__mmActionOwner === "trapEscape" || __mmTrapAttackActive)
);
return !!(
!v ||
!v.alive ||
(!__mmActionCanPreempt("insta") && !__mmTrapHandoffAvailable) ||
(!this.manualHotkey && (__mmPrimaryHeld || __mmSecondaryHeld)) ||
(__mmTrapAttackActive && !__mmTrapHandoffAvailable) ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
Date.now() < __mmAntiInstaUntil ||
__mmInstaSyncPending ||
__mmInstaSyncFiring ||
(this.isEmergencyHealth() && !__mmIsTrapped())
);
},
suspendTrapEscape() {
if (!__mmIsTrapped() || !__mmTrapEscapeEnabled) return;
this.trapHandoff = {
resume: !0,
weapon:
__mmTrapWeapon != null ? __mmTrapWeapon : __mmSelectedWeapon(),
hat:
__mmTrapHat != null
? __mmTrapHat
: __mmInstaSafeRestoreHat(__mmBushRestoreHat(v.skinIndex)),
};
(__mmTrapAttackActive || __mmActionOwner === "trapEscape") &&
__mmStopTrapAttack();
},
capture() {
const __mmCapturedHat =
this.trapHandoff && this.trapHandoff.hat != null
? this.trapHandoff.hat
: __mmBushRestoreHat(v.skinIndex);
this.snapshot = {
weapon:
this.trapHandoff && this.trapHandoff.weapon != null
? this.trapHandoff.weapon
: __mmSelectedWeapon(),
hat: __mmInstaSafeRestoreHat(__mmCapturedHat),
tail: __mmBushRestoreTail(v.tailIndex),
primaryHeld: __mmPrimaryHeld,
secondaryHeld: __mmSecondaryHeld,
heldPulse: !!__mmHeldAttackTimer,
movementGear: __mmMovementGearEnabled,
soldierAuto: __mmSoldierAutoEnabled,
autoHeal: __mmAutoHealEnabled,
};
},
nearestEnemy() {
if (__mmLiveStateFresh()) return __mmLiveState.nearestEnemy;
if (!v || !v.alive || !Array.isArray(E)) return null;
let __mmClosest = null;
let __mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
const __mmPlayer = E[__mmIndex];
if (
!__mmIsEnemyPlayer(__mmPlayer) ||
!Number.isFinite(Number(__mmPlayer.x)) ||
!Number.isFinite(Number(__mmPlayer.y))
)
continue;
const __mmDx = __mmPlayer.x - v.x;
const __mmDy = __mmPlayer.y - v.y;
const __mmDistance = __mmDx * __mmDx + __mmDy * __mmDy;
if (__mmDistance < __mmClosestDistance) {
__mmClosest = __mmPlayer;
__mmClosestDistance = __mmDistance;
}
}
return __mmClosest;
},
target() {
if (this.targetSid == null) return null;
let __mmTarget = null;
try {
__mmTarget = Rt(this.targetSid);
} catch (__mmLookupError) {}
if (!__mmTarget && Array.isArray(E)) {
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex += 1) {
const __mmPlayer = E[__mmIndex];
if (__mmPlayer && String(__mmPlayer.sid) === String(this.targetSid)) {
__mmTarget = __mmPlayer;
break;
}
}
}
return __mmTarget &&
String(__mmTarget.sid) === String(this.targetSid) &&
(__mmIsEnemyPlayer(__mmTarget) ||
(this.betrayal &&
__mmTarget !== v &&
__mmTarget.alive &&
__mmTarget.visible)) &&
Number.isFinite(Number(__mmTarget.x)) &&
Number.isFinite(Number(__mmTarget.y))
? __mmTarget
: null;
},
weaponData(__mmWeapon) {
return b && b.weapons && __mmWeapon != null ? b.weapons[__mmWeapon] : null;
},
supportedPrimary() {
if (!v || !v.alive || !v.weapons) return null;
const __mmWeapon = v.weapons[0];
if (
__mmWeapon !== __mmShortSword &&
__mmWeapon !== __mmKatana &&
__mmWeapon !== __mmPolearmWeapon
)
return null;
const __mmData = this.weaponData(__mmWeapon);
return __mmData &&
__mmData.projectile == null &&
__mmWeapon;
},
inRange(__mmWeapon, __mmTarget) {
const __mmData = this.weaponData(__mmWeapon);
const __mmRange = __mmData && Number(__mmData.range);
if (
!v ||
!__mmTarget ||
!Number.isFinite(__mmRange) ||
__mmRange <= 0
)
return !1;
const __mmReach =
(__mmRange +
(Number(v.scale) || 0) +
(Number(__mmTarget.scale) || 0)) *
__mmFullInstaRangeMultiplier;
return Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) <= __mmReach;
},
canFullBurst(__mmTarget) {
const __mmPrimary = this.supportedPrimary(),
__mmSecondary = v && v.weapons && v.weapons[1],
__mmSecondaryData = this.weaponData(__mmSecondary);
return !!(
__mmPrimary != null &&
__mmTarget &&
this.inRange(__mmPrimary, __mmTarget) &&
__mmSecondary != null &&
__mmSecondary !== __mmPrimary &&
__mmSecondary !== __mmShieldWeapon &&
__mmSecondaryData &&
!__mmSecondaryData.shield
);
},
fullBurstReady(
__mmTarget,
__mmProfile = "normal",
__mmBetrayal = !1,
__mmIgnoreShield = !1,
) {
if (
!v ||
!v.alive ||
!__mmTarget ||
!v.skins ||
!v.skins[7] ||
(!__mmBetrayal && !__mmIsEnemyPlayer(__mmTarget))
)
return !1;
if (!__mmIgnoreShield && !__mmShieldBypass(v, __mmTarget)) return !1;
const __mmPrimary = this.supportedPrimary();
if (
__mmPrimary == null ||
!this.inRange(__mmPrimary, __mmTarget) ||
!__mmWeaponReady(__mmPrimary)
)
return !1;
if (__mmProfile === "velTick" || __mmProfile === "autoPush")
return !!(
v.skins[__mmTurretGear] &&
this.turretReady()
);
const __mmSecondary = v.weapons && v.weapons[1],
__mmSecondaryData = this.weaponData(__mmSecondary);
if (
__mmSecondary == null ||
__mmSecondary === __mmPrimary ||
__mmSecondary === __mmShieldWeapon ||
!__mmSecondaryData ||
__mmSecondaryData.shield ||
!__mmWeaponReady(__mmSecondary)
)
return !1;
return __mmProfile === "polearmAids"
? !!v.skins[40]
: !!(
v.skins[__mmTurretGear] &&
this.turretReady()
);
},
aim(__mmTarget) {
return __mmTarget
? Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x)
: Ci();
},
projectileAim(__mmTarget) {
if (!__mmTarget || !v) return this.aim(__mmTarget);
const __mmWeaponData = b && b.weapons && b.weapons[__mmCrossbow],
__mmProjectile =
__mmWeaponData &&
b.projectiles &&
b.projectiles[__mmWeaponData.projectile],
__mmSpeed = Number(__mmProjectile && __mmProjectile.speed),
__mmDistance = Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y),
__mmTravelMs =
(Number.isFinite(__mmSpeed) && __mmSpeed > 0
? __mmDistance / __mmSpeed
: 0) +
Math.min(55, __mmServerTickMs() * 0.5);
return __mmSyncAimAngle(__mmTarget, __mmTravelMs);
},
launchDelay() {
const __mmPing = Number(window.pingTime),
__mmOneWayPing = Number.isFinite(__mmPing)
? Math.max(0, __mmPing / 2)
: 0;
// The boost pad must reach the server before the Crossbow phase. Aim for the
// following server phase, compensated by one-way latency, instead of the old
// 5ms ambush shortcut that could fire before the boost existed.
return Math.max(
12,
Math.min(
__mmServerTickMs(),
Math.round(__mmServerTickMs() - Math.min(70, __mmOneWayPing)),
),
);
},
damageTail() {
if (!v || !v.alive) return null;
if (v.tails && v.tails[__mmCorruptXWings]) return __mmCorruptXWings;
return (this.snapshot && this.snapshot.tail === 11) || v.tailIndex === 11
? 0
: null;
},
preparePostSpike(__mmTarget) {
if (!this.postSpikeEnabled || !__mmTarget || !v || !v.alive) return null;
this.postSpikeTarget = {
x: Number(__mmTarget.x),
y: Number(__mmTarget.y),
scale: Number(__mmTarget.scale) || 35,
sid: __mmTarget.sid,
};
const __mmSpike = __mmSpikeItem();
if (
__mmSpike == null ||
__mmHoldingMcGrabby() ||
!__mmAutoSpikeSpamHasCapacity(__mmSpike)
)
return null;
let __mmCandidate = __mmAutoSpikeSpamCandidate(
{ enemy: __mmTarget, trap: null },
__mmSpike,
);
if (__mmCandidate) __mmCandidate.contactRequired = !0;
if (!__mmCandidate) {
const __mmData = b && b.list && b.list[__mmSpike],
__mmSpikeScale = Number(__mmData && __mmData.scale) || 49,
__mmPlacementRadius =
(Number(v.scale) || 35) +
__mmSpikeScale +
(Number(__mmData && __mmData.placeOffset) || 0),
__mmBaseAngle = Math.atan2(
Number(__mmTarget.y) - Number(v.y),
Number(__mmTarget.x) - Number(v.x),
);
// If a touching slot is impossible, search the entire legal placement
// ring. Target-facing positions stay first, followed by increasingly
// wider offsets, so a Hammer Insta still puts down the closest useful
// spike instead of silently doing nothing.
for (let __mmStep = 0; __mmStep <= 36 && !__mmCandidate; __mmStep++) {
const __mmOffset = (__mmStep * Math.PI) / 36,
__mmSigns = __mmStep === 0 || __mmStep === 36 ? [1] : [1, -1];
for (
let __mmSignIndex = 0;
__mmSignIndex < __mmSigns.length;
__mmSignIndex++
) {
const __mmAngle = __mmBaseAngle + __mmOffset * __mmSigns[__mmSignIndex],
__mmX = Number(v.x) + Math.cos(__mmAngle) * __mmPlacementRadius,
__mmY = Number(v.y) + Math.sin(__mmAngle) * __mmPlacementRadius;
if (!__mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale))
continue;
__mmCandidate = {
item: __mmSpike,
x: __mmX,
y: __mmY,
angle: __mmAngle,
scale: __mmSpikeScale,
targetSid: __mmTarget.sid,
contactRequired: !1,
};
break;
}
}
}
if (__mmCandidate) {
((__mmCandidate.mode = "hammerInsta"),
(__mmCandidate.intentReady = !0),
(this.postSpikeCandidate = __mmCandidate),
(this.postSpikeCalculatedAt = Date.now()));
} else {
((this.postSpikeCandidate = null), (this.postSpikeCalculatedAt = 0));
}
return this.postSpikeCandidate;
},
placePostSpike(__mmTarget) {
if (!this.postSpikeEnabled || !__mmTarget || !v || !v.alive) return !1;
// Refresh synchronously in the final combo phase. Earlier phases have
// already warmed the solver, so this adds no timer or acknowledgement wait.
this.preparePostSpike(__mmTarget);
const __mmCandidate = this.postSpikeCandidate,
__mmData =
__mmCandidate && b && b.list && b.list[__mmCandidate.item];
if (
!__mmCandidate ||
!__mmData ||
Date.now() - this.postSpikeCalculatedAt > this.normalStageMs() * 2 ||
!__mmAutoSpikeSpamHasCapacity(__mmCandidate.item)
)
return !1;
const __mmSpikeScale = Number(__mmData.scale) || __mmCandidate.scale || 49,
__mmPlacementRadius =
(Number(v.scale) || 35) +
__mmSpikeScale +
(Number(__mmData.placeOffset) || 0),
__mmX = Number(v.x) + Math.cos(__mmCandidate.angle) * __mmPlacementRadius,
__mmY = Number(v.y) + Math.sin(__mmCandidate.angle) * __mmPlacementRadius,
__mmTouchRadius =
(Number(__mmTarget.scale) || 35) + __mmSpikeScale,
__mmTargetDistance = Math.hypot(
Number(__mmTarget.x) - __mmX,
Number(__mmTarget.y) - __mmY,
);
if (
(__mmCandidate.contactRequired &&
(__mmTargetDistance > __mmTouchRadius + 5 ||
__mmTargetDistance < __mmTouchRadius - 12)) ||
!__mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale)
)
return !1;
try {
if (
!__mmInstaPlaceAndReselect(
__mmCandidate.item,
__mmCandidate.angle,
this.primaryWeapon,
)
)
return !1;
(O.send("D", __mmCandidate.angle),
__mmAutoSpikeSpamReservations.push({
item: __mmCandidate.item,
x: __mmX,
y: __mmY,
scale: __mmSpikeScale,
expiresAt: Date.now() + 650,
}),
(__mmAutoSpikeSpamLastAt = Date.now()));
return !0;
} catch (__mmHammerInstaSpikeError) {
return !1;
}
},
context(__mmRequireRange) {
if (
(!__mmInstaUiEnabled && !this.automatic) ||
!this.runtimeReady() ||
this.isPriorityConflict()
)
return null;
const __mmPrimary = this.supportedPrimary();
if (__mmPrimary == null) return null;
const __mmTarget = this.target();
if (!__mmTarget && !this.targetOptional) return null;
if (__mmRequireRange && __mmTarget && !this.inRange(__mmPrimary, __mmTarget))
return null;
return { primary: __mmPrimary, target: __mmTarget };
},
selectDamageGear() {
if (!v || !v.alive) return;
// Dispatch both equipment packets from this same local/server-tick phase.
__mmEquipGearPair(
v.skins && v.skins[7] ? 7 : null,
this.damageTail(),
!0,
);
},
selectSecondaryDamageGear() {
if (!v || !v.alive) return;
// Re-send the damage tail in the exact Turret packet phase too. This keeps
// the secondary stage paired even if the Bull-stage acknowledgement has
// not reached the client yet.
const __mmHat =
this.profile === "polearmAids" && v.skins && v.skins[40]
? 40
: v.skins && v.skins[__mmTurretGear]
? __mmTurretGear
: null;
(__mmEquipGearPair(
__mmHat,
this.damageTail(),
!0,
),
__mmHat === __mmTurretGear && __mmAssumeTurretGearShot());
},
turretReady() {
return !!(
v &&
v.alive &&
v.skins &&
v.skins[__mmTurretGear] &&
__mmTurretCooldownRemaining(v, Date.now()) <= 0
);
},
turretInRange(__mmTarget) {
if (!v || !__mmTarget) return !1;
const __mmReach =
__mmTurretGearRange +
(Number(v.scale) || 0) +
(Number(__mmTarget.scale) || 0);
return Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) <= __mmReach;
},
finishTurretPoke() {
this.state === "turretPoke" && this.cleanup("turret-poke-complete");
},
startTurretPoke(__mmTarget) {
if (
!this.turretReady() ||
!__mmTarget ||
!__mmShieldBypass(v, __mmTarget)
)
return !1;
this.state = "turretPoke";
this.popupShown = !0;
__mmShowInstaTypePopup("Turret Poke");
(__mmEquipHatNow(__mmTurretGear), __mmAssumeTurretGearShot());
// Keep the game's aim direction on the distant target while Turret Gear
// is active. Turret Gear fires on its own cooldown; no normal attack is
// sent in this out-of-melee-range branch.
try {
O.send("D", this.aim(__mmTarget));
} catch (__mmTurretAimError) {}
// This is a best-effort troll shot: no weapon/loadout or distance gate and
// no server acknowledgement wait. Restore on the next local server tick.
this.schedule(() => this.finishTurretPoke());
return !0;
},
start(__mmOptions = {}) {
if (this.state !== "idle") return !1;
const __mmRequestedProfile = String(__mmOptions.profile || "normal"),
__mmAutomatic = !!__mmOptions.automatic,
__mmManualHotkey = !!__mmOptions.manualHotkey,
__mmNow = Date.now();
let __mmPreflightTarget = null;
try {
__mmPreflightTarget =
__mmOptions.targetSid == null
? this.nearestEnemy()
: Rt(__mmOptions.targetSid);
} catch (__mmPreflightTargetError) {}
// Revalidate at the one point that can actually claim the Insta. Earlier
// scanners may have observed a ready weapon a few milliseconds before a
// swing/reload packet changed it. Failed automatic attempts are briefly
// latched so 5 ms automation loops cannot spam the start path.
if (
__mmAutomatic &&
(__mmNow < this.automaticRetryUntil ||
!this.fullBurstReady(
__mmPreflightTarget,
__mmRequestedProfile,
!!__mmOptions.betrayal,
))
) {
this.automaticRetryUntil = Math.max(
this.automaticRetryUntil,
__mmNow + Math.max(120, this.tick()),
);
return !1;
}
if (__mmManualHotkey) __mmCancelScheduledSyncInsta();
else if (
!__mmOptions.syncScheduled &&
__mmTryScheduleSharedInsta(__mmOptions)
)
return !0;
this.cancelHatRestore();
// A real R burst has priority over a scheduled friendly-shot sync and idle
// reloading, but never steals selection from an emergency action.
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
this.suspendTrapEscape();
const __mmHeldAttackSuspended = __mmManualHotkey
? __mmSuspendHeldAttackForManualInsta()
: !1;
if (
!__mmActionClaim(
"insta",
__mmOptions.betrayal
? "betrayal combo"
: __mmOptions.automatic
? "auto target"
: "R combo",
)
) {
const __mmResumeTrap = !!(
this.trapHandoff &&
this.trapHandoff.resume &&
v &&
v.alive &&
__mmIsTrapped()
);
this.trapHandoff = null;
__mmResumeTrap && __mmBreakTrap();
__mmHeldAttackSuspended &&
(__mmPrimaryHeld || __mmSecondaryHeld) &&
(__mmActionClaim("manualAttack", "resume after blocked R Insta"),
__mmResumeHeldAttack());
return !1;
}
__mmCancelCombatHatLock(!1);
this.state = "validate";
this.targetOptional = !!__mmOptions.targetOptional;
this.automatic = !!__mmOptions.automatic;
this.betrayal = !!__mmOptions.betrayal;
this.manualHotkey = __mmManualHotkey;
this.bowUpgradeFollowup = !!__mmOptions.bowUpgradeFollowup;
this.profile = __mmRequestedProfile;
this.profileSource = String(__mmOptions.profileSource || this.profile);
this.popupShown = !1;
if (!this.runtimeReady()) return (this.cleanup("runtime-unavailable"), !1);
this.capture();
const __mmRequestedTarget =
__mmOptions.targetSid == null ? null : Rt(__mmOptions.targetSid),
__mmTarget =
__mmRequestedTarget &&
(__mmIsEnemyPlayer(__mmRequestedTarget) ||
(this.betrayal &&
__mmRequestedTarget !== v &&
__mmRequestedTarget.alive &&
__mmRequestedTarget.visible))
? __mmRequestedTarget
: this.betrayal
? null
: this.nearestEnemy();
if (__mmTarget) this.targetSid = __mmTarget.sid;
this.postSpikeEnabled = !!(
__mmTarget &&
v.weapons &&
Number(v.weapons[1]) === __mmGreatHammer
);
this.postSpikeCandidate = null;
this.postSpikeCalculatedAt = 0;
this.postSpikeTarget = null;
this.postSpikeEnabled && this.preparePostSpike(__mmTarget);
const __mmPrimary = this.supportedPrimary(),
__mmTargetInPrimaryRange = !!(
__mmTarget &&
__mmPrimary != null &&
this.inRange(__mmPrimary, __mmTarget)
);
// Manual R keeps the intentional out-of-range Turret poke, but an in-range
// full combo does not arm unless every weapon and combat hat is ready.
if (
__mmTargetInPrimaryRange &&
!this.fullBurstReady(
__mmTarget,
this.profile,
this.betrayal,
!this.automatic,
)
)
return (this.cleanup("kit-not-ready"), !1);
if (
!this.automatic &&
!this.betrayal &&
__mmInstaUiEnabled &&
__mmTarget &&
!this.canFullBurst(__mmTarget) &&
this.startTurretPoke(__mmTarget)
)
return !0;
const __mmContext = this.context(!1);
if (!__mmContext) return (this.cleanup("validation-failed"), !1);
this.primaryWeapon = __mmContext.primary;
this.preparePostSpike(__mmContext.target);
this.state = "arm";
this.arm();
return !0;
},
canAutoStart(__mmIgnoreAutoToggle = !1) {
if (
(!__mmIgnoreAutoToggle && !__mmAutoInstaEnabled) ||
this.state !== "idle" ||
Date.now() < this.automaticRetryUntil ||
!this.runtimeReady() ||
this.isPriorityConflict()
)
return !1;
return this.fullBurstReady(this.nearestEnemy(), "normal", !1);
},
arm() {
const __mmContext = this.context(!1);
if (!__mmContext) return void this.cleanup("arm-invalid");
this.primaryWeapon = __mmContext.primary;
// Do not change gear until the target is actually in reach.
this.state = "waitForRange";
this.waitForRange();
},
waitForRange() {
if (this.state !== "waitForRange") return;
const __mmContext = this.context(!1);
if (!__mmContext) return void this.cleanup("target-or-state-lost");
this.primaryWeapon = __mmContext.primary;
if (__mmContext.target && !this.inRange(__mmContext.primary, __mmContext.target))
return void (
this.startTurretPoke(__mmContext.target) ||
this.cleanup("out-of-range")
);
if (__mmContext.target && !__mmShieldBypass(v, __mmContext.target)) {
this.shieldWaitStartedAt || (this.shieldWaitStartedAt = Date.now());
if (
Date.now() - this.shieldWaitStartedAt >
Math.max(900, this.tick() * 6)
)
return void this.cleanup("shield-timeout");
try {
(je(__mmContext.primary, !0),
O.send("D", this.aim(__mmContext.target)));
} catch (__mmShieldWaitAimError) {}
return void this.schedule(
() => this.waitForRange(),
Math.max(10, Math.min(35, __mmFastCheckMs())),
);
}
this.shieldWaitStartedAt = 0;
// Use a one-stage setup: aim now, then start Bull + primary
// after its 120 ms opening delay. The distant Turret poke remains separate.
this.state = "executeBurst";
try {
// Hold main throughout setup instead of switching only when the attack
// packet is emitted. The combo snapshot still restores the old tool.
(je(__mmContext.primary, !0),
O.send("D", this.aim(__mmContext.target)));
} catch (__mmInstaSetupAimError) {}
this.schedule(() => this.executeBurst(), this.openingDelay());
},
releaseAttack() {
this.releaseTimer && clearTimeout(this.releaseTimer);
this.releaseTimer = 0;
if (!this.attackHeld) return;
try {
O && O.send && O.send("F", 0, null);
} catch (__mmReleaseError) {}
this.attackHeld = !1;
},
sendAttack(__mmItem, __mmIsWeapon, __mmTarget) {
if (!v || !v.alive || __mmItem == null) return !1;
this.releaseAttack();
try {
const __mmAngle = this.aim(__mmTarget);
je(__mmItem, !!__mmIsWeapon);
O.send("F", 1, __mmAngle);
this.attackHeld = !0;
return !0;
} catch (__mmAttackError) {
this.attackHeld = !1;
return !1;
}
},
executeBurst() {
if (this.state !== "executeBurst") return;
const __mmContext = this.context(!0);
if (!__mmContext)
return void this.cleanup("primary-unavailable");
if (__mmContext.target && !__mmShieldBypass(v, __mmContext.target)) {
this.state = "waitForRange";
return void this.waitForRange();
}
if (!this.popupShown) {
this.popupShown = !0;
__mmShowInstaTypePopup(
__mmInstaPopupLabel(this.profile, this.automatic, this.betrayal),
);
}
this.preparePostSpike(__mmContext.target);
if (this.profile === "velTick") {
if (!this.turretReady())
return void this.cleanup("veltick-turret-unavailable");
this.selectSecondaryDamageGear();
try {
(O.send("D", this.aim(__mmContext.target)),
je(__mmContext.primary, !0));
} catch (__mmVelTickOpeningError) {
return void this.cleanup("veltick-opening-failed");
}
this.schedule(() => this.executeFollowup(), this.tick());
return;
}
if (this.profile === "autoPush") {
this.selectDamageGear();
if (!this.sendAttack(__mmContext.primary, !0, __mmContext.target))
return void this.cleanup("auto-push-primary-send-failed");
this.scheduleRelease();
this.schedule(() => this.executeFollowup(), this.tick());
return;
}
if (this.reverseProfile()) {
const __mmSecondary = this.secondaryFollowup();
if (
__mmSecondary == null ||
!__mmWeaponReady(__mmSecondary) ||
!this.inRange(__mmSecondary, __mmContext.target)
)
return void this.cleanup("reverse-secondary-unavailable");
this.pendingSecondaryWeapon = __mmSecondary;
this.selectSecondaryDamageGear();
if (!this.sendAttack(__mmSecondary, !0, __mmContext.target))
return void this.cleanup("reverse-secondary-send-failed");
((this.pendingSecondaryWeapon = null),
this.scheduleRelease(),
this.schedule(
() => this.executeFollowup(),
this.profileStep(__mmContext.target, __mmSecondary),
));
return;
}
// Combo stage one: Bull + primary, with a short tap instead of a
// full-tick held attack.
this.selectDamageGear();
if (!this.sendAttack(__mmContext.primary, !0, __mmContext.target))
return void this.cleanup("primary-send-failed");
this.scheduleRelease();
this.schedule(() => this.executeFollowup(), this.normalStageMs());
},
secondaryFollowup() {
if (!v || !v.weapons) return null;
const __mmWeapon = v.weapons[1],
__mmData = this.weaponData(__mmWeapon);
return __mmWeapon != null &&
__mmWeapon !== this.primaryWeapon &&
__mmWeapon !== __mmShieldWeapon &&
__mmData &&
!__mmData.shield
? __mmWeapon
: null;
},
executeFollowup() {
if (this.state !== "executeBurst") return;
// Combo stage two: release the primary, then switch Turret gear and
// the secondary in the same phase before firing its 25 ms tap.
this.releaseAttack();
// The opening hit may knock the target out of primary melee range. Keep
// the confirmed target but let the equipped secondary make its own shot.
const __mmContext = this.context(!1);
if (!__mmContext) return void this.cleanup("followup-invalid");
this.preparePostSpike(__mmContext.target);
if (this.profile === "autoPush") {
if (!this.turretReady())
return void this.cleanup("auto-push-turret-unavailable");
this.selectSecondaryDamageGear();
try {
(O.send("D", this.aim(__mmContext.target)),
je(__mmContext.primary, !0));
} catch (__mmAutoPushTurretError) {
return void this.cleanup("auto-push-turret-failed");
}
this.schedule(() => this.finishNormalBurst(), this.tick());
return;
}
if (this.profile === "velTick") {
if (
!__mmWeaponReady(__mmContext.primary) ||
!this.inRange(__mmContext.primary, __mmContext.target)
)
return void this.cleanup("veltick-primary-unavailable");
this.selectDamageGear();
if (!this.sendAttack(__mmContext.primary, !0, __mmContext.target))
return void this.cleanup("veltick-primary-send-failed");
(this.scheduleRelease(),
this.schedule(() => this.finishNormalBurst(), this.tick()));
return;
}
if (this.reverseProfile()) {
if (
!__mmWeaponReady(__mmContext.primary) ||
!this.inRange(__mmContext.primary, __mmContext.target)
)
return void this.cleanup("reverse-primary-unavailable");
this.selectDamageGear();
if (!this.sendAttack(__mmContext.primary, !0, __mmContext.target))
return void this.cleanup("reverse-primary-send-failed");
(this.scheduleRelease(),
this.schedule(() => this.finishNormalBurst(), this.tick()));
return;
}
const __mmSecondary = this.secondaryFollowup();
if (
__mmSecondary == null ||
!__mmWeaponReady(__mmSecondary) ||
!this.turretReady()
)
return void this.cleanup("secondary-or-turret-unavailable");
this.pendingSecondaryWeapon = __mmSecondary;
__mmSmartPlaceUtilityForInsta(__mmContext.target, __mmSecondary);
this.selectSecondaryDamageGear();
try {
O.send("D", this.aim(__mmContext.target));
} catch (__mmSecondaryAimError) {}
if (!this.sendAttack(__mmSecondary, !0, __mmContext.target))
return void this.cleanup("secondary-send-failed");
((this.pendingSecondaryWeapon = null),
this.scheduleRelease(),
this.schedule(() => this.finishNormalBurst(), this.normalStageMs()));
},
finishNormalBurst() {
if (this.state !== "executeBurst") return;
this.releaseAttack();
if (!v || !v.alive || this.primaryWeapon == null)
return void this.cleanup("finish-context-lost");
const __mmTarget = this.target() || this.postSpikeTarget;
__mmTarget && this.placePostSpike(__mmTarget);
if (this.bowUpgradeFollowup) {
// The Bow was the normal Insta's secondary shot. Keep Turret Gear, the
// target direction, and the projectile weapon channel intact; cleanup
// hands directly to Crossbow instead of visibly restoring Soldier/main.
this.state = "soldier";
this.schedule(
() => this.cleanup("complete"),
Math.max(4, Math.min(10, __mmFastCheckMs())),
);
return;
}
// Combo stage three: Soldier and the primary are selected together. Kitty
// gives that visible settle stage 170 ms before restoring the loadout.
this.state = "soldier";
__mmEquipGearPair(
v.skins && v.skins[6]
? 6
: this.snapshot && this.snapshot.hat,
this.damageTail(),
!0,
);
je(this.primaryWeapon, !0);
this.schedule(() => this.cleanup("complete"), Math.max(170, this.tick()));
},
cleanup(__mmReason) {
const __mmSnapshot = this.snapshot,
__mmCompletedFullInsta = __mmReason === "complete",
__mmBowFollowupTarget = __mmCompletedFullInsta && this.bowUpgradeFollowup
? this.target()
: null,
__mmChainBowUpgrade = !!(
__mmBowFollowupTarget &&
__mmBowUpgradeInsta.ready(__mmBowFollowupTarget, !0)
),
__mmRestore = __mmActionMayRestore("insta"),
__mmResumeTrap = !!(
this.trapHandoff &&
this.trapHandoff.resume &&
__mmTrapEscapeEnabled &&
v &&
v.alive &&
__mmIsTrapped()
);
this.state = "cleanup";
this.timer && clearTimeout(this.timer);
this.timer = 0;
this.releaseTimer && clearTimeout(this.releaseTimer);
this.releaseTimer = 0;
this.releaseAttack();
__mmCompletedFullInsta &&
!__mmChainBowUpgrade &&
__mmSnapshot &&
__mmPreferWeaponRechargeRestore(__mmSnapshot.weapon);
const __mmSafeRestoreHat = __mmSnapshot
? __mmInstaSafeRestoreHat(__mmSnapshot.hat)
: __mmInstaSafeRestoreHat(__mmLastNormalHat);
if (
!__mmChainBowUpgrade &&
v &&
v.alive &&
__mmSnapshot &&
__mmRestore
) {
__mmEquipGearPair(__mmSafeRestoreHat, __mmSnapshot.tail, !0);
this.scheduleHatRestore(__mmSafeRestoreHat);
__mmSnapshot.weapon != null && __mmRestoreWeapon(__mmSnapshot.weapon);
(__mmSnapshot.primaryHeld || __mmSnapshot.secondaryHeld) &&
(__mmPrimaryHeld || __mmSecondaryHeld) &&
__mmResumeHeldAttack();
}
// If a higher-priority safety action preempted the combo, defer instead of
// abandoning the cleanup. The restore worker waits until that owner yields.
!__mmChainBowUpgrade &&
v &&
v.alive &&
(!__mmRestore || __mmTemporaryCombatHat(v.skinIndex)) &&
this.scheduleHatRestore(__mmSafeRestoreHat);
this.snapshot = null;
this.targetSid = null;
this.targetOptional = !1;
this.automatic = !1;
this.betrayal = !1;
this.manualHotkey = !1;
this.bowUpgradeFollowup = !1;
this.primaryWeapon = null;
this.pendingSecondaryWeapon = null;
this.trapHandoff = null;
this.postSpikeEnabled = !1;
this.postSpikeCandidate = null;
this.postSpikeCalculatedAt = 0;
this.postSpikeTarget = null;
this.profile = "normal";
this.profileSource = "R";
this.popupShown = !1;
this.shieldWaitStartedAt = 0;
this.reason = __mmReason || "cancelled";
this.state = "idle";
!__mmCompletedFullInsta &&
(this.automaticRetryUntil = Math.max(
this.automaticRetryUntil,
Date.now() + Math.max(120, this.tick()),
));
__mmActionRelease("insta", this.reason);
if (__mmChainBowUpgrade) {
const __mmChained = __mmBowUpgradeInsta.start(
__mmBowFollowupTarget,
"normal insta follow-up",
{
skipBow: !0,
restoreTool:
__mmSnapshot && __mmSnapshot.weapon != null
? { item: __mmSnapshot.weapon, weapon: !0 }
: null,
restoreHat: __mmSafeRestoreHat,
},
);
if (__mmChained) return;
// A safety state can appear between the final melee hit and this local
// handoff. If so, perform the ordinary Insta restore instead of leaving
// Turret/Soldier or the borrowed tool equipped.
if (v && v.alive && __mmSnapshot && __mmRestore) {
(__mmEquipGearPair(__mmSafeRestoreHat, __mmSnapshot.tail, !0),
this.scheduleHatRestore(__mmSafeRestoreHat),
__mmSnapshot.weapon != null && __mmRestoreWeapon(__mmSnapshot.weapon));
}
}
__mmCompletedFullInsta && __mmInstaChatEnabled && __mmSendChat("Meow!");
// These loops were gated while the burst owned gear/selection. Run their
// normal updates now instead of changing their user-configured toggles.
if (v && v.alive) {
__mmResumeTrap && __mmBreakTrap();
__mmUpdateMovementGear();
__mmUpdateSoldier();
__mmUpdateWeaponRecharge();
__mmAutoHeal();
}
},
cancel(__mmReason) {
this.cleanup(__mmReason || "cancelled");
},
};
const __mmBoostInsta = {
state: "idle",
timer: 0,
loop: 0,
targetSid: null,
primaryWeapon: null,
snapshot: null,
attackHeld: !1,
aimAngle: null,
moveAngle: null,
startedAt: 0,
ambush: !1,
manualBush: !1,
shieldWaitStartedAt: 0,
isActive() {
return this.state !== "idle" && this.state !== "cleanup";
},
target() {
if (this.targetSid == null) return null;
let __mmTarget = null;
try {
__mmTarget = Rt(this.targetSid);
} catch (__mmBoostTargetError) {}
return __mmIsEnemyPlayer(__mmTarget) ? __mmTarget : null;
},
trueMeleeRange(__mmTarget) {
const __mmData =
b && b.weapons && this.primaryWeapon != null
? b.weapons[this.primaryWeapon]
: null;
return __mmData && __mmTarget
? (Number(__mmData.range) || 0) +
(Number(v.scale) || 35) +
(Number(__mmTarget.scale) || 35)
: 0;
},
aim(__mmTarget) {
return __mmTarget
? Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x)
: Ci();
},
setMovement(__mmAngle) {
if (!Number.isFinite(__mmAngle)) return;
const __mmDifference =
this.moveAngle == null
? Infinity
: Math.abs(
Math.atan2(
Math.sin(__mmAngle - this.moveAngle),
Math.cos(__mmAngle - this.moveAngle),
),
);
if (__mmDifference < 0.035) return;
((this.moveAngle = __mmAngle), (Kt = __mmAngle), O.send("9", __mmAngle));
},
stopMovement() {
if (this.moveAngle == null) return;
((this.moveAngle = null), (Kt = null), O.send("9", null));
},
releaseAttack() {
if (!this.attackHeld) return;
(O.send(
"F",
0,
Number.isFinite(this.aimAngle) ? this.aimAngle : null,
),
(this.attackHeld = !1));
},
schedule(__mmCallback, __mmDelay = __mmServerTickMs()) {
this.timer && clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.timer = 0;
__mmCallback();
}, __mmDelay);
},
requirements(__mmTarget, __mmAllowAmbush = !1) {
const __mmPrimary = __mmInsta.supportedPrimary(),
__mmPad = __mmBoostPadItem(),
__mmCrossbowData = b && b.weapons && b.weapons[__mmCrossbow],
__mmProjectile =
__mmCrossbowData &&
b.projectiles &&
b.projectiles[__mmCrossbowData.projectile],
__mmMaximumRange =
Number(__mmProjectile && __mmProjectile.range) || 1200;
if (
(!__mmInstaUiEnabled && !__mmAllowAmbush) ||
!__mmInsta.runtimeReady() ||
!v ||
!v.alive ||
!__mmTarget ||
__mmPrimary == null ||
!v.weapons ||
Number(v.weapons[1]) !== __mmCrossbow ||
!__mmWeaponReady(__mmPrimary) ||
!__mmWeaponReady(__mmCrossbow) ||
!__mmShieldBypass(v, __mmTarget) ||
!v.skins ||
!v.skins[7] ||
!v.skins[__mmTurretGear] ||
!__mmInsta.turretReady() ||
__mmPad == null ||
!__mmCanUseBuildItem(__mmPad) ||
__mmMaxBuildCount(__mmPad) < 1 ||
__mmIsTrapped() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
Date.now() < __mmAntiInstaUntil ||
__mmInsta.isEmergencyHealth() ||
Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) >
__mmMaximumRange + (Number(v.scale) || 35)
)
return null;
return { primary: __mmPrimary, crossbow: __mmCrossbow, pad: __mmPad };
},
start(__mmOptions = {}) {
if (
this.state !== "idle" ||
__mmInsta.isActive() ||
(__mmOptions.automatic && !__mmAutoInstaEnabled)
)
return !1;
let __mmRequestedTarget = null;
try {
__mmRequestedTarget =
__mmOptions.targetSid == null ? null : Rt(__mmOptions.targetSid);
} catch (__mmBoostRequestedTargetError) {}
const __mmTarget = __mmIsEnemyPlayer(__mmRequestedTarget)
? __mmRequestedTarget
: __mmInsta.nearestEnemy(),
__mmKit = this.requirements(__mmTarget, !!__mmOptions.ambush);
if (!__mmKit || !__mmActionCanPreempt("boostInsta")) return !1;
(__mmActionOwner === "instaSync" && __mmStopInstaSync(),
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmActionOwner === "matThief" &&
__mmFinishMatThief("boost insta"),
__mmActionOwner === "mobSteal" && __mmFinishMobSteal("boost insta"),
__mmBoostBreakHeld && __mmStopBoostBreak());
if (!__mmActionClaim("boostInsta", "crossbow boost combo")) return !1;
__mmCancelCombatHatLock(!1);
const __mmAngle = this.aim(__mmTarget);
((this.ambush = !!__mmOptions.ambush),
(this.manualBush = !!(__mmOptions.manualBush && this.ambush)),
(this.state = "boost"),
(this.targetSid = __mmTarget.sid),
(this.primaryWeapon = __mmKit.primary),
(this.snapshot = {
weapon: __mmSelectedTool(),
hat: __mmInstaSafeRestoreHat(__mmBushRestoreHat(v.skinIndex)),
tail: __mmBushRestoreTail(v.tailIndex),
}),
(this.startedAt = Date.now()),
(this.aimAngle = __mmAngle),
(this.loop = setInterval(() => this.update(), __mmFastCheckMs())));
__mmShowInstaTypePopup(this.ambush ? "Bush Boost Insta" : "Boost Insta");
// Snapshot first, then preselect main before any boost/build packet. This
// keeps the primary loaded through setup while cleanup can still restore
// whatever tool the player had selected before the Insta.
(je(__mmKit.primary, !0),
O.send("D", __mmAngle),
__mmInstaPlaceAndReselect(__mmKit.pad, __mmAngle, __mmKit.primary),
this.setMovement(__mmAngle),
this.schedule(
() => this.fireCrossbow(),
this.launchDelay(),
));
this.ambush &&
!this.manualBush &&
__mmBushChatEnabled &&
__mmSendChat("SURPRISE!!!");
return !0;
},
fireCrossbow() {
if (this.state !== "boost") return;
const __mmTarget = this.target();
if (!__mmTarget || !__mmWeaponReady(__mmCrossbow))
return void this.cleanup("crossbow unavailable");
if (!__mmShieldBypass(v, __mmTarget)) {
this.shieldWaitStartedAt || (this.shieldWaitStartedAt = Date.now());
if (Date.now() - this.shieldWaitStartedAt > 650)
return void this.cleanup("shield-timeout");
this.aimAngle = this.aim(__mmTarget);
O.send("D", this.aimAngle);
return void this.schedule(
() => this.fireCrossbow(),
Math.max(10, Math.min(35, __mmFastCheckMs())),
);
}
this.shieldWaitStartedAt = 0;
const __mmAngle = this.projectileAim(__mmTarget);
((this.state = "crossbow"),
(this.aimAngle = __mmAngle),
O.send("D", __mmAngle),
__mmSmartPlaceUtilityForInsta(__mmTarget, __mmCrossbow),
__mmEquipGearPair(
__mmTurretGear,
__mmInsta.damageTail(),
!0,
),
__mmAssumeTurretGearShot(),
je(__mmCrossbow, !0),
O.send("F", 1, __mmAngle),
(this.attackHeld = !0),
this.schedule(() => {
if (this.state !== "crossbow") return;
this.releaseAttack();
((this.state = "chase"), this.update());
}));
},
update() {
if (!this.isActive()) return;
const __mmTarget = this.target();
if (
!v ||
!v.alive ||
!__mmTarget ||
Date.now() - this.startedAt > 3200
)
return void this.cleanup("target or boost timeout");
const __mmAngle = this.aim(__mmTarget),
__mmDistance = Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y);
this.aimAngle = __mmAngle;
// Boost movement begins before the projectile phase and stays locked to
// the live target through Crossbow and chase for one seamless approach.
this.setMovement(__mmAngle);
if (
this.state === "chase" &&
__mmDistance <= this.trueMeleeRange(__mmTarget) &&
__mmWeaponReady(this.primaryWeapon)
)
this.firePrimary(__mmTarget);
},
firePrimary(__mmTarget) {
if (this.state !== "chase" || !__mmTarget) return;
const __mmAngle = this.aim(__mmTarget);
// Solve the optional finisher spike before the swing packet so a legal
// contact/knockback slot and Bull + primary reach the same server phase.
const __mmSpike =
!__mmHoldingMcGrabby() && !__mmEmergencyGetawayActive()
? __mmSpikeItem()
: null,
__mmSpikeCandidates =
__mmSpike != null &&
__mmCanUseBuildItem(__mmSpike) &&
__mmMaxBuildCount(__mmSpike) > 0
? __mmBoostSpikePlacementCandidates(__mmTarget, __mmSpike, Date.now())
: [],
__mmFinisherSpike = __mmSpikeCandidates.length
? __mmSmartBestCombination(__mmSpikeCandidates, 1)[0]
: null;
(this.stopMovement(),
(this.state = "primary"),
(this.aimAngle = __mmAngle),
O.send("D", __mmAngle),
__mmFinisherSpike &&
__mmSmartPlaceNow(__mmFinisherSpike, __mmSelectedTool()),
__mmEquipGearPair(7, __mmInsta.damageTail(), !0),
je(this.primaryWeapon, !0),
O.send("F", 1, __mmAngle),
(this.attackHeld = !0),
this.schedule(() => this.cleanup("complete")));
},
cleanup(__mmReason) {
if (this.state === "idle") return;
const __mmCompleted = __mmReason === "complete",
__mmWasAmbush = this.ambush,
__mmWasManualBush = this.manualBush,
__mmSnapshot = this.snapshot,
__mmRestore = __mmActionMayRestore("boostInsta");
this.state = "cleanup";
(this.timer && clearTimeout(this.timer),
(this.timer = 0),
this.loop && clearInterval(this.loop),
(this.loop = 0),
this.releaseAttack(),
this.stopMovement());
__mmCompleted &&
__mmSnapshot &&
__mmPreferWeaponRechargeRestore(__mmSnapshot.weapon);
if (__mmRestore && v && v.alive && __mmSnapshot) {
(__mmEquipGearPair(__mmSnapshot.hat, __mmSnapshot.tail, !0),
__mmSnapshot.weapon != null && __mmRestoreTool(__mmSnapshot.weapon));
}
((this.targetSid = null),
(this.primaryWeapon = null),
(this.snapshot = null),
(this.aimAngle = null),
(this.startedAt = 0),
(this.shieldWaitStartedAt = 0),
(this.ambush = !1),
(this.manualBush = !1),
(this.state = "idle"),
__mmActionRelease("boostInsta", __mmReason || "cancelled"),
__mmScheduleMouseAimReturn(),
typeof Tt === "function" && Tt(),
__mmCompleted &&
(!__mmWasAmbush || __mmWasManualBush) &&
__mmInstaChatEnabled &&
__mmSendChat("Meow!"),
v && v.alive &&
(__mmUpdateMovementGear(),
__mmUpdateSoldier(),
__mmUpdateWeaponRecharge(),
__mmAutoHeal()));
},
cancel(__mmReason) {
this.cleanup(__mmReason || "cancelled");
},
};
function __mmNearestBetrayalTarget() {
if (!v || !v.alive || !Array.isArray(E) || __mmTeamKey(v) == null)
return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
String(__mmPlayer.sid) === String(v.sid) ||
!__mmSameTeam(__mmPlayer) ||
__mmIsFriendPlayer(__mmPlayer) ||
!Number.isFinite(Number(__mmPlayer.x)) ||
!Number.isFinite(Number(__mmPlayer.y))
)
continue;
const __mmDistance =
(__mmPlayer.x - v.x) ** 2 + (__mmPlayer.y - v.y) ** 2;
if (__mmDistance < __mmClosestDistance)
((__mmClosest = __mmPlayer), (__mmClosestDistance = __mmDistance));
}
return __mmClosest;
}
function __mmBetrayalInstaReady(__mmTarget) {
if (
!__mmInstaUiEnabled ||
!__mmTarget ||
__mmInsta.state !== "idle" ||
!__mmInsta.runtimeReady() ||
__mmIsTrapped() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
Date.now() < __mmAntiInstaUntil ||
__mmInsta.isEmergencyHealth() ||
!__mmActionAvailable("insta")
)
return !1;
return __mmInsta.fullBurstReady(__mmTarget, "normal", !0);
}
function __mmStartBetrayalInsta() {
const __mmTarget = __mmNearestBetrayalTarget();
if (!__mmTarget) return !1;
__mmActionOwner === "matThief" &&
__mmFinishMatThief("betrayal insta");
__mmActionOwner === "mobSteal" &&
__mmFinishMobSteal("betrayal insta");
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmBetrayalInstaReady(__mmTarget)) return !1;
// Send leave first and deliberately assume success. The betrayal target flag
// keeps this exact former teammate valid until the combo finishes, avoiding
// any wait for the server's team-state acknowledgement.
O.send("N");
return __mmInsta.start({ targetSid: __mmTarget.sid, betrayal: !0 });
}
function __mmTeamKey(__mmPlayer) {
if (!__mmPlayer) return null;
const __mmTeam = __mmPlayer.team;
return typeof __mmTeam === "number"
? __mmTeam > 0
? "n:" + __mmTeam
: null
: typeof __mmTeam === "string" && __mmTeam.trim()
? "s:" + __mmTeam
: null;
}
function __mmNormalizeFriendName(__mmName) {
return typeof __mmName === "string"
? __mmName.trim().slice(0, 15).toLowerCase()
: "";
}
function __mmFriendDisplayName(__mmName) {
return typeof __mmName === "string" ? __mmName.trim().slice(0, 15) : "";
}
function __mmIsFriendPlayer(__mmPlayer) {
const __mmKey = __mmNormalizeFriendName(__mmPlayer && __mmPlayer.name);
return !!(
__mmKey &&
!__mmSameTeam(__mmPlayer) &&
__mmFriendNames.has(__mmKey) &&
!__mmFriendEnemies.has(__mmKey)
);
}
function __mmDispatchFriendState(__mmType, __mmName) {
window.dispatchEvent(
new CustomEvent("MooMooFriendState", {
detail: { type: __mmType, name: __mmName },
}),
);
}
function __mmTeammateByFriendKey(__mmKey) {
return (
Array.isArray(E) &&
E.find(function (__mmPlayer) {
return (
__mmNormalizeFriendName(__mmPlayer && __mmPlayer.name) === __mmKey &&
__mmSameTeam(__mmPlayer)
);
})
);
}
function __mmAddFriend(__mmName, __mmAnnounce) {
const __mmDisplay = __mmFriendDisplayName(__mmName),
__mmKey = __mmNormalizeFriendName(__mmDisplay);
if (!__mmKey) return !1;
const __mmTeammate = __mmTeammateByFriendKey(__mmKey);
if (__mmTeammate) {
__mmFriendPickNotice("Teammates cannot be added as friends");
return !1;
}
(__mmFriendNames.set(__mmKey, __mmDisplay),
__mmFriendEnemies.delete(__mmKey),
__mmDispatchFriendState("add", __mmDisplay),
__mmAnnounce &&
__mmFriendAddedChatEnabled &&
__mmSendChat("Added friend, " + __mmDisplay + "!"),
__mmPublishHudState());
return !0;
}
function __mmRemoveFriend(__mmName, __mmAnnounce) {
const __mmKey = __mmNormalizeFriendName(__mmName),
__mmDisplay =
__mmFriendNames.get(__mmKey) || __mmFriendDisplayName(__mmName);
if (!__mmKey || !__mmDisplay) return !1;
if (__mmTeammateByFriendKey(__mmKey)) {
__mmFriendPickNotice("Teammates cannot be marked as enemies");
return !1;
}
(__mmFriendNames.delete(__mmKey),
__mmFriendEnemies.add(__mmKey),
delete __mmFriendAttackWindows[__mmKey],
__mmDispatchFriendState("remove", __mmDisplay),
__mmAnnounce &&
__mmEnemyMarkedChatEnabled &&
__mmSendChat(__mmDisplay + " is an enemy!"),
__mmPublishHudState());
return !0;
}
function __mmFriendPickNotice(__mmMessage) {
window.dispatchEvent(
new CustomEvent("MooMooFriendPickNotice", {
detail: String(__mmMessage || ""),
}),
);
}
function __mmArmFriendPick(__mmMode) {
if (!v || !v.alive) return !1;
__mmSyncPickArmed = !1;
const __mmNext =
__mmMode === "friend" || __mmMode === "enemy" ? __mmMode : null;
if (__mmFriendPickMode === __mmNext) {
(__mmFriendPickMode = null,
__mmFriendPickNotice("Player selection cancelled"));
return !1;
}
__mmFriendPickMode = __mmNext;
__mmFriendPickNotice(
__mmNext === "friend"
? "Click a non-teammate to add friend"
: "Click a non-teammate to mark enemy",
);
return !0;
}
function __mmPlayerAtFriendPick(__mmEvent) {
if (!v || !v.alive || !Array.isArray(E) || !__mmEvent) return null;
const __mmSurface =
document.getElementById("gameCanvas") ||
(__mmEvent.target instanceof Element
? __mmEvent.target.closest("#gameCanvas,#touch-controls-fullscreen")
: null),
__mmRect =
__mmSurface && typeof __mmSurface.getBoundingClientRect === "function"
? __mmSurface.getBoundingClientRect()
: null;
if (!__mmRect || __mmRect.width <= 0 || __mmRect.height <= 0) return null;
const __mmViewportWidth = Math.max(1, Number(_) || Number(De) || __mmRect.width),
__mmViewportHeight = Math.max(1, Number(L) || Number(Ae) || __mmRect.height),
__mmLeft = Number(oe) - __mmViewportWidth / 2,
__mmTop = Number(ae) - __mmViewportHeight / 2;
let __mmBest = null,
__mmBestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
String(__mmPlayer.sid) === String(v.sid)
)
continue;
const __mmPlayerPositions = [
{ x: Number(__mmPlayer.x), y: Number(__mmPlayer.y) },
],
__mmServerX = Number(__mmPlayer.x2),
__mmServerY = Number(__mmPlayer.y2);
if (
__mmPlayer.x2 != null &&
__mmPlayer.y2 != null &&
Number.isFinite(__mmServerX) &&
Number.isFinite(__mmServerY) &&
(__mmServerX !== Number(__mmPlayer.x) ||
__mmServerY !== Number(__mmPlayer.y))
)
__mmPlayerPositions.push({ x: __mmServerX, y: __mmServerY });
let __mmDistance = Infinity;
for (
let __mmPositionIndex = 0;
__mmPositionIndex < __mmPlayerPositions.length;
__mmPositionIndex++
) {
const __mmPosition = __mmPlayerPositions[__mmPositionIndex],
__mmScreenX =
__mmRect.left +
((__mmPosition.x - __mmLeft) / __mmViewportWidth) *
__mmRect.width,
__mmScreenY =
__mmRect.top +
((__mmPosition.y - __mmTop) / __mmViewportHeight) *
__mmRect.height;
__mmDistance = Math.min(
__mmDistance,
Math.hypot(
Number(__mmEvent.clientX) - __mmScreenX,
Number(__mmEvent.clientY) - __mmScreenY,
),
);
}
const __mmHitRadius = Math.max(
30,
((Number(__mmPlayer.scale) || 35) / __mmViewportWidth) *
__mmRect.width +
24,
);
if (__mmDistance <= __mmHitRadius && __mmDistance < __mmBestDistance)
((__mmBest = __mmPlayer), (__mmBestDistance = __mmDistance));
}
return __mmBest;
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (!__mmFriendPickMode || !__mmIsGameClick(__mmEvent)) return;
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
__mmCleanupActive && __mmStopCleanup("friend selection click", !1);
const __mmPlayer = __mmPlayerAtFriendPick(__mmEvent);
if (!__mmPlayer) {
__mmFriendPickNotice("No player there - click again");
return;
}
const __mmMode = __mmFriendPickMode;
if (__mmMode === "friend") {
if (__mmSameTeam(__mmPlayer)) {
__mmFriendPickNotice(
"That player is already your teammate - click a non-teammate",
);
return;
}
__mmFriendPickMode = null;
(__mmAddFriend(__mmPlayer.name, !0),
__mmFriendPickNotice("Friend: " + __mmPlayer.name));
} else {
if (__mmSameTeam(__mmPlayer)) {
__mmFriendPickNotice(
"That player is your teammate - click a non-teammate",
);
return;
}
__mmFriendPickMode = null;
(__mmRemoveFriend(__mmPlayer.name, !0),
__mmFriendPickNotice("Enemy: " + __mmPlayer.name));
}
},
!0,
);
function __mmSyncTargetLabel() {
return __mmSyncTargetName ||
(__mmSyncTargetSid == null ? "teammate" : "Player " + __mmSyncTargetSid);
}
function __mmClearSelectedSyncTarget(__mmMessage) {
((__mmSyncPickArmed = !1),
(__mmSyncTargetSid = null),
(__mmSyncTargetName = ""),
(__mmSyncTargetExplicit = !1),
(__mmSyncLeaderEnabled = !1),
(__mmSyncFollowerEnabled = !1),
(__mmSyncCombatOnlyEnabled = !1),
(__mmSyncLeaderState = null),
(__mmSyncStandLeaderKey = ""),
(__mmSyncStandAngle = null),
(__mmSyncArrivedBeside = !1),
(__mmSyncDirectAttackAt = 0),
(__mmSyncDirectAttackActive = !1),
__mmCancelScheduledSyncInsta(),
__mmStopObservedSyncAttack(!0),
__mmSyncRestoreCatchupGear(),
__mmSyncStopFollowMovement(),
__mmStopTabSync(),
__mmSetSyncStatus(__mmMessage || "Sync off"),
__mmPublishHudState());
}
function __mmSelectSyncTarget(__mmPlayer) {
if (!v || !v.alive || !__mmPlayer || !__mmPlayer.alive) return !1;
if (!__mmSameTeam(__mmPlayer)) {
__mmFriendPickNotice("Sync only works with a current teammate");
return !1;
}
if (String(__mmPlayer.sid) === String(__mmSyncTargetSid)) {
if (!__mmSyncFollowerEnabled || __mmSyncCombatOnlyEnabled) {
((__mmSyncPickArmed = !1),
(__mmSyncTargetName = String(
__mmPlayer.name || __mmSyncTargetName || "",
).trim().slice(0, 15)),
(__mmSyncTargetExplicit = !0),
(__mmSyncLeaderEnabled = !0),
(__mmSyncFollowerEnabled = !0),
(__mmSyncCombatOnlyEnabled = !1),
(__mmSyncStandLeaderKey = ""),
(__mmSyncStandAngle = null),
(__mmSyncArrivedBeside = !1),
(__mmSyncDirectAttackAt = 0),
(__mmSyncDirectAttackActive = !1),
(__mmSyncSelectionBlockedUntil = 0),
__mmStopObservedSyncAttack(!0),
__mmRefreshSelectedSyncTarget(),
__mmStartTabSync(),
__mmSetSyncStatus("Syncing… · " + __mmSyncTargetLabel()),
__mmFriendPickNotice("Reconnected with " + __mmSyncTargetLabel()),
__mmPublishHudState());
return !0;
}
__mmClearSelectedSyncTarget("Sync disconnected");
return !0;
}
((__mmSyncPickArmed = !1),
(__mmSyncTargetSid = __mmPlayer.sid),
(__mmSyncTargetName = String(__mmPlayer.name || "").trim().slice(0, 15)),
(__mmSyncTargetExplicit = !0),
(__mmSyncLeaderEnabled = !0),
(__mmSyncFollowerEnabled = !0),
(__mmSyncCombatOnlyEnabled = !1),
(__mmSyncLeaderState = null),
(__mmSyncStandLeaderKey = ""),
(__mmSyncStandAngle = null),
(__mmSyncArrivedBeside = !1),
(__mmSyncDirectAttackAt = 0),
(__mmSyncDirectAttackActive = !1),
__mmCancelScheduledSyncInsta(),
__mmStopObservedSyncAttack(!0),
__mmRefreshSelectedSyncTarget(),
__mmStartTabSync(),
__mmSetSyncStatus("Syncing… · " + __mmSyncTargetLabel()),
__mmFriendPickNotice("Synced with " + __mmSyncTargetLabel()),
__mmPublishHudState());
return !0;
}
function __mmArmSyncPick() {
if (!v || !v.alive) return !1;
__mmFriendPickMode = null;
if (__mmSyncPickArmed) {
((__mmSyncPickArmed = !1),
__mmFriendPickNotice("Teammate sync selection cancelled"));
return !1;
}
((__mmSyncPickArmed = !0),
__mmFriendPickNotice("Click a teammate to sync"));
return !0;
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (!__mmSyncPickArmed || !__mmIsGameClick(__mmEvent)) return;
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
__mmCleanupActive && __mmStopCleanup("sync selection click", !1);
const __mmPlayer = __mmPlayerAtFriendPick(__mmEvent);
if (!__mmPlayer) {
__mmFriendPickNotice("No player there - click again");
return;
}
if (!__mmSameTeam(__mmPlayer)) {
__mmFriendPickNotice("That player is not your teammate - click again");
return;
}
__mmSelectSyncTarget(__mmPlayer);
},
!0,
);
window.addEventListener("blur", function () {
((__mmFriendPickMode = null), (__mmSyncPickArmed = !1));
});
function __mmReplaceFriends(__mmNames) {
const __mmPrevious = Array.from(__mmFriendNames.keys()),
__mmNext = new Map();
if (Array.isArray(__mmNames)) {
for (let __mmIndex = 0; __mmIndex < __mmNames.length; __mmIndex++) {
const __mmDisplay = __mmFriendDisplayName(__mmNames[__mmIndex]),
__mmKey = __mmNormalizeFriendName(__mmDisplay);
__mmKey && !__mmNext.has(__mmKey) && __mmNext.set(__mmKey, __mmDisplay);
if (__mmNext.size >= 30) break;
}
}
__mmFriendNames.clear();
__mmNext.forEach(function (__mmDisplay, __mmKey) {
(__mmFriendNames.set(__mmKey, __mmDisplay),
__mmFriendEnemies.delete(__mmKey));
});
for (let __mmIndex = 0; __mmIndex < __mmPrevious.length; __mmIndex++)
__mmNext.has(__mmPrevious[__mmIndex]) ||
__mmFriendEnemies.add(__mmPrevious[__mmIndex]);
}
function __mmFriendAttackAimedAtUs(__mmPlayer, __mmWeapon) {
if (!v || !v.alive || !__mmPlayer || !__mmPlayer.alive) return !1;
const __mmWeaponId =
__mmWeapon == null ? __mmPlayer.weaponIndex : Number(__mmWeapon),
__mmWeaponData = b.weapons && b.weapons[__mmWeaponId],
__mmAttackAngle = Number(__mmPlayer.dir),
__mmTargetAngle = Math.atan2(v.y - __mmPlayer.y, v.x - __mmPlayer.x),
__mmAngleDifference = Math.abs(
Math.atan2(
Math.sin(__mmAttackAngle - __mmTargetAngle),
Math.cos(__mmAttackAngle - __mmTargetAngle),
),
),
__mmDistance = Math.hypot(v.x - __mmPlayer.x, v.y - __mmPlayer.y),
__mmReach = __mmWeaponData
? __mmWeaponData.projectile != null
? 900
: (Number(__mmWeaponData.range) || 0) +
(Number(__mmPlayer.scale) || 35) +
(Number(v.scale) || 35) +
45
: 220;
return __mmAngleDifference <= 0.72 && __mmDistance <= __mmReach;
}
function __mmObserveFriendAttack(__mmPlayerSid, __mmDidHit, __mmWeapon) {
const __mmPlayer = Rt(__mmPlayerSid);
if (!__mmIsFriendPlayer(__mmPlayer)) return;
const __mmKey = __mmNormalizeFriendName(__mmPlayer.name);
if (!__mmFriendAttackAimedAtUs(__mmPlayer, __mmWeapon)) return;
const __mmNow = Date.now(),
__mmWeaponId =
__mmWeapon == null ? Number(__mmPlayer.weaponIndex) : Number(__mmWeapon),
__mmWindow =
__mmFriendAttackWindows[__mmKey] ||
(__mmFriendAttackWindows[__mmKey] = {
lastAt: 0,
lastWeapon: null,
lastAimedAt: 0,
damageStartedAt: 0,
damage: 0,
}),
__mmRapidDistinct =
__mmWindow.lastAt > 0 &&
__mmNow - __mmWindow.lastAt <= Math.max(300, __mmServerTickMs() * 3) &&
__mmWindow.lastWeapon != null &&
__mmWindow.lastWeapon !== __mmWeaponId &&
([__mmShortSword, __mmKatana, __mmPolearmWeapon].includes(__mmWeaponId) ||
[__mmShortSword, __mmKatana, __mmPolearmWeapon].includes(
__mmWindow.lastWeapon,
)),
__mmInstaPrimary = [
__mmShortSword,
__mmKatana,
__mmPolearmWeapon,
].includes(__mmWeaponId),
__mmInstaGear =
Number(__mmPlayer.skinIndex) === 7 ||
Number(__mmPlayer.skinIndex) === __mmTurretGear;
((__mmWindow.lastAt = __mmNow),
(__mmWindow.lastWeapon = __mmWeaponId),
(__mmWindow.lastAimedAt = __mmNow));
(__mmRapidDistinct || (__mmInstaPrimary && __mmInstaGear)) &&
__mmRemoveFriend(__mmPlayer.name, !0);
}
function __mmObserveFriendDamage(__mmDamage) {
if (!(Number(__mmDamage) > 0) || !v || !v.alive) return;
const __mmNow = Date.now();
let __mmBestKey = "",
__mmBestAt = 0;
__mmFriendNames.forEach(function (__mmDisplay, __mmKey) {
const __mmWindow = __mmFriendAttackWindows[__mmKey];
if (
__mmWindow &&
__mmNow - __mmWindow.lastAimedAt <= 850 &&
__mmWindow.lastAimedAt > __mmBestAt
)
((__mmBestKey = __mmKey), (__mmBestAt = __mmWindow.lastAimedAt));
});
if (!__mmBestKey) return;
const __mmWindow = __mmFriendAttackWindows[__mmBestKey];
if (
!__mmWindow.damageStartedAt ||
__mmNow - __mmWindow.damageStartedAt > 1200
)
((__mmWindow.damageStartedAt = __mmNow), (__mmWindow.damage = 0));
__mmWindow.damage += Number(__mmDamage);
__mmWindow.damage > 20 &&
__mmRemoveFriend(__mmFriendNames.get(__mmBestKey), !0);
}
function __mmSameTeam(__mmPlayer) {
const __mmOwnTeam = __mmTeamKey(v),
__mmOtherTeam = __mmTeamKey(__mmPlayer);
return (
__mmOwnTeam != null &&
__mmOtherTeam != null &&
__mmOwnTeam === __mmOtherTeam
);
}
function __mmHandleTeamJoinRequest() {
if (
(!__mmAutoAcceptTeamRequestsEnabled &&
!__mmAutoDeclineTeamRequestsEnabled) ||
!document.body
)
return;
const __mmHolder =
document.getElementById("noticationDisplay") ||
document.getElementById("notificationDisplay");
if (!__mmHolder) return;
const __mmButtons = Array.from(
__mmHolder.querySelectorAll(".notifButton"),
);
if (__mmButtons.length < 2) return;
const __mmAccept = __mmAutoAcceptTeamRequestsEnabled,
__mmButtonPattern = __mmAccept
? /(?:8ecc51|e876|check|done|accept)/i
: /(?:cc5151|e14c|close|clear|decline|reject)/i,
// Prefer the native icon/color so this survives a button-order change.
// Current MooMoo still uses Decline first and Accept second as fallback.
__mmButton =
__mmButtons.find(function (__mmCandidate) {
return __mmButtonPattern.test(
String(__mmCandidate.innerHTML || "") +
" " +
String(__mmCandidate.getAttribute("aria-label") || "") +
" " +
String(__mmCandidate.title || ""),
);
}) || __mmButtons[__mmAccept ? 1 : 0];
if (
!__mmButton ||
__mmHandledTeamRequestButtons.has(__mmButton)
)
return;
__mmHandledTeamRequestButtons.add(__mmButton);
try {
if (typeof __mmButton.onclick === "function") {
// MooMoo's generateElement wraps onclick with checkTrusted(). A normal
// element.click() produces isTrusted=false and is silently discarded.
// Calling the already-installed native handler keeps its queue splice
// and P packet intact; this proxy only satisfies that local UI guard.
const __mmTrustedEvent = new Proxy(new Event("click"), {
get: function (__mmTarget, __mmProperty) {
if (__mmProperty === "isTrusted") return !0;
const __mmValue = Reflect.get(
__mmTarget,
__mmProperty,
__mmTarget,
);
return typeof __mmValue === "function"
? __mmValue.bind(__mmTarget)
: __mmValue;
},
});
__mmButton.onclick.call(__mmButton, __mmTrustedEvent);
} else if (typeof __mmButton.click === "function") __mmButton.click();
else throw new Error("team request button has no handler");
// If a changed client rejected the handler, allow the interval to retry
// instead of permanently blacklisting the still-visible request.
setTimeout(function () {
__mmButton.isConnected &&
__mmHandledTeamRequestButtons.delete(__mmButton);
}, 180);
} catch (__mmTeamRequestClickError) {
__mmHandledTeamRequestButtons.delete(__mmButton);
}
}
function __mmStartTeamRequestAutomation() {
if (__mmTeamRequestObserver || !document.documentElement) return;
__mmTeamRequestObserver = new MutationObserver(__mmHandleTeamJoinRequest);
__mmTeamRequestObserver.observe(document.documentElement, {
childList: !0,
subtree: !0,
attributes: !0,
attributeFilter: ["style"],
});
__mmTeamRequestTimer = setInterval(
__mmHandleTeamJoinRequest,
__mmFastCheckMs(),
);
__mmHandleTeamJoinRequest();
}
function __mmIsEnemyPlayer(__mmPlayer) {
const __mmFriendKey = __mmNormalizeFriendName(
__mmPlayer && __mmPlayer.name,
),
__mmBetrayedFriend =
!!__mmFriendKey && __mmFriendEnemies.has(__mmFriendKey);
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
(Number.isFinite(Number(__mmPlayer.health)) &&
Number(__mmPlayer.health) <= 0) ||
!v ||
!v.alive ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid
)
return !1;
// Team membership has absolute precedence over saved friend/enemy state.
if (__mmSameTeam(__mmPlayer)) return !1;
if (!__mmBetrayedFriend && __mmIsFriendPlayer(__mmPlayer)) return !1;
const __mmOwnTeam = __mmTeamKey(v),
__mmOtherTeam = __mmTeamKey(__mmPlayer);
if (__mmOwnTeam != null && __mmOtherTeam == null) {
const __mmSid = String(__mmPlayer.sid),
__mmNow = Date.now(),
__mmSeen =
__mmUnknownTeamSeen[__mmSid] ||
(__mmUnknownTeamSeen[__mmSid] = __mmNow);
return __mmNow - __mmSeen >= __mmUnknownTeamGraceMs;
}
return !0;
}
function __mmSyncOwnTeamKey() {
const __mmKey = __mmTeamKey(v);
return __mmKey == null ? "" : String(__mmKey);
}
function __mmSelectedSyncTargetPlayer() {
if (__mmSyncTargetSid == null || !v || !v.alive) return null;
let __mmPlayer = null;
try {
__mmPlayer = Rt(__mmSyncTargetSid);
} catch (__mmSyncTargetLookupError) {}
return __mmPlayer &&
__mmPlayer.alive &&
__mmPlayer.visible &&
__mmSameTeam(__mmPlayer)
? __mmPlayer
: null;
}
function __mmApplyVisibleSyncTargetState(__mmPlayer) {
if (!__mmSyncFollowerEnabled || !v || !v.alive || !__mmPlayer) return;
const __mmBuild = Number(__mmPlayer.buildIndex),
__mmWeapon = Number(__mmPlayer.weaponIndex),
__mmHat = Number(__mmPlayer.skinIndex),
__mmTail = Number(__mmPlayer.tailIndex);
if (
__mmSyncCopyBuildsEnabled &&
Number.isInteger(__mmBuild) &&
__mmBuild >= 0 &&
__mmSyncOwnsSelection(__mmBuild, !1) &&
Number(v.buildIndex) !== __mmBuild
)
je(__mmBuild);
else if (
__mmSyncCopyWeaponsEnabled &&
(!Number.isInteger(__mmBuild) || __mmBuild < 0) &&
Number.isInteger(__mmWeapon) &&
__mmSyncOwnsSelection(__mmWeapon, !0) &&
(Number(v.buildIndex) >= 0 || Number(v.weaponIndex) !== __mmWeapon)
)
je(__mmWeapon, !0);
if (!__mmSyncCopyGearEnabled) return;
if (__mmSyncCatchupActive) {
(__mmCanEquipHat(__mmHat) || __mmHat === 0) &&
(__mmSyncCatchupPreviousHat = __mmHat);
((v.tails && v.tails[__mmTail]) || __mmTail === 0) &&
(__mmSyncCatchupPreviousTail = __mmTail);
return;
}
((__mmCanEquipHat(__mmHat) || __mmHat === 0) &&
Number(v.skinIndex) !== __mmHat &&
__mmEquipHatNow(__mmHat),
((v.tails && v.tails[__mmTail]) || __mmTail === 0) &&
Number(v.tailIndex) !== __mmTail &&
__mmEquipTailNow(__mmTail));
}
function __mmRefreshSelectedSyncTarget() {
if (__mmSyncTargetSid == null || !v || !v.alive) return null;
const __mmPlayer = __mmSelectedSyncTargetPlayer(),
__mmNow = Date.now(),
__mmPrevious = __mmSyncLeaderState,
__mmNetworkFresh = !!(
__mmPrevious &&
__mmPrevious.kittyPeer &&
String(__mmPrevious.leaderSid) === String(__mmSyncTargetSid) &&
__mmNow - Number(__mmPrevious.networkReceivedAt || 0) <= 2500
);
if (!__mmPlayer) {
if (!__mmNetworkFresh)
__mmSetSyncStatus(
"Syncing… · " + __mmSyncTargetLabel() + " is out of view",
);
return null;
}
const __mmDirection = Number(__mmPlayer.dir),
__mmVelocity = __mmSyncPlayerVelocity(__mmPlayer),
__mmAimDistance = 1800;
__mmSyncTargetName = String(
__mmPlayer.name || __mmSyncTargetName || "",
).trim().slice(0, 15);
__mmSyncLeaderState = {
...(__mmNetworkFresh ? __mmPrevious : {}),
type: "state",
sender: __mmNetworkFresh
? __mmPrevious.sender
: "visible:" + __mmSyncTargetSid,
leaderSid: __mmSyncTargetSid,
x: Number(__mmPlayer.x),
y: Number(__mmPlayer.y),
scale: Number(__mmPlayer.scale) || 35,
vx: __mmVelocity.x,
vy: __mmVelocity.y,
weapon: Number(__mmPlayer.weaponIndex),
build: Number(__mmPlayer.buildIndex),
hat: Number(__mmPlayer.skinIndex),
tail: Number(__mmPlayer.tailIndex),
aimX:
__mmNetworkFresh && Number.isFinite(Number(__mmPrevious.aimX))
? Number(__mmPrevious.aimX)
: Number(__mmPlayer.x) +
Math.cos(Number.isFinite(__mmDirection) ? __mmDirection : 0) *
__mmAimDistance,
aimY:
__mmNetworkFresh && Number.isFinite(Number(__mmPrevious.aimY))
? Number(__mmPrevious.aimY)
: Number(__mmPlayer.y) +
Math.sin(Number.isFinite(__mmDirection) ? __mmDirection : 0) *
__mmAimDistance,
receivedAt: __mmNow,
kittyPeer: __mmNetworkFresh,
networkReceivedAt: __mmNetworkFresh
? __mmPrevious.networkReceivedAt
: 0,
};
__mmWithSyncReplay(function () {
__mmApplyVisibleSyncTargetState(__mmPlayer);
});
return __mmPlayer;
}
function __mmSyncSafeRelayUrl(__mmValue) {
const __mmRaw = String(__mmValue || "").trim().slice(0, 200);
if (!__mmRaw) return "";
try {
const __mmUrl = new URL(__mmRaw);
if (__mmUrl.protocol === "wss:") return __mmUrl.href;
if (
__mmUrl.protocol === "ws:" &&
(__mmUrl.hostname === "127.0.0.1" ||
__mmUrl.hostname === "localhost" ||
__mmUrl.hostname === "[::1]")
)
return __mmUrl.href;
} catch (__mmRelayUrlError) {}
return "";
}
function __mmSyncHash(__mmValue) {
let __mmHash = 2166136261;
const __mmText = String(__mmValue || "");
for (let __mmIndex = 0; __mmIndex < __mmText.length; __mmIndex++) {
(__mmHash ^= __mmText.charCodeAt(__mmIndex),
(__mmHash = Math.imul(__mmHash, 16777619)));
}
return (__mmHash >>> 0).toString(36);
}
function __mmSyncCurrentRelayRoom() {
const __mmTeam = __mmSyncOwnTeamKey(),
__mmPhrase = String(__mmSyncRoom || "").trim();
return __mmTeam && __mmPhrase.length >= 4
? "kitty-" +
__mmSyncHash(
location.hostname + "|" + __mmTeam + "|" + __mmPhrase,
)
: "";
}
function __mmSyncRelayWanted() {
return !!(
v &&
v.alive &&
__mmSyncSafeRelayUrl(__mmSyncRelayUrl) &&
__mmSyncCurrentRelayRoom()
);
}
function __mmSyncRelayConnected() {
return !!(
__mmSyncRelaySocket &&
__mmSyncRelaySocket.readyState === WebSocket.OPEN &&
__mmSyncRelayRoomKey === __mmSyncCurrentRelayRoom()
);
}
function __mmSyncServerNow() {
return Date.now() + __mmSyncRelayClockOffset;
}
function __mmCloseSyncRelay(__mmReconnect) {
(__mmSyncRelayReconnectTimer && clearTimeout(__mmSyncRelayReconnectTimer),
(__mmSyncRelayReconnectTimer = 0),
__mmSyncRelayPingTimer && clearInterval(__mmSyncRelayPingTimer),
(__mmSyncRelayPingTimer = 0));
const __mmSocket = __mmSyncRelaySocket;
__mmSyncRelaySocket = null;
__mmSyncRelayRoomKey = "";
if (__mmSocket)
try {
((__mmSocket.onopen = null),
(__mmSocket.onmessage = null),
(__mmSocket.onerror = null),
(__mmSocket.onclose = null),
__mmSocket.readyState < WebSocket.CLOSING && __mmSocket.close(1000));
} catch (__mmRelayCloseError) {}
if (__mmReconnect && __mmSyncRelayWanted())
__mmSyncRelayReconnectTimer = setTimeout(__mmConnectSyncRelay, 900);
}
function __mmSyncRelayPing() {
if (!__mmSyncRelayConnected()) return;
try {
__mmSyncRelaySocket.send(
JSON.stringify({ type: "ping", clientAt: Date.now() }),
);
} catch (__mmRelayPingError) {}
}
function __mmHandleSyncRelayMessage(__mmRaw) {
let __mmEnvelope = null;
try {
__mmEnvelope = JSON.parse(String(__mmRaw || ""));
} catch (__mmRelayParseError) {
return;
}
if (!__mmEnvelope || typeof __mmEnvelope !== "object") return;
if (__mmEnvelope.type === "joined") {
const __mmServerAt = Number(__mmEnvelope.serverAt);
Number.isFinite(__mmServerAt) &&
(__mmSyncRelayClockOffset = __mmServerAt - Date.now());
(__mmSetSyncStatus(
__mmSyncTargetSid == null
? "Sync off"
: "Synced · " + __mmSyncTargetLabel() + " · relay ready",
),
__mmSyncRelayPing());
return;
}
if (__mmEnvelope.type === "pong") {
const __mmClientAt = Number(__mmEnvelope.clientAt),
__mmServerAt = Number(__mmEnvelope.serverAt),
__mmNow = Date.now();
if (Number.isFinite(__mmClientAt) && Number.isFinite(__mmServerAt)) {
const __mmRtt = Math.max(0, __mmNow - __mmClientAt);
((__mmSyncRelayRtt = __mmSyncRelayRtt
? __mmSyncRelayRtt * 0.7 + __mmRtt * 0.3
: __mmRtt),
(__mmSyncRelayClockOffset =
__mmSyncRelayClockOffset * 0.7 +
(__mmServerAt - (__mmClientAt + __mmNow) / 2) * 0.3));
}
return;
}
if (
__mmEnvelope.type !== "event" ||
__mmEnvelope.room !== __mmSyncRelayRoomKey ||
String(__mmEnvelope.teamKey || "") !== __mmSyncOwnTeamKey() ||
!__mmEnvelope.payload ||
typeof __mmEnvelope.payload !== "object"
)
return;
__mmSyncHandleMessage({ data: __mmEnvelope.payload, relay: !0 });
}
function __mmConnectSyncRelay() {
if (!__mmSyncRelayWanted()) return void __mmCloseSyncRelay(!1);
const __mmUrl = __mmSyncSafeRelayUrl(__mmSyncRelayUrl),
__mmRoom = __mmSyncCurrentRelayRoom(),
__mmNow = Date.now();
if (
__mmSyncRelaySocket &&
__mmSyncRelaySocket._kittyUrl === __mmUrl &&
__mmSyncRelayRoomKey === __mmRoom &&
__mmSyncRelaySocket.readyState <= WebSocket.OPEN
)
return;
if (__mmNow - __mmSyncRelayAttemptAt < 700) return;
(__mmCloseSyncRelay(!1),
(__mmSyncRelayAttemptAt = __mmNow),
(__mmSyncRelayRoomKey = __mmRoom));
let __mmSocket = null;
try {
__mmSocket = new WebSocket(__mmUrl);
} catch (__mmRelayConnectError) {
(__mmSetSyncStatus("Sync failed · relay URL blocked"),
__mmCloseSyncRelay(!0));
return;
}
((__mmSyncRelaySocket = __mmSocket),
(__mmSocket._kittyUrl = __mmUrl),
__mmSetSyncStatus("Syncing… · connecting relay"));
__mmSocket.onopen = function () {
if (__mmSyncRelaySocket !== __mmSocket) return;
try {
__mmSocket.send(
JSON.stringify({
type: "join",
protocol: "kitty-klient-team-sync-v1",
room: __mmRoom,
teamKey: __mmSyncOwnTeamKey(),
clientId: __mmSyncTabId,
}),
);
(__mmSyncRelayPingTimer && clearInterval(__mmSyncRelayPingTimer),
(__mmSyncRelayPingTimer = setInterval(__mmSyncRelayPing, 5000)));
} catch (__mmRelayJoinError) {
__mmCloseSyncRelay(!0);
}
};
__mmSocket.onmessage = function (__mmEvent) {
__mmSyncRelaySocket === __mmSocket &&
__mmHandleSyncRelayMessage(__mmEvent.data);
};
__mmSocket.onerror = function () {
__mmSyncRelaySocket === __mmSocket &&
__mmSetSyncStatus("Sync error · relay unavailable");
};
__mmSocket.onclose = function () {
if (__mmSyncRelaySocket !== __mmSocket) return;
(__mmSyncFollowerEnabled &&
(__mmSyncRestoreCatchupGear(), __mmSyncStopFollowMovement()),
__mmCloseSyncRelay(!1),
__mmSyncRelayWanted() && __mmSetSyncStatus("Reconnecting…"),
__mmSyncRelayWanted() &&
(__mmSyncRelayReconnectTimer = setTimeout(
__mmConnectSyncRelay,
1200,
)));
};
}
function __mmSyncRelaySend(__mmPacket) {
if (!__mmSyncRelayConnected()) return !1;
try {
const __mmPayload = JSON.stringify({
type: "publish",
room: __mmSyncRelayRoomKey,
teamKey: __mmSyncOwnTeamKey(),
payload: __mmPacket,
});
if (__mmPayload.length > 1800) return !1;
(__mmSyncRelaySocket.send(__mmPayload), (__mmMetricPackets += 1));
return !0;
} catch (__mmRelaySendError) {
__mmCloseSyncRelay(!0);
return !1;
}
}
function __mmSetSyncRelayConfig(__mmKey, __mmValue) {
if (__mmKey === "syncRelayUrl")
__mmSyncRelayUrl = String(__mmValue || "").trim().slice(0, 200);
else if (__mmKey === "syncRoom")
__mmSyncRoom = String(__mmValue || "").trim().slice(0, 64);
else return;
(__mmCloseSyncRelay(!1),
(__mmSyncRelayClockOffset = 0),
(__mmSyncRelayRtt = 0),
__mmStartTabSync(),
__mmPublishHudState());
}
function __mmWithSyncReplay(__mmCallback) {
__mmSyncReplayDepth += 1;
try {
return __mmCallback();
} finally {
__mmSyncReplayDepth = Math.max(0, __mmSyncReplayDepth - 1);
}
}
function __mmStopObservedSyncAttack(__mmRelease = !0) {
(__mmSyncObservedAttackReleaseTimer &&
clearTimeout(__mmSyncObservedAttackReleaseTimer),
(__mmSyncObservedAttackReleaseTimer = 0));
if (!__mmSyncObservedAttackHeld) return;
__mmSyncObservedAttackHeld = !1;
__mmRelease &&
v &&
v.alive &&
__mmWithSyncReplay(function () {
O.send("F", 0, Ci());
});
}
function __mmSyncObservedPlayerSwing(__mmPlayerSid, __mmWeapon) {
if (
!__mmSyncCopyAttacksEnabled ||
(!__mmSyncFollowerEnabled && !__mmSyncCombatOnlyEnabled) ||
!v ||
!v.alive ||
__mmSyncTargetSid == null ||
String(__mmPlayerSid) !== String(__mmSyncTargetSid)
)
return;
const __mmNow = Date.now();
if (__mmSyncDirectAttackActive) {
if (__mmNow - __mmSyncDirectAttackAt < 1200) return;
__mmSyncDirectAttackActive = !1;
}
if (
__mmNow - __mmSyncDirectAttackAt <
Math.max(650, __mmServerTickMs() * 6)
)
return;
let __mmPlayer = null;
try {
__mmPlayer = Rt(__mmPlayerSid);
} catch (__mmObservedSyncPlayerError) {}
if (!__mmPlayer || !__mmPlayer.alive || !__mmSameTeam(__mmPlayer)) return;
const __mmRemoteWeapon = Number.isInteger(Number(__mmWeapon))
? Number(__mmWeapon)
: Number(__mmPlayer.weaponIndex),
__mmWeaponId = __mmSyncCombatWeapon(
__mmRemoteWeapon,
__mmPlayer,
__mmPlayerWeaponSlot(__mmPlayer, __mmRemoteWeapon),
),
__mmDirection = Number(__mmPlayer.dir),
__mmAngle = Number.isFinite(__mmDirection) ? __mmDirection : Ci();
if (__mmWeaponId == null) return;
__mmStopObservedSyncAttack(!0);
__mmWithSyncReplay(function () {
if (
Number(v.buildIndex) >= 0 ||
Number(v.weaponIndex) !== __mmWeaponId
)
je(__mmWeaponId, !0);
(O.send("D", __mmAngle), O.send("F", 1, __mmAngle));
});
(__mmSyncObservedAttackHeld = !0),
(__mmSyncObservedAttackReleaseTimer = setTimeout(function () {
(__mmSyncObservedAttackReleaseTimer = 0),
__mmStopObservedSyncAttack(!0);
}, Math.max(1, __mmServerTickMs())));
}
function __mmSyncPost(__mmMessage) {
const __mmTeamKey = __mmSyncOwnTeamKey();
if (
__mmSyncReplayDepth > 0 ||
!__mmSyncLeaderEnabled ||
!v ||
!v.alive ||
!__mmTeamKey
)
return;
const __mmPacket = {
...__mmMessage,
sender: __mmSyncTabId,
packetId: __mmSyncTabId + ":" + (++__mmSyncSequence),
leaderSid: v.sid,
teamKey: __mmTeamKey,
sentAt: Date.now(),
};
try {
__mmSyncChannel && __mmSyncChannel.postMessage(__mmPacket);
} catch (__mmSyncPostError) {}
try {
window.dispatchEvent(
new CustomEvent("MooMooTabSyncOutbound", {
detail: JSON.stringify(__mmPacket),
}),
);
} catch (__mmSyncBridgeError) {}
try {
window.dispatchEvent(
new CustomEvent("MooMooKittySyncOutbound", {
detail: {
protocol: __mmOpenSyncProtocol,
client: "kitty-klient",
clientVersion: "${KITTY_KLIENT_VERSION}",
packet: { ...__mmPacket },
},
}),
);
} catch (__mmOpenSyncOutboundError) {}
__mmSyncRelaySend(__mmPacket);
}
function __mmSyncStatusChatPump() {
if (
!__mmSyncStatusChatEnabled ||
!__mmSyncStatusChatQueue.length ||
!v ||
!v.alive
) {
(__mmSyncStatusChatTimer && clearTimeout(__mmSyncStatusChatTimer),
(__mmSyncStatusChatTimer = 0));
return;
}
const __mmNow = Date.now(),
__mmCooldown = Math.max(
550,
(Number(y && y.chatCooldown) || 500) + 60,
),
__mmDelay = Math.max(
0,
__mmSyncStatusChatLastAt + __mmCooldown - __mmNow,
);
if (__mmDelay > 0) {
__mmSyncStatusChatTimer && clearTimeout(__mmSyncStatusChatTimer);
__mmSyncStatusChatTimer = setTimeout(function () {
((__mmSyncStatusChatTimer = 0), __mmSyncStatusChatPump());
}, __mmDelay);
return;
}
const __mmMessage = __mmSyncStatusChatQueue.shift();
((__mmSyncStatusChatLastAt = __mmNow), __mmSendChat(__mmMessage));
if (__mmSyncStatusChatQueue.length)
__mmSyncStatusChatTimer = setTimeout(function () {
((__mmSyncStatusChatTimer = 0), __mmSyncStatusChatPump());
}, __mmCooldown);
}
function __mmQueueSyncStatusChat(__mmStatus) {
const __mmText = String(__mmStatus || ""),
__mmPhase = /^(?:Syncing|Reconnecting)/i.test(__mmText)
? "syncing"
: /^Synced\b/i.test(__mmText)
? "synced"
: /(?:disconnected|Sync off|stopped)/i.test(__mmText)
? "off"
: null;
if (!__mmPhase || __mmPhase === __mmSyncStatusChatPhase) return;
__mmSyncStatusChatPhase = __mmPhase;
if (!__mmSyncStatusChatEnabled) return;
const __mmMessage =
__mmPhase === "syncing"
? "Syncing..."
: __mmPhase === "synced"
? "Synced!"
: "Sync stopped.";
__mmSyncStatusChatQueue[__mmSyncStatusChatQueue.length - 1] !== __mmMessage &&
__mmSyncStatusChatQueue.push(__mmMessage);
__mmSyncStatusChatQueue.length > 3 && __mmSyncStatusChatQueue.shift();
__mmSyncStatusChatPump();
}
function __mmSetSyncStatus(__mmStatus) {
if (__mmSyncStatus === __mmStatus) return;
((__mmSyncStatus = __mmStatus),
__mmQueueSyncStatusChat(__mmStatus),
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomStatus", {
detail: __mmStatus,
}),
),
__mmPublishHudState());
}
function __mmSyncBroadcastState() {
if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
const __mmAim = Ci(),
__mmVelocity = __mmSyncPlayerVelocity(v),
__mmAimDistance = 1800,
__mmState = {
type: "state",
x: v.x,
y: v.y,
scale: Number(v.scale) || 35,
vx: __mmVelocity.x,
vy: __mmVelocity.y,
weapon: Number(v.weaponIndex),
weapons: Array.isArray(v.weapons) ? v.weapons.slice(0, 2) : [],
build: Number(v.buildIndex),
hat: Number(v.skinIndex),
tail: Number(v.tailIndex),
combat: __mmSyncLocalCombatActive(),
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,
packetId: __mmSyncTabId + ":" + (++__mmSyncSequence),
leaderSid: v.sid,
teamKey: __mmSyncOwnTeamKey(),
sentAt: Date.now(),
}),
);
} catch (__mmSyncStorageWriteError) {}
})());
}
function __mmSyncLeaderPlayer(__mmMessage) {
const __mmState = __mmSyncLeaderState;
if (
(!__mmSyncFollowerEnabled && !__mmSyncCombatOnlyEnabled) ||
!v ||
!v.alive
)
return null;
// An atomic combat packet can beat the next periodic state packet. If the
// explicitly selected teammate is already visible, accept that live player
// immediately instead of dropping the first synced swing.
if (
__mmMessage &&
__mmMessage.leaderSid != null &&
String(__mmMessage.leaderSid) === String(__mmSyncTargetSid)
) {
let __mmDirectLeader = null;
try {
__mmDirectLeader = Rt(__mmMessage.leaderSid);
} catch (__mmDirectSyncLeaderError) {}
if (
__mmDirectLeader &&
__mmDirectLeader.alive &&
__mmDirectLeader !== v &&
__mmSameTeam(__mmDirectLeader)
)
return __mmDirectLeader;
}
if (
!__mmState ||
Date.now() - __mmState.receivedAt > 2500 ||
(__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() {
((__mmSyncLastMoveDirection = null), (__mmSyncLastMoveAt = 0));
if (!__mmSyncMoveActive) return;
((__mmSyncMoveActive = !1), (Kt = null), Tt());
}
function __mmSyncMovementStateFresh() {
if (!__mmSyncLeaderState) return !1;
const __mmFreshFor = Math.max(
550,
Math.min(1200, Number(__mmSyncRelayRtt || 0) * 3 + 300),
);
return Date.now() - Number(__mmSyncLeaderState.receivedAt || 0) <= __mmFreshFor;
}
function __mmSyncLocalCombatActive() {
return !!(
__mmInsta.isActive() ||
__mmSyncScheduledInstaTimer ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmEnemyWithinCombatRange() ||
(__mmActionOwner !== "idle" && __mmActionPriority(__mmActionOwner) >= 60)
);
}
function __mmSyncCombatActive() {
return !!(
__mmSyncLocalCombatActive() ||
Date.now() < __mmSyncLeaderCombatUntil ||
(__mmSyncFollowerEnabled &&
__mmSyncMovementStateFresh() &&
__mmSyncLeaderState &&
__mmSyncLeaderState.combat)
);
}
function __mmSyncRestoreCatchupGear() {
if (!__mmSyncCatchupActive) return;
const __mmHat = __mmSyncCatchupPreviousHat,
__mmTail = __mmSyncCatchupPreviousTail;
((__mmSyncCatchupActive = !1),
(__mmSyncCatchupPreviousHat = null),
(__mmSyncCatchupPreviousTail = null));
v && v.alive && __mmEquipGearPair(__mmHat, __mmTail, !0);
}
function __mmSyncUseCatchupGear() {
if (
!__mmSyncCatchupGearEnabled ||
!v ||
!v.alive ||
__mmSyncCombatActive()
)
return void __mmSyncRestoreCatchupGear();
const __mmPreferredHat = __mmSpeedHat(),
__mmHat =
v.skins && v.skins[__mmPreferredHat]
? __mmPreferredHat
: v.skins && v.skins[__mmBoosterHat]
? __mmBoosterHat
: null,
__mmTail =
!__mmHasStick() && v.tails && v.tails[11] ? 11 : null;
if (__mmHat == null && __mmTail == null) return;
if (!__mmSyncCatchupActive) {
((__mmSyncCatchupActive = !0),
(__mmSyncCatchupPreviousHat = __mmBaseAutomationHat()),
(__mmSyncCatchupPreviousTail = __mmBushRestoreTail(v.tailIndex)),
__mmPauseSoldierForBreaking());
}
__mmEquipGearPair(
__mmHat == null ? v.skinIndex : __mmHat,
__mmTail == null ? v.tailIndex : __mmTail,
);
}
function __mmSyncStandBesideAngle() {
const __mmState = __mmSyncLeaderState;
if (!__mmState || !v) return 0;
const __mmLeaderKey = String(__mmState.leaderSid),
__mmAimX = Number(__mmState.aimX),
__mmAimY = Number(__mmState.aimY),
__mmLeaderX = Number(__mmState.x),
__mmLeaderY = Number(__mmState.y);
if (
__mmSyncStandLeaderKey !== __mmLeaderKey ||
!Number.isFinite(__mmSyncStandAngle)
) {
const __mmAimAngle =
Number.isFinite(__mmAimX) &&
Number.isFinite(__mmAimY) &&
Number.isFinite(__mmLeaderX) &&
Number.isFinite(__mmLeaderY)
? Math.atan2(__mmAimY - __mmLeaderY, __mmAimX - __mmLeaderX)
: 0,
__mmSideSeed = parseInt(
__mmSyncHash(String(v.sid) + ":" + __mmLeaderKey),
36,
),
__mmSide = Number.isFinite(__mmSideSeed) && __mmSideSeed % 2 ? 1 : -1;
((__mmSyncStandLeaderKey = __mmLeaderKey),
(__mmSyncStandAngle = __mmAimAngle + __mmSide * Math.PI / 2));
}
return __mmSyncStandAngle;
}
function __mmSyncApplyMoveDirection(__mmDirection) {
if (!Number.isFinite(__mmDirection) || !v || !v.alive) return !1;
const __mmNow = Date.now(),
__mmDirectionDifference = Number.isFinite(__mmSyncLastMoveDirection)
? Math.abs(
Math.atan2(
Math.sin(__mmDirection - __mmSyncLastMoveDirection),
Math.cos(__mmDirection - __mmSyncLastMoveDirection),
),
)
: Infinity;
if (
!__mmSyncMoveActive ||
__mmDirectionDifference >= 0.012 ||
__mmNow - __mmSyncLastMoveAt >= __mmSyncMoveRefreshMs
)
(O.send("9", __mmDirection),
(__mmSyncLastMoveDirection = __mmDirection),
(__mmSyncLastMoveAt = __mmNow));
((Kt = __mmDirection), (__mmSyncMoveActive = !0));
return !0;
}
function __mmSyncFollowTick() {
if (
!__mmSyncFollowerEnabled ||
!__mmSyncMovementEnabled ||
!v ||
!v.alive
)
return (__mmSyncRestoreCatchupGear(), void __mmSyncStopFollowMovement());
if (!__mmSyncMovementStateFresh())
return (
__mmSetSyncStatus(
"Syncing… · waiting for " + __mmSyncTargetLabel(),
),
__mmSyncRestoreCatchupGear(),
void __mmSyncStopFollowMovement()
);
const __mmLeader = __mmSyncLeaderPlayer();
if (!__mmLeader)
return (
__mmSetSyncStatus(
"Syncing… · waiting for " + __mmSyncTargetLabel(),
),
__mmSyncRestoreCatchupGear(),
void __mmSyncStopFollowMovement()
);
// Pick one deterministic side when this teammate is acquired and keep it.
// Predict only a short distance ahead so the follower reacts with the
// leader instead of visibly trailing or orbiting around old positions.
const __mmStandAngle = __mmSyncStandBesideAngle(),
__mmHitboxDistance =
(Number(v.scale) || 35) +
(Number(__mmLeader.scale) || 35),
// Target an extra tolerance outside the requested edge gap. Even if the
// arrival test stops at its closest legal edge, the configured hitbox gap
// remains intact rather than being consumed by the stop tolerance.
__mmStandDistance =
__mmHitboxDistance + __mmSyncFollowGap + __mmSyncStopTolerance,
__mmMeasuredVelocity = __mmSyncPlayerVelocity(__mmLeader),
__mmVelocityX = Number.isFinite(Number(__mmLeader.vx))
? Number(__mmLeader.vx)
: __mmMeasuredVelocity.x,
__mmVelocityY = Number.isFinite(Number(__mmLeader.vy))
? Number(__mmLeader.vy)
: __mmMeasuredVelocity.y,
__mmStateAge = Math.max(
0,
Date.now() - Number(__mmSyncLeaderState.receivedAt || Date.now()),
),
__mmPredictionMs = Math.min(
__mmSyncPredictionMs,
__mmStateAge +
Math.max(8, __mmFastCheckMs()) +
Math.min(45, Math.max(0, Number(__mmSyncRelayRtt) || 0) / 2),
),
__mmPredictedLeaderX =
Number(__mmLeader.x) + __mmVelocityX * __mmPredictionMs,
__mmPredictedLeaderY =
Number(__mmLeader.y) + __mmVelocityY * __mmPredictionMs,
__mmTargetX =
__mmPredictedLeaderX + Math.cos(__mmStandAngle) * __mmStandDistance,
__mmTargetY =
__mmPredictedLeaderY + Math.sin(__mmStandAngle) * __mmStandDistance,
__mmDx = __mmTargetX - v.x,
__mmDy = __mmTargetY - v.y,
__mmDistanceSquared = __mmDx * __mmDx + __mmDy * __mmDy,
__mmStopDistance = __mmSyncStopTolerance,
__mmResumeDistance = Math.max(
__mmStopDistance + 1,
__mmSyncResumeTolerance,
),
__mmCatchupDistance = __mmSyncCatchupDistance,
__mmCatchupReleaseDistance = Math.min(
__mmCatchupDistance - 10,
__mmSyncCatchupReleaseDistance,
),
__mmLeaderDx = Number(v.x) - Number(__mmLeader.x),
__mmLeaderDy = Number(v.y) - Number(__mmLeader.y),
__mmCurrentCenterDistance = Math.hypot(__mmLeaderDx, __mmLeaderDy),
__mmMinimumCenterDistance = __mmHitboxDistance + __mmSyncFollowGap,
__mmSafeCenterDistance =
__mmMinimumCenterDistance + __mmSyncStopTolerance;
if (__mmSyncCombatActive()) __mmSyncRestoreCatchupGear();
else if (__mmDistanceSquared >= __mmCatchupDistance * __mmCatchupDistance)
__mmSyncUseCatchupGear();
else if (
__mmSyncCatchupActive &&
__mmDistanceSquared <=
__mmCatchupReleaseDistance * __mmCatchupReleaseDistance
)
__mmSyncRestoreCatchupGear();
__mmSetSyncStatus(
__mmSyncCatchupActive
? "Synced · " + __mmSyncTargetLabel() + " · catching up"
: "Synced · " +
__mmSyncTargetLabel() +
(__mmSyncLeaderState && __mmSyncLeaderState.kittyPeer
? " · exact"
: " · visible"),
);
// A direct collision guard wins over side positioning. Move radially away
// until the player edges are separated by the configured minimum gap plus
// the stopping buffer, then resume the normal deterministic side target.
if (__mmCurrentCenterDistance < __mmSafeCenterDistance) {
const __mmAwayDirection =
__mmCurrentCenterDistance > 0.001
? Math.atan2(__mmLeaderDy, __mmLeaderDx)
: __mmStandAngle;
(__mmSyncArrivedBeside = !1,
__mmSyncRestoreCatchupGear(),
__mmSetSyncStatus(
"Synced · " +
__mmSyncTargetLabel() +
" · spacing " +
Math.max(
0,
Math.round(__mmCurrentCenterDistance - __mmHitboxDistance),
) +
"/" +
Math.round(__mmSyncFollowGap) +
"px",
),
__mmSyncApplyMoveDirection(__mmAwayDirection));
return;
}
if (__mmSyncPauseInCombatEnabled && __mmSyncCombatActive())
return (
__mmSyncRestoreCatchupGear(),
__mmSyncStopFollowMovement(),
void __mmSetSyncStatus(
"Synced · " + __mmSyncTargetLabel() + " · combat hold",
)
);
if (
(__mmSyncMoveActive &&
__mmDistanceSquared <= __mmStopDistance * __mmStopDistance) ||
(!__mmSyncMoveActive &&
__mmDistanceSquared <= __mmResumeDistance * __mmResumeDistance)
) {
(__mmSyncArrivedBeside = !0,
__mmSyncRestoreCatchupGear(),
__mmSyncStopFollowMovement(),
__mmSetSyncStatus(
"Synced · " + __mmSyncTargetLabel() + " · beside",
));
return;
}
__mmSyncArrivedBeside = !1;
__mmSyncApplyMoveDirection(Math.atan2(__mmDy, __mmDx));
}
function __mmSyncFollowFrameTick() {
__mmSyncFollowFrame = 0;
if (
!__mmSyncFollowerEnabled ||
!__mmSyncMovementEnabled ||
!v ||
!v.alive
)
return;
(__mmSyncFollowTick(),
(__mmSyncFollowFrame = requestAnimationFrame(__mmSyncFollowFrameTick)));
}
function __mmStartSyncFollowFrames() {
__mmSyncFollowerEnabled &&
__mmSyncMovementEnabled &&
!__mmSyncFollowFrame &&
(__mmSyncFollowFrame = requestAnimationFrame(__mmSyncFollowFrameTick));
}
function __mmStopSyncFollowFrames() {
(__mmSyncFollowFrame && cancelAnimationFrame(__mmSyncFollowFrame),
(__mmSyncFollowFrame = 0));
}
document.addEventListener("visibilitychange", function () {
document.hidden
? (__mmStopSyncFollowFrames(), __mmSyncStopFollowMovement())
: __mmStartSyncFollowFrames();
});
function __mmSyncManualMovementPressed(__mmKey) {
if (
!__mmSyncFollowerEnabled ||
!__mmSyncWasdCombatOnlyEnabled ||
(__mmKey !== 87 && __mmKey !== 65 && __mmKey !== 83 && __mmKey !== 68)
)
return;
((__mmSyncFollowerEnabled = !1),
(__mmSyncCombatOnlyEnabled = !0),
(__mmSyncStandLeaderKey = ""),
(__mmSyncStandAngle = null),
(__mmSyncArrivedBeside = !1),
__mmSyncRestoreCatchupGear(),
__mmSyncStopFollowMovement(),
__mmStartTabSync(),
__mmSetSyncStatus(
"Synced · " + __mmSyncTargetLabel() + " · combat only",
),
__mmPublishHudState());
}
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 __mmSyncCombatWeapon(__mmRemoteWeapon, __mmLeader, __mmRemoteSlot) {
if (!v || !v.alive || !Array.isArray(v.weapons)) return null;
const __mmRemoteId = Number(__mmRemoteWeapon);
if (
Number.isInteger(__mmRemoteId) &&
v.weapons.some((__mmWeapon) => Number(__mmWeapon) === __mmRemoteId)
)
return __mmRemoteId;
let __mmSlot = Number(__mmRemoteSlot);
if (!Number.isInteger(__mmSlot) || __mmSlot < 0 || __mmSlot > 1)
__mmSlot = __mmPlayerWeaponSlot(__mmLeader, __mmRemoteId);
const __mmLocalWeapon = Number(v.weapons[__mmSlot]);
return Number.isInteger(__mmLocalWeapon) ? __mmLocalWeapon : null;
}
function __mmSyncPacketFresh(__mmMessage) {
const __mmPacketId = String(__mmMessage && __mmMessage.packetId || "");
if (!__mmPacketId) return !0;
if (__mmSyncSeenPackets[__mmPacketId]) return !1;
const __mmNow = Date.now();
__mmSyncSeenPackets[__mmPacketId] = __mmNow;
if (__mmSyncSequence % 64 === 0)
for (const __mmSeenId in __mmSyncSeenPackets)
__mmNow - __mmSyncSeenPackets[__mmSeenId] > 5000 &&
delete __mmSyncSeenPackets[__mmSeenId];
return !0;
}
function __mmCancelScheduledSyncInsta() {
(__mmSyncScheduledInstaTimer &&
clearTimeout(__mmSyncScheduledInstaTimer),
(__mmSyncScheduledInstaTimer = 0),
(__mmSyncScheduledInstaAt = 0));
}
function __mmSyncInstaTargetReady(__mmTarget) {
if (__mmBowUpgradeInsta.ready(__mmTarget)) return !0;
if (
!__mmTarget ||
!__mmIsEnemyPlayer(__mmTarget) ||
!__mmInsta.canFullBurst(__mmTarget)
)
return !1;
return __mmInsta.fullBurstReady(__mmTarget, "normal", !1);
}
function __mmScheduleSyncInstaAt(
__mmExecuteAt,
__mmTargetSid,
__mmOptions,
) {
if (
!__mmSyncTickCombatEnabled ||
__mmSyncScheduledInstaTimer ||
!Number.isFinite(Number(__mmExecuteAt))
)
return !1;
let __mmTarget = null;
try {
__mmTarget = Rt(__mmTargetSid);
} catch (__mmSyncTargetLookupError) {}
if (!__mmSyncInstaTargetReady(__mmTarget)) return !1;
const __mmDelay = Math.round(Number(__mmExecuteAt) - __mmSyncServerNow());
if (__mmDelay < -45 || __mmDelay > 1500) return !1;
(__mmSyncRestoreCatchupGear(),
(__mmSyncScheduledInstaAt = Number(__mmExecuteAt)),
(__mmSyncScheduledInstaTimer = setTimeout(function () {
((__mmSyncScheduledInstaTimer = 0),
(__mmSyncScheduledInstaAt = 0));
let __mmLiveTarget = null;
try {
__mmLiveTarget = Rt(__mmTargetSid);
} catch (__mmLateSyncTargetLookupError) {}
if (!__mmSyncInstaTargetReady(__mmLiveTarget)) return;
if (
__mmBowUpgradeInsta.ready(__mmLiveTarget) &&
__mmInsta.fullBurstReady(__mmLiveTarget, "normal", !1, !0)
)
__mmInsta.start({
...(__mmOptions || {}),
automatic: !!(__mmOptions && __mmOptions.automatic),
targetSid: __mmTargetSid,
syncScheduled: !0,
profile: "normal",
profileSource: "Bow Upgrade sync",
bowUpgradeFollowup: !0,
});
else if (__mmBowUpgradeInsta.ready(__mmLiveTarget))
__mmBowUpgradeInsta.start(__mmLiveTarget, "teammate tick sync");
else
__mmInsta.start({
...(__mmOptions || {}),
automatic: !!(__mmOptions && __mmOptions.automatic),
targetSid: __mmTargetSid,
syncScheduled: !0,
});
}, Math.max(0, __mmDelay))));
return !0;
}
function __mmTryScheduleSharedInsta(__mmOptions) {
if (
!__mmSyncLeaderEnabled ||
!__mmSyncTickCombatEnabled ||
!__mmSyncRelayConnected() ||
(__mmOptions && __mmOptions.betrayal)
)
return !1;
if (__mmSyncScheduledInstaTimer) return !0;
let __mmTarget = null;
try {
__mmTarget =
__mmOptions && __mmOptions.targetSid != null
? Rt(__mmOptions.targetSid)
: __mmInsta.nearestEnemy();
} catch (__mmSharedInstaTargetError) {}
if (!__mmSyncInstaTargetReady(__mmTarget)) return !1;
const __mmLead = Math.min(
700,
Math.max(
__mmServerTickMs() * 3,
__mmSyncRelayRtt * 2 + 80,
250,
),
),
__mmExecuteAt = Math.ceil(__mmSyncServerNow() + __mmLead);
__mmSyncPost({
type: "instaIntent",
targetSid: __mmTarget.sid,
executeAt: __mmExecuteAt,
});
return __mmScheduleSyncInstaAt(
__mmExecuteAt,
__mmTarget.sid,
__mmOptions || {},
);
}
function __mmSyncHandleMessage(__mmEvent) {
const __mmMessage = __mmEvent && __mmEvent.data;
if (
!__mmMessage ||
__mmMessage.sender === __mmSyncTabId ||
typeof __mmMessage !== "object" ||
String(__mmMessage.teamKey || "") !== __mmSyncOwnTeamKey() ||
!__mmSyncPacketFresh(__mmMessage)
)
return;
if (__mmMessage.type === "syncRequest") {
if (
v &&
v.alive &&
String(__mmMessage.requestedSid) === String(v.sid)
) {
let __mmRequester = null;
try {
__mmRequester = Rt(__mmMessage.leaderSid);
} catch (__mmSyncRequesterLookupError) {}
// A request grants this peer our outgoing state; it must never select
// the requester as our own movement/combat target. Reciprocity is only
// created by this player explicitly pressing Y and clicking them too.
if (!__mmRequester || __mmSameTeam(__mmRequester)) {
const __mmRequesterName = String(
(__mmRequester && __mmRequester.name) ||
"Player " + __mmMessage.leaderSid,
).trim().slice(0, 15);
((__mmSyncLeaderEnabled = !0),
__mmStartTabSync(),
__mmSyncBroadcastState(),
__mmSyncTargetSid == null &&
__mmSetSyncStatus(__mmRequesterName + " is following you"),
__mmPublishHudState());
}
}
return;
}
if (!__mmSyncFollowerEnabled && !__mmSyncCombatOnlyEnabled) return;
if (
__mmSyncTargetSid == null ||
String(__mmMessage.leaderSid) !== String(__mmSyncTargetSid)
)
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(),
kittyPeer: !0,
networkReceivedAt: Date.now(),
};
!__mmSyncFollowerEnabled &&
__mmSetSyncStatus(
"Synced · " + __mmSyncTargetLabel() + " · combat linked",
);
const __mmBuild = Number(__mmMessage.build),
__mmWeapon = Number(__mmMessage.weapon),
__mmHat = Number(__mmMessage.hat),
__mmTail = Number(__mmMessage.tail);
__mmWithSyncReplay(function () {
if (
__mmSyncCopyBuildsEnabled &&
Number.isInteger(__mmBuild) &&
__mmBuild >= 0 &&
__mmSyncOwnsSelection(__mmBuild, !1) &&
Number(v.buildIndex) !== __mmBuild
)
je(__mmBuild);
else if (
__mmSyncCopyWeaponsEnabled &&
(!Number.isInteger(__mmBuild) || __mmBuild < 0) &&
Number.isInteger(__mmWeapon) &&
__mmSyncOwnsSelection(__mmWeapon, !0) &&
(Number(v.buildIndex) >= 0 || Number(v.weaponIndex) !== __mmWeapon)
)
je(__mmWeapon, !0);
if (!__mmSyncCopyGearEnabled) return;
if (__mmSyncCatchupActive) {
(__mmCanEquipHat(__mmHat) || __mmHat === 0) &&
(__mmSyncCatchupPreviousHat = __mmHat);
((v.tails && v.tails[__mmTail]) || __mmTail === 0) &&
(__mmSyncCatchupPreviousTail = __mmTail);
} else {
(__mmCanEquipHat(__mmHat) || __mmHat === 0) &&
Number(v.skinIndex) !== __mmHat &&
__mmEquipHatNow(__mmHat);
((v.tails && v.tails[__mmTail]) || __mmTail === 0) &&
Number(v.tailIndex) !== __mmTail &&
__mmEquipTailNow(__mmTail);
}
});
__mmSyncFollowerEnabled && __mmSyncFollowTick();
}
return;
}
if (__mmMessage.type === "instaIntent") {
if (
!__mmSyncTickCombatEnabled ||
!__mmSyncLeaderPlayer(__mmMessage)
)
return;
(__mmSyncLeaderCombatUntil = Math.max(
__mmSyncLeaderCombatUntil,
Date.now() + 1200,
));
__mmSyncRestoreCatchupGear();
__mmScheduleSyncInstaAt(
Number(__mmMessage.executeAt),
__mmMessage.targetSid,
{ automatic: !0 },
);
return;
}
const __mmLeader = __mmSyncLeaderPlayer(__mmMessage);
if (!__mmLeader) return;
if (__mmMessage.type === "attack" && __mmMessage.state) {
(__mmSyncLeaderCombatUntil =
Date.now() + Math.max(500, __mmServerTickMs() * 5));
__mmSyncRestoreCatchupGear();
}
if (__mmMessage.type === "selection") {
if (
__mmMessage.isWeapon
? !__mmSyncCopyWeaponsEnabled
: !__mmSyncCopyBuildsEnabled
)
return;
if (!__mmSyncOwnsSelection(__mmMessage.item, !!__mmMessage.isWeapon)) {
__mmSyncSelectionBlockedUntil = Date.now() + 900;
return;
}
((__mmSyncSelectionBlockedUntil = 0),
__mmWithSyncReplay(function () {
je(__mmMessage.item, !!__mmMessage.isWeapon);
}));
return;
}
if (__mmMessage.type === "gear") {
if (!__mmSyncCopyGearEnabled) return;
__mmWithSyncReplay(function () {
__mmMessage.tail
? __mmEquipTailNow(__mmMessage.item)
: __mmEquipHatNow(__mmMessage.item);
});
return;
}
if (__mmMessage.type === "gearPair") {
if (!__mmSyncCopyGearEnabled) return;
__mmWithSyncReplay(function () {
__mmEquipGearPair(__mmMessage.hat, __mmMessage.tail, !0);
});
return;
}
if (__mmMessage.type === "aim") {
if (!__mmSyncCopyAimEnabled) return;
const __mmAimX = Number(__mmMessage.aimX),
__mmAimY = Number(__mmMessage.aimY);
if (Number.isFinite(__mmAimX) && Number.isFinite(__mmAimY))
__mmWithSyncReplay(function () {
O.send("D", Math.atan2(__mmAimY - v.y, __mmAimX - v.x));
});
return;
}
if (
__mmMessage.type !== "attack" ||
!__mmSyncCopyAttacksEnabled
)
return;
const __mmAimX = Number(__mmMessage.aimX),
__mmAimY = Number(__mmMessage.aimY),
__mmAngle =
__mmSyncCopyAimEnabled &&
Number.isFinite(__mmAimX) && Number.isFinite(__mmAimY)
? Math.atan2(__mmAimY - v.y, __mmAimX - v.x)
: Ci(),
__mmCombatWeapon = __mmMessage.state
? __mmSyncCombatWeapon(
__mmMessage.weapon,
__mmLeader,
__mmMessage.weaponSlot,
)
: null,
__mmCombatHat = Number(__mmMessage.hat),
__mmCombatTail = Number(__mmMessage.tail);
((__mmSyncDirectAttackAt = Date.now()),
(__mmSyncDirectAttackActive = !!__mmMessage.state)),
__mmStopObservedSyncAttack(!1);
__mmWithSyncReplay(function () {
// The combat event is atomic: select a compatible local weapon slot and
// apply the leader's owned gear immediately before the copied attack. This
// removes the race between separately delivered selection/gear/F packets.
if (
__mmMessage.state &&
__mmSyncCopyWeaponsEnabled &&
__mmCombatWeapon != null &&
(Number(v.buildIndex) >= 0 || Number(v.weaponIndex) !== __mmCombatWeapon)
)
je(__mmCombatWeapon, !0);
if (__mmMessage.state && __mmSyncCopyGearEnabled) {
const __mmHat =
(__mmCanEquipHat(__mmCombatHat) || __mmCombatHat === 0)
? __mmCombatHat
: null,
__mmTail =
((v.tails && v.tails[__mmCombatTail]) || __mmCombatTail === 0)
? __mmCombatTail
: null;
(__mmHat != null || __mmTail != null) &&
__mmEquipGearPair(__mmHat, __mmTail, !0);
}
__mmSyncCopyAimEnabled && O.send("D", __mmAngle);
O.send("F", __mmMessage.state ? 1 : 0, __mmAngle);
});
}
function __mmReceiveOpenSync(__mmDetail) {
let __mmEnvelope = __mmDetail;
try {
if (typeof __mmEnvelope === "string")
__mmEnvelope = JSON.parse(__mmEnvelope);
} catch (__mmOpenSyncParseError) {
return !1;
}
if (!__mmEnvelope || typeof __mmEnvelope !== "object") return !1;
if (
__mmEnvelope.protocol &&
String(__mmEnvelope.protocol) !== __mmOpenSyncProtocol
)
return !1;
const __mmRaw =
__mmEnvelope.packet && typeof __mmEnvelope.packet === "object"
? __mmEnvelope.packet
: __mmEnvelope.action && typeof __mmEnvelope.action === "object"
? __mmEnvelope.action
: __mmEnvelope;
if (!__mmRaw || __mmSyncTargetSid == null || !v || !v.alive) return !1;
const __mmRawType = String(__mmRaw.type || __mmRaw.action || "")
.trim()
.toLowerCase(),
__mmType =
__mmRawType === "swing" || __mmRawType === "hit"
? "attack"
: __mmRawType === "weapon" || __mmRawType === "select"
? "selection"
: __mmRawType === "hat" || __mmRawType === "tail"
? "gear"
: __mmRawType === "equipment"
? "gearPair"
: __mmRawType === "look" || __mmRawType === "rotate"
? "aim"
: __mmRawType === "gearpair"
? "gearPair"
: __mmRawType === "instaintent" || __mmRawType === "insta"
? "instaIntent"
: __mmRawType,
__mmAllowed =
__mmType === "state" ||
__mmType === "selection" ||
__mmType === "gear" ||
__mmType === "gearPair" ||
__mmType === "aim" ||
__mmType === "attack" ||
__mmType === "instaIntent";
if (!__mmAllowed) return !1;
const __mmLeaderSid =
__mmRaw.leaderSid != null
? __mmRaw.leaderSid
: __mmRaw.playerSid != null
? __mmRaw.playerSid
: __mmSyncTargetSid;
if (String(__mmLeaderSid) !== String(__mmSyncTargetSid)) return !1;
let __mmLeader = null;
try {
__mmLeader = Rt(__mmLeaderSid);
} catch (__mmOpenSyncLeaderError) {}
if (__mmLeader && !__mmSameTeam(__mmLeader)) return !1;
const __mmSource = String(
__mmEnvelope.source || __mmEnvelope.client || "other-mod",
).replace(/[^a-z0-9_.-]/gi, "").slice(0, 32) || "other-mod",
__mmSender = "open:" + __mmSource + ":" + String(__mmLeaderSid),
__mmNow = Date.now(),
__mmPacket = {
...__mmRaw,
type: __mmType,
sender: __mmSender,
packetId:
__mmSender + ":" + __mmNow + ":" + (++__mmOpenSyncSequence),
leaderSid: __mmLeaderSid,
teamKey: __mmSyncOwnTeamKey(),
sentAt: __mmNow,
};
if (__mmType === "selection") {
__mmPacket.item = Number(
__mmRaw.item != null ? __mmRaw.item : __mmRaw.weapon,
);
__mmPacket.isWeapon =
__mmRaw.isWeapon == null ? !0 : !!__mmRaw.isWeapon;
} else if (__mmType === "gear") {
__mmPacket.item = Number(
__mmRaw.item != null
? __mmRaw.item
: __mmRawType === "tail"
? __mmRaw.tail
: __mmRaw.hat,
);
__mmPacket.tail =
__mmRawType === "tail" ||
__mmRaw.tail === !0 ||
!!__mmRaw.tailSlot;
} else if (__mmType === "gearPair") {
__mmPacket.hat = Number(__mmRaw.hat);
__mmPacket.tail = Number(__mmRaw.tail);
} else if (__mmType === "attack") {
__mmPacket.state =
__mmRaw.state != null
? __mmRaw.state ? 1 : 0
: __mmRaw.down != null
? __mmRaw.down ? 1 : 0
: 1;
}
const __mmAngle = Number(
__mmRaw.angle != null ? __mmRaw.angle : __mmRaw.dir,
);
if (
(__mmType === "aim" || __mmType === "attack") &&
(!Number.isFinite(Number(__mmPacket.aimX)) ||
!Number.isFinite(Number(__mmPacket.aimY))) &&
Number.isFinite(__mmAngle)
) {
const __mmBaseX = Number(
(__mmLeader && __mmLeader.x) ||
(__mmSyncLeaderState && __mmSyncLeaderState.x) ||
v.x,
),
__mmBaseY = Number(
(__mmLeader && __mmLeader.y) ||
(__mmSyncLeaderState && __mmSyncLeaderState.y) ||
v.y,
);
((__mmPacket.aimX = __mmBaseX + Math.cos(__mmAngle) * 1800),
(__mmPacket.aimY = __mmBaseY + Math.sin(__mmAngle) * 1800));
}
const __mmPrevious = __mmSyncLeaderState || {};
__mmSyncLeaderState = {
...__mmPrevious,
sender: __mmSender,
leaderSid: __mmLeaderSid,
x: __mmLeader && __mmLeader.alive
? Number(__mmLeader.x)
: Number(__mmPrevious.x),
y: __mmLeader && __mmLeader.alive
? Number(__mmLeader.y)
: Number(__mmPrevious.y),
receivedAt: __mmNow,
kittyPeer: !0,
networkReceivedAt: __mmNow,
openSyncPeer: !0,
};
(__mmSetSyncStatus(
"Synced · " + __mmSyncTargetLabel() + " · mod bridge",
),
__mmSyncHandleMessage({ data: __mmPacket }));
return !0;
}
function __mmSyncPublishSelection(__mmItem, __mmIsWeapon) {
__mmSyncPost({
type: "selection",
item: __mmItem,
isWeapon: !!__mmIsWeapon,
});
}
function __mmSyncPublishGear(__mmItem, __mmTail) {
__mmSyncPost({ type: "gear", item: __mmItem, tail: !!__mmTail });
}
function __mmSyncPublishGearPair(__mmHat, __mmTail) {
__mmSyncPost({ type: "gearPair", hat: __mmHat, tail: __mmTail });
}
function __mmSyncObserveSocketSend(__mmArguments) {
if (!__mmSyncLeaderEnabled || !v || !v.alive) return;
if (__mmArguments[0] === "c") {
if (__mmSyncGearPairDispatch) return;
__mmSyncPublishGear(__mmArguments[2], !!__mmArguments[3]);
return;
}
if (__mmArguments[0] === "D") {
const __mmDirection = Number(__mmArguments[1]),
__mmAimDistance = 1800;
Number.isFinite(__mmDirection) &&
__mmSyncPost({
type: "aim",
aimX: v.x + Math.cos(__mmDirection) * __mmAimDistance,
aimY: v.y + Math.sin(__mmDirection) * __mmAimDistance,
});
return;
}
if (__mmArguments[0] !== "F") return;
const __mmAngle = Number(__mmArguments[2]),
__mmDirection = Number.isFinite(__mmAngle) ? __mmAngle : Ci(),
__mmAimDistance = 1800,
__mmRecentWeapon =
__mmLastSelectionWasWeapon && Date.now() - __mmLastSelectionAt <= 250
? Number(__mmLastSelectionItem)
: Number(v.weaponIndex),
__mmWeapon = Number.isInteger(__mmRecentWeapon)
? __mmRecentWeapon
: Number(v.weaponIndex),
__mmHat =
__mmPendingHat != null && Date.now() - __mmPendingHatAt <= __mmServerTickMs()
? Number(__mmPendingHat)
: Number(v.skinIndex),
__mmTail =
__mmPendingTail != null && Date.now() - __mmPendingTailAt <= __mmServerTickMs()
? Number(__mmPendingTail)
: Number(v.tailIndex);
__mmSyncPost({
type: "attack",
state: __mmArguments[1] ? 1 : 0,
aimX: v.x + Math.cos(__mmDirection) * __mmAimDistance,
aimY: v.y + Math.sin(__mmDirection) * __mmAimDistance,
weapon: __mmWeapon,
weaponSlot: __mmPlayerWeaponSlot(v, __mmWeapon),
weapons: Array.isArray(v.weapons) ? v.weapons.slice(0, 2) : [],
hat: __mmHat,
tail: __mmTail,
});
}
function __mmUpdateTabSync() {
__mmSyncRelayWanted() && !__mmSyncRelayConnected() &&
__mmConnectSyncRelay();
__mmSyncTargetSid != null && __mmRefreshSelectedSyncTarget();
if (
__mmSyncTargetSid != null &&
(!__mmSyncLeaderState || !__mmSyncLeaderState.kittyPeer) &&
Date.now() - __mmSyncRequestLastAt >= 900
) {
((__mmSyncRequestLastAt = Date.now()),
__mmSyncPost({
type: "syncRequest",
requestedSid: __mmSyncTargetSid,
}));
}
__mmSyncLeaderEnabled && __mmSyncBroadcastState();
__mmSyncFollowerEnabled && __mmStartSyncFollowFrames();
}
function __mmStartTabSync() {
(__mmConnectSyncRelay(),
__mmUpdateTabSync(),
__mmStartSyncFollowFrames(),
__mmSyncTimer ||
(__mmSyncTimer = setInterval(__mmUpdateTabSync, __mmFastCheckMs())));
}
function __mmStopTabSync() {
if (
__mmSyncLeaderEnabled ||
__mmSyncFollowerEnabled ||
__mmSyncCombatOnlyEnabled ||
__mmSyncRelayWanted()
)
return;
(__mmSyncTimer && clearInterval(__mmSyncTimer),
(__mmSyncTimer = 0),
__mmStopSyncFollowFrames(),
(__mmSyncLeaderState = null),
(__mmSyncStandLeaderKey = ""),
(__mmSyncStandAngle = null),
(__mmSyncSelectionBlockedUntil = 0),
(__mmSyncLeaderCombatUntil = 0),
__mmCancelScheduledSyncInsta(),
__mmCloseSyncRelay(!1),
__mmSyncRestoreCatchupGear(),
__mmSyncStopFollowMovement());
}
__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) {}
});
window.addEventListener("MooMooKittySyncInbound", function (__mmOpenSyncEvent) {
__mmReceiveOpenSync(__mmOpenSyncEvent && __mmOpenSyncEvent.detail);
});
window.addEventListener("MooMooModSyncInbound", function (__mmOpenSyncEvent) {
__mmReceiveOpenSync(__mmOpenSyncEvent && __mmOpenSyncEvent.detail);
});
try {
const __mmOpenSyncApi =
window.KittyKlientSync && typeof window.KittyKlientSync === "object"
? window.KittyKlientSync
: {};
Object.assign(__mmOpenSyncApi, {
protocol: __mmOpenSyncProtocol,
apiVersion: 1,
clientVersion: "${KITTY_KLIENT_VERSION}",
capabilities: [
"state",
"selection",
"gear",
"gearPair",
"aim",
"attack",
"instaIntent",
],
receive: __mmReceiveOpenSync,
getTarget: function () {
return __mmSyncTargetSid == null
? null
: {
sid: __mmSyncTargetSid,
name: __mmSyncTargetName,
movement: __mmSyncFollowerEnabled,
combat: __mmSyncFollowerEnabled || __mmSyncCombatOnlyEnabled,
};
},
});
window.KittyKlientSync = __mmOpenSyncApi;
window.dispatchEvent(
new CustomEvent("MooMooKittySyncReady", {
detail: {
protocol: __mmOpenSyncProtocol,
apiVersion: 1,
clientVersion: "${KITTY_KLIENT_VERSION}",
},
}),
);
} catch (__mmOpenSyncApiError) {}
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),
__mmFpsBoostEnabled
? ((k.fillStyle = "rgba(168,85,247,.2)"),
(k.strokeStyle = "rgba(216,180,254,.72)"),
(k.lineWidth = 2),
k.beginPath(),
k.arc(0, 0, Number(v.scale) || 35, 0, Math.PI * 2),
k.fill(),
k.stroke())
: (k.rotate(Ci() + v.dirPlus), Dl(v, k)),
k.restore());
}
function __mmDrawEspArrow(
__mmContext,
__mmOwnX,
__mmOwnY,
__mmTargetX,
__mmTargetY,
__mmOwnScale,
__mmTargetScale,
__mmColor,
__mmFriendly,
) {
const __mmDx = __mmTargetX - __mmOwnX,
__mmDy = __mmTargetY - __mmOwnY,
__mmDistance = Math.hypot(__mmDx, __mmDy);
if (!Number.isFinite(__mmDistance) || __mmDistance < 1) return;
const __mmUnitX = __mmDx / __mmDistance,
__mmUnitY = __mmDy / __mmDistance,
__mmPerpX = -__mmUnitY,
__mmPerpY = __mmUnitX,
// Keep the indicator centered in the open space instead of drawing a line
// from one player all the way to the other. It grows and softens nearby.
__mmCloseness = 1 - Math.min(1, Math.max(0, (__mmDistance - 75) / 725)),
__mmSize = 1 + 0.55 * __mmCloseness,
__mmAlpha = 0.94 - 0.22 * __mmCloseness,
__mmMidX = (__mmOwnX + __mmTargetX) * 0.5,
__mmMidY = (__mmOwnY + __mmTargetY) * 0.5,
__mmDesiredLength = (__mmFriendly ? 70 : 82) * __mmSize,
__mmArrowLength = Math.max(
30,
Math.min(__mmDesiredLength, __mmDistance * 0.55),
),
__mmHalfLength = __mmArrowLength * 0.5,
__mmHeadLength = Math.min(
__mmArrowLength * 0.48,
(__mmFriendly ? 26 : 31) * __mmSize,
),
__mmHeadHalfWidth = (__mmFriendly ? 14 : 18) * __mmSize,
__mmTailX = __mmMidX - __mmUnitX * __mmHalfLength,
__mmTailY = __mmMidY - __mmUnitY * __mmHalfLength,
__mmTipX = __mmMidX + __mmUnitX * __mmHalfLength,
__mmTipY = __mmMidY + __mmUnitY * __mmHalfLength,
__mmNeckX = __mmTipX - __mmUnitX * __mmHeadLength,
__mmNeckY = __mmTipY - __mmUnitY * __mmHeadLength,
__mmWingTopX = __mmNeckX + __mmPerpX * __mmHeadHalfWidth,
__mmWingTopY = __mmNeckY + __mmPerpY * __mmHeadHalfWidth,
__mmWingBottomX = __mmNeckX - __mmPerpX * __mmHeadHalfWidth,
__mmWingBottomY = __mmNeckY - __mmPerpY * __mmHeadHalfWidth,
__mmCoreWidth = (__mmFriendly ? 9 : 13) * __mmSize;
function __mmArrowPath(
__mmWidth,
__mmPathAlpha,
__mmBlur,
__mmStrokeColor = __mmColor,
) {
(__mmContext.save(),
(__mmContext.globalAlpha = __mmAlpha * __mmPathAlpha),
(__mmContext.strokeStyle = __mmStrokeColor),
(__mmContext.lineWidth = __mmWidth),
(__mmContext.lineCap = "round"),
(__mmContext.lineJoin = "round"),
(__mmContext.shadowColor = __mmStrokeColor),
(__mmContext.shadowBlur = __mmBlur),
__mmContext.beginPath(),
__mmContext.moveTo(__mmTailX, __mmTailY),
__mmContext.lineTo(__mmNeckX, __mmNeckY),
__mmContext.moveTo(__mmWingTopX, __mmWingTopY),
__mmContext.quadraticCurveTo(
__mmTipX - __mmUnitX * 3,
__mmTipY - __mmUnitY * 3,
__mmTipX,
__mmTipY,
),
__mmContext.quadraticCurveTo(
__mmTipX - __mmUnitX * 3,
__mmTipY - __mmUnitY * 3,
__mmWingBottomX,
__mmWingBottomY,
),
__mmContext.stroke(),
__mmContext.restore());
}
// Always keep a dark-violet silhouette under the relationship color. It
// prevents yellow, red, and purple arrows from disappearing into bright
// snow, pale structures, or the purple-tinted HUD effects.
__mmFpsBoostEnabled
? (__mmArrowPath(
__mmCoreWidth + 5,
0.9,
0,
"rgba(9,3,16,.96)",
),
__mmArrowPath(__mmCoreWidth, 1, 0))
: (__mmArrowPath(__mmCoreWidth + 12, 0.32, 18),
__mmArrowPath(
__mmCoreWidth + 5,
0.94,
2,
"rgba(9,3,16,.96)",
),
__mmArrowPath(__mmCoreWidth, 1, 8));
}
function __mmDrawNearestEnemyTarget(
__mmContext,
__mmEnemy,
__mmLeft,
__mmTop,
) {
if (!__mmEnemy || !__mmIsEnemyPlayer(__mmEnemy)) return;
const __mmX = Number(__mmEnemy.x) - __mmLeft,
__mmY = Number(__mmEnemy.y) - __mmTop,
__mmScale = Math.max(10, Number(__mmEnemy.scale) || 35),
__mmPhase =
(typeof performance !== "undefined" ? performance.now() : Date.now()) /
620,
__mmRadius = __mmScale + 11 + 1.5 * Math.sin(__mmPhase * 2);
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
__mmX < -__mmRadius * 2 ||
__mmX > _ + __mmRadius * 2 ||
__mmY < -__mmRadius * 2 ||
__mmY > L + __mmRadius * 2
)
return;
(__mmContext.save(),
(__mmContext.globalAlpha = 0.9),
(__mmContext.strokeStyle = __mmEnemyColor),
(__mmContext.fillStyle = __mmEnemyColor),
(__mmContext.shadowColor = __mmEnemyColor),
(__mmContext.shadowBlur = __mmFpsBoostEnabled ? 0 : 7),
(__mmContext.lineWidth = 2.2),
__mmContext.beginPath(),
__mmContext.arc(__mmX, __mmY, __mmRadius, 0, Math.PI * 2),
__mmContext.stroke());
for (let __mmIndex = 0; __mmIndex < 3; __mmIndex++) {
const __mmAngle = __mmPhase + (__mmIndex * Math.PI * 2) / 3,
__mmCos = Math.cos(__mmAngle),
__mmSin = Math.sin(__mmAngle),
__mmPerpX = -__mmSin,
__mmPerpY = __mmCos,
// Each orbiting arrow points inward at the selected enemy.
__mmTipRadius = __mmRadius + 2,
__mmBaseRadius = __mmRadius + 12,
__mmHalfWidth = 5,
__mmTipX = __mmX + __mmCos * __mmTipRadius,
__mmTipY = __mmY + __mmSin * __mmTipRadius,
__mmBaseX = __mmX + __mmCos * __mmBaseRadius,
__mmBaseY = __mmY + __mmSin * __mmBaseRadius;
(__mmContext.beginPath(),
__mmContext.moveTo(__mmTipX, __mmTipY),
__mmContext.lineTo(
__mmBaseX + __mmPerpX * __mmHalfWidth,
__mmBaseY + __mmPerpY * __mmHalfWidth,
),
__mmContext.lineTo(
__mmBaseX - __mmPerpX * __mmHalfWidth,
__mmBaseY - __mmPerpY * __mmHalfWidth,
),
__mmContext.closePath(),
__mmContext.fill());
}
__mmContext.restore();
}
function __mmDrawAestheticEntityMarker(
__mmContext,
__mmX,
__mmY,
__mmRadius,
__mmColor,
__mmDanger,
) {
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmRadius)
)
return;
if (!__mmSmoothVisualsEnabled) {
(__mmContext.save(),
(__mmContext.globalAlpha = 0.9),
(__mmContext.strokeStyle = __mmColor),
(__mmContext.lineWidth = 2),
__mmContext.beginPath(),
__mmContext.arc(__mmX, __mmY, __mmRadius, 0, Math.PI * 2),
__mmContext.stroke(),
__mmContext.restore());
return;
}
const __mmNow = performance.now(),
__mmPulse = __mmDanger ? 1 + Math.sin(__mmNow / 105) * 0.055 : 1,
__mmOuterRadius = (__mmRadius + (__mmDanger ? 5 : 3)) * __mmPulse;
(__mmContext.save(),
(__mmContext.fillStyle = __mmColor),
(__mmContext.strokeStyle = __mmColor),
(__mmContext.shadowColor = __mmColor),
(__mmContext.shadowBlur = __mmFpsBoostEnabled ? 0 : __mmDanger ? 15 : 8),
(__mmContext.globalAlpha = __mmDanger ? 0.12 : 0.065),
__mmContext.beginPath(),
__mmContext.arc(__mmX, __mmY, __mmOuterRadius, 0, Math.PI * 2),
__mmContext.fill(),
(__mmContext.globalAlpha = __mmDanger ? 0.92 : 0.78),
(__mmContext.lineWidth = __mmDanger ? 3 : 2),
__mmContext.beginPath(),
__mmContext.arc(__mmX, __mmY, __mmOuterRadius, 0, Math.PI * 2),
__mmContext.stroke(),
(__mmContext.shadowBlur = 0),
(__mmContext.globalAlpha = 0.62),
(__mmContext.strokeStyle = "rgba(9,3,16,.96)"),
(__mmContext.lineWidth = 1.35),
typeof __mmContext.setLineDash === "function" &&
__mmContext.setLineDash([5, 7]),
__mmContext.beginPath(),
__mmContext.arc(
__mmX,
__mmY,
Math.max(5, __mmOuterRadius - 4),
0,
Math.PI * 2,
),
__mmContext.stroke(),
__mmContext.restore());
}
function __mmDrawEsp() {
if (!v || !v.alive || !k) return;
try {
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2;
__mmDrawPredictionGhost(__mmLeft, __mmTop);
if (
(!__mmEspEnabled && !__mmEspLinesEnabled && !__mmEntityDangerEnabled) ||
!Array.isArray(E) ||
!Array.isArray(N)
)
return;
const __mmOwnX = v.x - __mmLeft,
__mmOwnY = v.y - __mmTop;
(k.save(), (k.globalAlpha = 0.72));
if (__mmEspLinesEnabled) {
let __mmArrowCount = 0;
const __mmArrowLimit = __mmFpsBoostEnabled ? 12 : Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid
)
continue;
const __mmFriendly =
__mmIsFriendPlayer(__mmPlayer) || __mmSameTeam(__mmPlayer),
__mmColor = __mmIsFriendPlayer(__mmPlayer)
? __mmFriendColor
: __mmSameTeam(__mmPlayer)
? __mmAllyColor
: __mmEnemyColor,
__mmX = __mmPlayer.x - __mmLeft,
__mmY = __mmPlayer.y - __mmTop;
__mmDrawEspArrow(
k,
__mmOwnX,
__mmOwnY,
__mmX,
__mmY,
v.scale,
__mmPlayer.scale,
__mmColor,
__mmFriendly,
);
if (++__mmArrowCount >= __mmArrowLimit) break;
}
}
if (__mmEspEnabled || __mmEntityDangerEnabled) {
((k.lineWidth = 2), (k.globalAlpha = 0.9));
let __mmPlayerCircleCount = 0;
const __mmPlayerCircleLimit = __mmFpsBoostEnabled ? 12 : Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid
)
continue;
const __mmFriendly =
__mmIsFriendPlayer(__mmPlayer) || __mmSameTeam(__mmPlayer),
__mmColor = __mmIsFriendPlayer(__mmPlayer)
? __mmFriendColor
: __mmSameTeam(__mmPlayer)
? __mmAllyColor
: __mmEnemyColor,
__mmDanger = !!(
__mmEntityDangerEnabled &&
!__mmFriendly &&
Math.hypot(__mmPlayer.x - v.x, __mmPlayer.y - v.y) <=
Math.max(650, __mmCombatRange)
);
if (!__mmEspEnabled && !__mmDanger) continue;
__mmDrawAestheticEntityMarker(
k,
__mmPlayer.x - __mmLeft,
__mmPlayer.y - __mmTop,
Math.max(10, (__mmPlayer.scale || 35) + 5),
__mmColor,
__mmDanger,
);
if (++__mmPlayerCircleCount >= __mmPlayerCircleLimit) break;
}
let __mmAnimalCircleCount = 0;
const __mmAnimalCircleLimit = __mmFpsBoostEnabled ? 10 : Infinity;
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
const __mmAnimal = N[__mmIndex];
if (!__mmAnimal || !__mmAnimal.active || !__mmAnimal.visible) continue;
const __mmAnimalDanger = !!(
__mmEntityDangerEnabled && __mmAnimal.hostile
),
__mmAnimalColor = __mmAnimalDanger ? __mmEnemyColor : "#48df79";
if (!__mmEspEnabled && !__mmAnimalDanger) continue;
__mmDrawAestheticEntityMarker(
k,
__mmAnimal.x - __mmLeft,
__mmAnimal.y - __mmTop,
Math.max(9, (__mmAnimal.scale || 35) + 4),
__mmAnimalColor,
__mmAnimalDanger,
);
if (++__mmAnimalCircleCount >= __mmAnimalCircleLimit) break;
}
__mmEspEnabled &&
__mmDrawNearestEnemyTarget(k, __mmNearestEnemy(), __mmLeft, __mmTop);
}
k.restore();
} catch (__mmError) {
try {
k && k.restore();
} catch (__mmIgnore) {}
}
}
function __mmDrawReloadArcs() {
if (!__mmReloadArcsEnabled || !v || !v.alive || !k) return;
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2,
__mmNow = Date.now(),
__mmEnemy = __mmNearestEnemy(),
__mmPlayers = __mmEnemy && __mmEnemy !== v ? [v, __mmEnemy] : [v],
__mmColors = ["#a855f7", "#d8b4fe", "#f0abfc"];
try {
k.save();
for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
const __mmPlayer = __mmPlayers[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
(__mmPlayer !== v && !__mmPlayer.visible)
)
continue;
const __mmX = Number(__mmPlayer.x) - __mmLeft,
__mmY = Number(__mmPlayer.y) - __mmTop,
__mmScale = Math.max(15, Number(__mmPlayer.scale) || 35);
if (!ts(__mmX, __mmY, __mmScale + 25)) continue;
const __mmRows = __mmVisualCooldownRows(__mmPlayer, __mmNow);
for (let __mmRowIndex = 0; __mmRowIndex < __mmRows.length; __mmRowIndex++) {
const __mmRow = __mmRows[__mmRowIndex],
__mmSlot = Math.max(0, Math.min(2, Number(__mmRow.slot) || 0)),
__mmRatio = Math.max(0, Math.min(1, Number(__mmRow.ratio) || 0)),
__mmRadius = __mmScale + 8 + __mmSlot * 4.5,
__mmStart = -Math.PI * 0.88,
__mmSweep = Math.PI * 1.76,
__mmColor = __mmColors[__mmSlot];
((k.shadowBlur = 0),
(k.globalAlpha = 0.42),
(k.strokeStyle = "rgba(9,3,16,.96)"),
(k.lineWidth = 3.8),
(k.lineCap = "round"),
k.beginPath(),
k.arc(__mmX, __mmY, __mmRadius, __mmStart, __mmStart + __mmSweep),
k.stroke());
if (__mmRatio <= 0.001) continue;
((k.globalAlpha = __mmRatio >= 0.995 ? 0.96 : 0.82),
(k.strokeStyle = __mmColor),
(k.shadowColor = __mmColor),
(k.shadowBlur = __mmFpsBoostEnabled ? 0 : __mmRatio >= 0.995 ? 8 : 4),
(k.lineWidth = 2.4),
k.beginPath(),
k.arc(
__mmX,
__mmY,
__mmRadius,
__mmStart,
__mmStart + __mmSweep * __mmRatio,
),
k.stroke());
}
}
k.restore();
} catch (__mmReloadArcError) {
try {
k && k.restore();
} catch (__mmIgnore) {}
}
}
const __mmOriginalStructureSprite = Di,
__mmStructureTintCache = Object.create(null),
__mmStructureTintImageCache = new WeakMap();
function __mmStructureOwnerSid(__mmObject) {
if (!__mmObject) return null;
const __mmOwner = __mmObject.owner;
if (__mmOwner == null)
return __mmObject.ownerSid != null
? __mmObject.ownerSid
: __mmObject.ownerSID != null
? __mmObject.ownerSID
: null;
if (typeof __mmOwner === "object" && __mmOwner.sid != null)
return __mmOwner.sid;
if (typeof __mmOwner === "number" || typeof __mmOwner === "string")
return __mmOwner;
return __mmObject.ownerSid != null
? __mmObject.ownerSid
: __mmObject.ownerSID != null
? __mmObject.ownerSID
: null;
}
function __mmStructureOwnerPlayer(__mmObject) {
if (!__mmObject) return null;
const __mmOwner = __mmObject.owner,
__mmOwnerSid = __mmStructureOwnerSid(__mmObject);
if (__mmOwner === v) return v;
if (__mmOwnerSid != null && typeof Rt === "function") {
const __mmPlayer = Rt(__mmOwnerSid);
if (__mmPlayer) return __mmPlayer;
}
return typeof __mmOwner === "object" ? __mmOwner : null;
}
function __mmOwnStructure(__mmObject) {
if (!v || !__mmObject) return !1;
const __mmOwner = __mmObject.owner,
__mmOwnerSid = __mmStructureOwnerSid(__mmObject);
return !!(
__mmOwner === v ||
(__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
);
}
function __mmTintableStructure(__mmObject) {
const __mmItem = __mmObject && b && b.list && b.list[__mmObject.id];
// Every server-owned player placeable carries an item id and owner. Keeping
// this generic covers walls, pads, teleporters, mills, traps, spikes and
// turrets even when MooMoo changes an item's display name.
return !!(
__mmObject &&
__mmObject.isItem &&
__mmStructureOwnerSid(__mmObject) != null &&
__mmItem
);
}
function __mmFriendlyStructure(__mmObject) {
if (!v || !__mmObject || __mmStructureOwnerSid(__mmObject) == null) return !1;
if (__mmOwnStructure(__mmObject)) return !0;
const __mmOwner = __mmStructureOwnerPlayer(__mmObject);
if (!__mmOwner) return !1;
if (__mmSameTeam(__mmOwner)) return !0;
return __mmIsFriendPlayer(__mmOwner);
}
function __mmStructureRelationship(__mmObject) {
return __mmOwnStructure(__mmObject)
? "own"
: __mmFriendlyStructure(__mmObject)
? "friendly"
: "enemy";
}
function __mmStructureRelationshipColor(__mmRelationship) {
return __mmRelationship === "own"
? __mmOwnColor
: __mmRelationship === "friendly"
? __mmAllyColor
: __mmEnemyColor;
}
function __mmTintedStructureSprite(
__mmObject,
__mmRelationship,
__mmProvidedBase,
) {
const __mmBase = __mmProvidedBase || __mmOriginalStructureSprite(__mmObject),
__mmKind =
__mmRelationship === "own"
? "own"
: __mmRelationship === "friendly" || __mmRelationship === !0
? "friendly"
: "enemy",
__mmColor = __mmStructureRelationshipColor(__mmKind);
if (!__mmBase || !__mmBase.width || !__mmBase.height) return __mmBase;
let __mmImageTints =
typeof __mmBase === "object"
? __mmStructureTintImageCache.get(__mmBase)
: null;
if (!__mmImageTints && typeof __mmBase === "object") {
(__mmImageTints = Object.create(null),
__mmStructureTintImageCache.set(__mmBase, __mmImageTints));
}
const __mmTintKind = __mmKind + ":" + __mmColor;
if (__mmImageTints && __mmImageTints[__mmTintKind])
return __mmImageTints[__mmTintKind];
const __mmAssetKey = String(
__mmBase.currentSrc || __mmBase.src || "native",
),
__mmKey = String(__mmObject.id) + ":" + __mmColor + ":" +
__mmAssetKey + ":" + __mmBase.width + "x" + __mmBase.height;
let __mmTinted = __mmStructureTintCache[__mmKey];
if (__mmTinted) {
__mmImageTints && (__mmImageTints[__mmTintKind] = __mmTinted);
return __mmTinted;
}
__mmTinted = document.createElement("canvas");
__mmTinted.width = __mmBase.width;
__mmTinted.height = __mmBase.height;
const __mmContext = __mmTinted.getContext("2d");
(__mmContext.drawImage(__mmBase, 0, 0),
(__mmContext.globalCompositeOperation = "source-atop"),
(__mmContext.globalAlpha = __mmKind === "own" ? 0.7 : 0.8),
(__mmContext.fillStyle = __mmColor),
__mmContext.fillRect(0, 0, __mmTinted.width, __mmTinted.height),
(__mmContext.globalCompositeOperation = "source-over"),
(__mmContext.globalAlpha = 0.34),
__mmContext.drawImage(__mmBase, 0, 0));
(__mmStructureTintCache[__mmKey] = __mmTinted,
__mmImageTints && (__mmImageTints[__mmTintKind] = __mmTinted));
return __mmTinted;
}
// Tint the official sprite itself instead of painting a second, position-based
// copy over the object. MooMoo's renderer now owns every transform and culling
// decision, so ownership color cannot drift with camera movement or disappear
// behind Kitty's FPS overlay budget.
Di = function (__mmObject) {
const __mmBase = __mmOriginalStructureSprite.apply(this, arguments);
if (!v || !v.alive || !__mmTintableStructure(__mmObject)) return __mmBase;
try {
return __mmTintedStructureSprite(
__mmObject,
__mmStructureRelationship(__mmObject),
__mmBase,
);
} catch (__mmTintError) {
return __mmBase;
}
};
const __mmBreakableLabelRange = 950,
__mmBreakableLabelLimit = 72;
let __mmObjectSnapshotAt = 0,
__mmObjectSnapshotSource = null,
__mmObjectSnapshotLength = -1,
__mmObjectSnapshotCache = {
all: [],
breakables: [],
traps: [],
spikes: [],
turrets: [],
mills: [],
};
function __mmActiveObjectSnapshot(__mmForce) {
const __mmSource = Array.isArray(ge) ? ge : null,
__mmNow = performance.now(),
__mmRefreshMs = Math.max(40, Math.min(75, __mmFastCheckMs() * 2));
if (
!__mmForce &&
__mmSource === __mmObjectSnapshotSource &&
(__mmSource ? __mmSource.length : 0) === __mmObjectSnapshotLength &&
__mmNow - __mmObjectSnapshotAt < __mmRefreshMs
)
return __mmObjectSnapshotCache;
const __mmNext = {
all: [],
breakables: [],
traps: [],
spikes: [],
turrets: [],
mills: [],
},
__mmLabelRange = __mmFpsBoostEnabled
? Math.min(__mmBreakableLabelRange, 600)
: __mmBreakableLabelRange,
__mmLabelLimit = __mmFpsBoostEnabled
? Math.min(__mmBreakableLabelLimit, 12)
: __mmBreakableLabelLimit,
__mmLabelRangeSquared = __mmLabelRange * __mmLabelRange;
if (__mmSource)
for (let __mmIndex = 0; __mmIndex < __mmSource.length; __mmIndex++) {
const __mmObject = __mmSource[__mmIndex];
if (!__mmObject || !__mmObject.active) continue;
__mmNext.all.push(__mmObject);
const __mmData = b && b.list && b.list[__mmObject.id],
__mmName = String((__mmData && __mmData.name) || "").toLowerCase();
__mmObject.trap && __mmNext.traps.push(__mmObject);
__mmName.includes("spikes") && __mmNext.spikes.push(__mmObject);
__mmName === "turret" && __mmNext.turrets.push(__mmObject);
(__mmName === "windmill" ||
__mmName === "faster windmill" ||
__mmName === "power mill") &&
__mmNext.mills.push(__mmObject);
if (
v &&
v.alive &&
Number.isFinite(Number(__mmObject.health)) &&
Number(__mmObject.health) > 0
) {
const __mmDx = Number(__mmObject.x) - Number(v.x),
__mmDy = Number(__mmObject.y) - Number(v.y),
__mmDistanceSquared = __mmDx * __mmDx + __mmDy * __mmDy;
Number.isFinite(__mmDistanceSquared) &&
__mmDistanceSquared <= __mmLabelRangeSquared &&
__mmNext.breakables.push({
object: __mmObject,
distanceSquared: __mmDistanceSquared,
});
}
}
if (__mmNext.breakables.length > __mmLabelLimit) {
__mmNext.breakables.sort(
(__mmFirst, __mmSecond) =>
__mmFirst.distanceSquared - __mmSecond.distanceSquared,
);
__mmNext.breakables.length = __mmLabelLimit;
}
((__mmObjectSnapshotAt = __mmNow),
(__mmObjectSnapshotSource = __mmSource),
(__mmObjectSnapshotLength = __mmSource ? __mmSource.length : 0),
(__mmObjectSnapshotCache = __mmNext));
return __mmNext;
}
let __mmGroundGridFrameDrawn = !1;
function __mmDrawGroundGrid(__mmLeft, __mmTop) {
if (
__mmHudMenuOpen ||
__mmNativeMenuOpen ||
!__mmGroundGridEnabled ||
(document.documentElement &&
document.documentElement.getAttribute("data-kitty-ground-grid") === "0") ||
!v ||
!v.alive ||
!k
)
return;
const __mmViewLeft = Number.isFinite(Number(__mmLeft))
? Number(__mmLeft)
: Number(oe) - Number(_) / 2,
__mmViewTop = Number.isFinite(Number(__mmTop))
? Number(__mmTop)
: Number(ae) - Number(L) / 2,
__mmViewWidth = Math.max(1, Number(_) || k.canvas.width || 1),
__mmViewHeight = Math.max(1, Number(L) || k.canvas.height || 1),
__mmMinorStep = 100,
__mmMajorStep = 500,
// The game context already maps these world-space viewport units onto the
// physical canvas. Applying the zoom ratio again double-scaled the grid
// toward the top-left. One cell of overscan prevents edge gaps and keeps
// full-screen coverage while the camera moves between grid coordinates.
__mmOverscan = __mmMinorStep,
__mmMinWorldX = __mmViewLeft - __mmOverscan,
__mmMaxWorldX = __mmViewLeft + __mmViewWidth + __mmOverscan,
__mmMinWorldY = __mmViewTop - __mmOverscan,
__mmMaxWorldY = __mmViewTop + __mmViewHeight + __mmOverscan,
__mmMinScreenX = -__mmOverscan,
__mmMaxScreenX = __mmViewWidth + __mmOverscan,
__mmMinScreenY = -__mmOverscan,
__mmMaxScreenY = __mmViewHeight + __mmOverscan;
const __mmTraceGrid = function (__mmStep, __mmSkipMajor) {
k.beginPath();
let __mmWorld = Math.ceil(__mmMinWorldX / __mmStep) * __mmStep;
for (; __mmWorld <= __mmMaxWorldX; __mmWorld += __mmStep) {
if (__mmSkipMajor && __mmWorld % __mmMajorStep === 0) continue;
const __mmScreenX = Math.round(__mmWorld - __mmViewLeft) + 0.5;
(k.moveTo(__mmScreenX, __mmMinScreenY),
k.lineTo(__mmScreenX, __mmMaxScreenY));
}
__mmWorld = Math.ceil(__mmMinWorldY / __mmStep) * __mmStep;
for (; __mmWorld <= __mmMaxWorldY; __mmWorld += __mmStep) {
if (__mmSkipMajor && __mmWorld % __mmMajorStep === 0) continue;
const __mmScreenY = Math.round(__mmWorld - __mmViewTop) + 0.5;
(k.moveTo(__mmMinScreenX, __mmScreenY),
k.lineTo(__mmMaxScreenX, __mmScreenY));
}
k.stroke();
};
try {
(k.save(),
(k.globalAlpha = __mmFpsBoostEnabled ? 0.13 : 0.16),
(k.strokeStyle = "#6d28d9"),
(k.lineWidth = 1),
__mmTraceGrid(__mmMinorStep, !0),
(k.globalAlpha = __mmFpsBoostEnabled ? 0.22 : 0.28),
(k.strokeStyle = "#c084fc"),
(k.lineWidth = 1.5),
__mmTraceGrid(__mmMajorStep, !1),
k.restore());
} catch (__mmGroundGridError) {
try {
k.restore();
} catch (__mmGroundGridRestoreError) {}
}
}
function __mmDrawAutoSpikeSpamGhost() {
const __mmGhost = __mmAutoSpikeSpamGhost,
__mmData = __mmGhost && b && b.list && b.list[__mmGhost.item];
if (!v || !v.alive || !__mmGhost || !__mmData || !k) return;
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2,
__mmX = __mmGhost.x - __mmLeft,
__mmY = __mmGhost.y - __mmTop;
if (!ts(__mmX, __mmY, __mmGhost.scale + 12)) return;
const __mmSprite = __mmTintedStructureSprite(__mmData, "friendly");
(k.save(),
(k.globalAlpha = 0.42),
k.translate(__mmX, __mmY),
k.rotate(__mmGhost.angle),
k.drawImage(
__mmSprite,
-__mmSprite.width / 2,
-__mmSprite.height / 2,
),
k.rotate(-__mmGhost.angle),
(k.globalAlpha = 0.9),
(k.strokeStyle = "#c084fc"),
(k.lineWidth = 2),
k.setLineDash([5, 4]),
k.beginPath(),
k.arc(0, 0, __mmGhost.scale + 3, 0, Math.PI * 2),
k.stroke(),
k.restore());
}
function __mmBreakableState(__mmObject) {
if (!__mmObject || !Number.isFinite(Number(__mmObject.health))) return null;
const __mmBaseHealth = Number(__mmObject.health);
if (__mmBaseHealth <= 0) return null;
let __mmState = __mmBreakableHealth.get(__mmObject);
if (
!__mmState ||
String(__mmState.sid) !== String(__mmObject.sid) ||
__mmState.baseHealth !== __mmBaseHealth
) {
__mmState = {
sid: __mmObject.sid,
baseHealth: __mmBaseHealth,
health: __mmBaseHealth,
};
__mmBreakableHealth.set(__mmObject, __mmState);
}
return __mmState;
}
function __mmPlayerHatData(__mmPlayer) {
if (!__mmPlayer || !Array.isArray(Ze)) return null;
for (let __mmIndex = 0; __mmIndex < Ze.length; __mmIndex++)
if (Ze[__mmIndex].id === __mmPlayer.skinIndex) return Ze[__mmIndex];
return null;
}
function __mmToolCooldownDuration(__mmPlayer, __mmWeaponId) {
const __mmWeapon = b && b.weapons && b.weapons[__mmWeaponId];
if (!__mmWeapon) return 0;
const __mmBaseSpeed = Number(__mmWeapon.speed),
__mmHat = __mmPlayerHatData(__mmPlayer),
__mmHatSpeed = Number(__mmHat && __mmHat.atkSpd),
__mmMultiplier = Number.isFinite(__mmHatSpeed) && __mmHatSpeed > 0
? __mmHatSpeed
: 1;
return Number.isFinite(__mmBaseSpeed) && __mmBaseSpeed > 0
? Math.max(1, __mmBaseSpeed * __mmMultiplier)
: 0;
}
function __mmTurretCooldownDuration(__mmPlayer) {
const __mmHat = Array.isArray(Ze)
? Ze.find(function (__mmEntry) {
return __mmEntry && Number(__mmEntry.id) === __mmTurretGear;
})
: null,
__mmRate = Number(__mmHat && __mmHat.turret && __mmHat.turret.rate);
return Number.isFinite(__mmRate) && __mmRate > 0 ? __mmRate : 2500;
}
function __mmCooldownStateForSid(__mmPlayerSid, __mmNow = Date.now()) {
if (__mmPlayerSid == null) return null;
const __mmKey = String(__mmPlayerSid);
return (
__mmPlayerToolCooldowns[__mmKey] ||
(__mmPlayerToolCooldowns[__mmKey] = {
weapons: Object.create(null),
slots: [null, null],
turret: null,
updatedAt: __mmNow,
advancedAt: __mmNow,
})
);
}
function __mmPlayerWeaponSlot(__mmPlayer, __mmWeaponId) {
const __mmId = Number(__mmWeaponId);
if (!Number.isInteger(__mmId)) return null;
if (__mmPlayer && Array.isArray(__mmPlayer.weapons)) {
if (Number(__mmPlayer.weapons[0]) === __mmId) return 0;
if (Number(__mmPlayer.weapons[1]) === __mmId) return 1;
}
if (__mmPlayer && Number(__mmPlayer.primaryIndex) === __mmId) return 0;
if (__mmPlayer && Number(__mmPlayer.secondaryIndex) === __mmId) return 1;
return __mmId >= 9 ? 1 : 0;
}
function __mmProjectileWeapon(__mmPlayer, __mmProjectile) {
if (!__mmPlayer || !b || !b.weapons) return null;
const __mmCandidates = [],
__mmSeen = new Set();
function __mmAdd(__mmWeaponId) {
const __mmId = Number(__mmWeaponId),
__mmData = b.weapons[__mmId];
if (
!Number.isInteger(__mmId) ||
__mmSeen.has(__mmId) ||
!__mmData ||
__mmData.projectile == null
)
return;
(__mmSeen.add(__mmId), __mmCandidates.push(__mmId));
}
if (
v &&
String(__mmPlayer.sid) === String(v.sid) &&
__mmLastSelectionWasWeapon &&
Date.now() - __mmLastSelectionAt <= 300
)
__mmAdd(__mmLastSelectionItem);
(__mmAdd(__mmPlayer.weaponIndex),
Array.isArray(__mmPlayer.weapons) &&
__mmPlayer.weapons.forEach(__mmAdd),
__mmAdd(__mmPlayer.primaryIndex),
__mmAdd(__mmPlayer.secondaryIndex));
if (!__mmCandidates.length || !b.projectiles) return null;
const __mmLiveSpeed = Number(__mmProjectile && __mmProjectile.speed),
__mmLiveDamage = Number(__mmProjectile && __mmProjectile.dmg),
__mmLiveScale = Number(__mmProjectile && __mmProjectile.scale);
let __mmBest = __mmCandidates[0],
__mmBestScore = Infinity;
for (let __mmIndex = 0; __mmIndex < __mmCandidates.length; __mmIndex++) {
const __mmWeaponId = __mmCandidates[__mmIndex],
__mmWeapon = b.weapons[__mmWeaponId],
__mmData = b.projectiles[__mmWeapon.projectile],
__mmSpeed = Number(__mmData && __mmData.speed),
__mmDamage = Number(__mmData && __mmData.dmg),
__mmScale = Number(__mmData && __mmData.scale);
let __mmScore = 0,
__mmEvidence = 0;
if (Number.isFinite(__mmLiveSpeed) && Number.isFinite(__mmSpeed)) {
(__mmEvidence++,
(__mmScore +=
Math.abs(__mmLiveSpeed - __mmSpeed) /
Math.max(0.15, Math.abs(__mmSpeed))));
}
if (Number.isFinite(__mmLiveDamage) && Number.isFinite(__mmDamage)) {
(__mmEvidence++,
(__mmScore +=
Math.abs(__mmLiveDamage - __mmDamage) /
Math.max(5, Math.abs(__mmDamage))));
}
if (Number.isFinite(__mmLiveScale) && Number.isFinite(__mmScale)) {
(__mmEvidence++,
(__mmScore +=
Math.abs(__mmLiveScale - __mmScale) /
Math.max(5, Math.abs(__mmScale))));
}
__mmEvidence || (__mmScore = Infinity);
if (__mmScore < __mmBestScore)
((__mmBestScore = __mmScore), (__mmBest = __mmWeaponId));
}
// A player-owned Turret Gear bullet must not be guessed as their currently
// held bow or musket. Reject poor projectile-data matches instead.
return __mmBestScore <= 0.38 ? __mmBest : null;
}
function __mmProjectileIsTurretGearShot(__mmPlayer, __mmProjectile) {
if (!__mmPlayer || !__mmProjectile || !b || !b.projectiles) return !1;
const __mmTurretProjectile = b.projectiles[1];
if (!__mmTurretProjectile) return !1;
const __mmLiveSpeed = Number(__mmProjectile.speed),
__mmLiveDamage = Number(__mmProjectile.dmg),
__mmLiveScale = Number(__mmProjectile.scale),
__mmSpeed = Number(__mmTurretProjectile.speed),
__mmDamage = Number(__mmTurretProjectile.dmg),
__mmScale = Number(__mmTurretProjectile.scale),
__mmLooksLikeTurret =
(!Number.isFinite(__mmLiveSpeed) ||
!Number.isFinite(__mmSpeed) ||
Math.abs(__mmLiveSpeed - __mmSpeed) <= Math.max(0.08, __mmSpeed * 0.08)) &&
(!Number.isFinite(__mmLiveDamage) ||
!Number.isFinite(__mmDamage) ||
Math.abs(__mmLiveDamage - __mmDamage) <= 1) &&
(!Number.isFinite(__mmLiveScale) ||
!Number.isFinite(__mmScale) ||
Math.abs(__mmLiveScale - __mmScale) <= 2),
__mmDirectPlayerOwner = __mmProjectilePlayerOwner(__mmProjectile),
__mmHasTurretEvidence = !!(
(Number.isFinite(__mmLiveSpeed) && Number.isFinite(__mmSpeed)) ||
(Number.isFinite(__mmLiveDamage) && Number.isFinite(__mmDamage)) ||
(Number.isFinite(__mmLiveScale) && Number.isFinite(__mmScale))
);
// Projectile type 1 is exclusive to Turret Gear/structures in the current
// item table. Structure owners were rejected before this helper, so a data
// match here remains valid even after a fast client has restored its hat.
return !!(
__mmHasTurretEvidence &&
__mmLooksLikeTurret &&
__mmDirectPlayerOwner &&
String(__mmDirectPlayerOwner.sid) === String(__mmPlayer.sid)
);
}
function __mmProjectilePlayerOwner(__mmProjectile) {
const __mmOwner = __mmProjectile && __mmProjectile.owner;
if (!__mmOwner || typeof __mmOwner !== "object") return null;
// Nested owners are structures such as turrets; their shots must not reset
// a handheld weapon bar on the structure's owner.
if (__mmOwner.owner && !Array.isArray(__mmOwner.weapons)) return null;
if (__mmOwner === v) return v;
if (
Array.isArray(__mmOwner.weapons) ||
Number.isInteger(Number(__mmOwner.weaponIndex))
)
return __mmOwner;
if (__mmOwner.sid == null || typeof Rt !== "function") return null;
try {
return Rt(__mmOwner.sid) || null;
} catch (__mmLookupError) {
return null;
}
}
function __mmObserveProjectileCooldowns() {
const __mmNow = Date.now();
if (
(!__mmCooldownBarsEnabled && !__mmMusketRechargeEnabled) ||
!Array.isArray(Ve) ||
__mmNow - __mmProjectileCooldownLastScanAt < 20
)
return;
__mmProjectileCooldownLastScanAt = __mmNow;
for (let __mmIndex = 0; __mmIndex < Ve.length; __mmIndex++) {
const __mmProjectile = Ve[__mmIndex];
if (!__mmProjectile || typeof __mmProjectile !== "object") continue;
const __mmPrevious = __mmProjectileCooldownStates.get(__mmProjectile),
__mmSid = __mmProjectile.sid == null ? "" : String(__mmProjectile.sid),
__mmRange = Number(__mmProjectile.range),
__mmNewGeneration = !!(
__mmProjectile.active &&
(!__mmPrevious ||
!__mmPrevious.active ||
__mmPrevious.sid !== __mmSid ||
(Number.isFinite(__mmRange) &&
Number.isFinite(__mmPrevious.range) &&
__mmRange > __mmPrevious.range + 20))
);
__mmProjectileCooldownStates.set(__mmProjectile, {
active: !!__mmProjectile.active,
sid: __mmSid,
range: __mmRange,
});
if (!__mmNewGeneration) continue;
const __mmPlayer = __mmProjectilePlayerOwner(__mmProjectile);
if (!__mmPlayer || __mmPlayer.sid == null) continue;
if (__mmProjectileIsTurretGearShot(__mmPlayer, __mmProjectile)) {
__mmTrackPlayerTurretCooldown(__mmPlayer.sid, "projectile");
continue;
}
const __mmWeapon = __mmProjectileWeapon(__mmPlayer, __mmProjectile);
__mmWeapon != null &&
__mmTrackPlayerToolCooldown(__mmPlayer.sid, __mmWeapon, "projectile");
}
}
function __mmObserveOutgoingProjectileAttack(__mmArguments) {
if (
!__mmArguments ||
__mmArguments[0] !== "F" ||
Number(__mmArguments[1]) !== 1 ||
!v ||
!v.alive ||
!b ||
!b.weapons
)
return;
let __mmWeapon = null;
if (Date.now() - __mmLastSelectionAt <= 180) {
if (!__mmLastSelectionWasWeapon) return;
__mmWeapon = Number(__mmLastSelectionItem);
} else if (Number(v.buildIndex) < 0) {
__mmWeapon = Number(v.weaponIndex);
}
const __mmData = b.weapons[__mmWeapon];
if (
!Number.isInteger(__mmWeapon) ||
!__mmData ||
__mmData.projectile == null ||
__mmWeaponIsReloading(__mmWeapon)
)
return;
// Projectile attacks do not consistently emit the melee swing callback.
// Start the local bar optimistically; the spawned projectile below corrects
// the timestamp without waiting for a server confirmation round trip.
__mmTrackPlayerToolCooldown(v.sid, __mmWeapon, "outgoing-projectile");
}
function __mmTrackPlayerToolCooldown(
__mmPlayerSid,
__mmWeaponId,
__mmSource = "swing",
) {
if (__mmPlayerSid == null) return;
let __mmPlayer = null;
try {
__mmPlayer = Rt(__mmPlayerSid);
} catch (__mmLookupError) {}
if (
!__mmPlayer &&
v &&
v.sid != null &&
String(v.sid) === String(__mmPlayerSid)
)
__mmPlayer = v;
const __mmResolvedWeapon = Number(
__mmWeaponId == null && __mmPlayer
? __mmPlayer.weaponIndex
: __mmWeaponId,
),
__mmDuration = __mmToolCooldownDuration(
__mmPlayer,
__mmResolvedWeapon,
);
if (!Number.isInteger(__mmResolvedWeapon) || !__mmDuration) return;
const __mmKey = String(__mmPlayerSid),
__mmNow = Date.now(),
__mmState = __mmCooldownStateForSid(__mmKey, __mmNow);
__mmAdvancePlayerToolCooldowns(__mmPlayer, __mmNow);
Array.isArray(__mmState.slots) || (__mmState.slots = [null, null]);
const __mmSlot = __mmPlayerWeaponSlot(__mmPlayer, __mmResolvedWeapon);
(__mmSlot === 0 || __mmSlot === 1) &&
(__mmState.slots[__mmSlot] = __mmResolvedWeapon);
const __mmExisting = __mmState.weapons[String(__mmResolvedWeapon)];
const __mmProjectileDedupeWindow = Math.min(
350,
Math.max(90, __mmDuration * 0.5),
);
if (
__mmExisting &&
__mmNow - Number(__mmExisting.startedAt) <= __mmProjectileDedupeWindow &&
(__mmSource === "projectile" ||
__mmSource === "outgoing-projectile" ||
__mmExisting.source === "projectile" ||
__mmExisting.source === "outgoing-projectile")
) {
((__mmExisting.source =
__mmSource === "projectile" ? __mmSource : __mmExisting.source),
(__mmExisting.liveSeenAt = __mmNow),
(__mmState.updatedAt = __mmNow));
return;
}
((__mmState.weapons[String(__mmResolvedWeapon)] = {
weapon: __mmResolvedWeapon,
duration: __mmDuration,
remaining: __mmDuration,
startedAt: __mmNow,
readyAt: __mmNow + __mmDuration,
// Projectile shots begin locally, then reconcile to the spawned object or
// any live reload value the game exposes for this weapon.
outgoingAt: __mmSource === "outgoing-projectile" ? __mmNow : 0,
source: __mmSource,
liveSeen: !1,
}),
(__mmState.updatedAt = __mmNow),
(__mmState.advancedAt = __mmNow));
}
function __mmTrackPlayerTurretCooldown(
__mmPlayerSid,
__mmSource = "attack",
) {
if (__mmPlayerSid == null) return;
let __mmPlayer = null;
try {
__mmPlayer = Rt(__mmPlayerSid);
} catch (__mmTurretPlayerLookupError) {}
if (
!__mmPlayer &&
v &&
v.sid != null &&
String(v.sid) === String(__mmPlayerSid)
)
__mmPlayer = v;
const __mmNow = Date.now(),
__mmState = __mmCooldownStateForSid(__mmPlayerSid, __mmNow),
__mmDuration = __mmTurretCooldownDuration(__mmPlayer),
__mmExisting = __mmState && __mmState.turret;
__mmAdvancePlayerToolCooldowns(__mmPlayer, __mmNow);
if (
__mmExisting &&
(Number(__mmExisting.remaining) > 0 ||
__mmNow - Number(__mmExisting.startedAt) <= 350)
) {
((__mmExisting.source =
__mmSource === "projectile" ? "projectile" : __mmExisting.source),
(__mmExisting.observedAt = __mmNow),
(__mmState.updatedAt = __mmNow));
if (v && String(__mmPlayerSid) === String(v.sid))
__mmTurretReloadUntil = Math.max(
__mmTurretReloadUntil,
Number(__mmExisting.readyAt) || 0,
);
return;
}
__mmState.turret = {
duration: __mmDuration,
remaining: __mmDuration,
startedAt: __mmNow,
readyAt: __mmNow + __mmDuration,
observedAt: __mmNow,
source: __mmSource,
};
((__mmState.updatedAt = __mmNow), (__mmState.advancedAt = __mmNow));
if (v && String(__mmPlayerSid) === String(v.sid))
__mmTurretReloadUntil = Math.max(
__mmTurretReloadUntil,
__mmNow + __mmDuration,
);
}
function __mmAdvancePlayerToolCooldowns(__mmPlayer, __mmNow) {
if (!__mmPlayer || __mmPlayer.sid == null) return null;
const __mmState = __mmPlayerToolCooldowns[String(__mmPlayer.sid)];
if (!__mmState) return null;
const __mmPreviousAt = Number.isFinite(Number(__mmState.advancedAt))
? Number(__mmState.advancedAt)
: Number(__mmState.updatedAt) || __mmNow,
__mmElapsed = Math.max(0, __mmNow - __mmPreviousAt);
__mmState.advancedAt = __mmNow;
if (__mmState.turret && __mmElapsed) {
const __mmTurretRemaining = Number.isFinite(
Number(__mmState.turret.remaining),
)
? Number(__mmState.turret.remaining)
: Math.max(0, Number(__mmState.turret.readyAt) - __mmPreviousAt || 0);
((__mmState.turret.remaining = Math.max(
0,
__mmTurretRemaining - __mmElapsed,
)),
(__mmState.turret.readyAt =
__mmNow + __mmState.turret.remaining));
}
if (!__mmState.weapons) return __mmState;
// MooMoo only reloads a weapon while that weapon is actually held. Matching
// that rule prevents a put-away secondary from appearing ready too early.
const __mmHasAssumedLocalRecharge = !!(
v &&
v.sid != null &&
String(v.sid) === String(__mmPlayer.sid) &&
__mmWeaponRechargeActiveWeapon != null
);
if (
!__mmElapsed ||
(Number(__mmPlayer.buildIndex) >= 0 && !__mmHasAssumedLocalRecharge)
)
return __mmState;
const __mmLocalRechargeWeapon = __mmHasAssumedLocalRecharge
? Number(__mmWeaponRechargeActiveWeapon)
: Number(__mmPlayer.weaponIndex),
__mmWeaponId = __mmLocalRechargeWeapon,
__mmEntry = __mmState.weapons[String(__mmWeaponId)];
if (!__mmEntry) return __mmState;
const __mmRemaining = Number.isFinite(Number(__mmEntry.remaining))
? Number(__mmEntry.remaining)
: Math.max(0, Number(__mmEntry.readyAt) - __mmPreviousAt || 0);
((__mmEntry.remaining = Math.max(0, __mmRemaining - __mmElapsed)),
(__mmEntry.readyAt = __mmNow + __mmEntry.remaining));
return __mmState;
}
function __mmTurretCooldownRemaining(__mmPlayer, __mmNow = Date.now()) {
if (!__mmPlayer || __mmPlayer.sid == null) return 0;
const __mmState = __mmAdvancePlayerToolCooldowns(__mmPlayer, __mmNow),
__mmTracked = Math.max(
0,
Number(__mmState && __mmState.turret && __mmState.turret.remaining) || 0,
);
if (v && String(__mmPlayer.sid) === String(v.sid))
return Math.max(__mmTracked, Math.max(0, __mmTurretReloadUntil - __mmNow));
return __mmTracked;
}
function __mmReconcileLocalToolCooldown(
__mmPlayer,
__mmWeaponId,
__mmNow,
__mmKnownState,
) {
const __mmId = Number(__mmWeaponId),
__mmIsLocal = !!(
v &&
__mmPlayer &&
v.sid != null &&
String(v.sid) === String(__mmPlayer.sid)
);
let __mmState = __mmKnownState ||
(__mmPlayer && __mmPlayer.sid != null
? __mmPlayerToolCooldowns[String(__mmPlayer.sid)]
: null),
__mmEntry =
__mmState && __mmState.weapons
? __mmState.weapons[String(__mmId)]
: null;
if (!__mmIsLocal || !Number.isInteger(__mmId))
return {
state: __mmState,
entry: __mmEntry,
hasLive: !1,
live: null,
};
const __mmReloads = v.reloads,
__mmHasLive = !!(
__mmReloads &&
Object.prototype.hasOwnProperty.call(__mmReloads, __mmId) &&
Number.isFinite(Number(__mmReloads[__mmId]))
),
__mmLive = __mmHasLive
? Math.max(0, Number(__mmReloads[__mmId]))
: null,
__mmHeld =
(Number(v.buildIndex) < 0 && Number(v.weaponIndex) === __mmId) ||
Number(__mmWeaponRechargeActiveWeapon) === __mmId,
__mmBaseDuration = __mmToolCooldownDuration(v, __mmId);
if (__mmHasLive && __mmLive > 0) {
if (!__mmState) {
__mmState = __mmCooldownStateForSid(v.sid, __mmNow);
}
(__mmState.weapons ||
(__mmState.weapons = Object.create(null)),
Array.isArray(__mmState.slots) || (__mmState.slots = [null, null]));
if (!__mmEntry) {
__mmEntry = __mmState.weapons[String(__mmId)] = {
weapon: __mmId,
duration: Math.max(1, __mmBaseDuration || 0, __mmLive),
remaining: __mmLive,
startedAt: __mmNow,
readyAt: __mmNow + __mmLive,
outgoingAt: 0,
liveSeen: !0,
};
const __mmSlot = __mmPlayerWeaponSlot(v, __mmId);
(__mmSlot === 0 || __mmSlot === 1) &&
(__mmState.slots[__mmSlot] = __mmId);
} else {
((__mmEntry.duration = Math.max(
1,
Number(__mmEntry.duration) || 0,
__mmBaseDuration || 0,
__mmLive,
)),
(__mmEntry.remaining = __mmLive),
(__mmEntry.readyAt = __mmNow + __mmLive),
(__mmEntry.liveSeen = !0));
}
((__mmEntry.liveSeenAt = __mmNow),
(__mmState.updatedAt = __mmNow));
} else if (
__mmHasLive &&
__mmLive === 0 &&
__mmHeld &&
__mmEntry &&
__mmEntry.liveSeen
) {
// Once the game has exposed a positive reload for this shot, its later
// zero is authoritative. This prevents a prediction (especially Musket's
// long 1500 ms clock) from keeping the bar partially empty after reload.
((__mmEntry.remaining = 0),
(__mmEntry.readyAt = __mmNow),
(__mmEntry.outgoingAt = 0));
}
return {
state: __mmState,
entry: __mmEntry,
hasLive: __mmHasLive,
live: __mmLive,
};
}
function __mmPlayerCooldownRows(__mmPlayer, __mmNow) {
if (!__mmPlayer || __mmPlayer.sid == null) return [];
const __mmIsLocal = !!(
v && String(__mmPlayer.sid) === String(v.sid)
),
__mmState = __mmAdvancePlayerToolCooldowns(__mmPlayer, __mmNow),
__mmSlots = [null, null];
function __mmSetSlot(__mmSlot, __mmWeaponId, __mmOverwrite) {
if (__mmSlot !== 0 && __mmSlot !== 1) return;
const __mmId = Number(__mmWeaponId);
if (
!Number.isInteger(__mmId) ||
!b ||
!b.weapons ||
!b.weapons[__mmId] ||
(!__mmOverwrite && __mmSlots[__mmSlot] != null)
)
return;
__mmSlots[__mmSlot] = __mmId;
}
const __mmInventory = __mmIsLocal && Array.isArray(v.weapons)
? v.weapons
: Array.isArray(__mmPlayer.weapons)
? __mmPlayer.weapons
: null;
if (__mmInventory) {
(__mmSetSlot(0, __mmInventory[0], !0),
__mmSetSlot(1, __mmInventory[1], !0));
}
(__mmSetSlot(0, __mmPlayer.primaryIndex, !1),
__mmSetSlot(1, __mmPlayer.secondaryIndex, !1));
if (__mmState && Array.isArray(__mmState.slots)) {
(__mmSetSlot(0, __mmState.slots[0], !1),
__mmSetSlot(1, __mmState.slots[1], !1));
}
const __mmCurrentWeapon = Number(__mmPlayer.weaponIndex);
__mmSetSlot(
__mmPlayerWeaponSlot(__mmPlayer, __mmCurrentWeapon),
__mmCurrentWeapon,
!1,
);
if (__mmState && __mmState.weapons) {
Object.keys(__mmState.weapons)
.map(function (__mmKey) {
return __mmState.weapons[__mmKey];
})
.sort(function (__mmA, __mmB) {
return (__mmB.startedAt || 0) - (__mmA.startedAt || 0);
})
.forEach(function (__mmEntry) {
__mmSetSlot(
__mmPlayerWeaponSlot(__mmPlayer, __mmEntry.weapon),
__mmEntry.weapon,
!1,
);
});
}
const __mmRows = __mmSlots.reduce(function (__mmRows, __mmWeaponId, __mmSlot) {
if (__mmWeaponId == null) return __mmRows;
const __mmReconciled = __mmIsLocal
? __mmReconcileLocalToolCooldown(
__mmPlayer,
__mmWeaponId,
__mmNow,
__mmState,
)
: null,
__mmTracked = __mmReconciled
? __mmReconciled.entry
: __mmState && __mmState.weapons
? __mmState.weapons[String(__mmWeaponId)]
: null,
__mmTrackedRemaining = Math.max(
0,
Number(__mmTracked && __mmTracked.remaining) || 0,
),
__mmRemaining = __mmTrackedRemaining,
__mmDuration = Math.max(
1,
Number(__mmTracked && __mmTracked.duration) ||
__mmToolCooldownDuration(__mmPlayer, __mmWeaponId) ||
1,
__mmRemaining,
);
__mmRows.push({
weapon: __mmWeaponId,
slot: __mmSlot,
ratio: Math.max(0, Math.min(1, 1 - __mmRemaining / __mmDuration)),
});
return __mmRows;
}, []);
const __mmHasTurret = !!(
(__mmIsLocal && v.skins && v.skins[__mmTurretGear]) ||
Number(__mmPlayer.skinIndex) === __mmTurretGear ||
(__mmState && __mmState.turret)
),
__mmTurretEntry = __mmState && __mmState.turret;
if (__mmHasTurret) {
const __mmRemaining = __mmTurretCooldownRemaining(__mmPlayer, __mmNow),
__mmDuration = Math.max(
1,
Number(__mmTurretEntry && __mmTurretEntry.duration) ||
__mmTurretCooldownDuration(__mmPlayer),
__mmRemaining,
);
__mmRows.push({
weapon: null,
slot: 2,
ratio: Math.max(0, Math.min(1, 1 - __mmRemaining / __mmDuration)),
turret: !0,
});
}
return __mmRows;
}
const __mmVisualCooldownRowsCache = new WeakMap();
function __mmVisualCooldownRows(__mmPlayer, __mmNow) {
if (!__mmPlayer || typeof __mmPlayer !== "object") return [];
const __mmCached = __mmVisualCooldownRowsCache.get(__mmPlayer);
if (__mmCached && Math.abs(__mmNow - __mmCached.at) <= 12)
return __mmCached.rows;
const __mmRows = __mmPlayerCooldownRows(__mmPlayer, __mmNow);
__mmVisualCooldownRowsCache.set(__mmPlayer, {
at: __mmNow,
rows: __mmRows,
});
return __mmRows;
}
function __mmFillCooldownRoundRect(
__mmX,
__mmY,
__mmWidth,
__mmHeight,
__mmRadius,
) {
if (__mmWidth <= 0 || __mmHeight <= 0) return;
k.beginPath();
typeof k.roundRect === "function"
? k.roundRect(
__mmX,
__mmY,
__mmWidth,
__mmHeight,
Math.min(__mmRadius, __mmWidth / 2, __mmHeight / 2),
)
: k.rect(__mmX, __mmY, __mmWidth, __mmHeight);
k.fill();
}
function __mmDrawPlayerCooldownBars() {
if (
!__mmCooldownBarsEnabled ||
!v ||
!v.alive ||
!k ||
!Array.isArray(E)
)
return;
try {
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2,
__mmNow = Date.now();
k.save();
let __mmRenderedRemotePlayers = 0;
// Visit the local player first without allocating a filtered copy of the
// complete player list on every animation frame.
for (let __mmIndex = -1; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = __mmIndex < 0 ? v : E[__mmIndex],
__mmIsLocal =
__mmPlayer === v ||
(__mmPlayer && String(__mmPlayer.sid) === String(v.sid));
if (
!__mmPlayer ||
!__mmPlayer.alive ||
(__mmIndex >= 0 && __mmIsLocal) ||
(!__mmIsLocal && !__mmPlayer.visible)
)
continue;
const __mmX = __mmPlayer.x - __mmLeft,
__mmY = __mmPlayer.y - __mmTop,
__mmScale = Number(__mmPlayer.scale) || 35,
__mmNameOffset = Number(y && y.nameY) || 0,
__mmHealthHalfWidth = Math.max(
34,
Number(y && y.healthBarWidth) || 50,
),
__mmHealthPad = Math.max(
2,
Math.min(5, Number(y && y.healthBarPad) || 4),
),
__mmTotalWidth = __mmHealthHalfWidth * 2 + __mmHealthPad * 2,
__mmGap = 3,
__mmHeight = 17,
__mmStartX = Math.round(__mmX - __mmTotalWidth / 2),
__mmStartY = Math.round(
__mmY + __mmScale + __mmNameOffset + __mmHeight + 3,
);
// Cull and apply the remote budget before reconciling weapon cooldowns;
// that reconciliation is the costly part of this overlay.
if (
__mmStartX > _ + __mmTotalWidth ||
__mmStartX < -__mmTotalWidth ||
__mmStartY > L + 20 ||
__mmStartY < -20
)
continue;
if (
__mmFpsBoostEnabled &&
!__mmIsLocal &&
__mmRenderedRemotePlayers >= 8
)
continue;
const __mmRows = __mmVisualCooldownRows(__mmPlayer, __mmNow);
if (!__mmRows.length) continue;
!__mmIsLocal && __mmRenderedRemotePlayers++;
const __mmBarCount = __mmRows.some((__mmRow) => __mmRow.slot === 2)
? 3
: 2,
__mmBarWidth =
(__mmTotalWidth - __mmGap * (__mmBarCount - 1)) / __mmBarCount;
for (let __mmRow = 0; __mmRow < __mmRows.length; __mmRow++) {
const __mmSlot =
__mmRows[__mmRow].slot === 2
? 2
: __mmRows[__mmRow].slot === 1
? 1
: 0,
__mmBarX =
__mmStartX + __mmSlot * (__mmBarWidth + __mmGap),
__mmRatio = __mmRows[__mmRow].ratio,
__mmInnerX = __mmBarX + __mmHealthPad,
__mmInnerY = __mmStartY + __mmHealthPad,
__mmInnerWidth = __mmBarWidth - __mmHealthPad * 2,
__mmInnerHeight = __mmHeight - __mmHealthPad * 2,
__mmFillWidth = Math.max(0, __mmInnerWidth * __mmRatio),
__mmFill =
__mmSlot === 0
? "#a855f7"
: __mmSlot === 1
? "#d8b4fe"
: "#f0abfc";
((k.shadowBlur = 0),
(k.fillStyle = "rgba(48, 48, 52, 0.96)"),
__mmFillCooldownRoundRect(
__mmBarX,
__mmStartY,
__mmBarWidth,
__mmHeight,
__mmHeight / 2,
));
if (__mmFillWidth > 0) {
((k.fillStyle = __mmFill),
__mmFillCooldownRoundRect(
__mmInnerX,
__mmInnerY,
__mmFillWidth,
__mmInnerHeight,
__mmInnerHeight / 2,
));
}
}
}
k.restore();
} catch (__mmCooldownDrawError) {
try {
k && k.restore();
} catch (__mmIgnore) {}
}
}
function __mmDrawWeaponXpBar() {
if (
!__mmWeaponXpBarEnabled ||
!v ||
!v.alive ||
!k ||
!y ||
!Array.isArray(y.weaponVariants) ||
Number(v.buildIndex) >= 0
)
return;
try {
const __mmWeapon = Number(v.weaponIndex),
__mmXp = Math.max(
0,
Number(v.weaponXP && v.weaponXP[__mmWeapon]) || 0,
),
__mmThresholds = [];
if (!Number.isInteger(__mmWeapon) || __mmWeapon < 0) return;
for (let __mmIndex = 0; __mmIndex < y.weaponVariants.length; __mmIndex++) {
const __mmThreshold = Number(y.weaponVariants[__mmIndex].xp);
if (
Number.isFinite(__mmThreshold) &&
__mmThreshold > 0 &&
__mmThresholds.indexOf(__mmThreshold) < 0
)
__mmThresholds.push(__mmThreshold);
}
__mmThresholds.sort(function (__mmA, __mmB) {
return __mmA - __mmB;
});
if (!__mmThresholds.length) return;
let __mmPrevious = 0,
__mmNext = null;
for (let __mmIndex = 0; __mmIndex < __mmThresholds.length; __mmIndex++) {
if (__mmXp >= __mmThresholds[__mmIndex])
__mmPrevious = __mmThresholds[__mmIndex];
else {
__mmNext = __mmThresholds[__mmIndex];
break;
}
}
const __mmMaxed = __mmNext == null,
__mmRatio = __mmMaxed
? 1
: Math.max(
0,
Math.min(1, (__mmXp - __mmPrevious) / (__mmNext - __mmPrevious)),
),
__mmLeft = oe - _ / 2,
__mmTop = ae - L / 2,
__mmX = Number(v.x) - __mmLeft,
__mmY = Number(v.y) - __mmTop,
__mmScale = Number(v.scale) || 35,
__mmNameOffset = Number(y.nameY) || 0,
__mmHealthHalfWidth = Math.max(34, Number(y.healthBarWidth) || 50),
__mmHealthPad = Math.max(2, Math.min(5, Number(y.healthBarPad) || 4)),
__mmWidth = __mmHealthHalfWidth * 2 + __mmHealthPad * 2,
__mmHeight = 11,
__mmStartX = Math.round(__mmX - __mmWidth / 2),
__mmStartY = Math.round(__mmY + __mmScale + __mmNameOffset + 41),
__mmInnerX = __mmStartX + 2,
__mmInnerY = __mmStartY + 2,
__mmInnerWidth = __mmWidth - 4,
__mmLabel = __mmMaxed
? "XP " + Math.round(__mmXp) + " · MAX"
: "XP " + Math.round(__mmXp) + " / " + Math.round(__mmNext);
if (
__mmStartX > _ + __mmWidth ||
__mmStartX < -__mmWidth ||
__mmStartY > L + 20 ||
__mmStartY < -20
)
return;
(k.save(),
(k.shadowBlur = 0),
(k.fillStyle = "rgba(29,22,36,.96)"),
__mmFillCooldownRoundRect(
__mmStartX,
__mmStartY,
__mmWidth,
__mmHeight,
__mmHeight / 2,
));
if (__mmRatio > 0) {
((k.fillStyle = __mmOwnColor),
__mmFillCooldownRoundRect(
__mmInnerX,
__mmInnerY,
__mmInnerWidth * __mmRatio,
__mmHeight - 4,
(__mmHeight - 4) / 2,
));
}
((k.fillStyle = "#fff"),
(k.font = "800 8px ui-monospace,SFMono-Regular,Menlo,monospace"),
(k.textAlign = "center"),
(k.textBaseline = "middle"),
(k.shadowColor = "rgba(0,0,0,.9)"),
(k.shadowBlur = 2),
k.fillText(__mmLabel, __mmX, __mmStartY + __mmHeight / 2 + 0.5),
k.restore());
} catch (__mmXpDrawError) {
try {
k && k.restore();
} catch (__mmIgnore) {}
}
}
function __mmTrackWeaponXpResourceGain(
__mmResource,
__mmPreviousValue,
__mmNextValue,
__mmWeapon,
) {
if (
!v ||
!v.alive ||
(__mmResource !== "food" &&
__mmResource !== "wood" &&
__mmResource !== "stone")
)
return;
const __mmPrevious = Number(__mmPreviousValue),
__mmNext = Number(__mmNextValue),
__mmWeaponId = Number(__mmWeapon),
__mmGain = __mmNext - __mmPrevious;
if (
!Number.isFinite(__mmPrevious) ||
!Number.isFinite(__mmNext) ||
!Number.isInteger(__mmWeaponId) ||
__mmWeaponId < 0 ||
!Number.isFinite(__mmGain) ||
__mmGain <= 0
)
return;
// The stock client exposes weaponXP but leaves it untouched on resource
// packets. Weapon-variant progress is the positive food/wood/stone gain
// attributed to the weapon held when that packet arrived.
Array.isArray(v.weaponXP) || (v.weaponXP = []);
v.weaponXP[__mmWeaponId] =
(Number(v.weaponXP[__mmWeaponId]) || 0) + __mmGain;
}
function __mmRecordCombatDelta(__mmPlayer, __mmPrevious, __mmNext) {
if (
!__mmCombatTelemetryEnabled ||
!__mmTelemetryDamageHealingEnabled ||
!__mmPlayer
)
return;
const __mmBefore = Number(__mmPrevious),
__mmAfter = Number(__mmNext),
__mmDelta = __mmAfter - __mmBefore;
if (
!Number.isFinite(__mmBefore) ||
!Number.isFinite(__mmAfter) ||
Math.abs(__mmDelta) < 0.01
)
return;
const __mmSid = String(
__mmPlayer.sid == null ? __mmPlayer.id : __mmPlayer.sid,
),
__mmNow = Date.now(),
__mmStack =
__mmCombatDeltaStacks[__mmSid] ||
(__mmCombatDeltaStacks[__mmSid] = []);
__mmStack.push({
value: __mmDelta,
at: __mmNow,
expiresAt: __mmNow + 1450,
});
__mmStack.length > 6 && __mmStack.splice(0, __mmStack.length - 6);
}
function __mmTelemetryPlayerColor(__mmPlayer) {
if (!__mmPlayer || __mmPlayer === v) return __mmOwnColor;
return __mmIsFriendPlayer(__mmPlayer)
? __mmFriendColor
: __mmSameTeam(__mmPlayer)
? __mmAllyColor
: __mmEnemyColor;
}
function __mmTelemetryText(__mmText, __mmX, __mmY, __mmColor, __mmSize = 10) {
((k.font =
"900 " + __mmSize + "px ui-monospace,SFMono-Regular,Menlo,monospace"),
(k.textAlign = "center"),
(k.textBaseline = "middle"),
(k.lineWidth = 3),
(k.strokeStyle = "rgba(6,3,10,.92)"),
k.strokeText(__mmText, __mmX, __mmY),
(k.fillStyle = __mmColor),
k.fillText(__mmText, __mmX, __mmY));
}
function __mmDrawTelemetryProjectileHits(__mmLeft, __mmTop) {
if (!__mmTelemetryProjectileHitsEnabled) return;
const __mmThreat = __mmCombatThreatSnapshot(),
__mmEntries = __mmThreat && __mmThreat.entries,
__mmLimit = __mmFpsBoostEnabled ? 6 : 16;
if (!Array.isArray(__mmEntries)) return;
let __mmRendered = 0;
for (let __mmIndex = 0; __mmIndex < __mmEntries.length; __mmIndex++) {
const __mmEntry = __mmEntries[__mmIndex],
__mmProjectile = __mmEntry && __mmEntry.source;
if (
!__mmEntry ||
(__mmEntry.type !== "projectile" && __mmEntry.type !== "turret") ||
!__mmProjectile ||
!Number.isFinite(__mmEntry.impactMs)
)
continue;
const __mmDirection = Number(__mmProjectile.dir),
__mmSpeed = Number(__mmProjectile.speed),
__mmStartX = Number(__mmProjectile.x) - __mmLeft,
__mmStartY = Number(__mmProjectile.y) - __mmTop,
__mmImpactWorldX =
Number(__mmProjectile.x) +
Math.cos(__mmDirection) * __mmSpeed * __mmEntry.impactMs,
__mmImpactWorldY =
Number(__mmProjectile.y) +
Math.sin(__mmDirection) * __mmSpeed * __mmEntry.impactMs,
__mmImpactX = __mmImpactWorldX - __mmLeft,
__mmImpactY = __mmImpactWorldY - __mmTop,
__mmDamage = Math.max(0, Number(__mmEntry.damage) || 0);
if (
!Number.isFinite(__mmDirection) ||
!Number.isFinite(__mmSpeed) ||
!Number.isFinite(__mmImpactX) ||
!Number.isFinite(__mmImpactY) ||
(!ts(__mmStartX, __mmStartY, 30) &&
!ts(__mmImpactX, __mmImpactY, 45))
)
continue;
((k.globalAlpha = 0.78),
(k.strokeStyle = __mmEnemyColor),
(k.lineWidth = 1.7),
k.setLineDash([7, 5]),
k.beginPath(),
k.moveTo(__mmStartX, __mmStartY),
k.lineTo(__mmImpactX, __mmImpactY),
k.stroke(),
k.setLineDash([]),
(k.globalAlpha = 0.95),
k.beginPath(),
k.arc(__mmImpactX, __mmImpactY, 7, 0, Math.PI * 2),
k.stroke());
__mmTelemetryText(
"-" + Math.round(__mmDamage) + " · " +
Math.max(0, Math.round(__mmEntry.impactMs)) + "ms",
__mmImpactX,
__mmImpactY - 13,
__mmEnemyColor,
9,
);
if (++__mmRendered >= __mmLimit) break;
}
}
function __mmDrawTelemetrySpikeKnockback(__mmLeft, __mmTop) {
if (!__mmTelemetrySpikeKnockbackEnabled) return;
const __mmThreat = __mmCombatThreatSnapshot(),
__mmEntries = __mmThreat && __mmThreat.entries;
if (!Array.isArray(__mmEntries)) return;
const __mmStartX = Number(v.x) - __mmLeft,
__mmStartY = Number(v.y) - __mmTop;
for (let __mmIndex = 0; __mmIndex < __mmEntries.length; __mmIndex++) {
const __mmEntry = __mmEntries[__mmIndex],
__mmSpike = __mmEntry && __mmEntry.spike;
if (!__mmSpike) continue;
const __mmX = Number(__mmSpike.x) - __mmLeft,
__mmY = Number(__mmSpike.y) - __mmTop;
((k.globalAlpha = 0.9),
(k.strokeStyle = "#fb7185"),
(k.lineWidth = 3),
k.setLineDash([3, 4]),
k.beginPath(),
k.moveTo(__mmStartX, __mmStartY),
k.lineTo(__mmX, __mmY),
k.stroke(),
k.setLineDash([]),
k.beginPath(),
k.arc(__mmX, __mmY, __mmThreatObjectScale(__mmSpike) + 7, 0, Math.PI * 2),
k.stroke());
__mmTelemetryText(
"SPIKE -" + Math.round(Number(__mmEntry.spike.damage) || 0),
__mmX,
__mmY - __mmThreatObjectScale(__mmSpike) - 13,
"#fb7185",
10,
);
}
}
function __mmDrawTelemetryActualAim(__mmLeft, __mmTop) {
if (!__mmTelemetryActualAimEnabled) return;
const __mmPlayers = [v],
__mmLimit = __mmFpsBoostEnabled ? 9 : 24;
if (Array.isArray(E))
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++)
E[__mmIndex] && E[__mmIndex] !== v && __mmPlayers.push(E[__mmIndex]);
let __mmRendered = 0;
for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
const __mmPlayer = __mmPlayers[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
(__mmPlayer !== v && __mmPlayer.visible === !1)
)
continue;
const __mmDirection = Number.isFinite(Number(__mmPlayer.dir))
? Number(__mmPlayer.dir)
: Number(__mmPlayer.d2),
__mmWeapon = b && b.weapons && b.weapons[__mmPlayer.weaponIndex],
__mmReach = Math.max(
55,
Math.min(
320,
(Number(__mmWeapon && __mmWeapon.range) || 80) +
(Number(__mmPlayer.scale) || 35),
),
),
__mmX = Number(__mmPlayer.x) - __mmLeft,
__mmY = Number(__mmPlayer.y) - __mmTop,
__mmEndX = __mmX + Math.cos(__mmDirection) * __mmReach,
__mmEndY = __mmY + Math.sin(__mmDirection) * __mmReach,
__mmColor = __mmTelemetryPlayerColor(__mmPlayer);
if (!Number.isFinite(__mmDirection) || !ts(__mmX, __mmY, __mmReach))
continue;
((k.globalAlpha = __mmPlayer === v ? 0.82 : 0.58),
(k.strokeStyle = __mmColor),
(k.lineWidth = __mmPlayer === v ? 2.2 : 1.4),
k.beginPath(),
k.moveTo(__mmX, __mmY),
k.lineTo(__mmEndX, __mmEndY),
k.stroke(),
(k.fillStyle = __mmColor),
k.beginPath(),
k.arc(__mmEndX, __mmEndY, 3, 0, Math.PI * 2),
k.fill());
if (++__mmRendered >= __mmLimit) break;
}
}
function __mmDrawTelemetryBuildingOwners(__mmLeft, __mmTop) {
if (!__mmTelemetryBuildingOwnersEnabled) return;
const __mmBreakables = __mmActiveObjectSnapshot().breakables,
__mmLimit = __mmFpsBoostEnabled ? 8 : 24;
let __mmRendered = 0;
for (let __mmIndex = 0; __mmIndex < __mmBreakables.length; __mmIndex++) {
const __mmObject = __mmBreakables[__mmIndex].object,
__mmOwner = __mmStructureOwnerPlayer(__mmObject),
__mmOwnerSid = __mmStructureOwnerSid(__mmObject);
if (!__mmObject || __mmOwnerSid == null) continue;
const __mmName = String(
(__mmOwner && __mmOwner.name) || "SID " + __mmOwnerSid,
).slice(0, 20),
__mmX = Number(__mmObject.x) - __mmLeft,
__mmY =
Number(__mmObject.y) -
__mmTop +
__mmThreatObjectScale(__mmObject) +
13,
__mmColor = __mmOwnStructure(__mmObject)
? __mmOwnColor
: __mmFriendlyStructure(__mmObject)
? __mmAllyColor
: __mmEnemyColor;
if (!ts(__mmX, __mmY, 35)) continue;
__mmTelemetryText(__mmName, __mmX, __mmY, __mmColor, 9);
if (++__mmRendered >= __mmLimit) break;
}
}
function __mmDrawTelemetryShame(__mmLeft, __mmTop) {
if (!__mmTelemetryShameCountEnabled) return;
const __mmX = Number(v.x) - __mmLeft,
__mmY =
Number(v.y) -
__mmTop +
(Number(v.scale) || 35) +
(Number(y && y.nameY) || 0) +
58;
__mmTelemetryText(
"SHAME " + Math.max(0, Math.round(__mmAutoHealShameCount)),
__mmX,
__mmY,
__mmAutoHealShameCount > 0 ? "#facc15" : "#c4b5fd",
9,
);
}
function __mmDrawTelemetryDeltas(__mmLeft, __mmTop) {
if (!__mmTelemetryDamageHealingEnabled) return;
const __mmNow = Date.now(),
__mmPlayers = [v];
if (Array.isArray(E))
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++)
E[__mmIndex] && E[__mmIndex] !== v && __mmPlayers.push(E[__mmIndex]);
let __mmRenderedPlayers = 0;
const __mmLimit = __mmFpsBoostEnabled ? 8 : 20;
for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
const __mmPlayer = __mmPlayers[__mmIndex],
__mmSid = String(
__mmPlayer && (__mmPlayer.sid == null ? __mmPlayer.id : __mmPlayer.sid),
),
__mmStack = __mmCombatDeltaStacks[__mmSid];
if (!__mmPlayer || !Array.isArray(__mmStack)) continue;
for (let __mmEntry = __mmStack.length - 1; __mmEntry >= 0; __mmEntry--)
__mmNow >= __mmStack[__mmEntry].expiresAt &&
__mmStack.splice(__mmEntry, 1);
if (!__mmStack.length) {
delete __mmCombatDeltaStacks[__mmSid];
continue;
}
if (__mmPlayer !== v && __mmPlayer.visible === !1) continue;
const __mmX = Number(__mmPlayer.x) - __mmLeft,
__mmBaseY =
Number(__mmPlayer.y) -
__mmTop -
(Number(__mmPlayer.scale) || 35) -
24;
if (!ts(__mmX, __mmBaseY, 80)) continue;
for (let __mmEntry = 0; __mmEntry < __mmStack.length; __mmEntry++) {
const __mmDelta = __mmStack[__mmEntry],
__mmAge = __mmNow - __mmDelta.at,
__mmAlpha = Math.max(0, Math.min(1, (__mmDelta.expiresAt - __mmNow) / 350)),
__mmY = __mmBaseY - __mmEntry * 15 - Math.min(16, __mmAge / 55),
__mmValue = Number(__mmDelta.value) || 0;
k.globalAlpha = __mmAlpha;
__mmTelemetryText(
(__mmValue > 0 ? "+" : "") + Math.round(__mmValue),
__mmX,
__mmY,
__mmValue > 0 ? "#4ade80" : "#fb7185",
11,
);
}
if (++__mmRenderedPlayers >= __mmLimit) break;
}
}
function __mmDrawCombatTelemetry() {
if (!__mmCombatTelemetryEnabled || !v || !v.alive || !k) return;
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2;
try {
(k.save(),
__mmDrawTelemetryProjectileHits(__mmLeft, __mmTop),
__mmDrawTelemetrySpikeKnockback(__mmLeft, __mmTop),
__mmDrawTelemetryActualAim(__mmLeft, __mmTop),
__mmDrawTelemetryBuildingOwners(__mmLeft, __mmTop),
__mmDrawTelemetryShame(__mmLeft, __mmTop),
__mmDrawTelemetryDeltas(__mmLeft, __mmTop),
k.restore());
} catch (__mmTelemetryError) {
try {
k && k.restore();
} catch (__mmIgnore) {}
}
}
function __mmWeaponStructureDamage(__mmPlayer, __mmWeaponId, __mmObject) {
if (!__mmPlayer || !b || !b.weapons || !__mmObject) return 0;
const __mmWeapon = b.weapons[__mmWeaponId];
if (!__mmWeapon) return 0;
if (__mmWeapon.projectile != null) {
const __mmProjectile = b.projectiles && b.projectiles[__mmWeapon.projectile];
return __mmObject.projDmg && __mmProjectile
? Math.max(0, Number(__mmProjectile.dmg) || 0)
: 0;
}
const __mmVariant =
y && y.weaponVariants && y.weaponVariants[__mmPlayer.weaponVariant],
__mmVariantMultiplier = Number(__mmVariant && __mmVariant.val) || 1,
__mmStructureMultiplier = Number(__mmWeapon.sDmg) || 1,
__mmHat = __mmPlayerHatData(__mmPlayer),
__mmHatMultiplier = Number(__mmHat && __mmHat.bDmg) || 1;
return Math.max(
0,
(Number(__mmWeapon.dmg) || 0) *
__mmVariantMultiplier *
__mmStructureMultiplier *
__mmHatMultiplier,
);
}
function __mmCurrentStructureDamage(__mmObject) {
if (!v || !v.alive || Number(v.buildIndex) >= 0) return 0;
return __mmWeaponStructureDamage(v, v.weaponIndex, __mmObject);
}
function __mmMatThiefStructureAllowed(__mmObject) {
if (
!v ||
!v.alive ||
!__mmObject ||
!__mmObject.active ||
!__mmObject.isItem ||
!__mmObject.owner
)
return !1;
const __mmOwnerSid = __mmObject.owner.sid;
// Teammate structures are intentional targets too, but the local player's
// own placed structures must never be selected.
if (
__mmObject.owner === v ||
(__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
)
return !1;
const __mmOwnerPlayer =
__mmOwnerSid != null && typeof Rt === "function"
? Rt(__mmOwnerSid)
: __mmObject.owner;
if (__mmIsFriendPlayer(__mmOwnerPlayer)) return !1;
const __mmItem = b && b.list && b.list[__mmObject.id],
__mmName = String((__mmItem && __mmItem.name) || "").toLowerCase();
return (
__mmName === "windmill" ||
__mmName === "faster windmill" ||
__mmName === "power mill" ||
__mmName === "turret" ||
__mmName === "teleporter"
);
}
function __mmMatThiefWeaponCandidates() {
if (!v || !v.alive || !Array.isArray(v.weapons)) return [];
const __mmWeapons = [],
__mmSeen = new Set();
for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
const __mmWeapon = v.weapons[__mmIndex],
__mmData = b && b.weapons && b.weapons[__mmWeapon];
if (
__mmWeapon == null ||
__mmSeen.has(__mmWeapon) ||
!__mmData ||
__mmData.projectile != null ||
!__mmWeaponReady(__mmWeapon)
)
continue;
(__mmSeen.add(__mmWeapon), __mmWeapons.push(__mmWeapon));
}
return __mmWeapons;
}
function __mmMatThiefTargetsForWeapon(__mmWeapon, __mmNow) {
if (!v || !v.alive) return [];
const __mmWeaponData = b && b.weapons && b.weapons[__mmWeapon],
__mmRange = Number(__mmWeaponData && __mmWeaponData.range);
if (!Number.isFinite(__mmRange) || __mmRange <= 0) return [];
const __mmTargets = [],
__mmObjects = __mmActiveObjectSnapshot().all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (!__mmMatThiefStructureAllowed(__mmObject)) continue;
const __mmReservedUntil = Number(__mmMatThiefReservations.get(__mmObject));
if (Number.isFinite(__mmReservedUntil) && __mmReservedUntil > __mmNow)
continue;
const __mmState = __mmBreakableState(__mmObject),
__mmDamage = __mmWeaponStructureDamage(v, __mmWeapon, __mmObject);
if (!__mmState || __mmDamage <= 0 || __mmState.health > __mmDamage + 0.001)
continue;
const __mmDx = __mmObject.x - v.x,
__mmDy = __mmObject.y - v.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
// Match the server gather check: center distance minus structure scale
// must fit inside the selected weapon's range.
__mmReach = __mmRange + (Number(__mmObject.scale) || 0);
if (__mmDistance > __mmReach) continue;
__mmTargets.push({
object: __mmObject,
angle: Math.atan2(__mmDy, __mmDx),
distance: __mmDistance,
});
}
return __mmTargets;
}
function __mmMatThiefAngleDifference(__mmFirst, __mmSecond) {
return Math.atan2(
Math.sin(__mmSecond - __mmFirst),
Math.cos(__mmSecond - __mmFirst),
);
}
function __mmMatThiefAimPlan(__mmTargets) {
if (!__mmTargets.length) return null;
const __mmGatherAngle = Math.max(0.05, Number(y && y.gatherAngle) || 0.35),
__mmCandidateAngles = [];
for (let __mmIndex = 0; __mmIndex < __mmTargets.length; __mmIndex++)
__mmCandidateAngles.push(__mmTargets[__mmIndex].angle);
for (let __mmFirst = 0; __mmFirst < __mmTargets.length; __mmFirst++)
for (
let __mmSecond = __mmFirst + 1;
__mmSecond < __mmTargets.length;
__mmSecond++
) {
const __mmDifference = __mmMatThiefAngleDifference(
__mmTargets[__mmFirst].angle,
__mmTargets[__mmSecond].angle,
);
Math.abs(__mmDifference) <= 2 * __mmGatherAngle + 0.0001 &&
__mmCandidateAngles.push(
__mmTargets[__mmFirst].angle + __mmDifference / 2,
);
}
let __mmBest = null;
for (
let __mmAngleIndex = 0;
__mmAngleIndex < __mmCandidateAngles.length;
__mmAngleIndex++
) {
const __mmAim = __mmCandidateAngles[__mmAngleIndex],
__mmCovered = __mmTargets.filter(
(__mmTarget) =>
Math.abs(__mmMatThiefAngleDifference(__mmAim, __mmTarget.angle)) <=
__mmGatherAngle + 0.0001,
),
__mmDistanceScore = __mmCovered.reduce(
(__mmTotal, __mmTarget) => __mmTotal + __mmTarget.distance,
0,
);
if (
!__mmBest ||
__mmCovered.length > __mmBest.targets.length ||
(__mmCovered.length === __mmBest.targets.length &&
__mmDistanceScore < __mmBest.distanceScore)
)
__mmBest = {
angle: __mmAim,
targets: __mmCovered,
distanceScore: __mmDistanceScore,
};
}
return __mmBest;
}
function __mmMultiBreakAimPlan(
__mmWeapon,
__mmPreferredAngle,
__mmRequiredObject = null,
) {
if (!__mmMultiTargetBreakEnabled || !v || !v.alive) return null;
const __mmWeaponData = b && b.weapons && b.weapons[__mmWeapon],
__mmRange = Number(__mmWeaponData && __mmWeaponData.range),
__mmGatherAngle = Math.max(0.05, Number(y && y.gatherAngle) || 0.35);
if (
!__mmWeaponData ||
__mmWeaponData.projectile != null ||
__mmWeaponData.shield ||
!Number.isFinite(__mmRange) ||
__mmRange <= 0
)
return null;
const __mmTargets = [],
__mmObjects = __mmActiveObjectSnapshot().breakables;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex].object,
__mmState = __mmBreakableState(__mmObject),
__mmData = __mmObject && b && b.list && b.list[__mmObject.id];
if (
!__mmObject ||
!__mmObject.active ||
!__mmObject.isItem ||
!__mmData ||
!__mmState ||
!(Number(__mmState.health) > 0)
)
continue;
const __mmDx = Number(__mmObject.x) - Number(v.x),
__mmDy = Number(__mmObject.y) - Number(v.y),
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmReach = __mmRange + __mmCleanupObjectScale(__mmObject),
__mmAngle = Math.atan2(__mmDy, __mmDx),
__mmFromPreferred = Math.abs(
__mmMatThiefAngleDifference(__mmPreferredAngle, __mmAngle),
);
if (
!Number.isFinite(__mmDistance) ||
__mmDistance > __mmReach + 8 ||
(__mmObject !== __mmRequiredObject &&
__mmFromPreferred > __mmGatherAngle * 2.25)
)
continue;
__mmTargets.push({
object: __mmObject,
angle: __mmAngle,
distance: __mmDistance,
});
}
if (__mmTargets.length < 2) return null;
__mmTargets.sort(function (__mmA, __mmB) {
return __mmA.distance - __mmB.distance;
});
__mmTargets.length > 18 && (__mmTargets.length = 18);
const __mmCandidates = [__mmPreferredAngle];
for (let __mmIndex = 0; __mmIndex < __mmTargets.length; __mmIndex++)
__mmCandidates.push(__mmTargets[__mmIndex].angle);
for (let __mmFirst = 0; __mmFirst < __mmTargets.length; __mmFirst++)
for (
let __mmSecond = __mmFirst + 1;
__mmSecond < __mmTargets.length;
__mmSecond++
) {
const __mmDifference = __mmMatThiefAngleDifference(
__mmTargets[__mmFirst].angle,
__mmTargets[__mmSecond].angle,
);
if (Math.abs(__mmDifference) <= __mmGatherAngle * 2 + 0.0001)
__mmCandidates.push(
__mmTargets[__mmFirst].angle + __mmDifference / 2,
);
}
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < __mmCandidates.length; __mmIndex++) {
const __mmAngle = __mmCandidates[__mmIndex],
__mmCovered = __mmTargets.filter(function (__mmTarget) {
return (
Math.abs(
__mmMatThiefAngleDifference(__mmAngle, __mmTarget.angle),
) <= __mmGatherAngle + 0.0001
);
});
if (
__mmCovered.length < 2 ||
(__mmRequiredObject &&
!__mmCovered.some(function (__mmTarget) {
return __mmTarget.object === __mmRequiredObject;
}))
)
continue;
const __mmDeviation = Math.abs(
__mmMatThiefAngleDifference(__mmPreferredAngle, __mmAngle),
),
__mmDistanceScore = __mmCovered.reduce(function (__mmTotal, __mmTarget) {
return __mmTotal + __mmTarget.distance;
}, 0);
if (
!__mmBest ||
__mmCovered.length > __mmBest.targets.length ||
(__mmCovered.length === __mmBest.targets.length &&
__mmDeviation < __mmBest.deviation) ||
(__mmCovered.length === __mmBest.targets.length &&
__mmDeviation === __mmBest.deviation &&
__mmDistanceScore < __mmBest.distanceScore)
)
__mmBest = {
angle: __mmAngle,
targets: __mmCovered,
deviation: __mmDeviation,
distanceScore: __mmDistanceScore,
};
}
return __mmBest;
}
function __mmStopMultiBreakAim() {
const __mmHadAim = Number.isFinite(__mmMultiBreakAimAngle);
((__mmMultiBreakAimAngle = null), (__mmMultiBreakTargetCount = 0));
__mmHadAim && __mmScheduleMouseAimReturn();
}
function __mmUpdateMultiBreakAim() {
if (
!__mmMultiTargetBreakEnabled ||
!v ||
!v.alive ||
__mmCleanupActive ||
__mmTrapAttackActive ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmActionOwner !== "manualAttack" ||
(!__mmPrimaryHeld && !__mmSecondaryHeld)
)
return void __mmStopMultiBreakAim();
const __mmWeapon = __mmHeldAttackWeapon();
if (__mmWeapon == null) return void __mmStopMultiBreakAim();
const __mmPreferred = __mmRawMouseAimDirection(),
__mmPlan = __mmMultiBreakAimPlan(__mmWeapon, __mmPreferred);
if (!__mmPlan) return void __mmStopMultiBreakAim();
const __mmDifference = Number.isFinite(__mmMultiBreakAimAngle)
? Math.abs(
__mmMatThiefAngleDifference(
__mmMultiBreakAimAngle,
__mmPlan.angle,
),
)
: Infinity;
((__mmMultiBreakAimAngle = __mmPlan.angle),
(__mmMultiBreakTargetCount = __mmPlan.targets.length));
if (__mmDifference > 0.015) {
((It = __mmPlan.angle), O.send("D", __mmPlan.angle));
}
}
function __mmStartMultiBreak() {
__mmEnsureOperationPipeline();
}
function __mmStopMultiBreak() {
(__mmMultiBreakTimer && clearInterval(__mmMultiBreakTimer),
(__mmMultiBreakTimer = 0),
__mmStopMultiBreakAim());
}
function __mmMatThiefPlan() {
const __mmNow = Date.now(),
__mmWeapons = __mmMatThiefWeaponCandidates(),
__mmSelected = __mmSelectedWeapon();
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < __mmWeapons.length; __mmIndex++) {
const __mmWeapon = __mmWeapons[__mmIndex],
__mmTargets = __mmMatThiefTargetsForWeapon(__mmWeapon, __mmNow),
__mmAim = __mmMatThiefAimPlan(__mmTargets);
if (!__mmAim || !__mmAim.targets.length) continue;
const __mmData = b.weapons[__mmWeapon],
__mmDamage = __mmWeaponStructureDamage(
v,
__mmWeapon,
__mmAim.targets[0].object,
),
__mmPlan = {
weapon: __mmWeapon,
angle: __mmAim.angle,
targets: __mmAim.targets,
distanceScore: __mmAim.distanceScore,
damage: __mmDamage,
speed: Math.max(50, Number(__mmData.speed) || 400),
},
__mmPlanUsesSelected = __mmWeapon === __mmSelected,
__mmBestUsesSelected = __mmBest && __mmBest.weapon === __mmSelected;
if (
!__mmBest ||
__mmPlan.targets.length > __mmBest.targets.length ||
(__mmPlan.targets.length === __mmBest.targets.length &&
__mmPlanUsesSelected &&
!__mmBestUsesSelected) ||
(__mmPlan.targets.length === __mmBest.targets.length &&
__mmPlanUsesSelected === __mmBestUsesSelected &&
(__mmPlan.distanceScore < __mmBest.distanceScore ||
(__mmPlan.distanceScore === __mmBest.distanceScore &&
__mmPlan.damage > __mmBest.damage)))
)
__mmBest = __mmPlan;
}
return __mmBest;
}
function __mmFinishMatThief(__mmReason) {
const __mmAim = __mmMatThiefAimAngle,
__mmReturnAngle = __mmMatThiefReturnAngle,
__mmTool = __mmMatThiefRestoreTool,
__mmRestore = __mmActionMayRestore("matThief");
(__mmMatThiefReleaseTimer && clearTimeout(__mmMatThiefReleaseTimer),
(__mmMatThiefReleaseTimer = 0),
__mmMatThiefAttackHeld && O.send("F", 0, __mmAim),
(__mmMatThiefAttackHeld = !1),
(__mmMatThiefAimAngle = null),
(__mmMatThiefReturnAngle = null),
(__mmMatThiefRestoreTool = null),
__mmRestore && __mmRestoreTool(__mmTool),
__mmRestore &&
Number.isFinite(__mmReturnAngle) &&
O.send("D", __mmReturnAngle),
__mmActionRelease("matThief", __mmReason || "last hit complete"));
}
function __mmUpdateMatThief() {
if (
!__mmMatThiefEnabled ||
document.hidden ||
!v ||
!v.alive ||
v.lockMove ||
__mmMatThiefReleaseTimer ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmInsta.isActive() ||
__mmSyncFollowerEnabled ||
(__mmActionOwner !== "idle" && __mmActionOwner !== "weaponRecharge")
)
return;
const __mmPlan = __mmMatThiefPlan();
if (!__mmPlan) return;
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmActionClaim("matThief", "one-hit structure")) return;
let __mmReturnAngle;
try {
__mmReturnAngle = __mmOriginalAimDirection();
} catch (__mmAimError) {
__mmReturnAngle = 0;
}
const __mmNow = Date.now(),
__mmReservationUntil =
__mmNow + Math.max(__mmPlan.speed, 2 * __mmServerTickMs());
for (let __mmIndex = 0; __mmIndex < __mmPlan.targets.length; __mmIndex++)
__mmMatThiefReservations.set(
__mmPlan.targets[__mmIndex].object,
__mmReservationUntil,
);
((__mmMatThiefReturnAngle = __mmReturnAngle),
(__mmMatThiefRestoreTool = __mmSelectedTool()),
(__mmMatThiefAimAngle = __mmPlan.angle),
O.send("D", __mmPlan.angle),
je(__mmPlan.weapon, !0),
O.send("F", 1, __mmPlan.angle),
(__mmMatThiefAttackHeld = !0),
(__mmMatThiefReleaseTimer = setTimeout(function () {
__mmFinishMatThief("last hit sent");
}, __mmServerTickMs())));
}
function __mmStartMatThief() {
__mmEnsureOperationPipeline();
}
function __mmStopMatThief() {
(__mmMatThiefTimer && clearInterval(__mmMatThiefTimer),
(__mmMatThiefTimer = 0),
__mmFinishMatThief("mode disabled"));
}
function __mmMobStealEntityKey(__mmAnimal) {
if (!__mmAnimal) return null;
const __mmId =
__mmAnimal.sid != null
? __mmAnimal.sid
: __mmAnimal.id != null
? __mmAnimal.id
: __mmAnimal.index;
return __mmId == null ? null : "mob:" + String(__mmId);
}
function __mmMobStealVariantMultiplier(__mmWeapon) {
const __mmVariants = y && y.weaponVariants,
__mmXp = Number(v && v.weaponXP && v.weaponXP[__mmWeapon]) || 0;
if (!Array.isArray(__mmVariants)) return 1;
for (let __mmIndex = __mmVariants.length - 1; __mmIndex >= 0; __mmIndex--)
if (__mmXp >= (Number(__mmVariants[__mmIndex].xp) || 0))
return Number(__mmVariants[__mmIndex].val) || 1;
return 1;
}
function __mmMobStealTailData(__mmTail) {
if (typeof pa === "undefined" || !Array.isArray(pa)) return null;
for (let __mmIndex = 0; __mmIndex < pa.length; __mmIndex++)
if (Number(pa[__mmIndex].id) === Number(__mmTail)) return pa[__mmIndex];
return null;
}
function __mmMobStealMonkeyTailActive() {
if (!v || !v.alive) return !1;
const __mmPendingFresh = !!(
__mmPendingTail != null &&
Date.now() - __mmPendingTailAt <= Math.max(180, __mmServerTickMs() * 2)
);
return !!(
Number(v.tailIndex) === 11 ||
(__mmPendingFresh && Number(__mmPendingTail) === 11)
);
}
function __mmMobStealDamage(__mmWeapon, __mmUseBull, __mmStripMonkeyTail) {
const __mmData = b && b.weapons && b.weapons[__mmWeapon];
if (!__mmData || __mmData.projectile != null) return 0;
const __mmHat = __mmUseBull
? __mmPlayerHatData({ skinIndex: 7 })
: __mmPlayerHatData(v),
__mmTail = __mmStripMonkeyTail
? null
: __mmMobStealTailData(v && v.tailIndex),
__mmHatMultiplier = Number(__mmHat && __mmHat.dmgMultO) || 1,
__mmTailMultiplier = Number(__mmTail && __mmTail.dmgMultO) || 1;
return Math.max(
0,
(Number(__mmData.dmg) || 0) *
__mmMobStealVariantMultiplier(__mmWeapon) *
__mmHatMultiplier *
__mmTailMultiplier,
);
}
function __mmMobStealWeaponCandidates() {
if (!v || !v.alive || !Array.isArray(v.weapons)) return [];
const __mmUseBull = !!(
__mmBullHelmetEnabled && __mmCanEquipHat(7)
),
__mmStripMonkeyTail = __mmMobStealMonkeyTailActive(),
__mmSelected = __mmSelectedWeapon(),
__mmCandidates = [],
__mmSeen = new Set();
for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
const __mmWeapon = v.weapons[__mmIndex],
__mmData = b && b.weapons && b.weapons[__mmWeapon],
__mmRange = Number(__mmData && __mmData.range),
__mmDamage = __mmMobStealDamage(
__mmWeapon,
__mmUseBull,
__mmStripMonkeyTail,
);
if (
__mmWeapon == null ||
__mmSeen.has(__mmWeapon) ||
!__mmData ||
__mmData.projectile != null ||
__mmData.shield ||
!Number.isFinite(__mmRange) ||
__mmRange <= 0 ||
__mmDamage <= 0 ||
!__mmWeaponReady(__mmWeapon)
)
continue;
(__mmSeen.add(__mmWeapon),
__mmCandidates.push({
weapon: __mmWeapon,
range: __mmRange,
damage: __mmDamage,
speed: Math.max(50, Number(__mmData.speed) || 400),
selected: __mmWeapon === __mmSelected,
useBull: __mmUseBull,
stripMonkeyTail: __mmStripMonkeyTail,
}));
}
return __mmCandidates;
}
function __mmMobStealPredictPoint(
__mmEntity,
__mmKey,
__mmNow,
__mmLeadMs,
) {
const __mmX = Number(__mmEntity && __mmEntity.x),
__mmY = Number(__mmEntity && __mmEntity.y);
if (!Number.isFinite(__mmX) || !Number.isFinite(__mmY)) return null;
const __mmPrevious = __mmMobStealMotion[__mmKey],
__mmElapsed = __mmPrevious
? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
: 0;
let __mmVelocityX = __mmPrevious
? (__mmX - __mmPrevious.x) / __mmElapsed
: 0,
__mmVelocityY = __mmPrevious
? (__mmY - __mmPrevious.y) / __mmElapsed
: 0;
const __mmServerElapsed = Number(__mmEntity.t2) - Number(__mmEntity.t1),
__mmServerVelocityX =
(Number(__mmEntity.x2) - Number(__mmEntity.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(__mmEntity.y2) - Number(__mmEntity.y1)) / __mmServerElapsed;
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
) {
((__mmVelocityX = __mmPrevious
? __mmServerVelocityX * 0.75 + __mmVelocityX * 0.25
: __mmServerVelocityX),
(__mmVelocityY = __mmPrevious
? __mmServerVelocityY * 0.75 + __mmVelocityY * 0.25
: __mmServerVelocityY));
}
__mmMobStealMotion[__mmKey] = { x: __mmX, y: __mmY, at: __mmNow };
return {
x: Math.max(0, Math.min(y.mapScale, __mmX + __mmVelocityX * __mmLeadMs)),
y: Math.max(0, Math.min(y.mapScale, __mmY + __mmVelocityY * __mmLeadMs)),
};
}
function __mmMobStealPlan() {
if (!v || !v.alive || !Array.isArray(N)) return null;
const __mmWeapons = __mmMobStealWeaponCandidates();
if (!__mmWeapons.length) return null;
const __mmNow = Date.now(),
__mmPing = Number(window.pingTime),
__mmLeadMs = Math.min(
300,
__mmServerTickMs() +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0),
),
__mmSelf = __mmMobStealPredictPoint(
v,
"self",
__mmNow,
__mmLeadMs,
),
__mmSeen = Object.create(null);
if (!__mmSelf) return null;
__mmSeen.self = !0;
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
const __mmAnimal = N[__mmIndex],
__mmKey = __mmMobStealEntityKey(__mmAnimal);
if (__mmKey == null) continue;
__mmSeen[__mmKey] = !0;
const __mmPrediction = __mmMobStealPredictPoint(
__mmAnimal,
__mmKey,
__mmNow,
__mmLeadMs,
);
if (
!__mmPrediction ||
!__mmAnimal ||
__mmAnimal.active === !1 ||
__mmAnimal.alive === !1 ||
!__mmAnimal.visible ||
!(Number(__mmAnimal.health) > 0) ||
Number(__mmMobStealReservations[__mmKey]) > __mmNow
)
continue;
for (
let __mmWeaponIndex = 0;
__mmWeaponIndex < __mmWeapons.length;
__mmWeaponIndex++
) {
const __mmWeapon = __mmWeapons[__mmWeaponIndex];
if (Number(__mmAnimal.health) > __mmWeapon.damage + 0.001) continue;
const __mmDx = __mmPrediction.x - __mmSelf.x,
__mmDy = __mmPrediction.y - __mmSelf.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
// Match the server gather hitbox for players and AI targets.
__mmReach =
__mmWeapon.range + (Number(__mmAnimal.scale) || 35) * 1.8;
if (__mmDistance > __mmReach) continue;
const __mmScore =
__mmDistance / Math.max(1, __mmReach) +
(__mmWeapon.selected ? 0 : 0.08);
if (!__mmBest || __mmScore < __mmBest.score)
__mmBest = {
animal: __mmAnimal,
key: __mmKey,
weapon: __mmWeapon.weapon,
damage: __mmWeapon.damage,
speed: __mmWeapon.speed,
useBull: __mmWeapon.useBull,
stripMonkeyTail: __mmWeapon.stripMonkeyTail,
restoreTail: __mmWeapon.stripMonkeyTail ? 11 : null,
x: __mmPrediction.x,
y: __mmPrediction.y,
angle: Math.atan2(__mmDy, __mmDx),
score: __mmScore,
};
}
}
for (const __mmKey in __mmMobStealMotion)
__mmSeen[__mmKey] || delete __mmMobStealMotion[__mmKey];
for (const __mmKey in __mmMobStealReservations)
Number(__mmMobStealReservations[__mmKey]) <= __mmNow &&
delete __mmMobStealReservations[__mmKey];
return __mmBest;
}
function __mmFinishMobSteal(__mmReason) {
const __mmAim = __mmMobStealAimAngle,
__mmHadAim = Number.isFinite(__mmMobStealAimAngle),
__mmTool = __mmMobStealRestoreTool,
__mmHat = __mmMobStealRestoreHat,
__mmTail = __mmMobStealRestoreTail,
__mmRestore = __mmActionMayRestore("mobSteal");
(__mmMobStealStageTimer && clearTimeout(__mmMobStealStageTimer),
(__mmMobStealStageTimer = 0),
__mmMobStealReleaseTimer && clearTimeout(__mmMobStealReleaseTimer),
(__mmMobStealReleaseTimer = 0),
__mmMobStealAttackHeld && O.send("F", 0, __mmAim),
(__mmMobStealAttackHeld = !1),
(__mmMobStealAimAngle = null),
(__mmMobStealRestoreTool = null),
(__mmMobStealRestoreHat = null),
(__mmMobStealRestoreTail = null),
(__mmMobStealPendingPlan = null),
__mmRestore && __mmRestoreTool(__mmTool),
__mmRestore && __mmEquipGearPair(__mmHat, __mmTail, !0),
__mmActionRelease("mobSteal", __mmReason || "predicted last hit complete"),
__mmHadAim && __mmScheduleMouseAimReturn(),
v && v.alive && __mmUpdateWeaponRecharge());
}
function __mmMobStealFirePending() {
((__mmMobStealStageTimer = 0));
const __mmPlan = __mmMobStealPendingPlan;
if (
!__mmPlan ||
!v ||
!v.alive ||
__mmActionOwner !== "mobSteal" ||
__mmEmergencyGetawayActive()
)
return void __mmFinishMobSteal("staged mob steal interrupted");
const __mmAnimal = __mmPlan.animal,
__mmHealth = Number(__mmAnimal && __mmAnimal.health),
__mmNow = Date.now(),
__mmPing = Number(window.pingTime),
__mmLeadMs =
__mmServerTickMs() +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0),
__mmTarget = __mmMobStealPredictPoint(
__mmAnimal,
__mmPlan.key,
__mmNow,
__mmLeadMs,
),
__mmSelf = __mmMobStealPredictPoint(
v,
"self",
__mmNow,
__mmLeadMs,
),
__mmWeaponData = b && b.weapons && b.weapons[__mmPlan.weapon];
if (
!__mmAnimal ||
__mmAnimal.active === !1 ||
__mmAnimal.alive === !1 ||
!__mmAnimal.visible ||
!Number.isFinite(__mmHealth) ||
__mmHealth <= 0 ||
__mmHealth > __mmPlan.damage + 0.001 ||
!__mmTarget ||
!__mmSelf ||
!__mmWeaponData ||
!__mmWeaponReady(__mmPlan.weapon)
)
return void __mmFinishMobSteal("staged target no longer lethal");
const __mmDx = __mmTarget.x - __mmSelf.x,
__mmDy = __mmTarget.y - __mmSelf.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmReach =
(Number(__mmWeaponData.range) || 0) +
(Number(__mmAnimal.scale) || 35) * 1.8;
if (__mmDistance > __mmReach)
return void __mmFinishMobSteal("staged target left range");
if (
__mmPlan.stripMonkeyTail &&
Number(v.tailIndex) !== 0 &&
Number(__mmPendingTail) !== 0
)
return void __mmFinishMobSteal("monkey tail returned before hit");
const __mmAngle = Math.atan2(__mmDy, __mmDx);
((__mmMobStealAimAngle = __mmAngle),
O.send("D", __mmAngle),
je(__mmPlan.weapon, !0),
__mmPlan.useBull &&
__mmActivateCombatHat(7, __mmPlan.stripMonkeyTail ? 0 : null),
O.send("F", 1, __mmAngle),
(__mmMobStealAttackHeld = !0),
(__mmMobStealReleaseTimer = setTimeout(function () {
__mmFinishMobSteal("predicted last hit sent");
}, Math.max(120, __mmServerTickMs() * 2))));
}
function __mmMobStealEquipBullStage() {
((__mmMobStealStageTimer = 0));
const __mmPlan = __mmMobStealPendingPlan;
if (
!__mmPlan ||
!v ||
!v.alive ||
__mmActionOwner !== "mobSteal" ||
__mmEmergencyGetawayActive()
)
return void __mmFinishMobSteal("staged mob steal interrupted");
// Monkey Tail remains staged early for damage correctness, but Bull itself
// is deliberately deferred to __mmMobStealFirePending so it shares the
// weapon's exact packet phase.
__mmMobStealStageTimer = setTimeout(
__mmMobStealFirePending,
__mmServerTickMs() * 2,
);
}
function __mmStartMobStealAttack(__mmPlan) {
if (
!__mmPlan ||
!v ||
!v.alive ||
__mmEmergencyGetawayActive()
)
return !1;
(__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmActionOwner === "matThief" &&
__mmFinishMatThief("mob steal last hit"));
if (!__mmActionClaim("mobSteal", "predicted one-hit mob")) return !1;
const __mmNow = Date.now();
(__mmMobStealReservations[__mmPlan.key] =
__mmNow +
Math.max(__mmPlan.speed, 5 * __mmServerTickMs()),
(__mmMobStealRestoreTool = __mmSelectedTool()),
(__mmMobStealRestoreHat = __mmPlan.useBull
? __mmInstaSafeRestoreHat(__mmBushRestoreHat(v.skinIndex))
: null),
(__mmMobStealRestoreTail = __mmPlan.stripMonkeyTail
? __mmBushRestoreTail(__mmPlan.restoreTail)
: null),
(__mmMobStealPendingPlan = __mmPlan),
__mmPlan.stripMonkeyTail && __mmEquipTailNow(0, !0),
// Do not swing unless the tail-off request was actually emitted or is
// already active. This prevents Shift escape or another gear lock from
// allowing a reduced-damage Monkey Tail hit through.
__mmPlan.stripMonkeyTail &&
Number(v.tailIndex) !== 0 &&
Number(__mmPendingTail) !== 0)
return (
delete __mmMobStealReservations[__mmPlan.key],
(__mmMobStealRestoreTool = null),
(__mmMobStealRestoreHat = null),
(__mmMobStealRestoreTail = null),
(__mmMobStealPendingPlan = null),
__mmActionRelease("mobSteal", "monkey tail removal blocked"),
!1
);
__mmMobStealStageTimer = setTimeout(
__mmMobStealEquipBullStage,
__mmServerTickMs(),
);
return !0;
}
function __mmUpdateMobSteal() {
if (
!__mmMobStealEnabled ||
document.hidden ||
!v ||
!v.alive ||
v.lockMove ||
__mmMobStealReleaseTimer ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmInsta.isActive() ||
__mmSyncFollowerEnabled ||
!(
__mmActionOwner === "idle" ||
__mmActionOwner === "weaponRecharge" ||
__mmActionOwner === "matThief"
)
)
return;
const __mmPlan = __mmMobStealPlan();
__mmPlan && __mmStartMobStealAttack(__mmPlan);
}
function __mmStartMobSteal() {
__mmEnsureOperationPipeline();
}
function __mmStopMobSteal() {
(__mmMobStealTimer && clearInterval(__mmMobStealTimer),
(__mmMobStealTimer = 0),
__mmFinishMobSteal("mode disabled"));
}
function __mmRecordPlayerSwing(__mmPlayerSid, __mmWeapon) {
if (__mmPlayerSid == null) return;
__mmCombatThreatCalculatedAt = 0;
__mmTrackPlayerToolCooldown(__mmPlayerSid, __mmWeapon);
__mmRecentPlayerSwings[String(__mmPlayerSid)] = {
at: Date.now(),
weapon: __mmWeapon,
};
}
function __mmObservedObjectHitDamage(__mmObject, __mmHitAngle) {
if (!__mmObject || !Array.isArray(E)) return 0;
const __mmNow = Date.now();
let __mmBestDamage = 0,
__mmBestScore = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex],
__mmRecent =
__mmPlayer && __mmRecentPlayerSwings[String(__mmPlayer.sid)];
if (!__mmPlayer || !__mmPlayer.alive || !__mmRecent) continue;
const __mmAge = __mmNow - __mmRecent.at,
__mmWeaponId =
__mmRecent.weapon == null ? __mmPlayer.weaponIndex : __mmRecent.weapon,
__mmWeapon = b.weapons && b.weapons[__mmWeaponId];
if (__mmAge < 0 || __mmAge > 900 || !__mmWeapon) continue;
const __mmDx = __mmObject.x - __mmPlayer.x,
__mmDy = __mmObject.y - __mmPlayer.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmDirection = Math.atan2(__mmDy, __mmDx),
__mmAngleDifference = M.getAngleDist(__mmDirection, __mmHitAngle),
__mmMeleeReach =
(Number(__mmWeapon.range) || 0) + (Number(__mmObject.scale) || 0) + 16;
if (
__mmWeapon.projectile == null &&
(__mmDistance > __mmMeleeReach || __mmAngleDifference > 0.32)
)
continue;
const __mmDamage = __mmWeaponStructureDamage(
__mmPlayer,
__mmWeaponId,
__mmObject,
);
if (!__mmDamage) continue;
const __mmScore = __mmAge +
(__mmWeapon.projectile == null ? __mmDistance : 300);
if (__mmScore < __mmBestScore) {
((__mmBestScore = __mmScore), (__mmBestDamage = __mmDamage));
}
}
return __mmBestDamage || __mmCurrentStructureDamage(__mmObject);
}
function __mmObserveObjectHit(__mmAngle, __mmObjectSid) {
const __mmObject = typeof ns === "function" ? ns(__mmObjectSid) : null,
__mmState = __mmBreakableState(__mmObject);
if (!__mmObject || !__mmState) return;
const __mmDamage = __mmObservedObjectHitDamage(
__mmObject,
Number(__mmAngle) || 0,
);
if (__mmDamage > 0)
__mmState.health = Math.max(0, __mmState.health - __mmDamage);
}
function __mmBreakableHitLabel(__mmObject) {
const __mmState = __mmBreakableState(__mmObject);
if (!__mmState || !(Number(__mmState.health) > 0)) return null;
const __mmSignature = [
Number(__mmState.health).toFixed(3),
Number(v && v.weaponIndex),
Number(v && v.skinIndex),
Number(v && v.tailIndex),
].join(":"),
__mmCached = __mmBreakableLabelCache.get(__mmObject);
if (__mmCached && __mmCached.signature === __mmSignature)
return __mmCached.label;
const __mmDamage = __mmCurrentStructureDamage(__mmObject);
// A zero-damage tool used to draw an infinity glyph, and a locally
// destroyed object could briefly draw 0 while waiting for server removal.
// Both collapse into a stray center dot at normal game scale. Only render
// actionable, positive hit counts.
if (!(__mmDamage > 0)) return null;
const __mmLabel = String(
Math.max(1, Math.ceil(__mmState.health / __mmDamage)),
);
__mmBreakableLabelCache.set(__mmObject, {
signature: __mmSignature,
label: __mmLabel,
});
return __mmLabel;
}
function __mmDrawBreakableHitCounts() {
if (!v || !v.alive || !k) return;
const __mmLeft = oe - _ / 2,
__mmTop = ae - L / 2,
__mmBreakables = __mmActiveObjectSnapshot().breakables;
(k.save(),
(k.textAlign = "center"),
(k.textBaseline = "middle"),
(k.globalAlpha = 0.96),
(k.shadowColor = "#a855f7"),
(k.shadowBlur = __mmFpsBoostEnabled ? 0 : 4),
(k.strokeStyle = "rgba(5,3,9,.92)"),
(k.lineWidth = 3),
(k.font = "900 20px Hammersmith One, Arial, sans-serif"),
(k.fillStyle = "#ffffff"));
for (let __mmIndex = 0; __mmIndex < __mmBreakables.length; __mmIndex++) {
const __mmObject = __mmBreakables[__mmIndex].object;
if (!__mmObject || !__mmObject.active) continue;
const __mmX = __mmObject.x + __mmObject.xWiggle - __mmLeft,
__mmY = __mmObject.y + __mmObject.yWiggle - __mmTop;
if (!ts(__mmX, __mmY, (Number(__mmObject.scale) || 35) + 10)) continue;
const __mmHits = __mmBreakableHitLabel(__mmObject);
if (__mmHits == null) continue;
(k.strokeText(__mmHits, __mmX, __mmY),
k.fillText(__mmHits, __mmX, __mmY));
}
k.restore();
}
function __mmDrawPlacementVisuals() {
if (!__mmPlacementVisualsEnabled || !v || !v.alive || !k) return;
const __mmPreview = __mmSmartPlacementPreview,
__mmNow = performance.now(),
__mmAge = __mmNow - Number(__mmPreview && __mmPreview.updatedAt);
if (!__mmPreview || !__mmPreview.updatedAt || __mmAge > 850) return;
const __mmFade = Math.max(0, Math.min(1, (850 - __mmAge) / 220)),
__mmLeft = oe - _ / 2,
__mmTop = ae - L / 2,
__mmOwnX = Number(v.x) - __mmLeft,
__mmOwnY = Number(v.y) - __mmTop;
function __mmDrawSlot(
__mmCandidate,
__mmColor,
__mmAlpha,
__mmWidth,
__mmDash,
__mmFill,
__mmLabel,
) {
if (!__mmCandidate) return;
const __mmX = Number(__mmCandidate.x) - __mmLeft,
__mmY = Number(__mmCandidate.y) - __mmTop,
__mmScale = Math.max(8, Number(__mmCandidate.scale) || 45);
if (!ts(__mmX, __mmY, __mmScale + 18)) return;
(k.save(),
(k.globalAlpha = __mmAlpha * __mmFade),
(k.strokeStyle = __mmColor),
(k.fillStyle = __mmColor),
(k.lineWidth = __mmWidth),
(k.shadowColor = __mmColor),
(k.shadowBlur = __mmFpsBoostEnabled ? 0 : __mmWidth >= 3 ? 8 : 3),
typeof k.setLineDash === "function" && k.setLineDash(__mmDash || []),
k.beginPath(),
k.arc(__mmX, __mmY, __mmScale, 0, Math.PI * 2));
if (__mmFill) {
const __mmStrokeAlpha = k.globalAlpha;
((k.globalAlpha = __mmStrokeAlpha * 0.2),
k.fill(),
(k.globalAlpha = __mmStrokeAlpha));
}
k.stroke();
if (__mmLabel) {
((k.shadowBlur = __mmFpsBoostEnabled ? 0 : 5),
(k.fillStyle = "#ffffff"),
(k.font = "900 12px Hammersmith One, Arial, sans-serif"),
(k.textAlign = "center"),
(k.textBaseline = "middle"),
k.fillText(__mmLabel, __mmX, __mmY));
}
k.restore();
}
k.save();
const __mmSamples = Array.isArray(__mmPreview.samples)
? __mmPreview.samples
: [];
for (let __mmIndex = 0; __mmIndex < __mmSamples.length; __mmIndex++) {
const __mmCandidate = __mmSamples[__mmIndex],
__mmValid = __mmCandidate && __mmCandidate.valid !== !1;
__mmDrawSlot(
__mmCandidate,
__mmValid ? "#8b5cf6" : "#ef4444",
__mmValid ? 0.16 : 0.2,
1,
__mmValid ? [3, 5] : [2, 4],
!1,
"",
);
}
const __mmRanked = Array.isArray(__mmPreview.ranked)
? __mmPreview.ranked
: [];
for (let __mmIndex = __mmRanked.length - 1; __mmIndex >= 0; __mmIndex--) {
const __mmCandidate = __mmRanked[__mmIndex];
__mmDrawSlot(
__mmCandidate,
__mmCandidate.preplace ? "#38bdf8" : "#c084fc",
0.34,
1.6,
__mmCandidate.preplace ? [7, 4] : [],
!1,
"",
);
}
const __mmSelected = Array.isArray(__mmPreview.selected)
? __mmPreview.selected
: [];
for (let __mmIndex = 0; __mmIndex < __mmSelected.length; __mmIndex++) {
const __mmCandidate = __mmSelected[__mmIndex],
__mmX = Number(__mmCandidate.x) - __mmLeft,
__mmY = Number(__mmCandidate.y) - __mmTop,
__mmName = String(
(__mmCandidate.data && __mmCandidate.data.name) || "place",
).toLowerCase(),
__mmKind = __mmCandidate.data && __mmCandidate.data.trap
? "T"
: __mmName.includes("spike")
? "S"
: __mmName.slice(0, 1).toUpperCase(),
__mmColor = __mmCandidate.preplace ? "#38bdf8" : "#34d399";
(k.save(),
(k.globalAlpha = 0.45 * __mmFade),
(k.strokeStyle = __mmColor),
(k.lineWidth = 1.4),
typeof k.setLineDash === "function" && k.setLineDash([5, 5]),
k.beginPath(),
k.moveTo(__mmOwnX, __mmOwnY),
k.lineTo(__mmX, __mmY),
k.stroke(),
k.restore());
__mmDrawSlot(
__mmCandidate,
__mmColor,
0.78,
3.2,
__mmCandidate.preplace ? [8, 4] : [],
!0,
__mmKind + " " + Number(__mmCandidate.points || 0).toFixed(1),
);
}
k.restore();
}
Ge = function (__mmLayer, __mmLeft, __mmTop) {
if (!__mmGroundGridFrameDrawn) {
((__mmGroundGridFrameDrawn = !0),
__mmDrawGroundGrid(__mmLeft, __mmTop));
}
return __mmOriginalObjectRender.apply(this, arguments);
};
Wl = function (__mmAngle, __mmObjectSid) {
__mmObserveObjectHit(__mmAngle, __mmObjectSid);
return __mmOriginalObjectHit.apply(this, arguments);
};
function __mmSmartDepthCeiling() {
return Math.max(1, Math.min(10, Math.round(Number(__mmSmartDepth) || 1)));
}
function __mmEffectiveSmartDepth() {
const __mmCeiling = __mmSmartDepthCeiling();
if (!__mmAdaptiveSmartnessEnabled) return __mmCeiling;
return Math.max(
1,
Math.min(
__mmCeiling,
Math.round(Number(__mmAdaptiveSmartDepth) || __mmCeiling),
),
);
}
function __mmAdaptiveSmartnessCombatActive() {
if (!v || !v.alive) return !1;
if (
__mmLiveStateFresh() &&
__mmLiveState.nearestEnemyDistance <= Math.max(__mmCombatRange, 650)
)
return !0;
if (__mmPrimaryHeld || __mmSecondaryHeld || __mmTrapAttackActive) return !0;
return (
__mmActionOwner === "insta" ||
__mmActionOwner === "instaSync" ||
__mmActionOwner === "boostInsta" ||
__mmActionOwner === "spikeTickStrike" ||
__mmActionOwner === "antiInsta" ||
__mmActionOwner === "antiBoostBlock" ||
__mmActionOwner === "shieldDefense" ||
__mmActionOwner === "autoPushSetup" ||
__mmActionOwner === "velTickSetup"
);
}
function __mmPublishAdaptiveSmartness() {
window.dispatchEvent(
new CustomEvent("MooMooKittyAdaptiveSmartness", {
detail: {
enabled: __mmAdaptiveSmartnessEnabled,
effective: __mmEffectiveSmartDepth(),
ceiling: __mmSmartDepthCeiling(),
fps: Number.isFinite(__mmMetricFps) && __mmMetricFps > 0
? __mmMetricFps
: null,
combat: __mmAdaptiveCombat,
reason: __mmAdaptiveSmartnessEnabled
? __mmAdaptiveReason
: "manual ceiling",
},
}),
);
}
function __mmResetAdaptiveSmartness(__mmReason = "sampling") {
((__mmAdaptiveSmartDepth = __mmSmartDepthCeiling()),
(__mmAdaptiveFpsEma =
Number.isFinite(__mmMetricFps) && __mmMetricFps > 0
? __mmMetricFps
: 60),
(__mmAdaptiveLowSince = 0),
(__mmAdaptiveStableSince = 0),
(__mmAdaptiveLastChangeAt = 0),
(__mmAdaptiveReason = __mmReason),
(__mmAdaptiveCombat = !1),
__mmPublishAdaptiveSmartness());
}
function __mmUpdateAdaptiveSmartness(__mmFps, __mmNow) {
const __mmCeiling = __mmSmartDepthCeiling();
if (!__mmAdaptiveSmartnessEnabled) {
((__mmAdaptiveSmartDepth = __mmCeiling),
(__mmAdaptiveReason = "manual ceiling"),
(__mmAdaptiveCombat = !1),
__mmPublishAdaptiveSmartness());
return;
}
__mmAdaptiveSmartDepth = Math.max(
1,
Math.min(__mmCeiling, Math.round(Number(__mmAdaptiveSmartDepth) || __mmCeiling)),
);
if (
!Number.isFinite(__mmFps) ||
__mmFps <= 0 ||
document.hidden ||
__mmHudMenuOpen ||
__mmNativeMenuOpen
) {
((__mmAdaptiveLowSince = 0),
(__mmAdaptiveStableSince = 0),
(__mmAdaptiveReason = __mmHudMenuOpen || __mmNativeMenuOpen
? "paused while menu open"
: document.hidden
? "paused while hidden"
: "sampling"),
__mmPublishAdaptiveSmartness());
return;
}
__mmAdaptiveFpsEma =
__mmAdaptiveFpsEma > 0
? __mmAdaptiveFpsEma * 0.72 + __mmFps * 0.28
: __mmFps;
__mmAdaptiveCombat = __mmAdaptiveSmartnessCombatActive();
const __mmCritical = __mmFps < 28 || __mmAdaptiveFpsEma < 32,
__mmLow = __mmCritical || __mmFps < 40 || __mmAdaptiveFpsEma < 44,
__mmStableThreshold = __mmAdaptiveCombat ? 50 : 55,
__mmStable =
__mmFps >= __mmStableThreshold &&
__mmAdaptiveFpsEma >= __mmStableThreshold - 1;
if (__mmLow) {
__mmAdaptiveStableSince = 0;
__mmAdaptiveLowSince || (__mmAdaptiveLowSince = __mmNow);
const __mmDwell = __mmCritical ? 350 : 1000,
__mmChangeGap = __mmCritical ? 650 : 1050;
if (
__mmAdaptiveSmartDepth > 1 &&
__mmNow - __mmAdaptiveLowSince >= __mmDwell &&
__mmNow - __mmAdaptiveLastChangeAt >= __mmChangeGap
) {
__mmAdaptiveSmartDepth = Math.max(
1,
__mmAdaptiveSmartDepth - (__mmCritical ? 2 : 1),
);
((__mmAdaptiveLastChangeAt = __mmNow),
(__mmAdaptiveLowSince = __mmNow),
(__mmAdaptiveReason = __mmCritical
? "critical FPS · depth reduced"
: "FPS pressure · depth reduced"));
} else
__mmAdaptiveReason = __mmAdaptiveSmartDepth > 1
? "FPS pressure · watching"
: "minimum depth · FPS pressure";
} else if (__mmStable) {
__mmAdaptiveLowSince = 0;
__mmAdaptiveStableSince || (__mmAdaptiveStableSince = __mmNow);
const __mmRecoveryDwell = __mmAdaptiveCombat ? 1000 : 2600,
__mmRecoveryGap = __mmAdaptiveCombat ? 1200 : 2800;
if (
__mmAdaptiveSmartDepth < __mmCeiling &&
__mmNow - __mmAdaptiveStableSince >= __mmRecoveryDwell &&
__mmNow - __mmAdaptiveLastChangeAt >= __mmRecoveryGap
) {
__mmAdaptiveSmartDepth += 1;
((__mmAdaptiveLastChangeAt = __mmNow),
(__mmAdaptiveStableSince = __mmNow),
(__mmAdaptiveReason = __mmAdaptiveCombat
? "stable combat · depth raised"
: "stable FPS · depth raised"));
} else if (__mmAdaptiveSmartDepth < __mmCeiling)
__mmAdaptiveReason = __mmAdaptiveCombat
? "stable combat · recovering"
: "stable FPS · recovering";
else
__mmAdaptiveReason = __mmAdaptiveCombat
? "full depth · stable combat"
: "full depth · stable FPS";
} else {
((__mmAdaptiveLowSince = 0),
(__mmAdaptiveStableSince = 0),
(__mmAdaptiveReason = "holding depth"));
}
__mmPublishAdaptiveSmartness();
}
function __mmUpdateMetrics() {
__mmMetricFrames += 1;
const __mmNow = performance.now(),
__mmElapsed = __mmNow - __mmMetricUpdatedAt;
if (__mmElapsed < 500) return;
((__mmMetricFps = __mmMetricFrames * 1000 / __mmElapsed),
(__mmMetricPps = __mmMetricPacketWindow * 1000 / __mmElapsed),
(__mmMetricFrames = 0),
(__mmMetricPacketWindow = 0),
(__mmMetricUpdatedAt = __mmNow),
__mmUpdateAdaptiveSmartness(__mmMetricFps, __mmNow),
window.dispatchEvent(
new CustomEvent("MooMooKittyMetrics", {
detail: {
ping: Number.isFinite(Number(window.pingTime)) ? Number(window.pingTime) : null,
fps: __mmMetricFps,
packets: __mmMetricPackets,
pps: __mmMetricPps,
smartDepth: __mmEffectiveSmartDepth(),
smartDepthCeiling: __mmSmartDepthCeiling(),
},
}),
));
}
function __mmChatPlayer(__mmPlayerSid) {
try {
return typeof Rt === "function" ? Rt(__mmPlayerSid) : null;
} catch (__mmChatPlayerError) {
return null;
}
}
function __mmChatRelation(__mmPlayer) {
if (
v &&
__mmPlayer &&
String(__mmPlayer.sid) === String(v.sid)
)
return "self";
if (__mmPlayer && __mmIsFriendPlayer(__mmPlayer)) return "friend";
if (__mmPlayer && __mmSameTeam(__mmPlayer)) return "ally";
return "enemy";
}
function __mmRecordChatMessage(
__mmPlayerSid,
__mmRawMessage,
) {
if (!__mmChatHistoryEnabled) {
delete __mmChatBubbleStacks[String(__mmPlayerSid)];
return;
}
const __mmPlayer = __mmChatPlayer(__mmPlayerSid),
__mmMessage = String(
(__mmPlayer && __mmPlayer.chatMessage) || __mmRawMessage || "",
).slice(0, 120),
__mmNow = performance.now(),
__mmDuration = Math.max(
700,
Number(__mmPlayer && __mmPlayer.chatCountdown) || 3e3,
),
__mmSid = String(__mmPlayerSid);
let __mmStack = __mmChatBubbleStacks[__mmSid];
if (!Array.isArray(__mmStack)) __mmStack = [];
// Native chatMessage remains populated after its bubble has disappeared.
// Keep only Kitty-owned entries whose independent lifetime is still live so
// a later message can never resurrect already-faded text.
__mmStack = __mmStack.filter(function (__mmEntry) {
return __mmEntry && __mmEntry.expiresAt > __mmNow;
});
__mmStack.push({
text: __mmMessage,
createdAt: __mmNow,
expiresAt: __mmNow + __mmDuration,
});
__mmStack.length > 3 && __mmStack.splice(0, __mmStack.length - 3);
__mmChatBubbleStacks[__mmSid] = __mmStack;
window.dispatchEvent(
new CustomEvent("MooMooKittyChatMessage", {
detail: {
sid: __mmPlayerSid,
name:
String((__mmPlayer && __mmPlayer.name) || "").trim() ||
"Player " + __mmPlayerSid,
message: __mmMessage,
relation: __mmChatRelation(__mmPlayer),
at: Date.now(),
},
}),
);
}
function __mmHideNativeChatBubbles() {
if (!__mmChatHistoryEnabled || !Array.isArray(E)) return [];
const __mmHidden = [];
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex],
__mmCountdown = Number(__mmPlayer && __mmPlayer.chatCountdown);
if (!__mmPlayer || !__mmPlayer.visible || __mmCountdown <= 0) continue;
(__mmHidden.push({ player: __mmPlayer, countdown: __mmCountdown }),
(__mmPlayer.chatCountdown = 0));
}
return __mmHidden;
}
function __mmRestoreNativeChatBubbles(__mmHidden) {
if (!Array.isArray(__mmHidden)) return;
for (let __mmIndex = 0; __mmIndex < __mmHidden.length; __mmIndex++) {
const __mmEntry = __mmHidden[__mmIndex];
__mmEntry.player &&
(__mmEntry.player.chatCountdown = __mmEntry.countdown);
}
}
function __mmDrawKittyChatBubble(
__mmText,
__mmX,
__mmY,
__mmAlpha,
__mmUpper,
) {
if (!k || !__mmText || __mmAlpha <= 0) return;
const __mmFontSize = __mmUpper ? 34 : 31,
__mmHeight = __mmUpper ? 54 : 49,
__mmPadding = __mmUpper ? 34 : 28,
__mmMaxWidth = __mmUpper ? 560 : 520;
k.save();
((k.globalAlpha = Math.min(1, __mmAlpha) * 0.96),
(k.font =
"600 " + __mmFontSize + "px Hammersmith One, Arial, sans-serif"),
(k.textBaseline = "middle"),
(k.textAlign = "center"));
const __mmWidthKey = String(__mmUpper ? 1 : 0) + ":" + __mmText;
let __mmWidth = __mmChatBubbleWidthCache.get(__mmWidthKey);
if (!Number.isFinite(__mmWidth)) {
__mmWidth = Math.min(
__mmMaxWidth,
k.measureText(__mmText).width + __mmPadding,
);
(__mmChatBubbleWidthCache.size >= 180 &&
__mmChatBubbleWidthCache.clear(),
__mmChatBubbleWidthCache.set(__mmWidthKey, __mmWidth));
}
let __mmFillStyle;
if (__mmFpsBoostEnabled)
__mmFillStyle = __mmUpper
? "rgba(35,13,55,.88)"
: "rgba(24,10,38,.88)";
else {
const __mmGradient = k.createLinearGradient(
__mmX - __mmWidth / 2,
__mmY,
__mmX + __mmWidth / 2,
__mmY,
);
(__mmGradient.addColorStop(
0,
__mmUpper ? "rgba(14,7,23,.88)" : "rgba(8,5,13,.86)",
),
__mmGradient.addColorStop(
1,
__mmUpper ? "rgba(58,18,88,.82)" : "rgba(45,15,70,.78)",
));
__mmFillStyle = __mmGradient;
}
((k.shadowColor = "rgba(168,85,247,.72)"),
(k.shadowBlur = __mmFpsBoostEnabled ? 0 : __mmUpper ? 14 : 12),
(k.fillStyle = __mmFillStyle),
k.beginPath());
typeof k.roundRect === "function"
? k.roundRect(
__mmX - __mmWidth / 2,
__mmY - __mmHeight / 2,
__mmWidth,
__mmHeight,
__mmUpper ? 10 : 9,
)
: k.rect(
__mmX - __mmWidth / 2,
__mmY - __mmHeight / 2,
__mmWidth,
__mmHeight,
);
(k.fill(),
(k.shadowBlur = __mmFpsBoostEnabled ? 0 : 5),
(k.strokeStyle = "rgba(216,180,254,.78)"),
(k.lineWidth = __mmUpper ? 1.5 : 1.25),
k.stroke(),
(k.fillStyle = "#ffffff"),
(k.shadowColor = "#8b5cf6"),
(k.shadowBlur = __mmFpsBoostEnabled ? 0 : __mmUpper ? 9 : 8),
k.fillText(
__mmText,
__mmX,
__mmY,
Math.max(1, __mmWidth - __mmPadding + 4),
),
k.restore());
}
function __mmDrawInterruptedChats() {
if (!__mmChatHistoryEnabled || !k || !Array.isArray(E)) return;
const __mmNow = performance.now(),
__mmLeft = oe - _ / 2,
__mmTop = ae - L / 2;
// Expiry bookkeeping does not need animation-frame cadence. The bubbles
// still animate each frame, while stale-map cleanup runs four times a second.
if (__mmNow >= __mmChatBubbleCleanupAt) {
__mmChatBubbleCleanupAt = __mmNow + 250;
for (const __mmSid in __mmChatBubbleStacks) {
const __mmStack = __mmChatBubbleStacks[__mmSid];
if (!Array.isArray(__mmStack)) {
delete __mmChatBubbleStacks[__mmSid];
continue;
}
for (let __mmIndex = __mmStack.length - 1; __mmIndex >= 0; __mmIndex--)
__mmNow >= __mmStack[__mmIndex].expiresAt &&
__mmStack.splice(__mmIndex, 1);
__mmStack.length || delete __mmChatBubbleStacks[__mmSid];
}
}
let __mmRenderedBubblePlayers = 0;
const __mmBubblePlayerLimit = __mmFpsBoostEnabled ? 6 : Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (!__mmPlayer || !__mmPlayer.visible) continue;
const __mmSid = String(__mmPlayer.sid),
__mmStack = __mmChatBubbleStacks[__mmSid];
if (!Array.isArray(__mmStack) || !__mmStack.length) continue;
const __mmX = Number(__mmPlayer.x) - __mmLeft,
__mmMainY =
Number(__mmPlayer.y) -
(Number(__mmPlayer.scale) || 35) -
__mmTop -
104;
if (!ts(__mmX, __mmMainY, 145)) continue;
if (++__mmRenderedBubblePlayers > __mmBubblePlayerLimit) break;
const __mmFirstVisible = Math.max(0, __mmStack.length - 3),
__mmVisibleCount = __mmStack.length - __mmFirstVisible;
for (
let __mmMessageIndex = 0;
__mmMessageIndex < __mmVisibleCount;
__mmMessageIndex++
) {
const __mmState = __mmStack[__mmFirstVisible + __mmMessageIndex],
__mmDistanceFromNewest =
__mmVisibleCount - 1 - __mmMessageIndex,
__mmUpper = __mmDistanceFromNewest > 0,
__mmEnter = Math.min(
1,
Math.max(0, (__mmNow - __mmState.createdAt) / 160),
),
__mmRemaining = __mmState.expiresAt - __mmNow,
__mmAlpha =
__mmEnter * Math.min(1, Math.max(0, __mmRemaining / 650)),
__mmY =
__mmMainY -
__mmDistanceFromNewest * 66 +
(1 - __mmEnter) * 9;
__mmDrawKittyChatBubble(
__mmState.text,
__mmX,
__mmY,
__mmAlpha,
__mmUpper,
);
}
}
}
Cl = function () {
const __mmVisualMenuOpen = __mmHudMenuOpen || __mmNativeMenuOpen,
__mmHiddenChats = __mmVisualMenuOpen
? null
: __mmHideNativeChatBubbles();
let __mmResult;
try {
((__mmGroundGridFrameDrawn = !1),
(__mmResult = __mmOriginalRender.apply(this, arguments)));
} finally {
__mmHiddenChats && __mmRestoreNativeChatBubbles(__mmHiddenChats);
}
__mmUpdateMetrics();
if (!__mmVisualMenuOpen) {
(__mmDrawPlacementVisuals(),
__mmPlacementVisualsEnabled && __mmDrawAutoSpikeSpamGhost(),
__mmDrawEsp(),
__mmDrawReloadArcs(),
__mmDrawPlayerCooldownBars(),
__mmDrawWeaponXpBar(),
__mmDrawCombatTelemetry(),
__mmDrawBreakableHitCounts(),
__mmDrawAntiCollisionPopups(),
__mmDrawInstaTypePopups(),
__mmDrawClanPingAlerts(),
__mmDrawInterruptedChats());
}
return __mmResult;
};
function __mmDrawClanPingAlerts() {
if (!v || __mmTeamKey(v) == null) {
__mmClanPingAlerts.length = 0;
return;
}
if (
!__mmNotificationTracersEnabled ||
!k ||
!v.alive ||
!__mmClanPingAlerts.length
)
return;
const __mmNow = performance.now(),
__mmWidth = Math.max(1, Number(_) || Number(k.canvas && k.canvas.width) || 1),
__mmHeight = Math.max(1, Number(L) || Number(k.canvas && k.canvas.height) || 1),
__mmLeft = Number(oe) - __mmWidth / 2,
__mmTop = Number(ae) - __mmHeight / 2,
__mmMargin = Math.min(58, Math.max(12, Math.min(__mmWidth, __mmHeight) * 0.12)),
__mmRawSelfX = Number(v.x) - __mmLeft,
__mmRawSelfY = Number(v.y) - __mmTop,
__mmSelfX = Number.isFinite(__mmRawSelfX)
? Math.max(__mmMargin, Math.min(__mmWidth - __mmMargin, __mmRawSelfX))
: __mmWidth / 2,
__mmSelfY = Number.isFinite(__mmRawSelfY)
? Math.max(__mmMargin, Math.min(__mmHeight - __mmMargin, __mmRawSelfY))
: __mmHeight / 2;
for (
let __mmIndex = __mmClanPingAlerts.length - 1;
__mmIndex >= 0;
__mmIndex--
) {
const __mmAlert = __mmClanPingAlerts[__mmIndex];
if (__mmNow >= __mmAlert.expiresAt) {
__mmClanPingAlerts.splice(__mmIndex, 1);
continue;
}
const __mmAge = __mmNow - __mmAlert.startedAt,
__mmRemaining = __mmAlert.expiresAt - __mmNow,
__mmAlpha =
Math.min(1, __mmAge / 110) * Math.min(1, __mmRemaining / 650),
__mmPulse = 1 + Math.sin(__mmAge / 145) * 0.1,
__mmTargetX = __mmAlert.x - __mmLeft,
__mmTargetY = __mmAlert.y - __mmTop,
__mmDX = __mmTargetX - __mmSelfX,
__mmDY = __mmTargetY - __mmSelfY,
__mmDistance = Math.hypot(__mmDX, __mmDY),
__mmUnitX = __mmDistance > 0.01 ? __mmDX / __mmDistance : 0,
__mmUnitY = __mmDistance > 0.01 ? __mmDY / __mmDistance : -1;
let __mmEdgeDistance = Infinity;
if (__mmUnitX > 0.001)
__mmEdgeDistance = Math.min(
__mmEdgeDistance,
(__mmWidth - __mmMargin - __mmSelfX) / __mmUnitX,
);
else if (__mmUnitX < -0.001)
__mmEdgeDistance = Math.min(
__mmEdgeDistance,
(__mmMargin - __mmSelfX) / __mmUnitX,
);
if (__mmUnitY > 0.001)
__mmEdgeDistance = Math.min(
__mmEdgeDistance,
(__mmHeight - __mmMargin - __mmSelfY) / __mmUnitY,
);
else if (__mmUnitY < -0.001)
__mmEdgeDistance = Math.min(
__mmEdgeDistance,
(__mmMargin - __mmSelfY) / __mmUnitY,
);
if (!Number.isFinite(__mmEdgeDistance) || __mmEdgeDistance <= 0)
__mmEdgeDistance = Math.min(__mmWidth, __mmHeight) * 0.42;
// Notification tracers live halfway between the local player and the
// viewport edge along the actual world-space alert bearing. They no
// longer collapse to the top-center edge when the sender is far away.
const __mmMarkerDistance = Math.max(82, __mmEdgeDistance * 0.52),
__mmRawMarkerX = __mmSelfX + __mmUnitX * __mmMarkerDistance,
__mmRawMarkerY = __mmSelfY + __mmUnitY * __mmMarkerDistance,
__mmMarkerX = Math.max(
__mmMargin,
Math.min(__mmWidth - __mmMargin, __mmRawMarkerX),
),
__mmMarkerY = Math.max(
__mmMargin,
Math.min(__mmHeight - __mmMargin, __mmRawMarkerY),
),
__mmArrowX = __mmMarkerX - __mmUnitX * 35,
__mmArrowY = __mmMarkerY - __mmUnitY * 35,
__mmAngle = Math.atan2(__mmUnitY, __mmUnitX);
(k.save(),
(k.globalAlpha = __mmAlpha),
(k.lineJoin = "round"),
(k.lineCap = "round"),
(k.shadowColor = "#a855f7"),
(k.shadowBlur = 16),
(k.strokeStyle = "rgba(9, 5, 15, 0.96)"),
(k.fillStyle = "#ffffff"),
(k.lineWidth = 6),
k.beginPath(),
k.arc(__mmMarkerX, __mmMarkerY, 19 * __mmPulse, 0, 2 * Math.PI),
k.stroke(),
(k.strokeStyle = "#ffffff"),
(k.lineWidth = 3),
k.stroke(),
k.save(),
k.translate(__mmArrowX, __mmArrowY),
k.rotate(__mmAngle),
k.beginPath(),
k.moveTo(20 * __mmPulse, 0),
k.lineTo(-11 * __mmPulse, -11 * __mmPulse),
k.lineTo(-5 * __mmPulse, 0),
k.lineTo(-11 * __mmPulse, 11 * __mmPulse),
k.closePath(),
(k.strokeStyle = "rgba(9, 5, 15, 0.96)"),
(k.lineWidth = 6),
k.stroke(),
k.fill(),
k.restore(),
(k.textAlign = "center"),
(k.textBaseline = "middle"),
(k.font = "900 " + Math.round(25 * __mmPulse) + "px Hammersmith One"),
(k.lineWidth = 5),
k.strokeText("!", __mmMarkerX, __mmMarkerY + 1),
k.fillText("!", __mmMarkerX, __mmMarkerY + 1),
k.restore());
}
}
function __mmDrawAntiCollisionPopups() {
if (!k || !__mmAntiCollisionPopups.length) return;
const __mmNow = performance.now(),
__mmLeft = Number(oe) - Number(_) / 2,
__mmTop = Number(ae) - Number(L) / 2;
for (
let __mmIndex = __mmAntiCollisionPopups.length - 1;
__mmIndex >= 0;
__mmIndex--
) {
const __mmPopup = __mmAntiCollisionPopups[__mmIndex],
__mmAge = __mmNow - __mmPopup.startedAt;
if (__mmAge >= 850) {
__mmAntiCollisionPopups.splice(__mmIndex, 1);
continue;
}
const __mmProgress = Math.max(0, Math.min(1, __mmAge / 850)),
__mmAlpha = Math.min(1, __mmAge / 90) *
Math.min(1, (850 - __mmAge) / 260),
__mmPulse = Math.sin(Math.min(1, __mmAge / 180) * Math.PI),
__mmX = __mmPopup.x - __mmLeft,
__mmY =
__mmPopup.y -
__mmTop -
__mmPopup.scale -
18 -
__mmProgress * 32;
if (!ts(__mmX, __mmY, 100)) continue;
(k.save(),
(k.globalAlpha = __mmAlpha),
(k.textAlign = "center"),
(k.textBaseline = "middle"),
(k.lineJoin = "round"),
(k.font =
Math.round(27 + __mmPulse * 8) + "px Hammersmith One"),
(k.lineWidth = 7),
(k.strokeStyle = "rgba(8, 5, 13, 0.94)"),
(k.fillStyle = "#ffffff"),
(k.shadowColor = "#a855f7"),
(k.shadowBlur = 13),
k.strokeText("Stop!", __mmX, __mmY),
k.fillText("Stop!", __mmX, __mmY),
k.restore());
}
}
function __mmShowInstaTypePopup(__mmText) {
if (!v || !v.alive) return;
const __mmLabel = String(__mmText || "Insta").trim().slice(0, 32);
__mmInstaTypePopups.push({
text: __mmLabel || "Insta",
x: Number(v.x) || 0,
y: Number(v.y) || 0,
scale: Number(v.scale) || 35,
startedAt: performance.now(),
});
__mmInstaTypePopups.length > 4 && __mmInstaTypePopups.shift();
}
function __mmDrawInstaTypePopups() {
if (!k || !__mmInstaTypePopups.length) return;
const __mmNow = performance.now(),
__mmLeft = Number(oe) - Number(_) / 2,
__mmTop = Number(ae) - Number(L) / 2;
for (
let __mmIndex = __mmInstaTypePopups.length - 1;
__mmIndex >= 0;
__mmIndex--
) {
const __mmPopup = __mmInstaTypePopups[__mmIndex],
__mmAge = __mmNow - __mmPopup.startedAt;
if (__mmAge >= 1050) {
__mmInstaTypePopups.splice(__mmIndex, 1);
continue;
}
const __mmProgress = Math.max(0, Math.min(1, __mmAge / 1050)),
__mmAlpha = Math.min(1, __mmAge / 80) *
Math.min(1, (1050 - __mmAge) / 300),
__mmPulse = Math.sin(Math.min(1, __mmAge / 190) * Math.PI),
__mmX = __mmPopup.x - __mmLeft,
__mmY =
__mmPopup.y -
__mmTop -
__mmPopup.scale -
27 -
__mmProgress * 38;
if (!ts(__mmX, __mmY, 140)) continue;
(k.save(),
(k.globalAlpha = __mmAlpha),
(k.textAlign = "center"),
(k.textBaseline = "middle"),
(k.lineJoin = "round"),
(k.font = Math.round(24 + __mmPulse * 7) + "px Hammersmith One"),
(k.lineWidth = 7),
(k.strokeStyle = "rgba(8, 5, 13, 0.95)"),
(k.fillStyle = "#f5e9ff"),
(k.shadowColor = "#a855f7"),
(k.shadowBlur = 15),
k.strokeText(__mmPopup.text, __mmX, __mmY),
k.fillText(__mmPopup.text, __mmX, __mmY),
k.restore());
}
}
function __mmUpdateMinimapRegions() {
const __mmMap = document.getElementById("mapDisplay"),
__mmMapScale = Number(y && y.mapScale),
__mmSnowTop = Number(y && y.snowBiomeTop),
__mmRiverWidth = Number(y && y.riverWidth);
if (
!__mmMap ||
!Number.isFinite(__mmMapScale) ||
__mmMapScale <= 0 ||
!Number.isFinite(__mmSnowTop) ||
!Number.isFinite(__mmRiverWidth)
)
return;
if (__mmMinimapRegionElement !== __mmMap) {
__mmMinimapRegionElement = __mmMap;
const __mmComputed = getComputedStyle(__mmMap).backgroundImage;
__mmMinimapRegionBaseImage =
__mmComputed && __mmComputed !== "none" ? __mmComputed : "";
}
const __mmClampPercent = (__mmValue) =>
Math.max(0, Math.min(100, __mmValue)),
__mmSnowPercent = __mmClampPercent((__mmSnowTop / __mmMapScale) * 100),
__mmRiverStart = __mmClampPercent(
((__mmMapScale / 2 - __mmRiverWidth / 2) / __mmMapScale) * 100,
),
__mmRiverEnd = __mmClampPercent(
((__mmMapScale / 2 + __mmRiverWidth / 2) / __mmMapScale) * 100,
),
// MooMoo's desert mirrors the snow band at the bottom of the world. The
// previous overlay painted this entire area green and hid the native
// biome artwork, so give it a distinct, darker high-contrast sand band.
__mmDesertStart = Math.max(
__mmRiverEnd,
__mmClampPercent(
((__mmMapScale - __mmSnowTop) / __mmMapScale) * 100,
),
),
__mmGradient =
"linear-gradient(to bottom," +
"rgba(212,237,255,.88) 0%,rgba(212,237,255,.88) " +
__mmSnowPercent + "%," +
"rgba(99,157,75,.86) " + __mmSnowPercent + "%," +
"rgba(99,157,75,.86) " + __mmRiverStart + "%," +
"rgba(67,139,194,.9) " + __mmRiverStart + "%," +
"rgba(67,139,194,.9) " + __mmRiverEnd + "%," +
"rgba(99,157,75,.86) " + __mmRiverEnd + "%," +
"rgba(99,157,75,.86) " + __mmDesertStart + "%," +
"rgba(132,84,38,.96) " + __mmDesertStart + "%," +
"rgba(103,61,27,.98) 100%)";
(__mmMap.style.backgroundImage = __mmMinimapRegionBaseImage
? __mmGradient + "," + __mmMinimapRegionBaseImage
: __mmGradient,
(__mmMap.style.backgroundColor = "#639d4b"),
(__mmMap.style.backgroundRepeat = "no-repeat"),
(__mmMap.style.backgroundSize = "100% 100%"));
}
function __mmStartMinimapRegions() {
__mmUpdateMinimapRegions();
__mmMinimapRegionTimer ||
(__mmMinimapRegionTimer = setInterval(__mmUpdateMinimapRegions, 750));
}
function __mmIsPlaceableItem(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
return !!(__mmData && __mmData.group && __mmData.group.place);
}
function __mmSelectedPlaceableItem() {
if (!v || !Array.isArray(v.items)) return null;
// MooMoo reserves inventory slot 5 for the active special/utility build.
// Read it directly so automatic trap, spike, cleanup, or break routines can
// never overwrite what H places.
const __mmSpecialSlotItem = v.items[5];
if (__mmIsPlaceableItem(__mmSpecialSlotItem)) return __mmSpecialSlotItem;
const __mmSpecialNames = new Set([
"turret",
"teleporter",
"boost pad",
"platform",
"healing pad",
"blocker",
"spawn pad",
]);
for (let __mmIndex = 0; __mmIndex < v.items.length; __mmIndex++) {
const __mmItem = v.items[__mmIndex],
__mmData = b && b.list && b.list[__mmItem],
__mmName = String((__mmData && __mmData.name) || "")
.trim()
.toLowerCase();
if (__mmIsPlaceableItem(__mmItem) && __mmSpecialNames.has(__mmName))
return __mmItem;
}
return 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.bull,
__mmEntries.emp,
__mmEntries.turret,
__mmEntries.tank,
__mmEntries.shadow,
__mmEntries.angel,
__mmEntries.blood,
__mmEntries.corrupt,
]
: [
__mmEntries.monkeyTail,
__mmEntries.soldier,
__mmEntries.bull,
__mmEntries.booster,
__mmEntries.emp,
__mmEntries.turret,
__mmEntries.tank,
__mmEntries.shadow,
__mmEntries.angel,
__mmEntries.blood,
__mmEntries.corrupt,
];
}
function __mmOwnsAutoPurchaseEntry(__mmEntry) {
return !!(
v &&
__mmEntry &&
( __mmEntry.tail
? v.tails && v.tails[__mmEntry.id]
: v.skins && v.skins[__mmEntry.id])
);
}
function __mmUpdateAutoPurchase() {
if (
!__mmAutoPurchaseEnabled ||
__mmSyncFollowerEnabled ||
__mmInsta.isActive() ||
!v ||
!v.alive
)
return;
if (__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() {
__mmEnsureOperationPipeline();
}
function __mmStopAutoPurchase() {
(__mmAutoPurchaseTimer && clearInterval(__mmAutoPurchaseTimer),
(__mmAutoPurchaseTimer = 0),
(__mmAutoPurchasePending = null));
}
function __mmEnemyWithinCombatRange() {
if (!v || !v.alive) return !1;
if (__mmLiveStateFresh())
return __mmLiveState.nearestEnemyDistance <= __mmCombatRange;
for (let __mmEnemyIndex = 0; __mmEnemyIndex < E.length; __mmEnemyIndex++) {
const __mmEnemy = E[__mmEnemyIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmDx = __mmEnemy.x - v.x,
__mmDy = __mmEnemy.y - v.y;
if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmCombatRange * __mmCombatRange)
return !0;
}
return !1;
}
function __mmCombatSafeHat(__mmHat) {
return Number(__mmHat) === Number(__mmEmpHelmet) &&
__mmEnemyWithinCombatRange()
? v && v.skins && v.skins[6]
? 6
: 0
: __mmHat;
}
let __mmLastUpgradePacketAt = 0;
const __mmUpgradeOriginalClicks = new WeakMap(),
__mmUpgradeOriginalDisplays = new WeakMap();
function __mmUpgradeSelection(__mmSelection) {
const __mmIndex = Number(__mmSelection),
__mmWeaponCount = b && Array.isArray(b.weapons) ? b.weapons.length : 0;
if (!Number.isInteger(__mmIndex) || __mmIndex < 0) return null;
if (__mmIndex < __mmWeaponCount)
return {
entry: b.weapons[__mmIndex],
prerequisite: __mmOriginalWeaponPrerequisites[__mmIndex],
owned: v && v.weapons,
};
const __mmItemIndex = __mmIndex - __mmWeaponCount;
return {
entry: b && b.list && b.list[__mmItemIndex],
prerequisite: __mmOriginalItemPrerequisites[__mmItemIndex],
owned: v && v.items,
};
}
function __mmUpgradeServerSafe(__mmSelection) {
const __mmChoice = __mmUpgradeSelection(__mmSelection);
if (
!v ||
!v.alive ||
!__mmChoice ||
!__mmChoice.entry ||
!(Number(v.upgradePoints) > 0)
)
return !1;
const __mmRequiredAge = Number(__mmChoice.entry.age),
__mmCurrentUpgradeAge = Number(v.upgrAge);
if (
Number.isFinite(__mmRequiredAge) &&
Number.isFinite(__mmCurrentUpgradeAge) &&
__mmRequiredAge !== __mmCurrentUpgradeAge
)
return !1;
// Kitty clears prerequisites in MooMoo's item-data module, so a choice
// rendered by the native same-age screen is intentionally valid.
if (__mmAllItemsUnlockEnabled && __mmChoice.entry.pre == null) return !0;
return (
__mmChoice.prerequisite == null ||
(Array.isArray(__mmChoice.owned) &&
__mmChoice.owned.includes(__mmChoice.prerequisite))
);
}
function __mmUpgradeBlockedNotice(__mmSelection) {
const __mmDetail =
Number(__mmSelection) === __mmMusket
? "Musket blocked: Crossbow prerequisite missing"
: "Upgrade blocked: wrong weapon path";
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomStatus", {
detail: __mmDetail,
}),
);
}
function __mmAllowUpgradePacket(__mmSelection) {
if (!__mmUpgradeServerSafe(__mmSelection))
return (__mmUpgradeBlockedNotice(__mmSelection), !1);
const __mmNow = Date.now();
// Suppress a browser double-click, not the next legitimate choice. Send one
// normal packet and do not chain Katana and Musket in the same frame.
if (
__mmNow - __mmLastUpgradePacketAt <
Math.max(120, __mmServerTickMs())
)
return !1;
return ((__mmLastUpgradePacketAt = __mmNow), !0);
}
function __mmMarkUnsafeUpgradeChoices() {
if (!b || !Array.isArray(b.weapons) || !Array.isArray(b.list)) return;
const __mmTotal = b.weapons.length + b.list.length;
let __mmAvailableCount = 0;
for (let __mmIndex = 0; __mmIndex < __mmTotal; __mmIndex++) {
const __mmSafe = __mmUpgradeServerSafe(__mmIndex),
__mmElement = document.getElementById("upgradeItem" + __mmIndex);
if (__mmSafe) {
// Only count options the game's upgrade renderer actually created.
// Definitions can be age-valid in data while having no clickable DOM
// entry, which previously left an empty holder/counter visible.
if (!__mmElement) continue;
__mmAvailableCount++;
if (
__mmElement.getAttribute("data-kitty-upgrade-blocked") === "1"
) {
(__mmElement.removeAttribute("data-kitty-upgrade-blocked"),
__mmElement.removeAttribute("aria-disabled"),
__mmElement.removeAttribute("aria-hidden"),
__mmElement.style.removeProperty("opacity"),
__mmElement.style.removeProperty("filter"),
__mmElement.style.removeProperty("cursor"),
(__mmElement.style.display =
__mmUpgradeOriginalDisplays.get(__mmElement) || ""),
__mmUpgradeOriginalDisplays.delete(__mmElement),
__mmUpgradeOriginalClicks.has(__mmElement) &&
((__mmElement.onclick = __mmUpgradeOriginalClicks.get(__mmElement)),
__mmUpgradeOriginalClicks.delete(__mmElement)),
__mmElement.title === "Blocked: server prerequisite not met" &&
__mmElement.removeAttribute("title"));
}
continue;
}
if (!__mmElement) continue;
__mmElement.getAttribute("data-kitty-upgrade-blocked") !== "1" &&
(__mmUpgradeOriginalClicks.set(__mmElement, __mmElement.onclick),
__mmUpgradeOriginalDisplays.set(__mmElement, __mmElement.style.display));
// Vanilla never renders a locked branch as a disabled card. Fully remove
// stale entries that survived an upgrade-screen refresh.
((__mmElement.style.display = "none"),
__mmElement.setAttribute("data-kitty-upgrade-blocked", "1"),
__mmElement.setAttribute("aria-disabled", "true"),
__mmElement.setAttribute("aria-hidden", "true"),
(__mmElement.onclick = function () {
__mmUpgradeBlockedNotice(__mmIndex);
}));
}
const __mmHideChooser = __mmAvailableCount === 0,
__mmHolder = document.getElementById("upgradeHolder"),
__mmCounter = document.getElementById("upgradeCounter");
for (const __mmChooser of [__mmHolder, __mmCounter]) {
if (!__mmChooser) continue;
__mmHideChooser
? __mmChooser.setAttribute("data-kitty-no-upgrades", "1")
: __mmChooser.removeAttribute("data-kitty-no-upgrades");
}
}
function __mmApplyUpgradeUnlock() {
const __mmApply = function (__mmEntries, __mmOriginal) {
if (!Array.isArray(__mmEntries)) return;
for (let __mmIndex = 0; __mmIndex < __mmEntries.length; __mmIndex++) {
const __mmEntry = __mmEntries[__mmIndex],
__mmPrerequisite = __mmOriginal[__mmIndex];
if (!__mmEntry || __mmPrerequisite == null) continue;
__mmEntry.pre = __mmAllItemsUnlockEnabled ? null : __mmPrerequisite;
}
};
// Fallback for game builds where the early module-loader signature changes.
// This still edits the same item-data objects before the chooser is opened.
(__mmApply(b && b.weapons, __mmOriginalWeaponPrerequisites),
__mmApply(b && b.list, __mmOriginalItemPrerequisites));
}
function __mmHudState() {
return {
autoHeal: __mmAutoHealEnabled,
soldierAuto: __mmSoldierAutoEnabled,
movementGear: __mmMovementGearEnabled,
trapEscape: __mmTrapEscapeEnabled,
automaticStateRepair: __mmAutomaticStateRepairEnabled,
keybinds: Object.assign({}, __mmKeybinds),
autoAcceptTeamRequests: __mmAutoAcceptTeamRequestsEnabled,
autoDeclineTeamRequests: __mmAutoDeclineTeamRequestsEnabled,
antiBoostInsta: __mmAntiBoostInstaEnabled,
antiInsta: __mmAntiInstaEnabled,
antiCollision: __mmAntiCollisionEnabled,
antiCollisionPauseCombat: __mmAntiCollisionPauseCombatEnabled,
shieldDefense: __mmShieldDefenseEnabled,
placementDefense: __mmPlacementDefenseEnabled,
antiRetrapPush: __mmAntiRetrapPushEnabled,
teammateTrapRescue: __mmTeammateTrapRescueEnabled,
turretSteal: __mmTurretStealEnabled,
spikeGearCounter: __mmSpikeGearCounterEnabled,
dashMovement: __mmDashMovementEnabled,
musketRecharge: __mmMusketRechargeEnabled,
autoPurchase: __mmAutoPurchaseEnabled,
matThief: __mmMatThiefEnabled,
multiTargetBreak: __mmMultiTargetBreakEnabled,
mobSteal: __mmMobStealEnabled,
assassinAutomation: __mmAssassinAutomationEnabled,
spinningWindmills: __mmSpinningWindmillsEnabled,
forceFullServers: __mmForceFullServersEnabled,
bushMode: __mmBushModeRequested,
fpsBoost: __mmFpsBoostEnabled,
smoothVisuals: __mmSmoothVisualsEnabled,
reloadArcs: __mmReloadArcsEnabled,
entityDanger: __mmEntityDangerEnabled,
notificationTracers: __mmNotificationTracersEnabled,
groundGrid: __mmGroundGridEnabled,
esp: __mmEspEnabled,
espLines: __mmEspLinesEnabled,
predictionGhost: __mmPredictionGhostEnabled,
placementVisuals: __mmPlacementVisualsEnabled,
cooldownBars: __mmCooldownBarsEnabled,
weaponXpBar: __mmWeaponXpBarEnabled,
chatHistory: __mmChatHistoryEnabled,
combatTelemetry: __mmCombatTelemetryEnabled,
telemetryProjectileHits: __mmTelemetryProjectileHitsEnabled,
telemetrySpikeKnockback: __mmTelemetrySpikeKnockbackEnabled,
telemetryActualAim: __mmTelemetryActualAimEnabled,
telemetryBuildingOwners: __mmTelemetryBuildingOwnersEnabled,
telemetryShameCount: __mmTelemetryShameCountEnabled,
telemetryDamageHealing: __mmTelemetryDamageHealingEnabled,
enemyColor: __mmEnemyColor,
allyColor: __mmAllyColor,
friendColor: __mmFriendColor,
ownColor: __mmOwnColor,
bullHelmet: __mmBullHelmetEnabled,
tankRightClick: __mmTankRightClickEnabled,
instaKill: __mmInstaUiEnabled,
autoInsta: __mmAutoInstaEnabled,
autoBowUpgradeInsta: __mmAutoBowUpgradeInstaEnabled,
reverseInsta: __mmReverseInstaEnabled,
oneTickInsta: __mmOneTickInstaEnabled,
appleInsta: __mmAppleInstaEnabled,
bleedInsta: __mmBleedInstaEnabled,
knockbackInsta: __mmKnockbackInstaEnabled,
velTickInsta: __mmVelTickInstaEnabled,
polearmAids: __mmPolearmAidsEnabled,
autoPushInsta: __mmAutoPushInstaEnabled,
boostSpikeKill: __mmBoostSpikeEnabled,
autoTrapInsta: __mmAutoTrapInstaEnabled,
autoSpikeInsta: __mmAutoSpikeInstaEnabled,
autoSpikeSpam: __mmAutoSpikeSpamEnabled,
autoSpikeKill: __mmAutoSpikeKillEnabled,
animalTrap: __mmThreatTrapEnabled,
passiveMobTrap: __mmPassiveMobTrapEnabled,
bossTeleporter: __mmBossTeleporterEnabled,
smartAutoPlace: __mmSmartAutoPlaceEnabled,
smartPreplace: __mmSmartPreplaceEnabled,
smartMultiPlace: __mmSmartMultiPlaceEnabled,
smartQuadTraps: __mmSmartQuadTrapsEnabled,
smartQuadSpikes: __mmSmartQuadSpikesEnabled,
smartSpikeContact: __mmSmartSpikeContactEnabled,
smartTrapContact: __mmSmartTrapContactEnabled,
smartKnockbackChain: __mmSmartKnockbackChainEnabled,
smartTrapSurround: __mmSmartTrapSurroundEnabled,
smartAngleDenial: __mmSmartAngleDenialEnabled,
smartAutoPushWeight: __mmSmartAutoPushWeightEnabled,
smartAutoReplace: __mmSmartAutoReplaceEnabled,
smartSpikeSyncPlace: __mmSmartSpikeSyncPlaceEnabled,
smartAntiBoostPlace: __mmSmartAntiBoostPlaceEnabled,
smartMovingMills: __mmSmartMovingMillsEnabled,
smartInstaUtilityPlace: __mmSmartInstaUtilityPlaceEnabled,
instaSync: __mmInstaSyncEnabled,
boostBreak: __mmBoostBreakEnabled,
boostChat: __mmBoostChatEnabled,
materialReply: __mmMaterialReplyEnabled,
meowChainInsta: __mmMeowChainInstaEnabled,
instaChat: __mmInstaChatEnabled,
bushChat: __mmBushChatEnabled,
friendAddedChat: __mmFriendAddedChatEnabled,
enemyMarkedChat: __mmEnemyMarkedChatEnabled,
cleanupProgressChat: __mmCleanupProgressChatEnabled,
cleanupCompleteChat: __mmCleanupCompleteChatEnabled,
modReplyChat: __mmModReplyChatEnabled,
enemyTrapChat: __mmEnemyTrapChatEnabled,
friendTrapChat: __mmFriendTrapChatEnabled,
trapAlertChat: __mmTrapAlertChatEnabled,
deathHistoryChat: __mmDeathHistoryChatEnabled,
syncStatusChat: __mmSyncStatusChatEnabled,
syncMovement: __mmSyncMovementEnabled,
syncCopyWeapons: __mmSyncCopyWeaponsEnabled,
syncCopyBuilds: __mmSyncCopyBuildsEnabled,
syncCopyGear: __mmSyncCopyGearEnabled,
syncCopyAim: __mmSyncCopyAimEnabled,
syncCopyAttacks: __mmSyncCopyAttacksEnabled,
syncCatchupGear: __mmSyncCatchupGearEnabled,
syncPauseInCombat: __mmSyncPauseInCombatEnabled,
syncWasdCombatOnly: __mmSyncWasdCombatOnlyEnabled,
syncTickCombat: __mmSyncTickCombatEnabled,
syncFollowGap: __mmSyncFollowGap,
syncStopTolerance: __mmSyncStopTolerance,
syncResumeTolerance: __mmSyncResumeTolerance,
syncPredictionMs: __mmSyncPredictionMs,
syncCatchupDistance: __mmSyncCatchupDistance,
syncCatchupReleaseDistance: __mmSyncCatchupReleaseDistance,
syncMoveRefreshMs: __mmSyncMoveRefreshMs,
syncRelayUrl: __mmSyncRelayUrl,
syncRoom: __mmSyncRoom,
syncStatus: __mmSyncStatus,
syncTargetName: __mmSyncTargetName,
soldierRange: __mmSoldierRange,
combatRange: __mmCombatRange,
gearHoldTicks: __mmGearHoldTicks,
antiBoostRange: __mmAntiBoostRange,
antiCollisionRange: __mmAntiCollisionRange,
reactionMs: __mmReactionMs,
adaptiveSmartness: __mmAdaptiveSmartnessEnabled,
smartDepth: __mmSmartDepth,
smartPlaceAccuracy: __mmSmartPlaceAccuracy,
smartMaxPlacements: __mmSmartMaxPlacements,
smartPlaceDelay: __mmSmartPlaceDelay,
assassinSafeMs: __mmAssassinSafeMs,
assassinMinHealth: __mmAssassinMinHealth,
assassinDangerRange: __mmAssassinDangerRange,
debugPanel: __mmDebugPanelEnabled,
debugText: __mmRuntimeDebugText(),
killMessageEnabled: __mmKillMessageEnabled,
killMessage: __mmKillMessage,
friendNames: Array.from(__mmFriendNames.values()),
};
}
function __mmPublishHudState() {
window.dispatchEvent(
new CustomEvent("MooMooOPHudState", { detail: __mmHudState() }),
);
}
function __mmSetAutoHeal(__mmEnabled) {
((__mmAutoHealEnabled = !!__mmEnabled),
!__mmAutoHealEnabled &&
__mmAutoHealWasHealing &&
((__mmAutoHealWasHealing = !1), __mmRestoreAutoHealWeapon()),
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomAutoheal", {
detail: __mmAutoHealEnabled,
}),
),
__mmPublishHudState());
}
function __mmSetSoldierAuto(__mmEnabled) {
__mmSoldierAutoEnabled = !!__mmEnabled;
if (
!__mmSoldierAutoEnabled &&
v &&
v.alive &&
__mmSoldierPreviousHat != null
) {
const __mmHat = __mmSoldierPreviousHat;
((__mmSoldierPreviousHat = null),
v.skinIndex === 6 && __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat));
}
__mmPublishHudState();
}
function __mmSetMovementGear(__mmEnabled) {
((__mmMovementGearEnabled = !!__mmEnabled),
!__mmMovementGearEnabled &&
(__mmRestoreMovementGear(), __mmRestoreProximityTail()),
__mmPublishHudState());
}
function __mmSetHudNumber(__mmKey, __mmValue) {
const __mmNumber = Number(__mmValue);
if (!Number.isFinite(__mmNumber)) return;
if (__mmKey === "soldierRange")
__mmSoldierRange = Math.max(100, Math.min(1000, __mmNumber));
else if (__mmKey === "combatRange")
__mmCombatRange = Math.max(100, Math.min(1000, __mmNumber));
else if (__mmKey === "gearHoldTicks")
__mmGearHoldTicks = Math.max(1, Math.min(8, Math.round(__mmNumber)));
else if (__mmKey === "antiBoostRange")
__mmAntiBoostRange = Math.max(80, Math.min(500, __mmNumber));
else if (__mmKey === "antiCollisionRange")
__mmAntiCollisionRange = Math.max(120, Math.min(500, __mmNumber));
else if (__mmKey === "reactionMs") {
__mmReactionMs = Math.max(10, Math.min(100, __mmNumber));
__mmLiveStateTimer &&
(clearInterval(__mmLiveStateTimer),
(__mmLiveStateTimer = 0),
__mmStartLiveState());
__mmAntiCollisionTimer &&
(clearInterval(__mmAntiCollisionTimer),
(__mmAntiCollisionTimer = 0),
__mmStartAntiCollision());
} else if (__mmKey === "smartDepth") {
const __mmPreviousCeiling = __mmSmartDepthCeiling(),
__mmNextCeiling = Math.max(1, Math.min(10, Math.round(__mmNumber)));
__mmSmartDepth = __mmNextCeiling;
if (
!__mmAdaptiveSmartnessEnabled ||
__mmAdaptiveSmartDepth >= __mmPreviousCeiling ||
__mmAdaptiveSmartDepth > __mmNextCeiling
)
__mmAdaptiveSmartDepth = __mmNextCeiling;
__mmPublishAdaptiveSmartness();
}
else if (__mmKey === "smartPlaceAccuracy")
__mmSmartPlaceAccuracy = Math.max(20, Math.min(180, Math.round(__mmNumber)));
else if (__mmKey === "smartMaxPlacements")
__mmSmartMaxPlacements = Math.max(1, Math.min(4, Math.round(__mmNumber)));
else if (__mmKey === "smartPlaceDelay")
__mmSmartPlaceDelay = Math.max(0, Math.min(222, Math.round(__mmNumber)));
else if (__mmKey === "assassinSafeMs")
__mmAssassinSafeMs = Math.max(500, Math.min(5000, Math.round(__mmNumber)));
else if (__mmKey === "assassinMinHealth")
__mmAssassinMinHealth = Math.max(20, Math.min(100, Math.round(__mmNumber)));
else if (__mmKey === "assassinDangerRange")
__mmAssassinDangerRange = Math.max(250, Math.min(1200, Math.round(__mmNumber)));
else if (__mmKey === "syncFollowGap")
__mmSyncFollowGap = Math.max(2, Math.min(120, Math.round(__mmNumber)));
else if (__mmKey === "syncStopTolerance")
__mmSyncStopTolerance = Math.max(
1,
Math.min(30, Math.round(__mmNumber)),
);
else if (__mmKey === "syncResumeTolerance")
__mmSyncResumeTolerance = Math.max(
2,
Math.min(60, Math.round(__mmNumber)),
);
else if (__mmKey === "syncPredictionMs")
__mmSyncPredictionMs = Math.max(
0,
Math.min(300, Math.round(__mmNumber)),
);
else if (__mmKey === "syncCatchupDistance")
__mmSyncCatchupDistance = Math.max(
100,
Math.min(1200, Math.round(__mmNumber)),
);
else if (__mmKey === "syncCatchupReleaseDistance")
__mmSyncCatchupReleaseDistance = Math.max(
50,
Math.min(800, Math.round(__mmNumber)),
);
else if (__mmKey === "syncMoveRefreshMs")
__mmSyncMoveRefreshMs = Math.max(
16,
Math.min(250, Math.round(__mmNumber)),
);
else return;
__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 === "automaticStateRepair")
((__mmAutomaticStateRepairEnabled = __mmEnabled),
__mmEnabled && __mmUpdateAutomaticStateRepair());
else if (__mmKey === "autoAcceptTeamRequests")
((__mmAutoAcceptTeamRequestsEnabled = __mmEnabled),
__mmEnabled && (__mmAutoDeclineTeamRequestsEnabled = !1),
__mmHandleTeamJoinRequest());
else if (__mmKey === "autoDeclineTeamRequests")
((__mmAutoDeclineTeamRequestsEnabled = __mmEnabled),
__mmEnabled && (__mmAutoAcceptTeamRequestsEnabled = !1),
__mmHandleTeamJoinRequest());
else if (__mmKey === "antiBoostInsta")
__mmAntiBoostInstaEnabled = __mmEnabled;
else if (__mmKey === "antiInsta")
__mmAntiInstaEnabled = __mmEnabled;
else if (__mmKey === "antiCollision")
((__mmAntiCollisionEnabled = __mmEnabled),
__mmEnabled
? (__mmStartAntiCollision(), __mmUpdateAntiCollision())
: __mmStopAntiCollision());
else if (__mmKey === "antiCollisionPauseCombat")
((__mmAntiCollisionPauseCombatEnabled = __mmEnabled),
__mmUpdateAntiCollision());
else if (__mmKey === "shieldDefense")
((__mmShieldDefenseEnabled = __mmEnabled),
!__mmEnabled && __mmStopShieldDefense("hud disabled"));
else if (__mmKey === "placementDefense")
__mmPlacementDefenseEnabled = __mmEnabled;
else if (__mmKey === "antiRetrapPush")
__mmAntiRetrapPushEnabled = __mmEnabled;
else if (__mmKey === "teammateTrapRescue")
__mmTeammateTrapRescueEnabled = __mmEnabled;
else if (__mmKey === "turretSteal")
__mmTurretStealEnabled = __mmEnabled;
else if (__mmKey === "spikeGearCounter")
((__mmSpikeGearCounterEnabled = __mmEnabled),
!__mmEnabled && __mmResetSpikeGearCounter(!0));
else if (__mmKey === "dashMovement")
__mmDashMovementEnabled = __mmEnabled;
else if (__mmKey === "musketRecharge")
((__mmMusketRechargeEnabled = __mmEnabled),
!__mmEnabled && __mmStopWeaponRecharge(!1));
else if (__mmKey === "autoPurchase")
((__mmAutoPurchaseEnabled = __mmEnabled),
__mmEnabled ? (__mmStartAutoPurchase(), __mmUpdateAutoPurchase()) : __mmStopAutoPurchase());
else if (__mmKey === "matThief")
((__mmMatThiefEnabled = __mmEnabled),
__mmEnabled ? (__mmStartMatThief(), __mmUpdateMatThief()) : __mmStopMatThief());
else if (__mmKey === "multiTargetBreak")
((__mmMultiTargetBreakEnabled = __mmEnabled),
__mmEnabled ? (__mmStartMultiBreak(), __mmUpdateMultiBreakAim()) : __mmStopMultiBreak());
else if (__mmKey === "mobSteal")
((__mmMobStealEnabled = __mmEnabled),
__mmEnabled ? (__mmStartMobSteal(), __mmUpdateMobSteal()) : __mmStopMobSteal());
else if (__mmKey === "assassinAutomation")
((__mmAssassinAutomationEnabled = __mmEnabled),
__mmEnabled
? (__mmStartAssassinAutomation(), __mmUpdateAssassinAutomation())
: __mmStopAssassinAutomation());
else if (__mmKey === "spinningWindmills")
((__mmSpinningWindmillsEnabled = __mmEnabled),
document.documentElement &&
document.documentElement.setAttribute(
"data-kitty-spinning-windmills",
__mmEnabled ? "1" : "0",
),
__mmApplyWindmillRotationState());
else if (__mmKey === "forceFullServers")
((__mmForceFullServersEnabled = __mmEnabled),
(window.__KittyForceFullServers = __mmEnabled),
(() => {
try {
__mmEnabled
? localStorage.setItem("moofoll", "1")
: localStorage.removeItem("moofoll");
} catch {}
})());
else if (__mmKey === "bushMode")
return void __mmSetBushMode(__mmEnabled);
else if (__mmKey === "fpsBoost") {
__mmFpsBoostEnabled = __mmEnabled;
document.documentElement &&
document.documentElement.setAttribute(
"data-kitty-fps-boost",
__mmEnabled ? "1" : "0",
);
__mmObjectSnapshotAt = 0;
}
else if (__mmKey === "smoothVisuals")
__mmSmoothVisualsEnabled = __mmEnabled;
else if (__mmKey === "reloadArcs")
__mmReloadArcsEnabled = __mmEnabled;
else if (__mmKey === "entityDanger")
__mmEntityDangerEnabled = __mmEnabled;
else if (__mmKey === "notificationTracers")
__mmNotificationTracersEnabled = __mmEnabled;
else if (__mmKey === "groundGrid") {
__mmGroundGridEnabled = __mmEnabled;
__mmGroundGridFrameDrawn = !1;
document.documentElement &&
document.documentElement.setAttribute(
"data-kitty-ground-grid",
__mmEnabled ? "1" : "0",
);
}
else if (__mmKey === "esp") __mmEspEnabled = __mmEnabled;
else if (__mmKey === "espLines") __mmEspLinesEnabled = __mmEnabled;
else if (__mmKey === "predictionGhost")
__mmPredictionGhostEnabled = __mmEnabled;
else if (__mmKey === "placementVisuals") {
__mmPlacementVisualsEnabled = __mmEnabled;
if (!__mmEnabled) {
(__mmSmartPreviewSamples.length = 0,
(__mmSmartPlacementPreview = {
samples: [],
ranked: [],
selected: [],
reason: "disabled",
updatedAt: 0,
}));
}
}
else if (__mmKey === "cooldownBars")
__mmCooldownBarsEnabled = __mmEnabled;
else if (__mmKey === "weaponXpBar")
__mmWeaponXpBarEnabled = __mmEnabled;
else if (__mmKey === "combatTelemetry")
((__mmCombatTelemetryEnabled = __mmEnabled),
!__mmEnabled &&
(() => {
for (const __mmSid in __mmCombatDeltaStacks)
delete __mmCombatDeltaStacks[__mmSid];
})());
else if (__mmKey === "telemetryProjectileHits")
__mmTelemetryProjectileHitsEnabled = __mmEnabled;
else if (__mmKey === "telemetrySpikeKnockback")
__mmTelemetrySpikeKnockbackEnabled = __mmEnabled;
else if (__mmKey === "telemetryActualAim")
__mmTelemetryActualAimEnabled = __mmEnabled;
else if (__mmKey === "telemetryBuildingOwners")
__mmTelemetryBuildingOwnersEnabled = __mmEnabled;
else if (__mmKey === "telemetryShameCount")
__mmTelemetryShameCountEnabled = __mmEnabled;
else if (__mmKey === "telemetryDamageHealing") {
__mmTelemetryDamageHealingEnabled = __mmEnabled;
if (!__mmEnabled)
for (const __mmSid in __mmCombatDeltaStacks)
delete __mmCombatDeltaStacks[__mmSid];
}
else if (__mmKey === "chatHistory") {
__mmChatHistoryEnabled = __mmEnabled;
if (!__mmEnabled) {
for (const __mmSid in __mmChatBubbleStacks)
delete __mmChatBubbleStacks[__mmSid];
}
}
else if (__mmKey === "bullHelmet") {
__mmBullHelmetEnabled = __mmEnabled;
if (
!__mmEnabled &&
v &&
(__mmPrimaryClickHat != null || __mmPrimaryClickTail != null)
)
__mmForceRestoreBullForPrimary();
} else if (__mmKey === "tankRightClick")
((__mmTankRightClickEnabled = __mmEnabled),
!__mmEnabled &&
(__mmStopSecondary(), __mmForceRestoreRightClickHat()));
else if (__mmKey === "instaKill") {
((__mmInstaUiEnabled = __mmEnabled),
!__mmEnabled && __mmInsta.cancel("hud-disabled"));
}
else if (__mmKey === "autoInsta") {
((__mmAutoInstaEnabled = __mmEnabled),
!__mmEnabled &&
__mmInsta.automatic &&
__mmInsta.cancel("auto-insta-disabled"));
}
else if (__mmKey === "autoBowUpgradeInsta") {
__mmAutoBowUpgradeInstaEnabled = __mmEnabled;
!__mmEnabled && __mmBowUpgradeInsta.cancel("hud disabled");
}
else if (__mmKey === "reverseInsta")
__mmReverseInstaEnabled = __mmEnabled;
else if (__mmKey === "oneTickInsta")
__mmOneTickInstaEnabled = __mmEnabled;
else if (__mmKey === "appleInsta")
((__mmAppleInstaEnabled = __mmEnabled), __mmRefreshKittyInstaLoop());
else if (__mmKey === "bleedInsta")
((__mmBleedInstaEnabled = __mmEnabled), __mmRefreshKittyInstaLoop());
else if (__mmKey === "knockbackInsta")
((__mmKnockbackInstaEnabled = __mmEnabled), __mmRefreshKittyInstaLoop());
else if (__mmKey === "velTickInsta") {
__mmVelTickInstaEnabled = __mmEnabled;
(!__mmEnabled && __mmStopVelTickInsta("hud disabled"),
__mmRefreshKittyInstaLoop());
}
else if (__mmKey === "polearmAids")
((__mmPolearmAidsEnabled = __mmEnabled), __mmRefreshKittyInstaLoop());
else if (__mmKey === "autoPushInsta") {
__mmAutoPushInstaEnabled = __mmEnabled;
(!__mmEnabled && __mmStopAutoPushSetup("hud disabled"),
__mmRefreshKittyInstaLoop());
}
else if (__mmKey === "boostSpikeKill") {
__mmBoostSpikeEnabled = __mmEnabled;
!__mmEnabled && __mmStopBoostSpike();
}
else if (__mmKey === "autoTrapInsta") {
__mmAutoTrapInstaEnabled = __mmEnabled;
if (__mmEnabled) (__mmStartAutoTrapInsta(), __mmUpdateAutoTrapInsta());
else {
(__mmAutoTrapInstaTimer && clearInterval(__mmAutoTrapInstaTimer),
(__mmAutoTrapInstaTimer = 0));
for (const __mmSid in __mmAutoTrapInstaIncidents)
delete __mmAutoTrapInstaIncidents[__mmSid];
}
}
else if (__mmKey === "autoSpikeInsta")
((__mmAutoSpikeInstaEnabled = __mmEnabled),
__mmEnabled
? (__mmStartAutoSpikeInsta(), __mmUpdateAutoSpikeInsta())
: ((__mmAutoSpikeInstaTimer && clearInterval(__mmAutoSpikeInstaTimer),
(__mmAutoSpikeInstaTimer = 0),
__mmStopSpikeTickStrike("hud disabled"))));
else if (__mmKey === "autoSpikeSpam" || __mmKey === "autoSpikeKill") {
__mmKey === "autoSpikeSpam"
? (__mmAutoSpikeSpamEnabled = __mmEnabled)
: (__mmAutoSpikeKillEnabled = __mmEnabled);
if (__mmAutoSpikeSpamEnabled || __mmAutoSpikeKillEnabled)
(__mmStartAutoSpikeSpam(), __mmUpdateAutoSpikeSpam());
else {
(__mmAutoSpikeSpamTimer && clearInterval(__mmAutoSpikeSpamTimer),
(__mmAutoSpikeSpamTimer = 0),
__mmResetAutoSpikeSpamIntent(),
__mmAutoSpikeSpamResetCandidate(!0));
}
}
else if (__mmKey === "animalTrap") {
__mmThreatTrapEnabled = __mmEnabled;
if (__mmEnabled) (__mmStartThreatTrap(), __mmPlaceThreatTrap());
else {
__mmThreatTrapLastKey = null;
for (const __mmKey in __mmThreatTrapPlacements)
delete __mmThreatTrapPlacements[__mmKey];
!__mmPassiveMobTrapEnabled &&
!__mmBossTeleporterEnabled &&
__mmStopThreatTrapLoop();
}
}
else if (__mmKey === "passiveMobTrap") {
__mmPassiveMobTrapEnabled = __mmEnabled;
if (__mmEnabled) (__mmStartThreatTrap(), __mmPlaceThreatTrap());
else {
__mmThreatTrapLastKey = null;
for (const __mmKey in __mmThreatTrapPlacements)
delete __mmThreatTrapPlacements[__mmKey];
!__mmThreatTrapEnabled &&
!__mmBossTeleporterEnabled &&
__mmStopThreatTrapLoop();
}
}
else if (__mmKey === "bossTeleporter") {
__mmBossTeleporterEnabled = __mmEnabled;
if (__mmEnabled) (__mmStartThreatTrap(), __mmPlaceThreatTrap());
else if (!__mmThreatTrapEnabled && !__mmPassiveMobTrapEnabled)
__mmStopThreatTrapLoop();
}
else if (__mmKey === "smartAutoPlace") {
__mmSmartAutoPlaceEnabled = __mmEnabled;
if (
!__mmEnabled &&
!__mmAutomaticQuadPlacementEnabled() &&
__mmSmartPreplaceTimers.size
) {
for (const __mmTimer of __mmSmartPreplaceTimers) clearTimeout(__mmTimer);
(__mmSmartPreplaceTimers.clear(), __mmSmartPreplaceKeys.clear());
}
__mmRefreshSmartPlacementLoop();
}
else if (__mmKey === "smartPreplace") __mmSmartPreplaceEnabled = __mmEnabled;
else if (__mmKey === "smartMultiPlace")
((__mmSmartMultiPlaceEnabled = __mmEnabled), __mmRefreshSmartPlacementLoop());
else if (__mmKey === "smartQuadTraps")
((__mmSmartQuadTrapsEnabled = __mmEnabled), __mmRefreshSmartPlacementLoop());
else if (__mmKey === "smartQuadSpikes")
((__mmSmartQuadSpikesEnabled = __mmEnabled), __mmRefreshSmartPlacementLoop());
else if (__mmKey === "smartSpikeContact") __mmSmartSpikeContactEnabled = __mmEnabled;
else if (__mmKey === "smartTrapContact") __mmSmartTrapContactEnabled = __mmEnabled;
else if (__mmKey === "smartKnockbackChain") __mmSmartKnockbackChainEnabled = __mmEnabled;
else if (__mmKey === "smartTrapSurround") __mmSmartTrapSurroundEnabled = __mmEnabled;
else if (__mmKey === "smartAngleDenial") __mmSmartAngleDenialEnabled = __mmEnabled;
else if (__mmKey === "smartAutoPushWeight") __mmSmartAutoPushWeightEnabled = __mmEnabled;
else if (__mmKey === "smartAutoReplace")
((__mmSmartAutoReplaceEnabled = __mmEnabled), __mmRefreshSmartPlacementLoop());
else if (__mmKey === "smartSpikeSyncPlace")
((__mmSmartSpikeSyncPlaceEnabled = __mmEnabled), __mmRefreshSmartPlacementLoop());
else if (__mmKey === "smartAntiBoostPlace")
((__mmSmartAntiBoostPlaceEnabled = __mmEnabled), __mmRefreshSmartPlacementLoop());
else if (__mmKey === "smartMovingMills") {
__mmSmartMovingMillsEnabled = __mmEnabled;
if (!__mmEnabled) ((__mmSmartMillX = null), (__mmSmartMillY = null));
__mmRefreshSmartPlacementLoop();
}
else if (__mmKey === "smartInstaUtilityPlace") __mmSmartInstaUtilityPlaceEnabled = __mmEnabled;
else if (__mmKey === "adaptiveSmartness") {
if (__mmAdaptiveSmartnessEnabled !== __mmEnabled) {
__mmAdaptiveSmartnessEnabled = __mmEnabled;
__mmResetAdaptiveSmartness(__mmEnabled ? "sampling" : "manual ceiling");
} else __mmPublishAdaptiveSmartness();
}
else if (__mmKey === "instaSync") {
__mmInstaSyncEnabled = __mmEnabled;
__mmEnabled
? __mmStartInstaSync()
: ((__mmInstaSyncLoopTimer && clearInterval(__mmInstaSyncLoopTimer),
(__mmInstaSyncLoopTimer = 0),
__mmStopInstaSync()));
}
else if (__mmKey === "boostBreak") {
((__mmBoostBreakEnabled = __mmEnabled),
!__mmEnabled && __mmStopBoostBreak());
} else if (__mmKey === "boostChat") {
((__mmBoostChatEnabled = __mmEnabled), !__mmEnabled && __mmStopBoostChat());
} else if (__mmKey === "materialReply") {
__mmMaterialReplyEnabled = __mmEnabled;
} else if (__mmKey === "meowChainInsta") {
__mmMeowChainInstaEnabled = __mmEnabled;
} else if (__mmKey === "instaChat") {
__mmInstaChatEnabled = __mmEnabled;
} else if (__mmKey === "bushChat") {
__mmBushChatEnabled = __mmEnabled;
} else if (__mmKey === "friendAddedChat") {
__mmFriendAddedChatEnabled = __mmEnabled;
} else if (__mmKey === "enemyMarkedChat") {
__mmEnemyMarkedChatEnabled = __mmEnabled;
} else if (__mmKey === "cleanupProgressChat") {
__mmCleanupProgressChatEnabled = __mmEnabled;
} else if (__mmKey === "cleanupCompleteChat") {
__mmCleanupCompleteChatEnabled = __mmEnabled;
} else if (__mmKey === "modReplyChat") {
__mmModReplyChatEnabled = __mmEnabled;
} else if (__mmKey === "enemyTrapChat") {
__mmEnemyTrapChatEnabled = __mmEnabled;
} else if (__mmKey === "friendTrapChat") {
__mmFriendTrapChatEnabled = __mmEnabled;
} else if (__mmKey === "trapAlertChat") {
__mmTrapAlertChatEnabled = __mmEnabled;
} else if (__mmKey === "deathHistoryChat") {
__mmDeathHistoryChatEnabled = __mmEnabled;
} else if (__mmKey === "syncStatusChat") {
__mmSyncStatusChatEnabled = __mmEnabled;
if (!__mmEnabled) {
(__mmSyncStatusChatTimer && clearTimeout(__mmSyncStatusChatTimer),
(__mmSyncStatusChatTimer = 0),
(__mmSyncStatusChatQueue.length = 0));
} else {
__mmSyncStatusChatPhase = /^(?:Syncing|Reconnecting)/i.test(
__mmSyncStatus,
)
? "syncing"
: /^Synced\b/i.test(__mmSyncStatus)
? "synced"
: "off";
}
} else if (__mmKey === "syncMovement") {
__mmSyncMovementEnabled = __mmEnabled;
__mmEnabled
? __mmStartSyncFollowFrames()
: (__mmSyncRestoreCatchupGear(), __mmSyncStopFollowMovement());
} else if (__mmKey === "syncCopyWeapons") {
__mmSyncCopyWeaponsEnabled = __mmEnabled;
} else if (__mmKey === "syncCopyBuilds") {
__mmSyncCopyBuildsEnabled = __mmEnabled;
} else if (__mmKey === "syncCopyGear") {
__mmSyncCopyGearEnabled = __mmEnabled;
} else if (__mmKey === "syncCopyAim") {
__mmSyncCopyAimEnabled = __mmEnabled;
} else if (__mmKey === "syncCopyAttacks") {
__mmSyncCopyAttacksEnabled = __mmEnabled;
if (!__mmEnabled) {
(__mmStopObservedSyncAttack(!0),
__mmSyncDirectAttackActive &&
v &&
v.alive &&
__mmWithSyncReplay(function () {
O.send("F", 0, Ci());
}),
(__mmSyncDirectAttackActive = !1));
}
} else if (__mmKey === "syncCatchupGear") {
__mmSyncCatchupGearEnabled = __mmEnabled;
!__mmEnabled && __mmSyncRestoreCatchupGear();
} else if (__mmKey === "syncPauseInCombat") {
__mmSyncPauseInCombatEnabled = __mmEnabled;
} else if (__mmKey === "syncWasdCombatOnly") {
__mmSyncWasdCombatOnlyEnabled = __mmEnabled;
} else if (__mmKey === "syncTickCombat") {
__mmSyncTickCombatEnabled = __mmEnabled;
!__mmEnabled && __mmCancelScheduledSyncInsta();
} else if (__mmKey === "debugPanel")
__mmDebugPanelEnabled = __mmEnabled;
else if (__mmKey === "killMessageEnabled")
__mmKillMessageEnabled = __mmEnabled;
else return;
__mmPublishHudState();
}
function __mmSetHudValue(__mmKey, __mmValue) {
if (__mmKey === "keybinds") {
(__mmSetRuntimeBindings(__mmValue), __mmPublishHudState());
return;
}
if (__mmKey === "syncRelayUrl" || __mmKey === "syncRoom")
return void __mmSetSyncRelayConfig(__mmKey, __mmValue);
if (
__mmKey === "enemyColor" ||
__mmKey === "allyColor" ||
__mmKey === "friendColor" ||
__mmKey === "ownColor"
) {
const __mmColor = String(__mmValue || "").trim().toLowerCase();
if (!/^#[0-9a-f]{6}$/.test(__mmColor)) return;
if (__mmKey === "enemyColor") __mmEnemyColor = __mmColor;
else if (__mmKey === "allyColor") __mmAllyColor = __mmColor;
else if (__mmKey === "friendColor") __mmFriendColor = __mmColor;
else __mmOwnColor = __mmColor;
return void __mmPublishHudState();
}
if (__mmKey === "killMessage")
return (
(__mmKillMessage = String(__mmValue || "").slice(0, 30)),
void __mmPublishHudState()
);
__mmKey === "soldierRange" ||
__mmKey === "combatRange" ||
__mmKey === "gearHoldTicks" ||
__mmKey === "antiBoostRange" ||
__mmKey === "antiCollisionRange" ||
__mmKey === "reactionMs" ||
__mmKey === "smartDepth" ||
__mmKey === "smartPlaceAccuracy" ||
__mmKey === "smartMaxPlacements" ||
__mmKey === "smartPlaceDelay" ||
__mmKey === "assassinSafeMs" ||
__mmKey === "assassinMinHealth" ||
__mmKey === "assassinDangerRange" ||
__mmKey === "syncFollowGap" ||
__mmKey === "syncStopTolerance" ||
__mmKey === "syncResumeTolerance" ||
__mmKey === "syncPredictionMs" ||
__mmKey === "syncCatchupDistance" ||
__mmKey === "syncCatchupReleaseDistance" ||
__mmKey === "syncMoveRefreshMs"
? __mmSetHudNumber(__mmKey, __mmValue)
: __mmSetHudToggle(__mmKey, __mmValue);
}
function __mmApplyHudSettings(__mmSettings) {
if (!__mmSettings || typeof __mmSettings !== "object") return;
Object.prototype.hasOwnProperty.call(__mmSettings, "friendNames") &&
__mmReplaceFriends(__mmSettings.friendNames);
const __mmKeys = [
"autoHeal",
"soldierAuto",
"movementGear",
"trapEscape",
"automaticStateRepair",
"keybinds",
"autoAcceptTeamRequests",
"autoDeclineTeamRequests",
"antiBoostInsta",
"antiInsta",
"antiCollision",
"antiCollisionPauseCombat",
"shieldDefense",
"placementDefense",
"antiRetrapPush",
"teammateTrapRescue",
"turretSteal",
"spikeGearCounter",
"dashMovement",
"musketRecharge",
"autoPurchase",
"matThief",
"multiTargetBreak",
"mobSteal",
"assassinAutomation",
"spinningWindmills",
"forceFullServers",
"bushMode",
"fpsBoost",
"smoothVisuals",
"reloadArcs",
"entityDanger",
"notificationTracers",
"groundGrid",
"esp",
"espLines",
"predictionGhost",
"placementVisuals",
"cooldownBars",
"weaponXpBar",
"chatHistory",
"combatTelemetry",
"telemetryProjectileHits",
"telemetrySpikeKnockback",
"telemetryActualAim",
"telemetryBuildingOwners",
"telemetryShameCount",
"telemetryDamageHealing",
"enemyColor",
"allyColor",
"friendColor",
"ownColor",
"bullHelmet",
"tankRightClick",
"instaKill",
"autoInsta",
"autoBowUpgradeInsta",
"reverseInsta",
"oneTickInsta",
"appleInsta",
"bleedInsta",
"knockbackInsta",
"velTickInsta",
"polearmAids",
"autoPushInsta",
"boostSpikeKill",
"autoTrapInsta",
"autoSpikeInsta",
"autoSpikeSpam",
"autoSpikeKill",
"animalTrap",
"passiveMobTrap",
"bossTeleporter",
"smartAutoPlace",
"smartPreplace",
"smartMultiPlace",
"smartQuadTraps",
"smartQuadSpikes",
"smartSpikeContact",
"smartTrapContact",
"smartKnockbackChain",
"smartTrapSurround",
"smartAngleDenial",
"smartAutoPushWeight",
"smartAutoReplace",
"smartSpikeSyncPlace",
"smartAntiBoostPlace",
"smartMovingMills",
"smartInstaUtilityPlace",
"adaptiveSmartness",
"instaSync",
"boostBreak",
"boostChat",
"materialReply",
"meowChainInsta",
"instaChat",
"bushChat",
"friendAddedChat",
"enemyMarkedChat",
"cleanupProgressChat",
"cleanupCompleteChat",
"modReplyChat",
"enemyTrapChat",
"friendTrapChat",
"trapAlertChat",
"deathHistoryChat",
"syncStatusChat",
"syncMovement",
"syncCopyWeapons",
"syncCopyBuilds",
"syncCopyGear",
"syncCopyAim",
"syncCopyAttacks",
"syncCatchupGear",
"syncPauseInCombat",
"syncWasdCombatOnly",
"syncTickCombat",
"syncFollowGap",
"syncStopTolerance",
"syncResumeTolerance",
"syncPredictionMs",
"syncCatchupDistance",
"syncCatchupReleaseDistance",
"syncMoveRefreshMs",
"syncRelayUrl",
"syncRoom",
"debugPanel",
"killMessageEnabled",
"killMessage",
"soldierRange",
"combatRange",
"gearHoldTicks",
"antiBoostRange",
"antiCollisionRange",
"reactionMs",
"smartDepth",
"smartPlaceAccuracy",
"smartMaxPlacements",
"smartPlaceDelay",
"assassinSafeMs",
"assassinMinHealth",
"assassinDangerRange",
];
for (let __mmIndex = 0; __mmIndex < __mmKeys.length; __mmIndex++) {
const __mmKey = __mmKeys[__mmIndex];
Object.prototype.hasOwnProperty.call(__mmSettings, __mmKey) &&
__mmSetHudValue(__mmKey, __mmSettings[__mmKey]);
}
// Hydration can arrive synchronously while the injected client is mounting.
// Reconcile every placement worker once at the end so a saved ON toggle
// cannot be displayed without its controller actually running.
(__mmRefreshSmartPlacementLoop(),
__mmRefreshKittyInstaLoop(),
(__mmThreatTrapEnabled ||
__mmPassiveMobTrapEnabled ||
__mmBossTeleporterEnabled) &&
__mmStartThreatTrap(),
(__mmAutoSpikeSpamEnabled || __mmAutoSpikeKillEnabled) &&
__mmStartAutoSpikeSpam());
__mmPublishHudState();
}
function __mmHandleHudCommand(__mmEvent) {
const __mmCommand = __mmEvent.detail || {};
if (__mmCommand.type === "hydrate")
return void __mmApplyHudSettings(__mmCommand.settings);
if (__mmCommand.type === "set")
return void __mmSetHudValue(__mmCommand.key, __mmCommand.value);
if (__mmCommand.type === "friend-add")
return void __mmAddFriend(__mmCommand.name, !0);
if (__mmCommand.type === "friend-remove")
return void __mmRemoveFriend(__mmCommand.name, !0);
__mmPublishHudState();
}
window.addEventListener("MooMooOPHudCommand", __mmHandleHudCommand);
function __mmCombatHatAntiInstaActive() {
return !!(
__mmActionOwner === "antiInsta" ||
Date.now() < __mmAntiInstaUntil
);
}
function __mmCombatHatLockActive() {
return !!(
__mmCombatHatLockHat != null &&
Date.now() < __mmCombatHatLockUntil
);
}
function __mmCombatHatPacketAllowed(__mmHat) {
// Do not veto later equipment packets at the socket boundary. The Bull/Tank
// packet is authoritative only for the action phase in which it is
// sent; higher-priority safety gear and the following combo phase must be
// free to replace it immediately.
return !0;
}
function __mmBestPostCombatHat() {
if (!v || !v.alive) return null;
if (__mmBushModeEnabled && __mmBushGearOwned()) return __mmBushGear;
if (__mmMovementGearEnabled) {
const __mmDesired = __mmDesiredHeldHat();
if (
__mmDesired != null &&
!__mmTemporaryCombatHat(__mmDesired) &&
(__mmDesired === 0 || (v.skins && v.skins[__mmDesired]))
)
return __mmDesired;
}
if (__mmSoldierAutoEnabled && v.skins && v.skins[6]) return 6;
if (
!__mmTemporaryCombatHat(__mmLastNormalHat) &&
(__mmLastNormalHat === 0 || (v.skins && v.skins[__mmLastNormalHat]))
)
return __mmLastNormalHat;
if (
!__mmTemporaryCombatHat(v.skinIndex) &&
(v.skinIndex === 0 || (v.skins && v.skins[v.skinIndex]))
)
return v.skinIndex;
return 0;
}
function __mmScheduleCombatHatFinish(__mmEpoch = __mmCombatHatLockEpoch) {
__mmCombatHatLockTimer && clearTimeout(__mmCombatHatLockTimer);
const __mmDelay = Math.max(
1,
__mmCombatHatLockUntil - Date.now(),
);
__mmCombatHatLockTimer = setTimeout(function () {
__mmCombatHatLockTimer = 0;
__mmFinishCombatHatLock(__mmEpoch);
}, __mmDelay);
}
function __mmFinishCombatHatLock(__mmEpoch = __mmCombatHatLockEpoch) {
if (__mmEpoch !== __mmCombatHatLockEpoch) return;
if (Date.now() < __mmCombatHatLockUntil)
return void __mmScheduleCombatHatFinish(__mmEpoch);
const __mmTailRestore = __mmPrimaryClickTail;
(__mmCombatHatLockTimer && clearTimeout(__mmCombatHatLockTimer),
(__mmCombatHatLockTimer = 0),
(__mmCombatHatLockHat = null),
(__mmCombatHatLockUntil = 0),
(__mmPrimaryGearStage = __mmPrimaryHeld ? "downtime" : null),
(__mmSecondaryGearStage = __mmSecondaryHeld ? "downtime" : null),
(__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
(__mmRightClickHat = null));
// Anti-Insta owns equipment outright. Active Insta stages restore their own
// snapshot after the last phase, so do not insert a stray downtime packet
// between Bull/Tank and the next weapon stage.
if (
__mmCombatHatAntiInstaActive() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmInstaSyncPending ||
__mmInstaSyncFiring
)
return;
const __mmHat = __mmBestPostCombatHat();
if (__mmHat != null) {
__mmCombatHatLockWriting = !0;
try {
__mmEquipHatNow(__mmHat, !0, !0);
} finally {
__mmCombatHatLockWriting = !1;
}
}
const __mmHeldWeapon = __mmHeldAttackWeapon();
__mmHeldWeapon != null
? __mmUpdateHeldTail(__mmHeldWeapon)
: __mmTailRestore != null && __mmEquipTailNow(__mmTailRestore, !0);
}
function __mmCancelCombatHatLock(__mmRestoreBest = !0) {
const __mmBest = v && v.alive ? __mmBestPostCombatHat() : null,
__mmTailRestore = __mmPrimaryClickTail;
(__mmCombatHatLockTimer && clearTimeout(__mmCombatHatLockTimer),
(__mmCombatHatLockTimer = 0),
(__mmCombatHatLockEpoch += 1),
(__mmCombatHatLockHat = null),
(__mmCombatHatLockUntil = 0),
(__mmPrimaryGearStage = null),
(__mmSecondaryGearStage = null),
(__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
(__mmRightClickHat = null),
__mmBest != null &&
!__mmTemporaryCombatHat(__mmBest) &&
(__mmLastNormalHat = __mmBest));
if (!__mmRestoreBest || !v || !v.alive) return;
(__mmBest != null && __mmEquipHatNow(__mmBest, !0),
__mmTailRestore != null && __mmEquipTailNow(__mmTailRestore, !0));
}
function __mmActivateCombatHat(__mmHat, __mmTail = null) {
if (
!v ||
!v.alive ||
__mmCombatHatAntiInstaActive() ||
(__mmHat !== 0 && !(v.skins && v.skins[__mmHat]))
)
return !1;
const __mmNow = Date.now(),
__mmEpoch = ++__mmCombatHatLockEpoch;
(__mmCombatHatLockTimer && clearTimeout(__mmCombatHatLockTimer),
(__mmCombatHatLockTimer = 0),
(__mmCombatHatLockHat = __mmHat),
// Use same-phase equipment: Bull/Tank is sent beside the
// swing and remains the combat selection for one server action tick only.
(__mmCombatHatLockUntil = __mmNow + __mmServerTickMs()),
(__mmCombatHatLockWriting = !0));
try {
__mmEquipGearPair(__mmHat, __mmTail, !0, !0);
} finally {
__mmCombatHatLockWriting = !1;
}
(__mmScheduleCombatHatFinish(__mmEpoch), __mmPublishHudState());
return !0;
}
function __mmTankGearActive() {
return !!(v && v.skinIndex === 40);
}
function __mmMovementGearActive() {
return (
__mmMovementGearPreviousHat != null || __mmMovementGearPreviousTail != null
);
}
function __mmTemporaryCombatHat(__mmHat) {
return (
[7, 40, __mmTurretGear].includes(Number(__mmHat)) ||
(__mmSpikeGearCounterEnabled && Number(__mmHat) === 11)
);
}
function __mmStateRepairGraceMs() {
return Math.max(80, __mmServerTickMs() * 2);
}
function __mmStateRepairAutomationHoldActive() {
return !!(
__mmCleanupAttackHeld ||
__mmWeaponGrindHold ||
(__mmTrapAttackActive && __mmTrapAttackHeld) ||
__mmBoostBreakHeld ||
__mmMatThiefAttackHeld ||
__mmMobStealAttackHeld ||
__mmSpikeTickStrikeHeld ||
__mmInstaSyncWeaponHeld ||
__mmSyncDirectAttackActive ||
__mmSyncObservedAttackHeld ||
__mmBindingActionHeld("primaryAttack") ||
__mmBindingActionHeld("clickBoostInsta") ||
__mmBindingActionHeld("secondaryAttack")
);
}
function __mmStateRepairCombatActive() {
return !!(
__mmCombatHatAntiInstaActive() ||
__mmCombatHatLockActive() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmInstaSyncPending ||
__mmInstaSyncFiring ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmSpikeTickStrikeTimer ||
__mmAntiBoostBlockTimer ||
__mmTeammateRescueReleaseTimer ||
__mmDashMovementReleaseTimer ||
__mmTurretStealRestoreTimer ||
__mmSpikeGearCounterTimer ||
__mmSpikeGearCounterRestoreTimer ||
__mmStateRepairAutomationHoldActive() ||
(__mmPhysicalPrimaryDown && __mmPrimaryHeld) ||
(__mmPhysicalSecondaryDown && __mmSecondaryHeld) ||
(__mmActionOwner !== "idle" &&
__mmActionOwner !== "movementGear" &&
__mmActionOwner !== "soldierGear" &&
__mmActionOwner !== "weaponRecharge" &&
Date.now() - __mmActionSince < Math.max(500, 4 * __mmServerTickMs()))
);
}
function __mmRecordStateRepair(__mmReasons) {
if (!__mmReasons.length) return !1;
((__mmStateRepairLastAt = Date.now()),
(__mmStateRepairLastReason = __mmReasons.join(" + ")),
(__mmStateRepairCount += 1));
__mmPublishHudState();
return !0;
}
function __mmStateRepairTry(__mmCallback) {
try {
__mmCallback();
return !0;
} catch (__mmRepairError) {
return !1;
}
}
function __mmStateRepairReleaseAttack(__mmAngle) {
return __mmStateRepairTry(function () {
O.send("F", 0, Number.isFinite(__mmAngle) ? __mmAngle : null);
});
}
function __mmRepairBorrowedToolStates(__mmReasons) {
const __mmOwner = __mmActionOwner;
if (
(__mmOwner === "matThief" && !__mmMatThiefReleaseTimer) ||
(__mmOwner !== "matThief" &&
(__mmMatThiefAttackHeld ||
__mmMatThiefRestoreTool != null ||
Number.isFinite(__mmMatThiefAimAngle)))
)
(__mmMatThiefAttackHeld &&
__mmStateRepairReleaseAttack(__mmMatThiefAimAngle),
(__mmMatThiefAttackHeld = !1),
__mmStateRepairTry(function () {
__mmFinishMatThief("automatic state repair");
}),
__mmActionOwner === "matThief" &&
__mmActionRelease("matThief", "automatic state repair"),
__mmReasons.push("Mat Thief tool"));
if (
(__mmOwner === "mobSteal" &&
!__mmMobStealStageTimer &&
!__mmMobStealReleaseTimer) ||
(__mmOwner !== "mobSteal" &&
(__mmMobStealAttackHeld ||
__mmMobStealRestoreTool != null ||
Number.isFinite(__mmMobStealAimAngle)))
)
(__mmMobStealAttackHeld &&
__mmStateRepairReleaseAttack(__mmMobStealAimAngle),
(__mmMobStealAttackHeld = !1),
__mmStateRepairTry(function () {
__mmFinishMobSteal("automatic state repair");
}),
__mmActionOwner === "mobSteal" &&
__mmActionRelease("mobSteal", "automatic state repair"),
__mmReasons.push("Mob Steal tool"));
if (
(__mmOwner === "instaSync" &&
!__mmInstaSyncPending &&
!__mmInstaSyncFiring) ||
(__mmOwner !== "instaSync" &&
!__mmInstaSyncPending &&
!__mmInstaSyncFiring &&
(__mmInstaSyncWeaponHeld || __mmInstaSyncRestoreTool != null))
)
(__mmInstaSyncWeaponHeld && __mmStateRepairReleaseAttack(null),
(__mmInstaSyncWeaponHeld = !1),
__mmStateRepairTry(__mmStopInstaSync),
__mmActionOwner === "instaSync" &&
__mmActionRelease("instaSync", "automatic state repair"),
__mmReasons.push("sync tool"));
if (
(__mmOwner === "spikeTickStrike" && !__mmSpikeTickStrikeTimer) ||
(__mmOwner !== "spikeTickStrike" &&
(__mmSpikeTickStrikeHeld || __mmSpikeTickStrikeTool != null))
)
(__mmSpikeTickStrikeHeld &&
__mmStateRepairReleaseAttack(__mmSpikeTickStrikeAimAngle),
(__mmSpikeTickStrikeHeld = !1),
__mmStateRepairTry(function () {
__mmStopSpikeTickStrike("automatic state repair");
}),
__mmActionOwner === "spikeTickStrike" &&
__mmActionRelease("spikeTickStrike", "automatic state repair"),
__mmReasons.push("spike strike tool"));
if (
(__mmOwner === "antiBoostBlock" && !__mmAntiBoostBlockTimer) ||
(__mmOwner !== "antiBoostBlock" &&
__mmAntiBoostBlockTool != null &&
!__mmAntiBoostBlockTimer)
)
(__mmStateRepairTry(function () {
__mmStopAntiBoostBlock("automatic state repair");
}),
__mmActionOwner === "antiBoostBlock" &&
__mmActionRelease("antiBoostBlock", "automatic state repair"),
__mmReasons.push("anti-boost tool"));
if (
(__mmOwner === "teammateRescue" && !__mmTeammateRescueReleaseTimer) ||
(__mmOwner !== "teammateRescue" &&
__mmTeammateRescueRestoreTool != null &&
!__mmTeammateRescueReleaseTimer)
)
(__mmTeammateRescueAngle != null &&
__mmStateRepairReleaseAttack(__mmTeammateRescueAngle),
(__mmTeammateRescueAngle = null),
__mmStateRepairTry(function () {
__mmStopTeammateRescue("automatic state repair");
}),
__mmTeammateRescueRestoreTool != null &&
__mmActionMayRestore("teammateRescue") &&
__mmStateRepairTry(function () {
__mmRestoreTool(__mmTeammateRescueRestoreTool);
}),
(__mmTeammateRescueRestoreTool = null),
__mmActionOwner === "teammateRescue" &&
__mmActionRelease("teammateRescue", "automatic state repair"),
__mmReasons.push("rescue tool"));
if (
(__mmOwner === "dashMovement" && !__mmDashMovementReleaseTimer) ||
(__mmOwner !== "dashMovement" &&
__mmDashMovementRestoreTool != null &&
!__mmDashMovementReleaseTimer)
)
(__mmDashMovementAngle != null &&
__mmStateRepairReleaseAttack(__mmDashMovementAngle),
(__mmDashMovementAngle = null),
__mmStateRepairTry(function () {
__mmStopDashMovement("automatic state repair");
}),
__mmDashMovementRestoreTool != null &&
__mmActionMayRestore("dashMovement") &&
__mmStateRepairTry(function () {
__mmRestoreTool(__mmDashMovementRestoreTool);
}),
(__mmDashMovementRestoreTool = null),
__mmActionOwner === "dashMovement" &&
__mmActionRelease("dashMovement", "automatic state repair"),
__mmReasons.push("dash tool"));
if (
(__mmOwner === "weaponRecharge" &&
__mmWeaponRechargeActiveWeapon == null) ||
(__mmOwner === "idle" &&
__mmWeaponRechargePreviousTool != null &&
__mmWeaponRechargeActiveWeapon == null) ||
(__mmWeaponRechargeHeldLoan &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld)
)
(__mmStateRepairTry(function () {
__mmStopWeaponRecharge(!0);
}),
(__mmWeaponRechargeHeldLoan = null),
__mmActionOwner === "weaponRecharge" &&
__mmActionRelease("weaponRecharge", "automatic state repair"),
__mmReasons.push("reload tool"));
}
function __mmRepairForcedAimState(__mmReasons) {
let __mmCleared = !1;
if (!__mmTrapAttackActive && Number.isFinite(__mmTrapAimAngle))
((__mmTrapAimAngle = null), (__mmCleared = !0));
if (
(!__mmSecondaryShieldActive || !__mmSecondaryHeld) &&
Number.isFinite(__mmSecondaryShieldAngle)
)
((__mmSecondaryShieldActive = !1),
(__mmSecondaryShieldAngle = null),
(__mmSecondaryShieldAimAt = 0),
(__mmCleared = !0));
if (
Number.isFinite(__mmMultiBreakAimAngle) &&
(__mmActionOwner !== "manualAttack" ||
(!__mmPrimaryHeld && !__mmSecondaryHeld))
)
(__mmStopMultiBreakAim(), (__mmCleared = !0));
if (!__mmCleanupActive && Number.isFinite(__mmCleanupAimAngle))
((__mmCleanupAimAngle = null), (__mmCleared = !0));
if (
(!__mmWeaponGrindEnabled ||
(!__mmWeaponGrindHold && __mmActionOwner !== "weaponGrind")) &&
Number.isFinite(__mmWeaponGrindAimAngle)
)
((__mmWeaponGrindAimAngle = null), (__mmCleared = !0));
if (
Date.now() >= __mmAutoSpikeSpamAimUntil &&
Number.isFinite(__mmAutoSpikeSpamAimAngle)
)
((__mmAutoSpikeSpamAimAngle = null), (__mmCleared = !0));
if (__mmCleared) __mmReasons.push("forced aim");
if (
!__mmForcedDirectionStillActive() &&
(__mmCleared ||
(__mmLastForcedDirectionAt &&
Date.now() - __mmLastForcedDirectionAt >= __mmStateRepairGraceMs()))
)
__mmScheduleMouseAimReturn();
}
function __mmUpdateAutomaticStateRepair(__mmForce) {
if (!__mmAutomaticStateRepairEnabled || !v || !v.alive) return !1;
const __mmNow = Date.now(),
__mmReasons = [],
__mmInputSettled =
__mmForce ||
__mmNow - __mmPhysicalInputAt >= __mmStateRepairGraceMs();
if (__mmInputSettled) {
if (
__mmPrimaryHeld &&
!__mmPhysicalPrimaryDown &&
!__mmBindingActionHeld("primaryAttack") &&
!__mmBindingActionHeld("clickBoostInsta") &&
!(__mmCleanupAttackHeld && __mmCleanupMouseButton === 0) &&
!__mmWeaponGrindHold
)
(__mmStateRepairTry(__mmStopPrimaryInput),
(__mmPrimaryHeld = !1),
__mmReasons.push("primary hold"));
if (
__mmSecondaryHeld &&
!__mmPhysicalSecondaryDown &&
!__mmBindingActionHeld("secondaryAttack") &&
!(__mmCleanupAttackHeld && __mmCleanupMouseButton === 2) &&
!__mmWeaponGrindHold
)
(__mmStateRepairTry(__mmFinishSecondaryInput),
(__mmSecondaryHeld = !1),
__mmReasons.push("secondary hold"));
}
if (
__mmInputSettled &&
(__mmPrimaryAttackDown || __mmSecondaryAttackDown) &&
!__mmStateRepairAutomationHoldActive() &&
!(__mmPhysicalPrimaryDown && __mmPrimaryHeld) &&
!(__mmPhysicalSecondaryDown && __mmSecondaryHeld)
) {
(__mmHeldAttackTimer && clearInterval(__mmHeldAttackTimer),
(__mmHeldAttackTimer = 0),
__mmStateRepairReleaseAttack(null),
(__mmPrimaryAttackDown = !1),
(__mmSecondaryAttackDown = !1),
__mmReasons.push("attack release"));
}
if (
__mmInputSettled &&
__mmActionOwner === "manualAttack" &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmStateRepairAutomationHoldActive()
)
(__mmActionRelease("manualAttack", "automatic state repair"),
__mmReasons.push("manual owner"));
__mmRepairBorrowedToolStates(__mmReasons);
__mmRepairForcedAimState(__mmReasons);
if (
__mmCombatHatLockHat != null &&
__mmNow >= __mmCombatHatLockUntil
)
(__mmStateRepairTry(function () {
__mmFinishCombatHatLock(__mmCombatHatLockEpoch);
}),
__mmReasons.push("combat hat timer"));
if (
__mmInputSettled &&
!__mmStateRepairCombatActive() &&
(__mmPrimaryClickHat != null ||
__mmPrimaryClickTail != null ||
__mmRightClickHat != null ||
__mmPrimaryGearStage != null ||
__mmSecondaryGearStage != null)
)
(__mmCancelCombatHatLock(!1), __mmReasons.push("combat gear stage"));
if (
__mmInputSettled &&
!__mmStateRepairCombatActive() &&
(__mmTemporaryCombatHat(__mmPendingHat) ||
(__mmTemporaryCombatHat(v.skinIndex) &&
!(__mmPendingHat != null &&
!__mmTemporaryCombatHat(__mmPendingHat) &&
__mmNow - __mmPendingHatAt <
Math.max(250, 3 * __mmServerTickMs()))))
) {
const __mmHat = __mmInstaSafeRestoreHat(__mmBestPostCombatHat());
const __mmNeedsRequest =
Number(__mmPendingHat) !== Number(__mmHat) ||
__mmNow - __mmPendingHatAt >= __mmServerTickMs();
__mmCanEquipHat(__mmHat) &&
__mmStateRepairTry(function () {
__mmEquipHatNow(__mmHat, !0);
});
__mmNeedsRequest && __mmReasons.push("stray combat hat");
}
return __mmRecordStateRepair(__mmReasons);
}
function __mmRecoverStrayCombatHat() {
if (
!v ||
!v.alive ||
__mmCombatHatLockActive() ||
__mmCombatHatAntiInstaActive() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
(__mmActionOwner !== "idle" &&
__mmActionOwner !== "movementGear" &&
__mmActionOwner !== "soldierGear" &&
__mmActionOwner !== "weaponRecharge") ||
(!__mmTemporaryCombatHat(v.skinIndex) &&
!__mmTemporaryCombatHat(__mmPendingHat))
)
return !1;
const __mmHat = __mmInstaSafeRestoreHat(__mmBestPostCombatHat());
return __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat, !0);
}
function __mmRememberNormalHat() {
v &&
v.alive &&
!__mmTemporaryCombatHat(v.skinIndex) &&
(__mmLastNormalHat = v.skinIndex);
}
function __mmEquipHatNow(
__mmHat,
__mmOverridePending,
__mmCombatHatBypass = !1,
) {
__mmHat = __mmCombatSafeHat(__mmHat);
if (
!v ||
!v.alive ||
__mmHat == null ||
(__mmHat !== 0 && !(v.skins && v.skins[__mmHat])) ||
(!__mmCombatHatBypass && !__mmCombatHatPacketAllowed(__mmHat))
)
return !1;
const __mmHasConflictingPendingEquip = !!(
__mmOverridePending &&
__mmPendingHat != null &&
__mmPendingHat !== __mmHat
);
if (v.skinIndex === __mmHat && !__mmHasConflictingPendingEquip) {
__mmPendingHat === __mmHat &&
((__mmPendingHat = null), (__mmPendingHatAt = 0));
return !0;
}
const __mmNow = Date.now();
if (
__mmPendingHat === __mmHat &&
__mmNow - __mmPendingHatAt < __mmServerTickMs()
)
return !0;
return (
O.send("c", 0, __mmHat, !1),
(__mmPendingHat = __mmHat),
(__mmPendingHatAt = __mmNow),
!__mmTemporaryCombatHat(__mmHat) && (__mmLastNormalHat = __mmHat),
!0
);
}
function __mmEquipTailNow(__mmTail, __mmOverridePending) {
if (
!v ||
!v.alive ||
__mmTail == null ||
(__mmTail !== 0 && !(v.tails && v.tails[__mmTail]))
)
return !1;
const __mmHasConflictingPendingEquip = !!(
__mmOverridePending &&
__mmPendingTail != null &&
__mmPendingTail !== __mmTail
);
if (v.tailIndex === __mmTail && !__mmHasConflictingPendingEquip) {
__mmPendingTail === __mmTail &&
((__mmPendingTail = null), (__mmPendingTailAt = 0));
return !0;
}
const __mmNow = Date.now();
if (
__mmPendingTail === __mmTail &&
__mmNow - __mmPendingTailAt < __mmServerTickMs()
)
return !0;
return (
O.send("c", 0, __mmTail, !0),
(__mmPendingTail = __mmTail),
(__mmPendingTailAt = __mmNow),
!0
);
}
function __mmEquipGearPair(
__mmHat,
__mmTail,
__mmOverridePending,
__mmCombatHatBypass = !1,
) {
if (!v || !v.alive) return !1;
__mmHat = __mmCombatSafeHat(__mmHat);
const __mmHatValid = !!(
__mmHat != null &&
(__mmHat === 0 || (v.skins && v.skins[__mmHat])) &&
(__mmCombatHatBypass || __mmCombatHatPacketAllowed(__mmHat))
),
__mmTailValid = !!(
__mmTail != null &&
(__mmTail === 0 || (v.tails && v.tails[__mmTail]))
),
__mmNow = Date.now(),
__mmTick = __mmServerTickMs(),
// Combat/restore pairs must remain pairs even if one side is already the
// visible value or has an identical request awaiting acknowledgement.
__mmForcePair = !!(
__mmOverridePending &&
__mmHatValid &&
__mmTailValid
),
__mmHatConflict = !!(
__mmOverridePending &&
__mmPendingHat != null &&
__mmPendingHat !== __mmHat
),
__mmTailConflict = !!(
__mmOverridePending &&
__mmPendingTail != null &&
__mmPendingTail !== __mmTail
),
__mmSendHat = !!(
__mmHatValid &&
(__mmForcePair ||
v.skinIndex !== __mmHat ||
__mmHatConflict) &&
(__mmForcePair ||
__mmPendingHat !== __mmHat ||
__mmNow - __mmPendingHatAt >= __mmTick)
),
__mmSendTail = !!(
__mmTailValid &&
(__mmForcePair ||
v.tailIndex !== __mmTail ||
__mmTailConflict) &&
(__mmForcePair ||
__mmPendingTail !== __mmTail ||
__mmNow - __mmPendingTailAt >= __mmTick)
);
// Decide both slots first, then emit both socket packets synchronously with
// the same timestamp. No timer, microtask, acknowledgement, or helper call
// is allowed between the paired packets.
const __mmWasPairing = __mmSyncGearPairDispatch;
__mmSyncGearPairDispatch = !0;
try {
(__mmSendHat &&
(O.send("c", 0, __mmHat, !1),
(__mmPendingHat = __mmHat),
(__mmPendingHatAt = __mmNow),
!__mmTemporaryCombatHat(__mmHat) && (__mmLastNormalHat = __mmHat)),
__mmSendTail &&
(O.send("c", 0, __mmTail, !0),
(__mmPendingTail = __mmTail),
(__mmPendingTailAt = __mmNow)));
} finally {
__mmSyncGearPairDispatch = __mmWasPairing;
}
!__mmWasPairing &&
(__mmHat != null || __mmTail != null) &&
__mmSyncPublishGearPair(__mmHat, __mmTail);
return __mmSendHat || __mmSendTail;
}
function __mmSetProximityTail(__mmTail) {
if (!v || __mmTail == null) return;
(__mmProximityTailPrevious == null &&
(__mmProximityTailPrevious = __mmBushRestoreTail(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 __mmAnimalInWeaponPath(__mmWeapon) {
if (
!v ||
!v.alive ||
__mmWeapon == null ||
Number(__mmWeapon) === 8 ||
!Array.isArray(N)
)
return !1;
const __mmWeaponData = b && b.weapons && b.weapons[__mmWeapon];
if (!__mmWeaponData) return !1;
const __mmAim = Ci(),
__mmProjectile = __mmWeaponData.projectile != null,
__mmBaseRange = Number(__mmWeaponData.range) || 0;
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
const __mmAnimal = N[__mmIndex];
if (
!__mmAnimal ||
__mmAnimal.active === !1 ||
__mmAnimal.alive === !1 ||
!__mmAnimal.visible ||
(Number.isFinite(Number(__mmAnimal.health)) &&
Number(__mmAnimal.health) <= 0)
)
continue;
const __mmDx = Number(__mmAnimal.x) - Number(v.x),
__mmDy = Number(__mmAnimal.y) - Number(v.y),
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmAnimalScale = Number(__mmAnimal.scale) || 35,
__mmReach = __mmProjectile
? Math.max(700, __mmBaseRange + __mmAnimalScale)
: __mmBaseRange +
(Number(v.scale) || 35) +
__mmAnimalScale +
24;
if (!Number.isFinite(__mmDistance) || __mmDistance > __mmReach) continue;
const __mmDirection = Math.atan2(__mmDy, __mmDx),
__mmDifference = Math.abs(
Math.atan2(
Math.sin(__mmDirection - __mmAim),
Math.cos(__mmDirection - __mmAim),
),
),
__mmAimWindow = __mmProjectile
? Math.max(
0.12,
Math.min(
0.55,
Math.asin(
Math.min(0.99, (__mmAnimalScale + 18) / Math.max(1, __mmDistance)),
) + 0.08,
),
)
: Math.max(0.35, Number(y && y.gatherAngle) || 0.35);
if (__mmDifference <= __mmAimWindow) return !0;
}
return !1;
}
function __mmHeldTailRestoreValue() {
if (!v || !v.alive) return null;
return __mmMovementGearPreviousTail != null
? __mmMovementGearPreviousTail
: __mmProximityTailPrevious != null
? __mmProximityTailPrevious
: __mmBushRestoreTail(v.tailIndex);
}
function __mmHeldHatRestoreValue() {
if (!v || !v.alive) return null;
return __mmMovementGearPreviousHat != null
? __mmMovementGearPreviousHat
: __mmSoldierPreviousHat != null
? __mmSoldierPreviousHat
: __mmBaseAutomationHat();
}
function __mmEffectiveTailIndex() {
if (!v || !v.alive) return 0;
return __mmPendingTail != null &&
Date.now() - __mmPendingTailAt <= Math.max(180, __mmServerTickMs() * 2)
? Number(__mmPendingTail)
: Number(v.tailIndex);
}
function __mmDesiredHeldTail(__mmWeapon) {
if (!v || !v.alive || !v.tails) return null;
if (
Number(__mmWeapon) !== 8 &&
__mmAnimalInWeaponPath(__mmWeapon)
)
return 0;
if (!__mmMovementGearEnabled) return null;
const __mmEnemyNearby = __mmEnemyWithinCombatRange(),
__mmMoving = __mmPlayerMoving();
if (__mmEnemyNearby) {
if (__mmMoving && v.tails[__mmShadowWings]) return __mmShadowWings;
if (!__mmMoving && v.tails[__mmBloodWings]) return __mmBloodWings;
if (!__mmMoving || (!__mmHasStick() && __mmEffectiveTailIndex() === 11))
return 0;
return null;
}
if (__mmMoving && v.tails[11]) return 11;
if (!__mmMoving && v.tails[__mmAngelWings]) return __mmAngelWings;
return !__mmMoving && __mmEffectiveTailIndex() === 11 ? 0 : null;
}
function __mmRememberHeldTail(__mmTail) {
if (__mmTail == null || __mmHeldTailPrevious != null) return;
__mmHeldTailPrevious = __mmHeldTailRestoreValue();
}
function __mmUpdateHeldTail(__mmWeapon) {
if (!v || !v.alive) return;
if (__mmPrimaryHeld && __mmPrimaryGearStage === "bull") return;
const __mmTail = __mmDesiredHeldTail(__mmWeapon);
if (__mmTail == null) {
if (__mmHeldTailPrevious == null) return;
const __mmRestoreTail = __mmHeldTailPrevious;
__mmHeldTailPrevious = null;
return void __mmEquipTailNow(__mmRestoreTail, !0);
}
(__mmRememberHeldTail(__mmTail), __mmEquipTailNow(__mmTail, !0));
}
function __mmRestoreHeldTail() {
if (__mmHeldTailPrevious == null) return;
const __mmTail = __mmHeldTailPrevious;
((__mmHeldTailPrevious = null),
v && v.alive && __mmEquipTailNow(__mmTail, !0));
}
function __mmDesiredHeldHat() {
if (!v || !v.alive || !__mmMovementGearEnabled) return null;
__mmInSnowBiome() && __mmBuySnowHat();
if (__mmEnemyWithinCombatRange())
return v.skins && v.skins[6] ? 6 : null;
if (!__mmPlayerMoving())
return v.skins && v.skins[__mmEmpHelmet]
? __mmEmpHelmet
: v.skins && v.skins[6]
? 6
: null;
__mmInWater() && __mmBuyFlipperHat();
const __mmHat = __mmSpeedHat();
return v.skins && v.skins[__mmHat] ? __mmHat : 0;
}
function __mmRememberHeldHat(__mmHat) {
if (
__mmHat == null ||
__mmHeldHatPrevious != null ||
__mmPrimaryClickHat != null ||
__mmRightClickHat != null
)
return;
__mmHeldHatPrevious = __mmHeldHatRestoreValue();
}
function __mmUpdateHeldHat() {
if (!v || !v.alive) return;
if (
(__mmPrimaryHeld && __mmPrimaryGearStage === "bull") ||
(__mmSecondaryHeld && __mmSecondaryGearStage === "tank")
)
return;
const __mmHat = __mmDesiredHeldHat();
if (__mmHat == null) {
if (__mmHeldHatPrevious == null) return;
const __mmRestoreHat = __mmHeldHatPrevious;
__mmHeldHatPrevious = null;
return void __mmEquipHatNow(__mmRestoreHat, !0);
}
(__mmRememberHeldHat(__mmHat), __mmEquipHatNow(__mmHat, !0));
}
function __mmRestoreHeldHat() {
if (__mmHeldHatPrevious == null) return;
const __mmHat = __mmHeldHatPrevious;
((__mmHeldHatPrevious = null),
v && v.alive && __mmEquipHatNow(__mmHat, !0));
}
function __mmUpdateHeldGear(__mmWeapon) {
(__mmUpdateHeldHat(), __mmUpdateHeldTail(__mmWeapon));
}
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();
}
__mmUpdateHeldGear(__mmWeapon);
if (__mmPrimaryHeld && !__mmPrimaryAttackDown) {
(je(__mmWeapon, !0),
__mmSendWeaponAttack(1),
(__mmPrimaryAttackDown = !0));
}
}
function __mmStartHeldAttackPulse() {
__mmPulseHeldAttack();
if (__mmHeldAttackTimer) return;
__mmHeldAttackTimer = setInterval(function () {
__mmHeldAttackWeapon() != null
? __mmPulseHeldAttack()
: __mmStopHeldAttackPulse();
}, (__mmPrimaryHeld && __mmBullPrimaryAvailable()) ||
(__mmSecondaryHeld &&
__mmTankRightClickEnabled &&
v &&
v.skins &&
v.skins[40])
? __mmFastCheckMs()
: __mmServerTickMs());
}
function __mmStopHeldAttackPulse() {
if (__mmPrimaryHeld || __mmSecondaryHeld) return;
(__mmHeldAttackTimer &&
(clearInterval(__mmHeldAttackTimer), (__mmHeldAttackTimer = 0)),
v && v.alive && __mmSendWeaponAttack(0),
(__mmPrimaryAttackDown = !1));
}
function __mmResumeHeldAttack() {
if (
__mmTrapAttackActive &&
__mmTrapAttackHeld &&
__mmTrapAttackHeldWeapon != null
) {
const __mmAngle = Number.isFinite(__mmTrapAimAngle)
? __mmTrapAimAngle
: Ci();
(je(__mmTrapAttackHeldWeapon, !0),
O.send("D", __mmAngle),
O.send("F", 1, __mmAngle));
return;
}
// Food/build/insta actions issue their own F=0. Re-arm the native held
// attack once after restoring the primary instead of restarting a pulse loop.
__mmPrimaryHeld && (__mmPrimaryAttackDown = !1);
__mmSecondaryHeld && (__mmSecondaryAttackDown = !1);
__mmPulseHeldAttack();
}
function __mmCanEat() {
if (!v || !v.alive || v.items[0] == null) return !1;
const __mmFood = b.list[v.items[0]];
if (!__mmFood || !__mmFood.consume || !__mmFood.req) return !1;
for (
let __mmReqIndex = 0;
__mmReqIndex < __mmFood.req.length;
__mmReqIndex += 2
)
if ((v[__mmFood.req[__mmReqIndex]] || 0) < __mmFood.req[__mmReqIndex + 1])
return !1;
return !0;
}
function __mmFoodCharges() {
if (!__mmCanEat()) return 0;
const __mmFood = b.list[v.items[0]];
let __mmCharges = Infinity;
for (
let __mmReqIndex = 0;
__mmReqIndex < __mmFood.req.length;
__mmReqIndex += 2
)
__mmCharges = Math.min(
__mmCharges,
Math.floor(
(v[__mmFood.req[__mmReqIndex]] || 0) / __mmFood.req[__mmReqIndex + 1],
),
);
return Number.isFinite(__mmCharges) ? Math.max(0, __mmCharges) : 0;
}
function __mmUseFood() {
if (!__mmCanEat()) return;
const __mmTool = __mmSelectedTool();
(je(v.items[0]),
O.send("F", 1, Ci()),
O.send("F", 0, Ci()),
__mmRestoreTool(__mmTool),
__mmResumeHeldAttack());
}
function __mmUseFoodBurst(__mmCount) {
const __mmBites = Math.min(Math.max(0, __mmCount | 0), __mmFoodCharges());
if (!__mmBites) return;
const __mmFood = v.items[0],
__mmAngle = Ci(),
__mmTool = __mmSelectedTool();
for (let __mmBite = 0; __mmBite < __mmBites; __mmBite++)
(je(__mmFood), O.send("F", 1, __mmAngle), O.send("F", 0, __mmAngle));
(__mmRestoreTool(__mmTool), __mmResumeHeldAttack());
}
function __mmAtFullHealth() {
return v && v.alive && v.health >= v.maxHealth;
}
function __mmSelectedWeapon() {
return !v || !v.alive
? null
: v.weapons.includes(__mmLastWeapon)
? __mmLastWeapon
: v.weapons.includes(v.weaponIndex)
? v.weaponIndex
: v.weapons[0];
}
function __mmHoldingMcGrabby() {
return !!(
v &&
v.alive &&
Number(v.buildIndex) < 0 &&
Number(__mmSelectedWeapon()) === __mmMcGrabby
);
}
function __mmRestoreWeapon(__mmWeapon) {
v && v.alive && v.weapons.includes(__mmWeapon) && je(__mmWeapon, !0);
}
function __mmSelectedTool() {
if (!v || !v.alive) return null;
const __mmBuild = Number(v.buildIndex);
if (
Number.isInteger(__mmBuild) &&
__mmBuild >= 0 &&
v.items &&
v.items.includes(__mmBuild)
)
return { item: __mmBuild, weapon: !1 };
const __mmWeapon = __mmSelectedWeapon();
return __mmWeapon == null ? null : { item: __mmWeapon, weapon: !0 };
}
function __mmRestoreTool(__mmTool) {
if (!v || !v.alive || !__mmTool) return;
__mmTool.weapon
? __mmRestoreWeapon(__mmTool.item)
: v.items && v.items.includes(__mmTool.item) && je(__mmTool.item);
}
const __mmCleanupRadius = 1000,
__mmCleanupInputKeys = Object.freeze({
87: !0,
65: !0,
83: !0,
68: !0,
70: !0,
86: !0,
82: !0,
72: !0,
90: !0,
});
function __mmCleanupObjectScale(__mmObject) {
if (!__mmObject) return 0;
if (typeof __mmObject.getScale === "function") {
const __mmScale = Number(__mmObject.getScale(0.6, !!__mmObject.isItem));
if (Number.isFinite(__mmScale) && __mmScale > 0) return __mmScale;
}
return Math.max(
1,
Number(__mmObject.blocker) ||
Number(__mmObject.scale) ||
Number(b && b.list && b.list[__mmObject.id] && b.list[__mmObject.id].scale) ||
35,
);
}
function __mmCleanupIsSpike(__mmObject) {
const __mmItem = __mmObject && b && b.list && b.list[__mmObject.id],
__mmName = String((__mmItem && __mmItem.name) || "").toLowerCase();
return __mmName.includes("spikes");
}
function __mmCleanupStructureAllowed(__mmObject) {
const __mmData = __mmObject && b && b.list && b.list[__mmObject.id];
if (
!__mmCleanupActive ||
!__mmObject ||
!__mmObject.active ||
!__mmObject.isItem ||
!__mmData ||
!__mmData.group ||
!__mmData.group.place
)
return !1;
const __mmState = __mmBreakableState(__mmObject),
__mmLiveHealth = Number(__mmObject.health),
__mmHealth = __mmState
? Number(__mmState.health)
: Number.isFinite(__mmLiveHealth)
? __mmLiveHealth
: Number(__mmData.health);
if (!Number.isFinite(__mmHealth) || __mmHealth <= 0.001) return !1;
const __mmDx = Number(__mmObject.x) - __mmCleanupOriginX,
__mmDy = Number(__mmObject.y) - __mmCleanupOriginY;
return (
Number.isFinite(__mmDx) &&
Number.isFinite(__mmDy) &&
__mmDx * __mmDx + __mmDy * __mmDy <=
__mmCleanupRadius * __mmCleanupRadius
);
}
function __mmCleanupSafeDistance(__mmObject) {
return (
(Number(v && v.scale) || 35) +
__mmCleanupObjectScale(__mmObject) +
(__mmCleanupIsSpike(__mmObject) ? 18 : 8)
);
}
function __mmCleanupWeaponPlan(__mmObject) {
if (!v || !v.alive || !Array.isArray(v.weapons)) return null;
const __mmSafe = __mmCleanupSafeDistance(__mmObject),
__mmScale = __mmCleanupObjectScale(__mmObject);
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
const __mmWeapon = v.weapons[__mmIndex],
__mmData = b && b.weapons && b.weapons[__mmWeapon];
if (!__mmData || __mmData.projectile != null) continue;
const __mmDamage = __mmWeaponStructureDamage(v, __mmWeapon, __mmObject),
__mmRange = Number(__mmData.range) || 0,
__mmReach = __mmRange + __mmScale - 5,
__mmSpeed = Math.max(50, Number(__mmData.speed) || 400);
// Cleanup needs a real standing attack band. A two-pixel band caused the
// movement controller to cross it every update and reverse repeatedly.
if (__mmDamage <= 0 || __mmReach < __mmSafe + 10) continue;
const __mmScore = __mmDamage / __mmSpeed + __mmRange / 1e6;
if (
!__mmBest ||
__mmScore > __mmBest.score ||
(__mmScore === __mmBest.score && __mmReach > __mmBest.reach)
)
__mmBest = {
weapon: __mmWeapon,
damage: __mmDamage,
speed: __mmSpeed,
reach: __mmReach,
safe: __mmSafe,
score: __mmScore,
};
}
return __mmBest;
}
function __mmCleanupHasRemaining() {
const __mmObjects = __mmActiveObjectSnapshot().all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++)
if (__mmCleanupStructureAllowed(__mmObjects[__mmIndex])) return !0;
return !1;
}
function __mmCleanupNearestTarget(__mmNow) {
if (!v || !v.alive) return null;
let __mmBest = null,
__mmBestDistance = Infinity;
const __mmObjects = __mmActiveObjectSnapshot().all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (!__mmCleanupStructureAllowed(__mmObject)) continue;
const __mmReservedUntil = Number(__mmCleanupReservations.get(__mmObject));
if (Number.isFinite(__mmReservedUntil) && __mmReservedUntil > __mmNow)
continue;
const __mmPlan = __mmCleanupWeaponPlan(__mmObject);
if (!__mmPlan) {
__mmCleanupReservations.set(__mmObject, __mmNow + 750);
continue;
}
const __mmDistance = Math.hypot(
Number(__mmObject.x) - Number(v.x),
Number(__mmObject.y) - Number(v.y),
);
if (Number.isFinite(__mmDistance) && __mmDistance < __mmBestDistance)
((__mmBestDistance = __mmDistance),
(__mmBest = { object: __mmObject, plan: __mmPlan }));
}
return __mmBest;
}
function __mmCleanupRestoreApproachGear() {
if (__mmCleanupAttackHeld || __mmSecondaryHeld) return;
__mmClearSecondaryGearTimer();
if (__mmRightClickHat != null) {
__mmForceRestoreRightClickHat();
return;
}
// A Tank request can still be awaiting the next game-state update after the
// synthetic hold has ended. Override that pending request before walking so
// cleanup never approaches its next target at Tank speed.
if (__mmPendingHat === 40 || (v && v.skinIndex === 40)) {
const __mmHat =
__mmLastNormalHat === 0 ||
(v && v.skins && v.skins[__mmLastNormalHat])
? __mmLastNormalHat
: v && v.skins && v.skins[6]
? 6
: 0;
__mmEquipHatNow(__mmHat, !0);
}
}
function __mmCleanupSetMovement(__mmAngle) {
if (!v || !v.alive) {
((__mmCleanupMoveAngle = null), (Kt = null));
return;
}
if (!Number.isFinite(__mmAngle)) {
if (__mmCleanupMoveAngle == null) return;
((__mmCleanupMoveAngle = null), (Kt = null), O.send("9", null));
return;
}
__mmCleanupRestoreApproachGear();
const __mmFixed =
typeof M.fixTo === "function" ? M.fixTo(__mmAngle, 2) : __mmAngle,
__mmDifference =
__mmCleanupMoveAngle == null
? Infinity
: Math.abs(
Math.atan2(
Math.sin(__mmFixed - __mmCleanupMoveAngle),
Math.cos(__mmFixed - __mmCleanupMoveAngle),
),
);
if (__mmDifference < 0.04) return;
((__mmCleanupMoveAngle = __mmFixed),
(Kt = __mmFixed),
O.send("9", __mmFixed));
}
function __mmCleanupReleaseAttack() {
const __mmWasHeld = __mmCleanupAttackHeld,
__mmMouseButton = __mmCleanupMouseButton;
if (__mmWasHeld)
O.send(
"F",
0,
Number.isFinite(__mmCleanupAimAngle) ? __mmCleanupAimAngle : null,
);
U = 0;
if (__mmMouseButton === 0) {
((__mmPrimaryHeld = !1),
(__mmPrimaryAttackDown = !1),
__mmRestoreBullForPrimary(),
__mmRestoreHeldHat(),
__mmRestoreHeldTail());
} else if (__mmMouseButton === 2) {
((__mmSecondaryHeld = !1),
(__mmSecondaryAttackDown = !1),
__mmRestoreHeldHat(),
__mmRestoreHeldTail(),
__mmRestoreRightClickHat());
}
((__mmCleanupAttackHeld = !1),
(__mmCleanupMouseButton = null),
(__mmCleanupAimAngle = null),
(__mmCleanupWeapon = null));
}
function __mmCleanupMouseButtonForWeapon(__mmWeapon) {
// Cleanup always behaves as a held right-click, even when its best breaker
// is the primary weapon. This keeps cleanup on the Tank/Soldier gear path
// and never borrows the normal left-click/Bull state.
return 2;
}
function __mmCleanupUpdateSecondaryGear(__mmWeapon, __mmNow) {
if (
!__mmTankRightClickEnabled ||
!v ||
!v.alive ||
!v.skins ||
!v.skins[40]
)
return;
__mmRightClickHat == null &&
(__mmRightClickHat = __mmInstaSafeRestoreHat(
__mmBushRestoreHat(v.skinIndex),
));
__mmManualWeaponArming(__mmWeapon, __mmSecondaryManualReadyAt, __mmNow) &&
__mmEquipTankForSecondary(__mmWeapon, __mmNow);
}
function __mmCleanupUpdateMouseGear(__mmPlan, __mmNow) {
if (!__mmPlan || !__mmCleanupAttackHeld) return;
if (__mmCleanupMouseButton === 0) {
__mmBullPrimaryAvailable() && __mmPulsePrimaryBullWeapon();
return;
}
__mmCleanupMouseButton === 2 &&
__mmCleanupUpdateSecondaryGear(__mmPlan.weapon, __mmNow);
}
function __mmCleanupBeginMouseHold(__mmPlan, __mmAngle, __mmNow) {
const __mmMouseButton = __mmCleanupMouseButtonForWeapon(__mmPlan.weapon);
(__mmCleanupMouseButton = __mmMouseButton,
(__mmCleanupWeapon = __mmPlan.weapon),
(__mmCleanupAimAngle = __mmAngle),
(U = 1),
O.send("D", __mmAngle),
je(__mmPlan.weapon, !0));
if (__mmMouseButton === 0) {
((__mmPrimaryHeld = !0),
(__mmPrimaryAttackDown = !1),
Number(__mmPrimaryManualWeapon) !== Number(__mmPlan.weapon) &&
((__mmPrimaryManualWeapon = Number(__mmPlan.weapon)),
(__mmPrimaryManualReadyAt = 0)),
(__mmCleanupAttackHeld = !0),
__mmPulseHeldAttack());
return;
}
((__mmSecondaryHeld = !0),
(__mmSecondaryAttackDown = !0),
Number(__mmSecondaryManualWeapon) !== Number(__mmPlan.weapon) &&
((__mmSecondaryManualWeapon = Number(__mmPlan.weapon)),
(__mmSecondaryManualReadyAt = 0)),
(__mmCleanupAttackHeld = !0),
__mmCleanupUpdateSecondaryGear(__mmPlan.weapon, __mmNow),
O.send("F", 1, __mmAngle));
}
function __mmCleanupSteeringAngle(__mmDesired, __mmTarget) {
if (!v || !v.alive) return __mmDesired;
const __mmOffsets = [0, 0.24, -0.24, 0.48, -0.48, 0.78, -0.78, 1.08, -1.08, 1.57, -1.57],
__mmPlayerScale = Number(v.scale) || 35,
__mmStep = 90,
__mmObjects = __mmActiveObjectSnapshot().all;
let __mmBestAngle = __mmDesired,
__mmBestScore = Infinity;
for (let __mmOffsetIndex = 0; __mmOffsetIndex < __mmOffsets.length; __mmOffsetIndex++) {
const __mmAngle = __mmDesired + __mmOffsets[__mmOffsetIndex],
__mmEndX = Number(v.x) + Math.cos(__mmAngle) * __mmStep,
__mmEndY = Number(v.y) + Math.sin(__mmAngle) * __mmStep;
let __mmScore = Math.abs(__mmOffsets[__mmOffsetIndex]) * 15;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (
!__mmObject ||
__mmObject === __mmTarget ||
!__mmObject.active
)
continue;
const __mmClearance =
__mmPlayerScale +
__mmCleanupObjectScale(__mmObject) +
(__mmCleanupIsSpike(__mmObject) ? 20 : 6),
__mmDistanceSquared = __mmSegmentDistanceSquared(
Number(v.x),
Number(v.y),
__mmEndX,
__mmEndY,
Number(__mmObject.x),
Number(__mmObject.y),
);
if (__mmDistanceSquared < __mmClearance * __mmClearance) {
const __mmDistance = Math.sqrt(Math.max(0, __mmDistanceSquared));
__mmScore +=
1e4 + (__mmClearance - __mmDistance) *
(__mmCleanupIsSpike(__mmObject) ? 100 : 25);
}
}
if (__mmScore < __mmBestScore)
((__mmBestScore = __mmScore), (__mmBestAngle = __mmAngle));
}
return __mmBestAngle;
}
function __mmCleanupVelocityToward(__mmObject) {
if (!v || !__mmObject) return { closing: 0, speed: 0, x: 0, y: 0 };
let __mmVelocity = __mmPassiveSpikeVelocity(),
__mmVelocityX = Number(__mmVelocity && __mmVelocity.x) || 0,
__mmVelocityY = Number(__mmVelocity && __mmVelocity.y) || 0;
const __mmServerElapsed = Number(v.t2) - Number(v.t1),
__mmServerVelocityX =
(Number(v.x2) - Number(v.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(v.y2) - Number(v.y1)) / __mmServerElapsed,
__mmTrackedSpeed = Math.hypot(__mmVelocityX, __mmVelocityY),
__mmServerSpeed = Math.hypot(__mmServerVelocityX, __mmServerVelocityY);
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500 &&
__mmServerSpeed > __mmTrackedSpeed
)
((__mmVelocityX = __mmServerVelocityX),
(__mmVelocityY = __mmServerVelocityY));
const __mmDx = Number(__mmObject.x) - Number(v.x),
__mmDy = Number(__mmObject.y) - Number(v.y),
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmClosing = __mmDistance > 0
? (__mmVelocityX * __mmDx + __mmVelocityY * __mmDy) / __mmDistance
: 0;
return {
closing: Number.isFinite(__mmClosing) ? __mmClosing : 0,
speed: Math.hypot(__mmVelocityX, __mmVelocityY),
x: __mmVelocityX,
y: __mmVelocityY,
};
}
function __mmCleanupProjectedDistance(__mmObject, __mmMotion) {
if (!v || !__mmObject || !__mmMotion) return Infinity;
const __mmPing = Number(window.pingTime),
__mmLeadMs =
__mmServerTickMs() +
(Number.isFinite(__mmPing) ? Math.min(100, Math.max(0, __mmPing / 2)) : 0),
__mmPredictedX = Number(v.x) + __mmMotion.x * __mmLeadMs,
__mmPredictedY = Number(v.y) + __mmMotion.y * __mmLeadMs;
return Math.hypot(
Number(__mmObject.x) - __mmPredictedX,
Number(__mmObject.y) - __mmPredictedY,
);
}
function __mmCleanupAttackTarget(
__mmEntry,
__mmAngle,
__mmNow,
__mmBrakeAngle = null,
) {
const __mmObject = __mmEntry.object,
__mmPlan = __mmEntry.plan,
__mmState = __mmBreakableState(__mmObject),
__mmData = b && b.list && b.list[__mmObject.id],
__mmLiveHealth = Number(__mmObject.health),
__mmHealth = __mmState
? Number(__mmState.health)
: Number.isFinite(__mmLiveHealth)
? __mmLiveHealth
: Number(__mmData && __mmData.health) || 1;
const __mmMultiBreak = __mmMultiBreakAimPlan(
__mmPlan.weapon,
__mmAngle,
__mmObject,
);
__mmMultiBreak && (__mmAngle = __mmMultiBreak.angle);
__mmCleanupSetMovement(__mmBrakeAngle);
__mmCleanupAimAngle = __mmAngle;
if (
__mmCleanupWeapon !== __mmPlan.weapon ||
__mmCleanupMouseButton !== __mmCleanupMouseButtonForWeapon(__mmPlan.weapon)
)
__mmCleanupReleaseAttack();
if (!__mmCleanupAttackHeld)
__mmCleanupBeginMouseHold(__mmPlan, __mmAngle, __mmNow);
else
(O.send("D", __mmAngle), __mmCleanupUpdateMouseGear(__mmPlan, __mmNow));
if (
__mmCleanupTargetHealth == null ||
__mmHealth < __mmCleanupTargetHealth - 0.001
)
((__mmCleanupTargetHealth = __mmHealth),
(__mmCleanupProgressAt = __mmNow));
const __mmStallMs = Math.max(
2200,
__mmPlan.speed *
(Math.max(1, Math.ceil(__mmHealth / Math.max(1, __mmPlan.damage))) + 2) +
__mmServerTickMs() * 2,
);
if (__mmNow - __mmCleanupProgressAt > __mmStallMs) {
(__mmCleanupReleaseAttack(),
__mmCleanupReservations.set(__mmObject, __mmNow + 900),
(__mmCleanupTarget = null),
(__mmCleanupApproachStopped = !1),
(__mmCleanupTargetHealth = null));
}
}
function __mmUpdateCleanup() {
if (!__mmCleanupActive) return;
if (document.hidden || !v || !v.alive)
return void __mmStopCleanup("runtime unavailable", !1);
if (__mmActionOwner !== "cleanup")
return void __mmStopCleanup("action ownership lost", !1);
const __mmNow = Date.now();
let __mmEntry = __mmCleanupTarget;
if (!__mmEntry || !__mmCleanupStructureAllowed(__mmEntry.object)) {
(__mmCleanupReleaseAttack(),
(__mmCleanupTarget = null),
(__mmCleanupApproachStopped = !1),
(__mmCleanupTargetHealth = null),
(__mmEntry = __mmCleanupNearestTarget(__mmNow)));
if (__mmEntry) {
((__mmCleanupTarget = __mmEntry),
(__mmCleanupApproachStopped = !1),
(__mmCleanupTargetHealth = null),
(__mmCleanupProgressAt = __mmNow),
(__mmCleanupEmptySince = 0));
}
}
if (!__mmEntry) {
((__mmCleanupApproachStopped = !1),
__mmCleanupSetMovement(null),
__mmCleanupReleaseAttack());
if (__mmCleanupHasRemaining()) {
__mmCleanupEmptySince = 0;
return;
}
__mmCleanupEmptySince || (__mmCleanupEmptySince = __mmNow);
if (__mmNow - __mmCleanupEmptySince >= Math.max(650, Number(y && y.chatCooldown) + 100 || 650))
__mmStopCleanup("radius complete", !0);
return;
}
if (
__mmCleanupAttackHeld &&
((__mmCleanupMouseButton === 0 && !__mmPrimaryHeld) ||
(__mmCleanupMouseButton === 2 && !__mmSecondaryHeld))
)
__mmCleanupReleaseAttack();
const __mmObject = __mmEntry.object,
__mmDx = Number(__mmObject.x) - Number(v.x),
__mmDy = Number(__mmObject.y) - Number(v.y),
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmAngle = Math.atan2(__mmDy, __mmDx),
__mmSafe = __mmEntry.plan.safe,
__mmReach = __mmEntry.plan.reach,
__mmMotion = __mmCleanupVelocityToward(__mmObject),
__mmProjectedDistance = __mmCleanupProjectedDistance(
__mmObject,
__mmMotion,
),
__mmEdgeDistance = __mmSafe + 3,
__mmStopDistance = Math.min(__mmReach - 5, __mmEdgeDistance + 5),
__mmResumeDistance = Math.min(__mmReach - 2, __mmStopDistance + 18),
__mmNeedsBrake =
__mmMotion.closing > 0.015 &&
__mmProjectedDistance < __mmEdgeDistance;
if (!Number.isFinite(__mmDistance)) {
((__mmCleanupTarget = null), (__mmCleanupApproachStopped = !1));
return;
}
// Once the hold begins, target validity—not interpolation around the
// collision edge—owns attack-up. Even if residual movement carries the
// player slightly inside the edge, keep swinging and brake outward without
// breaking the continuous hit cycle.
if (__mmCleanupAttackHeld && __mmDistance <= __mmReach)
return void __mmCleanupAttackTarget(
__mmEntry,
__mmAngle,
__mmNow,
__mmNeedsBrake
? __mmCleanupSteeringAngle(__mmAngle + Math.PI, __mmObject)
: null,
);
if (__mmNeedsBrake) {
__mmCleanupApproachStopped = !0;
if (__mmDistance <= __mmReach)
return void __mmCleanupAttackTarget(
__mmEntry,
__mmAngle,
__mmNow,
__mmCleanupSteeringAngle(__mmAngle + Math.PI, __mmObject),
);
__mmCleanupReleaseAttack();
__mmCleanupSetMovement(
__mmCleanupSteeringAngle(__mmAngle + Math.PI, __mmObject),
);
return;
}
if (
__mmProjectedDistance <= __mmStopDistance ||
(__mmCleanupApproachStopped && __mmDistance <= __mmResumeDistance)
) {
(__mmCleanupApproachStopped = !0), __mmCleanupSetMovement(null);
if (__mmDistance <= __mmReach)
return void __mmCleanupAttackTarget(__mmEntry, __mmAngle, __mmNow);
return;
}
__mmCleanupApproachStopped = !1;
__mmCleanupReleaseAttack();
__mmCleanupSetMovement(__mmCleanupSteeringAngle(__mmAngle, __mmObject));
}
function __mmCleanupProgressChat() {
if (!__mmCleanupActive || !__mmCleanupProgressChatEnabled) return;
// Non-breaking spaces survive chat normalization and keep every animation
// frame exactly as wide as the three-dot version.
const __mmLines = [
"Cleaning.\u00a0\u00a0",
"Cleaning..\u00a0",
"Cleaning...",
];
(__mmSendChat(__mmLines[__mmCleanupChatStep % __mmLines.length]),
(__mmCleanupChatStep += 1));
}
function __mmStartCleanup() {
if (__mmCleanupActive || document.hidden || !v || !v.alive) return !1;
(__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmActionOwner === "matThief" && __mmFinishMatThief("cleanup started"),
__mmActionOwner === "mobSteal" && __mmFinishMobSteal("cleanup started"));
if (!__mmActionClaim("cleanup", "clearing 1000px radius")) return !1;
(__mmRestoreMovementGear(),
(__mmCleanupActive = !0),
(__mmCleanupOriginX = Number(v.x) || 0),
(__mmCleanupOriginY = Number(v.y) || 0),
(__mmCleanupTarget = null),
(__mmCleanupSavedTool = __mmSelectedTool()),
(__mmCleanupWeapon = null),
(__mmCleanupAttackHeld = !1),
(__mmCleanupMouseButton = null),
(__mmCleanupAimAngle = null),
(__mmCleanupMoveAngle = null),
(__mmCleanupApproachStopped = !1),
(__mmCleanupTargetHealth = null),
(__mmCleanupProgressAt = Date.now()),
(__mmCleanupEmptySince = 0),
(__mmCleanupChatStep = 0),
__mmCleanupProgressChat(),
(__mmCleanupProgressTimer = setInterval(
__mmCleanupProgressChat,
Math.max(750, (Number(y && y.chatCooldown) || 500) + 150),
)),
__mmEnsureOperationPipeline(),
__mmUpdateCleanup());
return !0;
}
function __mmStopCleanup(__mmReason, __mmCompleted) {
if (!__mmCleanupActive && __mmActionOwner !== "cleanup") return;
const __mmTool = __mmCleanupSavedTool,
__mmCanRestore = __mmActionMayRestore("cleanup");
((__mmCleanupActive = !1),
__mmCleanupTimer && clearInterval(__mmCleanupTimer),
(__mmCleanupTimer = 0),
__mmCleanupProgressTimer && clearInterval(__mmCleanupProgressTimer),
(__mmCleanupProgressTimer = 0),
__mmCleanupSetMovement(null),
__mmCleanupReleaseAttack(),
(__mmCleanupTarget = null),
(__mmCleanupSavedTool = null),
(__mmCleanupWeapon = null),
(__mmCleanupAimAngle = null),
(__mmCleanupApproachStopped = !1),
(__mmCleanupTargetHealth = null),
(__mmCleanupEmptySince = 0),
__mmCanRestore && __mmRestoreTool(__mmTool),
__mmActionRelease("cleanup", __mmReason || "stopped"),
__mmScheduleMouseAimReturn(),
__mmCompleted &&
__mmCleanupCompleteChatEnabled &&
__mmSendChat("Nice and tidy!"));
}
function __mmToggleCleanup() {
return __mmCleanupActive
? (__mmStopCleanup("C toggled off", !1), !1)
: __mmStartCleanup();
}
function __mmCleanupInputKey(__mmKey) {
if ([87, 65, 83, 68].includes(Number(__mmKey))) {
__mmVelTickManualUntil = Date.now() + 500;
__mmAutoPushManualUntil = Date.now() + 500;
__mmStopVelTickInsta("manual movement");
__mmStopAutoPushSetup("manual movement");
}
__mmCleanupActive &&
__mmCleanupInputKeys[Number(__mmKey)] &&
__mmStopCleanup("manual key", !1);
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (__mmEvent.isTrusted) {
__mmVelTickManualUntil = Date.now() + 500;
__mmAutoPushManualUntil = Date.now() + 500;
__mmStopVelTickInsta("manual click");
__mmStopAutoPushSetup("manual click");
}
__mmCleanupActive &&
__mmEvent.isTrusted &&
__mmStopCleanup("manual click", !1);
},
!0,
);
function __mmWeaponGrindResetPlacements() {
((__mmWeaponGrindPlaced.turret = 0),
(__mmWeaponGrindPlaced.teleporter = 0),
(__mmWeaponGrindSlots.turret.length = 0),
(__mmWeaponGrindSlots.teleporter.length = 0),
(__mmWeaponGrindReservations.length = 0),
(__mmWeaponGrindTargetIndex = 0),
(__mmWeaponGrindNextAimAt = 0),
(__mmWeaponGrindLastPlaceAt = 0));
}
function __mmWeaponGrindItem(__mmKind) {
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 &&
String(__mmData.name || "").trim().toLowerCase() === __mmKind
)
return __mmItem;
}
return null;
}
function __mmWeaponGrindCleanReservations(__mmNow) {
for (
let __mmIndex = __mmWeaponGrindReservations.length - 1;
__mmIndex >= 0;
__mmIndex--
)
__mmWeaponGrindReservations[__mmIndex].expiresAt <= __mmNow &&
__mmWeaponGrindReservations.splice(__mmIndex, 1);
}
function __mmWeaponGrindObjectOwned(__mmObject) {
if (!v || !__mmObject || !__mmObject.owner) return !1;
return !!(
__mmObject.owner === v ||
(__mmObject.owner.sid != null &&
String(__mmObject.owner.sid) === String(v.sid))
);
}
function __mmWeaponGrindObjectMatches(
__mmObject,
__mmSlot,
__mmKind,
) {
if (
!__mmObject ||
!__mmObject.active ||
!__mmObject.isItem ||
!__mmWeaponGrindObjectOwned(__mmObject)
)
return !1;
const __mmData = b && b.list && b.list[__mmObject.id];
if (
!__mmData ||
String(__mmData.name || "").trim().toLowerCase() !== __mmKind
)
return !1;
const __mmTolerance = Math.max(14, Number(__mmSlot.scale) * 0.35);
return (
(Number(__mmObject.x) - Number(__mmSlot.x)) ** 2 +
(Number(__mmObject.y) - Number(__mmSlot.y)) ** 2 <=
__mmTolerance * __mmTolerance
);
}
function __mmWeaponGrindRefreshSlots(__mmNow) {
const __mmClaimed = new Set(),
__mmKinds = ["turret", "teleporter"],
__mmConfirmTimeout = Math.max(1400, __mmServerTickMs() * 5),
__mmObjects = __mmActiveObjectSnapshot().all;
for (let __mmKindIndex = 0; __mmKindIndex < __mmKinds.length; __mmKindIndex++) {
const __mmKind = __mmKinds[__mmKindIndex],
__mmSlots = __mmWeaponGrindSlots[__mmKind];
for (let __mmSlotIndex = __mmSlots.length - 1; __mmSlotIndex >= 0; __mmSlotIndex--) {
const __mmSlot = __mmSlots[__mmSlotIndex];
if (
__mmSlot.object &&
!__mmClaimed.has(__mmSlot.object) &&
__mmWeaponGrindObjectMatches(__mmSlot.object, __mmSlot, __mmKind)
) {
(__mmClaimed.add(__mmSlot.object), (__mmSlot.confirmed = !0));
continue;
}
__mmSlot.object = null;
for (let __mmObjectIndex = 0; __mmObjectIndex < __mmObjects.length; __mmObjectIndex++) {
const __mmObject = __mmObjects[__mmObjectIndex];
if (
__mmClaimed.has(__mmObject) ||
!__mmWeaponGrindObjectMatches(__mmObject, __mmSlot, __mmKind)
)
continue;
((__mmSlot.object = __mmObject),
(__mmSlot.confirmed = !0),
__mmClaimed.add(__mmObject));
break;
}
if (
!__mmSlot.object &&
(__mmSlot.confirmed || __mmNow - __mmSlot.sentAt > __mmConfirmTimeout)
) {
for (
let __mmReservationIndex = __mmWeaponGrindReservations.length - 1;
__mmReservationIndex >= 0;
__mmReservationIndex--
)
__mmWeaponGrindReservations[__mmReservationIndex].slot === __mmSlot &&
__mmWeaponGrindReservations.splice(__mmReservationIndex, 1);
__mmSlots.splice(__mmSlotIndex, 1);
}
}
__mmWeaponGrindPlaced[__mmKind] = __mmSlots.length;
}
}
function __mmWeaponGrindCapacity(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
if (
__mmItem == null ||
!__mmData ||
!__mmData.group ||
!__mmCanUseBuildItem(__mmItem)
)
return 0;
const __mmLimit = __mmBuildGroupLimit(__mmData),
__mmPlaced = Number(v.itemCounts && v.itemCounts[__mmData.group.id]) || 0,
__mmReserved = __mmWeaponGrindReservations.reduce(function (
__mmCount,
__mmEntry,
) {
return __mmCount +
(__mmEntry.groupId === __mmData.group.id &&
__mmPlaced <= __mmEntry.placedAtSend
? 1
: 0);
}, 0),
__mmSlots = __mmLimit
? Math.max(0, __mmLimit - __mmPlaced - __mmReserved)
: __mmMaxBuildCount(__mmItem);
return Math.max(0, Math.min(__mmMaxBuildCount(__mmItem), __mmSlots));
}
function __mmWeaponGrindPositionClear(__mmX, __mmY, __mmScale) {
if (
!v ||
__mmX - __mmScale < 0 ||
__mmY - __mmScale < 0 ||
__mmX + __mmScale > y.mapScale ||
__mmY + __mmScale > y.mapScale ||
(__mmY >= y.mapScale / 2 - y.riverWidth / 2 &&
__mmY <= y.mapScale / 2 + y.riverWidth / 2)
)
return !1;
const __mmObjects = __mmActiveObjectSnapshot().all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (!__mmObject || !__mmObject.active) continue;
const __mmMinimum =
__mmScale + __mmCleanupObjectScale(__mmObject) + 3;
if (
(Number(__mmObject.x) - __mmX) ** 2 +
(Number(__mmObject.y) - __mmY) ** 2 <
__mmMinimum * __mmMinimum
)
return !1;
}
for (
let __mmIndex = 0;
__mmIndex < __mmWeaponGrindReservations.length;
__mmIndex++
) {
const __mmEntry = __mmWeaponGrindReservations[__mmIndex],
__mmMinimum = __mmScale + __mmEntry.scale + 3;
if (
(__mmEntry.x - __mmX) ** 2 + (__mmEntry.y - __mmY) ** 2 <
__mmMinimum * __mmMinimum
)
return !1;
}
return !0;
}
function __mmWeaponGrindPlacement(__mmKind, __mmItem) {
if (!v || !v.alive) return null;
const __mmData = b && b.list && b.list[__mmItem];
if (!__mmData) return null;
const __mmScale = Number(__mmData.scale) || 45,
__mmDistance =
(Number(v.scale) || 35) +
__mmScale +
(Number(__mmData.placeOffset) || 0),
__mmBase = Number.isFinite(__mmWeaponGrindLayoutAngle)
? __mmWeaponGrindLayoutAngle
: __mmRawMouseAimDirection(),
__mmOrdinal = __mmWeaponGrindPlaced[__mmKind],
__mmPreferred =
__mmKind === "turret"
? __mmBase + (__mmOrdinal ? 0.82 : -0.82)
: __mmBase + Math.PI + (__mmOrdinal ? 0.82 : -0.82),
__mmStep = Math.PI / 24;
for (let __mmOffset = 0; __mmOffset < 48; __mmOffset++) {
const __mmRing = Math.ceil(__mmOffset / 2),
__mmSign = __mmOffset === 0 || __mmOffset % 2 ? 1 : -1,
__mmAngle = __mmPreferred + __mmRing * __mmStep * __mmSign,
__mmX = Number(v.x) + Math.cos(__mmAngle) * __mmDistance,
__mmY = Number(v.y) + Math.sin(__mmAngle) * __mmDistance;
if (__mmWeaponGrindPositionClear(__mmX, __mmY, __mmScale))
return {
item: __mmItem,
kind: __mmKind,
angle: __mmAngle,
x: __mmX,
y: __mmY,
scale: __mmScale,
groupId: __mmData.group && __mmData.group.id,
};
}
return null;
}
function __mmWeaponGrindReleaseHold() {
if (!__mmWeaponGrindHold) return;
(O.send(
"F",
0,
Number.isFinite(__mmWeaponGrindAimAngle) ? __mmWeaponGrindAimAngle : null,
),
(U = 0),
(__mmSecondaryHeld = !1),
(__mmSecondaryAttackDown = !1),
(__mmWeaponGrindHold = !1),
__mmStopHeldAttackPulse(),
__mmRestoreHeldHat(),
__mmRestoreHeldTail(),
__mmRestoreRightClickHat());
}
function __mmWeaponGrindUpdateAim(__mmNow, __mmForce) {
if (
!v ||
!v.alive ||
(!__mmForce && __mmNow < __mmWeaponGrindNextAimAt)
)
return !1;
const __mmTargets = __mmWeaponGrindSlots.turret
.concat(__mmWeaponGrindSlots.teleporter)
.filter(function (__mmSlot) {
return !!(__mmSlot && __mmSlot.confirmed && __mmSlot.object);
});
let __mmAngle = Number.isFinite(__mmWeaponGrindLayoutAngle)
? __mmWeaponGrindLayoutAngle
: __mmRawMouseAimDirection();
if (__mmTargets.length) {
const __mmTarget =
__mmTargets[__mmWeaponGrindTargetIndex++ % __mmTargets.length];
__mmAngle = Math.atan2(
Number(__mmTarget.y) - Number(v.y),
Number(__mmTarget.x) - Number(v.x),
);
}
const __mmSwingMs = __mmManualWeaponCooldown(
__mmWeaponGrindWeapon,
__mmTankRightClickEnabled && v.skins && v.skins[40] ? 40 : null,
);
((__mmWeaponGrindAimAngle = __mmAngle),
(__mmWeaponGrindNextAimAt =
__mmNow + Math.max(__mmServerTickMs(), Number(__mmSwingMs) || 0)));
__mmWeaponGrindHold && O.send("D", __mmAngle);
return !0;
}
function __mmWeaponGrindBeginHold(__mmNow) {
if (
__mmWeaponGrindHold ||
!v ||
!v.alive ||
!v.weapons ||
!v.weapons.includes(__mmWeaponGrindWeapon)
)
return !1;
(Number.isFinite(__mmWeaponGrindLayoutAngle) ||
(__mmWeaponGrindLayoutAngle = __mmRawMouseAimDirection()),
__mmWeaponGrindUpdateAim(__mmNow, !0),
(U = 1),
(__mmSecondaryHeld = !0),
(__mmSecondaryAttackDown = !0),
je(__mmWeaponGrindWeapon, !0),
__mmCleanupUpdateSecondaryGear(__mmWeaponGrindWeapon, __mmNow),
O.send("D", __mmWeaponGrindAimAngle),
O.send("F", 1, __mmWeaponGrindAimAngle),
(__mmWeaponGrindHold = !0));
return !0;
}
function __mmWeaponGrindPlaceOne(__mmNow) {
const __mmKinds = ["turret", "teleporter"];
for (let __mmIndex = 0; __mmIndex < __mmKinds.length; __mmIndex++) {
const __mmKind = __mmKinds[__mmIndex];
if (__mmWeaponGrindPlaced[__mmKind] >= 2) continue;
const __mmItem = __mmWeaponGrindItem(__mmKind);
if (__mmItem == null || __mmWeaponGrindCapacity(__mmItem) < 1) continue;
const __mmPlacement = __mmWeaponGrindPlacement(__mmKind, __mmItem);
if (!__mmPlacement) continue;
const __mmSlot = {
x: __mmPlacement.x,
y: __mmPlacement.y,
scale: __mmPlacement.scale,
groupId: __mmPlacement.groupId,
item: __mmPlacement.item,
sentAt: __mmNow,
confirmed: !1,
object: null,
};
(__mmWeaponGrindReleaseHold(),
(__mmWeaponGrindAimAngle = __mmPlacement.angle));
if (
!__mmSendAutomaticPlacement(
__mmPlacement.item,
__mmPlacement.angle,
{ item: __mmWeaponGrindWeapon, weapon: !0 },
)
)
continue;
(
__mmWeaponGrindSlots[__mmKind].push(__mmSlot),
(__mmWeaponGrindPlaced[__mmKind] =
__mmWeaponGrindSlots[__mmKind].length),
(__mmWeaponGrindLastPlaceAt = __mmNow),
__mmWeaponGrindReservations.push({
slot: __mmSlot,
x: __mmPlacement.x,
y: __mmPlacement.y,
scale: __mmPlacement.scale,
groupId: __mmPlacement.groupId,
placedAtSend:
Number(
v.itemCounts && v.itemCounts[__mmPlacement.groupId],
) || 0,
expiresAt: __mmNow + 1200,
}),
__mmScheduleMouseAimReturn());
return !0;
}
return !1;
}
function __mmPauseWeaponGrind(__mmReason) {
(__mmWeaponGrindReleaseHold(),
__mmActionRelease("weaponGrind", __mmReason || "paused"));
}
function __mmUpdateWeaponGrind() {
if (!__mmWeaponGrindEnabled)
return void __mmStopWeaponGrind("disabled");
if (document.hidden || !v || !v.alive || !Array.isArray(v.weapons)) {
(__mmPauseWeaponGrind("runtime unavailable"),
(__mmWeaponGrindWeapon = null),
(__mmWeaponGrindLifeSid = null),
__mmWeaponGrindResetPlacements());
return;
}
const __mmLifeSid = String(v.sid);
if (__mmWeaponGrindLifeSid !== __mmLifeSid) {
((__mmWeaponGrindLifeSid = __mmLifeSid),
(__mmWeaponGrindWeapon = null),
(__mmWeaponGrindLayoutAngle = __mmRawMouseAimDirection()),
(__mmWeaponGrindAimAngle = __mmWeaponGrindLayoutAngle),
__mmWeaponGrindResetPlacements());
}
if (!__mmActionAvailable("weaponGrind")) {
__mmWeaponGrindReleaseHold();
return;
}
// Any outside input path that emitted attack-up must invalidate our local
// latch too; otherwise the mode would think it was still holding while the
// server had already stopped the weapon.
__mmWeaponGrindHold &&
!__mmSecondaryHeld &&
__mmWeaponGrindReleaseHold();
if (!__mmWeaponGrindHold) {
const __mmSelected = __mmSelectedWeapon();
v.weapons.includes(__mmSelected) && (__mmWeaponGrindWeapon = __mmSelected);
}
if (
__mmWeaponGrindWeapon == null ||
!v.weapons.includes(__mmWeaponGrindWeapon) ||
!__mmActionClaim("weaponGrind", "right-hold weapon grind")
)
return;
const __mmNow = Date.now();
__mmWeaponGrindCleanReservations(__mmNow);
__mmWeaponGrindRefreshSlots(__mmNow);
if (
__mmNow - __mmWeaponGrindLastPlaceAt >= __mmServerTickMs() &&
__mmWeaponGrindPlaceOne(__mmNow)
)
return;
if (!__mmWeaponGrindHold) __mmWeaponGrindBeginHold(__mmNow);
else {
(U = 1,
__mmSecondaryHeld || (__mmSecondaryHeld = !0),
__mmWeaponGrindUpdateAim(__mmNow, !1),
__mmCleanupUpdateSecondaryGear(__mmWeaponGrindWeapon, __mmNow));
}
}
function __mmStartWeaponGrind() {
if (!__mmWeaponGrindEnabled) return;
((__mmWeaponGrindLayoutAngle = __mmRawMouseAimDirection()),
(__mmWeaponGrindAimAngle = __mmWeaponGrindLayoutAngle),
__mmWeaponGrindResetPlacements(),
__mmEnsureOperationPipeline());
}
function __mmStopWeaponGrind(__mmReason) {
(__mmWeaponGrindTimer && clearInterval(__mmWeaponGrindTimer),
(__mmWeaponGrindTimer = 0),
__mmPauseWeaponGrind(__mmReason || "stopped"),
(__mmWeaponGrindWeapon = null),
(__mmWeaponGrindLayoutAngle = null),
(__mmWeaponGrindAimAngle = null),
(__mmWeaponGrindLifeSid = null),
__mmWeaponGrindResetPlacements(),
__mmScheduleMouseAimReturn());
}
function __mmDisableWeaponGrind(__mmReason) {
if (!__mmWeaponGrindEnabled) return;
((__mmWeaponGrindEnabled = !1),
__mmStopWeaponGrind(__mmReason || "disabled"),
__mmPublishHudState());
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
__mmWeaponGrindEnabled &&
__mmEvent.isTrusted &&
__mmIsGameClick(__mmEvent) &&
__mmDisableWeaponGrind("manual click");
},
!0,
);
function __mmWeaponIsReloading(__mmWeapon) {
if (
!v ||
!v.alive ||
!v.weapons ||
__mmWeapon == null ||
!v.weapons.includes(__mmWeapon)
)
return !1;
const __mmNow = Date.now(),
__mmState = __mmAdvancePlayerToolCooldowns(v, __mmNow),
__mmReconciled = __mmReconcileLocalToolCooldown(
v,
__mmWeapon,
__mmNow,
__mmState,
),
__mmTracked = __mmReconciled.entry,
__mmTrackedRemaining = Math.max(
0,
Number(__mmTracked && __mmTracked.remaining) || 0,
);
return (
__mmTrackedRemaining > 0 ||
(__mmReconciled.hasLive && Number(__mmReconciled.live) > 0)
);
}
function __mmMusketIsReloading() {
return __mmWeaponIsReloading(__mmMusket);
}
function __mmTurretGearIsReloading() {
return !!(
v &&
v.alive &&
__mmTurretCooldownRemaining(v, Date.now()) > 0
);
}
function __mmAssumeTurretGearShot() {
// Turret Gear has no exposed reload entry. Reserve its cooldown as soon as
// Kitty emits the firing gear phase instead of waiting for a server attack
// acknowledgement; this prevents another automation from immediately
// launching a second, empty Insta attempt.
if (!v || !v.alive || !v.skins || !v.skins[__mmTurretGear]) return !1;
__mmTrackPlayerTurretCooldown(v.sid, "assumed");
return !0;
}
function __mmTrackTurretGearReload(__mmPlayerSid) {
let __mmPlayer = null;
try {
__mmPlayer = Rt(__mmPlayerSid);
} catch (__mmTurretAttackLookupError) {}
if (
!__mmPlayer &&
v &&
String(__mmPlayerSid) === String(v.sid)
)
__mmPlayer = v;
if (!__mmPlayer || Number(__mmPlayer.skinIndex) !== __mmTurretGear) return;
__mmTrackPlayerTurretCooldown(__mmPlayerSid, "attack");
}
function __mmWeaponRechargeOverridden() {
return (
!v ||
!v.alive ||
__mmInsta.attackHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmAutoHealWasHealing ||
__mmShieldDefenseTimer ||
!__mmActionAvailable("weaponRecharge")
);
}
function __mmNextWeaponToRecharge() {
if (!v || !v.alive || !v.weapons) return null;
const __mmSeen = new Set(),
__mmHeldWeapon = __mmHeldAttackWeapon();
let __mmHeldCooling = null;
// Inventory order is main first, then secondary/any additional weapons.
// A weapon under a native hold is already reloading. Let the off-hand borrow
// that hold first so a continuously swinging main cannot starve it forever.
for (let __mmIndex = 0; __mmIndex < v.weapons.length; __mmIndex++) {
const __mmWeapon = v.weapons[__mmIndex];
if (__mmWeapon == null || __mmSeen.has(__mmWeapon)) continue;
__mmSeen.add(__mmWeapon);
if (!__mmWeaponIsReloading(__mmWeapon)) continue;
if (Number(__mmWeapon) === Number(__mmHeldWeapon)) {
__mmHeldCooling = __mmWeapon;
continue;
}
return __mmWeapon;
}
return __mmHeldCooling;
}
function __mmWeaponRechargeSelected(__mmWeapon) {
if (!v || !v.alive) return !1;
if (
Date.now() - __mmLastSelectionAt <= 180 &&
__mmLastSelectionWasWeapon &&
Number(__mmLastSelectionItem) === Number(__mmWeapon)
)
return !0;
return !!(
Number(v.buildIndex) < 0 &&
Number(v.weaponIndex) === Number(__mmWeapon)
);
}
function __mmPreferWeaponRechargeRestore(__mmTool) {
if (__mmWeaponRechargePreviousTool != null || __mmTool == null) return;
if (typeof __mmTool === "object" && __mmTool.item != null)
__mmWeaponRechargePreviousTool = {
item: Number(__mmTool.item),
weapon: !!__mmTool.weapon,
};
else if (
v &&
v.weapons &&
v.weapons.includes(Number(__mmTool))
)
__mmWeaponRechargePreviousTool = {
item: Number(__mmTool),
weapon: !0,
};
}
function __mmWeaponRechargeCurrentTool() {
if (!v || !v.alive) return null;
// Selection packets update Kitty's local selection immediately, while the
// mirrored player fields can trail by a server tick. Insta restores the main
// and calls this queue in that gap, so trust the just-issued selection first.
if (Date.now() - __mmLastSelectionAt <= 150) {
const __mmRecentItem = Number(__mmLastSelectionItem);
if (
__mmLastSelectionWasWeapon &&
v.weapons &&
v.weapons.includes(__mmRecentItem)
)
return { item: __mmRecentItem, weapon: !0 };
if (
!__mmLastSelectionWasWeapon &&
v.items &&
v.items.includes(__mmRecentItem)
)
return { item: __mmRecentItem, weapon: !1 };
}
const __mmBuild = Number(v.buildIndex);
if (
Number.isInteger(__mmBuild) &&
__mmBuild >= 0 &&
v.items &&
v.items.includes(__mmBuild)
)
return { item: __mmBuild, weapon: !1 };
const __mmWeapon = Number(v.weaponIndex);
return v.weapons && v.weapons.includes(__mmWeapon)
? { item: __mmWeapon, weapon: !0 }
: __mmSelectedTool();
}
function __mmSelectWeaponForRecharge(__mmWeapon) {
if (__mmWeaponRechargeSelected(__mmWeapon)) return !0;
const __mmNow = Date.now();
if (__mmNow - __mmWeaponRechargeSelectAt >= 25) {
((__mmWeaponRechargeSelectAt = __mmNow), je(__mmWeapon, !0));
}
return __mmWeaponRechargeSelected(__mmWeapon);
}
function __mmSuspendHeldAttackForRecharge(__mmWeapon) {
const __mmHeldWeapon = __mmHeldAttackWeapon();
if (
__mmHeldWeapon == null ||
Number(__mmHeldWeapon) === Number(__mmWeapon)
)
return !1;
if (!__mmWeaponRechargeHeldLoan)
__mmWeaponRechargeHeldLoan = {
weapon: Number(__mmHeldWeapon),
primary: !!__mmPrimaryHeld,
secondary: !!__mmSecondaryHeld,
attackDown: !!(__mmPrimaryAttackDown || __mmSecondaryAttackDown),
};
if (__mmHeldAttackTimer)
(clearInterval(__mmHeldAttackTimer), (__mmHeldAttackTimer = 0));
if (__mmPrimaryAttackDown || __mmSecondaryAttackDown)
__mmSendWeaponAttack(0);
((__mmPrimaryAttackDown = !1), (__mmSecondaryAttackDown = !1));
return !0;
}
function __mmResumeHeldAttackAfterRecharge() {
const __mmLoan = __mmWeaponRechargeHeldLoan;
__mmWeaponRechargeHeldLoan = null;
if (
!__mmLoan ||
!v ||
!v.alive ||
(!__mmPrimaryHeld && !__mmSecondaryHeld)
)
return !1;
const __mmWeapon = __mmHeldAttackWeapon();
if (__mmWeapon == null) return !1;
// Another borrowed action may already have restored the native hold while
// the reload worker was paused. In that case only retire our loan marker;
// never emit a second F=1 that could reset timing or latch a fast click.
if (__mmPrimaryAttackDown || __mmSecondaryAttackDown) {
__mmHeldAttackTimer || __mmStartHeldAttackPulse();
return !0;
}
((__mmPrimaryAttackDown = !1),
(__mmSecondaryAttackDown = !1),
__mmStartHeldAttackPulse());
return !0;
}
function __mmPrepareWeaponRechargeSelection(__mmWeapon) {
const __mmHeldWeapon = __mmHeldAttackWeapon();
if (
__mmWeaponRechargeHeldLoan &&
__mmHeldWeapon != null &&
Number(__mmHeldWeapon) === Number(__mmWeapon)
)
__mmResumeHeldAttackAfterRecharge();
else
__mmSuspendHeldAttackForRecharge(__mmWeapon);
}
function __mmPauseWeaponRecharge(__mmRestore) {
const __mmActive = __mmWeaponRechargeActiveWeapon,
__mmPrevious = __mmWeaponRechargePreviousTool;
(__mmRestore &&
__mmActionMayRestore("weaponRecharge") &&
__mmActive != null &&
__mmPrevious != null &&
__mmWeaponRechargeSelected(__mmActive) &&
__mmRestoreTool(__mmPrevious),
(__mmWeaponRechargeActiveWeapon = null),
(__mmWeaponRechargeSelectAt = 0),
__mmRestore && __mmResumeHeldAttackAfterRecharge(),
__mmActionRelease("weaponRecharge", "reload paused"));
}
function __mmStopWeaponRecharge(__mmRestore) {
const __mmRestoreTarget = __mmWeaponRechargePreviousTool;
((__mmWeaponRechargeActiveWeapon = null),
(__mmWeaponRechargePreviousTool = null),
(__mmWeaponRechargeSelectAt = 0),
__mmRestore &&
__mmRestoreTarget != null &&
__mmActionMayRestore("weaponRecharge") &&
__mmRestoreTool(__mmRestoreTarget),
__mmResumeHeldAttackAfterRecharge(),
__mmActionRelease("weaponRecharge", "reload queue complete"));
}
function __mmUpdateWeaponRecharge() {
if (
!__mmMusketRechargeEnabled ||
__mmSyncFollowerEnabled ||
!v ||
!v.alive ||
!v.weapons
)
return void __mmStopWeaponRecharge(!1);
const __mmTarget = __mmNextWeaponToRecharge(),
__mmActive = __mmWeaponRechargeActiveWeapon;
// Higher-priority actions pause selection but retain the original tool and
// cooldown queue. A normal held attack is handled as a resumable loan below,
// so it no longer blocks the off-hand from reloading indefinitely.
if (__mmWeaponRechargeOverridden()) {
__mmActive != null && __mmPauseWeaponRecharge(!1);
return;
}
if (__mmTarget == null) return void __mmStopWeaponRecharge(!0);
if (__mmActive === __mmTarget) {
__mmPrepareWeaponRechargeSelection(__mmTarget);
__mmSelectWeaponForRecharge(__mmTarget);
return;
}
// A newly cooling main preempts the secondary. A completed main advances to
// the secondary immediately in this same scan without clearing queue state.
if (__mmActive != null) {
((__mmWeaponRechargeActiveWeapon = __mmTarget),
(__mmWeaponRechargeSelectAt = 0),
__mmPrepareWeaponRechargeSelection(__mmTarget),
__mmSelectWeaponForRecharge(__mmTarget));
return;
}
if (!__mmActionClaim("weaponRecharge", "idle reload")) return;
((__mmWeaponRechargeActiveWeapon = __mmTarget),
__mmWeaponRechargePreviousTool == null &&
(__mmWeaponRechargePreviousTool = __mmWeaponRechargeCurrentTool()),
(__mmWeaponRechargeSelectAt = 0),
__mmPrepareWeaponRechargeSelection(__mmTarget),
__mmSelectWeaponForRecharge(__mmTarget));
}
function __mmStartWeaponRecharge() {
__mmEnsureOperationPipeline();
}
function __mmRestoreAutoHealWeapon() {
// __mmUseFood restores the selected weapon after each safe food use. Keep
// this cleanup hook for the HUD toggle and for older event paths.
__mmAutoHealWeapon = null;
}
function __mmAutoHealFoodValue() {
if (!v || v.items[0] == null) return 20;
const __mmFood = b.list[v.items[0]];
const __mmDescription = String((__mmFood && __mmFood.desc) || "");
const __mmMatch = __mmDescription.match(/restores\\s+(\\d+)\\s+health/i);
return __mmMatch ? Math.max(1, Number(__mmMatch[1])) : 20;
}
function __mmObserveAutoHealHealth(__mmHealth) {
const __mmCurrentHealth = Number(__mmHealth);
if (!Number.isFinite(__mmCurrentHealth)) return !1;
const __mmNow = Date.now(),
__mmHadHealth = __mmAutoHealLastObservedHealth != null,
__mmTookDamage =
__mmHadHealth &&
__mmCurrentHealth < __mmAutoHealLastObservedHealth,
__mmHealed =
__mmHadHealth &&
__mmCurrentHealth > __mmAutoHealLastObservedHealth;
if (__mmTookDamage)
((__mmAutoHealPending = !0),
(__mmAutoHealBitesRemaining = 0),
(__mmAutoHealNextBiteAt = 0),
(__mmAutoHealLastDamageAt = __mmNow));
// Track manual healing too. Autoheal predicts its own result at send time
// and clears LastDamageAt there, so its later health packet is not counted
// twice. This mirrors the server's <=120ms increment / late-heal -2 rule.
if (__mmHealed && __mmAutoHealLastDamageAt) {
const __mmElapsed = __mmNow - __mmAutoHealLastDamageAt;
((__mmAutoHealShameCount =
__mmElapsed <= 120
? Math.min(8, __mmAutoHealShameCount + 1)
: Math.max(0, __mmAutoHealShameCount - 2)),
(__mmAutoHealLastDamageAt = 0));
}
// Queue one catch-up heal if the script begins while already injured. Later
// heals are queued only by actual damage packets, so the 10ms backup loop
// cannot resend the same burst while the server is processing it.
if (
!__mmTookDamage &&
__mmAutoHealLastObservedHealth == null &&
v &&
v.alive &&
__mmCurrentHealth < v.maxHealth
)
((__mmAutoHealPending = !0),
(__mmAutoHealBitesRemaining = 0),
(__mmAutoHealNextBiteAt = 0));
__mmAutoHealLastObservedHealth = __mmCurrentHealth;
return __mmTookDamage;
}
function __mmAutoHealRecordFoodAttempt(__mmNow) {
if (!__mmAutoHealLastDamageAt) return;
const __mmElapsed = __mmNow - __mmAutoHealLastDamageAt;
((__mmAutoHealShameCount =
__mmElapsed <= 120
? Math.min(8, __mmAutoHealShameCount + 1)
: Math.max(0, __mmAutoHealShameCount - 2)),
// The server consumes the saved hit timestamp on this food attempt. Clear
// ours immediately as well; no acknowledgement retry is involved.
(__mmAutoHealLastDamageAt = 0));
}
function __mmAutoHealSafeAt(__mmEmergency, __mmFoodValue) {
if (!__mmAutoHealLastDamageAt || __mmAutoHealShameCount < 5)
return 0;
const __mmLowHealth =
v.health <= Math.max(35, Number(__mmFoodValue) || 20);
// Survival wins over Shame prevention. At non-critical health, 135ms from
// the received damage packet is deliberately beyond the server's 120ms
// comparison and turns this heal into a two-point counter reduction.
return __mmEmergency || __mmLowHealth
? 0
: __mmAutoHealLastDamageAt + 135;
}
function __mmResetAutoHeal() {
((__mmAutoHealWasHealing = !1),
(__mmAutoHealPending = !1),
(__mmAutoHealBitesRemaining = 0),
(__mmAutoHealNextBiteAt = 0),
(__mmAutoHealLastObservedHealth = v && v.alive ? Number(v.health) : null),
__mmRestoreAutoHealWeapon());
}
function __mmAutoHeal(__mmEmergency) {
if (!__mmAutoHealEnabled || !v || !v.alive)
return void __mmResetAutoHeal();
__mmObserveAutoHealHealth(v.health);
// The same forecast that drives Anti Insta also removes the Shame delay when
// damage already in flight would consume the current health. It does not
// create speculative food retries; an actual damage/health event still owns
// the heal queue.
const __mmIncomingThreat = __mmCombatThreatSnapshot();
__mmEmergency = !!(__mmEmergency || __mmIncomingThreat.urgent);
// Shame! (hat 45) means the server is rejecting food for its 30-second
// penalty. Do not burn resources or flood selection/attack packets during it.
if (Number(v.skinIndex) === 45) {
((__mmAutoHealShameCount = 8),
(__mmAutoHealPending = !1),
(__mmAutoHealBitesRemaining = 0),
(__mmAutoHealNextBiteAt = 0));
return;
}
if (v.health >= v.maxHealth || !__mmCanEat()) return void __mmResetAutoHeal();
if (__mmAutoHealPending) {
// Calculate the whole refill from the hit packet, then keep sending it on
// the server tick. This is optimistic (it never waits for a heal reply),
// but avoids the current server dropping a pile of same-frame F packets.
const __mmMissingHealth = Math.max(0, v.maxHealth - v.health),
__mmFoodValue = __mmAutoHealFoodValue(),
__mmNow = Date.now(),
__mmSafeAt = __mmAutoHealSafeAt(__mmEmergency, __mmFoodValue);
((__mmAutoHealBitesRemaining = Math.min(
Math.ceil(__mmMissingHealth / __mmFoodValue),
__mmFoodCharges(),
)),
(__mmAutoHealPending = !1),
(__mmAutoHealNextBiteAt = Math.max(__mmNow, __mmSafeAt || 0)));
}
if (!__mmAutoHealBitesRemaining || Date.now() < __mmAutoHealNextBiteAt)
return;
// A held mouse attack remains the action owner while food is pulsed between
// swings. __mmUseFood restores the selected tool and resumes the live held
// attack immediately, so healing does not require releasing either button.
const __mmHealingDuringHeldAttack = !!(
__mmActionOwner === "manualAttack" &&
(__mmPrimaryHeld || __mmSecondaryHeld)
),
__mmOwnsAction = __mmHealingDuringHeldAttack
? !1
: __mmActionClaim("autoHeal", "food recovery");
if (
!__mmOwnsAction &&
!__mmHealingDuringHeldAttack &&
!(__mmEmergency && __mmActionOwner === "trapEscape")
)
return;
const __mmFoodSentAt = Date.now();
((__mmAutoHealWasHealing = !0),
__mmAutoHealRecordFoodAttempt(__mmFoodSentAt),
__mmUseFood(),
(__mmAutoHealWasHealing = !1),
(__mmAutoHealBitesRemaining -= 1),
(__mmAutoHealNextBiteAt =
Date.now() + Math.max(1, __mmServerTickMs())),
__mmOwnsAction && __mmActionRelease("autoHeal", "food sent"));
}
function __mmToggleAutoHeal() {
__mmSetAutoHeal(!__mmAutoHealEnabled);
}
function __mmBushStatus(__mmMessage) {
window.dispatchEvent(
new CustomEvent("MooMooScrollZoomStatus", { detail: __mmMessage }),
);
}
function __mmBushGearOwned() {
return !!(v && v.skins && v.skins[__mmBushGear]);
}
function __mmClearBushPurchaseWatch() {
__mmBushPurchaseTimer && clearInterval(__mmBushPurchaseTimer);
__mmBushPurchaseTimer = 0;
}
function __mmBushRestoreHat(__mmFallback) {
return Date.now() <= __mmBushRestoreOverrideUntil &&
__mmBushRestoreOverrideHat != null
? __mmBushRestoreOverrideHat
: __mmFallback;
}
function __mmBushRestoreTail(__mmFallback) {
return Date.now() <= __mmBushRestoreOverrideUntil &&
__mmBushRestoreOverrideTail != null
? __mmBushRestoreOverrideTail
: __mmFallback;
}
function __mmBushAllowedMovingTail() {
if (!v || !v.alive || !v.tails) return 0;
if (
(v.tailIndex === __mmShadowWings || v.tailIndex === 11) &&
v.tails[v.tailIndex]
)
return v.tailIndex;
if (
(__mmBushPreviousTail === __mmShadowWings ||
__mmBushPreviousTail === 11) &&
v.tails[__mmBushPreviousTail]
)
return __mmBushPreviousTail;
if (v.tails[__mmShadowWings]) return __mmShadowWings;
return v.tails[11] ? 11 : 0;
}
function __mmBushBreaksOnActionOwner(__mmOwner) {
return (
__mmOwner === "manualAttack" ||
__mmOwner === "trapEscape" ||
__mmOwner === "spikeTickStrike" ||
__mmOwner === "instaSync" ||
__mmOwner === "boostBreak" ||
__mmOwner === "cleanup" ||
__mmOwner === "weaponGrind" ||
__mmOwner === "mobSteal" ||
__mmOwner === "matThief"
);
}
function __mmUpdateBushMode() {
if (!__mmBushModeEnabled) return;
if (!v || !v.alive)
return void __mmStopBushMode("player unavailable", !1);
const __mmSwingOwner = __mmBushBreaksOnActionOwner(__mmActionOwner);
if (
__mmSwingOwner ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive()
)
// Combat temporarily owns hats, tails, tools, and aim. Keep Bush mode
// armed and simply resume concealment on the first idle fast-check.
return;
const __mmTarget = __mmInsta.nearestEnemy();
const __mmPrimary = __mmInsta.supportedPrimary();
if (
__mmTarget &&
__mmPrimary != null &&
__mmInsta.inRange(__mmPrimary, __mmTarget) &&
__mmBoostInsta.requirements(__mmTarget, !0) &&
__mmActionCanPreempt("boostInsta")
) {
const __mmTargetSid = __mmTarget.sid;
return void __mmBoostInsta.start({
targetSid: __mmTargetSid,
ambush: !0,
});
}
const __mmTail = __mmPlayerMoving()
? __mmBushAllowedMovingTail()
: 0;
if (v.skinIndex !== __mmBushGear || __mmPendingHat !== __mmBushGear)
__mmEquipHatNow(__mmBushGear, !0);
if (v.tailIndex !== __mmTail || __mmPendingTail !== __mmTail)
__mmEquipTailNow(__mmTail, !0);
}
function __mmActivateBushMode() {
if (!__mmBushModeRequested || __mmBushModeEnabled || !__mmBushGearOwned())
return !1;
const __mmSavedHat =
__mmSoldierPreviousHat != null
? __mmSoldierPreviousHat
: __mmMovementGearPreviousHat != null
? __mmMovementGearPreviousHat
: v.skinIndex,
__mmSavedTail =
__mmMovementGearPreviousTail != null
? __mmMovementGearPreviousTail
: __mmProximityTailPrevious != null
? __mmProximityTailPrevious
: v.tailIndex;
(__mmBushExitRestoreTimer && clearTimeout(__mmBushExitRestoreTimer),
(__mmBushExitRestoreTimer = 0),
__mmClearBushPurchaseWatch(),
(__mmBushRestoreOverrideHat = null),
(__mmBushRestoreOverrideTail = null),
(__mmBushRestoreOverrideUntil = 0),
__mmRestoreMovementGear(),
__mmRestoreProximityTail(),
__mmPauseSoldierForBreaking(),
(__mmBushPreviousHat = __mmSavedHat),
(__mmBushPreviousTail = __mmSavedTail),
(__mmBushModeEnabled = !0),
__mmEnsureOperationPipeline(),
__mmUpdateBushMode(),
__mmBushStatus("Bush ambush: armed"),
__mmPublishHudState());
return !0;
}
function __mmScheduleBushExitRestore(__mmHat, __mmTail) {
(__mmBushExitRestoreTimer && clearTimeout(__mmBushExitRestoreTimer),
(__mmBushExitRestoreTimer = 0));
const __mmRestoreWhenIdle = function () {
__mmBushExitRestoreTimer = 0;
if (__mmBushModeRequested || !v || !v.alive) return;
if (
__mmBushBreaksOnActionOwner(__mmActionOwner) ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive()
) {
__mmBushExitRestoreTimer = setTimeout(
__mmRestoreWhenIdle,
__mmFastCheckMs(),
);
return;
}
((__mmBushRestoreOverrideHat = __mmHat),
(__mmBushRestoreOverrideTail = __mmTail),
(__mmBushRestoreOverrideUntil = Date.now() + __mmServerTickMs() * 3),
__mmEquipGearPair(__mmHat, __mmTail, !0));
};
__mmRestoreWhenIdle();
}
function __mmStopBushMode(__mmReason, __mmRestore = !0) {
const __mmWasRequested = __mmBushModeRequested,
__mmWasEnabled = __mmBushModeEnabled,
__mmHat = __mmBushPreviousHat,
__mmTail = __mmBushPreviousTail;
((__mmBushModeRequested = !1),
(__mmBushModeEnabled = !1),
__mmClearBushPurchaseWatch(),
__mmBushModeTimer && clearInterval(__mmBushModeTimer),
(__mmBushModeTimer = 0),
(__mmBushPreviousHat = null),
(__mmBushPreviousTail = null));
if (__mmRestore && __mmWasEnabled && v && v.alive) {
__mmScheduleBushExitRestore(__mmHat, __mmTail);
}
(__mmWasRequested || __mmWasEnabled) &&
(__mmReason && __mmBushStatus("Bush ambush: " + __mmReason),
__mmPublishHudState());
}
function __mmWatchBushPurchase() {
if (__mmBushPurchaseTimer) return;
const __mmStartedAt = Date.now();
__mmBushPurchaseTimer = setInterval(function () {
if (!__mmBushModeRequested)
return void __mmClearBushPurchaseWatch();
if (__mmBushGearOwned()) return void __mmActivateBushMode();
if (!v || !v.alive || Date.now() - __mmStartedAt > 3e3)
return void __mmStopBushMode("purchase was not accepted", !1);
}, __mmFastCheckMs());
}
function __mmSetBushMode(__mmEnabled) {
if (!__mmEnabled) return void __mmStopBushMode("off", !0);
if (__mmBushModeRequested) return;
if (
!v ||
!v.alive ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmBushBreaksOnActionOwner(__mmActionOwner)
)
return void __mmBushStatus("Bush ambush unavailable");
__mmBushModeRequested = !0;
if (__mmBushGearOwned()) return void __mmActivateBushMode();
if (
(Number(v.points) || 0) < __mmBushGearPrice ||
Date.now() - __mmBushPurchaseAt < 500
)
return void __mmStopBushMode("needs 3,000 points for Bush Gear", !1);
((__mmBushPurchaseAt = Date.now()),
Xn(__mmBushGear, !1),
__mmBushStatus("Bush ambush: buying Bush Gear"),
__mmPublishHudState(),
__mmWatchBushPurchase());
}
function __mmToggleBushMode() {
__mmSetBushMode(!__mmBushModeRequested);
}
function __mmHandleBushHotkey() {
if (__mmBushHotkeyDown) return;
const __mmActiveElement = document.activeElement,
__mmActiveTag =
__mmActiveElement && __mmActiveElement.tagName
? __mmActiveElement.tagName.toLowerCase()
: "";
if (
__mmActiveElement &&
(__mmActiveTag === "input" ||
__mmActiveTag === "textarea" ||
__mmActiveElement.isContentEditable)
)
return;
((__mmBushHotkeyDown = !0), __mmToggleBushMode());
}
const __mmBowUpgradeInsta = {
active: !1,
targetSid: null,
source: "manual",
restoreTool: null,
restoreHat: null,
timers: new Set(),
stageGap() {
// Keep the ordered packets in one server-update window without putting
// upgrade and attack messages in the same transport write.
return Math.max(4, Math.min(10, Math.round(__mmFastCheckMs() * 0.5)));
},
target() {
let __mmTarget = null;
try {
__mmTarget = Rt(this.targetSid);
} catch (__mmBowUpgradeLookupError) {}
return __mmIsEnemyPlayer(__mmTarget) ? __mmTarget : null;
},
weaponProjectile(__mmWeapon) {
const __mmWeaponData = b && b.weapons && b.weapons[__mmWeapon];
return __mmWeaponData && __mmWeaponData.projectile != null
? b.projectiles && b.projectiles[__mmWeaponData.projectile]
: null;
},
inRange(__mmTarget) {
if (!__mmTarget) return !1;
const __mmDistance = __mmProjectileTravelDistance(v, __mmTarget);
for (const __mmWeapon of [__mmBow, __mmCrossbow, __mmMusket]) {
const __mmProjectile = this.weaponProjectile(__mmWeapon),
__mmRange = Number(__mmProjectile && __mmProjectile.range);
if (!__mmProjectile || !Number.isFinite(__mmRange) || __mmDistance > __mmRange)
return !1;
}
return !0;
},
hasSpecialUpgrade() {
// The saved-up branch is only meaningful after the player has selected a
// special deployable (Turret, Teleporter, pad, platform, or blocker).
return __mmSelectedPlaceableItem() != null;
},
ready(__mmTarget, __mmSkipBow = !1) {
const __mmPoints = Number(v && v.upgradePoints);
return !!(
__mmAutoBowUpgradeInstaEnabled &&
v &&
v.alive &&
Array.isArray(v.weapons) &&
v.weapons.includes(__mmBow) &&
!v.weapons.includes(__mmCrossbow) &&
!v.weapons.includes(__mmMusket) &&
Number.isFinite(__mmPoints) &&
__mmPoints >= 2 &&
this.hasSpecialUpgrade() &&
v.skins &&
v.skins[__mmTurretGear] &&
b &&
b.weapons &&
b.weapons[__mmCrossbow] &&
b.weapons[__mmMusket] &&
(__mmSkipBow || __mmWeaponReady(__mmBow)) &&
this.inRange(__mmTarget) &&
!this.active &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmBoostBreakHeld &&
(__mmActionCanPreempt("bowUpgradeInsta") ||
(__mmIsTrapped() &&
(__mmTrapAttackActive || __mmActionOwner === "trapEscape")))
);
},
aim(__mmWeapon, __mmTarget) {
const __mmProjectile = this.weaponProjectile(__mmWeapon),
__mmSpeed = Number(__mmProjectile && __mmProjectile.speed),
__mmDistance = __mmProjectileTravelDistance(v, __mmTarget),
__mmTravelMs = Number.isFinite(__mmSpeed) && __mmSpeed > 0
? __mmDistance / __mmSpeed
: 0;
return __mmSyncAimAngle(__mmTarget, __mmTravelMs);
},
schedule(__mmCallback, __mmDelay) {
const __mmTimer = setTimeout(() => {
this.timers.delete(__mmTimer);
__mmCallback();
}, Math.max(0, Number(__mmDelay) || 0));
this.timers.add(__mmTimer);
return __mmTimer;
},
clearTimers() {
for (const __mmTimer of this.timers) clearTimeout(__mmTimer);
this.timers.clear();
},
assumeUpgrade(__mmFrom, __mmTo) {
if (!v || !v.alive || !Array.isArray(v.weapons)) return !1;
const __mmSlot = v.weapons.indexOf(__mmFrom);
if (__mmSlot < 0) return !1;
v.weapons[__mmSlot] = __mmTo;
if (Number(v.weaponIndex) === Number(__mmFrom)) v.weaponIndex = __mmTo;
if (v.reloads) v.reloads[__mmTo] = 0;
const __mmState = v.sid == null
? null
: __mmPlayerToolCooldowns[String(v.sid)];
__mmState && __mmState.weapons && delete __mmState.weapons[String(__mmTo)];
const __mmPoints = Number(v.upgradePoints);
Number.isFinite(__mmPoints) && (v.upgradePoints = Math.max(0, __mmPoints - 1));
return !0;
},
fire(__mmWeapon) {
const __mmTarget = this.target();
if (!this.active || !__mmTarget || !this.inRange(__mmTarget))
return (this.cancel("target lost"), !1);
const __mmAngle = this.aim(__mmWeapon, __mmTarget);
try {
(je(__mmWeapon, !0),
O.send("D", __mmAngle),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle));
return !0;
} catch (__mmBowUpgradeFireError) {
return (this.cancel("shot failed"), !1);
}
},
upgradeAndFire(__mmFrom, __mmTo, __mmNext) {
if (!this.active || !v || !v.alive) return this.cancel("player lost");
try {
// Send through the captured native socket method so the ordinary click
// debounce and Katana/Musket helper cannot split this reserved sequence.
((__mmLastUpgradePacketAt = Date.now()),
__mmOriginalSocketSend.call(O, "H", __mmTo));
} catch (__mmBowUpgradePacketError) {
return this.cancel("upgrade packet failed");
}
if (!this.assumeUpgrade(__mmFrom, __mmTo) || !this.fire(__mmTo)) return;
typeof __mmNext === "function" && __mmNext();
},
finish() {
if (!this.active) return;
const __mmToolRestore = this.restoreTool,
__mmRestoreHat = this.restoreHat,
__mmMayRestore = __mmActionMayRestore("bowUpgradeInsta");
(this.clearTimers(),
(this.active = !1),
(this.targetSid = null),
(this.restoreTool = null),
(this.restoreHat = null),
__mmMayRestore &&
v &&
v.alive &&
__mmEquipHatNow(__mmBestPostCombatHat() || __mmRestoreHat, !0),
__mmMayRestore && __mmToolRestore && __mmRestoreTool(__mmToolRestore),
__mmActionRelease("bowUpgradeInsta", "three shots sent"),
__mmScheduleMouseAimReturn(),
__mmInstaChatEnabled && __mmSendChat("Meow!"));
},
cancel(__mmReason) {
if (!this.active) return !1;
const __mmToolRestore = this.restoreTool,
__mmRestoreHat = this.restoreHat,
__mmMayRestore = __mmActionMayRestore("bowUpgradeInsta");
(this.clearTimers(),
(this.active = !1),
(this.targetSid = null),
(this.restoreTool = null),
(this.restoreHat = null),
__mmMayRestore &&
v &&
v.alive &&
__mmEquipHatNow(__mmBestPostCombatHat() || __mmRestoreHat, !0),
__mmMayRestore && __mmToolRestore && __mmRestoreTool(__mmToolRestore),
__mmActionRelease("bowUpgradeInsta", __mmReason || "cancelled"),
__mmScheduleMouseAimReturn());
return !1;
},
start(__mmRequestedTarget, __mmSource = "manual", __mmOptions = {}) {
const __mmTarget =
__mmRequestedTarget && __mmIsEnemyPlayer(__mmRequestedTarget)
? __mmRequestedTarget
: __mmInsta.nearestEnemy();
const __mmSkipBow = !!__mmOptions.skipBow;
if (!this.ready(__mmTarget, __mmSkipBow)) return !1;
(__mmIsTrapped() &&
(__mmTrapAttackActive || __mmActionOwner === "trapEscape")) &&
__mmStopTrapAttack();
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmActionClaim("bowUpgradeInsta", __mmSource + " triple projectile"))
return !1;
(__mmCancelCombatHatLock(!1),
(this.active = !0),
(this.targetSid = __mmTarget.sid),
(this.source = __mmSource),
(this.restoreTool = __mmOptions.restoreTool || __mmSelectedTool()),
(this.restoreHat = __mmOptions.restoreHat != null
? __mmOptions.restoreHat
: __mmInstaSafeRestoreHat(__mmBushRestoreHat(v.skinIndex))));
const __mmAngle = this.aim(__mmBow, __mmTarget),
__mmTurretWasReady = __mmInsta.turretReady(),
__mmGap = this.stageGap();
try {
(O.send("D", __mmAngle),
__mmEquipHatNow(__mmTurretGear, !0),
__mmTurretWasReady && __mmAssumeTurretGearShot());
} catch (__mmBowUpgradeGearError) {
return this.cancel("Turret Gear failed");
}
__mmShowInstaTypePopup(
__mmSkipBow ? "Bow Upgrade Follow-up" : "Bow Upgrade Insta",
);
if (!__mmSkipBow && !this.fire(__mmBow)) return !1;
this.schedule(() => {
this.upgradeAndFire(__mmBow, __mmCrossbow, () => {
this.schedule(() => {
this.upgradeAndFire(__mmCrossbow, __mmMusket, () => {
this.schedule(() => this.finish(), __mmServerTickMs());
});
}, __mmGap);
});
}, __mmGap);
return !0;
},
};
function __mmHandleInstaHotkey() {
const __mmBowUpgradeTarget = __mmInsta.nearestEnemy();
if (__mmBowUpgradeInsta.ready(__mmBowUpgradeTarget)) {
const __mmCanLeadWithNormalInsta =
__mmInsta.supportedPrimary() != null &&
__mmInsta.fullBurstReady(__mmBowUpgradeTarget, "normal", !1, !0);
if (
__mmTryScheduleSharedInsta({
automatic: !1,
bowUpgrade: !0,
targetSid: __mmBowUpgradeTarget.sid,
})
)
return !0;
if (
__mmCanLeadWithNormalInsta &&
__mmInsta.start({
profile: "normal",
profileSource: "R + Bow Upgrade",
manualHotkey: !0,
targetSid: __mmBowUpgradeTarget.sid,
bowUpgradeFollowup: !0,
})
)
return !0;
if (__mmBowUpgradeInsta.start(__mmBowUpgradeTarget, "R")) return !0;
}
if (__mmBushModeRequested && __mmBushModeEnabled) {
const __mmTarget = __mmInsta.nearestEnemy();
if (
__mmTarget &&
__mmBoostInsta.start({
targetSid: __mmTarget.sid,
ambush: !0,
manualBush: !0,
})
)
return !0;
}
const __mmProfile = __mmOneTickInstaEnabled
? "oneTick"
: __mmReverseInstaEnabled
? "reverse"
: "normal",
__mmStarted = __mmInsta.start({
profile: __mmProfile,
profileSource: "R",
manualHotkey: !0,
});
if (!__mmStarted)
__mmBushStatus(
"R Insta: " + __mmInstaHotkeyBlockReason(__mmProfile),
);
return __mmStarted;
}
function __mmInstaHotkeyBlockReason(__mmProfile) {
if (!__mmInstaUiEnabled) return "disabled in Combat settings";
if (!__mmInsta.runtimeReady()) return "client is not ready";
if (!v || !v.alive) return "spawn first";
const __mmTarget = __mmInsta.nearestEnemy();
if (!__mmTarget) return "no enemy target";
const __mmPrimary = __mmInsta.supportedPrimary();
if (__mmPrimary == null) return "needs Short Sword, Katana, or Polearm";
if (!__mmInsta.inRange(__mmPrimary, __mmTarget))
return __mmInsta.turretReady()
? "enemy left range"
: "enemy out of range and Turret Gear is reloading";
if (!v.skins || !v.skins[7]) return "Bull Helmet not owned";
if (!__mmWeaponReady(__mmPrimary)) return "main weapon is reloading";
const __mmSecondary = v.weapons && v.weapons[1],
__mmSecondaryData = __mmInsta.weaponData(__mmSecondary);
if (
__mmSecondary == null ||
__mmSecondary === __mmPrimary ||
__mmSecondary === __mmShieldWeapon ||
!__mmSecondaryData ||
__mmSecondaryData.shield
)
return "usable secondary not equipped";
if (!__mmWeaponReady(__mmSecondary)) return "secondary is reloading";
if (!v.skins[__mmTurretGear]) return "Turret Gear not owned";
if (!__mmInsta.turretReady()) return "Turret Gear is reloading";
if (!__mmActionCanPreempt("insta"))
return "busy with " + String(__mmActionOwner || "another action");
return String(__mmInsta.reason || "kit validation failed");
}
function __mmToggleOneTickInsta() {
((__mmOneTickInstaEnabled = !__mmOneTickInstaEnabled),
__mmBushStatus(
"One-Tick Insta: " + (__mmOneTickInstaEnabled ? "on" : "off"),
),
__mmPublishHudState());
}
function __mmToggleVelTickInsta() {
((__mmVelTickInstaEnabled = !__mmVelTickInstaEnabled),
!__mmVelTickInstaEnabled && __mmStopVelTickInsta("hotkey disabled"),
__mmBushStatus(
"VelTick Insta: " + (__mmVelTickInstaEnabled ? "on" : "off"),
),
__mmPublishHudState());
}
function __mmHandleBushCombatClick(__mmEvent) {
if (!__mmBushModeRequested || !__mmBushModeEnabled) return !1;
const __mmTarget = __mmInsta.nearestEnemy(),
__mmPrimary = __mmInsta.supportedPrimary(),
__mmCanAmbush = !!(
__mmTarget &&
__mmPrimary != null &&
__mmInsta.inRange(__mmPrimary, __mmTarget) &&
__mmBoostInsta.requirements(__mmTarget, !0) &&
__mmActionCanPreempt("boostInsta")
);
if (__mmCanAmbush)
__mmBoostInsta.start({
targetSid: __mmTarget.sid,
ambush: !0,
});
else __mmUpdateBushMode();
// A click without a launchable nearby ambush is not a combat action. Keep
// it away from MooMoo's normal attack path so Bull/Tank cannot replace Bush
// Gear for a frame and make the armed mode appear to toggle itself off.
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
return !0;
}
function __mmTemporaryHatOverlay() {
return (
!v ||
!v.alive ||
__mmBushModeEnabled ||
__mmSyncFollowerEnabled ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmTankGearActive() ||
__mmPrimaryClickHat != null ||
__mmRightClickHat != null ||
__mmTrapHat != null ||
__mmSoldierPreviousHat != null
);
}
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 __mmBaseAutomationHat() {
return __mmTrapHat != null
? __mmTrapHat
: __mmRightClickHat != null
? __mmRightClickHat
: __mmPrimaryClickHat != null
? __mmPrimaryClickHat
: __mmSoldierPreviousHat != null
? __mmSoldierPreviousHat
: v
? __mmInstaSafeRestoreHat(__mmBushRestoreHat(v.skinIndex))
: null;
}
function __mmAssassinGearOwned() {
return !!(v && v.skins && v.skins[__mmAssassinGear]);
}
function __mmAssassinGearPrice() {
if (Array.isArray(Ze))
for (let __mmIndex = 0; __mmIndex < Ze.length; __mmIndex++)
if (Number(Ze[__mmIndex] && Ze[__mmIndex].id) === __mmAssassinGear)
return Math.max(0, Number(Ze[__mmIndex].price) || 20000);
return 20000;
}
function __mmAssassinStationary() {
if (!v || !v.alive || __mmPlayerMoving()) return !1;
const __mmElapsed = Number(v.t2) - Number(v.t1),
__mmVelocityX =
(Number(v.x2) - Number(v.x1)) / Math.max(1, __mmElapsed),
__mmVelocityY =
(Number(v.y2) - Number(v.y1)) / Math.max(1, __mmElapsed);
return !(
__mmElapsed > 0 &&
__mmElapsed <= 500 &&
Number.isFinite(__mmVelocityX) &&
Number.isFinite(__mmVelocityY) &&
Math.hypot(__mmVelocityX, __mmVelocityY) > 0.025
);
}
function __mmAssassinHostileTurretNearby() {
if (!v || !v.alive) return !1;
const __mmTurrets = __mmActiveObjectSnapshot().turrets,
__mmRangeSquared = __mmAssassinDangerRange * __mmAssassinDangerRange;
for (let __mmIndex = 0; __mmIndex < __mmTurrets.length; __mmIndex++) {
const __mmTurret = __mmTurrets[__mmIndex];
if (!__mmTurret || !__mmTurret.active || __mmFriendlyStructure(__mmTurret))
continue;
const __mmDx = Number(__mmTurret.x) - Number(v.x),
__mmDy = Number(__mmTurret.y) - Number(v.y);
if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmRangeSquared) return !0;
}
return !1;
}
function __mmAssassinEnemyNearby() {
if (!v || !v.alive) return !0;
const __mmEnemies = __mmLiveStateFresh() ? __mmLiveState.enemies : E,
__mmRangeSquared = __mmAssassinDangerRange * __mmAssassinDangerRange;
if (!Array.isArray(__mmEnemies)) return !1;
for (let __mmIndex = 0; __mmIndex < __mmEnemies.length; __mmIndex++) {
const __mmEnemy = __mmEnemies[__mmIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmDx = Number(__mmEnemy.x) - Number(v.x),
__mmDy = Number(__mmEnemy.y) - Number(v.y);
if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmRangeSquared) return !0;
}
return !1;
}
function __mmAssassinSafe() {
if (!v || !v.alive || !__mmAssassinStationary()) return !1;
const __mmHealth = Math.max(0, Number(v.health) || 0),
__mmMaxHealth = Math.max(1, Number(v.maxHealth) || 100),
__mmThreat = __mmCombatThreatSnapshot();
return !!(
(__mmHealth / __mmMaxHealth) * 100 >= __mmAssassinMinHealth &&
Date.now() >= __mmAssassinCooldownUntil &&
!__mmAssassinEnemyNearby() &&
!__mmAssassinHostileTurretNearby() &&
!__mmIsTrapped() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
!__mmBuildSpamTimer &&
!__mmFoodSpamTimer &&
!__mmInsta.isActive() &&
!__mmBoostInsta.isActive() &&
!__mmSyncFollowerEnabled &&
!__mmBushModeEnabled &&
!__mmCombatHatLockActive() &&
(!__mmThreat ||
(Number(__mmThreat.damage) <= 0 &&
Number(__mmThreat.potentialDamage) <= 0)) &&
["idle", "movementGear", "soldierGear", "weaponRecharge"].includes(
__mmActionOwner,
)
);
}
function __mmRestoreAssassinGear() {
const __mmRestore = __mmAssassinPreviousHat,
__mmWasAutomated = __mmAssassinConcealed || __mmRestore != null;
(__mmWasAutomated &&
(__mmAssassinCooldownUntil = Math.max(
__mmAssassinCooldownUntil,
Date.now() + __mmAssassinSafeMs,
)),
(__mmAssassinConcealed = !1),
(__mmAssassinPreviousHat = null),
(__mmAssassinSafeSince = 0));
if (
__mmWasAutomated &&
v &&
v.alive &&
(Number(v.skinIndex) === __mmAssassinGear ||
Number(__mmPendingHat) === __mmAssassinGear)
) {
const __mmHat =
__mmRestore != null &&
__mmRestore !== __mmAssassinGear &&
__mmCanEquipHat(__mmRestore)
? __mmRestore
: v.skins && v.skins[6]
? 6
: 0;
__mmEquipHatNow(__mmHat, !0);
}
}
function __mmUpdateAssassinAutomation() {
if (!__mmAssassinAutomationEnabled || document.hidden || !v || !v.alive)
return void __mmRestoreAssassinGear();
const __mmNow = Date.now();
if (!__mmAssassinSafe()) {
((__mmAssassinLastUnsafeAt = __mmNow), (__mmAssassinSafeSince = 0));
return void __mmRestoreAssassinGear();
}
__mmAssassinSafeSince || (__mmAssassinSafeSince = __mmNow);
if (__mmNow - __mmAssassinSafeSince < __mmAssassinSafeMs) return;
if (!__mmAssassinGearOwned()) {
if (
Number(v.points) >= __mmAssassinGearPrice() &&
__mmNow - __mmAssassinPurchaseAt >= 1000
)
((__mmAssassinPurchaseAt = __mmNow), Xn(__mmAssassinGear, !1));
return;
}
if (!__mmAssassinConcealed) {
const __mmPrevious = __mmInstaSafeRestoreHat(__mmBaseAutomationHat());
((__mmAssassinPreviousHat =
__mmPrevious === __mmAssassinGear
? v.skins && v.skins[6]
? 6
: 0
: __mmPrevious),
(__mmAssassinConcealed = !0),
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmRestoreMovementGear(),
__mmPauseSoldierForBreaking());
}
if (
Number(v.skinIndex) !== __mmAssassinGear ||
Number(__mmPendingHat) !== __mmAssassinGear
) {
const __mmRestoreLastNormal = __mmLastNormalHat;
(__mmEquipHatNow(__mmAssassinGear, !0),
(__mmLastNormalHat = __mmRestoreLastNormal));
}
}
function __mmStartAssassinAutomation() {
__mmEnsureOperationPipeline();
}
function __mmStopAssassinAutomation() {
(__mmAssassinTimer && clearInterval(__mmAssassinTimer),
(__mmAssassinTimer = 0),
__mmRestoreAssassinGear());
}
function __mmEmergencyGetawayActive() {
return !1;
}
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 (__mmAssassinConcealed) return;
if (v && v.alive && __mmRecoverStrayCombatHat()) return;
if (!__mmMovementGearEnabled)
return void (__mmRestoreMovementGear(),
__mmRestoreProximityTail(),
__mmClearIdleMonkeyTail());
if (!v || !v.alive)
return void (__mmRestoreMovementGear(), __mmRestoreProximityTail());
if (__mmCombatHatLockActive()) return;
if (__mmBushModeEnabled) return;
if (__mmPrimaryHeld || __mmSecondaryHeld) {
const __mmHeldWeapon = __mmHeldAttackWeapon();
__mmHeldWeapon != null && __mmUpdateHeldGear(__mmHeldWeapon);
return;
}
if (!__mmActionAvailable("movementGear")) return;
if (__mmInsta.isActive()) return;
// Existing combat actions own their hat and tail until they finish, avoiding
// tick-by-tick flicker between movement and combat gear.
if (
__mmSyncFollowerEnabled ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmTankGearActive()
)
return;
__mmInSnowBiome() && __mmBuySnowHat();
__mmRememberNormalHat();
const __mmEnemyNearby = __mmEnemyWithinCombatRange(),
__mmMoving = __mmPlayerMoving();
if (__mmEnemyNearby) {
// EMP is strictly an out-of-combat idle hat. Remove it immediately when
// the combat radius becomes occupied, even if no movement-gear snapshot
// exists to restore.
(Number(v.skinIndex) === Number(__mmEmpHelmet) ||
Number(__mmPendingHat) === Number(__mmEmpHelmet)) &&
__mmEquipHatNow(v.skins && v.skins[6] ? 6 : 0, !0);
const __mmTail =
__mmMoving && v.tails && v.tails[__mmShadowWings]
? __mmShadowWings
: !__mmMoving && v.tails && v.tails[__mmBloodWings]
? __mmBloodWings
: __mmMoving
? null
: 0;
__mmRestoreMovementGear(!0);
return __mmTail == null
? void __mmRestoreProximityTail()
: void __mmSetProximityTail(__mmTail);
}
__mmRestoreProximityTail();
if (!__mmMoving && !__mmBoostBreakHeld) {
if (!(v.skins && v.skins[__mmEmpHelmet])) {
__mmRestoreMovementGear();
if (v.tails && v.tails[__mmAngelWings])
return void __mmEquipTailNow(__mmAngelWings);
return void __mmClearIdleMonkeyTail();
}
if (!__mmMovementGearActive()) {
((__mmMovementGearPreviousHat = __mmBaseAutomationHat()),
(__mmMovementGearPreviousTail = __mmBushRestoreTail(v.tailIndex)),
__mmPauseSoldierForBreaking());
}
const __mmIdleTail =
v.tails && v.tails[__mmAngelWings]
? __mmAngelWings
: __mmMovementGearPreviousTail;
// EMP Helmet's anti-turret protection also owns the stationary safe phase.
// Its paired tail leaves in the same packet tick.
return void __mmEquipGearPair(__mmEmpHelmet, __mmIdleTail);
}
if (__mmTankGearActive()) return;
if (
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld
)
return void __mmRestoreMovementGear();
__mmInWater() && __mmBuyFlipperHat();
const __mmHat = __mmSpeedHat(),
__mmHasHat = !!(v.skins && v.skins[__mmHat]),
__mmHasTail = !!(v.tails && v.tails[11]);
if (!__mmMovementGearActive()) {
((__mmMovementGearPreviousHat = __mmBaseAutomationHat()),
(__mmMovementGearPreviousTail = __mmBushRestoreTail(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() {
(__mmEnsureOperationPipeline(), __mmUpdateMovementGear());
}
function __mmUpdatePassiveSpikeMotion() {
if (!v || !v.alive) {
__mmPassiveSpikeMotion = null;
return;
}
const __mmNow = Date.now(),
__mmPrevious = __mmPassiveSpikeMotion,
__mmElapsed = __mmPrevious
? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
: 0,
__mmSampleVelocityX = __mmElapsed
? (Number(v.x) - __mmPrevious.x) / __mmElapsed
: 0,
__mmSampleVelocityY = __mmElapsed
? (Number(v.y) - __mmPrevious.y) / __mmElapsed
: 0,
__mmVelocityX = __mmPrevious && __mmElapsed < 250
? __mmSampleVelocityX * 0.72 + __mmPrevious.velocityX * 0.28
: __mmSampleVelocityX,
__mmVelocityY = __mmPrevious && __mmElapsed < 250
? __mmSampleVelocityY * 0.72 + __mmPrevious.velocityY * 0.28
: __mmSampleVelocityY;
__mmPassiveSpikeMotion = {
x: Number(v.x) || 0,
y: Number(v.y) || 0,
at: __mmNow,
velocityX: Number.isFinite(__mmVelocityX) ? __mmVelocityX : 0,
velocityY: Number.isFinite(__mmVelocityY) ? __mmVelocityY : 0,
};
}
function __mmPassiveSpikeVelocity() {
let __mmVelocityX = Number(
__mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityX,
) || 0,
__mmVelocityY = Number(
__mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityY,
) || 0;
const __mmServerElapsed = Number(v && v.t2) - Number(v && v.t1),
__mmServerVelocityX =
(Number(v && v.x2) - Number(v && v.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(v && v.y2) - Number(v && v.y1)) / __mmServerElapsed,
__mmTrackedSpeed = Math.hypot(__mmVelocityX, __mmVelocityY),
__mmServerSpeed = Math.hypot(__mmServerVelocityX, __mmServerVelocityY);
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500 &&
__mmServerSpeed > __mmTrackedSpeed
)
((__mmVelocityX = __mmServerVelocityX),
(__mmVelocityY = __mmServerVelocityY));
return { x: __mmVelocityX, y: __mmVelocityY };
}
function __mmPassiveSpikeEnemyNearby() {
if (
!v ||
!v.alive ||
!Array.isArray(E) ||
__mmPassiveSpikeEnemyRange <= 0
)
return !1;
const __mmRangeSquared =
__mmPassiveSpikeEnemyRange * __mmPassiveSpikeEnemyRange;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
const __mmDx = __mmPlayer.x - v.x,
__mmDy = __mmPlayer.y - v.y;
if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmRangeSquared) return !0;
}
return !1;
}
function __mmPassiveSpikeThreat() {
if (!v || !v.alive) return null;
const __mmVelocity = __mmPassiveSpikeVelocity(),
__mmSpeed = Math.hypot(__mmVelocity.x, __mmVelocity.y);
if (!Number.isFinite(__mmSpeed) || __mmSpeed < 0.01) return null;
const __mmLeadMs = Math.max(
150,
Math.min(280, __mmServerTickMs() * 1.8),
),
__mmCoastDistance = Math.min(95, __mmSpeed * __mmLeadMs),
__mmEndX = v.x + (__mmVelocity.x / __mmSpeed) * __mmCoastDistance,
__mmEndY = v.y + (__mmVelocity.y / __mmSpeed) * __mmCoastDistance;
let __mmBest = null,
__mmBestDistance = Infinity;
const __mmSpikes = __mmActiveObjectSnapshot().spikes;
for (let __mmIndex = 0; __mmIndex < __mmSpikes.length; __mmIndex++) {
const __mmSpike = __mmSpikes[__mmIndex],
__mmData = __mmSpike && b && b.list && b.list[__mmSpike.id],
__mmName = String(__mmData && __mmData.name || "").toLowerCase();
if (
!__mmSpike ||
!__mmSpike.active ||
!__mmSpike.isItem ||
!__mmName.includes("spikes") ||
__mmSpikeOwnedByUsOrAlly(__mmSpike)
)
continue;
const __mmToSpikeX = __mmSpike.x - v.x,
__mmToSpikeY = __mmSpike.y - v.y,
__mmToward =
__mmToSpikeX * __mmVelocity.x +
__mmToSpikeY * __mmVelocity.y;
if (__mmToward <= 0) continue;
const __mmRadius =
(Number(v.scale) || 35) +
(Number(__mmSpike.scale) || Number(__mmData.scale) || 45) +
4,
__mmPathDistanceSquared = __mmSegmentDistanceSquared(
v.x,
v.y,
__mmEndX,
__mmEndY,
__mmSpike.x,
__mmSpike.y,
),
__mmCenterDistanceSquared =
__mmToSpikeX * __mmToSpikeX + __mmToSpikeY * __mmToSpikeY;
if (
__mmPathDistanceSquared <= __mmRadius * __mmRadius &&
__mmCenterDistanceSquared < __mmBestDistance
)
((__mmBest = __mmSpike),
(__mmBestDistance = __mmCenterDistanceSquared));
}
return __mmBest;
}
function __mmStopPassiveSpikeCorrection(__mmUserMovementTakingOver) {
(__mmPassiveSpikePendingTimer &&
clearTimeout(__mmPassiveSpikePendingTimer),
(__mmPassiveSpikePendingTimer = 0),
__mmPassiveSpikeCorrectionTimer &&
clearTimeout(__mmPassiveSpikeCorrectionTimer),
(__mmPassiveSpikeCorrectionTimer = 0));
if (!__mmPassiveSpikeCorrecting) return;
((__mmPassiveSpikeCorrecting = !1), (Kt = null));
__mmUserMovementTakingOver || Tt();
}
function __mmRunPassiveSpikeCorrection() {
__mmPassiveSpikePendingTimer = 0;
if (
!__mmPassiveSpikeAvoidanceEnabled ||
!v ||
!v.alive ||
(typeof ul === "function" && ul() != null) ||
__mmPassiveSpikeEnemyNearby() ||
__mmSyncFollowerEnabled ||
__mmBoostBackingUp ||
__mmBoostBreakHeld ||
__mmTrapAttackActive ||
__mmInsta.isActive() ||
__mmIsTrapped()
)
return;
const __mmSpike = __mmPassiveSpikeThreat();
if (!__mmSpike) return;
const __mmAway = Math.atan2(v.y - __mmSpike.y, v.x - __mmSpike.x),
__mmDuration = Math.max(75, Math.min(140, __mmServerTickMs()));
((__mmPassiveSpikeCorrecting = !0),
(Kt = __mmAway),
O.send("9", __mmAway),
(__mmPassiveSpikeCorrectionTimer = setTimeout(function () {
__mmStopPassiveSpikeCorrection(!1);
}, __mmDuration)));
}
function __mmPassiveSpikeMovementPressed() {
__mmStopPassiveSpikeCorrection(!0);
}
function __mmPassiveSpikeMovementReleased() {
if (
!__mmPassiveSpikeAvoidanceEnabled ||
(typeof ul === "function" && ul() != null)
)
return;
__mmPassiveSpikePendingTimer && clearTimeout(__mmPassiveSpikePendingTimer);
__mmPassiveSpikePendingTimer = setTimeout(__mmRunPassiveSpikeCorrection, 0);
}
function __mmStartPassiveSpikeAvoidance() {
if (!__mmPassiveSpikeAvoidanceEnabled || __mmPassiveSpikeMotionTimer) return;
(__mmUpdatePassiveSpikeMotion(),
(__mmPassiveSpikeMotionTimer = setInterval(
__mmUpdatePassiveSpikeMotion,
Math.max(8, __mmFastCheckMs()),
)));
}
function __mmStopPassiveSpikeAvoidance() {
(__mmPassiveSpikeMotionTimer && clearInterval(__mmPassiveSpikeMotionTimer),
(__mmPassiveSpikeMotionTimer = 0),
(__mmPassiveSpikeMotion = null),
__mmStopPassiveSpikeCorrection(!1));
}
function __mmAntiCollisionObjectKey(__mmObject) {
if (!__mmObject) return null;
const __mmSid =
__mmObject.sid != null
? __mmObject.sid
: __mmObject.id != null
? __mmObject.id + ":" + Math.round(Number(__mmObject.x) || 0) +
":" + Math.round(Number(__mmObject.y) || 0)
: null;
return __mmSid == null ? null : String(__mmSid);
}
function __mmAntiCollisionObjectAllowed(__mmObject) {
if (
!__mmObject ||
!__mmObject.active ||
!__mmObject.isItem ||
!b ||
!b.list
)
return !1;
const __mmData = b.list[__mmObject.id],
__mmName = String((__mmData && __mmData.name) || "").toLowerCase();
return !!(
__mmName === "teleporter" ||
(__mmName.includes("spikes") && !__mmFriendlyStructure(__mmObject))
);
}
function __mmAntiCollisionInputPointsToward(__mmObject, __mmDirection) {
if (!v || !__mmObject || !Number.isFinite(Number(__mmDirection))) return !1;
const __mmDx = Number(__mmObject.x) - Number(v.x),
__mmDy = Number(__mmObject.y) - Number(v.y);
return (
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection) >
0
);
}
function __mmAntiCollisionDecelDistance(__mmSpeed) {
// Forecast the full stopping point with MooMoo's 0.993 velocity decay
// instead of waiting for the player's current hitbox to reach an object.
// Speed is stored per millisecond, so convert one server tick to travel
// distance before applying the decay curve.
const __mmTickMs = Math.max(75, Math.min(140, __mmServerTickMs())),
__mmDecay = Math.pow(0.993, __mmTickMs);
let __mmStep = Math.max(0, Number(__mmSpeed) || 0) * __mmTickMs,
__mmDistance = __mmStep,
__mmSteps = 0;
while (__mmStep >= 0.5 && __mmSteps++ < 14) {
((__mmStep *= __mmDecay), (__mmDistance += __mmStep));
}
return Math.max(0, __mmDistance);
}
function __mmAntiCollisionThreat(__mmDirection, __mmSkipKey) {
if (!v || !v.alive || !Number.isFinite(Number(__mmDirection))) return null;
const __mmMotion = __mmPassiveSpikeVelocity(),
__mmDirectionX = Math.cos(__mmDirection),
__mmDirectionY = Math.sin(__mmDirection),
__mmMeasuredX = Number(__mmMotion && __mmMotion.x) || 0,
__mmMeasuredY = Number(__mmMotion && __mmMotion.y) || 0,
__mmMeasuredSpeed = Math.min(0.65, Math.hypot(__mmMeasuredX, __mmMeasuredY)),
__mmMeasuredForward = Math.max(
0,
__mmMeasuredX * __mmDirectionX + __mmMeasuredY * __mmDirectionY,
),
// Include a just-pressed movement key even before the first position
// packet exposes velocity.
__mmInputSpeed = Math.max(0.19, __mmMeasuredSpeed, __mmMeasuredForward),
__mmMeasuredDecel = __mmAntiCollisionDecelDistance(__mmMeasuredForward),
__mmInputDecel = __mmAntiCollisionDecelDistance(__mmInputSpeed),
__mmPing = Number(window.pingTime),
__mmReactionMs = Math.max(
8,
Math.min(
38,
__mmFastCheckMs() +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing) * 0.1 : 0),
),
),
__mmReactionDistance = __mmInputSpeed * __mmReactionMs,
__mmBrakingDistance =
Math.max(__mmMeasuredDecel, __mmInputDecel) + __mmReactionDistance,
__mmEndX = Number(v.x) + __mmDirectionX * __mmBrakingDistance,
__mmEndY = Number(v.y) + __mmDirectionY * __mmBrakingDistance,
__mmRange = Math.max(120, Number(__mmAntiCollisionRange) || 260),
__mmCombatPaused = __mmAntiCollisionCombatPaused(),
__mmObjects = __mmActiveObjectSnapshot().all;
let __mmBest = null,
__mmBestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex],
__mmKey = __mmAntiCollisionObjectKey(__mmObject),
__mmData = __mmObject && b && b.list && b.list[__mmObject.id],
__mmName = String((__mmData && __mmData.name) || "")
.trim()
.toLowerCase(),
__mmTeleporter = __mmName === "teleporter";
if (
!__mmAntiCollisionObjectAllowed(__mmObject) ||
// Teleporters are always guarded. Only hostile spikes participate in
// the combat auto-pause, matching the requested safe-gathering behavior.
(!__mmTeleporter && __mmCombatPaused) ||
(__mmSkipKey != null && __mmKey === __mmSkipKey)
)
continue;
const __mmDx = Number(__mmObject.x) - Number(v.x),
__mmDy = Number(__mmObject.y) - Number(v.y),
__mmCenterDistanceSquared = __mmDx * __mmDx + __mmDy * __mmDy,
__mmCenterDistance = Math.sqrt(__mmCenterDistanceSquared),
__mmRawScale = Math.max(
1,
Number(__mmObject.scale) ||
Number(__mmData && __mmData.scale) ||
__mmCleanupObjectScale(__mmObject),
),
// Use a slightly smaller TP boundary so the player can approach closely,
// while hostile damaging spikes keep their full scale.
__mmObjectScale = __mmTeleporter
? __mmRawScale * 0.75
: Math.max(__mmRawScale, __mmCleanupObjectScale(__mmObject)),
__mmCollisionRadius =
(Number(v.scale) || 35) + __mmObjectScale,
__mmCloseRadius = __mmRange + __mmCollisionRadius,
__mmToward = __mmDx * __mmDirectionX + __mmDy * __mmDirectionY,
__mmClosingSpeed = Math.max(0, __mmMeasuredForward, __mmInputSpeed),
__mmBaseGap = __mmTeleporter ? 1.5 : 3,
__mmStopGap = Math.max(
__mmBaseGap,
Math.min(
__mmRange,
__mmBaseGap + __mmBrakingDistance,
),
),
__mmCurrentGap = __mmCenterDistance - __mmCollisionRadius;
if (
__mmCenterDistanceSquared > __mmCloseRadius * __mmCloseRadius ||
__mmCurrentGap > __mmStopGap ||
__mmToward <= 0 ||
!__mmAntiCollisionInputPointsToward(__mmObject, __mmDirection)
)
continue;
const __mmPathDistanceSquared = __mmSegmentDistanceSquared(
Number(v.x),
Number(v.y),
__mmEndX,
__mmEndY,
Number(__mmObject.x),
Number(__mmObject.y),
),
__mmEndDx = __mmEndX - Number(__mmObject.x),
__mmEndDy = __mmEndY - Number(__mmObject.y),
__mmEndDistanceSquared = __mmEndDx * __mmEndDx + __mmEndDy * __mmEndDy,
__mmPredictedIntersection =
__mmEndDistanceSquared <=
(__mmCollisionRadius + __mmBaseGap) *
(__mmCollisionRadius + __mmBaseGap) ||
__mmPathDistanceSquared <=
__mmCollisionRadius * __mmCollisionRadius;
if (
__mmPredictedIntersection &&
__mmCenterDistanceSquared < __mmBestDistance
)
((__mmBest = {
object: __mmObject,
key: __mmKey,
scale: __mmObjectScale,
gap: __mmCurrentGap,
stopGap: __mmStopGap,
closingSpeed: __mmClosingSpeed,
brakingDistance: __mmBrakingDistance,
teleporter: __mmTeleporter,
}),
(__mmBestDistance = __mmCenterDistanceSquared));
}
return __mmBest;
}
function __mmAntiCollisionShowStop(__mmThreat) {
if (!__mmThreat || !__mmThreat.object) return;
const __mmNow = Date.now();
if (
__mmAntiCollisionLastPopupKey === __mmThreat.key &&
__mmNow - __mmAntiCollisionLastPopupAt < 550
)
return;
((__mmAntiCollisionLastPopupKey = __mmThreat.key),
(__mmAntiCollisionLastPopupAt = __mmNow),
__mmAntiCollisionPopups.push({
x: Number(__mmThreat.object.x) || 0,
y: Number(__mmThreat.object.y) || 0,
scale: Math.max(20, Number(__mmThreat.scale) || 45),
startedAt: performance.now(),
}));
__mmAntiCollisionPopups.length > 5 && __mmAntiCollisionPopups.shift();
}
function __mmAntiCollisionCombatPaused() {
return !!(
__mmAntiCollisionPauseCombatEnabled &&
typeof __mmSyncLocalCombatActive === "function" &&
__mmSyncLocalCombatActive()
);
}
function __mmAntiCollisionReleaseBlock(__mmResumeMovement) {
if (!__mmAntiCollisionBlocked) return;
((__mmAntiCollisionBlocked = !1),
(__mmAntiCollisionBlockedObject = null),
(__mmAntiCollisionBlockedKey = null),
(Kt = null));
__mmResumeMovement && v && v.alive && Tt();
}
function __mmAntiCollisionQuickRightClick(__mmThreat) {
if (
!__mmThreat ||
!__mmThreat.object ||
!v ||
!v.alive ||
__mmAntiCollisionRightClickTimer ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmInsta.isActive()
)
return;
const __mmObject = __mmThreat.object,
__mmData = b && b.list && b.list[__mmObject.id],
__mmName = String((__mmData && __mmData.name) || "")
.trim()
.toLowerCase();
if (__mmName !== "teleporter") return;
if (
__mmActionOwner !== "idle" &&
__mmActionOwner !== "movementGear" &&
__mmActionOwner !== "soldierGear" &&
__mmActionOwner !== "weaponRecharge"
)
return;
const __mmWeapon = __mmRightClickWeapon();
if (__mmWeapon == null) return;
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmActionClaim("manualAttack", "teleporter guard quick right click"))
return;
const __mmTool = __mmSelectedTool(),
__mmUseTank = !!(
__mmTankRightClickEnabled &&
v.skins &&
v.skins[40]
),
__mmAngle = Math.atan2(
Number(__mmObject.y) - Number(v.y),
Number(__mmObject.x) - Number(v.x),
);
(__mmUseTank && __mmActivateCombatHat(40),
je(__mmWeapon, !0),
O.send("D", __mmAngle),
__mmSendWeaponAttack(1),
(__mmAntiCollisionRightClickTimer = setTimeout(function () {
__mmAntiCollisionRightClickTimer = 0;
if (v && v.alive) {
(__mmSendWeaponAttack(0),
__mmRestoreTool(__mmTool),
__mmResumeHeldAttack());
}
(__mmActionRelease("manualAttack", "teleporter quick click complete"),
__mmScheduleMouseAimReturn());
}, Math.max(12, __mmFastCheckMs()))));
}
function __mmAntiCollisionStop(__mmThreat) {
if (!__mmThreat || !__mmThreat.object) return;
const __mmNewStop =
!__mmAntiCollisionBlocked ||
__mmAntiCollisionBlockedKey !== __mmThreat.key;
((__mmAntiCollisionBlocked = !0),
(__mmAntiCollisionBlockedObject = __mmThreat.object),
(__mmAntiCollisionBlockedKey = __mmThreat.key),
(Kt = null),
O.send("9", null));
__mmNewStop &&
(__mmAntiCollisionShowStop(__mmThreat),
__mmAntiCollisionQuickRightClick(__mmThreat));
}
function __mmUpdateAntiCollision() {
__mmUpdatePassiveSpikeMotion();
if (!v || !v.alive) {
__mmAntiCollisionBlocked && __mmAntiCollisionReleaseBlock(!1);
return;
}
const __mmDirection = typeof ul === "function" ? ul() : null,
__mmCanGuard = !!(
__mmAntiCollisionEnabled &&
!document.hidden
);
if (!__mmCanGuard) {
__mmAntiCollisionBlocked && __mmAntiCollisionReleaseBlock(__mmDirection != null);
return;
}
const __mmNow = Date.now();
if (
__mmAntiCollisionBypassArmedKey != null &&
__mmNow >= __mmAntiCollisionBypassArmedUntil
)
((__mmAntiCollisionBypassArmedKey = null),
(__mmAntiCollisionBypassArmedUntil = 0));
if (!Number.isFinite(Number(__mmDirection))) return;
if (__mmAntiCollisionBlocked) {
const __mmBlockedData =
__mmAntiCollisionBlockedObject &&
b &&
b.list &&
b.list[__mmAntiCollisionBlockedObject.id],
__mmBlockedIsTeleporter =
String((__mmBlockedData && __mmBlockedData.name) || "")
.trim()
.toLowerCase() === "teleporter",
__mmReleaseForCombat =
!__mmBlockedIsTeleporter && __mmAntiCollisionCombatPaused();
if (
__mmReleaseForCombat ||
!__mmAntiCollisionBlockedObject ||
!__mmAntiCollisionBlockedObject.active ||
!__mmAntiCollisionInputPointsToward(
__mmAntiCollisionBlockedObject,
__mmDirection,
)
)
__mmAntiCollisionReleaseBlock(!0);
else {
Kt !== null && ((Kt = null), O.send("9", null));
return;
}
}
let __mmThreat = __mmAntiCollisionThreat(
__mmDirection,
__mmAntiCollisionBypassActiveKey,
);
if (
__mmThreat &&
__mmAntiCollisionBypassArmedKey != null &&
__mmThreat.key === __mmAntiCollisionBypassArmedKey
) {
((__mmAntiCollisionBypassActiveKey = __mmThreat.key),
(__mmAntiCollisionBypassArmedKey = null),
(__mmAntiCollisionBypassArmedUntil = 0));
__mmThreat = __mmAntiCollisionThreat(
__mmDirection,
__mmAntiCollisionBypassActiveKey,
);
}
__mmThreat && __mmAntiCollisionStop(__mmThreat);
}
function __mmAntiCollisionMovementPressed(__mmKey) {
__mmSyncManualMovementPressed(__mmKey);
__mmUpdateAntiCollision();
Tt();
}
function __mmAntiCollisionMovementReleased() {
const __mmDirection = typeof ul === "function" ? ul() : null;
if (__mmDirection == null) {
if (__mmAntiCollisionBlocked && __mmAntiCollisionBlockedKey != null) {
((__mmAntiCollisionBypassArmedKey = __mmAntiCollisionBlockedKey),
(__mmAntiCollisionBypassArmedUntil = Date.now() + 3000));
}
(__mmAntiCollisionReleaseBlock(!1),
(__mmAntiCollisionBypassActiveKey = null));
} else {
__mmUpdateAntiCollision();
}
Tt();
}
function __mmStartAntiCollision() {
(__mmUpdatePassiveSpikeMotion(),
__mmEnsureOperationPipeline(),
__mmUpdateAntiCollision());
}
function __mmStopAntiCollision() {
(__mmAntiCollisionTimer && clearInterval(__mmAntiCollisionTimer),
(__mmAntiCollisionTimer = 0),
(__mmAntiCollisionBypassArmedKey = null),
(__mmAntiCollisionBypassArmedUntil = 0),
(__mmAntiCollisionBypassActiveKey = null),
(__mmAntiCollisionPopups.length = 0),
__mmAntiCollisionReleaseBlock(!0));
}
const __mmOriginalMovementUpdate = Tt;
Tt = function () {
if (__mmAntiCollisionBlocked) {
Kt !== null && ((Kt = null), O.send("9", null));
return;
}
return __mmOriginalMovementUpdate.apply(this, arguments);
};
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 __mmIsSandboxServer() {
const __mmHost =
typeof location !== "undefined"
? String(location.hostname || "").toLowerCase()
: "";
return __mmHost === "sandbox.moomoo.io" || !!(y && y.inSandbox);
}
function __mmIsMillBuildData(__mmData) {
return !!(
__mmData && /mill/i.test(String(__mmData.name || ""))
);
}
function __mmBuildGroupLimit(__mmData) {
const __mmGroup = __mmData && __mmData.group;
if (!__mmGroup) return 0;
const __mmNormalLimit = Number(__mmGroup.limit) || 0;
if (!__mmIsSandboxServer()) return __mmNormalLimit;
// sandbox.moomoo.io permits 299 mills in the shared mill group. The stock
// client metadata/canBuild path can still expose the normal seven-mill cap,
// so use the server's real limit for mills while retaining the published
// sandbox limit/fallback behavior for every other placeable group.
if (__mmIsMillBuildData(__mmData)) return 299;
const __mmSandboxLimit = Number(__mmGroup.sandboxLimit) || 0;
return __mmSandboxLimit || Math.max(__mmNormalLimit * 3, 99);
}
function __mmCanUseBuildItem(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
if (!v || !__mmData || !Array.isArray(__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;
// MooMoo's own canBuild also enforces the active group limit. Use this check
// before every place call; relying on material costs alone made
// Kitty repeatedly select a full spike/trap group and send a rejected hit.
// The stock sandbox client may keep enforcing the normal seven-mill limit.
// Material costs were checked above and Kitty's group counter enforces 299,
// so only bypass that stale native limit for mills on the sandbox hostname.
if (
!(__mmIsSandboxServer() && __mmIsMillBuildData(__mmData)) &&
typeof v.canBuild === "function"
)
try {
if (!v.canBuild(__mmData)) return !1;
} catch (__mmCanBuildError) {}
return !0;
}
function __mmSendAutomaticPlacement(
__mmItem,
__mmAngle,
__mmOriginalTool,
__mmReservedSlot,
) {
if (
!v ||
!v.alive ||
__mmItem == null ||
!Number.isFinite(Number(__mmAngle)) ||
!__mmCanUseBuildItem(__mmItem) ||
(!__mmReservedSlot && __mmMaxBuildCount(__mmItem) < 1)
)
return !1;
const __mmRestore = __mmOriginalTool || __mmSelectedTool();
try {
(je(__mmItem), O.send("F", 1, __mmAngle));
// End a build by selecting the weapon rather than injecting an
// F=0 between place and restore. Preserve a manually selected build item
// with the explicit release path because it has no weapon-select edge.
__mmRestore && __mmRestore.weapon
? __mmRestoreTool(__mmRestore)
: (O.send("F", 0, __mmAngle),
__mmRestore && __mmRestoreTool(__mmRestore));
(__mmResumeHeldAttack(), __mmScheduleMouseAimReturn());
return !0;
} catch (__mmAutomaticPlacementError) {
try {
(O.send("F", 0, __mmAngle),
__mmRestore && __mmRestoreTool(__mmRestore),
__mmResumeHeldAttack(),
__mmScheduleMouseAimReturn());
} catch (__mmAutomaticPlacementRestoreError) {}
return !1;
}
}
function __mmThreatTrapItem() {
if (!v || !v.items || !b || !b.list) return null;
if (__mmThreatTrapEnabled)
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmItem = v.items[__mmItemIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
__mmData.trap &&
__mmCanUseBuildItem(__mmItem) &&
__mmMaxBuildCount(__mmItem) > 0
)
return __mmItem;
}
// A usable pit trap always wins. The animal-defense toggle owns its spike
// fallback too, while Mc Grabby and emergency getaway continue suppressing
// automatic spikes.
if (
!__mmThreatTrapEnabled ||
__mmHoldingMcGrabby() ||
__mmEmergencyGetawayActive()
)
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.toLowerCase().includes("spikes") &&
__mmCanUseBuildItem(__mmItem) &&
__mmMaxBuildCount(__mmItem) > 0
)
return __mmItem;
}
return null;
}
function __mmPassiveMobTrapItem() {
if (!__mmPassiveMobTrapEnabled || !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) &&
__mmMaxBuildCount(__mmItem) > 0
)
return __mmItem;
}
return null;
}
function __mmThreatTeleporterItem() {
if (!v || !v.items || !b || !b.list) return null;
for (let __mmItemIndex = 0; __mmItemIndex < v.items.length; __mmItemIndex++) {
const __mmItem = v.items[__mmItemIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
String(__mmData.name || "").toLowerCase() === "teleporter" &&
__mmCanUseBuildItem(__mmItem) &&
__mmMaxBuildCount(__mmItem) > 0
)
return __mmItem;
}
return null;
}
function __mmAntiTrollPredictedPlayer(__mmPlayer, __mmNow) {
const __mmSid = String(__mmPlayer.sid),
__mmX = Number(__mmPlayer.x),
__mmY = Number(__mmPlayer.y);
let __mmState = __mmAntiTrollMotion[__mmSid];
if (!__mmState)
__mmState = __mmAntiTrollMotion[__mmSid] = {
x: __mmX,
y: __mmY,
at: __mmNow,
vx: 0,
vy: 0,
};
else if (__mmState.x !== __mmX || __mmState.y !== __mmY) {
const __mmElapsed = Math.max(1, __mmNow - __mmState.at);
((__mmState.vx = (__mmX - __mmState.x) / __mmElapsed),
(__mmState.vy = (__mmY - __mmState.y) / __mmElapsed),
(__mmState.x = __mmX),
(__mmState.y = __mmY),
(__mmState.at = __mmNow));
}
const __mmHorizon = Math.min(110, __mmServerTickMs());
return {
x: __mmX + __mmState.vx * __mmHorizon,
y: __mmY + __mmState.vy * __mmHorizon,
};
}
function __mmAntiTrollPlacement(
__mmPlacer,
__mmItem,
__mmAngle,
__mmOrigin,
) {
const __mmData = b && b.list && b.list[__mmItem];
if (!__mmPlacer || !__mmData || !Number.isFinite(__mmAngle)) return null;
const __mmScale = Number(__mmData.scale) || 45,
__mmDistance =
(Number(__mmPlacer.scale) || 35) +
__mmScale +
(Number(__mmData.placeOffset) || 0),
__mmX = Number(__mmOrigin && __mmOrigin.x),
__mmY = Number(__mmOrigin && __mmOrigin.y);
if (!Number.isFinite(__mmX) || !Number.isFinite(__mmY)) return null;
return {
x: __mmX + Math.cos(__mmAngle) * __mmDistance,
y: __mmY + Math.sin(__mmAngle) * __mmDistance,
angle: __mmAngle,
scale: __mmScale,
item: __mmItem,
};
}
function __mmAntiTrollPositionClear(__mmPlacement, __mmPlacer) {
if (!__mmPlacement || !y) return !1;
const __mmScale = __mmPlacement.scale,
__mmX = __mmPlacement.x,
__mmY = __mmPlacement.y;
if (
__mmX - __mmScale < 0 ||
__mmY - __mmScale < 0 ||
__mmX + __mmScale > Number(y.mapScale) ||
__mmY + __mmScale > Number(y.mapScale) ||
(__mmPlacement.item !== 18 &&
__mmY >= y.mapScale / 2 - y.riverWidth / 2 &&
__mmY <= y.mapScale / 2 + y.riverWidth / 2)
)
return !1;
if (X && typeof X.checkItemLocation === "function")
try {
return !!X.checkItemLocation(
__mmX,
__mmY,
__mmScale,
0.6,
__mmPlacement.item,
!1,
__mmPlacer,
ge,
);
} catch (__mmAntiTrollLocationError) {}
const __mmObjects = __mmActiveObjectSnapshot().all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (!__mmObject || !__mmObject.active) continue;
const __mmBlockScale = Number(__mmObject.blocker) ||
(typeof __mmObject.getScale === "function"
? Number(__mmObject.getScale(0.6, __mmObject.isItem))
: Number(__mmObject.scale)) || 35;
if (
Math.hypot(
Number(__mmObject.x) - __mmX,
Number(__mmObject.y) - __mmY,
) <
__mmScale + __mmBlockScale
)
return !1;
}
return !0;
}
function __mmAntiTrollThreat() {
if (!v || !v.alive || !Array.isArray(E)) return null;
const __mmNow = Date.now();
let __mmBest = null,
__mmBestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex],
__mmBuild = Number(__mmPlayer && __mmPlayer.buildIndex),
__mmData = b && b.list && b.list[__mmBuild];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
__mmPlayer === v ||
!__mmSameTeam(__mmPlayer) ||
!__mmData ||
String(__mmData.name || "").trim().toLowerCase() !== "teleporter" ||
!Number.isFinite(Number(__mmPlayer.dir))
)
continue;
const __mmDistance = Math.hypot(
Number(__mmPlayer.x) - Number(v.x),
Number(__mmPlayer.y) - Number(v.y),
);
if (__mmDistance > 190 || __mmDistance >= __mmBestDistance) continue;
const __mmPredicted = __mmAntiTrollPredictedPlayer(__mmPlayer, __mmNow),
__mmTheirPlacement = __mmAntiTrollPlacement(
__mmPlayer,
__mmBuild,
Number(__mmPlayer.dir),
__mmPredicted,
),
__mmHitboxRange =
(Number(v.scale) || 35) +
(Number(__mmTheirPlacement && __mmTheirPlacement.scale) || 45) * 0.55;
if (
!__mmTheirPlacement ||
Math.hypot(
__mmTheirPlacement.x - Number(v.x),
__mmTheirPlacement.y - Number(v.y),
) > __mmHitboxRange ||
!__mmAntiTrollPositionClear(__mmTheirPlacement, __mmPlayer)
)
continue;
((__mmBest = {
player: __mmPlayer,
predicted: __mmPredicted,
}),
(__mmBestDistance = __mmDistance));
}
return __mmBest;
}
function __mmAntiTrollCounterPlan(__mmThreat) {
const __mmItem = __mmThreatTeleporterItem(),
__mmData = __mmItem == null ? null : b && b.list && b.list[__mmItem],
__mmLimit = __mmBuildGroupLimit(__mmData),
__mmPlaced =
__mmData && __mmData.group
? Number(v.itemCounts && v.itemCounts[__mmData.group.id]) || 0
: 0;
if (
!__mmThreat ||
__mmItem == null ||
!__mmCanUseBuildItem(__mmItem) ||
__mmMaxBuildCount(__mmItem) < 1 ||
(__mmLimit && __mmPlaced >= __mmLimit)
)
return null;
const __mmAngle = Math.atan2(
__mmThreat.predicted.y - Number(v.y),
__mmThreat.predicted.x - Number(v.x),
),
__mmPlacement = __mmAntiTrollPlacement(
v,
__mmItem,
__mmAngle,
{ x: v.x, y: v.y },
),
__mmTouchRange =
(Number(__mmThreat.player.scale) || 35) +
(Number(__mmPlacement && __mmPlacement.scale) || 45) * 0.55;
if (
!__mmPlacement ||
Math.hypot(
__mmPlacement.x - __mmThreat.predicted.x,
__mmPlacement.y - __mmThreat.predicted.y,
) > __mmTouchRange ||
!__mmAntiTrollPositionClear(__mmPlacement, v)
)
return null;
return __mmPlacement;
}
function __mmUpdateAntiTroll() {
if (
!__mmAntiTrollEnabled ||
document.hidden ||
!v ||
!v.alive ||
v.lockMove ||
__mmIsTrapped() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer
)
return;
const __mmThreat = __mmAntiTrollThreat();
if (!__mmThreat) {
__mmAntiTrollLatchedSid = null;
return;
}
const __mmSid = String(__mmThreat.player.sid);
if (
__mmAntiTrollLatchedSid === __mmSid ||
Date.now() - __mmAntiTrollLastAt < __mmServerTickMs()
)
return;
const __mmPlan = __mmAntiTrollCounterPlan(__mmThreat);
if (!__mmPlan) return;
(__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmActionOwner === "instaSync" && __mmStopInstaSync(),
__mmActionOwner === "matThief" &&
__mmFinishMatThief("anti troll"),
__mmActionOwner === "mobSteal" &&
__mmFinishMobSteal("anti troll"));
if (!__mmActionClaim("antiTroll", "teammate teleporter counter")) return;
const __mmTool = __mmSelectedTool();
try {
if (!__mmSendAutomaticPlacement(__mmPlan.item, __mmPlan.angle, __mmTool))
return;
(
(__mmAntiTrollLastAt = Date.now()),
(__mmAntiTrollLatchedSid = __mmSid),
__mmScheduleMouseAimReturn());
} finally {
(__mmTool != null && __mmRestoreTool(__mmTool),
__mmResumeHeldAttack(),
__mmActionRelease("antiTroll", "counter placed"));
}
}
function __mmStartAntiTroll() {
(__mmEnsureOperationPipeline(), __mmUpdateAntiTroll());
}
function __mmStopAntiTroll() {
(__mmAntiTrollTimer && clearInterval(__mmAntiTrollTimer),
(__mmAntiTrollTimer = 0),
(__mmAntiTrollLatchedSid = null));
for (const __mmSid in __mmAntiTrollMotion)
delete __mmAntiTrollMotion[__mmSid];
__mmActionRelease("antiTroll", "disabled");
}
function __mmThreatTrapAnimalName(__mmAnimal) {
return String((__mmAnimal && __mmAnimal.name) || "").trim().toLowerCase();
}
function __mmThreatAnimalIsWolf(__mmAnimal) {
return __mmThreatTrapAnimalName(__mmAnimal) === "wolf";
}
function __mmThreatItemIsPitTrap(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
return !!(__mmData && __mmData.trap);
}
function __mmThreatTeleporterAnimalAllowed(__mmAnimal) {
const __mmName = __mmThreatTrapAnimalName(__mmAnimal);
return !!(
__mmAnimal &&
__mmAnimal.active &&
__mmAnimal.alive &&
__mmAnimal.visible &&
(__mmName === "moostafa" || __mmName === "moofie")
);
}
function __mmThreatTrapAnimalAllowed(__mmAnimal) {
if (
!__mmAnimal ||
!__mmAnimal.active ||
!__mmAnimal.alive ||
!__mmAnimal.visible ||
!__mmAnimal.hostile
)
return !1;
const __mmName = __mmThreatTrapAnimalName(__mmAnimal);
return __mmName !== "moostafa" && __mmName !== "moofie";
}
function __mmPassiveMobTrapAnimalAllowed(__mmAnimal) {
if (
!__mmAnimal ||
!__mmAnimal.active ||
!__mmAnimal.alive ||
!__mmAnimal.visible ||
__mmAnimal.hostile
)
return !1;
const __mmName = __mmThreatTrapAnimalName(__mmAnimal);
return __mmName !== "moostafa" && __mmName !== "moofie";
}
function __mmPassiveMobTrapPrediction(__mmAnimal) {
const __mmX = Number(__mmAnimal && __mmAnimal.x),
__mmY = Number(__mmAnimal && __mmAnimal.y),
__mmElapsed = Number(__mmAnimal && __mmAnimal.t2) -
Number(__mmAnimal && __mmAnimal.t1),
__mmVelocityX =
(Number(__mmAnimal && __mmAnimal.x2) -
Number(__mmAnimal && __mmAnimal.x1)) /
__mmElapsed,
__mmVelocityY =
(Number(__mmAnimal && __mmAnimal.y2) -
Number(__mmAnimal && __mmAnimal.y1)) /
__mmElapsed,
__mmPing = Number(window.pingTime),
__mmLead = Math.min(
150,
__mmServerTickMs() +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing) * 0.5 : 0),
),
__mmUseVelocity = !!(
Number.isFinite(__mmVelocityX) &&
Number.isFinite(__mmVelocityY) &&
__mmElapsed > 0 &&
__mmElapsed <= 500
),
__mmLeadX = __mmUseVelocity ? __mmVelocityX * __mmLead : 0,
__mmLeadY = __mmUseVelocity ? __mmVelocityY * __mmLead : 0,
__mmLeadDistance = Math.hypot(__mmLeadX, __mmLeadY),
__mmScale = __mmLeadDistance > 24 ? 24 / __mmLeadDistance : 1;
return {
x: __mmX + __mmLeadX * __mmScale,
y: __mmY + __mmLeadY * __mmScale,
};
}
function __mmThreatTargetKey(__mmTarget) {
if (!__mmTarget) return null;
const __mmId =
__mmTarget.sid != null
? __mmTarget.sid
: __mmTarget.id != null
? __mmTarget.id
: __mmTarget.index != null
? __mmTarget.index
: null;
return __mmId == null ? null : String(__mmId);
}
function __mmRememberThreatTrap(__mmTarget, __mmItem, __mmAngle) {
const __mmKey = __mmThreatTargetKey(__mmTarget),
__mmData = b && b.list && b.list[__mmItem];
if (!__mmKey || !__mmData || !__mmData.trap || !v) return;
const __mmPlaceDistance =
(Number(v.scale) || 35) +
(Number(__mmData.scale) || 50) +
(Number(__mmData.placeOffset) || 0),
__mmCollisionScale = Math.max(
10,
(Number(__mmData.scale) || 50) * (Number(__mmData.colDiv) || 1),
);
__mmThreatTrapPlacements[__mmKey] = {
x: v.x + Math.cos(__mmAngle) * __mmPlaceDistance,
y: v.y + Math.sin(__mmAngle) * __mmPlaceDistance,
scale: __mmCollisionScale,
// Keep only a brief acknowledgement bridge; never retain a stale target
// position after a death or despawn.
expiresAt: Date.now() + 2500,
};
}
function __mmThreatAlreadyTrapped(__mmTarget) {
if (
!__mmTarget ||
!Number.isFinite(Number(__mmTarget.x)) ||
!Number.isFinite(Number(__mmTarget.y))
)
return !1;
const __mmKey = __mmThreatTargetKey(__mmTarget),
__mmPending = __mmKey && __mmThreatTrapPlacements[__mmKey];
if (__mmPending) {
if (Date.now() < Number(__mmPending.expiresAt)) return !0;
delete __mmThreatTrapPlacements[__mmKey];
}
const __mmTraps = __mmActiveTrapObjects();
for (let __mmIndex = __mmTraps.length - 1; __mmIndex >= 0; __mmIndex--) {
const __mmTrap = __mmTraps[__mmIndex];
if (
__mmTrap &&
__mmTrap.active &&
__mmTrap.trap &&
__mmSpikeHostileToEnemy(__mmTrap, __mmTarget) &&
__mmServerTrapContact(__mmTarget, __mmTrap)
)
return !0;
}
return !1;
}
function __mmThreatTrapTarget(__mmTrap, __mmTeleporter, __mmPassiveTrap) {
if (!v || !v.alive) return null;
const __mmAnimals = __mmLiveStateFresh() ? __mmLiveState.animals : N;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmConsider = function (
__mmTarget,
__mmType,
__mmItem,
__mmRange,
__mmAimPoint,
) {
if (
!__mmTarget ||
__mmThreatAlreadyTrapped(__mmTarget) ||
!Number.isFinite(Number(__mmTarget.x)) ||
!Number.isFinite(Number(__mmTarget.y))
)
return;
const __mmDistance = Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y);
if (__mmDistance > __mmRange || __mmDistance >= __mmClosestDistance)
return;
const __mmId =
__mmTarget.sid != null
? __mmTarget.sid
: __mmTarget.id != null
? __mmTarget.id
: __mmTarget.index != null
? __mmTarget.index
: Math.round(__mmTarget.x) + ":" + Math.round(__mmTarget.y);
((__mmClosest = {
target: __mmTarget,
key: __mmType + ":" + __mmId,
item: __mmItem,
distance: __mmDistance,
aimX:
__mmAimPoint && Number.isFinite(Number(__mmAimPoint.x))
? Number(__mmAimPoint.x)
: Number(__mmTarget.x),
aimY:
__mmAimPoint && Number.isFinite(Number(__mmAimPoint.y))
? Number(__mmAimPoint.y)
: Number(__mmTarget.y),
}),
(__mmClosestDistance = __mmDistance));
};
if (Array.isArray(__mmAnimals))
for (let __mmIndex = 0; __mmIndex < __mmAnimals.length; __mmIndex++) {
const __mmAnimal = __mmAnimals[__mmIndex];
__mmTrap != null &&
__mmThreatTrapAnimalAllowed(__mmAnimal) &&
// Wolves are easy melee kills and flee after spike damage. They are
// still trapped normally whenever the chosen item is a real pit trap.
(!__mmThreatAnimalIsWolf(__mmAnimal) ||
__mmThreatItemIsPitTrap(__mmTrap)) &&
__mmConsider(
__mmAnimal,
"animal",
__mmTrap,
__mmThreatAnimalRange,
);
__mmTeleporter != null &&
__mmThreatTeleporterAnimalAllowed(__mmAnimal) &&
__mmConsider(
__mmAnimal,
"teleporter",
__mmTeleporter,
__mmThreatAnimalRange,
);
}
// Passive trapping is opportunistic. Never let a neutral mob steal this
// placement phase from hostile-animal defense or a boss Teleporter.
if (!__mmClosest && __mmPassiveTrap != null && Array.isArray(__mmAnimals))
for (let __mmIndex = 0; __mmIndex < __mmAnimals.length; __mmIndex++) {
const __mmAnimal = __mmAnimals[__mmIndex];
if (!__mmPassiveMobTrapAnimalAllowed(__mmAnimal)) continue;
__mmConsider(
__mmAnimal,
"passive-animal",
__mmPassiveTrap,
__mmPassiveMobTrapRange,
__mmPassiveMobTrapPrediction(__mmAnimal),
);
}
return __mmClosest;
}
function __mmPlaceThreatTrap() {
if (
(!__mmThreatTrapEnabled &&
!__mmPassiveMobTrapEnabled &&
!__mmBossTeleporterEnabled) ||
!v ||
!v.alive ||
v.lockMove ||
__mmInsta.isActive() ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer
)
return !1;
const __mmTrap = __mmThreatTrapItem(),
__mmPassiveTrap = __mmPassiveMobTrapItem(),
__mmTeleporter = __mmBossTeleporterEnabled
? __mmThreatTeleporterItem()
: null,
__mmThreat = __mmThreatTrapTarget(
__mmTrap,
__mmTeleporter,
__mmPassiveTrap,
),
__mmNow = Date.now();
if (
!__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 defensive item between us.
const __mmAngle = Math.atan2(
__mmThreat.aimY - v.y,
__mmThreat.aimX - v.x,
),
__mmPlacement = __mmSmartNearestLegalCandidate(
__mmThreat.item,
__mmAngle,
0.72,
0.04,
),
__mmTool = __mmSelectedTool();
if (!__mmPlacement) return !1;
const __mmPlacementAngle = __mmPlacement.angle;
((__mmPlacement.points = 10),
(__mmPlacement.priority = !0),
__mmSmartSetPlacementPreview(
[__mmPlacement],
[__mmPlacement],
__mmThreat.key.startsWith("teleporter:")
? "boss teleporter"
: __mmThreat.key.startsWith("passive-animal:")
? "passive mob trap"
: "animal trap",
));
// Only take action ownership after a real, non-cooled-down threat and a
// currently legal build position both exist.
if (
!__mmActionClaim(
"threatTrap",
__mmThreat.key.startsWith("passive-animal:")
? "nearby passive mob"
: "nearby hostile animal",
)
)
return !1;
try {
if (
!__mmSendAutomaticPlacement(
__mmThreat.item,
__mmPlacementAngle,
__mmTool,
)
)
throw new Error("automatic placement rejected locally");
(
__mmRememberThreatTrap(
__mmThreat.target,
__mmThreat.item,
__mmPlacementAngle,
),
(__mmThreatTrapLastAt = __mmNow),
(__mmThreatTrapLastKey = __mmThreat.key),
__mmActionRelease("threatTrap", "placed"));
return !0;
} catch (__mmThreatTrapError) {
return (
__mmRestoreTool(__mmTool),
__mmResumeHeldAttack(),
__mmActionRelease("threatTrap", "placement failed"),
!1
);
}
}
function __mmStartThreatTrap() {
__mmEnsureOperationPipeline();
}
function __mmStopThreatTrapLoop() {
(__mmThreatTrapTimer && clearInterval(__mmThreatTrapTimer),
(__mmThreatTrapTimer = 0));
}
function __mmNearestEnemy() {
if (!v || !v.alive) return null;
if (__mmLiveStateFresh()) return __mmLiveState.nearestEnemy;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
const __mmPlayer = E[__mmPlayerIndex];
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
const __mmDx = __mmPlayer.x - v.x,
__mmDy = __mmPlayer.y - v.y,
__mmDistance = __mmDx * __mmDx + __mmDy * __mmDy;
if (__mmDistance < __mmClosestDistance) {
((__mmClosestDistance = __mmDistance), (__mmClosest = __mmPlayer));
}
}
return __mmClosest;
}
function __mmWeaponReady(__mmWeapon) {
if (!v || !v.alive || __mmWeapon == null) return !1;
if (__mmWeaponIsReloading(__mmWeapon)) return !1;
const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]);
return !Number.isFinite(__mmReload) || __mmReload <= 0;
}
function __mmBoostBreakWeapon() {
if (!v || !v.weapons) return null;
if (v.weapons.includes(__mmGreatHammer)) return __mmGreatHammer;
const __mmMainWeapon = v.weapons[0];
return __mmMainWeapon === __mmKatana || __mmMainWeapon === __mmPolearmWeapon
? __mmMainWeapon
: null;
}
function __mmCanBoostBreak() {
const __mmPad = __mmBoostPadItem();
return !!(
v &&
v.alive &&
v.skins &&
v.skins[40] &&
__mmPad != null &&
!__mmHasPitTrap() &&
__mmCanUseBuildItem(__mmPad) &&
__mmBoostBreakWeapon() != null &&
!__mmInsta.isActive() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive
);
}
function __mmBoostBreakWeaponReady() {
const __mmWeapon = __mmBoostBreakWeapon(),
__mmReload = v && v.reloads && Number(v.reloads[__mmWeapon]);
if (__mmWeapon == null || (Number.isFinite(__mmReload) && __mmReload > 0))
return !1;
return !(
__mmBoostBreakCooldownWeapon === __mmWeapon &&
Date.now() < __mmBoostBreakReadyAt
);
}
function __mmShuffleBoostChat() {
__mmBoostChatOrder = __mmBoostChatLines.slice();
for (
let __mmIndex = __mmBoostChatOrder.length - 1;
__mmIndex > 0;
__mmIndex--
) {
const __mmRandom = Math.floor(Math.random() * (__mmIndex + 1)),
__mmSwap = __mmBoostChatOrder[__mmIndex];
((__mmBoostChatOrder[__mmIndex] = __mmBoostChatOrder[__mmRandom]),
(__mmBoostChatOrder[__mmRandom] = __mmSwap));
}
__mmBoostChatIndex = 0;
}
function __mmSendChat(__mmMessage) {
typeof on === "function" &&
typeof __mmMessage === "string" &&
on(__mmMessage.slice(0, 30));
}
let __mmMaterialReplyLastAt = 0;
function __mmChatMentionsMaterials(__mmMessage) {
if (typeof __mmMessage !== "string") return !1;
const __mmWords = __mmMessage
.toLowerCase()
.replace(/[@4]/g, "a")
.replace(/1/g, "i")
.replace(/3/g, "e")
.replace(/0/g, "o")
.replace(/5/g, "s")
.replace(/7/g, "t")
.replace(/[^a-z]+/g, " ")
.trim();
return /(?:^|\s)(?:mats?|materials?|resources?|res|supplies|wood|stone)(?:\s|$)/.test(
__mmWords,
);
}
function __mmReplyToMaterialRequest(__mmPlayerSid, __mmMessage) {
if (
!__mmMaterialReplyEnabled ||
!v ||
!v.alive ||
__mmPlayerSid == null ||
String(__mmPlayerSid) === String(v.sid) ||
!__mmChatMentionsMaterials(__mmMessage)
)
return;
let __mmPlayer = null;
try {
__mmPlayer = Rt(__mmPlayerSid);
} catch (__mmLookupError) {}
if (
!__mmPlayer ||
(!__mmSameTeam(__mmPlayer) && !__mmIsFriendPlayer(__mmPlayer))
)
return;
const __mmNow = Date.now(),
__mmCooldown = Math.max(2500, (Number(y && y.chatCooldown) || 500) * 2);
if (__mmNow - __mmMaterialReplyLastAt < __mmCooldown) return;
const __mmWood = Math.max(0, Math.floor(Number(v.wood) || 0)),
__mmStone = Math.max(0, Math.floor(Number(v.stone) || 0));
((__mmMaterialReplyLastAt = __mmNow),
__mmSendChat("Wood " + __mmWood + " Stone " + __mmStone));
}
let __mmModReplyLastAt = 0;
const __mmModReplyText = "kitty klient v${KITTY_KLIENT_VERSION}",
__mmModReplyCooldownMs = 5000;
function __mmChatMentionsMod(__mmMessage) {
if (typeof __mmMessage !== "string") return !1;
const __mmNormalized = __mmMessage
.toLowerCase()
.replace(/[@4]/g, "a")
.replace(/1/g, "i")
.replace(/3/g, "e")
.replace(/0/g, "o")
.replace(/5/g, "s")
.replace(/7/g, "t"),
__mmWords = __mmNormalized.replace(/[^a-z]+/g, " ").trim(),
__mmCompact = __mmNormalized.replace(/[^a-z]+/g, "");
// Match direct questions and casual accusations without depending on exact
// phrasing or punctuation. Distinctive compact forms also catch "h a c k"
// and similarly spaced-out attempts.
return !!(
/(?:^|\s)(?:mod(?:s|ded)?|hack(?:s|er|ing|ed)?|hax|client|klient|macro(?:s)?|script(?:s|ed)?|userscript|cheat(?:s|er|ing|ed)?|tampermonkey)(?:\s|$)/.test(
__mmWords,
) ||
/(?:hack|hax|client|klient|macro|userscript|tampermonkey)/.test(
__mmCompact,
)
);
}
function __mmReplyToModQuestion(__mmPlayerSid, __mmMessage) {
if (
!__mmModReplyChatEnabled ||
!v ||
!v.alive ||
__mmPlayerSid === v.sid ||
!__mmChatMentionsMod(__mmMessage)
)
return;
const __mmNow = Date.now();
if (__mmNow - __mmModReplyLastAt < __mmModReplyCooldownMs) return;
((__mmModReplyLastAt = __mmNow), __mmSendChat(__mmModReplyText));
}
function __mmBoostBreakInputHeld() {
return __mmBindingActionHeld("boostBreak") || __mmShiftHeld();
}
let __mmMeowChainLastAt = 0;
function __mmTryMeowChainInsta(__mmPlayerSid, __mmMessage) {
if (
!__mmMeowChainInstaEnabled ||
String(__mmMessage || "").trim() !== "Meow!" ||
!v ||
!v.alive ||
String(__mmPlayerSid) === String(v.sid)
)
return !1;
const __mmPlayer = __mmChatPlayer(__mmPlayerSid),
__mmRecent = __mmRecentPlayerSwings[String(__mmPlayerSid)],
__mmNow = Date.now();
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
(!__mmSameTeam(__mmPlayer) && !__mmIsFriendPlayer(__mmPlayer)) ||
!__mmRecent ||
__mmNow - Number(__mmRecent.at || 0) > 2500 ||
__mmNow - __mmMeowChainLastAt < 750 ||
!__mmInsta.canAutoStart(!0)
)
return !1;
const __mmTarget = __mmInsta.nearestEnemy();
if (!__mmTarget || !__mmInsta.canFullBurst(__mmTarget)) return !1;
__mmMeowChainLastAt = __mmNow;
return __mmInsta.start({
automatic: !0,
targetSid: __mmTarget.sid,
});
}
function __mmSendBoostChat() {
if (!__mmBoostBreakHeld || !__mmBoostBreakInputHeld() || !v || !v.alive) return;
if (!__mmBoostChatOrder.length) __mmShuffleBoostChat();
__mmSendChat(
__mmBoostChatOrder[__mmBoostChatIndex++ % __mmBoostChatOrder.length],
);
}
function __mmStartBoostChat() {
if (!__mmBoostChatEnabled || __mmBoostChatTimer) return;
(__mmShuffleBoostChat(),
__mmSendBoostChat(),
(__mmBoostChatTimer = setInterval(
__mmSendBoostChat,
Math.max(550, Number(y.chatCooldown) || 500),
)));
}
function __mmStopBoostChat() {
(__mmBoostChatTimer &&
(clearInterval(__mmBoostChatTimer), (__mmBoostChatTimer = 0)),
__mmShuffleBoostChat());
}
function __mmStartBoostForward(__mmAngle) {
((__mmBoostMoveDirection = __mmAngle),
O.send("9", __mmAngle),
(Kt = __mmAngle));
}
function __mmFinishBoostBreakGear() {
if (!v || !v.alive) return;
const __mmEnemyNearby = __mmEnemyWithinCombatRange(),
__mmTail =
!__mmEnemyNearby && v.tails && v.tails[11] && v.tailIndex !== 11
? 11
: __mmEnemyNearby && !__mmHasStick() && v.tailIndex === 11
? 0
: null,
__mmSpeed = __mmSpeedHat();
let __mmHat = null;
if (!__mmEnemyNearby && v.skins && v.skins[__mmSpeed]) __mmHat = __mmSpeed;
else if (
__mmBoostTankPreviousHat != null &&
v.skinIndex === 40 &&
__mmCanEquipHat(__mmBoostTankPreviousHat)
)
__mmHat = __mmBoostTankPreviousHat;
else if (
__mmInSnowBiome() &&
v.skins &&
v.skins[__mmBoosterHat] &&
v.skinIndex !== __mmBoosterHat
)
__mmHat = __mmBoosterHat;
__mmEquipGearPair(__mmHat, __mmTail, !0);
}
function __mmSelectBoostBreakWeapon(__mmWeapon) {
if (!v || !v.weapons || !v.weapons.includes(__mmWeapon)) return !1;
return ((__mmLastWeapon = __mmWeapon), je(__mmWeapon, !0), !0);
}
function __mmFinishBoostBreakStrike(__mmWeapon, __mmAngle) {
__mmBoostBreakStrikeTimer = 0;
const __mmPreviousWeapon = __mmBoostBreakPreviousWeapon,
__mmDestroyAngle = Math.atan2(
Math.sin(Number(__mmAngle) + Math.PI),
Math.cos(Number(__mmAngle) + Math.PI),
);
__mmBoostBreakPreviousWeapon = null;
if (!__mmBoostBreakHeld || !v || !v.alive)
return void (__mmBoostBreakStriking = !1);
(__mmSelectBoostBreakWeapon(__mmWeapon) &&
(__mmTankRightClickEnabled &&
v.skins &&
v.skins[40] &&
__mmActivateCombatHat(40),
// Packet order is deliberate: face behind, destroy the pad behind the
// boosted player, release, then restore the original forward aim without
// changing the forward movement direction.
O.send("D", __mmDestroyAngle),
(It = __mmDestroyAngle),
O.send("F", 1, __mmDestroyAngle),
O.send("F", 0, __mmDestroyAngle),
O.send("D", __mmAngle),
(It = __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 || !__mmBoostBreakInputHeld() || !__mmCanBoostBreak())
return void __mmStopBoostBreak();
if (!__mmBoostBreakWeaponReady()) return;
const __mmPad = __mmBoostPadItem();
if (__mmPad == null || !__mmCanUseBuildItem(__mmPad))
return void __mmStopBoostBreak();
const __mmWeapon = __mmBoostBreakWeapon();
if (__mmWeapon == null) return void __mmStopBoostBreak();
const __mmAngle = Ci(),
__mmTail =
!__mmEnemyWithinCombatRange() &&
v.tails &&
v.tails[11] &&
v.tailIndex !== 11
? 11
: null;
(__mmPauseSoldierForBreaking(),
__mmBoostTankPreviousHat == null &&
(__mmBoostTankPreviousHat = __mmInstaSafeRestoreHat(
__mmBushRestoreHat(v.skinIndex),
)),
__mmEquipGearPair(null, __mmTail, !0),
je(__mmPad),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmStartBoostForward(__mmAngle),
(__mmBoostBreakPreviousWeapon = __mmSelectedWeapon()),
(__mmBoostBreakStriking = !0),
__mmSelectBoostBreakWeapon(__mmWeapon),
(__mmBoostBreakStrikeTimer = setTimeout(function () {
__mmFinishBoostBreakStrike(__mmWeapon, __mmAngle);
}, __mmServerTickMs())));
}
function __mmStartBoostBreak() {
__mmInsta.isActive() && __mmInsta.cancel("boost-break");
if (!__mmBoostBreakEnabled || !__mmBoostBreakInputHeld() || !__mmCanBoostBreak())
return;
if (!__mmActionClaim("boostBreak", "shift boost-break")) return;
((__mmBoostBreakHeld = !0),
__mmBoostBreakTimer ||
(__mmBoostBreakTimer = setInterval(
__mmBoostBreakTick,
__mmServerTickMs(),
)),
__mmStartBoostChat(),
__mmBoostBreakTick());
}
function __mmStopBoostBreak() {
const __mmRestore = __mmActionMayRestore("boostBreak");
((__mmBoostBreakHeld = !1),
__mmBoostBreakTimer &&
(clearInterval(__mmBoostBreakTimer), (__mmBoostBreakTimer = 0)),
__mmBoostBreakStrikeTimer &&
(clearTimeout(__mmBoostBreakStrikeTimer),
(__mmBoostBreakStrikeTimer = 0)),
(__mmBoostBreakStriking = !1),
__mmRestore &&
__mmBoostBreakPreviousWeapon != null &&
__mmRestoreWeapon(__mmBoostBreakPreviousWeapon),
(__mmBoostBreakPreviousWeapon = null),
__mmStopBoostChat(),
(__mmBoostBreakCooldownWeapon = null),
(__mmBoostBreakReadyAt = 0));
if (__mmRestore && v && v.alive && __mmBoostTankPreviousHat != null) {
const __mmHat = __mmBoostTankPreviousHat;
((__mmBoostTankPreviousHat = null),
v.skinIndex === 40 && __mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat));
} else __mmBoostTankPreviousHat = null;
(__mmBoostMoveDirection != null &&
((Kt = null), Tt(), (__mmBoostMoveDirection = null)),
__mmActionRelease("boostBreak", "boost-break complete"),
__mmUpdateMovementGear());
}
function __mmStartAutoHeal() {
__mmEnsureOperationPipeline();
}
function __mmUpdateAutoInsta() {
if (__mmShiftHeld())
return !!(
__mmAutoInstaEnabled &&
__mmBoostInsta.start({ automatic: !0 })
);
return !!(
__mmInsta.canAutoStart() &&
__mmInsta.start({ automatic: !0 })
);
}
function __mmStartAutoInsta() {
// Auto Insta is intentionally input-assisted. The primary mousedown path
// calls __mmUpdateAutoInsta; proximity by itself never starts a combo.
__mmAutoInstaTimer && clearInterval(__mmAutoInstaTimer);
__mmAutoInstaTimer = 0;
}
function __mmKittyPolearmHammerLoadout() {
return !!(
v &&
v.alive &&
v.weapons &&
Number(v.weapons[0]) === __mmPolearmWeapon &&
Number(v.weapons[1]) === __mmGreatHammer
);
}
function __mmKittyProfileReady(__mmEnemy, __mmProfile) {
if (
!v ||
!v.alive ||
!__mmIsEnemyPlayer(__mmEnemy) ||
__mmInsta.state !== "idle" ||
!__mmInsta.runtimeReady() ||
__mmInsta.isPriorityConflict() ||
!v.skins ||
!v.skins[7]
)
return !1;
const __mmPrimary = __mmInsta.supportedPrimary();
if (
__mmPrimary == null ||
!__mmWeaponReady(__mmPrimary) ||
!__mmInsta.inRange(__mmPrimary, __mmEnemy)
)
return !1;
if (__mmProfile === "velTick" || __mmProfile === "autoPush")
return !!(
v.skins[__mmTurretGear] &&
__mmInsta.turretReady()
);
const __mmSecondary = v.weapons && v.weapons[1],
__mmSecondaryData = __mmInsta.weaponData(__mmSecondary);
if (
__mmSecondary == null ||
__mmSecondary === __mmPrimary ||
__mmSecondary === __mmShieldWeapon ||
!__mmSecondaryData ||
__mmSecondaryData.shield ||
!__mmWeaponReady(__mmSecondary) ||
!__mmInsta.inRange(__mmSecondary, __mmEnemy)
)
return !1;
return __mmProfile === "polearmAids"
? !!v.skins[40]
: !!(
v.skins[__mmTurretGear] &&
__mmInsta.turretReady()
);
}
function __mmStartKittyProfile(__mmProfile, __mmEnemy, __mmReason) {
const __mmNow = Date.now();
if (
!__mmEnemy ||
__mmNow - __mmKittyInstaLastAt < Math.max(180, __mmServerTickMs() * 2) ||
!__mmKittyProfileReady(__mmEnemy, __mmProfile)
)
return !1;
(__mmVelTickMoveAngle != null || __mmActionOwner === "velTickSetup") &&
__mmStopVelTickInsta("launching " + __mmProfile);
(__mmAutoPushMoveAngle != null || __mmActionOwner === "autoPushSetup") &&
__mmStopAutoPushSetup("launching " + __mmProfile);
const __mmStarted = __mmInsta.start({
automatic: !0,
targetSid: __mmEnemy.sid,
profile: __mmProfile,
profileSource: __mmReason || "Kitty " + __mmProfile,
// These profiles already choose their own local tick edge. The shared
// projectile synchronizer must not insert an extra lead delay.
syncScheduled: !0,
});
__mmStarted && (__mmKittyInstaLastAt = __mmNow);
return __mmStarted;
}
function __mmKittyBleedReady(__mmEnemy) {
if (!__mmKittyPolearmHammerLoadout() || !__mmEnemy) return !1;
const __mmPrimaryVariant = __mmMobStealVariantMultiplier(v.weapons[0]),
__mmSecondaryVariant = __mmMobStealVariantMultiplier(v.weapons[1]);
// Use this non-Soldier branch only with the high-damage variants.
// Keep the same gate so Bleed and Apple cannot race each other.
return !!(
Number(__mmEnemy.skinIndex) !== 6 &&
(__mmPrimaryVariant >= 1.18 ||
(__mmPrimaryVariant > 1 && __mmSecondaryVariant >= 1.18))
);
}
function __mmKittyKnockbackContact(__mmEnemy, __mmPrediction) {
if (!__mmEnemy || !__mmPrediction || __mmAutoSpikeSpamTrapForEnemy(__mmEnemy))
return null;
const __mmPrimary = v && v.weapons && v.weapons[0],
__mmData = b && b.weapons && b.weapons[__mmPrimary],
__mmKnock = Number(__mmData && __mmData.knock),
__mmPushDistance = Math.min(
170,
Math.max(65, (Number.isFinite(__mmKnock) ? __mmKnock : 0.3) * 165),
),
__mmAngle = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
__mmStartX = Number(__mmEnemy.x) +
Number(__mmPrediction.velocityX || 0) * __mmServerTickMs(),
__mmStartY = Number(__mmEnemy.y) +
Number(__mmPrediction.velocityY || 0) * __mmServerTickMs(),
__mmEndX = __mmStartX + Math.cos(__mmAngle) * __mmPushDistance,
__mmEndY = __mmStartY + Math.sin(__mmAngle) * __mmPushDistance,
__mmSpikes = __mmAutoSpikeKillAlliedSpikes(__mmEnemy);
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < __mmSpikes.length; __mmIndex++) {
const __mmEntry = __mmSpikes[__mmIndex],
__mmSpike = __mmEntry.object,
__mmRadius =
(Number(__mmEnemy.scale) || 35) + (Number(__mmEntry.scale) || 49) + 5,
__mmCurrentDistance = Math.hypot(
Number(__mmEnemy.x) - Number(__mmSpike.x),
Number(__mmEnemy.y) - Number(__mmSpike.y),
),
__mmPathDistanceSquared = __mmSegmentDistanceSquared(
__mmStartX,
__mmStartY,
__mmEndX,
__mmEndY,
Number(__mmSpike.x),
Number(__mmSpike.y),
);
if (
__mmCurrentDistance > __mmRadius - 3 &&
__mmPathDistanceSquared <= __mmRadius * __mmRadius
) {
const __mmEndDistance = Math.hypot(
__mmEndX - Number(__mmSpike.x),
__mmEndY - Number(__mmSpike.y),
);
if (!__mmBest || __mmEndDistance < __mmBest.distance)
__mmBest = {
spike: __mmSpike,
distance: __mmEndDistance,
x: __mmEndX,
y: __mmEndY,
};
}
}
return __mmBest;
}
function __mmVelTickSetMovement(__mmAngle) {
if (!v || !v.alive || !Number.isFinite(__mmAngle)) return;
const __mmDifference =
__mmVelTickMoveAngle == null
? Infinity
: Math.abs(
Math.atan2(
Math.sin(__mmAngle - __mmVelTickMoveAngle),
Math.cos(__mmAngle - __mmVelTickMoveAngle),
),
);
if (__mmDifference < 0.035) return;
((__mmVelTickMoveAngle = __mmAngle),
(Kt = __mmAngle),
O.send("9", __mmAngle));
}
function __mmStopVelTickInsta(__mmReason) {
if (__mmVelTickMoveAngle != null && O && typeof O.send === "function") {
try {
((Kt = null), O.send("9", null));
} catch (__mmVelTickStopError) {}
}
((__mmVelTickMoveAngle = null),
(__mmVelTickTargetSid = null),
(__mmVelTickStartedAt = 0),
__mmActionRelease("velTickSetup", __mmReason || "stopped"));
}
function __mmAutoPushSetMovement(__mmAngle) {
if (!v || !v.alive || !Number.isFinite(__mmAngle)) return;
const __mmDifference =
__mmAutoPushMoveAngle == null
? Infinity
: Math.abs(
Math.atan2(
Math.sin(__mmAngle - __mmAutoPushMoveAngle),
Math.cos(__mmAngle - __mmAutoPushMoveAngle),
),
);
if (__mmDifference < 0.035) return;
((__mmAutoPushMoveAngle = __mmAngle),
(Kt = __mmAngle),
O.send("9", __mmAngle));
}
function __mmStopAutoPushSetup(__mmReason) {
if (__mmAutoPushMoveAngle != null && O && typeof O.send === "function") {
try {
((Kt = null), O.send("9", null));
} catch (__mmAutoPushStopError) {}
}
((__mmAutoPushMoveAngle = null),
(__mmAutoPushTargetSid = null),
(__mmAutoPushRoute = []),
(__mmAutoPushRouteAt = 0),
(__mmAutoPushRouteGoalX = null),
(__mmAutoPushRouteGoalY = null),
(__mmAutoPushRouteTargetSid = null),
__mmActionRelease("autoPushSetup", __mmReason || "stopped"));
}
function __mmAutoPushAlliedSpike(__mmEnemy, __mmTrap) {
if (!__mmEnemy || !__mmTrap) return null;
const __mmSpikes = __mmAutoSpikeKillAlliedSpikes(__mmEnemy),
__mmTrapScale =
typeof __mmTrap.getScale === "function"
? Number(__mmTrap.getScale()) || Number(__mmTrap.scale) || 50
: Number(__mmTrap.scale) || 50;
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < __mmSpikes.length; __mmIndex++) {
const __mmEntry = __mmSpikes[__mmIndex],
__mmSpike = __mmEntry.object,
__mmTrapDistance = Math.hypot(
Number(__mmSpike.x) - Number(__mmTrap.x),
Number(__mmSpike.y) - Number(__mmTrap.y),
),
__mmEnemyDistance = Math.hypot(
Number(__mmSpike.x) - Number(__mmEnemy.x),
Number(__mmSpike.y) - Number(__mmEnemy.y),
),
__mmNearTrap =
__mmTrapDistance <=
__mmTrapScale + (Number(__mmEntry.scale) || 49) + 30;
if (
__mmNearTrap &&
(!__mmBest || __mmEnemyDistance < __mmBest.enemyDistance)
)
__mmBest = {
object: __mmSpike,
scale: Number(__mmEntry.scale) || 49,
enemyDistance: __mmEnemyDistance,
};
}
return __mmBest;
}
function __mmAutoPushPathObstacles(__mmGoalX, __mmGoalY, __mmTrap) {
const __mmObjects = __mmActiveObjectSnapshot().all,
__mmPlayerScale = Number(v && v.scale) || 35,
__mmCandidates = [];
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (
!__mmObject ||
!__mmObject.active ||
__mmObject === __mmTrap ||
__mmObject.ignoreCollision ||
!Number.isFinite(Number(__mmObject.x)) ||
!Number.isFinite(Number(__mmObject.y))
)
continue;
const __mmRadius = __mmThreatObjectScale(__mmObject) + __mmPlayerScale + 7,
__mmCorridorDistance = Math.sqrt(
__mmSegmentDistanceSquared(
Number(v.x),
Number(v.y),
__mmGoalX,
__mmGoalY,
Number(__mmObject.x),
Number(__mmObject.y),
),
),
__mmEndpointDistance = Math.min(
Math.hypot(Number(__mmObject.x) - Number(v.x), Number(__mmObject.y) - Number(v.y)),
Math.hypot(Number(__mmObject.x) - __mmGoalX, Number(__mmObject.y) - __mmGoalY),
);
if (__mmCorridorDistance > __mmRadius + 210 && __mmEndpointDistance > 300)
continue;
__mmCandidates.push({
x: Number(__mmObject.x),
y: Number(__mmObject.y),
radius: __mmRadius,
score: Math.min(__mmCorridorDistance, __mmEndpointDistance * 0.7),
});
}
__mmCandidates.sort((__mmA, __mmB) => __mmA.score - __mmB.score);
return __mmCandidates.slice(0, __mmFpsBoostEnabled ? 7 : 11);
}
function __mmAutoPushSegmentClear(__mmA, __mmB, __mmObstacles) {
for (let __mmIndex = 0; __mmIndex < __mmObstacles.length; __mmIndex++) {
const __mmObstacle = __mmObstacles[__mmIndex],
__mmStartDistance = Math.hypot(
__mmA.x - __mmObstacle.x,
__mmA.y - __mmObstacle.y,
),
__mmEndDistance = Math.hypot(
__mmB.x - __mmObstacle.x,
__mmB.y - __mmObstacle.y,
),
__mmDistanceSquared = __mmSegmentDistanceSquared(
__mmA.x,
__mmA.y,
__mmB.x,
__mmB.y,
__mmObstacle.x,
__mmObstacle.y,
);
// The server can leave a player a few pixels inside our conservative
// padding. Permit only an outward edge from that starting overlap.
if (
__mmStartDistance < __mmObstacle.radius &&
__mmEndDistance > __mmStartDistance &&
(__mmB.x - __mmA.x) * (__mmA.x - __mmObstacle.x) +
(__mmB.y - __mmA.y) * (__mmA.y - __mmObstacle.y) >
0
)
continue;
if (__mmDistanceSquared < (__mmObstacle.radius - 1) ** 2) return !1;
}
return !0;
}
function __mmAutoPushSolveRoute(__mmGoalX, __mmGoalY, __mmTrap) {
const __mmStart = { x: Number(v.x), y: Number(v.y) },
__mmGoal = { x: __mmGoalX, y: __mmGoalY },
__mmObstacles = __mmAutoPushPathObstacles(__mmGoalX, __mmGoalY, __mmTrap);
if (__mmAutoPushSegmentClear(__mmStart, __mmGoal, __mmObstacles))
return [__mmGoal];
const __mmNodes = [__mmStart, __mmGoal],
__mmMapScale = Number(y && y.mapScale) || Infinity;
for (let __mmObstacleIndex = 0; __mmObstacleIndex < __mmObstacles.length; __mmObstacleIndex++) {
const __mmObstacle = __mmObstacles[__mmObstacleIndex];
for (let __mmStep = 0; __mmStep < 8; __mmStep++) {
const __mmAngle = (__mmStep * Math.PI) / 4,
__mmClearance = Math.max(6, __mmObstacle.radius * 0.1),
__mmNode = {
x:
__mmObstacle.x +
Math.cos(__mmAngle) * (__mmObstacle.radius + __mmClearance),
y:
__mmObstacle.y +
Math.sin(__mmAngle) * (__mmObstacle.radius + __mmClearance),
};
if (
__mmNode.x < 8 ||
__mmNode.y < 8 ||
__mmNode.x > __mmMapScale - 8 ||
__mmNode.y > __mmMapScale - 8
)
continue;
let __mmInside = !1;
for (let __mmOtherIndex = 0; __mmOtherIndex < __mmObstacles.length; __mmOtherIndex++) {
const __mmOther = __mmObstacles[__mmOtherIndex];
if (
Math.hypot(__mmNode.x - __mmOther.x, __mmNode.y - __mmOther.y) <
__mmOther.radius - 1
) {
__mmInside = !0;
break;
}
}
!__mmInside && __mmNodes.push(__mmNode);
}
}
const __mmDistance = new Array(__mmNodes.length).fill(Infinity),
__mmPrevious = new Array(__mmNodes.length).fill(-1),
__mmVisited = new Array(__mmNodes.length).fill(!1);
__mmDistance[0] = 0;
for (let __mmIteration = 0; __mmIteration < __mmNodes.length; __mmIteration++) {
let __mmCurrent = -1;
for (let __mmIndex = 0; __mmIndex < __mmNodes.length; __mmIndex++)
if (
!__mmVisited[__mmIndex] &&
(__mmCurrent < 0 || __mmDistance[__mmIndex] < __mmDistance[__mmCurrent])
)
__mmCurrent = __mmIndex;
if (__mmCurrent < 0 || !Number.isFinite(__mmDistance[__mmCurrent])) break;
if (__mmCurrent === 1) break;
__mmVisited[__mmCurrent] = !0;
for (let __mmNext = 1; __mmNext < __mmNodes.length; __mmNext++) {
if (
__mmNext === __mmCurrent ||
__mmVisited[__mmNext] ||
!__mmAutoPushSegmentClear(
__mmNodes[__mmCurrent],
__mmNodes[__mmNext],
__mmObstacles,
)
)
continue;
const __mmCandidate =
__mmDistance[__mmCurrent] +
Math.hypot(
__mmNodes[__mmNext].x - __mmNodes[__mmCurrent].x,
__mmNodes[__mmNext].y - __mmNodes[__mmCurrent].y,
);
if (__mmCandidate < __mmDistance[__mmNext]) {
((__mmDistance[__mmNext] = __mmCandidate),
(__mmPrevious[__mmNext] = __mmCurrent));
}
}
}
if (!Number.isFinite(__mmDistance[1])) return [];
const __mmRoute = [];
for (let __mmCursor = 1; __mmCursor > 0; __mmCursor = __mmPrevious[__mmCursor]) {
if (__mmCursor < 0) return [];
__mmRoute.unshift(__mmNodes[__mmCursor]);
}
return __mmRoute;
}
function __mmAutoPushWaypoint(__mmGoalX, __mmGoalY, __mmEnemy, __mmTrap) {
const __mmNow = performance.now(),
__mmGoalMoved =
__mmAutoPushRouteGoalX == null ||
Math.hypot(
__mmGoalX - __mmAutoPushRouteGoalX,
__mmGoalY - __mmAutoPushRouteGoalY,
) > 12,
__mmTargetChanged =
String(__mmAutoPushRouteTargetSid) !== String(__mmEnemy.sid);
if (
__mmGoalMoved ||
__mmTargetChanged ||
!__mmAutoPushRouteAt ||
__mmNow - __mmAutoPushRouteAt > 75
) {
((__mmAutoPushRoute = __mmAutoPushSolveRoute(__mmGoalX, __mmGoalY, __mmTrap)),
(__mmAutoPushRouteAt = __mmNow),
(__mmAutoPushRouteGoalX = __mmGoalX),
(__mmAutoPushRouteGoalY = __mmGoalY),
(__mmAutoPushRouteTargetSid = __mmEnemy.sid));
}
while (
__mmAutoPushRoute.length > 1 &&
Math.hypot(
__mmAutoPushRoute[0].x - Number(v.x),
__mmAutoPushRoute[0].y - Number(v.y),
) <= 18
)
__mmAutoPushRoute.shift();
return __mmAutoPushRoute[0] || null;
}
function __mmUpdateAutoPushSetup(__mmEnemy, __mmTrap) {
const __mmNow = Date.now();
if (
!__mmAutoPushInstaEnabled ||
__mmNow < __mmAutoPushManualUntil ||
!__mmEnemy ||
!__mmTrap ||
!v ||
!v.alive ||
__mmIsTrapped() ||
__mmPrimaryHeld ||
__mmSecondaryHeld
) {
__mmStopAutoPushSetup("conditions lost");
return !1;
}
const __mmSpike = __mmAutoPushAlliedSpike(__mmEnemy, __mmTrap);
if (!__mmSpike) {
__mmStopAutoPushSetup("no allied push spike");
return !1;
}
const __mmTargetToSpike = Math.atan2(
Number(__mmSpike.object.y) - Number(__mmEnemy.y),
Number(__mmSpike.object.x) - Number(__mmEnemy.x),
),
__mmStandDistance =
(Number(v.scale) || 35) + (Number(__mmEnemy.scale) || 35) + 3,
__mmStandX =
Number(__mmEnemy.x) - Math.cos(__mmTargetToSpike) * __mmStandDistance,
__mmStandY =
Number(__mmEnemy.y) - Math.sin(__mmTargetToSpike) * __mmStandDistance,
__mmDistanceToStand = Math.hypot(__mmStandX - v.x, __mmStandY - v.y),
__mmDistanceToEnemy = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y),
__mmContactRadius =
(Number(__mmEnemy.scale) || 35) + Number(__mmSpike.scale) + 5,
__mmAlignedDifference = Math.abs(
Math.atan2(
Math.sin(
Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x) -
__mmTargetToSpike,
),
Math.cos(
Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x) -
__mmTargetToSpike,
),
),
);
if (!__mmActionClaim("autoPushSetup", "aligning trapped enemy to spike")) {
__mmStopAutoPushSetup("alignment blocked");
return !1;
}
__mmAutoPushTargetSid = __mmEnemy.sid;
if (
__mmSpike.enemyDistance <= __mmContactRadius + 7 &&
__mmDistanceToEnemy <= __mmStandDistance + 18 &&
__mmAlignedDifference <= 0.48 &&
__mmKittyProfileReady(__mmEnemy, "autoPush")
) {
__mmStopAutoPushSetup("push contact reached");
return __mmStartKittyProfile(
"autoPush",
__mmEnemy,
"trapped enemy pushed into allied spike",
);
}
const __mmWaypoint =
__mmDistanceToStand > 18
? __mmAutoPushWaypoint(__mmStandX, __mmStandY, __mmEnemy, __mmTrap)
: null,
__mmMoveAngle =
__mmDistanceToStand > 18 && __mmWaypoint
? Math.atan2(__mmWaypoint.y - v.y, __mmWaypoint.x - v.x)
: __mmDistanceToStand <= 18
? __mmTargetToSpike
: null;
if (!Number.isFinite(__mmMoveAngle)) {
__mmAutoPushMoveAngle != null &&
((__mmAutoPushMoveAngle = null), (Kt = null), O.send("9", null));
return !0;
}
__mmAutoPushSetMovement(__mmMoveAngle);
return !0;
}
function __mmUpdateVelTickInsta(__mmEnemy) {
const __mmNow = Date.now();
if (
!__mmVelTickInstaEnabled ||
__mmNow < __mmVelTickManualUntil ||
!__mmEnemy ||
!v ||
!v.alive ||
Number(v.weapons && v.weapons[0]) !== __mmPolearmWeapon ||
Number(__mmEnemy.skinIndex) === 6 ||
Number(__mmEnemy.skinIndex) === 22 ||
__mmAutoSpikeSpamTrapForEnemy(__mmEnemy) ||
__mmIsTrapped()
)
return void __mmStopVelTickInsta("conditions lost");
const __mmPing = Number(window.pingTime) || 0,
__mmMinRange =
__mmPing > 140 ? 230 : __mmPing > 110 ? 210 : __mmPing > 85 ? 190 : 170,
__mmMaxRange = 245,
__mmDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y),
__mmAngle = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x);
if (__mmDistance > 300)
return void __mmStopVelTickInsta("target too far");
if (!__mmActionClaim("velTickSetup", "Kitty auto spacing"))
return void __mmStopVelTickInsta("spacing blocked");
((__mmVelTickTargetSid = __mmEnemy.sid),
__mmVelTickStartedAt || (__mmVelTickStartedAt = __mmNow));
if (__mmDistance > __mmMaxRange)
return void __mmVelTickSetMovement(__mmAngle);
if (__mmDistance < __mmMinRange)
return void __mmVelTickSetMovement(__mmAngle + Math.PI);
__mmStopVelTickInsta("spacing complete");
__mmStartKittyProfile("velTick", __mmEnemy, "VelTick range band");
}
function __mmUpdateKittyInstas() {
if (
!v ||
!v.alive ||
!Array.isArray(E) ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive()
)
return;
const __mmAnyEnabled = !!(
__mmAppleInstaEnabled ||
__mmBleedInstaEnabled ||
__mmKnockbackInstaEnabled ||
__mmVelTickInstaEnabled ||
__mmPolearmAidsEnabled ||
__mmAutoPushInstaEnabled
);
if (!__mmAnyEnabled) {
(__mmStopVelTickInsta("Insta automation disabled"),
__mmStopAutoPushSetup("Insta automation disabled"));
return;
}
const __mmEnemy = __mmNearestEnemy();
if (!__mmEnemy) {
(__mmStopVelTickInsta("no target"),
__mmStopAutoPushSetup("no target"));
return;
}
const __mmNow = Date.now(),
__mmPrediction = __mmPredictEnemyNextTick(__mmEnemy, __mmNow),
__mmPolearmHammer = __mmKittyPolearmHammerLoadout(),
__mmEnemyTrap = __mmAutoSpikeSpamTrapForEnemy(__mmEnemy);
if (
__mmPolearmAidsEnabled &&
__mmPolearmHammer &&
__mmEnemyTrap &&
__mmStartKittyProfile(
"polearmAids",
__mmEnemy,
"enemy caught in allied trap",
)
)
return;
if (
__mmAutoPushInstaEnabled &&
__mmEnemyTrap &&
__mmUpdateAutoPushSetup(__mmEnemy, __mmEnemyTrap)
)
return;
__mmStopAutoPushSetup("no trapped auto-push target");
if (
__mmKnockbackInstaEnabled &&
__mmPolearmHammer &&
__mmKittyKnockbackContact(__mmEnemy, __mmPrediction) &&
__mmStartKittyProfile(
"knockback",
__mmEnemy,
"predicted knockback into allied spike",
)
)
return;
if (
__mmAppleInstaEnabled &&
__mmPolearmHammer &&
Number(__mmEnemy.skinIndex) === 6 &&
__mmStartKittyProfile("apple", __mmEnemy, "Soldier-hat Apple Insta")
)
return;
if (
__mmBleedInstaEnabled &&
__mmKittyBleedReady(__mmEnemy) &&
__mmStartKittyProfile("bleed", __mmEnemy, "high-variant Bleed Insta")
)
return;
__mmVelTickInstaEnabled
? __mmUpdateVelTickInsta(__mmEnemy)
: __mmStopVelTickInsta("VelTick disabled");
}
function __mmStartKittyInstas() {
__mmEnsureOperationPipeline();
}
function __mmRefreshKittyInstaLoop() {
const __mmWanted = !!(
__mmAppleInstaEnabled ||
__mmBleedInstaEnabled ||
__mmKnockbackInstaEnabled ||
__mmVelTickInstaEnabled ||
__mmPolearmAidsEnabled ||
__mmAutoPushInstaEnabled
);
if (__mmWanted) return void __mmStartKittyInstas();
(__mmKittyInstaTimer && clearInterval(__mmKittyInstaTimer),
(__mmKittyInstaTimer = 0),
__mmStopVelTickInsta("Insta automation disabled"),
__mmStopAutoPushSetup("Insta automation disabled"));
}
function __mmAutoTrapInstaTrapForEnemy(__mmEnemy) {
if (!v || !v.alive || !__mmEnemy) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmTraps = __mmActiveTrapObjects();
for (let __mmIndex = 0; __mmIndex < __mmTraps.length; __mmIndex++) {
const __mmTrap = __mmTraps[__mmIndex];
if (
!__mmTrap ||
!__mmTrap.active ||
!__mmTrap.trap ||
!__mmOwnStructure(__mmTrap) ||
!__mmSpikeHostileToEnemy(__mmTrap, __mmEnemy)
)
continue;
const __mmPosition = __mmServerEntityPosition(__mmEnemy),
__mmDistance = __mmPosition
? Math.hypot(__mmPosition.x - __mmTrap.x, __mmPosition.y - __mmTrap.y)
: Infinity;
if (
__mmServerTrapContact(__mmEnemy, __mmTrap) &&
__mmDistance < __mmClosestDistance
)
((__mmClosest = __mmTrap), (__mmClosestDistance = __mmDistance));
}
return __mmClosest;
}
function __mmAutoTrapInstaCloseEnough(__mmEnemy) {
const __mmPrimary = __mmInsta.supportedPrimary(),
__mmData = __mmInsta.weaponData(__mmPrimary);
if (__mmPrimary == null || !__mmData || !v || !__mmEnemy) return !1;
const __mmReach =
(Number(__mmData.range) || 0) +
(Number(v.scale) || 35) +
(Number(__mmEnemy.scale) || 35) +
8;
return (
Math.hypot(
Number(__mmEnemy.x) - Number(v.x),
Number(__mmEnemy.y) - Number(v.y),
) <= __mmReach
);
}
function __mmAutoTrapInstaTrapActive(__mmTrap) {
if (!__mmTrap || !__mmTrap.active || !__mmTrap.trap) return !1;
const __mmKey = __mmTrapBuildKey(__mmTrap),
__mmTraps = __mmActiveTrapObjects();
for (let __mmIndex = 0; __mmIndex < __mmTraps.length; __mmIndex++) {
const __mmCurrent = __mmTraps[__mmIndex];
if (
__mmCurrent === __mmTrap ||
(__mmKey != null && __mmTrapBuildKey(__mmCurrent) === __mmKey)
)
return !0;
}
return !1;
}
function __mmUpdateAutoTrapInsta() {
const __mmNow = Date.now(),
__mmSeen = Object.create(null);
let __mmBest = null;
if (
__mmAutoTrapInstaEnabled &&
!(__mmPolearmAidsEnabled && __mmKittyPolearmHammerLoadout()) &&
v &&
v.alive &&
Array.isArray(E) &&
!__mmIsTrapped()
)
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmEnemy = E[__mmIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmSid = String(__mmEnemy.sid),
__mmTrap = __mmAutoTrapInstaTrapForEnemy(__mmEnemy);
let __mmIncident = __mmAutoTrapInstaIncidents[__mmSid];
__mmSeen[__mmSid] = !0;
if (__mmTrap) {
if (!__mmIncident || __mmIncident.trap !== __mmTrap)
__mmIncident = __mmAutoTrapInstaIncidents[__mmSid] = {
trap: __mmTrap,
trapped: !0,
catchLatched: !1,
hammerArmed: !1,
releasedAt: 0,
releaseLatched: !1,
lastSeen: __mmNow,
};
((__mmIncident.trap = __mmTrap),
(__mmIncident.trapped = !0),
(__mmIncident.lastSeen = __mmNow),
Number(v.weapons && v.weapons[1]) === __mmGreatHammer &&
(__mmIncident.hammerArmed = !0));
// Great Hammer owns the break-edge combo below. Other secondaries
// preserve the original immediate caught-player Insta behavior.
if (
__mmIncident.hammerArmed ||
__mmIncident.catchLatched ||
!__mmAutoTrapInstaCloseEnough(__mmEnemy) ||
!__mmFullInstaReadyFor(__mmEnemy)
)
continue;
const __mmDistance = Math.hypot(
Number(__mmEnemy.x) - Number(v.x),
Number(__mmEnemy.y) - Number(v.y),
);
if (!__mmBest || __mmDistance < __mmBest.distance)
__mmBest = {
enemy: __mmEnemy,
incident: __mmIncident,
release: !1,
distance: __mmDistance,
};
continue;
}
if (!__mmIncident) continue;
__mmIncident.lastSeen = __mmNow;
if (
__mmIncident.trapped &&
!__mmAutoTrapInstaTrapActive(__mmIncident.trap)
) {
((__mmIncident.trapped = !1),
(__mmIncident.releasedAt = __mmNow));
}
const __mmReleaseWindow = Math.max(450, __mmServerTickMs() * 4);
if (
!__mmIncident.hammerArmed ||
__mmIncident.trapped ||
__mmIncident.releaseLatched ||
!__mmIncident.releasedAt ||
__mmNow - __mmIncident.releasedAt > __mmReleaseWindow ||
Number(v.weapons && v.weapons[1]) !== __mmGreatHammer ||
!__mmAutoTrapInstaCloseEnough(__mmEnemy) ||
!__mmFullInstaReadyFor(__mmEnemy)
)
continue;
const __mmDistance = Math.hypot(
Number(__mmEnemy.x) - Number(v.x),
Number(__mmEnemy.y) - Number(v.y),
);
if (!__mmBest || __mmDistance < __mmBest.distance)
__mmBest = {
enemy: __mmEnemy,
incident: __mmIncident,
release: !0,
distance: __mmDistance,
};
}
if (
__mmBest &&
__mmInsta.start({
automatic: !0,
targetSid: __mmBest.enemy.sid,
// The server trap-contact update is already the synchronization edge.
// Always launch locally: relay tick-sync can otherwise add 250–700 ms,
// which lets another Katana + Musket client complete its Insta first.
syncScheduled: !0,
// Keep the normal Katana -> Musket order but skip normal R's deliberate
// 120 ms setup pause. Follow-up weapon timing remains unchanged.
profile: __mmBest.release ? "normal" : "trapCatch",
profileSource: __mmBest.release ? "trap release" : "trap catch",
})
)
__mmBest.release
? (__mmBest.incident.releaseLatched = !0)
: (__mmBest.incident.catchLatched = !0);
for (const __mmSid in __mmAutoTrapInstaIncidents) {
const __mmIncident = __mmAutoTrapInstaIncidents[__mmSid];
const __mmExpiredRelease = !!(
__mmIncident.releasedAt &&
__mmNow - __mmIncident.releasedAt >
Math.max(600, __mmServerTickMs() * 5)
);
if (
(!__mmSeen[__mmSid] && __mmNow - __mmIncident.lastSeen > 300) ||
__mmExpiredRelease
)
delete __mmAutoTrapInstaIncidents[__mmSid];
}
}
function __mmStartAutoTrapInsta() {
__mmEnsureOperationPipeline();
}
function __mmSpikeHostileToEnemy(__mmSpike, __mmEnemy) {
if (!__mmSpike || !__mmEnemy || !__mmSpike.owner) return !0;
const __mmOwner = __mmSpike.owner,
__mmOwnerSid = __mmOwner.sid;
if (
__mmOwner === __mmEnemy ||
String(__mmOwnerSid) === String(__mmEnemy.sid)
)
return !1;
const __mmOwnerPlayer = typeof Rt === "function" ? Rt(__mmOwnerSid) : null,
__mmOwnerTeam = __mmTeamKey(__mmOwnerPlayer || __mmOwner),
__mmEnemyTeam = __mmTeamKey(__mmEnemy);
return !(
__mmOwnerTeam != null &&
__mmEnemyTeam != null &&
__mmOwnerTeam === __mmEnemyTeam
);
}
function __mmPredictEnemyNextTick(__mmEnemy, __mmNow) {
const __mmSid = String(__mmEnemy.sid),
__mmPrevious = __mmAutoSpikeInstaMotion[__mmSid],
__mmSampleElapsed = __mmPrevious
? Math.max(1, Math.min(250, __mmNow - __mmPrevious.at))
: 0;
let __mmVelocityX = __mmPrevious
? (__mmEnemy.x - __mmPrevious.x) / __mmSampleElapsed
: 0,
__mmVelocityY = __mmPrevious
? (__mmEnemy.y - __mmPrevious.y) / __mmSampleElapsed
: 0;
const __mmServerElapsed = Number(__mmEnemy.t2) - Number(__mmEnemy.t1),
__mmServerVelocityX =
(Number(__mmEnemy.x2) - Number(__mmEnemy.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(__mmEnemy.y2) - Number(__mmEnemy.y1)) / __mmServerElapsed;
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
) {
((__mmVelocityX = __mmPrevious
? __mmServerVelocityX * 0.75 + __mmVelocityX * 0.25
: __mmServerVelocityX),
(__mmVelocityY = __mmPrevious
? __mmServerVelocityY * 0.75 + __mmVelocityY * 0.25
: __mmServerVelocityY));
}
__mmAutoSpikeInstaMotion[__mmSid] = {
x: __mmEnemy.x,
y: __mmEnemy.y,
at: __mmNow,
};
const __mmLeadMs = __mmServerTickMs();
return {
x: __mmEnemy.x + __mmVelocityX * __mmLeadMs,
y: __mmEnemy.y + __mmVelocityY * __mmLeadMs,
velocityX: __mmVelocityX,
velocityY: __mmVelocityY,
};
}
function __mmSegmentDistanceSquared(
__mmStartX,
__mmStartY,
__mmEndX,
__mmEndY,
__mmPointX,
__mmPointY,
) {
const __mmPathX = __mmEndX - __mmStartX,
__mmPathY = __mmEndY - __mmStartY,
__mmLengthSquared = __mmPathX * __mmPathX + __mmPathY * __mmPathY;
if (__mmLengthSquared <= 1e-6)
return (
(__mmPointX - __mmStartX) ** 2 + (__mmPointY - __mmStartY) ** 2
);
const __mmProgress = Math.max(
0,
Math.min(
1,
((__mmPointX - __mmStartX) * __mmPathX +
(__mmPointY - __mmStartY) * __mmPathY) /
__mmLengthSquared,
),
),
__mmClosestX = __mmStartX + __mmPathX * __mmProgress,
__mmClosestY = __mmStartY + __mmPathY * __mmProgress;
return (
(__mmPointX - __mmClosestX) ** 2 +
(__mmPointY - __mmClosestY) ** 2
);
}
function __mmSpikeOwnedByUsOrAlly(__mmSpike) {
if (!v || !v.alive || !__mmSpike || !__mmSpike.owner) return !1;
const __mmOwner = __mmSpike.owner,
__mmOwnerSid = __mmOwner.sid;
if (
__mmOwner === v ||
(__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
)
return !0;
const __mmOwnerPlayer =
__mmOwnerSid != null && typeof Rt === "function" ? Rt(__mmOwnerSid) : null;
return __mmSameTeam(__mmOwnerPlayer || __mmOwner);
}
function __mmEnemyWillHitSpikeNextTick(__mmEnemy, __mmPrediction) {
const __mmSpeedSquared =
__mmPrediction.velocityX * __mmPrediction.velocityX +
__mmPrediction.velocityY * __mmPrediction.velocityY;
if (__mmSpeedSquared <= 1e-6) return null;
const __mmPing = Number(window.pingTime),
__mmHorizonMs = Math.min(
240,
__mmServerTickMs() * 1.35 +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0),
),
__mmSpikes = __mmActiveObjectSnapshot().spikes;
let __mmBestContact = null;
for (let __mmIndex = 0; __mmIndex < __mmSpikes.length; __mmIndex++) {
const __mmSpike = __mmSpikes[__mmIndex],
__mmData = __mmSpike && b.list && b.list[__mmSpike.id],
__mmName = String(__mmData && __mmData.name || "").toLowerCase();
if (
!__mmSpike ||
!__mmSpike.active ||
!__mmSpike.isItem ||
!__mmName.includes("spikes") ||
!__mmSpikeOwnedByUsOrAlly(__mmSpike) ||
!__mmSpikeHostileToEnemy(__mmSpike, __mmEnemy)
)
continue;
const __mmCollisionRadius =
(Number(__mmEnemy.scale) || 35) +
(Number(__mmSpike.scale) || Number(__mmData.scale) || 45) +
4,
__mmOffsetX = Number(__mmEnemy.x) - Number(__mmSpike.x),
__mmOffsetY = Number(__mmEnemy.y) - Number(__mmSpike.y),
__mmB =
2 *
(__mmOffsetX * __mmPrediction.velocityX +
__mmOffsetY * __mmPrediction.velocityY),
__mmC =
__mmOffsetX * __mmOffsetX +
__mmOffsetY * __mmOffsetY -
__mmCollisionRadius * __mmCollisionRadius;
// A spike already touching the target is no longer an upcoming contact,
// and a target moving away should never retrigger the strike.
if (__mmC <= 0 || __mmB >= 0) continue;
const __mmDiscriminant =
__mmB * __mmB - 4 * __mmSpeedSquared * __mmC;
if (__mmDiscriminant < 0) continue;
const __mmEtaMs =
(-__mmB - Math.sqrt(__mmDiscriminant)) / (2 * __mmSpeedSquared);
if (
!Number.isFinite(__mmEtaMs) ||
__mmEtaMs < 0 ||
__mmEtaMs > __mmHorizonMs
)
continue;
const __mmContact = {
spike: __mmSpike,
etaMs: __mmEtaMs,
x: Number(__mmEnemy.x) + __mmPrediction.velocityX * __mmEtaMs,
y: Number(__mmEnemy.y) + __mmPrediction.velocityY * __mmEtaMs,
velocityX: __mmPrediction.velocityX,
velocityY: __mmPrediction.velocityY,
collisionRadius: __mmCollisionRadius,
};
if (!__mmBestContact || __mmContact.etaMs < __mmBestContact.etaMs)
__mmBestContact = __mmContact;
}
return __mmBestContact;
}
function __mmSpikeTickPrimary() {
if (!v || !v.alive || !v.weapons) return null;
const __mmPrimary = v.weapons[0];
return __mmPrimary === __mmKatana || __mmPrimary === __mmPolearmWeapon
? __mmPrimary
: null;
}
function __mmSpikeTickSelfPoint(__mmLeadMs) {
if (!v || !v.alive) return null;
const __mmElapsed = Number(v.t2) - Number(v.t1),
__mmVelocityX = (Number(v.x2) - Number(v.x1)) / __mmElapsed,
__mmVelocityY = (Number(v.y2) - Number(v.y1)) / __mmElapsed,
__mmUseVelocity = !!(
Number.isFinite(__mmVelocityX) &&
Number.isFinite(__mmVelocityY) &&
__mmElapsed > 0 &&
__mmElapsed <= 500
);
return {
x: Number(v.x) + (__mmUseVelocity ? __mmVelocityX * __mmLeadMs : 0),
y: Number(v.y) + (__mmUseVelocity ? __mmVelocityY * __mmLeadMs : 0),
};
}
function __mmSpikeTickTrueReach(__mmPrimary, __mmEnemy) {
const __mmData = b && b.weapons && b.weapons[__mmPrimary];
return __mmData
? (Number(__mmData.range) || 0) +
(Number(__mmEnemy && __mmEnemy.scale) || 35) * 1.8
: 0;
}
function __mmSpikeTickContactInRange(
__mmPrimary,
__mmEnemy,
__mmContact,
) {
const __mmSelf = __mmSpikeTickSelfPoint(__mmContact.etaMs),
__mmReach = __mmSpikeTickTrueReach(__mmPrimary, __mmEnemy);
return !!(
__mmSelf &&
__mmReach > 0 &&
Math.hypot(__mmContact.x - __mmSelf.x, __mmContact.y - __mmSelf.y) <=
__mmReach + 8
);
}
function __mmFullInstaReadyFor(__mmEnemy) {
if (
!v ||
!v.alive ||
!__mmEnemy ||
__mmInsta.state !== "idle" ||
!__mmInsta.runtimeReady() ||
__mmInsta.isPriorityConflict() ||
!v.skins ||
!v.skins[7] ||
!v.skins[__mmTurretGear] ||
!__mmInsta.turretReady()
)
return !1;
return __mmInsta.fullBurstReady(__mmEnemy, "normal", !1);
}
function __mmSpikeTickStrikeReady(__mmEnemy, __mmPrediction) {
if (
!__mmAutoSpikeInstaEnabled ||
!v ||
!v.alive ||
!__mmEnemy ||
!__mmPrediction ||
__mmSpikeTickStrikeTimer ||
__mmInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmBuildSpamTimer ||
__mmFoodSpamTimer ||
__mmShieldDefenseTimer ||
__mmIsTrapped() ||
!(
__mmActionAvailable("spikeTickStrike") ||
__mmActionOwner === "weaponRecharge" ||
__mmActionOwner === "matThief" ||
__mmActionOwner === "mobSteal" ||
__mmActionOwner === "instaSync"
)
)
return !1;
const __mmPrimary = __mmSpikeTickPrimary();
return !!(
__mmPrimary != null &&
__mmWeaponReady(__mmPrimary) &&
__mmShieldBypass(v, __mmEnemy) &&
__mmSpikeTickContactInRange(__mmPrimary, __mmEnemy, __mmPrediction)
);
}
function __mmStopSpikeTickStrike(__mmReason) {
const __mmTool = __mmSpikeTickStrikeTool,
__mmHat = __mmSpikeTickStrikeHat,
__mmTail = __mmSpikeTickStrikeTail,
__mmHadAim = Number.isFinite(__mmSpikeTickStrikeAimAngle),
__mmRestore = __mmActionMayRestore("spikeTickStrike");
(__mmSpikeTickStrikeTimer && clearTimeout(__mmSpikeTickStrikeTimer),
(__mmSpikeTickStrikeTimer = 0),
__mmSpikeTickStrikeHeld && O.send("F", 0, __mmSpikeTickStrikeAimAngle),
(__mmSpikeTickStrikeHeld = !1),
(__mmSpikeTickStrikeTool = null),
(__mmSpikeTickStrikeHat = null),
(__mmSpikeTickStrikeTail = null),
(__mmSpikeTickStrikeAimAngle = null),
__mmRestore && __mmEquipGearPair(__mmHat, __mmTail, !0),
__mmRestore && __mmRestoreTool(__mmTool),
__mmActionRelease(
"spikeTickStrike",
__mmReason || "predicted spike strike complete",
),
__mmHadAim && __mmScheduleMouseAimReturn(),
v && v.alive && __mmUpdateWeaponRecharge());
}
function __mmFireSpikeTickStrike(
__mmTargetSid,
__mmPrimary,
__mmContact,
__mmDeadline,
) {
if (
!v ||
!v.alive ||
__mmActionOwner !== "spikeTickStrike" ||
__mmSpikeTickPrimary() !== __mmPrimary ||
!__mmWeaponReady(__mmPrimary)
)
return void __mmStopSpikeTickStrike("spike strike context lost");
let __mmEnemy = null;
try {
__mmEnemy = Rt(__mmTargetSid);
} catch (__mmSpikeTargetError) {}
if (!__mmIsEnemyPlayer(__mmEnemy))
return void __mmStopSpikeTickStrike("spike target lost");
const __mmPing = Number(window.pingTime),
__mmLeadMs = Number.isFinite(__mmPing)
? Math.min(80, Math.max(0, __mmPing / 2))
: 0,
__mmTargetX = Number(__mmEnemy.x) + __mmContact.velocityX * __mmLeadMs,
__mmTargetY = Number(__mmEnemy.y) + __mmContact.velocityY * __mmLeadMs,
__mmSelf = __mmSpikeTickSelfPoint(__mmLeadMs),
__mmReach = __mmSpikeTickTrueReach(__mmPrimary, __mmEnemy),
__mmInRange = !!(
__mmSelf &&
Math.hypot(__mmTargetX - __mmSelf.x, __mmTargetY - __mmSelf.y) <=
__mmReach + 8
);
if (!__mmInRange && Date.now() + 5 < __mmDeadline) {
__mmSpikeTickStrikeTimer = setTimeout(function () {
__mmFireSpikeTickStrike(
__mmTargetSid,
__mmPrimary,
__mmContact,
__mmDeadline,
);
}, 5);
return;
}
if (!__mmInRange)
return void __mmStopSpikeTickStrike("spike target missed melee reach");
const __mmAngle = Math.atan2(
__mmTargetY - __mmSelf.y,
__mmTargetX - __mmSelf.x,
),
__mmDamageTail = __mmInsta.damageTail();
((__mmSpikeTickStrikeAimAngle = __mmAngle),
__mmEquipGearPair(
v.skins && v.skins[7] ? 7 : __mmSpikeTickStrikeHat,
__mmDamageTail,
!0,
),
O.send("D", __mmAngle),
je(__mmPrimary, !0),
O.send("F", 1, __mmAngle),
(__mmSpikeTickStrikeHeld = !0),
(__mmSpikeTickStrikeTimer = setTimeout(function () {
__mmStopSpikeTickStrike("polearm/katana spike strike complete");
}, 25)));
}
function __mmStartSpikeTickStrike(__mmEnemy, __mmPrediction) {
if (!__mmSpikeTickStrikeReady(__mmEnemy, __mmPrediction)) return !1;
(__mmActionOwner === "instaSync" && __mmStopInstaSync(),
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0),
__mmActionOwner === "matThief" &&
__mmFinishMatThief("predicted spike strike"),
__mmActionOwner === "mobSteal" &&
__mmFinishMobSteal("predicted spike strike"));
if (!__mmActionClaim("spikeTickStrike", "predicted allied-spike contact"))
return !1;
__mmCancelCombatHatLock(!1);
const __mmPrimary = __mmSpikeTickPrimary(),
__mmNow = Date.now(),
__mmPing = Number(window.pingTime),
__mmOneWayPing = Number.isFinite(__mmPing)
? Math.min(100, Math.max(0, __mmPing / 2))
: 0,
__mmFireDelay = Math.max(
0,
__mmPrediction.etaMs - __mmOneWayPing - 6,
),
__mmDeadline =
__mmNow + __mmPrediction.etaMs + Math.min(35, __mmOneWayPing),
__mmSelf = __mmSpikeTickSelfPoint(__mmPrediction.etaMs),
__mmAngle = Math.atan2(
__mmPrediction.y - (__mmSelf ? __mmSelf.y : v.y),
__mmPrediction.x - (__mmSelf ? __mmSelf.x : v.x),
),
__mmDamageTail = __mmInsta.damageTail();
if (__mmPrimary == null)
return (__mmActionRelease("spikeTickStrike", "primary unavailable"), !1);
((__mmSpikeTickStrikeTool = __mmSelectedTool()),
(__mmSpikeTickStrikeHat = __mmInstaSafeRestoreHat(
__mmBushRestoreHat(v.skinIndex),
)),
(__mmSpikeTickStrikeTail = __mmBushRestoreTail(v.tailIndex)),
(__mmSpikeTickStrikeAimAngle = __mmAngle),
__mmInsta.turretReady() &&
__mmFireDelay >= 8 &&
(__mmEquipGearPair(__mmTurretGear, __mmDamageTail, !0),
__mmAssumeTurretGearShot()),
O.send("D", __mmAngle),
(__mmSpikeTickStrikeTimer = setTimeout(function () {
__mmFireSpikeTickStrike(
__mmEnemy.sid,
__mmPrimary,
__mmPrediction,
__mmDeadline,
);
}, Math.max(1, __mmFireDelay))));
return !0;
}
function __mmUpdateAutoSpikeInsta() {
const __mmNow = Date.now(),
__mmSeen = Object.create(null);
if (
(!__mmAutoSpikeInstaEnabled && !__mmAutoPushInstaEnabled) ||
!v ||
!v.alive ||
!Array.isArray(E)
)
return;
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmEnemy = E[__mmIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmSid = String(__mmEnemy.sid),
__mmPrediction = __mmPredictEnemyNextTick(__mmEnemy, __mmNow);
__mmSeen[__mmSid] = !0;
const __mmContact = __mmEnemyWillHitSpikeNextTick(
__mmEnemy,
__mmPrediction,
),
__mmPushReady = !!(
__mmContact &&
__mmAutoPushInstaEnabled &&
__mmKittyProfileReady(__mmEnemy, "autoPush")
),
__mmStrikeReady = !!(
__mmContact &&
__mmAutoSpikeInstaEnabled &&
__mmSpikeTickStrikeReady(__mmEnemy, __mmContact)
);
if (
__mmContact &&
(__mmPushReady || __mmStrikeReady) &&
(!__mmBest || __mmContact.etaMs < __mmBest.contact.etaMs)
)
__mmBest = {
enemy: __mmEnemy,
contact: __mmContact,
pushReady: __mmPushReady,
strikeReady: __mmStrikeReady,
};
}
for (const __mmSid in __mmAutoSpikeInstaMotion)
__mmSeen[__mmSid] || delete __mmAutoSpikeInstaMotion[__mmSid];
if (
__mmBest &&
__mmNow - __mmAutoSpikeInstaLastAt >= __mmServerTickMs()
) {
const __mmStarted = __mmBest.pushReady
? __mmStartKittyProfile(
"autoPush",
__mmBest.enemy,
"predicted allied-spike impact",
)
: __mmBest.strikeReady
? __mmStartSpikeTickStrike(__mmBest.enemy, __mmBest.contact)
: !1;
__mmStarted && (__mmAutoSpikeInstaLastAt = __mmNow);
}
}
function __mmStartAutoSpikeInsta() {
__mmEnsureOperationPipeline();
}
function __mmAutoSpikeSpamGhostStillRelevant() {
const __mmGhost = __mmAutoSpikeSpamGhost;
if (!__mmGhost || __mmGhost.targetSid == null || !v || !v.alive)
return !1;
// Lethal-push previews are recomputed from live health and geometry every
// scan. Never pin one after the placement packet has been sent.
if (__mmGhost.mode === "spikeKill") return !1;
let __mmEnemy = null;
try {
__mmEnemy = Rt(__mmGhost.targetSid);
} catch (__mmLookupError) {}
return !!(
__mmIsEnemyPlayer(__mmEnemy) &&
__mmAutoSpikeSpamTrapForEnemy(__mmEnemy)
);
}
function __mmAutoSpikeSpamResetCandidate(__mmForceGhostClear) {
((__mmForceGhostClear || !__mmAutoSpikeSpamGhostStillRelevant()) &&
(__mmAutoSpikeSpamGhost = null),
(__mmAutoSpikeSpamCandidateKey = null),
(__mmAutoSpikeSpamCandidateSince = 0));
}
function __mmAutoSpikeSpamCleanReservations(__mmNow) {
for (let __mmIndex = __mmAutoSpikeSpamReservations.length - 1; __mmIndex >= 0; __mmIndex--)
__mmAutoSpikeSpamReservations[__mmIndex].expiresAt <= __mmNow &&
__mmAutoSpikeSpamReservations.splice(__mmIndex, 1);
}
function __mmAutoSpikeSpamHasCapacity(__mmSpike) {
const __mmData = b && b.list && b.list[__mmSpike];
if (
__mmSpike == null ||
!__mmData ||
!__mmData.group ||
!__mmCanUseBuildItem(__mmSpike) ||
__mmMaxBuildCount(__mmSpike) < 1
)
return !1;
// __mmMaxBuildCount already subtracts same-group pending reservations. Do
// not subtract the whole shared reservation array a second time: traps,
// mills, and teleporters previously consumed fake spike capacity here.
return !0;
}
function __mmAutoSpikeSpamTrapForEnemy(__mmEnemy) {
if (!__mmEnemy) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmTraps = __mmActiveTrapObjects();
for (let __mmIndex = 0; __mmIndex < __mmTraps.length; __mmIndex++) {
const __mmTrap = __mmTraps[__mmIndex];
if (
!__mmTrap ||
!__mmTrap.active ||
!__mmTrap.trap ||
!__mmSpikeHostileToEnemy(__mmTrap, __mmEnemy)
)
continue;
const __mmPosition = __mmServerEntityPosition(__mmEnemy),
__mmDistance = __mmPosition
? Math.hypot(__mmPosition.x - __mmTrap.x, __mmPosition.y - __mmTrap.y)
: Infinity;
if (
__mmServerTrapContact(__mmEnemy, __mmTrap) &&
__mmDistance < __mmClosestDistance
) {
((__mmClosest = __mmTrap), (__mmClosestDistance = __mmDistance));
}
}
return __mmClosest;
}
function __mmAutoSpikeSpamTarget() {
const __mmTargets = __mmAutoSpikeSpamTargets();
return __mmTargets.length ? __mmTargets[0] : null;
}
function __mmAutoSpikeSpamTargets() {
if (!v || !v.alive || !Array.isArray(E)) return [];
const __mmTargets = [];
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmEnemy = E[__mmIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmTrap = __mmAutoSpikeSpamTrapForEnemy(__mmEnemy);
if (!__mmTrap) continue;
const __mmDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y);
Number.isFinite(__mmDistance) &&
__mmTargets.push({
enemy: __mmEnemy,
trap: __mmTrap,
distance: __mmDistance,
});
}
__mmTargets.sort(function (__mmLeft, __mmRight) {
return __mmLeft.distance - __mmRight.distance;
});
return __mmTargets;
}
function __mmResetAutoSpikeSpamIntent() {
((__mmAutoSpikeSpamIntent.targetSid = null),
(__mmAutoSpikeSpamIntent.lastX = null),
(__mmAutoSpikeSpamIntent.lastY = null),
(__mmAutoSpikeSpamIntent.lastAt = 0),
(__mmAutoSpikeSpamIntent.score = 0),
(__mmAutoSpikeSpamIntent.armed = !1));
}
function __mmUpdateAutoSpikeSpamIntent(__mmTarget, __mmNow) {
if (!v || !v.alive || !__mmTarget || !__mmTarget.enemy) {
__mmResetAutoSpikeSpamIntent();
return !1;
}
const __mmEnemy = __mmTarget.enemy,
__mmSid = String(__mmEnemy.sid);
if (__mmAutoSpikeSpamIntent.targetSid !== __mmSid) {
((__mmAutoSpikeSpamIntent.targetSid = __mmSid),
(__mmAutoSpikeSpamIntent.lastX = Number(v.x)),
(__mmAutoSpikeSpamIntent.lastY = Number(v.y)),
(__mmAutoSpikeSpamIntent.lastAt = __mmNow),
(__mmAutoSpikeSpamIntent.score = 0),
(__mmAutoSpikeSpamIntent.armed = !1));
}
const __mmLastX = Number(__mmAutoSpikeSpamIntent.lastX),
__mmLastY = Number(__mmAutoSpikeSpamIntent.lastY),
__mmElapsed = __mmNow - Number(__mmAutoSpikeSpamIntent.lastAt),
__mmMoveX = Number(v.x) - __mmLastX,
__mmMoveY = Number(v.y) - __mmLastY,
__mmMoveDistance = Math.hypot(__mmMoveX, __mmMoveY),
__mmToEnemyX = Number(__mmEnemy.x) - __mmLastX,
__mmToEnemyY = Number(__mmEnemy.y) - __mmLastY,
__mmDistance = Math.hypot(__mmToEnemyX, __mmToEnemyY),
__mmToward =
__mmDistance > 1e-6
? (__mmMoveX * __mmToEnemyX + __mmMoveY * __mmToEnemyY) /
__mmDistance
: 0,
__mmMovementAngle =
typeof Kt === "number" && Number.isFinite(Kt) ? Kt : null,
__mmCommandedToward =
__mmMovementAngle == null || __mmDistance <= 1e-6
? 0
: Math.cos(
__mmMovementAngle - Math.atan2(__mmToEnemyY, __mmToEnemyX),
);
((__mmAutoSpikeSpamIntent.lastX = Number(v.x)),
(__mmAutoSpikeSpamIntent.lastY = Number(v.y)),
(__mmAutoSpikeSpamIntent.lastAt = __mmNow));
if (__mmElapsed > 250 || __mmMoveDistance > 60) {
((__mmAutoSpikeSpamIntent.score = 0),
(__mmAutoSpikeSpamIntent.armed = !1));
return !1;
}
if (__mmToward <= -0.25 || __mmCommandedToward <= -0.45) {
// Retreat is an immediate escape decision. Clear all accumulated forward
// evidence so a later turn back toward the target must deliberately re-arm.
((__mmAutoSpikeSpamIntent.score = 0),
(__mmAutoSpikeSpamIntent.armed = !1));
return !1;
}
if (__mmToward >= 0.15)
__mmAutoSpikeSpamIntent.score = Math.min(
12,
__mmAutoSpikeSpamIntent.score + __mmToward,
);
// A live forward movement command is predictive intent: arm before the next
// position packet arrives. Physical motion still accumulates as a fallback.
if (__mmCommandedToward >= 0.55)
__mmAutoSpikeSpamIntent.score = Math.min(
12,
__mmAutoSpikeSpamIntent.score + 1.5,
);
if (__mmAutoSpikeSpamIntent.score >= 1.5)
__mmAutoSpikeSpamIntent.armed = !0;
return __mmAutoSpikeSpamIntent.armed;
}
function __mmAutoSpikeSpamObjectScale(__mmObject) {
if (!__mmObject) return 0;
if (Number(__mmObject.blocker) > 0) return Number(__mmObject.blocker);
if (typeof __mmObject.getScale === "function") {
// Match the server's checkItemLocation scale arguments for a normal build.
const __mmScale = Number(__mmObject.getScale(0.6, !!__mmObject.isItem));
if (Number.isFinite(__mmScale) && __mmScale > 0) return __mmScale;
}
return Number(__mmObject.scale) || 0;
}
function __mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale) {
if (
__mmX - __mmSpikeScale < 0 ||
__mmY - __mmSpikeScale < 0 ||
__mmX + __mmSpikeScale > y.mapScale ||
__mmY + __mmSpikeScale > y.mapScale ||
(__mmY >= y.mapScale / 2 - y.riverWidth / 2 &&
__mmY <= y.mapScale / 2 + y.riverWidth / 2)
)
return !1;
const __mmObjects = __mmActiveObjectSnapshot().all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (!__mmObject || !__mmObject.active) continue;
const __mmObjectScale = __mmAutoSpikeSpamObjectScale(__mmObject),
// Match the game's collision boundary instead of adding a stricter
// two-pixel buffer around every nearby structure.
__mmMinimum = __mmSpikeScale + __mmObjectScale;
if (
(__mmObject.x - __mmX) ** 2 + (__mmObject.y - __mmY) ** 2 <
__mmMinimum * __mmMinimum
)
return !1;
}
for (let __mmIndex = 0; __mmIndex < __mmAutoSpikeSpamReservations.length; __mmIndex++) {
const __mmReservation = __mmAutoSpikeSpamReservations[__mmIndex],
__mmMinimum = __mmSpikeScale + __mmReservation.scale;
if (
(__mmReservation.x - __mmX) ** 2 +
(__mmReservation.y - __mmY) ** 2 <
__mmMinimum * __mmMinimum
)
return !1;
}
return !0;
}
function __mmAutoSpikeSpamPredictionLead() {
const __mmPing = Number(window.pingTime);
return Math.max(
10,
Math.min(
65,
__mmServerTickMs() * 0.16 +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing) * 0.5 : 0),
),
);
}
function __mmAutoSpikeSpamPredictedEnemy(__mmTarget, __mmNow) {
const __mmEnemy = __mmTarget && __mmTarget.enemy,
__mmTrap = __mmTarget && __mmTarget.trap;
if (!__mmEnemy) return null;
const __mmKey = String(__mmEnemy.sid),
__mmPrevious = __mmAutoSpikeSpamMotion[__mmKey],
__mmMoved = !!(
__mmPrevious &&
Math.hypot(
__mmEnemy.x - __mmPrevious.x,
__mmEnemy.y - __mmPrevious.y,
) > 0.001
),
// Only advance the sample clock when the coordinates actually change.
// The solver runs every 5 ms, while player coordinates commonly update
// once per render/server step; advancing it on identical scans creates a
// false, extremely high velocity on the next real update.
__mmSampleElapsed = __mmMoved
? Math.max(1, Math.min(250, __mmNow - __mmPrevious.sampleAt))
: 0,
__mmSampleFresh = !!(
__mmPrevious &&
__mmNow - __mmPrevious.sampleAt <= 250
),
__mmSampleVelocityX = __mmMoved
? (__mmEnemy.x - __mmPrevious.x) / __mmSampleElapsed
: __mmSampleFresh
? __mmPrevious.sampleVelocityX
: 0,
__mmSampleVelocityY = __mmMoved
? (__mmEnemy.y - __mmPrevious.y) / __mmSampleElapsed
: __mmSampleFresh
? __mmPrevious.sampleVelocityY
: 0,
__mmServerElapsed = Number(__mmEnemy.t2) - Number(__mmEnemy.t1),
__mmServerVelocityX =
(Number(__mmEnemy.x2) - Number(__mmEnemy.x1)) / __mmServerElapsed,
__mmServerVelocityY =
(Number(__mmEnemy.y2) - Number(__mmEnemy.y1)) / __mmServerElapsed,
__mmHasServerVelocity = !!(
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
);
let __mmVelocityX = __mmHasServerVelocity
? __mmServerVelocityX * 0.68 + __mmSampleVelocityX * 0.32
: __mmSampleVelocityX,
__mmVelocityY = __mmHasServerVelocity
? __mmServerVelocityY * 0.68 + __mmSampleVelocityY * 0.32
: __mmSampleVelocityY;
if (__mmPrevious) {
((__mmVelocityX = __mmVelocityX * 0.72 + __mmPrevious.velocityX * 0.28),
(__mmVelocityY = __mmVelocityY * 0.72 + __mmPrevious.velocityY * 0.28));
}
__mmAutoSpikeSpamMotion[__mmKey] = {
x: __mmMoved || !__mmPrevious ? __mmEnemy.x : __mmPrevious.x,
y: __mmMoved || !__mmPrevious ? __mmEnemy.y : __mmPrevious.y,
sampleAt:
__mmMoved || !__mmPrevious ? __mmNow : __mmPrevious.sampleAt,
sampleVelocityX: __mmSampleVelocityX,
sampleVelocityY: __mmSampleVelocityY,
velocityX: __mmVelocityX,
velocityY: __mmVelocityY,
};
const __mmLeadMs = __mmAutoSpikeSpamPredictionLead(),
__mmRawLeadX = __mmVelocityX * __mmLeadMs,
__mmRawLeadY = __mmVelocityY * __mmLeadMs,
__mmLeadDistance = Math.hypot(__mmRawLeadX, __mmRawLeadY),
__mmLeadScale = __mmLeadDistance > 14 ? 14 / __mmLeadDistance : 1;
let __mmX = __mmEnemy.x + __mmRawLeadX * __mmLeadScale,
__mmY = __mmEnemy.y + __mmRawLeadY * __mmLeadScale;
if (__mmTrap) {
const __mmTrapScale =
typeof __mmTrap.getScale === "function"
? Number(__mmTrap.getScale()) || Number(__mmTrap.scale) || 50
: Number(__mmTrap.scale) || 50,
__mmLockRadius = (Number(__mmEnemy.scale) || 35) + __mmTrapScale + 14,
__mmTrapDx = __mmX - __mmTrap.x,
__mmTrapDy = __mmY - __mmTrap.y,
__mmTrapDistance = Math.hypot(__mmTrapDx, __mmTrapDy);
if (__mmTrapDistance > __mmLockRadius && __mmTrapDistance > 0) {
((__mmX = __mmTrap.x + (__mmTrapDx / __mmTrapDistance) * __mmLockRadius),
(__mmY = __mmTrap.y + (__mmTrapDy / __mmTrapDistance) * __mmLockRadius));
}
}
return {
x: __mmX,
y: __mmY,
scale: __mmEnemy.scale,
sid: __mmEnemy.sid,
};
}
function __mmAutoSpikeSpamPredictedOrigin() {
if (!v || !v.alive) return null;
let __mmVelocityX = Number(
__mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityX,
) || 0,
__mmVelocityY = Number(
__mmPassiveSpikeMotion && __mmPassiveSpikeMotion.velocityY,
) || 0;
const __mmServerElapsed = Number(v.t2) - Number(v.t1),
__mmServerVelocityX = (Number(v.x2) - Number(v.x1)) / __mmServerElapsed,
__mmServerVelocityY = (Number(v.y2) - Number(v.y1)) / __mmServerElapsed;
if (
Number.isFinite(__mmServerVelocityX) &&
Number.isFinite(__mmServerVelocityY) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
) {
((__mmVelocityX = __mmVelocityX * 0.35 + __mmServerVelocityX * 0.65),
(__mmVelocityY = __mmVelocityY * 0.35 + __mmServerVelocityY * 0.65));
}
const __mmLeadMs = __mmAutoSpikeSpamPredictionLead(),
__mmLeadX = __mmVelocityX * __mmLeadMs,
__mmLeadY = __mmVelocityY * __mmLeadMs,
__mmDistance = Math.hypot(__mmLeadX, __mmLeadY),
__mmScale = __mmDistance > 10 ? 10 / __mmDistance : 1;
return {
x: v.x + __mmLeadX * __mmScale,
y: v.y + __mmLeadY * __mmScale,
};
}
function __mmAutoSpikeKillDamage(__mmSpike, __mmFallbackItem) {
const __mmItem =
__mmSpike && __mmSpike.id != null
? __mmSpike.id
: __mmFallbackItem,
__mmData = b && b.list && b.list[__mmItem],
__mmObjectDamage = Number(__mmSpike && __mmSpike.dmg),
__mmItemDamage = Number(__mmData && __mmData.dmg);
if (Number.isFinite(__mmObjectDamage) && __mmObjectDamage > 0)
return __mmObjectDamage;
return Number.isFinite(__mmItemDamage) && __mmItemDamage > 0
? __mmItemDamage
: 0;
}
function __mmAutoSpikeKillAlliedSpikes(__mmEnemy) {
const __mmResult = [],
__mmSpikes = __mmActiveObjectSnapshot().spikes;
for (let __mmIndex = 0; __mmIndex < __mmSpikes.length; __mmIndex++) {
const __mmSpike = __mmSpikes[__mmIndex],
__mmData = __mmSpike && b && b.list && b.list[__mmSpike.id],
__mmDamage = __mmAutoSpikeKillDamage(__mmSpike);
if (
!__mmSpike ||
!__mmSpike.active ||
!__mmSpike.isItem ||
!__mmData ||
__mmDamage <= 0 ||
!__mmSpikeOwnedByUsOrAlly(__mmSpike) ||
!__mmSpikeHostileToEnemy(__mmSpike, __mmEnemy)
)
continue;
__mmResult.push({
object: __mmSpike,
damage: __mmDamage,
scale: Number(__mmSpike.scale) || Number(__mmData.scale) || 49,
});
}
return __mmResult;
}
function __mmAutoSpikeKillCandidate(__mmSpike) {
if (
!__mmAutoSpikeKillEnabled ||
!v ||
!v.alive ||
!Array.isArray(E) ||
__mmSpike == null
)
return null;
const __mmData = b && b.list && b.list[__mmSpike],
__mmNewDamage = __mmAutoSpikeKillDamage(null, __mmSpike),
__mmOrigin = __mmAutoSpikeSpamPredictedOrigin();
if (!__mmData || __mmNewDamage <= 0 || !__mmOrigin) return null;
const __mmSpikeScale = Number(__mmData.scale) || 49,
__mmPlacementRadius =
(Number(v.scale) || 35) +
__mmSpikeScale +
(Number(__mmData.placeOffset) || 0),
__mmNow = Date.now();
let __mmBest = null,
__mmBestScore = Infinity;
for (let __mmEnemyIndex = 0; __mmEnemyIndex < E.length; __mmEnemyIndex++) {
const __mmEnemy = E[__mmEnemyIndex],
__mmHealth = Number(__mmEnemy && __mmEnemy.health),
__mmEnemySid = String(__mmEnemy && __mmEnemy.sid);
if (
!__mmIsEnemyPlayer(__mmEnemy) ||
!Number.isFinite(__mmHealth) ||
__mmHealth <= 0 ||
Number(__mmAutoSpikeKillAssumedUntil[__mmEnemySid]) > __mmNow
)
continue;
delete __mmAutoSpikeKillAssumedUntil[__mmEnemySid];
const __mmPredicted = __mmAutoSpikeSpamPredictedEnemy(
{ enemy: __mmEnemy, trap: null },
__mmNow,
),
__mmEnemyScale = Number(__mmPredicted && __mmPredicted.scale) || 35,
__mmExisting = __mmAutoSpikeKillAlliedSpikes(__mmEnemy).filter(
function (__mmEntry) {
return (
Math.hypot(
__mmPredicted.x - __mmEntry.object.x,
__mmPredicted.y - __mmEntry.object.y,
) <=
__mmEnemyScale + __mmEntry.scale + 13
);
},
),
__mmContactRadius = __mmEnemyScale + __mmSpikeScale,
// A slight overlap is what makes the newly-created collision displace
// the enemy. The resolved point remains exactly tangent to the new spike.
__mmPlacementTouchRadius = __mmContactRadius - 5,
__mmTargetDx = __mmPredicted.x - __mmOrigin.x,
__mmTargetDy = __mmPredicted.y - __mmOrigin.y,
__mmTargetDistance = Math.hypot(__mmTargetDx, __mmTargetDy);
if (
!__mmExisting.length ||
__mmTargetDistance <= 1e-6 ||
__mmTargetDistance >
__mmPlacementRadius + __mmPlacementTouchRadius + 9 ||
__mmTargetDistance <
Math.abs(__mmPlacementRadius - __mmPlacementTouchRadius) - 9
)
continue;
const __mmBaseAngle = Math.atan2(__mmTargetDy, __mmTargetDx),
__mmCosOffset = Math.max(
-1,
Math.min(
1,
(__mmPlacementRadius * __mmPlacementRadius +
__mmTargetDistance * __mmTargetDistance -
__mmPlacementTouchRadius * __mmPlacementTouchRadius) /
(2 * __mmPlacementRadius * __mmTargetDistance),
),
),
__mmIntersectionOffset = Math.acos(__mmCosOffset),
__mmSeeds = [
__mmBaseAngle - __mmIntersectionOffset,
__mmBaseAngle + __mmIntersectionOffset,
];
for (let __mmSeedIndex = 0; __mmSeedIndex < __mmSeeds.length; __mmSeedIndex++) {
for (let __mmStep = 0; __mmStep <= 96; __mmStep++) {
const __mmOffset = __mmStep * 0.0025,
__mmSigns = __mmStep === 0 ? [0] : [-1, 1];
for (let __mmSignIndex = 0; __mmSignIndex < __mmSigns.length; __mmSignIndex++) {
const __mmSignedOffset = __mmOffset * __mmSigns[__mmSignIndex],
__mmAngle = __mmSeeds[__mmSeedIndex] + __mmSignedOffset,
__mmX =
__mmOrigin.x + Math.cos(__mmAngle) * __mmPlacementRadius,
__mmY =
__mmOrigin.y + Math.sin(__mmAngle) * __mmPlacementRadius;
const __mmEnemyDx = __mmPredicted.x - __mmX,
__mmEnemyDy = __mmPredicted.y - __mmY,
__mmEnemyDistance = Math.hypot(__mmEnemyDx, __mmEnemyDy);
if (
__mmEnemyDistance <= 1e-6 ||
__mmEnemyDistance > __mmContactRadius - 1 ||
__mmEnemyDistance < __mmContactRadius - 12
)
continue;
if (!__mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale))
continue;
const __mmPushUnitX = __mmEnemyDx / __mmEnemyDistance,
__mmPushUnitY = __mmEnemyDy / __mmEnemyDistance,
__mmPushedX = __mmX + __mmPushUnitX * __mmContactRadius,
__mmPushedY = __mmY + __mmPushUnitY * __mmContactRadius;
let __mmCombinedDamage = __mmNewDamage,
__mmContactCount = 0,
__mmContactDepth = 0;
for (let __mmExistingIndex = 0; __mmExistingIndex < __mmExisting.length; __mmExistingIndex++) {
const __mmEntry = __mmExisting[__mmExistingIndex],
__mmObject = __mmEntry.object,
__mmBeforeDistance = Math.hypot(
__mmPredicted.x - __mmObject.x,
__mmPredicted.y - __mmObject.y,
),
__mmAfterDistance = Math.hypot(
__mmPushedX - __mmObject.x,
__mmPushedY - __mmObject.y,
),
__mmExistingTouchRadius = __mmEnemyScale + __mmEntry.scale;
// It must genuinely push toward the existing spike and finish in
// contact; proximity alone is not treated as a combo hit.
if (
__mmAfterDistance > __mmExistingTouchRadius + 1 ||
__mmAfterDistance >= __mmBeforeDistance - 0.2
)
continue;
(__mmCombinedDamage += __mmEntry.damage,
__mmContactCount++,
(__mmContactDepth +=
__mmExistingTouchRadius - __mmAfterDistance));
}
if (!__mmContactCount || __mmCombinedDamage + 0.001 < __mmHealth)
continue;
const __mmScore =
Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y) * 0.05 +
Math.abs(__mmEnemyDistance - __mmPlacementTouchRadius) * 8 +
Math.abs(__mmSignedOffset) * 2 -
__mmContactCount * 45 -
Math.min(30, __mmContactDepth) * 0.5 -
Math.min(50, __mmCombinedDamage - __mmHealth) * 0.15;
if (__mmScore >= __mmBestScore) continue;
((__mmBestScore = __mmScore),
(__mmBest = {
item: __mmSpike,
x: __mmX,
y: __mmY,
angle: __mmAngle,
scale: __mmSpikeScale,
targetSid: __mmEnemy.sid,
mode: "spikeKill",
combinedDamage: __mmCombinedDamage,
contactCount: __mmContactCount,
pushedX: __mmPushedX,
pushedY: __mmPushedY,
}));
}
}
}
}
return __mmBest;
}
function __mmAutoSpikeSpamRearCandidate(__mmTarget, __mmSpike) {
if (!__mmTarget || !__mmTarget.enemy || !v || !v.alive) return null;
const __mmEnemy = __mmTarget.enemy,
__mmEnemyDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y);
// Rear defense is local combat behavior. Do not build because somebody is
// trapped elsewhere in the visible world.
if (__mmEnemyDistance > __mmThreatTrapRange) return null;
const __mmOrigin = __mmAutoSpikeSpamPredictedOrigin(),
__mmData = b && b.list && b.list[__mmSpike];
if (!__mmOrigin || !__mmData) return null;
const __mmSpikeScale = Number(__mmData.scale) || 49,
__mmPlacementRadius =
(Number(v.scale) || 35) +
__mmSpikeScale +
(Number(__mmData.placeOffset) || 0),
__mmFacing = Math.atan2(
Number(__mmEnemy.y) - __mmOrigin.y,
Number(__mmEnemy.x) - __mmOrigin.x,
),
__mmRearCenter = __mmFacing + Math.PI,
__mmMinimumAngularSpacing =
2 *
Math.asin(
Math.min(
0.999,
(2 * __mmSpikeScale + 1) / (2 * __mmPlacementRadius),
),
) +
0.04,
__mmRearOffsets = [0];
// Prefer a tightly packed, non-colliding rear row. Then scan the full rear
// half-ring in fine steps so obstacles do not turn those preferred slots into
// a permanent stop. The 5ms controller calls this again for as long as the
// target remains trapped, so newly legal space is filled automatically.
for (
let __mmOffset = __mmMinimumAngularSpacing;
__mmOffset <= Math.PI / 2 + 0.001;
__mmOffset += __mmMinimumAngularSpacing
)
(__mmRearOffsets.push(-__mmOffset), __mmRearOffsets.push(__mmOffset));
for (let __mmOffset = 0.04; __mmOffset <= Math.PI / 2; __mmOffset += 0.04)
(__mmRearOffsets.push(-__mmOffset), __mmRearOffsets.push(__mmOffset));
for (let __mmIndex = 0; __mmIndex < __mmRearOffsets.length; __mmIndex++) {
const __mmAngle = __mmRearCenter + __mmRearOffsets[__mmIndex],
__mmX = __mmOrigin.x + Math.cos(__mmAngle) * __mmPlacementRadius,
__mmY = __mmOrigin.y + Math.sin(__mmAngle) * __mmPlacementRadius;
if (!__mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale)) continue;
return {
item: __mmSpike,
x: __mmX,
y: __mmY,
angle: __mmAngle,
faceAngle: __mmFacing,
scale: __mmSpikeScale,
targetSid: __mmEnemy.sid,
rear: !0,
};
}
return null;
}
function __mmAutoSpikeSpamCandidate(__mmTarget, __mmSpike) {
if (!__mmTarget || !v) return null;
const __mmNow = Date.now(),
__mmEnemy = __mmAutoSpikeSpamPredictedEnemy(__mmTarget, __mmNow),
__mmOrigin = __mmAutoSpikeSpamPredictedOrigin(),
__mmData = b.list[__mmSpike],
__mmSpikeScale = Number(__mmData.scale) || 49,
__mmPlacementRadius =
(Number(v.scale) || 35) +
__mmSpikeScale +
(Number(__mmData.placeOffset) || 0),
__mmTouchRadius =
(Number(__mmEnemy.scale) || 35) + __mmSpikeScale - 2,
__mmTargetDx = __mmEnemy.x - __mmOrigin.x,
__mmTargetDy = __mmEnemy.y - __mmOrigin.y,
__mmTargetDistance = Math.hypot(__mmTargetDx, __mmTargetDy);
if (
__mmTargetDistance <= 1e-6 ||
__mmTargetDistance > __mmPlacementRadius + __mmTouchRadius + 10 ||
__mmTargetDistance < Math.abs(__mmPlacementRadius - __mmTouchRadius) - 10
)
return null;
const __mmBaseAngle = Math.atan2(__mmTargetDy, __mmTargetDx),
__mmCosOffset = Math.max(
-1,
Math.min(
1,
(__mmPlacementRadius * __mmPlacementRadius +
__mmTargetDistance * __mmTargetDistance -
__mmTouchRadius * __mmTouchRadius) /
(2 * __mmPlacementRadius * __mmTargetDistance),
),
),
__mmIntersectionOffset = Math.acos(__mmCosOffset),
__mmSeeds = [
__mmBaseAngle - __mmIntersectionOffset,
__mmBaseAngle + __mmIntersectionOffset,
];
let __mmBest = null,
__mmBestScore = Infinity;
for (let __mmSeedIndex = 0; __mmSeedIndex < __mmSeeds.length; __mmSeedIndex++) {
let __mmSeedFound = !1;
for (let __mmStep = 0; __mmStep <= 140 && !__mmSeedFound; __mmStep++) {
const __mmOffset = __mmStep * 0.0025,
__mmSigns = __mmStep === 0 ? [0] : [-1, 1];
for (
let __mmSignIndex = 0;
__mmSignIndex < __mmSigns.length;
__mmSignIndex++
) {
const __mmSignedOffset = __mmOffset * __mmSigns[__mmSignIndex],
__mmAngle = __mmSeeds[__mmSeedIndex] + __mmSignedOffset,
__mmX = __mmOrigin.x + Math.cos(__mmAngle) * __mmPlacementRadius,
__mmY = __mmOrigin.y + Math.sin(__mmAngle) * __mmPlacementRadius,
__mmEnemyDistance = Math.hypot(
__mmX - __mmEnemy.x,
__mmY - __mmEnemy.y,
),
__mmTouchError = Math.abs(__mmEnemyDistance - __mmTouchRadius);
if (
__mmEnemyDistance > __mmTouchRadius + 4 ||
__mmEnemyDistance < __mmTouchRadius - 9 ||
!__mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmSpikeScale)
)
continue;
const __mmScore =
__mmTouchError * 12 + Math.abs(__mmSignedOffset) * 2;
if (__mmScore < __mmBestScore) {
((__mmBestScore = __mmScore),
(__mmBest = {
item: __mmSpike,
x: __mmX,
y: __mmY,
angle: __mmAngle,
scale: __mmSpikeScale,
targetSid: __mmEnemy.sid,
}));
}
__mmSeedFound = !0;
}
}
}
return __mmBest;
}
function __mmAutoSpikeSpamTrappedPlan(__mmSpike) {
const __mmTargets = __mmAutoSpikeSpamTargets();
for (let __mmIndex = 0; __mmIndex < __mmTargets.length; __mmIndex++) {
const __mmTarget = __mmTargets[__mmIndex],
__mmCandidate =
__mmAutoSpikeSpamRearCandidate(__mmTarget, __mmSpike) ||
__mmAutoSpikeSpamCandidate(__mmTarget, __mmSpike);
if (__mmCandidate)
return { target: __mmTarget, candidate: __mmCandidate };
}
return {
target: __mmTargets.length ? __mmTargets[0] : null,
candidate: null,
};
}
function __mmPlaceAutoSpikeSpam(__mmCandidate, __mmNow) {
if (
!__mmCandidate ||
(__mmCandidate.mode !== "spikeKill" && !__mmCandidate.intentReady) ||
__mmEmergencyGetawayActive() ||
__mmHoldingMcGrabby() ||
!__mmAutoSpikeSpamHasCapacity(__mmCandidate.item) ||
!__mmActionClaim(
"spikeSpam",
__mmCandidate && __mmCandidate.mode === "spikeKill"
? "lethal allied-spike push"
: "trapped enemy edge",
)
)
return !1;
const __mmTool = __mmSelectedTool();
try {
((__mmAutoSpikeSpamAimAngle = __mmCandidate.angle),
(__mmAutoSpikeSpamAimUntil = __mmNow + __mmServerTickMs()),
O.send("D", __mmCandidate.angle));
if (
!__mmSendAutomaticPlacement(
__mmCandidate.item,
__mmCandidate.angle,
__mmTool,
)
)
throw new Error("automatic spike placement rejected locally");
(
__mmCandidate.mode === "spikeKill" &&
(__mmAutoSpikeKillAssumedUntil[String(__mmCandidate.targetSid)] =
__mmNow + Math.max(450, __mmServerTickMs() * 2)),
__mmAutoSpikeSpamReservations.push({
item: __mmCandidate.item,
x: __mmCandidate.x,
y: __mmCandidate.y,
scale: __mmCandidate.scale,
expiresAt: __mmNow + 650,
}),
(__mmAutoSpikeSpamLastAt = __mmNow),
__mmActionRelease("spikeSpam", "spike placed"),
__mmAutoSpikeSpamResetCandidate());
return !0;
} catch (__mmSpikeSpamError) {
(__mmRestoreTool(__mmTool),
__mmResumeHeldAttack(),
__mmActionRelease("spikeSpam", "placement failed"),
__mmAutoSpikeSpamResetCandidate());
return !1;
}
}
function __mmAutoSpikeSpamCanPlaceNow() {
return !!(
v &&
v.alive &&
!__mmEmergencyGetawayActive() &&
!v.lockMove &&
!__mmInsta.isActive() &&
!__mmBoostInsta.isActive() &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
!__mmBuildSpamTimer &&
!__mmFoodSpamTimer &&
__mmActionCanPreempt("spikeSpam")
);
}
function __mmUpdateAutoSpikeSpam() {
const __mmNow = Date.now();
__mmAutoSpikeSpamCleanReservations(__mmNow);
if (
(!__mmAutoSpikeSpamEnabled && !__mmAutoSpikeKillEnabled) ||
__mmEmergencyGetawayActive() ||
!v ||
!v.alive
) {
__mmResetAutoSpikeSpamIntent();
return void __mmAutoSpikeSpamResetCandidate(!0);
}
const __mmSpike = __mmSpikeItem();
if (!__mmAutoSpikeSpamHasCapacity(__mmSpike))
return void __mmAutoSpikeSpamResetCandidate();
// A verified lethal pin wins the same placement tick. Ordinary trapped
// enemy filling now searches every trapped target by distance until it finds
// a legal slot, rather than letting one blocked target stall the controller.
const __mmLethalCandidate =
__mmAutoSpikeKillEnabled && __mmAutoSpikeKillCandidate(__mmSpike),
__mmTrappedPlan = __mmAutoSpikeSpamEnabled
? __mmAutoSpikeSpamTrappedPlan(__mmSpike)
: { target: null, candidate: null },
__mmTarget = __mmTrappedPlan.target,
__mmIntentReady = __mmUpdateAutoSpikeSpamIntent(__mmTarget, __mmNow),
__mmCandidate = __mmLethalCandidate || __mmTrappedPlan.candidate;
if (!__mmCandidate) return void __mmAutoSpikeSpamResetCandidate();
__mmCandidate.mode !== "spikeKill" &&
(__mmCandidate.intentReady = __mmIntentReady);
__mmAutoSpikeSpamGhost = __mmCandidate;
const __mmKey =
String(__mmCandidate.targetSid) + ":" +
Math.round(__mmCandidate.x / 3) + ":" +
Math.round(__mmCandidate.y / 3);
if (__mmKey !== __mmAutoSpikeSpamCandidateKey) {
((__mmAutoSpikeSpamCandidateKey = __mmKey),
(__mmAutoSpikeSpamCandidateSince = __mmNow));
}
// Previewing is independent from action ownership. Keep drawing the legal
// non-colliding position while a click, insta, or reload temporarily blocks
// placement instead of erasing the ghost every 10ms. After placement, the
// last valid ghost remains pinned until this target is no longer trapped.
if (!__mmAutoSpikeSpamCanPlaceNow()) return;
if (
__mmNow - __mmAutoSpikeSpamLastAt >=
Math.max(5, Math.min(10, __mmServerTickMs() * 0.08))
) {
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
__mmActionOwner === "matThief" &&
__mmFinishMatThief(
__mmCandidate.mode === "spikeKill"
? "lethal spike push priority"
: "trapped-player spike priority",
);
__mmActionOwner === "mobSteal" &&
__mmFinishMobSteal(
__mmCandidate.mode === "spikeKill"
? "lethal spike push priority"
: "trapped-player spike priority",
);
__mmPlaceAutoSpikeSpam(__mmCandidate, __mmNow);
}
}
function __mmStartAutoSpikeSpam() {
__mmEnsureOperationPipeline();
}
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),
__mmResumeHeldAttack());
}
function __mmDashMovementWeapon(__mmItem) {
if (!v || !v.alive || !v.weapons || !b || !b.list || !b.weapons)
return null;
const __mmItemData = b.list[__mmItem],
__mmHealth = Math.max(1, Number(__mmItemData && __mmItemData.health) || 1),
__mmCandidates = [__mmSelectedWeapon(), v.weapons[0], __mmGreatHammer];
for (let __mmIndex = 0; __mmIndex < __mmCandidates.length; __mmIndex++) {
const __mmWeapon = __mmCandidates[__mmIndex];
if (
__mmWeapon == null ||
!v.weapons.includes(__mmWeapon) ||
!__mmWeaponReady(__mmWeapon) ||
__mmWeaponStructureDamage(v, __mmWeapon, { projDmg: !0 }) + 0.001 <
__mmHealth
)
continue;
return __mmWeapon;
}
return null;
}
function __mmStopDashMovement(__mmReason) {
const __mmAngle = __mmDashMovementAngle,
__mmRestore = __mmDashMovementRestoreTool,
__mmMayRestore = __mmActionMayRestore("dashMovement");
(__mmDashMovementReleaseTimer && clearTimeout(__mmDashMovementReleaseTimer),
(__mmDashMovementReleaseTimer = 0),
__mmAngle != null && v && v.alive && O.send("F", 0, __mmAngle),
__mmMayRestore && __mmRestore != null && __mmRestoreTool(__mmRestore),
(__mmDashMovementAngle = null),
(__mmDashMovementRestoreTool = null),
__mmActionRelease(
"dashMovement",
__mmReason || "dash pad broken",
),
__mmResumeHeldAttack(),
__mmScheduleMouseAimReturn());
}
function __mmTryDashMovement(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
if (
!__mmDashMovementEnabled ||
__mmDashMovementReleaseTimer ||
!v ||
!v.alive ||
!__mmData ||
!__mmData.boostSpeed ||
!v.skins ||
!v.skins[40] ||
__mmIsTrapped() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
!__mmActionCanPreempt("dashMovement")
)
return !1;
const __mmWeapon = __mmDashMovementWeapon(__mmItem);
if (__mmWeapon == null || !__mmActionClaim("dashMovement", "manual boost-pad dash"))
return !1;
const __mmAngle = Ci(),
__mmRestore = __mmSelectedTool();
try {
(je(__mmItem),
O.send("F", 1, __mmAngle),
O.send("F", 0, __mmAngle),
__mmActivateCombatHat(40),
je(__mmWeapon, !0),
O.send("D", __mmAngle),
O.send("F", 1, __mmAngle),
(__mmDashMovementAngle = __mmAngle),
(__mmDashMovementRestoreTool = __mmRestore));
} catch (__mmDashMovementError) {
((__mmDashMovementAngle = __mmAngle),
(__mmDashMovementRestoreTool = __mmRestore),
__mmStopDashMovement("dash packet failed"));
return !1;
}
__mmDashMovementReleaseTimer = setTimeout(function () {
__mmStopDashMovement("dash pad broken");
}, __mmServerTickMs());
return !0;
}
function __mmUseBuildItem(__mmItem) {
if (
!v ||
!v.alive ||
__mmItem == null ||
__mmItem <= 0 ||
!__mmCanUseBuildItem(__mmItem)
)
return;
if (__mmTryDashMovement(__mmItem)) return;
const __mmWeapon = __mmSelectedWeapon();
(je(__mmItem),
O.send("F", 1, Ci()),
O.send("F", 0, Ci()),
__mmRestoreWeapon(__mmWeapon),
__mmResumeHeldAttack());
}
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 __mmThreatEntityVelocity(__mmEntity) {
if (!__mmEntity) return { x: 0, y: 0 };
const __mmElapsed = Number(__mmEntity.t2) - Number(__mmEntity.t1),
__mmVelocityX =
(Number(__mmEntity.x2) - Number(__mmEntity.x1)) / __mmElapsed,
__mmVelocityY =
(Number(__mmEntity.y2) - Number(__mmEntity.y1)) / __mmElapsed;
if (
__mmElapsed > 0 &&
__mmElapsed <= 500 &&
Number.isFinite(__mmVelocityX) &&
Number.isFinite(__mmVelocityY)
)
return {
x: Math.max(-2, Math.min(2, __mmVelocityX)),
y: Math.max(-2, Math.min(2, __mmVelocityY)),
};
return { x: 0, y: 0 };
}
function __mmThreatObjectScale(__mmObject) {
if (!__mmObject) return 0;
const __mmRealScale = Number(__mmObject.realScale),
__mmScale = Number(__mmObject.scale);
if (Number.isFinite(__mmRealScale) && __mmRealScale > 0)
return __mmRealScale;
if (typeof __mmObject.getScale === "function")
try {
const __mmComputed = Number(__mmObject.getScale());
if (Number.isFinite(__mmComputed) && __mmComputed > 0)
return __mmComputed;
} catch (__mmScaleError) {}
return Number.isFinite(__mmScale) && __mmScale > 0 ? __mmScale : 35;
}
function __mmThreatMovingCircleImpact(
__mmProjectile,
__mmTarget,
__mmRadius,
__mmHorizonMs,
) {
const __mmX = Number(__mmProjectile && __mmProjectile.x),
__mmY = Number(__mmProjectile && __mmProjectile.y),
__mmDirection = Number(__mmProjectile && __mmProjectile.dir),
__mmSpeed = Number(__mmProjectile && __mmProjectile.speed),
__mmTargetPosition = __mmServerEntityPosition(__mmTarget),
__mmVelocity = __mmThreatEntityVelocity(__mmTarget);
if (
!__mmTargetPosition ||
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmDirection) ||
!Number.isFinite(__mmSpeed) ||
__mmSpeed <= 0 ||
!Number.isFinite(__mmRadius) ||
__mmRadius <= 0
)
return Infinity;
const __mmRelativeX = __mmX - __mmTargetPosition.x,
__mmRelativeY = __mmY - __mmTargetPosition.y,
__mmRelativeVelocityX =
Math.cos(__mmDirection) * __mmSpeed - __mmVelocity.x,
__mmRelativeVelocityY =
Math.sin(__mmDirection) * __mmSpeed - __mmVelocity.y,
__mmA =
__mmRelativeVelocityX * __mmRelativeVelocityX +
__mmRelativeVelocityY * __mmRelativeVelocityY,
__mmB =
2 *
(__mmRelativeX * __mmRelativeVelocityX +
__mmRelativeY * __mmRelativeVelocityY),
__mmC =
__mmRelativeX * __mmRelativeX +
__mmRelativeY * __mmRelativeY -
__mmRadius * __mmRadius;
if (__mmC <= 0) return 0;
if (__mmA <= 1e-9) return Infinity;
const __mmDiscriminant = __mmB * __mmB - 4 * __mmA * __mmC;
if (__mmDiscriminant < 0) return Infinity;
const __mmImpactMs =
(-__mmB - Math.sqrt(__mmDiscriminant)) / (2 * __mmA),
__mmRange = Number(__mmProjectile.range),
__mmTravel = __mmImpactMs * __mmSpeed;
return __mmImpactMs >= 0 &&
__mmImpactMs <= __mmHorizonMs &&
(!Number.isFinite(__mmRange) || __mmTravel <= __mmRange + __mmRadius)
? __mmImpactMs
: Infinity;
}
function __mmThreatProjectileOwnerChain(__mmProjectile) {
const __mmOwners = [];
let __mmOwner = __mmProjectile && __mmProjectile.owner;
for (let __mmDepth = 0; __mmOwner && __mmDepth < 5; __mmDepth++) {
if (__mmOwners.includes(__mmOwner)) break;
(__mmOwners.push(__mmOwner), (__mmOwner = __mmOwner.owner));
}
return __mmOwners;
}
function __mmThreatProjectileRootPlayer(__mmProjectile) {
const __mmOwners = __mmThreatProjectileOwnerChain(__mmProjectile);
for (let __mmIndex = __mmOwners.length - 1; __mmIndex >= 0; __mmIndex--) {
const __mmOwner = __mmOwners[__mmIndex];
if (__mmOwner === v) return v;
if (
Array.isArray(__mmOwner.weapons) ||
Number.isInteger(Number(__mmOwner.weaponIndex))
)
return __mmOwner;
if (__mmOwner.sid != null && typeof Rt === "function")
try {
const __mmPlayer = Rt(__mmOwner.sid);
if (__mmPlayer) return __mmPlayer;
} catch (__mmOwnerLookupError) {}
}
return null;
}
function __mmThreatProjectileFriendly(__mmProjectile) {
const __mmRootPlayer = __mmThreatProjectileRootPlayer(__mmProjectile);
return !!(
__mmRootPlayer &&
(__mmRootPlayer === v ||
String(__mmRootPlayer.sid) === String(v && v.sid) ||
__mmSameTeam(__mmRootPlayer))
);
}
function __mmThreatProjectileSameSidePlayer(__mmProjectile, __mmPlayer) {
const __mmOwner = __mmThreatProjectileRootPlayer(__mmProjectile);
if (!__mmOwner || !__mmPlayer) return !1;
if (
__mmOwner === __mmPlayer ||
String(__mmOwner.sid) === String(__mmPlayer.sid)
)
return !0;
const __mmOwnerTeam = __mmTeamKey(__mmOwner),
__mmPlayerTeam = __mmTeamKey(__mmPlayer);
return !!(
__mmOwnerTeam != null &&
__mmPlayerTeam != null &&
__mmOwnerTeam === __mmPlayerTeam
);
}
function __mmThreatProjectileFromTurret(__mmProjectile) {
const __mmOwners = __mmThreatProjectileOwnerChain(__mmProjectile);
for (let __mmIndex = 0; __mmIndex < __mmOwners.length; __mmIndex++) {
const __mmOwner = __mmOwners[__mmIndex],
__mmData = __mmOwner && b && b.list && b.list[__mmOwner.id];
if (String((__mmData && __mmData.name) || "").toLowerCase() === "turret")
return !0;
}
return !1;
}
function __mmThreatProjectileFirstCollision(
__mmProjectile,
__mmHorizonMs,
__mmCollisionObjects,
) {
if (
!__mmProjectile ||
!__mmProjectile.active ||
__mmThreatProjectileFriendly(__mmProjectile)
)
return null;
const __mmProjectileScale = Math.max(0, Number(__mmProjectile.scale) || 0),
__mmAvoid = Number(__mmProjectile.avoid),
__mmOwnerChain = __mmThreatProjectileOwnerChain(__mmProjectile);
let __mmFirst = null,
__mmFirstImpactMs = Infinity;
const __mmConsider = function (
__mmTarget,
__mmKind,
__mmRadius,
__mmMoving,
) {
if (!__mmTarget || __mmOwnerChain.includes(__mmTarget)) return;
const __mmImpactMs = __mmThreatMovingCircleImpact(
__mmProjectile,
__mmMoving
? __mmTarget
: {
x: Number(__mmTarget.x),
y: Number(__mmTarget.y),
},
Math.max(1, Number(__mmRadius) || 0) + __mmProjectileScale,
__mmHorizonMs,
);
if (__mmImpactMs >= __mmFirstImpactMs) return;
((__mmFirstImpactMs = __mmImpactMs),
(__mmFirst = {
target: __mmTarget,
kind: __mmKind,
impactMs: __mmImpactMs,
}));
};
const __mmObjects = Array.isArray(__mmCollisionObjects)
? __mmCollisionObjects
: __mmActiveObjectSnapshot().all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex],
__mmElevation = Number(__mmObject && __mmObject.elevation);
if (
!__mmObject ||
!__mmObject.active ||
__mmObject.ignoreCollision ||
(Number.isFinite(__mmAvoid) &&
Number.isFinite(__mmElevation) &&
__mmElevation <= __mmAvoid)
)
continue;
__mmConsider(
__mmObject,
"structure",
__mmThreatObjectScale(__mmObject),
!1,
);
}
if (Array.isArray(N))
for (let __mmIndex = 0; __mmIndex < N.length; __mmIndex++) {
const __mmAnimal = N[__mmIndex];
if (!__mmAnimal || __mmAnimal.active === !1 || __mmAnimal.visible === !1)
continue;
__mmConsider(
__mmAnimal,
"animal",
__mmThreatObjectScale(__mmAnimal),
!0,
);
}
const __mmPlayers = [];
v && __mmPlayers.push(v);
if (Array.isArray(E))
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++)
E[__mmIndex] && !__mmPlayers.includes(E[__mmIndex]) &&
__mmPlayers.push(E[__mmIndex]);
for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
const __mmPlayer = __mmPlayers[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
(__mmPlayer !== v && __mmPlayer.visible === !1) ||
__mmThreatProjectileSameSidePlayer(__mmProjectile, __mmPlayer)
)
continue;
__mmConsider(
__mmPlayer,
__mmPlayer === v ? "localPlayer" : "player",
Number(__mmPlayer.scale) || 35,
!0,
);
}
return __mmFirst;
}
function __mmThreatIncomingDamageMultiplier() {
const __mmHat = __mmPlayerHatData(v),
__mmTail = __mmMobStealTailData(v && v.tailIndex),
__mmHatMultiplier = Number(__mmHat && __mmHat.dmgMult),
__mmTailMultiplier = Number(__mmTail && __mmTail.dmgMult);
return (
(Number.isFinite(__mmHatMultiplier) && __mmHatMultiplier > 0
? __mmHatMultiplier
: 1) *
(Number.isFinite(__mmTailMultiplier) && __mmTailMultiplier > 0
? __mmTailMultiplier
: 1)
);
}
function __mmThreatMeleeDamage(__mmPlayer, __mmWeaponId) {
const __mmWeapon = b && b.weapons && b.weapons[__mmWeaponId];
if (!__mmWeapon || __mmWeapon.projectile != null) return 0;
const __mmHat = __mmPlayerHatData(__mmPlayer),
__mmTail = __mmMobStealTailData(__mmPlayer && __mmPlayer.tailIndex),
__mmVariant =
y && y.weaponVariants && y.weaponVariants[__mmPlayer.weaponVariant],
__mmHatMultiplier = Number(__mmHat && __mmHat.dmgMultO) || 1,
__mmTailMultiplier = Number(__mmTail && __mmTail.dmgMultO) || 1,
__mmVariantMultiplier = Number(__mmVariant && __mmVariant.val) || 1;
return Math.max(
0,
(Number(__mmWeapon.dmg) || 0) *
__mmHatMultiplier *
__mmTailMultiplier *
__mmVariantMultiplier *
__mmThreatIncomingDamageMultiplier(),
);
}
function __mmThreatHostileSpikeOnSegment(
__mmStartX,
__mmStartY,
__mmEndX,
__mmEndY,
) {
const __mmSpikes = __mmActiveObjectSnapshot().spikes,
__mmPlayerScale = Number(v && v.scale) || 35,
__mmSegmentX = __mmEndX - __mmStartX,
__mmSegmentY = __mmEndY - __mmStartY,
__mmSegmentLengthSquared =
__mmSegmentX * __mmSegmentX + __mmSegmentY * __mmSegmentY;
let __mmBest = null;
for (let __mmIndex = 0; __mmIndex < __mmSpikes.length; __mmIndex++) {
const __mmSpike = __mmSpikes[__mmIndex],
__mmData = __mmSpike && b && b.list && b.list[__mmSpike.id],
__mmDamage = __mmAutoSpikeKillDamage(__mmSpike),
__mmRadius = __mmPlayerScale + __mmThreatObjectScale(__mmSpike),
__mmProjection = __mmSegmentLengthSquared > 0
? Math.max(
0,
Math.min(
1,
((Number(__mmSpike.x) - __mmStartX) * __mmSegmentX +
(Number(__mmSpike.y) - __mmStartY) * __mmSegmentY) /
__mmSegmentLengthSquared,
),
)
: 0,
__mmClosestX = __mmStartX + __mmSegmentX * __mmProjection,
__mmClosestY = __mmStartY + __mmSegmentY * __mmProjection,
__mmDistance = Math.hypot(
Number(__mmSpike && __mmSpike.x) - __mmClosestX,
Number(__mmSpike && __mmSpike.y) - __mmClosestY,
);
if (
!__mmSpike ||
!__mmSpike.active ||
!__mmData ||
__mmDamage <= 0 ||
__mmFriendlyStructure(__mmSpike) ||
__mmDistance > __mmRadius + 3
)
continue;
if (
!__mmBest ||
__mmProjection < __mmBest.projection ||
(__mmProjection === __mmBest.projection &&
__mmDamage > __mmBest.damage)
)
__mmBest = {
object: __mmSpike,
damage: __mmDamage * __mmThreatIncomingDamageMultiplier(),
projection: __mmProjection,
};
}
return __mmBest;
}
function __mmThreatMeleeEntries(__mmNow, __mmHorizonMs) {
const __mmEntries = [],
__mmEnemies = __mmLiveStateFresh() ? __mmLiveState.enemies : E;
if (!v || !v.alive || !Array.isArray(__mmEnemies)) return __mmEntries;
for (let __mmIndex = 0; __mmIndex < __mmEnemies.length; __mmIndex++) {
const __mmEnemy = __mmEnemies[__mmIndex],
__mmRecent =
__mmEnemy && __mmRecentPlayerSwings[String(__mmEnemy.sid)],
__mmAge = __mmRecent ? __mmNow - Number(__mmRecent.at) : Infinity,
__mmWeaponId = __mmRecent
? Number(__mmRecent.weapon)
: Number(__mmEnemy && __mmEnemy.weaponIndex),
__mmWeapon = b && b.weapons && b.weapons[__mmWeaponId];
if (
!__mmIsEnemyPlayer(__mmEnemy) ||
!__mmRecent ||
__mmAge < 0 ||
__mmAge > Math.max(__mmHorizonMs, __mmServerTickMs() * 1.75) ||
!__mmWeapon ||
__mmWeapon.projectile != null ||
__mmWeapon.shield
)
continue;
const __mmEnemyPosition = __mmServerEntityPosition(__mmEnemy),
__mmPlayerPosition = __mmServerEntityPosition(v);
if (!__mmEnemyPosition || !__mmPlayerPosition) continue;
const __mmTargetAngle = Math.atan2(
__mmPlayerPosition.y - __mmEnemyPosition.y,
__mmPlayerPosition.x - __mmEnemyPosition.x,
),
__mmFacing = Number.isFinite(Number(__mmEnemy.dir))
? Number(__mmEnemy.dir)
: Number(__mmEnemy.d2),
__mmAngleDifference = Number.isFinite(__mmFacing)
? Math.abs(
Math.atan2(
Math.sin(__mmFacing - __mmTargetAngle),
Math.cos(__mmFacing - __mmTargetAngle),
),
)
: 0,
__mmDistance = Math.hypot(
__mmPlayerPosition.x - __mmEnemyPosition.x,
__mmPlayerPosition.y - __mmEnemyPosition.y,
),
__mmReach =
(Number(__mmWeapon.range) || 0) +
(Number(__mmEnemy.scale) || 35) +
(Number(v.scale) || 35) +
8,
__mmGatherAngle =
Math.max(0.25, Number(y && y.gatherAngle) || 0.35) + 0.12;
if (__mmDistance > __mmReach || __mmAngleDifference > __mmGatherAngle)
continue;
const __mmDamage = __mmThreatMeleeDamage(__mmEnemy, __mmWeaponId),
__mmKnockDistance =
(0.3 + Math.max(0, Number(__mmWeapon.knock) || 0)) *
__mmServerTickMs(),
__mmPushX =
__mmPlayerPosition.x + Math.cos(__mmTargetAngle) * __mmKnockDistance,
__mmPushY =
__mmPlayerPosition.y + Math.sin(__mmTargetAngle) * __mmKnockDistance,
__mmSpike = __mmThreatHostileSpikeOnSegment(
__mmPlayerPosition.x,
__mmPlayerPosition.y,
__mmPushX,
__mmPushY,
);
if (__mmDamage <= 0) continue;
__mmEntries.push({
type: "melee",
source: __mmEnemy,
weapon: __mmWeaponId,
damage: __mmDamage,
impactMs: Math.max(0, __mmServerTickMs() - __mmAge),
angle: Math.atan2(
__mmEnemyPosition.y - __mmPlayerPosition.y,
__mmEnemyPosition.x - __mmPlayerPosition.x,
),
spike: __mmSpike,
});
}
return __mmEntries;
}
function __mmCombatThreatSnapshot(__mmForce) {
const __mmNow = Date.now(),
// Roughly 40-60 forecasts per second still samples between normal
// render/server updates while keeping object x projectile work bounded.
__mmCacheMs = Math.max(16, Math.min(25, __mmFastCheckMs()));
if (
!__mmForce &&
__mmCombatThreatCache &&
__mmNow - __mmCombatThreatCalculatedAt <= __mmCacheMs
)
return __mmCombatThreatCache;
const __mmSnapshot = {
at: __mmNow,
horizonMs: 650,
entries: [],
damage: 0,
projectileDamage: 0,
turretDamage: 0,
meleeDamage: 0,
potentialDamage: 0,
spikeDamage: 0,
healPotential: 0,
nearbyEnemies: 0,
firstImpactMs: Infinity,
angle: null,
lethalSpike: null,
urgent: !1,
lethal: !1,
};
if (!v || !v.alive) {
((__mmCombatThreatCalculatedAt = __mmNow),
(__mmCombatThreatCache = __mmSnapshot));
return __mmSnapshot;
}
const __mmEnemies = __mmLiveStateFresh() ? __mmLiveState.enemies : E;
if (Array.isArray(__mmEnemies))
for (let __mmIndex = 0; __mmIndex < __mmEnemies.length; __mmIndex++) {
const __mmEnemy = __mmEnemies[__mmIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y);
if (__mmDistance > Math.max(__mmCombatRange, __mmTurretGearRange))
continue;
__mmSnapshot.nearbyEnemies++;
const __mmWeaponId = Number(__mmEnemy.weaponIndex),
__mmWeapon = b && b.weapons && b.weapons[__mmWeaponId],
__mmReach = __mmWeapon
? (Number(__mmWeapon.range) || 0) +
(Number(__mmEnemy.scale) || 35) +
(Number(v.scale) || 35) +
65
: 0,
__mmFacing = Number.isFinite(Number(__mmEnemy.dir))
? Number(__mmEnemy.dir)
: Number(__mmEnemy.d2),
__mmToUs = Math.atan2(v.y - __mmEnemy.y, v.x - __mmEnemy.x),
__mmAngleDifference = Number.isFinite(__mmFacing)
? Math.abs(
Math.atan2(
Math.sin(__mmFacing - __mmToUs),
Math.cos(__mmFacing - __mmToUs),
),
)
: Infinity;
if (
__mmWeapon &&
__mmWeapon.projectile == null &&
!__mmWeapon.shield &&
__mmDistance <= __mmReach &&
__mmAngleDifference <= 0.9
)
__mmSnapshot.potentialDamage = Math.max(
__mmSnapshot.potentialDamage,
__mmThreatMeleeDamage(__mmEnemy, __mmWeaponId),
);
}
const __mmHasActiveProjectiles =
Array.isArray(Ve) &&
Ve.some(function (__mmProjectile) {
return !!(__mmProjectile && __mmProjectile.active);
}),
__mmCollisionObjects = __mmHasActiveProjectiles
? __mmActiveObjectSnapshot(!0).all
: [];
if (Array.isArray(Ve))
for (let __mmIndex = 0; __mmIndex < Ve.length; __mmIndex++) {
const __mmProjectile = Ve[__mmIndex],
__mmDamageValue = Number(__mmProjectile && __mmProjectile.dmg);
if (
!__mmProjectile ||
!__mmProjectile.active ||
!Number.isFinite(__mmDamageValue) ||
__mmDamageValue <= 0
)
continue;
const __mmCollision = __mmThreatProjectileFirstCollision(
__mmProjectile,
__mmSnapshot.horizonMs,
__mmCollisionObjects,
);
if (!__mmCollision || __mmCollision.kind !== "localPlayer") continue;
const __mmDamage =
__mmDamageValue * __mmThreatIncomingDamageMultiplier(),
__mmPosition = __mmServerEntityPosition(v),
__mmDirection = Number(__mmProjectile.dir),
__mmKnock = Math.max(0, Number(__mmProjectile.knock) || 0),
__mmPushDistance = __mmKnock * __mmServerTickMs(),
__mmSpike =
__mmPosition && __mmPushDistance > 0
? __mmThreatHostileSpikeOnSegment(
__mmPosition.x,
__mmPosition.y,
__mmPosition.x + Math.cos(__mmDirection) * __mmPushDistance,
__mmPosition.y + Math.sin(__mmDirection) * __mmPushDistance,
)
: null,
__mmTurret = __mmThreatProjectileFromTurret(__mmProjectile);
__mmSnapshot.entries.push({
type: __mmTurret ? "turret" : "projectile",
source: __mmProjectile,
damage: __mmDamage,
impactMs: __mmCollision.impactMs,
angle: Math.atan2(
Number(__mmProjectile.y) - Number(v.y),
Number(__mmProjectile.x) - Number(v.x),
),
spike: __mmSpike,
});
}
const __mmMeleeEntries = __mmThreatMeleeEntries(
__mmNow,
__mmSnapshot.horizonMs,
);
for (let __mmIndex = 0; __mmIndex < __mmMeleeEntries.length; __mmIndex++)
__mmSnapshot.entries.push(__mmMeleeEntries[__mmIndex]);
let __mmBestSpike = null;
for (let __mmIndex = 0; __mmIndex < __mmSnapshot.entries.length; __mmIndex++) {
const __mmEntry = __mmSnapshot.entries[__mmIndex];
__mmSnapshot.damage += __mmEntry.damage;
if (__mmEntry.type === "melee")
__mmSnapshot.meleeDamage += __mmEntry.damage;
else {
__mmSnapshot.projectileDamage += __mmEntry.damage;
__mmEntry.type === "turret" &&
(__mmSnapshot.turretDamage += __mmEntry.damage);
}
if (__mmEntry.impactMs < __mmSnapshot.firstImpactMs)
((__mmSnapshot.firstImpactMs = __mmEntry.impactMs),
(__mmSnapshot.angle = __mmEntry.angle));
if (
__mmEntry.spike &&
(!__mmBestSpike || __mmEntry.spike.damage > __mmBestSpike.damage)
)
__mmBestSpike = __mmEntry.spike;
}
if (__mmBestSpike) {
((__mmSnapshot.spikeDamage = __mmBestSpike.damage),
(__mmSnapshot.damage += __mmBestSpike.damage),
(__mmSnapshot.lethalSpike = __mmBestSpike.object));
}
const __mmHealth = Math.max(0, Number(v.health) || 0),
__mmMissingHealth = Math.max(
0,
(Number(v.maxHealth) || __mmHealth) - __mmHealth,
),
__mmFoodValue = __mmAutoHealFoodValue(),
__mmImpactWindows = Number.isFinite(__mmSnapshot.firstImpactMs)
? Math.max(
0,
Math.floor(__mmSnapshot.firstImpactMs / __mmServerTickMs()),
)
: 0,
__mmFoodChargesAvailable =
!__mmAutoHealEnabled ||
Number(v.skinIndex) === 45 ||
!__mmCanEat() ||
(!__mmAutoHealPending && __mmAutoHealBitesRemaining <= 0)
? 0
: Math.min(__mmFoodCharges(), __mmImpactWindows);
__mmSnapshot.healPotential = Math.min(
__mmMissingHealth,
__mmFoodChargesAvailable * __mmFoodValue,
);
((__mmSnapshot.urgent = __mmSnapshot.damage + 0.001 >= __mmHealth),
(__mmSnapshot.lethal =
__mmSnapshot.damage + 0.001 >=
__mmHealth + __mmSnapshot.healPotential));
if (!__mmSnapshot.lethal) __mmSnapshot.lethalSpike = null;
((__mmCombatThreatCalculatedAt = __mmNow),
(__mmCombatThreatCache = __mmSnapshot));
return __mmSnapshot;
}
function __mmPlacementDefenseItem() {
if (!v || !v.items || !b || !b.list) return null;
const __mmRanks = [
/(?:greater |stone |wood )?wall|blocker/i,
/platform/i,
/mill/i,
];
for (let __mmRank = 0; __mmRank < __mmRanks.length; __mmRank++)
for (let __mmIndex = 0; __mmIndex < v.items.length; __mmIndex++) {
const __mmItem = v.items[__mmIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
__mmRanks[__mmRank].test(String(__mmData.name || "")) &&
__mmCanUseBuildItem(__mmItem) &&
__mmMaxBuildCount(__mmItem) > 0
)
return __mmItem;
}
return null;
}
function __mmUpdatePlacementDefense() {
if (
!__mmPlacementDefenseEnabled ||
!v ||
!v.alive ||
__mmIsTrapped() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmTrapAttackActive ||
!__mmActionCanPreempt("placementDefense")
)
return;
const __mmNow = Date.now(),
__mmThreat = __mmCombatThreatSnapshot(),
__mmProjectileEntries = __mmThreat.entries.filter(function (__mmEntry) {
return __mmEntry && __mmEntry.type !== "melee";
});
if (!__mmProjectileEntries.length) return;
__mmProjectileEntries.sort(function (__mmLeft, __mmRight) {
return Number(__mmLeft.impactMs) - Number(__mmRight.impactMs);
});
const __mmIncoming = __mmProjectileEntries[0],
__mmUrgent =
__mmThreat.lethal ||
__mmThreat.projectileDamage + 0.001 >= Number(v.health) ||
Number(__mmIncoming.impactMs) <= Math.max(180, __mmServerTickMs() * 2.15);
if (
!__mmUrgent ||
!Number.isFinite(Number(__mmIncoming.angle)) ||
Number(__mmPlacementDefenseHandled.get(__mmIncoming.source)) > __mmNow ||
__mmNow - __mmPlacementDefenseLastAt < __mmServerTickMs()
)
return;
const __mmItem = __mmPlacementDefenseItem();
if (__mmItem == null) return;
const __mmCandidate = __mmSmartNearestLegalCandidate(
__mmItem,
Number(__mmIncoming.angle),
0.52,
0.04,
);
if (
!__mmCandidate ||
!__mmActionClaim("placementDefense", "incoming projectile blocker")
)
return;
const __mmRestore = __mmSelectedTool();
if (
__mmSendAutomaticPlacement(
__mmItem,
__mmCandidate.angle,
__mmRestore,
)
)
((__mmPlacementDefenseLastAt = __mmNow),
__mmIncoming.source &&
__mmPlacementDefenseHandled.set(__mmIncoming.source, __mmNow + 800));
__mmActionRelease("placementDefense", "defensive placement sent");
}
function __mmStartPlacementDefense() {
__mmEnsureOperationPipeline();
}
function __mmTurretStealTarget() {
if (!v || !v.alive) return null;
const __mmEntities = [];
Array.isArray(E) && __mmEntities.push.apply(__mmEntities, E);
__mmLiveStateFresh() && Array.isArray(__mmLiveState.animals)
? __mmEntities.push.apply(__mmEntities, __mmLiveState.animals)
: typeof N !== "undefined" &&
Array.isArray(N) &&
__mmEntities.push.apply(__mmEntities, N);
let __mmBest = null,
__mmBestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < __mmEntities.length; __mmIndex++) {
const __mmEntity = __mmEntities[__mmIndex],
__mmPlayerTarget = Array.isArray(E) && E.includes(__mmEntity),
__mmHealth = Number(
__mmEntity &&
(__mmEntity.health == null
? __mmEntity.currentHealth
: __mmEntity.health),
);
if (
!__mmEntity ||
__mmEntity === v ||
__mmEntity.alive === !1 ||
(__mmPlayerTarget && !__mmIsEnemyPlayer(__mmEntity)) ||
!Number.isFinite(__mmHealth) ||
__mmHealth <= 0 ||
__mmHealth > 25
)
continue;
const __mmDistance = Math.hypot(__mmEntity.x - v.x, __mmEntity.y - v.y);
if (__mmDistance <= __mmTurretGearRange && __mmDistance < __mmBestDistance)
((__mmBest = __mmEntity), (__mmBestDistance = __mmDistance));
}
return __mmBest;
}
function __mmUpdateTurretSteal() {
if (
!__mmTurretStealEnabled ||
__mmTurretStealRestoreTimer ||
!v ||
!v.alive ||
!__mmInsta.turretReady() ||
__mmCombatHatLockActive() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmTrapAttackActive ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
!__mmActionAvailable("turretSteal")
)
return;
const __mmTarget = __mmTurretStealTarget();
if (!__mmTarget || !__mmActionClaim("turretSteal", "25-health turret finish"))
return;
const __mmAngle = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x),
__mmRestoreHat = __mmBestPostCombatHat();
try {
(O.send("D", __mmAngle),
__mmEquipHatNow(__mmTurretGear, !0),
__mmAssumeTurretGearShot());
} catch (__mmTurretStealError) {
__mmActionRelease("turretSteal", "turret finisher failed");
return;
}
__mmTurretStealRestoreTimer = setTimeout(function () {
((__mmTurretStealRestoreTimer = 0),
__mmActionMayRestore("turretSteal") &&
v &&
v.alive &&
__mmEquipHatNow(__mmBestPostCombatHat() || __mmRestoreHat, !0),
__mmActionRelease("turretSteal", "turret finisher sent"),
__mmScheduleMouseAimReturn());
}, __mmServerTickMs());
}
function __mmStartTurretSteal() {
__mmEnsureOperationPipeline();
}
function __mmResetSpikeGearCounter(__mmRestore) {
const __mmTailRestore = __mmSpikeGearCounterPreviousTail;
(__mmSpikeGearCounterRestoreTimer &&
clearTimeout(__mmSpikeGearCounterRestoreTimer),
(__mmSpikeGearCounterRestoreTimer = 0),
(__mmSpikeGearCounterTargetSid = null),
(__mmSpikeGearCounterArmedAt = 0),
(__mmSpikeGearCounterPreviousTail = null));
if (__mmActionOwner !== "spikeGearCounter") return;
(__mmRestore &&
v &&
v.alive &&
!__mmCombatHatLockActive() &&
__mmEquipHatNow(__mmBestPostCombatHat(), !0),
__mmRestore &&
__mmTailRestore != null &&
v &&
v.alive &&
__mmEquipTailNow(__mmTailRestore, !0),
__mmActionRelease("spikeGearCounter", "counter reset"));
}
function __mmUpdateSpikeGearCounter() {
if (
!__mmSpikeGearCounterEnabled ||
!v ||
!v.alive ||
!v.skins ||
!v.skins[11] ||
!v.skins[7] ||
!v.tails ||
!v.tails[__mmCorruptXWings] ||
__mmIsTrapped() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmTrapAttackActive
)
return void __mmResetSpikeGearCounter(!0);
const __mmEnemy = __mmNearestEnemy(),
__mmPrimary = v.weapons && v.weapons[0],
__mmPrimaryData = b && b.weapons && b.weapons[__mmPrimary];
if (!__mmEnemy || __mmPrimary == null || !__mmPrimaryData)
return void __mmResetSpikeGearCounter(!0);
const __mmEnemyWeapon =
b && b.weapons && b.weapons[Number(__mmEnemy.weaponIndex)],
__mmDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y),
__mmOurReach =
(Number(__mmPrimaryData.range) || 0) +
(Number(v.scale) || 35) +
(Number(__mmEnemy.scale) || 35) +
8,
__mmEnemyReach =
(Number(__mmEnemyWeapon && __mmEnemyWeapon.range) || 0) +
(Number(v.scale) || 35) +
(Number(__mmEnemy.scale) || 35) +
8;
if (
!__mmEnemyWeapon ||
__mmEnemyWeapon.projectile != null ||
__mmDistance > Math.min(__mmOurReach, __mmEnemyReach) ||
(Number(__mmEnemy.skinIndex) !== 7 &&
String(__mmSpikeGearCounterTargetSid) !== String(__mmEnemy.sid))
)
return void __mmResetSpikeGearCounter(!0);
const __mmRecent = __mmRecentPlayerSwings[String(__mmEnemy.sid)],
__mmSwingAge = __mmRecent ? Date.now() - Number(__mmRecent.at) : Infinity;
if (
String(__mmSpikeGearCounterTargetSid) !== String(__mmEnemy.sid) &&
__mmActionCanPreempt("spikeGearCounter") &&
__mmActionClaim("spikeGearCounter", "close Bull-primary counter")
) {
((__mmSpikeGearCounterTargetSid = __mmEnemy.sid),
(__mmSpikeGearCounterArmedAt = Date.now()),
(__mmSpikeGearCounterPreviousTail = __mmBushRestoreTail(v.tailIndex)),
__mmEquipGearPair(11, __mmCorruptXWings, !0));
return;
}
if (
String(__mmSpikeGearCounterTargetSid) !== String(__mmEnemy.sid) ||
__mmSwingAge < 0 ||
__mmSwingAge > __mmServerTickMs() * 1.55 ||
!__mmWeaponReady(__mmPrimary) ||
__mmSpikeGearCounterRestoreTimer
) {
Date.now() - __mmSpikeGearCounterArmedAt > 650 &&
__mmResetSpikeGearCounter(!0);
return;
}
const __mmAngle = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
__mmRestore = __mmSelectedTool();
try {
(__mmActivateCombatHat(7),
O.send("D", __mmAngle),
je(__mmPrimary, !0),
O.send("F", 1, __mmAngle));
} catch (__mmSpikeGearCounterError) {
return void __mmResetSpikeGearCounter(!0);
}
__mmSpikeGearCounterRestoreTimer = setTimeout(function () {
((__mmSpikeGearCounterRestoreTimer = 0),
v && v.alive && O.send("F", 0, __mmAngle),
__mmActionMayRestore("spikeGearCounter") && __mmRestoreTool(__mmRestore),
__mmResetSpikeGearCounter(!0),
__mmScheduleMouseAimReturn());
}, __mmServerTickMs());
}
function __mmStartSpikeGearCounter() {
__mmEnsureOperationPipeline();
}
function __mmLethalCombatThreat() {
const __mmThreat = __mmCombatThreatSnapshot();
return __mmThreat.lethal && __mmThreat.damage > 0
? {
damage: __mmThreat.damage,
angle: Number.isFinite(__mmThreat.angle) ? __mmThreat.angle : Ci(),
projectileDamage: __mmThreat.projectileDamage,
turretDamage: __mmThreat.turretDamage,
meleeDamage: __mmThreat.meleeDamage,
spikeDamage: __mmThreat.spikeDamage,
firstImpactMs: __mmThreat.firstImpactMs,
}
: null;
}
function __mmCanUseAntiInsta() {
return !!(
__mmAntiInstaEnabled &&
!__mmEmergencyGetawayActive() &&
!__mmHoldingMcGrabby() &&
__mmActionCanPreempt("antiInsta") &&
v &&
v.alive &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
!__mmBuildSpamTimer &&
!__mmFoodSpamTimer &&
!__mmShieldDefenseTimer
);
}
function __mmPlaceAntiInstaSpike(__mmAngle) {
if (__mmEmergencyGetawayActive() || __mmHoldingMcGrabby()) return !1;
const __mmSpike = __mmSpikeItem();
if (__mmSpike == null || !__mmCanUseBuildItem(__mmSpike)) return !1;
const __mmTool = __mmSelectedTool();
return __mmSendAutomaticPlacement(__mmSpike, __mmAngle, __mmTool);
}
function __mmUpdateAntiInsta() {
if (
!__mmAntiInstaEnabled ||
__mmEmergencyGetawayActive() ||
!v ||
!v.alive ||
__mmHoldingMcGrabby()
)
return;
const __mmNow = Date.now();
if (__mmNow - __mmAntiInstaLastAt < 450) return;
const __mmThreat = __mmLethalCombatThreat();
if (!__mmThreat) return;
// One shared forecast covers melee, hostile projectiles, turret bullets and
// a knockback spike follow-up. Held mouse attacks loan the build channel and
// are re-armed immediately after the defensive spike.
__mmInsta.isActive() && __mmInsta.cancel("lethal-combat-threat");
__mmInstaSyncPending || __mmInstaSyncFiring ? __mmStopInstaSync() : null;
if (!__mmActionCanPreempt("antiInsta")) return;
__mmActionOwner === "shieldDefense" &&
__mmStopShieldDefense("lethal combat priority");
__mmBoostBreakHeld && __mmStopBoostBreak();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmActionClaim("antiInsta", "lethal combat forecast")) return;
// Anti Insta is the sole defensive path allowed to break an active manual
// Bull/Tank lock immediately.
__mmCancelCombatHatLock(!0);
if (!__mmCanUseAntiInsta())
return void __mmActionRelease("antiInsta", "unsafe to place");
if (!__mmPlaceAntiInstaSpike(__mmThreat.angle))
return void __mmActionRelease("antiInsta", "no spike");
((__mmAntiInstaLastAt = __mmNow),
(__mmAntiInstaUntil = __mmNow + Math.max(140, __mmServerTickMs())),
__mmAntiInstaActionTimer && clearTimeout(__mmAntiInstaActionTimer),
(__mmAntiInstaActionTimer = setTimeout(function () {
((__mmAntiInstaActionTimer = 0),
__mmActionRelease("antiInsta", "threat window complete"));
}, Math.max(140, __mmServerTickMs()))));
}
function __mmStartAntiInsta() {
__mmEnsureOperationPipeline();
}
function __mmProjectileTravelDistance(__mmFrom, __mmTarget) {
return Math.max(
0,
Math.hypot(__mmTarget.x - __mmFrom.x, __mmTarget.y - __mmFrom.y) -
(Number(__mmFrom.scale) || 35) -
(Number(__mmTarget.scale) || 35),
);
}
function __mmDirectFriendlyProjectileSource(__mmProjectile) {
if (!v || !v.alive || !__mmProjectile || !__mmProjectile.owner) return null;
const __mmOwner = __mmProjectile.owner,
__mmOwnerSid = __mmOwner.sid;
// A normal shot from this player should not recursively trigger another
// sync shot. Personal structures are allowed through the nested owner path.
if (
__mmOwner === v ||
(__mmOwnerSid != null && String(__mmOwnerSid) === String(v.sid))
)
return null;
let __mmOwnerPlayer =
__mmOwnerSid != null && typeof Rt === "function" ? Rt(__mmOwnerSid) : null;
if (__mmSameTeam(__mmOwnerPlayer || __mmOwner))
return __mmOwnerPlayer || __mmOwner;
const __mmStructureOwner = __mmOwner.owner,
__mmStructureOwnerSid = __mmStructureOwner && __mmStructureOwner.sid;
if (!__mmStructureOwner) return null;
if (String(__mmStructureOwnerSid) === String(v.sid)) return __mmOwner;
__mmOwnerPlayer =
__mmStructureOwnerSid != null && typeof Rt === "function"
? Rt(__mmStructureOwnerSid)
: null;
return __mmSameTeam(__mmOwnerPlayer || __mmStructureOwner)
? __mmOwner
: null;
}
function __mmFriendlyProjectileSource(__mmProjectile) {
if (!__mmProjectile || !Array.isArray(E)) return null;
const __mmX = Number(__mmProjectile.x),
__mmY = Number(__mmProjectile.y),
__mmDirection = Number(__mmProjectile.dir);
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmDirection)
)
return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
!__mmPlayer.visible ||
!__mmSameTeam(__mmPlayer)
)
continue;
const __mmDx = __mmX - __mmPlayer.x,
__mmDy = __mmY - __mmPlayer.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmForward =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection),
__mmSide = Math.abs(
__mmDx * Math.sin(__mmDirection) -
__mmDy * Math.cos(__mmDirection),
);
if (
__mmForward < -35 ||
__mmSide > 125 ||
__mmDistance > Math.max(320, (Number(__mmPlayer.scale) || 35) + 180) ||
__mmDistance >= __mmClosestDistance
)
continue;
((__mmClosest = __mmPlayer), (__mmClosestDistance = __mmDistance));
}
return __mmClosest;
}
function __mmPersonalTurretProjectileSource(__mmProjectile) {
if (!v || !v.alive || !__mmProjectile) return null;
const __mmX = Number(__mmProjectile.x),
__mmY = Number(__mmProjectile.y),
__mmDirection = Number(__mmProjectile.dir);
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmDirection)
)
return null;
const __mmTurrets = __mmActiveObjectSnapshot().turrets;
for (let __mmIndex = 0; __mmIndex < __mmTurrets.length; __mmIndex++) {
const __mmObject = __mmTurrets[__mmIndex],
__mmItem = __mmObject && b.list[__mmObject.id];
if (
!__mmObject ||
!__mmObject.active ||
!__mmItem ||
String(__mmItem.name || "").toLowerCase() !== "turret" ||
!__mmObject.owner
)
continue;
const __mmOwnerSid = __mmObject.owner.sid,
__mmOwnerPlayer =
String(__mmOwnerSid) === String(v.sid)
? v
: typeof Rt === "function"
? Rt(__mmOwnerSid)
: null;
if (
String(__mmOwnerSid) !== String(v.sid) &&
!__mmSameTeam(__mmOwnerPlayer || __mmObject.owner)
)
continue;
const __mmDx = __mmX - __mmObject.x,
__mmDy = __mmY - __mmObject.y,
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmForward =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection),
__mmSide = Math.abs(
__mmDx * Math.sin(__mmDirection) -
__mmDy * Math.cos(__mmDirection),
);
if (
__mmForward >= -35 &&
__mmSide <= Math.max(150, Number(__mmObject.scale) || 0) &&
__mmDistance <= Math.max(340, (Number(__mmObject.scale) || 45) + 200)
)
return __mmObject;
}
return null;
}
function __mmSyncPlayerVelocity(__mmPlayer) {
if (!__mmPlayer) return { x: 0, y: 0 };
const __mmElapsed = Number(__mmPlayer.t2) - Number(__mmPlayer.t1),
__mmX =
(Number(__mmPlayer.x2) - Number(__mmPlayer.x1)) / __mmElapsed,
__mmY =
(Number(__mmPlayer.y2) - Number(__mmPlayer.y1)) / __mmElapsed;
return __mmElapsed > 0 &&
__mmElapsed <= 500 &&
Number.isFinite(__mmX) &&
Number.isFinite(__mmY)
? { x: Math.max(-1.5, Math.min(1.5, __mmX)), y: Math.max(-1.5, Math.min(1.5, __mmY)) }
: { x: 0, y: 0 };
}
function __mmProjectileEnemyTarget(__mmProjectile) {
const __mmPlayers = __mmLiveStateFresh() ? __mmLiveState.enemies : E;
if (!__mmProjectile || !Array.isArray(__mmPlayers)) return null;
const __mmX = Number(__mmProjectile.x),
__mmY = Number(__mmProjectile.y),
__mmDirection = Number(__mmProjectile.dir),
__mmSpeed = Number(__mmProjectile.speed),
__mmRange = Number(__mmProjectile.range);
if (
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmDirection) ||
!Number.isFinite(__mmSpeed) ||
__mmSpeed <= 0
)
return null;
let __mmTarget = null,
__mmForwardBest = Infinity;
for (let __mmIndex = 0; __mmIndex < __mmPlayers.length; __mmIndex++) {
const __mmPlayer = __mmPlayers[__mmIndex];
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
let __mmDx = __mmPlayer.x - __mmX,
__mmDy = __mmPlayer.y - __mmY,
__mmForward =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection);
const __mmVelocity = __mmSyncPlayerVelocity(__mmPlayer),
__mmInitialArrival = Math.max(0, __mmForward) / __mmSpeed,
__mmLead = Math.min(400, __mmInitialArrival);
(__mmDx += __mmVelocity.x * __mmLead,
__mmDy += __mmVelocity.y * __mmLead,
(__mmForward =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection)));
const __mmSide = Math.abs(
__mmDx * Math.sin(__mmDirection) -
__mmDy * Math.cos(__mmDirection),
),
__mmHitRadius =
(Number(__mmPlayer.scale) || 35) +
(Number(__mmProjectile.scale) || 0) +
18;
if (
__mmForward < 0 ||
__mmSide > __mmHitRadius ||
(Number.isFinite(__mmRange) && __mmForward > __mmRange + __mmHitRadius) ||
__mmForward >= __mmForwardBest
)
continue;
((__mmTarget = __mmPlayer), (__mmForwardBest = __mmForward));
}
return __mmTarget
? {
target: __mmTarget,
arrivalMs: __mmForwardBest / __mmSpeed,
}
: null;
}
function __mmSyncProjectileWeapons(__mmTarget) {
if (!v || !v.alive || !v.weapons || !__mmTarget) return [];
const __mmDistance = __mmProjectileTravelDistance(v, __mmTarget);
const __mmShots = [],
__mmSeen = new Set();
for (const __mmWeapon of [v.weapons[1], v.weapons[0]]) {
if (__mmWeapon == null || __mmSeen.has(__mmWeapon)) continue;
__mmSeen.add(__mmWeapon);
const __mmWeaponData =
b.weapons[__mmWeapon],
__mmProjectile =
__mmWeaponData && __mmWeaponData.projectile != null
? b.projectiles[__mmWeaponData.projectile]
: null,
__mmSpeed = __mmProjectile && Number(__mmProjectile.speed),
__mmRange = __mmProjectile && Number(__mmProjectile.range);
if (
!__mmWeaponData ||
!__mmProjectile ||
!__mmWeaponReady(__mmWeapon) ||
!Number.isFinite(__mmSpeed) ||
__mmSpeed <= 0 ||
!Number.isFinite(__mmRange) ||
__mmDistance > __mmRange
)
continue;
__mmShots.push({
type: "projectile",
weapon: __mmWeapon,
// A weapon packet normally lands between server updates. Include half a
// tick of launch latency so the arrival scheduler does not fire late.
travelMs:
Math.min(55, __mmServerTickMs() * 0.5) +
__mmDistance / __mmSpeed,
});
}
return __mmShots;
}
function __mmSyncTurretShot(__mmTarget) {
if (
!v ||
!v.alive ||
!__mmTarget ||
!v.skins ||
!v.skins[__mmTurretGear] ||
!__mmInsta.turretReady()
)
return null;
const __mmDistance = __mmProjectileTravelDistance(v, __mmTarget);
if (__mmDistance > __mmTurretGearRange) return null;
// Turret shots use the bullet travel profile. Account for one gear-apply
// tick before its shot can leave the player.
return {
type: "turret",
travelMs: __mmServerTickMs() + __mmDistance / 3.6,
};
}
function __mmSyncShotsForTarget(__mmTarget) {
const __mmTurret = __mmSyncTurretShot(__mmTarget);
return (__mmTurret ? [__mmTurret] : []).concat(
__mmSyncProjectileWeapons(__mmTarget),
);
}
function __mmSyncAimAngle(__mmTarget, __mmTravelMs) {
const __mmVelocity = __mmSyncPlayerVelocity(__mmTarget),
__mmPing = Number(window.pingTime),
__mmLead = Math.min(
450,
Math.max(0, Number(__mmTravelMs) || 0) +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0),
),
__mmTargetX = __mmTarget.x + __mmVelocity.x * __mmLead,
__mmTargetY = __mmTarget.y + __mmVelocity.y * __mmLead;
return Math.atan2(__mmTargetY - v.y, __mmTargetX - v.x);
}
function __mmCanFireInstaSync() {
return !!(
__mmInstaSyncEnabled &&
(__mmActionAvailable("instaSync") ||
__mmActionOwner === "weaponRecharge" ||
__mmActionOwner === "matThief" ||
__mmActionOwner === "mobSteal") &&
v &&
v.alive &&
!__mmInsta.isActive() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
!__mmBuildSpamTimer &&
!__mmFoodSpamTimer &&
!__mmShieldDefenseTimer &&
!__mmInstaSyncFiring
);
}
function __mmFinishInstaSync() {
const __mmTool = __mmInstaSyncRestoreTool,
__mmHat = __mmInstaSyncRestoreHat,
__mmRestore = __mmActionMayRestore("instaSync");
(__mmInstaSyncReleaseTimer && clearTimeout(__mmInstaSyncReleaseTimer),
(__mmInstaSyncReleaseTimer = 0),
__mmInstaSyncWeaponHeld && O.send("F", 0, null),
(__mmInstaSyncWeaponHeld = !1),
(__mmInstaSyncRestoreTool = null),
(__mmInstaSyncRestoreHat = null),
(__mmInstaSyncFiring = !1),
__mmRestore && __mmHat != null && __mmEquipHatNow(__mmHat),
__mmRestore && __mmRestoreTool(__mmTool),
__mmActionRelease("instaSync", "sync shot complete"));
}
function __mmStopInstaSync() {
(__mmInstaSyncTimer && clearTimeout(__mmInstaSyncTimer),
(__mmInstaSyncTimer = 0),
(__mmInstaSyncPending = !1),
__mmFinishInstaSync());
}
function __mmFireInstaSync(__mmShot, __mmTargetSid) {
((__mmInstaSyncTimer = 0), (__mmInstaSyncPending = !1));
let __mmTarget = null;
try {
__mmTarget = Rt(__mmTargetSid);
} catch (__mmLookupError) {}
if (!__mmCanFireInstaSync() || !__mmIsEnemyPlayer(__mmTarget))
return void __mmFinishInstaSync();
const __mmAngle = __mmSyncAimAngle(__mmTarget, __mmShot.travelMs);
((__mmInstaSyncFiring = !0), (__mmInstaSyncLastAt = Date.now()));
__mmSmartPlaceUtilityForInsta(
__mmTarget,
__mmShot.weapon != null ? __mmShot.weapon : v.weapons && v.weapons[0],
);
if (__mmShot.type === "turret") {
((__mmInstaSyncRestoreHat = __mmInstaSafeRestoreHat(
__mmBushRestoreHat(v.skinIndex),
)),
__mmEquipHatNow(__mmTurretGear),
__mmAssumeTurretGearShot(),
O.send("D", __mmAngle),
(__mmInstaSyncReleaseTimer = setTimeout(
__mmFinishInstaSync,
__mmServerTickMs(),
)));
return;
}
if (
__mmShot.weapon == null ||
!__mmWeaponReady(__mmShot.weapon) ||
!v.weapons.includes(__mmShot.weapon)
)
return void __mmFinishInstaSync();
((__mmInstaSyncRestoreTool = __mmSelectedTool()),
je(__mmShot.weapon, !0),
O.send("D", __mmAngle),
O.send("F", 1, __mmAngle),
(__mmInstaSyncWeaponHeld = !0),
(__mmInstaSyncReleaseTimer = setTimeout(
__mmFinishInstaSync,
__mmServerTickMs(),
)));
}
function __mmScheduleInstaSync(__mmProjectile, __mmTargetInfo) {
if (
!__mmCanFireInstaSync() ||
__mmInstaSyncPending ||
Date.now() - __mmInstaSyncLastAt < 45
)
return !1;
const __mmShots = __mmSyncShotsForTarget(__mmTargetInfo.target),
__mmPing = Number(window.pingTime),
__mmOneWayPing = Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0;
let __mmChoice = null;
for (let __mmIndex = 0; __mmIndex < __mmShots.length; __mmIndex++) {
const __mmShot = __mmShots[__mmIndex],
__mmRawDelay =
__mmTargetInfo.arrivalMs - __mmShot.travelMs - __mmOneWayPing;
// Do not schedule a shot that is already meaningfully too late. Among
// viable shots, prefer the one that can leave soonest for less aim drift.
if (__mmRawDelay < -35 || __mmRawDelay > 900) continue;
const __mmDelay = Math.max(0, Math.round(__mmRawDelay));
if (!__mmChoice || __mmDelay < __mmChoice.delay)
__mmChoice = { shot: __mmShot, delay: __mmDelay };
}
if (!__mmChoice) return !1;
if (!__mmActionClaim("instaSync", "friendly projectile")) return !1;
__mmCancelCombatHatLock(!1);
((__mmInstaSyncPending = !0),
__mmChoice.delay <= 1
? __mmFireInstaSync(__mmChoice.shot, __mmTargetInfo.target.sid)
: (__mmInstaSyncTimer = setTimeout(function () {
__mmFireInstaSync(__mmChoice.shot, __mmTargetInfo.target.sid);
}, __mmChoice.delay)));
return !0;
}
function __mmUpdateInstaSync() {
__mmObserveProjectileCooldowns();
if (
(!__mmInstaSyncEnabled && !__mmAutoBowUpgradeInstaEnabled) ||
__mmInstaSyncPending ||
__mmInstaSyncFiring ||
!Array.isArray(Ve)
)
return;
for (let __mmIndex = 0; __mmIndex < Ve.length; __mmIndex++) {
const __mmProjectile = Ve[__mmIndex];
if (!__mmProjectile) continue;
const __mmSid = __mmProjectile.sid,
__mmRange = Number(__mmProjectile.range),
__mmPreviousState = __mmInstaSyncProjectileStates.get(__mmProjectile),
__mmNewGeneration = !!(
__mmProjectile.active &&
(!__mmPreviousState ||
!__mmPreviousState.active ||
(__mmSid != null && String(__mmSid) !== __mmPreviousState.sid) ||
(Number.isFinite(__mmRange) &&
Number.isFinite(__mmPreviousState.range) &&
__mmRange > __mmPreviousState.range + 20))
),
__mmState = __mmNewGeneration
? {
active: !0,
handled: !1,
sid: __mmSid == null ? "" : String(__mmSid),
range: __mmRange,
}
: __mmPreviousState || {
active: !!__mmProjectile.active,
handled: !1,
sid: __mmSid == null ? "" : String(__mmSid),
range: __mmRange,
};
((__mmState.active = !!__mmProjectile.active),
(__mmState.range = __mmRange),
__mmInstaSyncProjectileStates.set(__mmProjectile, __mmState));
if (!__mmProjectile.active || __mmState.handled) continue;
if (
!__mmDirectFriendlyProjectileSource(__mmProjectile) &&
!__mmFriendlyProjectileSource(__mmProjectile) &&
!__mmPersonalTurretProjectileSource(__mmProjectile)
)
continue;
const __mmTargetInfo = __mmProjectileEnemyTarget(__mmProjectile);
if (!__mmTargetInfo) continue;
if (__mmAutoBowUpgradeInstaEnabled) {
const __mmBowReady = __mmBowUpgradeInsta.ready(__mmTargetInfo.target),
__mmMeleeChainReady =
__mmBowReady &&
__mmInsta.supportedPrimary() != null &&
__mmInsta.fullBurstReady(__mmTargetInfo.target, "normal", !1),
__mmBowSyncStarted = __mmMeleeChainReady
? __mmInsta.start({
automatic: !0,
targetSid: __mmTargetInfo.target.sid,
syncScheduled: !0,
profile: "normal",
profileSource: "Friendly projectile + Bow Upgrade",
bowUpgradeFollowup: !0,
})
: __mmBowReady &&
__mmBowUpgradeInsta.start(
__mmTargetInfo.target,
"friendly projectile sync",
);
if (__mmBowSyncStarted) {
__mmState.handled = !0;
return;
}
}
if (__mmScheduleInstaSync(__mmProjectile, __mmTargetInfo)) {
__mmState.handled = !0;
return;
}
}
}
function __mmStartInstaSync() {
__mmEnsureOperationPipeline();
}
function __mmMaxBuildCount(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem];
if (!v || !__mmData || !Array.isArray(__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],
),
);
const __mmGroup = __mmData.group,
__mmGroupId = __mmGroup && __mmGroup.id;
if (__mmGroupId != null) {
const __mmLimit = __mmBuildGroupLimit(__mmData),
__mmPlaced = Number(v.itemCounts && v.itemCounts[__mmGroupId]) || 0;
let __mmReserved = 0;
for (
let __mmReservationIndex = 0;
__mmReservationIndex < __mmAutoSpikeSpamReservations.length;
__mmReservationIndex++
) {
const __mmReservation =
__mmAutoSpikeSpamReservations[__mmReservationIndex],
__mmReservedData =
__mmReservation && b.list[__mmReservation.item];
__mmReservedData &&
__mmReservedData.group &&
__mmReservedData.group.id === __mmGroupId &&
__mmReserved++;
}
__mmLimit &&
(__mmCount = Math.min(
__mmCount,
Math.max(0, __mmLimit - __mmPlaced - __mmReserved),
));
}
return Number.isFinite(__mmCount) ? Math.max(0, __mmCount) : 0;
}
function __mmSmartBuildItem(__mmMatcher) {
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 &&
__mmMatcher(__mmData) &&
__mmCanUseBuildItem(__mmItem) &&
__mmMaxBuildCount(__mmItem) > 0
)
return __mmItem;
}
return null;
}
function __mmSmartPitTrapItem() {
return __mmSmartBuildItem(function (__mmData) {
return !!__mmData.trap;
});
}
function __mmSmartMillItem() {
return __mmSmartBuildItem(function (__mmData) {
return /mill/i.test(String(__mmData.name || ""));
});
}
function __mmSmartNamedItem(__mmName) {
const __mmNeedle = String(__mmName || "").toLowerCase();
return __mmSmartBuildItem(function (__mmData) {
return String(__mmData.name || "").toLowerCase() === __mmNeedle;
});
}
function __mmSmartBlockingObject(__mmX, __mmY, __mmScale) {
const __mmObjects = __mmActiveObjectSnapshot().all;
let __mmClosest = null,
__mmClosestGap = Infinity;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (!__mmObject || !__mmObject.active) continue;
const __mmObjectScale = __mmAutoSpikeSpamObjectScale(__mmObject),
__mmGap =
Math.hypot(
Number(__mmObject.x) - __mmX,
Number(__mmObject.y) - __mmY,
) -
(__mmScale + __mmObjectScale);
if (__mmGap < 0 && __mmGap < __mmClosestGap)
((__mmClosest = __mmObject), (__mmClosestGap = __mmGap));
}
return __mmClosest;
}
function __mmSmartCollisionResult(__mmItem, __mmX, __mmY, __mmScale) {
if (
!y ||
!Number.isFinite(__mmX) ||
!Number.isFinite(__mmY) ||
!Number.isFinite(__mmScale)
)
return { clear: !1, reason: "invalid geometry" };
if (
__mmX - __mmScale < 0 ||
__mmY - __mmScale < 0 ||
__mmX + __mmScale > Number(y.mapScale) ||
__mmY + __mmScale > Number(y.mapScale)
)
return { clear: !1, reason: "map edge" };
if (
Number(__mmItem) !== 18 &&
__mmY >= Number(y.mapScale) / 2 - Number(y.riverWidth) / 2 &&
__mmY <= Number(y.mapScale) / 2 + Number(y.riverWidth) / 2
)
return { clear: !1, reason: "river" };
for (
let __mmIndex = 0;
__mmIndex < __mmAutoSpikeSpamReservations.length;
__mmIndex++
) {
const __mmReservation = __mmAutoSpikeSpamReservations[__mmIndex];
if (
__mmReservation &&
Math.hypot(
Number(__mmReservation.x) - __mmX,
Number(__mmReservation.y) - __mmY,
) <
(Number(__mmReservation.scale) || 0) + __mmScale
)
return { clear: !1, reason: "pending placement" };
}
if (X && typeof X.checkItemLocation === "function")
try {
// The current official client accepts seven arguments. Its seventh is
// retained for compatibility even though the current implementation
// ignores it; the old eighth ge argument never belonged here.
if (
X.checkItemLocation(
__mmX,
__mmY,
__mmScale,
0.6,
__mmItem,
!1,
v,
)
)
return { clear: !0, reason: "legal" };
return { clear: !1, reason: "occupied" };
} catch (__mmSmartLocationError) {}
const __mmFallbackBlocker = __mmSmartBlockingObject(
__mmX,
__mmY,
__mmScale,
);
if (__mmFallbackBlocker) {
const __mmFallbackData =
b && b.list && b.list[__mmFallbackBlocker.id];
return {
clear: !1,
reason: "blocked by " +
String((__mmFallbackData && __mmFallbackData.name) || "structure"),
};
}
return { clear: !0, reason: "legal fallback" };
}
function __mmSmartPositionClear(__mmItem, __mmX, __mmY, __mmScale) {
return __mmSmartCollisionResult(
__mmItem,
__mmX,
__mmY,
__mmScale,
).clear;
}
function __mmSmartSetStatus(__mmState, __mmReason, __mmDetails) {
const __mmInfo = __mmDetails || {},
__mmNow = Date.now();
((__mmSmartPlacementStats.state = String(__mmState || "idle")),
(__mmSmartPlacementStats.reason = String(__mmReason || "waiting")),
Number.isFinite(Number(__mmInfo.legal)) &&
(__mmSmartPlacementStats.legal = Number(__mmInfo.legal)),
Number.isFinite(Number(__mmInfo.scored)) &&
(__mmSmartPlacementStats.scored = Number(__mmInfo.scored)),
Number.isFinite(Number(__mmInfo.blocked)) &&
(__mmSmartPlacementStats.blocked = Number(__mmInfo.blocked)),
typeof __mmInfo.itemSummary === "string" &&
(__mmSmartPlacementStats.itemSummary = __mmInfo.itemSummary),
(__mmSmartPlacementStats.updatedAt = __mmNow));
const __mmSignature = [
__mmSmartPlacementStats.state,
__mmSmartPlacementStats.reason,
__mmSmartPlacementStats.legal,
__mmSmartPlacementStats.scored,
__mmSmartPlacementStats.sent,
__mmSmartPlacementStats.itemSummary,
].join("|");
if (
__mmSignature !== __mmSmartPlacementStats.signature ||
__mmNow - __mmSmartPlacementStats.broadcastAt >= 250
) {
((__mmSmartPlacementStats.signature = __mmSignature),
(__mmSmartPlacementStats.broadcastAt = __mmNow),
window.dispatchEvent(
new CustomEvent("MooMooKittyPlacementStatus", {
detail: {
state: __mmSmartPlacementStats.state,
reason: __mmSmartPlacementStats.reason,
legal: __mmSmartPlacementStats.legal,
scored: __mmSmartPlacementStats.scored,
sent: __mmSmartPlacementStats.sent,
failed: __mmSmartPlacementStats.failed,
blocked: __mmSmartPlacementStats.blocked,
itemSummary: __mmSmartPlacementStats.itemSummary,
},
}),
));
}
}
function __mmSmartSetPlacementPreview(
__mmCandidates,
__mmSelected,
__mmReason,
) {
if (!__mmPlacementVisualsEnabled) return;
const __mmRanked = (Array.isArray(__mmCandidates) ? __mmCandidates : [])
.filter(function (__mmCandidate) {
return __mmCandidate && __mmCandidate.valid !== !1 && __mmCandidate.points > 0;
})
.slice()
.sort(function (__mmLeft, __mmRight) {
return __mmRight.points - __mmLeft.points;
})
.slice(0, __mmFpsBoostEnabled ? 8 : 14);
__mmSmartPlacementPreview = {
samples: __mmSmartPreviewSamples.slice(
0,
__mmFpsBoostEnabled ? 30 : 54,
),
ranked: __mmRanked,
selected: (Array.isArray(__mmSelected) ? __mmSelected : []).slice(0, 4),
reason: String(__mmReason || "scanning"),
updatedAt: performance.now(),
};
}
function __mmSmartCandidateForAngle(
__mmItem,
__mmAngle,
__mmIncludeBlocked,
) {
const __mmData = b && b.list && b.list[__mmItem];
if (!v || !v.alive || !__mmData) return null;
const __mmPlayerX = v.x2 != null && Number.isFinite(Number(v.x2))
? Number(v.x2)
: Number(v.x),
__mmPlayerY = v.y2 != null && Number.isFinite(Number(v.y2))
? Number(v.y2)
: Number(v.y),
__mmScale = Number(__mmData.scale) || 45,
__mmOffset =
(Number(v.scale) || 35) +
__mmScale +
(Number(__mmData.placeOffset) || 0),
__mmX = __mmPlayerX + Math.cos(__mmAngle) * __mmOffset,
__mmY = __mmPlayerY + Math.sin(__mmAngle) * __mmOffset,
__mmCollision = __mmSmartCollisionResult(
__mmItem,
__mmX,
__mmY,
__mmScale,
),
__mmValid = __mmCollision.clear;
if (!__mmValid && !__mmIncludeBlocked) return null;
return {
item: __mmItem,
data: __mmData,
angle: __mmAngle,
x: __mmX,
y: __mmY,
scale: __mmScale,
valid: __mmValid,
blockReason: __mmCollision.reason,
points: 0,
preplace: !1,
priority: !1,
reasons: [],
};
}
function __mmSmartNearestLegalCandidate(
__mmItem,
__mmPreferredAngle,
__mmMaxSweep = 0.7,
__mmStep = 0.045,
) {
const __mmDirect = __mmSmartCandidateForAngle(
__mmItem,
__mmPreferredAngle,
);
if (__mmDirect) return __mmDirect;
const __mmSteps = Math.max(
1,
Math.ceil(Math.max(0, Number(__mmMaxSweep) || 0) /
Math.max(0.015, Number(__mmStep) || 0.045)),
);
for (let __mmIndex = 1; __mmIndex <= __mmSteps; __mmIndex++) {
const __mmOffset = __mmIndex * __mmStep,
__mmLeft = __mmSmartCandidateForAngle(
__mmItem,
__mmPreferredAngle - __mmOffset,
);
if (__mmLeft) return __mmLeft;
const __mmRight = __mmSmartCandidateForAngle(
__mmItem,
__mmPreferredAngle + __mmOffset,
);
if (__mmRight) return __mmRight;
}
return null;
}
function __mmSmartDepthScale() {
// Five is the compatibility midpoint. Lower values spend less CPU; higher
// values search wider and lead farther without changing packet cadence.
return 0.72 + __mmEffectiveSmartDepth() * 0.056;
}
function __mmSmartDepthEnemyLimit() {
return Math.max(1, Math.min(5, Math.ceil(__mmEffectiveSmartDepth() / 2)));
}
function __mmSmartEnemyPrediction(__mmEnemy, __mmNow) {
const __mmSid = String(__mmEnemy.sid),
__mmX = Number(__mmEnemy.x),
__mmY = Number(__mmEnemy.y),
__mmState =
__mmSmartPlacementMotion[__mmSid] ||
(__mmSmartPlacementMotion[__mmSid] = {
x: __mmX,
y: __mmY,
at: __mmNow,
vx: 0,
vy: 0,
});
if (__mmState.x !== __mmX || __mmState.y !== __mmY) {
const __mmElapsed = Math.max(1, Math.min(250, __mmNow - __mmState.at));
((__mmState.vx = (__mmX - __mmState.x) / __mmElapsed),
(__mmState.vy = (__mmY - __mmState.y) / __mmElapsed),
(__mmState.x = __mmX),
(__mmState.y = __mmY),
(__mmState.at = __mmNow));
}
const __mmServerElapsed =
Number(__mmEnemy.t2) - Number(__mmEnemy.t1),
__mmServerVx =
(Number(__mmEnemy.x2) - Number(__mmEnemy.x1)) / __mmServerElapsed,
__mmServerVy =
(Number(__mmEnemy.y2) - Number(__mmEnemy.y1)) / __mmServerElapsed,
__mmHasServerVelocity = !!(
Number.isFinite(__mmServerVx) &&
Number.isFinite(__mmServerVy) &&
__mmServerElapsed > 0 &&
__mmServerElapsed <= 500
);
let __mmVelocityX = __mmHasServerVelocity
? __mmServerVx * 0.68 + __mmState.vx * 0.32
: __mmState.vx,
__mmVelocityY = __mmHasServerVelocity
? __mmServerVy * 0.68 + __mmState.vy * 0.32
: __mmState.vy;
const __mmVelocityLength = Math.hypot(__mmVelocityX, __mmVelocityY),
__mmVelocityClamp = __mmVelocityLength > 0.72
? 0.72 / __mmVelocityLength
: 1;
((__mmVelocityX *= __mmVelocityClamp),
(__mmVelocityY *= __mmVelocityClamp));
const __mmPing = Number(window.pingTime),
__mmLead =
(__mmServerTickMs() +
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing / 2) : 0)) *
__mmSmartDepthScale(),
__mmLeadX = __mmVelocityX * __mmLead,
__mmLeadY = __mmVelocityY * __mmLead,
__mmLeadDistance = Math.hypot(__mmLeadX, __mmLeadY),
__mmLeadClamp = __mmLeadDistance > 170 ? 170 / __mmLeadDistance : 1;
return {
x: __mmX,
y: __mmY,
futureX: __mmX + __mmLeadX * __mmLeadClamp,
futureY: __mmY + __mmLeadY * __mmLeadClamp,
vx: __mmVelocityX,
vy: __mmVelocityY,
speed: Math.hypot(__mmVelocityX, __mmVelocityY),
};
}
function __mmSmartFriendlyHazards() {
const __mmResult = [],
__mmObjects = __mmActiveObjectSnapshot().all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex],
__mmData = __mmObject && b && b.list && b.list[__mmObject.id];
if (
!__mmObject ||
!__mmObject.active ||
!__mmData ||
(!__mmData.trap && !__mmData.dmg && !__mmObject.dmg) ||
!__mmSpikeOwnedByUsOrAlly(__mmObject)
)
continue;
__mmResult.push({
object: __mmObject,
trap: !!__mmData.trap,
spike: !!(__mmData.dmg || __mmObject.dmg),
scale: Number(__mmObject.scale) || Number(__mmData.scale) || 45,
});
}
return __mmResult;
}
// Predictive enemy placement, knockback, angle grading, and automatic
// placement helpers with Kitty ownership and action-priority safeguards.
function __mmSmartEnemyPlacementPotentials(
__mmEnemies,
__mmItem,
__mmNow,
) {
const __mmResult = Object.create(null),
__mmData = b && b.list && b.list[__mmItem];
if (__mmItem == null || !__mmData) return __mmResult;
const __mmScale = Number(__mmData.scale) || 45,
__mmSamples = Math.max(
10,
Math.min(
48,
Math.round((__mmFpsBoostEnabled ? 18 : 28) * __mmSmartDepthScale()),
),
),
__mmEnemyLimit = __mmSmartDepthEnemyLimit();
for (
let __mmEnemyIndex = 0;
__mmEnemyIndex < Math.min(__mmEnemyLimit, __mmEnemies.length);
__mmEnemyIndex++
) {
const __mmEnemy = __mmEnemies[__mmEnemyIndex],
__mmPrediction = __mmSmartEnemyPrediction(__mmEnemy, __mmNow),
__mmRange =
(Number(__mmEnemy.scale) || 35) +
__mmScale +
(Number(__mmData.placeOffset) || 0),
__mmBase = Math.atan2(v.y - __mmEnemy.y, v.x - __mmEnemy.x),
__mmPossible = [];
for (let __mmIndex = 0; __mmIndex < __mmSamples; __mmIndex++) {
const __mmAngle = __mmBase + (__mmIndex * Math.PI * 2) / __mmSamples,
__mmX = __mmPrediction.futureX + Math.cos(__mmAngle) * __mmRange,
__mmY = __mmPrediction.futureY + Math.sin(__mmAngle) * __mmRange;
__mmSmartPositionClear(__mmItem, __mmX, __mmY, __mmScale) &&
__mmPossible.push({
x: __mmX,
y: __mmY,
scale: __mmScale,
angle: __mmAngle,
});
}
__mmResult[String(__mmEnemy.sid)] = {
possible: __mmPossible,
placeRange: __mmRange,
prediction: __mmPrediction,
trap: __mmAutoSpikeSpamTrapForEnemy(__mmEnemy),
};
}
return __mmResult;
}
function __mmSmartKnockIntoHazard(
__mmCandidate,
__mmPrediction,
__mmEnemyScale,
__mmHazards,
) {
const __mmDirection = Math.atan2(
__mmPrediction.futureY - __mmCandidate.y,
__mmPrediction.futureX - __mmCandidate.x,
),
__mmEndX = __mmPrediction.futureX + Math.cos(__mmDirection) * 170,
__mmEndY = __mmPrediction.futureY + Math.sin(__mmDirection) * 170;
let __mmBest = null,
__mmBestAlong = Infinity;
for (
let __mmHazardIndex = 0;
__mmHazardIndex < __mmHazards.length;
__mmHazardIndex++
) {
const __mmHazard = __mmHazards[__mmHazardIndex],
__mmDx = Number(__mmHazard.object.x) - __mmPrediction.futureX,
__mmDy = Number(__mmHazard.object.y) - __mmPrediction.futureY,
__mmAlong =
__mmDx * Math.cos(__mmDirection) +
__mmDy * Math.sin(__mmDirection),
__mmRadius = __mmEnemyScale + __mmHazard.scale + 3;
if (
__mmAlong < 0 ||
__mmAlong > 180 ||
__mmSegmentDistanceSquared(
__mmPrediction.futureX,
__mmPrediction.futureY,
__mmEndX,
__mmEndY,
Number(__mmHazard.object.x),
Number(__mmHazard.object.y),
) >
__mmRadius * __mmRadius ||
__mmAlong >= __mmBestAlong
)
continue;
((__mmBestAlong = __mmAlong),
(__mmBest = {
hazard: __mmHazard,
along: __mmAlong,
bounce: !!(__mmHazard.spike && __mmAlong >= 50 && __mmAlong <= 150),
}));
}
return __mmBest;
}
function __mmSmartScoreCandidate(
__mmCandidate,
__mmEnemies,
__mmHazards,
__mmNow,
__mmEnemyPotentials,
) {
const __mmIsTrap = !!__mmCandidate.data.trap,
__mmIsSpike = !!(
__mmCandidate.data.dmg ||
/spike/i.test(String(__mmCandidate.data.name || ""))
);
for (let __mmIndex = 0; __mmIndex < __mmEnemies.length; __mmIndex++) {
const __mmEnemy = __mmEnemies[__mmIndex],
__mmPlacementPotential =
__mmEnemyPotentials && __mmEnemyPotentials[String(__mmEnemy.sid)],
__mmPrediction =
(__mmPlacementPotential && __mmPlacementPotential.prediction) ||
__mmSmartEnemyPrediction(__mmEnemy, __mmNow),
__mmEnemyScale = Number(__mmEnemy.scale) || 35,
__mmCurrentDistance = Math.hypot(
__mmPrediction.x - __mmCandidate.x,
__mmPrediction.y - __mmCandidate.y,
),
__mmFutureDistance = Math.hypot(
__mmPrediction.futureX - __mmCandidate.x,
__mmPrediction.futureY - __mmCandidate.y,
),
__mmRouteDistance = Math.sqrt(
__mmSegmentDistanceSquared(
__mmPrediction.x,
__mmPrediction.y,
__mmPrediction.futureX,
__mmPrediction.futureY,
__mmCandidate.x,
__mmCandidate.y,
),
),
__mmTouch = __mmEnemyScale + __mmCandidate.scale,
__mmTrap = __mmPlacementPotential
? __mmPlacementPotential.trap
: __mmAutoSpikeSpamTrapForEnemy(__mmEnemy),
__mmEnemyDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y);
if (__mmEnemyDistance > 350) continue;
if (__mmIsSpike && __mmSmartSpikeContactEnabled) {
if (__mmCurrentDistance <= __mmTouch + 3) {
((__mmCandidate.points += 3),
__mmCandidate.reasons.push("spike contact"));
} else if (
__mmSmartPreplaceEnabled &&
Math.min(__mmFutureDistance, __mmRouteDistance) <= __mmTouch + 5
) {
((__mmCandidate.points += 3.5),
(__mmCandidate.preplace = !0),
(__mmCandidate.priority = !0),
__mmCandidate.reasons.push("predicted spike contact"));
}
}
if (__mmIsTrap && __mmSmartTrapContactEnabled) {
if (__mmCurrentDistance <= 235 && !__mmTrap) {
((__mmCandidate.points += 1),
__mmCandidate.reasons.push("trap pressure"));
}
if (__mmCurrentDistance <= 20.4) {
((__mmCandidate.points += 1),
(__mmCandidate.priority = !0),
__mmCandidate.reasons.push("placement denial"));
}
if (__mmCurrentDistance <= 50) {
((__mmCandidate.points += __mmTrap ? 5 : 3),
__mmCandidate.reasons.push(__mmTrap ? "retrap" : "trap contact"));
} else if (
__mmSmartPreplaceEnabled &&
Math.min(__mmFutureDistance, __mmRouteDistance) <= 52
) {
((__mmCandidate.points += 3.5),
(__mmCandidate.preplace = !0),
(__mmCandidate.priority = !0),
__mmCandidate.reasons.push("predicted trap"));
}
}
if (__mmSmartAngleDenialEnabled && __mmCurrentDistance <= 235) {
let __mmInterceptsPlacement = !1;
const __mmPossible =
__mmPlacementPotential && __mmPlacementPotential.possible;
if (Array.isArray(__mmPossible))
for (
let __mmPotentialIndex = 0;
__mmPotentialIndex < __mmPossible.length;
__mmPotentialIndex++
) {
const __mmPotential = __mmPossible[__mmPotentialIndex];
if (
Math.hypot(
__mmCandidate.x - __mmPotential.x,
__mmCandidate.y - __mmPotential.y,
) <=
__mmCandidate.scale + __mmPotential.scale
) {
__mmInterceptsPlacement = !0;
break;
}
}
if (__mmInterceptsPlacement) {
((__mmCandidate.points += 1),
(__mmCandidate.priority = !0),
__mmCandidate.reasons.push("enemy-angle block"));
} else if (
__mmPlacementPotential &&
__mmCurrentDistance <= __mmPlacementPotential.placeRange
) {
((__mmCandidate.points += 0.5),
__mmCandidate.reasons.push("angle abuse"));
}
}
if (__mmTrap && __mmIsSpike && __mmSmartTrapSurroundEnabled) {
const __mmTrapDistance = Math.hypot(
__mmCandidate.x - __mmTrap.x,
__mmCandidate.y - __mmTrap.y,
),
__mmAwayFromUs = Math.abs(
Math.atan2(
Math.sin(
__mmCandidate.angle -
Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
),
Math.cos(
__mmCandidate.angle -
Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
),
),
);
if (__mmTrapDistance <= 50 + __mmCandidate.scale + 24) {
((__mmCandidate.points += 2),
__mmCandidate.reasons.push("trapped surround"));
__mmAwayFromUs >= 1.5 && (__mmCandidate.points += 2);
}
}
if (
__mmIsSpike &&
__mmSmartKnockbackChainEnabled &&
__mmCurrentDistance <= __mmTouch + 5
) {
const __mmKnock = __mmSmartKnockIntoHazard(
__mmCandidate,
__mmPrediction,
__mmEnemyScale,
__mmHazards,
);
if (__mmKnock) {
((__mmCandidate.points += __mmKnock.hazard.trap
? 2.5
: __mmKnock.bounce
? 5
: 3),
(__mmCandidate.priority = !0),
(__mmCandidate.knockInto = __mmKnock),
__mmCandidate.reasons.push(
__mmKnock.hazard.trap
? "knock into trap"
: __mmKnock.bounce
? "spike bounce chain"
: "spike chain",
));
}
}
if (__mmIsTrap && __mmSmartAutoPushWeightEnabled)
for (let __mmHazardIndex = 0; __mmHazardIndex < __mmHazards.length; __mmHazardIndex++) {
const __mmHazard = __mmHazards[__mmHazardIndex];
if (
__mmHazard.spike &&
Math.hypot(
__mmCandidate.x - __mmHazard.object.x,
__mmCandidate.y - __mmHazard.object.y,
) <=
__mmCandidate.scale + __mmHazard.scale + 24
) {
((__mmCandidate.points += 2),
__mmCandidate.reasons.push("auto-push trap"));
break;
}
}
}
if (__mmSmartReplacePoint) {
const __mmReplaceDistance = Math.hypot(
__mmCandidate.x - __mmSmartReplacePoint.x,
__mmCandidate.y - __mmSmartReplacePoint.y,
);
if (__mmReplaceDistance <= __mmCandidate.scale + 55) {
((__mmCandidate.points += 6),
(__mmCandidate.priority = !0),
__mmCandidate.reasons.push("replace"));
if (
__mmSmartSpikeSyncPlaceEnabled &&
__mmSmartReplacePoint.trap &&
__mmIsSpike
)
((__mmCandidate.points += 5),
__mmCandidate.reasons.push("spike sync"));
}
}
return __mmCandidate;
}
function __mmSmartPlacementCandidates(
__mmItem,
__mmEnemies,
__mmHazards,
__mmNow,
__mmEnemyPotentials,
) {
if (__mmItem == null) return [];
const __mmResult = [],
__mmSamples = Math.max(
24,
Math.min(
360,
Math.round(__mmSmartPlaceAccuracy * 2 * __mmSmartDepthScale()),
),
),
__mmPreviewStride = Math.max(
1,
Math.ceil(__mmSamples / (__mmFpsBoostEnabled ? 15 : 27)),
),
__mmBase = __mmEnemies.length
? Math.atan2(__mmEnemies[0].y - v.y, __mmEnemies[0].x - v.x)
: 0;
for (let __mmIndex = 0; __mmIndex < __mmSamples; __mmIndex++) {
const __mmAngle = __mmBase + (__mmIndex * Math.PI * 2) / __mmSamples,
__mmCandidate = __mmSmartCandidateForAngle(
__mmItem,
__mmAngle,
__mmPlacementVisualsEnabled,
);
if (
__mmCandidate &&
__mmPlacementVisualsEnabled &&
__mmIndex % __mmPreviewStride === 0
)
__mmSmartPreviewSamples.push(__mmCandidate);
__mmCandidate && __mmCandidate.valid &&
__mmResult.push(
__mmSmartScoreCandidate(
__mmCandidate,
__mmEnemies,
__mmHazards,
__mmNow,
__mmEnemyPotentials,
),
);
}
return __mmResult;
}
function __mmSmartApplyCorePressureFallback(
__mmCandidates,
__mmEnemies,
__mmNow,
) {
if (
!__mmCandidates.length ||
!__mmEnemies.length ||
__mmCandidates.some(function (__mmCandidate) {
return __mmCandidate && __mmCandidate.points > 0;
})
)
return !1;
const __mmEnemy = __mmEnemies[0],
__mmEnemyDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y);
if (!Number.isFinite(__mmEnemyDistance) || __mmEnemyDistance > 335)
return !1;
const __mmPrediction = __mmSmartEnemyPrediction(__mmEnemy, __mmNow),
__mmEnemyScale = Number(__mmEnemy.scale) || 35;
let __mmBest = null,
__mmBestMetric = Infinity;
for (
let __mmCandidateIndex = 0;
__mmCandidateIndex < __mmCandidates.length;
__mmCandidateIndex++
) {
const __mmCandidate = __mmCandidates[__mmCandidateIndex];
if (!__mmCandidate || !__mmCandidate.valid) continue;
const __mmIsTrap = !!__mmCandidate.data.trap,
__mmIsSpike = !!(
__mmCandidate.data.dmg ||
/spike/i.test(String(__mmCandidate.data.name || ""))
),
__mmCurrentDistance = Math.hypot(
__mmEnemy.x - __mmCandidate.x,
__mmEnemy.y - __mmCandidate.y,
),
__mmFutureDistance = Math.hypot(
__mmPrediction.futureX - __mmCandidate.x,
__mmPrediction.futureY - __mmCandidate.y,
),
__mmRouteDistance = Math.sqrt(
__mmSegmentDistanceSquared(
__mmEnemy.x,
__mmEnemy.y,
__mmPrediction.futureX,
__mmPrediction.futureY,
__mmCandidate.x,
__mmCandidate.y,
),
),
__mmMetric = Math.min(
__mmCurrentDistance,
__mmFutureDistance,
__mmRouteDistance,
),
__mmUseful = __mmIsTrap
? __mmMetric <= 255
: __mmIsSpike &&
__mmEnemyDistance <= 215 &&
__mmMetric <= __mmEnemyScale + __mmCandidate.scale + 28;
if (!__mmUseful || __mmMetric >= __mmBestMetric) continue;
((__mmBest = __mmCandidate), (__mmBestMetric = __mmMetric));
}
if (!__mmBest) return !1;
((__mmBest.points = __mmBest.data.trap ? 1.15 : 1.35),
(__mmBest.priority = !0),
// The fallback is already the closest legal pressure slot. Send it on the
// current placement phase instead of turning a weak prediction into an
// extra user-configured pre-place delay.
(__mmBest.preplace = !1),
__mmBest.reasons.push("core pressure fallback"));
return !0;
}
function __mmAutomaticQuadPlacementEnabled() {
return !!(__mmSmartQuadTrapsEnabled || __mmSmartQuadSpikesEnabled);
}
function __mmAutomaticQuadCandidateEnabled(__mmCandidate) {
const __mmData = __mmCandidate && __mmCandidate.data;
if (!__mmData) return !1;
if (__mmData.trap) return __mmSmartQuadTrapsEnabled;
return !!(
__mmSmartQuadSpikesEnabled &&
(__mmData.dmg || /spike/i.test(String(__mmData.name || "")))
);
}
function __mmSmartQuadTrapCandidates(
__mmCandidates,
__mmEnemies,
__mmNow,
) {
if (
!__mmSmartQuadTrapsEnabled ||
!__mmCandidates.length ||
!__mmEnemies.length
)
return [];
const __mmEnemy = __mmEnemies[0],
__mmEnemyDistance = Math.hypot(
Number(__mmEnemy.x) - Number(v.x),
Number(__mmEnemy.y) - Number(v.y),
);
if (
!Number.isFinite(__mmEnemyDistance) ||
__mmEnemyDistance > 450
)
return [];
const __mmPrediction = __mmSmartEnemyPrediction(__mmEnemy, __mmNow);
const __mmTrapCandidates = [];
for (
let __mmCandidateIndex = 0;
__mmCandidateIndex < __mmCandidates.length;
__mmCandidateIndex++
) {
const __mmCandidate = __mmCandidates[__mmCandidateIndex];
if (
!__mmCandidate ||
!__mmCandidate.valid ||
!(__mmCandidate.data && __mmCandidate.data.trap)
)
continue;
const __mmCurrentDistance = Math.hypot(
Number(__mmEnemy.x) - __mmCandidate.x,
Number(__mmEnemy.y) - __mmCandidate.y,
),
__mmFutureDistance = Math.hypot(
__mmPrediction.futureX - __mmCandidate.x,
__mmPrediction.futureY - __mmCandidate.y,
),
__mmRouteDistance = Math.sqrt(
__mmSegmentDistanceSquared(
__mmPrediction.x,
__mmPrediction.y,
__mmPrediction.futureX,
__mmPrediction.futureY,
__mmCandidate.x,
__mmCandidate.y,
),
),
__mmPressureDistance = Math.min(
__mmCurrentDistance,
__mmFutureDistance,
__mmRouteDistance,
);
// Full-place keeps every legal trap in the ranked pool. Direct contact,
// retrap, pre-place, and angle denial retain their stronger score; empty
// legal slots receive only a small fill score so they can complete the
// non-overlapping four-slot pattern after the important angles.
if (__mmCandidate.points <= 0)
__mmCandidate.points =
0.62 + Math.max(0, 450 - __mmPressureDistance) / 2000;
__mmCandidate.reasons.includes("quad trap fill") ||
__mmCandidate.reasons.push("quad trap fill");
__mmTrapCandidates.push(__mmCandidate);
}
return __mmTrapCandidates;
}
function __mmSmartQuadSpikeCandidates(
__mmCandidates,
__mmEnemies,
__mmNow,
) {
if (
!__mmSmartQuadSpikesEnabled ||
!__mmCandidates.length ||
!__mmEnemies.length
)
return [];
const __mmEnemy = __mmEnemies[0],
__mmEnemyDistance = Math.hypot(
Number(__mmEnemy.x) - Number(v.x),
Number(__mmEnemy.y) - Number(v.y),
);
if (!Number.isFinite(__mmEnemyDistance) || __mmEnemyDistance > 450) return [];
const __mmPrediction = __mmSmartEnemyPrediction(__mmEnemy, __mmNow),
__mmTrap = __mmAutoSpikeSpamTrapForEnemy(__mmEnemy),
__mmToward = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
__mmMovementToward =
typeof Kt === "number" &&
Math.abs(Math.atan2(Math.sin(Kt - __mmToward), Math.cos(Kt - __mmToward))) <=
Math.PI / 3,
// Require either contact/retrap pressure or an aggressive close-range
// approach so automatic quad spikes do not waste four structures on passersby.
__mmAggressive = !!(
__mmTrap ||
__mmMovementToward ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmEnemyDistance <= 175
),
__mmSpikeCandidates = [];
if (!__mmAggressive) return [];
for (
let __mmCandidateIndex = 0;
__mmCandidateIndex < __mmCandidates.length;
__mmCandidateIndex++
) {
const __mmCandidate = __mmCandidates[__mmCandidateIndex];
if (
!__mmCandidate ||
!__mmCandidate.valid ||
!__mmCandidate.data ||
!(
__mmCandidate.data.dmg ||
/spike/i.test(String(__mmCandidate.data.name || ""))
)
)
continue;
const __mmTouch =
(Number(__mmEnemy.scale) || 35) + Number(__mmCandidate.scale || 0),
__mmCurrentDistance = Math.hypot(
Number(__mmEnemy.x) - __mmCandidate.x,
Number(__mmEnemy.y) - __mmCandidate.y,
),
__mmFutureDistance = Math.hypot(
__mmPrediction.futureX - __mmCandidate.x,
__mmPrediction.futureY - __mmCandidate.y,
),
__mmRouteDistance = Math.sqrt(
__mmSegmentDistanceSquared(
__mmPrediction.x,
__mmPrediction.y,
__mmPrediction.futureX,
__mmPrediction.futureY,
__mmCandidate.x,
__mmCandidate.y,
),
),
__mmPressureDistance = Math.min(
__mmCurrentDistance,
__mmFutureDistance,
__mmRouteDistance,
);
if (__mmCandidate.points <= 0 && __mmPressureDistance > __mmTouch + 55)
continue;
if (__mmCandidate.points <= 0)
__mmCandidate.points =
0.72 + Math.max(0, __mmTouch + 55 - __mmPressureDistance) / 120;
__mmTrap && (__mmCandidate.points += 1.5);
__mmCandidate.reasons.includes("quad spike fill") ||
__mmCandidate.reasons.push("quad spike fill");
__mmSpikeCandidates.push(__mmCandidate);
}
return __mmSpikeCandidates;
}
function __mmManualQuadPlacement(__mmKind) {
const __mmIsTrap = __mmKind === "trap";
if (
!v ||
!v.alive ||
(__mmIsTrap ? !__mmSmartQuadTrapsEnabled : !__mmSmartQuadSpikesEnabled) ||
!__mmActionCanPreempt("smartAutoPlace")
)
return !1;
const __mmItem = __mmIsTrap ? __mmSmartPitTrapItem() : __mmSpikeItem();
if (
__mmItem == null ||
!__mmCanUseBuildItem(__mmItem) ||
__mmMaxBuildCount(__mmItem) < 1
)
return !1;
const __mmTarget = __mmNearestEnemy(),
__mmNow = Date.now(),
__mmEnemies = __mmTarget ? [__mmTarget] : [],
__mmHazards = __mmSmartFriendlyHazards(),
__mmPotentials = __mmTarget
? __mmSmartEnemyPlacementPotentials(__mmEnemies, __mmItem, __mmNow)
: Object.create(null),
__mmPreferred = __mmTarget
? Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x)
: __mmRawMouseAimDirection(),
__mmCandidates = __mmSmartPlacementCandidates(
__mmItem,
__mmEnemies,
__mmHazards,
__mmNow,
__mmPotentials,
);
for (let __mmIndex = 0; __mmIndex < __mmCandidates.length; __mmIndex++) {
const __mmCandidate = __mmCandidates[__mmIndex],
__mmAngleDistance = Math.abs(
Math.atan2(
Math.sin(__mmCandidate.angle - __mmPreferred),
Math.cos(__mmCandidate.angle - __mmPreferred),
),
);
if (__mmCandidate.points <= 0)
__mmCandidate.points = 0.55 + (Math.PI - __mmAngleDistance) / (Math.PI * 20);
__mmCandidate.reasons.push(
__mmIsTrap ? "manual quad trap" : "manual quad spike",
);
}
const __mmPlaced = __mmSmartPlaceBatch(
__mmCandidates,
__mmIsTrap ? "manual quad traps" : "manual quad spikes",
4,
);
__mmPlaced &&
__mmShowInstaTypePopup(__mmIsTrap ? "Quad Traps" : "Quad Spikes");
return __mmPlaced > 0;
}
function __mmBoostSpikePlacementCandidates(__mmTarget, __mmSpike, __mmNow) {
const __mmEnemies = [__mmTarget],
__mmCandidates = __mmSmartPlacementCandidates(
__mmSpike,
__mmEnemies,
__mmSmartFriendlyHazards(),
__mmNow,
__mmSmartEnemyPlacementPotentials(__mmEnemies, __mmSpike, __mmNow),
),
__mmPrediction = __mmSmartEnemyPrediction(__mmTarget, __mmNow),
__mmBase = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x),
__mmResult = [];
for (let __mmIndex = 0; __mmIndex < __mmCandidates.length; __mmIndex++) {
const __mmCandidate = __mmCandidates[__mmIndex],
__mmTouch =
(Number(__mmTarget.scale) || 35) + Number(__mmCandidate.scale || 0),
__mmPressure = Math.min(
Math.hypot(__mmTarget.x - __mmCandidate.x, __mmTarget.y - __mmCandidate.y),
Math.hypot(
__mmPrediction.futureX - __mmCandidate.x,
__mmPrediction.futureY - __mmCandidate.y,
),
),
__mmRelative = Math.abs(
Math.atan2(
Math.sin(__mmCandidate.angle - __mmBase),
Math.cos(__mmCandidate.angle - __mmBase),
),
),
__mmSideDistance = Math.abs(__mmRelative - Math.PI / 2),
__mmContact = __mmPressure <= __mmTouch + 16,
__mmSideLane = __mmSideDistance <= 0.24;
if (!__mmContact && !__mmSideLane && !__mmCandidate.knockInto) continue;
(__mmCandidate.points +=
(__mmContact ? 6 : 0) +
(__mmSideLane ? 3 : 0) +
(__mmCandidate.knockInto ? 4 : 0),
__mmCandidate.reasons.push(
__mmContact ? "boost-spike contact" : "boost-spike side lane",
),
__mmResult.push(__mmCandidate));
}
return __mmResult;
}
function __mmBoostSpikeScanMs() {
return Math.max(8, Math.min(12, __mmFastCheckMs()));
}
function __mmBoostSpikeBurstCooldownMs() {
// Scan continuously, but keep successful multi-place bursts bounded. At the
// normal 9 Hz server rate this permits the newly opened lane to be used in
// about half a tick instead of waiting for the next full 111 ms interval.
return Math.max(32, Math.min(55, __mmServerTickMs() * 0.48));
}
function __mmBoostSpikeBurst() {
const __mmNow = Date.now();
if (
!__mmBoostSpikeEnabled ||
!v ||
!v.alive ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmIsTrapped() ||
__mmHoldingMcGrabby() ||
__mmEmergencyGetawayActive() ||
__mmNow - __mmBoostSpikeLastAt < __mmBoostSpikeBurstCooldownMs() ||
!__mmActionCanPreempt("boostSpike")
)
return !1;
const __mmTarget = __mmNearestEnemy(),
__mmSpike = __mmSpikeItem(),
__mmPad = __mmBoostPadItem();
if (
!__mmTarget ||
__mmSpike == null ||
__mmPad == null ||
!__mmCanUseBuildItem(__mmSpike) ||
!__mmCanUseBuildItem(__mmPad) ||
__mmMaxBuildCount(__mmSpike) < 1 ||
__mmMaxBuildCount(__mmPad) < 1 ||
Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y) > 420 ||
!__mmActionClaim("boostSpike", "predictive boost-spike")
)
return !1;
const __mmDirection = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x),
__mmTool = __mmSelectedTool(),
__mmDistance = Math.hypot(__mmTarget.x - v.x, __mmTarget.y - v.y),
__mmSpikeLimit = Math.min(
__mmDistance <= 175 ? 4 : 2,
__mmMaxBuildCount(__mmSpike),
),
__mmCandidates = __mmBoostSpikePlacementCandidates(
__mmTarget,
__mmSpike,
__mmNow,
),
__mmPadCandidate = __mmSmartNearestLegalCandidate(
__mmPad,
__mmDirection,
0.48,
0.035,
),
__mmCompatibleCandidates = __mmPadCandidate
? __mmCandidates.filter(function (__mmCandidate) {
return (
Math.hypot(
__mmCandidate.x - __mmPadCandidate.x,
__mmCandidate.y - __mmPadCandidate.y,
) >=
__mmCandidate.scale + __mmPadCandidate.scale
);
})
: [],
__mmSelected = __mmSmartBestCombination(
__mmCompatibleCandidates,
__mmSpikeLimit,
);
if (!__mmSelected.length || !__mmPadCandidate) {
if (Number.isFinite(__mmBoostSpikeMoveAngle)) {
const __mmTurn = Math.abs(
Math.atan2(
Math.sin(__mmDirection - __mmBoostSpikeMoveAngle),
Math.cos(__mmDirection - __mmBoostSpikeMoveAngle),
),
);
if (__mmTurn > 0.025) {
((__mmBoostSpikeMoveAngle = __mmDirection),
(Kt = __mmDirection),
O.send("9", __mmDirection),
O.send("D", __mmDirection));
}
}
(__mmActionRelease("boostSpike", "no legal boost-spike pattern"),
__mmSmartSetPlacementPreview(
__mmCandidates.concat(__mmPadCandidate ? [__mmPadCandidate] : []),
[],
"no legal boost-spike pattern",
));
return !1;
}
let __mmPlaced = 0;
(O.send("D", __mmDirection),
(__mmBoostSpikeMoveAngle = __mmDirection),
(Kt = __mmDirection),
O.send("9", __mmDirection));
for (let __mmIndex = 0; __mmIndex < __mmSelected.length; __mmIndex++)
__mmSmartPlaceNow(__mmSelected[__mmIndex], __mmTool) && __mmPlaced++;
if (__mmPadCandidate && __mmSmartPlaceNow(__mmPadCandidate, __mmTool))
__mmPlaced++;
(__mmPlaced && (__mmBoostSpikeLastAt = __mmNow),
__mmSmartSetPlacementPreview(
__mmCandidates.concat(__mmPadCandidate ? [__mmPadCandidate] : []),
__mmSelected.concat(__mmPadCandidate ? [__mmPadCandidate] : []),
"predictive boost-spike",
),
__mmPlaced && __mmShowInstaTypePopup("Boost + Spike"),
__mmActionRelease("boostSpike", "boost-spike packets sent"),
__mmScheduleMouseAimReturn());
return __mmPlaced > 0;
}
function __mmStartBoostSpike() {
if (!__mmBoostSpikeEnabled || __mmBoostSpikeTimer) return;
(__mmBoostSpikeBurst(),
(__mmBoostSpikeTimer = setInterval(
__mmBoostSpikeBurst,
__mmBoostSpikeScanMs(),
)));
}
function __mmStopBoostSpike() {
(__mmBoostSpikeTimer && clearInterval(__mmBoostSpikeTimer),
(__mmBoostSpikeTimer = 0),
(__mmBoostSpikeMoveAngle = null));
if (__mmActionOwner === "boostSpike")
__mmActionRelease("boostSpike", "boost-spike released");
if (v && v.alive) {
Kt = null;
typeof Tt === "function" && Tt();
__mmScheduleMouseAimReturn();
}
}
function __mmSmartPlaceNow(
__mmCandidate,
__mmOriginalTool,
__mmReservedSlot,
) {
if (
!__mmCandidate ||
!__mmCanUseBuildItem(__mmCandidate.item) ||
(!__mmReservedSlot && __mmMaxBuildCount(__mmCandidate.item) < 1)
)
return !1;
const __mmFresh = __mmSmartCandidateForAngle(
__mmCandidate.item,
__mmCandidate.angle,
);
if (!__mmFresh) return !1;
try {
if (
!__mmSendAutomaticPlacement(
__mmCandidate.item,
__mmCandidate.angle,
__mmOriginalTool,
__mmReservedSlot,
)
)
return !1;
(
__mmAutoSpikeSpamReservations.push({
item: __mmCandidate.item,
x: __mmFresh.x,
y: __mmFresh.y,
scale: __mmFresh.scale,
expiresAt: Date.now() + 650,
}),
(__mmSmartPlacementStats.sent += 1));
return !0;
} catch (__mmSmartPlaceError) {
__mmSmartPlacementStats.failed += 1;
return !1;
}
}
// A placement phase is one packet burst, not a sequence of unrelated clicks.
// Select/place each legal entry, then restore the borrowed tool only once after
// the final entry. This keeps the later angles in an automatic quad from being
// interrupted by weapon restore, held-click resume, or another pipeline owner.
function __mmSmartPlaceBurst(__mmCandidates, __mmOriginalTool) {
if (!Array.isArray(__mmCandidates) || !__mmCandidates.length) return 0;
const __mmRestore = __mmOriginalTool || __mmSelectedTool(),
__mmPlaced = [];
try {
for (let __mmIndex = 0; __mmIndex < __mmCandidates.length; __mmIndex++) {
const __mmCandidate = __mmCandidates[__mmIndex];
if (
!__mmCandidate ||
!__mmCanUseBuildItem(__mmCandidate.item) ||
__mmMaxBuildCount(__mmCandidate.item) < 1
)
continue;
const __mmFresh = __mmSmartCandidateForAngle(
__mmCandidate.item,
__mmCandidate.angle,
);
if (!__mmFresh) continue;
(je(__mmCandidate.item), O.send("F", 1, __mmCandidate.angle));
(__mmAutoSpikeSpamReservations.push({
item: __mmCandidate.item,
x: __mmFresh.x,
y: __mmFresh.y,
scale: __mmFresh.scale,
expiresAt: Date.now() + 650,
}),
__mmPlaced.push(__mmFresh),
(__mmSmartPlacementStats.sent += 1));
}
} catch (__mmSmartBurstError) {
__mmSmartPlacementStats.failed += 1;
} finally {
try {
__mmRestore && __mmRestore.weapon
? __mmRestoreTool(__mmRestore)
: (O.send(
"F",
0,
__mmPlaced.length
? __mmPlaced[__mmPlaced.length - 1].angle
: Ci(),
),
__mmRestore && __mmRestoreTool(__mmRestore));
(__mmResumeHeldAttack(), __mmScheduleMouseAimReturn());
} catch (__mmSmartBurstRestoreError) {}
}
return __mmPlaced.length;
}
function __mmSmartReserveCandidateCost(
__mmCandidate,
__mmResourceUse,
__mmGroupUse,
) {
const __mmData = __mmCandidate && __mmCandidate.data;
if (
!v ||
!__mmData ||
!__mmData.req ||
!Number.isFinite(Number(__mmData.req.length))
)
return !1;
for (
let __mmReqIndex = 0;
__mmReqIndex < __mmData.req.length;
__mmReqIndex += 2
) {
const __mmResource = String(__mmData.req[__mmReqIndex]),
__mmCost = Number(__mmData.req[__mmReqIndex + 1]) || 0,
__mmUsed = Number(__mmResourceUse[__mmResource]) || 0;
if ((Number(v[__mmResource]) || 0) - __mmUsed < __mmCost) return !1;
}
const __mmGroup = __mmData.group,
__mmGroupId = __mmGroup && __mmGroup.id;
if (__mmGroupId != null) {
const __mmLimit = __mmBuildGroupLimit(__mmData),
__mmPlaced = Number(v.itemCounts && v.itemCounts[__mmGroupId]) || 0,
__mmReserved = Number(__mmGroupUse[String(__mmGroupId)]) || 0;
if (__mmLimit && __mmPlaced + __mmReserved >= __mmLimit) return !1;
}
for (
let __mmReqIndex = 0;
__mmReqIndex < __mmData.req.length;
__mmReqIndex += 2
) {
const __mmResource = String(__mmData.req[__mmReqIndex]),
__mmCost = Number(__mmData.req[__mmReqIndex + 1]) || 0;
__mmResourceUse[__mmResource] =
(Number(__mmResourceUse[__mmResource]) || 0) + __mmCost;
}
__mmGroupId != null &&
(__mmGroupUse[String(__mmGroupId)] =
(Number(__mmGroupUse[String(__mmGroupId)]) || 0) + 1);
return !0;
}
function __mmSmartBestCombination(__mmCandidates, __mmLimit) {
const __mmPool = __mmCandidates
.filter(function (__mmCandidate) {
return __mmCandidate && __mmCandidate.points > 0;
})
.slice()
.sort(function (__mmLeft, __mmRight) {
const __mmPointDifference = __mmRight.points - __mmLeft.points;
if (__mmPointDifference) return __mmPointDifference;
if (!!__mmRight.priority !== !!__mmLeft.priority)
return Number(!!__mmRight.priority) - Number(!!__mmLeft.priority);
return Number(!!(__mmRight.data && __mmRight.data.trap)) -
Number(!!(__mmLeft.data && __mmLeft.data.trap));
}),
__mmSelected = [],
__mmResources = Object.create(null),
__mmGroups = Object.create(null),
__mmMax = Math.max(1, Math.min(4, Math.round(Number(__mmLimit) || 1)));
// Full-place scans the complete ranked list and greedily retains the
// first four non-overlapping builds. Kitty's old 18/24-candidate truncation
// kept only a tight high-score cluster, so every later candidate overlapped
// the first and the intended quad trap silently collapsed to one placement.
for (let __mmIndex = 0; __mmIndex < __mmPool.length; __mmIndex++) {
const __mmCandidate = __mmPool[__mmIndex];
if (
__mmSelected.some(function (__mmPlaced) {
return (
Math.hypot(
__mmPlaced.x - __mmCandidate.x,
__mmPlaced.y - __mmCandidate.y,
) <
__mmPlaced.scale + __mmCandidate.scale
);
})
)
continue;
const __mmNextResources = { ...__mmResources },
__mmNextGroups = { ...__mmGroups };
if (
!__mmSmartReserveCandidateCost(
__mmCandidate,
__mmNextResources,
__mmNextGroups,
)
)
continue;
for (const __mmResource in __mmNextResources)
__mmResources[__mmResource] = __mmNextResources[__mmResource];
for (const __mmGroup in __mmNextGroups)
__mmGroups[__mmGroup] = __mmNextGroups[__mmGroup];
__mmSelected.push(__mmCandidate);
if (__mmSelected.length >= __mmMax) break;
}
return __mmSelected;
}
function __mmSmartPlaceBatch(__mmCandidates, __mmReason, __mmForcedLimit) {
if (!__mmCandidates.length) {
__mmSmartSetPlacementPreview([], [], __mmReason || "no legal slots");
__mmSmartSetStatus("blocked", __mmReason || "no legal slots", {
legal: 0,
scored: 0,
});
return 0;
}
if (!__mmActionClaim("smartAutoPlace", __mmReason)) {
__mmSmartSetStatus(
"deferred",
"action owned by " + __mmActionOwner,
{
legal: __mmCandidates.length,
scored: __mmCandidates.filter(function (__mmCandidate) {
return __mmCandidate.points > 0;
}).length,
},
);
return 0;
}
const __mmTool = __mmSelectedTool(),
__mmLimit = Number.isFinite(Number(__mmForcedLimit))
? Math.max(1, Math.min(4, Math.round(Number(__mmForcedLimit))))
: __mmSmartMultiPlaceEnabled
? __mmSmartMaxPlacements
: 1;
__mmCandidates.sort(function (__mmLeft, __mmRight) {
if (__mmRight.points !== __mmLeft.points)
return __mmRight.points - __mmLeft.points;
const __mmLeftTrap = !!__mmLeft.data.trap,
__mmRightTrap = !!__mmRight.data.trap;
return Number(__mmRightTrap) - Number(__mmLeftTrap);
});
const __mmSelected = __mmSmartBestCombination(__mmCandidates, __mmLimit);
__mmSmartSetPlacementPreview(__mmCandidates, __mmSelected, __mmReason);
if (!__mmSelected.length) {
(__mmActionRelease("smartAutoPlace", "no affordable scored slots"),
__mmSmartSetStatus("blocked", "no affordable scored slots", {
legal: __mmCandidates.length,
scored: __mmCandidates.filter(function (__mmCandidate) {
return __mmCandidate.points > 0;
}).length,
}));
return 0;
}
let __mmPlaced = 0;
const __mmImmediate = [];
for (let __mmIndex = 0; __mmIndex < __mmSelected.length; __mmIndex++) {
const __mmCandidate = __mmSelected[__mmIndex],
__mmPing = Number(window.pingTime),
__mmDelay = __mmCandidate.preplace
? Math.max(
0,
__mmSmartPlaceDelay -
(Number.isFinite(__mmPing) ? Math.max(0, __mmPing) : 0),
)
: 0;
if (__mmDelay > 0) {
const __mmPreplaceKey =
String(__mmCandidate.item) + ":" +
Math.round(__mmCandidate.x / 3) + ":" +
Math.round(__mmCandidate.y / 3);
if (__mmSmartPreplaceKeys.has(__mmPreplaceKey)) continue;
if (__mmSmartPreplaceTimers.size < 2) {
const __mmScheduledReservation = {
item: __mmCandidate.item,
x: __mmCandidate.x,
y: __mmCandidate.y,
scale: __mmCandidate.scale,
expiresAt: Date.now() + __mmDelay + 650,
preplaceKey: __mmPreplaceKey,
};
__mmAutoSpikeSpamReservations.push(__mmScheduledReservation);
const __mmTimer = setTimeout(function () {
(__mmSmartPreplaceTimers.delete(__mmTimer),
__mmSmartPreplaceKeys.delete(__mmPreplaceKey));
const __mmReservationIndex =
__mmAutoSpikeSpamReservations.indexOf(__mmScheduledReservation);
__mmReservationIndex >= 0 &&
__mmAutoSpikeSpamReservations.splice(__mmReservationIndex, 1);
if (
(!__mmSmartAutoPlaceEnabled &&
!__mmAutomaticQuadCandidateEnabled(__mmCandidate) &&
!__mmSmartAutoReplaceEnabled &&
!__mmSmartSpikeSyncPlaceEnabled) ||
!__mmActionCanPreempt("smartAutoPlace") ||
!__mmActionClaim("smartAutoPlace", "predictive pre-place")
)
return;
const __mmCurrentTool = __mmSelectedTool(),
__mmDidPlace = __mmSmartPlaceNow(
__mmCandidate,
__mmCurrentTool,
!0,
);
(__mmDidPlace
? __mmSmartSetStatus("sent", "predictive pre-place", {
legal: 1,
scored: 1,
})
: __mmSmartSetStatus("blocked", "pre-place became illegal", {
legal: 0,
scored: 0,
}),
__mmActionRelease("smartAutoPlace", "predictive pre-place complete"));
}, __mmDelay);
(__mmSmartPreplaceTimers.add(__mmTimer),
__mmSmartPreplaceKeys.add(__mmPreplaceKey));
__mmPlaced++;
continue;
}
// Limit delayed priority placements without throwing away the remaining
// members of a four-slot batch.
// Once both predictive timers are occupied, send later legal slots now.
__mmImmediate.push(__mmCandidate);
} else if (!__mmDelay)
__mmImmediate.push(__mmCandidate);
}
__mmImmediate.length &&
(__mmPlaced += __mmSmartPlaceBurst(__mmImmediate, __mmTool));
(__mmActionRelease("smartAutoPlace", __mmReason + " complete"),
__mmPlaced > 0
? ((__mmSmartPlacementLastAt = Date.now()),
__mmSmartSetStatus("sent", __mmReason, {
legal: __mmCandidates.length,
scored: __mmCandidates.filter(function (__mmCandidate) {
return __mmCandidate.points > 0;
}).length,
}))
: __mmSmartSetStatus("blocked", "selected slots became illegal", {
legal: __mmCandidates.length,
scored: __mmSelected.length,
}));
return __mmPlaced;
}
function __mmSmartObserveRemovedObjects(__mmNow) {
if (!v || !v.alive) return;
if (!__mmSmartAutoReplaceEnabled && !__mmSmartSpikeSyncPlaceEnabled) {
__mmSmartKnownObjects.clear();
return;
}
if (__mmNow - __mmSmartObjectScanAt < 25) return;
__mmSmartObjectScanAt = __mmNow;
const __mmSeen = new Set(),
__mmObjects = __mmActiveObjectSnapshot(!0).all;
for (let __mmIndex = 0; __mmIndex < __mmObjects.length; __mmIndex++) {
const __mmObject = __mmObjects[__mmIndex];
if (!__mmObject || !__mmObject.active || __mmObject.sid == null) continue;
const __mmKey = String(__mmObject.sid),
__mmData = b && b.list && b.list[__mmObject.id];
__mmSeen.add(__mmKey);
if (Math.hypot(__mmObject.x - v.x, __mmObject.y - v.y) <= 450)
__mmSmartKnownObjects.set(__mmKey, {
x: Number(__mmObject.x),
y: Number(__mmObject.y),
scale: Number(__mmObject.scale) || 45,
trap: !!(__mmData && __mmData.trap),
seenAt: __mmNow,
});
}
for (const [__mmKey, __mmKnown] of __mmSmartKnownObjects) {
if (__mmSeen.has(__mmKey)) continue;
__mmSmartKnownObjects.delete(__mmKey);
if (
(!__mmSmartAutoReplaceEnabled &&
!(__mmSmartSpikeSyncPlaceEnabled && __mmKnown.trap)) ||
__mmNow - __mmKnown.seenAt > 350 ||
Math.hypot(__mmKnown.x - v.x, __mmKnown.y - v.y) > 190
)
continue;
const __mmEnemy = __mmNearestEnemy();
if (!__mmEnemy || Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y) > 235)
continue;
((__mmSmartReplacePoint = __mmKnown),
(__mmSmartReplaceUntil = __mmNow + Math.max(250, __mmServerTickMs() * 2)));
}
}
function __mmSmartUpdateMovingMills(__mmNow) {
if (!__mmSmartMovingMillsEnabled || !v || !v.alive) return;
const __mmPlayerX = v.x2 != null && Number.isFinite(Number(v.x2))
? Number(v.x2)
: Number(v.x),
__mmPlayerY = v.y2 != null && Number.isFinite(Number(v.y2))
? Number(v.y2)
: Number(v.y);
if (!Number.isFinite(__mmPlayerX) || !Number.isFinite(__mmPlayerY)) return;
const __mmMill = __mmSmartMillItem();
if (__mmMill == null) {
// A missing resource or a temporarily full client-side counter must not
// switch Automill off. Keep it armed so it resumes on the first usable
// tick (including sandbox's 299-mill group) without another key press.
__mmSmartSetStatus("waiting", "auto mills waiting for a buildable mill", {
legal: 0,
scored: 0,
itemSummary: "mill",
});
return;
}
const __mmData = b && b.list && b.list[__mmMill],
__mmMillScale = Number(__mmData && __mmData.scale) || 45,
__mmPlaceDistance =
(Number(v.scale) || 35) +
__mmMillScale +
(Number(__mmData && __mmData.placeOffset) || 0),
__mmHasMovementDirection =
typeof Kt === "number" && Number.isFinite(Kt),
__mmMoved =
__mmSmartMillX == null || __mmSmartMillY == null
? Infinity
: Math.hypot(
__mmPlayerX - __mmSmartMillX,
__mmPlayerY - __mmSmartMillY,
),
// Probe after only a few pixels and let the native collision test decide
// the exact first legal frame. The anchor is advanced only after a full
// row is sent, while short reservations suppress duplicate packets.
__mmProbeDistance = Math.max(4, __mmMillScale * 0.12);
if (__mmSmartMillX == null || __mmSmartMillY == null) {
((__mmSmartMillX = __mmPlayerX), (__mmSmartMillY = __mmPlayerY));
// Do not choose an arbitrary world angle while standing still. If the
// movement key is already held, Kt is available and the first row can be
// emitted immediately; otherwise wait for actual movement.
if (!__mmHasMovementDirection) return;
}
if (
__mmMoved < __mmProbeDistance ||
__mmNow - __mmSmartMillLastAt < 4 ||
!__mmActionCanPreempt("smartAutoPlace")
)
return;
const __mmDirection =
__mmHasMovementDirection
? Kt
: Math.atan2(
__mmPlayerY - __mmSmartMillY,
__mmPlayerX - __mmSmartMillX,
),
__mmBehind = __mmDirection + Math.PI,
// Derive this offset from the real mill diameter and placement distance.
// The tiny clearance avoids floating-point overlap between the
// three candidates while keeping the row tighter than a hardcoded angle.
__mmSideOffset =
2 *
Math.asin(
Math.min(0.999, (__mmMillScale + 1) / __mmPlaceDistance),
),
__mmAngles = [
__mmBehind,
__mmBehind - __mmSideOffset,
__mmBehind + __mmSideOffset,
],
__mmCandidates = [];
for (let __mmIndex = 0; __mmIndex < __mmAngles.length; __mmIndex++) {
const __mmCandidate = __mmSmartCandidateForAngle(__mmMill, __mmAngles[__mmIndex]);
if (__mmCandidate) ((__mmCandidate.points = 1), __mmCandidates.push(__mmCandidate));
}
const __mmTargetCount = Math.min(3, __mmMaxBuildCount(__mmMill));
// Match the fast clients' one-tick row: do not send a partial pattern merely
// because one side is still touching the previous row. Retry on the next
// 10ms placement scan and emit all available row slots together.
const __mmPlaced =
__mmTargetCount > 0 && __mmCandidates.length >= __mmTargetCount
? __mmSmartPlaceBatch(
__mmCandidates,
"fast moving mills",
__mmTargetCount,
)
: 0;
if (__mmPlaced)
((__mmSmartMillX = __mmPlayerX),
(__mmSmartMillY = __mmPlayerY),
(__mmSmartMillLastAt = __mmNow));
}
function __mmSmartAntiBoostCandidates(__mmEnemy, __mmNow) {
if (!__mmSmartAntiBoostPlaceEnabled || !__mmEnemy || __mmInsta.isActive())
return [];
const __mmPrediction = __mmSmartEnemyPrediction(__mmEnemy, __mmNow),
__mmToUsX = v.x - __mmEnemy.x,
__mmToUsY = v.y - __mmEnemy.y,
__mmMovingToward =
__mmPrediction.speed > 0.055 &&
__mmPrediction.vx * __mmToUsX + __mmPrediction.vy * __mmToUsY > 0;
if (
(!__mmMovingToward && !__mmEnemyNearBoostPad(__mmEnemy)) ||
Math.hypot(__mmToUsX, __mmToUsY) > __mmAntiBoostRange
)
return [];
const __mmDirection = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
__mmBlocker = __mmSmartNamedItem("blocker"),
__mmSpike = __mmHoldingMcGrabby() ? null : __mmSpikeItem(),
__mmTrap = __mmSmartPitTrapItem(),
__mmWall = __mmSmartBuildItem(function (__mmData) {
return /wall/i.test(String(__mmData.name || ""));
}),
__mmItem =
__mmBlocker != null
? __mmBlocker
: __mmSpike != null && __mmCanUseBuildItem(__mmSpike)
? __mmSpike
: __mmTrap != null
? __mmTrap
: __mmWall;
if (__mmItem == null) return [];
const __mmRingSamples = Math.max(
16,
Math.min(56, Math.round(20 + __mmEffectiveSmartDepth() * 3.2)),
),
__mmAngles =
__mmItem === __mmSpike
? [
__mmDirection + Math.PI / 2,
__mmDirection - Math.PI / 2,
__mmDirection + Math.PI,
]
: Array.from({ length: __mmRingSamples }, function (_, __mmIndex) {
return (
__mmDirection +
(__mmIndex * Math.PI * 2) / __mmRingSamples
);
}),
__mmCandidates = [];
for (let __mmIndex = 0; __mmIndex < __mmAngles.length; __mmIndex++) {
const __mmCandidate = __mmSmartCandidateForAngle(__mmItem, __mmAngles[__mmIndex]);
if (__mmCandidate)
((__mmCandidate.points = 20 - __mmIndex * 0.01),
__mmCandidates.push(__mmCandidate));
}
return __mmCandidates;
}
function __mmUpdateSmartPlacement() {
const __mmNow = Date.now();
if (!v || !v.alive) {
__mmSmartSetStatus("waiting", "player not spawned", {
legal: 0,
scored: 0,
itemSummary: "none",
});
return;
}
((__mmSmartPreviewSamples.length = 0),
__mmAutoSpikeSpamCleanReservations(__mmNow),
__mmSmartObserveRemovedObjects(__mmNow),
__mmSmartUpdateMovingMills(__mmNow));
if (__mmNow > __mmSmartReplaceUntil) __mmSmartReplacePoint = null;
const __mmWanted = !!(
__mmSmartAutoPlaceEnabled ||
__mmAutomaticQuadPlacementEnabled() ||
__mmSmartReplacePoint ||
__mmSmartAntiBoostPlaceEnabled
);
if (!__mmWanted) {
__mmSmartSetStatus("off", "smart auto place disabled", {
legal: 0,
scored: 0,
});
return;
}
__mmActionOwner === "manualAttack" &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
__mmActionRelease("manualAttack", "stale click state cleared");
let __mmBusyReason = "";
if (__mmInsta.isActive()) __mmBusyReason = "Insta active";
else if (__mmBoostInsta.isActive()) __mmBusyReason = "boost Insta active";
else if (__mmTrapAttackActive) __mmBusyReason = "trap escape active";
else if (__mmBoostBreakHeld) __mmBusyReason = "boost break active";
else if (__mmFoodSpamTimer) __mmBusyReason = "food input held";
else if (__mmBuildSpamTimer) __mmBusyReason = "manual build held";
else if (!__mmActionCanPreempt("smartAutoPlace"))
__mmBusyReason = "action owned by " + __mmActionOwner;
if (__mmBusyReason) {
__mmSmartSetStatus("deferred", __mmBusyReason);
return;
}
const __mmEnemies = (__mmLiveStateFresh() ? __mmLiveState.enemies : E)
.filter(__mmIsEnemyPlayer)
.sort(function (__mmLeft, __mmRight) {
const __mmLeftTrapped = !!__mmAutoSpikeSpamTrapForEnemy(__mmLeft),
__mmRightTrapped = !!__mmAutoSpikeSpamTrapForEnemy(__mmRight);
if (__mmLeftTrapped !== __mmRightTrapped)
return __mmLeftTrapped ? -1 : 1;
return (
Math.hypot(__mmLeft.x - v.x, __mmLeft.y - v.y) -
Math.hypot(__mmRight.x - v.x, __mmRight.y - v.y)
);
}),
__mmScanInterval = __mmSmartReplacePoint
? 5
: __mmEnemies.length
? Math.max(12, Math.min(25, __mmFastCheckMs()))
: 60;
if (
__mmNow - __mmSmartPlacementCalculatedAt < __mmScanInterval &&
!__mmSmartReplacePoint
)
return;
((__mmSmartPlacementCalculatedAt = __mmNow),
(__mmSmartPlacementStats.scans += 1));
const __mmCanSend = !!(
__mmSmartReplacePoint ||
__mmNow - __mmSmartPlacementLastAt >= __mmServerTickMs()
);
let __mmAntiBoost = [];
for (let __mmIndex = 0; __mmIndex < __mmEnemies.length; __mmIndex++) {
__mmAntiBoost = __mmSmartAntiBoostCandidates(__mmEnemies[__mmIndex], __mmNow);
if (__mmAntiBoost.length) break;
}
if (__mmAntiBoost.length) {
if (__mmCanSend)
__mmSmartPlaceBatch(__mmAntiBoost, "anti-boost fallback");
else {
const __mmArmed = __mmSmartBestCombination(
__mmAntiBoost.slice().sort(function (__mmLeft, __mmRight) {
return __mmRight.points - __mmLeft.points;
}),
__mmSmartMultiPlaceEnabled ? __mmSmartMaxPlacements : 1,
);
(__mmSmartSetPlacementPreview(
__mmAntiBoost,
__mmArmed,
"armed for next placement tick",
),
__mmSmartSetStatus("armed", "anti-boost next tick", {
legal: __mmAntiBoost.length,
scored: __mmAntiBoost.length,
}));
}
return;
}
if (
!__mmSmartAutoPlaceEnabled &&
!__mmAutomaticQuadPlacementEnabled() &&
!__mmSmartReplacePoint
)
return;
if (!__mmEnemies.length && !__mmSmartReplacePoint) {
(__mmSmartSetPlacementPreview([], [], "waiting for enemy"),
__mmSmartSetStatus("watching", "waiting for enemy", {
legal: 0,
scored: 0,
}));
return;
}
const __mmNearestPlacementEnemyDistance = __mmEnemies.length
? Math.hypot(
__mmEnemies[0].x - v.x,
__mmEnemies[0].y - v.y,
)
: Infinity;
if (
!__mmSmartReplacePoint &&
__mmNearestPlacementEnemyDistance > 450
) {
(__mmSmartSetPlacementPreview([], [], "enemy outside placement ring"),
__mmSmartSetStatus(
"watching",
"nearest enemy " +
Math.round(__mmNearestPlacementEnemyDistance) +
"px away",
{ legal: 0, scored: 0 },
));
return;
}
const __mmSpike =
__mmHoldingMcGrabby() || __mmEmergencyGetawayActive()
? null
: __mmSpikeItem(),
__mmTrap = __mmSmartPitTrapItem(),
__mmSpikeReady =
__mmSpike != null &&
__mmCanUseBuildItem(__mmSpike) &&
__mmMaxBuildCount(__mmSpike) > 0,
__mmTrapReady =
__mmTrap != null &&
__mmCanUseBuildItem(__mmTrap) &&
__mmMaxBuildCount(__mmTrap) > 0,
__mmItemSummary = [
__mmSpike == null
? __mmHoldingMcGrabby()
? "spike suppressed by Mc Grabby"
: __mmEmergencyGetawayActive()
? "spike suppressed by getaway"
: "no spike"
: __mmSpikeReady
? "spike ready"
: "spike unavailable",
__mmTrap == null
? "no pit trap"
: __mmTrapReady
? "pit trap ready"
: "pit trap unavailable",
].join(" · "),
__mmHazards = __mmSmartFriendlyHazards(),
__mmSpikeEnemyPotentials = __mmSpikeReady
? __mmSmartEnemyPlacementPotentials(
__mmEnemies,
__mmSpike,
__mmNow,
)
: null,
__mmTrapEnemyPotentials = __mmTrapReady
? __mmSmartEnemyPlacementPotentials(
__mmEnemies,
__mmTrap,
__mmNow,
)
: null,
__mmCandidates = [];
if (!__mmSpikeReady && !__mmTrapReady) {
(__mmSmartSetPlacementPreview([], [], __mmItemSummary),
__mmSmartSetStatus("blocked", "no affordable equipped placeable", {
legal: 0,
scored: 0,
itemSummary: __mmItemSummary,
}));
return;
}
__mmSpikeReady &&
__mmCandidates.push(
...__mmSmartPlacementCandidates(
__mmSpike,
__mmEnemies,
__mmHazards,
__mmNow,
__mmSpikeEnemyPotentials,
),
);
__mmTrapReady &&
__mmCandidates.push(
...__mmSmartPlacementCandidates(
__mmTrap,
__mmEnemies,
__mmHazards,
__mmNow,
__mmTrapEnemyPotentials,
),
);
__mmSmartAutoPlaceEnabled &&
__mmSmartApplyCorePressureFallback(
__mmCandidates,
__mmEnemies,
__mmNow,
);
const __mmQuadTrapCandidates = __mmSmartQuadTrapCandidates(
__mmCandidates,
__mmEnemies,
__mmNow,
),
__mmQuadSpikeCandidates = __mmSmartQuadSpikeCandidates(
__mmCandidates,
__mmEnemies,
__mmNow,
),
__mmQuadLimit = Math.max(
1,
Math.min(4, Number(__mmSmartMaxPlacements) || 4),
),
__mmQuadTrapSelection = __mmQuadTrapCandidates.length
? __mmSmartBestCombination(
__mmQuadTrapCandidates,
__mmQuadLimit,
)
: [],
__mmQuadSpikeSelection = __mmQuadSpikeCandidates.length
? __mmSmartBestCombination(__mmQuadSpikeCandidates, __mmQuadLimit)
: [],
__mmNearestIsTrapped = !!(
__mmEnemies[0] && __mmAutoSpikeSpamTrapForEnemy(__mmEnemies[0])
),
__mmHasSpikeOpportunity = __mmQuadSpikeSelection.some(function (
__mmCandidate,
) {
return (
__mmCandidate.priority ||
__mmCandidate.reasons.some(function (__mmReason) {
return /(?:contact|trapped surround|knock|spike chain|bounce)/i.test(
String(__mmReason),
);
})
);
}),
__mmUseQuadSpikesFirst =
(__mmNearestIsTrapped || __mmHasSpikeOpportunity) &&
__mmQuadSpikeSelection.length > 0;
if (__mmUseQuadSpikesFirst) {
__mmSmartSetStatus(
__mmCanSend ? "ready" : "armed",
__mmCanSend
? __mmNearestIsTrapped
? "quad spike trapped surround"
: "quad spike contact/knockback"
: "quad spikes armed for next placement tick",
{
legal: __mmQuadSpikeCandidates.length,
scored: __mmQuadSpikeSelection.length,
itemSummary: __mmItemSummary,
},
);
if (__mmCanSend)
__mmSmartPlaceBatch(
__mmQuadSpikeCandidates,
__mmNearestIsTrapped
? "quad spike trapped surround"
: "quad spike contact/knockback",
__mmQuadLimit,
);
else
__mmSmartSetPlacementPreview(
__mmQuadSpikeCandidates,
__mmQuadSpikeSelection,
"quad spikes armed for next placement tick",
);
return;
}
if (__mmQuadTrapSelection.length) {
__mmSmartSetStatus(
__mmCanSend ? "ready" : "armed",
__mmCanSend
? "quad trap full-place"
: "quad traps armed for next placement tick",
{
legal: __mmQuadTrapCandidates.length,
scored: __mmQuadTrapSelection.length,
itemSummary: __mmItemSummary,
},
);
if (__mmCanSend)
__mmSmartPlaceBatch(
__mmQuadTrapCandidates,
"quad trap full-place",
__mmQuadLimit,
);
else
__mmSmartSetPlacementPreview(
__mmQuadTrapCandidates,
__mmQuadTrapSelection,
"quad traps armed for next placement tick",
);
return;
}
if (__mmQuadSpikeSelection.length) {
__mmSmartSetStatus(
__mmCanSend ? "ready" : "armed",
__mmCanSend
? "quad spike contact full-place"
: "quad spikes armed for next placement tick",
{
legal: __mmQuadSpikeCandidates.length,
scored: __mmQuadSpikeSelection.length,
itemSummary: __mmItemSummary,
},
);
if (__mmCanSend)
__mmSmartPlaceBatch(
__mmQuadSpikeCandidates,
"quad spike contact full-place",
__mmQuadLimit,
);
else
__mmSmartSetPlacementPreview(
__mmQuadSpikeCandidates,
__mmQuadSpikeSelection,
"quad spikes armed for next placement tick",
);
return;
}
if (!__mmSmartAutoPlaceEnabled && !__mmSmartReplacePoint) {
(__mmSmartSetPlacementPreview(
__mmCandidates,
[],
"automatic quads found no useful legal pattern",
),
__mmSmartSetStatus(
"watching",
"automatic quads waiting for trap/contact pressure",
{
legal: __mmCandidates.length,
scored: 0,
itemSummary: __mmItemSummary,
},
));
return;
}
const __mmScored = __mmCandidates.filter(function (__mmCandidate) {
return __mmCandidate.points > 0;
}).length,
__mmBlockedSamples = __mmSmartPreviewSamples.filter(function (__mmCandidate) {
return __mmCandidate && __mmCandidate.valid === !1;
}).length,
__mmReason = __mmSmartReplacePoint
? "destroyed-object replace"
: "smart auto place";
__mmSmartSetStatus(
__mmScored ? (__mmCanSend ? "ready" : "armed") : "blocked",
__mmScored
? __mmCanSend
? "legal scored slots"
: "waiting for next placement tick"
: __mmCandidates.length
? "legal ring but no useful intercept"
: "all sampled slots occupied",
{
legal: __mmCandidates.length,
scored: __mmScored,
blocked: __mmBlockedSamples,
itemSummary: __mmItemSummary,
},
);
if (__mmCandidates.length && __mmScored && __mmCanSend)
__mmSmartPlaceBatch(__mmCandidates, __mmReason);
else if (__mmCandidates.length && __mmScored) {
const __mmRanked = __mmCandidates.slice().sort(function (
__mmLeft,
__mmRight,
) {
return __mmRight.points - __mmLeft.points;
}),
__mmArmed = __mmSmartBestCombination(
__mmRanked,
__mmSmartMultiPlaceEnabled ? __mmSmartMaxPlacements : 1,
);
__mmSmartSetPlacementPreview(
__mmCandidates,
__mmArmed,
"armed for next placement tick",
);
} else
__mmSmartSetPlacementPreview(
[],
[],
__mmCandidates.length
? "legal ring but no useful intercept"
: "all sampled slots occupied",
);
__mmSmartReplacePoint &&
(__mmCanSend || !__mmCandidates.length) &&
(__mmSmartReplacePoint = null);
}
function __mmStartSmartPlacement() {
(__mmEnsureOperationPipeline(), __mmUpdateSmartPlacement());
}
function __mmRefreshSmartPlacementLoop() {
const __mmWanted = !!(
__mmSmartAutoPlaceEnabled ||
__mmAutomaticQuadPlacementEnabled() ||
__mmSmartAutoReplaceEnabled ||
__mmSmartSpikeSyncPlaceEnabled ||
__mmSmartAntiBoostPlaceEnabled ||
__mmSmartMovingMillsEnabled
);
if (__mmWanted) return void __mmStartSmartPlacement();
(function () {
for (const __mmTimer of __mmSmartPreplaceTimers) clearTimeout(__mmTimer);
(__mmSmartPreplaceTimers.clear(), __mmSmartPreplaceKeys.clear());
})();
(__mmSmartPlacementTimer && clearInterval(__mmSmartPlacementTimer),
(__mmSmartPlacementTimer = 0),
(__mmSmartReplacePoint = null),
__mmSmartSetStatus("off", "smart auto place disabled", {
legal: 0,
scored: 0,
}));
}
function __mmToggleSmartMovingMills() {
((__mmSmartMovingMillsEnabled = !__mmSmartMovingMillsEnabled),
(__mmSmartMillX = null),
(__mmSmartMillY = null),
(__mmSmartMillLastAt = 0),
__mmRefreshSmartPlacementLoop(),
__mmBushStatus(
"auto mills: " + (__mmSmartMovingMillsEnabled ? "on" : "off"),
),
__mmPublishHudState());
}
function __mmEnableSmartMovingMills() {
if (__mmSmartMovingMillsEnabled) return;
((__mmSmartMovingMillsEnabled = !0),
(__mmSmartMillX = null),
(__mmSmartMillY = null),
(__mmSmartMillLastAt = 0),
__mmRefreshSmartPlacementLoop(),
__mmBushStatus("auto mills: on"),
__mmPublishHudState());
}
function __mmSmartPlaceUtilityForInsta(__mmTarget, __mmWeapon) {
if (
!__mmSmartInstaUtilityPlaceEnabled ||
!v ||
!v.alive ||
!__mmTarget ||
Date.now() - __mmSmartUtilityLastAt < __mmServerTickMs()
)
return !1;
const __mmPlatform = __mmSmartNamedItem("platform");
if (__mmPlatform == null) return !1;
const __mmAngle = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x),
__mmCandidate = __mmSmartCandidateForAngle(__mmPlatform, __mmAngle);
if (!__mmCandidate) return !1;
const __mmPlaced = __mmInstaPlaceAndReselect(
__mmPlatform,
__mmAngle,
__mmWeapon,
);
__mmPlaced && (__mmSmartUtilityLastAt = Date.now());
return __mmPlaced;
}
function __mmEnemyNearBoostPad(__mmPlayer) {
if (!__mmPlayer || !__mmPlayer.alive) return !1;
const __mmGrids = X.getGridArrays(__mmPlayer.x, __mmPlayer.y, 180);
for (let __mmGridIndex = 0; __mmGridIndex < __mmGrids.length; __mmGridIndex++)
for (
let __mmItemIndex = 0;
__mmItemIndex < __mmGrids[__mmGridIndex].length;
__mmItemIndex++
) {
const __mmObject = __mmGrids[__mmGridIndex][__mmItemIndex];
if (!__mmObject.active || !__mmObject.boostSpeed) continue;
const __mmRange = __mmPlayer.scale + __mmObject.scale + 80,
__mmDx = __mmPlayer.x - __mmObject.x,
__mmDy = __mmPlayer.y - __mmObject.y;
if (__mmDx * __mmDx + __mmDy * __mmDy <= __mmRange * __mmRange) return !0;
}
return !1;
}
function __mmAntiBoostAngles(__mmAngle, __mmCount) {
if (__mmCount <= 1) return [__mmAngle];
return [__mmAngle - 0.46, __mmAngle + 0.46];
}
function __mmPlaceAntiBoostSpikes(__mmAngle) {
// Boost-rush defense is the one automatic spike exception while Mc Grabby
// is selected, matching the anti-boost insta safety path.
if (
__mmEmergencyGetawayActive() ||
(__mmHoldingMcGrabby() && !__mmAntiBoostInstaEnabled)
)
return 0;
const __mmSpike = __mmSpikeItem(),
__mmCount = Math.min(2, __mmMaxBuildCount(__mmSpike));
if (__mmSpike == null || __mmCount < 1) return 0;
const __mmTool = __mmSelectedTool(),
__mmAngles = __mmAntiBoostAngles(__mmAngle, __mmCount);
let __mmPlaced = 0;
for (let __mmIndex = 0; __mmIndex < __mmAngles.length; __mmIndex++) {
const __mmCandidate = __mmSmartNearestLegalCandidate(
__mmSpike,
__mmAngles[__mmIndex],
0.34,
0.04,
);
if (
!__mmCandidate ||
!__mmSendAutomaticPlacement(
__mmSpike,
__mmCandidate.angle,
__mmTool,
)
)
continue;
(__mmAutoSpikeSpamReservations.push({
item: __mmSpike,
x: __mmCandidate.x,
y: __mmCandidate.y,
scale: __mmCandidate.scale,
expiresAt: Date.now() + 650,
}),
__mmPlaced++);
}
return __mmPlaced;
}
function __mmStopAntiBoostRetreat() {
(__mmAntiBoostMoveTimer && clearTimeout(__mmAntiBoostMoveTimer),
(__mmAntiBoostMoveTimer = 0));
if (!__mmAntiBoostBackingUp) return;
((__mmAntiBoostBackingUp = !1), (Kt = null), Tt());
}
function __mmStopAntiBoostBlock(__mmReason) {
const __mmTool = __mmAntiBoostBlockTool,
__mmRestore = __mmActionMayRestore("antiBoostBlock");
(__mmAntiBoostBlockTimer && clearTimeout(__mmAntiBoostBlockTimer),
(__mmAntiBoostBlockTimer = 0),
__mmStopAntiBoostRetreat(),
(__mmAntiBoostBlockTool = null),
(__mmAntiBoostBlockAimAngle = null),
__mmRestore && __mmRestoreTool(__mmTool),
__mmRestore && __mmResumeHeldAttack(),
__mmActionRelease(
"antiBoostBlock",
__mmReason || "boost block complete",
));
}
function __mmStartAntiBoostBlock(__mmEnemy) {
if (
!__mmAntiBoostEnabled ||
!v ||
!v.alive ||
!__mmEnemy ||
__mmAntiBoostBlockTimer
)
return !1;
__mmActionOwner === "shieldDefense" &&
__mmStopShieldDefense("boost block priority");
if (!__mmActionClaim("antiBoostBlock", "boost-pad rush")) return !1;
const __mmToward = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x),
__mmAway = __mmToward + Math.PI,
__mmWindow = Math.max(180, 3 * __mmServerTickMs());
((__mmAntiBoostBlockTool = __mmSelectedTool()),
(__mmAntiBoostBlockAimAngle = __mmToward),
__mmPlaceAntiBoostSpikes(__mmToward),
O.send("D", __mmToward),
O.send("9", __mmAway),
(Kt = __mmAway),
(__mmAntiBoostBackingUp = !0),
v.weapons &&
v.weapons.includes(__mmShieldWeapon) &&
je(__mmShieldWeapon, !0),
(__mmAntiBoostMoveTimer = setTimeout(
__mmStopAntiBoostRetreat,
Math.max(120, 2 * __mmServerTickMs()),
)),
(__mmAntiBoostBlockTimer = setTimeout(function () {
__mmStopAntiBoostBlock("boost block complete");
}, __mmWindow)));
return !0;
}
function __mmUpdateAntiBoostInsta() {
// An active burst owns its complete Bull-primary -> Turret-secondary window.
if (__mmInsta.isActive()) return;
if (
!__mmAntiBoostInstaEnabled ||
__mmEmergencyGetawayActive() ||
!v ||
!v.alive ||
__mmTrapAttackActive ||
__mmBoostBreakHeld
)
return;
const __mmNow = Date.now();
for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
const __mmEnemy = E[__mmPlayerIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmSid = String(__mmEnemy.sid),
__mmTrail =
__mmEnemyBoostTrail[__mmSid] ||
(__mmEnemyBoostTrail[__mmSid] = {
x: __mmEnemy.x,
y: __mmEnemy.y,
time: __mmNow,
boostAt: 0,
}),
__mmDx = __mmEnemy.x - __mmTrail.x,
__mmDy = __mmEnemy.y - __mmTrail.y,
__mmToPlayerX = v.x - __mmEnemy.x,
__mmToPlayerY = v.y - __mmEnemy.y,
__mmDistance =
__mmToPlayerX * __mmToPlayerX + __mmToPlayerY * __mmToPlayerY;
if (__mmEnemyNearBoostPad(__mmEnemy)) __mmTrail.boostAt = __mmNow;
const __mmFreshBoost = __mmNow - __mmTrail.boostAt <= 700,
__mmMovingToward =
__mmDx * __mmDx + __mmDy * __mmDy > 0.25 &&
__mmDx * __mmToPlayerX + __mmDy * __mmToPlayerY > 0;
((__mmTrail.x = __mmEnemy.x),
(__mmTrail.y = __mmEnemy.y),
(__mmTrail.time = __mmNow));
if (
__mmFreshBoost &&
__mmDistance <= __mmAntiBoostRange * __mmAntiBoostRange &&
__mmMovingToward
) {
if (
__mmAntiBoostInstaEnabled &&
__mmFullInstaReadyFor(__mmEnemy) &&
__mmInsta.start({ automatic: !0, targetSid: __mmEnemy.sid })
) {
((__mmAntiBoostLast = __mmNow), (__mmTrail.boostAt = 0));
return;
}
}
}
}
function __mmStartAntiBoostInsta() {
__mmEnsureOperationPipeline();
}
function __mmReloadSpikeTarget() {
if (!v || !v.alive) return null;
if (!__mmMusketIsReloading() && !__mmTurretGearIsReloading()) return null;
const __mmEnemy = __mmNearestEnemy();
if (!__mmEnemy) return null;
const __mmDx = __mmEnemy.x - v.x;
const __mmDy = __mmEnemy.y - v.y;
const __mmRange = Math.min(220, Math.max(120, __mmCombatRange));
return __mmDx * __mmDx + __mmDy * __mmDy <= __mmRange * __mmRange
? __mmEnemy
: null;
}
function __mmPlaceReloadSpike(__mmTarget) {
if (__mmEmergencyGetawayActive() || __mmHoldingMcGrabby()) return !1;
const __mmSpike = __mmSpikeItem();
if (
!__mmTarget ||
__mmSpike == null ||
!__mmCanUseBuildItem(__mmSpike)
)
return !1;
const __mmTool = __mmSelectedTool();
const __mmAngle = Math.atan2(__mmTarget.y - v.y, __mmTarget.x - v.x),
__mmCandidate = __mmSmartNearestLegalCandidate(
__mmSpike,
__mmAngle,
0.52,
0.04,
);
if (!__mmCandidate) return !1;
return __mmSendAutomaticPlacement(
__mmSpike,
__mmCandidate.angle,
__mmTool,
);
}
function __mmUpdateReloadSpike() {
const __mmReloading = __mmMusketIsReloading() || __mmTurretGearIsReloading();
if (!__mmReloading) return void (__mmReloadSpikePlaced = !1);
if (
!__mmReloadSpikeEnabled ||
__mmEmergencyGetawayActive() ||
__mmReloadSpikePlaced ||
__mmHoldingMcGrabby() ||
!v ||
!v.alive ||
__mmInsta.isActive() ||
__mmTrapAttackActive ||
__mmBoostBreakHeld ||
__mmFoodSpamTimer ||
__mmAutoHealWasHealing ||
__mmBuildSpamTimer
)
return;
const __mmTarget = __mmReloadSpikeTarget();
if (!__mmTarget || !__mmActionClaim("reloadSpike", "reload defense")) return;
(__mmPlaceReloadSpike(__mmTarget) && (__mmReloadSpikePlaced = !0),
__mmActionRelease("reloadSpike", "reload defense sent"));
}
function __mmStartReloadSpike() {
__mmEnsureOperationPipeline();
}
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 __mmWindmillData(__mmValue) {
const __mmName = String(__mmValue && __mmValue.name || "")
.trim()
.toLowerCase();
return !!(
__mmValue &&
(__mmName === "windmill" ||
__mmName === "faster windmill" ||
__mmName === "power mill")
);
}
function __mmRememberWindmillTurnSpeed(__mmObject, __mmRemembered) {
if (!__mmObject || !__mmRemembered) return;
const __mmProperties = ["turnSpeed", "spinSpeed", "rotationSpeed"];
for (let __mmIndex = 0; __mmIndex < __mmProperties.length; __mmIndex++) {
const __mmProperty = __mmProperties[__mmIndex],
__mmSpeed = Number(__mmObject[__mmProperty]);
if (
!Object.prototype.hasOwnProperty.call(__mmRemembered, __mmProperty) &&
Number.isFinite(__mmSpeed)
)
__mmRemembered[__mmProperty] = __mmSpeed;
}
}
function __mmApplyRememberedWindmillSpeed(
__mmObject,
__mmRemembered,
) {
if (!__mmObject || !__mmRemembered) return;
for (const __mmProperty in __mmRemembered)
try {
__mmObject[__mmProperty] = __mmSpinningWindmillsEnabled
? __mmRemembered[__mmProperty]
: 0;
} catch (__mmWindmillSpeedWriteError) {}
}
function __mmApplyWindmillRotationState() {
if (b && Array.isArray(b.list))
for (let __mmItem = 0; __mmItem < b.list.length; __mmItem++) {
const __mmData = b.list[__mmItem];
if (!__mmWindmillData(__mmData)) continue;
const __mmKey = String(__mmItem),
__mmRemembered =
__mmWindmillDataTurnSpeeds[__mmKey] ||
(__mmWindmillDataTurnSpeeds[__mmKey] = Object.create(null));
__mmRememberWindmillTurnSpeed(__mmData, __mmRemembered);
__mmApplyRememberedWindmillSpeed(
__mmData,
__mmRemembered,
);
}
const __mmMills = __mmActiveObjectSnapshot(!0).mills;
for (let __mmIndex = 0; __mmIndex < __mmMills.length; __mmIndex++) {
const __mmObject = __mmMills[__mmIndex],
__mmData = __mmObject && b && b.list && b.list[__mmObject.id];
if (!__mmObject || !__mmObject.active || !__mmWindmillData(__mmData))
continue;
let __mmRemembered = __mmWindmillObjectTurnSpeeds.get(__mmObject);
if (!__mmRemembered) {
__mmRemembered = Object.create(null);
__mmWindmillObjectTurnSpeeds.set(__mmObject, __mmRemembered);
}
__mmRememberWindmillTurnSpeed(__mmObject, __mmRemembered);
const __mmDataRemembered =
__mmWindmillDataTurnSpeeds[String(__mmObject.id)];
if (__mmDataRemembered)
for (const __mmProperty in __mmDataRemembered)
(!Object.prototype.hasOwnProperty.call(
__mmRemembered,
__mmProperty,
) ||
(__mmSpinningWindmillsEnabled &&
__mmRemembered[__mmProperty] === 0 &&
__mmDataRemembered[__mmProperty] !== 0)) &&
(__mmRemembered[__mmProperty] =
__mmDataRemembered[__mmProperty]);
__mmApplyRememberedWindmillSpeed(__mmObject, __mmRemembered);
}
}
function __mmStartWindmillHold() {
if (__mmWindmillHotkeyDown) return;
((__mmWindmillHotkeyDown = !0), __mmToggleSmartMovingMills());
}
function __mmStopWindmillHold() {
__mmWindmillHotkeyDown = !1;
}
function __mmServerEntityPosition(__mmEntity) {
if (!__mmEntity) return null;
const __mmServerX = Number(__mmEntity.x2),
__mmServerY = Number(__mmEntity.y2),
__mmRenderX = Number(__mmEntity.x),
__mmRenderY = Number(__mmEntity.y);
if (
__mmEntity.x2 != null &&
__mmEntity.y2 != null &&
Number.isFinite(__mmServerX) &&
Number.isFinite(__mmServerY)
)
return { x: __mmServerX, y: __mmServerY };
return Number.isFinite(__mmRenderX) && Number.isFinite(__mmRenderY)
? { x: __mmRenderX, y: __mmRenderY }
: null;
}
function __mmActiveTrapObjects() {
const __mmTraps = [];
if (!Array.isArray(ge)) return __mmTraps;
// Read the live render-object list directly. The general structure snapshot
// is intentionally cached for FPS, but trap contact must update every scan.
for (let __mmIndex = ge.length - 1; __mmIndex >= 0; __mmIndex--) {
const __mmObject = ge[__mmIndex];
__mmObject && __mmObject.active && __mmObject.trap &&
__mmTraps.push(__mmObject);
}
return __mmTraps;
}
function __mmServerTrapContact(__mmEntity, __mmTrap) {
const __mmPosition = __mmServerEntityPosition(__mmEntity),
__mmTrapX = Number(__mmTrap && __mmTrap.x),
__mmTrapY = Number(__mmTrap && __mmTrap.y);
if (
!__mmPosition ||
!Number.isFinite(__mmTrapX) ||
!Number.isFinite(__mmTrapY)
)
return !1;
const __mmDx = __mmTrapX - __mmPosition.x,
__mmDy = __mmTrapY - __mmPosition.y;
// A player is caught only once its latest server point is within 47px of
// the active pit-trap center. Render interpolation and player scale do not
// widen this test, which prevents early and lingering trap incidents.
return __mmDx * __mmDx + __mmDy * __mmDy <= 47 * 47;
}
function __mmPlayerCenterTouchesEnemyTrap(__mmTrap) {
if (
!v ||
!v.alive ||
!__mmTrap ||
!__mmTrap.active ||
!__mmTrap.trap ||
__mmFriendlyStructure(__mmTrap)
)
return !1;
return __mmServerTrapContact(v, __mmTrap);
}
function __mmNearestLockingTrap() {
if (!v || !v.alive) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmSeen = new Set(),
__mmConsider = function (__mmObject) {
if (
!__mmObject ||
__mmSeen.has(__mmObject) ||
!__mmObject.active ||
!__mmObject.trap ||
__mmFriendlyStructure(__mmObject)
)
return;
__mmSeen.add(__mmObject);
const __mmPosition = __mmServerEntityPosition(v),
__mmDistance = __mmPosition
? (__mmObject.x - __mmPosition.x) ** 2 +
(__mmObject.y - __mmPosition.y) ** 2
: Infinity;
if (!__mmPlayerCenterTouchesEnemyTrap(__mmObject)) return;
__mmDistance < __mmClosestDistance &&
((__mmClosestDistance = __mmDistance), (__mmClosest = __mmObject));
};
try {
const __mmGrids = X.getGridArrays(v.x, v.y, Math.max(180, v.scale * 5));
for (let __mmGridIndex = 0; __mmGridIndex < __mmGrids.length; __mmGridIndex++)
for (
let __mmItemIndex = 0;
__mmItemIndex < __mmGrids[__mmGridIndex].length;
__mmItemIndex++
)
__mmConsider(__mmGrids[__mmGridIndex][__mmItemIndex]);
} catch (__mmTrapGridError) {}
// Item-grid visibility can lag a trap collision by one update. Scan the
// render object list too, so the escape routine starts on the first lock tick.
const __mmTraps = __mmActiveTrapObjects();
for (let __mmItemIndex = 0; __mmItemIndex < __mmTraps.length; __mmItemIndex++)
__mmConsider(__mmTraps[__mmItemIndex]);
return __mmClosest;
}
function __mmFriendlyTrapForPlayer(__mmPlayer) {
if (!v || !v.alive || !__mmPlayer) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmTraps = __mmActiveTrapObjects();
for (let __mmIndex = 0; __mmIndex < __mmTraps.length; __mmIndex++) {
const __mmTrap = __mmTraps[__mmIndex];
if (
!__mmTrap ||
!__mmTrap.active ||
!__mmTrap.trap ||
!__mmFriendlyStructure(__mmTrap)
)
continue;
const __mmPosition = __mmServerEntityPosition(__mmPlayer),
__mmDistance = __mmPosition
? Math.hypot(__mmPosition.x - __mmTrap.x, __mmPosition.y - __mmTrap.y)
: Infinity,
__mmCaught = __mmServerTrapContact(__mmPlayer, __mmTrap);
if (__mmCaught && __mmDistance < __mmClosestDistance)
((__mmClosest = __mmTrap), (__mmClosestDistance = __mmDistance));
}
return __mmClosest;
}
function __mmUpdateFriendlyTrapChat() {
const __mmNow = Date.now(),
__mmSeen = Object.create(null);
let __mmFriendIncident = null,
__mmEnemyIncident = null;
if (v && v.alive && Array.isArray(E)) {
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
__mmPlayer === v ||
String(__mmPlayer.sid) === String(v.sid) ||
(Number.isFinite(Number(__mmPlayer.health)) &&
Number(__mmPlayer.health) <= 0)
)
continue;
const __mmTeammate = __mmSameTeam(__mmPlayer),
__mmFriend = __mmIsFriendPlayer(__mmPlayer),
__mmFriendKey = __mmNormalizeFriendName(__mmPlayer.name),
__mmBetrayed =
!!__mmFriendKey && __mmFriendEnemies.has(__mmFriendKey),
__mmEnemy = !__mmTeammate && !__mmFriend &&
(__mmBetrayed || !__mmSameTeam(__mmPlayer));
if (!__mmFriend && !__mmEnemy) continue;
const __mmMessageRange = __mmFriend
? __mmFriendTrapChatRange
: __mmEnemyTrapChatRange;
if (
Math.hypot(
Number(__mmPlayer.x) - Number(v.x),
Number(__mmPlayer.y) - Number(v.y),
) > __mmMessageRange
)
continue;
const __mmTrap = __mmFriendlyTrapForPlayer(__mmPlayer);
if (!__mmTrap) continue;
const __mmKind = __mmFriend ? "friend" : "enemy",
__mmKey = __mmKind + ":" + String(__mmPlayer.sid),
__mmIncident =
__mmFriendlyTrapChatIncidents[__mmKey] ||
(__mmFriendlyTrapChatIncidents[__mmKey] = {
announced: !1,
lastSeen: __mmNow,
});
((__mmIncident.lastSeen = __mmNow), (__mmSeen[__mmKey] = !0));
if (!__mmIncident.announced) {
const __mmCandidate = {
key: __mmKey,
player: __mmPlayer,
trap: __mmTrap,
};
__mmFriend
? (__mmFriendIncident || (__mmFriendIncident = __mmCandidate))
: (__mmEnemyIncident || (__mmEnemyIncident = __mmCandidate));
}
}
}
for (const __mmKey in __mmFriendlyTrapChatIncidents) {
const __mmIncident = __mmFriendlyTrapChatIncidents[__mmKey];
if (!__mmSeen[__mmKey] && __mmNow - __mmIncident.lastSeen > 450)
delete __mmFriendlyTrapChatIncidents[__mmKey];
}
const __mmCandidate =
(__mmFriendTrapChatEnabled && __mmFriendIncident) ||
(__mmEnemyTrapChatEnabled && __mmEnemyIncident),
__mmCooldown = Math.max(
750,
(Number(y && y.chatCooldown) || 500) + 150,
);
if (
!__mmCandidate ||
__mmNow - __mmFriendlyTrapChatLastAt < __mmCooldown
)
return;
const __mmIncident = __mmFriendlyTrapChatIncidents[__mmCandidate.key];
if (!__mmIncident || __mmIncident.announced) return;
((__mmIncident.announced = !0),
(__mmFriendlyTrapChatLastAt = __mmNow),
__mmSendChat(
__mmCandidate.key.startsWith("friend:")
? "Uh oh! let me free you!"
: "Ha, I have you in my trap!",
));
}
function __mmStartFriendlyTrapChat() {
__mmFriendlyTrapChatTimer ||
((__mmFriendlyTrapChatTimer = setInterval(
__mmUpdateFriendlyTrapChat,
__mmFastCheckMs(),
)),
__mmUpdateFriendlyTrapChat());
}
function __mmTrapAngle() {
const __mmTrap = __mmNearestLockingTrap();
return __mmTrap == null
? null
: Math.round(100 * Math.atan2(__mmTrap.y - v.y, __mmTrap.x - v.x)) / 100;
}
function __mmTrapBuildKey(__mmTrap) {
if (!__mmTrap) return null;
const __mmId =
__mmTrap.sid != null
? __mmTrap.sid
: __mmTrap.id != null
? __mmTrap.id
: null;
return __mmId != null
? "id:" + __mmId
: "pos:" + Math.round(__mmTrap.x) + ":" + Math.round(__mmTrap.y);
}
function __mmAffordableBuildItem(__mmMatches) {
if (!v || !v.items || !b || !b.list) return null;
for (let __mmIndex = 0; __mmIndex < v.items.length; __mmIndex++) {
const __mmItem = v.items[__mmIndex],
__mmData = b.list[__mmItem];
if (
__mmData &&
__mmMatches(__mmData, __mmItem) &&
__mmCanUseBuildItem(__mmItem) &&
__mmMaxBuildCount(__mmItem) > 0
)
return __mmItem;
}
return null;
}
function __mmTrapEmergencyItemKind(__mmItem) {
const __mmData = b && b.list && b.list[__mmItem],
__mmName = String((__mmData && __mmData.name) || "").toLowerCase();
if (!__mmData) return null;
if (__mmData.trap) return "trap";
if (__mmName.includes("spikes")) return "spike";
if (__mmName.includes("mill")) return "windmill";
return null;
}
function __mmTrapEmergencyItemAvailable(__mmItem) {
return !!(
v &&
Array.isArray(v.items) &&
__mmItem != null &&
v.items.includes(__mmItem) &&
__mmCanUseBuildItem(__mmItem) &&
__mmMaxBuildCount(__mmItem) > 0
);
}
function __mmTrapEmergencyHeldPreference() {
if (!v || !v.alive || !Array.isArray(v.items)) return null;
const __mmBuild = Number(v.buildIndex);
return Number.isInteger(__mmBuild) &&
__mmBuild >= 0 &&
v.items.includes(__mmBuild) &&
__mmTrapEmergencyItemKind(__mmBuild)
? __mmBuild
: null;
}
function __mmTrapEmergencySpikePressure(__mmEnemy) {
if (!v || !v.alive || !__mmEnemy) return !1;
const __mmDistance = Math.hypot(
Number(__mmEnemy.x) - Number(v.x),
Number(__mmEnemy.y) - Number(v.y),
);
if (!Number.isFinite(__mmDistance) || __mmDistance > 450) return !1;
// An enemy already on top of the pin or closing into the next server tick
// is immediate pressure and earns the two rear spike slots.
if (__mmAutoSpikeSpamTrapForEnemy(__mmEnemy)) return !0;
const __mmWeapon = b && b.weapons && b.weapons[Number(__mmEnemy.weaponIndex)],
__mmEnemyReach =
(Number(__mmWeapon && __mmWeapon.range) || 0) +
(Number(__mmEnemy.scale) || 35) +
(Number(v.scale) || 35) +
42;
if (__mmDistance <= Math.max(275, __mmEnemyReach)) return !0;
const __mmVelocity = __mmSyncPlayerVelocity(__mmEnemy),
__mmLead = __mmServerTickMs(),
__mmFutureDistance = Math.hypot(
Number(__mmEnemy.x) + __mmVelocity.x * __mmLead - Number(v.x),
Number(__mmEnemy.y) + __mmVelocity.y * __mmLead - Number(v.y),
);
return __mmFutureDistance <= 340 && __mmFutureDistance < __mmDistance - 1.5;
}
function __mmTrapEmergencyFallbackItem(
__mmPreferredItem,
__mmSpikeOverride,
) {
const __mmTrap = __mmAffordableBuildItem((__mmData) => !!__mmData.trap),
__mmWindmill = __mmAffordableBuildItem(
(__mmData) =>
typeof __mmData.name === "string" &&
__mmData.name.toLowerCase().includes("mill"),
),
__mmSpike =
__mmEmergencyGetawayActive() || __mmHoldingMcGrabby()
? null
: __mmSpikeItem(),
__mmOrder = __mmSpikeOverride
? [__mmSpike, __mmTrap, __mmWindmill]
: [__mmPreferredItem, __mmTrap, __mmWindmill, __mmSpike],
__mmSeen = new Set();
for (let __mmIndex = 0; __mmIndex < __mmOrder.length; __mmIndex++) {
const __mmItem = __mmOrder[__mmIndex];
if (__mmItem == null || __mmSeen.has(__mmItem)) continue;
__mmSeen.add(__mmItem);
if (
(__mmEmergencyGetawayActive() || __mmHoldingMcGrabby()) &&
__mmTrapEmergencyItemKind(__mmItem) === "spike"
)
continue;
if (__mmTrapEmergencyItemAvailable(__mmItem)) return __mmItem;
}
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) {
if (!v || !v.alive) return [];
const __mmEnemy = __mmNearestEnemy(),
__mmThreatAngle =
__mmEnemy &&
Math.hypot(Number(__mmEnemy.x) - v.x, Number(__mmEnemy.y) - v.y) <= 450
? Math.atan2(Number(__mmEnemy.y) - v.y, Number(__mmEnemy.x) - v.x)
: Ci(),
__mmBehind = __mmThreatAngle + Math.PI,
__mmSpikeOverride = __mmTrapEmergencySpikePressure(__mmEnemy),
// Trapped-enemy spike contact overrides the current build; otherwise use
// the current placement type and default to Pit Trap while a weapon is
// held. Remember that initial preference because the continuous breaker
// necessarily switches back to a weapon afterward.
__mmItem = __mmTrapEmergencyFallbackItem(
__mmTrapBuildPreferredItem,
__mmSpikeOverride,
);
if (__mmItem == null) return [];
const __mmData = b && b.list && b.list[__mmItem],
__mmScale = Number(__mmData && __mmData.scale) || 45,
__mmRadius =
(Number(v.scale) || 35) +
__mmScale +
(Number(__mmData && __mmData.placeOffset) || 0),
__mmSpacing =
2 *
Math.asin(
Math.min(0.999, (2 * __mmScale + 1) / (2 * __mmRadius)),
) +
0.025,
__mmCount = Math.min(
Math.max(0, 2 - __mmTrapBuildPlacedCount),
__mmMaxBuildCount(__mmItem),
);
return __mmCount <= 1
? [{ item: __mmItem, angle: __mmBehind }]
: [
{ item: __mmItem, angle: __mmBehind - __mmSpacing / 2 },
{ item: __mmItem, angle: __mmBehind + __mmSpacing / 2 },
];
}
function __mmRememberTrapSpikeReplaceSlot(__mmEntry, __mmTrapKey) {
if (
!__mmAutoSpikeReplaceEnabled ||
!__mmEntry ||
!v ||
!v.alive ||
!b ||
!b.list
)
return;
const __mmData = b.list[__mmEntry.item];
if (!__mmData || !__mmData.trap) return;
const __mmScale = Number(__mmData.scale) || 50,
__mmDistance =
(Number(v.scale) || 35) +
__mmScale +
(Number(__mmData.placeOffset) || 0);
__mmTrapSpikeReplaceSlot = {
trapKey: __mmTrapKey,
angle: __mmEntry.angle,
x: Number(v.x) + Math.cos(__mmEntry.angle) * __mmDistance,
y: Number(v.y) + Math.sin(__mmEntry.angle) * __mmDistance,
scale: __mmScale,
rememberedAt: Date.now(),
seenBlockingTrap: !1,
};
}
function __mmTrapSpikeReplaceBlocker(__mmSlot) {
if (!__mmSlot) return null;
let __mmClosest = null,
__mmClosestDistance = Infinity;
const __mmTraps = __mmActiveObjectSnapshot().traps;
for (let __mmIndex = 0; __mmIndex < __mmTraps.length; __mmIndex++) {
const __mmObject = __mmTraps[__mmIndex];
if (
!__mmObject ||
!__mmObject.active ||
!__mmObject.trap ||
!__mmFriendlyStructure(__mmObject)
)
continue;
const __mmDistance = Math.hypot(
Number(__mmObject.x) - __mmSlot.x,
Number(__mmObject.y) - __mmSlot.y,
);
if (
__mmDistance <= Math.max(24, __mmSlot.scale * 0.75) &&
__mmDistance < __mmClosestDistance
)
((__mmClosest = __mmObject), (__mmClosestDistance = __mmDistance));
}
return __mmClosest;
}
function __mmUpdateTrapSpikeReplace(__mmCurrentTrap) {
const __mmSlot = __mmTrapSpikeReplaceSlot;
if (
!__mmAutoSpikeReplaceEnabled ||
__mmEmergencyGetawayActive() ||
!__mmSlot ||
!v ||
!v.alive ||
!__mmIsTrapped() ||
__mmInsta.isActive()
)
return;
if (
__mmCurrentTrap &&
__mmSlot.trapKey != null &&
__mmTrapBuildKey(__mmCurrentTrap) !== __mmSlot.trapKey
)
return void (__mmTrapSpikeReplaceSlot = null);
const __mmBlocker = __mmTrapSpikeReplaceBlocker(__mmSlot);
if (__mmBlocker) {
(__mmSlot.seenBlockingTrap = !0,
(__mmSlot.x = Number(__mmBlocker.x)),
(__mmSlot.y = Number(__mmBlocker.y)),
(__mmSlot.scale = Number(__mmBlocker.scale) || __mmSlot.scale));
return;
}
// Wait until the rear trap has genuinely appeared once. This prevents a
// rejected trap packet from being mistaken for an opened replacement slot.
if (!__mmSlot.seenBlockingTrap) return;
const __mmNow = Date.now(),
__mmSpike = __mmSpikeItem();
if (
__mmNow - __mmTrapSpikeReplaceLastAt < __mmFastCheckMs() ||
__mmHoldingMcGrabby() ||
!__mmAutoSpikeSpamHasCapacity(__mmSpike)
)
return;
const __mmData = b && b.list && b.list[__mmSpike];
if (!__mmData) return;
const __mmAngle = Math.atan2(__mmSlot.y - v.y, __mmSlot.x - v.x),
__mmScale = Number(__mmData.scale) || 49,
__mmDistance =
(Number(v.scale) || 35) +
__mmScale +
(Number(__mmData.placeOffset) || 0),
__mmX = Number(v.x) + Math.cos(__mmAngle) * __mmDistance,
__mmY = Number(v.y) + Math.sin(__mmAngle) * __mmDistance;
if (!__mmAutoSpikeSpamPositionClear(__mmX, __mmY, __mmScale)) return;
const __mmWeapon = __mmTrapAttackHeldWeapon || __mmSelectedWeapon(),
__mmRestore = __mmWeapon == null
? __mmSelectedTool()
: { item: __mmWeapon, weapon: !0 };
if (!__mmSendAutomaticPlacement(__mmSpike, __mmAngle, __mmRestore)) return;
(
__mmAutoSpikeSpamReservations.push({
item: __mmSpike,
x: __mmX,
y: __mmY,
scale: __mmScale,
expiresAt: __mmNow + 650,
}),
(__mmTrapSpikeReplaceLastAt = __mmNow),
(__mmTrapSpikeReplaceSlot = null),
__mmScheduleMouseAimReturn());
}
function __mmStopTrapBuildEscape(__mmClearAttempt = !0) {
const __mmWeapon = __mmTrapAttackActive
? __mmTrapAttackHeldWeapon || __mmTrapBreakWeapon(__mmCurrentNearbyTrap())
: __mmTrapBuildWeapon;
((__mmTrapBuildTimer && clearTimeout(__mmTrapBuildTimer),
(__mmTrapBuildTimer = 0),
(__mmTrapBuildWeapon = null),
__mmClearAttempt && (__mmTrapBuildAttemptKey = null),
!__mmIsTrapped() &&
((__mmTrapBuildPreferredItem = null),
(__mmTrapBuildPlacedKey = null),
(__mmTrapBuildPlacedCount = 0)),
__mmWeapon != null && __mmRestoreWeapon(__mmWeapon)));
}
function __mmStartTrapBuildEscape(__mmTrap) {
if (!v || !v.alive || !__mmIsTrapped() || __mmTrapBuildTimer) return;
const __mmNow = Date.now(),
__mmTrapKey = __mmTrap ? __mmTrapBuildKey(__mmTrap) : "locked";
if (__mmTrapKey !== __mmTrapBuildPlacedKey) {
((__mmTrapBuildPlacedKey = __mmTrapKey),
(__mmTrapBuildPlacedCount = 0),
(__mmTrapBuildPreferredItem = __mmTrapEmergencyHeldPreference()));
}
if (
__mmTrapKey == null ||
__mmTrapBuildPlacedCount >= 2 ||
(__mmTrapBuildAttemptKey === __mmTrapKey &&
__mmNow - __mmTrapBuildLastAt < Math.max(90, __mmServerTickMs()))
)
return;
const __mmPlan = __mmTrapEmergencyBuildPlan(__mmTrap);
((__mmTrapBuildAttemptKey = __mmTrapKey),
(__mmTrapBuildLastAt = __mmNow));
if (!__mmPlan.length) return;
const __mmCandidates = [];
for (let __mmIndex = 0; __mmIndex < __mmPlan.length; __mmIndex++) {
const __mmEntry = __mmPlan[__mmIndex],
// A blocked exact rear slot should not permanently disable emergency
// placement. Search the neighboring rear arc and retry on later ticks.
__mmCandidate = __mmSmartNearestLegalCandidate(
__mmEntry.item,
__mmEntry.angle,
0.72,
0.03,
);
if (!__mmCandidate) continue;
__mmCandidate.points = 10 - __mmIndex * 0.01;
if (
__mmCandidates.some(function (__mmExisting) {
return (
Math.hypot(
__mmExisting.x - __mmCandidate.x,
__mmExisting.y - __mmCandidate.y,
) <
__mmExisting.scale + __mmCandidate.scale
);
})
)
continue;
__mmCandidates.push(__mmCandidate);
}
if (!__mmCandidates.length) return;
__mmTrapBuildWeapon = __mmSelectedWeapon();
const __mmRestore =
__mmTrapBuildWeapon == null
? __mmSelectedTool()
: { item: __mmTrapBuildWeapon, weapon: !0 },
__mmPlaced = __mmSmartPlaceBurst(__mmCandidates, __mmRestore);
__mmPlaced > 0 &&
(__mmTrapBuildPlacedCount = Math.min(
2,
__mmTrapBuildPlacedCount + __mmPlaced,
));
if (__mmPlaced > 0)
for (
let __mmIndex = 0;
__mmIndex < Math.min(__mmPlaced, __mmCandidates.length);
__mmIndex++
)
__mmRememberTrapSpikeReplaceSlot(
__mmCandidates[__mmIndex],
__mmTrapKey,
);
__mmTrapBuildWeapon = null;
}
function __mmEquipTankForTrap() {
if (!v || !v.alive || !v.skins || !v.skins[40] || __mmRightClickHat != null)
return !1;
__mmTrapHat == null && (__mmTrapHat = __mmBestPostCombatHat());
return __mmActivateCombatHat(40);
}
function __mmEquipTrapDowntimeHat() {
if (
!v ||
!v.alive ||
__mmTrapHat == null ||
__mmRightClickHat != null ||
__mmCombatHatLockActive()
)
return;
const __mmHat = __mmBestPostCombatHat();
__mmEquipHatNow(__mmHat, !0);
}
function __mmUpdateTrapEscapeGear(__mmWeapon) {
if (!__mmTrapAttackActive || !v || !v.alive || __mmWeapon == null) return;
__mmTrapHat == null &&
(__mmTrapHat = __mmInstaSafeRestoreHat(
__mmBushRestoreHat(v.skinIndex),
));
if (!v.skins || !v.skins[40] || __mmRightClickHat != null) return;
const __mmNow = Date.now();
Number(__mmTrapAttackHeldWeapon) !== Number(__mmWeapon) &&
(__mmTrapManualReadyAt = 0);
const __mmSwingReady = __mmManualWeaponArming(
__mmWeapon,
__mmTrapManualReadyAt,
__mmNow,
);
if (__mmSwingReady) {
__mmEquipTankForTrap() &&
(__mmTrapManualReadyAt =
__mmNow + __mmManualWeaponCooldown(__mmWeapon, 40));
return;
}
__mmEquipTrapDowntimeHat();
}
function __mmObserveTrapEscapeSwing(__mmPlayerSid, __mmWeapon) {
const __mmResolvedWeapon =
__mmWeapon == null ? Number(v && v.weaponIndex) : Number(__mmWeapon);
if (
!v ||
!v.alive ||
!__mmTrapAttackActive ||
String(__mmPlayerSid) !== String(v.sid) ||
(__mmTrapAttackHeldWeapon != null &&
__mmResolvedWeapon !== Number(__mmTrapAttackHeldWeapon))
)
return;
__mmTrapManualReadyAt =
Date.now() + __mmManualWeaponCooldown(__mmResolvedWeapon, 40);
}
function __mmCancelTrapHatRestoreTimer() {
(__mmTrapHatRestoreTimer && clearTimeout(__mmTrapHatRestoreTimer),
(__mmTrapHatRestoreTimer = 0));
}
function __mmScheduleTrapHatRestore() {
__mmCancelTrapHatRestoreTimer();
__mmTrapHatRestoreTimer = setTimeout(function () {
((__mmTrapHatRestoreTimer = 0), __mmRestoreTrapHat());
}, __mmServerTickMs());
}
function __mmRestoreTrapHat() {
__mmCancelTrapHatRestoreTimer();
if (__mmTrapHat == null) return;
if (!v || !v.alive) {
((__mmTrapHat = null), (__mmTrapHatRestoreAttempts = 0));
return;
}
if (
__mmTrapAttackActive ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
__mmRightClickHat != null ||
__mmInsta.isActive() ||
__mmInstaSyncPending ||
__mmInstaSyncFiring ||
__mmBoostBreakHeld ||
__mmCombatHatLockActive() ||
(__mmActionOwner !== "idle" && __mmActionOwner !== "trapEscape")
)
return void __mmScheduleTrapHatRestore();
const __mmHat = __mmBestPostCombatHat(),
__mmPendingConflict = !!(
__mmPendingHat != null &&
__mmPendingHat !== __mmHat &&
Date.now() - __mmPendingHatAt < __mmGearHoldMs()
);
if (v.skinIndex === __mmHat && !__mmPendingConflict) {
((__mmPendingHat === __mmHat &&
((__mmPendingHat = null), (__mmPendingHatAt = 0))),
(__mmTrapHat = null),
(__mmTrapHatRestoreAttempts = 0));
return;
}
(__mmCanEquipHat(__mmHat) && __mmEquipHatNow(__mmHat, !0),
(__mmTrapHatRestoreAttempts += 1));
if (__mmTrapHatRestoreAttempts < 6)
return void __mmScheduleTrapHatRestore();
((__mmTrapHat = null), (__mmTrapHatRestoreAttempts = 0));
}
function __mmStopTrapAttack() {
const __mmRestore = __mmActionMayRestore("trapEscape"),
__mmReleaseAngle = Number.isFinite(__mmTrapAimAngle)
? __mmTrapAimAngle
: Ci();
(__mmTrapResumeTimer && clearTimeout(__mmTrapResumeTimer),
(__mmTrapResumeTimer = 0),
__mmStopTrapBuildEscape(),
__mmTrapAttackHeld && O.send("F", 0, __mmReleaseAngle),
(__mmTrapAttackHeld = !1),
(__mmTrapAttackHeldWeapon = null),
(__mmTrapAttackTargetKey = null),
(__mmTrapManualReadyAt = 0),
(__mmTrapWeaponSelectAt = 0),
__mmTrapAttackActive &&
((__mmTrapAttackActive = !1),
__mmRestore && __mmRestoreWeapon(__mmTrapWeapon),
(__mmTrapWeapon = null)),
(__mmTrapAimAngle = null),
(__mmTrapSpikeReplaceSlot = null),
__mmRestoreTrapHat(),
__mmActionRelease("trapEscape", "trap clear"));
}
function __mmPauseSoldierForBreaking() {
__mmCancelSoldierRestore();
if (__mmSoldierPreviousHat == null || !v || !v.alive || v.skinIndex !== 6)
return;
const __mmPreviousHat = __mmSoldierPreviousHat;
((__mmSoldierPreviousHat = null),
__mmCanEquipHat(__mmPreviousHat) && __mmEquipHatNow(__mmPreviousHat));
}
function __mmTrapWeaponRange(__mmWeapon, __mmTrap) {
const __mmData = b && b.weapons && b.weapons[__mmWeapon];
if (!__mmData || __mmData.projectile != null) return 0;
return (
(Number(__mmData.range) || 0) +
(v.scale || 35) +
(__mmTrap.scale || 35) +
8
);
}
function __mmTrapBreakWeapon(__mmTrap) {
if (!v || !v.weapons || !__mmTrap) return null;
const __mmCandidates = [
__mmGreatHammer,
v.weapons[0],
v.weapons[1],
];
const __mmDistance = Math.hypot(__mmTrap.x - v.x, __mmTrap.y - v.y);
for (
let __mmIndex = 0;
__mmIndex < __mmCandidates.length;
__mmIndex += 1
) {
const __mmWeapon = __mmCandidates[__mmIndex];
if (
__mmWeapon == null ||
!v.weapons.includes(__mmWeapon) ||
__mmDistance > __mmTrapWeaponRange(__mmWeapon, __mmTrap)
)
continue;
return __mmWeapon;
}
return null;
}
function __mmTrapEscapeLethalSpike(__mmTrap) {
if (!v || !v.alive || !__mmTrap || !__mmTrap.active) return null;
const __mmThreat = __mmCombatThreatSnapshot(),
// Trap escape is safety critical, so bypass the general FPS snapshot's
// short cache while caught. This sees a newly placed adjacent spike on the
// next reaction scan without making normal-world rendering more expensive.
__mmSpikes = __mmActiveObjectSnapshot(!0).spikes,
__mmHealth = Math.max(0, Number(v.health) || 0),
__mmBaseThreatDamage = Math.max(
0,
Number(__mmThreat.damage) - Number(__mmThreat.spikeDamage),
),
__mmPotentialDamage = Math.max(
Number(__mmThreat.potentialDamage) || 0,
__mmBaseThreatDamage,
),
__mmTrapScale = __mmThreatObjectScale(__mmTrap),
__mmPlayerScale = Number(v.scale) || 35;
let __mmBest = null,
__mmBestScore = Infinity;
for (let __mmIndex = 0; __mmIndex < __mmSpikes.length; __mmIndex++) {
const __mmSpike = __mmSpikes[__mmIndex];
if (!__mmSpike || !__mmSpike.active) continue;
const __mmDamage =
__mmAutoSpikeKillDamage(__mmSpike) *
__mmThreatIncomingDamageMultiplier(),
__mmSpikeScale = __mmThreatObjectScale(__mmSpike),
__mmPlayerDistance = Math.hypot(__mmSpike.x - v.x, __mmSpike.y - v.y),
__mmTrapDistance = Math.hypot(
__mmSpike.x - __mmTrap.x,
__mmSpike.y - __mmTrap.y,
),
__mmPredictedLethal =
__mmSpike === __mmThreat.lethalSpike ||
__mmPotentialDamage + __mmDamage + 0.001 >= __mmHealth,
__mmReachableWeapon = __mmTrapBreakWeapon(__mmSpike);
if (
__mmDamage <= 0 ||
__mmFriendlyStructure(__mmSpike) ||
!__mmPredictedLethal ||
__mmReachableWeapon == null ||
__mmPlayerDistance > __mmPlayerScale + __mmSpikeScale + 145 ||
__mmTrapDistance > __mmTrapScale + __mmSpikeScale + 95
)
continue;
const __mmScore =
__mmPlayerDistance * 2 +
__mmTrapDistance -
__mmDamage * 4 -
(__mmSpike === __mmThreat.lethalSpike ? 500 : 0);
if (__mmScore < __mmBestScore)
((__mmBestScore = __mmScore), (__mmBest = __mmSpike));
}
return __mmBest;
}
function __mmTrapEscapeBreakTarget(__mmTrap) {
return __mmTrapEscapeLethalSpike(__mmTrap) || __mmTrap;
}
function __mmTryAntiRetrapPush(__mmTrap) {
if (
!__mmAntiRetrapPushEnabled ||
__mmAntiRetrapReleaseTimer ||
!v ||
!v.alive ||
!__mmTrap ||
!v.weapons ||
!v.weapons.includes(__mmGreatHammer) ||
!__mmWeaponReady(__mmGreatHammer) ||
Date.now() - __mmAntiRetrapLastAt < __mmServerTickMs()
)
return !1;
const __mmTrapState = __mmBreakableState(__mmTrap),
__mmTrapHealth = Number(
__mmTrapState ? __mmTrapState.health : __mmTrap.health,
),
__mmHammerDamage = __mmWeaponStructureDamage(
v,
__mmGreatHammer,
__mmTrap,
),
__mmEnemy = __mmNearestEnemy(),
__mmPrimary = v.weapons[0],
__mmPrimaryData = b && b.weapons && b.weapons[__mmPrimary];
if (
!__mmEnemy ||
__mmPrimary == null ||
!__mmPrimaryData ||
__mmPrimaryData.projectile != null ||
!__mmWeaponReady(__mmPrimary) ||
!Number.isFinite(__mmTrapHealth) ||
__mmTrapHealth > __mmHammerDamage + 0.001
)
return !1;
const __mmDistance = Math.hypot(__mmEnemy.x - v.x, __mmEnemy.y - v.y),
__mmRange =
(Number(__mmPrimaryData.range) || 0) +
(Number(v.scale) || 35) +
(Number(__mmEnemy.scale) || 35) +
8;
if (__mmDistance > __mmRange) return !1;
const __mmAngle = Math.atan2(__mmEnemy.y - v.y, __mmEnemy.x - v.x);
try {
(__mmTrapAttackHeld && O.send("F", 0, __mmTrapAimAngle),
(__mmTrapAttackHeld = !1),
(__mmTrapAttackHeldWeapon = null),
(__mmTrapAttackTargetKey = null),
__mmInsta.turretReady() &&
(__mmActivateCombatHat(__mmTurretGear), __mmAssumeTurretGearShot()),
O.send("D", __mmAngle),
je(__mmPrimary, !0),
O.send("F", 1, __mmAngle),
(__mmAntiRetrapLastAt = Date.now()));
} catch (__mmAntiRetrapError) {
return !1;
}
__mmAntiRetrapReleaseTimer = setTimeout(function () {
((__mmAntiRetrapReleaseTimer = 0),
v && v.alive && O.send("F", 0, __mmAngle),
(__mmTrapAttackHeld = !1),
(__mmTrapAttackHeldWeapon = null),
(__mmTrapAttackTargetKey = null),
(__mmTrapWeaponSelectAt = 0),
__mmBreakTrap());
}, __mmServerTickMs());
return !0;
}
function __mmFriendlyPlayerTrapRescueTarget() {
if (!v || !v.alive || !Array.isArray(E)) return null;
const __mmTraps = __mmActiveTrapObjects();
let __mmBest = null,
__mmBestDistance = Infinity;
for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
const __mmPlayer = E[__mmPlayerIndex];
if (
!__mmPlayer ||
__mmPlayer === v ||
__mmPlayer.alive === !1 ||
(!__mmSameTeam(__mmPlayer) && !__mmIsFriendPlayer(__mmPlayer))
)
continue;
for (let __mmTrapIndex = 0; __mmTrapIndex < __mmTraps.length; __mmTrapIndex++) {
const __mmTrap = __mmTraps[__mmTrapIndex];
if (!__mmServerTrapContact(__mmPlayer, __mmTrap)) continue;
const __mmDistance = Math.hypot(__mmTrap.x - v.x, __mmTrap.y - v.y);
if (
__mmDistance <= __mmTrapWeaponRange(__mmGreatHammer, __mmTrap) &&
__mmDistance < __mmBestDistance
)
((__mmBestDistance = __mmDistance),
(__mmBest = { player: __mmPlayer, trap: __mmTrap }));
}
}
return __mmBest;
}
function __mmStopTeammateRescue(__mmReason) {
const __mmAngle = __mmTeammateRescueAngle,
__mmRestore = __mmTeammateRescueRestoreTool,
__mmMayRestore = __mmActionMayRestore("teammateRescue");
(__mmTeammateRescueReleaseTimer &&
clearTimeout(__mmTeammateRescueReleaseTimer),
(__mmTeammateRescueReleaseTimer = 0),
__mmAngle != null && v && v.alive && O.send("F", 0, __mmAngle),
__mmMayRestore && __mmRestore != null && __mmRestoreTool(__mmRestore),
(__mmTeammateRescueAngle = null),
(__mmTeammateRescueRestoreTool = null),
__mmActionRelease(
"teammateRescue",
__mmReason || "rescue swing sent",
),
__mmScheduleMouseAimReturn());
}
function __mmUpdateTeammateTrapRescue() {
if (
!__mmTeammateTrapRescueEnabled ||
__mmTeammateRescueReleaseTimer ||
!v ||
!v.alive ||
!v.weapons ||
!v.weapons.includes(__mmGreatHammer) ||
!__mmWeaponReady(__mmGreatHammer) ||
__mmIsTrapped() ||
__mmInsta.isActive() ||
__mmBoostInsta.isActive() ||
__mmPrimaryHeld ||
__mmSecondaryHeld ||
Date.now() - __mmTeammateRescueLastAt < __mmServerTickMs() ||
!__mmActionCanPreempt("teammateRescue")
)
return;
const __mmTarget = __mmFriendlyPlayerTrapRescueTarget();
if (
!__mmTarget ||
!__mmActionClaim("teammateRescue", "friendly player trapped")
)
return;
const __mmAngle = Math.atan2(
__mmTarget.trap.y - v.y,
__mmTarget.trap.x - v.x,
),
__mmRestore = __mmSelectedTool();
try {
(__mmActivateCombatHat(40),
O.send("D", __mmAngle),
je(__mmGreatHammer, !0),
O.send("F", 1, __mmAngle),
(__mmTeammateRescueAngle = __mmAngle),
(__mmTeammateRescueRestoreTool = __mmRestore),
(__mmTeammateRescueLastAt = Date.now()));
} catch (__mmTeammateRescueError) {
((__mmTeammateRescueAngle = __mmAngle),
(__mmTeammateRescueRestoreTool = __mmRestore),
__mmStopTeammateRescue("rescue packet failed"));
return;
}
__mmTeammateRescueReleaseTimer = setTimeout(function () {
__mmStopTeammateRescue("rescue swing sent");
}, __mmServerTickMs());
}
function __mmStartTeammateTrapRescue() {
__mmEnsureOperationPipeline();
}
function __mmBreakTrap() {
if (
!__mmTrapEscapeEnabled ||
!v ||
!v.alive ||
!__mmIsTrapped()
)
return void __mmStopTrapAttack();
// The insta owns the same weapon, hat, and aim channels for only a few
// ticks. Leave the trap interval alive but idle until cleanup hands control
// back, instead of cancelling the combo on its next fast scan.
if (__mmInsta.isActive()) return;
// Being genuinely trapped is still a safety priority; an idle trap-escape
// interval must not otherwise terminate every R insta burst.
if (!__mmActionCanPreempt("trapEscape")) return;
const __mmTrapRestoreHat =
__mmPrimaryClickHat != null
? __mmPrimaryClickHat
: __mmRightClickHat != null
? __mmRightClickHat
: __mmSoldierPreviousHat != null
? __mmSoldierPreviousHat
: __mmInstaSafeRestoreHat(__mmBushRestoreHat(v.skinIndex));
if (__mmInsta.isActive()) __mmInsta.cancel("trap-escape");
(__mmInstaSyncPending || __mmInstaSyncFiring) && __mmStopInstaSync();
__mmBoostBreakHeld && __mmStopBoostBreak();
__mmActionOwner === "shieldDefense" && __mmStopShieldDefense("trap priority");
__mmPrimaryHeld && __mmStopPrimaryInput();
(__mmPrimaryClickHat != null || __mmPrimaryClickTail != null) &&
__mmForceRestoreBullForPrimary();
__mmSecondaryHeld && __mmStopSecondary();
__mmRightClickHat != null && __mmForceRestoreRightClickHat();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (__mmActionOwner === "antiInsta") {
(__mmAntiInstaActionTimer && clearTimeout(__mmAntiInstaActionTimer),
(__mmAntiInstaActionTimer = 0),
__mmActionRelease("antiInsta", "trap priority"));
}
if (!__mmActionClaim("trapEscape", "locked pit trap")) return;
__mmAutoHeal(!0);
const __mmTrap = __mmCurrentNearbyTrap();
if (__mmTrap == null) return;
// Emergency rear placement borrows this trap-escape phase, then restores
// the breaker before its continuous attack is armed below.
__mmStartTrapBuildEscape(__mmTrap);
if (__mmTryAntiRetrapPush(__mmTrap)) return;
const __mmBreakTarget = __mmTrapEscapeBreakTarget(__mmTrap),
__mmBreakingSpike = __mmBreakTarget !== __mmTrap,
__mmTargetKey =
(__mmBreakingSpike ? "spike:" : "trap:") +
String(
__mmBreakTarget.sid == null
? __mmBreakTarget.x + ":" + __mmBreakTarget.y
: __mmBreakTarget.sid,
),
__mmAngle = Math.atan2(
__mmBreakTarget.y - v.y,
__mmBreakTarget.x - v.x,
);
__mmActionClaim(
"trapEscape",
__mmBreakingSpike ? "lethal adjacent spike" : "locked pit trap",
);
(__mmTrapAttackActive ||
(__mmCancelTrapHatRestoreTimer(),
(__mmTrapHatRestoreAttempts = 0),
__mmPauseSoldierForBreaking(),
(__mmTrapAttackActive = !0),
(__mmTrapWeapon = __mmSelectedWeapon()),
(__mmTrapHat == null && (__mmTrapHat = __mmTrapRestoreHat))));
// Lock the normal aim source onto the selected break target. When the lethal
// spike disappears, the target key changes and the same continuous breaker
// is re-armed toward the pit without waiting for a fresh input.
__mmTrapAimAngle = __mmAngle;
const __mmWeapon = __mmTrapBreakWeapon(__mmBreakTarget);
if (__mmWeapon == null) return;
__mmUpdateTrapEscapeGear(__mmWeapon);
if (
!__mmTrapAttackHeld ||
__mmTrapAttackHeldWeapon !== __mmWeapon ||
__mmTrapAttackTargetKey !== __mmTargetKey
) {
(__mmTrapAttackHeld && O.send("F", 0, __mmAngle),
je(__mmWeapon, !0),
O.send("D", __mmAngle),
O.send("F", 1, __mmAngle),
(__mmTrapAttackHeld = !0),
(__mmTrapAttackHeldWeapon = __mmWeapon),
(__mmTrapAttackTargetKey = __mmTargetKey),
(__mmTrapWeaponSelectAt = Date.now()));
} else if (
(Number(v.buildIndex) >= 0 || Number(v.weaponIndex) !== Number(__mmWeapon)) &&
Date.now() - __mmTrapWeaponSelectAt >= 25
)
((__mmTrapWeaponSelectAt = Date.now()), je(__mmWeapon, !0));
}
function __mmStartTrapEscape() {
__mmEnsureOperationPipeline();
}
function __mmQueueTrapEscapeResume(__mmEvent) {
if (
(__mmEvent && __mmEvent.isTrusted === !1) ||
!__mmTrapEscapeEnabled ||
!v ||
!v.alive ||
!__mmIsTrapped()
)
return;
__mmTrapResumeTimer && clearTimeout(__mmTrapResumeTimer);
__mmTrapResumeTimer = setTimeout(function () {
__mmTrapResumeTimer = 0;
if (!__mmTrapEscapeEnabled || !v || !v.alive || !__mmIsTrapped()) return;
// User input may have emitted attack-up or changed tools after the escape
// loop set this latch. Invalidate it and issue a fresh continuous hold now
// that the input event has completely finished propagating.
((__mmTrapAttackHeld = !1),
(__mmTrapAttackHeldWeapon = null),
(__mmTrapAttackTargetKey = null),
(__mmTrapWeaponSelectAt = 0),
__mmBreakTrap());
}, 0);
}
document.addEventListener("mouseup", __mmQueueTrapEscapeResume, !0);
document.addEventListener("pointerup", __mmQueueTrapEscapeResume, !0);
document.addEventListener("touchend", __mmQueueTrapEscapeResume, !0);
document.addEventListener("keyup", __mmQueueTrapEscapeResume, !0);
function __mmWithinTrapAlertRange(__mmTrap) {
return __mmPlayerCenterTouchesEnemyTrap(__mmTrap);
}
function __mmUpdateTrapAlert() {
const __mmNearbyTrap = v && v.alive ? __mmCurrentNearbyTrap() : null;
// Only the local player's center entering the enemy trap's hitbox counts as
// caught. A server movement lock alone is intentionally not trap evidence.
const __mmIncident = !!(
v &&
v.alive &&
__mmWithinTrapAlertRange(__mmNearbyTrap)
);
if (__mmIncident) {
if (!__mmTrapChatIncidentActive) {
(__mmTrapChatIncidentActive = !0,
__mmTrapAlertChatEnabled && __mmSendChat("Oh no! A trap!"));
}
} else {
__mmTrapChatIncidentActive = !1;
}
const __mmTrapped = __mmIncident;
let __mmAlert = document.getElementById("kitty-klient-trap-alert");
if (!__mmAlert && !__mmTrapped) return;
if (!__mmAlert) {
if (!document.body) return;
((__mmAlert = document.createElement("div")),
(__mmAlert.id = "kitty-klient-trap-alert"),
(__mmAlert.setAttribute("role", "status")),
(__mmAlert.setAttribute("aria-live", "assertive")),
(__mmAlert.style.cssText =
"position:fixed;top:18%;left:50%;z-index:2147483647;transform:translate(-50%,-8px);max-width:min(560px,calc(100vw - 30px));box-sizing:border-box;padding:11px 18px;border:1px solid #ffb4b4;border-radius:11px;background:rgba(127,20,28,.92);color:#fff;font:800 18px/1.3 Arial,sans-serif;letter-spacing:.01em;text-align:center;text-shadow:0 0 7px rgba(255,180,180,.7);box-shadow:0 5px 22px rgba(0,0,0,.4),0 0 16px rgba(239,68,68,.28);pointer-events:none;opacity:0;transition:opacity .12s ease,transform .12s ease;"),
document.body.appendChild(__mmAlert));
}
(__mmAlert.textContent = "Oh no! A trap!"),
(__mmAlert.style.opacity = __mmTrapped ? "1" : "0"),
(__mmAlert.style.transform = __mmTrapped
? "translate(-50%,0)"
: "translate(-50%,-8px)");
}
function __mmStartTrapAlert() {
__mmTrapAlertTimer ||
(__mmTrapAlertTimer = setInterval(__mmUpdateTrapAlert, __mmFastCheckMs()));
}
function __mmStopTrapEscape() {
(__mmTrapAttackTimer &&
(clearInterval(__mmTrapAttackTimer), (__mmTrapAttackTimer = 0)),
__mmStopTrapAttack());
}
function __mmCanAutoSoldier() {
return (
__mmSoldierAutoEnabled &&
!__mmAssassinConcealed &&
!__mmCombatHatLockActive() &&
__mmActionAvailable("soldierGear") &&
v &&
v.alive &&
v.skinIndex !== 40 &&
v.skins &&
v.skins[6] &&
!__mmSyncFollowerEnabled &&
!__mmBushModeEnabled &&
!__mmInsta.isActive() &&
!__mmMovementGearActive() &&
!__mmPlayerMoving() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
!__mmBoostBreakHeld &&
__mmPrimaryClickHat == null &&
__mmRightClickHat == null
);
}
function __mmEnemyWithinSoldierRange() {
if (!v || !v.alive) return !1;
if (__mmLiveStateFresh())
return __mmLiveState.nearestEnemyDistance <= __mmSoldierRange;
for (let __mmPlayerIndex = 0; __mmPlayerIndex < E.length; __mmPlayerIndex++) {
const __mmPlayer = E[__mmPlayerIndex];
if (!__mmIsEnemyPlayer(__mmPlayer)) continue;
const __mmDx = __mmPlayer.x - v.x,
__mmDy = __mmPlayer.y - v.y;
if (
__mmDx * __mmDx + __mmDy * __mmDy <=
__mmSoldierRange * __mmSoldierRange
)
return !0;
}
return !1;
}
function __mmCancelSoldierRestore() {
__mmSoldierRestoreTimer &&
(clearTimeout(__mmSoldierRestoreTimer), (__mmSoldierRestoreTimer = 0));
}
function __mmEquipSoldier() {
if (!__mmCanAutoSoldier()) return;
__mmCancelSoldierRestore();
if (v.skinIndex !== 6) {
(__mmSoldierPreviousHat == null &&
(__mmSoldierPreviousHat = __mmInstaSafeRestoreHat(
__mmBushRestoreHat(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() {
__mmEnsureOperationPipeline();
}
function __mmTurretGearCanFire(__mmPlayer) {
return __mmPlayer.skinIndex === __mmTurretGear;
}
function __mmAiEnemySnapshot(__mmPlayer) {
const __mmDx = __mmPlayer.x - v.x,
__mmDy = __mmPlayer.y - v.y;
return {
distance: Math.round(Math.sqrt(__mmDx * __mmDx + __mmDy * __mmDy)),
health: Number(__mmPlayer.health) || 0,
maxHealth: Number(__mmPlayer.maxHealth) || 0,
weapon: Number(__mmPlayer.weaponIndex) || 0,
hat: Number(__mmPlayer.skinIndex) || 0,
tail: Number(__mmPlayer.tailIndex) || 0,
turretGear: __mmPlayer.skinIndex === __mmTurretGear,
};
}
function __mmAiContext() {
if (!v) return { available: !1 };
const __mmEnemies = [];
for (let __mmIndex = 0; __mmIndex < E.length; __mmIndex++) {
const __mmPlayer = E[__mmIndex];
if (
!__mmPlayer ||
!__mmPlayer.alive ||
__mmPlayer === v ||
__mmPlayer.sid === v.sid ||
!__mmIsEnemyPlayer(__mmPlayer)
)
continue;
__mmEnemies.push(__mmAiEnemySnapshot(__mmPlayer));
}
__mmEnemies.sort(function (__mmFirst, __mmSecond) {
return __mmFirst.distance - __mmSecond.distance;
});
const __mmAngle = __mmTrapAngle();
return {
available: !0,
modVersion: "3.15.0",
player: {
alive: !!v.alive,
health: Number(v.health) || 0,
maxHealth: Number(v.maxHealth) || 0,
gold: Number(v.points) || 0,
wood: Number(v.wood) || 0,
food: Number(v.food) || 0,
stone: Number(v.stone) || 0,
weapons: Array.isArray(v.weapons) ? v.weapons.slice(0, 4) : [],
selectedWeapon: __mmSelectedWeapon(),
hat: Number(v.skinIndex) || 0,
tail: Number(v.tailIndex) || 0,
trapped: __mmIsTrapped(),
foodItem: v.items ? v.items[0] : null,
},
nearbyEnemies: __mmEnemies.slice(0, 8),
nearbyTrap: { detected: __mmAngle != null, angle: __mmAngle },
features: { autoHeal: __mmAutoHealEnabled, soldierRange: __mmSoldierRange },
};
}
function __mmPublishAiContext() {
window.dispatchEvent(
new CustomEvent("MooMooAIContext", { detail: __mmAiContext() }),
);
}
window.addEventListener("MooMooAIRequestContext", __mmPublishAiContext);
function __mmCanUseShieldDefense() {
return (
__mmShieldDefenseEnabled &&
__mmActionAvailable("shieldDefense") &&
v &&
v.alive &&
v.weapons.includes(__mmShieldWeapon) &&
!__mmInsta.isActive() &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive
);
}
function __mmStopShieldDefense(__mmReason) {
const __mmWeapon = __mmShieldDefenseWeapon,
__mmRestore = __mmActionMayRestore("shieldDefense");
((__mmShieldDefenseTimer && clearTimeout(__mmShieldDefenseTimer),
(__mmShieldDefenseTimer = 0),
(__mmShieldDefenseWeapon = null),
__mmRestore &&
!__mmPrimaryHeld &&
!__mmSecondaryHeld &&
!__mmTrapAttackActive &&
__mmWeapon != null &&
__mmWeapon !== __mmShieldWeapon &&
__mmRestoreWeapon(__mmWeapon),
__mmActionRelease("shieldDefense", __mmReason || "defense complete")));
}
function __mmUseShieldDefense(__mmPlayer) {
if (!__mmCanUseShieldDefense()) return;
const __mmDistance = (__mmPlayer.x - v.x) ** 2 + (__mmPlayer.y - v.y) ** 2;
if (__mmDistance > __mmShieldDefenseRange * __mmShieldDefenseRange) return;
if (!__mmActionClaim("shieldDefense", "polearm defense")) return;
const __mmWeapon = __mmSelectedWeapon();
(__mmShieldDefenseTimer && clearTimeout(__mmShieldDefenseTimer),
__mmShieldDefenseWeapon == null && (__mmShieldDefenseWeapon = __mmWeapon),
je(__mmShieldWeapon, !0),
O.send("9", Math.atan2(__mmPlayer.y - v.y, __mmPlayer.x - v.x)),
(__mmShieldDefenseTimer = setTimeout(function () {
__mmStopShieldDefense("defense complete");
}, __mmShieldDefenseMs)));
}
function __mmHandleEnemyPolearmSwing(__mmPlayerSid, __mmWeapon) {
const __mmPlayer = Rt(__mmPlayerSid);
if (
!__mmIsEnemyPlayer(__mmPlayer) ||
(__mmPlayer.weaponIndex !== __mmPolearmWeapon &&
__mmWeapon !== __mmPolearmWeapon) ||
!__mmTurretGearCanFire(__mmPlayer)
)
return;
__mmUseShieldDefense(__mmPlayer);
}
window.addEventListener("blur", __mmStopFoodSpam);
window.addEventListener("blur", function () {
__mmStopBuildSpam();
});
function __mmIsGameClick(__mmEvent) {
return (
__mmEvent.target instanceof Element &&
__mmEvent.target.closest("#gameCanvas,#touch-controls-fullscreen")
);
}
function __mmManualWeaponCooldown(__mmWeapon, __mmSwingHat = null) {
const __mmData = b && b.weapons && b.weapons[__mmWeapon];
const __mmEffective =
__mmSwingHat == null
? 0
: __mmToolCooldownDuration({ skinIndex: __mmSwingHat }, __mmWeapon);
return Math.max(
__mmServerTickMs(),
Number(__mmEffective) ||
Number(__mmData && __mmData.speed) ||
__mmServerTickMs(),
);
}
function __mmGearHoldMs() {
return __mmServerTickMs() * Math.max(
1,
Math.min(8, Math.round(Number(__mmGearHoldTicks) || 3)),
);
}
function __mmBullPrimaryAvailable() {
return !!(
__mmBullHelmetEnabled &&
v &&
v.alive &&
v.weapons &&
v.weapons[0] != null &&
v.weapons[0] !== 8 &&
v.skins &&
v.skins[7] &&
!__mmSecondaryHeld &&
__mmRightClickHat == null
);
}
function __mmPrimaryDamageTail() {
if (!v || !v.alive) return null;
if (v.tails && v.tails[__mmCorruptXWings]) {
__mmPrimaryClickTail == null &&
(__mmPrimaryClickTail = __mmBushRestoreTail(v.tailIndex));
return __mmCorruptXWings;
}
if (__mmEffectiveTailIndex() === 11) {
__mmPrimaryClickTail == null &&
(__mmPrimaryClickTail = __mmBushRestoreTail(v.tailIndex));
return 0;
}
return null;
}
function __mmClearPrimaryGearTimer() {
(__mmPrimaryGearTimer && clearTimeout(__mmPrimaryGearTimer),
(__mmPrimaryGearTimer = 0));
}
function __mmSchedulePrimaryGear(__mmCallback) {
__mmClearPrimaryGearTimer();
__mmPrimaryGearTimer = setTimeout(function () {
(__mmPrimaryGearTimer = 0, __mmCallback());
}, __mmServerTickMs());
}
function __mmManualWeaponArming(__mmWeapon, __mmReadyAt, __mmNow = Date.now()) {
if (!v || !v.alive || __mmWeapon == null || __mmNow < __mmReadyAt) return !1;
// A mouse-down is only intent. Both the server reload and Kitty's
// actual-swing clock must be clear before any swing gear/timer is renewed.
if (__mmWeaponIsReloading(__mmWeapon)) return !1;
const __mmReload = v.reloads && Number(v.reloads[__mmWeapon]);
return !Number.isFinite(__mmReload) || __mmReload <= __mmFastCheckMs();
}
function __mmSecondaryTankLead(__mmWeapon, __mmReadyAt, __mmNow = Date.now()) {
return __mmManualWeaponArming(__mmWeapon, __mmReadyAt, __mmNow) ? 0 : -1;
}
function __mmEquipBullForPrimary(__mmNow = Date.now()) {
if (!__mmBullPrimaryAvailable()) return !1;
const __mmWeapon = v.weapons[0];
(__mmClearPrimaryGearTimer(),
(__mmPrimaryGearStage = "bull"),
__mmPrimaryClickHat == null &&
(__mmPrimaryClickHat = __mmBestPostCombatHat()),
// This call and the F=1 press run in the same synchronous packet phase.
__mmActivateCombatHat(7, __mmPrimaryDamageTail()),
(__mmPrimaryManualWeapon = __mmWeapon),
(__mmPrimaryManualReadyAt =
__mmNow + __mmManualWeaponCooldown(__mmWeapon, 7)));
return !0;
}
function __mmEquipPrimaryDowntimeHat() {
if (!v || !v.alive || __mmCombatHatLockActive()) return;
const __mmHat = __mmBestPostCombatHat(),
__mmTail = __mmDesiredHeldTail(v.weapons && v.weapons[0]);
(__mmClearPrimaryGearTimer(),
(__mmPrimaryGearStage = "downtime"),
__mmRememberHeldTail(__mmTail),
__mmEquipGearPair(
__mmHat,
__mmTail == null ? __mmPrimaryClickTail : __mmTail,
!0,
));
}
function __mmRestoreBullForPrimary() {
if (__mmCombatHatLockActive() && Number(__mmCombatHatLockHat) === 7) {
__mmScheduleCombatHatFinish();
return;
}
if (__mmPrimaryHeld || __mmSecondaryHeld || __mmRightClickHat != null) return;
if (!v || !v.alive) {
(__mmClearPrimaryGearTimer(),
(__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
(__mmPrimaryGearStage = null));
return;
}
const __mmHat = __mmBestPostCombatHat(),
__mmTail = __mmPrimaryClickTail;
(__mmClearPrimaryGearTimer(),
(__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
(__mmPrimaryGearStage = null),
__mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmForceRestoreBullForPrimary() {
if (__mmPrimaryClickHat == null && __mmPrimaryClickTail == null) return;
const __mmHat = __mmBestPostCombatHat(),
__mmTail = __mmPrimaryClickTail;
(__mmClearPrimaryGearTimer(),
(__mmPrimaryClickHat = null),
(__mmPrimaryClickTail = null),
(__mmPrimaryGearStage = null),
v &&
v.alive &&
!__mmCombatHatLockActive() &&
__mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmPulsePrimaryBullWeapon() {
if (!__mmPrimaryHeld || !__mmBullPrimaryAvailable()) return;
const __mmNow = Date.now(),
__mmWeapon = v.weapons[0],
__mmSwinging = __mmManualWeaponArming(
__mmWeapon,
__mmPrimaryManualReadyAt,
__mmNow,
);
__mmSwinging && __mmEquipBullForPrimary(__mmNow);
!__mmSwinging &&
__mmPrimaryGearStage !== "bull" &&
__mmUpdateHeldGear(__mmWeapon);
// Native press-and-hold: never release between weapon cooldowns. The server
// repeats attacks at the weapon's real speed while this state remains down.
if (!__mmPrimaryAttackDown) {
(je(v.weapons[0], !0),
__mmSendWeaponAttack(1),
(__mmPrimaryAttackDown = !0));
}
}
function __mmStartPrimaryInput() {
if (__mmPrimaryHeld || !v || !v.alive || v.weapons[0] == null) return !1;
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (!__mmActionClaim("manualAttack", "left click")) return !1;
const __mmWeapon = Number(v.weapons[0]);
(Number(__mmPrimaryManualWeapon) !== __mmWeapon &&
((__mmPrimaryManualWeapon = __mmWeapon),
(__mmPrimaryManualReadyAt = 0)),
(__mmPrimaryHeld = !0),
__mmStartHeldAttackPulse(),
__mmAtFullHealth() && __mmStopFoodSpam());
return !0;
}
function __mmStopPrimaryInput() {
((__mmPrimaryHeld = !1),
__mmStopHeldAttackPulse(),
__mmSecondaryHeld && __mmPulseHeldAttack(),
__mmRestoreBullForPrimary(),
__mmRestoreHeldHat(),
__mmRestoreHeldTail(),
__mmRestoreTrapHat(),
!__mmSecondaryHeld && __mmActionRelease("manualAttack", "left click released"));
(__mmUpdateMovementGear(), __mmUpdateWeaponRecharge());
}
function __mmObservePhysicalMouseButtons(__mmButtons) {
const __mmPrimary = !!(Number(__mmButtons) & 1),
__mmSecondary = !!(Number(__mmButtons) & 2);
if (
__mmPrimary === __mmPhysicalPrimaryDown &&
__mmSecondary === __mmPhysicalSecondaryDown
)
return;
((__mmPhysicalPrimaryDown = __mmPrimary),
(__mmPhysicalSecondaryDown = __mmSecondary),
(__mmPhysicalInputAt = Date.now()));
}
function __mmObservePhysicalMouseRelease(__mmEvent) {
if (__mmEvent && __mmEvent.button === 0)
__mmPhysicalPrimaryDown = !1;
if (__mmEvent && __mmEvent.button === 2)
__mmPhysicalSecondaryDown = !1;
__mmPhysicalInputAt = Date.now();
}
window.addEventListener("mouseup", __mmObservePhysicalMouseRelease, !0);
window.addEventListener("pointerup", __mmObservePhysicalMouseRelease, !0);
window.addEventListener(
"pointermove",
function (__mmEvent) {
(!__mmEvent.pointerType || __mmEvent.pointerType === "mouse") &&
__mmObservePhysicalMouseButtons(__mmEvent.buttons);
},
!0,
);
window.addEventListener(
"pointercancel",
function () {
((__mmPhysicalPrimaryDown = !1),
(__mmPhysicalSecondaryDown = !1),
(__mmPhysicalInputAt = Date.now()));
},
!0,
);
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (!__mmIsGameClick(__mmEvent) || __mmEvent.button !== 0) return;
if (
!__mmRuntimeBindingMatches(__mmKeybinds.primaryAttack, __mmEvent, !0) &&
!__mmRuntimeBindingMatches(__mmKeybinds.clickBoostInsta, __mmEvent, !0)
)
return;
((__mmPhysicalPrimaryDown = !0), (__mmPhysicalInputAt = Date.now()));
if (__mmHandleBushCombatClick(__mmEvent)) return;
if (__mmBoostInsta.isActive()) {
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
return;
}
// Mouse modes are exclusive. Cancel right-click before left becomes active.
(__mmSecondaryHeld || __mmRightClickHat != null) &&
(__mmFinishSecondaryInput(), __mmForceRestoreRightClickHat());
// A real click always wins over the queued R burst; cancel first, then
// allow this existing input path to proceed normally.
__mmInsta.isActive() && __mmInsta.cancel("manual-primary");
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
if (__mmUpdateAutoInsta()) {
(__mmEvent.preventDefault(), __mmEvent.stopImmediatePropagation());
return;
}
if (!__mmStartPrimaryInput()) return;
(__mmEvent.preventDefault(),
__mmEvent.stopImmediatePropagation(),
null);
},
!0,
);
document.addEventListener(
"mouseup",
function (__mmEvent) {
if (
__mmCleanupAttackHeld &&
__mmCleanupMouseButton === 0 &&
__mmEvent.button === 0
)
return;
if (
__mmEvent.button !== 0 ||
!__mmPrimaryHeld ||
__mmBindingActionHeld("primaryAttack") ||
__mmBindingActionHeld("clickBoostInsta")
)
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 __mmRightClickAngleDistance(__mmFirst, __mmSecond) {
return Math.abs(
Math.atan2(
Math.sin(Number(__mmFirst) - Number(__mmSecond)),
Math.cos(Number(__mmFirst) - Number(__mmSecond)),
),
);
}
function __mmRightClickShieldPlan(__mmForce = !1) {
const __mmNow = Date.now(),
__mmCacheMs = Math.max(10, Math.min(25, __mmFastCheckMs()));
if (
!__mmForce &&
__mmNow - __mmRightClickShieldPlanAt <= __mmCacheMs
)
return __mmRightClickShieldPlanCache;
(__mmRightClickShieldPlanAt = __mmNow,
(__mmRightClickShieldPlanCache = null));
if (
!__mmShieldDefenseEnabled ||
!v ||
!v.alive ||
!v.weapons ||
Number(v.weapons[1]) !== __mmShieldWeapon
)
return null;
const __mmThreat = __mmCombatThreatSnapshot(),
__mmThreatEntries = Array.isArray(__mmThreat && __mmThreat.entries)
? __mmThreat.entries.filter(function (__mmEntry) {
return !!(
__mmEntry &&
(__mmEntry.type === "projectile" || __mmEntry.type === "turret") &&
Number.isFinite(Number(__mmEntry.angle)) &&
Number.isFinite(Number(__mmEntry.impactMs)) &&
Number(__mmEntry.impactMs) <= Number(__mmThreat.horizonMs)
);
})
: [],
__mmEnemies = __mmLiveStateFresh() ? __mmLiveState.enemies : E,
__mmCandidates = [],
__mmRangedSources = [];
let __mmCloseEnemy = null,
__mmCloseDistance = Infinity;
if (Array.isArray(__mmEnemies))
for (let __mmIndex = 0; __mmIndex < __mmEnemies.length; __mmIndex++) {
const __mmEnemy = __mmEnemies[__mmIndex];
if (!__mmIsEnemyPlayer(__mmEnemy)) continue;
const __mmDx = Number(__mmEnemy.x) - Number(v.x),
__mmDy = Number(__mmEnemy.y) - Number(v.y),
__mmDistance = Math.hypot(__mmDx, __mmDy),
__mmWeapon = b && b.weapons && b.weapons[Number(__mmEnemy.weaponIndex)],
__mmCloseReach = Math.min(
__mmShieldDefenseRange,
Math.max(
145,
(Number(__mmWeapon && __mmWeapon.range) || 0) +
(Number(__mmEnemy.scale) || 35) +
(Number(v.scale) || 35) +
38,
),
),
__mmAngle = Math.atan2(__mmDy, __mmDx);
if (__mmDistance <= __mmCloseReach && __mmDistance < __mmCloseDistance)
((__mmCloseEnemy = {
angle: __mmAngle,
distance: __mmDistance,
reach: __mmCloseReach,
damage: Math.max(20, __mmThreatMeleeDamage(__mmEnemy, __mmEnemy.weaponIndex)),
}),
(__mmCloseDistance = __mmDistance));
if (!__mmWeapon || __mmWeapon.projectile == null || __mmDistance > 950)
continue;
const __mmFacing = Number.isFinite(Number(__mmEnemy.dir))
? Number(__mmEnemy.dir)
: Number(__mmEnemy.d2),
__mmTowardUs = Math.atan2(-__mmDy, -__mmDx);
if (
Number.isFinite(__mmFacing) &&
__mmRightClickAngleDistance(__mmFacing, __mmTowardUs) <= 0.72
)
__mmRangedSources.push({
angle: __mmAngle,
damage: Math.max(12, Number(__mmWeapon.dmg) || 0),
impactMs: Math.max(80, __mmDistance),
});
}
let __mmProjectileDamage = 0,
__mmSoonestProjectile = Infinity;
for (let __mmIndex = 0; __mmIndex < __mmThreatEntries.length; __mmIndex++) {
const __mmEntry = __mmThreatEntries[__mmIndex];
((__mmProjectileDamage += Math.max(0, Number(__mmEntry.damage) || 0)),
(__mmSoonestProjectile = Math.min(
__mmSoonestProjectile,
Number(__mmEntry.impactMs),
)));
}
const __mmHealth = Math.max(1, Number(v.health) || 100),
__mmProjectilePressure = !!(
__mmThreatEntries.length >= 2 ||
__mmRangedSources.length >= 2 ||
__mmProjectileDamage >= Math.max(25, __mmHealth * 0.28) ||
__mmSoonestProjectile <= Math.max(260, __mmServerTickMs() * 2)
);
if (!__mmCloseEnemy && !__mmProjectilePressure) return null;
__mmCloseEnemy && __mmCandidates.push(__mmCloseEnemy);
if (__mmProjectilePressure) {
for (let __mmIndex = 0; __mmIndex < __mmThreatEntries.length; __mmIndex++)
__mmCandidates.push(__mmThreatEntries[__mmIndex]);
for (let __mmIndex = 0; __mmIndex < __mmRangedSources.length; __mmIndex++)
__mmCandidates.push(__mmRangedSources[__mmIndex]);
}
const __mmShieldArc = Math.max(
0.65,
Number(y && y.shieldAngle) || Math.PI / 3,
);
let __mmBestAngle = __mmCandidates[0]
? Number(__mmCandidates[0].angle)
: Ci(),
__mmBestScore = -Infinity;
for (let __mmCandidateIndex = 0; __mmCandidateIndex < __mmCandidates.length; __mmCandidateIndex++) {
const __mmAngle = Number(__mmCandidates[__mmCandidateIndex].angle);
if (!Number.isFinite(__mmAngle)) continue;
let __mmScore = 0;
if (
__mmCloseEnemy &&
__mmRightClickAngleDistance(__mmAngle, __mmCloseEnemy.angle) <= __mmShieldArc
)
__mmScore +=
80 +
Math.max(0, 1 - __mmCloseEnemy.distance / __mmCloseEnemy.reach) * 80 +
__mmCloseEnemy.damage;
for (let __mmIndex = 0; __mmIndex < __mmThreatEntries.length; __mmIndex++) {
const __mmEntry = __mmThreatEntries[__mmIndex];
if (__mmRightClickAngleDistance(__mmAngle, __mmEntry.angle) > __mmShieldArc)
continue;
const __mmUrgency = Math.max(
0,
1 - Number(__mmEntry.impactMs) / Math.max(1, Number(__mmThreat.horizonMs)),
);
__mmScore += Math.max(1, Number(__mmEntry.damage) || 0) * (1.5 + __mmUrgency);
}
for (let __mmIndex = 0; __mmIndex < __mmRangedSources.length; __mmIndex++) {
const __mmSource = __mmRangedSources[__mmIndex];
__mmRightClickAngleDistance(__mmAngle, __mmSource.angle) <= __mmShieldArc &&
(__mmScore += 18 + __mmSource.damage * 0.35);
}
if (__mmScore > __mmBestScore)
((__mmBestScore = __mmScore), (__mmBestAngle = __mmAngle));
}
return (__mmRightClickShieldPlanCache = {
weapon: __mmShieldWeapon,
angle: __mmBestAngle,
closeEnemy: !!__mmCloseEnemy,
projectileCount: __mmThreatEntries.length,
rangedCount: __mmRangedSources.length,
});
}
function __mmRightClickWeapon(
__mmShieldPlan = __mmRightClickShieldPlan(),
) {
const __mmPrimary = v && v.alive && v.weapons ? v.weapons[0] : null,
__mmSecondary = __mmSecondaryWeapon(),
__mmData =
__mmSecondary == null ? null : b && b.weapons && b.weapons[__mmSecondary];
return __mmSecondary == null
? __mmPrimary
: __mmSecondary === __mmShieldWeapon
? __mmShieldPlan
? __mmShieldWeapon
: __mmPrimary
: __mmData && __mmData.projectile != null && __mmPrimary != null
? __mmPrimary
: __mmSecondary;
}
function __mmServerTickMs() {
return Math.max(
60,
Math.ceil(1e3 / Math.max(1, Number(y && y.serverUpdateRate) || 9)),
);
}
function __mmFastCheckMs() {
// State detection should react between server updates; action paths retain
// their separate server-tick rate limits before sending packets.
return Math.min(
Math.max(10, Number(__mmReactionMs) || 25),
__mmServerTickMs(),
);
}
function __mmEquipTankForSecondary(
__mmWeapon = __mmRightClickWeapon(),
__mmNow = Date.now(),
__mmLeadMs = 0,
) {
if (
!__mmTankRightClickEnabled ||
!v ||
!v.alive ||
__mmWeapon == null ||
!v.skins ||
!v.skins[40]
)
return !1;
(__mmClearSecondaryGearTimer(),
(__mmSecondaryGearStage = "tank"),
__mmRightClickHat == null &&
(__mmRightClickHat = __mmBestPostCombatHat()),
// Tank is emitted in the same synchronous phase as the ready weapon swing.
// The action-phase timer restores the best current hat next server tick.
__mmActivateCombatHat(40),
(__mmSecondaryManualWeapon = __mmWeapon),
(__mmSecondaryManualReadyAt =
__mmNow +
__mmManualWeaponCooldown(__mmWeapon, 40) +
Math.max(0, Number(__mmLeadMs) || 0)));
return !0;
}
function __mmClearSecondaryGearTimer() {
(__mmSecondaryGearTimer && clearTimeout(__mmSecondaryGearTimer),
(__mmSecondaryGearTimer = 0));
}
function __mmInvalidateSecondaryGearTimer() {
(__mmClearSecondaryGearTimer(), (__mmSecondaryGearEpoch += 1));
}
function __mmClearSecondaryReleaseRestore() {
(__mmSecondaryReleaseRestoreTimer &&
clearTimeout(__mmSecondaryReleaseRestoreTimer),
(__mmSecondaryReleaseRestoreTimer = 0),
(__mmSecondaryReleaseRestoreHat = null),
(__mmSecondaryReleaseRestoreAttempts = 0));
}
function __mmScheduleSecondaryReleaseRestore(__mmHat, __mmEpoch) {
if (__mmCombatHatLockActive() && Number(__mmCombatHatLockHat) === 40)
__mmScheduleCombatHatFinish();
}
function __mmScheduleSecondaryGear(
__mmCallback,
__mmDelay = __mmServerTickMs(),
) {
__mmClearSecondaryGearTimer();
const __mmEpoch = __mmSecondaryGearEpoch;
__mmSecondaryGearTimer = setTimeout(function () {
__mmSecondaryGearTimer = 0;
__mmEpoch === __mmSecondaryGearEpoch && __mmCallback();
}, Math.max(1, Number(__mmDelay) || __mmServerTickMs()));
}
function __mmEquipSecondaryDowntimeHat() {
if (!v || !v.alive || __mmCombatHatLockActive()) return;
const __mmHat = __mmBestPostCombatHat(),
__mmTail = __mmDesiredHeldTail(__mmRightClickWeapon());
(__mmClearSecondaryGearTimer(),
(__mmSecondaryGearStage = "downtime"),
__mmRememberHeldTail(__mmTail),
__mmEquipGearPair(__mmHat, __mmTail, !0));
}
function __mmRestoreRightClickHat() {
if (__mmCombatHatLockActive() && Number(__mmCombatHatLockHat) === 40) {
__mmScheduleCombatHatFinish();
return;
}
if (__mmRightClickHat == null) return void __mmClearSecondaryGearTimer();
if (__mmSecondaryHeld) return;
if (!v || !v.alive) {
(__mmInvalidateSecondaryGearTimer(),
__mmClearSecondaryReleaseRestore(),
(__mmRightClickHat = null),
(__mmSecondaryGearStage = null));
return;
}
const __mmHat = __mmBestPostCombatHat();
(__mmInvalidateSecondaryGearTimer(),
(__mmRightClickHat = null),
(__mmSecondaryGearStage = null),
__mmEquipHatNow(__mmHat, !0));
}
function __mmForceRestoreRightClickHat() {
if (__mmRightClickHat == null) return void __mmClearSecondaryGearTimer();
const __mmHat = __mmBestPostCombatHat();
(__mmInvalidateSecondaryGearTimer(),
(__mmRightClickHat = null),
(__mmSecondaryGearStage = null),
v &&
v.alive &&
!__mmCombatHatLockActive() &&
__mmEquipHatNow(__mmHat, !0));
}
function __mmPulseSecondaryWeapon() {
if (!__mmSecondaryHeld) return;
const __mmShieldPlan = __mmRightClickShieldPlan(),
__mmWeapon = __mmRightClickWeapon(__mmShieldPlan),
__mmShieldMode = !!(
__mmShieldPlan && Number(__mmWeapon) === __mmShieldWeapon
),
__mmUseTank = !!(
!__mmShieldMode &&
__mmTankRightClickEnabled &&
v &&
v.skins &&
v.skins[40]
),
__mmNow = Date.now(),
__mmTankLead = __mmUseTank
? __mmSecondaryTankLead(
__mmWeapon,
__mmSecondaryManualReadyAt,
__mmNow,
)
: -1;
if (__mmWeapon == null) return;
Number(__mmSecondaryManualWeapon) !== Number(__mmWeapon) &&
((__mmSecondaryManualWeapon = Number(__mmWeapon)),
(__mmSecondaryManualReadyAt = 0));
if (__mmShieldMode) {
if (
__mmCombatHatLockActive() &&
Number(__mmCombatHatLockHat) === 40
)
__mmCancelCombatHatLock(!0);
((__mmSecondaryShieldActive = !0),
(__mmSecondaryShieldUsed = !0),
(__mmSecondaryShieldAngle = Number(__mmShieldPlan.angle)),
(__mmSecondaryGearStage = "shield"),
__mmUpdateHeldGear(__mmWeapon),
je(__mmShieldWeapon, !0));
if (
__mmNow - __mmSecondaryShieldAimAt >= __mmFastCheckMs()
) {
((__mmSecondaryShieldAimAt = __mmNow),
O.send("D", __mmSecondaryShieldAngle));
}
} else {
if (__mmSecondaryShieldActive) {
((__mmSecondaryShieldActive = !1),
(__mmSecondaryShieldAngle = null),
(__mmSecondaryShieldAimAt = 0));
__mmScheduleMouseAimReturn();
}
__mmTankLead >= 0
? (__mmUpdateHeldTail(__mmWeapon),
__mmEquipTankForSecondary(__mmWeapon, __mmNow, __mmTankLead))
: __mmUpdateHeldGear(__mmWeapon);
}
// Native press-and-hold is sent once. Gear timing follows the weapon clock
// without converting the hold into repeated click packets.
if (!__mmSecondaryAttackDown)
(je(__mmWeapon, !0),
__mmShieldMode
? O.send("F", 1, __mmSecondaryShieldAngle)
: __mmSendWeaponAttack(1),
(__mmSecondaryAttackDown = !0));
}
function __mmObserveHeldGearSwing(__mmPlayerSid, __mmWeapon) {
if (
!v ||
!v.alive ||
__mmPlayerSid == null ||
String(__mmPlayerSid) !== String(v.sid)
)
return;
const __mmResolvedWeapon =
__mmWeapon == null ? Number(v.weaponIndex) : Number(__mmWeapon),
__mmNow = Date.now();
if (
__mmPrimaryHeld &&
v.weapons &&
Number(v.weapons[0]) === __mmResolvedWeapon &&
__mmBullPrimaryAvailable()
)
((__mmPrimaryManualWeapon = __mmResolvedWeapon),
(__mmPrimaryManualReadyAt =
__mmNow + __mmManualWeaponCooldown(__mmResolvedWeapon, 7)));
if (
__mmSecondaryHeld &&
Number(__mmSecondaryManualWeapon) === __mmResolvedWeapon &&
__mmResolvedWeapon !== __mmShieldWeapon &&
__mmTankRightClickEnabled &&
v.skins &&
v.skins[40]
)
((__mmSecondaryManualWeapon = __mmResolvedWeapon),
(__mmSecondaryManualReadyAt =
__mmNow + __mmManualWeaponCooldown(__mmResolvedWeapon, 40)));
}
function __mmStopSecondary() {
const __mmRestoreSelection = __mmSecondaryRestoreWeapon,
__mmUsedShield = __mmSecondaryShieldUsed,
__mmMayRestoreWeapon = __mmActionMayRestore("manualAttack");
((__mmSecondaryHeld = !1),
(__mmSecondaryAttackDown = !1),
(__mmSecondaryShieldActive = !1),
(__mmSecondaryShieldAngle = null),
(__mmSecondaryShieldUsed = !1),
(__mmSecondaryShieldAimAt = 0),
(__mmSecondaryRestoreWeapon = null),
(__mmRightClickShieldPlanAt = 0),
(__mmRightClickShieldPlanCache = null),
(U = 0),
__mmStopHeldAttackPulse(),
__mmPrimaryHeld && __mmPulseHeldAttack(),
__mmRestoreHeldHat(),
__mmRestoreHeldTail(),
__mmRestoreRightClickHat(),
__mmRestoreTrapHat(),
!__mmPrimaryHeld && __mmActionRelease("manualAttack", "right click released"));
if (
__mmUsedShield &&
__mmMayRestoreWeapon &&
v &&
v.alive &&
__mmRestoreSelection != null &&
Number(__mmSelectedWeapon()) === __mmShieldWeapon
)
__mmRestoreWeapon(__mmRestoreSelection);
__mmUsedShield && __mmScheduleMouseAimReturn();
(__mmUpdateMovementGear(), __mmUpdateWeaponRecharge());
}
function __mmFinishSecondaryInput() {
(__mmStopSecondary(), __mmRestoreBullForPrimary());
}
function __mmStartConfiguredSecondary(__mmEvent) {
if (!v || !v.alive) return !1;
if (__mmHandleBushCombatClick(__mmEvent)) return !0;
__mmBoostInsta.isActive() && __mmBoostInsta.cancel("manual-secondary");
__mmInsta.isActive() && __mmInsta.cancel("manual-secondary");
__mmActionOwner === "instaSync" && __mmStopInstaSync();
__mmActionOwner === "weaponRecharge" && __mmPauseWeaponRecharge(!0);
__mmActionOwner === "shieldDefense" &&
__mmStopShieldDefense("manual right-click handoff");
const __mmShieldPlan = __mmRightClickShieldPlan(!0),
__mmPlannedWeapon = __mmRightClickWeapon(__mmShieldPlan);
if (
(!__mmTankRightClickEnabled && !__mmShieldPlan) ||
__mmPlannedWeapon == null
)
return (__mmRestoreRightClickHat(), !1);
(__mmPrimaryHeld || __mmPrimaryClickHat != null) &&
(__mmStopPrimaryInput(), __mmForceRestoreBullForPrimary());
if (!__mmActionClaim("manualAttack", "configured secondary")) return !1;
const __mmWeapon = Number(__mmPlannedWeapon);
return (
__mmClearSecondaryReleaseRestore(),
(__mmSecondaryGearEpoch += 1),
(U = 1),
(__mmSecondaryRestoreWeapon = __mmSelectedWeapon()),
(__mmSecondaryShieldUsed = !1),
Number(__mmSecondaryManualWeapon) !== __mmWeapon &&
((__mmSecondaryManualWeapon = __mmWeapon),
(__mmSecondaryManualReadyAt = 0)),
(__mmSecondaryHeld = !0),
__mmStartHeldAttackPulse(),
!0
);
}
document.addEventListener(
"mousedown",
function (__mmEvent) {
if (__mmEvent.button !== 2 || !__mmIsGameClick(__mmEvent))
return void __mmRestoreRightClickHat();
if (
!__mmRuntimeBindingMatches(
__mmKeybinds.secondaryAttack,
__mmEvent,
!0,
)
)
return;
((__mmPhysicalSecondaryDown = !0),
(__mmPhysicalInputAt = Date.now()),
__mmStartConfiguredSecondary(__mmEvent),
__mmEvent.preventDefault(),
__mmEvent.stopImmediatePropagation());
},
!0,
);
document.addEventListener(
"mouseup",
function (__mmEvent) {
if (
(__mmWeaponGrindHold ||
(__mmCleanupAttackHeld && __mmCleanupMouseButton === 2)) &&
__mmEvent.button === 2
)
return;
if (
__mmEvent.button !== 2 ||
__mmBindingActionHeld("secondaryAttack") ||
(!__mmSecondaryHeld && __mmRightClickHat == null)
)
return;
(__mmEvent.preventDefault(),
__mmEvent.stopImmediatePropagation(),
__mmFinishSecondaryInput());
},
!0,
);
function __mmManualSecondaryReleaseBlocked() {
return !!(
__mmWeaponGrindHold ||
(__mmCleanupAttackHeld && __mmCleanupMouseButton === 2)
);
}
function __mmCaptureManualSecondaryRelease(__mmEvent) {
if (
__mmEvent.button !== 2 ||
__mmBindingActionHeld("secondaryAttack") ||
__mmManualSecondaryReleaseBlocked() ||
(!__mmSecondaryHeld &&
__mmRightClickHat == null &&
!(!__mmPrimaryHeld && __mmActionOwner === "manualAttack"))
)
return;
__mmFinishSecondaryInput();
}
// Capture releases at window level before the game or another listener can
// consume them. This is especially important for a one-frame right-click,
// where a missed mouseup otherwise leaves Tank and manualAttack latched.
window.addEventListener("pointerup", __mmCaptureManualSecondaryRelease, !0);
window.addEventListener("mouseup", __mmCaptureManualSecondaryRelease, !0);
window.addEventListener(
"pointermove",
function (__mmEvent) {
if (
(__mmEvent.pointerType === "" || __mmEvent.pointerType === "mouse") &&
!(__mmEvent.buttons & 2) &&
!__mmBindingActionHeld("secondaryAttack") &&
!__mmManualSecondaryReleaseBlocked() &&
(__mmSecondaryHeld || __mmRightClickHat != null)
)
__mmFinishSecondaryInput();
},
!0,
);
document.addEventListener(
"pointerup",
function (__mmEvent) {
if (
__mmEvent.button === 0 &&
__mmPrimaryHeld &&
!__mmBindingActionHeld("primaryAttack") &&
!__mmBindingActionHeld("clickBoostInsta") &&
!(__mmCleanupAttackHeld && __mmCleanupMouseButton === 0)
)
__mmStopPrimaryInput();
if (
__mmEvent.button === 2 &&
!__mmBindingActionHeld("secondaryAttack") &&
!__mmWeaponGrindHold &&
!(__mmCleanupAttackHeld && __mmCleanupMouseButton === 2) &&
(__mmSecondaryHeld || __mmRightClickHat != null)
)
__mmFinishSecondaryInput();
},
!0,
);
document.addEventListener(
"pointermove",
function (__mmEvent) {
if (__mmEvent.pointerType && __mmEvent.pointerType !== "mouse") return;
__mmPrimaryHeld &&
!__mmBindingActionHeld("primaryAttack") &&
!__mmBindingActionHeld("clickBoostInsta") &&
!(__mmCleanupAttackHeld && __mmCleanupMouseButton === 0) &&
!(__mmEvent.buttons & 1) &&
__mmStopPrimaryInput();
__mmSecondaryHeld &&
!__mmBindingActionHeld("secondaryAttack") &&
!__mmWeaponGrindHold &&
!(__mmCleanupAttackHeld && __mmCleanupMouseButton === 2) &&
!(__mmEvent.buttons & 2) &&
__mmFinishSecondaryInput();
},
!0,
);
document.addEventListener(
"pointercancel",
function () {
(!(__mmCleanupAttackHeld && __mmCleanupMouseButton === 0) &&
__mmStopPrimaryInput(),
!__mmWeaponGrindHold &&
!(__mmCleanupAttackHeld && __mmCleanupMouseButton === 2) &&
__mmFinishSecondaryInput());
},
!0,
);
document.addEventListener(
"contextmenu",
function (__mmEvent) {
__mmIsGameClick(__mmEvent) && __mmEvent.preventDefault();
},
!0,
);
window.addEventListener("blur", function () {
((__mmPhysicalPrimaryDown = !1),
(__mmPhysicalSecondaryDown = !1),
(__mmPhysicalInputAt = Date.now()),
(__mmBushHotkeyDown = !1),
__mmStopPrimaryInput(),
__mmStopSecondary(),
__mmPauseWeaponGrind("window blur"),
__mmStopCleanup("window blur", !1),
__mmFinishMatThief("window blur"),
__mmFinishMobSteal("window blur"),
__mmStopWindmillHold(),
__mmStopInstaSync(),
__mmStopSpikeTickStrike("window blur"),
__mmStopAntiBoostBlock("window blur"),
__mmStopBoostSpike(),
__mmStopVelTickInsta("window blur"),
__mmStopAutoPushSetup("window blur"),
__mmInsta.cancel("window-blur"),
__mmBoostInsta.cancel("window-blur"),
__mmStopBushMode("window blur", !0),
__mmRestoreBullForPrimary(),
__mmRestoreMovementGear());
});
document.addEventListener("visibilitychange", function () {
document.hidden &&
((__mmPhysicalPrimaryDown = !1),
(__mmPhysicalSecondaryDown = !1),
(__mmPhysicalInputAt = Date.now()),
__mmStopPrimaryInput(),
__mmStopSecondary(),
__mmPauseWeaponGrind("document hidden"),
__mmStopCleanup("document hidden", !1),
__mmFinishMatThief("document hidden"),
__mmFinishMobSteal("document hidden"),
__mmStopWindmillHold(),
__mmStopInstaSync(),
__mmStopSpikeTickStrike("document hidden"),
__mmStopAntiBoostBlock("document hidden"),
__mmStopBoostSpike(),
__mmStopVelTickInsta("document hidden"),
__mmStopAutoPushSetup("document hidden"),
__mmInsta.cancel("document-hidden"),
__mmBoostInsta.cancel("document-hidden"),
__mmStopBushMode("document hidden", !0),
__mmRestoreMovementGear());
});
function __mmSendKillMessage() {
if (!__mmKillMessageEnabled || !__mmKillMessage || !v || !v.alive) return;
__mmSendChat(__mmKillMessage);
}
const __mmDeathHistoryTimes = new Map();
function __mmRecordDeathHistory(__mmPlayer) {
if (!__mmChatHistoryEnabled || !__mmDeathHistoryChatEnabled || !__mmPlayer)
return;
const __mmNow = Date.now();
const __mmSid = __mmPlayer.sid == null ? __mmPlayer.id : __mmPlayer.sid,
__mmKey = String(__mmSid == null ? __mmPlayer.name || "player" : __mmSid),
__mmLastAt = Number(__mmDeathHistoryTimes.get(__mmKey)) || 0;
if (__mmNow - __mmLastAt < 2000) return;
__mmDeathHistoryTimes.set(__mmKey, __mmNow);
if (__mmDeathHistoryTimes.size > 80)
for (const [__mmOldKey, __mmOldAt] of __mmDeathHistoryTimes)
__mmNow - __mmOldAt > 10000 && __mmDeathHistoryTimes.delete(__mmOldKey);
const __mmName = String(__mmPlayer.name || "Player").slice(0, 32);
window.dispatchEvent(
new CustomEvent("MooMooKittyChatMessage", {
detail: {
name: "Death",
message: __mmName + " died",
relation: __mmChatRelation(__mmPlayer),
at: __mmNow,
},
}),
);
}
__mmApplyUpgradeUnlock();
__mmStartLiveState();
__mmStartTabSync();
__mmStartDebugHud();
__mmStartAutoHeal();
__mmStartAutoTrapInsta();
__mmStartAutoInsta();
__mmStartKittyInstas();
__mmStartAutoSpikeInsta();
__mmStartTrapAlert();
__mmStartFriendlyTrapChat();
__mmStartTeamRequestAutomation();
__mmStartTrapEscape();
__mmStartPlacementDefense();
__mmStartTeammateTrapRescue();
__mmStartTurretSteal();
__mmStartSpikeGearCounter();
__mmStartSoldierAuto();
__mmStartMovementGear();
__mmStartMultiBreak();
__mmStartWeaponRecharge();
__mmStartAutoPurchase();
__mmStartMobSteal();
__mmApplyWindmillRotationState();
__mmStartInstaSync();
__mmStartAntiBoostInsta();
__mmStartAntiCollision();
__mmStartThreatTrap();
__mmStartSmartPlacement();
Sl = function () {
__mmRecordDeathHistory(v);
const __mmResult = __mmOriginalDeath.apply(this, arguments);
window.dispatchEvent(new CustomEvent("MooMooKittyLocalDeath"));
return __mmResult;
};
Xl = function () {
const __mmResult = __mmOriginalAnimalUpdate.apply(this, arguments);
__mmMobStealEnabled && __mmUpdateMobSteal();
return __mmResult;
};
$l = function (__mmPlayerSid, __mmHealth) {
const __mmHealthPlayer = __mmChatPlayer(__mmPlayerSid),
__mmObservedPreviousHealth = __mmHealthPlayer
? Number(__mmHealthPlayer.health)
: null,
__mmPreviousHealth =
v && __mmPlayerSid === v.sid ? Number(v.health) : null;
const __mmResult = __mmOriginalHealthUpdate.apply(this, arguments);
Number.isFinite(__mmObservedPreviousHealth) &&
Number.isFinite(Number(__mmHealth)) &&
__mmRecordCombatDelta(
__mmHealthPlayer ||
(v && String(__mmPlayerSid) === String(v.sid) ? v : null) ||
__mmChatPlayer(__mmPlayerSid),
__mmObservedPreviousHealth,
Number(__mmHealth),
);
Number.isFinite(__mmObservedPreviousHealth) &&
__mmObservedPreviousHealth > 0 &&
Number(__mmHealth) <= 0 &&
__mmRecordDeathHistory(__mmHealthPlayer);
if (v && __mmPlayerSid === v.sid) {
__mmCombatThreatCalculatedAt = 0;
Number.isFinite(__mmPreviousHealth) &&
Number(__mmHealth) < __mmPreviousHealth &&
((__mmAssassinLastDamageAt = Date.now()),
(__mmAssassinSafeSince = 0));
Number.isFinite(__mmPreviousHealth) &&
Number.isFinite(Number(__mmHealth)) &&
__mmObserveFriendDamage(
Math.max(0, __mmPreviousHealth - Number(__mmHealth)),
);
const __mmTookDamage = __mmObserveAutoHealHealth(__mmHealth);
__mmTookDamage && __mmDisableWeaponGrind("incoming damage");
__mmTookDamage &&
__mmBushModeRequested &&
__mmStopBushMode("attacked", !0);
// A confirmed hit always takes priority over a queued insta. Healing is
// packet-driven, so do it now rather than deferring for combat cleanup.
__mmInsta.isActive() && __mmTookDamage &&
__mmInsta.cancel("health-damage");
__mmAutoHeal();
}
return __mmResult;
};
Kl = function (__mmKey, __mmValue, __mmRefresh) {
const __mmResourceKey = String(__mmKey),
__mmPreviousKills =
v && __mmResourceKey === "kills" ? Number(v.kills) || 0 : null,
__mmPreviousResource =
v &&
(__mmResourceKey === "food" ||
__mmResourceKey === "wood" ||
__mmResourceKey === "stone")
? v[__mmResourceKey]
: null,
__mmXpWeapon = v ? v.weaponIndex : null,
__mmResult = __mmOriginalPlayerStatUpdate.apply(this, arguments);
return (
__mmPreviousResource != null &&
__mmTrackWeaponXpResourceGain(
__mmResourceKey,
__mmPreviousResource,
__mmValue,
__mmXpWeapon,
),
__mmPreviousKills != null &&
Number(__mmValue) > __mmPreviousKills &&
__mmSendKillMessage(),
__mmResult
);
};
Un = function () {
const __mmResult = __mmOriginalUpgradeDisplay.apply(this, arguments);
(__mmMarkUnsafeUpgradeChoices(), __mmResult);
return __mmResult;
};
Pl = function (__mmPlayerSid, __mmDidHit, __mmWeapon) {
__mmObserveHeldGearSwing(__mmPlayerSid, __mmWeapon);
__mmRecordPlayerSwing(__mmPlayerSid, __mmWeapon);
__mmSyncObservedPlayerSwing(__mmPlayerSid, __mmWeapon);
__mmObserveTrapEscapeSwing(__mmPlayerSid, __mmWeapon);
__mmObserveFriendAttack(__mmPlayerSid, __mmDidHit, __mmWeapon);
__mmTrackTurretGearReload(__mmPlayerSid);
__mmHandleEnemyPolearmSwing(__mmPlayerSid, __mmWeapon);
return __mmOriginalPlayerAttack.apply(this, arguments);
};
dl = function (__mmPlayerSid, __mmMessage) {
const __mmResult = __mmOriginalChatDisplay.apply(this, arguments);
(__mmRecordChatMessage(
__mmPlayerSid,
__mmMessage,
),
__mmReplyToMaterialRequest(__mmPlayerSid, __mmMessage),
__mmReplyToModQuestion(__mmPlayerSid, __mmMessage),
__mmTryMeowChainInsta(__mmPlayerSid, __mmMessage),
__mmResult);
return __mmResult;
};
window.__KittyHandleInstaHotkey = __mmHandleInstaHotkey;
window.addEventListener("blur", __mmStopTrapAttack);
__mmStartMinimapRegions();
__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() {
// Configured Kitty actions are claimed by the capture dispatcher. The
// native chain remains available for unclaimed MooMoo keys.
return "__mmCleanupInputKey(t)," + HOTKEY_MARKER;
}
function patchedFoodHotkeyCode() {
return "";
}
function patchedFoodKeyupCode() {
return "function pl(e){if(v&&v.alive){const t=e.which||e.keyCode||0;";
}
function patchedMovementKeydownCode() {
return "bt[t]?__mmAntiCollisionMovementPressed(t):t==32&&(U=1,ke())";
}
function patchedMovementKeyupCode() {
return "bt[t]?__mmAntiCollisionMovementReleased(t):t==32&&(U=0,ke())";
}
function wait(milliseconds) {
return new Promise((resolve) => window.setTimeout(resolve, milliseconds));
}
function loadOriginalBundle(originalUrl) {
if (originalBundleLoaded) return;
originalBundleLoaded = true;
installKittyUpgradeModuleUnlock();
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) => {
installKittyUpgradeModuleUnlock();
const blobUrl = URL.createObjectURL(new Blob([patchedSource], { type: "text/javascript" }));
const patchedScript = document.createElement("script");
patchedScript.type = "module";
patchedScript.src = blobUrl;
patchedScript.onload = () => {
URL.revokeObjectURL(blobUrl);
resolve();
};
patchedScript.onerror = () => {
URL.revokeObjectURL(blobUrl);
patchedScript.remove();
reject(new Error("patched game bundle could not load"));
};
(document.head || document.documentElement).appendChild(patchedScript);
});
}
function waitForDocumentParsed() {
if (document.readyState !== "loading") return Promise.resolve();
return new Promise((resolve) => {
document.addEventListener("DOMContentLoaded", resolve, { once: true });
});
}
function findMissingPatchMarkers(source) {
const markers = [
["viewport", VIEWPORT_MARKER],
["hotkeys", HOTKEY_MARKER],
["food hotkey", FOOD_HOTKEY_MARKER],
["food keyup", FOOD_KEYUP_MARKER],
["movement keydown", MOVEMENT_KEYDOWN_MARKER],
["movement keyup", MOVEMENT_KEYUP_MARKER],
["native ground grid", NATIVE_GROUND_GRID_MARKER],
["player-stat update", PLAYER_STAT_UPDATE_MARKER],
["chat display", CHAT_DISPLAY_MARKER],
["insta player lookup", INSTA_PLAYER_LOOKUP_MARKER],
["insta player attack", INSTA_PLAYER_ATTACK_MARKER],
["full-server direct connect", FORCE_FULL_DIRECT_MARKER],
["full-server browser filter", FORCE_FULL_FILTER_MARKER],
["full-server automatic filter", FORCE_FULL_AUTO_MARKER],
["full-server spawn flag", FORCE_FULL_SPAWN_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(VIEWPORT_MARKER, patchedViewportCode())
.replace(HOTKEY_MARKER, patchedHotkeyCode())
.replace(FOOD_HOTKEY_MARKER, patchedFoodHotkeyCode())
.replace(FOOD_KEYUP_MARKER, patchedFoodKeyupCode())
.replace(MOVEMENT_KEYDOWN_MARKER, patchedMovementKeydownCode())
.replace(MOVEMENT_KEYUP_MARKER, patchedMovementKeyupCode())
.replace(NATIVE_GROUND_GRID_MARKER, "")
.replace(
FORCE_FULL_DIRECT_MARKER,
'!window.__KittyForceFullServers&&s.playerCount>=s.playerCapacity){this.errorCallback("Server is already full.");return}'
)
.replace(
FORCE_FULL_FILTER_MARKER,
".filter(function(h){return window.__KittyForceFullServers||h.playerCount<n})"
)
.replace(
FORCE_FULL_AUTO_MARKER,
"e=window.__KittyForceFullServers?e:e.filter(n=>n.playerCount!==n.playerCapacity)"
)
.replace(
FORCE_FULL_SPAWN_MARKER,
"moofoll:window.__KittyForceFullServers||xt"
)
.replace(/from"\.\/vendor-[^"]+\.js"/, (specifier) => {
const path = specifier.slice(5, -1);
return `from"${new URL(path, bundleUrl).href}"`;
});
// The site's original module is parser-deferred. Our replacement is
// dynamically appended, so preserve the same ordering explicitly;
// otherwise a cached bundle can run before MooMoo's body exists.
await waitForDocumentParsed();
let lastError;
for (let attempt = 1; attempt <= PATCHED_MODULE_RETRY_LIMIT; attempt += 1) {
try {
await loadPatchedModule(patchedSource);
return;
} catch (error) {
lastError = error;
if (attempt < PATCHED_MODULE_RETRY_LIMIT) {
console.warn(`[MooMoo Scroll Zoom] patched bundle attempt ${attempt} failed; retrying.`);
await wait(BUNDLE_RETRY_DELAY_MS * attempt);
}
}
}
throw lastError || new Error("patched game bundle could not load");
} catch (error) {
console.error("[MooMoo Scroll Zoom] could not patch the game bundle; loading the original bundle.", error);
loadOriginalBundle(originalUrl);
}
}
function gameBundleUrl(value) {
if (!value) return null;
try {
const url = new URL(String(value), location.href);
return GAME_BUNDLE.test(url.pathname) ? url.href : null;
} catch {
return null;
}
}
function claimGameBundle(script, originalUrl, removeConnected = true) {
if (gameScriptHijacked || !script || !originalUrl) return false;
gameScriptHijacked = true;
restoreBundleInsertionGuards();
script.type = "application/x-kitty-klient-blocked";
script.removeAttribute("src");
if (removeConnected && script.isConnected) script.remove();
// Start the replacement fetch during the same turn that blocked the
// original module. No observer/microtask gap is left for it to execute.
loadPatchedBundle(originalUrl);
return true;
}
function interceptGameBundle(script, removeConnected = true) {
if (gameScriptHijacked || !script || script.tagName !== "SCRIPT") return false;
const originalUrl = gameBundleUrl(script.src || script.getAttribute("src"));
return claimGameBundle(script, originalUrl, removeConnected);
}
function installSynchronousBundleGuards() {
const nodePrototype = Node.prototype;
const elementPrototype = Element.prototype;
const scriptPrototype = HTMLScriptElement.prototype;
const originalAppendChild = nodePrototype.appendChild;
const originalInsertBefore = nodePrototype.insertBefore;
const originalReplaceChild = nodePrototype.replaceChild;
const originalAppend = elementPrototype.append;
const originalPrepend = elementPrototype.prepend;
const originalSetAttribute = elementPrototype.setAttribute;
const originalSrc = Object.getOwnPropertyDescriptor(scriptPrototype, "src");
let restored = false;
const restore = () => {
if (restored) return;
restored = true;
nodePrototype.appendChild = originalAppendChild;
nodePrototype.insertBefore = originalInsertBefore;
nodePrototype.replaceChild = originalReplaceChild;
if (originalAppend) elementPrototype.append = originalAppend;
if (originalPrepend) elementPrototype.prepend = originalPrepend;
elementPrototype.setAttribute = originalSetAttribute;
if (originalSrc) Object.defineProperty(scriptPrototype, "src", originalSrc);
};
restoreBundleInsertionGuards = restore;
const captureNode = (node) => {
if (
gameScriptHijacked ||
!node ||
node.nodeType !== Node.ELEMENT_NODE ||
node.tagName !== "SCRIPT"
) return false;
const originalUrl = gameBundleUrl(node.src || node.getAttribute("src"));
return claimGameBundle(node, originalUrl, false);
};
nodePrototype.appendChild = function (node) {
if (captureNode(node)) return node;
return originalAppendChild.call(this, node);
};
nodePrototype.insertBefore = function (node, reference) {
if (captureNode(node)) return node;
return originalInsertBefore.call(this, node, reference);
};
nodePrototype.replaceChild = function (node, previous) {
if (captureNode(node)) return previous;
return originalReplaceChild.call(this, node, previous);
};
if (originalAppend) {
elementPrototype.append = function (...nodes) {
const remaining = nodes.filter((node) => !captureNode(node));
if (remaining.length) return originalAppend.apply(this, remaining);
};
}
if (originalPrepend) {
elementPrototype.prepend = function (...nodes) {
const remaining = nodes.filter((node) => !captureNode(node));
if (remaining.length) return originalPrepend.apply(this, remaining);
};
}
elementPrototype.setAttribute = function (name, value) {
if (
!gameScriptHijacked &&
this instanceof HTMLScriptElement &&
String(name).toLowerCase() === "src"
) {
const originalUrl = gameBundleUrl(value);
if (claimGameBundle(this, originalUrl, false)) return;
}
return originalSetAttribute.call(this, name, value);
};
if (originalSrc && originalSrc.get && originalSrc.set) {
Object.defineProperty(scriptPrototype, "src", {
configurable: originalSrc.configurable,
enumerable: originalSrc.enumerable,
get: originalSrc.get,
set(value) {
if (!gameScriptHijacked) {
const originalUrl = gameBundleUrl(value);
if (claimGameBundle(this, originalUrl, false)) return;
}
return originalSrc.set.call(this, value);
}
});
}
}
})();