blackhack-logic

Game logic, physics hooks and update extensions for blackhack

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greasyfork.org/scripts/573606/1796986/blackhack-logic.js

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name           blackhack-logic
// @namespace      brofist.io 1st-cheat (FOR ALL MODES)
// @version        1.0
// @description    Game logic, physics hooks and update extensions for blackhack
// @author         CiNoP
// @license        GPL-3.0-only
// ==/UserScript==

/* blackhack-logic.js */
(function () {
	'use strict';
	const BH = window.BH = window.BH || {};
	BH.logicVer = 1.0;

	// ─── Bind Hack (Runs immediately) ───
	const _bind = Function.prototype.bind;
	const pathname = location.pathname.toLowerCase();
	const isTwoPlayer = pathname.includes("twoplayer");
	const bm = { processOthers: false, movement: false, _allFound: false, _origPO: null, _origMV: null };

	Function.prototype.bind = function (ctx, ...args) {
		const b = _bind.apply(this, [ctx, ...args]);
		if (!bm._allFound) {
			try {
				const s = this.toString();
				if (!bm.processOthers && s.includes('othersPlayerNetworkData') && s.includes('oldPlayersIndex')) {
					b.__hk_processOthers = true; bm.processOthers = true; bm._origPO = this;
				}
				if (!bm.movement && s.includes('moveLeft') && (s.includes('raycast') || s.includes('velocity[1]'))) {
					b.__hk_movement = true; bm.movement = true; bm._origMV = this;
				}
				if (bm.processOthers && bm.movement) bm._allFound = true;
			} catch (_) {}
		} else {
			if (this === bm._origPO) b.__hk_processOthers = true;
			if (this === bm._origMV) b.__hk_movement = true;
		}
		if (isTwoPlayer && window.hack && !window.hack.mode && ctx && ctx.playerData && ctx.twoPlayerController) {
			window.hack.mode = ctx; window.hack.modeController = ctx.twoPlayerController;
			window.hack.gp = ctx.gp; window.hack.networkHandler = ctx.networkHandler;
			window.hack.client = ctx.client;
		}
		return b;
	};

	BH.Logic = {
		diff: (a, b) => a.filter(x => !b.includes(x)),

		getIdxByName: (hack, n) => {
			const r =[], o = hack.mode.otherPlayers;
			for (let i = 0; i < o.length; i++) if (o[i]?.myName === n) r.push(i);
			return r;
		},

		processBL: (hack) => {
			const bl = hack.vars.blacklisted;
			for (const n of bl.names) {
				for (const i of BH.Logic.getIdxByName(hack, n)) {
					if (!bl.data.some(e => e?.[0] === i && e?.[1] === n)) bl.data.push([i, n]);
				}
			}
			if (bl.data.length) bl.data = bl.data.filter(e => e?.[1] && bl.names.includes(e[1]));
		},

		isIdxBL: (hack, i) => hack.vars.blacklisted.data.some(e => e?.[0] === i),

		enforceBL: (hack) => {
			const bl = hack.vars.blacklisted; if (!bl.data.length) return;
			const o = hack.mode.otherPlayers;
			for (const [i] of bl.data) {
				const p = o[i]; if (!p?.gpData) continue;
				p.gpData.g.visible = false;
				if (p.gpData.p) p.gpData.p.collisionResponse = false;
			}
			const msgs = hack.mode.othersPlayerMsgNetworkData;
			if (msgs) {
				const s = new Set(bl.data.map(e => e[0]));
				for (let i = 0; i < msgs.length; i++) msgs[i] = msgs[i].filter(m => !s.has(m[0]));
			}
		},

		getEV: (hack) => {
			const u = hack.keyBinds.ARROW_UP, d = hack.keyBinds.ARROW_DOWN;
			if (u && d) {
				if (hack.vars.arrowFirstPressed === 'up') return 'down';
				if (hack.vars.arrowFirstPressed === 'down') return 'up';
				return null;
			}
			return u ? 'up' : d ? 'down' : null;
		},

		initHooks: (hack, is2pa) => {
			const customPO = function () {
				const mode = hack.mode, gp = hack.gp, nh = hack.networkHandler;
				BH.Logic.processBL(hack);
				if (!mode.othersPlayerNetworkData.length) return;
				var cur =[];
				for (var x = 0; x < mode.othersPlayerNetworkData.length; x++) {
					for (var y = 0; y < mode.othersPlayerNetworkData[x].length; y++) {
						var d = mode.othersPlayerNetworkData[x][y], idx = d[0], xV = d[1], yV = d[2], xA = d[3], yA = d[4];
						if (BH.Logic.isIdxBL(hack, idx)) continue;
						if (mode.otherPlayers[idx] == null) {
							mode.oldPlayersIndex.push(idx);
							var p = {}; p.myName = ""; p.mySkin = 0; p.reset = Infinity;
							p.gpData = is2pa ? mode.basePlayer.createPlayer(mode.playerData) : mode.createPlayer();
							p.gpData.g.myIndex = idx; mode.otherPlayers[idx] = p;
							if (nh?.gsSocket) nh.gsSocket.emit("rBio", idx);
							gp.gWorld.removeChild(p.gpData.g); gp.gWorld.mid.addChild(p.gpData.g);
						}
						if (10 < mode.otherPlayers[idx].reset) { mode.otherPlayers[idx].gpData.setX(xA); mode.otherPlayers[idx].gpData.setY(yA); mode.otherPlayers[idx].reset = 0; }
						mode.otherPlayers[idx].reset++;
						mode.otherPlayers[idx].gpData.p.velocity[0] = xV;
						mode.otherPlayers[idx].gpData.p.velocity[1] = yV;
						cur.push(idx);
					}
				}
				var r = BH.Logic.diff(mode.oldPlayersIndex, cur);
				for (var i = 0; i < r.length; i++) {
					var p2 = mode.otherPlayers[r[i]];
					if (p2 != null) {
						gp.gWorld.mid.removeChild(p2.gpData.g); gp.pWorld.removeBody(p2.gpData.p);
						gp.list[gp.list.indexOf(p2.gpData)] = null; gp.deleteCounter++; mode.otherPlayers[r[i]] = null;
					}
				}
				mode.oldPlayersIndex = cur; mode.othersPlayerNetworkData =[];
			};

			const customMV = function () {
				const ctrl = hack.modeController, p = hack.getLP();
				const mult = hack.vars.mult.value, jh = hack.vars.jumpHeight, gs = hack.vars.gravNoclipGravScale;
				if (!p || !ctrl) return;

				if (hack.vars.noclip) {
					p.p.velocity[0] = ctrl.moveRight ? 3 * mult : ctrl.moveLeft ? -3 * mult : 0;
					p.p.velocity[1] = ctrl.moveUp ? 3 * mult : ctrl.moveDown ? -3 * mult : 0;
					return;
				}

				if (hack.vars.gravNoclip) {
					p.p.velocity[0] = ctrl.moveRight ? 3 * mult : ctrl.moveLeft ? -3 * mult : 0;
					const v = BH.Logic.getEV(hack);
					if (v === 'up') { p.p.gravityScale = -gs; p.setAngle(180); }
					else if (v === 'down') { p.p.gravityScale = gs; p.setAngle(0); }
					else p.p.gravityScale = 0;
					const gd = p.p.gravityScale;
					let sj = false, jd = 0, rsY, reY;
					const ex = p.getX(), ty = p.getY(), hH = 50, rL = 50, n = ex - 15, r = 30 / 11;
					if (gd > 0 && ctrl.moveUp) { sj = true; jd = jh; rsY = ty + (hH - 1); reY = rsY + rL; }
					else if (gd < 0 && ctrl.moveDown) { sj = true; jd = -jh; rsY = ty - (hH - 1); reY = rsY - rL; }
					if (sj) {
						const ph = is2pa ? ctrl.physics : hack.gp;
						for (let i = 0; i < 12; i++) {
							const ox = n + i * r;
							p.ray.from = [ph.xAxis(ox, 0), ph.yAxis(rsY, 0)]; p.ray.to =[ph.xAxis(ox, 0), ph.yAxis(reY, 0)];
							p.ray.update(); p.ray.result.reset(); p.ray.hitPoint = [Infinity, Infinity];
							if (hack.gp.pWorld.raycast(p.ray.result, p.ray))
								if (p.ray.result.shape.ref.getCollision() && p.ray.result.getHitDistance(p.ray) < 0.15) { p.p.velocity[1] = jd; break; }
						}
					}
					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 ph = 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 =[ph.xAxis(ox, 0), ph.yAxis(oy1, 0)]; p.ray.to =[ph.xAxis(ox, 0), ph.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))
						if (p.ray.result.shape.ref.getCollision() && p.ray.result.getHitDistance(p.ray) < 0.05) { p.p.velocity[1] = jh; break; }
				}
			};

			let poI = false, mvI = false;
			function cih() {
				const lf = hack.client.loopFunctions;
				if (!poI) { const i = lf.findIndex(e => e?.fun?.__hk_processOthers || (e?.fun?.toString().includes('othersPlayerNetworkData') && e.fun.toString().includes('oldPlayersIndex'))); if (i !== -1) { lf[i].fun = customPO; poI = true; } }
				if (!mvI) { const i = lf.findIndex(e => e?.fun?.__hk_movement || (e?.fun?.toString().includes('moveLeft') && (e.fun.toString().includes('raycast') || e.fun.toString().includes('velocity[1]')))); if (i !== -1) { lf[i].fun = customMV; mvI = true; } else if (is2pa && lf.length > 7) { lf[7].fun = customMV; mvI = true; } }
				if (!poI || !mvI) requestAnimationFrame(cih);
			}
			cih();

			const oal = hack.client.addLoopFunction;
			hack.client.addLoopFunction = function (f, p, t, e) {
				if (f) {
					if (f.__hk_processOthers || (f.toString().includes('othersPlayerNetworkData') && f.toString().includes('oldPlayersIndex'))) return oal.call(this, customPO, p, t, e);
					if (f.__hk_movement || (f.toString().includes('moveLeft') && (f.toString().includes('raycast') || f.toString().includes('velocity[1]')))) return oal.call(this, customMV, p, t, e);
				}
				return oal.call(this, f, p, t, e);
			};
		},

		updateTP: (hack) => {
			const v = hack.vars;
			if (v.tpToPlayerEnabled && v.tpTargetName !== "Никто") {
				let target = hack.mode.otherPlayers[v.tpTargetIndex];
				if (!target || target.myName !== v.tpTargetName) {
					let foundNewIndex = -1;
					const oPlayers = hack.mode.otherPlayers;
					for (let i = 0; i < oPlayers.length; i++) {
						if (oPlayers[i] && oPlayers[i].myName === v.tpTargetName) { foundNewIndex = i; break; }
					}
					if (foundNewIndex !== -1) {
						v.tpTargetIndex = foundNewIndex;
						target = oPlayers[foundNewIndex];
					}
				}
				if (target && target.gpData && target.reset <= 10) {
					const lp = hack.getLP();
					if (lp) {
						lp.setX(target.gpData.getX());
						lp.setY(target.gpData.getY());
						if (lp.p) { lp.p.velocity[0] = 0; lp.p.velocity[1] = 0; }
					}
				}
			}
		},

		updateXray: (hack) => {
			const v = hack.vars;
			if (v.layoutMode) {
				if (v.xrayGates.length === 0 && hack.gp && hack.gp.list) {
					const pixi = window.pixi || window.PIXI;
					if (pixi && pixi.Graphics) {
						hack.gp.list.forEach(obj => {
							if (obj && obj.id && obj.id.toLowerCase().startsWith('gate')) {
								const parts = obj.id.split(':');
								const action = parts[parts.length - 1];
								obj.shapes.forEach((shape, idx) => {
									if (shape && shape.make !== 3 && shape.g && shape.g.parent) {
										const gfx = new pixi.Graphics();
										const color = action === "1" ? 0xFF00FF : 0x00FFFF;
										let baseW = 50, baseH = 50, baseR = 25;
										if (shape.p) {
											if (shape.p.width) baseW = shape.p.width * 100;
											if (shape.p.height) baseH = shape.p.height * 100;
											if (shape.p.radius) baseR = shape.p.radius * 100;
										} else if (shape.g) {
											const sx = shape.g.scale ? Math.abs(shape.g.scale.x) : 1;
											const sy = shape.g.scale ? Math.abs(shape.g.scale.y) : 1;
											if (shape.g.width) baseW = shape.g.width / sx;
											if (shape.g.height) baseH = shape.g.height / sy;
											baseR = baseW / 2;
										}
										const type = typeof shape.getType === 'function' ? shape.getType() : shape.type;
										if (type === 2) { gfx.circle(0, 0, baseR); }
										else if (type === 5) {
											const triH = baseW * Math.sqrt(3) / 2;
											const rOff = triH / 6;
											gfx.moveTo(-baseW / 2, triH / 2 - rOff); gfx.lineTo(baseW / 2, triH / 2 - rOff); gfx.lineTo(0, -triH / 2 - rOff); gfx.closePath();
										} else { gfx.rect(-baseW / 2, -baseH / 2, baseW, baseH); }

										gfx.fill({ color: color, alpha: 0.15 });
										gfx.stroke({ width: 3, color: color, alpha: 1 });
										if (hack.gp.gWorld && hack.gp.gWorld.mid) hack.gp.gWorld.mid.addChild(gfx);

										let textObj = null;
										if (idx === 0) {
											textObj = new pixi.Text(obj.id, { fontFamily: 'monospace', fontSize: 14, fill: color, stroke: 0x000000, strokeThickness: 3, fontWeight: 'bold' });
											textObj.anchor.set(0.5, 1);
											hack.gp.gWorld.mid.addChild(textObj);
										}
										v.xrayGates.push({ gfx: gfx, src: shape, text: textObj, baseH: baseH, baseR: baseR, type: type });
									}
								});
							}
						});
					}
				}
				v.xrayGates.forEach(item => {
					const { src, gfx, text, baseH, baseR, type } = item;
					if (src && gfx) {
						if (!src.g || !src.g.parent) { gfx.visible = false; if (text) text.visible = false; return; }
						gfx.visible = true; gfx.scale.set(1);
						if (typeof src.getGlobalPosition === 'function') {
							const pos = src.getGlobalPosition(); gfx.x = pos.x * 100; gfx.y = pos.y * -100; gfx.rotation = -pos.angle;
						} else { gfx.x = src.g.x; gfx.y = src.g.y; gfx.rotation = src.g.rotation || 0; }
						const hasCollision = typeof src.getCollision === 'function' ? src.getCollision() : src.collision;
						if (!hasCollision) { gfx.alpha = 1.0; if (text) text.alpha = 1.0; } else { gfx.alpha = 0.15; if (text) text.alpha = 0.5; }
						if (text) {
							text.visible = true; text.x = gfx.x;
							const objHeight = type === 2 ? baseR * 2 : baseH;
							text.y = gfx.y - (objHeight / 2) - 5; text.scale.set(1);
						}
					}
				});
			} else if (v.xrayGates.length > 0) {
				v.xrayGates.forEach(item => {
					if (item.gfx && item.gfx.parent) item.gfx.parent.removeChild(item.gfx);
					if (item.gfx && typeof item.gfx.destroy === 'function') item.gfx.destroy();
					if (item.text && item.text.parent) item.text.parent.removeChild(item.text);
					if (item.text && typeof item.text.destroy === 'function') item.text.destroy();
				});
				v.xrayGates =[];
			}
		}
	};
})();