Modified to allow toggling Chams with [K] for environment maintenance.
// ==UserScript==
// @name betteraimbot
// @namespace http://tampermonkey.net/
// @version 12
// @description Modified to allow toggling Chams with [K] for environment maintenance.
// @author furtgay & AI
// @match *://*deadshot.io/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=deadshot.io
// @grant unsafeWindow
// @run-at document-start
// @license MIT
// ==/UserScript==
(() => {
'use strict';
const config = {
fov: 100,
sensitivity: 0.1,
headOffset: 0.6,
prediction: 2,
enemyColor: '#ff0000',
boxEnabled: false,
};
// 環境維護開關:控制透視功能的執行
let chamsEnabled = true;
const MENU_STYLE = `
#cheat-menu {
position: fixed; top: 20px; right: 20px; width: 220px;
background: rgba(10, 10, 10, 0.9); backdrop-filter: blur(10px);
border: 1px solid rgba(0, 255, 210, 0.5); border-radius: 8px;
color: #fff; font-family: sans-serif; padding: 15px; z-index: 2147483647;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); user-select: none; display: block;
transition: opacity 0.2s ease;
}
.a-row { margin-bottom: 12px; }
.a-label { display: block; font-size: 10px; color: #888; margin-bottom: 5px; text-transform: uppercase; }
.a-val { float: right; color: #00ffd2; }
.a-slider { width: 100%; height: 4px; background: #333; border-radius: 2px; appearance: none; outline: none; }
.a-slider::-webkit-slider-thumb { appearance: none; width: 12px; height: 12px; background: #00ffd2; border-radius: 50%; cursor: pointer; box-shadow: 0 0 8px #00ffd2; }
.a-btn {
width: 100%; padding: 6px; background: rgba(0, 255, 210, 0.1);
border: 1px solid rgba(0, 255, 210, 0.3); color: #00ffd2;
font-size: 11px; cursor: pointer; margin-bottom: 5px; border-radius: 4px;
transition: all 0.2s;
}
.a-btn.active { background: rgba(0, 255, 210, 0.3); border-color: #00ffd2; }
`;
const createUI = () => {
const style = document.createElement('style'); style.innerHTML = MENU_STYLE; document.head.appendChild(style);
const menu = document.createElement('div'); menu.id = 'cheat-menu';
menu.innerHTML = /* HTML */`
<div class="a-row"><label class="a-label">Aim FOV <span id="v-fov" class="a-val">${config.fov}</span></label><input type="range" id="i-fov" class="a-slider" min="10" max="1000" value="${config.fov}"></div>
<div class="a-row"><label class="a-label">Sensitivity <span id="v-sens" class="a-val">${config.sensitivity}</span></label><input type="range" id="i-sens" class="a-slider" min="0.1" max="2.5" step="0.05" value="${config.sensitivity}"></div>
<div class="a-row"><label class="a-label">Prediction <span id="v-pred" class="a-val">${config.prediction}</span></label><input type="range" id="i-pred" class="a-slider" min="0" max="2" step="0.1" value="${config.prediction}"></div>
<div class="a-row"><label class="a-label">Enemy Color <span id="v-color" class="a-val">${config.enemyColor}</span></label><input type="color" id="i-color" style="width:100%; height:25px; background:transparent; border:1px solid #333; cursor:pointer;" value="${config.enemyColor}"></div>
<button id="btn-box" class="a-btn">Box ESP: OFF</button>
<div style="font-size: 9px; color: #888; text-align: center; margin-top: 10px;">[Insert] Toggle Menu | [K] Toggle Chams</div>
`;
document.body.appendChild(menu);
const link = (id, key, valId) => {
const el = document.getElementById(id), vEl = document.getElementById(valId);
el.oninput = () => { config[key] = parseFloat(el.value); vEl.innerText = el.value; };
};
link('i-fov', 'fov', 'v-fov'); link('i-sens', 'sensitivity', 'v-sens'); link('i-pred', 'prediction', 'v-pred');
const colorInput = document.getElementById('i-color'), colorVal = document.getElementById('v-color');
colorInput.oninput = () => { config.enemyColor = colorInput.value; colorVal.innerText = colorInput.value; };
const setupBtn = (id, key, label) => {
const btn = document.getElementById(id);
btn.onclick = () => {
config[key] = !config[key];
btn.innerText = `${label}: ${config[key] ? 'ON' : 'OFF'}`;
btn.classList.toggle('active', config[key]);
};
};
setupBtn('btn-box', 'boxEnabled', 'Box ESP');
window.addEventListener('keydown', (e) => {
if (e.key === 'Insert') menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
// 按下 K 鍵切換透視與功能
if (e.key.toLowerCase() === 'k') {
chamsEnabled = !chamsEnabled;
config.boxEnabled = chamsEnabled; // 同步 Box ESP 狀態
// 更新 UI 按鈕狀態
const boxBtn = document.getElementById('btn-box');
if (boxBtn) {
boxBtn.innerText = `Box ESP: ${config.boxEnabled ? 'ON' : 'OFF'}`;
boxBtn.classList.toggle('active', config.boxEnabled);
}
console.log(`[Env Guard] Global status: ${chamsEnabled ? 'ON' : 'OFF'}`);
}
});
};
const detectedPlayers = [];
let currentTarget = null, isAiming = false;
const PLAYER_HISTORY = new Map();
let viewProjMatrix = null;
const PLAYER_VERTEX_SET = new Set([8829, 10392, 10944, 16413]);
let overlay = null, ctx2d = null;
const createOverlay = () => {
overlay = document.createElement('canvas');
overlay.id = 'cheat-overlay';
overlay.style = 'position:fixed; top:0; left:0; width:100%; height:100%; pointer-events:none; z-index:2147483646;';
document.body.appendChild(overlay);
ctx2d = overlay.getContext('2d');
const resize = () => { overlay.width = window.innerWidth; overlay.height = window.innerHeight; };
window.addEventListener('resize', resize); resize();
};
const uniformCache = new Map();
let activeTextureUnit = 0;
const textureUnitBindings = new Array(32).fill(null);
const textureDataMap = new WeakMap();
let currentProgram = null;
let isDepthEnabled = false;
const multiplyMatrixVec4 = (m, [x, y, z, w]) => [
m[0] * x + m[4] * y + m[8] * z + m[12] * w, m[1] * x + m[5] * y + m[9] * z + m[13] * w,
m[2] * x + m[6] * y + m[10] * z + m[14] * w, m[3] * x + m[7] * y + m[11] * z + m[15] * w,
];
const worldToScreen = (pos) => {
if (!viewProjMatrix) return null;
const clip = multiplyMatrixVec4(viewProjMatrix, [...pos, 1]);
if (clip[3] <= 0.001) return null;
return [(clip[0] / clip[3] + 1) * 0.5 * window.innerWidth, (1 - clip[1] / clip[3]) * 0.5 * window.innerHeight];
};
class PlayerDetector {
static getBonePos = (boneData, index) => {
const offset = index * 16;
if (boneData.length < offset + 15) return null;
return [boneData[offset + 12], boneData[offset + 13], boneData[offset + 14]];
};
static getCachedMatrices = (program) => {
const cache = uniformCache.get(program);
if (!cache) return { vp: null, model: null, boneUnit: null, opacity: 1.0, isEnemy: true };
let vp = null, model = null, boneUnit = null, opacity = 1.0, isEnemy = false;
for (const [name, val] of cache) {
if (val?.length === 16) {
if (val[11] !== 0 && Math.abs(val[15]) > 1.0) vp = val;
else if (/modelMatrix/i.test(name)) model = val;
} else if (name === 'boneTexture') boneUnit = val;
else if (name === 'opacity') opacity = val;
else if (typeof val === 'number' && val === 1 && !['left', 'specMultMult', 'opacity'].includes(name) && name.length > 5) {
isEnemy = true;
}
}
return { vp, model, boneUnit, opacity, isEnemy };
};
static processDrawCall = (gl, program, vertexCount) => {
const { vp, model, boneUnit, opacity, isEnemy } = this.getCachedMatrices(program);
if (vp) { viewProjMatrix = vp }
if (!model || !PLAYER_VERTEX_SET.has(vertexCount) || opacity < 0.1 || !isEnemy) return;
let pos = [model[12], model[13] + config.headOffset, model[14]];
let bones = {};
if (boneUnit !== null && textureUnitBindings[boneUnit]) {
const boneData = textureDataMap.get(textureUnitBindings[boneUnit]);
if (boneData?.length >= 23 * 16) {
const b22 = 22 * 16;
pos = [boneData[b22 + 12], boneData[b22 + 13] + config.headOffset, boneData[b22 + 14]];
if (config.boxEnabled) {
const indices = { head: 22, lAnkle: 3 };
for (const [name, idx] of Object.entries(indices)) {
const bPos = this.getBonePos(boneData, idx);
if (bPos) bones[name] = bPos;
}
}
}
}
if (!pos.every(Number.isFinite)) return;
const playerKey = `${vertexCount}_${model[12].toFixed(1)}_${model[14].toFixed(1)}`;
let finalPos = [...pos];
if (config.prediction > 0) {
const hist = PLAYER_HISTORY.get(playerKey) || { last: pos, vel: [0, 0, 0], tick: Date.now() };
const now = Date.now(), dt = (now - hist.tick) / 1000;
// 優化:過濾極小或極大的時間差,減少抖動
if (dt > 0.008 && dt < 0.2) {
const instVel = [(pos[0] - hist.last[0]) / dt, (pos[1] - hist.last[1]) / dt, (pos[2] - hist.last[2]) / dt];
// 優化:更平滑的 EMA 濾波 (0.7 / 0.3)
hist.vel = hist.vel.map((v, i) => v * 0.7 + instVel[i] * 0.3);
// 優化:根據預測強度計算前瞻時間 (0.05 為經驗基準)
const lookAhead = 0.05 * config.prediction;
finalPos = pos.map((v, i) => v + hist.vel[i] * lookAhead);
}
PLAYER_HISTORY.set(playerKey, { last: pos, vel: hist.vel, tick: now });
}
if (finalPos.every(Number.isFinite)) {
detectedPlayers.push({ position: finalPos, bones, isEnemy });
}
};
}
const originalX = Object.getOwnPropertyDescriptor(MouseEvent.prototype, 'movementX').get;
const originalY = Object.getOwnPropertyDescriptor(MouseEvent.prototype, 'movementY').get;
let aimRemainderX = 0, aimRemainderY = 0;
let lastAimbotFrame = 0, cachedSPos = null;
const applyAimbot = (orig, isY) => {
if (isAiming && currentTarget) {
const now = performance.now();
// 效能優化:同一個 frame 內只計算一次螢幕座標
if (now !== lastAimbotFrame) {
cachedSPos = worldToScreen(currentTarget.position);
lastAimbotFrame = now;
}
if (cachedSPos && Number.isFinite(cachedSPos[0]) && Number.isFinite(cachedSPos[1])) {
const center = isY ? window.innerHeight / 2 : window.innerWidth / 2;
const delta = (cachedSPos[isY ? 1 : 0] - center) * config.sensitivity;
// 精準度優化:累積並補償捨入誤差 (Accumulator)
let total = delta + (isY ? aimRemainderY : aimRemainderX);
let movement = Math.round(total);
if (isY) aimRemainderY = total - movement;
else aimRemainderX = total - movement;
if (Number.isFinite(movement)) {
const MAX_SNAP = 120; // 提高上限以增加反應速度
return Math.max(-MAX_SNAP, Math.min(MAX_SNAP, movement));
}
}
} else {
// 停止瞄準時重置累積器
aimRemainderX = 0; aimRemainderY = 0;
}
return typeof orig === 'number' ? orig : 0;
};
Object.defineProperty(MouseEvent.prototype, 'movementX', { get: function () { return applyAimbot(originalX.call(this), false); } });
Object.defineProperty(MouseEvent.prototype, 'movementY', { get: function () { return applyAimbot(originalY.call(this), true); } });
const hookWebGL = (GL) => {
if (!GL || GL._hooked) return;
GL._hooked = true;
GL.enable = new Proxy(GL.enable, { apply(target, thisArg, args) { if (args[0] === 2929) isDepthEnabled = true; return Reflect.apply(...arguments); } });
GL.disable = new Proxy(GL.disable, { apply(target, thisArg, args) { if (args[0] === 2929) isDepthEnabled = false; return Reflect.apply(...arguments); } });
GL.useProgram = new Proxy(GL.useProgram, { apply(target, thisArg, args) { currentProgram = args[0]; return Reflect.apply(...arguments); } });
GL.getUniformLocation = new Proxy(GL.getUniformLocation, { apply(target, thisArg, args) { const loc = Reflect.apply(...arguments); if (loc) loc._name = args[1]; return loc; } });
GL.activeTexture = new Proxy(GL.activeTexture, { apply(target, thisArg, args) { activeTextureUnit = args[0] - thisArg.TEXTURE0; return Reflect.apply(...arguments); } });
GL.bindTexture = new Proxy(GL.bindTexture, { apply(target, thisArg, args) { if (args[0] === thisArg.TEXTURE_2D) textureUnitBindings[activeTextureUnit] = args[1]; return Reflect.apply(...arguments); } });
GL.texImage2D = new Proxy(GL.texImage2D, {
apply(target, thisArg, args) {
const p = args[args.length - 1];
if (p instanceof Float32Array) {
const tex = textureUnitBindings[activeTextureUnit];
if (tex) textureDataMap.set(tex, p);
}
return Reflect.apply(...arguments);
}
});
["uniformMatrix4fv", "uniform1f", "uniform1i"].forEach(s => {
if (GL[s]) {
GL[s] = new Proxy(GL[s], {
apply(target, thisArg, args) {
const loc = args[0];
if (currentProgram && loc?._name) {
if (!uniformCache.has(currentProgram)) uniformCache.set(currentProgram, new Map());
let val = s === "uniformMatrix4fv" ? args[2].slice() : args[1];
if (s === "uniformMatrix4fv" && val.length === 16) {
if (val[11] !== 0 && Math.abs(val[15]) > 1.0) viewProjMatrix = val;
}
uniformCache.get(currentProgram).set(loc._name, val);
}
return Reflect.apply(...arguments);
}
});
}
});
GL.drawElements = new Proxy(GL.drawElements, {
apply(target, thisArg, args) {
const gl = thisArg, vC = args[1];
if (currentProgram && vC > 1000) PlayerDetector.processDrawCall(gl, currentProgram, vC);
if (PLAYER_VERTEX_SET.has(vC)) {
const { isEnemy } = PlayerDetector.getCachedMatrices(currentProgram);
const wasEnabled = isDepthEnabled;
if (chamsEnabled && isEnemy) {
// 敵人透視:關閉深度測試並套用自定義顏色
if (wasEnabled) gl.disable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
const oldBlendSrc = gl.getParameter(gl.BLEND_SRC_RGB);
const oldBlendDst = gl.getParameter(gl.BLEND_DST_RGB);
const oldBlendCol = gl.getParameter(gl.BLEND_COLOR);
// 強制套用顏色混合
gl.blendFunc(gl.CONSTANT_COLOR, gl.ZERO);
const r = parseInt(config.enemyColor.slice(1, 3), 16) / 255;
const g = parseInt(config.enemyColor.slice(3, 5), 16) / 255;
const b = parseInt(config.enemyColor.slice(5, 7), 16) / 255;
gl.blendColor(r, g, b, 1);
const result = Reflect.apply(...arguments);
// 恢復原始狀態
gl.blendFunc(oldBlendSrc, oldBlendDst);
gl.blendColor(...oldBlendCol);
if (wasEnabled) gl.enable(gl.DEPTH_TEST);
return result;
} else if (chamsEnabled) {
// 隊友:僅開啟透視但不改色
if (wasEnabled) gl.disable(gl.DEPTH_TEST);
const result = Reflect.apply(...arguments);
if (wasEnabled) gl.enable(gl.DEPTH_TEST);
return result;
}
}
return Reflect.apply(...arguments);
}
});
};
unsafeWindow.HTMLCanvasElement.prototype.getContext = new Proxy(unsafeWindow.HTMLCanvasElement.prototype.getContext, {
apply(target, thisArg, args) {
const ctx = Reflect.apply(...arguments);
if (ctx && (args[0] === 'webgl2' || args[0] === 'webgl')) {
if (args[1]) args[1].preserveDrawingBuffer = false;
hookWebGL(Object.getPrototypeOf(ctx));
}
return ctx;
}
});
if (unsafeWindow.WebGLRenderingContext) hookWebGL(unsafeWindow.WebGLRenderingContext.prototype);
if (unsafeWindow.WebGL2RenderingContext) hookWebGL(unsafeWindow.WebGL2RenderingContext.prototype);
const init = () => {
createUI();
createOverlay();
window.addEventListener('mousedown', (e) => { if (e.button === 2) isAiming = true; });
window.addEventListener('mouseup', (e) => { if (e.button === 2) isAiming = false; });
const loop = () => {
ctx2d.clearRect(0, 0, overlay.width, overlay.height);
const cx = window.innerWidth / 2, cy = window.innerHeight / 2;
let best = null, minDist = config.fov;
for (let i = 0; i < detectedPlayers.length; i++) {
const p = detectedPlayers[i];
const sPos = worldToScreen(p.position);
if (!sPos) continue;
// 優化:快取螢幕座標以供後續繪製使用
p.screenPos = sPos;
const d = Math.hypot(sPos[0] - cx, sPos[1] - cy);
if (d < minDist) { minDist = d; best = p; }
if (p.isEnemy) {
ctx2d.strokeStyle = config.enemyColor;
ctx2d.lineWidth = 1.5;
// 繪製邊框 (Box ESP)
if (config.boxEnabled && p.bones.head && p.bones.lAnkle) {
const hPos = worldToScreen(p.bones.head);
const fPos = worldToScreen(p.bones.lAnkle);
if (hPos && fPos) {
const h = Math.abs(fPos[1] - hPos[1]) * 1.2;
const w = h / 2;
ctx2d.strokeRect(sPos[0] - w / 2, sPos[1] - h * 0.1, w, h);
}
}
}
}
currentTarget = best;
detectedPlayers.length = 0;
if (PLAYER_HISTORY.size > 50) {
const now = Date.now();
for (const [id, data] of PLAYER_HISTORY) if (now - data.tick > 2000) PLAYER_HISTORY.delete(id);
}
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
};
if (document.readyState === 'complete') init();
else window.addEventListener('load', init);
})();