feat(noknockback): 新增拒绝击退开关,中弹不再被推开

在本地坦克实体的 kz7 事件派发处丢弃外力事件(ODt:作用点/方向/强度),坦克物理收不到就不产生位移与旋转;悬挂与行驶仍走 m9k 直调,不受影响。面板新增「拒绝击退」开关。字段名走 hornet_schema。
This commit is contained in:
TermiNexus committed 2026-10-20 20:35:19 +08:00
1 parent 692b812e58
commit bea22bb5f9
6 files changed
+480 -11

No files matched your search

@@ -280,6 +280,12 @@
'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位
'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应 'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应
// ---- 实体事件总线 / 外力事件(ODt)----
'Entity.Dispatch': 'kz7()', // 向实体内所有订阅者派发事件
'Event.PushPoint': 'o13i_1', // 外力事件:作用点(O$ 向量)
'Event.PushDir': 'p13i_1', // 外力事件:方向(O$ 向量)
'Event.PushStrength': 'q13i_1', // 外力事件:强度(坦克物理交给 m9k)
// ---- 血量组件(Vkt)---- // ---- 血量组件(Vkt)----
'Health.Max': 'p12o_1', 'Health.Max': 'p12o_1',
'Health.Current': 'q12o_1', 'Health.Current': 'q12o_1',
@@ -6348,6 +6354,156 @@
})(); })();
// ===== hornet_noknockback.js =====
// hornet_noknockback.js — 拒绝击退(中弹不再被推着走)
// 放在控制面板「拒绝击退」开关里,只作用于**本地坦克**。
//
// 引擎里「被打中弹开」的完整链路(module_87072 / module_55088):
// 碰撞/武器命中 → 目标坦克实体派发 ODt 事件(外力事件):
// ODt.o13i_1 = 作用点,ODt.p13i_1 = 方向,ODt.q13i_1 = 强度
// → 坦克物理组件 ejt 在 oz4() 里订阅它(callableName = "applyForce"):
// t.pbk().m9k(点, 方向, 强度) // m9k = 在点处施加力,直接进速度/角速度
// → 车体被推开 / 被弹得转圈
//
// 为什么在「事件派发」这一层拦:
// m9k 同时被悬挂/弹簧(Gbt.s151)和自身开炮后座使用,直接封 m9k 会把悬挂也废掉;
// 而 ODt 只承载外力(炮弹/地雷/撞击),拦掉它 → 只失去被推动,悬挂与驾驶完全不受影响。
//
// 拦法:给本地坦克实体实例的 kz7(事件派发方法)套一层,遇到外力事件直接丢弃。
// 只影响本客户端本地坦克;自己的开炮后座走的是直接 m9k 调用,不受影响。
(function () {
'use strict';
var Lib = window.__hornetLib__;
if (!Lib) {
console.error('[拒绝击退] 请先加载 hornet_lib.js');
return;
}
// ===== 字段抽象层(语义名 → 匿名字段,总表在 hornet_schema.js)=====
var Schema = window.__hornetSchema__ || null;
function Fld(Key, Fallback) {
var N = Schema ? Schema.FieldName(Key) : null;
return N || Fallback;
}
function Mth(Key, Fallback) {
var N = Schema ? Schema.MethodName(Key) : null;
return N || Fallback;
}
var FPushPoint = Fld('Event.PushPoint', 'o13i_1'); // 外力作用点
var FPushDir = Fld('Event.PushDir', 'p13i_1'); // 外力方向
var FPushStrength = Fld('Event.PushStrength', 'q13i_1'); // 外力强度
var MDispatch = Mth('Entity.Dispatch', 'kz7'); // 实体事件派发
var Stat = {
running: false,
blocked: 0, // 累计拦下的外力事件数
tankId: -1
};
var PatchedTank = null; // 当前已接管的坦克实体
var OrigDispatch = null; // 该实体原来的派发方法
// 外力事件识别(ODt):作用点 + 方向 + 强度 + r13i 写入方法
// ⚠ 不能用 instanceof:ODt 类没有对外导出,且每版类对象都会重建
function IsPushEvent(Event) {
if (!Event || typeof Event !== 'object') return false;
if (typeof Event[FPushStrength] !== 'number') return false;
var Point = Event[FPushPoint];
var Dir = Event[FPushDir];
if (!Point || !Dir) return false;
if (typeof Point.f20_1 !== 'number' || typeof Dir.f20_1 !== 'number') return false;
return true;
}
// 本地坦克:拥有中的优先;死亡时退回观察目标(此时不参与战斗,影响可忽略)
function GetLocalTank() {
var Gm = window.__gameMode__;
if (!Gm) return null;
try { if (Gm.u10b_1) return Gm.u10b_1; } catch (e) {}
try { if (Gm.t10b_1) return Gm.t10b_1; } catch (e) {}
return null;
}
function Unpatch() {
if (PatchedTank && OrigDispatch) {
try { PatchedTank[MDispatch] = OrigDispatch; } catch (e) {}
}
PatchedTank = null;
OrigDispatch = null;
Stat.tankId = -1;
}
function Patch(Tank) {
if (!Tank) return;
if (PatchedTank === Tank) return;
Unpatch();
var Orig = Tank[MDispatch];
if (typeof Orig !== 'function') return;
OrigDispatch = Orig;
Tank[MDispatch] = function (Event) {
// 外力事件:直接吞掉(坦克物理收不到 → 不产生位移/旋转)
if (Stat.running && IsPushEvent(Event)) {
Stat.blocked++;
return undefined;
}
return OrigDispatch.apply(this, arguments);
};
PatchedTank = Tank;
Stat.tankId = (Tank.iz1_1 !== undefined) ? Tank.iz1_1 : -1;
console.log('[拒绝击退] 已接管本地坦克事件派发 id=' + Stat.tankId);
}
function Loop() {
if (!Stat.running) return;
requestAnimationFrame(Loop);
try {
var Tank = GetLocalTank();
if (Tank && Tank !== PatchedTank) Patch(Tank); // 换车/重生:实体换了要重新套
if (!Tank && PatchedTank) Unpatch(); // 离开战局:还原
} catch (e) {}
}
function _start() {
if (Stat.running) return;
Stat.running = true;
Stat.blocked = 0;
Patch(GetLocalTank());
requestAnimationFrame(Loop);
console.log('[拒绝击退] 已启动(中弹/撞击不再推动本地坦克;悬挂、行驶、自身后座不受影响)');
}
function _stop() {
if (!Stat.running) return;
Stat.running = false;
Unpatch();
console.log('[拒绝击退] 已停止,事件派发已还原');
}
var Tool = {
Start: function () { _start(); },
Stop: function () { _stop(); },
GetRunning: function () { return Stat.running; },
Status: function () {
if (!Stat.running) return '已停止';
return PatchedTank ? ('拦截 ' + Stat.blocked + ' 次') : '等待坦克';
}
};
window.__hornetTools__ = window.__hornetTools__ || {};
window.__hornetTools__.NoKnockback = Tool;
window.__hornetNoKnockback__ = {
IsPushEvent: IsPushEvent,
GetStat: function () {
return { running: Stat.running, blocked: Stat.blocked, tankId: Stat.tankId };
}
};
console.log('[3DTank] 拒绝击退模块已加载');
})();
// ===== hornet_panel.js ===== // ===== hornet_panel.js =====
// ===== 3DTank 控制面板 ===== // ===== 3DTank 控制面板 =====
// 功能:Alt+T 切换面板显示,控制各工具开关 // 功能:Alt+T 切换面板显示,控制各工具开关
@@ -6501,14 +6657,15 @@
{ key: 'FreeLook', label: '自由视角', obj: tools.FreeLook }, { key: 'FreeLook', label: '自由视角', obj: tools.FreeLook },
{ key: 'WarSandbox', label: '战争沙盘', obj: tools.WarSandbox }, { key: 'WarSandbox', label: '战争沙盘', obj: tools.WarSandbox },
{ key: 'Mouse', label: '鼠标稳定', obj: tools.Mouse }, { key: 'Mouse', label: '鼠标稳定', obj: tools.Mouse },
{ key: 'NoClip', label: '穿坦克', obj: tools.NoClip } { key: 'NoClip', label: '穿坦克', obj: tools.NoClip },
{ key: 'NoKnockback', label: '拒绝击退', obj: tools.NoKnockback }
]; ];
} }
// ===== 工具启用状态(持久化 + 默认启用)===== // ===== 工具启用状态(持久化 + 默认启用)=====
// 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀 // 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀
var ToolKeys = ['Radar', 'Wireframe', 'Rearview', 'AimWarning', 'FreeLook', 'WarSandbox', 'Mouse', 'NoClip']; 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 }; var ToolDefaults = { Radar: true, Wireframe: true, Rearview: true, AimWarning: true, FreeLook: false, WarSandbox: true, Mouse: true, NoClip: false, NoKnockback: false };
var ToolEnabled = {}; var ToolEnabled = {};
try { try {
var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}'); var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}');
+160 -3
View File
@@ -280,6 +280,12 @@
'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位
'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应 'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应
// ---- 实体事件总线 / 外力事件(ODt)----
'Entity.Dispatch': 'kz7()', // 向实体内所有订阅者派发事件
'Event.PushPoint': 'o13i_1', // 外力事件:作用点(O$ 向量)
'Event.PushDir': 'p13i_1', // 外力事件:方向(O$ 向量)
'Event.PushStrength': 'q13i_1', // 外力事件:强度(坦克物理交给 m9k)
// ---- 血量组件(Vkt)---- // ---- 血量组件(Vkt)----
'Health.Max': 'p12o_1', 'Health.Max': 'p12o_1',
'Health.Current': 'q12o_1', 'Health.Current': 'q12o_1',
@@ -6348,6 +6354,156 @@
})(); })();
// ===== hornet_noknockback.js =====
// hornet_noknockback.js — 拒绝击退(中弹不再被推着走)
// 放在控制面板「拒绝击退」开关里,只作用于**本地坦克**。
//
// 引擎里「被打中弹开」的完整链路(module_87072 / module_55088):
// 碰撞/武器命中 → 目标坦克实体派发 ODt 事件(外力事件):
// ODt.o13i_1 = 作用点,ODt.p13i_1 = 方向,ODt.q13i_1 = 强度
// → 坦克物理组件 ejt 在 oz4() 里订阅它(callableName = "applyForce"):
// t.pbk().m9k(点, 方向, 强度) // m9k = 在点处施加力,直接进速度/角速度
// → 车体被推开 / 被弹得转圈
//
// 为什么在「事件派发」这一层拦:
// m9k 同时被悬挂/弹簧(Gbt.s151)和自身开炮后座使用,直接封 m9k 会把悬挂也废掉;
// 而 ODt 只承载外力(炮弹/地雷/撞击),拦掉它 → 只失去被推动,悬挂与驾驶完全不受影响。
//
// 拦法:给本地坦克实体实例的 kz7(事件派发方法)套一层,遇到外力事件直接丢弃。
// 只影响本客户端本地坦克;自己的开炮后座走的是直接 m9k 调用,不受影响。
(function () {
'use strict';
var Lib = window.__hornetLib__;
if (!Lib) {
console.error('[拒绝击退] 请先加载 hornet_lib.js');
return;
}
// ===== 字段抽象层(语义名 → 匿名字段,总表在 hornet_schema.js)=====
var Schema = window.__hornetSchema__ || null;
function Fld(Key, Fallback) {
var N = Schema ? Schema.FieldName(Key) : null;
return N || Fallback;
}
function Mth(Key, Fallback) {
var N = Schema ? Schema.MethodName(Key) : null;
return N || Fallback;
}
var FPushPoint = Fld('Event.PushPoint', 'o13i_1'); // 外力作用点
var FPushDir = Fld('Event.PushDir', 'p13i_1'); // 外力方向
var FPushStrength = Fld('Event.PushStrength', 'q13i_1'); // 外力强度
var MDispatch = Mth('Entity.Dispatch', 'kz7'); // 实体事件派发
var Stat = {
running: false,
blocked: 0, // 累计拦下的外力事件数
tankId: -1
};
var PatchedTank = null; // 当前已接管的坦克实体
var OrigDispatch = null; // 该实体原来的派发方法
// 外力事件识别(ODt):作用点 + 方向 + 强度 + r13i 写入方法
// ⚠ 不能用 instanceof:ODt 类没有对外导出,且每版类对象都会重建
function IsPushEvent(Event) {
if (!Event || typeof Event !== 'object') return false;
if (typeof Event[FPushStrength] !== 'number') return false;
var Point = Event[FPushPoint];
var Dir = Event[FPushDir];
if (!Point || !Dir) return false;
if (typeof Point.f20_1 !== 'number' || typeof Dir.f20_1 !== 'number') return false;
return true;
}
// 本地坦克:拥有中的优先;死亡时退回观察目标(此时不参与战斗,影响可忽略)
function GetLocalTank() {
var Gm = window.__gameMode__;
if (!Gm) return null;
try { if (Gm.u10b_1) return Gm.u10b_1; } catch (e) {}
try { if (Gm.t10b_1) return Gm.t10b_1; } catch (e) {}
return null;
}
function Unpatch() {
if (PatchedTank && OrigDispatch) {
try { PatchedTank[MDispatch] = OrigDispatch; } catch (e) {}
}
PatchedTank = null;
OrigDispatch = null;
Stat.tankId = -1;
}
function Patch(Tank) {
if (!Tank) return;
if (PatchedTank === Tank) return;
Unpatch();
var Orig = Tank[MDispatch];
if (typeof Orig !== 'function') return;
OrigDispatch = Orig;
Tank[MDispatch] = function (Event) {
// 外力事件:直接吞掉(坦克物理收不到 → 不产生位移/旋转)
if (Stat.running && IsPushEvent(Event)) {
Stat.blocked++;
return undefined;
}
return OrigDispatch.apply(this, arguments);
};
PatchedTank = Tank;
Stat.tankId = (Tank.iz1_1 !== undefined) ? Tank.iz1_1 : -1;
console.log('[拒绝击退] 已接管本地坦克事件派发 id=' + Stat.tankId);
}
function Loop() {
if (!Stat.running) return;
requestAnimationFrame(Loop);
try {
var Tank = GetLocalTank();
if (Tank && Tank !== PatchedTank) Patch(Tank); // 换车/重生:实体换了要重新套
if (!Tank && PatchedTank) Unpatch(); // 离开战局:还原
} catch (e) {}
}
function _start() {
if (Stat.running) return;
Stat.running = true;
Stat.blocked = 0;
Patch(GetLocalTank());
requestAnimationFrame(Loop);
console.log('[拒绝击退] 已启动(中弹/撞击不再推动本地坦克;悬挂、行驶、自身后座不受影响)');
}
function _stop() {
if (!Stat.running) return;
Stat.running = false;
Unpatch();
console.log('[拒绝击退] 已停止,事件派发已还原');
}
var Tool = {
Start: function () { _start(); },
Stop: function () { _stop(); },
GetRunning: function () { return Stat.running; },
Status: function () {
if (!Stat.running) return '已停止';
return PatchedTank ? ('拦截 ' + Stat.blocked + ' 次') : '等待坦克';
}
};
window.__hornetTools__ = window.__hornetTools__ || {};
window.__hornetTools__.NoKnockback = Tool;
window.__hornetNoKnockback__ = {
IsPushEvent: IsPushEvent,
GetStat: function () {
return { running: Stat.running, blocked: Stat.blocked, tankId: Stat.tankId };
}
};
console.log('[3DTank] 拒绝击退模块已加载');
})();
// ===== hornet_panel.js ===== // ===== hornet_panel.js =====
// ===== 3DTank 控制面板 ===== // ===== 3DTank 控制面板 =====
// 功能:Alt+T 切换面板显示,控制各工具开关 // 功能:Alt+T 切换面板显示,控制各工具开关
@@ -6501,14 +6657,15 @@
{ key: 'FreeLook', label: '自由视角', obj: tools.FreeLook }, { key: 'FreeLook', label: '自由视角', obj: tools.FreeLook },
{ key: 'WarSandbox', label: '战争沙盘', obj: tools.WarSandbox }, { key: 'WarSandbox', label: '战争沙盘', obj: tools.WarSandbox },
{ key: 'Mouse', label: '鼠标稳定', obj: tools.Mouse }, { key: 'Mouse', label: '鼠标稳定', obj: tools.Mouse },
{ key: 'NoClip', label: '穿坦克', obj: tools.NoClip } { key: 'NoClip', label: '穿坦克', obj: tools.NoClip },
{ key: 'NoKnockback', label: '拒绝击退', obj: tools.NoKnockback }
]; ];
} }
// ===== 工具启用状态(持久化 + 默认启用)===== // ===== 工具启用状态(持久化 + 默认启用)=====
// 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀 // 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀
var ToolKeys = ['Radar', 'Wireframe', 'Rearview', 'AimWarning', 'FreeLook', 'WarSandbox', 'Mouse', 'NoClip']; 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 }; var ToolDefaults = { Radar: true, Wireframe: true, Rearview: true, AimWarning: true, FreeLook: false, WarSandbox: true, Mouse: true, NoClip: false, NoKnockback: false };
var ToolEnabled = {}; var ToolEnabled = {};
try { try {
var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}'); var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}');
+3 -2
View File
@@ -26,8 +26,9 @@ FILES = [
"hornet_warsandbox.js", # 9. 战争沙盘模块 -> __hornetTools__.WarSandbox "hornet_warsandbox.js", # 9. 战争沙盘模块 -> __hornetTools__.WarSandbox
"hornet_mouse.js", # 10. 鼠标输入稳定器 -> __hornetTools__.Mouse "hornet_mouse.js", # 10. 鼠标输入稳定器 -> __hornetTools__.Mouse
"hornet_noclip.js", # 11. 穿坦克(忽略玩家碰撞)-> __hornetTools__.NoClip "hornet_noclip.js", # 11. 穿坦克(忽略玩家碰撞)-> __hornetTools__.NoClip
"hornet_panel.js", # 12. 控制面板(Alt+T + HUD) "hornet_noknockback.js", # 12. 拒绝击退(中弹不再被推开)-> __hornetTools__.NoKnockback
"hornet_prefetch.js", # 13. 车库资源预热(战局空闲时后台加载车库所需资源) "hornet_panel.js", # 13. 控制面板(Alt+T + HUD)
"hornet_prefetch.js", # 14. 车库资源预热(战局空闲时后台加载车库所需资源)
] ]
HEADER = """// ============================================================ HEADER = """// ============================================================
+147
View File
@@ -0,0 +1,147 @@
// hornet_noknockback.js — 拒绝击退(中弹不再被推着走)
// 放在控制面板「拒绝击退」开关里,只作用于**本地坦克**。
//
// 引擎里「被打中弹开」的完整链路(module_87072 / module_55088):
// 碰撞/武器命中 → 目标坦克实体派发 ODt 事件(外力事件):
// ODt.o13i_1 = 作用点,ODt.p13i_1 = 方向,ODt.q13i_1 = 强度
// → 坦克物理组件 ejt 在 oz4() 里订阅它(callableName = "applyForce"):
// t.pbk().m9k(点, 方向, 强度) // m9k = 在点处施加力,直接进速度/角速度
// → 车体被推开 / 被弹得转圈
//
// 为什么在「事件派发」这一层拦:
// m9k 同时被悬挂/弹簧(Gbt.s151)和自身开炮后座使用,直接封 m9k 会把悬挂也废掉;
// 而 ODt 只承载外力(炮弹/地雷/撞击),拦掉它 → 只失去被推动,悬挂与驾驶完全不受影响。
//
// 拦法:给本地坦克实体实例的 kz7(事件派发方法)套一层,遇到外力事件直接丢弃。
// 只影响本客户端本地坦克;自己的开炮后座走的是直接 m9k 调用,不受影响。
(function () {
'use strict';
var Lib = window.__hornetLib__;
if (!Lib) {
console.error('[拒绝击退] 请先加载 hornet_lib.js');
return;
}
// ===== 字段抽象层(语义名 → 匿名字段,总表在 hornet_schema.js)=====
var Schema = window.__hornetSchema__ || null;
function Fld(Key, Fallback) {
var N = Schema ? Schema.FieldName(Key) : null;
return N || Fallback;
}
function Mth(Key, Fallback) {
var N = Schema ? Schema.MethodName(Key) : null;
return N || Fallback;
}
var FPushPoint = Fld('Event.PushPoint', 'o13i_1'); // 外力作用点
var FPushDir = Fld('Event.PushDir', 'p13i_1'); // 外力方向
var FPushStrength = Fld('Event.PushStrength', 'q13i_1'); // 外力强度
var MDispatch = Mth('Entity.Dispatch', 'kz7'); // 实体事件派发
var Stat = {
running: false,
blocked: 0, // 累计拦下的外力事件数
tankId: -1
};
var PatchedTank = null; // 当前已接管的坦克实体
var OrigDispatch = null; // 该实体原来的派发方法
// 外力事件识别(ODt):作用点 + 方向 + 强度 + r13i 写入方法
// ⚠ 不能用 instanceof:ODt 类没有对外导出,且每版类对象都会重建
function IsPushEvent(Event) {
if (!Event || typeof Event !== 'object') return false;
if (typeof Event[FPushStrength] !== 'number') return false;
var Point = Event[FPushPoint];
var Dir = Event[FPushDir];
if (!Point || !Dir) return false;
if (typeof Point.f20_1 !== 'number' || typeof Dir.f20_1 !== 'number') return false;
return true;
}
// 本地坦克:拥有中的优先;死亡时退回观察目标(此时不参与战斗,影响可忽略)
function GetLocalTank() {
var Gm = window.__gameMode__;
if (!Gm) return null;
try { if (Gm.u10b_1) return Gm.u10b_1; } catch (e) {}
try { if (Gm.t10b_1) return Gm.t10b_1; } catch (e) {}
return null;
}
function Unpatch() {
if (PatchedTank && OrigDispatch) {
try { PatchedTank[MDispatch] = OrigDispatch; } catch (e) {}
}
PatchedTank = null;
OrigDispatch = null;
Stat.tankId = -1;
}
function Patch(Tank) {
if (!Tank) return;
if (PatchedTank === Tank) return;
Unpatch();
var Orig = Tank[MDispatch];
if (typeof Orig !== 'function') return;
OrigDispatch = Orig;
Tank[MDispatch] = function (Event) {
// 外力事件:直接吞掉(坦克物理收不到 → 不产生位移/旋转)
if (Stat.running && IsPushEvent(Event)) {
Stat.blocked++;
return undefined;
}
return OrigDispatch.apply(this, arguments);
};
PatchedTank = Tank;
Stat.tankId = (Tank.iz1_1 !== undefined) ? Tank.iz1_1 : -1;
console.log('[拒绝击退] 已接管本地坦克事件派发 id=' + Stat.tankId);
}
function Loop() {
if (!Stat.running) return;
requestAnimationFrame(Loop);
try {
var Tank = GetLocalTank();
if (Tank && Tank !== PatchedTank) Patch(Tank); // 换车/重生:实体换了要重新套
if (!Tank && PatchedTank) Unpatch(); // 离开战局:还原
} catch (e) {}
}
function _start() {
if (Stat.running) return;
Stat.running = true;
Stat.blocked = 0;
Patch(GetLocalTank());
requestAnimationFrame(Loop);
console.log('[拒绝击退] 已启动(中弹/撞击不再推动本地坦克;悬挂、行驶、自身后座不受影响)');
}
function _stop() {
if (!Stat.running) return;
Stat.running = false;
Unpatch();
console.log('[拒绝击退] 已停止,事件派发已还原');
}
var Tool = {
Start: function () { _start(); },
Stop: function () { _stop(); },
GetRunning: function () { return Stat.running; },
Status: function () {
if (!Stat.running) return '已停止';
return PatchedTank ? ('拦截 ' + Stat.blocked + ' 次') : '等待坦克';
}
};
window.__hornetTools__ = window.__hornetTools__ || {};
window.__hornetTools__.NoKnockback = Tool;
window.__hornetNoKnockback__ = {
IsPushEvent: IsPushEvent,
GetStat: function () {
return { running: Stat.running, blocked: Stat.blocked, tankId: Stat.tankId };
}
};
console.log('[3DTank] 拒绝击退模块已加载');
})();
+4 -3
View File
@@ -150,14 +150,15 @@
{ key: 'FreeLook', label: '自由视角', obj: tools.FreeLook }, { key: 'FreeLook', label: '自由视角', obj: tools.FreeLook },
{ key: 'WarSandbox', label: '战争沙盘', obj: tools.WarSandbox }, { key: 'WarSandbox', label: '战争沙盘', obj: tools.WarSandbox },
{ key: 'Mouse', label: '鼠标稳定', obj: tools.Mouse }, { key: 'Mouse', label: '鼠标稳定', obj: tools.Mouse },
{ key: 'NoClip', label: '穿坦克', obj: tools.NoClip } { key: 'NoClip', label: '穿坦克', obj: tools.NoClip },
{ key: 'NoKnockback', label: '拒绝击退', obj: tools.NoKnockback }
]; ];
} }
// ===== 工具启用状态(持久化 + 默认启用)===== // ===== 工具启用状态(持久化 + 默认启用)=====
// 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀 // 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀
var ToolKeys = ['Radar', 'Wireframe', 'Rearview', 'AimWarning', 'FreeLook', 'WarSandbox', 'Mouse', 'NoClip']; 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 }; var ToolDefaults = { Radar: true, Wireframe: true, Rearview: true, AimWarning: true, FreeLook: false, WarSandbox: true, Mouse: true, NoClip: false, NoKnockback: false };
var ToolEnabled = {}; var ToolEnabled = {};
try { try {
var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}'); var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}');
+6
View File
@@ -65,6 +65,12 @@
'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位
'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应 'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应
// ---- 实体事件总线 / 外力事件(ODt)----
'Entity.Dispatch': 'kz7()', // 向实体内所有订阅者派发事件
'Event.PushPoint': 'o13i_1', // 外力事件:作用点(O$ 向量)
'Event.PushDir': 'p13i_1', // 外力事件:方向(O$ 向量)
'Event.PushStrength': 'q13i_1', // 外力事件:强度(坦克物理交给 m9k)
// ---- 血量组件(Vkt)---- // ---- 血量组件(Vkt)----
'Health.Max': 'p12o_1', 'Health.Max': 'p12o_1',
'Health.Current': 'q12o_1', 'Health.Current': 'q12o_1',