SkidWare ModMenu - diep.io

Spinner, Aimbot, AutoFarm

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @license MIT
// @name         SkidWare ModMenu - diep.io
// @namespace    bo$$
// @version      v1.1.0
// @description  Spinner, Aimbot, AutoFarm
// @author       Dreamy @C:Mi300(Aimbot+Fov)
// @match        https://diep.io/*
// @match        https://staging.diep.io/*
// @match        https://diep-io.rivet.game/*
// @icon         https://gamesense.pub/favicon.ico
// @grant        none
// @run-at       document-start
// ==/UserScript==

// mi300's discord - https://discord.gg/S4CA5w9p8p
// my discord - https://discord.gg/NBN3jgQDGe
const FOV_UPDATE_INTERVAL = 16.6;
const FOV_LERP = 0.1;
let setFov = 0.5;
let foxv = 0.5;
let keyStates = new Map();

const onWheelEvent = event => {setFov += -Math.sign(event.deltaY) * 0.02 * Math.log10(setFov / 0.55 + 1)}
const onKeyDown = event => {keyStates.set(event.keyCode, 1)}
const onKeyUp = event => {keyStates.set(event.keyCode, 0)}

function updateFov(){
  if(typeof window.extern === 'undefined')return;
  if(!window.extern.doesHaveTank())return;
  if(keyStates.get(187)) setFov += 0.01 * Math.log10(setFov / 0.55 + 1);
  if(keyStates.get(189)) setFov -= 0.01 * Math.log10(setFov / 0.55 + 1);

  foxv += (setFov - foxv) * FOV_LERP;
  window.extern.setScreensizeZoom(1, foxv);
}
function init(){
  document.addEventListener("wheel", onWheelEvent);
  document.addEventListener("keydown", onKeyDown);
  document.addEventListener("keyup", onKeyUp);
  setInterval(updateFov, FOV_UPDATE_INTERVAL);
}
init();

let a;
class _a {
  constructor() {
    this.p = {};
    this.v = false;
    document.addEventListener("DOMContentLoaded", this.tu.bind(this));
  }

  tu() {
    if (this.v) return;
    this.v = true;
    const originalGetElementById = HTMLDocument.prototype.getElementById;
    HTMLDocument.prototype.getElementById = function (id) {
      const elem = originalGetElementById.call(document, id);
      if (id === "canvas") return wrapCanvas(elem);
      return elem;
    };

    const originalCreateElement = HTMLDocument.prototype.createElement;
    HTMLDocument.prototype.createElement = function (tag) {
      const elem = originalCreateElement.call(document, tag);
      if (tag === "canvas") return wrapCanvas(elem);
      return elem;
    };

    function wrapCanvas(origCanvas) {
      class HTMLCanvasElementProxy {}
      let proxyCanvas = new HTMLCanvasElementProxy();
      proxyCanvas.width = origCanvas.width;
      proxyCanvas.height = origCanvas.height;
      proxyCanvas.transferControlToOffscreen = origCanvas.transferControlToOffscreen.bind(origCanvas);
      proxyCanvas.toDataURL = origCanvas.toDataURL.bind(origCanvas);
      proxyCanvas.toBlob = origCanvas.toBlob.bind(origCanvas);
      proxyCanvas.captureStream = origCanvas.captureStream.bind(origCanvas);

      proxyCanvas.getContext = function (...args) {
        let ctx = origCanvas.getContext(...args);
        if (args[0] !== "2d") return ctx;
        return new Proxy(ctx, {
          get: function (target, prop) {
            const original = target[prop];
            if (typeof original !== "function") return original;
            if (Object.keys(a.p).includes(prop)) {
              return function (...pArgs) {
                let skip = false;
                a.p[prop].forEach((hook) => {
                  const result = hook(ctx, ...pArgs);
                  if (!result) {
                    skip = true;
                  } else {
                    [ctx, pArgs] = result;
                  }
                });
                if (skip) return;
                return original.apply(target, pArgs);
              };
            }
            return original.bind(target);
          },
          set: function (target, prop, value) {
            target[prop] = value;
            return true;
          },
        });
      };
      return proxyCanvas;
    }

    createUnifiedMenu();
  }

  _(methodName, hookFn) {
    if (Object.keys(a.p).includes(methodName)) {
      a.p[methodName].push(hookFn);
    } else {
      a.p[methodName] = [hookFn];
    }
  }
}
a = new _a();

let spinSpeed = 0.80; 
let isSpinning = false;
let spinAngle = 0;
let isShooting = false;
let isFiring = false;
let isAimbotActive = false;
let playerTank = "Tank";
let playerLevel = 1;
let playerX = 0;
let playerY = 0;
let arrowPos = [0, 0];
let minimapPos = [0, 0];
let minimapSize = [0, 0];
let fov = 0.5;
let text = [];
let tankShapes = [];
let lastPlayers = [];
let players = [];
let lastArc = [Infinity, Infinity];
let mousePressed = false;
let mouseLocked = false;
let mouseX = 0;
let mouseY = 0;
let isAutoFarm = false;  
let neutralSquares = [];  
let neutralPentagons = []; 
let neutralTriangles = [];
let farmPriority = "pentagon";
let isDebug = false;
let hasJoined = false;
const averageEnemyDodgeTime = 1750;
const destroyerAccuracy = true;
const playerVelocityPredictionSampleSize = 50;
const arenaSize = 26000;
const gameStyle = {
  ren_grid_base_alpha: 0.05,
  square: "#ffe869",
  triangle: "#fc7677",
  pentagon: "#768dfc",
  teamBlue: "#00b2e1",
  teamRed: "#f14e54",
  teamPurple: "#bf7ff5",
  teamGreen: "#00e16e",
};
let teamColor = "";
const bulletSpeedOffsets = {
  Skimmer: 0.5,
  Factory: 0.56,
  Annihilator: 0.7,
  Streamliner: 1.1,
  "Auto Gunner": 1.1,
  Gunner: 1.1,
  Predator: 1.4,
  Mothership: 0.48,
  Manager: 0.8,
  Hybrid: 0.7,
  Ranger: 1.5,
  Stalker: 1.5,
  Assassin: 1.5,
  Sniper: 1.5,
  Hunter: 1.4,
  Necromancer: 0.72,
  "Arena Closer": 2,
  Overlord: 0.8,
  Overseer: 0.8,
  Destroyer: 0.7,
};
const predatorStackTime = [
  [50, 500, 1400, 2800],
  [50, 500, 1300, 2700],
  [50, 400, 1200, 2450],
  [50, 300, 1100, 2200],
  [50, 300, 1000, 2100],
  [50, 300, 900, 1800],
  [50, 300, 800, 1700],
  [50, 300, 750, 1500],
];
const hunterStackTime = [
  [50, 1200],
  [50, 1100],
  [50, 1000],
  [50, 950],
  [50, 800],
  [50, 725],
  [50, 700],
  [50, 625],
];
const buildStatLevels = [
  2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
  23, 24, 25, 26, 27, 28, 30, 33, 36, 39, 42, 45,
];
const statNumbers = {
  1: "healthRegen",
  2: "maxHealth",
  3: "bodyDamage",
  4: "bulletSpeed",
  5: "bulletPenetration",
  6: "bulletDamage",
  7: "reload",
  8: "movementSpeed",
};

