feat(ignore): 面板新增「忽略」区域(坦克按阵营 / 反弹 / 栅栏)
hornet_noclip 改为通用忽略模块:配对过滤支持 关闭/仅敌方/仅友方/全部 的坦克忽略,并新增忽略栅栏(只跳过 |法线z|<0.5 的静态三角形,地面与缓坡保留);面板新增可折叠「忽略」区域,接管忽略坦克下拉、忽略反弹(NoKnockback)、忽略栅栏,各自 localStorage 持久化;schema 补 Shape.Type/Vertex0-2。
This commit is contained in:
1 parent
5088524f22
commit
7481dad24e
5 files changed
+783
-216
No files matched your search
@@ -299,6 +299,10 @@
|
||||
'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位
|
||||
'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应
|
||||
'Shape.Body': 'b9k_1', // 形状 → 所属刚体(Fn)
|
||||
'Shape.Type': 'v9j_1', // 形状类型位组(1/2/4/8/16/32;8 = 三角形)
|
||||
'Shape.Vertex0': 'u9x_1', // 三角形顶点 0
|
||||
'Shape.Vertex1': 'v9x_1', // 三角形顶点 1
|
||||
'Shape.Vertex2': 'w9x_1', // 三角形顶点 2
|
||||
'Body.Owner': 'x9i_1', // 刚体 → 拥有者(坦克物理组件 ejt)
|
||||
|
||||
// ---- 碰撞世界(module_55088 的 ki)----
|
||||
@@ -6516,36 +6520,29 @@
|
||||
|
||||
|
||||
// ===== hornet_noclip.js =====
|
||||
// hornet_noclip.js — 穿坦克(移动中忽略玩家坦克碰撞,强行行走)
|
||||
// 放在控制面板「穿坦克」开关里,只影响**本地坦克**,不改服务端/其他玩家。
|
||||
// hornet_noclip.js — 忽略模块(穿坦克 / 忽略栅栏)
|
||||
// 面板「忽略」区域控制:
|
||||
// · 忽略坦克:关闭 / 仅敌方 / 仅友方 / 全部
|
||||
// · 忽略栅栏:穿墙(只忽略陡峭的静态三角形,地面与缓坡照常)
|
||||
//
|
||||
// ⚠ 关键修正(2026-10-20):**不再改碰撞 mask**。
|
||||
// 之前清掉坦克形状 mask 的 bit0(1)会让拾取物失效 —— 坦克 category=1,
|
||||
// 而拾取物的触发体(module_87072 的 Ilt:category=1、mask=1、半径触发)
|
||||
// 判定需要「触发体.cat & 坦克.mask」成立,清掉 bit0 后就检测不到拾取物了。
|
||||
//
|
||||
// 现在的做法:在**碰撞世界的配对过滤**上精确拦截。
|
||||
// module_55088 的 ki.q9q(a, b) 是全物理世界唯一的配对判定:
|
||||
// if (0 === (a.y9j_1 & b.z9j_1) || 0 === (b.y9j_1 & a.z9j_1)) return; // 不生成接触
|
||||
// ...按形状类型取配对处理器,生成接触点
|
||||
// 我们只在「a、b 两边的拥有者都是坦克物理组件」时直接返回,
|
||||
// 等价于引擎自己的「不碰撞」分支 → 坦克之间没有接触点、没有推力,也不会互相卡住。
|
||||
//
|
||||
// 这样做的收益:
|
||||
// · mask / category 一个字节都不改 → 地形、拾取物触发、地雷、子弹全部保持原样
|
||||
// · 关闭开关不需要还原任何状态(wrapper 直接转发原函数)
|
||||
// · 只影响坦克↔坦克这一种配对,不波及静态物体与触发体
|
||||
// 原理(module_55088 碰撞世界 ki):
|
||||
// q9q(a, b) 是全物理世界唯一的「接触配对过滤」:
|
||||
// if (0 === (a.y9j_1 & b.z9j_1) || 0 === (b.y9j_1 & a.y9j_1)) return; // 不生成接触
|
||||
// 我们包装它,在满足条件时直接返回(等价引擎自己的「不碰撞」分支):
|
||||
// · 坦克↔坦克:一边是本车、另一边是目标阵营的坦克 → 跳过
|
||||
// · 本车↔静态三角形:三角形法线接近水平(墙/栅栏/悬崖立面)→ 跳过;法线朝上(地面/缓坡)→ 保留
|
||||
//
|
||||
// 关键点:**不改 mask/category**,所以拾取物触发、地雷、子弹、地形判定都不受影响。
|
||||
// 形状 → 刚体 → 拥有者:
|
||||
// Shape.b9k_1 = 刚体(Fn,u9j 里 `t.b9k_1 = this`)
|
||||
// Body.x9i_1 = 拥有者(坦克物理组件 ejt 在 y15j 里 `pbk().x9i_1 = this`)
|
||||
// Shape.b9k_1 = 刚体(Fn);Body.x9i_1 = 拥有者(坦克物理组件 ejt)
|
||||
// 静态三角形(类型 8):顶点 u9x_1 / v9x_1 / w9x_1;本引擎 x,y 为水平面,**z 是高度**。
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var Lib = window.__hornetLib__;
|
||||
if (!Lib) {
|
||||
console.error('[穿坦克] 请先加载 hornet_lib.js');
|
||||
console.error('[忽略] 请先加载 hornet_lib.js');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6564,25 +6561,37 @@
|
||||
return Fallback;
|
||||
}
|
||||
|
||||
var FPhysicsHull = Fld('Physics.Hull', 'zzq_1'); // 车体主碰撞形状
|
||||
var FShapeName = Fld('Shape.Name', 'x9j_1'); // 形状名('hull-main')
|
||||
var FShapeBody = Fld('Shape.Body', 'b9k_1'); // 形状 → 刚体
|
||||
var FBodyOwner = Fld('Body.Owner', 'x9i_1'); // 刚体 → 拥有者
|
||||
var MRemoveMask = Mth('Physics.RemoveMask', 'm155'); // 坦克物理组件的识别方法
|
||||
var FPhysicsHull = Fld('Physics.Hull', 'zzq_1'); // 车体主碰撞形状
|
||||
var FShapeName = Fld('Shape.Name', 'x9j_1'); // 形状名('hull-main')
|
||||
var FShapeCategory = Fld('Shape.Category', 'y9j_1'); // category 位组
|
||||
var FShapeType = Fld('Shape.Type', 'v9j_1'); // 形状类型位组(8 = 三角形)
|
||||
var FShapeBody = Fld('Shape.Body', 'b9k_1'); // 形状 → 刚体
|
||||
var FBodyOwner = Fld('Body.Owner', 'x9i_1'); // 刚体 → 拥有者
|
||||
var FV0 = Fld('Shape.Vertex0', 'u9x_1'); // 三角形顶点 0
|
||||
var FV1 = Fld('Shape.Vertex1', 'v9x_1'); // 三角形顶点 1
|
||||
var FV2 = Fld('Shape.Vertex2', 'w9x_1'); // 三角形顶点 2
|
||||
var MRemoveMask = Mth('Physics.RemoveMask', 'm155'); // 坦克物理组件识别方法
|
||||
var MCollide = Mth('CollisionWorld.ShouldCollide', 'q9q');
|
||||
var WorldKeys = ExportKeys('Export.PhysicsWorld', ['h']);
|
||||
var PHYSICS_MODULE = 55088; // 碰撞世界所在模块
|
||||
var PHYSICS_MODULE = 55088;
|
||||
|
||||
var STATIC_CATEGORY_BIT = 16; // 地图静态几何 category 位(s6() 造地形:y9j_1 = 16)
|
||||
var TRIANGLE_TYPE = 8; // yi 子类 wu(三角形)的 v9j_1
|
||||
var FENCE_NORMAL_Z = 0.5; // |法线 z| 小于它 → 视为墙/栅栏(地面与缓坡保留)
|
||||
|
||||
var Stat = {
|
||||
running: false,
|
||||
skipped: 0, // 累计跳过的坦克↔坦克配对次数
|
||||
mode: 'all', // 'off' | 'enemy' | 'friendly' | 'all'
|
||||
ignoreFence: false,
|
||||
skippedTank: 0,
|
||||
skippedFence: 0,
|
||||
patched: false
|
||||
};
|
||||
|
||||
var WorldProto = null; // 碰撞世界类原型(ki.prototype)
|
||||
var OrigCollide = null; // 原始配对过滤
|
||||
var WorldProto = null;
|
||||
var OrigCollide = null;
|
||||
|
||||
// 拥有者是否是坦克物理组件(ejt):带 m155,且 zzq_1.x9j_1 === 'hull-main'
|
||||
// 拥有者是否是坦克物理组件(ejt)
|
||||
function IsTankOwner(Owner) {
|
||||
if (!Owner || typeof Owner !== 'object') return false;
|
||||
if (typeof Owner[MRemoveMask] !== 'function') return false;
|
||||
@@ -6590,14 +6599,107 @@
|
||||
return !!(Hull && Hull[FShapeName] === 'hull-main');
|
||||
}
|
||||
|
||||
function IsTankShape(Shape) {
|
||||
if (!Shape || typeof Shape !== 'object') return false;
|
||||
function OwnerOf(Shape) {
|
||||
if (!Shape || typeof Shape !== 'object') return null;
|
||||
var Body = Shape[FShapeBody];
|
||||
if (!Body) return false;
|
||||
return IsTankOwner(Body[FBodyOwner]);
|
||||
return Body ? (Body[FBodyOwner] || null) : null;
|
||||
}
|
||||
|
||||
// 取碰撞世界类原型:module 55088 的导出键 → 校验原型上确实有配对过滤方法
|
||||
function IsTankShape(Shape) {
|
||||
return IsTankOwner(OwnerOf(Shape));
|
||||
}
|
||||
|
||||
// 本地坦克物理组件(100ms 节流缓存;重生/换车后最多 100ms 生效)
|
||||
var LocalPhys = null;
|
||||
var LocalPhysAt = 0;
|
||||
function GetLocalPhysics() {
|
||||
var Now = Date.now();
|
||||
if (Now - LocalPhysAt < 100) return LocalPhys;
|
||||
LocalPhysAt = Now;
|
||||
LocalPhys = null;
|
||||
var Gm = window.__gameMode__;
|
||||
if (!Gm) return null;
|
||||
var Tank = null;
|
||||
try { Tank = Gm.u10b_1 || Gm.t10b_1; } catch (e) { Tank = null; }
|
||||
if (!Tank || !Tank.qz1_1 || !Tank.qz1_1.s2a_1) return null;
|
||||
try {
|
||||
Tank.qz1_1.s2a_1.forEach(function (ValueList) {
|
||||
if (LocalPhys) return;
|
||||
var Comp = (ValueList && typeof ValueList.g1 === 'function') ? ValueList.g1(0) : ValueList;
|
||||
if (IsTankOwner(Comp)) LocalPhys = Comp;
|
||||
});
|
||||
} catch (e) {}
|
||||
return LocalPhys;
|
||||
}
|
||||
|
||||
function EntityOf(Owner) {
|
||||
if (!Owner || typeof Owner.lz4 !== 'function') return null;
|
||||
try { return Owner.lz4(); } catch (e) { return null; }
|
||||
}
|
||||
|
||||
// 三角形是否「陡」:法线 z 分量接近 0(墙/栅栏/悬崖立面)
|
||||
function IsSteepTriangle(Shape) {
|
||||
if (!Shape || Shape[FShapeType] !== TRIANGLE_TYPE) return false;
|
||||
var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2];
|
||||
if (!A || !B || !C) return false;
|
||||
if (typeof A.f20_1 !== 'number' || typeof B.f20_1 !== 'number' || typeof C.f20_1 !== 'number') return false;
|
||||
var ABx = B.f20_1 - A.f20_1, ABy = B.g20_1 - A.g20_1, ABz = B.h20_1 - A.h20_1;
|
||||
var ACx = C.f20_1 - A.f20_1, ACy = C.g20_1 - A.g20_1, ACz = C.h20_1 - A.h20_1;
|
||||
var Nx = ABy * ACz - ABz * ACy;
|
||||
var Ny = ABz * ACx - ABx * ACz;
|
||||
var Nz = ABx * ACy - ABy * ACx;
|
||||
var Len = Math.sqrt(Nx * Nx + Ny * Ny + Nz * Nz);
|
||||
if (!(Len > 1e-6)) return false;
|
||||
return Math.abs(Nz / Len) < FENCE_NORMAL_Z;
|
||||
}
|
||||
|
||||
// 静态几何:category 含 bit4,且不是坦克部件
|
||||
function IsStaticShape(Shape) {
|
||||
if (!Shape || typeof Shape[FShapeCategory] !== 'number') return false;
|
||||
if ((Shape[FShapeCategory] & STATIC_CATEGORY_BIT) === 0) return false;
|
||||
return !IsTankShape(Shape);
|
||||
}
|
||||
|
||||
// ===== 判定:这一对形状要不要跳过 =====
|
||||
function ShouldSkip(ShapeA, ShapeB) {
|
||||
var Local = GetLocalPhysics();
|
||||
var TankA = IsTankShape(ShapeA);
|
||||
var TankB = IsTankShape(ShapeB);
|
||||
|
||||
// ① 忽略坦克(按阵营)
|
||||
if (Stat.mode !== 'off' && TankA && TankB) {
|
||||
var OA = OwnerOf(ShapeA);
|
||||
var OB = OwnerOf(ShapeB);
|
||||
if (Local && (OA === Local || OB === Local)) {
|
||||
var OtherOwner = (OA === Local) ? OB : OA;
|
||||
if (Stat.mode === 'all') {
|
||||
Stat.skippedTank++;
|
||||
return true;
|
||||
}
|
||||
var OtherEntity = EntityOf(OtherOwner);
|
||||
if (OtherEntity) {
|
||||
var Friendly = Lib.IsFriendly(OtherEntity, null, window.__gameMode__);
|
||||
if ((Stat.mode === 'enemy' && !Friendly) || (Stat.mode === 'friendly' && Friendly)) {
|
||||
Stat.skippedTank++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ② 忽略栅栏(只跳过陡峭静态三角形,保留地面/缓坡)
|
||||
if (Stat.ignoreFence && Local) {
|
||||
if ((TankA && OwnerOf(ShapeA) === Local && IsStaticShape(ShapeB) && IsSteepTriangle(ShapeB)) ||
|
||||
(TankB && OwnerOf(ShapeB) === Local && IsStaticShape(ShapeA) && IsSteepTriangle(ShapeA))) {
|
||||
Stat.skippedFence++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===== 安装/卸载配对过滤 =====
|
||||
function GetWorldProto() {
|
||||
if (WorldProto) return WorldProto;
|
||||
var Req = window.__wp_require__;
|
||||
@@ -6620,25 +6722,24 @@
|
||||
if (Stat.patched) return true;
|
||||
var Proto = GetWorldProto();
|
||||
if (!Proto) {
|
||||
console.warn('[穿坦克] 未找到碰撞世界(module ' + PHYSICS_MODULE + ' 导出键可能已变),本功能无效');
|
||||
console.warn('[忽略] 未找到碰撞世界(module ' + PHYSICS_MODULE + ' 导出键可能已变),本功能无效');
|
||||
return false;
|
||||
}
|
||||
OrigCollide = Proto[MCollide];
|
||||
var Wrapper = function (ShapeA, ShapeB) {
|
||||
// 开关打开且两边都是坦克 → 直接当作"不碰撞"返回(不生成接触点)
|
||||
if (Stat.running && IsTankShape(ShapeA) && IsTankShape(ShapeB)) {
|
||||
Stat.skipped++;
|
||||
return undefined;
|
||||
Proto[MCollide] = function (ShapeA, ShapeB) {
|
||||
if (Stat.running) {
|
||||
try {
|
||||
if (ShouldSkip(ShapeA, ShapeB)) return undefined; // 等价引擎的「不碰撞」分支:不生成接触
|
||||
} catch (e) {}
|
||||
}
|
||||
return OrigCollide.apply(this, arguments);
|
||||
};
|
||||
Proto[MCollide] = Wrapper;
|
||||
Stat.patched = true;
|
||||
console.log('[穿坦克] 已接管碰撞配对过滤(只拦坦克↔坦克,拾取物/地形/子弹不受影响)');
|
||||
console.log('[忽略] 已接管碰撞配对过滤(坦克按阵营 / 陡峭静态三角形)');
|
||||
return true;
|
||||
}
|
||||
|
||||
// 碰撞世界可能还没加载(在车库里提前开开关):每 0.5s 重试一次,加载后自动接管
|
||||
// 碰撞世界可能还没加载(车库里提前开):每 0.5s 重试
|
||||
var RetryTimer = null;
|
||||
function ScheduleRetry() {
|
||||
if (RetryTimer) return;
|
||||
@@ -6647,36 +6748,58 @@
|
||||
if (InstallPatch()) { clearInterval(RetryTimer); RetryTimer = null; }
|
||||
}, 500);
|
||||
}
|
||||
function CancelRetry() {
|
||||
if (RetryTimer) { clearInterval(RetryTimer); RetryTimer = null; }
|
||||
}
|
||||
|
||||
function _start() {
|
||||
if (Stat.running) return;
|
||||
Stat.running = true;
|
||||
Stat.skipped = 0;
|
||||
if (!InstallPatch()) {
|
||||
console.warn('[穿坦克] 碰撞世界尚未加载,进入等待(加载后自动接管)');
|
||||
ScheduleRetry();
|
||||
function Apply() {
|
||||
var NeedRun = Stat.mode !== 'off' || Stat.ignoreFence;
|
||||
if (NeedRun && !Stat.running) {
|
||||
Stat.running = true;
|
||||
if (!InstallPatch()) {
|
||||
console.warn('[忽略] 碰撞世界尚未加载,进入等待(加载后自动接管)');
|
||||
ScheduleRetry();
|
||||
}
|
||||
} else if (!NeedRun && Stat.running) {
|
||||
Stat.running = false;
|
||||
if (RetryTimer) { clearInterval(RetryTimer); RetryTimer = null; }
|
||||
}
|
||||
console.log('[穿坦克] 已启动');
|
||||
}
|
||||
|
||||
function _stop() {
|
||||
if (!Stat.running) return;
|
||||
Stat.running = false;
|
||||
CancelRetry();
|
||||
console.log('[穿坦克] 已停止(碰撞恢复,无需还原任何状态)');
|
||||
// ===== 对外接口 =====
|
||||
function SetTankMode(Mode) {
|
||||
if (['off', 'enemy', 'friendly', 'all'].indexOf(Mode) < 0) Mode = 'off';
|
||||
Stat.mode = Mode;
|
||||
Apply();
|
||||
try { localStorage.setItem('hornet_ignore_tanks', Mode); } catch (e) {}
|
||||
console.log('[忽略] 忽略坦克 = ' + Mode);
|
||||
}
|
||||
function GetTankMode() { return Stat.mode; }
|
||||
|
||||
function SetIgnoreFence(On) {
|
||||
Stat.ignoreFence = !!On;
|
||||
Apply();
|
||||
try { localStorage.setItem('hornet_ignore_fence', On ? '1' : '0'); } catch (e) {}
|
||||
console.log('[忽略] 忽略栅栏 = ' + (On ? '开' : '关'));
|
||||
}
|
||||
function GetIgnoreFence() { return Stat.ignoreFence; }
|
||||
|
||||
// 兼容旧接口(面板旧版/热键可能还在调用)
|
||||
function _start() { SetTankMode(Stat.mode === 'off' ? 'all' : Stat.mode); }
|
||||
function _stop() { Stat.mode = 'off'; Stat.ignoreFence = false; Apply(); }
|
||||
|
||||
var Tool = {
|
||||
Start: function () { _start(); },
|
||||
Stop: function () { _stop(); },
|
||||
Start: _start,
|
||||
Stop: _stop,
|
||||
GetRunning: function () { return Stat.running; },
|
||||
Status: function () {
|
||||
if (!Stat.running) return '已停止';
|
||||
return Stat.patched ? ('拦截 ' + Stat.skipped + ' 对') : '等待碰撞世界';
|
||||
}
|
||||
var Parts = [];
|
||||
if (Stat.mode !== 'off') Parts.push('坦克:' + Stat.mode);
|
||||
if (Stat.ignoreFence) Parts.push('栅栏');
|
||||
return Parts.length ? Parts.join(' + ') : '已停止';
|
||||
},
|
||||
SetTankMode: SetTankMode,
|
||||
GetTankMode: GetTankMode,
|
||||
SetIgnoreFence: SetIgnoreFence,
|
||||
GetIgnoreFence: GetIgnoreFence
|
||||
};
|
||||
|
||||
window.__hornetTools__ = window.__hornetTools__ || {};
|
||||
@@ -6684,12 +6807,16 @@
|
||||
window.__hornetNoClip__ = {
|
||||
IsTankOwner: IsTankOwner,
|
||||
IsTankShape: IsTankShape,
|
||||
IsSteepTriangle: IsSteepTriangle,
|
||||
GetStat: function () {
|
||||
return { running: Stat.running, skipped: Stat.skipped, patched: Stat.patched };
|
||||
return {
|
||||
running: Stat.running, mode: Stat.mode, ignoreFence: Stat.ignoreFence,
|
||||
skippedTank: Stat.skippedTank, skippedFence: Stat.skippedFence, patched: Stat.patched
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
console.log('[3DTank] 穿坦克模块已加载(配对过滤模式)');
|
||||
console.log('[3DTank] 忽略模块已加载(忽略坦克 / 忽略栅栏)');
|
||||
})();
|
||||
|
||||
|
||||
@@ -6995,16 +7122,15 @@
|
||||
{ key: 'AimWarning', label: '瞄准警告', obj: tools.AimWarning },
|
||||
{ key: 'FreeLook', label: '自由视角', obj: tools.FreeLook },
|
||||
{ key: 'WarSandbox', label: '战争沙盘', obj: tools.WarSandbox },
|
||||
{ key: 'Mouse', label: '鼠标稳定', obj: tools.Mouse },
|
||||
{ key: 'NoClip', label: '穿坦克', obj: tools.NoClip },
|
||||
{ key: 'NoKnockback', label: '拒绝击退', obj: tools.NoKnockback }
|
||||
{ key: 'Mouse', label: '鼠标稳定', obj: tools.Mouse }
|
||||
];
|
||||
}
|
||||
|
||||
// ===== 工具启用状态(持久化 + 默认启用)=====
|
||||
// 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀
|
||||
var ToolKeys = ['Radar', 'Wireframe', 'Rearview', 'AimWarning', 'FreeLook', 'WarSandbox', 'Mouse', 'NoClip', 'NoKnockback'];
|
||||
var ToolDefaults = { Radar: true, Wireframe: true, Rearview: true, AimWarning: true, FreeLook: false, WarSandbox: true, Mouse: true, NoClip: false, NoKnockback: false };
|
||||
// 忽略模块(NoClip / NoKnockback)不在这里:由「忽略」区域单独管理,自带 localStorage 持久化
|
||||
var ToolKeys = ['Radar', 'Wireframe', 'Rearview', 'AimWarning', 'FreeLook', 'WarSandbox', 'Mouse'];
|
||||
var ToolDefaults = { Radar: true, Wireframe: true, Rearview: true, AimWarning: true, FreeLook: false, WarSandbox: true, Mouse: true };
|
||||
var ToolEnabled = {};
|
||||
try {
|
||||
var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}');
|
||||
@@ -7418,6 +7544,64 @@
|
||||
} catch (e) {}
|
||||
})();
|
||||
|
||||
// ===== 忽略(坦克 / 反弹 / 栅栏)=====
|
||||
// 忽略坦克:关闭 / 仅敌方 / 仅友方 / 全部(由 hornet_noclip.js 的配对过滤实现)
|
||||
// 忽略反弹:对应 hornet_noknockback.js(中弹不再被推开)
|
||||
// 忽略栅栏:只忽略陡峭的静态三角形(墙/栅栏立面),地面与缓坡照常
|
||||
var igSec = MakeSettingsSection('忽略');
|
||||
|
||||
var igTankRow = igSec.row('忽略坦克');
|
||||
var igTankSel = document.createElement('select');
|
||||
igTankSel.style.cssText =
|
||||
'padding:3px 6px;border:1px solid rgba(125,249,255,0.25);border-radius:4px;' +
|
||||
'background:rgba(20,30,40,0.6);color:#e8eef5;font:11px Consolas;cursor:pointer;';
|
||||
[
|
||||
{ v: 'off', t: '关闭' },
|
||||
{ v: 'enemy', t: '仅敌方' },
|
||||
{ v: 'friendly', t: '仅友方' },
|
||||
{ v: 'all', t: '全部' }
|
||||
].forEach(function (o) {
|
||||
var opt = document.createElement('option');
|
||||
opt.value = o.v; opt.textContent = o.t;
|
||||
igTankSel.appendChild(opt);
|
||||
});
|
||||
igTankRow.ctrl.appendChild(igTankSel);
|
||||
igTankSel.onchange = function () {
|
||||
var tools = window.__hornetTools__ || {};
|
||||
if (tools.NoClip) tools.NoClip.SetTankMode(igTankSel.value);
|
||||
};
|
||||
|
||||
var igKnockCtl = igSec.checkbox('忽略反弹', function (on) {
|
||||
var tools = window.__hornetTools__ || {};
|
||||
if (tools.NoKnockback) { on ? tools.NoKnockback.Start() : tools.NoKnockback.Stop(); }
|
||||
try { localStorage.setItem('hornet_ignore_knockback', on ? '1' : '0'); } catch (e) {}
|
||||
});
|
||||
|
||||
var igFenceCtl = igSec.checkbox('忽略栅栏', function (on) {
|
||||
var tools = window.__hornetTools__ || {};
|
||||
if (tools.NoClip) tools.NoClip.SetIgnoreFence(on);
|
||||
});
|
||||
|
||||
// 启动时按上次保存的状态恢复
|
||||
(function () {
|
||||
var tools = window.__hornetTools__ || {};
|
||||
var Mode = 'off';
|
||||
try { Mode = localStorage.getItem('hornet_ignore_tanks') || 'off'; } catch (e) {}
|
||||
if (['off', 'enemy', 'friendly', 'all'].indexOf(Mode) < 0) Mode = 'off';
|
||||
igTankSel.value = Mode;
|
||||
if (tools.NoClip) tools.NoClip.SetTankMode(Mode);
|
||||
|
||||
var Fence = false;
|
||||
try { Fence = localStorage.getItem('hornet_ignore_fence') === '1'; } catch (e) {}
|
||||
igFenceCtl.set(Fence);
|
||||
if (tools.NoClip) tools.NoClip.SetIgnoreFence(Fence);
|
||||
|
||||
var Knock = false;
|
||||
try { Knock = localStorage.getItem('hornet_ignore_knockback') === '1'; } catch (e) {}
|
||||
igKnockCtl.set(Knock);
|
||||
if (tools.NoKnockback && Knock) tools.NoKnockback.Start();
|
||||
})();
|
||||
|
||||
// 从工具读取当前设置(打开面板时同步)
|
||||
function SyncWfSettings() {
|
||||
var tools = window.__hornetTools__ || {};
|
||||
@@ -7445,6 +7629,11 @@
|
||||
wsGridCtl.set(tools.WarSandbox.GetShowGrid());
|
||||
wsMarkerCtl.set(tools.WarSandbox.GetMarkerSize());
|
||||
}
|
||||
if (tools.NoClip) {
|
||||
igTankSel.value = tools.NoClip.GetTankMode();
|
||||
igFenceCtl.set(tools.NoClip.GetIgnoreFence());
|
||||
}
|
||||
if (tools.NoKnockback) igKnockCtl.set(tools.NoKnockback.GetRunning());
|
||||
}
|
||||
|
||||
// 底部状态
|
||||
|
||||
Reference in new issue
Block a user