From 86b9322a9fcccf82f58aeabd69a083cf4144c4c2 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 18 Oct 2026 19:10:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(wireframe):=20=E6=8C=89=E6=96=B0=E7=89=88?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E4=BF=AE=E5=A4=8D=E6=A8=A1=E5=9E=8B=E9=87=87?= =?UTF-8?q?=E9=9B=86=E4=B8=8E=E6=95=8C=E6=88=91=E5=88=A4=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../play/static/js/unpacked/hornet_bundle.js | 127 +++++++++++------- 3dtank_bundle.js | 127 +++++++++++------- tools/hornet_3d_wireframe.js | 109 ++++++++------- tools/hornet_lib.js | 18 ++- 4 files changed, 234 insertions(+), 147 deletions(-) diff --git a/3dtank.com/play/static/js/unpacked/hornet_bundle.js b/3dtank.com/play/static/js/unpacked/hornet_bundle.js index 2477a47..3e53f2f 100644 --- a/3dtank.com/play/static/js/unpacked/hornet_bundle.js +++ b/3dtank.com/play/static/js/unpacked/hornet_bundle.js @@ -229,15 +229,25 @@ var ZCt = null, m2Fn = null; // 加载队伍判断函数(从 module_87072 导出) - // ZCt (mod.$_$.kd): 从坦克对象获取队伍ID - // m2 (mod.$_$.rk): 判断两个队伍ID是否相同且非中立 = t.equals(n) && !t.equals(E$()) + // 新旧差异(main.7cfa4058): + // 取队伍 $_$.vd = WIt(t) → g$(HIt(), t).b135_1(坦克无队伍时返回中立 q$()) + // 同队判定 $_$.dl = R7(a, b) → a.equals(b) && !a.equals(q$()) + // ⚠ 旧键 $_$.kd / $_$.rk 在新版已指向无关的构造器类(CCt / FIn),用了会"敌我不分" + var TEAM_GET_KEYS = ['vd', 'kd']; + var TEAM_EQ_KEYS = ['dl', 'rk']; function LoadTeamFunctions() { if (ZCt && m2Fn) return { ZCt: ZCt, m2Fn: m2Fn }; try { var mod87072 = window.__wp_require__(87072); if (mod87072 && mod87072.$_$) { - ZCt = mod87072.$_$.kd; - m2Fn = mod87072.$_$.rk; + for (var i = 0; i < TEAM_GET_KEYS.length && !ZCt; i++) { + var G = mod87072.$_$[TEAM_GET_KEYS[i]]; + if (typeof G === 'function') ZCt = G; + } + for (var j = 0; j < TEAM_EQ_KEYS.length && !m2Fn; j++) { + var E = mod87072.$_$[TEAM_EQ_KEYS[j]]; + if (typeof E === 'function') m2Fn = E; + } console.log('[公共库] 队伍判断函数已加载: ZCt=' + (typeof ZCt) + ', m2=' + (typeof m2Fn)); } } catch(e) { @@ -1735,36 +1745,47 @@ return vc; } - // ===== 获取 KMt / TDt 渲染组件 ===== - // 新 build:车身皮肤组件字段是 w14w_1(kDt(t)=t.w14w_1,缺失报 "skin";RDt.j16r 里赋值) - // 旧 build:w14x_1 / t14l_1 / p14l_1(新版 t14l_1 已改成悬停车体状态 Qmt,务必别再当皮肤用) - function GetKMtComponent(entity) { - var comp = FindComponentByField(entity, 'w14w_1'); + // ===== 皮肤组件(新旧差异修正) ===== + // 新版(main.7cfa4058): + // skin 组件(类 eUt)构造后由 j16r 把皮肤对象存到 **组件自己的 g159_1**, + // 皮肤对象.g17r_1 = 车身部件表;每个部件 part.j17r_1 是**单个 BP 节点**(旧版是节点列表)。 + // 炮塔根节点 = skinComp.a17q_1(weaponSkin 组件 LUt.u11p() = e13a().a17q_1,e13a 取的就是 skin 组件)。 + // 旧写法(w14w_1 / n11c_1 / m17a_1)在新版已被无关类占用(w14w_1=SetReverseBackTurn、m17a_1=数值参数),不再可用。 + function GetSkinComponent(entity) { + var comp = FindComponentByField(entity, 'g159_1'); if (comp) return comp; - comp = FindComponentByField(entity, 'w14x_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 't14l_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 'p14l_1'); + comp = FindComponentByField(entity, 'a17q_1'); return comp; } - // 取车身皮肤对象(含 g17r_1 部件表),跨版本兼容;stats 用于诊断来源 + // 取车身皮肤对象(含 g17r_1 部件表);stats 用于诊断来源 function GetHullSkin(tank, stats) { - var comp = GetKMtComponent(tank); - if (!comp) { if (stats) stats.hullSource = '无组件'; return null; } - if (comp.w14w_1 && comp.w14w_1.g17r_1) { if (stats) stats.hullSource = 'w14w_1'; return comp.w14w_1; } // 新 build - if (comp.t14l_1 && comp.t14l_1.g17r_1) { if (stats) stats.hullSource = 't14l_1'; return comp.t14l_1; } // 旧 build - if (comp.p14l_1 && comp.p14l_1.g17r_1) { if (stats) stats.hullSource = 'p14l_1'; return comp.p14l_1; } // 旧 build + var comp = GetSkinComponent(tank); + if (!comp) { if (stats) stats.hullSource = '无皮肤组件'; return null; } + if (comp.g159_1 && comp.g159_1.g17r_1) { if (stats) stats.hullSource = 'g159_1'; return comp.g159_1; } if (stats) stats.hullSource = '有组件但无皮肤'; return null; } - function GetTDtComponent(entity) { - var comp = FindComponentByField(entity, 'n11c_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 'q112_1'); - return comp; + // 炮塔 BP 根节点 + function GetTurretNode(entity) { + var comp = GetSkinComponent(entity); + return (comp && comp.a17q_1) ? comp.a17q_1 : null; + } + + // 兼容两种集合:引擎列表类(e1/g1)与迭代器(t/u/v) + function ForEachInList(list, fn) { + if (!list) return; + try { + if (typeof list.e1 === 'function' && typeof list.g1 === 'function') { + var n = list.e1(); + for (var i = 0; i < n; i++) fn(list.g1(i)); + return; + } + if (typeof list.t === 'function') { + for (var it = list.t(); it.u();) fn(it.v()); + } + } catch (e) {} } // ===== 从GPU读取顶点位置数据(缓冲区[0]) ===== @@ -1887,14 +1908,14 @@ } } catch(e) {} } - if (bpNode.p35_1 && typeof bpNode.p35_1.e1 === 'function') { - var childCount = bpNode.p35_1.e1(); - for (var c = 0; c < childCount; c++) { - try { - var child = bpNode.p35_1.g1(c); - if (child) CollectMeshNodes(child, nodes, depth + 1, group, stats); - } catch(e) {} - } + // 子节点:新版是 r35_1(zl 基类:this.r35_1 = new lo(),r3k 里递归子节点) + // 旧版是 p35_1;新版 p35_1 已变成"世界矩阵",绝不能当子节点列表 + var Children = (bpNode.r35_1 && typeof bpNode.r35_1.e1 === 'function') ? bpNode.r35_1 : + ((bpNode.p35_1 && typeof bpNode.p35_1.e1 === 'function') ? bpNode.p35_1 : null); + if (Children) { + ForEachInList(Children, function (child) { + if (child) CollectMeshNodes(child, nodes, depth + 1, group, stats); + }); } } @@ -1904,25 +1925,27 @@ var skin = GetHullSkin(tank, stats); if (skin) { try { - var partCount = skin.g17r_1.e1(); - if (stats) stats.hullParts = partCount; - for (var p = 0; p < partCount; p++) { - var part = skin.g17r_1.g1(p); - if (!part || !part.j17r_1) continue; - var nodeCount = part.j17r_1.e1(); - for (var n = 0; n < nodeCount; n++) { - var bpNode = part.j17r_1.g1(n); - if (!bpNode) continue; - CollectMeshNodes(bpNode, nodes, 0, 'hull', stats ? stats.hull : null); + if (stats) stats.hullParts = (typeof skin.g17r_1.e1 === 'function') ? skin.g17r_1.e1() : -1; + ForEachInList(skin.g17r_1, function (part) { + if (!part) return; + // 新版:part.j17r_1 是单个 BP 节点;旧版是节点列表 + var j = part.j17r_1; + if (!j) return; + if (typeof j === 'object' && typeof j.e1 === 'function' && typeof j.g1 === 'function') { + ForEachInList(j, function (bp) { + if (bp) CollectMeshNodes(bp, nodes, 0, 'hull', stats ? stats.hull : null); + }); + } else { + CollectMeshNodes(j, nodes, 0, 'hull', stats ? stats.hull : null); } - } + }); } catch(e) {} } - var tdt = GetTDtComponent(tank); - if (stats) stats.turretComp = !!tdt; - if (tdt && tdt.n11c_1 && tdt.n11c_1.m17a_1) { + var turretNode = GetTurretNode(tank); + if (stats) stats.turretComp = !!turretNode; + if (turretNode) { if (stats) stats.turretRoot = true; - try { CollectMeshNodes(tdt.n11c_1.m17a_1, nodes, 0, 'turret', stats ? stats.turret : null); } catch(e) {} + try { CollectMeshNodes(turretNode, nodes, 0, 'turret', stats ? stats.turret : null); } catch(e) {} } return nodes; } @@ -1940,7 +1963,13 @@ var NodeMatrixScratch = new Float32Array(16); function IsNodeValid(bpNode, pos, tankIsMoving, diagStats) { - var M = bpNode.n35_1; + // 世界矩阵:新版是 p35_1(zl 基类构造里 = hl(),s3k/t3k/u3k 读 p35_1[12..14]) + // 旧版是 n35_1;新版 n35_1 已变成布尔标志 + var M = bpNode.p35_1; + if (!M || typeof M.length !== 'number' || M.length < 16) { + var OldM = bpNode.n35_1; + M = (OldM && typeof OldM.length === 'number' && OldM.length >= 16) ? OldM : null; + } if (!M) return null; if (diagStats) diagStats.totalNodes++; diff --git a/3dtank_bundle.js b/3dtank_bundle.js index 2477a47..3e53f2f 100644 --- a/3dtank_bundle.js +++ b/3dtank_bundle.js @@ -229,15 +229,25 @@ var ZCt = null, m2Fn = null; // 加载队伍判断函数(从 module_87072 导出) - // ZCt (mod.$_$.kd): 从坦克对象获取队伍ID - // m2 (mod.$_$.rk): 判断两个队伍ID是否相同且非中立 = t.equals(n) && !t.equals(E$()) + // 新旧差异(main.7cfa4058): + // 取队伍 $_$.vd = WIt(t) → g$(HIt(), t).b135_1(坦克无队伍时返回中立 q$()) + // 同队判定 $_$.dl = R7(a, b) → a.equals(b) && !a.equals(q$()) + // ⚠ 旧键 $_$.kd / $_$.rk 在新版已指向无关的构造器类(CCt / FIn),用了会"敌我不分" + var TEAM_GET_KEYS = ['vd', 'kd']; + var TEAM_EQ_KEYS = ['dl', 'rk']; function LoadTeamFunctions() { if (ZCt && m2Fn) return { ZCt: ZCt, m2Fn: m2Fn }; try { var mod87072 = window.__wp_require__(87072); if (mod87072 && mod87072.$_$) { - ZCt = mod87072.$_$.kd; - m2Fn = mod87072.$_$.rk; + for (var i = 0; i < TEAM_GET_KEYS.length && !ZCt; i++) { + var G = mod87072.$_$[TEAM_GET_KEYS[i]]; + if (typeof G === 'function') ZCt = G; + } + for (var j = 0; j < TEAM_EQ_KEYS.length && !m2Fn; j++) { + var E = mod87072.$_$[TEAM_EQ_KEYS[j]]; + if (typeof E === 'function') m2Fn = E; + } console.log('[公共库] 队伍判断函数已加载: ZCt=' + (typeof ZCt) + ', m2=' + (typeof m2Fn)); } } catch(e) { @@ -1735,36 +1745,47 @@ return vc; } - // ===== 获取 KMt / TDt 渲染组件 ===== - // 新 build:车身皮肤组件字段是 w14w_1(kDt(t)=t.w14w_1,缺失报 "skin";RDt.j16r 里赋值) - // 旧 build:w14x_1 / t14l_1 / p14l_1(新版 t14l_1 已改成悬停车体状态 Qmt,务必别再当皮肤用) - function GetKMtComponent(entity) { - var comp = FindComponentByField(entity, 'w14w_1'); + // ===== 皮肤组件(新旧差异修正) ===== + // 新版(main.7cfa4058): + // skin 组件(类 eUt)构造后由 j16r 把皮肤对象存到 **组件自己的 g159_1**, + // 皮肤对象.g17r_1 = 车身部件表;每个部件 part.j17r_1 是**单个 BP 节点**(旧版是节点列表)。 + // 炮塔根节点 = skinComp.a17q_1(weaponSkin 组件 LUt.u11p() = e13a().a17q_1,e13a 取的就是 skin 组件)。 + // 旧写法(w14w_1 / n11c_1 / m17a_1)在新版已被无关类占用(w14w_1=SetReverseBackTurn、m17a_1=数值参数),不再可用。 + function GetSkinComponent(entity) { + var comp = FindComponentByField(entity, 'g159_1'); if (comp) return comp; - comp = FindComponentByField(entity, 'w14x_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 't14l_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 'p14l_1'); + comp = FindComponentByField(entity, 'a17q_1'); return comp; } - // 取车身皮肤对象(含 g17r_1 部件表),跨版本兼容;stats 用于诊断来源 + // 取车身皮肤对象(含 g17r_1 部件表);stats 用于诊断来源 function GetHullSkin(tank, stats) { - var comp = GetKMtComponent(tank); - if (!comp) { if (stats) stats.hullSource = '无组件'; return null; } - if (comp.w14w_1 && comp.w14w_1.g17r_1) { if (stats) stats.hullSource = 'w14w_1'; return comp.w14w_1; } // 新 build - if (comp.t14l_1 && comp.t14l_1.g17r_1) { if (stats) stats.hullSource = 't14l_1'; return comp.t14l_1; } // 旧 build - if (comp.p14l_1 && comp.p14l_1.g17r_1) { if (stats) stats.hullSource = 'p14l_1'; return comp.p14l_1; } // 旧 build + var comp = GetSkinComponent(tank); + if (!comp) { if (stats) stats.hullSource = '无皮肤组件'; return null; } + if (comp.g159_1 && comp.g159_1.g17r_1) { if (stats) stats.hullSource = 'g159_1'; return comp.g159_1; } if (stats) stats.hullSource = '有组件但无皮肤'; return null; } - function GetTDtComponent(entity) { - var comp = FindComponentByField(entity, 'n11c_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 'q112_1'); - return comp; + // 炮塔 BP 根节点 + function GetTurretNode(entity) { + var comp = GetSkinComponent(entity); + return (comp && comp.a17q_1) ? comp.a17q_1 : null; + } + + // 兼容两种集合:引擎列表类(e1/g1)与迭代器(t/u/v) + function ForEachInList(list, fn) { + if (!list) return; + try { + if (typeof list.e1 === 'function' && typeof list.g1 === 'function') { + var n = list.e1(); + for (var i = 0; i < n; i++) fn(list.g1(i)); + return; + } + if (typeof list.t === 'function') { + for (var it = list.t(); it.u();) fn(it.v()); + } + } catch (e) {} } // ===== 从GPU读取顶点位置数据(缓冲区[0]) ===== @@ -1887,14 +1908,14 @@ } } catch(e) {} } - if (bpNode.p35_1 && typeof bpNode.p35_1.e1 === 'function') { - var childCount = bpNode.p35_1.e1(); - for (var c = 0; c < childCount; c++) { - try { - var child = bpNode.p35_1.g1(c); - if (child) CollectMeshNodes(child, nodes, depth + 1, group, stats); - } catch(e) {} - } + // 子节点:新版是 r35_1(zl 基类:this.r35_1 = new lo(),r3k 里递归子节点) + // 旧版是 p35_1;新版 p35_1 已变成"世界矩阵",绝不能当子节点列表 + var Children = (bpNode.r35_1 && typeof bpNode.r35_1.e1 === 'function') ? bpNode.r35_1 : + ((bpNode.p35_1 && typeof bpNode.p35_1.e1 === 'function') ? bpNode.p35_1 : null); + if (Children) { + ForEachInList(Children, function (child) { + if (child) CollectMeshNodes(child, nodes, depth + 1, group, stats); + }); } } @@ -1904,25 +1925,27 @@ var skin = GetHullSkin(tank, stats); if (skin) { try { - var partCount = skin.g17r_1.e1(); - if (stats) stats.hullParts = partCount; - for (var p = 0; p < partCount; p++) { - var part = skin.g17r_1.g1(p); - if (!part || !part.j17r_1) continue; - var nodeCount = part.j17r_1.e1(); - for (var n = 0; n < nodeCount; n++) { - var bpNode = part.j17r_1.g1(n); - if (!bpNode) continue; - CollectMeshNodes(bpNode, nodes, 0, 'hull', stats ? stats.hull : null); + if (stats) stats.hullParts = (typeof skin.g17r_1.e1 === 'function') ? skin.g17r_1.e1() : -1; + ForEachInList(skin.g17r_1, function (part) { + if (!part) return; + // 新版:part.j17r_1 是单个 BP 节点;旧版是节点列表 + var j = part.j17r_1; + if (!j) return; + if (typeof j === 'object' && typeof j.e1 === 'function' && typeof j.g1 === 'function') { + ForEachInList(j, function (bp) { + if (bp) CollectMeshNodes(bp, nodes, 0, 'hull', stats ? stats.hull : null); + }); + } else { + CollectMeshNodes(j, nodes, 0, 'hull', stats ? stats.hull : null); } - } + }); } catch(e) {} } - var tdt = GetTDtComponent(tank); - if (stats) stats.turretComp = !!tdt; - if (tdt && tdt.n11c_1 && tdt.n11c_1.m17a_1) { + var turretNode = GetTurretNode(tank); + if (stats) stats.turretComp = !!turretNode; + if (turretNode) { if (stats) stats.turretRoot = true; - try { CollectMeshNodes(tdt.n11c_1.m17a_1, nodes, 0, 'turret', stats ? stats.turret : null); } catch(e) {} + try { CollectMeshNodes(turretNode, nodes, 0, 'turret', stats ? stats.turret : null); } catch(e) {} } return nodes; } @@ -1940,7 +1963,13 @@ var NodeMatrixScratch = new Float32Array(16); function IsNodeValid(bpNode, pos, tankIsMoving, diagStats) { - var M = bpNode.n35_1; + // 世界矩阵:新版是 p35_1(zl 基类构造里 = hl(),s3k/t3k/u3k 读 p35_1[12..14]) + // 旧版是 n35_1;新版 n35_1 已变成布尔标志 + var M = bpNode.p35_1; + if (!M || typeof M.length !== 'number' || M.length < 16) { + var OldM = bpNode.n35_1; + M = (OldM && typeof OldM.length === 'number' && OldM.length >= 16) ? OldM : null; + } if (!M) return null; if (diagStats) diagStats.totalNodes++; diff --git a/tools/hornet_3d_wireframe.js b/tools/hornet_3d_wireframe.js index 61cca6a..145dd8a 100644 --- a/tools/hornet_3d_wireframe.js +++ b/tools/hornet_3d_wireframe.js @@ -220,36 +220,47 @@ return vc; } - // ===== 获取 KMt / TDt 渲染组件 ===== - // 新 build:车身皮肤组件字段是 w14w_1(kDt(t)=t.w14w_1,缺失报 "skin";RDt.j16r 里赋值) - // 旧 build:w14x_1 / t14l_1 / p14l_1(新版 t14l_1 已改成悬停车体状态 Qmt,务必别再当皮肤用) - function GetKMtComponent(entity) { - var comp = FindComponentByField(entity, 'w14w_1'); + // ===== 皮肤组件(新旧差异修正) ===== + // 新版(main.7cfa4058): + // skin 组件(类 eUt)构造后由 j16r 把皮肤对象存到 **组件自己的 g159_1**, + // 皮肤对象.g17r_1 = 车身部件表;每个部件 part.j17r_1 是**单个 BP 节点**(旧版是节点列表)。 + // 炮塔根节点 = skinComp.a17q_1(weaponSkin 组件 LUt.u11p() = e13a().a17q_1,e13a 取的就是 skin 组件)。 + // 旧写法(w14w_1 / n11c_1 / m17a_1)在新版已被无关类占用(w14w_1=SetReverseBackTurn、m17a_1=数值参数),不再可用。 + function GetSkinComponent(entity) { + var comp = FindComponentByField(entity, 'g159_1'); if (comp) return comp; - comp = FindComponentByField(entity, 'w14x_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 't14l_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 'p14l_1'); + comp = FindComponentByField(entity, 'a17q_1'); return comp; } - // 取车身皮肤对象(含 g17r_1 部件表),跨版本兼容;stats 用于诊断来源 + // 取车身皮肤对象(含 g17r_1 部件表);stats 用于诊断来源 function GetHullSkin(tank, stats) { - var comp = GetKMtComponent(tank); - if (!comp) { if (stats) stats.hullSource = '无组件'; return null; } - if (comp.w14w_1 && comp.w14w_1.g17r_1) { if (stats) stats.hullSource = 'w14w_1'; return comp.w14w_1; } // 新 build - if (comp.t14l_1 && comp.t14l_1.g17r_1) { if (stats) stats.hullSource = 't14l_1'; return comp.t14l_1; } // 旧 build - if (comp.p14l_1 && comp.p14l_1.g17r_1) { if (stats) stats.hullSource = 'p14l_1'; return comp.p14l_1; } // 旧 build + var comp = GetSkinComponent(tank); + if (!comp) { if (stats) stats.hullSource = '无皮肤组件'; return null; } + if (comp.g159_1 && comp.g159_1.g17r_1) { if (stats) stats.hullSource = 'g159_1'; return comp.g159_1; } if (stats) stats.hullSource = '有组件但无皮肤'; return null; } - function GetTDtComponent(entity) { - var comp = FindComponentByField(entity, 'n11c_1'); - if (comp) return comp; - comp = FindComponentByField(entity, 'q112_1'); - return comp; + // 炮塔 BP 根节点 + function GetTurretNode(entity) { + var comp = GetSkinComponent(entity); + return (comp && comp.a17q_1) ? comp.a17q_1 : null; + } + + // 兼容两种集合:引擎列表类(e1/g1)与迭代器(t/u/v) + function ForEachInList(list, fn) { + if (!list) return; + try { + if (typeof list.e1 === 'function' && typeof list.g1 === 'function') { + var n = list.e1(); + for (var i = 0; i < n; i++) fn(list.g1(i)); + return; + } + if (typeof list.t === 'function') { + for (var it = list.t(); it.u();) fn(it.v()); + } + } catch (e) {} } // ===== 从GPU读取顶点位置数据(缓冲区[0]) ===== @@ -372,14 +383,14 @@ } } catch(e) {} } - if (bpNode.p35_1 && typeof bpNode.p35_1.e1 === 'function') { - var childCount = bpNode.p35_1.e1(); - for (var c = 0; c < childCount; c++) { - try { - var child = bpNode.p35_1.g1(c); - if (child) CollectMeshNodes(child, nodes, depth + 1, group, stats); - } catch(e) {} - } + // 子节点:新版是 r35_1(zl 基类:this.r35_1 = new lo(),r3k 里递归子节点) + // 旧版是 p35_1;新版 p35_1 已变成"世界矩阵",绝不能当子节点列表 + var Children = (bpNode.r35_1 && typeof bpNode.r35_1.e1 === 'function') ? bpNode.r35_1 : + ((bpNode.p35_1 && typeof bpNode.p35_1.e1 === 'function') ? bpNode.p35_1 : null); + if (Children) { + ForEachInList(Children, function (child) { + if (child) CollectMeshNodes(child, nodes, depth + 1, group, stats); + }); } } @@ -389,25 +400,27 @@ var skin = GetHullSkin(tank, stats); if (skin) { try { - var partCount = skin.g17r_1.e1(); - if (stats) stats.hullParts = partCount; - for (var p = 0; p < partCount; p++) { - var part = skin.g17r_1.g1(p); - if (!part || !part.j17r_1) continue; - var nodeCount = part.j17r_1.e1(); - for (var n = 0; n < nodeCount; n++) { - var bpNode = part.j17r_1.g1(n); - if (!bpNode) continue; - CollectMeshNodes(bpNode, nodes, 0, 'hull', stats ? stats.hull : null); + if (stats) stats.hullParts = (typeof skin.g17r_1.e1 === 'function') ? skin.g17r_1.e1() : -1; + ForEachInList(skin.g17r_1, function (part) { + if (!part) return; + // 新版:part.j17r_1 是单个 BP 节点;旧版是节点列表 + var j = part.j17r_1; + if (!j) return; + if (typeof j === 'object' && typeof j.e1 === 'function' && typeof j.g1 === 'function') { + ForEachInList(j, function (bp) { + if (bp) CollectMeshNodes(bp, nodes, 0, 'hull', stats ? stats.hull : null); + }); + } else { + CollectMeshNodes(j, nodes, 0, 'hull', stats ? stats.hull : null); } - } + }); } catch(e) {} } - var tdt = GetTDtComponent(tank); - if (stats) stats.turretComp = !!tdt; - if (tdt && tdt.n11c_1 && tdt.n11c_1.m17a_1) { + var turretNode = GetTurretNode(tank); + if (stats) stats.turretComp = !!turretNode; + if (turretNode) { if (stats) stats.turretRoot = true; - try { CollectMeshNodes(tdt.n11c_1.m17a_1, nodes, 0, 'turret', stats ? stats.turret : null); } catch(e) {} + try { CollectMeshNodes(turretNode, nodes, 0, 'turret', stats ? stats.turret : null); } catch(e) {} } return nodes; } @@ -425,7 +438,13 @@ var NodeMatrixScratch = new Float32Array(16); function IsNodeValid(bpNode, pos, tankIsMoving, diagStats) { - var M = bpNode.n35_1; + // 世界矩阵:新版是 p35_1(zl 基类构造里 = hl(),s3k/t3k/u3k 读 p35_1[12..14]) + // 旧版是 n35_1;新版 n35_1 已变成布尔标志 + var M = bpNode.p35_1; + if (!M || typeof M.length !== 'number' || M.length < 16) { + var OldM = bpNode.n35_1; + M = (OldM && typeof OldM.length === 'number' && OldM.length >= 16) ? OldM : null; + } if (!M) return null; if (diagStats) diagStats.totalNodes++; diff --git a/tools/hornet_lib.js b/tools/hornet_lib.js index cd478e8..1b9fc87 100644 --- a/tools/hornet_lib.js +++ b/tools/hornet_lib.js @@ -14,15 +14,25 @@ var ZCt = null, m2Fn = null; // 加载队伍判断函数(从 module_87072 导出) - // ZCt (mod.$_$.kd): 从坦克对象获取队伍ID - // m2 (mod.$_$.rk): 判断两个队伍ID是否相同且非中立 = t.equals(n) && !t.equals(E$()) + // 新旧差异(main.7cfa4058): + // 取队伍 $_$.vd = WIt(t) → g$(HIt(), t).b135_1(坦克无队伍时返回中立 q$()) + // 同队判定 $_$.dl = R7(a, b) → a.equals(b) && !a.equals(q$()) + // ⚠ 旧键 $_$.kd / $_$.rk 在新版已指向无关的构造器类(CCt / FIn),用了会"敌我不分" + var TEAM_GET_KEYS = ['vd', 'kd']; + var TEAM_EQ_KEYS = ['dl', 'rk']; function LoadTeamFunctions() { if (ZCt && m2Fn) return { ZCt: ZCt, m2Fn: m2Fn }; try { var mod87072 = window.__wp_require__(87072); if (mod87072 && mod87072.$_$) { - ZCt = mod87072.$_$.kd; - m2Fn = mod87072.$_$.rk; + for (var i = 0; i < TEAM_GET_KEYS.length && !ZCt; i++) { + var G = mod87072.$_$[TEAM_GET_KEYS[i]]; + if (typeof G === 'function') ZCt = G; + } + for (var j = 0; j < TEAM_EQ_KEYS.length && !m2Fn; j++) { + var E = mod87072.$_$[TEAM_EQ_KEYS[j]]; + if (typeof E === 'function') m2Fn = E; + } console.log('[公共库] 队伍判断函数已加载: ZCt=' + (typeof ZCt) + ', m2=' + (typeof m2Fn)); } } catch(e) {