Slither Full Auto Bot 2025 (Zoom Dezoom enabled)

Detects and avoid enemies, Zoom Dezoom, Automatically collects food strategically and use strategic pathfinding. Enhanced and responsive overlay.

  1. // ==UserScript==
  2. // @name Slither Full Auto Bot 2025 (Zoom Dezoom enabled)
  3. // @namespace http://slither.com/io
  4. // @version 1.6
  5. // @description Detects and avoid enemies, Zoom Dezoom, Automatically collects food strategically and use strategic pathfinding. Enhanced and responsive overlay.
  6. // @author EliottValette
  7. // @match http://slither.com/io
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. /*
  13. ===================================================
  14. Section 1: Utility Functions and Debugging
  15. ===================================================
  16. */
  17.  
  18. // Custom log function (only displays if "logDebugging" is enabled)
  19. window.log = (...args) => window.logDebugging && console.log(...args);
  20.  
  21. // Functions to save and load preferences in localStorage
  22. const savePreference = (key, value) => localStorage.setItem(key, value);
  23. const loadPreference = (key, def) => JSON.parse(localStorage.getItem(key)) ?? def;
  24.  
  25. let Logger = 0;
  26. let IsBotActive = true;
  27. let targetFood = null;
  28. let targetFoodTimestamp = 0;
  29. let blacklistedFoods = {};
  30. let criticDanger = false;
  31.  
  32. // Ajout des variables et fonctions pour le zoom
  33. window.zoomMultiplier = 1.0;
  34.  
  35. window.updateZoom = function() {
  36. window.gsc = window.zoomMultiplier;
  37. const zoomElement = document.getElementById("bot_zoom_overlay");
  38. if (zoomElement) {
  39. zoomElement.textContent = `Zoom: ${window.zoomMultiplier.toFixed(1)} (a to zoom, e to zoom out, z to reset)`;
  40. }
  41. };
  42.  
  43. window.recursiveZoomUpdate = function() {
  44. window.gsc = window.zoomMultiplier;
  45. requestAnimationFrame(window.recursiveZoomUpdate);
  46. };
  47.  
  48. window.resetZoom = function() {
  49. window.zoomMultiplier = 1.0;
  50. window.updateZoom();
  51. };
  52.  
  53. window.adjustZoom = function(amount) {
  54. window.zoomMultiplier = Math.max(0.2, Math.min(3.0, window.zoomMultiplier + amount));
  55. window.updateZoom();
  56. };
  57.  
  58. // Add listener to memorize real mouse position
  59. window.mousePos = { x: 0, y: 0 };
  60. document.addEventListener('mousemove', function(e) {
  61. window.mousePos = { x: e.clientX, y: e.clientY };
  62. });
  63.  
  64. // Variable to memorize bot target position (the "bot mouse pose")
  65. window.botTargetPos = null;
  66.  
  67. console.log('Bot Starting');
  68.  
  69. /*
  70. ===================================================
  71. Section 2: Window Object Debug Scan
  72. ===================================================
  73. After 5 seconds, scans the window object to find
  74. potential snake objects (presence of xx and yy)
  75. */
  76. setTimeout(() => {
  77. for (let key in window) {
  78. try {
  79. let val = window[key];
  80. if (val && typeof val === 'object') {
  81. // Checks if the object has coordinates
  82. if ('xx' in val && 'yy' in val) {
  83. console.log(`🟢 Snake? -> window.${key}`, val);
  84. }
  85. // Checks if the object is an array of objects with coordinates
  86. if (Array.isArray(val) && val.length > 0 && val[0] && 'xx' in val[0] && 'yy' in val[0]) {
  87. console.log(`🍏 Array of objects with coords? -> window.${key}`, val);
  88. }
  89. }
  90. } catch (e) {
  91. // In case of error, move to next property
  92. }
  93. }
  94. }, 5000);
  95.  
  96. /*
  97. ===================================================
  98. Section 3: Improved Interface Overlay
  99. ===================================================
  100. Creation of a unique container that displays bot status,
  101. coordinates and enemy count in real-time.
  102. */
  103. (function setupOverlayUI() {
  104. // Creation of main container with semi-transparent background
  105. const overlayContainer = document.createElement('div');
  106. overlayContainer.id = 'bot-overlay-container';
  107. overlayContainer.style.cssText = `
  108. position: fixed;
  109. top: 10px;
  110. left: 10px;
  111. background: rgba(0, 0, 0, 0.5);
  112. padding: 10px;
  113. border-radius: 5px;
  114. z-index: 9999;
  115. font-family: Arial, sans-serif;
  116. color: #FFF;
  117. font-size: 14px;
  118. `;
  119. document.body.appendChild(overlayContainer);
  120.  
  121. // Creation of sub-elements for status, coordinates and enemy count
  122. const statusDiv = document.createElement('div');
  123. statusDiv.id = 'bot_status_overlay';
  124. statusDiv.textContent = 'Status: BOT ON (To Toggle - Press t)';
  125. overlayContainer.appendChild(statusDiv);
  126.  
  127. // Ajout de l'élément de zoom dans le conteneur principal
  128. const zoomDiv = document.createElement('div');
  129. zoomDiv.id = 'bot_zoom_overlay';
  130. zoomDiv.textContent = `Zoom: ${window.zoomMultiplier.toFixed(1)} (a to zoom, e to zoom out, z to reset)`;
  131. overlayContainer.appendChild(zoomDiv);
  132.  
  133. const coordsDiv = document.createElement('div');
  134. coordsDiv.id = 'bot_coords_overlay';
  135. coordsDiv.textContent = 'Coords: loading...';
  136. overlayContainer.appendChild(coordsDiv);
  137.  
  138. const enemyDiv = document.createElement('div');
  139. enemyDiv.id = 'bot_enemies_overlay';
  140. enemyDiv.textContent = 'Enemies: loading...';
  141. overlayContainer.appendChild(enemyDiv);
  142.  
  143. const nearEnemiesDiv = document.createElement('div');
  144. nearEnemiesDiv.id = 'bot_enemies_near_overlay';
  145. nearEnemiesDiv.textContent = 'Enemies (Near): loading...';
  146. overlayContainer.appendChild(nearEnemiesDiv);
  147.  
  148. const midEnemiesDiv = document.createElement('div');
  149. midEnemiesDiv.id = 'bot_enemies_mid_overlay';
  150. midEnemiesDiv.textContent = 'Enemies (Mid): loading...';
  151. overlayContainer.appendChild(midEnemiesDiv);
  152.  
  153. const farEnemiesDiv = document.createElement('div');
  154. farEnemiesDiv.id = 'bot_enemies_far_overlay';
  155. farEnemiesDiv.textContent = 'Enemies (Far): loading...';
  156. overlayContainer.appendChild(farEnemiesDiv);
  157.  
  158. const criticDangerDiv = document.createElement('div');
  159. criticDangerDiv.id = 'bot_critic_danger_overlay';
  160. criticDangerDiv.textContent = 'Danger: loading...';
  161. overlayContainer.appendChild(criticDangerDiv);
  162.  
  163. // Continuous overlay update via requestAnimationFrame
  164. function updateOverlay() {
  165. if (window.slither && typeof window.slither.xx === 'number') {
  166. statusDiv.textContent = IsBotActive ? 'Status: BOT ON (To Turn OFF - Press t)' : 'Status: BOT OFF (To Turn ON - Press t)';
  167. coordsDiv.textContent = `Coords: ${Math.round(window.slither.xx)} / ${Math.round(window.slither.yy)}`;
  168. criticDangerDiv.textContent = `Danger: ${criticDanger}`;
  169. }
  170. if (Array.isArray(window.slithers) && window.slither) {
  171. const self = window.slither;
  172. // Building enemy lists based on distance from their body points
  173. const nearEnemies = [];
  174. const midEnemies = [];
  175. const farEnemies = [];
  176. window.slithers.forEach(e => {
  177. if (!e || typeof e.xx !== 'number' || typeof e.yy !== 'number' || e.xx === self.xx)
  178. return;
  179. const bodyPoints = getEnemyBodyPoints(e);
  180. let minDistance = Infinity;
  181. let closestPoint = null;
  182. bodyPoints.forEach(p => {
  183. const dx = p.xx - self.xx;
  184. const dy = p.yy - self.yy;
  185. const dist = Math.sqrt(dx * dx + dy * dy);
  186. if (dist < minDistance) {
  187. minDistance = dist;
  188. closestPoint = p;
  189. }
  190. });
  191. if (closestPoint) {
  192. if (minDistance < 300) {
  193. nearEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
  194. } else if (minDistance >= 300 && minDistance <= 700) {
  195. midEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
  196. } else if (minDistance > 700) {
  197. farEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
  198. }
  199. }
  200. });
  201. enemyDiv.textContent = 'Enemies: ' + window.slithers.length;
  202. nearEnemiesDiv.textContent = 'Enemies (Near): ' + nearEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
  203. midEnemiesDiv.textContent = 'Enemies (Mid): ' + midEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
  204. farEnemiesDiv.textContent = 'Enemies (Far): ' + farEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
  205. }
  206. requestAnimationFrame(updateOverlay);
  207. }
  208. requestAnimationFrame(updateOverlay);
  209. })();
  210.  
  211. /*
  212. ===================================================
  213. Section 4: World to Screen Coordinate Conversion
  214. ===================================================
  215. Utility function to convert game coordinates
  216. (in "world") to screen coordinates.
  217. */
  218. const worldToScreen = (xx, yy) => {
  219. const mapX = (xx - window.view_xx) * window.gsc + window.mww2;
  220. const mapY = (yy - window.view_yy) * window.gsc + window.mhh2;
  221. return { x: mapX, y: mapY };
  222. };
  223.  
  224. /*
  225. ===================================================
  226. Section 5: Enemy Processing
  227. ===================================================
  228. Functions to extract enemy body points and
  229. calculate line color based on distance.
  230. */
  231.  
  232. // Gets enemy body points by traversing its segments
  233. function getEnemyBodyPoints(enemy) {
  234. const points = [];
  235. if (!enemy.pts) return points;
  236.  
  237. for (const segment of enemy.pts) {
  238. if (!segment.fxs || !segment.fys) continue;
  239.  
  240. // Sampling: we get about 10% of the segment points
  241. const step = Math.max(1, Math.floor(segment.fxs.length / 10));
  242. for (let i = 0; i < segment.fxs.length; i += step) {
  243. const x = segment.xx + segment.fxs[i];
  244. const y = segment.yy + segment.fys[i];
  245.  
  246. if (isFinite(x) && isFinite(y)) {
  247. points.push({ xx: x, yy: y });
  248. }
  249. }
  250. }
  251. return points;
  252. }
  253.  
  254. // Calculates a color transitioning from red (close) to green (far)
  255. function DangerColor(start, end) {
  256. const dx = end.x - start.x;
  257. const dy = end.y - start.y;
  258. const dist = Math.sqrt(dx * dx + dy * dy);
  259. const maxDist = 3000; // Maximum distance to fully transition to green
  260. const dangerRatio = Math.max(0, Math.min(1, 1 - dist / maxDist));
  261. const r = Math.floor(255 * dangerRatio);
  262. const g = Math.floor(255 * (1 - dangerRatio));
  263. return `rgb(${r},${g},0)`;
  264. }
  265.  
  266. /*
  267. ===================================================
  268. Section 6: Drawing Lines to Enemies and Food
  269. ===================================================
  270. Two functions to draw lines between the player and:
  271. - Enemies (by choosing the closest point of each enemy)
  272. - Food (with a custom color)
  273. */
  274. // Draws lines connecting the player to enemies
  275. function drawAllEnemyLines(start, enemyList) {
  276. let canvas = document.getElementById('bot-line-overlay');
  277. if (!canvas) {
  278. canvas = document.createElement('canvas');
  279. canvas.id = 'bot-line-overlay';
  280. canvas.style.cssText = `
  281. position: fixed;
  282. top: 0;
  283. left: 0;
  284. pointer-events: none;
  285. z-index: 9998;
  286. `;
  287. document.body.appendChild(canvas);
  288.  
  289. // Resize canvas when window is resized
  290. window.addEventListener('resize', () => {
  291. canvas.width = window.innerWidth;
  292. canvas.height = window.innerHeight;
  293. });
  294. canvas.width = window.innerWidth;
  295. canvas.height = window.innerHeight;
  296. }
  297.  
  298. const ctx = canvas.getContext('2d');
  299. ctx.clearRect(0, 0, canvas.width, canvas.height);
  300.  
  301. // Si le bot est OFF, on trie les ennemis par distance et on garde les 5 plus proches
  302. let enemiesToDraw = enemyList;
  303. if (!IsBotActive) {
  304. enemiesToDraw = enemyList
  305. .map(enemy => {
  306. const body_points = getEnemyBodyPoints(enemy);
  307. let min_dist = Infinity;
  308. body_points.forEach(p => {
  309. const dx = p.xx - window.slither.xx;
  310. const dy = p.yy - window.slither.yy;
  311. const d = dx * dx + dy * dy;
  312. if (d < min_dist) min_dist = d;
  313. });
  314. return { enemy, min_dist };
  315. })
  316. .sort((a, b) => a.min_dist - b.min_dist)
  317. .slice(0, 5)
  318. .map(obj => obj.enemy);
  319. }
  320.  
  321. enemiesToDraw.forEach(enemy => {
  322. const body_points = getEnemyBodyPoints(enemy);
  323. let min_dist = Infinity;
  324. let min_dist_point = null;
  325. body_points.forEach(p => {
  326. const screenPoint = worldToScreen(p.xx, p.yy);
  327. const dx = screenPoint.x - start.x;
  328. const dy = screenPoint.y - start.y;
  329. const d = dx * dx + dy * dy;
  330. if (d < min_dist && d > 0) {
  331. min_dist = d;
  332. min_dist_point = screenPoint;
  333. }
  334. });
  335. if (Logger < 100) {
  336. console.log('min_dist', min_dist);
  337. Logger++;
  338. }
  339. if (min_dist_point) {
  340. ctx.beginPath();
  341. ctx.moveTo(start.x, start.y);
  342. ctx.lineTo(min_dist_point.x, min_dist_point.y);
  343. ctx.strokeStyle = DangerColor(start, min_dist_point);
  344. ctx.lineWidth = 1.5;
  345. ctx.stroke();
  346. }
  347. });
  348. }
  349.  
  350.  
  351. // Draws lines connecting the player to food particles
  352. function drawAllFoodLines(start, foodList) {
  353. let canvas = document.getElementById('bot-line-overlay-food');
  354. if (!canvas) {
  355. canvas = document.createElement('canvas');
  356. canvas.id = 'bot-line-overlay-food';
  357. canvas.style.cssText = `
  358. position: fixed;
  359. top: 0;
  360. left: 0;
  361. pointer-events: none;
  362. z-index: 9997;
  363. `;
  364. document.body.appendChild(canvas);
  365.  
  366. window.addEventListener('resize', () => {
  367. canvas.width = window.innerWidth;
  368. canvas.height = window.innerHeight;
  369. });
  370. canvas.width = window.innerWidth;
  371. canvas.height = window.innerHeight;
  372. }
  373.  
  374. const ctx = canvas.getContext('2d');
  375. ctx.clearRect(0, 0, canvas.width, canvas.height);
  376.  
  377. foodList.forEach(food => {
  378. const end = worldToScreen(food.xx, food.yy);
  379. ctx.beginPath();
  380. ctx.moveTo(start.x, start.y);
  381. ctx.lineTo(end.x, end.y);
  382. ctx.strokeStyle = 'cyan';
  383. ctx.lineWidth = 1;
  384. ctx.stroke();
  385. });
  386. }
  387.  
  388. /*
  389. ===================================================
  390. Section 7: Animation Loop for Line Drawing
  391. ===================================================
  392. Uses requestAnimationFrame for smooth animation.
  393. */
  394. (function updateEnemyLines() {
  395. function update() {
  396. if (
  397. window.slither &&
  398. window.slither.xx !== undefined &&
  399. window.view_xx !== undefined &&
  400. Array.isArray(window.slithers)
  401. ) {
  402. const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
  403. const validEnemies = window.slithers.filter(e =>
  404. e &&
  405. typeof e.xx === 'number' &&
  406. typeof e.yy === 'number' &&
  407. window.slither.xx !== e.xx
  408. );
  409. drawAllEnemyLines(selfScreen, validEnemies);
  410. }
  411. requestAnimationFrame(update);
  412. }
  413. requestAnimationFrame(update);
  414. })();
  415.  
  416. (function updateFoodTargetLine() {
  417. let canvas = document.getElementById('bot-line-overlay-food');
  418. if (!canvas) {
  419. canvas = document.createElement('canvas');
  420. canvas.id = 'bot-line-overlay-food';
  421. canvas.style.cssText = `
  422. position: fixed;
  423. top: 0;
  424. left: 0;
  425. pointer-events: none;
  426. z-index: 9997;
  427. `;
  428. document.body.appendChild(canvas);
  429. canvas.width = window.innerWidth;
  430. canvas.height = window.innerHeight;
  431. window.addEventListener('resize', () => {
  432. canvas.width = window.innerWidth;
  433. canvas.height = window.innerHeight;
  434. });
  435. }
  436.  
  437. function update() {
  438. const ctx = canvas.getContext('2d');
  439. ctx.clearRect(0, 0, canvas.width, canvas.height);
  440. if (window.slither && typeof window.slither.xx === 'number' && targetFood) {
  441. const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
  442. const end = worldToScreen(targetFood.xx, targetFood.yy);
  443. ctx.beginPath();
  444. ctx.moveTo(selfScreen.x, selfScreen.y);
  445. ctx.lineTo(end.x, end.y);
  446. ctx.strokeStyle = 'cyan';
  447. ctx.lineWidth = 1;
  448. ctx.stroke();
  449. }
  450. requestAnimationFrame(update);
  451. }
  452. requestAnimationFrame(update);
  453. })();
  454.  
  455. /*
  456. ===================================================
  457. Section 8: Line between Snake and Real Mouse
  458. ===================================================
  459. Draws a magenta line between the snake and the real mouse position.
  460. */
  461. (function updateMouseLine() {
  462. let canvas = document.getElementById('bot-line-mouse');
  463. if (!canvas) {
  464. canvas = document.createElement('canvas');
  465. canvas.id = 'bot-line-mouse';
  466. canvas.style.cssText = `
  467. position: fixed;
  468. top: 0;
  469. left: 0;
  470. pointer-events: none;
  471. z-index: 9996;
  472. `;
  473. document.body.appendChild(canvas);
  474. canvas.width = window.innerWidth;
  475. canvas.height = window.innerHeight;
  476. window.addEventListener('resize', () => {
  477. canvas.width = window.innerWidth;
  478. canvas.height = window.innerHeight;
  479. });
  480. }
  481. function update() {
  482. const ctx = canvas.getContext('2d');
  483. ctx.clearRect(0, 0, canvas.width, canvas.height);
  484. if (window.slither && typeof window.slither.xx === 'number' && window.mousePos) {
  485. const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
  486. ctx.beginPath();
  487. ctx.moveTo(selfScreen.x, selfScreen.y);
  488. ctx.lineTo(window.mousePos.x, window.mousePos.y);
  489. ctx.strokeStyle = 'magenta';
  490. ctx.lineWidth = 2;
  491. ctx.stroke();
  492. }
  493. requestAnimationFrame(update);
  494. }
  495. requestAnimationFrame(update);
  496. })();
  497.  
  498. /*
  499. ===================================================
  500. Section 9: Line between Snake and Bot Mouse Position
  501. ===================================================
  502. Draws a yellow line between the snake and the bot's target position.
  503. */
  504. (function updateBotMouseLine() {
  505. let canvas = document.getElementById('bot-line-botmouse');
  506. if (!canvas) {
  507. canvas = document.createElement('canvas');
  508. canvas.id = 'bot-line-botmouse';
  509. canvas.style.cssText = `
  510. position: fixed;
  511. top: 0;
  512. left: 0;
  513. pointer-events: none;
  514. z-index: 9995;
  515. `;
  516. document.body.appendChild(canvas);
  517. canvas.width = window.innerWidth;
  518. canvas.height = window.innerHeight;
  519. window.addEventListener('resize', () => {
  520. canvas.width = window.innerWidth;
  521. canvas.height = window.innerHeight;
  522. });
  523. }
  524. function update() {
  525. const ctx = canvas.getContext('2d');
  526. ctx.clearRect(0, 0, canvas.width, canvas.height);
  527. if (window.slither && typeof window.slither.xx === 'number' && window.botTargetPos) {
  528. const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
  529. const targetScreen = worldToScreen(window.botTargetPos.x, window.botTargetPos.y);
  530. ctx.beginPath();
  531. ctx.moveTo(selfScreen.x, selfScreen.y);
  532. ctx.lineTo(targetScreen.x, targetScreen.y);
  533. ctx.strokeStyle = 'yellow';
  534. ctx.lineWidth = 2;
  535. ctx.stroke();
  536. }
  537. requestAnimationFrame(update);
  538. }
  539. requestAnimationFrame(update);
  540. })();
  541.  
  542. /*
  543. ===================================================
  544. Section 10: FoodBot - Automatic Movement Towards Food
  545. ===================================================
  546. Detects the closest enemy and chooses a food particle
  547. located in the opposite direction to move the mouse (and thus the snake).
  548. */
  549.  
  550. // Simulates a mouse movement event towards a given position in the world
  551. function moveMouseToward(worldX, worldY) {
  552. // Updates the bot's target position
  553. window.botTargetPos = { x: worldX, y: worldY };
  554.  
  555. const screenX = (worldX - window.view_xx) * window.gsc + window.mww2;
  556. const screenY = (worldY - window.view_yy) * window.gsc + window.mhh2;
  557.  
  558. const event = new MouseEvent('mousemove', {
  559. clientX: screenX,
  560. clientY: screenY,
  561. bubbles: true
  562. });
  563. window.dispatchEvent(event);
  564. }
  565.  
  566. // Declare a variable for the FoodBot interval
  567. let foodBotInterval = null;
  568.  
  569. // The function containing the FoodBot update code
  570. function foodBotUpdate() {
  571. if (
  572. window.slither &&
  573. typeof window.slither.xx === 'number' &&
  574. Array.isArray(window.foods)
  575. ) {
  576. const self = window.slither;
  577. const now = Date.now();
  578.  
  579. // Building the list of enemies with their closest body point
  580. let enemyList = [];
  581. if (Array.isArray(window.slithers)) {
  582. window.slithers.forEach(enemy => {
  583. if (!enemy || typeof enemy.xx !== 'number' || typeof enemy.yy !== 'number' || enemy.xx === self.xx)
  584. return;
  585. const bodyPoints = getEnemyBodyPoints(enemy);
  586. if (bodyPoints.length === 0) return;
  587. let bestPoint = null;
  588. let bestDistance = Infinity;
  589. let bestDx = 0, bestDy = 0;
  590. bodyPoints.forEach(p => {
  591. const dx = p.xx - self.xx;
  592. const dy = p.yy - self.yy;
  593. const d = Math.sqrt(dx * dx + dy * dy);
  594. if (d < bestDistance) {
  595. bestDistance = d;
  596. bestPoint = p;
  597. bestDx = dx;
  598. bestDy = dy;
  599. }
  600. });
  601. if (bestPoint) {
  602. enemyList.push({ point: bestPoint, distance: bestDistance, dx: bestDx, dy: bestDy });
  603. }
  604. });
  605. }
  606.  
  607. // Utility function to choose the best food in SAFE mode
  608. // This targets foods with the largest size and high local density (grouping)
  609. function chooseBestFood(foods) {
  610. // D'abord, filtrer les nourritures pour ne garder que celles à moins de 100 pixels du joueur
  611. const maxPlayerDistance = 300;
  612. const nearbyFoods = foods.filter(f => {
  613. if (!f || typeof f.xx !== 'number' || typeof f.yy !== 'number') return false;
  614. const dx = f.xx - self.xx;
  615. const dy = f.yy - self.yy;
  616. const d = Math.sqrt(dx * dx + dy * dy);
  617. return d <= maxPlayerDistance;
  618. });
  619.  
  620. // Si aucune nourriture à proximité, retourner null
  621. if (nearbyFoods.length === 0) return null;
  622.  
  623. let bestFood = null;
  624. let bestScore = -Infinity;
  625. const groupRadius = 60; // rayon pour déterminer le groupement
  626.  
  627. nearbyFoods.forEach(f => {
  628. if (!f || typeof f.xx !== 'number' || typeof f.yy !== 'number' || typeof f.sz !== 'number') return;
  629. let groupCount = 0;
  630.  
  631. // Compter combien d'autres nourritures sont proches de celle-ci
  632. nearbyFoods.forEach(other => {
  633. if (other === f) return;
  634. const dx = other.xx - f.xx;
  635. const dy = other.yy - f.yy;
  636. const d = Math.sqrt(dx * dx + dy * dy);
  637. if (d < groupRadius) {
  638. groupCount++;
  639. groupCount += 1/(d+1e-5) * 100;
  640. }
  641. });
  642.  
  643. const score = f.sz + groupCount; // combine taille et densité
  644. if (score > bestScore) {
  645. bestScore = score;
  646. bestFood = f;
  647. }
  648. });
  649.  
  650. return bestFood;
  651. }
  652.  
  653. // Filter the food list to exclude blacklisted ones
  654. let availableFoods = window.foods.filter(f => {
  655. return (
  656. f &&
  657. typeof f.xx === 'number' &&
  658. typeof f.yy === 'number' &&
  659. !(blacklistedFoods[`${f.xx}_${f.yy}`] && now < blacklistedFoods[`${f.xx}_${f.yy}`])
  660. );
  661. });
  662.  
  663. let target = null;
  664.  
  665. if (enemyList.length === 0) {
  666. // No nearby enemies (safe mode): target food with highest value (size + grouping)
  667. target = chooseBestFood(availableFoods);
  668. } else {
  669. // Separate enemies by distance
  670. const enemiesWithin300 = enemyList.filter(e => e.distance < 300);
  671. const enemiesBetween300And700 = enemyList.filter(e => e.distance >= 300 && e.distance <= 700);
  672. // Case 3: If there are one or more enemies in the <300 range, run away
  673. if (enemiesWithin300.length > 0) {
  674. let totalWeight = 0;
  675. let avgX = 0;
  676. let avgY = 0;
  677.  
  678. enemiesWithin300.forEach(e => {
  679. const weight = 1 / (e.distance + 1e-5); // Closer = more weight
  680. const normX = e.dx / e.distance;
  681. const normY = e.dy / e.distance;
  682. avgX += normX * weight;
  683. avgY += normY * weight;
  684. totalWeight += weight;
  685. });
  686.  
  687. if (totalWeight > 0) {
  688. avgX /= totalWeight;
  689. avgY /= totalWeight;
  690. }
  691.  
  692. const scale = 150;
  693. const runAwayX = self.xx - avgX * scale;
  694. const runAwayY = self.yy - avgY * scale;
  695. moveMouseToward(runAwayX, runAwayY);
  696. targetFood = null;
  697. return;
  698. }
  699.  
  700. // Case 2: No critical enemies (<300) but at least one between 300 and 700
  701. if (enemiesBetween300And700.length > 0) {
  702. enemiesBetween300And700.sort((a, b) => a.distance - b.distance);
  703. const closest = enemiesBetween300And700[0];
  704. // Calculate opposite vector from enemy body point
  705. const vecX = self.xx - closest.point.xx;
  706. const vecY = self.yy - closest.point.yy;
  707. const vecLength = Math.sqrt(vecX * vecX + vecY * vecY);
  708. const normX = vecLength ? vecX / vecLength : 0;
  709. const normY = vecLength ? vecY / vecLength : 0;
  710. // Only keep foods in the opposite direction
  711. const filteredFoods = availableFoods.filter(f => {
  712. const foodVecX = f.xx - self.xx;
  713. const foodVecY = f.yy - self.yy;
  714. const dot = foodVecX * normX + foodVecY * normY;
  715. return dot > 0;
  716. });
  717. target = filteredFoods.length ? chooseBestFood(filteredFoods) : chooseBestFood(availableFoods);
  718. } else {
  719. // Case 1: All enemies are beyond 700: choose nearest food
  720. target = chooseBestFood(availableFoods);
  721. }
  722. }
  723.  
  724. // Blacklist mechanism if the same target is aimed at for more than 2 seconds
  725. if (
  726. target &&
  727. targetFood &&
  728. target.xx === targetFood.xx &&
  729. target.yy === targetFood.yy
  730. ) {
  731. if (now - targetFoodTimestamp >= 2000) {
  732. const key = `${targetFood.xx}_${targetFood.yy}`;
  733. blacklistedFoods[key] = now + 2000;
  734. const alternatives = availableFoods.filter(
  735. f => !(f.xx === targetFood.xx && f.yy === targetFood.yy)
  736. );
  737. if (alternatives.length > 0) {
  738. target = chooseBestFood(alternatives);
  739. targetFoodTimestamp = now;
  740. } else {
  741. target = null;
  742. }
  743. }
  744. } else {
  745. targetFoodTimestamp = now;
  746. }
  747.  
  748. if (target) {
  749. moveMouseToward(target.xx, target.yy);
  750. targetFood = target;
  751. }
  752. }
  753. }
  754.  
  755. // Start FoodBot by launching the setInterval
  756. function startFoodBot() {
  757. if (!foodBotInterval) {
  758. foodBotInterval = setInterval(foodBotUpdate, 20);
  759. }
  760. }
  761.  
  762. // Stop FoodBot
  763. function stopFoodBot() {
  764. if (foodBotInterval) {
  765. clearInterval(foodBotInterval);
  766. foodBotInterval = null;
  767. }
  768. }
  769.  
  770. // On startup, if bot is enabled, launch FoodBot
  771. if (IsBotActive) {
  772. startFoodBot();
  773.  
  774. // Initialise Zoom overlay
  775. window.recursiveZoomUpdate();
  776. }
  777.  
  778. // Modifier le gestionnaire d'événements de touches pour ajouter les commandes de zoom
  779. document.addEventListener('keydown', (e) => {
  780. // Here we use the "t" key to toggle the bot (you can modify according to your needs)
  781. if (e.key.toLowerCase() === 't') {
  782. IsBotActive = !IsBotActive;
  783. if (IsBotActive) {
  784. startFoodBot();
  785. } else {
  786. stopFoodBot();
  787. }
  788. }
  789.  
  790. // Ajout des touches pour le zoom
  791. if (e.key.toLowerCase() === 'a') {
  792. window.adjustZoom(0.1);
  793. } else if (e.key.toLowerCase() === 'e') {
  794. window.adjustZoom(-0.1);
  795. } else if (e.key.toLowerCase() === 'z') {
  796. window.resetZoom();
  797. }
  798. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址