function getUpgrades() {
  let upgrades = 0;
  for (let i = 0; i < buildStatLevels.length; ++i) {
    upgrades++;
    if (playerLevel < buildStatLevels[i]) break;
  }
  return upgrades;
}
function canUpgrade() {
  const rawStats = window.extern.get_convar("game_stats_build");
  return getUpgrades() - 1 > rawStats.length;
}
function truncateStats() {
  const rawStats = window.extern.get_convar("game_stats_build");
  return rawStats.slice(0, getUpgrades());
}
function getStats() {
  const rawStats = window.extern.get_convar("game_stats_build");
  let stats = {
    healthRegen: 0,
    maxHealth: 0,
    bodyDamage: 0,
    bulletSpeed: 0,
    bulletPenetration: 0,
    bulletDamage: 0,
    reload: 0,
    movementSpeed: 0,
  };
  for (let i = 0; i < rawStats.length; ++i) {
    ++stats[statNumbers[rawStats[i]]];
  }
  return stats;
}

let forcingU = false;
function forceU() {
  if (canUpgrade()) {
    forcingU = true;
    window.extern.onKeyDown(21, 1);
  } else if (forcingU) {
    forcingU = false;
    window.extern.onKeyUp(21, 1);
  }
}
function getTankBulletSpeedOffset(tank) {
  return bulletSpeedOffsets[tank] || 1;
}
function calculateMainBulletSpeed() {
  const speedstat = getStats().bulletSpeed;
  return (
    (20 + speedstat * 3 * getTankBulletSpeedOffset(playerTank)) * 0.03
  );
}
function getDistance(x1, y1, x2, y2) {
  const distX = x1 - x2;
  const distY = y1 - y2;
  return Math.hypot(distX, distY);
}

function calculateTime(player) {
  const distance = getDistance(playerX, playerY, player.wx, player.wy);
  const bulletSpeed = calculateMainBulletSpeed();
  const playerVel = getDistVel(player);
  const relativeBulletToTargetVel = bulletSpeed - playerVel;
  return distance / relativeBulletToTargetVel;
}

function predictPlayer(player, time) {
  const [velX, velY] =
    typeof player.velocity === "undefined"
      ? [0, 0]
      : [(player.velocity[0] || 0), (player.velocity[1] || 0)];
  return [player.wx + time * velX, player.wy + time * velY];
}

function getDistVel(player) {
  let dd = 0;
  let dataPoints = 0;
  for (let i = 1; i < player.positionTable.length; ++i) {
    if (!player.positionTable[i] || !player.positionTable[i - 1]) continue;
    const d =
      getDistance(
        playerX,
        playerY,
        player.positionTable[i].x,
        player.positionTable[i].y
      ) -
      getDistance(
        playerX,
        playerY,
        player.positionTable[i - 1].x,
        player.positionTable[i - 1].y
      );
    const dt =
      player.positionTable[i].timestamp - player.positionTable[i - 1].timestamp;
    dd += d / dt;
    dataPoints++;
  }
  return dataPoints > 0 ? dd / dataPoints : 0;
}

function getPlayerWeight(player) {
  const distanceWeight =
    (1 / getDistance(playerX, playerY, player.wx, player.wy)) * 1000;
  const scoreWeight = Math.min(23536, Math.max(0, player.score || 0)) / 100000;
  return distanceWeight + scoreWeight;
}

function setPlayerPos() {
  const dx = arrowPos[0] - minimapPos[0];
  const dy = arrowPos[1] - minimapPos[1];
  playerX = (dx / minimapSize[0]) * arenaSize;
  playerY = (dy / minimapSize[1]) * arenaSize;
}

function getRenderedWorldPosition(x, y) {
  const mainCanvas = document.getElementById("canvas");
  const midX = x - mainCanvas.width / 2;
  const midY = y - mainCanvas.height / 2;
  const scaledX = midX / (fov / 2.8);
  const scaledY = midY / (fov / 2.8);
  return [playerX + scaledX, playerY + scaledY];
}

function worldToCanvasPosition(x, y) {
  const mainCanvas = document.getElementById("canvas");
  const deltaX = x - playerX;
  const deltaY = y - playerY;
  return [
    mainCanvas.width / 2 + deltaX * (fov / 2.8),
    mainCanvas.height / 2 + deltaY * (fov / 2.8),
  ];
}

function worldToMousePosition(x, y) {
  const deltaX = x - playerX;
  const deltaY = y - playerY;
  return [
    window.innerWidth / 2 + deltaX * (fov / 2.8),
    window.innerHeight / 2 + deltaY * (fov / 2.8),
  ];
}

function parseDiepScore(s) {
  let scoreMultiplier = 1;
  if (s[s.length - 1] === "k") scoreMultiplier = 1000;
  else if (s[s.length - 1] === "m") scoreMultiplier = 1000000;
  else if (!s.includes(".")) {
    if (isNaN(s)) return null;
    const toInt = parseInt(s, 10);
    return isNaN(toInt) ? null : toInt;
  } else return null;
  const toFloat = parseFloat(s.slice(0, -1));
  if (isNaN(toFloat)) return null;
  return toFloat * scoreMultiplier;
}

function getClosestText(arr, x, y) {
  return arr.reduce(function (acc, cur) {
    if (!acc) return cur;
    const distAcc = getDistance(x, y, acc.mx, acc.my);
    const distCur = getDistance(x, y, cur.mx, cur.my);
    return distAcc > distCur ? cur : acc;
  }, null);
}

function getPlayers() {
  lastPlayers = players;
  players = [];
  for (let aIndex = 0; aIndex < tankShapes.length; ++aIndex) {
    if (tankShapes[aIndex].radius / fov < 19) continue;
    const scoreTextPos = [
      tankShapes[aIndex].x,
      tankShapes[aIndex].y - tankShapes[aIndex].radius * 1.3,
    ];
    const nameTextPos = [
      tankShapes[aIndex].x,
      tankShapes[aIndex].y - tankShapes[aIndex].radius * 2,
    ];
    const closestScoreText = getClosestText(text, ...scoreTextPos);
    const closestNameText = getClosestText(text, ...nameTextPos);
    const distToScore = closestScoreText
      ? getDistance(
          ...scoreTextPos,
          closestScoreText.mx,
          closestScoreText.my
        )
      : Infinity;
    const distToName = closestNameText
      ? getDistance(...nameTextPos, closestNameText.mx, closestNameText.my)
      : Infinity;

    let score = "";
    let name = "";
    if (distToScore < 25) {
      score = parseDiepScore(closestScoreText ? closestScoreText.text : "-1");
    }
    if (distToName < 25) {
      name = closestNameText ? closestNameText.text : "";
    }
    if (score !== "") {
      const [wx, wy] = getRenderedWorldPosition(
        tankShapes[aIndex].x,
        tankShapes[aIndex].y
      );
      players.push({
        wx,
        wy,
        x: tankShapes[aIndex].x,
        y: tankShapes[aIndex].y,
        radius: tankShapes[aIndex].radius,
        name,
        score,
        velocity: undefined,
        teammate: tankShapes[aIndex].fillStyle === gameStyle[teamColor],
      });
    }
  }
}

