在本地坦克实体的 kz7 事件派发处丢弃外力事件(ODt:作用点/方向/强度),坦克物理收不到就不产生位移与旋转;悬挂与行驶仍走 m9k 直调,不受影响。面板新增「拒绝击退」开关。字段名走 hornet_schema。
148 lines
5.4 KiB
JavaScript
148 lines
5.4 KiB
JavaScript
// 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] 拒绝击退模块已加载');
|
||
})();
|