- // ==UserScript==
- // @name Slither Full Auto Bot (Responsive Overlay)
- // @namespace http://slither.com/io
- // @version 1.3
- // @description Slither.com/io Bot with improved overlay and comments
- // @author EliottValette
- // @match http://slither.com/io
- // @grant none
- // @license MIT
- // ==/UserScript==
-
- /*
- ===================================================
- Section 1: Utility Functions and Debugging
- ===================================================
- */
-
- // Custom log function (only displays if "logDebugging" is enabled)
- window.log = (...args) => window.logDebugging && console.log(...args);
-
- // Functions to save and load preferences in localStorage
- const savePreference = (key, value) => localStorage.setItem(key, value);
- const loadPreference = (key, def) => JSON.parse(localStorage.getItem(key)) ?? def;
-
- let Logger = 0;
- let IsBotActive = true;
- let targetFood = null;
- let targetFoodTimestamp = 0;
- let blacklistedFoods = {};
- let criticDanger = false;
-
- // Add listener to memorize real mouse position
- window.mousePos = { x: 0, y: 0 };
- document.addEventListener('mousemove', function(e) {
- window.mousePos = { x: e.clientX, y: e.clientY };
- });
-
- // Variable to memorize bot target position (the "bot mouse pose")
- window.botTargetPos = null;
-
- console.log('Bot Starting');
-
- /*
- ===================================================
- Section 2: Window Object Debug Scan
- ===================================================
- After 5 seconds, scans the window object to find
- potential snake objects (presence of xx and yy)
- */
- setTimeout(() => {
- for (let key in window) {
- try {
- let val = window[key];
- if (val && typeof val === 'object') {
- // Checks if the object has coordinates
- if ('xx' in val && 'yy' in val) {
- console.log(`🟢 Snake? -> window.${key}`, val);
- }
- // Checks if the object is an array of objects with coordinates
- if (Array.isArray(val) && val.length > 0 && val[0] && 'xx' in val[0] && 'yy' in val[0]) {
- console.log(`🍏 Array of objects with coords? -> window.${key}`, val);
- }
- }
- } catch (e) {
- // In case of error, move to next property
- }
- }
- }, 5000);
-
- /*
- ===================================================
- Section 3: Improved Interface Overlay
- ===================================================
- Creation of a unique container that displays bot status,
- coordinates and enemy count in real-time.
- */
- (function setupOverlayUI() {
- // Creation of main container with semi-transparent background
- const overlayContainer = document.createElement('div');
- overlayContainer.id = 'bot-overlay-container';
- overlayContainer.style.cssText = `
- position: fixed;
- top: 10px;
- left: 10px;
- background: rgba(0, 0, 0, 0.5);
- padding: 10px;
- border-radius: 5px;
- z-index: 9999;
- font-family: Arial, sans-serif;
- color: #FFF;
- font-size: 14px;
- `;
- document.body.appendChild(overlayContainer);
-
- // Creation of sub-elements for status, coordinates and enemy count
- const statusDiv = document.createElement('div');
- statusDiv.id = 'bot_status_overlay';
- statusDiv.textContent = 'Status: BOT ON (To Toggle - Press t)';
- overlayContainer.appendChild(statusDiv);
-
- const coordsDiv = document.createElement('div');
- coordsDiv.id = 'bot_coords_overlay';
- coordsDiv.textContent = 'Coords: loading...';
- overlayContainer.appendChild(coordsDiv);
-
- const enemyDiv = document.createElement('div');
- enemyDiv.id = 'bot_enemies_overlay';
- enemyDiv.textContent = 'Enemies: loading...';
- overlayContainer.appendChild(enemyDiv);
-
- const nearEnemiesDiv = document.createElement('div');
- nearEnemiesDiv.id = 'bot_enemies_near_overlay';
- nearEnemiesDiv.textContent = 'Enemies (Near): loading...';
- overlayContainer.appendChild(nearEnemiesDiv);
-
- const midEnemiesDiv = document.createElement('div');
- midEnemiesDiv.id = 'bot_enemies_mid_overlay';
- midEnemiesDiv.textContent = 'Enemies (Mid): loading...';
- overlayContainer.appendChild(midEnemiesDiv);
-
- const farEnemiesDiv = document.createElement('div');
- farEnemiesDiv.id = 'bot_enemies_far_overlay';
- farEnemiesDiv.textContent = 'Enemies (Far): loading...';
- overlayContainer.appendChild(farEnemiesDiv);
-
- const criticDangerDiv = document.createElement('div');
- criticDangerDiv.id = 'bot_critic_danger_overlay';
- criticDangerDiv.textContent = 'Danger: loading...';
- overlayContainer.appendChild(criticDangerDiv);
-
- // Continuous overlay update via requestAnimationFrame
- function updateOverlay() {
- if (window.slither && typeof window.slither.xx === 'number') {
- statusDiv.textContent = IsBotActive ? 'Status: BOT ON (To Turn OFF - Press t)' : 'Status: BOT OFF (To Turn ON - Press t)';
- coordsDiv.textContent = `Coords: ${Math.round(window.slither.xx)} / ${Math.round(window.slither.yy)}`;
- criticDangerDiv.textContent = `Danger: ${criticDanger}`;
- }
- if (Array.isArray(window.slithers) && window.slither) {
- const self = window.slither;
- // Building enemy lists based on distance from their body points
- const nearEnemies = [];
- const midEnemies = [];
- const farEnemies = [];
- window.slithers.forEach(e => {
- if (!e || typeof e.xx !== 'number' || typeof e.yy !== 'number' || e.xx === self.xx)
- return;
- const bodyPoints = getEnemyBodyPoints(e);
- let minDistance = Infinity;
- let closestPoint = null;
- bodyPoints.forEach(p => {
- const dx = p.xx - self.xx;
- const dy = p.yy - self.yy;
- const dist = Math.sqrt(dx * dx + dy * dy);
- if (dist < minDistance) {
- minDistance = dist;
- closestPoint = p;
- }
- });
- if (closestPoint) {
- if (minDistance < 300) {
- nearEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
- } else if (minDistance >= 300 && minDistance <= 700) {
- midEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
- } else if (minDistance > 700) {
- farEnemies.push({ enemy: e, dist: minDistance, point: closestPoint });
- }
- }
- });
- enemyDiv.textContent = 'Enemies: ' + window.slithers.length;
- nearEnemiesDiv.textContent = 'Enemies (Near): ' + nearEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
- midEnemiesDiv.textContent = 'Enemies (Mid): ' + midEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
- farEnemiesDiv.textContent = 'Enemies (Far): ' + farEnemies.map(e => e.enemy.id || `(${Math.round(e.point.xx)},${Math.round(e.point.yy)})`).join(', ');
- }
- requestAnimationFrame(updateOverlay);
- }
- requestAnimationFrame(updateOverlay);
- })();
-
- /*
- ===================================================
- Section 4: World to Screen Coordinate Conversion
- ===================================================
- Utility function to convert game coordinates
- (in "world") to screen coordinates.
- */
- const worldToScreen = (xx, yy) => {
- const mapX = (xx - window.view_xx) * window.gsc + window.mww2;
- const mapY = (yy - window.view_yy) * window.gsc + window.mhh2;
- return { x: mapX, y: mapY };
- };
-
- /*
- ===================================================
- Section 5: Enemy Processing
- ===================================================
- Functions to extract enemy body points and
- calculate line color based on distance.
- */
-
- // Gets enemy body points by traversing its segments
- function getEnemyBodyPoints(enemy) {
- const points = [];
- if (!enemy.pts) return points;
-
- for (const segment of enemy.pts) {
- if (!segment.fxs || !segment.fys) continue;
-
- // Sampling: we get about 10% of the segment points
- const step = Math.max(1, Math.floor(segment.fxs.length / 10));
- for (let i = 0; i < segment.fxs.length; i += step) {
- const x = segment.xx + segment.fxs[i];
- const y = segment.yy + segment.fys[i];
-
- if (isFinite(x) && isFinite(y)) {
- points.push({ xx: x, yy: y });
- }
- }
- }
- return points;
- }
-
- // Calculates a color transitioning from red (close) to green (far)
- function DangerColor(start, end) {
- const dx = end.x - start.x;
- const dy = end.y - start.y;
- const dist = Math.sqrt(dx * dx + dy * dy);
- const maxDist = 3000; // Maximum distance to fully transition to green
- const dangerRatio = Math.max(0, Math.min(1, 1 - dist / maxDist));
- const r = Math.floor(255 * dangerRatio);
- const g = Math.floor(255 * (1 - dangerRatio));
- return `rgb(${r},${g},0)`;
- }
-
- /*
- ===================================================
- Section 6: Drawing Lines to Enemies and Food
- ===================================================
- Two functions to draw lines between the player and:
- - Enemies (by choosing the closest point of each enemy)
- - Food (with a custom color)
- */
- // Draws lines connecting the player to enemies
- function drawAllEnemyLines(start, enemyList) {
- let canvas = document.getElementById('bot-line-overlay');
- if (!canvas) {
- canvas = document.createElement('canvas');
- canvas.id = 'bot-line-overlay';
- canvas.style.cssText = `
- position: fixed;
- top: 0;
- left: 0;
- pointer-events: none;
- z-index: 9998;
- `;
- document.body.appendChild(canvas);
-
- // Resize canvas when window is resized
- window.addEventListener('resize', () => {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- });
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- }
-
- const ctx = canvas.getContext('2d');
- ctx.clearRect(0, 0, canvas.width, canvas.height);
-
- // Si le bot est OFF, on trie les ennemis par distance et on garde les 5 plus proches
- let enemiesToDraw = enemyList;
- if (!IsBotActive) {
- enemiesToDraw = enemyList
- .map(enemy => {
- const body_points = getEnemyBodyPoints(enemy);
- let min_dist = Infinity;
- body_points.forEach(p => {
- const dx = p.xx - window.slither.xx;
- const dy = p.yy - window.slither.yy;
- const d = dx * dx + dy * dy;
- if (d < min_dist) min_dist = d;
- });
- return { enemy, min_dist };
- })
- .sort((a, b) => a.min_dist - b.min_dist)
- .slice(0, 5)
- .map(obj => obj.enemy);
- }
-
- enemiesToDraw.forEach(enemy => {
- const body_points = getEnemyBodyPoints(enemy);
- let min_dist = Infinity;
- let min_dist_point = null;
- body_points.forEach(p => {
- const screenPoint = worldToScreen(p.xx, p.yy);
- const dx = screenPoint.x - start.x;
- const dy = screenPoint.y - start.y;
- const d = dx * dx + dy * dy;
- if (d < min_dist && d > 0) {
- min_dist = d;
- min_dist_point = screenPoint;
- }
- });
- if (Logger < 100) {
- console.log('min_dist', min_dist);
- Logger++;
- }
- if (min_dist_point) {
- ctx.beginPath();
- ctx.moveTo(start.x, start.y);
- ctx.lineTo(min_dist_point.x, min_dist_point.y);
- ctx.strokeStyle = DangerColor(start, min_dist_point);
- ctx.lineWidth = 1.5;
- ctx.stroke();
- }
- });
- }
-
-
- // Draws lines connecting the player to food particles
- function drawAllFoodLines(start, foodList) {
- let canvas = document.getElementById('bot-line-overlay-food');
- if (!canvas) {
- canvas = document.createElement('canvas');
- canvas.id = 'bot-line-overlay-food';
- canvas.style.cssText = `
- position: fixed;
- top: 0;
- left: 0;
- pointer-events: none;
- z-index: 9997;
- `;
- document.body.appendChild(canvas);
-
- window.addEventListener('resize', () => {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- });
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- }
-
- const ctx = canvas.getContext('2d');
- ctx.clearRect(0, 0, canvas.width, canvas.height);
-
- foodList.forEach(food => {
- const end = worldToScreen(food.xx, food.yy);
- ctx.beginPath();
- ctx.moveTo(start.x, start.y);
- ctx.lineTo(end.x, end.y);
- ctx.strokeStyle = 'cyan';
- ctx.lineWidth = 1;
- ctx.stroke();
- });
- }
-
- /*
- ===================================================
- Section 7: Animation Loop for Line Drawing
- ===================================================
- Uses requestAnimationFrame for smooth animation.
- */
- (function updateEnemyLines() {
- function update() {
- if (
- window.slither &&
- window.slither.xx !== undefined &&
- window.view_xx !== undefined &&
- Array.isArray(window.slithers)
- ) {
- const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
- const validEnemies = window.slithers.filter(e =>
- e &&
- typeof e.xx === 'number' &&
- typeof e.yy === 'number' &&
- window.slither.xx !== e.xx
- );
- drawAllEnemyLines(selfScreen, validEnemies);
- }
- requestAnimationFrame(update);
- }
- requestAnimationFrame(update);
- })();
-
- (function updateFoodTargetLine() {
- let canvas = document.getElementById('bot-line-overlay-food');
- if (!canvas) {
- canvas = document.createElement('canvas');
- canvas.id = 'bot-line-overlay-food';
- canvas.style.cssText = `
- position: fixed;
- top: 0;
- left: 0;
- pointer-events: none;
- z-index: 9997;
- `;
- document.body.appendChild(canvas);
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- window.addEventListener('resize', () => {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- });
- }
-
- function update() {
- const ctx = canvas.getContext('2d');
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- if (window.slither && typeof window.slither.xx === 'number' && targetFood) {
- const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
- const end = worldToScreen(targetFood.xx, targetFood.yy);
- ctx.beginPath();
- ctx.moveTo(selfScreen.x, selfScreen.y);
- ctx.lineTo(end.x, end.y);
- ctx.strokeStyle = 'cyan';
- ctx.lineWidth = 1;
- ctx.stroke();
- }
- requestAnimationFrame(update);
- }
- requestAnimationFrame(update);
- })();
-
- /*
- ===================================================
- Section 8: Line between Snake and Real Mouse
- ===================================================
- Draws a magenta line between the snake and the real mouse position.
- */
- (function updateMouseLine() {
- let canvas = document.getElementById('bot-line-mouse');
- if (!canvas) {
- canvas = document.createElement('canvas');
- canvas.id = 'bot-line-mouse';
- canvas.style.cssText = `
- position: fixed;
- top: 0;
- left: 0;
- pointer-events: none;
- z-index: 9996;
- `;
- document.body.appendChild(canvas);
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- window.addEventListener('resize', () => {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- });
- }
- function update() {
- const ctx = canvas.getContext('2d');
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- if (window.slither && typeof window.slither.xx === 'number' && window.mousePos) {
- const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
- ctx.beginPath();
- ctx.moveTo(selfScreen.x, selfScreen.y);
- ctx.lineTo(window.mousePos.x, window.mousePos.y);
- ctx.strokeStyle = 'magenta';
- ctx.lineWidth = 2;
- ctx.stroke();
- }
- requestAnimationFrame(update);
- }
- requestAnimationFrame(update);
- })();
-
- /*
- ===================================================
- Section 9: Line between Snake and Bot Mouse Position
- ===================================================
- Draws a yellow line between the snake and the bot's target position.
- */
- (function updateBotMouseLine() {
- let canvas = document.getElementById('bot-line-botmouse');
- if (!canvas) {
- canvas = document.createElement('canvas');
- canvas.id = 'bot-line-botmouse';
- canvas.style.cssText = `
- position: fixed;
- top: 0;
- left: 0;
- pointer-events: none;
- z-index: 9995;
- `;
- document.body.appendChild(canvas);
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- window.addEventListener('resize', () => {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- });
- }
- function update() {
- const ctx = canvas.getContext('2d');
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- if (window.slither && typeof window.slither.xx === 'number' && window.botTargetPos) {
- const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
- const targetScreen = worldToScreen(window.botTargetPos.x, window.botTargetPos.y);
- ctx.beginPath();
- ctx.moveTo(selfScreen.x, selfScreen.y);
- ctx.lineTo(targetScreen.x, targetScreen.y);
- ctx.strokeStyle = 'yellow';
- ctx.lineWidth = 2;
- ctx.stroke();
- }
- requestAnimationFrame(update);
- }
- requestAnimationFrame(update);
- })();
-
- /*
- ===================================================
- Section 10: FoodBot - Automatic Movement Towards Food
- ===================================================
- Detects the closest enemy and chooses a food particle
- located in the opposite direction to move the mouse (and thus the snake).
- */
-
- // Simulates a mouse movement event towards a given position in the world
- function moveMouseToward(worldX, worldY) {
- // Updates the bot's target position
- window.botTargetPos = { x: worldX, y: worldY };
-
- const screenX = (worldX - window.view_xx) * window.gsc + window.mww2;
- const screenY = (worldY - window.view_yy) * window.gsc + window.mhh2;
-
- const event = new MouseEvent('mousemove', {
- clientX: screenX,
- clientY: screenY,
- bubbles: true
- });
- window.dispatchEvent(event);
- }
-
- // Declare a variable for the FoodBot interval
- let foodBotInterval = null;
-
- // The function containing the FoodBot update code
- function foodBotUpdate() {
- if (
- window.slither &&
- typeof window.slither.xx === 'number' &&
- Array.isArray(window.foods)
- ) {
- const self = window.slither;
- const now = Date.now();
-
- // Building the list of enemies with their closest body point
- let enemyList = [];
- if (Array.isArray(window.slithers)) {
- window.slithers.forEach(enemy => {
- if (!enemy || typeof enemy.xx !== 'number' || typeof enemy.yy !== 'number' || enemy.xx === self.xx)
- return;
- const bodyPoints = getEnemyBodyPoints(enemy);
- if (bodyPoints.length === 0) return;
- let bestPoint = null;
- let bestDistance = Infinity;
- let bestDx = 0, bestDy = 0;
- bodyPoints.forEach(p => {
- const dx = p.xx - self.xx;
- const dy = p.yy - self.yy;
- const d = Math.sqrt(dx * dx + dy * dy);
- if (d < bestDistance) {
- bestDistance = d;
- bestPoint = p;
- bestDx = dx;
- bestDy = dy;
- }
- });
- if (bestPoint) {
- enemyList.push({ point: bestPoint, distance: bestDistance, dx: bestDx, dy: bestDy });
- }
- });
- }
-
- // Utility function to choose the nearest food
- function chooseNearestFood(foods) {
- let bestFood = null;
- let bestFoodDist = Infinity;
- foods.forEach(f => {
- if (!f || typeof f.xx !== 'number' || typeof f.yy !== 'number') return;
- const dx = f.xx - self.xx;
- const dy = f.yy - self.yy;
- const d = Math.sqrt(dx * dx + dy * dy);
- if (d < bestFoodDist) {
- bestFoodDist = d;
- bestFood = f;
- }
- });
- return bestFood;
- }
-
- // Utility function to choose the best food in SAFE mode
- // This targets foods with the largest size and high local density (grouping)
- function chooseBestFood(foods) {
- let bestFood = null;
- let bestScore = -Infinity;
- const groupRadius = 100; // radius to determine grouping
- foods.forEach(f => {
- if (!f || typeof f.xx !== 'number' || typeof f.yy !== 'number' || typeof f.sz !== 'number') return;
- let groupCount = 0;
- foods.forEach(other => {
- if (other === f) return;
- const dx = other.xx - f.xx;
- const dy = other.yy - f.yy;
- const d = Math.sqrt(dx * dx + dy * dy);
- if (d < groupRadius) {
- groupCount++;
- }
- });
- const score = f.sz + groupCount; // combines size and density
- if (score > bestScore) {
- bestScore = score;
- bestFood = f;
- }
- });
- return bestFood;
- }
-
- // Filter the food list to exclude blacklisted ones
- let availableFoods = window.foods.filter(f => {
- return (
- f &&
- typeof f.xx === 'number' &&
- typeof f.yy === 'number' &&
- !(blacklistedFoods[`${f.xx}_${f.yy}`] && now < blacklistedFoods[`${f.xx}_${f.yy}`])
- );
- });
-
- let target = null;
-
- if (enemyList.length === 0) {
- // No nearby enemies (safe mode): target food with highest value (size + grouping)
- target = chooseBestFood(availableFoods);
- } else {
- // Separate enemies by distance
- const enemiesWithin300 = enemyList.filter(e => e.distance < 300);
- const enemiesBetween300And700 = enemyList.filter(e => e.distance >= 300 && e.distance <= 700);
- // Case 3: If there are one or more enemies in the <300 range, run away
- if (enemiesWithin300.length > 0) {
- let totalWeight = 0;
- let avgX = 0;
- let avgY = 0;
-
- enemiesWithin300.forEach(e => {
- const weight = 1 / (e.distance + 1e-5); // Closer = more weight
- const normX = e.dx / e.distance;
- const normY = e.dy / e.distance;
- avgX += normX * weight;
- avgY += normY * weight;
- totalWeight += weight;
- });
-
- if (totalWeight > 0) {
- avgX /= totalWeight;
- avgY /= totalWeight;
- }
-
- const scale = 150;
- const runAwayX = self.xx - avgX * scale;
- const runAwayY = self.yy - avgY * scale;
- moveMouseToward(runAwayX, runAwayY);
- targetFood = null;
- return;
- }
-
- // Case 2: No critical enemies (<300) but at least one between 300 and 700
- if (enemiesBetween300And700.length > 0) {
- enemiesBetween300And700.sort((a, b) => a.distance - b.distance);
- const closest = enemiesBetween300And700[0];
- // Calculate opposite vector from enemy body point
- const vecX = self.xx - closest.point.xx;
- const vecY = self.yy - closest.point.yy;
- const vecLength = Math.sqrt(vecX * vecX + vecY * vecY);
- const normX = vecLength ? vecX / vecLength : 0;
- const normY = vecLength ? vecY / vecLength : 0;
- // Only keep foods in the opposite direction
- const filteredFoods = availableFoods.filter(f => {
- const foodVecX = f.xx - self.xx;
- const foodVecY = f.yy - self.yy;
- const dot = foodVecX * normX + foodVecY * normY;
- return dot > 0;
- });
- target = filteredFoods.length ? chooseNearestFood(filteredFoods) : chooseNearestFood(availableFoods);
- } else {
- // Case 1: All enemies are beyond 700: choose nearest food
- target = chooseNearestFood(availableFoods);
- }
- }
-
- // Blacklist mechanism if the same target is aimed at for more than 2 seconds
- if (
- target &&
- targetFood &&
- target.xx === targetFood.xx &&
- target.yy === targetFood.yy
- ) {
- if (now - targetFoodTimestamp >= 2000) {
- const key = `${targetFood.xx}_${targetFood.yy}`;
- blacklistedFoods[key] = now + 2000;
- const alternatives = availableFoods.filter(
- f => !(f.xx === targetFood.xx && f.yy === targetFood.yy)
- );
- if (alternatives.length > 0) {
- target = chooseNearestFood(alternatives);
- targetFoodTimestamp = now;
- } else {
- target = null;
- }
- }
- } else {
- targetFoodTimestamp = now;
- }
-
- if (target) {
- moveMouseToward(target.xx, target.yy);
- targetFood = target;
- }
- }
- }
-
- // Start FoodBot by launching the setInterval
- function startFoodBot() {
- if (!foodBotInterval) {
- foodBotInterval = setInterval(foodBotUpdate, 20);
- }
- }
-
- // Stop FoodBot
- function stopFoodBot() {
- if (foodBotInterval) {
- clearInterval(foodBotInterval);
- foodBotInterval = null;
- }
- }
-
- // On startup, if bot is enabled, launch FoodBot
- if (IsBotActive) {
- startFoodBot();
- }
-
- document.addEventListener('keydown', (e) => {
- // Here we use the "t" key to toggle the bot (you can modify according to your needs)
- if (e.key.toLowerCase() === 't') {
- IsBotActive = !IsBotActive;
- if (IsBotActive) {
- startFoodBot();
- } else {
- stopFoodBot();
- }
- }
- });