Map parsing functions for blackhack
بۇ قوليازمىنى بىۋاسىتە قاچىلاشقا بولمايدۇ. بۇ باشقا قوليازمىلارنىڭ ئىشلىتىشى ئۈچۈن تەمىنلەنگەن ئامبار بولۇپ، ئىشلىتىش ئۈچۈن مېتا كۆرسەتمىسىگە قىستۇرىدىغان كود: // @require https://update.greasyfork.org/scripts/571914/1789017/blackhack-map.js
// ==UserScript==
// @name blackhack-map
// @namespace brofist.io 1st-cheat (FOR ALL MODES)
// @version 1.12
// @description Map parsing functions for blackhack
// @author CiNoP
// @license GPL-3.0-only
// ==/UserScript==
/* blackhack-map.js */
(function () {
'use strict';
const BH = window.BH = window.BH || {};
BH.mapVer = 1.12;
const leverParts = new Set(['leftstick', 'leftball', 'rightstick', 'rightball']);
function isPoison(sid) { return sid === 'poision' || sid === 'poison'; }
function getFuncLabel(sid) {
if (sid === 'checkpoint') return 'C';
if (sid === 'playarea') return 'P';
if (sid === 'exitgate') return 'D';
if (sid.startsWith('button:')) return 'B';
if (sid.startsWith('leaver:')) return 'L';
return null;
}
function makeStub() {
return { x: 0, y: 0, type: 1, width: 1, height: 1, alpha: 0, id: '', collision: false, color: '0x000000', make: 3 };
}
function processShape(sh, oid, isFakeStatic, al, measureTextWidth) {
const sid = (sh.id || '').toLowerCase();
const oidLower = (oid || '').toLowerCase();
if (sid.includes('mapcredits')) {
return [{ ...sh, alpha: 0.8, collision: false, make: 3 }];
}
const poison = isPoison(sid);
const isPlatform = oidLower.startsWith('platform:');
if (sh.collision === false && !poison && !isPlatform) return null;
const c = { ...sh };
if (isPlatform && sh.make === 3) {
c.alpha = sh.alpha !== undefined ? sh.alpha : 1;
} else {
c.alpha = poison ? al.poison : al.collision;
c.color = poison ? '0x00FF00' : (isFakeStatic ? '0xFFFF00' : '0x000000');
}
const out = [];
if (sh.type === 3 && !oidLower.includes('mapcredits')) {
out.push({ ...c, type: 1, id: '', make: 3, alpha: 0.3,
width: measureTextWidth(sh.fontSize, sh.text), height: sh.fontSize * 1.108 });
}
out.push(c);
return out;
}
function removeCoverFromId(oid) {
return oid.split('|')
.filter(p => !p.trim().toLowerCase().startsWith('cover'))
.join('|');
}
BH.parseMapToLayout = mapData => {
const clamp = BH.clamp || ((v, m, x) => Math.max(m, Math.min(x, v)));
const measureTextWidth = BH.measureTextWidth || (() => 30);
const al = window.hack?.vars?.layoutAlpha || { collision: 1, poison: 1, functional: 1, background: 0xCCCCCC };
let parsed = mapData;
try {
if (typeof parsed === 'string') parsed = JSON.parse(parsed);
if (Array.isArray(parsed) && typeof parsed[0] === 'number' && window.LZMA)
parsed = JSON.parse(window.LZMA.decompress(parsed));
} catch (e) { return mapData; }
try { parsed = JSON.parse(JSON.stringify(parsed)); } catch (_) {}
const result = [];
for (const obj of parsed) {
if (!obj || !obj.shapes || !obj.shapes.length) { result.push(obj || {}); continue; }
const oid = (obj.id || '');
const oidLower = oid.toLowerCase();
// ── ПРОПУСК ГРАНИЦ КАРТЫ И ОБРАБОТКА MAP CREDITS ──
if (oidLower.includes('99999999999') || oidLower.includes('mapcredits')) {
const isCredits = oidLower.includes('mapcredits');
obj.shapes = obj.shapes.map(sh => {
if (!sh) return sh;
return { ...sh, alpha: isCredits ? 0.8 : 0, collision: false, make: 3 };
});
result.push(obj);
continue;
}
const shapes = obj.shapes;
const isFakeStatic = typeof obj.mass === 'number' && obj.mass !== 0 && Math.abs(obj.mass) < 1e-6;
const isGate = /^gate/i.test(oid);
// ── ВОРОТА: просто перекрашиваем в бирюзовый, убираем cover ──
if (isGate) {
obj.id = removeCoverFromId(oid);
const fs = [];
for (const sh of shapes) {
if (!sh) continue;
const sid = (sh.id || '').toLowerCase();
const shPoison = isPoison(sid);
// Пропускаем декорации без коллизии (кроме яда)
if (!sh.collision && !shPoison) continue;
const color = shPoison ? '0x00FFAA' : '0x00AAAA';
// Текст с коллизией → прямоугольная аппроксимация
if (sh.type === 3) {
fs.push({
...sh, type: 1, id: '', make: 3, alpha: 0.3, color,
width: measureTextWidth(sh.fontSize, sh.text),
height: sh.fontSize * 1.108
});
}
fs.push({ ...sh, alpha: 0.8, color });
}
if (!fs.length) fs.push(makeStub());
obj.shapes = fs;
result.push(obj);
continue;
}
// ── ОБРАБОТКА ФУНКЦИОНАЛЬНЫХ ОБЪЕКТОВ ──
const isFunctional = oidLower === 'spawn' || oidLower === 'door' || oidLower === 'playarea' || oidLower === 'checkpoint' ||
shapes.some(s => {
const sid = (s && s.id) ? s.id.toLowerCase() : '';
return sid === 'spawn' || sid === 'playarea' || sid === 'checkpoint' || sid === 'exitgate' ||
sid === 'egcounter' || sid.startsWith('roundtime:') || sid.startsWith('button:') || sid.startsWith('leaver:');
});
if (isFunctional) {
const fs = [];
const hasLeaver = shapes.some(s => s && s.id && s.id.toLowerCase().startsWith('leaver:'));
for (const sh of shapes) {
if (!sh) continue;
const sid = (sh.id || '').toLowerCase();
const isFunc = sid === 'spawn' || sid === 'playarea' || sid === 'checkpoint' || sid === 'exitgate' ||
sid === 'egcounter' || sid.startsWith('roundtime:') || sid.startsWith('button:') || sid.startsWith('leaver:');
if (isFunc) {
const c = { ...sh };
if (sid === 'egcounter' || (sid.startsWith('roundtime:') && sh.make === 3) || sid === 'spawn') {
c.alpha = 0; fs.push(c); continue;
}
c.alpha = al.functional; c.color = '0x0000FF'; fs.push(c);
const label = getFuncLabel(sid);
if (label) {
const w = Math.abs(sh.width || 30), h = Math.abs(sh.height || 30);
const fontSize = clamp(Math.min(w, h) * 0.6, 8, 30);
fs.push({ x: sh.x || 0, y: sh.y || 0, width: measureTextWidth(fontSize, label),
height: fontSize * 1.108, angle: -(obj.angle || 0), radius: 50, alpha: 1,
id: '', collision: false, color: '0x000000', fontSize, text: label, make: 3, type: 3 });
}
continue;
}
if (sh.make === 3 && hasLeaver && leverParts.has(sid)) { fs.push({ ...sh }); continue; }
if (sh.make === 3) continue;
const r = processShape(sh, oid, isFakeStatic, al, measureTextWidth);
if (r) fs.push(...r);
}
if (!fs.length) fs.push(makeStub());
obj.shapes = fs;
result.push(obj);
continue;
}
// ── ОБЫЧНЫЕ ОБЪЕКТЫ ──
if (oidLower.includes('cover')) {
obj.id = removeCoverFromId(obj.id);
}
const fs = [];
const isPlatform = oidLower.startsWith('platform:');
for (const sh of shapes) {
if (!sh || (sh.make === 3 && !isPlatform)) continue;
const r = processShape(sh, oid, isFakeStatic, al, measureTextWidth);
if (r) fs.push(...r);
}
if (!fs.length) fs.push(makeStub());
obj.shapes = fs; result.push(obj);
}
return result;
};
})();