Greasy Fork 还支持 简体中文。

Clap mod

Public mod for MooMoo.io

目前為 2025-03-17 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Clap mod
  3. // @namespace Good Guy
  4. // @version v1
  5. // @description Public mod for MooMoo.io
  6. // @match http*://*.moomoo.io/*
  7. // @icon https://www.google.com/s2/favicons?sz=64&domain=moomoo.io
  8. // @require https://update.greasyfork.org/scripts/423602/1005014/msgpack.js
  9. // @license MIT
  10. // @grant none
  11. // ==/UserScript==
  12. /** VARIABLES **/
  13. document.getElementById("gameName").innerHTML = "Clap mod";
  14. let spike = 0;
  15. let weapongrind = false;
  16. let { msgpack, config, jQuery: $ } = window;
  17. let leaderboard = document.getElementById('leaderboard')
  18. let gameCanvas = document.getElementById("gameCanvas");
  19. let mainContext = gameCanvas.getContext("2d");
  20. let storeMenu = document.getElementById("storeMenu");
  21. let allianceMenu = document.getElementById("allianceMenu");
  22. let chatHolder = document.getElementById("chatHolder");
  23. let altchaCheckbox = document.getElementById('altcha_checkbox');
  24. let altcha = document.getElementById('altcha');
  25. let menuOpened = false;
  26. let mouseX, mouseY, width = innerWidth, height = innerHeight;
  27. let moveKeys = { w: false, a: false, s: false, d: false };
  28. let myPlayer = {
  29. id: null, x: null, y: null, dir: null, object: null, weapon: null, clan: null,
  30. isLeader: null, maxXP: 300, XP: 0, age: 1, hat: null, accessory: null, isSkull: null, maxHealth: 100
  31. };
  32. let locked = false, gameTick = 0, enemy = [], ws = null;
  33. let tPing = 90;
  34. let players = [], nearestEnemy = {}, enemyAngle, isEnemyNear;
  35. let primary, secondary, foodType, wallType, spikeType, millType, mineType, boostType, spawnpadType, turretType, haveMine;
  36. let SaVeGe = {
  37. tick: 0,
  38. tickQueue: [],
  39. manage: [],
  40. tickRate: 1000 / 9,
  41. tickSpeed: 0,
  42. lastTick: performance.now(),
  43. tickBase(set, tick) {
  44. const targetTick = this.tick + tick;
  45. this.tickQueue[targetTick] = this.tickQueue[targetTick] ?? [];
  46. this.tickQueue[targetTick].push(set);
  47. }
  48. };
  49.  
  50. /** SOCKET **/
  51. WebSocket.prototype.oldSend = WebSocket.prototype.send;
  52. WebSocket.prototype.send = function (m) {
  53. if (!ws) {
  54. document.websocket = this;
  55. ws = this;
  56. socketFound(this);
  57. }
  58. this.oldSend(m);
  59. };
  60.  
  61. /** FPS BOOSTER **/
  62. let { maxScreenWidth, maxScreenHeight } = config;
  63. let FPSBooster;
  64. let { moveTo, lineTo } = CanvasRenderingContext2D.prototype;
  65.  
  66. CanvasRenderingContext2D.prototype.moveTo = function(x, y) {
  67. if (!FPSBooster || this.globalAlpha !== 0.06) {
  68. return moveTo.call(this, x, y);
  69. }
  70. };
  71. CanvasRenderingContext2D.prototype.lineTo = function(x, y) {
  72. if (!FPSBooster || this.globalAlpha !== 0.06) {
  73. return lineTo.call(this, x, y);
  74. }
  75. };
  76.  
  77. class Checker {
  78. check(callback) {
  79. return (event) => {
  80. if (event instanceof Event && (event.isTrusted ?? true)) {
  81. callback(event);
  82. }
  83. };
  84. }
  85. }
  86.  
  87. let checker = new Checker();
  88. let updateScreen = () => {
  89. let currentWidth = window.innerWidth;
  90. let currentHeight = window.innerHeight;
  91.  
  92. if (FPSBooster) {
  93. let pixelDensity = 0.35;
  94. let scale = Math.max(currentWidth / maxScreenWidth, currentHeight / maxScreenHeight) * pixelDensity;
  95.  
  96. gameCanvas.width = currentWidth * pixelDensity;
  97. gameCanvas.height = currentHeight * pixelDensity;
  98.  
  99. gameCanvas.style.width = `${currentWidth}px`;
  100. gameCanvas.style.height = `${currentHeight}px`;
  101.  
  102. mainContext.setTransform(scale, 0, 0, scale, (currentWidth * pixelDensity - maxScreenWidth * scale) / 2, (currentHeight * pixelDensity - maxScreenHeight * scale) / 2);
  103. } else {
  104. let pixelDensity = 0.8;
  105. let scale = Math.max(currentWidth / maxScreenWidth, currentHeight / maxScreenHeight) * pixelDensity;
  106.  
  107. gameCanvas.width = currentWidth * pixelDensity;
  108. gameCanvas.height = currentHeight * pixelDensity;
  109.  
  110. gameCanvas.style.width = `${currentWidth}px`;
  111. gameCanvas.style.height = `${currentHeight}px`;
  112.  
  113. mainContext.setTransform(scale, 0, 0, scale, (currentWidth * pixelDensity - maxScreenWidth * scale) / 2, (currentHeight * pixelDensity - maxScreenHeight * scale) / 2);
  114. }
  115. };
  116. window.addEventListener("resize", checker.check(updateScreen));
  117. /** LOCKERS **/
  118. let lockers = {
  119. attacker: false,
  120. breaker: false,
  121. storeOpened: false,
  122. }
  123.  
  124. /** WS SEND PACKET **/
  125. let sendPacket = (packet, ...data) => {
  126. ws.send(new Uint8Array(msgpack.encode([packet, data])));
  127. };
  128.  
  129. /** FOR STORE FUNCTIONS **/
  130. let goldCount = () => {
  131. let scoreCount = document.getElementById("scoreDisplay");
  132. return scoreCount ? parseInt(scoreCount.innerText) : 0;
  133. };
  134.  
  135. let hatPrice = (hatId) => {
  136. let hatPrice = {
  137. 45: 0,
  138. 51: 0,
  139. 50: 0,
  140. 28: 0,
  141. 29: 0,
  142. 30: 0,
  143. 36: 0,
  144. 37: 0,
  145. 38: 0,
  146. 44: 0,
  147. 35: 0,
  148. 42: 0,
  149. 43: 0,
  150. 49: 0,
  151. 57: 50,
  152. 8: 100,
  153. 2: 500,
  154. 15: 600,
  155. 5: 1000,
  156. 4: 2000,
  157. 18: 2000,
  158. 31: 2500,
  159. 1: 3000,
  160. 10: 3000,
  161. 48: 3000,
  162. 6: 4000,
  163. 23: 4000,
  164. 13: 5000,
  165. 9: 5000,
  166. 32: 5000,
  167. 7: 6000,
  168. 22: 6000,
  169. 12: 6000,
  170. 26: 8000,
  171. 21: 10000,
  172. 46: 10000,
  173. 14: 10000,
  174. 11: 10000,
  175. 53: 10000,
  176. 20: 12000,
  177. 58: 12000,
  178. 27: 15000,
  179. 40: 15000,
  180. 52: 15000,
  181. 55: 20000,
  182. 56: 20000
  183. };
  184. return hatPrice[hatId] || 0;
  185. };
  186.  
  187. let accPrice = (accessoryId) => {
  188. let accPrice = {
  189. 12: 1000,
  190. 9: 1000,
  191. 10: 1000,
  192. 3: 1500,
  193. 8: 2000,
  194. 11: 2000,
  195. 17: 3000,
  196. 6: 3000,
  197. 4: 4000,
  198. 5: 5000,
  199. 2: 6000,
  200. 1: 8000,
  201. 7: 8000,
  202. 14: 10000,
  203. 15: 10000,
  204. 20: 10000,
  205. 16: 12000,
  206. 13: 15000,
  207. 19: 15000,
  208. 18: 20000,
  209. 21: 20000
  210. };
  211. return accPrice[accessoryId] || 0;
  212. };
  213. let purchased = [];
  214. let isPurchased = (id) => {
  215. return purchased.includes(id);
  216. };
  217.  
  218. /** STORE **/
  219. let storeBuy = (id, index) => {
  220. if (isPurchased(id)) {
  221. return;
  222. }
  223. let gold = goldCount();
  224. let cost = 0;
  225. if (index === 0) {
  226. cost = hatPrice(id);
  227. } else if (index === 1) {
  228. cost = accPrice(id);
  229. }
  230. if (gold >= cost) {
  231. sendPacket('c', 1, id, index);
  232. purchased.push(id);
  233. }
  234. };
  235. let storeEquip = (id, index) => sendPacket('c', 0, id, index);
  236.  
  237. /** EQUIP WEAPONS **/
  238. let equipWeapon = (weapon) => sendPacket('z', weapon, true);
  239.  
  240. /** SEND CHAT **/
  241. let sendChat = message => sendPacket('6', message);
  242.  
  243. /** AUTO GATHER **/
  244. let autoGather = () => sendPacket('K', 1, 1);
  245.  
  246. /** REQUEST ANIMATION FRAME **/
  247. let requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || (callback => setTimeout(callback, 1000 / 60));
  248.  
  249. /** HANDLE MESSAGE **/
  250. let handleMessage = (message) => {
  251. let decodeData = msgpack.decode(new Uint8Array(message.data));
  252.  
  253. let data = Array.isArray(decodeData) && decodeData.length > 1 ? [decodeData[0], ...decodeData[1]] : decodeData;
  254.  
  255. if (!data) return;
  256.  
  257. let dataType = data[0];
  258.  
  259. if (dataType === "C" && myPlayer.id == null) {
  260. myPlayer.id = data[1];
  261. }
  262. if (dataType == "D" && data[2]) {
  263. secondary = null;
  264. primary = 0;
  265. foodType = 0;
  266. wallType = 3;
  267. spikeType = 6;
  268. millType = 10;
  269. spawnpadType = 36;
  270. }
  271. if (dataType == "V") {
  272. if (data[2] == 1) {
  273. primary = data[1][0];
  274. secondary = data[1][1] ?? null;
  275. } else {
  276. foodType = data[1][0];
  277. wallType = data[1][1];
  278. spikeType = data[1][2];
  279. millType = data[1][3];
  280. boostType = data[1][4] ?? -1;
  281. haveMine = data[1][5] == 13 || data[1][4] == 14;
  282. if (haveMine) {
  283. mineType = data[1][5];
  284. }
  285. turretType = data[1][5 + (haveMine ? 1 : 0)];
  286. }
  287. }
  288. if (dataType == "a") updatePlayers(data);
  289. if (dataType === "T") updateAge(data[1], data[2], data[3]);
  290. if (dataType == "O" && data[1] == myPlayer.id) {
  291. let playerID = data[1];
  292. let health = data[2];
  293. updateHealth(health, playerID);
  294. }
  295. };
  296.  
  297. /** DISTANCE CALCULATE **/
  298. let distance = (a, b) => {
  299. return Math.sqrt(Math.pow(b.y - a[2], 2) + Math.pow(b.x - a[1], 2));
  300. };
  301.  
  302. /** ANTI ALTCHA **/
  303. document.getElementById('altcha').style.display = 'none';
  304. document.getElementById('altcha_checkbox').click();
  305.  
  306. /** UPDATE XP/MAXXP/AGE **/
  307. let updateAge = (xp, maxXp, age) => {
  308. if (xp != undefined) {
  309. myPlayer.XP = xp;
  310. }
  311. if (maxXp != undefined) {
  312. myPlayer.maxXP = maxXp;
  313. }
  314. if (age != undefined) {
  315. myPlayer.age = age;
  316. }
  317. }
  318.  
  319. /** PLACE **/
  320. let place = (id, angle = Math.atan2(mouseY - height / 2, mouseX - width / 2)) => {
  321. if (typeof id !== "number" || id == -1) return;
  322. sendPacket("z", id, null);
  323. sendPacket("F", 1, angle);
  324. sendPacket("F", 0, angle);
  325. sendPacket("z", myPlayer.weapon, true);
  326. }
  327. //sendupgrade
  328. function sendUpgrade(index) {
  329. sendPacket("H");
  330. }
  331. /** HOOK **/
  332. let hook = (target, prop, setter, getter) => {
  333. let symbol = Symbol(prop);
  334. Object.defineProperty(target, prop, {
  335. get() {
  336. getter(this, this[symbol]);
  337. return this[symbol];
  338. },
  339. set(value) {
  340. setter(this, symbol, value);
  341. },
  342. configurable: true
  343. })
  344. }
  345.  
  346. /** IS TEAM **/
  347. let isTeam = (kaka) => {
  348. return kaka.clan == myPlayer.clan;
  349. };
  350.  
  351. /** OPEN/CLOSED **/
  352. let checkMenu = () => {
  353. return (allianceMenu.style.display != "block" && chatHolder.style.display != "block" && storeMenu.style.display != "block" && !menuOpened);
  354. }
  355.  
  356. /** RENDERING **/
  357. let object = null;
  358. hook(Object.prototype, "isItem", function(that, symbol, value) {
  359. that[symbol] = value;
  360. }, function(that, value) {
  361. if (value === true) {
  362. object = that;
  363. }
  364. });
  365.  
  366. CanvasRenderingContext2D.prototype.restore = new Proxy(CanvasRenderingContext2D.prototype.restore, {
  367. apply(target, thisArg, args) {
  368. markObject(thisArg);
  369. return Reflect.apply(target, thisArg, args);
  370. }
  371. });
  372.  
  373. let markColor = (id) => {
  374.  
  375. if (id === myPlayer.id) {
  376. return { color: "#00ff00", render: true };
  377. } else {
  378. return { color: "#FF4D4D", render: false };
  379. }
  380. };
  381.  
  382. // item.owner.sid
  383.  
  384. let markObject = (ctx) => {
  385. if (!object || !object.owner || myPlayer.id === null) return;
  386. let distance = Math.sqrt(Math.pow(myPlayer.x - object.x, 2) + Math.pow(myPlayer.y - object.y, 2));
  387. if (distance > 300) return;
  388. let type = markColor(object.owner.sid);
  389. if (!type.render) return;
  390. ctx.fillStyle = type.color;
  391. ctx.beginPath();
  392. ctx.arc(0, 0, 10, 0, 2 * Math.PI);
  393. ctx.fill();
  394. object = null;
  395. };
  396.  
  397. /** WEAPONS/NAMES/IDS **/
  398. let weapon = {
  399. "tool_hammer": 0,
  400. "hand_axe": 1,
  401. "great_axe": 2,
  402. "short_sword": 3,
  403. "katana": 4,
  404. "polearm": 5,
  405. "bat": 6,
  406. "daggers": 7,
  407. "stick": 8,
  408. "hunting_bow": 9,
  409. "great_hammer": 10,
  410. "wooden_shield": 11,
  411. "crossbow": 12,
  412. "repeater_crossbow": 13,
  413. "mc_grabby": 14,
  414. "musket": 15
  415. };
  416.  
  417. /** UPDATE PLAYERS **/
  418. let updatePlayers = data => {
  419. SaVeGe.tick++
  420. let enemies = [];
  421. let players = [];
  422. let cTickQ = SaVeGe.tickQueue[SaVeGe.tick];
  423. if (Array.isArray(cTickQ)) {
  424. cTickQ.forEach((did) => did());
  425. SaVeGe.tickQueue[SaVeGe.tick] = null;
  426. }
  427. for (let i = 0; i < data[1].length / 13; i++) {
  428. let playerInfo = data[1].slice(13 * i, 13 * i + 13);
  429. players.push(playerInfo);
  430.  
  431. if (playerInfo[0] == myPlayer.id) {
  432. myPlayer.x = playerInfo[1];
  433. myPlayer.y = playerInfo[2];
  434. myPlayer.dir = playerInfo[3];
  435. myPlayer.object = playerInfo[4];
  436. myPlayer.weapon = playerInfo[5];
  437. myPlayer.clan = playerInfo[7];
  438. myPlayer.isLeader = playerInfo[8];
  439. myPlayer.hat = playerInfo[9];
  440. myPlayer.accessory = playerInfo[10];
  441. myPlayer.isSkull = playerInfo[11];
  442. } else if (playerInfo[7] != myPlayer.clan && playerInfo[7] !== null) {
  443. enemies.push({
  444. id: playerInfo[0],
  445. x: playerInfo[1],
  446. y: playerInfo[2],
  447. dir: playerInfo[3],
  448. object: playerInfo[4],
  449. weapon: playerInfo[5],
  450. clan: playerInfo[7],
  451. isLeader: playerInfo[8],
  452. hat: playerInfo[9],
  453. accessory: playerInfo[10],
  454. isSkull: playerInfo[11]
  455. });
  456. }
  457. }
  458.  
  459. if (enemies) {
  460. nearestEnemy = enemies.sort((a, b) => distance(a, myPlayer) - distance(b, myPlayer))[0];
  461. }
  462.  
  463. let isEnemyNear = (Math.sqrt(Math.pow((myPlayer.y - nearestEnemy), 2) + Math.pow((myPlayer.x-nearestEnemy[1]), 2)) < 300) /**nearestEnemy ? (Math.sqrt(Math.pow(myPlayer.y - nearestEnemy.y, 2) + Math.pow(myPlayer.x - nearestEnemy.x, 2)) < 320) : false;
  464. enemyAngle = nearestEnemy ? Math.atan2(nearestEnemy.y - myPlayer.y, nearestEnemy.x - myPlayer.x) : (myPlayer?.dir ?? 0)**/
  465. };
  466.  
  467. /** PLACE REPEATER **/
  468. let placeRepeater = (key, action) => {
  469. return {
  470. interval: null,
  471. action,
  472. key,
  473. };
  474. }
  475.  
  476. let repeaters = [
  477. placeRepeater("q", () => {
  478. place(foodType);
  479. }),
  480. placeRepeater("f", () => {
  481. place(boostType);
  482. }),
  483. placeRepeater("v", () => {
  484. place(spikeType);
  485. }),
  486. placeRepeater("F", () => {
  487. place(millType);
  488. }),
  489. placeRepeater("h", () => {
  490. place(turretType);
  491. }),
  492. placeRepeater("t", () => {
  493. place(wallType);
  494. }),
  495. ];
  496.  
  497.  
  498. /** HIT **/
  499. let hit = () => {
  500. sendPacket("F", 1, enemyAngle);
  501. sendPacket("F", 0);
  502. }
  503.  
  504. /** SOCKET CONNECTION **/
  505. let socketFound = stuff => {
  506. stuff.addEventListener("message", handleMessage);
  507. gameCanvas.addEventListener("mousemove", ({ x, y }) => {
  508. mouseX = x;
  509. mouseY = y;
  510. });
  511. window.addEventListener("resize", () => {
  512. height = innerHeight;
  513. width = innerWidth;
  514. });
  515. };
  516. /** MOVEMENT **/
  517. let moveEz = (key, isKeyDown) => {
  518. moveKeys[key] = isKeyDown;
  519. if ((moveKeys.w || moveKeys.a || moveKeys.s || moveKeys.d) && !locked) {
  520. // storeEquip(12, 0);
  521. locked = true;
  522. }
  523. if (!moveKeys.w && !moveKeys.a && !moveKeys.s && !moveKeys.d && locked) {
  524. // storeEquip(6, 0);
  525. locked = false;
  526. }
  527. };
  528.  
  529. /** AUTO HEAL **/
  530. let defHealSpeed = 200;
  531. let autoHeal = (health, damage) => {
  532. let cHealSpeed = defHealSpeed;
  533. if (health <= 50) {
  534. cHealSpeed = 230;
  535. place(foodType);
  536. storeEquip(21, 1);
  537. sendChat("");
  538. if (health < 100){
  539. place(foodType);
  540. }
  541. } else if (damage >= 35) {
  542. sendChat("");
  543. spike = 1;
  544. storeEquip(21, 1);
  545. cHealSpeed = 170;
  546. place(foodType, null);
  547. }
  548. if (health < myPlayer.maxHealth) {
  549. let healing = setInterval(() => {
  550. if (myPlayer.health < myPlayer.maxHealth) {
  551. place(foodType, null);
  552. } else {
  553. clearInterval(healing);
  554. }
  555. }, cHealSpeed);
  556. }
  557. };
  558. /** UPDATE HEALTH **/
  559. let lastHealth = 100;
  560. let updateHealth = (health, playerID) => {
  561. if (myPlayer.id === playerID) {
  562. let damage = Math.max(0, lastHealth - health);
  563. myPlayer.health = health;
  564. if (myPlayer.health > 0) {
  565. autoHeal(myPlayer.health, damage);
  566. }
  567. lastHealth = health;
  568. } else {
  569. enemy.health = health;
  570. }
  571. };
  572.  
  573. /** INSTA KILL **/
  574. let instaKill = (...instaType) => {
  575. let type = instaType[0];
  576.  
  577. switch (type) {
  578. case "normal":
  579. sendChat("");
  580. storeBuy(0, 1);
  581. storeEquip(0, 1);
  582. setTimeout(()=>{
  583. storeBuy(7, 0);
  584. storeEquip(7, 0);
  585. equipWeapon(primary);
  586. hit();
  587. setTimeout(()=>{
  588. storeBuy(53, 0);
  589. storeEquip(53, 0);
  590. equipWeapon(secondary);
  591. hit();
  592. setTimeout(() => {
  593. storeBuy(6, 0);
  594. storeEquip(6, 0);
  595. if (secondary == 15){
  596. equipWeapon(secondary);
  597. setTimeout(()=>{
  598. equipWeapon(primary);
  599. },1500);
  600. } else if (secondary == 12){
  601. equipWeapon(secondary);
  602. setTimeout(()=>{
  603. equipWeapon(primary);
  604. },1000);
  605. } else if (secondary == 13){
  606. equipWeapon(secondary);
  607. setTimeout(()=>{
  608. equipWeapon(primary);
  609. },400);
  610. }
  611. setTimeout(() => {
  612. storeBuy(11, 1);
  613. storeEquip(11, 1);
  614. equipWeapon(primary);
  615. equipWeapon(secondary);
  616. }, 170);
  617. }, 170);
  618. }, 105);
  619. }, 100);
  620. break;
  621.  
  622. case "boostTick":
  623. sendChat("");
  624. storeEquip(0, 1);
  625. place(boostType, null);
  626. setTimeout(()=>{
  627. equipWeapon(secondary);
  628. storeBuy(53, 0);
  629. storeEquip(53, 0);
  630. hit();
  631. setTimeout(()=>{
  632. equipWeapon(primary);
  633. storeBuy(7, 0);
  634. storeEquip(7, 0);
  635. hit();
  636. setTimeout(() => {
  637. storeBuy(6, 0);
  638. storeEquip(6, 0);
  639. setTimeout(() => {
  640. storeBuy(11, 1);
  641. storeEquip(11, 1);
  642. if (secondary == 15){
  643. equipWeapon(secondary);
  644. setTimeout(()=>{
  645. equipWeapon(primary);
  646. },1500);
  647. } else if (secondary == 12){
  648. equipWeapon(secondary);
  649. setTimeout(()=>{
  650. equipWeapon(primary);
  651. },1000);
  652. } else if (secondary == 13){
  653. equipWeapon(secondary);
  654. setTimeout(()=>{
  655. equipWeapon(primary);
  656. },400);
  657. }
  658. equipWeapon(primary);
  659. equipWeapon(secondary);
  660. }, 170);
  661. }, 170);
  662. }, 110);
  663. }, 100);
  664. break;
  665.  
  666. case "reverseInsta":
  667. sendChat("");
  668. storeEquip(0, 1);
  669. setTimeout(()=>{
  670. equipWeapon(secondary);
  671. storeBuy(53, 0);
  672. storeEquip(53, 0);
  673. hit();
  674. setTimeout(()=>{
  675. storeBuy(7, 0);
  676. storeEquip(7, 0);
  677. hit();
  678. equipWeapon(primary);
  679. setTimeout(() => {
  680. storeBuy(6, 0);
  681. storeEquip(6, 0);
  682. setTimeout(() => {
  683. storeBuy(11, 1);
  684. storeEquip(11, 1);
  685. if (secondary == 15){
  686. equipWeapon(secondary);
  687. setTimeout(()=>{
  688. equipWeapon(primary);
  689. },1500);
  690. } else if (secondary == 12){
  691. equipWeapon(secondary);
  692. setTimeout(()=>{
  693. equipWeapon(primary);
  694. },1000);
  695. } else if (secondary == 13){
  696. equipWeapon(secondary);
  697. setTimeout(()=>{
  698. equipWeapon(primary);
  699. },400);
  700. }
  701. equipWeapon(primary);
  702. equipWeapon(secondary);
  703. }, 170);
  704. }, 170);
  705. }, 100);
  706. }, 100);
  707.  
  708. break;
  709.  
  710. case "oneTick":
  711. sendChat("");
  712. storeEquip(0, 1);
  713. setTimeout(()=>{
  714. equipWeapon(primary);
  715. storeBuy(7, 0);
  716. storeEquip(7, 0);
  717. hit();
  718. setTimeout(()=>{
  719. equipWeapon(secondary);
  720. hit();
  721. storeEquip(53, 0);
  722. setTimeout(() => {
  723. storeBuy(6, 0);
  724. storeEquip(6, 0);
  725. equipWeapon(primary);
  726. setTimeout(() => {
  727. storeBuy(11, 1);
  728. storeEquip(11, 1);
  729. equipWeapon(secondary);
  730. }, 800);
  731. }, 170);
  732. }, 105);
  733. }, 100);
  734.  
  735. break;
  736.  
  737. default:
  738. sendChat("");
  739. break;
  740. }
  741. };
  742.  
  743. let instaKillMode = 0;
  744. let isInstaKillModeEnabled = false;
  745.  
  746. let humanBasedInsta = () => {
  747. if (!isInstaKillModeEnabled) return;
  748.  
  749. switch (instaKillMode) {
  750. case 0:
  751. equipWeapon(primary);
  752. storeBuy(7, 0);
  753. storeEquip(7, 0);
  754. hit();
  755. break;
  756.  
  757. case 1:
  758. equipWeapon(secondary);
  759. storeBuy(53, 0);
  760. storeEquip(53, 0);
  761. hit();
  762. break;
  763.  
  764. case 2:
  765. equipWeapon(primary);
  766. storeBuy(6, 0);
  767. storeEquip(6, 0);
  768. break;
  769.  
  770. case 3:
  771. sendChat("");
  772. break;
  773.  
  774. default:
  775. sendChat("");
  776. break;
  777. }
  778.  
  779. instaKillMode = (instaKillMode + 1) % 4;
  780. };
  781. let movementdir;
  782. document.addEventListener("keydown", (event) => {
  783. if (event.key === "w") {
  784. movementdir = -1.57;
  785. }
  786. });
  787. document.addEventListener("keydown", (event) => {
  788. if (event.key === "d") {
  789. movementdir = 0;
  790. }
  791. });
  792. document.addEventListener("keydown", (event) => {
  793. if (event.key === "s") {
  794. movementdir = 1.57;
  795. }
  796. });
  797. document.addEventListener("keydown", (event) => {
  798. if (event.key === "a") {
  799. movementdir = -3.14
  800. }
  801. });
  802. let keys = {};
  803.  
  804. document.addEventListener("keydown", (event) => {
  805. keys[event.code] = true;
  806. if (window.location.hostname === "sandbox.moomoo.io") {
  807. // Check if both keys are pressed
  808. if (keys["KeyW"] && keys["KeyD"]) {
  809. movementdir = -0.785;
  810. }
  811. if (keys["KeyD"] && keys["KeyS"]) {
  812. movementdir = 0.785;
  813. }
  814. if (keys["KeyS"] && keys["KeyA"]) {
  815. movementdir = 2.355;
  816. }
  817. if (keys["KeyA"] && keys["KeyW"]) {
  818. movementdir = -2.355;
  819. }
  820. }
  821. });
  822. document.addEventListener("keyup", (event) => {
  823. keys[event.code] = false;
  824. });
  825. // clown hat
  826. let clownInterval;
  827.  
  828. setInterval(function() {
  829. if (myPlayer.hat === 45) {
  830. storeBuy(13, 1);
  831. storeEquip(13, 1);
  832. }
  833. }, 100);
  834. //autospike
  835. let spikeInterval;
  836.  
  837. setInterval(function() {
  838. if (spike === 1) {
  839. let c = myPlayer.dir;
  840. place(spikeType, myPlayer.dir + toRad(0));
  841. place(spikeType, myPlayer.dir + toRad(120));
  842. place(spikeType, myPlayer.dir - toRad(120));
  843. place(spikeType, c);
  844. spike = 0;
  845. }
  846. }, 100);
  847. /** KEY EVENTS **/
  848. document.addEventListener('keydown', ({ key }) => {
  849. if (key == 'Escape') {
  850. let menu = document.getElementById('modMenu');
  851. if (menu) {
  852. if (menu.style.visibility === 'hidden') {
  853. menu.style.visibility = 'visible';
  854. menu.style.opacity = '1';
  855. menu.style.transform = 'translate(-50%, -50%) scale(1)';
  856. menuOpened = true;
  857. } else {
  858. menu.style.opacity = '0';
  859. menu.style.transform = 'translate(-50%, -50%) scale(0.95)';
  860. menuOpened = false;
  861. menu.style.visibility = 'hidden';
  862. }
  863. }
  864. }
  865. if (!checkMenu()) return;
  866. for (let repeater of repeaters) {
  867. if (repeater.key === key && repeater.interval === null) {
  868. repeater.interval = setInterval(
  869. repeater.action, 100
  870. );
  871. }
  872. }
  873. // if (key in moveKeys) moveEz(key, true);
  874. if (key == "r") {
  875. let instaTypes = document.getElementById('instaKillType');
  876. let instaType = instaTypes.value;
  877. instaKill(instaType);
  878. }
  879. });
  880.  
  881. document.addEventListener('keyup', ({ key }) => {
  882. if (!checkMenu()) return;
  883. for (let repeater of repeaters) {
  884. if (repeater.key === key && repeater.interval !== null) {
  885. clearInterval(repeater.interval);
  886. repeater.interval = null;
  887. }
  888. }
  889. // if (key in moveKeys) moveEz(key, false);
  890. });
  891. document.addEventListener("keydown", (event) => {
  892. if (event.key === "c") {
  893. let c = myPlayer.dir;
  894. place(spikeType, myPlayer.dir + toRad(0));
  895. place(spikeType, myPlayer.dir + toRad(120));
  896. place(spikeType, myPlayer.dir - toRad(120));
  897. place(spikeType, c);
  898. storeEquip(0, 1);
  899. setTimeout(()=>{
  900. equipWeapon(primary);
  901. storeBuy(7, 0);
  902. storeEquip(7, 0);
  903. hit();
  904. setTimeout(()=>{
  905. equipWeapon(secondary);
  906. hit();
  907. storeEquip(53, 0);
  908. setTimeout(() => {
  909. storeBuy(53, 0);
  910. storeEquip(53, 0);
  911. if (enemy.object) {
  912. place(spikeType);
  913. }
  914. setTimeout(() => {
  915. storeBuy(6, 0);
  916. storeEquip(6, 0);
  917. equipWeapon(primary);
  918. setTimeout(() => {
  919. storeBuy(11, 1);
  920. storeEquip(11, 1);
  921. equipWeapon(secondary);
  922. }, 800);
  923. }, 170);
  924. }, 120);
  925. }, 105);
  926. }, 100);
  927. }
  928. });
  929. document.addEventListener("keydown", (event) => {
  930. if (event.key === ",") {
  931. storeBuy(31, 0);
  932. storeEquip(31, 0);
  933. }
  934. });
  935. document.addEventListener("keyup", (event) => {
  936. if (event.key === ",") {
  937. storeBuy(15, 0);
  938. storeEquip(15, 0);
  939. }
  940. });
  941. document.addEventListener("keydown", (event) => {
  942. if (event.key === "e") {
  943. storeEquip(20, 0);
  944. }
  945. });
  946. let x = myPlayer.x;
  947. let y = myPlayer.y;
  948. function toRad(angle) {
  949. return angle * 0.01745329251;
  950. }
  951. document.addEventListener("keydown", (event) => {
  952. if (event.key === "z") {
  953. let a = myPlayer.dir;
  954. place(boostType, myPlayer.dir + toRad(45));
  955. place(boostType, myPlayer.dir - toRad(45));
  956. place(boostType, myPlayer.dir + toRad(135));
  957. place(boostType, myPlayer.dir - toRad(135));
  958. place(boostType, myPlayer.dir + toRad(0));
  959. place(boostType, myPlayer.dir - toRad(180));
  960. place(boostType, myPlayer.dir + toRad(90));
  961. place(boostType, myPlayer.dir - toRad(90));
  962. place(boostType, a);
  963. }
  964. });
  965. let autospin = false;
  966. let spinInterval;
  967.  
  968. document.addEventListener("keydown", (event) => {
  969. if (event.key === ".") {
  970. autospin = !autospin;
  971. sendChat(autospin ? "" : "");
  972.  
  973. if (autospin) {
  974. let autospinDir = myPlayer.dir;
  975. spinInterval = setInterval(() => {
  976. myPlayer.dir + toRad(45);
  977. myPlayer.dir - toRad(45);
  978. myPlayer.dir + toRad(135);
  979. myPlayer.dir - toRad(135);
  980. myPlayer.dir = autospin.dir;
  981. }, 100);
  982. } else {
  983. clearInterval(spinInterval);
  984. }
  985. }
  986. });
  987. let automill = false;
  988. let millInterval;
  989. if (window.location.hostname === "sandbox.moomoo.io") {
  990. document.addEventListener("keydown", (event) => {
  991. if (event.key === "n") {
  992. automill = !automill;
  993. if (automill) {
  994. millInterval = setInterval(() => {
  995. place(millType, movementdir - 1.90);
  996. place(millType, movementdir - 3.14);
  997. place(millType, movementdir + 1.90);
  998. }, 100);
  999. } else {
  1000. clearInterval(millInterval);
  1001. }
  1002. }
  1003. });
  1004. };
  1005. /** MOUSE EVENTS **/
  1006. document.addEventListener('mousedown', (mouse) => {
  1007. if (!checkMenu()) return;
  1008. if (mouse.button === 0 && !lockers.attacker) {
  1009. humanBasedInsta();
  1010. if (!isInstaKillModeEnabled) {
  1011. storeBuy(11, 1);
  1012. storeEquip(0, 1);
  1013. equipWeapon(primary);
  1014. setTimeout(()=>{
  1015. storeBuy(7, 0);
  1016. storeEquip(7, 0);
  1017. autoGather();
  1018. }, 100);
  1019. lockers.attacker = true;
  1020. }
  1021. }
  1022. if (mouse.button === 2 && !lockers.breaker) {
  1023. if (!isInstaKillModeEnabled) {
  1024. sendChat("");
  1025. storeBuy(40, 0);
  1026. storeEquip(40, 0);
  1027. autoGather();
  1028.  
  1029. lockers.breaker = true;
  1030. }
  1031. if (secondary == 10 && weapongrind == false) {
  1032. equipWeapon(secondary);
  1033. }
  1034. }
  1035. });
  1036.  
  1037. document.addEventListener('mouseup', (mouse) => {
  1038. if (!checkMenu()) return;
  1039. if (mouse.button === 0 && lockers.attacker) {
  1040. if (!isInstaKillModeEnabled) {
  1041. storeBuy(11, 1);
  1042. storeEquip(11, 1);
  1043. autoGather();
  1044. setTimeout(()=>{
  1045. storeBuy(6, 0);
  1046. storeEquip(6, 0);
  1047. }, 200);
  1048. lockers.attacker = false;
  1049. }
  1050. }
  1051. if (mouse.button === 2 && lockers.breaker) {
  1052. if (!isInstaKillModeEnabled) {
  1053. storeBuy(6, 0);
  1054. storeEquip(6, 0);
  1055. autoGather();
  1056.  
  1057. lockers.breaker = false;
  1058. }
  1059. }
  1060. });
  1061. //bow insta
  1062. document.addEventListener('mousedown', (mouse) => {
  1063. if (mouse.button === 1) {
  1064. sendChat("");
  1065. storeEquip(0, 1);
  1066. setTimeout(() => {
  1067. equipWeapon(secondary);
  1068. hit();
  1069. setTimeout(() => {
  1070. sendUpgrade(12);
  1071. hit();
  1072. storeEquip(53, 0);
  1073. setTimeout(() => {
  1074. sendUpgrade(15);
  1075. hit();
  1076. }, 100);
  1077. }, 100);
  1078. }, 100);
  1079.  
  1080. }
  1081. });
  1082. let prevCount = 0;
  1083. const handleMutations = (mutationsList) => {
  1084. for (const mutation of mutationsList) {
  1085. if (mutation.target.id === "killCounter") {
  1086. const count = parseInt(mutation.target.innerText, 10) || 0;
  1087. if (count > prevCount) {
  1088. if (myPlayer.clan != null){
  1089. sendChat("Clap mod by Good Guy");
  1090. setTimeout(()=>{
  1091. sendChat(count + " kills");
  1092. },650);
  1093. }
  1094. prevCount = count;
  1095. }
  1096. }
  1097. }
  1098. };
  1099. const observer = new MutationObserver(handleMutations);
  1100. observer.observe(document, {
  1101. subtree: true,
  1102. childList: true,
  1103. });
  1104. setInterval(function() {
  1105. if (myPlayer.y > 6850 && myPlayer.y < 7550) {
  1106. storeBuy(31, 0);
  1107. storeEquip(31, 0);
  1108. }
  1109. }, 130);
  1110. setInterval(function() {
  1111. if (myPlayer.y < 2400) {
  1112. storeEquip(15, 0);
  1113. storeEquip(15, 0);
  1114. }
  1115. }, 900);
  1116. setInterval(function() {
  1117. storeBuy(11, 1);
  1118. }, 100);
  1119. setInterval(function() {
  1120. storeBuy(6, 0);
  1121. }, 100);
  1122. setInterval(function() {
  1123. storeBuy(7, 0);
  1124. }, 100);
  1125. setInterval(function() {
  1126. storeBuy(40, 0);
  1127. }, 100);
  1128. // weapond grinder
  1129. document.addEventListener("keydown", (event) => {
  1130. if (event.key === "`") {
  1131. sendChat("Weapond Grinding...");
  1132. weapongrind = !weapongrind;
  1133. }
  1134. });
  1135. /*
  1136.  
  1137.  
  1138. STYLING AND MOD MENUS UNDER
  1139.  
  1140.  
  1141. */
  1142.  
  1143.  
  1144. /** MOD MENU **/
  1145. let createModMenu = () => {
  1146. let menuContainer = document.createElement('div');
  1147. menuContainer.id = 'modMenu';
  1148.  
  1149. menuContainer.innerHTML = `
  1150. <h2 class="mod-menu-title">
  1151. </h2>
  1152. <div class="menu-item" style="margin-top: 0px;">
  1153. <label style="cursor: pointer;">
  1154. <div class="toggle-switch">
  1155. <input type="checkbox" id="fpsBoosterToggle" class="checkbox">
  1156. <span class="slider"></span>
  1157. </div>
  1158. <span class="menu-label">FPS Booster</span>
  1159. </label>
  1160. </div>
  1161. <div class="menu-item" style="margin-top: 0px;">
  1162. <label style="cursor: pointer;">
  1163. <div class="toggle-switch">
  1164. <input type="checkbox" id="autoGatherToggle" class="checkbox">
  1165. <span class="slider"></span>
  1166. </div>
  1167. <span class="menu-label">Auto Gather</span>
  1168. </label>
  1169. </div>
  1170. <div class="menu-item">
  1171. <label for="instaKillType" style="font-size: 16px">InstaKill Type:</label>
  1172. <select id="instaKillType">
  1173. <option value="reverseInsta">Reverse Insta</option>
  1174. <option value="boostTick">Boost Tick</option>
  1175. <option value="normal">Normal Insta</option>
  1176. <option value="oneTick">One Tick</option>
  1177. </select>
  1178. </div>
  1179. <div class="menu-footer">
  1180. Credits: SaVeGe
  1181. </div>
  1182. `;
  1183.  
  1184. document.body.appendChild(menuContainer);
  1185.  
  1186. document.getElementById('fpsBoosterToggle').checked = FPSBooster;
  1187. document.getElementById('fpsBoosterToggle').addEventListener('change', (e) => {
  1188. FPSBooster = e.target.checked;
  1189. updateScreen();
  1190. });
  1191.  
  1192. document.getElementById('autoGatherToggle').addEventListener('change', (e) => {
  1193. if (e.target.checked) {
  1194. autoGather();
  1195. } else {
  1196. autoGather();
  1197. }
  1198. });
  1199. };
  1200.  
  1201. createModMenu();
  1202.  
  1203. let menuStyles = `
  1204. @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap');
  1205.  
  1206. #modMenu {
  1207. position: fixed;
  1208. top: 50%;
  1209. left: 50%;
  1210. transform: translate(-50%, -50%) scale(0.95);
  1211. width: 420px;
  1212. background: rgba(30, 30, 30, 0.8);
  1213. border-radius: 20px;
  1214. padding: 20px;
  1215. box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4);
  1216. color: #ffffff;
  1217. visibility: hidden;
  1218. opacity: 0;
  1219. z-index: 10000;
  1220. font-family: 'Poppins', sans-serif;
  1221. transition: transform 0.6s ease, opacity 0.6s ease, visibility 0.6s ease;
  1222. border: 1px solid rgba(255, 255, 255, 0.25);
  1223. }
  1224.  
  1225. #modMenu h2 {
  1226. text-align: center;
  1227. color: #ffffff;
  1228. font-size: 36px;
  1229. letter-spacing: 1.5px;
  1230. margin-bottom: 20px;
  1231. text-shadow: 0px 2px 5px rgba(0, 0, 0, 0.5);
  1232. }
  1233.  
  1234. #modMenu .menu-item {
  1235. margin-bottom: 15px;
  1236. }
  1237.  
  1238. #modMenu .menu-footer {
  1239. margin-top: 20px;
  1240. text-align: center;
  1241. color: #ccc;
  1242. font-size: 14px;
  1243. font-style: italic;
  1244. }
  1245.  
  1246. #modMenu .toggle-switch {
  1247. position: relative;
  1248. display: inline-block;
  1249. width: 50px;
  1250. height: 26px;
  1251. }
  1252.  
  1253. #modMenu .toggle-switch input {
  1254. display: none;
  1255. }
  1256.  
  1257. #modMenu .slider {
  1258. position: absolute;
  1259. cursor: pointer;
  1260. top: 0;
  1261. left: 0;
  1262. right: 0;
  1263. bottom: 0;
  1264. background-color: rgba(255, 255, 255, 0.2);
  1265. border-radius: 34px;
  1266. transition: background-color 0.4s, box-shadow 0.4s;
  1267. box-shadow: inset 0px 2px 4px rgba(0, 0, 0, 0.3);
  1268. }
  1269.  
  1270. #modMenu .slider:before {
  1271. position: absolute;
  1272. content: "";
  1273. height: 22px;
  1274. width: 22px;
  1275. left: 4px;
  1276. bottom: 2px;
  1277. background-color: #ffffff;
  1278. border-radius: 50%;
  1279. transition: transform 0.4s, box-shadow 0.4s;
  1280. box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.3);
  1281. }
  1282.  
  1283. #modMenu input:checked + .slider {
  1284. background-color: rgba(0, 234, 255, 0.8);
  1285. box-shadow: 0 0 15px rgba(0, 234, 255, 0.6);
  1286. }
  1287.  
  1288. #modMenu input:checked + .slider:before {
  1289. transform: translateX(24px);
  1290. box-shadow: 0px 4px 6px rgba(0, 234, 255, 0.6);
  1291. }
  1292.  
  1293. #modMenu .menu-label {
  1294. position: absolute;
  1295. font-size: 16px;
  1296. margin-top: 5px;
  1297. color: #ddd;
  1298. margin-left: 10px;
  1299. transition: color 0.3s ease;
  1300. text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  1301. }
  1302.  
  1303. #modMenu select {
  1304. background: rgba(255, 255, 255, 0.2);
  1305. border: 1px solid rgba(255, 255, 255, 0.4);
  1306. border-radius: 5px;
  1307. color: #ddd;
  1308. padding: 10px;
  1309. font-size: 16px;
  1310. font-family: 'Poppins', sans-serif;
  1311. width: 100%;
  1312. margin-top: 5px;
  1313. transition: background 0.3s, border-color 0.3s;
  1314. }
  1315.  
  1316. #modMenu select:hover {
  1317. background: rgba(255, 255, 255, 0.3);
  1318. border-color: rgba(255, 255, 255, 0.6);
  1319. }
  1320.  
  1321. #modMenu select option {
  1322. background-color: rgba(30, 30, 30, 0.8);
  1323. color: #ffffff;
  1324. }
  1325.  
  1326. #modMenu select option:hover {
  1327. background-color: rgba(0, 234, 255, 0.5);
  1328. }
  1329.  
  1330. #modMenu select:focus {
  1331. outline: none;
  1332. border-color: rgba(0, 234, 255, 0.8);
  1333. background-color: rgba(255, 255, 255, 0.3);
  1334. }
  1335.  
  1336. #modMenu button {
  1337. background: rgba(255, 255, 255, 0.2);
  1338. border: 1px solid rgba(255, 255, 255, 0.4);
  1339. color: #ffffff;
  1340. border-radius: 5px;
  1341. padding: 12px 20px;
  1342. font-size: 18px;
  1343. cursor: pointer;
  1344. transition: background 0.3s, box-shadow 0.3s;
  1345. width: 100%;
  1346. }
  1347.  
  1348. #modMenu button:hover {
  1349. background: rgba(255, 255, 255, 0.3);
  1350. border-color: rgba(255, 255, 255, 0.6);
  1351. }
  1352. #leaderboard::after {
  1353. display: block;
  1354. font-size: 40px;
  1355. text-align: center;
  1356. margin: 0 auto;
  1357. }
  1358. `;
  1359.  
  1360. let styleSheet = document.createElement('style');
  1361. Object.assign(styleSheet, { type: 'text/css', textContent: menuStyles });
  1362. document.head.append(styleSheet);
  1363.