function matchPlayers() {
  for (let i = 0; i < players.length; ++i) {
    const [x, y] = [players[i].wx, players[i].wy];
    const lastPlayer = lastPlayers.reduce((acc, cur) => {
      if (!acc) return cur;
      const distAcc = getDistance(x, y, acc.wx, acc.wy);
      const distCur = getDistance(x, y, cur.wx, cur.wy);
      return distAcc > distCur ? cur : acc;
    }, null);
    if (
      lastPlayer &&
      getDistance(
        players[i].wx,
        players[i].wy,
        lastPlayer.wx,
        lastPlayer.wy
      ) < 25
    ) {
      players[i].teammate = lastPlayer.teammate || players[i].teammate;
      players[i].positionTable = lastPlayer.positionTable.concat();
      players[i].positionTable.push({
        x: players[i].wx,
        y: players[i].wy,
        timestamp: performance.now(),
      });
      players[i].positionTable.shift();
      players[i].velocity = getVelocity(players[i]);
    } else {
      players[i].positionTable = Array.from(
        new Array(playerVelocityPredictionSampleSize),
        () => null
      );
    }
  }
}

function getVelocity(player) {
  let tx = 0,
    ty = 0;
  let dataPoints = 0;
  for (let i = 1; i < player.positionTable.length; ++i) {
    if (!player.positionTable[i] || !player.positionTable[i - 1]) continue;
    const dx = player.positionTable[i].x - player.positionTable[i - 1].x;
    const dy = player.positionTable[i].y - player.positionTable[i - 1].y;
    const dt =
      player.positionTable[i].timestamp - player.positionTable[i - 1].timestamp;
    tx += dx / dt;
    ty += dy / dt;
    dataPoints++;
  }
  return dataPoints > 0 ? [tx / dataPoints, ty / dataPoints] : [0, 0];
}

function renderOverlay(player, tx, ty, px, py) {
  if (!isDebug) return;
  const ctx = document.getElementById("canvas").getContext("2d");
  const [stx, sty] = worldToCanvasPosition(tx, ty);
  const [spx, spy] = worldToCanvasPosition(px, py);
  ctx.beginPath();
  ctx.arc(stx, sty, 25, Math.PI * 2, 0, 1);
  ctx.globalAlpha = 0.35;
  ctx.fillStyle = "#ff5294";
  ctx.fill();
  ctx.beginPath();
  ctx.arc(spx, spy, 25, Math.PI * 2, 0, 1);
  ctx.fillStyle = "#52e8ff";
  ctx.fill();
  ctx.globalAlpha = 1;
  ctx.beginPath();
  ctx.moveTo(stx, sty);
  ctx.lineTo(spx, spy);
  ctx.strokeStyle = "#000000";
  ctx.lineWidth = 1;
  ctx.stroke();
}

function aim() {
  const target = players
    .filter(plr => !plr.teammate)
    .reduce((acc, cur) => {
      if (!acc) return cur;
      return getPlayerWeight(cur) > getPlayerWeight(acc) ? cur : acc;
    }, null);
  const enemyMightDodge =
    destroyerAccuracy &&
    !!target &&
    ["Destroyer", "Hybrid", "Annihilator"].includes(playerTank) &&
    calculateTime(target) >= averageEnemyDodgeTime;

  if (!target || enemyMightDodge || !isAimbotActive || mousePressed) {
    if (mouseLocked) {
      mouseLocked = false;
      window.extern.onTouchMove(-1, mouseX, mouseY, true);
      setTimeout(() => {
        window.extern.onKeyUp(36);
      }, 80);
    }
    return;
  }
  if (!mouseLocked) {
    mouseLocked = true;
    setTimeout(() => {
      isFiring = true;
      window.extern.onKeyDown(36);
    }, 80);
  }

  const [sPX, sPY] = worldToMousePosition(target.wx, target.wy);

  if (sPX != null && sPY != null) {
    if (typeof window.extern.onTouchMove === "function") {
      window.extern.onTouchMove(-1, sPX, sPY, true);
    } else if (typeof window.extern.onMouseMove === "function") {
      window.extern.onMouseMove(sPX, sPY);
    } else {
      window.extern.onTouchMove(-1, sPX, sPY, true);
    }

    setTimeout(() => {
      isFiring = true;
      window.extern.onKeyDown(36);
      setTimeout(() => {
        window.extern.onKeyUp(36);
      }, 50);
    }, 10);
  }
  renderOverlay(target, target.wx, target.wy, target.wx, target.wy);
}

function stack() {
  if (!(window && window.extern)) return;
  const reload = getStats().reload;
  window.extern.onKeyUp(36); // release fire

  if (playerTank === "Hunter") {
    shoot(hunterStackTime[reload][0]);
    setTimeout(() => {
      window.extern.onKeyDown(5);
      window.extern.onKeyUp(5);
    }, hunterStackTime[reload][1]);
  } else if (playerTank === "Predator") {
    shoot(predatorStackTime[reload][0]);
    setTimeout(() => {
      shoot(predatorStackTime[reload][1]);
    }, predatorStackTime[reload][2]);
    setTimeout(() => {
      window.extern.onKeyDown(5);
      window.extern.onKeyUp(5);
    }, predatorStackTime[reload][3]);
  }
}
function shoot(t) {
  isFiring = true;
  window.extern.onKeyDown(36);
  setTimeout(() => {
    window.extern.onKeyUp(36);
  }, t);
}

document.addEventListener("mousedown", function (ev) {
  mousePressed = true;
  if (ev.button === 0) {
    if (mouseLocked) {
      isFiring = true;
      window.extern.onKeyDown(36);
      setTimeout(() => {
        window.extern.onKeyDown(36);
      }, 10);
    }
  }
});
document.addEventListener("mouseup", function (ev) {
  mousePressed = false;
  if (ev.button === 0) {
    window.extern.onKeyUp(36);
  }
});
document.addEventListener("touchstart", function (ev) {
  isShooting = true;
});
document.addEventListener("touchend", function (ev) {
  isShooting = false;
});
document.addEventListener(
  "mousemove",
  function (ev) {
    if (isSpinning) {
      ev.stopImmediatePropagation();
      ev.preventDefault();
    }
  },
  true
);
document.addEventListener(
  "touchmove",
  function (ev) {
    if (isSpinning) {
      ev.stopImmediatePropagation();
      ev.preventDefault();
    }
  },
  true
);
// yes
const KeyToToggleAimbot = "KeyU";
const KeyToStack       = "KeyI";
const KeyToToggleMenu  = "KeyM";

