// ==UserScript== // @name Meeland Enhancement Suite // @namespace meeland-script // @version 7.0.0 // @match *://*/* // @run-at document-end // @license MIT // @grant none // @description Meeland.io cheat script with auto-lock, speed boost, infinite jump, teleportation & more! Works on CrazyGames, twoplayergames.org, meeland.io, iogames.onl, sprunki-game.io, gameflare.com and other sites hosting Meeland // @downloadURL none // ==/UserScript== (async function () { 'use strict'; const W = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window; for (let i = 0; i < 150 && !W.pc?.app?.root; i++) await new Promise(r => setTimeout(r, 100)); if (!W.pc?.app?.root) return; const STORE_KEY = 'ml_wp'; const CFG_KEY = 'ml_cfg'; const isMobile = ('ontouchstart' in window || navigator.maxTouchPoints > 0) && window.matchMedia('(pointer: coarse)').matches; let ACCEL = 6; let FLY_MIN_SPEED = 10; let SPEED_CAP = 100; let GRAVITY = -18; let SPEED_DEFAULT = 7; let flyActive = false; let _flyStartTime = 0; const slots = new Array(10).fill(null); let flyUp = false; let flyDown = false; let flyVelY = 0; let prevTick = Date.now(); let sprinting = false; let sprintSpeed = SPEED_DEFAULT; let homePos = null; let backPos = null; let _pendingBaseCapture = false; let cuddleTarget = null; let cuddling = false; let accelEnabled = true; let featFly = true; let featSprint = true; let featWaypoints = true; let featCuddle = true; let featCuddleFollow = true; let featPets = true; let featAutoLock = true; let featAntiKnockback = true; let featNoclip = false; let featFreeMoney = true; let featAutoCollect = true; let featInvincible = true; let featGhostMode = true; let autoCollectInterval = 30; let snipeFilter = 'exclusive'; let snipeActive = false; let snipeAutoDrop = true; const autoRefresh = true; const refreshInterval = 5; let kbListeningRow = null; let petFilter = 'wild'; let petSortCol = 'price'; let petSortDir = -1; let petAutoRefresh = true; let petRefreshInterval = 1; const KEYBINDS = { fly: 'Space', flyDown: 'KeyF', setHome: 'KeyQ', home: 'Backquote', back: 'KeyZ', cuddle: 'KeyJ', settings: 'KeyM', pets: 'KeyK', slots: 'KeyI', help: 'Slash', snipe: 'KeyU', }; const DEFAULT_KEYBINDS = { ...KEYBINDS }; function saveSettings() { try { localStorage.setItem(CFG_KEY, JSON.stringify({ ACCEL, SPEED_CAP, SPEED_DEFAULT, accelEnabled, featFly, featSprint, featWaypoints, featCuddle, featCuddleFollow, featPets, featAutoLock, featAntiKnockback, featNoclip, featFreeMoney, featAutoCollect, featInvincible, featGhostMode, autoCollectInterval, snipeFilter, snipeAutoDrop, snipeActive, keybinds: { ...KEYBINDS }, petFilter, petSortCol, petSortDir, petAutoRefresh, petRefreshInterval, })); } catch (_) {} } function loadSettings() { try { const raw = localStorage.getItem(CFG_KEY); if (!raw) return; const d = JSON.parse(raw); const assign = (key, fn) => { if (d[key] !== undefined) fn(d[key]); }; assign('ACCEL', v => ACCEL = v); assign('SPEED_CAP', v => SPEED_CAP = v); assign('SPEED_DEFAULT', v => SPEED_DEFAULT = v); assign('accelEnabled', v => accelEnabled = v); assign('featFly', v => featFly = v); assign('featSprint', v => featSprint = v); assign('featWaypoints', v => featWaypoints = v); assign('featCuddle', v => featCuddle = v); assign('featVisit', v => featCuddle = v); assign('featCuddleFollow', v => featCuddleFollow = v); assign('featStalk', v => featCuddleFollow = v); assign('featPets', v => featPets = v); assign('featAutoLock', v => featAutoLock = v); assign('featAntiKnockback', v => featAntiKnockback = v); assign('featNoclip', v => featNoclip = v); assign('featFreeMoney', v => featFreeMoney = v); assign('featAutoCollect', v => featAutoCollect = v); assign('featInvincible', v => featInvincible = v); assign('featGhostMode', v => featGhostMode = v); assign('autoCollectInterval', v => autoCollectInterval = v); assign('snipeFilter', v => snipeFilter = v); assign('snipeAutoDrop', v => snipeAutoDrop = v); assign('snipeActive', v => snipeActive = v); assign('petFilter', v => petFilter = v); assign('petSortCol', v => petSortCol = v); assign('petSortDir', v => petSortDir = v); assign('petAutoRefresh', v => petAutoRefresh = v); assign('petRefreshInterval', v => petRefreshInterval = v); if (d.keybinds) { for (const k of Object.keys(KEYBINDS)) { if (typeof d.keybinds[k] === 'string') KEYBINDS[k] = d.keybinds[k]; } } } catch (_) {} } loadSettings(); const getPlayer = () => W.pc?.app?.root?.findByName('Player') ?? null; const getKcc = p => p?.script?.kcc ?? null; const getPC = p => p?.script?.playerController ?? null; const $ = id => document.getElementById(id); const flash = id => { const el = $(id); if (el) { el.classList.add('fresh'); setTimeout(() => el.classList.remove('fresh'), 400); } if (_nativeHud) { const idMap = { 'ml-fly': 'fly', 'ml-spr': 'spr', 'ml-home': 'home', 'ml-go': 'go', 'ml-back': 'back', 'ml-slots': 'slots', 'ml-lock': 'lock' }; const k = idMap[id]; if (k && _nativeHud[k]) { _nativeHud[k].classList.add('fresh'); setTimeout(() => _nativeHud[k].classList.remove('fresh'), 400); } } }; const syncSlider = (id, valId, v, uom) => { const el = $(id), ve = $(valId); if (el) el.value = v; if (ve) ve.textContent = uom ? v + uom : v; }; const vec3 = v => ({ x: v.x, y: v.y, z: v.z }); const getCamera = () => W.pc?.app?.root?.findByName('Camera') ?? null; function capturePos(player) { const p = player.getPosition(); const r = player.getEulerAngles(); const camera = getCamera(); const cam = camera?.getEulerAngles(); let se = null; for (const inst of (camera?.script?._scripts || [])) { if (inst.eulers) { se = vec3(inst.eulers); break; } } return { x: p.x, y: p.y, z: p.z, rot: vec3(r), cam: cam ? vec3(cam) : null, se }; } function restoreCam(posData) { if (!posData?.cam) return; const camera = getCamera(); if (!camera) return; let scriptRestored = false; for (const inst of (camera.script?._scripts || [])) { if ('_yaw' in inst) { inst._yaw = posData.cam.y; scriptRestored = true; } if ('_pitch' in inst) { inst._pitch = posData.cam.x; scriptRestored = true; } if ('yaw' in inst) { inst.yaw = posData.cam.y; scriptRestored = true; } if ('pitch' in inst) { inst.pitch = posData.cam.x; scriptRestored = true; } if (inst.eulers && posData.se) { inst.eulers.x = posData.se.x; inst.eulers.y = posData.se.y; inst.eulers.z = posData.se.z; scriptRestored = true; } } if (!scriptRestored) camera.setEulerAngles(posData.cam.x, posData.cam.y, posData.cam.z); } const FEAT_IDS = ['ml-f-fly','ml-f-sprint','ml-f-waypoints','ml-f-cuddle','ml-f-cuddle-follow','ml-f-pets','ml-f-autolock','ml-f-antiknockback','ml-f-noclip','ml-f-freemoney','ml-f-autocollect','ml-f-invincible','ml-f-ghostmode']; const MOVE_KEYS = new Set(['KeyW','KeyA','KeyS','KeyD','ArrowUp','ArrowDown','ArrowLeft','ArrowRight']); function getPlayerState() { const nm = W.pc?.app?.root?.findByName('NetworkManager')?.script?.networkManager; if (!nm?.room?.state?.players) return null; return nm.room.state.players.get(nm.room.sessionId) ?? null; } const setSpeed = (pc, kcc, v) => { if (pc) { pc.currentSpeed = v; pc.speed = v; } if (kcc.speed !== undefined) kcc.speed = v; const ps = getPlayerState(); if (ps && ps.movementSpeed !== undefined) ps.movementSpeed = v / SPEED_DEFAULT; }; function teleport(player, pos) { player.setPosition(pos.x, pos.y, pos.z); player.rigidbody?.teleport(pos.x, pos.y, pos.z); if (pos.rot) player.setEulerAngles(pos.rot.x, pos.rot.y, pos.rot.z); restoreCam(pos); } function serializePos(p) { if (!p) return null; const o = vec3(p); if (p.rot) o.rot = vec3(p.rot); if (p.cam) o.cam = vec3(p.cam); if (p.se) o.se = vec3(p.se); return o; } function saveWaypoints() { try { localStorage.setItem(STORE_KEY, JSON.stringify({ home: serializePos(homePos), back: serializePos(backPos), slots: slots.map(s => serializePos(s)), })); } catch (_) {} } function loadWaypoints() { try { const raw = localStorage.getItem(STORE_KEY); if (!raw) return; const d = JSON.parse(raw); if (d.home) homePos = d.home; if (d.back) backPos = d.back; if (Array.isArray(d.slots)) d.slots.forEach((s, i) => { if (s) slots[i] = s; }); } catch (_) {} } function flyOn(kcc, hover) { flyActive = true; _flyStartTime = Date.now(); kcc.gravity = 0; if (hover) { flyUp = false; flyDown = false; flyVelY = 0; kcc._velY = 0; } else { flyUp = true; flyVelY = FLY_MIN_SPEED; kcc._velY = FLY_MIN_SPEED; } } function flyOff(kcc, resetVel = true) { flyActive = false; flyUp = false; flyDown = false; flyVelY = 0; kcc.gravity = GRAVITY; if (resetVel) kcc._velY = 0; } const DESCRIPTION = `

Meeland Script — Cheat & Enhancement Suite

General-purpose cheat script for Meeland.io. Works across all game modes — Meeland Hub, Escape Waves, Steal a Pet, and Obby Tower — on all supported platforms.

Works on PC and mobile. On PC, use keyboard shortcuts or click the in-game HUD buttons. On mobile, tap the HUD buttons directly — dedicated fly controls (toggle, up, down) appear on the right side of the screen.

This script is 100% free and always will be. If you have a suggestion, bug report, or something you'd like changed — awesome, leave it in a positive review and it'll get looked at. Dropping a 1-star review over a misunderstanding or a missing feature is the fastest way to make sure nothing gets done about it. Good reviews keep development alive. ⭐

Features

Keyboard Shortcuts

All keybindings are rebindable via Settings → Keybindings.

Pet Browser

Installation

  1. Install a userscript manager:
  2. Click Install above
  3. Load any Meeland game — the script activates automatically

Supported Sites (61+)

meeland.io, CrazyGames, Miniplay.com, MiniPlay.io, PlayMiniGames, RocketGames.io, KBH Games, Gamenora, WooGames.io, TwoPlayerGames.org, KizGame, OmiGames, PlayingFunGames, Gameflare.com, Free AI Games, ZapGames.io, Play-Games.com, GoGy Games, iogames.games, Sprunki-Game.io, 1000Games.io, Play-IOGames.com, ArcadeHippo, Sleepy Arcade, HotGames.io, geodashlite.io, YoPlay.io, Geometry-Free.com, Sprunki.org, Gombis.com, Wordle Unlimited, Games-Kids.com, spacewavesgame.io, amongusfree.io, Veck IO, geometrylitegame.org, Geometry Dash Subzero, Dinosaur-Game.io, Crossy-Road.io, Snow Rider 3D, Drive Mad 3, geometrylitegame.io, That's Not My Neighbor, Melon Playground, Capybara Game, FNF Games, 8Games.net, CrazyGames.tools, LoveMoneyGames.com, Zahraj.cz, iogames.onl, 1Games.io, TrendGames.io, StickmanHook2.io, GeometryDashSpam.io, SGameS.org, robbrainrot.io, Animalverse.social, BasketRandom.io, YupGames.io, GameDistribution CDN, + any site embedding meeland.io in an iframe

Privacy

Disclaimer

For educational and entertainment purposes. Use at your own risk.

