Advertisement
Hocherntung

Ho chern tung#1 slither io

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