document.addEventListener("keydown", function (ev) {
  if (ev.code === KeyToToggleAimbot) {
    isAimbotActive ^= 1;
    if (window.__common__ && window.__common__.active_gamemode === "sandbox") {
      window.extern &&
        window.extern.inGameNotification(
          "Aimbot Doesn't Work in Sandbox",
          0xF533FF
        );
      isAimbotActive = 0;
    } else {
      window.extern &&
        window.extern.inGameNotification(
          isAimbotActive ? "Aimbot: ON" : "Aimbot: OFF",
          0xF533FF
        );
    }
    const aimbotCheckbox = document.getElementById("aimbot-checkbox");
    if (aimbotCheckbox) aimbotCheckbox.checked = Boolean(isAimbotActive);
  }
  else if (ev.code === KeyToStack) {
    if (["Hunter", "Predator"].includes(playerTank)) {
      stack();
      window.extern &&
        window.extern.inGameNotification("Stacking Bullets...", 0xF533FF);
    }
  }
  else if (ev.code === KeyToToggleMenu) {
    if (!menuContainer) return;
    const isHidden = menuContainer.style.display === "none";
    menuContainer.style.display = isHidden ? "block" : "none";
  }
});
// why am I even doing this?
let ctxTransform;
a._("setTransform", (context, ...args) => {
  ctxTransform = args;
  return [context, args];
});

a._("drawImage", (context, ...args) => {
  if (args[0].renderMethod) {
    const x = ctxTransform[4] + args[1];
    const y = ctxTransform[5] + args[2];
    if (args[0].renderMethod.method === "text") {
      text.push({
        x,
        y,
        cw: args[0].width,
        ch: args[0].height,
        mx: x + args[0].width / 4,
        my: y + args[0].height / 4,
        text: args[0].renderMethod.text,
      });
    }
  }
  return [context, args];
});

a._("strokeText", (context, ...args) => {
  if (context.canvas.id !== "canvas") {
    context.canvas.renderMethod = {
      method: "text",
      text: args[0],
      args,
      fillStyle: context.fillStyle,
    };
    if (args[0].startsWith("Lvl ")) {
      if (args[0][5] === " ") {
        playerLevel = Number(args[0].slice(4, 5));
        playerTank = args[0].slice(6);
      } else {
        playerLevel = Number(args[0].slice(4, 6));
        playerTank = args[0].slice(7);
      }
    }
  }
  return [context, args];
});
a._("arc", (context, ...args) => {
  if (
    context.canvas.id === "canvas" &&
    ctxTransform[4] === lastArc[0] &&
    ctxTransform[5] === lastArc[1]
  ) {
    tankShapes.push({
      x: ctxTransform[4],
      y: ctxTransform[5],
      radius: Math.hypot(ctxTransform[1], ctxTransform[0]),
      fillStyle: context.fillStyle,
    });
    lastArc = [Infinity, Infinity];
  } else {
    lastArc = [ctxTransform[4], ctxTransform[5]];
  }
  return [context, args];
});
// maybe my sister looks hot
a._("stroke", (context, ...args) => {
  if (
    ["#cccccc", "#cdcdcd"].includes(context.fillStyle) &&
    context.strokeStyle === "#000000"
  ) {
    fov = context.globalAlpha / gameStyle.ren_grid_base_alpha;
  }
  return [context, args];
});

a._("strokeRect", (context, ...args) => {
  const t = context.getTransform();
  minimapPos = [t.e, t.f];
  minimapSize = [t.a, t.d];
  return [context, args];
});

// yes i will kill myself one day
let position = 0;
let vertex = [];

a._("beginPath", (context, ...args) => {
  position = 0;
  vertex = [];
  return [context, args];
});
a._("moveTo", (context, ...args) => {
  position = 1;
  vertex.push(args);
  return [context, args];
});
a._("lineTo", (context, ...args) => {
  position++;
  vertex.push(args);
  return [context, args];
});
a._("fill", (context, ...args) => {
  if (
    context.fillStyle === "#000000" &&
    context.globalAlpha > 0.949 &&
    position === 3
  ) {
    arrowPos = getAverage(vertex);
    setPlayerPos();
  }
  else if (
    position === 4 &&
    context.fillStyle &&
    context.fillStyle.toLowerCase().includes("ffe869")
  ) {
    const [rawX, rawY] = getAverage(vertex);
    const centerX = ctxTransform[4] + rawX;
    const centerY = ctxTransform[5] + rawY;
    neutralSquares.push([centerX, centerY]);
  }
  else if (
    position === 5 &&
    context.fillStyle &&
    context.fillStyle.toLowerCase().includes("768dfc")
  ) {
    const [rawX, rawY] = getAverage(vertex);
    const centerX = ctxTransform[4] + rawX;
    const centerY = ctxTransform[5] + rawY;
    neutralPentagons.push([centerX, centerY]);
  }

  else if (
    position === 3 &&
    context.fillStyle &&
    context.fillStyle.toLowerCase().includes("fc7677")
  ) {
    const [rawX, rawY] = getAverage(vertex);
    const centerX = ctxTransform[4] + rawX;
    const centerY = ctxTransform[5] + rawY;
    neutralTriangles.push([centerX, centerY]);
  }

  return [context, args];
});

function getAverage(points) {
  let tx = 0,
    ty = 0;
  points.forEach((point) => {
    tx += point[0];
    ty += point[1];
  });
  return [tx / points.length, ty / points.length];
}

