Slither.io Trainer Hack

A Trainer to help you play on slither.io.Reveal the positions of worms close to you.Shows where's the closest and biggest food near you, and can also create 2 danger zone circles around you.

当前为 2021-11-22 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Slither.io Trainer Hack
  3. // @namespace slithertrainer
  4. // @version 1.3
  5. // @description A Trainer to help you play on slither.io.Reveal the positions of worms close to you.Shows where's the closest and biggest food near you, and can also create 2 danger zone circles around you.
  6. // @author hacker09
  7. // @match http://slither.io/
  8. // @license Mozilla Public License Version 2.0
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. /*
  13. Copyright (c) 2016 Ermiya Eskandary & Théophile Cailliau and other contributors
  14. This Source Code Form is subject to the terms of the Mozilla Public
  15. License, v. 2.0. If a copy of the MPL was not distributed with this
  16. file, You can obtain one at http://mozilla.org/MPL/2.0/.
  17. */
  18.  
  19. const TARGET_FPS = 30;
  20.  
  21. window.log = function() {};
  22.  
  23. window.getSnakeLength = function() {
  24. return (Math.floor(
  25. 150 *
  26. (window.fpsls[window.snake.sct] + window.snake.fam / window.fmlts[window.snake.sct] - 1) -
  27. 50) / 10);
  28. };
  29. window.getSnakeWidth = function(sc) {
  30. if (sc === undefined) sc = window.snake.sc;
  31. return sc * 29.0;
  32. };
  33.  
  34. var canvas = window.canvas = (function() {
  35. return {
  36. // Ratio of screen size divided by canvas size.
  37. canvasRatio: {
  38. x: window.mc.width / window.ww,
  39. y: window.mc.height / window.hh
  40. },
  41.  
  42. // Convert snake-relative coordinates to absolute screen coordinates.
  43. mouseToScreen: function(point) {
  44. var screenX = point.x + (window.ww / 2);
  45. var screenY = point.y + (window.hh / 2);
  46. return { x: screenX, y: screenY };
  47. },
  48.  
  49. // Convert screen coordinates to canvas coordinates.
  50. screenToCanvas: function(point) {
  51. var canvasX = window.csc *
  52. (point.x * canvas.canvasRatio.x) - parseInt(window.mc.style.left);
  53. var canvasY = window.csc *
  54. (point.y * canvas.canvasRatio.y) - parseInt(window.mc.style.top);
  55. return { x: canvasX, y: canvasY };
  56. },
  57.  
  58. // Convert map coordinates to mouse coordinates.
  59. mapToMouse: function(point) {
  60. var mouseX = (point.x - window.snake.xx) * window.gsc;
  61. var mouseY = (point.y - window.snake.yy) * window.gsc;
  62. return { x: mouseX, y: mouseY };
  63. },
  64.  
  65. // Map cordinates to Canvas cordinate shortcut
  66. mapToCanvas: function(point) {
  67. var c = canvas.mapToMouse(point);
  68. c = canvas.mouseToScreen(c);
  69. c = canvas.screenToCanvas(c);
  70. return c;
  71. },
  72.  
  73. // Map to Canvas coordinate conversion for drawing circles.
  74. // Radius also needs to scale by .gsc
  75. circleMapToCanvas: function(circle) {
  76. var newCircle = canvas.mapToCanvas(circle);
  77. return canvas.circle(
  78. newCircle.x,
  79. newCircle.y,
  80. circle.radius * window.gsc
  81. );
  82. },
  83.  
  84. // Constructor for point type
  85. point: function(x, y) {
  86. var p = {
  87. x: Math.round(x),
  88. y: Math.round(y)
  89. };
  90.  
  91. return p;
  92. },
  93.  
  94. // Constructor for rect type
  95. rect: function(x, y, w, h) {
  96. var r = {
  97. x: Math.round(x),
  98. y: Math.round(y),
  99. width: Math.round(w),
  100. height: Math.round(h)
  101. };
  102.  
  103. return r;
  104. },
  105.  
  106. // Constructor for circle type
  107. circle: function(x, y, r) {
  108. var c = {
  109. x: Math.round(x),
  110. y: Math.round(y),
  111. radius: Math.round(r)
  112. };
  113.  
  114. return c;
  115. },
  116.  
  117. // Fast atan2
  118. fastAtan2: function(y, x) {
  119. const QPI = Math.PI / 4;
  120. const TQPI = 3 * Math.PI / 4;
  121. var r = 0.0;
  122. var angle = 0.0;
  123. var abs_y = Math.abs(y) + 1e-10;
  124. if (x < 0) {
  125. r = (x + abs_y) / (abs_y - x);
  126. angle = TQPI;
  127. } else {
  128. r = (x - abs_y) / (x + abs_y);
  129. angle = QPI;
  130. }
  131. angle += (0.1963 * r * r - 0.9817) * r;
  132. if (y < 0) {
  133. return -angle;
  134. }
  135.  
  136. return angle;
  137. },
  138.  
  139. // Adjusts zoom in response to the mouse wheel.
  140. setZoom: function(e) {
  141. // Scaling ratio
  142. if (window.gsc) {
  143. window.gsc *= Math.pow(0.9, e.wheelDelta / -120 || e.detail / 2 || 0);
  144. window.desired_gsc = window.gsc;
  145. }
  146. },
  147.  
  148. // Restores zoom to the default value.
  149. resetZoom: function() {
  150. window.gsc = 0.9;
  151. window.desired_gsc = 0.9;
  152. },
  153.  
  154. // Maintains Zoom
  155. maintainZoom: function() {
  156. if (window.desired_gsc !== undefined) {
  157. window.gsc = window.desired_gsc;
  158. }
  159. },
  160.  
  161. // Sets background to the given image URL.
  162. // Defaults to slither.io's own background.
  163. setBackground: function(url) {
  164. url = typeof url !== 'undefined' ? url : '/s/bg45.jpg';
  165. window.ii.src = url;
  166. },
  167.  
  168. // Draw a rectangle on the canvas.
  169. drawRect: function(rect, color, fill, alpha) {
  170. if (alpha === undefined) alpha = 1;
  171.  
  172. var context = window.mc.getContext('2d');
  173. var lc = canvas.mapToCanvas({x: rect.x, y: rect.y});
  174.  
  175. context.save();
  176. context.globalAlpha = alpha;
  177. context.strokeStyle = color;
  178. context.rect(lc.x, lc.y, rect.width * window.gsc, rect.height * window.gsc);
  179. context.stroke();
  180. if (fill) {
  181. context.fillStyle = color;
  182. context.fill();
  183. }
  184. context.restore();
  185. },
  186.  
  187. // Draw a circle on the canvas.
  188. drawCircle: function(circle, color, fill, alpha) {
  189. if (alpha === undefined) alpha = 1;
  190. if (circle.radius === undefined) circle.radius = 5;
  191.  
  192. var context = window.mc.getContext('2d');
  193. var drawCircle = canvas.circleMapToCanvas(circle);
  194.  
  195. context.save();
  196. context.globalAlpha = alpha;
  197. context.beginPath();
  198. context.strokeStyle = color;
  199. context.arc(drawCircle.x, drawCircle.y, drawCircle.radius, 0, Math.PI * 2);
  200. context.stroke();
  201. if (fill) {
  202. context.fillStyle = color;
  203. context.fill();
  204. }
  205. context.restore();
  206. },
  207.  
  208. // Draw an angle.
  209. // @param {number} start -- where to start the angle
  210. // @param {number} angle -- width of the angle
  211. // @param {bool} danger -- green if false, red if true
  212. drawAngle: function(start, angle, color, fill, alpha) {
  213. if (alpha === undefined) alpha = 0.6;
  214.  
  215. var context = window.mc.getContext('2d');
  216.  
  217. context.save();
  218. context.globalAlpha = alpha;
  219. context.beginPath();
  220. context.moveTo(window.mc.width / 2, window.mc.height / 2);
  221. context.arc(window.mc.width / 2, window.mc.height / 2, window.gsc * 100, start, angle);
  222. context.lineTo(window.mc.width / 2, window.mc.height / 2);
  223. context.closePath();
  224. context.stroke();
  225. if (fill) {
  226. context.fillStyle = color;
  227. context.fill();
  228. }
  229. context.restore();
  230. },
  231.  
  232. // Draw a line on the canvas.
  233. drawLine: function(p1, p2, color, width) {
  234. if (width === undefined) width = 5;
  235.  
  236. var context = window.mc.getContext('2d');
  237. var dp1 = canvas.mapToCanvas(p1);
  238. var dp2 = canvas.mapToCanvas(p2);
  239.  
  240. context.save();
  241. context.beginPath();
  242. context.lineWidth = width * window.gsc;
  243. context.strokeStyle = color;
  244. context.moveTo(dp1.x, dp1.y);
  245. context.lineTo(dp2.x, dp2.y);
  246. context.stroke();
  247. context.restore();
  248. },
  249.  
  250. // Given the start and end of a line, is point left.
  251. isLeft: function(start, end, point) {
  252. return ((end.x - start.x) * (point.y - start.y) -
  253. (end.y - start.y) * (point.x - start.x)) > 0;
  254.  
  255. },
  256.  
  257. // Get distance squared
  258. getDistance2: function(x1, y1, x2, y2) {
  259. var distance2 = Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2);
  260. return distance2;
  261. },
  262.  
  263. getDistance2FromSnake: function(point) {
  264. point.distance = canvas.getDistance2(window.snake.xx, window.snake.yy,
  265. point.xx, point.yy);
  266. return point;
  267. },
  268.  
  269. // Check if point in Rect
  270. pointInRect: function(point, rect) {
  271. if (rect.x <= point.x && rect.y <= point.y &&
  272. rect.x + rect.width >= point.x && rect.y + rect.height >= point.y) {
  273. return true;
  274. }
  275. return false;
  276. },
  277.  
  278. // Check if circles intersect
  279. circleIntersect: function(circle1, circle2) {
  280. var bothRadii = circle1.radius + circle2.radius;
  281.  
  282. // Pretends the circles are squares for a quick collision check.
  283. // If it collides, do the more expensive circle check.
  284. if (circle1.x + bothRadii > circle2.x &&
  285. circle1.y + bothRadii > circle2.y &&
  286. circle1.x < circle2.x + bothRadii &&
  287. circle1.y < circle2.y + bothRadii) {
  288.  
  289. var distance2 = canvas.getDistance2(circle1.x, circle1.y, circle2.x, circle2.y);
  290.  
  291. if (distance2 < bothRadii * bothRadii) {
  292. if (window.visualDebugging) {
  293. var collisionPointCircle = canvas.circle(
  294. ((circle1.x * circle2.radius) + (circle2.x * circle1.radius)) /
  295. bothRadii,
  296. ((circle1.y * circle2.radius) + (circle2.y * circle1.radius)) /
  297. bothRadii,
  298. 5
  299. );
  300. canvas.drawCircle(circle2, 'red', true);
  301. canvas.drawCircle(collisionPointCircle, 'cyan', true);
  302. }
  303. return true;
  304. }
  305. }
  306. return false;
  307. }
  308. };
  309. })();
  310.  
  311. var bot = window.bot = (function() {
  312. return {
  313. isBotRunning: false,
  314. isBotEnabled: true,
  315. lookForFood: false,
  316. collisionPoints: [],
  317. collisionAngles: [],
  318. scores: [],
  319. foodTimeout: undefined,
  320. sectorBoxSide: 0,
  321. defaultAccel: 0,
  322. sectorBox: {},
  323. currentFood: {},
  324. MID_X: 0,
  325. MID_Y: 0,
  326. MAP_R: 0,
  327.  
  328. quickRespawn: function() {
  329. window.dead_mtm = 0;
  330. window.login_fr = 0;
  331.  
  332. bot.isBotRunning = false;
  333. window.forcing = true;
  334. window.connect();
  335. window.forcing = false;
  336. },
  337.  
  338. // Avoid headPoint
  339. avoidHeadPoint: function(collisionPoint) {},
  340.  
  341. // Avoid collison point by ang
  342. // ang radians <= Math.PI (180deg)
  343. avoidCollisionPoint: function(collisionPoint, ang) {
  344. },
  345.  
  346. // Sorting by property 'distance'
  347. sortDistance: function(a, b) {
  348. return a.distance - b.distance;
  349. },
  350.  
  351. // get collision angle index, expects angle +/i 0 to Math.PI
  352. getAngleIndex: function(angle) {
  353. const ARCSIZE = Math.PI / 4;
  354. var index;
  355.  
  356. if (angle < 0) {
  357. angle += 2 * Math.PI;
  358. }
  359.  
  360. index = Math.round(angle * (1 / ARCSIZE));
  361.  
  362. if (index === (2 * Math.PI) / ARCSIZE) {
  363. return 0;
  364. }
  365. return index;
  366. },
  367.  
  368. // Add to collisionAngles if distance is closer
  369. addCollisionAngle: function(sp) {
  370. var ang = canvas.fastAtan2(
  371. Math.round(sp.yy - window.snake.yy),
  372. Math.round(sp.xx - window.snake.xx));
  373. var aIndex = bot.getAngleIndex(ang);
  374.  
  375. var actualDistance = Math.round(
  376. sp.distance - (Math.pow(window.getSnakeWidth(window.snakes[sp.snake].sc), 2) / 2));
  377.  
  378. if (bot.collisionAngles[aIndex] === undefined) {
  379. bot.collisionAngles[aIndex] = {
  380. x: Math.round(sp.xx),
  381. y: Math.round(sp.yy),
  382. ang: ang,
  383. snake: sp.snake,
  384. distance: actualDistance
  385. };
  386. } else if (bot.collisionAngles[aIndex].distance > sp.distance) {
  387. bot.collisionAngles[aIndex].x = Math.round(sp.xx);
  388. bot.collisionAngles[aIndex].y = Math.round(sp.yy);
  389. bot.collisionAngles[aIndex].ang = ang;
  390. bot.collisionAngles[aIndex].snake = sp.snake;
  391. bot.collisionAngles[aIndex].distance = actualDistance;
  392. }
  393. },
  394.  
  395. // Get closest collision point per snake.
  396. getCollisionPoints: function() {
  397. var scPoint;
  398.  
  399. bot.collisionPoints = [];
  400. bot.collisionAngles = [];
  401.  
  402.  
  403. for (var snake = 0, ls = window.snakes.length; snake < ls; snake++) {
  404. scPoint = undefined;
  405.  
  406. if (window.snakes[snake].id !== window.snake.id &&
  407. window.snakes[snake].alive_amt === 1) {
  408. if (window.visualDebugging) {
  409. canvas.drawCircle(canvas.circle(
  410. window.snakes[snake].xx,
  411. window.snakes[snake].yy,
  412. window.getSnakeWidth(window.snakes[snake].sc) / 2),
  413. 'red', false);
  414. }
  415. scPoint = {
  416. xx: window.snakes[snake].xx,
  417. yy: window.snakes[snake].yy,
  418. snake: snake
  419. };
  420. canvas.getDistance2FromSnake(scPoint);
  421. bot.addCollisionAngle(scPoint);
  422.  
  423. for (var pts = 0, lp = window.snakes[snake].pts.length; pts < lp; pts++) {
  424. if (!window.snakes[snake].pts[pts].dying &&
  425. canvas.pointInRect(
  426. {x: window.snakes[snake].pts[pts].xx,
  427. y: window.snakes[snake].pts[pts].yy}, bot.sectorBox)
  428. ) {
  429. var collisionPoint = {
  430. xx: window.snakes[snake].pts[pts].xx,
  431. yy: window.snakes[snake].pts[pts].yy,
  432. snake: snake
  433. };
  434.  
  435. if (window.visualDebugging && true === false) {
  436. canvas.drawCircle(canvas.circle(
  437. collisionPoint.xx,
  438. collisionPoint.yy,
  439. window.getSnakeWidth(window.snakes[snake].sc) / 2),
  440. '#00FF00', false);
  441. }
  442.  
  443. canvas.getDistance2FromSnake(collisionPoint);
  444. bot.addCollisionAngle(collisionPoint);
  445.  
  446. if (scPoint === undefined ||
  447. scPoint.distance > collisionPoint.distance) {
  448. scPoint = collisionPoint;
  449. }
  450. }
  451. }
  452. }
  453. if (scPoint !== undefined) {
  454. bot.collisionPoints.push(scPoint);
  455. if (window.visualDebugging) {
  456. canvas.drawCircle(canvas.circle(
  457. scPoint.xx,
  458. scPoint.yy,
  459. window.getSnakeWidth(window.snakes[scPoint.snake].sc) / 2
  460. ), 'red', false);
  461. }
  462. }
  463. }
  464.  
  465. if (canvas.getDistance2(bot.MID_X, bot.MID_Y, window.snake.xx, window.snake.yy) >
  466. Math.pow(bot.MAP_R - 1000, 2)) {
  467. var midAng = canvas.fastAtan2(
  468. window.snake.yy - bot.MID_X, window.snake.xx - bot.MID_Y);
  469. scPoint = {
  470. xx: bot.MID_X + bot.MAP_R * Math.cos(midAng),
  471. yy: bot.MID_Y + bot.MAP_R * Math.sin(midAng),
  472. snake: -1
  473. };
  474. bot.collisionPoints.push(scPoint);
  475. if (window.visualDebugging) {
  476. canvas.drawCircle(canvas.circle(
  477. scPoint.xx,
  478. scPoint.yy,
  479. window.getSnakeWidth(1) * 5
  480. ), 'yellow', false);
  481. }
  482. }
  483.  
  484.  
  485. bot.collisionPoints.sort(bot.sortDistance);
  486. if (window.visualDebugging) {
  487. for (var i = 0; i < bot.collisionAngles.length; i++) {
  488. if (bot.collisionAngles[i] !== undefined) {
  489. canvas.drawLine(
  490. {x: window.snake.xx, y: window.snake.yy},
  491. {x: bot.collisionAngles[i].x, y: bot.collisionAngles[i].y},
  492. '#99ffcc', 2);
  493. }
  494. }
  495. }
  496. },
  497.  
  498. // Checks to see if you are going to collide with anything in the collision detection radius
  499. checkCollision: function(r) {
  500. if (!window.collisionDetection) return false;
  501.  
  502. r = Number(r);
  503. var xx = Number(window.snake.xx.toFixed(3));
  504. var yy = Number(window.snake.yy.toFixed(3));
  505.  
  506. window.snake.cos = Math.cos(window.snake.ang).toFixed(3);
  507. window.snake.sin = Math.sin(window.snake.ang).toFixed(3);
  508.  
  509. const speedMult = window.snake.sp / 5.78;
  510. const widthMult = window.getSnakeWidth();
  511.  
  512. var headCircle = canvas.circle(
  513. xx, yy,
  514. speedMult * r / 2 * widthMult / 2
  515. );
  516.  
  517. var fullHeadCircle = canvas.circle(
  518. xx, yy,
  519. r * widthMult / 2
  520. );
  521.  
  522. var sidecircle_r = canvas.circle(
  523. window.snake.lnp.xx -
  524. ((window.snake.lnp.yy + window.snake.sin * window.getSnakeWidth()) -
  525. window.snake.lnp.yy),
  526. window.snake.lnp.yy +
  527. ((window.snake.lnp.xx + window.snake.cos * window.getSnakeWidth()) -
  528. window.snake.lnp.xx),
  529. window.getSnakeWidth() * speedMult
  530. );
  531.  
  532. var sidecircle_l = canvas.circle(
  533. window.snake.lnp.xx +
  534. ((window.snake.lnp.yy + window.snake.sin * window.getSnakeWidth()) -
  535. window.snake.lnp.yy),
  536. window.snake.lnp.yy -
  537. ((window.snake.lnp.xx + window.snake.cos * window.getSnakeWidth()) -
  538. window.snake.lnp.xx),
  539. window.getSnakeWidth() * speedMult
  540. );
  541.  
  542. window.snake.sidecircle_r = sidecircle_r;
  543. window.snake.sidecircle_l = sidecircle_l;
  544.  
  545. if (window.visualDebugging) {
  546. canvas.drawCircle(fullHeadCircle, 'red');
  547. canvas.drawCircle(headCircle, 'blue', false);
  548. // canvas.drawCircle(sidecircle_r, 'orange', true, 0.3);
  549. // canvas.drawCircle(sidecircle_l, 'orange', true, 0.3);
  550. }
  551.  
  552. bot.getCollisionPoints();
  553. if (bot.collisionPoints.length === 0) return false;
  554.  
  555. for (var i = 0; i < bot.collisionPoints.length; i++) {
  556. // -1 snake is special case for non snake object.
  557. var colR = bot.collisionPoints[i].snake === -1 ? window.getSnakeWidth(1) * 5 :
  558. window.getSnakeWidth(window.snakes[bot.collisionPoints[i].snake].sc) / 2;
  559.  
  560. var collisionCircle = canvas.circle(
  561. bot.collisionPoints[i].xx,
  562. bot.collisionPoints[i].yy,
  563. colR
  564. );
  565.  
  566. if (canvas.circleIntersect(headCircle, collisionCircle)) {
  567. window.setAcceleration(bot.defaultAccel);
  568. bot.avoidCollisionPoint(bot.collisionPoints[i]);
  569. return true;
  570. }
  571.  
  572. if (bot.collisionPoints[i].snake !== -1) {
  573. var eHeadCircle = canvas.circle(
  574. window.snakes[bot.collisionPoints[i].snake].xx,
  575. window.snakes[bot.collisionPoints[i].snake].yy,
  576. colR
  577. );
  578. }
  579. }
  580. window.setAcceleration(bot.defaultAccel);
  581. return false;
  582. },
  583.  
  584. sortScore: function(a, b) {
  585. return b.score - a.score;
  586. },
  587.  
  588. // 2.546 ~ 1 / (Math.PI / 8) - round angle difference up to nearest 22.5 degrees.
  589. // Round food up to nearest 5, square for distance^2
  590. scoreFood: function(f) {
  591. f.score = Math.pow(Math.ceil(f.sz / 5) * 5, 2) /
  592. f.distance / (Math.ceil(f.da * 2.546) / 2.546);
  593. },
  594.  
  595. computeFoodGoal: function() {
  596. var foodClusters = [];
  597. var foodGetIndex = [];
  598. var fi = 0;
  599. var sw = window.getSnakeWidth();
  600.  
  601. for (var i = 0; i < window.foods.length && window.foods[i] !== null; i++) {
  602. var a;
  603. var da;
  604. var distance;
  605. var sang = window.snake.ehang;
  606. var f = window.foods[i];
  607.  
  608. if (!f.eaten &&
  609. !(
  610. canvas.circleIntersect(
  611. canvas.circle(f.xx, f.yy, 2),
  612. window.snake.sidecircle_l) ||
  613. canvas.circleIntersect(
  614. canvas.circle(f.xx, f.yy, 2),
  615. window.snake.sidecircle_r))) {
  616.  
  617. var cx = Math.round(Math.round(f.xx / sw) * sw);
  618. var cy = Math.round(Math.round(f.yy / sw) * sw);
  619. var csz = Math.round(f.sz);
  620.  
  621. if (foodGetIndex[cx + '|' + cy] === undefined) {
  622. foodGetIndex[cx + '|' + cy] = fi;
  623. a = canvas.fastAtan2(cy - window.snake.yy, cx - window.snake.xx);
  624. da = Math.min(
  625. (2 * Math.PI) - Math.abs(a - sang), Math.abs(a - sang));
  626. distance = Math.round(
  627. canvas.getDistance2(cx, cy, window.snake.xx, window.snake.yy));
  628. foodClusters[fi] = {
  629. x: cx, y: cy, a: a, da: da, sz: csz, distance: distance, score: 0.0 };
  630. fi++;
  631. } else {
  632. foodClusters[foodGetIndex[cx + '|' + cy]].sz += csz;
  633. }
  634. }
  635. }
  636.  
  637. foodClusters.forEach(bot.scoreFood);
  638. foodClusters.sort(bot.sortScore);
  639.  
  640. for (i = 0; i < foodClusters.length; i++) {
  641. var aIndex = bot.getAngleIndex(foodClusters[i].a);
  642. if (bot.collisionAngles[aIndex] === undefined ||
  643. (bot.collisionAngles[aIndex].distance - Math.pow(window.getSnakeWidth(), 2) >
  644. foodClusters[i].distance && foodClusters[i].sz > 10)
  645. ) {
  646. bot.currentFood = foodClusters[i];
  647. return;
  648. }
  649. }
  650. bot.currentFood = {x: bot.MID_X, y: bot.MID_Y};
  651. },
  652.  
  653. foodAccel: function() {
  654. var aIndex = 0;
  655.  
  656. if (bot.currentFood && bot.currentFood.sz > 60) {
  657. aIndex = bot.getAngleIndex(bot.currentFood.a);
  658.  
  659. if (
  660. bot.collisionAngles[aIndex] && bot.collisionAngles[aIndex].distance >
  661. bot.currentFood.distance * 2) {
  662. return 1;
  663. }
  664.  
  665. if (bot.collisionAngles[aIndex] === undefined) {
  666. return 1;
  667. }
  668. }
  669.  
  670. return bot.defaultAccel;
  671. },
  672.  
  673. // Loop version of collision check
  674. collisionLoop: function() {
  675. if (bot.checkCollision(window.collisionRadiusMultiplier)) {
  676. bot.lookForFood = false;
  677. if (bot.foodTimeout) {
  678. window.clearTimeout(bot.foodTimeout);
  679. bot.foodTimeout = window.setTimeout(bot.foodTimer, 1000 / TARGET_FPS * 4);
  680. }
  681. } else {
  682. bot.lookForFood = true;
  683. if (bot.foodTimeout === undefined) {
  684. bot.foodTimeout = window.setTimeout(bot.foodTimer, 1000 / TARGET_FPS * 4);
  685. }
  686. window.setAcceleration(bot.foodAccel());
  687. }
  688. },
  689.  
  690. // Timer version of food check
  691. foodTimer: function() {
  692. if (window.playing && bot.lookForFood &&
  693. window.snake !== null && window.snake.alive_amt === 1) {
  694. bot.computeFoodGoal();
  695. window.goalCoordinates = bot.currentFood;
  696. }
  697. bot.foodTimeout = undefined;
  698. }
  699. };
  700. })();
  701.  
  702. var userInterface = window.userInterface = (function() {
  703. // Save the original slither.io functions so we can modify them, or reenable them later.
  704. var original_keydown = document.onkeydown;
  705. var original_onmouseDown = window.onmousedown;
  706. var original_oef = window.oef;
  707. var original_redraw = window.redraw;
  708. var original_onmousemove = window.onmousemove;
  709.  
  710. window.oef = function() {};
  711. window.redraw = function() {};
  712.  
  713. return {
  714. overlays: {},
  715.  
  716. initOverlays: function() {
  717. var botOverlay = document.createElement('div');
  718. botOverlay.style.position = 'fixed';
  719. botOverlay.style.right = '5px';
  720. botOverlay.style.bottom = '112px';
  721. botOverlay.style.width = '150px';
  722. botOverlay.style.height = '85px';
  723. // botOverlay.style.background = 'rgba(0, 0, 0, 0.5)';
  724. botOverlay.style.color = '#C0C0C0';
  725. botOverlay.style.fontFamily = 'Consolas, Verdana';
  726. botOverlay.style.zIndex = 999;
  727. botOverlay.style.fontSize = '14px';
  728. botOverlay.style.padding = '5px';
  729. botOverlay.style.borderRadius = '5px';
  730. botOverlay.className = 'nsi';
  731. document.body.appendChild(botOverlay);
  732.  
  733. var serverOverlay = document.createElement('div');
  734. serverOverlay.style.position = 'fixed';
  735. serverOverlay.style.right = '5px';
  736. serverOverlay.style.bottom = '5px';
  737. serverOverlay.style.width = '160px';
  738. serverOverlay.style.height = '14px';
  739. serverOverlay.style.color = '#C0C0C0';
  740. serverOverlay.style.fontFamily = 'Consolas, Verdana';
  741. serverOverlay.style.zIndex = 999;
  742. serverOverlay.style.fontSize = '14px';
  743. serverOverlay.className = 'nsi';
  744. document.body.appendChild(serverOverlay);
  745. var prefOverlay = document.createElement('div');
  746. prefOverlay.style.position = 'fixed';
  747. prefOverlay.style.left = '10px';
  748. prefOverlay.style.top = '75px';
  749. prefOverlay.style.width = '260px';
  750. prefOverlay.style.height = '210px';
  751. // prefOverlay.style.background = 'rgba(0, 0, 0, 0.5)';
  752. prefOverlay.style.color = '#C0C0C0';
  753. prefOverlay.style.fontFamily = 'Consolas, Verdana';
  754. prefOverlay.style.zIndex = 999;
  755. prefOverlay.style.fontSize = '14px';
  756. prefOverlay.style.padding = '5px';
  757. prefOverlay.style.borderRadius = '5px';
  758. prefOverlay.className = 'nsi';
  759. document.body.appendChild(prefOverlay);
  760.  
  761. var statsOverlay = document.createElement('div');
  762. statsOverlay.style.position = 'fixed';
  763. statsOverlay.style.left = '10px';
  764. statsOverlay.style.top = '295px';
  765. statsOverlay.style.width = '140px';
  766. statsOverlay.style.height = '210px';
  767. // statsOverlay.style.background = 'rgba(0, 0, 0, 0.5)';
  768. statsOverlay.style.color = '#C0C0C0';
  769. statsOverlay.style.fontFamily = 'Consolas, Verdana';
  770. statsOverlay.style.zIndex = 998;
  771. statsOverlay.style.fontSize = '14px';
  772. statsOverlay.style.padding = '5px';
  773. statsOverlay.style.borderRadius = '5px';
  774. statsOverlay.className = 'nsi';
  775. document.body.appendChild(statsOverlay);
  776.  
  777. userInterface.overlays.botOverlay = botOverlay;
  778. userInterface.overlays.serverOverlay = serverOverlay;
  779. userInterface.overlays.prefOverlay = prefOverlay;
  780. userInterface.overlays.statsOverlay = statsOverlay;
  781. },
  782.  
  783. toggleOverlays: function() {
  784. Object.keys(userInterface.overlays).forEach(function(okey) {
  785. var oVis = userInterface.overlays[okey].style.visibility !== 'hidden' ?
  786. 'hidden' : 'visible';
  787. userInterface.overlays[okey].style.visibility = oVis;
  788. window.visualDebugging = oVis === 'visible';
  789. });
  790. },
  791.  
  792. // Save variable to local storage
  793. savePreference: function(item, value) {
  794. window.localStorage.setItem(item, value);
  795. userInterface.onPrefChange();
  796. },
  797.  
  798. // Load a variable from local storage
  799. loadPreference: function(preference, defaultVar) {
  800. var savedItem = window.localStorage.getItem(preference);
  801. if (savedItem !== null) {
  802. if (savedItem === 'true') {
  803. window[preference] = true;
  804. } else if (savedItem === 'false') {
  805. window[preference] = false;
  806. } else {
  807. window[preference] = savedItem;
  808. }
  809. window.log('Setting found for ' + preference + ': ' + window[preference]);
  810. } else {
  811. window[preference] = defaultVar;
  812. window.log('No setting found for ' + preference +
  813. '. Used default: ' + window[preference]);
  814. }
  815. userInterface.onPrefChange();
  816. return window[preference];
  817. },
  818.  
  819. // Saves username when you click on "Play" button
  820. playButtonClickListener: function() {
  821. userInterface.saveNick();
  822. userInterface.loadPreference('autoRespawn', false);
  823. userInterface.onPrefChange();
  824. },
  825.  
  826. // Preserve nickname
  827. saveNick: function() {
  828. var nick = document.getElementById('nick').value;
  829. userInterface.savePreference('savedNick', nick);
  830. },
  831.  
  832. // Hide top score
  833. hideTop: function() {
  834. var nsidivs = document.querySelectorAll('div.nsi');
  835. for (var i = 0; i < nsidivs.length; i++) {
  836. if (nsidivs[i].style.top === '4px' && nsidivs[i].style.width === '300px') {
  837. nsidivs[i].style.visibility = 'hidden';
  838. bot.isTopHidden = true;
  839. window.topscore = nsidivs[i];
  840. }
  841. }
  842. },
  843.  
  844. // Store FPS data
  845. framesPerSecond: {
  846. fps: 0,
  847. fpsTimer: function() {
  848. if (window.playing && window.fps && window.lrd_mtm) {
  849. if (Date.now() - window.lrd_mtm > 970) {
  850. userInterface.framesPerSecond.fps = window.fps;
  851. }
  852. }
  853. }
  854. },
  855.  
  856. onkeydown: function(e) {
  857. // Original slither.io onkeydown function + whatever is under it
  858. original_keydown(e);
  859. if (window.playing) {
  860. // Letter `T` to toggle bot
  861. if (e.keyCode === 84) {
  862. bot.isBotEnabled = !bot.isBotEnabled;
  863. }
  864. // Letter 'U' to toggle debugging (console)
  865. if (e.keyCode === 85) {
  866. window.logDebugging = !window.logDebugging;
  867. console.log('Log debugging set to: ' + window.logDebugging);
  868. userInterface.savePreference('logDebugging', window.logDebugging);
  869. }
  870. // Letter 'Y' to toggle debugging (visual)
  871. if (e.keyCode === 89) {
  872. window.visualDebugging = !window.visualDebugging;
  873. console.log('Visual debugging set to: ' + window.visualDebugging);
  874. userInterface.savePreference('visualDebugging', window.visualDebugging);
  875. }
  876. // Letter 'I' to toggle autorespawn
  877. if (e.keyCode === 73) {
  878. window.autoRespawn = !window.autoRespawn;
  879. console.log('Automatic Respawning set to: ' + window.autoRespawn);
  880. userInterface.savePreference('autoRespawn', window.autoRespawn);
  881. }
  882. // Letter 'H' to toggle hidden mode
  883. if (e.keyCode === 72) {
  884. userInterface.toggleOverlays();
  885. }
  886. // Letter 'O' to change rendermode (visual)
  887. if (e.keyCode === 79) {
  888. userInterface.toggleMobileRendering(!window.mobileRender);
  889. }
  890. // Letter 'C' to toggle Collision detection / enemy avoidance
  891. if (e.keyCode === 67) {
  892. window.collisionDetection = !window.collisionDetection;
  893. console.log('collisionDetection set to: ' + window.collisionDetection);
  894. userInterface.savePreference('collisionDetection', window.collisionDetection);
  895. }
  896. // Letter 'A' to increase collision detection radius
  897. if (e.keyCode === 65) {
  898. window.collisionRadiusMultiplier++;
  899. console.log(
  900. 'collisionRadiusMultiplier set to: ' + window.collisionRadiusMultiplier);
  901. userInterface.savePreference(
  902. 'collisionRadiusMultiplier', window.collisionRadiusMultiplier);
  903. }
  904. // Letter 'S' to decrease collision detection radius
  905. if (e.keyCode === 83) {
  906. if (window.collisionRadiusMultiplier > 1) {
  907. window.collisionRadiusMultiplier--;
  908. console.log(
  909. 'collisionRadiusMultiplier set to: ' +
  910. window.collisionRadiusMultiplier);
  911. userInterface.savePreference(
  912. 'collisionRadiusMultiplier', window.collisionRadiusMultiplier);
  913. }
  914. }
  915. // Letter 'Z' to reset zoom
  916. if (e.keyCode === 90) {
  917. canvas.resetZoom();
  918. }
  919. // Letter 'Q' to quit to main menu
  920. if (e.keyCode === 81) {
  921. window.autoRespawn = false;
  922. userInterface.quit();
  923. }
  924. // 'ESC' to quickly respawn
  925. if (e.keyCode === 27) {
  926. bot.quickRespawn();
  927. }
  928. // Save nickname when you press "Enter"
  929. if (e.keyCode === 13) {
  930. userInterface.saveNick();
  931. }
  932. userInterface.onPrefChange();
  933. }
  934. },
  935.  
  936. // Manual mobile rendering
  937. toggleMobileRendering: function(mobileRendering) {
  938. window.mobileRender = mobileRendering;
  939. window.log('Mobile rendering set to: ' + window.mobileRender);
  940. userInterface.savePreference('mobileRender', window.mobileRender);
  941. // Set render mode
  942. if (window.mobileRender) {
  943. canvas.setBackground(
  944. 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs');
  945. window.render_mode = 1;
  946. window.want_quality = 0;
  947. window.high_quality = false;
  948. } else {
  949. canvas.setBackground();
  950. window.render_mode = 2;
  951. window.want_quality = 1;
  952. window.high_quality = true;
  953. }
  954. },
  955.  
  956. onPrefChange: function() {
  957. // Set static display options here.
  958. var oContent = [];
  959. var ht = userInterface.handleTextColor;
  960.  
  961. oContent.push('version: ' + GM_info.script.version);
  962. oContent.push('[T] Enable / disable bot: ' + ht(bot.isBotEnabled));
  963. oContent.push('[C] collision detection on/off: ' + ht(window.collisionDetection));
  964. oContent.push('[O] Mobile version on/off: ' + ht(window.mobileRender));
  965. oContent.push('[A/S] Radius multiplier (S-less, A-Greater): ' + window.collisionRadiusMultiplier);
  966. oContent.push('[I] Auto spawn on / off: ' + ht(window.autoRespawn));
  967. oContent.push('[Y] Visual debugging on / off: ' + ht(window.visualDebugging));
  968. oContent.push('[U] debug log: ' + ht(window.logDebugging));
  969. oContent.push('[Wheel(mouse)] Zoom (zoom in on top, zoom out down');
  970. oContent.push('[Z] Reset Zoom.');
  971. oContent.push('[ESC] Respawn');
  972. oContent.push('[Q] Exit to menu.');
  973.  
  974. userInterface.overlays.prefOverlay.innerHTML = oContent.join('<br/>');
  975. },
  976.  
  977. onFrameUpdate: function() {
  978. // Botstatus overlay
  979. var oContent = [];
  980.  
  981. if (window.playing && window.snake !== null) {
  982. oContent.push('fps: ' + userInterface.framesPerSecond.fps);
  983.  
  984. // Display the X and Y of the snake
  985. oContent.push('x: ' +
  986. (Math.round(window.snake.xx) || 0) + ' y: ' +
  987. (Math.round(window.snake.yy) || 0));
  988.  
  989. if (window.goalCoordinates) {
  990. oContent.push('target');
  991. oContent.push('x: ' + window.goalCoordinates.x + ' y: ' +
  992. window.goalCoordinates.y);
  993. if (window.goalCoordinates.sz) {
  994. oContent.push('sz: ' + window.goalCoordinates.sz);
  995. }
  996. }
  997.  
  998. if (window.bso !== undefined && userInterface.overlays.serverOverlay.innerHTML !==
  999. window.bso.ip + ':' + window.bso.po) {
  1000. userInterface.overlays.serverOverlay.innerHTML =
  1001. window.bso.ip + ':' + window.bso.po;
  1002. }
  1003. }
  1004.  
  1005. userInterface.overlays.botOverlay.innerHTML = oContent.join('<br/>');
  1006.  
  1007.  
  1008. if (window.playing && window.visualDebugging) {
  1009. // Only draw the goal when a bot has a goal.
  1010. if (window.goalCoordinates && bot.isBotEnabled) {
  1011. var headCoord = {x: window.snake.xx, y: window.snake.yy};
  1012. canvas.drawLine(
  1013. headCoord,
  1014. window.goalCoordinates,
  1015. 'green');
  1016. canvas.drawCircle(window.goalCoordinates, 'red', true);
  1017. }
  1018. }
  1019. },
  1020.  
  1021. oefTimer: function() {
  1022. var start = Date.now();
  1023. canvas.maintainZoom();
  1024. original_oef();
  1025. original_redraw();
  1026.  
  1027. if (window.playing && bot.isBotEnabled && window.snake !== null) {
  1028. window.onmousemove = function() { };
  1029. bot.isBotRunning = true;
  1030. bot.collisionLoop();
  1031. } else if (bot.isBotEnabled && bot.isBotRunning) {
  1032. bot.isBotRunning = false;
  1033. if (window.lastscore && window.lastscore.childNodes[1]) {
  1034. bot.scores.push(parseInt(window.lastscore.childNodes[1].innerHTML));
  1035. bot.scores.sort(function(a, b) { return b - a; });
  1036. userInterface.updateStats();
  1037. }
  1038.  
  1039. if (window.autoRespawn) {
  1040. window.connect();
  1041. }
  1042. }
  1043.  
  1044. if (!bot.isBotEnabled || bot.isBotRunning) {
  1045. window.onmousemove = original_onmousemove;
  1046. }
  1047.  
  1048. userInterface.onFrameUpdate();
  1049. setTimeout(userInterface.oefTimer, (1000 / TARGET_FPS) - (Date.now() - start));
  1050. },
  1051.  
  1052. // Quit to menu
  1053. quit: function() {
  1054. if (window.playing && window.resetGame) {
  1055. window.want_close_socket = true;
  1056. window.dead_mtm = 0;
  1057. if (window.play_btn) {
  1058. window.play_btn.setEnabled(true);
  1059. }
  1060. window.resetGame();
  1061. }
  1062. },
  1063.  
  1064. // Update the relation between the screen and the canvas.
  1065. onresize: function() {
  1066. window.resize();
  1067. // Canvas different size from the screen (often bigger).
  1068. canvas.canvasRatio = {
  1069. x: window.mc.width / window.ww,
  1070. y: window.mc.height / window.hh
  1071. };
  1072. },
  1073.  
  1074. handleTextColor: function(enabled) {
  1075. return '<span style=\"color:' +
  1076. (enabled ? 'green;\">enabled' : 'red;\">disabled') + '</span>';
  1077. }
  1078. };
  1079. })();
  1080.  
  1081. // Main
  1082. (function() {
  1083. window.play_btn.btnf.addEventListener('click', userInterface.playButtonClickListener);
  1084. document.onkeydown = userInterface.onkeydown;
  1085. window.onmousedown = userInterface.onmousedown;
  1086. window.addEventListener('mouseup', userInterface.onmouseup);
  1087. window.onresize = userInterface.onresize;
  1088.  
  1089. // Hide top score
  1090. userInterface.hideTop();
  1091.  
  1092. // Overlays
  1093. userInterface.initOverlays();
  1094.  
  1095. // Load preferences
  1096. userInterface.loadPreference('logDebugging', true);
  1097. userInterface.loadPreference('visualDebugging', true);
  1098. userInterface.loadPreference('autoRespawn', true);
  1099. userInterface.loadPreference('mobileRender', true);
  1100. userInterface.loadPreference('collisionDetection', true);
  1101. userInterface.loadPreference('collisionRadiusMultiplier', 10);
  1102. window.nick.value = userInterface.loadPreference('savedNick', 'Slither.io Trainer Hack');
  1103.  
  1104. // Listener for mouse wheel scroll - used for setZoom function
  1105. document.body.addEventListener('mousewheel', canvas.setZoom);
  1106. document.body.addEventListener('DOMMouseScroll', canvas.setZoom);
  1107.  
  1108. // Set render mode
  1109. if (window.mobileRender) {
  1110. userInterface.toggleMobileRendering(false);
  1111. } else {
  1112. userInterface.toggleMobileRendering(true);
  1113. }
  1114.  
  1115. // Unblocks all skins without the need for FB sharing.
  1116. window.localStorage.setItem('edttsg', '1');
  1117.  
  1118. // Remove social
  1119. window.social.remove();
  1120.  
  1121. // Maintain fps
  1122. setInterval(userInterface.framesPerSecond.fpsTimer, 80);
  1123.  
  1124. // Start!
  1125. userInterface.oefTimer();
  1126. })();

QingJ © 2025

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