`; let _savedPointerLock = false; const anyPanelOpen = () => $('ml-plist')?.classList.contains('open') || $('ml-settings')?.classList.contains('open') || $('ml-pets')?.classList.contains('open') || $('ml-dialog')?.classList.contains('open') || $('ml-slots-pop')?.classList.contains('open') || $('ml-snipe')?.classList.contains('open'); function panelPause() { _savedPointerLock = _savedPointerLock || !!document.pointerLockElement; if (document.pointerLockElement) document.exitPointerLock(); } function panelResume() { if (anyPanelOpen()) return; if (_savedPointerLock) { const app = W.pc?.app; const canvas = app?.graphicsDevice?.canvas; if (canvas) canvas.requestPointerLock(); if (app) app.fire('GameManager:GameResumed'); } _savedPointerLock = false; } let _ptCache = null, _ptCacheTime = 0; let _etCache = null, _etCacheTime = 0; function _getPetTycoon() { const now = Date.now(); if (_ptCacheTime && now - _ptCacheTime < 5000) return _ptCache; const app = W.pc?.app; if (!app) return null; const e = app.root?.findByName('PetTycoonRoom')?.script?.petTycoon || app.root?.find(e => e.script?.petTycoon)?.[0]?.script?.petTycoon; _ptCache = e || null; _ptCacheTime = now; return _ptCache; } function _getEscapeTsunami() { const now = Date.now(); if (_etCacheTime && now - _etCacheTime < 5000) return _etCache; const app = W.pc?.app; if (!app) return null; const e = app.root?.findByName('EscapeTsunamiRoom')?.script?.escapeTsunamiRoom || app.root?.find(e => e.script?.escapeTsunamiRoom)?.[0]?.script?.escapeTsunamiRoom; _etCache = e || null; _etCacheTime = now; return _etCache; } let _nmCache = null, _nmCacheTime = 0; let _bmCache = null, _bmCacheTime = 0; function _getNetworkManager() { const now = Date.now(); if (_nmCacheTime && now - _nmCacheTime < 5000) return _nmCache; _nmCache = W.pc?.app?.root?.findByName('NetworkManager')?.script?.networkManager || null; _nmCacheTime = now; return _nmCache; } function _getBasesManager() { const now = Date.now(); if (_bmCacheTime && now - _bmCacheTime < 5000) return _bmCache; _bmCache = W.pc?.app?.root?.findByName('Bases')?.script?.petTycoonBasesManager || null; _bmCacheTime = now; return _bmCache; } let _blmCache = null, _blmCacheTime = 0; function createHUD() { if ($('ml-hud')) return; const s = document.createElement('style'); s.textContent = [ '#ml-hud{display:none}', '#ml-dialog{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.75);z-index:100000;display:none;overflow:auto;padding:40px 20px;box-sizing:border-box;scrollbar-width:auto;scrollbar-color:rgba(160,120,240,.5) rgba(255,255,255,.06)}', '#ml-dialog::-webkit-scrollbar{width:8px}', '#ml-dialog::-webkit-scrollbar-track{background:rgba(255,255,255,.06);border-radius:4px}', '#ml-dialog::-webkit-scrollbar-thumb{background:rgba(160,120,240,.5);border-radius:4px;border:1px solid rgba(255,255,255,.08)}', '#ml-dialog::-webkit-scrollbar-thumb:hover{background:rgba(160,120,240,.7)}', '#ml-dialog.open{display:block}', '#ml-inner{background:#181818;color:#ccc;max-width:580px;margin:0 auto;border-radius:8px;padding:24px 28px;font-family:sans-serif;font-size:14px;line-height:1.65;position:relative}', '#ml-inner h1{color:#fff;font-size:1.2em;margin:0 0 10px}', '#ml-inner h2{color:#aaa;font-size:.85em;text-transform:uppercase;letter-spacing:.08em;margin:18px 0 6px;border-top:1px solid #333;padding-top:12px}', '#ml-inner li{margin:4px 0}', '#ml-inner kbd{background:#2a2a2a;border:1px solid #444;border-radius:3px;padding:1px 5px;font-family:monospace;font-size:.9em}', '#ml-inner a{color:#4af}', '#ml-inner blockquote{border-left:3px solid #333;margin:8px 0 0;padding:6px 12px;color:#888;font-size:.9em}', '#ml-close{position:absolute;top:10px;right:14px;cursor:pointer;color:#555;font-size:20px;background:none;border:none;font-family:monospace;line-height:1}', '#ml-close:hover{color:#fff}', '#ml-plist{position:fixed;top:50%;right:20px;transform:translateY(-50%);width:260px;max-height:70vh;display:none;z-index:100001;pointer-events:auto;overflow:hidden;border-radius:16px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:linear-gradient(170deg,rgba(55,45,80,.92) 0%,rgba(45,38,72,.94) 40%,rgba(40,32,65,.95) 100%);border:1.5px solid rgba(160,120,240,.3);box-shadow:0 8px 32px rgba(0,0,0,.4),0 0 0 1px rgba(80,50,140,.2),0 0 60px rgba(120,80,200,.1);user-select:none}', '#ml-plist::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,#7c3aed,#a855f7,#c084fc,#a855f7,#7c3aed);border-radius:16px 16px 0 0;z-index:1}', '#ml-plist.open{display:flex;flex-direction:column}', '#ml-plist-head{padding:14px 14px 10px;display:flex;align-items:center;justify-content:space-between}', '#ml-plist-title{font-size:14px;font-weight:800;color:rgba(255,250,255,.97);letter-spacing:.02em}', '#ml-plist-timer{font-size:10px;color:rgba(190,155,245,.65);font-variant-numeric:tabular-nums;margin-left:6px;font-weight:600}', '#ml-plist-refresh{cursor:pointer;background:rgba(140,100,220,.12);border:1px solid rgba(140,100,220,.25);color:rgba(200,170,255,.8);font-size:12px;padding:3px 9px;border-radius:8px;font-family:inherit;transition:all .15s}', '#ml-plist-refresh:hover{background:rgba(140,100,220,.22);color:rgba(240,220,255,.95);border-color:rgba(140,100,220,.4)}', '#ml-plist-close{cursor:pointer;background:rgba(255,255,255,.08);border:none;color:rgba(220,200,245,.6);font-size:16px;width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:8px;font-family:inherit;line-height:1;transition:all .15s}', '#ml-plist-close:hover{color:#ff6b6b;background:rgba(255,80,80,.15)}', '#ml-plist-body{overflow-y:auto;flex:1;padding:4px 8px 6px;scrollbar-width:auto;scrollbar-color:rgba(160,120,240,.5) rgba(255,255,255,.06)}', '#ml-plist-body::-webkit-scrollbar{width:8px}', '#ml-plist-body::-webkit-scrollbar-track{background:rgba(255,255,255,.06);border-radius:4px}', '#ml-plist-body::-webkit-scrollbar-thumb{background:rgba(160,120,240,.5);border-radius:4px;border:1px solid rgba(255,255,255,.08)}', '#ml-plist-body::-webkit-scrollbar-thumb:hover{background:rgba(160,120,240,.7)}', '#ml-plist-empty{color:rgba(190,155,245,.5);text-align:center;padding:20px 8px;font-size:12px;font-style:italic}', '.ml-prow{display:flex;align-items:center;gap:8px;padding:7px 10px;margin:2px 0;border-radius:10px;cursor:pointer;transition:all .15s;border:1px solid transparent;background:rgba(140,100,220,.04)}', '.ml-prow:hover{background:rgba(140,100,220,.1);border-color:rgba(140,100,220,.15)}', '.ml-prow:active{background:rgba(140,100,220,.18);transform:scale(.98);border-color:rgba(140,100,220,.25)}', '.ml-pnum{font-size:10px;color:rgba(168,130,230,.6);font-weight:700;min-width:16px;text-align:right;font-variant-numeric:tabular-nums}', '.ml-pinfo{flex:1;overflow:hidden}', '.ml-pname{font-size:12.5px;font-weight:600;color:rgba(255,250,255,.97);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3}', '.ml-pdist{font-size:10px;color:rgba(168,130,230,.55);line-height:1.2}', '.ml-parrow{color:rgba(140,100,220,.3);font-size:14px;transition:all .15s}', '.ml-prow:hover .ml-parrow{color:rgba(168,130,230,.75);transform:translateX(3px)}', '#ml-settings{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:320px;max-height:80vh;display:none;z-index:100002;pointer-events:auto;overflow:hidden;border-radius:16px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;user-select:none;background:linear-gradient(170deg,rgba(55,45,80,.92) 0%,rgba(45,38,72,.94) 40%,rgba(40,32,65,.95) 100%);border:1.5px solid rgba(160,120,240,.3);box-shadow:0 8px 32px rgba(0,0,0,.4),0 0 0 1px rgba(80,50,140,.2),0 0 60px rgba(120,80,200,.1)}', '#ml-settings::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,#7c3aed,#a855f7,#c084fc,#a855f7,#7c3aed);border-radius:16px 16px 0 0;z-index:1}', '#ml-settings.open{display:flex;flex-direction:column}', '#ml-settings-head{position:relative;padding:18px 18px 14px;display:flex;align-items:center;justify-content:space-between}', '#ml-settings-title{font-size:16px;font-weight:800;color:rgba(255,250,255,.97);letter-spacing:.02em}', '#ml-settings-close{cursor:pointer;background:rgba(255,255,255,.08);border:none;color:rgba(220,200,245,.6);font-size:16px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:8px;font-family:inherit;line-height:1;transition:all .15s}', '#ml-settings-close:hover{color:#ff6b6b;background:rgba(255,80,80,.15)}', '#ml-settings-reset{cursor:pointer;background:rgba(255,255,255,.08);border:1px solid rgba(160,120,240,.25);color:rgba(220,200,245,.7);font-size:10px;padding:5px 14px;border-radius:8px;font-family:inherit;font-weight:600;transition:all .15s}', '#ml-settings-reset:hover{color:rgba(240,220,255,.9);background:rgba(140,100,220,.15);border-color:rgba(140,100,220,.4)}', '#ml-settings-body{position:relative;overflow-y:auto;flex:1;padding:2px 12px 14px;scrollbar-width:auto;scrollbar-color:rgba(160,120,240,.5) rgba(255,255,255,.06)}', '#ml-settings-body::-webkit-scrollbar{width:8px}', '#ml-settings-body::-webkit-scrollbar-track{background:rgba(255,255,255,.06);border-radius:4px}', '#ml-settings-body::-webkit-scrollbar-thumb{background:rgba(160,120,240,.5);border-radius:4px;border:1px solid rgba(255,255,255,.08)}', '#ml-settings-body::-webkit-scrollbar-thumb:hover{background:rgba(160,120,240,.7)}', '.ml-sgroup{margin:0 0 2px}', '#ml-tabs{display:flex;gap:4px;padding:0 16px 12px;margin-bottom:2px;border-bottom:1px solid rgba(160,120,240,.15)}', '.ml-tab{flex:1;padding:8px 0;font-size:11px;font-weight:700;text-align:center;color:rgba(200,180,240,.5);cursor:pointer;transition:all .2s;border-radius:10px;background:rgba(255,255,255,.05);border:1px solid transparent;font-family:inherit}', '.ml-tab:hover{color:rgba(200,180,240,.7);background:rgba(140,100,220,.08)}', '.ml-tab.active{color:#fff;background:linear-gradient(135deg,rgba(140,90,230,.45) 0%,rgba(110,70,210,.35) 100%);border-color:rgba(160,110,240,.35);box-shadow:0 2px 12px rgba(130,80,220,.25),inset 0 1px 0 rgba(255,255,255,.1)}', '.ml-tab-content{display:none;min-height:380px}', '.ml-tab-content.active{display:block}', '.ml-srow{display:flex;align-items:center;justify-content:space-between;padding:9px 10px;border-radius:10px;transition:all .12s;margin:1px 0}', '.ml-srow:hover{background:rgba(140,100,220,.06)}', '.ml-srow-label{font-size:13px;color:rgba(245,238,255,.92);flex:1;font-weight:500}', '.ml-srow-value{font-size:11px;color:rgba(190,155,245,.9);font-variant-numeric:tabular-nums;min-width:34px;text-align:right;margin-right:8px;font-weight:700}', '.ml-toggle{position:relative;width:40px;height:22px;border-radius:11px;background:rgba(255,255,255,.12);border:1.5px solid rgba(255,255,255,.15);cursor:pointer;transition:all .2s;flex-shrink:0}', '.ml-toggle::after{content:"";position:absolute;top:3px;left:3px;width:14px;height:14px;border-radius:7px;background:rgba(255,255,255,.35);transition:all .2s;box-shadow:0 1px 3px rgba(0,0,0,.3)}', '.ml-toggle.on{background:linear-gradient(135deg,#7c3aed 0%,#a855f7 100%);border-color:rgba(168,85,247,.5)}', '.ml-toggle.on::after{left:21px;background:#fff;box-shadow:0 1px 4px rgba(120,60,220,.4),0 0 8px rgba(168,85,247,.3)}', '.ml-slider{-webkit-appearance:none;appearance:none;width:90px;height:6px;border-radius:3px;background:rgba(255,255,255,.12);outline:none;cursor:pointer;border:none}', '.ml-slider::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;border-radius:9px;background:linear-gradient(135deg,#a855f7 0%,#7c3aed 100%);border:2px solid rgba(255,255,255,.25);box-shadow:0 2px 8px rgba(120,60,220,.4);cursor:pointer;transition:all .15s}', '.ml-slider::-webkit-slider-thumb:hover{transform:scale(1.1);box-shadow:0 2px 12px rgba(120,60,220,.5)}', '.ml-slider::-moz-range-thumb{width:18px;height:18px;border-radius:9px;background:linear-gradient(135deg,#a855f7 0%,#7c3aed 100%);border:2px solid rgba(255,255,255,.25);box-shadow:0 2px 8px rgba(120,60,220,.4);cursor:pointer}', '#ml-keybinds-body{padding:0}', '.ml-krow{display:flex;align-items:center;justify-content:space-between;padding:9px 10px;border-radius:10px;cursor:pointer;transition:all .12s;margin:1px 0}', '.ml-krow:hover{background:rgba(140,100,220,.06)}', '.ml-krow.listening{background:rgba(255,180,40,.1);border:1px solid rgba(255,180,40,.35);border-radius:10px}', '.ml-krow-action{font-size:13px;color:rgba(245,238,255,.92);font-weight:500}', '.ml-krow-key{font-size:11px;color:rgba(190,155,245,.9);font-weight:700;padding:4px 10px;border-radius:8px;background:rgba(140,100,220,.1);border:1px solid rgba(140,100,220,.2);min-width:40px;text-align:center;transition:all .15s}', '.ml-krow.listening .ml-krow-key{color:rgba(255,200,80,.9);background:rgba(120,80,0,.15);border-color:rgba(255,180,40,.4)}', '#ml-pets{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:680px;max-height:82vh;display:none;z-index:100004;pointer-events:auto;overflow:hidden;border-radius:16px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;user-select:none;background:linear-gradient(170deg,rgba(55,45,80,.92) 0%,rgba(45,38,72,.94) 40%,rgba(40,32,65,.95) 100%);border:1.5px solid rgba(160,120,240,.3);box-shadow:0 8px 32px rgba(0,0,0,.4),0 0 0 1px rgba(80,50,140,.2),0 0 60px rgba(120,80,200,.1)}', '#ml-pets::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,#7c3aed,#a855f7,#c084fc,#a855f7,#7c3aed);border-radius:16px 16px 0 0;z-index:1}', '#ml-pets.open{display:flex;flex-direction:column}', '#ml-pets-head{position:relative;padding:16px 18px 12px;display:flex;align-items:center;justify-content:space-between}', '#ml-pets-title{font-size:16px;font-weight:800;color:rgba(255,250,255,.97);letter-spacing:.02em}', '#ml-pets-count{font-size:10px;color:rgba(190,155,245,.7);margin-left:8px;font-weight:600}', '#ml-pets-close{cursor:pointer;background:rgba(255,255,255,.08);border:none;color:rgba(220,200,245,.6);font-size:16px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:8px;font-family:inherit;line-height:1;transition:all .15s}', '#ml-pets-close:hover{color:#ff6b6b;background:rgba(255,80,80,.15)}', '#ml-pets-filter{position:relative;padding:8px 14px;border-bottom:1px solid rgba(160,120,240,.15)}', '#ml-pets-search{width:100%;background:rgba(255,255,255,.07);border:1.5px solid rgba(160,120,240,.25);color:rgba(240,230,255,.9);font-size:11px;padding:7px 12px;border-radius:10px;font-family:inherit;outline:none;box-sizing:border-box;transition:all .15s}', '#ml-pets-search:focus{border-color:rgba(140,100,220,.45);box-shadow:0 0 8px rgba(120,70,200,.12)}', '#ml-pets-search::placeholder{color:rgba(168,130,230,.35)}', '#ml-pets-body{position:relative;overflow-y:auto;flex:1;padding:0;scrollbar-width:auto;scrollbar-color:rgba(160,120,240,.5) rgba(255,255,255,.06)}', '#ml-pets-body::-webkit-scrollbar{width:8px}', '#ml-pets-body::-webkit-scrollbar-track{background:rgba(255,255,255,.06);border-radius:4px}', '#ml-pets-body::-webkit-scrollbar-thumb{background:rgba(160,120,240,.5);border-radius:4px;border:1px solid rgba(255,255,255,.08)}', '#ml-pets-body::-webkit-scrollbar-thumb:hover{background:rgba(160,120,240,.7)}', '#ml-ptable{width:100%;border-collapse:collapse;font-size:11px}', '#ml-ptable th{position:sticky;top:0;background:linear-gradient(180deg,rgba(55,45,80,.98),rgba(45,38,72,.95));color:rgba(168,130,230,.7);font-size:9.5px;text-transform:uppercase;letter-spacing:.15em;padding:7px 8px;text-align:left;cursor:pointer;border-bottom:1px solid rgba(140,100,220,.15);white-space:nowrap;transition:color .12s;z-index:1;font-weight:700}', '#ml-ptable th:hover{color:rgba(200,170,255,.95)}', '#ml-ptable th.sort-asc::after{content:" ▲";font-size:8px}', '#ml-ptable th.sort-desc::after{content:" ▼";font-size:8px}', '#ml-ptable td{padding:5px 8px;border-bottom:1px solid rgba(160,120,240,.08);color:rgba(245,238,255,.85);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:140px}', '#ml-ptable tr:hover td{background:rgba(140,100,220,.08)}', '#ml-ptable .own-you{color:rgba(80,255,120,.9);font-weight:600}', '#ml-ptable .own-wild{color:rgba(255,190,60,.85);font-style:italic}', '#ml-ptable .pet-var{color:rgba(180,140,255,.85);font-style:italic}', '#ml-ptable .pet-mut-Golden{color:rgba(255,215,0,.95)}', '#ml-ptable .pet-mut-Diamond{color:rgba(185,242,255,.95)}', '#ml-ptable .pet-mut-Emerald{color:rgba(80,255,120,.95)}', '#ml-ptable .pet-mut-Rainbow{color:rgba(255,120,200,.95)}', '#ml-ptable .pet-mut-Galaxy{color:rgba(200,140,255,.95)}', '#ml-ptable .pet-rar{font-size:10px;letter-spacing:.05em}', '.pet-tp{background:rgba(140,100,220,.15);border:1px solid rgba(140,100,220,.3);color:rgba(200,170,255,.8);font-size:11px;padding:3px 8px;border-radius:8px;cursor:pointer;transition:all .12s;line-height:1}', '.pet-tp:hover{background:rgba(140,100,220,.3);color:#fff;border-color:rgba(168,120,255,.6)}', '.pet-grab{background:rgba(60,200,60,.15);border:1px solid rgba(60,200,60,.3);color:rgba(140,255,140,.8);font-size:11px;padding:3px 8px;border-radius:8px;cursor:pointer;transition:all .12s;line-height:1;margin-left:3px}', '.pet-grab:hover{background:rgba(60,200,60,.3);color:#fff;border-color:rgba(80,230,80,.6)}', '#ml-pets-empty{color:rgba(190,155,245,.5);text-align:center;padding:30px 8px;font-size:12px;font-style:italic}', '#ml-slots-pop{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:300px;max-height:70vh;display:none;z-index:100003;pointer-events:auto;overflow:hidden;border-radius:16px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;user-select:none;background:linear-gradient(170deg,rgba(55,45,80,.92) 0%,rgba(45,38,72,.94) 40%,rgba(40,32,65,.95) 100%);border:1.5px solid rgba(160,120,240,.3);box-shadow:0 8px 32px rgba(0,0,0,.4),0 0 0 1px rgba(80,50,140,.2),0 0 60px rgba(120,80,200,.1)}', '#ml-slots-pop::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,#7c3aed,#a855f7,#c084fc,#a855f7,#7c3aed);border-radius:16px 16px 0 0;z-index:1}', '#ml-slots-pop.open{display:flex;flex-direction:column}', '#ml-slots-pop-head{padding:14px 14px 10px;display:flex;align-items:center;justify-content:space-between}', '#ml-slots-pop-title{font-size:14px;font-weight:800;color:rgba(255,250,255,.97);letter-spacing:.02em}', '#ml-slots-pop-close{cursor:pointer;background:rgba(255,255,255,.08);border:none;color:rgba(220,200,245,.6);font-size:16px;width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:8px;font-family:inherit;line-height:1;transition:all .15s}', '#ml-slots-pop-close:hover{color:#ff6b6b;background:rgba(255,80,80,.15)}', '#ml-slots-pop-body{overflow-y:auto;flex:1;padding:4px 8px 8px;scrollbar-width:auto;scrollbar-color:rgba(160,120,240,.5) rgba(255,255,255,.06)}', '#ml-slots-pop-body::-webkit-scrollbar{width:8px}', '#ml-slots-pop-body::-webkit-scrollbar-track{background:rgba(255,255,255,.06);border-radius:4px}', '#ml-slots-pop-body::-webkit-scrollbar-thumb{background:rgba(160,120,240,.5);border-radius:4px;border:1px solid rgba(255,255,255,.08)}', '#ml-slots-pop-body::-webkit-scrollbar-thumb:hover{background:rgba(160,120,240,.7)}', '.ml-slot{display:flex;align-items:center;gap:6px;padding:5px 8px;margin:2px 0;border-radius:8px;transition:all .12s;border:1px solid transparent}', '.ml-slot:hover{background:rgba(140,100,220,.1);border-color:rgba(140,100,220,.15)}', '.ml-slot-num{font-size:10px;color:rgba(168,130,230,.6);font-weight:700;min-width:14px;text-align:right}', '.ml-slot-info{flex:1;font-size:10px;color:rgba(200,180,240,.65);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}', '.ml-slot-info.filled{color:rgba(200,180,240,.9)}', '.ml-slot-go{background:rgba(140,100,220,.15);border:1px solid rgba(140,100,220,.25);color:rgba(200,170,255,.8);font-size:10px;padding:2px 8px;border-radius:6px;cursor:pointer;transition:all .12s}', '.ml-slot-go:hover{background:rgba(140,100,220,.3);color:#fff}', '.ml-slot-go.empty{opacity:.35;pointer-events:none}', '.ml-slot-set{background:rgba(60,180,60,.12);border:1px solid rgba(60,180,60,.25);color:rgba(140,230,140,.8);font-size:10px;padding:2px 8px;border-radius:6px;cursor:pointer;transition:all .12s}', '.ml-slot-set:hover{background:rgba(60,180,60,.25);color:#fff}', '.ml-slot-clr{background:rgba(220,60,60,.12);border:1px solid rgba(220,60,60,.25);color:rgba(255,140,140,.8);font-size:10px;padding:2px 6px;border-radius:6px;cursor:pointer;transition:all .12s}', '.ml-slot-clr:hover{background:rgba(220,60,60,.25);color:#fff}', '.ml-slot-clr.empty{opacity:.35;pointer-events:none}', '#ml-snipe{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:360px;display:none;z-index:100005;pointer-events:auto;overflow:hidden;border-radius:16px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;user-select:none;background:linear-gradient(170deg,rgba(55,45,80,.92) 0%,rgba(45,38,72,.94) 40%,rgba(40,32,65,.95) 100%);border:1.5px solid rgba(240,120,120,.3);box-shadow:0 8px 32px rgba(0,0,0,.4),0 0 0 1px rgba(140,50,50,.2),0 0 60px rgba(200,80,80,.1)}', '#ml-snipe::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,#ed3a3a,#f75555,#fc8484,#f75555,#ed3a3a);border-radius:16px 16px 0 0;z-index:1}', '#ml-snipe.open{display:flex;flex-direction:column}', '#ml-snipe-head{padding:14px 14px 10px;display:flex;align-items:center;justify-content:space-between}', '#ml-snipe-title{font-size:14px;font-weight:800;color:rgba(255,250,255,.97);letter-spacing:.02em}', '#ml-snipe-close{cursor:pointer;background:rgba(255,255,255,.08);border:none;color:rgba(220,200,245,.6);font-size:16px;width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:8px;font-family:inherit;line-height:1;transition:all .15s}', '#ml-snipe-close:hover{color:#ff6b6b;background:rgba(255,80,80,.15)}', '#ml-snipe-body{padding:8px 14px 14px}', '#ml-snipe-search{width:100%;background:rgba(255,255,255,.07);border:1.5px solid rgba(240,120,120,.25);color:rgba(240,230,255,.9);font-size:11px;padding:7px 12px;border-radius:10px;font-family:inherit;outline:none;box-sizing:border-box;transition:all .15s}', '#ml-snipe-search:focus{border-color:rgba(240,120,120,.45);box-shadow:0 0 8px rgba(200,70,70,.12)}', '#ml-snipe-search::placeholder{color:rgba(255,170,170,.5)}', '#ml-snipe-toggle{width:100%;margin-top:10px;padding:8px 0;border-radius:10px;border:1.5px solid rgba(240,120,120,.3);background:rgba(240,120,120,.12);color:rgba(255,200,200,.95);font-size:12px;font-weight:700;cursor:pointer;transition:all .15s;font-family:inherit}', '#ml-snipe-toggle:hover{background:rgba(240,120,120,.25)}', '#ml-snipe-toggle.active{background:rgba(60,200,60,.15);border-color:rgba(60,200,60,.3);color:rgba(140,255,140,.95)}', '#ml-snipe-status{margin-top:8px;font-size:11px;color:rgba(255,220,220,.85);min-height:14px}', '#ml-snipe-types{margin-top:4px;font-size:10px;color:rgba(255,220,210,.9);line-height:1.5;max-height:80px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(240,120,120,.3) transparent}', '#ml-snipe-log{margin-top:6px;max-height:120px;overflow-y:auto;font-size:9.5px;color:rgba(220,200,240,.7);scrollbar-width:thin;scrollbar-color:rgba(160,120,240,.4) transparent}', '.ml-snipe-entry{padding:2px 0;border-bottom:1px solid rgba(160,120,240,.08)}', '#ml-carry-timer{position:fixed;bottom:18px;left:18px;display:none;padding:6px 14px;border-radius:10px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:14px;font-weight:800;color:rgba(255,220,140,.95);background:rgba(40,32,60,.85);border:1.5px solid rgba(255,180,80,.35);box-shadow:0 4px 16px rgba(0,0,0,.3);z-index:100010;pointer-events:none;letter-spacing:.03em}', ].join(''); document.head.appendChild(s); const h = document.createElement('div'); const carryTimer = document.createElement('div'); carryTimer.id = 'ml-carry-timer'; document.body.appendChild(carryTimer); h.id = 'ml-hud'; h.innerHTML = ''; document.body.appendChild(h); const d = document.createElement('div'); d.id = 'ml-dialog'; d.innerHTML = `
${DESCRIPTION}
`; document.body.appendChild(d); const plist = document.createElement('div'); plist.id = 'ml-plist'; plist.innerHTML = '
Players10s
No other players found
'; document.body.appendChild(plist); const settings = document.createElement('div'); settings.id = 'ml-settings'; settings.innerHTML = `
Settings
Move
Features
Auto
Keys
Acceleration
Speed Cap${SPEED_CAP}
Accel Rate${ACCEL}
Base Speed${SPEED_DEFAULT}
Fly Hack
Speed Hack
Waypoints
Anti-Knockback
Noclip
Free Daily Money
Invincibility
Ghost Mode
Cuddle Panel
Continuous Cuddle
Pet Browser
Auto-Lock Base
Auto-Collect Earnings
Collect Interval${autoCollectInterval}s
`; document.body.appendChild(settings); const KB_LABELS = { fly: 'Fly (toggle/up)', flyDown: 'Fly Down', setHome: 'Set Home', home: 'Teleport Home', back: 'Back Teleport', cuddle: 'Cuddle Panel', settings: 'Settings', pets: 'Pet Browser', slots: 'Waypoint Slots', snipe: 'Pet Sniper', help: 'Help / Description', }; function keyCodeLabel(code) { if (code === 'Space') return 'Space'; if (code === 'Backquote') return '`'; if (code.startsWith('Key')) return code.slice(3); if (code.startsWith('Digit')) return code.slice(5); return code; } function buildKeybindsHTML() { let rows = ''; for (const [action, code] of Object.entries(KEYBINDS)) { rows += '
' + (KB_LABELS[action] || action) + '' + keyCodeLabel(code) + '
'; } $('ml-keybinds-body').innerHTML = rows; } buildKeybindsHTML(); const petsPanel = document.createElement('div'); petsPanel.id = 'ml-pets'; petsPanel.innerHTML = '
Pets
' + petRefreshInterval + 's
Words are AND\u2019d together. Use OR for alternatives, brackets to group. * or % as wildcard.
'; document.body.appendChild(petsPanel); const slotsPop = document.createElement('div'); slotsPop.id = 'ml-slots-pop'; slotsPop.innerHTML = '
Waypoint Slots
'; document.body.appendChild(slotsPop); function buildSlotsHTML() { const body = $('ml-slots-pop-body'); if (!body) return; let html = ''; for (let i = 0; i < 10; i++) { const s = slots[i]; const info = s ? `${s.x.toFixed(1)}, ${s.y.toFixed(1)}, ${s.z.toFixed(1)}` : 'empty'; html += `
${i}${info}
`; } body.innerHTML = html; } buildSlotsHTML(); $('ml-slots-pop-close').addEventListener('click', () => toggleSlots(false)); slotsPop.addEventListener('click', e => { const goBtn = e.target.closest('.ml-slot-go'); const setBtn = e.target.closest('.ml-slot-set'); const clrBtn = e.target.closest('.ml-slot-clr'); if (!goBtn && !setBtn && !clrBtn) return; const idx = parseInt((goBtn || setBtn || clrBtn).dataset.slot); if (isNaN(idx)) return; const p = getPlayer(); if (!p) return; if (clrBtn) { slots[idx] = null; saveWaypoints(); flash('ml-slots'); buildSlotsHTML(); console.log(`[slot ${idx}] cleared`); } else if (setBtn) { slots[idx] = capturePos(p); saveWaypoints(); flash('ml-slots'); buildSlotsHTML(); console.log(`[slot ${idx}] saved via popout`); } else if (goBtn && slots[idx]) { backPos = capturePos(p); teleport(p, slots[idx]); saveWaypoints(); flash('ml-slots'); toggleSlots(false); console.log(`[slot ${idx}] teleported via popout`); } }); slotsPop.addEventListener('ml-rebuild', () => buildSlotsHTML()); const snipePanel = document.createElement('div'); snipePanel.id = 'ml-snipe'; snipePanel.innerHTML = '
Pet Sniper
Words are AND\u2019d. Use OR for alternatives, brackets to group. * or % as wildcard.
Idle
'; document.body.appendChild(snipePanel); [plist, settings, d, petsPanel, slotsPop, snipePanel].forEach(el => { ['mousedown','mouseup','click','pointerdown','pointerup','mousemove','mouseover','mouseenter','mouseleave','wheel','contextmenu','pointermove','pointerover','pointerenter'].forEach(evt => { el.addEventListener(evt, e => e.stopPropagation()); }); ['keydown','keyup','keypress'].forEach(evt => { el.addEventListener(evt, e => e.stopPropagation()); }); }); function makeDraggable(panel, handle) { let dragging = false, ox = 0, oy = 0; handle.style.cursor = 'grab'; panel.style.resize = 'both'; panel.style.overflow = 'auto'; handle.addEventListener('mousedown', e => { if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT' || e.target.tagName === 'LABEL') return; dragging = true; handle.style.cursor = 'grabbing'; const rect = panel.getBoundingClientRect(); panel.style.left = rect.left + 'px'; panel.style.top = rect.top + 'px'; panel.style.right = 'auto'; panel.style.bottom = 'auto'; panel.style.transform = 'none'; ox = e.clientX - rect.left; oy = e.clientY - rect.top; e.preventDefault(); }); window.addEventListener('mousemove', e => { if (!dragging) return; panel.style.left = Math.max(0, Math.min(e.clientX - ox, window.innerWidth - 40)) + 'px'; panel.style.top = Math.max(0, Math.min(e.clientY - oy, window.innerHeight - 40)) + 'px'; }, true); window.addEventListener('mouseup', () => { if (dragging) { dragging = false; handle.style.cursor = 'grab'; } }, true); panel._resetPos = () => { panel.style.left = ''; panel.style.top = ''; panel.style.right = ''; panel.style.bottom = ''; panel.style.transform = ''; panel.style.width = ''; panel.style.height = ''; }; } makeDraggable(plist, $('ml-plist-head')); makeDraggable(settings, $('ml-settings-head')); makeDraggable(petsPanel, $('ml-pets-head')); makeDraggable(slotsPop, $('ml-slots-pop-head')); makeDraggable(snipePanel, $('ml-snipe-head')); makeDraggable(d.querySelector('#ml-inner'), d.querySelector('#ml-inner h1')); function syncSettingsUI() { syncSlider('ml-s-cap', 'ml-sv-cap', SPEED_CAP); syncSlider('ml-s-accel', 'ml-sv-accel', ACCEL); syncSlider('ml-s-base', 'ml-sv-base', SPEED_DEFAULT); syncSlider('ml-s-acinterval', 'ml-sv-acinterval', autoCollectInterval, 's'); const ae = $('ml-s-accel-en'); if (ae) ae.classList.toggle('on', accelEnabled); const featVals = [featFly, featSprint, featWaypoints, featCuddle, featCuddleFollow, featPets, featAutoLock, featAntiKnockback, featNoclip, featFreeMoney, featAutoCollect, featInvincible, featGhostMode]; FEAT_IDS.forEach((id, i) => { const el = $(id); if (el) el.classList.toggle('on', featVals[i]); }); } syncSettingsUI(); function getPlayers() { const holder = W.pc?.app?.root?.findByName('EnemyHolder'); if (!holder) return []; const player = getPlayer(); const playerPos = player?.getPosition(); const results = []; for (const enemy of holder.children) { const pos = enemy.getPosition(); let username = null; try { username = enemy.script?.enemy?.usernameEntity?.element?.text; } catch (_) {} if (!username) { const ue = enemy.findByName?.('Username'); if (ue?.element?.text) username = ue.element.text; } if (!username || username === 'Enemy') username = enemy.name !== 'Enemy' ? enemy.name : null; if (!username) username = 'Player'; const dist = playerPos ? Math.floor(playerPos.distance(pos)) : '?'; results.push({ name: username, dist, pos: vec3(pos), entity: enemy }); } results.sort((a, b) => (typeof a.dist === 'number' && typeof b.dist === 'number') ? a.dist - b.dist : 0); return results; } function refreshPlayerList() { const body = $('ml-plist-body'); if (!body) return; const players = getPlayers(); if (players.length === 0) { body.innerHTML = '
No other players found
'; return; } body.innerHTML = ''; players.forEach((p, i) => { const row = document.createElement('div'); row.className = 'ml-prow'; row.innerHTML = `${i + 1}
${p.dist}m
`; row.querySelector('.ml-pname').textContent = p.name; row.addEventListener('click', () => { const player = getPlayer(); if (!player) return; const freshPos = p.entity?.getPosition(); const target = freshPos || p.pos; backPos = capturePos(player); teleport(player, vec3(target)); saveWaypoints(); if (featCuddleFollow) { cuddleTarget = p.entity; cuddling = true; console.log(`[cuddle] locked → ${p.name}`); } flash('ml-back'); const app = W.pc?.app; if (app) app.fire('GameManager:GameResumed'); }); body.appendChild(row); }); } function getPetOwnerId(pet) { if (!pet) return null; const d = pet.owner; if (d === false) return false; if (d != null) return d; return pet?.data?.owner ?? pet?.ownerId ?? pet?.data?.ownerId ?? null; } let _ownerMapCache = null; let _ownerMapTime = 0; function buildOwnerMap() { const now = Date.now(); if (_ownerMapCache && now - _ownerMapTime < 2000) return _ownerMapCache; const map = {}; const myId = W.pc?.sessionId; if (myId) map[myId] = 'Yours'; const nm = W.pc?.app?.root?.findByName('NetworkManager')?.script?.networkManager; if (nm?.sessionId && !map[nm.sessionId]) map[nm.sessionId] = 'Yours'; const holder = W.pc?.app?.root?.findByName('EnemyHolder'); if (holder) { for (const child of holder.children) { let id = child.id || child.sessionId || child.playerId; if (!id && child.script) { for (const sk of Object.keys(child.script._scriptsIndex || {})) { const inst = child.script[sk]; id = inst?.id || inst?.sessionId || inst?.playerId; if (id) break; } } if (!id) continue; let name = null; try { name = child.script?.enemy?.usernameEntity?.element?.text; } catch (_) {} if (!name) { const ue = child.findByName?.('Username'); if (ue?.element?.text) name = ue.element.text; } if (name && name !== 'Enemy') map[id] = name; } } _ownerMapCache = map; _ownerMapTime = now; return map; } function getPetOwnerName(pet, ownerMap) { const ownerId = getPetOwnerId(pet); if (ownerId === false || ownerId == null) return 'Wild'; if (ownerMap?.[ownerId]) return ownerMap[ownerId]; return ownerId.length > 10 ? ownerId.substring(0, 8) + '…' : ownerId; } let _pmCache = null; let _pmCacheTime = 0; function getPetsManager() { const now = Date.now(); if (_pmCacheTime && now - _pmCacheTime < 5000 && (_pmCache?.activePets || _pmCache?.basePets)) return _pmCache; const pmEntity = W.pc?.app?.root?.findByName('PetsManager'); let pm = pmEntity?.script?.petsManager; if (!pm && pmEntity?.script) { for (const k of Object.keys(pmEntity.script)) { const s = pmEntity.script[k]; if (s?.activePets || s?.basePets) { pm = s; break; } } } if (!pm) { const root = W.pc?.app?.root; if (!root) return null; root.find(e => { if (!e.script) return false; for (const k of Object.keys(e.script)) { const s = e.script[k]; if (s?.activePets || s?.basePets) { pm = s; return true; } } return false; }); } _pmCache = pm || null; _pmCacheTime = now; return _pmCache; } function getAllPets() { const pm = getPetsManager(); if (!pm) return []; hookPetSpawn(); const ownerMap = buildOwnerMap(); const pets = []; const scan = (map, type) => { if (!map) return; map.forEach((pet, token) => { const name = pet.name || String(token).substring(0, 8); const sd = petSpawnData.get(token); let mutation = sd?.mutation ?? ''; let rarity = sd?.rarity ?? ''; let profit = sd?.profit ?? null; if (mutation === 'Default') mutation = ''; if (!mutation) { try { if (pet._mlMut) { mutation = pet._mlMut; } else { const mutNames = ['Golden', 'Diamond', 'Emerald', 'Rainbow', 'Galaxy']; for (const mn of mutNames) { if (pet.findByName?.(`Mutation ${mn} Effect`)) { mutation = mn; break; } } if (mutation) pet._mlMut = mutation; } } catch (_) {} } if (!rarity) { try { if (pet._mlRar) { rarity = pet._mlRar; } else { const RARITIES = ['BASIC', 'RARE', 'EPIC', 'LEGENDARY', 'MYTHICAL', 'EXOTIC', 'SECRET', 'EXCLUSIVE']; for (const r of RARITIES) { const node = pet.findByName?.(r); if (node && node.enabled) { rarity = r; break; } } if (rarity) pet._mlRar = rarity; } } catch (_) {} } if (!profit) { try { const statsEl = pet.findByName?.('PetStats'); if (statsEl) { const profitEl = statsEl.findByName?.('Profit') || statsEl.findByName?.('PetProfit'); if (profitEl?.element?.text) { const m = profitEl.element.text.match(/\$\s*([\d,.]+)\s*([kmbtqsxi]*)/); if (m) { let v = parseFloat(m[1].replace(/,/g, '')); const suf = m[2]?.toLowerCase(); if (suf === 'k') v *= 1e3; else if (suf === 'm') v *= 1e6; else if (suf === 'b') v *= 1e9; else if (suf === 't') v *= 1e12; else if (suf === 'q') v *= 1e15; profit = v; } } } } catch (_) {} } const pos = pet.getPosition ? pet.getPosition() : pet.position; const price = pet.price ?? 0; pets.push({ token, name, price, income: profit ?? 0, owner: getPetOwnerName(pet, ownerMap), ownerId: getPetOwnerId(pet), type, mutation, rarity, x: pos?.x ?? 0, y: pos?.y ?? 0, z: pos?.z ?? 0, }); }); }; scan(pm.activePets, 'active'); scan(pm.basePets, 'base'); return pets; } let lastRenderedPets = []; const grabbedTokens = new Map(); function renderPetTable() { const body = $('ml-pets-body'); const countEl = $('ml-pets-count'); if (!body) return; let pets = getAllPets(); if (countEl) countEl.textContent = `(${pets.length})`; if (pets.length === 0) { lastRenderedPets = []; body.innerHTML = '
No pets found in this room
'; return; } if (petFilter) pets = pets.filter(p => petMatchesFilter(p, petFilter)); const playerPos = getPlayer()?.getPosition(); if (playerPos) pets.forEach(p => { p._dist = Math.hypot(p.x - playerPos.x, p.y - playerPos.y, p.z - playerPos.z); }); pets.sort((a, b) => { const key = petSortCol === 'dist' ? '_dist' : petSortCol; let av = a[key], bv = b[key]; if (av == null) av = Infinity; if (bv == null) bv = Infinity; if (typeof av === 'string') av = av.toLowerCase(); if (typeof bv === 'string') bv = bv.toLowerCase(); if (av < bv) return -petSortDir; if (av > bv) return petSortDir; return 0; }); lastRenderedPets = pets; const cols = ['name','mutation','rarity','owner','price','income','dist','go']; const labels = { name:'Name', mutation:'Mutation', rarity:'Rarity', owner:'Owner', price:'Worth', income:'Income/s', dist:'Dist', go:'' }; let html = ''; cols.forEach(c => { const cls = petSortCol === c ? (petSortDir === 1 ? 'sort-asc' : 'sort-desc') : ''; html += c === 'go' ? '' : ``; }); html += ''; const now = Date.now(); pets.forEach(p => { const ownerCls = p.owner === 'Yours' ? 'own-you' : p.owner === 'Wild' ? 'own-wild' : ''; const mutCls = p.mutation ? `pet-mut-${p.mutation}` : 'pet-var'; const tokenStr = String(p.token); const grabbed = grabbedTokens.has(tokenStr) && grabbedTokens.get(tokenStr) > now; const grabBtn = p.owner !== 'Yours' ? `` : ''; html += ``; }); html += '
${labels[c]}
${esc(p.name)}${esc(p.mutation) || '\u2014'}${esc(p.rarity) || '\u2014'}${esc(p.owner)}${numFmt(p.price)}${numFmt(p.income)}/s${p._dist != null ? numFmt(Math.round(p._dist)) : '\u2014'}${grabBtn}
'; body.innerHTML = html; } function findPetByToken(token) { return lastRenderedPets.find(p => String(p.token) === token) || null; } $('ml-pets-body').addEventListener('click', e => { const th = e.target.closest('th[data-col]'); if (th) { const col = th.dataset.col; if (petSortCol === col) petSortDir *= -1; else { petSortCol = col; petSortDir = col === 'price' || col === 'income' || col === 'dist' ? -1 : 1; } saveSettings(); renderPetTable(); return; } const tpBtn = e.target.closest('.pet-tp'); if (tpBtn) { const p = findPetByToken(tpBtn.dataset.token); if (!p) return; const player = getPlayer(); if (!player) return; player.setPosition(p.x, p.y + 1, p.z); togglePetsPanel(false); return; } const grabBtn = e.target.closest('.pet-grab'); if (grabBtn) { const p = findPetByToken(grabBtn.dataset.token); if (!p) return; const app = W.pc?.app; if (!app) return; const player = getPlayer(); if (!player) return; const tokenStr = String(p.token); const orig = player.getPosition().clone(); player.setPosition(p.x, p.y + 0.5, p.z); grabBtn.disabled = true; grabBtn.textContent = '…'; setTimeout(() => { app.fire('ModeOverlay:BuyPet', p.token); console.log(`[ml] grab pet: ${p.name} (${p.token})`); setTimeout(() => { player.setPosition(orig.x, orig.y, orig.z); setTimeout(() => { app.fire('NetworkManager:Send', 'dropPet'); console.log(`[ml] drop pet at origin`); grabbedTokens.set(tokenStr, Date.now() + 5000); renderPetTable(); }, 150); }, 150); }, 100); } }); function esc(s) { return String(s).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); } function numFmt(n) { if (n >= 1e15) return (n / 1e15).toFixed(1) + 'q'; if (n >= 1e12) return (n / 1e12).toFixed(1) + 't'; if (n >= 1e9) return (n / 1e9).toFixed(1) + 'b'; if (n >= 1e6) return (n / 1e6).toFixed(1) + 'm'; if (n >= 1e3) return (n / 1e3).toFixed(1) + 'k'; return n % 1 === 0 ? String(n) : n.toFixed(1); } function petMatchesFilter(p, raw) { if (!raw) return true; const text = [p.name, p.owner, p.mutation, p.rarity].join(' ').toLowerCase(); const tokens = raw.match(/\(|\)|AND|OR|[^\s()]+/gi) || []; function parseOr(i) { let [result, j] = parseAnd(i); while (j < tokens.length && tokens[j]?.toUpperCase() === 'OR') { const [r2, j2] = parseAnd(j + 1); result = result || r2; j = j2; } return [result, j]; } function parseAnd(i) { let [result, j] = parseAtom(i); while (j < tokens.length) { const up = tokens[j]?.toUpperCase(); if (up === 'AND') { j++; } else if (up === 'OR' || tokens[j] === ')') break; const [r2, j2] = parseAtom(j); result = result && r2; j = j2; } return [result, j]; } function parseAtom(i) { if (i >= tokens.length) return [false, i]; if (tokens[i] === '(') { const [result, j] = parseOr(i + 1); return [result, j < tokens.length && tokens[j] === ')' ? j + 1 : j]; } const t = tokens[i].toLowerCase(); if (t.includes('*') || t.includes('%')) { const re = new RegExp(t.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/[*%]/g, '.*')); return [re.test(text), i + 1]; } return [text.includes(t), i + 1]; } try { return parseOr(0)[0]; } catch (_) { return text.includes(raw.toLowerCase()); } } let petRefreshTimer = null; function startPetRefresh() { stopPetRefresh(); petRefreshTimer = setInterval(() => renderPetTable(), petRefreshInterval * 1000); } function stopPetRefresh() { if (petRefreshTimer) { clearInterval(petRefreshTimer); petRefreshTimer = null; } } function togglePetsPanel(forceOpen) { const open = forceOpen !== undefined ? forceOpen : !petsPanel.classList.contains('open'); petsPanel.classList.toggle('open', open); if (open) { $('ml-pets-search').value = petFilter; $('ml-pets-auto').checked = petAutoRefresh; syncSlider('ml-pets-interval', 'ml-pets-iv', petRefreshInterval); renderPetTable(); if (petAutoRefresh) startPetRefresh(); panelPause(); } else { stopPetRefresh(); petsPanel._resetPos?.(); panelResume(); } } $('ml-pets-btn').addEventListener('click', () => { togglePetsPanel(); }); $('ml-pets-close').addEventListener('click', () => togglePetsPanel(false)); $('ml-pets-search').addEventListener('input', e => { petFilter = e.target.value; saveSettings(); renderPetTable(); }); $('ml-pets-auto').addEventListener('change', e => { petAutoRefresh = e.target.checked; saveSettings(); if (petAutoRefresh && petsPanel.classList.contains('open')) startPetRefresh(); else stopPetRefresh(); }); $('ml-pets-interval').addEventListener('input', e => { petRefreshInterval = parseInt(e.target.value); const iv = $('ml-pets-iv'); if (iv) iv.textContent = petRefreshInterval; saveSettings(); if (petAutoRefresh && petsPanel.classList.contains('open')) startPetRefresh(); }); let _snipeTimer = null; let _snipeCooldown = 0; let _snipeDropInProgress = false; function isOwnerBaseLocked(ownerId) { if (!ownerId) return false; const now = Date.now(); if (!_blmCache || now - _blmCacheTime > 3000) { const app = W.pc?.app; if (!app) return false; let blm = app.root?.findByName('BaseLockdownManager')?.script?.petTycoonBaseLockdownManager; if (!blm) { const bm = _getBasesManager(); if (bm) { const entity = bm.entity; blm = entity?.script?.petTycoonBaseLockdownManager; if (!blm) { for (const c of (entity?.children || [])) { blm = c.script?.petTycoonBaseLockdownManager; if (blm) break; } } } } if (!blm) { const e = app.root?.find(e => e.script?.petTycoonBaseLockdownManager)?.[0]; blm = e?.script?.petTycoonBaseLockdownManager; } _blmCache = blm || null; _blmCacheTime = now; } if (_blmCache?.lockedBases) { return _blmCache.lockedBases.has(ownerId); } return false; } const _snipedPets = []; const SNIPE_HISTORY_CAP = 200; function recordSnipe(token) { _snipedPets.push({ token: String(token), time: Date.now() }); while (_snipedPets.length > SNIPE_HISTORY_CAP) _snipedPets.shift(); } function getSnipeTime(token) { const t = String(token); for (let i = _snipedPets.length - 1; i >= 0; i--) { if (_snipedPets[i].token === t) return _snipedPets[i].time; } return 0; } function snipeLog(msg) { const log = $('ml-snipe-log'); if (!log) return; const entry = document.createElement('div'); entry.className = 'ml-snipe-entry'; entry.textContent = new Date().toLocaleTimeString() + ' ' + msg; log.prepend(entry); while (log.children.length > 30) log.lastChild.remove(); } function snipeScan() { if (!snipeFilter) { $('ml-snipe-status').textContent = 'No filter set'; $('ml-snipe-types').textContent = ''; return null; } const app = W.pc?.app; const player = getPlayer(); if (!app || !player) { $('ml-snipe-status').textContent = 'Waiting for game...'; return null; } const nm = _getNetworkManager(); const myId = nm?.room?.sessionId || W.pc?.sessionId; const bm = _getBasesManager(); const isStealMode = !!(bm?.activeBases); const pets = getAllPets(); const nameMatches = pets.filter(p => { if (p.ownerId === myId || p.owner === 'Yours') return false; return petMatchesFilter(p, snipeFilter); }); let blocked = 0; const matches = nameMatches.filter(p => { if (isStealMode) { if (p.owner === 'Wild' || !p.ownerId) { blocked++; return false; } if (isOwnerBaseLocked(p.ownerId)) { blocked++; return false; } return true; } else { if (p.owner !== 'Wild' && p.ownerId) { blocked++; return false; } return true; } }); const blockedStr = blocked ? ' (' + blocked + ' locked)' : ''; $('ml-snipe-status').textContent = (isStealMode ? '[Steal] ' : '[Waves] ') + matches.length + ' target(s) / ' + nameMatches.length + ' matched' + blockedStr; const typeCounts = {}; for (const m of nameMatches) { const variant = [m.rarity, m.mutation, m.name].filter(Boolean).join(' '); const isLocked = isStealMode && m.ownerId && isOwnerBaseLocked(m.ownerId); if (!typeCounts[variant]) typeCounts[variant] = { total: 0, locked: 0 }; typeCounts[variant].total++; if (isLocked) typeCounts[variant].locked++; } const typesEl = $('ml-snipe-types'); if (typesEl) { const entries = Object.entries(typeCounts).sort((a, b) => b[1].total - a[1].total); typesEl.textContent = entries.map(([k, v]) => { let label = k + (v.total > 1 ? ' \u00d7' + v.total : ''); if (v.locked > 0) label += ' (\ud83d\udd12' + v.locked + ')'; return label; }).join(', '); } return { matches, isStealMode }; } let _snipeScanTimer = null; function snipeTick() { if (!snipeActive) return; const now = Date.now(); if (now < _snipeCooldown) { $('ml-snipe-status').textContent = 'Cooldown ' + (((_snipeCooldown - now) / 1000) | 0) + 's...'; return; } const app = W.pc?.app; const pt = _getPetTycoon(); const et = _getEscapeTsunami(); if (pt?.isHoldingPet || et?.isHoldingPet) { $('ml-snipe-status').textContent = 'Holding a pet \u2014 paused'; return; } const scan = snipeScan(); if (!scan || scan.matches.length === 0) return; const { matches, isStealMode } = scan; const player = getPlayer(); if (!player) return; const pPos = player.getPosition(); for (const m of matches) { m._dist = Math.hypot(m.x - pPos.x, m.y - pPos.y, m.z - pPos.z); m._snipeTime = getSnipeTime(m.token); m._value = Math.max(m.price || 0, m.income || 0); } matches.sort((a, b) => { if (!a._snipeTime && b._snipeTime) return -1; if (a._snipeTime && !b._snipeTime) return 1; if (a._snipeTime && b._snipeTime) return a._snipeTime - b._snipeTime; if (isStealMode) { if (b.income !== a.income) return b.income - a.income; } if (b._value !== a._value) return b._value - a._value; return a._dist - b._dist; }); const target = matches[0]; $('ml-snipe-status').textContent = 'Sniping: ' + target.name + '...'; snipeLog('Sniping ' + target.name + ' (' + (target.owner || 'wild') + ') dist=' + Math.round(target._dist)); if (isStealMode) { _snipeCooldown = Date.now() + 6000; player.setPosition(target.x, target.y + 0.5, target.z); recordSnipe(target.token); snipeLog('TP\u2019d to ' + target.name + ' — click to grab!'); $('ml-snipe-status').textContent = 'At ' + target.name + '. Click to grab.'; } else { const orig = player.getPosition().clone(); const nm = _getNetworkManager(); const room = nm?.room; const sid = room?.sessionId; if (!room || !sid) return; const rawSend = room.__mlOrigSend || room.send.bind(room); _snipeCooldown = Date.now() + 5000; if (featGhostMode) { _wavesGhostPos = { x: target.x, y: target.y + 0.5, z: target.z }; } else { player.setPosition(target.x, target.y + 0.5, target.z); } (async () => { await new Promise(r => setTimeout(r, 150)); app.fire('ModeOverlay:BuyPet', target.token); recordSnipe(target.token); console.log('[ml] snipe grab:', target.name, target.token); const grabbed = await new Promise(resolve => { const timer = setTimeout(() => { unsub(); resolve(false); }, 600); const unsub = room.onMessage('petHeld', msg => { if (msg.holderSessionId !== sid) return; clearTimeout(timer); unsub(); resolve(true); }); }); if (!grabbed) { _wavesGhostPos = null; if (!featGhostMode) player.setPosition(orig.x, orig.y, orig.z); snipeLog(target.name + ': grab timeout'); $('ml-snipe-status').textContent = 'Grab failed. Retrying...'; _snipeCooldown = Date.now() + 500; return; } _wavesGhostPos = null; if (!featGhostMode) player.setPosition(orig.x, orig.y, orig.z); if (snipeAutoDrop) { _snipeDropInProgress = true; const realPos = player.getPosition(); rawSend('p', { x: realPos.x, y: realPos.y, z: realPos.z, w: 0 }); let dropped = false; for (let att = 0; att < 4 && !dropped; att++) { await new Promise(r => setTimeout(r, att === 0 ? 200 : 500)); const et = _getEscapeTsunami(); if (!et?.isHoldingPet) { dropped = true; break; } const dp = new Promise(resolve => { const t = setTimeout(() => { u(); resolve(false); }, 800); const u = room.onMessage('escapeTsunamiPetDropped', msg => { if (msg.holderSessionId !== sid) return; clearTimeout(t); u(); resolve(true); }); }); rawSend('dropPet'); if (att > 0) rawSend('p', { x: realPos.x, y: realPos.y, z: realPos.z, w: 0 }); dropped = await dp; if (!dropped) console.log('[ml] drop attempt', att + 1, 'failed'); } _snipeDropInProgress = false; if (!dropped) console.log('[ml] drop failed after retries — isHolding:', _getEscapeTsunami()?.isHoldingPet); snipeLog('Sniped ' + target.name + (dropped ? ' ✓ dropped' : ' (drop failed!)')); $('ml-snipe-status').textContent = dropped ? 'Dropped ' + target.name : 'Drop failed!'; _snipeCooldown = Date.now() + 300; } else { snipeLog('Sniped ' + target.name + ' ✓ — place on base!'); $('ml-snipe-status').textContent = 'Holding ' + target.name + '! Place on base.'; _snipeCooldown = Date.now() + 1000; } })(); } } let _heldPetCleanup = null; function heldPetCleanupTick() { if (!snipeActive || !snipeAutoDrop || _snipeDropInProgress) return; const et = _getEscapeTsunami(); if (!et?.isHoldingPet) return; const nm = _getNetworkManager(); const room = nm?.room; if (!room) return; const rawSend = room.__mlOrigSend || room.send.bind(room); const pos = getPlayer()?.getPosition(); if (pos) rawSend('p', { x: pos.x, y: pos.y, z: pos.z, w: 0 }); rawSend('dropPet'); console.log('[ml] held-pet cleanup: forced drop'); } function startSnipe() { if (_snipeTimer) return; _snipeTimer = setInterval(snipeTick, 200); if (!_heldPetCleanup) _heldPetCleanup = setInterval(heldPetCleanupTick, 3000); snipeLog('Sniping started: ' + snipeFilter); } function stopSnipe() { if (_snipeTimer) { clearInterval(_snipeTimer); _snipeTimer = null; } if (_heldPetCleanup) { clearInterval(_heldPetCleanup); _heldPetCleanup = null; } } function toggleSnipePanel(forceOpen) { const open = forceOpen !== undefined ? forceOpen : !snipePanel.classList.contains('open'); snipePanel.classList.toggle('open', open); if (open) { $('ml-snipe-search').value = snipeFilter; $('ml-snipe-drop').checked = snipeAutoDrop; $('ml-snipe-toggle').textContent = snipeActive ? 'Stop Sniping' : 'Start Sniping'; $('ml-snipe-toggle').classList.toggle('active', snipeActive); snipeScan(); if (!_snipeScanTimer && !_snipeTimer) _snipeScanTimer = setInterval(snipeScan, 2000); panelPause(); } else { if (_snipeScanTimer) { clearInterval(_snipeScanTimer); _snipeScanTimer = null; } snipePanel._resetPos?.(); panelResume(); } } $('ml-snipe-btn').addEventListener('click', () => { toggleSnipePanel(); }); $('ml-snipe-close').addEventListener('click', () => toggleSnipePanel(false)); $('ml-snipe-search').addEventListener('input', e => { snipeFilter = e.target.value; saveSettings(); }); $('ml-snipe-drop').addEventListener('change', e => { snipeAutoDrop = e.target.checked; saveSettings(); }); $('ml-snipe-toggle').addEventListener('click', () => { snipeActive = !snipeActive; saveSettings(); $('ml-snipe-toggle').textContent = snipeActive ? 'Stop Sniping' : 'Start Sniping'; $('ml-snipe-toggle').classList.toggle('active', snipeActive); if (snipeActive) startSnipe(); else { stopSnipe(); $('ml-snipe-status').textContent = 'Idle'; } }); if (snipeActive) { $('ml-snipe-toggle').textContent = 'Stop Sniping'; $('ml-snipe-toggle').classList.add('active'); startSnipe(); } function toggleCuddlePanel(forceOpen) { const wasOpen = plist.classList.contains('open'); const open = forceOpen !== undefined ? forceOpen : !wasOpen; plist.classList.toggle('open', open); if (open) { refreshPlayerList(); panelPause(); if (!wasOpen && autoRefresh) startRefreshTimer(); } else if (wasOpen) { stopRefreshTimer(); plist._resetPos?.(); panelResume(); } } const origRequestPointerLock = Element.prototype.requestPointerLock; Element.prototype.requestPointerLock = function() { if (anyPanelOpen()) return; return origRequestPointerLock.call(this); }; const origRequestFullscreen = Element.prototype.requestFullscreen; Element.prototype.requestFullscreen = function(opts) { return origRequestFullscreen.call(document.body, opts); }; document.addEventListener('pointerlockchange', e => { if (anyPanelOpen() && !document.pointerLockElement) { e.stopImmediatePropagation(); } if (document.pointerLockElement) { const app = W.pc?.app; if (app) app.fire('GameManager:GameResumed'); console.log('[guard] pointer lock active → forced GameResumed'); } }, true); let refreshCountdown = refreshInterval; let refreshTimer = null; function startRefreshTimer() { stopRefreshTimer(); refreshCountdown = refreshInterval; const timerEl = $('ml-plist-timer'); if (timerEl) timerEl.textContent = refreshCountdown + 's'; refreshTimer = setInterval(() => { refreshCountdown--; if (timerEl) timerEl.textContent = refreshCountdown + 's'; if (refreshCountdown <= 0) { refreshPlayerList(); refreshCountdown = refreshInterval; if (timerEl) timerEl.textContent = refreshCountdown + 's'; } }, 1000); } function stopRefreshTimer() { if (refreshTimer) { clearInterval(refreshTimer); refreshTimer = null; } } $('ml-tp').addEventListener('click', () => { toggleCuddlePanel(); }); $('ml-plist-refresh').addEventListener('click', () => { refreshPlayerList(); if (autoRefresh && plist.classList.contains('open')) startRefreshTimer(); }); $('ml-plist-close').addEventListener('click', () => toggleCuddlePanel(false)); function toggleSettings(forceOpen) { const open = forceOpen !== undefined ? forceOpen : !settings.classList.contains('open'); settings.classList.toggle('open', open); if (open) { panelPause(); } else if (!open) { kbListeningRow = null; settings._resetPos?.(); panelResume(); } } $('ml-cfg').addEventListener('click', () => { toggleSettings(); }); $('ml-settings-close').addEventListener('click', () => toggleSettings(false)); document.querySelectorAll('#ml-tabs .ml-tab').forEach(tab => { tab.addEventListener('click', () => { const t = tab.dataset.tab; document.querySelectorAll('#ml-tabs .ml-tab').forEach(x => x.classList.toggle('active', x.dataset.tab === t)); document.querySelectorAll('#ml-settings-body .ml-tab-content').forEach(x => x.classList.toggle('active', x.dataset.tab === t)); if (t === 'keys') buildKeybindsHTML(); else { kbListeningRow = null; $('ml-keybinds-body').querySelectorAll('.ml-krow.listening').forEach(r => r.classList.remove('listening')); } }); }); const DEFAULTS = { ACCEL: 6, SPEED_CAP: 100, SPEED_DEFAULT: 7, petRefreshInterval: 1, petFilter: 'wild', petSortCol: 'price', petSortDir: -1 }; $('ml-settings-reset').addEventListener('click', () => { ACCEL = DEFAULTS.ACCEL; SPEED_CAP = DEFAULTS.SPEED_CAP; SPEED_DEFAULT = DEFAULTS.SPEED_DEFAULT; petRefreshInterval = DEFAULTS.petRefreshInterval; petFilter = DEFAULTS.petFilter; petSortCol = DEFAULTS.petSortCol; petSortDir = DEFAULTS.petSortDir; accelEnabled = true; featFly = true; featSprint = true; featWaypoints = true; featCuddle = true; featCuddleFollow = true; featPets = true; featAutoLock = true; featAntiKnockback = true; featNoclip = false; featFreeMoney = true; featAutoCollect = true; featInvincible = true; featGhostMode = true; autoCollectInterval = 30; Object.assign(KEYBINDS, DEFAULT_KEYBINDS); syncSettingsUI(); buildKeybindsHTML(); updateHUDBadgeLabels(); console.log('[settings] reset'); saveSettings(); }); const sliderMap = [ { id: 'ml-s-cap', valId: 'ml-sv-cap', apply: v => { SPEED_CAP = v; } }, { id: 'ml-s-accel', valId: 'ml-sv-accel', apply: v => { ACCEL = v; } }, { id: 'ml-s-base', valId: 'ml-sv-base', apply: v => { SPEED_DEFAULT = v; } }, { id: 'ml-s-acinterval', valId: 'ml-sv-acinterval', uom: 's', apply: v => { autoCollectInterval = v; } }, ]; sliderMap.forEach(s => { const el = $(s.id); const valEl = $(s.valId); if (!el) return; el.addEventListener('input', () => { const v = parseInt(el.value); if (valEl) valEl.textContent = s.uom ? v + s.uom : v; s.apply(v); saveSettings(); }); }); const accelToggle = $('ml-s-accel-en'); if (accelToggle) { accelToggle.addEventListener('click', () => { accelEnabled = !accelEnabled; accelToggle.classList.toggle('on', accelEnabled); saveSettings(); }); } const featToggles = [ { id: 'ml-f-fly', get: () => featFly, set: v => { featFly = v; if (!v) { const p = getPlayer(); const k = getKcc(p); if (k && flyActive) flyOff(k); } } }, { id: 'ml-f-sprint', get: () => featSprint, set: v => { featSprint = v; if (!v) sprinting = false; } }, { id: 'ml-f-waypoints', get: () => featWaypoints, set: v => { featWaypoints = v; } }, { id: 'ml-f-cuddle', get: () => featCuddle, set: v => { featCuddle = v; if (!v) toggleCuddlePanel(false); } }, { id: 'ml-f-cuddle-follow', get: () => featCuddleFollow, set: v => { featCuddleFollow = v; if (!v) { cuddling = false; cuddleTarget = null; } } }, { id: 'ml-f-pets', get: () => featPets, set: v => { featPets = v; if (!v) togglePetsPanel(false); } }, { id: 'ml-f-autolock', get: () => featAutoLock, set: v => { featAutoLock = v; } }, { id: 'ml-f-antiknockback', get: () => featAntiKnockback, set: v => { featAntiKnockback = v; if (!v) antiKnockbackReady = false; } }, { id: 'ml-f-noclip', get: () => featNoclip, set: v => { featNoclip = v; } }, { id: 'ml-f-freemoney', get: () => featFreeMoney, set: v => { featFreeMoney = v; if (v && !freeMoneyDone) autoFarmFreeMoney(); } }, { id: 'ml-f-autocollect', get: () => featAutoCollect, set: v => { featAutoCollect = v; } }, { id: 'ml-f-invincible', get: () => featInvincible, set: v => { featInvincible = v; } }, { id: 'ml-f-ghostmode', get: () => featGhostMode, set: v => { featGhostMode = v; if (!v) { _ghostActive = true; updateGhostEffect(); } } }, ]; featToggles.forEach(ft => { const el = $(ft.id); if (!el) return; el.addEventListener('click', () => { const nv = !ft.get(); ft.set(nv); el.classList.toggle('on', nv); saveSettings(); console.log(`[feat] ${ft.id.replace('ml-f-','')} = ${nv}`); }); }); $('ml-keybinds-body').addEventListener('click', e => { const row = e.target.closest('.ml-krow'); if (!row) return; $('ml-keybinds-body').querySelectorAll('.ml-krow.listening').forEach(r => r.classList.remove('listening')); if (kbListeningRow === row) { kbListeningRow = null; return; } row.classList.add('listening'); row.querySelector('.ml-krow-key').textContent = '...'; kbListeningRow = row; }); window.addEventListener('keydown', e => { if (!kbListeningRow) return; e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); const action = kbListeningRow.dataset.action; if (!action || !(action in KEYBINDS)) return; if (e.code === 'Escape') { kbListeningRow.classList.remove('listening'); kbListeningRow.querySelector('.ml-krow-key').textContent = keyCodeLabel(KEYBINDS[action]); kbListeningRow = null; return; } KEYBINDS[action] = e.code; kbListeningRow.querySelector('.ml-krow-key').textContent = keyCodeLabel(e.code); kbListeningRow.classList.remove('listening'); kbListeningRow = null; saveSettings(); updateHUDBadgeLabels(); console.log('[keybind] ' + action + ' → ' + e.code); }, true); function updateHUDBadgeLabels() { const map = { 'ml-fly': ['FLY', 'fly'], 'ml-spr': ['SPR', null], 'ml-home': ['SETHOME', 'setHome'], 'ml-go': ['HOME', 'home'], 'ml-back': ['BACK', 'back'], 'ml-tp': ['CUDDLE', 'cuddle'], 'ml-pets-btn': ['PETS', 'pets'], 'ml-snipe-btn': ['SNIPE', 'snipe'], 'ml-cfg': ['CFG', 'settings'], }; const nativeKeyMap = { 'ml-fly': 'fly', 'ml-spr': 'spr', 'ml-home': 'home', 'ml-go': 'go', 'ml-back': 'back', 'ml-tp': 'tp', 'ml-pets-btn': 'petsBtn', 'ml-snipe-btn': 'snipeBtn', 'ml-cfg': 'cfg' }; for (const [id, [label, action]] of Object.entries(map)) { if (_nativeHud) { const k = nativeKeyMap[id]; const kl = k && _nativeHud[k]?._native?.keyLbl; if (kl?.element) { kl.element.text = !action ? 'SH' : keyCodeLabel(KEYBINDS[action]); } } } } updateHUDBadgeLabels(); function toggleHelp(forceOpen) { const open = forceOpen !== undefined ? forceOpen : !d.classList.contains('open'); d.classList.toggle('open', open); if (open) { panelPause(); } else { d.querySelector('#ml-inner')._resetPos?.(); panelResume(); } } $('ml-help').addEventListener('click', () => { toggleHelp(); }); $('ml-close').addEventListener('click', () => toggleHelp(false)); d.addEventListener('click', e => { if (e.target === d) toggleHelp(false); }); d.addEventListener('wheel', e => { e.stopPropagation(); e.preventDefault(); d.scrollTop += e.deltaY; }, { passive: false }); document.addEventListener('click', e => { if (plist.classList.contains('open') && !plist.contains(e.target) && e.target.id !== 'ml-tp') { toggleCuddlePanel(false); } if (settings.classList.contains('open') && !settings.contains(e.target) && e.target.id !== 'ml-cfg') { toggleSettings(false); } if (petsPanel.classList.contains('open') && !petsPanel.contains(e.target) && e.target.id !== 'ml-pets-btn') { togglePetsPanel(false); } if (slotsPop.classList.contains('open') && !slotsPop.contains(e.target) && e.target.id !== 'ml-slots') { toggleSlots(false); } if (snipePanel.classList.contains('open') && !snipePanel.contains(e.target) && e.target.id !== 'ml-snipe-btn') { toggleSnipePanel(false); } }); } let _nativeHud = null; function createNativeHUD() { const app = W.pc?.app; const pc = W.pc; if (!app || !pc) return null; const roundedTex = app.assets.get(236692532); const fontAsset = app.assets.get(236690804); const gpm = app.root.findByName('GamePlayMenu'); if (!gpm || !roundedTex || !fontAsset) return null; const old = app.root.findByName('ML-HUD'); if (old) old.destroy(); const btnSize = 50, spacing = 56, rowGap = 68; const COL_NORM = [0.071, 0.071, 0.071]; const COL_ON = [0, 0.5, 1]; const COL_FRESH = [0, 0.66, 1]; const COL_DISABLED = [0.071, 0.071, 0.071]; const topDefs = [ ['fly', 'FLY', 'SPC', 'ml-fly'], ['spr', 'SPR', 'SH', 'ml-spr'], ['home', 'SET', 'Q', 'ml-home'], ['go', 'GO', '~', 'ml-go'], ['back', 'BCK', 'Z', 'ml-back'], ['slots','0/10', 'I', 'ml-slots'], ['lock', 'LCK', '', 'ml-lock'], ]; const botDefs = [ ['tp', 'CUD', 'J', 'ml-tp'], ['petsBtn', 'PET', 'K', 'ml-pets-btn'], ['snipeBtn','SNP', 'U', 'ml-snipe-btn'], ['cfg', 'CFG', 'M', 'ml-cfg'], ['help', '?', '/', 'ml-help'], ]; const mlGroup = new pc.Entity('ML-HUD'); mlGroup.addComponent('element', { type: 'group', anchor: [0,1,0,1], pivot: [0,1], width: 440, height: 200 }); mlGroup.setLocalPosition(10, -70, 0); mlGroup.enabled = false; function makeBtn(id, label, keyText, idx, yBase) { const btn = new pc.Entity('ML-' + id); btn.addComponent('element', { type: 'group', anchor: [0,1,0,1], pivot: [0,1], width: btnSize + 6, height: btnSize + 30 }); btn.setLocalPosition(idx * spacing, -yBase, 0); const bg = new pc.Entity('BG'); bg.addComponent('element', { type: 'image', anchor: [.5,.5,.5,.5], pivot: [.5,.5], width: btnSize, height: btnSize, color: new pc.Color(COL_NORM[0], COL_NORM[1], COL_NORM[2]), opacity: 1, textureAsset: roundedTex.id, useInput: true }); btn.addChild(bg); const fs = label.length > 3 ? 15 : (label.length > 2 ? 20 : label.length > 1 ? 24 : 30); const lbl = new pc.Entity('Label'); lbl.addComponent('element', { type: 'text', anchor: [.5,.5,.5,.5], pivot: [.5,.5], text: label, fontSize: fs, fontAsset: fontAsset.id, color: new pc.Color(1, 1, 1), outlineThickness: .3, outlineColor: new pc.Color(0, 0, 0), autoWidth: true, autoHeight: true }); bg.addChild(lbl); if (keyText) { const isLong = keyText.length > 2, isMed = keyText.length === 2; if (isLong || isMed) { const hg = isLong ? 6 : 3, rw = hg * 2 + 0.5; const dk = new pc.Entity('DesktopKey'); dk.addComponent('element', { type:'group', anchor:[.5,.5,.5,.5], pivot:[.5,.5], width:25, height:25 }); dk.setLocalPosition(17.5, -17.5, 0); bg.addChild(dk); [[-hg,25,25],[hg,25,25],[0,rw,25]].forEach(([x,w,h],j)=>{ const e = new pc.Entity('Image'); const c = { type:'image', anchor:[.5,.5,.5,.5], pivot:[.5,.5], width:w, height:h, color:new pc.Color(.388,.388,.388), opacity:1 }; if (j < 2) c.textureAsset = roundedTex.id; e.addComponent('element', c); if (x) e.setLocalPosition(x,0,0); dk.addChild(e); }); [[-hg,20,20],[hg,20,20],[0,rw,20]].forEach(([x,w,h],j)=>{ const e = new pc.Entity('Group'); const c = { type:'image', anchor:[.5,.5,.5,.5], pivot:[.5,.5], width:w, height:h, color:new pc.Color(1,1,1), opacity:1 }; if (j < 2) c.textureAsset = roundedTex.id; e.addComponent('element', c); if (x) e.setLocalPosition(x,0,0); dk.addChild(e); }); const kl = new pc.Entity('Text'); kl.addComponent('element', { type:'text', anchor:[.5,.5,.5,.5], pivot:[.5,.5], text:keyText, fontSize:15, fontAsset:fontAsset.id, color:new pc.Color(0,0,0), autoWidth:true, autoHeight:true }); kl.setLocalPosition(0, -0.3, 0); dk.addChild(kl); } else { const dk = new pc.Entity('DesktopKey'); dk.addComponent('element', { type:'image', anchor:[.5,.5,.5,.5], pivot:[.5,.5], width:25, height:25, color:new pc.Color(.388,.388,.388), opacity:1, textureAsset:roundedTex.id }); dk.setLocalPosition(17.5, -17.5, 0); bg.addChild(dk); const inner = new pc.Entity('Group'); inner.addComponent('element', { type:'image', anchor:[.5,.5,.5,.5], pivot:[.5,.5], width:20, height:20, color:new pc.Color(1,1,1), opacity:1, textureAsset:roundedTex.id }); dk.addChild(inner); const kl = new pc.Entity('Text'); kl.addComponent('element', { type:'text', anchor:[.5,.5,.5,.5], pivot:[.5,.5], text:keyText, fontSize:15, fontAsset:fontAsset.id, color:new pc.Color(0,0,0), autoWidth:true, autoHeight:true }); kl.setLocalPosition(0.6, 0, 0); dk.addChild(kl); } } mlGroup.addChild(btn); return { bg, lbl, btn, keyLbl: keyText ? btn.findByName('Text') : null }; } function makeProxy(parts, htmlId) { const st = {}; const setCol = (r, g, b) => { if (parts.bg.element) { parts.bg.element.color = new pc.Color(r, g, b); } }; const update = () => { if (st.disabled) { setCol(COL_DISABLED[0], COL_DISABLED[1], COL_DISABLED[2]); parts.bg.element.opacity = .45; parts.lbl.element.color = new pc.Color(1, .24, .24); } else if (st.fresh) { setCol(COL_FRESH[0], COL_FRESH[1], COL_FRESH[2]); parts.bg.element.opacity = 1; parts.lbl.element.color = new pc.Color(1, 1, 1); } else if (st.on) { setCol(COL_ON[0], COL_ON[1], COL_ON[2]); parts.bg.element.opacity = 1; parts.lbl.element.color = new pc.Color(1, 1, 1); } else { setCol(COL_NORM[0], COL_NORM[1], COL_NORM[2]); parts.bg.element.opacity = 1; parts.lbl.element.color = new pc.Color(1, 1, 1); } }; return { _native: parts, classList: { toggle(cls, force) { st[cls] = force; update(); }, add(cls) { st[cls] = true; update(); }, remove(cls) { delete st[cls]; update(); }, contains(cls) { return !!st[cls]; } }, set textContent(t) { const short = t.replace(/^SLOTS\s*/, '').replace(/^\u{1F512}\s*/u, '').replace(/^\u{1F513}\s*/u, ''); parts.lbl.element.text = short.length > 5 ? short.substring(0, 5) : short; }, get textContent() { return parts.lbl.element.text; }, addEventListener() {}, click() { const el = document.getElementById(htmlId); if (el) el.click(); } }; } const result = {}; topDefs.forEach(([key, label, keyText, htmlId], i) => { result[key] = makeProxy(makeBtn(key, label, keyText, i, 0), htmlId); }); botDefs.forEach(([key, label, keyText, htmlId], i) => { result[key] = makeProxy(makeBtn(key, label, keyText, i, rowGap), htmlId); }); const prevOverlay = document.getElementById('ml-click-overlay'); if (prevOverlay) prevOverlay.remove(); const clickOverlay = document.createElement('div'); clickOverlay.id = 'ml-click-overlay'; clickOverlay.style.cssText = 'position:fixed;inset:0;z-index:10;pointer-events:none'; document.body.appendChild(clickOverlay); const clickDivs = {}; for (const key of Object.keys(result)) { const div = document.createElement('div'); div.style.cssText = 'position:absolute;pointer-events:auto;cursor:pointer'; div.dataset.key = key; clickOverlay.appendChild(div); clickDivs[key] = div; } ['mousedown','mouseup','pointerdown','pointerup'].forEach(evt => { clickOverlay.addEventListener(evt, e => { if (e.target.dataset?.key) e.stopPropagation(); }); }); clickOverlay.addEventListener('touchstart', e => { if (e.target.dataset?.key) { e.stopPropagation(); e.preventDefault(); } }); clickOverlay.addEventListener('touchend', e => { const key = e.target.dataset?.key; if (key && result[key]) { e.stopPropagation(); e.preventDefault(); console.log('[ml] btn-touch ' + key); result[key].click(); } }); clickOverlay.addEventListener('click', e => { const key = e.target.dataset?.key; if (!key || !result[key]) return; console.log('[ml] btn-click ' + key); e.stopPropagation(); e.preventDefault(); result[key].click(); }); const btnLayout = {}; topDefs.forEach(([key], i) => { btnLayout[key] = { idx: i, yBase: 0 }; }); botDefs.forEach(([key], i) => { btnLayout[key] = { idx: i, yBase: rowGap }; }); let _syncDiag = false; function syncOverlay() { const canvas = app.graphicsDevice.canvas; const rect = canvas.getBoundingClientRect(); const cw = rect.width, ch = rect.height; const scr = mlGroup.parent?.screen; const refW = scr?.referenceResolution?.x || 1280; const refH = scr?.referenceResolution?.y || 720; const sx = cw / refW, sy = ch / refH; const blend = scr?.scaleBlend ?? 0.5; const scale = Math.pow(sx, 1 - blend) * Math.pow(sy, blend); const groupY = Math.abs(mlGroup.localPosition.y); const groupX = mlGroup.localPosition.x; const visible = mlGroup.enabled; for (const key of Object.keys(result)) { const lay = btnLayout[key]; if (!lay) continue; const bgLeft = groupX + lay.idx * spacing + 3; const bgTop = groupY + lay.yBase + 15; const div = clickDivs[key]; div.style.left = (rect.left + bgLeft * scale) + 'px'; div.style.top = (rect.top + bgTop * scale) + 'px'; div.style.width = (btnSize * scale) + 'px'; div.style.height = (btnSize * scale) + 'px'; div.style.display = visible ? 'block' : 'none'; } if (!_syncDiag && visible) { _syncDiag = true; console.log('[ml] overlay-sync scale=' + scale.toFixed(3) + ' groupXY=' + groupX + ',' + groupY + ' canvas=' + cw.toFixed(0) + 'x' + ch.toFixed(0) + ' buttons=' + Object.keys(btnLayout).join(',')); } requestAnimationFrame(syncOverlay); } const overlay = gpm.parent; overlay.addChild(mlGroup); syncOverlay(); const chatEntity = gpm.findByName('Chat'); if (chatEntity) { const chatY = -(Math.abs(mlGroup.localPosition.y) + rowGap + btnSize + 12); chatEntity.setLocalPosition(chatEntity.localPosition.x, chatY, 0); console.log('[ml] chat repositioned to y=' + chatY); } function setPauseLayout() { mlGroup.setLocalPosition(10, -115, 0); } function setGameplayLayout() { mlGroup.setLocalPosition(10, -70, 0); } const pauseEntity = overlay.findByName('Pause'); if (pauseEntity) { const origDesc = Object.getOwnPropertyDescriptor(pc.GraphNode.prototype, 'enabled'); if (origDesc?.set) { Object.defineProperty(pauseEntity, 'enabled', { get() { return origDesc.get.call(this); }, set(v) { origDesc.set.call(this, v); if (v) setPauseLayout(); else setGameplayLayout(); }, configurable: true }); } } const loadingEntity = overlay.findByName('LoadingScreen'); if (loadingEntity) { const origDesc = Object.getOwnPropertyDescriptor(pc.GraphNode.prototype, 'enabled'); if (origDesc?.set) { Object.defineProperty(loadingEntity, 'enabled', { get() { return origDesc.get.call(this); }, set(v) { origDesc.set.call(this, v); mlGroup.enabled = !v; const mf = $('ml-mobile-fly'); if (mf) mf.style.display = v ? 'none' : 'flex'; }, configurable: true }); mlGroup.enabled = !loadingEntity.enabled; const mfInit = $('ml-mobile-fly'); if (mfInit) mfInit.style.display = loadingEntity.enabled ? 'none' : 'flex'; } else { mlGroup.enabled = true; const mfOrig = $('ml-mobile-fly'); if (mfOrig) mfOrig.style.display = 'flex'; } } else { mlGroup.enabled = true; const mfFallback = $('ml-mobile-fly'); if (mfFallback) mfFallback.style.display = 'flex'; } console.log('[ml] native PlayCanvas HUD created'); return result; } function getApiManager() { const root = W.pc?.app?.root; const scripts = root?.findComponents('script') || []; for (const s of scripts) { for (const name of Object.keys(s)) { const inst = s[name]; if (inst?.freeCurrency && inst?.balance !== undefined) return inst; } } return null; } let freeMoneyDone = false; async function autoFarmFreeMoney() { if (freeMoneyDone || !featFreeMoney) return; const api = getApiManager(); if (!api) return; const nm = W.pc?.app?.root?.findByName('NetworkManager')?.script?.networkManager; if (!nm?.room?.sessionId) return; freeMoneyDone = true; const remaining = (api.freeCurrencyAdLimit || 10) - (api.freeCurrencyAdCounter || 0); if (remaining <= 0) { console.log('[ml] free money: daily limit already reached'); return; } let total = 0, calls = 0; for (let i = 0; i < remaining; i++) { const before = api.balance; api.freeCurrency(); await new Promise(r => setTimeout(r, 1500)); const gained = api.balance - before; if (gained <= 0) break; total += gained; calls++; } console.log('[ml] free money: +' + total + ' coins (' + calls + ' calls, balance: ' + api.balance + ')'); } let lastAutoCollect = 0; let _mlBatchCollecting = false; let _mlBatchTotal = 0; let _mlBatchCount = 0; let _mlBatchTimer = null; let _mlCachedBalance = null; function findPetOverlay() { const app = W.pc?.app; if (!app) return null; let overlay = null; app.root.find(e => { if (!e.script) return false; for (const k of Object.keys(e.script)) { const s = e.script[k]; if (s?.coinContainer && s?.onCoinAnimation) { overlay = s; return true; } } return false; }); return overlay; } function flushBatch() { if (!_mlBatchCollecting) return; _mlBatchCollecting = false; clearTimeout(_mlBatchTimer); if (_mlBatchTotal !== 0) { console.log('[ml] auto-collect: batched ' + _mlBatchCount + ' notifications → +$' + _mlBatchTotal); const overlay = findPetOverlay(); const app = W.pc?.app; if (overlay) { for (let i = 0; i < 3; i++) { setTimeout(() => overlay.onCoinAnimation(5), i * 200); } } if (_mlCachedBalance !== null && app?._mlOrigFire) { const bal = _mlCachedBalance; _mlCachedBalance = null; setTimeout(() => { app._mlOrigFire.call(app, 'ModeOverlay:Balance', bal); }, 1500); } } else if (_mlCachedBalance !== null) { const app = W.pc?.app; if (app?._mlOrigFire) { app._mlOrigFire.call(app, 'ModeOverlay:Balance', _mlCachedBalance); } _mlCachedBalance = null; } _mlBatchTotal = 0; _mlBatchCount = 0; } function autoCollectPetEarnings() { if (!featAutoCollect) return; const now = Date.now(); if (now - lastAutoCollect < autoCollectInterval * 1000) return; lastAutoCollect = now; const app = W.pc?.app; if (!app) return; const root = app.root; if (!app._mlNotifBatched) { app._mlNotifBatched = true; const origFire = app.fire; app._mlOrigFire = origFire; app.fire = function() { if (_mlBatchCollecting) { if (arguments[0] === 'ModeOverlay:BalanceChange') { const amt = arguments[1]; _mlBatchTotal += (typeof amt === 'number' ? amt : 0); _mlBatchCount++; clearTimeout(_mlBatchTimer); _mlBatchTimer = setTimeout(flushBatch, 2000); return app; } if (arguments[0] === 'ModeOverlay:Balance') { _mlCachedBalance = arguments[1]; return app; } } return origFire.apply(this, arguments); }; } let pm = null; const pmEntity = root.findByName('PetsManager'); if (pmEntity?.script) { for (const k of Object.keys(pmEntity.script)) { const s = pmEntity.script[k]; if (s?.basePets) { pm = s; break; } } } if (!pm) { root.find(e => { if (!e.script) return false; for (const k of Object.keys(e.script)) { const s = e.script[k]; if (s?.basePets) { pm = s; return true; } } return false; }); } if (!pm?.basePets || pm.basePets.size === 0) return; const nm = root.findByName('NetworkManager')?.script?.networkManager; if (!nm?.room?.sessionId) return; const myId = nm.room.sessionId; _mlBatchCollecting = true; _mlBatchTotal = 0; _mlBatchCount = 0; clearTimeout(_mlBatchTimer); let claimed = 0; pm.basePets.forEach((pet, token) => { if (String(pet.owner) === String(myId)) { app.fire('NetworkManager:Send', 'claimPetBalance', token); claimed++; } }); if (claimed > 0) { console.log('[ml] auto-collect: claimed ' + claimed + ' pets'); _mlBatchTimer = setTimeout(flushBatch, 5000); } else { _mlBatchCollecting = false; } } const petSpawnData = new Map(); const PET_SPAWN_CAP = 2000; function hookPetSpawn() { const app = W.pc?.app; if (!app) return; if (app._mlPetSpawnHooked) return; app._mlPetSpawnHooked = true; const onPetsSpawn = data => { const items = Array.isArray(data) ? data : (data && typeof data === 'object' ? Object.values(data) : []); if (!items.length) return; if (petSpawnData.size > PET_SPAWN_CAP) { const excess = petSpawnData.size - PET_SPAWN_CAP + items.length; const it = petSpawnData.keys(); for (let i = 0; i < excess; i++) petSpawnData.delete(it.next().value); } for (const p of items) { if (!p.token) continue; petSpawnData.set(p.token, { profit: p.profit ?? null, rarity: p.rarity ?? null, mutation: p.mutation ?? null, isEgg: !!p.isEgg, }); } }; app.on('PetsManager:PetsSpawn', onPetsSpawn); app.on('BasesManager:PetsSpawn', onPetsSpawn); console.log('[ml] pet spawn hook installed'); } function getMyBase() { const basesScript = _getBasesManager(); if (!basesScript?.activeBases) return null; const nm = _getNetworkManager(); const sessionId = nm?.room?.sessionId || W.pc?.sessionId; if (!sessionId) return null; for (const bd of basesScript.activeBases) { if (bd?.data?.sessionId === sessionId) return basesScript.baseEntities?.[bd.data.id] ?? null; } return null; } function getLockBtn() { const base = getMyBase(); if (!base) return null; const btn = base.findByName('LockdownButton'); return btn?.script?.lockdownButton ?? null; } let _lastLockTriggerLog = 0; function triggerLock() { const btn = getLockBtn(); if (!btn || typeof btn.onTriggerEnter !== 'function') return false; const player = getPlayer(); if (!player) return false; btn.onTriggerEnter(player); const now = Date.now(); if (now - _lastLockTriggerLog > 10000) { _lastLockTriggerLog = now; console.log('[ml] auto-lock: triggered'); } return true; } let lastLockCheck = 0; let _wallsDisabled = false; function disableBaseWalls() { if (_wallsDisabled) return; const bm = _getBasesManager(); if (!bm?.activeBases) return; let count = 0; for (const bd of bm.activeBases) { if (!bd?.entity) continue; bd.entity.forEach(child => { if (!child.collision?.enabled || child.rigidbody?.type !== 'static') return; const he = child.collision.halfExtents; if (!he) return; const isVertical = he.y > 0.3 && (he.x < 1.0 || he.z < 1.0); const isWall = child.name === 'Wall' || child.name === 'collision'; const isFence = child.name === 'New Entity' && he.y > 0.3; if (isVertical || isWall || isFence) { child.collision.enabled = false; child.rigidbody.enabled = false; count++; } }); } if (count > 0) { _wallsDisabled = true; console.log('[ml] barriers: disabled ' + count); } } function hookAntiDisconnect() { const nm = W.pc?.app?.root?.findByName('NetworkManager')?.script?.networkManager; const room = nm?.room; if (!room) return; if (room.__mlSendHooked) return; room.__mlSendHooked = true; const origSend = room.send.bind(room); room.__mlOrigSend = origSend; const HEIGHT_OFFSET = 200; let _currentOffset = 0; let _wasHolding = false; room.send = function (type, message) { if (type === 'p' && message && featGhostMode) { if (_wavesGhostPos) { return origSend(type, { x: _wavesGhostPos.x, y: _wavesGhostPos.y, z: _wavesGhostPos.z, w: message.w }); } const pt = _getPetTycoon(); const holding = !!pt?.isHoldingPet; if (holding) { _currentOffset = HEIGHT_OFFSET; _wasHolding = true; } else if (_wasHolding && _currentOffset > 0) { _currentOffset = Math.max(0, _currentOffset - 10); if (_currentOffset === 0) _wasHolding = false; } if (_currentOffset > 0) { return origSend(type, { x: message.x, y: message.y + _currentOffset, z: message.z, w: message.w }); } } return origSend(type, message); }; console.log('[ml] ghost position hook installed'); _ptCache = null; _etCache = null; _nmCache = null; _bmCache = null; _blmCache = null; _wallsDisabled = false; _pendingBaseCapture = true; if (featAntiKnockback) { room.onMessage('gotAttacked', () => {}); } room.onMessage('petClaimed', msg => { if (msg.stealerSessionId === room.sessionId) { _snipeCooldown = Date.now() + 10000; console.log('[ml] pet claimed — 10s snipe cooldown'); } }); if (typeof room.onLeave === 'function') { room.onLeave((code) => { console.log('[ml] room closed code=' + code); }); } } let _ghostActive = false; let _wavesGhostPos = null; const GHOST_OPACITY = 0.25; function _getCharMeshInstances() { const player = getPlayer(); const ch = player?.findByName('CharacterHolder'); if (!ch) return []; const result = []; ch.forEach(child => { const mis = child.render?.meshInstances || child.model?.meshInstances || []; for (const mi of mis) if (mi.material) result.push(mi); }); return result; } function updateGhostEffect() { const pt = _getPetTycoon(); const shouldGhost = featGhostMode && (!!pt?.isHoldingPet || !!_wavesGhostPos); if (shouldGhost === _ghostActive) return; const mis = _getCharMeshInstances(); if (!mis.length) return; for (const mi of mis) { if (shouldGhost) { if (!mi.__mlGhostCloned) { mi.material = mi.material.clone(); mi.__mlGhostCloned = true; } mi.material.blendType = W.pc.BLEND_NORMAL; mi.material.opacity = GHOST_OPACITY; mi.material.depthWrite = false; } else { mi.material.blendType = W.pc.BLEND_NONE; mi.material.opacity = 1.0; mi.material.depthWrite = true; } mi.material.update(); } _ghostActive = shouldGhost; console.log('[ml] ghost:', shouldGhost ? 'faded (holding pet)' : 'restored'); } let antiDeathReady = false; function hookAntiDeath() { if (antiDeathReady) return; const app = W.pc?.app; if (!app) return; app.root.find(entity => { if (!entity.script?._scripts) return false; for (const inst of entity.script._scripts) { if (inst && typeof inst.deathYThreshold === 'number' && inst.deathYThreshold > -9999) { inst.deathYThreshold = -99999; console.log('[ml] anti-death: Y threshold → -99999 on %s', entity.name); } } return false; }); const origFire = app.fire; app.fire = function (event, ...args) { if (event === 'DeathScreen:Trigger' && featInvincible) return this; if (event === 'PlayerController:GotHit' && featAntiKnockback) return this; return origFire.call(this, event, ...args); }; antiDeathReady = true; console.log('[ml] anti-death: ready'); } let antiKnockbackReady = false; function hookAntiKnockback() { if (antiKnockbackReady || !featAntiKnockback) return; const player = getPlayer(); const pc = getPC(player); if (!pc) return; pc.shockedTime = 0; pc.knockbackDecay = 1.0; antiKnockbackReady = true; } let noclipHooked = false; function hookNoclip() { if (noclipHooked) return; const player = getPlayer(); const kcc = getKcc(player); if (!kcc || !kcc.update) return; const origUpdate = kcc.update.bind(kcc); kcc.update = function (dt) { if (!featNoclip) return origUpdate(dt); const pos = this.entity.getPosition(); const preX = pos.x, preZ = pos.z; origUpdate(dt); const speed = this.speed || 7; const h = this._horizontal || 0, v = this._vertical || 0; const newPos = this.entity.getPosition(); this.entity.setPosition(preX + h * speed * dt, newPos.y, preZ + v * speed * dt); }; noclipHooked = true; console.log('[ml] noclip: KCC update hooked'); } let netSpyHooked = false; function hookNetSpy() { if (netSpyHooked) return; const nm = _getNetworkManager(); if (!nm?.room) return; netSpyHooked = true; const NOISY = new Set(['positions', 'animSetBooleans', 'animSetTrigger']); const origOnMessage = nm.room.onMessage.bind(nm.room); nm.room.onMessage = function (type, cb) { return origOnMessage(type, function (...args) { if (!NOISY.has(type)) { console.log('[ml] NET ←', type, args.length === 1 ? args[0] : args); } return cb(...args); }); }; const prevSend = nm.room.send; nm.room.send = function (type, message) { if (type !== 'p' && !NOISY.has(type)) { console.log('[ml] NET →', type, message); } return prevSend.call(this, type, message); }; console.log('[ml] net-spy: active'); } createHUD(); loadWaypoints(); if (isMobile) { const mfc = document.createElement('div'); mfc.id = 'ml-mobile-fly'; mfc.innerHTML = ''; const mfcStyle = document.createElement('style'); mfcStyle.textContent = [ '#ml-mobile-fly{position:fixed;right:2.5vmin;bottom:3vmin;z-index:15;display:none;flex-direction:column;align-items:flex-end;gap:clamp(6px,1.5vmin,12px);pointer-events:none}', '.ml-mfly{pointer-events:auto;width:clamp(52px,12vmin,80px);height:clamp(52px,12vmin,80px);border-radius:50%;border:2px solid rgba(200,170,255,.35);background:rgba(55,45,80,.55);color:rgba(255,250,255,.85);font-size:clamp(14px,3.5vmin,22px);font-weight:700;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;cursor:pointer;user-select:none;-webkit-user-select:none;touch-action:none;display:flex;align-items:center;justify-content:center;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);transition:background .12s,border-color .12s,transform .08s}', '.ml-mfly:active{transform:scale(.92);background:rgba(140,100,220,.4);border-color:rgba(200,170,255,.6)}', '.ml-mfly.on{background:rgba(100,180,100,.4);border-color:rgba(140,230,140,.5)}', '.ml-mcollapse{width:clamp(36px,8vmin,52px);height:clamp(36px,8vmin,52px);font-size:clamp(16px,4vmin,24px);border-color:rgba(180,180,200,.3);background:rgba(40,40,55,.55)}', '.ml-mcollapse:active{background:rgba(100,100,140,.4)}', '#ml-mobile-fly.collapsed .ml-mfly:not(.ml-mcollapse){display:none}', '.ml-msprint-btn{border-color:rgba(255,180,60,.35);background:rgba(80,55,30,.55);font-size:clamp(11px,2.8vmin,16px)}', '.ml-msprint-btn:active{background:rgba(220,160,40,.4);border-color:rgba(255,200,80,.6)}', '.ml-msprint-btn.on{background:rgba(220,160,40,.4);border-color:rgba(255,200,80,.5)}', ].join(''); document.head.appendChild(mfcStyle); document.body.appendChild(mfc); const mflyToggle = $('ml-mfly-toggle'); const mflyUp = $('ml-mfly-up'); const mflyDown = $('ml-mfly-down'); const msprint = $('ml-msprint'); const mCollapse = $('ml-mfly-collapse'); let _collapseLock = false; const toggleCollapse = () => { if (_collapseLock) return; _collapseLock = true; setTimeout(() => _collapseLock = false, 200); const collapsed = mfc.classList.toggle('collapsed'); mCollapse.textContent = collapsed ? '⊞' : '⊟'; }; mCollapse.addEventListener('touchstart', e => { e.preventDefault(); toggleCollapse(); }); mCollapse.addEventListener('click', toggleCollapse); mflyToggle.addEventListener('touchstart', e => { e.preventDefault(); if (!featFly) return; const p = getPlayer(), k = getKcc(p); if (!k) return; if (flyActive) { flyOff(k); mflyToggle.classList.remove('on'); } else { flyOn(k, true); mflyToggle.classList.add('on'); } }); msprint.addEventListener('touchstart', e => { e.preventDefault(); if (!featSprint) return; sprinting = !sprinting; msprint.classList.toggle('on', sprinting); }); mflyUp.addEventListener('touchstart', e => { e.preventDefault(); if (!featFly || !flyActive) return; flyUp = true; }); mflyUp.addEventListener('touchend', e => { e.preventDefault(); flyUp = false; }); mflyUp.addEventListener('touchcancel', () => { flyUp = false; }); mflyDown.addEventListener('touchstart', e => { e.preventDefault(); if (!featFly || !flyActive) return; flyDown = true; }); mflyDown.addEventListener('touchend', e => { e.preventDefault(); flyDown = false; }); mflyDown.addEventListener('touchcancel', () => { flyDown = false; }); } let _flyClickTime = 0; $('ml-fly').addEventListener('click', () => { if (!featFly || isMobile) return; const now = Date.now(); if (now - _flyClickTime < 300) return; _flyClickTime = now; const p = getPlayer(), k = getKcc(p); if (!k) return; if (flyActive) flyOff(k); else flyOn(k, true); }); $('ml-spr').addEventListener('click', () => { if (!featSprint) return; sprinting = !sprinting; }); $('ml-home').addEventListener('click', () => { if (!featWaypoints) return; const p = getPlayer(); if (!p) return; homePos = capturePos(p); saveWaypoints(); flash('ml-home'); console.log('[ml] home set via click'); }); $('ml-go').addEventListener('click', () => { if (!featWaypoints || !homePos) return; const p = getPlayer(); if (!p) return; backPos = capturePos(p); teleport(p, homePos); saveWaypoints(); flash('ml-go'); }); $('ml-back').addEventListener('click', () => { if (!featWaypoints || !backPos) return; const p = getPlayer(); if (!p) return; const cur = capturePos(p); teleport(p, backPos); backPos = cur; saveWaypoints(); flash('ml-back'); }); $('ml-lock').addEventListener('click', () => { if (!featAutoLock) return; triggerLock(); flash('ml-lock'); }); function toggleSlots(forceOpen) { if (!featWaypoints) return; const pop = $('ml-slots-pop'); if (!pop) return; const open = forceOpen !== undefined ? forceOpen : !pop.classList.contains('open'); pop.classList.toggle('open', open); if (open) { pop.dispatchEvent(new CustomEvent('ml-rebuild')); panelPause(); } else { pop._resetPos?.(); panelResume(); } } $('ml-slots').addEventListener('click', () => { toggleSlots(); }); window.addEventListener('keydown', e => { const openPanel = $('ml-pets')?.classList.contains('open') ? 'pets' : $('ml-settings')?.classList.contains('open') ? 'settings' : $('ml-plist')?.classList.contains('open') ? 'plist' : $('ml-dialog')?.classList.contains('open') ? 'dialog' : $('ml-slots-pop')?.classList.contains('open') ? 'slots' : null; if (openPanel) { if (e.code === 'Escape') { e.stopPropagation(); e.preventDefault(); if (openPanel === 'pets') $('ml-pets-close')?.click(); else if (openPanel === 'settings') $('ml-settings-close')?.click(); else if (openPanel === 'plist') $('ml-plist-close')?.click(); else if (openPanel === 'dialog') $('ml-close')?.click(); else if (openPanel === 'slots') $('ml-slots-pop-close')?.click(); return; } const active = document.activeElement; if (active?.tagName === 'INPUT' || active?.tagName === 'TEXTAREA') { e.stopPropagation(); return; } e.stopPropagation(); e.preventDefault(); return; } const active = document.activeElement; if (active?.tagName === 'INPUT' || active?.tagName === 'TEXTAREA') return; if (kbListeningRow) return; if (e.code === KEYBINDS.cuddle) { e.preventDefault(); e.stopPropagation(); if (featCuddle) $('ml-tp')?.click(); return; } if (e.code === KEYBINDS.settings) { e.preventDefault(); e.stopPropagation(); $('ml-cfg')?.click(); return; } if (e.code === KEYBINDS.pets) { e.preventDefault(); e.stopPropagation(); if (featPets) $('ml-pets-btn')?.click(); return; } if (e.code === KEYBINDS.snipe) { e.preventDefault(); e.stopPropagation(); $('ml-snipe-btn')?.click(); return; } if (e.code === KEYBINDS.slots) { e.preventDefault(); e.stopPropagation(); $('ml-slots')?.click(); return; } if (e.code === KEYBINDS.help) { e.preventDefault(); e.stopPropagation(); $('ml-help')?.click(); return; } const player = getPlayer(); const kcc = getKcc(player); if (!kcc) return; if (cuddling && MOVE_KEYS.has(e.code)) { cuddling = false; cuddleTarget = null; console.log('[cuddle] cancelled'); } const numpadMatch = e.code.match(/^Numpad(\d)$/); let slotIdx = numpadMatch ? parseInt(numpadMatch[1]) : -1; if (slotIdx < 0 && e.location === 3) { const alt = { Insert: 0, End: 1, ArrowDown: 2, PageDown: 3, ArrowLeft: 4, Clear: 5, ArrowRight: 6, Home: 7, ArrowUp: 8, PageUp: 9 }; slotIdx = alt[e.key] ?? -1; } if (slotIdx >= 0 && featWaypoints) { const idx = slotIdx; if (e.ctrlKey) { e.preventDefault(); e.stopPropagation(); slots[idx] = capturePos(player); saveWaypoints(); flash('ml-slots'); console.log(`[slot ${idx}] saved`, slots[idx]); return; } else if (slots[idx]) { e.preventDefault(); e.stopPropagation(); backPos = capturePos(player); teleport(player, slots[idx]); saveWaypoints(); flash('ml-slots'); console.log(`[slot ${idx}] teleported to`, slots[idx]); return; } } if (e.code === KEYBINDS.fly) { if (!featFly) return; e.stopPropagation(); if (flyActive) { flyUp = true; } else { flyOn(kcc); } return; } if (e.code === KEYBINDS.flyDown && flyActive) { flyDown = true; return; } if (e.key === 'Shift' && !sprinting && featSprint) { sprinting = true; return; } if (e.code === KEYBINDS.setHome) { e.preventDefault(); if (!featWaypoints) return; homePos = capturePos(player); saveWaypoints(); flash('ml-home'); return; } if (e.code === KEYBINDS.home) { e.preventDefault(); if (!featWaypoints) return; if (homePos) { backPos = capturePos(player); teleport(player, homePos); saveWaypoints(); flash('ml-go'); } return; } if (e.code === KEYBINDS.back) { e.preventDefault(); if (!featWaypoints) return; if (backPos) { const cur = capturePos(player); teleport(player, backPos); backPos = cur; saveWaypoints(); flash('ml-back'); } } }, true); window.addEventListener('keyup', e => { if (anyPanelOpen()) { e.stopPropagation(); return; } if (e.code === KEYBINDS.fly) flyUp = false; if (e.code === KEYBINDS.flyDown) flyDown = false; if (e.key === 'Shift' && sprinting) { sprinting = false; } }, true); const _htmlHud = { fly: $('ml-fly'), spr: $('ml-spr'), home: $('ml-home'), go: $('ml-go'), back: $('ml-back'), slots: $('ml-slots'), lock: $('ml-lock'), tp: $('ml-tp'), petsBtn: $('ml-pets-btn'), snipeBtn: $('ml-snipe-btn'), cfg: $('ml-cfg'), help: $('ml-help') }; _nativeHud = createNativeHUD(); if (!_nativeHud) { const retryId = setInterval(() => { _nativeHud = createNativeHUD(); if (_nativeHud) { clearInterval(retryId); Object.assign(hud, _nativeHud); console.log('[ml] native HUD loaded (deferred)'); } }, 500); } const hud = _nativeHud || _htmlHud; const panels = { plist: $('ml-plist'), settings: $('ml-settings'), dialog: $('ml-dialog'), pets: $('ml-pets'), snipe: $('ml-snipe') }; setInterval(() => { hookPetSpawn(); hookAntiDisconnect(); hookAntiDeath(); hookAntiKnockback(); hookNoclip(); disableBaseWalls(); updateGhostEffect(); hookNetSpy(); if (!freeMoneyDone && featFreeMoney) autoFarmFreeMoney(); autoCollectPetEarnings(); const ct = $('ml-carry-timer'); if (ct) { const pt = _getPetTycoon(); const holding = !!(pt?.isHoldingPet); const isSteal = !!_getBasesManager()?.activeBases; if (holding && isSteal) { if (!ct._start) ct._start = Date.now(); ct.style.display = ''; ct.textContent = '\u23F1 ' + ((Date.now() - ct._start) / 1000).toFixed(1) + 's'; } else { if (ct._start) ct._start = 0; ct.style.display = 'none'; } } const player = getPlayer(); if (!player) return; if (_pendingBaseCapture) { const myBase = getMyBase(); if (myBase) { const bp = myBase.getPosition(); backPos = { x: bp.x, y: bp.y, z: bp.z }; _pendingBaseCapture = false; console.log('[ml] backPos set to home base:', bp.x.toFixed(1), bp.y.toFixed(1), bp.z.toFixed(1)); } } const kcc = getKcc(player); if (!kcc) return; const now = Date.now(); const dt = Math.min((now - prevTick) / 1000, 0.1); prevTick = now; const pc = getPC(player); if (pc?.isDied) { pc.isDied = false; } if (sprinting && !isMobile) { const kb = W.pc?.app?.keyboard; if (kb && !kb.isPressed(W.pc.KEY_SHIFT)) { sprinting = false; } } if (sprinting) { const sprintMin = SPEED_DEFAULT * 3; if (sprintSpeed < sprintMin) sprintSpeed = sprintMin; if (accelEnabled) sprintSpeed = Math.min(sprintSpeed + ACCEL * dt, SPEED_CAP); setSpeed(pc, kcc, sprintSpeed); if (pc?.isSlowedSpeed) pc.isSlowedSpeed = false; } else if (sprintSpeed !== SPEED_DEFAULT) { sprintSpeed = SPEED_DEFAULT; setSpeed(pc, kcc, SPEED_DEFAULT); } if (hud.fly) { hud.fly.classList.toggle('on', flyActive); hud.fly.classList.toggle('disabled', !featFly); } const mft = $('ml-mfly-toggle'); if (mft) mft.classList.toggle('on', flyActive); if (hud.spr) { hud.spr.classList.toggle('on', sprinting); hud.spr.classList.toggle('disabled', !featSprint); } const msp = $('ml-msprint'); if (msp) msp.classList.toggle('on', sprinting); if (hud.home) hud.home.classList.toggle('disabled', !featWaypoints); if (hud.go) hud.go.classList.toggle('disabled', !featWaypoints); if (hud.back) hud.back.classList.toggle('disabled', !featWaypoints); if (hud.slots) { const n = slots.filter(Boolean).length; hud.slots.textContent = `SLOTS ${n}/10`; hud.slots.classList.toggle('disabled', !featWaypoints); } if (hud.tp) { hud.tp.classList.toggle('disabled', !featCuddle); hud.tp.classList.toggle('on', !!panels.plist?.classList.contains('open')); } if (hud.petsBtn) { hud.petsBtn.classList.toggle('disabled', !featPets); hud.petsBtn.classList.toggle('on', !!panels.pets?.classList.contains('open')); } if (hud.snipeBtn) { hud.snipeBtn.classList.toggle('on', snipeActive || !!panels.snipe?.classList.contains('open')); } if (hud.cfg) hud.cfg.classList.toggle('on', !!panels.settings?.classList.contains('open')); if (hud.help) hud.help.classList.toggle('on', !!panels.dialog?.classList.contains('open')); if (featAutoLock && now - lastLockCheck > 100) { lastLockCheck = now; const lockBtn = getLockBtn(); if (lockBtn) { const timeLeft = lockBtn.lockdownTimeLeft || 0; const isActive = lockBtn.isLockdownActive || false; if (hud.lock) { hud.lock.classList.toggle('on', isActive && timeLeft > 0); hud.lock.textContent = (isActive && timeLeft > 0) ? `\ud83d\udd12 ${Math.ceil(timeLeft)}s` : '\ud83d\udd13 UNLOCKED'; } if (!isActive || timeLeft <= 0) triggerLock(); } else if (hud.lock) { hud.lock.textContent = '\ud83d\udd12 LOCK'; hud.lock.classList.remove('on'); } } if (hud.lock) hud.lock.classList.toggle('disabled', !featAutoLock); if (cuddling && cuddleTarget && featCuddleFollow) { if (kcc._horizontal || kcc._vertical) { cuddling = false; cuddleTarget = null; console.log('[cuddle] cancelled (movement input)'); } else { const tPos = cuddleTarget.getPosition?.(); if (tPos) { kcc.gravity = 0; kcc._velY = 0; teleport(player, vec3(tPos)); } else { cuddling = false; cuddleTarget = null; console.log('[cuddle] target lost'); } } } if (!flyActive) return; if (kcc._grounded && Date.now() - _flyStartTime > 500) { flyOff(kcc, false); return; } if (kcc.gravity !== 0) kcc.gravity = 0; flyVelY = kcc._velY; const flySpeedCap = sprinting ? sprintSpeed : SPEED_CAP; if (flyUp) { if (flyVelY < 0) { flyVelY = 0; } else if (accelEnabled) { if (flyVelY < FLY_MIN_SPEED) flyVelY = FLY_MIN_SPEED; flyVelY = Math.min(flyVelY + ACCEL * dt, flySpeedCap); } else { flyVelY = flySpeedCap; } } else if (flyDown) { if (flyVelY > 0) { flyVelY = 0; } else if (accelEnabled) { if (flyVelY > -FLY_MIN_SPEED) flyVelY = -FLY_MIN_SPEED; flyVelY = Math.max(flyVelY - ACCEL * dt, -flySpeedCap); } else { flyVelY = -flySpeedCap; } } else { flyVelY = 0; } kcc._velY = flyVelY; }, 16); })();