blackhack

Cheat for brofist.io

2026-03-23 기준 버전입니다. 최신 버전을 확인하세요.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name           blackhack
// @version        1.15-beta0
// @description    Cheat for brofist.io
// @author         CiNoP
// @match          *://*.brofist.io/*
// @icon           https://www.google.com/s2/favicons?sz=64&domain=brofist.io
// @grant          none
// @license        GPL-3.0-only
// @namespace      brofist.io 1st-cheat (FOR ALL MODES)
// ==/UserScript==
/* jshint esversion: 11 */
/* jshint asi: true */




(() => {
	const _bind = Function.prototype.bind;
	const pathname = location.pathname.toLowerCase();
	const isTwoPlayer = pathname.includes("twoplayer");

	window.hack = {
		mode: null,
		modeController: null,
		gp: null,
		networkHandler: null,
		client: null,
		originalMakeMeGhost: null,
		originalSocketEmit: null,
	};

	new Promise((resolve) => {

		if (isTwoPlayer) {
			console.log("Подключение хука для Two Player Adventure...");

			Function.prototype.bind = function(context, ...args) {
				if (context && context.playerData && context.twoPlayerController) {
					window.hack.mode = context;
					window.hack.modeController = context.twoPlayerController;
					window.hack.gp = context.gp;
					window.hack.networkHandler = context.networkHandler;
					window.hack.client = context.client;

					Function.prototype.bind = _bind;
					console.log("2PA Hack Ready:", window.hack);
					resolve(window.hack);
				}
				return _bind.apply(this, [context, ...args]);
			};

		} else {
			console.log("Подключение хука для Sandbox/HideAndSeek...");

			let modeCaptured = false;
			let networkCaptured = false;

			const checkReady = () => {
				if (modeCaptured && networkCaptured) {
					window.hack.gp = window.gp;
					window.hack.client = window.client;
					console.log("Sandbox/Other Hack Ready:", window.hack);
					resolve(window.hack);
				}
			};

			Object.defineProperty(Object.prototype, 'pingCheckCount', {
				set(val) {
					delete Object.prototype.pingCheckCount;
					this.pingCheckCount = val;
					window.hack.networkHandler = this;
					networkCaptured = true;
					checkReady();
				},
				configurable: true
			});

			Object.defineProperty(Object.prototype, 'othersPlayerNetworkData', {
				set(val) {
					delete Object.prototype.othersPlayerNetworkData;
					this.othersPlayerNetworkData = val;
					window.hack.mode = this;
					window.hack.modeController = this;
					modeCaptured = true;
					checkReady();
				},
				configurable: true
			});
		}

	}).then(() => main(isTwoPlayer));

	function main(is2pa) {

		// --- Хук на сокет ---
		if (hack.networkHandler) {
			const existingSock = hack.networkHandler.gsSocket;
			if (existingSock && !existingSock.__patched) {
				existingSock.__patched = true;
				hack.originalSocketEmit = existingSock.emit;
				existingSock.emit = function(eventName, ...args) {
					if (eventName === "rGho" && hack.vars.imm) {
						console.log("[NETWORK] Заблокирована отправка rGho");
						return;
					}
					return hack.originalSocketEmit.apply(this, [eventName, ...args]);
				};
			}

			const origConnect = hack.networkHandler.connectToGs;
			if (origConnect) {
				hack.networkHandler.connectToGs = function(...args) {
					origConnect.apply(this, args);
					const sock = this.gsSocket;
					if (sock && !sock.__patched) {
						sock.__patched = true;
						hack.originalSocketEmit = sock.emit;
						sock.emit = function(eventName, ...args) {
							if (eventName === "rGho" && hack.vars.imm) {
								console.log("[NETWORK] Заблокирована отправка rGho");
								return;
							}
							return hack.originalSocketEmit.apply(this, [eventName, ...args]);
						};
					}
				};
			}
		}

		// ─── Состояния ──────────────────────────────────────────────
		hack.vars = {
			imm: false,
			noclip: false,
			mult: { enabled: false, value: 1 }
		};
		hack.keyBinds = {
			F2: false,
			F4: false,
			SHIFT: false,
			HOME: false,
			END: false
		};
		hack.prevKeys = {};

		const keyMap = {
			'F2': 'F2',
			'F4': 'F4',
			'Shift': 'SHIFT',
			'Home': 'HOME',
			'End': 'END'
		};

		document.addEventListener('keydown', (e) => {
			if (keyMap[e.key]) {
				e.preventDefault();
				hack.keyBinds[keyMap[e.key]] = true;
			}
		});
		document.addEventListener('keyup', (e) => {
			if (keyMap[e.key]) hack.keyBinds[keyMap[e.key]] = false;
		});
		window.addEventListener('blur', () => {
			for (const k in hack.keyBinds) hack.keyBinds[k] = false;
		});

		// ─── Доступ к игроку ────────────────────────────────────────
		const getLocalPlayer = () => {
			if (is2pa) return hack.modeController.localPlayer;
			return hack.modeController.player ? hack.modeController.player.gpData : null;
		};

		const getPlayerGpData = () => {
			if (is2pa) return hack.mode.player ? hack.mode.player.gpData : null;
			return getLocalPlayer();
		};

		// ─── Обработчики ────────────────────────────────────────────
		hack.funcs = {
			handlers: {
				immE: (obj, key) => {
					obj[key] = true;
					const gpData = getPlayerGpData();
					if (gpData) gpData.me = void 0;
					if (hack.mode.makeMeGhost && !hack.originalMakeMeGhost) {
						hack.originalMakeMeGhost = hack.mode.makeMeGhost;
					}
					if (hack.mode.makeMeGhost) {
						hack.mode.makeMeGhost = function() {
							console.log("[IMM] Попытка убить игрока заблокирована");
						};
					}
					console.log("Бессмертие ВКЛЮЧЕНО");
				},

				immD: (obj, key) => {
					obj[key] = false;
					const gpData = getPlayerGpData();
					if (gpData) gpData.me = true;
					if (hack.originalMakeMeGhost) {
						hack.mode.makeMeGhost = hack.originalMakeMeGhost;
					}
					console.log("Бессмертие ОТКЛЮЧЕНО");
				},

				noclipE: (obj, key, _mult) => {
					obj[key] = true;
					const gpData = getPlayerGpData();
					if (gpData && gpData.p) gpData.p.invMass = 0;
					const lp = getLocalPlayer();
					if (lp && lp.p) {
						lp.p.invMass = 0;
						lp.p.collisionResponse = false;
					}
					if (_mult.enabled) hack.vars.mult.value = 4;
					console.log("Noclip ВКЛЮЧЁН");
				},

				noclipD: (obj, key, _mult) => {
					obj[key] = false;
					const gpData = getPlayerGpData();
					if (gpData && gpData.p) gpData.p.invMass = 1;
					const lp = getLocalPlayer();
					if (lp && lp.p) {
						lp.p.invMass = 1;
						lp.p.mass = 1;
						lp.p.collisionResponse = true;
					}
					if (_mult.enabled) hack.vars.mult.value = 1;
					console.log("Noclip ОТКЛЮЧЁН");
				},

				multE: (obj, key, _noclip) => {
					if (_noclip) {
						obj[key] = true;
						hack.vars.mult.value = 4;
						console.log("Speedhack ВКЛЮЧЁН");
						return;
					}
					console.log("Включите noclip, чтобы изменить Speedhack");
				},

				multD: (obj, key, _noclip) => {
					if (_noclip) {
						obj[key] = false;
						hack.vars.mult.value = 1;
						console.log("Speedhack ОТКЛЮЧЁН");
						return;
					}
					console.log("Включите noclip, чтобы изменить Speedhack");
				},

				tpDoor: () => {
					const door = hack.gp.list.find(i => i.id && i.id.includes('door'));
					const lp = getLocalPlayer();
					if (door && lp) {
						lp.setX(door.getX());
						lp.setY(door.getY());
					}
				},

				tpSpawn: () => {
					const spawn = hack.gp.list.find(i => i.id && i.id.includes('spawn'));
					const lp = getLocalPlayer();
					if (spawn && lp) {
						lp.setX(spawn.getX());
						lp.setY(spawn.getY());
					}
				}
			}
		};

		// ─── Game Loop ──────────────────────────────────────────────
		function updateLoop() {
			const binds = hack.keyBinds;
			const prev = hack.prevKeys;
			const funcs = hack.funcs.handlers;
			const vars = hack.vars;
			const justPressed = (key) => binds[key] && !prev[key];

			if (is2pa) {
				if (justPressed('HOME')) funcs.tpSpawn();
				if (justPressed('END')) funcs.tpDoor();
				if (justPressed('F4')) {
					if (!vars.imm) funcs.immE(vars, 'imm');
					else funcs.immD(vars, 'imm');
				}
			}

			if (justPressed('F2')) {
				if (!vars.noclip) funcs.noclipE(vars, 'noclip', vars.mult);
				else funcs.noclipD(vars, 'noclip', vars.mult);
			}

			if (justPressed('SHIFT')) {
				if (!vars.mult.enabled) funcs.multE(vars.mult, 'enabled', vars.noclip);
				else funcs.multD(vars.mult, 'enabled', vars.noclip);
			}

			if (vars.noclip) {
				const gpData = getPlayerGpData();
				if (gpData && gpData.p && gpData.p.invMass !== 0) gpData.p.invMass = 0;
				const lp = getLocalPlayer();
				if (lp && lp.p) {
					if (lp.p.invMass !== 0) lp.p.invMass = 0;
					if (lp.p.collisionResponse !== false) lp.p.collisionResponse = false;
				}
			}

			if (is2pa && vars.imm) {
				const gpData = getPlayerGpData();
				if (gpData && gpData.me !== undefined) gpData.me = void 0;
			}

			for (const k in binds) prev[k] = binds[k];
			requestAnimationFrame(updateLoop);
		}
		requestAnimationFrame(updateLoop);

		// ─── Кастомная функция движения ─────────────────────────────
		const customMovement = function() {
			const ctrl = hack.modeController;
			const p = getLocalPlayer();
			const mult = hack.vars.mult.value;
			if (!p) return;

			if (hack.vars.noclip) {
				if (ctrl.moveRight) p.p.velocity[0] = 3 * mult;
				else if (ctrl.moveLeft) p.p.velocity[0] = -3 * mult;
				else p.p.velocity[0] = 0;

				if (ctrl.moveUp) p.p.velocity[1] = 3 * mult;
				else if (ctrl.moveDown) p.p.velocity[1] = -3 * mult;
				else p.p.velocity[1] = 0;
				return;
			}

			if (ctrl.moveRight) p.p.velocity[0] = 3;
			if (ctrl.moveLeft) p.p.velocity[0] = -3;
			if (!ctrl.moveUp) return;

			const ex = p.getX(),
				ty = p.getY(),
				n = ex - 15,
				r = 30 / 11;
			const phys = is2pa ? ctrl.physics : hack.gp;

			for (let i = 0; i < 12; i++) {
				const ox = n + i * r,
					oy1 = ty + 49,
					oy2 = oy1 + 50;
				p.ray.from = [phys.xAxis(ox, 0), phys.yAxis(oy1, 0)];
				p.ray.to = [phys.xAxis(ox, 0), phys.yAxis(oy2, 0)];
				p.ray.update();
				p.ray.result.reset();
				p.ray.hitPoint = [Infinity, Infinity];

				if (hack.gp.pWorld.raycast(p.ray.result, p.ray)) {
					const hitDist = p.ray.result.getHitDistance(p.ray);
					if (p.ray.result.shape.ref.getCollision() && hitDist < 0.05) {
						p.p.velocity[1] = 8;
						break;
					}
				}
			}
		};

		// ─── Замена movement (прямой поиск) ─────────────────────────
		let replaced = false;
		for (let i = 0; i < hack.client.loopFunctions.length; i++) {
			const funcStr = hack.client.loopFunctions[i].fun.toString();
			if (funcStr.includes("moveLeft") &&
				(funcStr.includes("raycast") || funcStr.includes("velocity[1]"))) {
				hack.client.loopFunctions[i].fun = customMovement;
				console.log("[MOVEMENT] Заменено в loopFunctions[" + i + "]");
				replaced = true;
				break;
			}
		}

		if (!replaced && is2pa && hack.client.loopFunctions.length > 7) {
			hack.client.loopFunctions[7].fun = customMovement;
			console.log("[MOVEMENT] 2PA-фолбэк loopFunctions[7]");
			replaced = true;
		}

		// Хук на addLoopFunction — ловим movement при смене карты
		const origAddLoop = hack.client.addLoopFunction;
		hack.client.addLoopFunction = function(fun, par, exeCount, timeOut) {
			if (fun) {
				const str = fun.toString();
				if (str.includes("moveLeft") &&
					(str.includes("raycast") || str.includes("velocity[1]"))) {
					console.log("[MOVEMENT] Перехвачено через addLoopFunction");
					return origAddLoop.call(this, customMovement, par, exeCount, timeOut);
				}
			}
			return origAddLoop.call(this, fun, par, exeCount, timeOut);
		};

		// ─── Промис: ждём sendMyStatus и ставим timeOut = 0 ────────
		new Promise((resolve) => {
			const check = () => {
				const lf = hack.client.loopFunctions;
				for (let i = 0; i < lf.length; i++) {
					if (lf[i] && (lf[i].timeOut === 200 || lf[i].timeOut === 150)) {
						lf[i].timeOut = 0;
						console.log("[SEND_STATUS] timeOut → 0 в loopFunctions[" + i + "]");
						resolve(i);
						return;
					}
				}
				requestAnimationFrame(check);
			};
			check();
		});

		console.log("Main Hook завершён. Game Loop (rAF) запущен.");
	}
})();