diff --git a/3dtank.com/play/static/js/unpacked/hornet_bundle.js b/3dtank.com/play/static/js/unpacked/hornet_bundle.js index 2442f2c..2408d72 100644 --- a/3dtank.com/play/static/js/unpacked/hornet_bundle.js +++ b/3dtank.com/play/static/js/unpacked/hornet_bundle.js @@ -280,6 +280,12 @@ 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 '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)---- 'Health.Max': 'p12o_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 ===== // ===== 3DTank 控制面板 ===== // 功能:Alt+T 切换面板显示,控制各工具开关 @@ -6501,14 +6657,15 @@ { 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: 'NoClip', label: '穿坦克', obj: tools.NoClip }, + { key: 'NoKnockback', label: '拒绝击退', obj: tools.NoKnockback } ]; } // ===== 工具启用状态(持久化 + 默认启用)===== // 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀 - var ToolKeys = ['Radar', 'Wireframe', 'Rearview', 'AimWarning', 'FreeLook', 'WarSandbox', 'Mouse', 'NoClip']; - var ToolDefaults = { Radar: true, Wireframe: true, Rearview: true, AimWarning: true, FreeLook: false, WarSandbox: true, Mouse: true, NoClip: false }; + 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 }; var ToolEnabled = {}; try { var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}'); diff --git a/3dtank_bundle.js b/3dtank_bundle.js index 2442f2c..2408d72 100644 --- a/3dtank_bundle.js +++ b/3dtank_bundle.js @@ -280,6 +280,12 @@ 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 '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)---- 'Health.Max': 'p12o_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 ===== // ===== 3DTank 控制面板 ===== // 功能:Alt+T 切换面板显示,控制各工具开关 @@ -6501,14 +6657,15 @@ { 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: 'NoClip', label: '穿坦克', obj: tools.NoClip }, + { key: 'NoKnockback', label: '拒绝击退', obj: tools.NoKnockback } ]; } // ===== 工具启用状态(持久化 + 默认启用)===== // 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀 - var ToolKeys = ['Radar', 'Wireframe', 'Rearview', 'AimWarning', 'FreeLook', 'WarSandbox', 'Mouse', 'NoClip']; - var ToolDefaults = { Radar: true, Wireframe: true, Rearview: true, AimWarning: true, FreeLook: false, WarSandbox: true, Mouse: true, NoClip: false }; + 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 }; var ToolEnabled = {}; try { var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}'); diff --git a/build_bundle.py b/build_bundle.py index b17a468..4d836ea 100644 --- a/build_bundle.py +++ b/build_bundle.py @@ -26,8 +26,9 @@ FILES = [ "hornet_warsandbox.js", # 9. 战争沙盘模块 -> __hornetTools__.WarSandbox "hornet_mouse.js", # 10. 鼠标输入稳定器 -> __hornetTools__.Mouse "hornet_noclip.js", # 11. 穿坦克(忽略玩家碰撞)-> __hornetTools__.NoClip - "hornet_panel.js", # 12. 控制面板(Alt+T + HUD) - "hornet_prefetch.js", # 13. 车库资源预热(战局空闲时后台加载车库所需资源) + "hornet_noknockback.js", # 12. 拒绝击退(中弹不再被推开)-> __hornetTools__.NoKnockback + "hornet_panel.js", # 13. 控制面板(Alt+T + HUD) + "hornet_prefetch.js", # 14. 车库资源预热(战局空闲时后台加载车库所需资源) ] HEADER = """// ============================================================ diff --git a/tools/hornet_noknockback.js b/tools/hornet_noknockback.js new file mode 100644 index 0000000..743b31a --- /dev/null +++ b/tools/hornet_noknockback.js @@ -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] 拒绝击退模块已加载'); +})(); diff --git a/tools/hornet_panel.js b/tools/hornet_panel.js index 14743b3..101fed4 100644 --- a/tools/hornet_panel.js +++ b/tools/hornet_panel.js @@ -150,14 +150,15 @@ { 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: 'NoClip', label: '穿坦克', obj: tools.NoClip }, + { key: 'NoKnockback', label: '拒绝击退', obj: tools.NoKnockback } ]; } // ===== 工具启用状态(持久化 + 默认启用)===== // 默认除「自由视角」外全部开启:自由视角会直接接管相机,默认开启过于突兀 - var ToolKeys = ['Radar', 'Wireframe', 'Rearview', 'AimWarning', 'FreeLook', 'WarSandbox', 'Mouse', 'NoClip']; - var ToolDefaults = { Radar: true, Wireframe: true, Rearview: true, AimWarning: true, FreeLook: false, WarSandbox: true, Mouse: true, NoClip: false }; + 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 }; var ToolEnabled = {}; try { var __savedEnabled = JSON.parse(localStorage.getItem('hornet_tool_enabled') || '{}'); diff --git a/tools/hornet_schema.js b/tools/hornet_schema.js index 2fc7be2..0c930b5 100644 --- a/tools/hornet_schema.js +++ b/tools/hornet_schema.js @@ -65,6 +65,12 @@ 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 '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)---- 'Health.Max': 'p12o_1', 'Health.Current': 'q12o_1',