// i hate niggers btw
function onFrame() {
  window.requestAnimationFrame(onFrame);

  getPlayers();
  matchPlayers();

  if (isDebug) {
    const ctx = document.getElementById("canvas").getContext("2d");
    ctx.save();
    ctx.strokeStyle = "#FF0000";
    ctx.lineWidth = 1;
    const centerX = ctx.canvas.width / 2;
    const centerY = ctx.canvas.height / 2;
    players.forEach((plr) => {
      if (!plr.teammate) {
        ctx.beginPath();
        ctx.moveTo(centerX, centerY);
        ctx.lineTo(plr.x, plr.y);
        ctx.stroke();
      }
    });
    ctx.restore();
  }

  forceU();
  aim();
  text = [];
  tankShapes = [];
  getTeam();

  if (isAutoFarm && window.extern && window.extern.doesHaveTank()) {
    if (isDebug) {
      const ctx = document.getElementById("canvas").getContext("2d");
      ctx.save();
      const centerX = ctx.canvas.width / 2;
      const centerY = ctx.canvas.height / 2;

      ctx.strokeStyle = "#9600D6";
      ctx.lineWidth = 1;
      neutralPentagons.forEach(([cx, cy]) => {
        ctx.beginPath();
        ctx.moveTo(centerX, centerY);
        ctx.lineTo(cx, cy);
        ctx.stroke();
      });

      ctx.strokeStyle = "#00FF00";
      ctx.lineWidth = 1;
      neutralSquares.forEach(([cx, cy]) => {
        ctx.beginPath();
        ctx.moveTo(centerX, centerY);
        ctx.lineTo(cx, cy);
        ctx.stroke();
      });
      ctx.strokeStyle = "#FF9900";
      ctx.lineWidth = 1;
      neutralTriangles.forEach(([cx, cy]) => {
        ctx.beginPath();
        ctx.moveTo(centerX, centerY);
        ctx.lineTo(cx, cy);
        ctx.stroke();
      });

      ctx.restore();
    }

    let targetWorld = null;

    if (farmPriority === "pentagon" && neutralPentagons.length > 0) {
      targetWorld = nearestShapeWorld(neutralPentagons);
    } else if (farmPriority === "square" && neutralSquares.length > 0) {
      targetWorld = nearestShapeWorld(neutralSquares);
    } else if (farmPriority === "triangle" && neutralTriangles.length > 0) {
      targetWorld = nearestShapeWorld(neutralTriangles);
    }
    if (!targetWorld) {
      if (farmPriority !== "pentagon" && neutralPentagons.length > 0) {
        targetWorld = nearestShapeWorld(neutralPentagons);
      } else if (farmPriority !== "square" && neutralSquares.length > 0) {
        targetWorld = nearestShapeWorld(neutralSquares);
      } else if (farmPriority !== "triangle" && neutralTriangles.length > 0) {
        targetWorld = nearestShapeWorld(neutralTriangles);
      }
    }
    if (targetWorld) {
      const [sPX, sPY] = worldToMousePosition(targetWorld[0], targetWorld[1]);
      if (sPX != null && sPY != null) {
        isFiring = true;
        window.extern.onTouchMove(-1, sPX, sPY, true);
        window.extern.onKeyDown(36);
        setTimeout(() => {
          window.extern.onKeyUp(36);
        }, 50);
      }
    }
  }
  neutralSquares = [];
  neutralPentagons = [];
  neutralTriangles = [];
  if (
    isSpinning &&
    !isShooting &&
    !isFiring &&
    window.extern &&
    window.extern.doesHaveTank()
  ) {
    spinAngle += spinSpeed;
    const cx = window.innerWidth / 2;
    const cy = window.innerHeight / 2;
    const radius = 120;
    const targetX = cx + radius * Math.cos(spinAngle);
    const targetY = cy + radius * Math.sin(spinAngle);
    if (typeof window.extern.onTouchMove === "function") {
      window.extern.onTouchMove(-1, targetX, targetY, true);
    } else if (typeof window.extern.onMouseMove === "function") {
      window.extern.onMouseMove(targetX, targetY);
    }
  }

  if (window.extern && window.extern.doesHaveTank() && !hasJoined) {
    hasJoined = true;
    window.extern.inGameNotification("Welcome to SkidWare. Press M for menu.", 0x6670ff);
  }
}

function nearestShapeWorld(arr) {
  let nearest = null;
  let nearestDist = Infinity;
  for (const [cx, cy] of arr) {
    const [wx, wy] = getRenderedWorldPosition(cx, cy);
    const dist = getDistance(playerX, playerY, wx, wy);
    if (dist < nearestDist) {
      nearestDist = dist;
      nearest = [wx, wy];
    }
  }
  return nearest;
}


function onGameStart() {
  if (typeof extern === "undefined") return;
  clearInterval(checkGameStart);
  window.requestAnimationFrame(onFrame);

  window.extern.onKeyDown = new Proxy(window.extern.onKeyDown, {
    apply: function (method, context, args) {
      if (args[0] === 36) {
        isFiring = true;
      }
      if (args[0] === 21 && !args[1]) return;
      return Reflect.apply(method, context, args);
    },
  });
  window.extern.onKeyUp = new Proxy(window.extern.onKeyUp, {
    apply: function (method, context, args) {
      if (args[0] === 36) {
        isFiring = false;
      }
      if (args[0] === 21 && !args[1]) return;
      return Reflect.apply(method, context, args);
    },
  });

  const mouseHandler = {
    apply: function (method, context, args) {
      if (!args[3]) {
        [mouseX, mouseY] = [args[1], args[2]];
        if (mouseLocked) return;
      }
      return Reflect.apply(method, context, args);
    },
  };
  window.extern.onTouchStart = new Proxy(window.extern.onTouchStart, mouseHandler);
  window.extern.onTouchMove  = new Proxy(window.extern.onTouchMove,  mouseHandler);
  window.extern.onTouchEnd   = new Proxy(window.extern.onTouchEnd,   mouseHandler);

  window.extern.set_convar = new Proxy(window.extern.set_convar, {
    apply: function (method, context, args) {
      gameStyle[args[0]] = args[1];
      return Reflect.apply(method, context, args);
    },
  });

  window.extern.execute = new Proxy(window.extern.execute, {
    apply: function (method, context, args) {
      if (args[0].startsWith("net_replace_color 3 ")) {
        gameStyle.teamBlue =
          args[0][20] === "0" ? "#" + args[0].slice(22) : args[0].slice(20);
      }
      if (args[0].startsWith("net_replace_color 4 ")) {
        gameStyle.teamRed =
          args[0][20] === "0" ? "#" + args[0].slice(22) : args[0].slice(20);
      }
      if (args[0].startsWith("net_replace_color 5 ")) {
        gameStyle.teamPurple =
          args[0][20] === "0" ? "#" + args[0].slice(22) : args[0].slice(20);
      }
      if (args[0].startsWith("net_replace_color 6 ")) {
        gameStyle.teamGreen =
          args[0][20] === "0" ? "#" + args[0].slice(22) : args[0].slice(20);
      }
      if (args[0].startsWith("net_replace_color 8 ")) {
        gameStyle.square =
          args[0][20] === "0" ? "#" + args[0].slice(22) : args[0].slice(20);
      }
      if (args[0].startsWith("net_replace_color 9 ")) {
        gameStyle.triangle =
          args[0][20] === "0" ? "#" + args[0].slice(22) : args[0].slice(20);
      }
      if (args[0].startsWith("net_replace_color 10 ")) {
        gameStyle.pentagon =
          args[0][21] === "0" ? "#" + args[0].slice(23) : args[0].slice(21);
      }
      return Reflect.apply(method, context, args);
    },
  });
}

const checkGameStart = setInterval(onGameStart, 400);

function getTeam() {
  const partyLinkButton = document.getElementById("copy-party-link");
  if (!partyLinkButton) return;
  switch (partyLinkButton.className) {
    case "active blue":
      teamColor = "teamBlue";
      break;
    case "active purple":
      teamColor = "teamPurple";
      break;
    case "active green":
      teamColor = "teamGreen";
      break;
    case "active red":
      teamColor = "teamRed";
      break;
  }
}

let menuContainer = null;
let isBlackBg = false;
let blackBgDiv = null;

