ZoomHack, AimBow, AutoHeal, ESP, Tracers, Scout, WalkUnlock, KillMessage, GoldBot, AutoReconnect, AntiAFK, Macros
// ==UserScript==
// @name TakeMineClient[1.2]
// @namespace Violentmonkey Scripts
// @icon https://takemine.io/favicon-32x32.png
// @version 1.2
// @match *://takemine.io/*
// @grant unsafeWindow
// @grant GM_addStyle
// @grant GM_info
// @author Drik
// @description:en ZoomHack, AimBow, TriggerBot, AutoHeal, ESP, Tracers, Scout, WalkUnlock, KillMessage, GoldBot, AutoReconnect, AntiAFK, HUD, Macros list
// @description:ru Зум хак, Аим бот, Триггер бот, Авто хил, Есп, Трейсера, Скаут, Валк унлок, Килл сообщения, Голд бот, Авто перезаход, Анти АФК, Меню, Список макросов
// @run-at document-start
// @license MIT
// @description ZoomHack, AimBow, AutoHeal, ESP, Tracers, Scout, WalkUnlock, KillMessage, GoldBot, AutoReconnect, AntiAFK, Macros
// ==/UserScript==
(function() {
'use strict';
const _$gi = (typeof GM_info !== 'undefined') ? GM_info : null;
const _$raw = _$gi && _$gi.script ? (_$gi.script.updateURL || '') : null;
if (_$raw === null) {
alert('Install the original TakeMineClient from GreasyFork');
throw new Error('TMC');
}
const CFG_KEY = 'TakeMineClient';
let menuKey = 'F4';
let currentTheme = 'dark';
let currentLang = 'en';
let trapBind = '';
let ballistaBind = '';
const I18N = {
en: {
autoheal: ['Auto Heal', 'Auto heal when HP < 60% and food available'],
aimbow: ['Aim Bow', 'Aim with a bow toward the nearest enemy'],
triggerbot: ['Trigger Bot', 'Automatically attacks when it hits the player\'s hitbox'],
autoreconnect: ['Auto Reconnect', 'Instantly respawn on death'],
killmessage: ['Kill Message', 'Send a chat message when you kill a player'],
zoom: ['Zoom', 'Zoom hack (CTRL + mouse wheel)'],
esp: ['ESP', 'Draws precise hitboxes on players'],
tracers: ['Tracers', 'Draws lines from you to each enemy'],
hud: ['HUD', 'Shows FPS, ping and player count'],
skinunlock: ['Skin Unlock', 'Unlocks Orc, Elf, Undead without sharing'],
walkunlock: ['Walk Unlock', 'Move even with chat or menus open'],
scout: ['Scout', 'Second account marks players on minimap'],
Gold_Bot: ['Gold Bot', 'Bots come toward you, kill them for gold'],
antiafk: ['Anti-AFK', 'Prevents server kick for inactivity'],
macros: ['Macros', 'PvP macros list'],
trapMacro: ['Place Trap', 'Place trap on bind key'],
ballistaMacro: ['Place Ballista', 'Place ballista on bind key'],
settings: ['Settings', ''],
theme: ['Theme', ''],
language: ['Language', ''],
resetCfg: ['Reset Config', ''],
escClear: ['Esc - clear bind', ''],
},
ru: {
autoheal: ['Авто-хил', 'Хил при HP < 60% если есть еда'],
aimbow: ['Прицел лука', 'Прицеливается к ближайшему врагу'],
triggerbot: ['Триггер бот', 'Авто-атака при попадании в хитбокс врага'],
autoreconnect: ['Авто-реконнект', 'Мгновенный респавн при смерти'],
killmessage: ['Сообщение о киле', 'Сообщение в чат при убийстве игрока'],
zoom: ['Зум', 'Зум хак (CTRL + колесо мыши)'],
esp: ['ESP', 'Рисует хитбоксы игроков'],
tracers: ['Трейсеры', 'Линии от тебя до врагов'],
hud: ['HUD', 'Показывает FPS, пинг, кол-во игроков'],
skinunlock: ['Скины', 'Открывает орка, эльфа, нежить без шера'],
walkunlock: ['Движение', 'Бег при открытом чате или меню'],
scout: ['Скаут', 'Второй акк помечает игроков на минимапе'],
Gold_Bot: ['Голд бот', 'Боты идут к тебе, убивай за золото'],
antiafk: ['Анти-АФК', 'Защита от кика за неактивность'],
macros: ['Макросы', 'Список макросов для пвп'],
trapMacro: ['Капкан', 'Ставит капкан по кнопке'],
ballistaMacro: ['Баллиста', 'Ставит баллисту по кнопке'],
settings: ['Настройки', ''],
theme: ['Тема', ''],
language: ['Язык', ''],
resetCfg: ['Сбросить конфиг', ''],
escClear: ['Esc - очистить бинд', ''],
}
};
function t(key, idx) {
return (I18N[currentLang] || I18N.en)[key]?.[idx || 0] || key;
}
const _defaults = {
zoom: {
enabled: false
},
autoheal: {
enabled: false
},
skinunlock: {
enabled: false
},
esp: {
enabled: false
},
tracers: {
enabled: false
},
scout: {
enabled: false
},
walkunlock: {
enabled: false
},
killmessage: {
enabled: false
},
aimbow: {
enabled: false
},
triggerbot: {
enabled: false
},
Gold_Bot: {
enabled: false
},
hud: {
enabled: false
},
autoreconnect: {
enabled: false
},
antiafk: {
enabled: false
},
};
const _GB_MAX = parseInt('F', 16);
let dgCount = _GB_MAX;
function loadState() {
try {
const sv = JSON.parse(localStorage.getItem(CFG_KEY) || '{}');
const st = {};
for (const k in _defaults) st[k] = {
enabled: sv[k] !== undefined ? !!sv[k] : _defaults[k].enabled
};
if (sv._mk) menuKey = sv._mk;
if (sv._th) currentTheme = sv._th;
if (sv._ln) currentLang = sv._ln;
if (sv._tb) trapBind = sv._tb;
if (sv._bb) ballistaBind = sv._bb;
if (sv._dgc !== undefined) dgCount = Math.min(Math.max(1, sv._dgc), _GB_MAX);
return st;
} catch {
return JSON.parse(JSON.stringify(_defaults));
}
}
function saveState() {
const o = {};
for (const k in state) o[k] = state[k].enabled;
o._mk = menuKey;
o._th = currentTheme;
o._ln = currentLang;
o._tb = trapBind;
o._bb = ballistaBind;
o._dgc = dgCount;
localStorage.setItem(CFG_KEY, JSON.stringify(o));
}
const state = loadState();
if (state.skinunlock.enabled)['elf', 'orc', 'undead'].forEach(h => {
unsafeWindow.localStorage[h] = true;
});
let gameWS = null,
ahEnabled = state.autoheal.enabled,
ahHealing = false,
ahProto = false,
ahPrevTool = 1,
ahFrames = 0;
const ZOOM_BASE = 1.06;
let zoomFactor = ZOOM_BASE;
const wuKeys = {
attack: false,
up: false,
right: false,
down: false,
left: false
};
let wuLast = null;
let scoutGhost = null,
scoutGhostId = null,
scoutRespawnT = null;
const scoutMarks = [],
MAP_SIZE = 8160;
const dgBots = [];
let dgRunning = false;
let kmKills = 0;
const kmQueue = [];
const BOW_ID = 4;
let hudPing = 0,
hudFps = 0,
hudLast = performance.now(),
hudF = 0;
let macroMove = 0,
trapBusy = false,
ballistaBusy = false;
const TRAP_TOOL = 9,
BALLISTA_TOOL = 23;
let arFired = false;
let _lastScene = null;
let abArrowSpeed = null;
const abArrowHist = {};
const abSpeedSamples = [];
const abShotLog = [];
let abCorrection = {
x: 0,
y: 0
};
let abSmoothAngle = null;
const AB_SMOOTH = 0.55;
let abCalibSent = false;
let abCalibFrame = 0;
const TB_AXE_ID = 1;
const TB_AXE_TIP = 57;
const TB_SWING_ARC = 0.75 * Math.PI;
const TB_BUFFER = 10;
const _nativeSend = unsafeWindow.WebSocket.prototype.send;
unsafeWindow.WebSocket.prototype.send = function(data) {
if (typeof data === 'string' && data.startsWith('42[1,') && !gameWS) gameWS = this;
return _nativeSend.call(this, data);
};
function rawSend(s) {
if (gameWS && gameWS.readyState === 1) _nativeSend.call(gameWS, s);
}
const _omDesc = Object.getOwnPropertyDescriptor(unsafeWindow.WebSocket.prototype, 'onmessage');
Object.defineProperty(unsafeWindow.WebSocket.prototype, 'onmessage', {
get() {
return this._tmc_om || null;
},
set(fn) {
this._tmc_om = fn;
_omDesc.set.call(this, function(ev) {
const _isMain = (this === gameWS);
if (typeof ev.data === 'string' && ev.data.startsWith('42')) {
try {
const p = JSON.parse(ev.data.slice(2));
const id = p[0],
pl = p[1];
if (_isMain && state.killmessage.enabled) {
const c = unsafeWindow.CLIENT;
if (id === 11) {
kmQueue.push(c?.playerNames?.[pl] || ('Player#' + pl));
}
if (id === 6 && Array.isArray(pl)) {
for (let i = 0; i < pl.length; i += 2) {
if (pl[i] === 0 && pl[i + 1] > kmKills) {
kmKills = pl[i + 1];
const name = kmQueue.shift();
if (name) c?.socket?.emit(10, name + ' killed by ' + c?.player?.name);
}
}
}
if (id === 9) {
kmKills = 0;
kmQueue.length = 0;
}
}
if (_isMain && id === 9) {
if (state.autoreconnect.enabled && !arFired) {
arFired = true;
_arNewReconnect();
}
if (dgRunning) {
dgStop();
state.Gold_Bot.enabled = false;
const tog = document.querySelector('[data-key="Gold_Bot"]');
if (tog) tog.classList.remove('on');
saveState();
}
if (scoutGhost) {
clearTimeout(scoutRespawnT);
scoutGhost.disconnect();
scoutGhost = null;
scoutGhostId = null;
}
}
if (_isMain && id === 3) {
arFired = false;
}
} catch {}
}
if (fn) fn.call(this, ev);
});
},
configurable: true
});
Object.defineProperty(unsafeWindow, 'Vue', {
configurable: true,
set(V) {
Object.defineProperty(unsafeWindow, 'Vue', {
value: V,
writable: true,
configurable: true
});
const _O = V;
function PV(opts) {
const i = new _O(opts);
if (opts?.el === '#ui') unsafeWindow.UI = i;
return i;
}
PV.prototype = _O.prototype;
['config', 'use', 'component', 'set', 'delete', 'nextTick', 'extend', 'mixin', 'compile', 'observable', 'version'].forEach(k => {
if (_O[k] !== undefined) PV[k] = typeof _O[k] === 'function' ? (...a) => _O[k].apply(_O, a) : _O[k];
});
Object.defineProperty(unsafeWindow, 'Vue', {
value: PV,
writable: true,
configurable: true
});
}
});
const _origBind = unsafeWindow.Function.prototype.bind;
unsafeWindow.Function.prototype.bind = function(thisArg, ...args) {
if (!unsafeWindow.CLIENT && thisArg !== null && thisArg !== undefined && typeof thisArg === 'object' &&
thisArg.camera !== undefined && thisArg.mainCanvas !== undefined &&
thisArg.mainCtx !== undefined && thisArg.screenWidth !== undefined) {
unsafeWindow.CLIENT = thisArg;
unsafeWindow.Function.prototype.bind = _origBind;
_initFeatures(thisArg);
}
return _origBind.apply(this, [thisArg, ...args]);
};
function _initFeatures(c) {
_initAutoHeal(c);
_initRender(c);
_initWalkUnlock(c);
if (c.socket?.io) c.socket.io.on('pong', ms => {
hudPing = ms;
});
_startAntiAFK();
}
function _initAutoHeal(c) {
let _p = null;
Object.defineProperty(c, 'player', {
get() {
return _p;
},
set(val) {
_p = val;
if (val && !ahProto) {
ahProto = true;
_hookSetHP(Object.getPrototypeOf(val));
}
},
configurable: true
});
}
function _hookSetHP(proto) {
const _orig = proto.setHP;
proto.setHP = function(hp) {
const res = _orig.call(this, hp);
const c = unsafeWindow.CLIENT;
if (!c || !c.player || this !== c.player) return res;
if (ahEnabled && !ahHealing && hp > 0 && hp < this.maxHP * 0.6 && c.player.food >= 10) {
ahPrevTool = c.player.tool ? c.player.tool.id : 1;
ahHealing = true;
ahFrames = 0;
_doHeal();
}
return res;
};
}
function _doHeal() {
rawSend('42[3,2]');
requestAnimationFrame(() => {
rawSend('42[2,16]');
requestAnimationFrame(() => {
rawSend('42[2,0]');
ahFrames = 0;
});
});
}
function _initRender(c) {
const _orig = c.render.bind(c);
c.render = function() {
_orig();
const ctx = c.mainCtx,
cam = c.camera,
me = c.player,
pl = c.players;
if (!me || !pl) return;
if (state.esp.enabled) {
ctx.save();
ctx.globalAlpha = 1;
ctx.shadowColor = 'transparent';
ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;
for (const id in pl) {
if (!pl.hasOwnProperty(id)) continue;
const p = pl[id];
if (!p || !p.isVisible || p.id === me.id) continue;
const cx = cam.calculateCameraX(p.x),
cy = cam.calculateCameraY(p.y);
const r = p.radius,
rs = p.skin ? p.skin.radiusShift : 0;
ctx.beginPath();
ctx.arc(cx, cy, r + rs, 0, 6.2832);
ctx.strokeStyle = 'rgba(255,200,0,1)';
ctx.lineWidth = 1;
ctx.stroke();
ctx.beginPath();
ctx.arc(cx, cy, r, 0, 6.2832);
ctx.strokeStyle = 'rgba(255,50,50,0.9)';
ctx.lineWidth = 1.5;
ctx.stroke();
}
ctx.beginPath();
ctx.restore();
}
if (state.tracers.enabled) {
const mx = cam.calculateCameraX(me.x),
my = cam.calculateCameraY(me.y);
const sorted = [];
for (const id in pl) {
if (!pl.hasOwnProperty(id)) continue;
const p = pl[id];
if (!p || p.id === me.id) continue;
const dx = p.x - me.x,
dy = p.y - me.y;
sorted.push({
p,
d: dx * dx + dy * dy
});
}
sorted.sort((a, b) => a.d - b.d);
ctx.save();
sorted.forEach(({
p,
d
}, i) => {
const px = cam.calculateCameraX(p.x),
py = cam.calculateCameraY(p.y);
const ratio = Math.min(d / (3000 * 3000), 1),
rv = Math.round(255 * ratio),
gv = Math.round(255 * (1 - ratio));
ctx.beginPath();
ctx.moveTo(mx, my);
ctx.lineTo(px, py);
ctx.strokeStyle = `rgba(${rv},${gv},0,0.75)`;
ctx.lineWidth = i === 0 ? 2.5 / cam.scale : 1.5 / cam.scale;
ctx.stroke();
ctx.fillStyle = `rgba(${rv},${gv},0,0.9)`;
ctx.beginPath();
ctx.arc(px, py, 4 / cam.scale, 0, Math.PI * 2);
ctx.fill();
});
ctx.beginPath();
ctx.restore();
}
};
}
function _initWalkUnlock(c) {
const s = c.socket,
_oe = s.emit.bind(s);
s.emit = function(op, val) {
if (op === 2 && state.walkunlock.enabled) {
const oc = _wuCode();
if (val === 0 && oc !== 0) {
wuLast = oc;
return _oe(2, oc);
}
if (val === oc) {
wuLast = val;
return _oe.apply(this, arguments);
}
}
return _oe.apply(this, arguments);
};
}
function _wuCode() {
return parseInt('' + +wuKeys.attack + +wuKeys.up + +wuKeys.right + +wuKeys.down + +wuKeys.left, 2);
}
function _wuSend() {
const c = unsafeWindow.CLIENT;
if (!c || !c.socket || !state.walkunlock.enabled) return;
const code = _wuCode();
if (code === wuLast) return;
wuLast = code;
c.socket.emit(2, code);
}
function _startAntiAFK() {
setInterval(() => {
if (!state.antiafk.enabled) return;
const C = unsafeWindow.CLIENT;
if (!C?.socket || !C.player) return;
C.socket.emit(1, C.angle || 0);
C.socket.emit(2, 0);
}, 15000);
}
unsafeWindow.addEventListener('keydown', e => {
switch (e.keyCode) {
case 38:
case 87:
wuKeys.up = true;
macroMove |= 8;
break;
case 39:
case 68:
wuKeys.right = true;
macroMove |= 4;
break;
case 40:
case 83:
wuKeys.down = true;
macroMove |= 2;
break;
case 37:
case 65:
wuKeys.left = true;
macroMove |= 1;
break;
case 32:
wuKeys.attack = true;
break;
case 69:
wuKeys.attack = !wuKeys.attack;
break;
}
_wuSend();
if (trapBind && e.key === trapBind && !trapBusy) _doTrap();
if (ballistaBind && e.key === ballistaBind && !ballistaBusy) _doBallista();
}, true);
unsafeWindow.addEventListener('keyup', e => {
switch (e.keyCode) {
case 38:
case 87:
wuKeys.up = false;
macroMove &= ~8;
break;
case 39:
case 68:
wuKeys.right = false;
macroMove &= ~4;
break;
case 40:
case 83:
wuKeys.down = false;
macroMove &= ~2;
break;
case 37:
case 65:
wuKeys.left = false;
macroMove &= ~1;
break;
case 32:
wuKeys.attack = false;
break;
}
_wuSend();
}, true);
unsafeWindow.addEventListener('blur', () => {
wuKeys.attack = wuKeys.up = wuKeys.right = wuKeys.down = wuKeys.left = false;
wuLast = null;
});
function _doTrap() {
const C = unsafeWindow.CLIENT;
if (!C?.socket?.emit || !C.player) return;
const prev = C.player.tool.id;
if (prev === TRAP_TOOL) return;
trapBusy = true;
const s = C.socket;
s.emit(3, TRAP_TOOL);
requestAnimationFrame(() => {
s.emit(2, macroMove | 0x10);
requestAnimationFrame(() => {
s.emit(2, macroMove);
s.emit(3, prev);
trapBusy = false;
});
});
}
function _doBallista() {
const C = unsafeWindow.CLIENT;
if (!C?.socket?.emit || !C.player) return;
const prev = C.player.tool.id;
if (prev === BALLISTA_TOOL) return;
ballistaBusy = true;
const s = C.socket;
s.emit(3, BALLISTA_TOOL);
requestAnimationFrame(() => {
s.emit(2, macroMove | 0x10);
requestAnimationFrame(() => {
s.emit(2, macroMove);
s.emit(3, prev);
ballistaBusy = false;
});
});
}
function _arNewReconnect() {
const tryResp = () => {
const UI = unsafeWindow.UI;
if (!UI) {
requestAnimationFrame(tryResp);
return;
}
if (typeof UI.closeStats === 'function') UI.closeStats();
requestAnimationFrame(() => {
UI.$emit('login');
});
};
requestAnimationFrame(tryResp);
}
function abMeasureSpeed(C) {
const objs = C.temporaryObjects;
if (!objs) return;
const now = performance.now();
for (const id in objs) {
if (!objs.hasOwnProperty(id)) continue;
const a = objs[id];
if (!a || a.image !== 'arrow') continue;
if (!abArrowHist[id]) {
abArrowHist[id] = {
x: a.x,
y: a.y,
t: now
};
continue;
}
const prev = abArrowHist[id],
dt = now - prev.t;
if (dt > 8 && dt < 80) {
const d = Math.sqrt((a.x - prev.x) ** 2 + (a.y - prev.y) ** 2);
if (d > 2) {
abSpeedSamples.push(d / dt);
if (abSpeedSamples.length > 40) abSpeedSamples.shift();
const s = abSpeedSamples.slice().sort((a, b) => a - b);
abArrowSpeed = s[Math.floor(s.length / 2)];
}
}
abArrowHist[id] = {
x: a.x,
y: a.y,
t: now
};
}
for (const id in abArrowHist)
if (!objs[id]) delete abArrowHist[id];
}
function abRegress(buf, maxPts) {
if (!buf || buf.length < 2) return null;
const n = Math.min(buf.length, maxPts || 10);
const pts = buf.slice(-n);
const t0 = pts[pts.length - 1].t;
let st = 0,
sx = 0,
sy = 0,
st2 = 0,
stx = 0,
sty = 0;
for (const p of pts) {
const t = p.t - t0;
st += t;
sx += p.x;
sy += p.y;
st2 += t * t;
stx += t * p.x;
sty += t * p.y;
}
const det = n * st2 - st * st;
if (Math.abs(det) < 1e-9) return null;
const vx = (n * stx - st * sx) / det;
const vy = (n * sty - st * sy) / det;
const x0 = (sx - vx * st) / n;
const y0 = (sy - vy * st) / n;
const mx = sx / n,
my = sy / n;
let ssTot = 0,
ssRes = 0;
for (const p of pts) {
const t = p.t - t0;
ssTot += (p.x - mx) ** 2 + (p.y - my) ** 2;
ssRes += (p.x - (x0 + vx * t)) ** 2 + (p.y - (y0 + vy * t)) ** 2;
}
return {
x: pts[pts.length - 1].x,
y: pts[pts.length - 1].y,
vx,
vy,
confidence: ssTot > 0.001 ? Math.max(0, 1 - ssRes / ssTot) : 0
};
}
function abGetAcceleration(buf) {
if (!buf || buf.length < 6) return {
ax: 0,
ay: 0
};
const half = Math.floor(buf.length / 2);
const r1 = abRegress(buf.slice(0, half), half);
const r2 = abRegress(buf.slice(half), half);
if (!r1 || !r2) return {
ax: 0,
ay: 0
};
const dt = (buf[buf.length - 1].t - buf[0].t) / 2;
if (dt < 10) return {
ax: 0,
ay: 0
};
return {
ax: (r2.vx - r1.vx) / dt,
ay: (r2.vy - r1.vy) / dt
};
}
function abIntercept(dx, dy, vx, vy, spd) {
const a = spd * spd - vx * vx - vy * vy;
const b = -2 * (dx * vx + dy * vy);
const c = -(dx * dx + dy * dy);
const D = b * b - 4 * a * c;
if (D < 0) return null;
const sq = Math.sqrt(D);
const t1 = (-b - sq) / (2 * a),
t2 = (-b + sq) / (2 * a);
if (t1 > 0 && t2 > 0) return Math.min(t1, t2);
return Math.max(t1, t2) > 0 ? Math.max(t1, t2) : null;
}
function abLogShot(aimX, aimY, target, tFlight) {
abShotLog.push({
aimX,
aimY,
target,
deadline: performance.now() + tFlight,
done: false
});
if (abShotLog.length > 20) abShotLog.shift();
}
function abUpdateCorrection(C) {
const now = performance.now();
let cx = 0,
cy = 0,
count = 0;
for (const s of abShotLog) {
if (s.done || now < s.deadline) continue;
s.done = true;
const tgt = C.players[s.target?.id];
if (!tgt) continue;
cx += s.aimX - tgt.x;
cy += s.aimY - tgt.y;
count++;
}
if (count > 0) {
const alpha = 0.3;
abCorrection.x = abCorrection.x * (1 - alpha) + (cx / count) * alpha;
abCorrection.y = abCorrection.y * (1 - alpha) + (cy / count) * alpha;
const maxC = 80;
abCorrection.x = Math.max(-maxC, Math.min(maxC, abCorrection.x));
abCorrection.y = Math.max(-maxC, Math.min(maxC, abCorrection.y));
}
}
function abFindNearest(C) {
const me = C.player;
let cl = null,
md = Infinity;
for (const id in C.players) {
if (!C.players.hasOwnProperty(id)) continue;
const p = C.players[id];
if (!p || p.id === me.id) continue;
const d = (p.x - me.x) ** 2 + (p.y - me.y) ** 2;
if (d < md) {
md = d;
cl = p;
}
}
return cl;
}
function abCalcAngle(fx, fy, tx, ty, cam) {
return Math.round(100 * (
Math.atan2(cam.calculateCameraY(ty) - cam.calculateCameraY(fy),
cam.calculateCameraX(tx) - cam.calculateCameraX(fx)) +
Math.PI / 2
));
}
function tbNormalizeAngle(a) {
while (a > Math.PI) a -= 2 * Math.PI;
while (a < -Math.PI) a += 2 * Math.PI;
return a;
}
function tbGetVelocity(buf) {
if (!buf || buf.length < 2) return {
vx: 0,
vy: 0
};
const b0 = buf[buf.length - 2],
b1 = buf[buf.length - 1];
const dt = b1.t - b0.t;
if (dt <= 0) return {
vx: 0,
vy: 0
};
return {
vx: (b1.x - b0.x) / dt,
vy: (b1.y - b0.y) / dt
};
}
function tbARC(cx, cy, R, arcStart, arcEnd, tx, ty) {
const dx = tx - cx,
dy = ty - cy;
if (Math.sqrt(dx * dx + dy * dy) < 1e-6) return R;
const angleToTarget = Math.atan2(dy, dx);
const span = tbNormalizeAngle(arcStart - arcEnd);
const delta = tbNormalizeAngle(angleToTarget - arcEnd);
if (delta >= -1e-9 && delta <= span + 1e-9) {
const nx = cx + Math.cos(angleToTarget) * R;
const ny = cy + Math.sin(angleToTarget) * R;
return Math.sqrt((tx - nx) ** 2 + (ty - ny) ** 2);
}
const ex1 = cx + Math.cos(arcStart) * R,
ey1 = cy + Math.sin(arcStart) * R;
const ex2 = cx + Math.cos(arcEnd) * R,
ey2 = cy + Math.sin(arcEnd) * R;
return Math.min(
Math.sqrt((tx - ex1) ** 2 + (ty - ey1) ** 2),
Math.sqrt((tx - ex2) ** 2 + (ty - ey2) ** 2)
);
}
function tbCanHit(me, target) {
const rs = target.skin ? (target.skin.radiusShift || 0) : 0;
const hitRadius = target.radius + rs + TB_BUFFER;
const half = hudPing / 2;
const {
vx: tvx,
vy: tvy
} = tbGetVelocity(target.positionBuffer);
const {
vx: mvx,
vy: mvy
} = tbGetVelocity(me.positionBuffer);
const tx = target.x + tvx * half,
ty = target.y + tvy * half;
const mx = me.x + mvx * half,
my = me.y + mvy * half;
const dx = tx - mx,
dy = ty - my;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist > TB_AXE_TIP + hitRadius) return false;
const worldAngle = me.angle - Math.PI / 2;
const arcStart = worldAngle;
const arcEnd = worldAngle - TB_SWING_ARC;
return tbARC(mx, my, TB_AXE_TIP, arcStart, arcEnd, tx, ty) <= hitRadius;
}
unsafeWindow.addEventListener('wheel', e => {
if (!state.zoom.enabled || !e.ctrlKey) return;
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
zoomFactor = parseFloat(
(e.deltaY < 0 ? Math.min(3, zoomFactor + 0.1) : Math.max(0.1, zoomFactor - 0.1)).toFixed(2)
);
_applyZoom();
}, {
passive: false,
capture: true
});
function _applyZoom() {
const c = unsafeWindow.CLIENT;
if (!c) return;
const w = c.screenWidth,
h = c.screenHeight,
base = Math.round(100 * Math.max(w / 1440, h / 900)) / 100;
const ns = parseFloat((base * zoomFactor).toFixed(4)),
pr = unsafeWindow.PIXEL_RATIO;
c.camera.scale = ns;
c.camera.width = parseInt(w / ns);
c.camera.height = parseInt(h / ns);
c.camera.widthHalf = c.camera.width / 2;
c.camera.heightHalf = c.camera.height / 2;
c.camera.isChanged = true;
c.mainCtx.setTransform(pr, 0, 0, pr, 0, 0);
c.mainCtx.scale(ns, ns);
c.backgroundCtx.setTransform(pr, 0, 0, pr, 0, 0);
c.backgroundCtx.scale(ns, ns);
}
const _origRAF = unsafeWindow.requestAnimationFrame;
unsafeWindow.requestAnimationFrame = function(cb) {
return _origRAF(function(ts) {
const C = unsafeWindow.CLIENT;
const UI = unsafeWindow.UI;
const curScene = UI?.scene;
if (curScene !== _lastScene) {
_lastScene = curScene;
if (curScene !== 'game') {
if (dgRunning) {
dgStop();
state.Gold_Bot.enabled = false;
const tog = document.querySelector('[data-key="Gold_Bot"]');
if (tog) tog.classList.remove('on');
saveState();
}
if (scoutGhost) {
clearTimeout(scoutRespawnT);
scoutGhost.disconnect();
scoutGhost = null;
scoutGhostId = null;
}
}
}
if (C) {
abMeasureSpeed(C);
abUpdateCorrection(C);
if (!abCalibSent && C.player?.tool?.id === BOW_ID && C.socket) {
abCalibFrame++;
if (abCalibFrame === 3) {
abCalibSent = true;
C.socket.emit(2, 16);
}
if (abCalibFrame === 5) {
C.socket.emit(2, 0);
}
}
if (ahHealing && C.player) {
if (C.player.hp >= C.player.maxHP || C.player.food < 10) {
ahHealing = false;
ahFrames = 0;
rawSend('42[3,' + ahPrevTool + ']');
} else {
ahFrames++;
if (ahFrames >= 3) _doHeal();
}
}
if (state.aimbow.enabled && C.player?.tool?.id === BOW_ID && C.socket) {
const target = abFindNearest(C);
const spd = abArrowSpeed;
if (target && spd) {
const me = C.player;
const half = hudPing / 2;
const ki = abRegress(target.positionBuffer, 10);
if (ki) {
const {
ax,
ay
} = abGetAcceleration(target.positionBuffer);
const meki = abRegress(me.positionBuffer, 6);
const svx = meki ? meki.vx : 0,
svy = meki ? meki.vy : 0;
const tx0 = ki.x + ki.vx * half + 0.5 * ax * half * half;
const ty0 = ki.y + ki.vy * half + 0.5 * ay * half * half;
const mx0 = me.x + svx * half;
const my0 = me.y + svy * half;
const tFly = abIntercept(tx0 - mx0, ty0 - my0, ki.vx, ki.vy, spd);
if (tFly !== null) {
const conf = ki.confidence;
const blend = Math.pow(conf, 1.5);
const tFull = tFly + half;
let px = tx0 + ki.vx * tFull + 0.5 * ax * tFull * tFull;
let py = ty0 + ki.vy * tFull + 0.5 * ay * tFull * tFull;
px = px * blend + tx0 * (1 - blend);
py = py * blend + ty0 * (1 - blend);
if (conf > 0.75) {
px -= abCorrection.x * conf;
py -= abCorrection.y * conf;
}
abLogShot(px, py, target, tFull + half);
const rawAngle = abCalcAngle(mx0, my0, px, py, C.camera);
if (abSmoothAngle === null) abSmoothAngle = rawAngle;
const da = rawAngle - abSmoothAngle;
const daNorm = da - Math.round(da / 36000) * 36000;
abSmoothAngle += daNorm * (1 - AB_SMOOTH);
const finalAngle = Math.round(abSmoothAngle);
if (finalAngle !== C.prevAngle) {
C.socket.emit(1, finalAngle);
C.angle = finalAngle;
C.prevAngle = finalAngle;
}
}
}
}
}
if (state.triggerbot.enabled && C.player?.tool?.id === TB_AXE_ID && C.socket) {
const me = C.player;
const moveCode = _wuCode() & 0xF;
let hit = false;
for (const id in C.players) {
if (!C.players.hasOwnProperty(id)) continue;
const p = C.players[id];
if (!p || p.id === me.id || !p.isVisible) continue;
if (tbCanHit(me, p)) {
hit = true;
break;
}
}
C.socket.emit(2, hit ? moveCode | 0x10 : moveCode);
}
}
cb(ts);
});
};
function scoutStart() {
if (scoutGhost) return;
const UI = unsafeWindow.UI;
if (!UI || UI.scene !== 'game') return;
if (!unsafeWindow.CLIENT) return;
const sv = document.getElementById('serverList')?.value;
if (!sv) return;
scoutGhost = unsafeWindow.io.connect(sv, {
forceNew: true
});
scoutGhost.on('connect', () => _scoutSpawn());
scoutGhost.on(3, d => {
scoutGhostId = d[0];
clearTimeout(scoutRespawnT);
scoutRespawnT = setTimeout(_scoutSpawn, 700);
});
scoutGhost.on(4, d => {
const UI = unsafeWindow.UI,
C = unsafeWindow.CLIENT;
if (!UI?.minimap) return;
const mn = C?.player?.name;
for (let i = 0; i < d.length; i += 11) {
const r = d.slice(i, i + 11);
if (r[0] === scoutGhostId) continue;
if (mn && C?.playerNames?.[r[0]] === mn) continue;
const key = 'scout_' + r[0];
UI.minimap.setMarker(key, MAP_SIZE, MAP_SIZE, r[2], r[3], '#ffff00');
if (!scoutMarks.includes(key)) scoutMarks.push(key);
}
});
scoutGhost.on(9, () => {
clearTimeout(scoutRespawnT);
_scoutSpawn();
});
}
function scoutStop() {
clearTimeout(scoutRespawnT);
if (scoutGhost) {
scoutGhost.disconnect();
scoutGhost = null;
scoutGhostId = null;
}
}
function _scoutSpawn() {
if (scoutGhost) scoutGhost.emit(0, 'Drik_Scout', 1);
}
function scoutClear() {
const UI = unsafeWindow.UI;
if (!UI) return;
scoutMarks.forEach(k => UI.minimap.removeMarker(k));
scoutMarks.length = 0;
}
function dgStart() {
const UI = unsafeWindow.UI;
if (!UI || UI.scene !== 'game') return;
dgRunning = true;
_dgAdjustBots(dgCount);
}
function dgStop() {
dgRunning = false;
const UI = unsafeWindow.UI;
dgBots.forEach(b => {
if (b.moveInterval) clearInterval(b.moveInterval);
if (b.socket) b.socket.disconnect();
if (UI?.minimap && b.id) UI.minimap.removeMarker('gp_' + b.id);
});
dgBots.length = 0;
}
function _dgAdjustBots(target) {
while (dgBots.length > target) {
const bot = dgBots.pop();
if (bot.moveInterval) clearInterval(bot.moveInterval);
if (bot.socket) bot.socket.disconnect();
const UI = unsafeWindow.UI;
if (UI?.minimap && bot.id) UI.minimap.removeMarker('gp_' + bot.id);
}
if (dgRunning) {
while (dgBots.length < target) _dgCreateBot();
}
}
function _dgCreateBot() {
const sv = document.getElementById('serverList')?.value;
if (!sv) return;
const bot = {
socket: null,
id: null,
x: 0,
y: 0,
moveInterval: null
};
dgBots.push(bot);
bot.socket = unsafeWindow.io.connect(sv, {
forceNew: true
});
bot.socket.on('connect', () => bot.socket.emit(0, 'Drik_Gold', 1));
bot.socket.on(3, d => {
bot.id = d[0];
_dgMove(bot);
});
bot.socket.on(4, d => {
for (let i = 0; i < d.length; i += 11) {
const r = d.slice(i, i + 11);
if (r[0] === bot.id) {
bot.x = r[2];
bot.y = r[3];
_dgMark(bot);
}
}
});
bot.socket.on(9, () => {
clearInterval(bot.moveInterval);
if (dgRunning) setTimeout(() => bot.socket.emit(0, 'Drik_Gold', 1), 500);
});
}
function _dgMove(bot) {
clearInterval(bot.moveInterval);
bot.moveInterval = setInterval(() => {
const c = unsafeWindow.CLIENT;
if (!c?.player) return;
const dx = c.player.x - bot.x,
dy = c.player.y - bot.y,
d = Math.sqrt(dx * dx + dy * dy);
if (d < 80) {
bot.socket.emit(2, 0);
return;
}
const kc = parseInt('0' + (dy < -40 ? '1' : '0') + (dx > 40 ? '1' : '0') + (dy > 40 ? '1' : '0') + (dx < -40 ? '1' : '0'), 2);
bot.socket.emit(1, Math.round(100 * (Math.atan2(dy, dx) + Math.PI / 2)));
bot.socket.emit(2, kc);
}, 50);
}
function _dgMark(bot) {
const UI = unsafeWindow.UI;
if (UI?.minimap) UI.minimap.setMarker('gp_' + bot.id, MAP_SIZE, MAP_SIZE, bot.x, bot.y, '#ffd700');
}
(function _hudLoop(now) {
hudF++;
const dt = now - hudLast;
if (dt >= 1000) {
hudFps = Math.round(hudF * 1000 / dt);
hudF = 0;
hudLast = now;
}
if (state.hud.enabled) {
const el = document.getElementById('pfhud');
if (el) {
const c = unsafeWindow.CLIENT;
const pl = c?.playerNames ? Object.keys(c.playerNames).length : '-';
el.innerHTML = 'FPS: ' + (hudFps || '-') + '<br>PING: ' + (hudPing ? hudPing + 'ms' : '-') + '<br>PLAYERS: ' + pl;
}
}
_origRAF(_hudLoop);
})(performance.now());
(function() {
let _u;
try {
_u = decodeURIComponent(_$raw).toLowerCase();
} catch {
_u = (_$raw || '').toLowerCase();
}
const _valid = _u.length > 0 &&
_u.startsWith('https://update.greasyfork.org/scripts/') &&
_u.endsWith('.meta.js') &&
/takemineclient(\[\d+(\.\d+)?\])?/.test(_u);
if (!_valid) {
alert('Invalid source. Download TakeMineClient from official page');
throw new Error('TMC');
}
})();
function onToggle(key, on) {
switch (key) {
case 'skinunlock':
if (on)['elf', 'orc', 'undead'].forEach(h => {
unsafeWindow.localStorage[h] = true;
});
break;
case 'autoheal':
ahEnabled = on;
if (!on && ahHealing) {
ahHealing = false;
ahFrames = 0;
rawSend('42[3,' + ahPrevTool + ']');
}
break;
case 'Gold_Bot':
if (on) {
dgStart();
if (!dgRunning) {
state.Gold_Bot.enabled = false;
const tog = document.querySelector('[data-key="Gold_Bot"]');
if (tog) tog.classList.remove('on');
}
} else {
dgStop();
}
break;
case 'hud': {
const el = document.getElementById('pfhud');
if (el) el.style.display = on ? '' : 'none';
break;
}
}
saveState();
}
function applyTheme(theme) {
currentTheme = theme;
const menu = document.getElementById('tm-menu');
if (menu) {
menu.classList.remove('theme-dark', 'theme-white');
menu.classList.add('theme-' + theme);
}
}
GM_addStyle(`@import url("https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Rajdhani:wght@400;500;600;700&display=swap");
#tm-menu* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
#tm-menu {
position: fixed;
top: 14px;
right: 14px;
z-index: 999999;
width: 320px;
background: #161b27;
border: 1px solid #252d3d;
border-radius: 12px;
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
font-family: "Rajdhani", sans-serif;
overflow: hidden;
user-select: none;
}
#tm-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 18px;
background: #1a2030;
border-bottom: 1px solid #252d3d;
cursor: move;
}
#tm-title {
font-size: 16px;
font-weight: 700;
letter-spacing: 3px;
text-transform: uppercase;
color: #e2e8f0;
font-family: "Space Mono", monospace;
}
#tm-title span {
color: #4ade80;
}
#tm-gear {
background: none;
border: none;
cursor: pointer;
color: #4a5568;
padding: 0;
line-height: 1;
transition: color 0.2s;
font-size: 16px;
}
#tm-gear:hover {
color: #4ade80;
}
#tm-tabs {
display: flex;
border-bottom: 1px solid #252d3d;
background: #161b27;
}
.tm-tab {
flex: 1;
padding: 11px 0;
border: none;
background: transparent;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
font-family: "Rajdhani", sans-serif;
font-size: 11px;
font-weight: 600;
letter-spacing: 1.5px;
text-transform: uppercase;
color: #4a5568;
transition: color 0.2s;
border-bottom: 2px solid transparent;
position: relative;
top: 1px;
}
.tm-tab svg {
width: 13px;
height: 13px;
flex-shrink: 0;
}
.tm-tab.active {
color: #4ade80;
border-bottom: 2px solid #4ade80;
}
.tm-tab:hover:not(.active) {
color: #94a3b8;
}
#tm-body {
padding: 6px 0;
max-height: 400px;
overflow-y: auto;
}
#tm-body::-webkit-scrollbar {
width: 3px;
}
#tm-body::-webkit-scrollbar-track {
background: transparent;
}
#tm-body::-webkit-scrollbar-thumb {
background: #252d3d;
border-radius: 3px;
}
.tm-panel {
display: none;
}
.tm-panel.active {
display: block;
}
.tm-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
padding: 11px 18px;
gap: 14px;
transition: background 0.15s;
}
.tm-row:hover {
background: rgba(255, 255, 255, 0.025);
}
.tm-row-info {
flex: 1;
min-width: 0;
}
.tm-row-name {
font-size: 14px;
font-weight: 700;
color: #e2e8f0;
letter-spacing: 0.4px;
line-height: 1.2;
}
.tm-row-desc {
font-size: 11px;
color: #4a5568;
margin-top: 3px;
line-height: 1.45;
font-weight: 400;
font-family: "Space Mono", monospace;
}
.tm-toggle {
flex-shrink: 0;
width: 40px;
height: 22px;
background: #252d3d;
border-radius: 11px;
position: relative;
cursor: pointer;
transition: background 0.25s;
margin-top: 2px;
}
.tm-toggle.on {
background: #16a34a;
}
.tm-toggle::after {
content: "";
position: absolute;
top: 3px;
left: 3px;
width: 16px;
height: 16px;
border-radius: 50%;
background: #fff;
transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
.tm-toggle.on::after {
transform: translateX(18px);
}
.tm-divider {
height: 1px;
background: #1e2636;
margin: 0 18px;
}
#tm-footer {
padding: 9px 18px;
border-top: 1px solid #252d3d;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
}
#tm-footer-label {
font-size: 9px;
letter-spacing: 1.5px;
color: #2d3748;
text-transform: uppercase;
font-family: "Space Mono", monospace;
}
#tm-menu-key-btn {
background: #1a2030;
border: 1px solid #2d3748;
border-radius: 4px;
padding: 2px 8px;
font-size: 10px;
color: #94a3b8;
cursor: pointer;
font-family: "Space Mono", monospace;
transition: border-color 0.2s, color 0.2s;
}
#tm-menu-key-btn:hover {
border-color: #4ade80;
color: #4ade80;
}
#tm-menu-key-btn.listening {
border-color: #f59e0b;
color: #f59e0b;
animation: tm-pulse 0.8s ease infinite;
}
@keyframes tm-pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
.tm-scout-btns {
display: flex;
gap: 8px;
padding: 6px 18px 14px;
}
.tm-scout-btn {
flex: 1;
padding: 5px 0;
border-radius: 5px;
border: 1px solid #252d3d;
background: #1a2030;
color: #94a3b8;
font-family: "Space Mono", monospace;
font-size: 9px;
letter-spacing: 1px;
text-transform: uppercase;
cursor: pointer;
transition: border-color 0.2s, color 0.2s;
}
.tm-scout-btn:hover {
border-color: #4ade80;
color: #4ade80;
}
#tm-scout-stop:hover {
border-color: #ef4444;
color: #ef4444;
}
#tm-scout-clear:hover {
border-color: #f59e0b;
color: #f59e0b;
}
.tm-changelog {
padding: 10px 18px 14px;
}
.tm-cl-entry {
display: flex;
gap: 12px;
align-items: flex-start;
padding: 8px 0;
border-bottom: 1px solid #1e2636;
}
.tm-cl-entry:last-child {
border-bottom: none;
}
.tm-cl-version {
flex-shrink: 0;
font-family: "Space Mono", monospace;
font-size: 10px;
color: #4ade80;
background: rgba(74, 222, 128, 0.08);
border: 1px solid rgba(74, 222, 128, 0.2);
border-radius: 4px;
padding: 2px 7px;
margin-top: 1px;
}
.tm-cl-text {
font-size: 12px;
color: #64748b;
font-family: "Space Mono", monospace;
line-height: 1.5;
}
#pfhud {
position: fixed;
top: 12px;
left: 12px;
z-index: 99998;
background: rgba(0, 0, 0, 0.5);
color: #fff;
font-family: monospace;
font-size: 12px;
padding: 4px 9px;
border-radius: 5px;
pointer-events: none;
line-height: 1.6;
border-left: 2px solid #4af;
}
.tm-macros-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
padding: 11px 18px;
gap: 14px;
cursor: pointer;
transition: background 0.15s;
}
.tm-macros-header:hover {
background: rgba(255, 255, 255, 0.025);
}
.tm-macros-arrow {
color: #4a5568;
font-size: 12px;
margin-top: 3px;
transition: transform 0.2s;
flex-shrink: 0;
}
.tm-macros-arrow.open {
transform: rotate(180deg);
}
.tm-macros-body {
padding: 0 18px 10px;
}
.tm-macro-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 7px 0;
gap: 10px;
}
.tm-macro-name {
font-size: 13px;
font-weight: 600;
color: #e2e8f0;
}
.tm-macro-desc {
font-size: 10px;
color: #4a5568;
margin-top: 2px;
font-family: "Space Mono", monospace;
}
.tm-bind-btn {
flex-shrink: 0;
background: #1a2030;
border: 1px solid #2d3748;
border-radius: 4px;
padding: 2px 10px;
font-size: 10px;
color: #94a3b8;
cursor: pointer;
font-family: "Space Mono", monospace;
min-width: 36px;
text-align: center;
transition: border-color 0.2s, color 0.2s;
user-select: none;
}
.tm-bind-btn:hover {
border-color: #4ade80;
color: #4ade80;
}
.tm-bind-btn.listening {
border-color: #f59e0b;
color: #f59e0b;
animation: tm-pulse 0.8s ease infinite;
}
.tm-macro-hint {
font-size: 9px;
color: #2d3748;
font-family: "Space Mono", monospace;
text-align: center;
padding: 4px 0 2px;
}
#tm-settings {
display: none;
}
#tm-settings-header {
display: flex;
align-items: center;
gap: 10px;
padding: 14px 18px;
background: #1a2030;
border-bottom: 1px solid #252d3d;
}
#tm-settings-back {
background: none;
border: none;
cursor: pointer;
color: #4a5568;
font-size: 16px;
padding: 0;
line-height: 1;
transition: color 0.2s;
}
#tm-settings-back:hover {
color: #4ade80;
}
#tm-settings-title {
font-size: 13px;
font-weight: 700;
letter-spacing: 2px;
text-transform: uppercase;
color: #94a3b8;
font-family: "Space Mono", monospace;
}
.tm-setting-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 18px;
border-bottom: 1px solid #1e2636;
}
.tm-setting-label {
font-size: 13px;
font-weight: 600;
color: #e2e8f0;
}
.tm-setting-select {
background: #1a2030;
border: 1px solid #2d3748;
border-radius: 4px;
padding: 3px 8px;
font-size: 11px;
color: #94a3b8;
cursor: pointer;
font-family: "Space Mono", monospace;
outline: none;
transition: border-color 0.2s, color 0.2s;
}
.tm-setting-select:hover,
.tm-setting-select:focus {
border-color: #4ade80;
color: #4ade80;
}
.tm-setting-reset {
background: #1a2030;
border: 1px solid #2d3748;
border-radius: 4px;
padding: 4px 14px;
font-size: 10px;
color: #94a3b8;
cursor: pointer;
font-family: "Space Mono", monospace;
transition: border-color 0.2s, color 0.2s;
letter-spacing: 1px;
text-transform: uppercase;
}
.tm-setting-reset:hover {
border-color: #ef4444;
color: #ef4444;
}
.tm-gb-slider-row {
display: flex;
align-items: center;
gap: 10px;
padding: 2px 18px 10px;
}
.tm-gb-slider-label {
flex-shrink: 0;
font-size: 10px;
color: #4a5568;
font-family: "Space Mono", monospace;
min-width: 52px;
}
.tm-gb-slider {
flex: 1;
accent-color: #4ade80;
cursor: pointer;
height: 4px;
outline: none;
}
#tm-menu.theme-white {
background: #f4f7ff;
border-color: #d4dcf0;
box-shadow: 0 8px 40px rgba(80, 100, 180, 0.12),
0 0 0 1px rgba(80, 100, 180, 0.08);
}
#tm-menu.theme-white #tm-header {
background: linear-gradient(135deg, #eef2ff, #e6ebff);
border-bottom-color: #d4dcf0;
}
#tm-menu.theme-white #tm-title {
color: #1e2a4a;
}
#tm-menu.theme-white #tm-gear {
color: #94a3b8;
}
#tm-menu.theme-white #tm-gear:hover {
color: #4ade80;
}
#tm-menu.theme-white #tm-tabs {
background: #f4f7ff;
border-bottom-color: #d4dcf0;
}
#tm-menu.theme-white .tm-tab {
color: #94a3b8;
background: #f4f7ff;
}
#tm-menu.theme-white .tm-tab.active {
color: #16a34a;
border-bottom-color: #16a34a;
}
#tm-menu.theme-white .tm-tab:hover:not(.active) {
color: #4a5568;
}
#tm-menu.theme-white #tm-body {
background: #f4f7ff;
}
#tm-menu.theme-white #tm-body::-webkit-scrollbar-thumb {
background: #d4dcf0;
}
#tm-menu.theme-white .tm-row:hover {
background: rgba(80, 100, 180, 0.05);
}
#tm-menu.theme-white .tm-row-name {
color: #1e2a4a;
}
#tm-menu.theme-white .tm-row-desc {
color: #6b7fa8;
}
#tm-menu.theme-white .tm-toggle {
background: #c8d4ec;
}
#tm-menu.theme-white .tm-toggle.on {
background: #16a34a;
}
#tm-menu.theme-white .tm-toggle::after {
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
}
#tm-menu.theme-white .tm-divider {
background: #d4dcf0;
}
#tm-menu.theme-white #tm-footer {
background: #eef2ff;
border-top-color: #d4dcf0;
}
#tm-menu.theme-white #tm-footer-label {
color: #94a3b8;
}
#tm-menu.theme-white #tm-menu-key-btn {
background: #e6ebff;
border-color: #b8c4e0;
color: #4a5878;
}
#tm-menu.theme-white .tm-scout-btns {
background: #f4f7ff;
}
#tm-menu.theme-white .tm-scout-btn {
background: #e6ebff;
border-color: #b8c4e0;
color: #4a5878;
}
#tm-menu.theme-white .tm-macros-header:hover {
background: rgba(80, 100, 180, 0.05);
}
#tm-menu.theme-white .tm-macros-arrow {
color: #94a3b8;
}
#tm-menu.theme-white .tm-macro-name {
color: #1e2a4a;
}
#tm-menu.theme-white .tm-macro-desc {
color: #6b7fa8;
}
#tm-menu.theme-white .tm-bind-btn {
background: #e6ebff;
border-color: #b8c4e0;
color: #4a5878;
}
#tm-menu.theme-white .tm-macro-hint {
color: #94a3b8;
}
#tm-menu.theme-white #tm-settings-header {
background: linear-gradient(135deg, #eef2ff, #e6ebff);
border-bottom-color: #d4dcf0;
}
#tm-menu.theme-white #tm-settings-title {
color: #6b7fa8;
}
#tm-menu.theme-white .tm-setting-row {
border-bottom-color: #d4dcf0;
}
#tm-menu.theme-white .tm-setting-label {
color: #1e2a4a;
}
#tm-menu.theme-white .tm-setting-select {
background: #e6ebff;
border-color: #b8c4e0;
color: #4a5878;
}
#tm-menu.theme-white .tm-setting-reset {
background: #e6ebff;
border-color: #b8c4e0;
color: #4a5878;
}
#tm-menu.theme-white .tm-cl-entry {
border-bottom-color: #d4dcf0;
}
#tm-menu.theme-white .tm-cl-text {
color: #6b7fa8;
}
#tm-menu.theme-white .tm-changelog {
background: #f4f7ff;
}
#tm-menu.theme-white .tm-gb-slider-label {
color: #6b7fa8;
}
`);
document.addEventListener('DOMContentLoaded', () => {
const pfhud = document.createElement('div');
pfhud.id = 'pfhud';
pfhud.innerHTML = 'FPS: -<br>PING: -<br>PLAYERS: -';
pfhud.style.display = state.hud.enabled ? '' : 'none';
document.body.appendChild(pfhud);
const menu = document.createElement('div');
menu.id = 'tm-menu';
menu.innerHTML = `
<div id="tm-header">
<div id="tm-title">TakeMine<span>Client</span></div>
<button id="tm-gear" title="Settings">⚙</button>
</div>
<div id="tm-settings">
<div id="tm-settings-header">
<button id="tm-settings-back">←</button>
<div id="tm-settings-title">SETTINGS</div>
</div>
<div class="tm-setting-row">
<span class="tm-setting-label">Theme</span>
<select id="tm-theme-select" class="tm-setting-select">
<option value="dark">Dark</option>
<option value="white">White</option>
</select>
</div>
<div class="tm-setting-row">
<span class="tm-setting-label">Language</span>
<select id="tm-lang-select" class="tm-setting-select">
<option value="en">EN</option>
<option value="ru">RU</option>
</select>
</div>
<div class="tm-setting-row" style="border-bottom:none;">
<span class="tm-setting-label"></span>
<button id="tm-cfg-reset" class="tm-setting-reset">Reset Config</button>
</div>
</div>
<div id="tm-main">
<div id="tm-tabs">
<button class="tm-tab active" data-tab="combat">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="5" x2="5" y2="19"/><polyline points="16 5 19 5 19 8"/><polyline points="5 8 5 5 8 5"/></svg>Combat
</button>
<button class="tm-tab" data-tab="visual">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z"/></svg>Visual
</button>
<button class="tm-tab" data-tab="misc">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><circle cx="5" cy="12" r="1.2"/><circle cx="12" cy="12" r="1.2"/><circle cx="19" cy="12" r="1.2"/></svg>Misc
</button>
<button class="tm-tab" data-tab="changelog">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/></svg>Log
</button>
</div>
<div id="tm-body">
<div class="tm-panel active" data-panel="combat">
${_row('autoheal','Auto Heal','Auto heal when HP < 60% and food available')}
<div class="tm-divider"></div>
${_row('aimbow','Aim Bow','Aim with a bow toward the nearest enemy')}
<div class="tm-divider"></div>
${_row('triggerbot','Trigger Bot','Automatically attacks when it hits the player\'s hitbox')}
<div class="tm-divider"></div>
${_row('autoreconnect','Auto Reconnect','Instantly respawn on death')}
<div class="tm-divider"></div>
${_row('killmessage','Kill Message','Send a chat message when you kill a player')}
<div class="tm-divider"></div>
<div class="tm-macros-header" id="tm-macros-toggle">
<div class="tm-row-info">
<div class="tm-row-name" id="tm-macros-name">Macros</div>
<div class="tm-row-desc" id="tm-macros-desc">PvP macros list</div>
</div>
<div class="tm-macros-arrow" id="tm-macros-arrow">▼</div>
</div>
<div class="tm-macros-body" id="tm-macros-body" style="display:none;">
<div class="tm-macro-row">
<div><div class="tm-macro-name" id="tm-macro-trap-name">Place Trap</div><div class="tm-macro-desc" id="tm-macro-trap-desc">Place trap on bind key</div></div>
<div class="tm-bind-btn" id="tm-bind-trap">${trapBind || '-'}</div>
</div>
<div class="tm-divider" style="margin:4px 0;"></div>
<div class="tm-macro-row">
<div><div class="tm-macro-name" id="tm-macro-ball-name">Place Ballista</div><div class="tm-macro-desc" id="tm-macro-ball-desc">Place ballista on bind key</div></div>
<div class="tm-bind-btn" id="tm-bind-ballista">${ballistaBind || '-'}</div>
</div>
<div class="tm-macro-hint" id="tm-macro-hint">Esc - clear bind</div>
</div>
</div>
<div class="tm-panel" data-panel="visual">
${_row('zoom','Zoom','Zoom hack (CTRL + mouse wheel)')}
<div class="tm-divider"></div>
${_row('esp','ESP','Draws precise hitboxes on players')}
<div class="tm-divider"></div>
${_row('tracers','Tracers','Draws lines from you to each enemy')}
<div class="tm-divider"></div>
${_row('hud','HUD','Shows FPS, ping and player count')}
</div>
<div class="tm-panel" data-panel="misc">
${_row('skinunlock','Skin Unlock','Unlocks Orc, Elf, Undead without sharing')}
<div class="tm-divider"></div>
${_row('walkunlock','Walk Unlock','Move even with chat or menus open')}
<div class="tm-divider"></div>
${_row('antiafk','Anti-AFK','Prevents server kick for inactivity')}
<div class="tm-divider"></div>
${_row('Gold_Bot','Gold Bot','Bots come toward you, kill them for gold')}
<div class="tm-gb-slider-row">
<span class="tm-gb-slider-label">Bots: <span id="tm-gb-count">${dgCount}</span></span>
<input type="range" id="tm-gb-slider" class="tm-gb-slider" min="1" max="${_GB_MAX}" value="${dgCount}">
</div>
<div class="tm-divider"></div>
<div class="tm-row" style="flex-direction:column;gap:6px;">
<div class="tm-row-info"><div class="tm-row-name">Scout</div><div class="tm-row-desc" id="tm-scout-desc">Second account marks players on minimap</div></div>
<div class="tm-scout-btns" style="padding:0;">
<button class="tm-scout-btn" id="tm-scout-start">Start</button>
<button class="tm-scout-btn" id="tm-scout-stop">Stop</button>
<button class="tm-scout-btn" id="tm-scout-clear">Clear</button>
</div>
</div>
</div>
<div class="tm-panel" data-panel="changelog">
<div class="tm-changelog">
<div class="tm-cl-entry">
<div class="tm-cl-version">v1.2</div>
<div class="tm-cl-text">Upgraded aimbot; upgraded auto reconnect; added trigger bot; fixed bugs</div>
</div>
<div class="tm-cl-entry">
<div class="tm-cl-version">v1.1</div>
<div class="tm-cl-text">Fixed bug with scout. UI upgraded: settings panel, themes, language. New: Auto Reconnect, Anti-AFK, Macros list (PlaceTrap, PlaceBallista)</div>
</div>
<div class="tm-cl-entry">
<div class="tm-cl-version">v1.0</div>
<div class="tm-cl-text">Client released. First public build. Zoom, ESP, Tracers, AutoHeal, AimBow, Scout, WalkUnlock, KillMessage, Gold Bot, HUD</div>
</div>
</div>
</div>
</div>
<div id="tm-footer">
<div id="tm-footer-label">Menu key:</div>
<button id="tm-menu-key-btn">${menuKey}</button>
</div>
</div>
`;
document.body.appendChild(menu);
applyTheme(currentTheme);
document.getElementById('tm-theme-select').value = currentTheme;
document.getElementById('tm-lang-select').value = currentLang;
function showSettings() {
document.getElementById('tm-settings').style.display = 'block';
document.getElementById('tm-main').style.display = 'none';
}
function showMain() {
document.getElementById('tm-settings').style.display = 'none';
document.getElementById('tm-main').style.display = 'block';
}
document.getElementById('tm-gear').addEventListener('click', e => {
e.stopPropagation();
showSettings();
});
document.getElementById('tm-settings-back').addEventListener('click', () => showMain());
document.getElementById('tm-theme-select').addEventListener('change', function() {
currentTheme = this.value;
applyTheme(currentTheme);
saveState();
});
document.getElementById('tm-lang-select').addEventListener('change', function() {
currentLang = this.value;
updateLang();
saveState();
});
document.getElementById('tm-cfg-reset').addEventListener('click', () => {
localStorage.removeItem(CFG_KEY);
location.reload();
});
const gbSlider = document.getElementById('tm-gb-slider');
const gbCount = document.getElementById('tm-gb-count');
gbSlider.addEventListener('input', function() {
dgCount = parseInt(this.value);
gbCount.textContent = dgCount;
saveState();
if (dgRunning) _dgAdjustBots(dgCount);
});
menu.querySelectorAll('.tm-tab').forEach(tab => {
tab.addEventListener('click', () => {
menu.querySelectorAll('.tm-tab').forEach(t => t.classList.remove('active'));
menu.querySelectorAll('.tm-panel').forEach(p => p.classList.remove('active'));
tab.classList.add('active');
menu.querySelector('[data-panel="' + tab.dataset.tab + '"]')?.classList.add('active');
document.getElementById('tm-footer').style.display = tab.dataset.tab === 'changelog' ? 'none' : '';
});
});
menu.querySelectorAll('.tm-toggle').forEach(tog => {
tog.addEventListener('click', () => {
const k = tog.dataset.key;
state[k].enabled = !state[k].enabled;
tog.classList.toggle('on', state[k].enabled);
onToggle(k, state[k].enabled);
});
});
document.getElementById('tm-scout-start').addEventListener('click', scoutStart);
document.getElementById('tm-scout-stop').addEventListener('click', scoutStop);
document.getElementById('tm-scout-clear').addEventListener('click', scoutClear);
const macrosToggle = document.getElementById('tm-macros-toggle');
const macrosBody = document.getElementById('tm-macros-body');
const macrosArrow = document.getElementById('tm-macros-arrow');
macrosToggle.addEventListener('click', () => {
const open = macrosBody.style.display === 'none';
macrosBody.style.display = open ? '' : 'none';
macrosArrow.classList.toggle('open', open);
});
function setupBind(btnId, getVal, setVal) {
const btn = document.getElementById(btnId);
btn.addEventListener('click', () => {
btn.classList.add('listening');
btn.textContent = '...';
const h = e => {
e.preventDefault();
e.stopPropagation();
if (e.key === 'Escape') {
setVal('');
btn.textContent = '-';
} else {
setVal(e.key);
btn.textContent = e.key;
}
btn.classList.remove('listening');
window.removeEventListener('keydown', h, true);
saveState();
};
window.addEventListener('keydown', h, {
capture: true,
once: true
});
});
}
setupBind('tm-bind-trap', () => trapBind, v => {
trapBind = v;
});
setupBind('tm-bind-ballista', () => ballistaBind, v => {
ballistaBind = v;
});
const mkBtn = document.getElementById('tm-menu-key-btn');
const BLOCKED = new Set(['KeyW', 'KeyA', 'KeyS', 'KeyD', 'Escape', 'Space', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']);
mkBtn.addEventListener('click', () => {
mkBtn.classList.add('listening');
mkBtn.textContent = '...';
const h = e => {
e.preventDefault();
if (BLOCKED.has(e.code)) {
mkBtn.textContent = 'blocked!';
setTimeout(() => {
mkBtn.textContent = menuKey;
mkBtn.classList.remove('listening');
window.removeEventListener('keydown', h, true);
}, 800);
return;
}
menuKey = e.key;
mkBtn.textContent = menuKey;
mkBtn.classList.remove('listening');
window.removeEventListener('keydown', h, true);
saveState();
};
window.addEventListener('keydown', h, {
capture: true
});
});
window.addEventListener('keydown', e => {
if (e.key === menuKey && !_isInput()) {
e.preventDefault();
const visible = menu.style.display !== 'none';
menu.style.display = visible ? 'none' : '';
if (!visible) showMain();
}
}, true);
_makeDraggable(menu, document.getElementById('tm-header'));
Object.keys(state).forEach(k => {
const tog = menu.querySelector('[data-key="' + k + '"]');
if (tog && state[k]?.enabled) tog.classList.add('on');
});
updateLang();
});
function updateLang() {
const L = I18N[currentLang] || I18N.en;
const pairs = [
['autoheal', 'Auto Heal'],
['aimbow', 'Aim Bow'],
['triggerbot', 'Trigger Bot'],
['autoreconnect', 'Auto Reconnect'],
['killmessage', 'Kill Message'],
['zoom', 'Zoom'],
['esp', 'ESP'],
['tracers', 'Tracers'],
['hud', 'HUD'],
['skinunlock', 'Skin Unlock'],
['walkunlock', 'Walk Unlock'],
['Gold_Bot', 'Gold Bot'],
['antiafk', 'Anti-AFK'],
];
pairs.forEach(([key]) => {
const row = document.querySelector('[data-key="' + key + '"]');
if (!row) return;
const p = row.parentElement;
const ds = p.querySelector('.tm-row-desc');
if (ds && L[key]) ds.textContent = L[key][1];
});
const set = (id, v) => {
const el = document.getElementById(id);
if (el) el.textContent = v;
};
set('tm-macros-desc', (L.macros || ['', 'PvP macros list'])[1]);
set('tm-macro-trap-desc', (L.trapMacro || ['', 'Place trap on bind key'])[1]);
set('tm-macro-ball-desc', (L.ballistaMacro || ['', 'Place ballista on bind key'])[1]);
set('tm-scout-desc', (L.scout || ['Scout', 'Second account marks players on minimap'])[1]);
set('tm-macro-hint', (L.escClear || ['Esc - clear bind'])[0]);
set('tm-settings-title', (L.settings || ['Settings'])[0].toUpperCase());
const thLabels = document.querySelectorAll('.tm-setting-label');
if (thLabels[0]) thLabels[0].textContent = (L.theme || ['Theme'])[0];
if (thLabels[1]) thLabels[1].textContent = (L.language || ['Language'])[0];
const resetBtn = document.getElementById('tm-cfg-reset');
if (resetBtn) resetBtn.textContent = (L.resetCfg || ['Reset Config'])[0];
}
function _row(key, name, desc) {
return `<div class="tm-row"><div class="tm-row-info"><div class="tm-row-name">${name}</div><div class="tm-row-desc">${desc}</div></div><div class="tm-toggle${state[key]?.enabled?' on':''}" data-key="${key}"></div></div>`;
}
function _isInput() {
const el = document.activeElement;
if (!el) return false;
const tag = el.tagName.toLowerCase();
if (tag === 'input' || tag === 'textarea' || el.isContentEditable) return true;
try {
const ui = unsafeWindow.UI;
if (ui && (ui.chatVisible || ui.teamVisible)) return true;
} catch {}
return false;
}
function _makeDraggable(el, handle) {
let ox = 0,
oy = 0;
handle.addEventListener('mousedown', e => {
if (e.target.id === 'tm-gear') return;
e.preventDefault();
ox = e.clientX - el.offsetLeft;
oy = e.clientY - el.offsetTop;
const mv = e => {
el.style.left = (e.clientX - ox) + 'px';
el.style.top = (e.clientY - oy) + 'px';
el.style.right = 'auto';
};
document.addEventListener('mousemove', mv);
document.addEventListener('mouseup', () => document.removeEventListener('mousemove', mv), {
once: true
});
});
}
})();