Deadshot.io Cheat (AIMBOT, WALL HACKS) -- discord.gg/783Ve3Fd
// ==UserScript==
// @name Destiny V3
// @namespace http://tampermonkey.net/
// @version 3.0
// @description Deadshot.io Cheat (AIMBOT, WALL HACKS) -- discord.gg/783Ve3Fd
// @match *://*deadshot.io/*
// @grant none
// @run-at document-start
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// =====================================================================
// CONFIG
// =====================================================================
const STORAGE_KEY = 'destiny_v2_config';
const defaultConfig = {
// Aimbot
aimbotEnabled: true,
aimKey: 'RightClick',
aimSmooth: 1.5,
lockDist: 80,
hitbox: 0,
priority: 1,
targetLock: false,
predictionEnabled: true,
predictionStrength: 2.0,
velocityTracking: true,
visibilityCheck: true,
// TriggerBot
triggerBot: false,
triggerDelay: 50,
triggerRadius: 12,
// ESP / Visuals
espEnabled: true,
showDistance: true,
showTracers: false,
espThickness: 2,
showFov: false,
fov: 300,
fovGradient: true,
showCrosshair: false,
showFPS: true,
// Program detection
autoDetect: true,
manualTargetID: -1,
// Combat
crouchSpam: false,
crouchSpamSpeed: 80,
autoStrafe: false,
autoStrafeSpeed: 100,
// Hacks
fovHack: false,
fovHackScale: 1.0,
// Misc
antiAFK: false,
performanceMode: false,
blockFullscreen: false,
debugOverlay: true,
// Radar & Indicators
radarEnabled: true,
radarSize: 120,
radarRange: 80,
offScreenIndicators: true,
// UI
menuVisible: true,
menuKey: 'Insert',
accentColor: '#a855f7',
x: 60,
y: 60,
};
let config = { ...defaultConfig };
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) config = { ...config, ...JSON.parse(saved) };
} catch (e) {}
let _saveTimer = null;
function save() {
if (_saveTimer) clearTimeout(_saveTimer);
_saveTimer = setTimeout(saveImmediate, 200);
}
function saveImmediate() {
if (_saveTimer) { clearTimeout(_saveTimer); _saveTimer = null; }
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(config)); } catch (e) {}
}
if (config.blockFullscreen) {
const block = () => Promise.resolve();
['requestFullscreen', 'webkitRequestFullscreen', 'mozRequestFullScreen', 'msRequestFullscreen']
.forEach(fn => { if (Element.prototype[fn]) Element.prototype[fn] = block; });
}
// =====================================================================
// STATE
// =====================================================================
const state = {
programCounter: 0,
vpMatrices: [],
matricesByProgram: new Map(),
programScores: new Map(),
detectedTargetID: -1,
modelMatrices: [],
lockedTarget: null,
lastPositions: new Map(),
velocities: new Map(),
deadPositions: new Map(),
lastMouseMove: Date.now(),
lastTriggerFire: 0,
lastCrouchToggle: 0,
crouchDown: false,
lastStrafeToggle: 0,
strafeRight: false,
input: { left: false, right: false, shift: false, alt: false },
pointerLocked: false,
rebindingField: null,
keyJustRebound: false,
accX: 0,
accY: 0,
fps: 0,
frameCount: 0,
lastFPSUpdate: Date.now(),
totalTargets: 0,
overlayCtx: null,
baselineVP0: 0,
currentZoom: 1.0,
};
// =====================================================================
// INPUT
// =====================================================================
function aimKeyHeld() {
switch (config.aimKey) {
case 'RightClick': return state.input.right;
case 'LeftClick': return state.input.left;
case 'ShiftLeft': return state.input.shift;
case 'AltLeft': return state.input.alt;
case 'Always': return true;
default: return state.input.right;
}
}
document.addEventListener('keydown', (e) => {
if (state.rebindingField) {
const field = state.rebindingField;
state.rebindingField = null;
state.keyJustRebound = true;
config[field] = e.code;
saveImmediate();
refreshGUI();
e.preventDefault();
e.stopImmediatePropagation();
return;
}
if (e.code === config.menuKey) {
config.menuVisible = !config.menuVisible;
const el = document.getElementById('d2-root');
if (el) el.style.display = config.menuVisible ? 'flex' : 'none';
saveImmediate();
e.preventDefault();
e.stopImmediatePropagation();
}
if (e.code === 'ArrowRight') {
config.autoDetect = false;
config.manualTargetID++;
state.modelMatrices = [];
save();
refreshTargetBadge();
e.preventDefault();
e.stopImmediatePropagation();
}
if (e.code === 'ArrowLeft') {
config.autoDetect = false;
config.manualTargetID--;
state.modelMatrices = [];
save();
refreshTargetBadge();
e.preventDefault();
e.stopImmediatePropagation();
}
if (e.code === 'ShiftLeft') state.input.shift = true;
if (e.code === 'AltLeft') state.input.alt = true;
}, true);
document.addEventListener('keyup', (e) => {
if (e.code === 'ShiftLeft') state.input.shift = false;
if (e.code === 'AltLeft') state.input.alt = false;
}, true);
const onMouseDown = e => {
if (e.button === 0) state.input.left = true;
if (e.button === 2) state.input.right = true;
};
const onMouseUp = e => {
if (e.button === 0) state.input.left = false;
if (e.button === 2) state.input.right = false;
};
document.addEventListener('mousedown', onMouseDown, true);
document.addEventListener('mouseup', onMouseUp, true);
window.addEventListener('mousedown', onMouseDown);
window.addEventListener('mouseup', onMouseUp);
document.addEventListener('pointerlockchange', () => {
const wasLocked = state.pointerLocked;
state.pointerLocked = !!document.pointerLockElement;
if (state.pointerLocked && !wasLocked) {
state.lastPositions.clear();
state.velocities.clear();
state.deadPositions.clear();
state.lockedTarget = null;
}
}, true);
// Browser mouse input: dispatchEvent with Object.defineProperty for movementX/Y
function mouseMove(dx, dy) {
const evt = new MouseEvent('mousemove', { bubbles: true, cancelable: true });
Object.defineProperty(evt, 'movementX', { value: dx });
Object.defineProperty(evt, 'movementY', { value: dy });
const canvas = document.pointerLockElement || document.querySelector('canvas');
if (canvas) canvas.dispatchEvent(evt);
const evt2 = new MouseEvent('mousemove', { bubbles: true, cancelable: true });
Object.defineProperty(evt2, 'movementX', { value: dx });
Object.defineProperty(evt2, 'movementY', { value: dy });
window.dispatchEvent(evt2);
}
function mouseClick(isDown) {
window.dispatchEvent(new MouseEvent(isDown ? 'mousedown' : 'mouseup', { button: 0, bubbles: true }));
}
// =====================================================================
// WEBGL HOOK
// =====================================================================
const originalGetContext = HTMLCanvasElement.prototype.getContext;
const proxyCache = new WeakMap();
const programMap = new WeakMap();
function spoof(fake, real) {
Object.defineProperty(fake, 'name', { value: real.name, configurable: true });
Object.defineProperty(fake, 'toString', { value: () => real.toString(), configurable: true });
return fake;
}
function currentTargetID() {
return config.autoDetect ? state.detectedTargetID : config.manualTargetID;
}
HTMLCanvasElement.prototype.getContext = spoof(function (type, options) {
const ctx = originalGetContext.call(this, type, options);
if (!ctx || (type !== 'webgl' && type !== 'webgl2')) return ctx;
if (proxyCache.has(ctx)) return proxyCache.get(ctx);
const handler = {
get(target, prop) {
const val = target[prop];
if (typeof val !== 'function') return val;
if (prop === 'uniformMatrix4fv') {
return function (loc, transpose, value) {
if (value && value.length === 16) {
if (Math.abs(value[11] + 1) < 0.1 && Math.abs(value[15]) < 0.1) {
if (state.vpMatrices.length > 3) state.vpMatrices.shift();
state.vpMatrices.push(new Float32Array(value));
if (config.fovHack && config.fovHackScale !== 1.0) {
const modified = new Float32Array(value);
modified[0] *= config.fovHackScale;
modified[5] *= config.fovHackScale;
arguments[2] = modified;
}
}
else if (Math.abs(value[3]) < 1e-6 &&
Math.abs(value[7]) < 1e-6 &&
Math.abs(value[15] - 1) < 1e-6) {
const gl = target;
const pid = programMap.get(gl.getParameter(gl.CURRENT_PROGRAM));
if (pid !== undefined) {
let arr = state.matricesByProgram.get(pid);
if (!arr) { arr = []; state.matricesByProgram.set(pid, arr); }
if (arr.length < 64) arr.push(new Float32Array(value));
}
}
}
return val.apply(target, arguments);
};
}
if (prop === 'useProgram') {
return function (program) {
if (program && !programMap.has(program)) {
programMap.set(program, state.programCounter++);
}
return val.apply(target, arguments);
};
}
if (prop === 'drawElements') {
return function () {
const gl = target;
const pid = programMap.get(gl.getParameter(gl.CURRENT_PROGRAM));
const tgt = currentTargetID();
const espActive = config.aimbotEnabled && config.espEnabled && pid === tgt && tgt >= 0;
if (espActive) gl.disable(gl.DEPTH_TEST);
const res = val.apply(target, arguments);
if (espActive) gl.enable(gl.DEPTH_TEST);
return res;
};
}
return val.bind(target);
},
};
const proxied = new Proxy(ctx, handler);
proxyCache.set(ctx, proxied);
return proxied;
}, originalGetContext);
// =====================================================================
// AUTO-DETECT
// =====================================================================
function scoreProgramsThisFrame() {
if (!config.autoDetect) return;
const now = Date.now();
for (const [pid, mats] of state.matricesByProgram.entries()) {
const n = mats.length;
if (n < 2 || n > 40) { decay(pid, now); continue; }
let sumX = 0, sumZ = 0, minY = Infinity, maxY = -Infinity;
for (let i = 0; i < n; i++) {
const m = mats[i];
sumX += m[12]; sumZ += m[14];
if (m[13] < minY) minY = m[13];
if (m[13] > maxY) maxY = m[13];
}
const meanX = sumX / n, meanZ = sumZ / n;
let varXZ = 0;
for (let i = 0; i < n; i++) {
const m = mats[i];
const dx = m[12] - meanX, dz = m[14] - meanZ;
varXZ += dx * dx + dz * dz;
}
varXZ /= n;
const spread = Math.sqrt(varXZ);
if (spread < 0.8) { decay(pid, now); continue; }
if (maxY - minY > 200) { decay(pid, now); continue; }
const countScore = n <= 3 ? n / 3 : n <= 12 ? 1.0 : Math.max(0, 1 - (n - 12) / 28);
const spreadScore = Math.min(1, spread / 10);
const frameScore = countScore * 0.6 + spreadScore * 0.4;
const prev = state.programScores.get(pid) || { score: 0, lastSeen: 0 };
const alpha = 0.25;
prev.score = prev.score * (1 - alpha) + frameScore * alpha;
prev.lastSeen = now;
prev.matrixCount = n;
prev.spread = spread;
state.programScores.set(pid, prev);
}
for (const [pid, data] of state.programScores.entries()) {
if (!state.matricesByProgram.has(pid)) decay(pid, now);
if (now - data.lastSeen > 5000) state.programScores.delete(pid);
}
let best = -1, bestScore = 0.15;
for (const [pid, data] of state.programScores.entries()) {
if (data.score > bestScore) { best = pid; bestScore = data.score; }
}
if (best !== state.detectedTargetID) {
state.detectedTargetID = best;
refreshTargetBadge();
}
}
function decay(pid, now) {
const prev = state.programScores.get(pid);
if (!prev) return;
prev.score *= 0.85;
prev.lastSeen = now;
}
// =====================================================================
// CANVAS & UTILITIES
// =====================================================================
let overlayCanvas = null;
function setupCanvas() {
if (overlayCanvas) return;
overlayCanvas = document.createElement('canvas');
overlayCanvas.id = 'd2-overlay';
overlayCanvas.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:2147483645;pointer-events:none;';
(document.body || document.documentElement).appendChild(overlayCanvas);
const resize = () => {
overlayCanvas.width = window.innerWidth;
overlayCanvas.height = window.innerHeight;
};
window.addEventListener('resize', resize);
document.addEventListener('fullscreenchange', () => setTimeout(resize, 50));
document.addEventListener('webkitfullscreenchange', () => setTimeout(resize, 50));
resize();
(function loop() { render(); requestAnimationFrame(loop); })();
setInterval(() => { if (!document.getElementById('d2-root')) createGUI(); }, 2000);
}
function getBoneOffset() {
return config.hitbox === 0 ? 2.15 : config.hitbox === 1 ? 1.5 : 0.8;
}
function calculateVelocity(posKey, pos) {
const last = state.lastPositions.get(posKey);
const now = Date.now();
if (last) {
const dt = (now - last.time) / 1000;
if (dt > 0.001 && dt < 0.5) {
const vx = (pos.x - last.x) / dt;
const vy = (pos.y - last.y) / dt;
const vz = (pos.z - last.z) / dt;
const prev = state.velocities.get(posKey);
const blend = 0.85;
if (prev) {
state.velocities.set(posKey, {
vx: vx * blend + prev.vx * (1 - blend),
vy: vy * blend + prev.vy * (1 - blend),
vz: vz * blend + prev.vz * (1 - blend),
time: now,
});
} else {
state.velocities.set(posKey, { vx, vy, vz, time: now });
}
}
}
state.lastPositions.set(posKey, { x: pos.x, y: pos.y, z: pos.z, time: now });
}
function project(vp, x, y, z, w, h) {
const X = x*vp[0] + y*vp[4] + z*vp[8] + vp[12];
const Y = x*vp[1] + y*vp[5] + z*vp[9] + vp[13];
const W = x*vp[3] + y*vp[7] + z*vp[11] + vp[15];
if (W < 0.1) return null;
return { x: (X/W + 1) * w * 0.5, y: (-Y/W + 1) * h * 0.5, w: W };
}
function easeOutQuart(x) { return 1 - Math.pow(1 - x, 4); }
function easeInOutCubic(x) { return x < 0.5 ? 4*x*x*x : 1 - Math.pow(-2*x+2, 3) / 2; }
function applySmoothCurve(value) {
return value < 0.5 ? 4*value*value*value : 1 - Math.pow(-2*value+2, 3) / 2;
}
// =====================================================================
// RENDER LOOP
// =====================================================================
function render() {
if (!overlayCanvas) return;
if (!state.overlayCtx) state.overlayCtx = overlayCanvas.getContext('2d');
const ctx = state.overlayCtx;
const w = overlayCanvas.width;
const h = overlayCanvas.height;
const cx = w / 2, cy = h / 2;
ctx.clearRect(0, 0, w, h);
state.frameCount++;
const now = Date.now();
if (now - state.lastFPSUpdate > 1000) {
state.fps = state.frameCount;
state.frameCount = 0;
state.lastFPSUpdate = now;
updateStatusBar();
}
scoreProgramsThisFrame();
const tgt = currentTargetID();
state.modelMatrices = (tgt >= 0 && state.matricesByProgram.get(tgt)) || [];
if (config.debugOverlay) {
ctx.font = '10px monospace';
let dy = 10;
const sorted = [...state.programScores.entries()].sort((a,b) => b[1].score - a[1].score);
for (let i = 0; i < Math.min(sorted.length, 6); i++) {
const [pid, data] = sorted[i];
const mats = state.matricesByProgram.get(pid);
const n = mats ? mats.length : 0;
ctx.fillStyle = pid === tgt ? '#0f0' : '#888';
ctx.fillText(`pid:${pid} score:${data.score.toFixed(3)} mats:${n} spread:${(data.spread||0).toFixed(1)}`, 10, dy);
dy += 12;
}
}
if (config.showFPS) {
ctx.font = 'bold 14px Segoe UI, system-ui';
ctx.fillStyle = config.accentColor;
ctx.fillText(`${state.fps} fps`, 10, 24);
}
if (config.debugOverlay) {
ctx.font = '11px monospace';
ctx.fillStyle = state.pointerLocked ? '#0f0' : '#f77';
const keyLbl = aimKeyHeld() ? 'FIRE' : 'idle';
ctx.fillText(`ptr:${state.pointerLocked?'lock':'free'} key:${keyLbl} tgt:${tgt} mats:${state.modelMatrices.length} zoom:${state.currentZoom.toFixed(2)}`, 10, h - 10);
}
if (config.showCrosshair) {
const s = 10, g = 4;
ctx.strokeStyle = config.accentColor;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(cx, cy-g-s); ctx.lineTo(cx, cy-g);
ctx.moveTo(cx, cy+g); ctx.lineTo(cx, cy+g+s);
ctx.moveTo(cx-g-s, cy); ctx.lineTo(cx-g, cy);
ctx.moveTo(cx+g, cy); ctx.lineTo(cx+g+s, cy);
ctx.stroke();
ctx.fillStyle = config.accentColor;
ctx.fillRect(cx-1, cy-1, 2, 2);
}
if (config.showFov) {
ctx.beginPath();
ctx.arc(cx, cy, config.fov, 0, Math.PI * 2);
if (config.fovGradient && !config.performanceMode) {
const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, config.fov);
grad.addColorStop(0, 'transparent');
grad.addColorStop(0.8, 'transparent');
grad.addColorStop(1, config.accentColor + '40');
ctx.fillStyle = grad;
ctx.fill();
}
ctx.strokeStyle = config.accentColor;
ctx.lineWidth = 1.5;
ctx.stroke();
}
if (state.vpMatrices.length === 0) { clearFrameBuffers(); return; }
const vp = state.vpMatrices[state.vpMatrices.length - 1];
let bestTarget = null;
let bestScore = Infinity;
let bestLockData = null;
state.totalTargets = 0;
const MIN_DIST_SQ = 0.25;
const processed = [];
for (let i = 0; i < state.modelMatrices.length; i++) {
const mat = state.modelMatrices[i];
const wx = mat[12], wy = mat[13], wz = mat[14];
let dup = false;
for (let j = 0; j < processed.length; j++) {
const p = processed[j];
const ddx = wx-p.x, ddy = wy-p.y, ddz = wz-p.z;
if (ddx*ddx+ddy*ddy+ddz*ddz < MIN_DIST_SQ) { dup = true; break; }
}
if (dup) continue;
if (processed.length < 24) processed.push({ x: wx, y: wy, z: wz });
const posKey = `${Math.round(wx*10)}_${Math.round(wy*10)}_${Math.round(wz*10)}`;
if (config.velocityTracking && config.predictionEnabled) {
calculateVelocity(posKey, { x: wx, y: wy, z: wz });
}
const boneY = getBoneOffset();
const head = project(vp, wx, wy + boneY, wz, w, h);
const foot = project(vp, wx, wy, wz, w, h);
if (!head || !foot) continue;
const boxH = foot.y - head.y;
const boxW = boxH * 0.6;
if (boxH < 30 || boxH > 400) continue;
if (boxW < 15 || boxW > 250) continue;
const aspect = boxW / boxH;
if (aspect < 0.3 || aspect > 1.0) continue;
if (head.x < -100 || head.x > w + 100) continue;
if (head.y < -100 || head.y > h + 100) continue;
let px = wx, py = wy + boneY, pz = wz;
if (config.predictionEnabled && config.velocityTracking) {
const vel = state.velocities.get(posKey);
if (vel && now - vel.time < 200) {
const dt = config.predictionStrength * 0.05;
px += vel.vx * dt;
py += vel.vy * dt;
pz += vel.vz * dt;
}
}
const curVel = state.velocities.get(posKey);
if (!curVel || Math.abs(curVel.vx) > 0.2 || Math.abs(curVel.vy) > 0.5 || Math.abs(curVel.vz) > 0.2) {
state.deadPositions.set(posKey, now);
} else if (!state.deadPositions.has(posKey)) {
state.deadPositions.set(posKey, now);
}
const depthRatio = head.w / (foot.w + 0.001);
const isOccluded = depthRatio < 0.3 || depthRatio > 3.0;
const lastMoving = state.deadPositions.get(posKey);
const velCheck = state.velocities.get(posKey);
const isCurrentlyStill = velCheck && Math.abs(velCheck.vx) < 0.1 && Math.abs(velCheck.vy) < 0.3 && Math.abs(velCheck.vz) < 0.1;
const isDead = isCurrentlyStill && lastMoving && (now - lastMoving > 3000);
state.totalTargets++;
const dist3D = Math.sqrt(wx*wx + wy*wy + wz*wz);
const dist2D = Math.hypot(head.x - cx, head.y - cy);
// ── ESP Drawing ──
if (config.espEnabled) {
const inFov = dist2D <= config.fov;
const bx = head.x - boxW / 2;
const by = head.y;
const cornerLen = Math.min(boxW, boxH) * 0.25;
const alpha = isDead ? '40' : isOccluded ? '60' : 'ff';
const baseColor = inFov ? config.accentColor : '#888888';
const color = baseColor + alpha;
ctx.strokeStyle = color;
ctx.lineWidth = config.espThickness;
ctx.beginPath();
ctx.moveTo(bx, by+cornerLen); ctx.lineTo(bx, by); ctx.lineTo(bx+cornerLen, by);
ctx.moveTo(bx+boxW-cornerLen, by); ctx.lineTo(bx+boxW, by); ctx.lineTo(bx+boxW, by+cornerLen);
ctx.moveTo(bx, by+boxH-cornerLen); ctx.lineTo(bx, by+boxH); ctx.lineTo(bx+cornerLen, by+boxH);
ctx.moveTo(bx+boxW-cornerLen, by+boxH); ctx.lineTo(bx+boxW, by+boxH); ctx.lineTo(bx+boxW, by+boxH-cornerLen);
ctx.stroke();
if (!config.performanceMode) {
const barW = 3, barX = bx - barW - 3;
const hpGrad = ctx.createLinearGradient(barX, by, barX, by + boxH);
hpGrad.addColorStop(0, '#00e676' + alpha);
hpGrad.addColorStop(1, '#ff1744' + alpha);
ctx.fillStyle = '#00000060';
ctx.fillRect(barX-1, by-1, barW+2, boxH+2);
ctx.fillStyle = hpGrad;
ctx.fillRect(barX, by, barW, boxH);
if (config.showDistance) {
const distText = `${Math.round(dist3D)}m`;
ctx.font = 'bold 10px "Segoe UI", system-ui';
const tw = ctx.measureText(distText).width;
const pillX = head.x - tw/2 - 4, pillY = by - 18;
ctx.fillStyle = '#00000090';
ctx.beginPath();
ctx.roundRect(pillX, pillY, tw+8, 14, 4);
ctx.fill();
ctx.fillStyle = '#ffffff' + alpha;
ctx.fillText(distText, pillX+4, pillY+11);
}
if (isDead) {
ctx.font = 'bold 9px "Segoe UI", system-ui';
ctx.fillStyle = '#ff5555';
ctx.fillText('DEAD', head.x - 14, by + boxH + 12);
}
if (config.showTracers) {
ctx.beginPath();
ctx.moveTo(cx, h);
ctx.lineTo(foot.x, foot.y);
ctx.strokeStyle = baseColor + '40';
ctx.lineWidth = 1;
ctx.setLineDash([4,4]);
ctx.stroke();
ctx.setLineDash([]);
}
}
}
if (dist2D > config.fov) continue;
if (config.visibilityCheck) {
if (head.w < 0.01 || head.w > 100) continue;
if (dist3D / (dist2D + 1) > 50) continue;
}
if (isOccluded) continue;
if (isDead) continue;
const score = config.priority === 1 ? dist2D : head.w;
if (score < bestScore) {
bestScore = score;
const pred = project(vp, px, py, pz, w, h);
bestTarget = pred || head;
bestLockData = { wx, wy, wz, boneY, posKey };
}
}
// Target lock
if (config.targetLock) {
if (state.lockedTarget) {
const lt = state.lockedTarget;
let lx = lt.wx, ly = lt.wy + lt.boneY, lz = lt.wz;
if (config.predictionEnabled && config.velocityTracking) {
const vel = state.velocities.get(lt.posKey);
if (vel && now - vel.time < 200) {
const dt = config.predictionStrength * 0.05;
lx += vel.vx * dt; ly += vel.vy * dt; lz += vel.vz * dt;
}
}
const locked = project(vp, lx, ly, lz, w, h);
const lastSeen = state.lastPositions.get(lt.posKey);
if (locked && lastSeen && now - lastSeen.time < 500) {
bestTarget = locked;
} else {
state.lockedTarget = null;
}
}
if (!state.lockedTarget && bestLockData) state.lockedTarget = bestLockData;
} else if (state.lockedTarget) {
state.lockedTarget = null;
}
// Aim target highlight
if (config.aimbotEnabled && bestTarget) {
const pulse = 0.6 + Math.sin(now * 0.008) * 0.4;
const glowSize = 12 + pulse * 6;
ctx.beginPath();
ctx.arc(bestTarget.x, bestTarget.y, glowSize, 0, Math.PI * 2);
const glow = ctx.createRadialGradient(bestTarget.x, bestTarget.y, 0, bestTarget.x, bestTarget.y, glowSize);
glow.addColorStop(0, `rgba(255, 50, 50, ${0.5 * pulse})`);
glow.addColorStop(1, 'rgba(255, 50, 50, 0)');
ctx.fillStyle = glow;
ctx.fill();
ctx.beginPath();
ctx.arc(bestTarget.x, bestTarget.y, 4, 0, Math.PI * 2);
ctx.fillStyle = '#ff3232';
ctx.fill();
if (config.debugOverlay) {
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(bestTarget.x, bestTarget.y);
const lineGrad = ctx.createLinearGradient(cx, cy, bestTarget.x, bestTarget.y);
lineGrad.addColorStop(0, 'rgba(255,255,0,0.1)');
lineGrad.addColorStop(1, 'rgba(255,50,50,0.6)');
ctx.strokeStyle = lineGrad;
ctx.lineWidth = 1.5;
ctx.stroke();
}
}
// TriggerBot
if (config.triggerBot && bestTarget) {
const tdx = bestTarget.x - cx, tdy = bestTarget.y - cy;
if (Math.hypot(tdx, tdy) < config.triggerRadius && now - state.lastTriggerFire > config.triggerDelay) {
mouseClick(true);
setTimeout(() => mouseClick(false), 50);
state.lastTriggerFire = now;
}
}
// ── AIMBOT (browser smooth approach) ──
const shouldAim = config.aimbotEnabled && bestTarget && state.pointerLocked && aimKeyHeld();
// Zoom detection
if (vp) {
const vpScale = Math.abs(vp[0]);
if (vpScale > 0.5 && vpScale < 20) {
if (state.baselineVP0 === 0) {
state.baselineVP0 = vpScale;
} else if (vpScale < state.baselineVP0 * 1.1) {
state.baselineVP0 = state.baselineVP0 * 0.95 + vpScale * 0.05;
}
state.currentZoom = state.baselineVP0 > 0 ? vpScale / state.baselineVP0 : 1.0;
}
}
if (shouldAim) {
const dx = bestTarget.x - cx;
const dy = bestTarget.y - cy;
const dist = Math.hypot(dx, dy);
// Zoom compensation for scoped weapons
const zoom = state.currentZoom;
const zoomComp = zoom > 1.5 ? 1.0 / zoom : 1.0;
const DEADZONE = 3;
if (dist < DEADZONE) {
state.accX *= 0.7;
state.accY *= 0.7;
} else {
let smooth = config.aimSmooth;
const distRatio = Math.min(1, dist / config.fov);
if (dist < config.lockDist * 0.5) {
smooth *= 2.5;
} else if (dist < config.lockDist) {
const closeRatio = (dist - config.lockDist * 0.5) / (config.lockDist * 0.5);
smooth *= 1.5 + easeOutQuart(closeRatio);
} else if (dist < config.lockDist * 2) {
const midRatio = (dist - config.lockDist) / config.lockDist;
smooth *= 1.0 + (0.5 * easeInOutCubic(midRatio));
}
const easedProgress = applySmoothCurve(distRatio);
smooth = smooth * (0.8 + easedProgress * 0.4);
let tx = (dx / smooth) * zoomComp;
let ty = (dy / smooth) * zoomComp;
tx += state.accX * 0.85;
ty += state.accY * 0.85;
let mx = Math.round(tx);
let my = Math.round(ty);
state.accX = (tx - mx) * 0.9;
state.accY = (ty - my) * 0.9;
if (Math.abs(mx) >= 1 || Math.abs(my) >= 1) {
mouseMove(mx, my);
state.lastMouseMove = now;
}
}
} else {
state.accX *= 0.5;
state.accY *= 0.5;
}
// Crouch spam
if (config.crouchSpam && state.pointerLocked && state.input.left) {
if (now - state.lastCrouchToggle > config.crouchSpamSpeed) {
state.crouchDown = !state.crouchDown;
document.dispatchEvent(new KeyboardEvent(state.crouchDown ? 'keydown' : 'keyup', {
code: 'ShiftLeft', key: 'Shift', keyCode: 16, which: 16, bubbles: true, cancelable: true
}));
state.lastCrouchToggle = now;
}
} else if (state.crouchDown) {
document.dispatchEvent(new KeyboardEvent('keyup', {
code: 'ShiftLeft', key: 'Shift', keyCode: 16, which: 16, bubbles: true, cancelable: true
}));
state.crouchDown = false;
}
// Auto-strafe
if (config.autoStrafe && state.pointerLocked && state.input.left) {
if (now - state.lastStrafeToggle > config.autoStrafeSpeed) {
const oldKey = state.strafeRight ? 'KeyD' : 'KeyA';
document.dispatchEvent(new KeyboardEvent('keyup', { code: oldKey, key: state.strafeRight ? 'd' : 'a', bubbles: true }));
state.strafeRight = !state.strafeRight;
const newKey = state.strafeRight ? 'KeyD' : 'KeyA';
document.dispatchEvent(new KeyboardEvent('keydown', { code: newKey, key: state.strafeRight ? 'd' : 'a', bubbles: true }));
state.lastStrafeToggle = now;
}
} else if (state.lastStrafeToggle > 0) {
document.dispatchEvent(new KeyboardEvent('keyup', { code: 'KeyA', key: 'a', bubbles: true }));
document.dispatchEvent(new KeyboardEvent('keyup', { code: 'KeyD', key: 'd', bubbles: true }));
state.lastStrafeToggle = 0;
}
// Minimap radar
if (config.radarEnabled && state.vpMatrices.length > 0 && state.pointerLocked) {
const rSize = config.radarSize;
const rX = w - rSize - 15, rY = 15;
const rCx = rX + rSize/2, rCy = rY + rSize/2;
const rScale = (rSize / 2) / config.radarRange;
ctx.beginPath();
ctx.arc(rCx, rCy, rSize/2, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(0,0,0,0.55)';
ctx.fill();
ctx.strokeStyle = 'rgba(255,255,255,0.15)';
ctx.lineWidth = 1;
ctx.stroke();
ctx.beginPath();
ctx.moveTo(rCx, rY+4); ctx.lineTo(rCx, rY+rSize-4);
ctx.moveTo(rX+4, rCy); ctx.lineTo(rX+rSize-4, rCy);
ctx.strokeStyle = 'rgba(255,255,255,0.06)';
ctx.stroke();
ctx.beginPath();
ctx.arc(rCx, rCy, 3, 0, Math.PI * 2);
ctx.fillStyle = '#00e676';
ctx.fill();
const fwdX = -vp[2], fwdZ = -vp[10];
const fwdLen = Math.sqrt(fwdX*fwdX + fwdZ*fwdZ) || 1;
const cosA = fwdX/fwdLen, sinA = fwdZ/fwdLen;
for (let i = 0; i < state.modelMatrices.length; i++) {
const mat = state.modelMatrices[i];
const rx = mat[12]*cosA + mat[14]*sinA;
const rz = -mat[12]*sinA + mat[14]*cosA;
const dotX = rCx + rx*rScale, dotY = rCy - rz*rScale;
if (Math.hypot(dotX-rCx, dotY-rCy) > rSize/2 - 4) continue;
ctx.beginPath();
ctx.arc(dotX, dotY, 2.5, 0, Math.PI * 2);
ctx.fillStyle = '#ff3232';
ctx.fill();
}
}
// Off-screen indicators
if (config.offScreenIndicators && state.pointerLocked) {
const margin = 30;
for (let i = 0; i < state.modelMatrices.length; i++) {
const mat = state.modelMatrices[i];
const bY = getBoneOffset();
const projected = project(vp, mat[12], mat[13]+bY, mat[14], w, h);
if (!projected) continue;
if (projected.x >= 0 && projected.x <= w && projected.y >= 0 && projected.y <= h) continue;
const adx = projected.x - cx, ady = projected.y - cy;
const angle = Math.atan2(ady, adx);
const edgeX = Math.max(margin, Math.min(w-margin, cx + Math.cos(angle)*(w/2-margin)));
const edgeY = Math.max(margin, Math.min(h-margin, cy + Math.sin(angle)*(h/2-margin)));
ctx.save();
ctx.translate(edgeX, edgeY);
ctx.rotate(angle);
ctx.beginPath();
ctx.moveTo(10, 0); ctx.lineTo(-5, -6); ctx.lineTo(-5, 6);
ctx.closePath();
ctx.fillStyle = '#ff3232cc';
ctx.fill();
ctx.restore();
}
}
if (config.antiAFK && now - state.lastMouseMove > 60000) {
mouseMove(1, 0);
state.lastMouseMove = now;
}
state.pointerLocked = !!document.pointerLockElement;
if (now % 2000 < 16) {
const cutoff = now - 3000;
for (const [k,v] of state.lastPositions.entries()) if (v.time < cutoff) state.lastPositions.delete(k);
for (const [k,v] of state.velocities.entries()) if (v.time < cutoff) state.velocities.delete(k);
for (const [k,t] of state.deadPositions.entries()) if (t < cutoff) state.deadPositions.delete(k);
}
clearFrameBuffers();
}
function clearFrameBuffers() { state.matricesByProgram.clear(); }
// =====================================================================
// GUI
// =====================================================================
const TABS = [
{ id: 'aim', label: 'AIMBOT', icon: '\u25CE' },
{ id: 'esp', label: 'ESP', icon: '\u25A3' },
{ id: 'combat', label: 'COMBAT', icon: '\u2694' },
{ id: 'other', label: 'OTHER', icon: '\u2699' },
{ id: 'config', label: 'CONFIGS', icon: '\u25A1' },
];
let currentTab = 'aim';
const CSS = `
#d2-root *{box-sizing:border-box;margin:0;padding:0;font-family:'Segoe UI',system-ui,-apple-system,sans-serif}
#d2-root{position:fixed;display:flex;flex-direction:row;width:820px;height:540px;background:#0d0d11;border:1px solid rgba(255,255,255,.04);border-radius:10px;color:#c5c5cc;z-index:2147483646;user-select:none;box-shadow:0 30px 80px rgba(0,0,0,.85);overflow:hidden}
#d2-root .d2-sidebar{width:160px;background:#0a0a0e;display:flex;flex-direction:column;border-right:1px solid rgba(255,255,255,.04)}
#d2-root .d2-brand{padding:20px 12px 16px;text-align:center;overflow:hidden}
#d2-root .d2-brand-logo{font-size:22px;font-weight:900;letter-spacing:2px;color:#fff;line-height:1;white-space:nowrap}
#d2-root .d2-brand-logo span{color:var(--accent)}
#d2-root .d2-brand-sub{font-size:9px;color:#444;letter-spacing:4px;text-transform:uppercase;margin-top:2px}
#d2-root .d2-nav{flex:1;padding:8px;display:flex;flex-direction:column;gap:2px}
#d2-root .d2-nav-item{display:flex;align-items:center;gap:10px;padding:10px 14px;border-radius:6px;font-size:11px;font-weight:600;letter-spacing:1px;color:#555;cursor:pointer;transition:all .12s;position:relative}
#d2-root .d2-nav-item:hover{background:rgba(255,255,255,.025);color:#999}
#d2-root .d2-nav-item.active{color:var(--accent);background:rgba(168,85,247,.06)}
#d2-root .d2-nav-item.active::before{content:'';position:absolute;left:0;top:6px;bottom:6px;width:3px;background:var(--accent);border-radius:0 3px 3px 0}
#d2-root .d2-nav-icon{font-size:14px;width:18px;text-align:center;opacity:.8}
#d2-root .d2-status-box{margin:8px;padding:12px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.04);border-radius:8px}
#d2-root .d2-status-name{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;color:#ddd}
#d2-root .d2-status-dot{width:7px;height:7px;border-radius:50%;background:#00e676;box-shadow:0 0 6px #00e676}
#d2-root .d2-status-label{font-size:9px;color:#00e676;font-weight:700;letter-spacing:1px;margin-top:3px}
#d2-root .d2-status-ver{font-size:8px;color:#333;font-family:monospace;margin-top:6px}
#d2-root .d2-main{flex:1;display:flex;flex-direction:column;min-width:0}
#d2-root .d2-topbar{display:flex;align-items:center;justify-content:space-between;height:42px;padding:0 16px;background:#09090c;border-bottom:1px solid rgba(255,255,255,.04);cursor:move;flex-shrink:0}
#d2-root .d2-tab-pills{display:flex;gap:0;height:100%}
#d2-root .d2-tab-pill{display:flex;align-items:center;gap:6px;padding:0 16px;font-size:11px;font-weight:600;letter-spacing:1px;color:#555;cursor:pointer;border-bottom:2px solid transparent;transition:all .12s;height:100%}
#d2-root .d2-tab-pill:hover{color:#999}
#d2-root .d2-tab-pill.active{color:var(--accent);border-bottom-color:var(--accent)}
#d2-root .d2-tab-pill .tp-icon{font-size:12px;opacity:.7}
#d2-root .d2-win-btns{display:flex;gap:2px}
#d2-root .d2-win-btn{width:28px;height:28px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;color:#444;cursor:pointer;border-radius:4px;font-size:14px;transition:all .12s}
#d2-root .d2-win-btn:hover{background:rgba(255,255,255,.05);color:#ccc}
#d2-root .d2-win-btn.close:hover{background:#c53030;color:#fff}
#d2-root .d2-body{flex:1;overflow-y:auto;overflow-x:hidden;padding:16px 18px;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.08) transparent}
#d2-root .d2-body::-webkit-scrollbar{width:4px}
#d2-root .d2-body::-webkit-scrollbar-thumb{background:rgba(255,255,255,.1);border-radius:4px}
#d2-root .d2-body::-webkit-scrollbar-track{background:transparent}
#d2-root .d2-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
#d2-root .d2-grid .span-2{grid-column:span 2}
#d2-root .d2-card{background:rgba(255,255,255,.018);border:1px solid rgba(255,255,255,.04);border-radius:8px;padding:14px 16px;min-width:0}
#d2-root .d2-card-title{font-size:10px;font-weight:700;letter-spacing:2px;color:#666;text-transform:uppercase;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid rgba(255,255,255,.04)}
#d2-root .d2-row{display:flex;align-items:center;justify-content:space-between;padding:4px 0;min-height:28px}
#d2-root .d2-row>.label{font-size:12px;color:#bbb;white-space:nowrap}
#d2-root .d2-toggle{position:relative;width:36px;height:18px;cursor:pointer;display:inline-block;flex-shrink:0}
#d2-root .d2-toggle input{opacity:0;width:0;height:0;position:absolute}
#d2-root .d2-toggle .slider{position:absolute;inset:0;background:rgba(255,255,255,.07);border-radius:10px;transition:all .2s}
#d2-root .d2-toggle .slider:before{content:'';position:absolute;width:14px;height:14px;left:2px;top:2px;background:#666;border-radius:50%;transition:all .2s}
#d2-root .d2-toggle input:checked+.slider{background:color-mix(in srgb,var(--accent) 40%,transparent)}
#d2-root .d2-toggle input:checked+.slider:before{transform:translateX(18px);background:var(--accent);box-shadow:0 0 8px color-mix(in srgb,var(--accent) 60%,transparent)}
#d2-root .d2-slider{padding:5px 0}
#d2-root .d2-slider-label{display:flex;justify-content:space-between;font-size:11px;color:#888;margin-bottom:4px}
#d2-root .d2-slider-label .val{color:var(--accent);font-family:'Cascadia Code','Consolas',monospace;font-size:11px;font-weight:700}
#d2-root input[type=range]{-webkit-appearance:none;width:100%;height:4px;background:rgba(255,255,255,.06);border-radius:4px;outline:none;cursor:pointer}
#d2-root input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:14px;height:14px;background:var(--accent);border-radius:50%;cursor:pointer;border:2px solid #0d0d11;box-shadow:0 0 6px color-mix(in srgb,var(--accent) 50%,transparent)}
#d2-root .d2-select{padding:4px 0}
#d2-root .d2-select .label{font-size:11px;color:#777;margin-bottom:4px;display:block}
#d2-root select{width:100%;background:#111116;color:#ccc;border:1px solid rgba(255,255,255,.06);padding:7px 10px;border-radius:6px;font-size:11px;outline:none;cursor:pointer;font-family:inherit}
#d2-root select:hover{border-color:rgba(255,255,255,.12)}
#d2-root select:focus{border-color:var(--accent)}
#d2-root .d2-keybind{background:#111116;color:#ccc;border:1px solid rgba(255,255,255,.06);padding:5px 12px;border-radius:5px;font-size:10px;font-family:'Cascadia Code','Consolas',monospace;font-weight:600;cursor:pointer;min-width:72px;text-align:center;transition:all .12s}
#d2-root .d2-keybind:hover{border-color:var(--accent);color:var(--accent)}
#d2-root .d2-keybind.listening{background:var(--accent);color:#000;animation:d2Pulse 1s infinite}
@keyframes d2Pulse{0%,100%{opacity:1}50%{opacity:.5}}
#d2-root .d2-btn{width:100%;padding:9px;background:rgba(255,255,255,.025);color:var(--accent);border:1px solid rgba(255,255,255,.05);border-radius:6px;cursor:pointer;font-size:10px;font-weight:700;letter-spacing:1.2px;text-transform:uppercase;transition:all .15s;font-family:inherit}
#d2-root .d2-btn:hover{background:rgba(255,255,255,.05);border-color:var(--accent)}
#d2-root .d2-btn.danger{color:#ff5c5c}
#d2-root .d2-btn.danger:hover{border-color:#ff5c5c}
#d2-root .d2-stats{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px}
#d2-root .d2-stat{background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.04);border-radius:6px;padding:10px;text-align:center}
#d2-root .d2-stat-val{font-size:20px;font-weight:800;color:var(--accent);font-family:'Cascadia Code','Consolas',monospace}
#d2-root .d2-stat-lbl{font-size:7px;color:#444;text-transform:uppercase;letter-spacing:2px;margin-top:2px}
#d2-root .d2-badge{display:flex;align-items:center;justify-content:space-between;gap:8px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.04);border-radius:6px;padding:10px 14px;margin-top:10px}
#d2-root .d2-badge .lbl{font-size:9px;color:#555;text-transform:uppercase;letter-spacing:2px}
#d2-root .d2-badge .val{font-size:16px;font-weight:800;color:var(--accent);font-family:'Cascadia Code','Consolas',monospace}
#d2-root .d2-badge .hint{font-size:9px;color:#444;font-family:monospace}
#d2-root .d2-color{width:28px;height:28px;border:1px solid rgba(255,255,255,.08);border-radius:6px;padding:0;background:var(--accent);cursor:pointer;flex-shrink:0}
#d2-root input[type=color]{opacity:0;width:0;height:0;position:absolute}
`;
function row(label, inner) {
return `<div class="d2-row"><span class="label">${label}</span>${inner}</div>`;
}
function toggle(id, checked) {
return `<label class="d2-toggle"><input type="checkbox" id="${id}" ${checked ? 'checked' : ''}><span class="slider"></span></label>`;
}
function slider(id, label, val, min, max, step) {
return `<div class="d2-slider"><div class="d2-slider-label"><span>${label}</span><span class="val" id="${id}-v">${val}</span></div><input type="range" id="${id}" min="${min}" max="${max}" step="${step}" value="${val}"></div>`;
}
function select(id, label, options, current) {
const opts = options.map(o => `<option value="${o.v}" ${String(current)===String(o.v)?'selected':''}>${o.l}</option>`).join('');
return `<div class="d2-select"><span class="label">${label}</span><select id="${id}">${opts}</select></div>`;
}
function card(title, content, extraClass) {
return `<div class="d2-card ${extraClass||''}"><div class="d2-card-title">${title}</div>${content}</div>`;
}
function keybind(field, value) {
return `<button class="d2-keybind" data-rebind="${field}">${value || '\u2014'}</button>`;
}
function aimTab() {
return `<div class="d2-grid">` +
card('General', [
row('Aimbot', toggle('t-aim', config.aimbotEnabled)),
row('Aim Key', keybind('aimKey', config.aimKey)),
row('Visible Check', toggle('t-vis', config.visibilityCheck)),
row('Target Lock', toggle('t-lock', config.targetLock)),
].join('')) +
card('Target', [
select('sel-prio','Selection',[{v:1,l:'Closest to Crosshair'},{v:0,l:'Closest Distance'}], config.priority),
select('sel-bone','Hitbox',[{v:0,l:'Head'},{v:1,l:'Neck'},{v:2,l:'Body'}], config.hitbox),
slider('s-lockd','Lock Distance', config.lockDist, 5, 200, 1),
slider('s-smooth','Smoothing', config.aimSmooth, 1, 10, 0.1),
].join('')) +
card('Prediction', [
row('Enabled', toggle('t-pred', config.predictionEnabled)),
row('Track Velocity', toggle('t-vel', config.velocityTracking)),
slider('s-pred','Strength', config.predictionStrength, 0.5, 3, 0.1),
].join('')) +
card('TriggerBot', [
row('Enabled', toggle('t-trig', config.triggerBot)),
slider('s-trigr','Trigger Radius', config.triggerRadius, 4, 30, 1),
slider('s-trigd','Trigger Delay', config.triggerDelay, 0, 500, 10),
].join('')) +
`<div class="d2-badge span-2"><span class="lbl">Target Program</span><span class="val" id="d2-target-val">${currentTargetID()}</span><span class="hint">${config.autoDetect?'AUTO':'MANUAL'}</span></div>` +
`</div>`;
}
function espTab() {
return `<div class="d2-grid">` +
card('ESP', [
row('Box ESP', toggle('t-esp', config.espEnabled)),
row('Distance', toggle('t-dist', config.showDistance)),
row('Tracers', toggle('t-tracers', config.showTracers)),
slider('s-thick','Box Thickness', config.espThickness, 1, 5, 0.5),
].join('')) +
card('Overlay', [
row('FOV Circle', toggle('t-fov', config.showFov)),
row('FOV Gradient', toggle('t-grad', config.fovGradient)),
slider('s-fov','FOV Radius', config.fov, 50, 600, 10),
row('Crosshair', toggle('t-cross', config.showCrosshair)),
].join('')) +
card('Radar', [
row('Minimap', toggle('t-radar', config.radarEnabled)),
row('Off-Screen Arrows', toggle('t-offscreen', config.offScreenIndicators)),
slider('s-rsize','Radar Size', config.radarSize, 80, 200, 10),
slider('s-rrange','Radar Range', config.radarRange, 30, 200, 10),
].join('')) +
card('Display', [
row('Show FPS', toggle('t-fps', config.showFPS)),
row('Debug Strip', toggle('t-dbg', config.debugOverlay)),
].join('')) +
`</div>`;
}
function combatTab() {
return `<div class="d2-grid">` +
card('Crouch Spam', [
row('Enabled', toggle('t-crouch', config.crouchSpam)),
slider('s-crouchspd','Speed (ms)', config.crouchSpamSpeed, 20, 300, 10),
].join('')) +
card('Auto Strafe', [
row('Enabled', toggle('t-strafe', config.autoStrafe)),
slider('s-strafespd','Speed (ms)', config.autoStrafeSpeed, 40, 300, 10),
].join('')) +
card('Anti-AFK', [
row('Enabled', toggle('t-afk', config.antiAFK)),
].join('')) +
card('Performance', [
row('Performance Mode', toggle('t-perf', config.performanceMode)),
row('Block Fullscreen', toggle('t-blockfs', config.blockFullscreen)),
].join('')) +
`</div>`;
}
function otherTab() {
return `<div class="d2-grid">` +
card('FOV Hack', [
row('Enabled', toggle('t-fovhack', config.fovHack)),
slider('s-fovscale','FOV Scale', config.fovHackScale, 0.3, 1.0, 0.05),
].join('')) +
card('Stats', `
<div class="d2-stats">
<div class="d2-stat"><div class="d2-stat-val" id="stat-fps">${state.fps}</div><div class="d2-stat-lbl">FPS</div></div>
<div class="d2-stat"><div class="d2-stat-val" id="stat-tgts">${state.totalTargets}</div><div class="d2-stat-lbl">Targets</div></div>
<div class="d2-stat"><div class="d2-stat-val" id="stat-prog">${state.programScores.size}</div><div class="d2-stat-lbl">Programs</div></div>
</div>
`) +
card('Detection', [
`<div style="display:flex;gap:8px"><button class="d2-btn" id="btn-auto">${config.autoDetect?'Auto Detect ON':'Enable Auto'}</button><button class="d2-btn" id="btn-reset-tgt">Reset Target</button></div>`,
].join(''), 'span-2') +
`</div>`;
}
function configTab() {
return `<div class="d2-grid">` +
card('Interface', [
row('Menu Key', keybind('menuKey', config.menuKey)),
row('Accent Color', `<label class="d2-color" style="background:${config.accentColor}"><input type="color" id="c-accent" value="${config.accentColor}"></label>`),
].join('')) +
card('Danger Zone', `
<button class="d2-btn danger" id="btn-reset">Reset All Settings</button>
`) +
`</div>`;
}
function tabContent() {
if (currentTab === 'aim') return aimTab();
if (currentTab === 'esp') return espTab();
if (currentTab === 'combat') return combatTab();
if (currentTab === 'other') return otherTab();
if (currentTab === 'config') return configTab();
return '';
}
function createGUI() {
if (document.getElementById('d2-root')) return;
if (!document.body) return;
let style = document.getElementById('d2-style');
if (!style) {
style = document.createElement('style');
style.id = 'd2-style';
style.textContent = CSS;
document.head.appendChild(style);
}
document.documentElement.style.setProperty('--accent', config.accentColor);
const root = document.createElement('div');
root.id = 'd2-root';
root.style.left = config.x + 'px';
root.style.top = config.y + 'px';
root.style.display = config.menuVisible ? 'flex' : 'none';
root.innerHTML = `
<div class="d2-sidebar">
<div class="d2-brand">
<div class="d2-brand-logo"><span>D</span>ESTINY</div>
<div class="d2-brand-sub">DEADSHOT</div>
</div>
<div class="d2-nav">
${TABS.map(t => `<div class="d2-nav-item ${t.id===currentTab?'active':''}" data-tab="${t.id}"><span class="d2-nav-icon">${t.icon}</span><span>${t.label}</span></div>`).join('')}
</div>
<div class="d2-status-box">
<div class="d2-status-name"><span class="d2-status-dot"></span> DESTINY</div>
<div class="d2-status-label">STATUS: UNDETECTED</div>
<div class="d2-status-ver">Version 3.0.0<br>destiny.menu</div>
</div>
</div>
<div class="d2-main">
<div class="d2-topbar" id="d2-header">
<div class="d2-tab-pills">
${TABS.map(t => `<div class="d2-tab-pill ${t.id===currentTab?'active':''}" data-tab="${t.id}"><span class="tp-icon">${t.icon}</span><span>${t.label}</span></div>`).join('')}
</div>
<div class="d2-win-btns">
<button class="d2-win-btn close" id="d2-close" title="Close">\u00D7</button>
</div>
</div>
<div class="d2-body" id="d2-body">${tabContent()}</div>
</div>
`;
document.body.appendChild(root);
// Drag
const header = document.getElementById('d2-header');
let drag = false, ox = 0, oy = 0;
header.addEventListener('mousedown', (e) => {
drag = true; ox = e.clientX - root.offsetLeft; oy = e.clientY - root.offsetTop; e.preventDefault();
});
window.addEventListener('mousemove', (e) => {
if (!drag) return;
const x = Math.max(0, Math.min(window.innerWidth - root.offsetWidth, e.clientX - ox));
const y = Math.max(0, Math.min(window.innerHeight - root.offsetHeight, e.clientY - oy));
root.style.left = x + 'px'; root.style.top = y + 'px';
config.x = x; config.y = y;
});
window.addEventListener('mouseup', () => { if (drag) save(); drag = false; });
root.querySelectorAll('.d2-nav-item, .d2-tab-pill').forEach(el => {
el.addEventListener('click', (e) => { e.stopPropagation(); currentTab = el.dataset.tab; refreshGUI(); });
});
document.getElementById('d2-close').addEventListener('click', () => {
config.menuVisible = false; root.style.display = 'none'; saveImmediate();
});
attachHandlers();
}
function refreshGUI() {
const root = document.getElementById('d2-root');
if (!root) { createGUI(); return; }
document.documentElement.style.setProperty('--accent', config.accentColor);
root.querySelectorAll('.d2-nav-item').forEach(el => el.classList.toggle('active', el.dataset.tab === currentTab));
root.querySelectorAll('.d2-tab-pill').forEach(el => el.classList.toggle('active', el.dataset.tab === currentTab));
const body = document.getElementById('d2-body');
if (body) body.innerHTML = tabContent();
attachHandlers();
refreshTargetBadge();
}
function bindToggle(id, field) {
const el = document.getElementById(id);
if (el) el.addEventListener('change', e => { config[field] = e.target.checked; save(); });
}
function bindSlider(id, field, parser = parseFloat) {
const el = document.getElementById(id);
const valEl = document.getElementById(id + '-v');
if (el) el.addEventListener('input', e => {
const v = parser(e.target.value);
config[field] = v;
if (valEl) valEl.textContent = v;
save();
});
}
function bindSelect(id, field, parser = (x => x)) {
const el = document.getElementById(id);
if (el) el.addEventListener('change', e => { config[field] = parser(e.target.value); save(); });
}
function attachHandlers() {
bindToggle('t-aim', 'aimbotEnabled');
bindToggle('t-pred', 'predictionEnabled');
bindToggle('t-vel', 'velocityTracking');
bindToggle('t-lock', 'targetLock');
bindToggle('t-trig', 'triggerBot');
bindToggle('t-crouch','crouchSpam');
bindToggle('t-strafe','autoStrafe');
bindSlider('s-crouchspd','crouchSpamSpeed', parseInt);
bindSlider('s-strafespd','autoStrafeSpeed', parseInt);
bindSlider('s-lockd', 'lockDist', parseInt);
bindSlider('s-smooth','aimSmooth');
bindSlider('s-pred', 'predictionStrength');
bindSlider('s-trigr', 'triggerRadius', parseInt);
bindSlider('s-trigd', 'triggerDelay', parseInt);
bindSelect('sel-bone','hitbox', parseInt);
bindSelect('sel-prio','priority', parseInt);
const btnAuto = document.getElementById('btn-auto');
if (btnAuto) btnAuto.addEventListener('click', () => { config.autoDetect = true; save(); refreshGUI(); });
const btnResetTgt = document.getElementById('btn-reset-tgt');
if (btnResetTgt) btnResetTgt.addEventListener('click', () => {
config.autoDetect = true; config.manualTargetID = -1;
state.detectedTargetID = -1; state.programScores.clear();
save(); refreshGUI();
});
bindToggle('t-esp', 'espEnabled');
bindToggle('t-dist', 'showDistance');
bindToggle('t-tracers', 'showTracers');
bindSlider('s-thick', 'espThickness');
bindToggle('t-fov', 'showFov');
bindToggle('t-grad', 'fovGradient');
bindSlider('s-fov', 'fov', parseInt);
bindToggle('t-cross', 'showCrosshair');
bindToggle('t-fps', 'showFPS');
bindToggle('t-dbg', 'debugOverlay');
bindToggle('t-radar', 'radarEnabled');
bindSlider('s-rsize', 'radarSize', parseInt);
bindSlider('s-rrange', 'radarRange', parseInt);
bindToggle('t-offscreen','offScreenIndicators');
bindToggle('t-vis', 'visibilityCheck');
bindToggle('t-perf', 'performanceMode');
bindToggle('t-fovhack', 'fovHack');
bindSlider('s-fovscale','fovHackScale');
bindToggle('t-afk', 'antiAFK');
const blockFs = document.getElementById('t-blockfs');
if (blockFs) blockFs.addEventListener('change', e => {
config.blockFullscreen = e.target.checked; saveImmediate();
if (confirm('Reload to apply fullscreen setting?')) location.reload();
});
const accent = document.getElementById('c-accent');
if (accent) accent.addEventListener('input', e => {
config.accentColor = e.target.value;
document.documentElement.style.setProperty('--accent', config.accentColor);
const swatch = accent.parentElement;
if (swatch) swatch.style.background = config.accentColor;
save();
});
const reset = document.getElementById('btn-reset');
if (reset) reset.addEventListener('click', () => {
if (!confirm('Reset all settings?')) return;
config = { ...defaultConfig };
saveImmediate();
refreshGUI();
});
document.querySelectorAll('#d2-root .d2-keybind').forEach(btn => {
const field = btn.dataset.rebind;
const aimKeyDropdown = field === 'aimKey';
btn.addEventListener('click', () => {
if (aimKeyDropdown) {
const opts = ['RightClick','LeftClick','ShiftLeft','AltLeft','Always'];
const idx = opts.indexOf(config.aimKey);
config.aimKey = opts[(idx+1)%opts.length];
saveImmediate(); refreshGUI();
return;
}
document.querySelectorAll('#d2-root .d2-keybind').forEach(b => b.classList.remove('listening'));
btn.classList.add('listening');
btn.textContent = '\u2026';
state.rebindingField = field;
});
});
}
function refreshTargetBadge() {
const tv = document.getElementById('d2-target-val');
if (tv) tv.textContent = currentTargetID();
}
function updateStatusBar() {
const c = document.getElementById('stat-fps'); if (c) c.textContent = state.fps;
const d = document.getElementById('stat-tgts'); if (d) d.textContent = state.totalTargets;
const e = document.getElementById('stat-prog'); if (e) e.textContent = state.programScores.size;
}
// =====================================================================
// INIT
// =====================================================================
function init() {
setupCanvas();
createGUI();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();