// menu full chatgpt
function createUnifiedMenu() {
  const styleEl = document.createElement("style");
  styleEl.textContent = `
    /* ===================== skeet.cc-Style Menu (30% Bigger & Draggable) ===================== */

    @font-face {
      font-family: 'SkeetFont';
      src: local('Segoe UI'), local('Arial'), sans-serif;
      /* Fallback: system sans-serif if Segoe UI not present */
    }

    /* ── Main Menu Container ───────────────────────────────────────────────────── */
    .skeet-menu {
      position: fixed;
      /* Initial position at 50px, 50px; will be overridden during dragging */
      top: 50px;
      left: 50px;
      width: 494px;                    /* 380px * 1.3 */
      background-color: #1b1b1b;
      border: 1px solid #2f2f2f;
      border-radius: 6px;
      box-shadow: 0 0 12px rgba(0, 0, 0, 0.7);
      font-family: 'SkeetFont', sans-serif;
      color: #e0e0e0;
      font-size: 17px;                 /* 13px * 1.3 */
      user-select: none;
      display: none;                   /* hidden by default; toggled with “M” */
      pointer-events: auto;
      z-index: 9999;
    }

    /* ── Drag Handle (26px high) ─────────────────────────────────────────────────── */
    .skeet-drag-handle {
      height: 26px;                    /* 20px * 1.3 */
      background-color: #2f2f2f;
      border-bottom: 1px solid #2f2f2f;
      cursor: move;
      text-align: center;
      line-height: 26px;               /* same as height, to center text vertically */
      font-size: 17px;                 /* 13px * 1.3 */
      font-weight: 500;
      color: #e0e0e0;
      user-select: none;
    }

    /* ── Sidebar (104px-wide Text Tabs) ────────────────────────────────────────── */
    .skeet-sidebar {
      float: left;
      width: 104px;                    /* 80px * 1.3 */
      background-color: #171717;
      border-right: 1px solid #2f2f2f;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding-top: 16px;               /* 12px * 1.3 */
    }

    .skeet-sidebar button {
      width: 83px;                     /* 64px * 1.3 ≈ 83 */
      height: 42px;                    /* 32px * 1.3 ≈ 42 */
      margin: 8px 0;                   /* 6px * 1.3 ≈ 8 */
      background-color: transparent;
      border: none;
      outline: none;
      cursor: pointer;
      transition: background-color 0.15s ease, color 0.15s ease;
      color: #888888;
      font-size: 17px;                 /* 13px * 1.3 ≈ 17 */
      font-weight: 500;
    }

    .skeet-sidebar button:hover,
    .skeet-sidebar button.active {
      background-color: #2f2f2f;
      color: #00b4ff;
      border-radius: 4px;
    }

    /* ── Content Area (Remaining ≈390px) ────────────────────────────────────────── */
    .skeet-content {
      margin-left: 104px;              /* leave room for sidebar */
      padding: 21px;                   /* 16px * 1.3 ≈ 21 */
      box-sizing: border-box;
    }

    /* Hide all sections by default; only the “.active” one displays */
    .skeet-section {
      display: none;
    }
    .skeet-section.active {
      display: block;
    }

    .skeet-content .section-title {
      font-size: 21px;                 /* 16px * 1.3 ≈ 21 */
      font-weight: 600;
      color: #ffffff;
      margin-bottom: 13px;             /* 10px * 1.3 ≈ 13 */
    }

    /* ── Section Header ───────────────────────────────────────────────────────── */
    .skeet-section .header {
      font-size: 18px;                 /* 14px * 1.3 ≈ 18 */
      font-weight: 500;
      margin-bottom: 10px;             /* 8px * 1.3 ≈ 10 */
      color: #e0e0e0;
    }

    /* ── Toggle Labels (Checkbox + Text) ───────────────────────────────────────── */
    .skeet-toggle-label {
      display: flex;
      align-items: center;
      margin-bottom: 10px;             /* 8px * 1.3 ≈ 10 */
      cursor: pointer;
    }
    .skeet-toggle-label input[type="checkbox"] {
      width: 18px;                     /* 14px * 1.3 ≈ 18 */
      height: 18px;                    /* 14px * 1.3 ≈ 18 */
      margin-right: 10px;              /* 8px * 1.3 ≈ 10 */
      accent-color: #00b4ff;
      cursor: pointer;
      outline: none;
    }
    .skeet-toggle-label span {
      font-size: 17px;                 /* 13px * 1.3 ≈ 17 */
      color: #e0e0e0;
    }

    /* ── Slider (Range Input) ─────────────────────────────────────────────────── */
    .skeet-slider-container {
      display: flex;
      align-items: center;
      margin-bottom: 15px;             /* 12px * 1.3 ≈ 15 */
    }
    .skeet-slider-container span {
      margin-right: 10px;              /* 8px * 1.3 ≈ 10 */
      font-size: 16px;                 /* 12px * 1.3 ≈ 16 */
      color: #cccccc;
      min-width: 91px;                 /* 70px * 1.3 ≈ 91 */
    }
    .skeet-slider {
      flex: 1;
      -webkit-appearance: none;
      width: 100%;
      height: 5px;                     /* 4px * 1.3 ≈ 5 */
      background: #2f2f2f;
      border-radius: 3px;
      cursor: pointer;
      outline: none;
    }
    .skeet-slider::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 16px;                     /* 12px * 1.3 ≈ 16 */
      height: 16px;                    /* 12px * 1.3 ≈ 16 */
      border-radius: 50%;
      background: #00b4ff;
      border: 1px solid #1b1b1b;
      cursor: pointer;
      margin-top: -5px;                /* center thumb (≈ half the thumb height) */
    }
    .skeet-slider::-moz-range-thumb {
      width: 16px;
      height: 16px;
      border-radius: 50%;
      background: #00b4ff;
      border: 1px solid #1b1b1b;
      cursor: pointer;
    }

    /* ── Buttons (Load/Save/Stack etc.) ───────────────────────────────────────── */
    .skeet-button {
      display: inline-block;
      background-color: #2f2f2f;
      color: #e0e0e0;
      font-size: 15px;                 /* 12px * 1.3 ≈ 15 */
      padding: 8px 16px;               /* 6px*1.3≈8  & 12px*1.3≈16 */
      margin-top: 8px;                 /* 6px * 1.3 ≈ 8 */
      border: 1px solid #3f3f3f;
      border-radius: 4px;
      cursor: pointer;
      transition: background-color 0.15s ease, border-color 0.15s ease;
    }
    .skeet-button:hover {
      background-color: #3f3f3f;
      border-color: #5f5f5f;
    }
    .skeet-button:active {
      background-color: #5f5f5f;
      border-color: #7f7f7f;
    }

    /* ── Radio Buttons for Farming Priority ───────────────────────────────────── */
    .skeet-radio-group {
      margin-bottom: 10px; /* some spacing */
    }
    .skeet-radio-label {
      display: flex;
      align-items: center;
      margin-right: 20px;
      cursor: pointer;
      font-size: 17px; /* 13px * 1.3 */
      color: #e0e0e0;
    }
    .skeet-radio-label input[type="radio"] {
      margin-right: 8px;
      accent-color: #00b4ff;
      cursor: pointer;
      outline: none;
    }

    /* ── Focus Ring for Keyboard Navigation ──────────────────────────────────── */
    .skeet-menu input:focus-visible,
    .skeet-menu button:focus-visible {
      outline: 2px solid #00b4ff;
      outline-offset: 1px;
    }
  `;
  document.head.appendChild(styleEl);

  menuContainer = document.createElement("div");
  menuContainer.classList.add("skeet-menu");

  const dragHandle = document.createElement("div");
  dragHandle.classList.add("skeet-drag-handle");
  dragHandle.innerText = "Skid Ware";
  menuContainer.appendChild(dragHandle);
  const sidebar = document.createElement("div");
  sidebar.classList.add("skeet-sidebar");

  const tabs = [
    { id: "tab-spin",    label: "Spin"    },
    { id: "tab-aim",     label: "Aim"     },
    { id: "tab-farm",    label: "Farm"    },
    { id: "tab-visuals", label: "Visuals" },
  ];

  tabs.forEach((t, idx) => {
    const btn = document.createElement("button");
    btn.id = t.id + "-btn";
    btn.innerText = t.label;
    btn.title = t.label;
    if (idx === 0) btn.classList.add("active");
    btn.addEventListener("click", () => switchTab(t.id));
    sidebar.appendChild(btn);
  });
  menuContainer.appendChild(sidebar);

  const content = document.createElement("div");
  content.classList.add("skeet-content");
  const spinSection = document.createElement("div");
  spinSection.id = "tab-spin";
  spinSection.classList.add("skeet-section", "active"); 

  const spinTitle = document.createElement("div");
  spinTitle.classList.add("section-title");
  spinTitle.innerText = "Spinner Settings:";
  spinSection.appendChild(spinTitle);

  const spinHeader = document.createElement("div");
  spinHeader.classList.add("header");
  spinHeader.innerText = "• Enable / Disable Spinner:";
  spinSection.appendChild(spinHeader);

  const spinToggleLabel = document.createElement("label");
  spinToggleLabel.classList.add("skeet-toggle-label");
  const spinCheckbox = document.createElement("input");
  spinCheckbox.type = "checkbox";
  spinCheckbox.id = "spinner-checkbox";
  spinCheckbox.checked = isSpinning;
  const spinLabelText = document.createElement("span");
  spinLabelText.innerText = "Enable Spinner";
  spinToggleLabel.appendChild(spinCheckbox);
  spinToggleLabel.appendChild(spinLabelText);
  spinSection.appendChild(spinToggleLabel);

  spinCheckbox.addEventListener("change", function () {
    isSpinning = this.checked;
    if (window.extern) {
      window.extern.inGameNotification(
        isSpinning ? "Spinner: ON" : "Spinner: OFF",
        0xF533FF
      );
    }
  });

  const spinSpeedHeader = document.createElement("div");
  spinSpeedHeader.classList.add("header");
  spinSpeedHeader.innerText = "• Spin Speed:";
  spinSection.appendChild(spinSpeedHeader);

  const spinSpeedContainer = document.createElement("div");
  spinSpeedContainer.classList.add("skeet-slider-container");
  const speedLabelText = document.createElement("span");
  speedLabelText.innerText = `Speed: ${spinSpeed.toFixed(2)}`;
  const spinSlider = document.createElement("input");
  spinSlider.type = "range";
  spinSlider.min = "0";
  spinSlider.max = "2";
  spinSlider.step = "0.01";
  spinSlider.value = spinSpeed.toString();
  spinSlider.classList.add("skeet-slider");

  spinSlider.addEventListener("input", (ev) => {
    spinSpeed = parseFloat(ev.target.value);
    speedLabelText.innerText = `Speed: ${spinSpeed.toFixed(2)}`;
  });
  ["mousedown", "mousemove", "mouseup", "touchstart", "touchmove", "touchend"].forEach((evt) => {
    spinSlider.addEventListener(evt, (e) => e.stopPropagation(), { capture: true, passive: false });
  });

  spinSpeedContainer.appendChild(speedLabelText);
  spinSpeedContainer.appendChild(spinSlider);
  spinSection.appendChild(spinSpeedContainer);

  content.appendChild(spinSection);

  const aimSection = document.createElement("div");
  aimSection.id = "tab-aim";
  aimSection.classList.add("skeet-section");

  const aimTitle = document.createElement("div");
  aimTitle.classList.add("section-title");
  aimTitle.innerText = "Aimbot Settings:";
  aimSection.appendChild(aimTitle);

  const aimHeader = document.createElement("div");
  aimHeader.classList.add("header");
  aimHeader.innerText = "• Enable / Disable Aimbot:";
  aimSection.appendChild(aimHeader);

  const aimToggleLabel = document.createElement("label");
  aimToggleLabel.classList.add("skeet-toggle-label");
  const aimCheckbox = document.createElement("input");
  aimCheckbox.type = "checkbox";
  aimCheckbox.id = "aimbot-checkbox";
  aimCheckbox.checked = isAimbotActive;
  const aimLabelText = document.createElement("span");
  aimLabelText.innerText = "Enable Aimbot";
  aimToggleLabel.appendChild(aimCheckbox);
  aimToggleLabel.appendChild(aimLabelText);
  aimSection.appendChild(aimToggleLabel);

  aimCheckbox.addEventListener("change", function () {
    isAimbotActive = this.checked;
    if (window.extern) {
      window.extern.inGameNotification(
        isAimbotActive ? "Aimbot: ON" : "Aimbot: OFF",
        0xF533FF
      );
    }
  });

  const stackHeader = document.createElement("div");
  stackHeader.classList.add("header");
  stackHeader.innerText = "• Manual Stack (Hunter/Predator):";
  aimSection.appendChild(stackHeader);

  const stackButton = document.createElement("button");
  stackButton.innerText = "Stack Bullets";
  stackButton.classList.add("skeet-button");
  stackButton.addEventListener("click", () => {
    if (["Hunter", "Predator"].includes(playerTank)) {
      stack();
      window.extern &&
        window.extern.inGameNotification("Stacking Bullets...", 0xF533FF);
    } else {
      window.extern &&
        window.extern.inGameNotification("Not Hunter/Predator", 0xF533FF);
    }
  });
  aimSection.appendChild(stackButton);

  content.appendChild(aimSection);

  const farmSection = document.createElement("div");
  farmSection.id = "tab-farm";
  farmSection.classList.add("skeet-section");

  const farmTitle = document.createElement("div");
  farmTitle.classList.add("section-title");
  farmTitle.innerText = "AutoFarm:";
  farmSection.appendChild(farmTitle);

  const farmHeader = document.createElement("div");
  farmHeader.classList.add("header");
  farmHeader.innerText = "• Enable / Disable AutoFarm:";
  farmSection.appendChild(farmHeader);

  const farmToggleLabel = document.createElement("label");
  farmToggleLabel.classList.add("skeet-toggle-label");
  const farmCheckbox = document.createElement("input");
  farmCheckbox.type = "checkbox";
  farmCheckbox.id = "autofarm-checkbox";
  farmCheckbox.checked = isAutoFarm;
  const farmLabelText = document.createElement("span");
  farmLabelText.innerText = "Enable AutoFarm";
  farmToggleLabel.appendChild(farmCheckbox);
  farmToggleLabel.appendChild(farmLabelText);
  farmSection.appendChild(farmToggleLabel);

  farmCheckbox.addEventListener("change", function () {
    isAutoFarm = this.checked;
    if (window.extern) {
      window.extern.inGameNotification(
        isAutoFarm ? "AutoFarm: ON" : "AutoFarm: OFF",
        0xF533FF
      );
    }
  });

  const priorityContainer = document.createElement("div");
  priorityContainer.classList.add("skeet-radio-group");
  const priorityLabel = document.createElement("div");
  priorityLabel.classList.add("header");
  priorityLabel.innerText = "• Farming Priority:";
  farmSection.appendChild(priorityLabel);

  const pentRadioLabel = document.createElement("label");
  pentRadioLabel.classList.add("skeet-radio-label");
  const pentRadio = document.createElement("input");
  pentRadio.type = "radio";
  pentRadio.name = "farm-priority";
  pentRadio.id = "farm-priority-pentagon";
  pentRadio.value = "pentagon";
  pentRadio.checked = (farmPriority === "pentagon");
  const pentLabelText = document.createElement("span");
  pentLabelText.innerText = "Prioritize Pentagons";
  pentRadioLabel.appendChild(pentRadio);
  pentRadioLabel.appendChild(pentLabelText);
  priorityContainer.appendChild(pentRadioLabel);

  pentRadio.addEventListener("change", function () {
    if (this.checked) {
      farmPriority = "pentagon";
      if (window.extern) {
        window.extern.inGameNotification("FarmPriority: Pentagons", 0xF533FF);
      }
    }
  });
  const sqRadioLabel = document.createElement("label");
  sqRadioLabel.classList.add("skeet-radio-label");
  const sqRadio = document.createElement("input");
  sqRadio.type = "radio";
  sqRadio.name = "farm-priority";
  sqRadio.id = "farm-priority-square";
  sqRadio.value = "square";
  sqRadio.checked = (farmPriority === "square");
  const sqLabelText = document.createElement("span");
  sqLabelText.innerText = "Prioritize Squares";
  sqRadioLabel.appendChild(sqRadio);
  sqRadioLabel.appendChild(sqLabelText);
  priorityContainer.appendChild(sqRadioLabel);

  sqRadio.addEventListener("change", function () {
    if (this.checked) {
      farmPriority = "square";
      if (window.extern) {
        window.extern.inGameNotification("FarmPriority: Squares", 0xF533FF);
      }
    }

  });
  const triRadioLabel = document.createElement("label");
  triRadioLabel.classList.add("skeet-radio-label");
  const triRadio = document.createElement("input");
  triRadio.type = "radio";
  triRadio.name = "farm-priority";
  triRadio.id = "farm-priority-triangle";
  triRadio.value = "triangle";
  triRadio.checked = (farmPriority === "triangle");
  const triLabelText = document.createElement("span");
  triLabelText.innerText = "Prioritize Triangles";
  triRadioLabel.appendChild(triRadio);
  triRadioLabel.appendChild(triLabelText);
  priorityContainer.appendChild(triRadioLabel);

  triRadio.addEventListener("change", function () {
    if (this.checked) {
      farmPriority = "triangle";
      if (window.extern) {
        window.extern.inGameNotification("FarmPriority: Triangles", 0xF533FF);
      }
    }
  });

  farmSection.appendChild(priorityContainer);
  content.appendChild(farmSection);
  const visualsSection = document.createElement("div");
  visualsSection.id = "tab-visuals";
  visualsSection.classList.add("skeet-section");

  const visualsTitle = document.createElement("div");
  visualsTitle.classList.add("section-title");
  visualsTitle.innerText = "Debug / Visuals:";
  visualsSection.appendChild(visualsTitle);

  const visualsHeader = document.createElement("div");
  visualsHeader.classList.add("header");
  visualsHeader.innerText = "• Enable / Disable Debug Lines:";
  visualsSection.appendChild(visualsHeader);

  const visualsToggleLabel = document.createElement("label");
  visualsToggleLabel.classList.add("skeet-toggle-label");
  const visualsCheckbox = document.createElement("input");
  visualsCheckbox.type = "checkbox";
  visualsCheckbox.id = "debug-checkbox";
  visualsCheckbox.checked = isDebug;
  const visualsLabelText = document.createElement("span");
  visualsLabelText.innerText = "Enable Debug Lines";
  visualsToggleLabel.appendChild(visualsCheckbox);
  visualsToggleLabel.appendChild(visualsLabelText);
  visualsSection.appendChild(visualsToggleLabel);

  visualsCheckbox.addEventListener("change", function () {
    isDebug = this.checked;
    if (window.extern) {
      window.extern.inGameNotification(
        isDebug ? "Debug Lines: ON" : "Debug Lines: OFF",
        0xF533FF
      );
    }
  });
  const blackBgToggleLabel = document.createElement("label");
  blackBgToggleLabel.classList.add("skeet-toggle-label");
  const blackBgCheckbox = document.createElement("input");
  blackBgCheckbox.type = "checkbox";
  blackBgCheckbox.id = "blackbg-checkbox";
  blackBgCheckbox.checked = isBlackBg;
  const blackBgLabelText = document.createElement("span");
  blackBgLabelText.innerText = "Black Background (buggy on aim)";
  blackBgToggleLabel.appendChild(blackBgCheckbox);
  blackBgToggleLabel.appendChild(blackBgLabelText);
  visualsSection.appendChild(blackBgToggleLabel);

  blackBgCheckbox.addEventListener("change", function () {
    isBlackBg = this.checked;
    if (window.input && typeof window.input.set_convar === "function") {
        window.input.set_convar("ren_background_color",
                                isBlackBg ? "#000000" : "#CDCDCD");
    }
    if (window.extern) {
      window.extern.inGameNotification(
        isBlackBg ? "Black background: ON" : "Black background: OFF",
        0xF533FF
      );
    }
  });
  content.appendChild(visualsSection);
  menuContainer.appendChild(content);
  document.body.appendChild(menuContainer);
  function switchTab(activeId) {
    tabs.forEach((t) => {
      const btn = document.getElementById(t.id + "-btn");
      if (t.id === activeId) btn.classList.add("active");
      else btn.classList.remove("active");
    });
    tabs.forEach((t) => {
      const section = document.getElementById(t.id);
      if (t.id === activeId) section.classList.add("active");
      else section.classList.remove("active");
    });
  }
  let isDragging = false;
  let dragOffsetX = 0;
  let dragOffsetY = 0;

  dragHandle.addEventListener("mousedown", function (e) {
    isDragging = true;
    const rect = menuContainer.getBoundingClientRect();
    dragOffsetX = e.clientX - rect.left;
    dragOffsetY = e.clientY - rect.top;
    document.addEventListener("mousemove", onMouseMove);
    document.addEventListener("mouseup", onMouseUp);
    e.preventDefault();
  });

  function onMouseMove(e) {
    if (!isDragging) return;
    const newLeft = e.clientX - dragOffsetX;
    const newTop = e.clientY - dragOffsetY;
    menuContainer.style.left = newLeft + "px";
    menuContainer.style.top = newTop + "px";
  }

  function onMouseUp() {
    isDragging = false;
    document.removeEventListener("mousemove", onMouseMove);
    document.removeEventListener("mouseup", onMouseUp);
  }
}

// https://discord.gg/NBN3jgQDGe