blackhack-logic

Game logic, physics hooks and update extensions for blackhack

Ce script ne doit pas être installé directement. C'est une librairie destinée à être incluse dans d'autres scripts avec la méta-directive // @require https://update.greasyfork.org/scripts/573606/1796986/blackhack-logic.js

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==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 =[];
			}
		}
	};
})();