- 双向校验误判:q100_1 / r11l / jyw / t101_1 在新版同名但含义不同(普通数值 / 别的方法),被当作未变而跳过 - 强制替换:q100_1 到 m10b_1(坦克管理)、r11l 到 j11y(坦克列表)、jyw 到 lz4(取实体)、t101_1 到 p10c_1 - 覆盖 hook_gamemode.js(文件名不匹配 hornet_ 被漏掉) - 物理组件字段 gzh_1 改为 rzf_1(新版 gzh_1 已是 TerminatorCC 字段,非物理) - 移除已不存在的 xyu(GameMode),改用 gm.lz4()(等价:取 GameMode 实体) - 重新生成 hornet_bundle.js(10 模块 / 249229 字节)并同步 unpacked
349 lines
12 KiB
JavaScript
349 lines
12 KiB
JavaScript
// ===== 坦克移动控制(j14b_1 控制值修改版) =====
|
||
// 功能:通过修改 Dyt.j14b_1(履带控制状态 Uyt)触发 KC 回调 → ryp(Ds) → kyt 发送网络包
|
||
// 原理:
|
||
// 1. Dyt 构造函数中 KC 回调(z14a_1)注册到 gameScene 每帧更新
|
||
// 2. KC 回调检测 j14b_1.equals(d14n_1) === false 时:
|
||
// a) 复制 j14b_1 → d14n_1(l14a)
|
||
// b) 触发 ryp(Ds)(_yt 事件全局单例)
|
||
// 3. kyt 监听 _yt 事件 → 调用 r14n_1.b14c(time, j14b_1) 发送网络包
|
||
// 4. 这是游戏自然移动路径,网络包格式/时机完全正常,不触发服务器检测
|
||
// 控制:W/S 前进/后退,A/D 左转/右转,松开停止
|
||
// 在浏览器控制台运行(需先运行 hook_gamemode.js + hornet_lib.js)
|
||
// 注册到 __hornetTools__.TankControl
|
||
// 注意:本文件不加入 bundle,独立加载
|
||
|
||
(function() {
|
||
var running = false;
|
||
var keys = {};
|
||
var updateInterval = null;
|
||
var verifyInterval = null;
|
||
var dyt = null;
|
||
var playerTank = null;
|
||
var maxSpeed = 100;
|
||
var maxTurn = 30;
|
||
var lastS140 = 0;
|
||
var lastT140 = 0;
|
||
var kcVerified = false;
|
||
|
||
function _start() {
|
||
console.log('===== 坦克移动控制启动(v14m_1 控制值修改版) =====');
|
||
|
||
if (!window.__gameMode__) {
|
||
console.error('请先运行 hook_gamemode.js');
|
||
return;
|
||
}
|
||
if (window.__hornetTankTest__ && window.__hornetTankTest__.GetRunning && window.__hornetTankTest__.GetRunning()) {
|
||
window.__hornetTankTest__.Stop();
|
||
}
|
||
|
||
var gm = window.__gameMode__;
|
||
var lib = window.__hornetLib__;
|
||
if (!lib) {
|
||
console.error('[测试] 请先运行 hornet_lib.js');
|
||
return;
|
||
}
|
||
var FindComponentByField = lib.FindComponentByField;
|
||
var GetTankPosition = lib.GetTankPosition;
|
||
|
||
// ===== 获取玩家坦克 =====
|
||
function GetPlayerTank() {
|
||
var t = gm.u10b_1;
|
||
if (t) return t;
|
||
t = gm.t10b_1;
|
||
if (t) return t;
|
||
try {
|
||
var tl = gm.m10b_1.j11y();
|
||
if (tl.e1() > 0) return tl.g1(0);
|
||
} catch(e) {}
|
||
return null;
|
||
}
|
||
|
||
playerTank = GetPlayerTank();
|
||
if (!playerTank) {
|
||
console.error('[测试] 未找到玩家坦克');
|
||
return;
|
||
}
|
||
|
||
// ===== 获取 Dyt 组件(履带底盘,有 j14b_1 字段) =====
|
||
dyt = FindComponentByField(playerTank, 'v14m_1');
|
||
if (!dyt) {
|
||
console.error('[测试] 未找到 Dyt 组件(v14m_1 字段)');
|
||
console.error('[测试] 玩家坦克可能不是履带坦克,或移动组件未初始化');
|
||
return;
|
||
}
|
||
|
||
// ===== 诊断信息 =====
|
||
console.log('[诊断] Dyt 组件状态:');
|
||
console.log(' n14m_1 (在战斗中):', dyt.n14m_1);
|
||
try {
|
||
console.log(' v14m_1:', dyt.v14m_1.toString());
|
||
console.log(' d14n_1:', dyt.d14n_1.toString());
|
||
} catch(e) {
|
||
console.log(' v14m_1/d14n_1 toString 失败:', e.message);
|
||
}
|
||
|
||
// 检查 KC(z14a_1)的方法
|
||
if (dyt.l14m_1) {
|
||
console.log(' l14m_1.aye:', typeof dyt.l14m_1.aye);
|
||
console.log(' l14m_1.kak:', typeof dyt.l14m_1.kak);
|
||
console.log(' l14m_1 constructor:', dyt.l14m_1.constructor && dyt.l14m_1.constructor.name);
|
||
} else {
|
||
console.warn(' l14m_1 为 null,KC 回调可能未注册');
|
||
}
|
||
|
||
// ===== 获取 maxSpeed 和 maxTurn =====
|
||
// 尝试从 a14n_1(speedCharacteristics/dgt 组件)获取
|
||
try {
|
||
var sc = dyt.q14y_1;
|
||
if (sc) {
|
||
if (typeof sc.na9 === 'function') {
|
||
maxSpeed = sc.na9();
|
||
console.log(' 从 q14y_1.na9() 获取 maxSpeed:', maxSpeed);
|
||
} else if (sc.f14c_1 !== undefined) {
|
||
maxSpeed = sc.f14c_1;
|
||
console.log(' 从 q14y_1.f14c_1 获取 maxSpeed:', maxSpeed);
|
||
}
|
||
if (sc.j14c_1 !== undefined) {
|
||
maxTurn = sc.j14c_1;
|
||
console.log(' 从 q14y_1.j14c_1 获取 maxTurn:', maxTurn);
|
||
}
|
||
}
|
||
} catch(e) {
|
||
console.warn('[测试] 获取速度参数失败:', e.message);
|
||
}
|
||
|
||
// 尝试从其他组件获取(u14k_1 字段存储 na9() 的值)
|
||
if (maxSpeed === 100) {
|
||
try {
|
||
playerTank.qz1_1.s2a_1.forEach(function(valueList) {
|
||
if (maxSpeed !== 100) return;
|
||
try {
|
||
var comp = valueList && typeof valueList.g1 === 'function' ? valueList.g1(0) : valueList;
|
||
if (comp && comp.p14w_1 !== undefined && typeof comp.p14w_1 === 'number' && comp.p14w_1 > 0) {
|
||
maxSpeed = comp.p14w_1;
|
||
console.log(' 从组件 p14w_1 获取 maxSpeed:', maxSpeed);
|
||
}
|
||
} catch(e) {}
|
||
});
|
||
} catch(e) {}
|
||
}
|
||
|
||
console.log(' 最终 maxSpeed:', maxSpeed);
|
||
console.log(' 最终 maxTurn:', maxTurn);
|
||
|
||
if (!dyt.n14m_1) {
|
||
console.warn('[测试] 玩家不在战斗中(n14m_1=false),KC 回调会直接返回不触发 iyz(Ds)');
|
||
console.warn('[测试] 请确保在战斗中再启动移动控制');
|
||
}
|
||
|
||
// ===== 键盘事件 =====
|
||
keys = {};
|
||
function onKeyDown(e) {
|
||
var k = e.key.toLowerCase();
|
||
if (k === 'w' || k === 'a' || k === 's' || k === 'd') {
|
||
keys[k] = true;
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
}
|
||
}
|
||
function onKeyUp(e) {
|
||
var k = e.key.toLowerCase();
|
||
if (k === 'w' || k === 'a' || k === 's' || k === 'd') {
|
||
keys[k] = false;
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
}
|
||
}
|
||
document.addEventListener('keydown', onKeyDown, true);
|
||
document.addEventListener('keyup', onKeyUp, true);
|
||
|
||
// ===== 主循环:设置 j14b_1 控制值 =====
|
||
running = true;
|
||
lastS140 = dyt.v14m_1.m14b_1;
|
||
lastT140 = dyt.v14m_1.n14b_1;
|
||
|
||
updateInterval = setInterval(function() {
|
||
if (!running || !dyt) return;
|
||
|
||
var forward = (keys['w'] ? 1 : 0) + (keys['s'] ? -1 : 0);
|
||
var turn = (keys['a'] ? 1 : 0) + (keys['d'] ? -1 : 0);
|
||
|
||
var newS140 = forward * maxSpeed;
|
||
var newT140 = turn * maxTurn;
|
||
|
||
// 只在值变化时设置(KC 回调检测 j14b_1 ≠ d14n_1 才触发 ryp(Ds))
|
||
if (newS140 !== lastS140 || newT140 !== lastT140) {
|
||
try {
|
||
dyt.v14m_1.m14b_1 = newS140;
|
||
dyt.v14m_1.n14b_1 = newT140;
|
||
// k14c_1 (reverseBackTurn) 不修改
|
||
lastS140 = newS140;
|
||
lastT140 = newT140;
|
||
console.log('[移动] m14b_1=' + newS140 + ' n14b_1=' + newT140 +
|
||
' (v14m_1 ≠ d14n_1 → KC 回调将触发 iyz(Ds) → kyt 发送网络包)');
|
||
} catch(e) {
|
||
console.error('[测试] 设置 v14m_1 失败:', e.message);
|
||
}
|
||
}
|
||
}, 50);
|
||
|
||
// ===== KC 回调验证:修改 j14b_1 后检查 d14n_1 是否更新 =====
|
||
// KC 回调会复制 j14b_1 → d14n_1(d14n_1.l14a(j14b_1))
|
||
// 如果 d14n_1 更新了,说明 KC 回调每帧调用,方案有效
|
||
kcVerified = false;
|
||
var verifyCount = 0;
|
||
verifyInterval = setInterval(function() {
|
||
if (kcVerified || !running || !dyt) return;
|
||
verifyCount++;
|
||
if (verifyCount > 60) { // 3秒后停止验证
|
||
clearInterval(verifyInterval);
|
||
verifyInterval = null;
|
||
if (!kcVerified) {
|
||
console.warn('[验证] 3秒内未检测到 KC 回调工作(d14n_1 未跟随 v14m_1 更新)');
|
||
console.warn('[验证] 可能原因:1) KC 回调不每帧调用 2) n14m_1=false 3) l14m_1 未注册');
|
||
console.warn('[验证] 请尝试在游戏中移动(点击地面寻路),观察 d14n_1 是否变化');
|
||
}
|
||
return;
|
||
}
|
||
// 如果 j14b_1 ≠ d14n_1,说明 KC 回调还没复制(可能 KC 不每帧调用)
|
||
// 如果 j14b_1 == d14n_1,说明 KC 回调已复制(KC 工作正常)
|
||
try {
|
||
if (dyt.v14m_1.m14b_1 === dyt.d14n_1.m14b_1 &&
|
||
dyt.v14m_1.n14b_1 === dyt.d14n_1.n14b_1) {
|
||
if (lastS140 !== 0 || lastT140 !== 0) {
|
||
// j14b_1 有非零值且 d14n_1 已同步
|
||
kcVerified = true;
|
||
clearInterval(verifyInterval);
|
||
verifyInterval = null;
|
||
console.log('[验证] KC 回调工作正常!d14n_1 已跟随 v14m_1 更新');
|
||
console.log('[验证] iyz(Ds) 应已触发,kyt 应已发送网络包');
|
||
}
|
||
}
|
||
} catch(e) {}
|
||
}, 50);
|
||
|
||
// ===== 位置监控(每秒打印一次) =====
|
||
var posLogCount = 0;
|
||
var posLogInterval = setInterval(function() {
|
||
if (!running) {
|
||
clearInterval(posLogInterval);
|
||
return;
|
||
}
|
||
posLogCount++;
|
||
if (posLogCount % 20 === 0) { // 每10秒打印一次
|
||
try {
|
||
var p = GetTankPosition(playerTank);
|
||
if (p) {
|
||
console.log('[位置] (' + p.x.toFixed(1) + ', ' + p.y.toFixed(1) + ', ' + p.z.toFixed(1) + ')');
|
||
}
|
||
} catch(e) {}
|
||
}
|
||
}, 500);
|
||
|
||
console.log('[测试] 移动控制已启动');
|
||
console.log('[测试] W/S 前进/后退,A/D 左转/右转');
|
||
console.log('[测试] 停止请调用 TankControl.Stop()');
|
||
|
||
// 保存引用以便 Stop 清理
|
||
_stopCallbacks = {
|
||
onKeyDown: onKeyDown,
|
||
onKeyUp: onKeyUp,
|
||
posLogInterval: posLogInterval
|
||
};
|
||
}
|
||
|
||
var _stopCallbacks = null;
|
||
|
||
function Stop() {
|
||
running = false;
|
||
if (updateInterval) {
|
||
clearInterval(updateInterval);
|
||
updateInterval = null;
|
||
}
|
||
if (verifyInterval) {
|
||
clearInterval(verifyInterval);
|
||
verifyInterval = null;
|
||
}
|
||
if (_stopCallbacks) {
|
||
if (_stopCallbacks.posLogInterval) clearInterval(_stopCallbacks.posLogInterval);
|
||
document.removeEventListener('keydown', _stopCallbacks.onKeyDown, true);
|
||
document.removeEventListener('keyup', _stopCallbacks.onKeyUp, true);
|
||
_stopCallbacks = null;
|
||
}
|
||
// 停止移动:设置 j14b_1 为 0
|
||
if (dyt && dyt.v14m_1) {
|
||
try {
|
||
dyt.v14m_1.m14b_1 = 0;
|
||
dyt.v14m_1.n14b_1 = 0;
|
||
console.log('[测试] v14m_1 已归零,坦克停止移动');
|
||
} catch(e) {
|
||
console.error('[测试] 归零 v14m_1 失败:', e.message);
|
||
}
|
||
}
|
||
keys = {};
|
||
lastS140 = 0;
|
||
lastT140 = 0;
|
||
kcVerified = false;
|
||
console.log('[测试] 移动控制已停止');
|
||
}
|
||
|
||
function Status() {
|
||
if (!running) return '未运行';
|
||
var info = '运行中';
|
||
try {
|
||
if (playerTank) {
|
||
var p = window.__hornetLib__.GetTankPosition(playerTank);
|
||
if (p) info += ' 位置(' + p.x.toFixed(0) + ',' + p.y.toFixed(0) + ',' + p.z.toFixed(0) + ')';
|
||
}
|
||
} catch(e) {}
|
||
if (kcVerified) info += ' [KC回调已验证]';
|
||
else info += ' [KC回调未验证]';
|
||
return info;
|
||
}
|
||
|
||
function GetRunning() {
|
||
return running;
|
||
}
|
||
|
||
// ===== 手动设置移动值(不通过键盘) =====
|
||
function SetMove(forward, turn) {
|
||
if (!dyt || !dyt.v14m_1) {
|
||
console.error('[测试] Dyt 组件未初始化,请先 Start');
|
||
return;
|
||
}
|
||
var newS140 = Math.round(forward * maxSpeed);
|
||
var newT140 = Math.round(turn * maxTurn);
|
||
try {
|
||
dyt.v14m_1.m14b_1 = newS140;
|
||
dyt.v14m_1.n14b_1 = newT140;
|
||
lastS140 = newS140;
|
||
lastT140 = newT140;
|
||
console.log('[手动移动] m14b_1=' + newS140 + ' n14b_1=' + newT140);
|
||
} catch(e) {
|
||
console.error('[测试] 手动设置失败:', e.message);
|
||
}
|
||
}
|
||
|
||
// ===== 设置速度参数 =====
|
||
function SetParams(speed, turn) {
|
||
if (speed !== undefined && speed > 0) maxSpeed = Math.round(speed);
|
||
if (turn !== undefined && turn > 0) maxTurn = Math.round(turn);
|
||
console.log('[参数] maxSpeed=' + maxSpeed + ' maxTurn=' + maxTurn);
|
||
}
|
||
|
||
window.__hornetTankTest__ = {
|
||
Start: _start,
|
||
Stop: Stop,
|
||
Status: Status,
|
||
GetRunning: GetRunning,
|
||
SetMove: SetMove,
|
||
SetParams: SetParams
|
||
};
|
||
|
||
if (window.__hornetTools__) {
|
||
window.__hornetTools__.TankControl = window.__hornetTankTest__;
|
||
}
|
||
|
||
_start();
|
||
})();
|