diff --git a/3dtank.com/play/static/js/unpacked/hornet_bundle.js b/3dtank.com/play/static/js/unpacked/hornet_bundle.js index 51a9469..fdf9f58 100644 --- a/3dtank.com/play/static/js/unpacked/hornet_bundle.js +++ b/3dtank.com/play/static/js/unpacked/hornet_bundle.js @@ -299,7 +299,8 @@ 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应 'Shape.Body': 'b9k_1', // 形状 → 所属刚体(Fn) - 'Shape.Type': 'v9j_1', // 形状类型位组(1/2/4/8/16/32;8 = 三角形) + 'Shape.Type': 'v9j_1', // 形状类型位组(1/2/4/8/16/32;8 = 三角形,4 = 克隆包装) + 'Shape.Clone': 'c9w_1', // 类型 4 的克隆包装:真实几何在 c9w_1 里 'Shape.Vertex0': 'u9x_1', // 三角形顶点 0 'Shape.Vertex1': 'v9x_1', // 三角形顶点 1 'Shape.Vertex2': 'w9x_1', // 三角形顶点 2 @@ -6568,6 +6569,7 @@ var FShapeName = Fld('Shape.Name', 'x9j_1'); // 形状名('hull-main') var FShapeCategory = Fld('Shape.Category', 'y9j_1'); // category 位组 var FShapeType = Fld('Shape.Type', 'v9j_1'); // 形状类型位组(8 = 三角形) + var FShapeClone = Fld('Shape.Clone', 'c9w_1'); // 类型 4 包装里的真实形状 var FShapeBody = Fld('Shape.Body', 'b9k_1'); // 形状 → 刚体 var FBodyOwner = Fld('Body.Owner', 'x9i_1'); // 刚体 → 拥有者 var FV0 = Fld('Shape.Vertex0', 'u9x_1'); // 三角形顶点 0 @@ -6646,14 +6648,23 @@ } // 三角形是否「陡」:法线 z 分量接近 0(墙/栅栏/悬崖立面) + // type 4 是「克隆包装」(hu: this.c9w_1 = 原形状.d21()),真实几何在 c9w_1 里,必须先解包 + function UnwrapShape(Shape) { + var S = Shape, Guard = 0; + while (S && S[FShapeType] === 4 && S[FShapeClone] && Guard++ < 4) S = S[FShapeClone]; + return S; + } + function IsTriangle(Shape) { - return !!(Shape && Shape[FShapeType] === TRIANGLE_TYPE); + var S = UnwrapShape(Shape); + return !!(S && S[FShapeType] === TRIANGLE_TYPE); } // 返回法线 z 分量(-1..1);读不到返回 null function TriangleNormalZ(Shape) { - if (!IsTriangle(Shape)) return null; - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (!S || S[FShapeType] !== TRIANGLE_TYPE) return null; + var A = S[FV0], B = S[FV1], C = S[FV2]; if (!A || !B || !C) return null; if (typeof A.f20_1 !== 'number' || typeof B.f20_1 !== 'number' || typeof C.f20_1 !== 'number') return null; var ABx = B.f20_1 - A.f20_1, ABy = B.g20_1 - A.g20_1, ABz = B.h20_1 - A.h20_1; @@ -6687,8 +6698,9 @@ } function ShapeMaxZ(Shape) { - if (IsTriangle(Shape)) { - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (S && S[FShapeType] === TRIANGLE_TYPE) { + var A = S[FV0], B = S[FV1], C = S[FV2]; if (!A || !B || !C) return null; var Max = Math.max(A.h20_1, B.h20_1, C.h20_1); return isFinite(Max) ? Max : null; @@ -6741,8 +6753,9 @@ function ShapePoint(Shape) { if (!Shape) return null; - if (IsTriangle(Shape)) { - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (S && S[FShapeType] === TRIANGLE_TYPE) { + var A = S[FV0], B = S[FV1], C = S[FV2]; if (A && B && C) { return { x: (A.f20_1 + B.f20_1 + C.f20_1) / 3, diff --git a/3dtank_bundle.js b/3dtank_bundle.js index 51a9469..fdf9f58 100644 --- a/3dtank_bundle.js +++ b/3dtank_bundle.js @@ -299,7 +299,8 @@ 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应 'Shape.Body': 'b9k_1', // 形状 → 所属刚体(Fn) - 'Shape.Type': 'v9j_1', // 形状类型位组(1/2/4/8/16/32;8 = 三角形) + 'Shape.Type': 'v9j_1', // 形状类型位组(1/2/4/8/16/32;8 = 三角形,4 = 克隆包装) + 'Shape.Clone': 'c9w_1', // 类型 4 的克隆包装:真实几何在 c9w_1 里 'Shape.Vertex0': 'u9x_1', // 三角形顶点 0 'Shape.Vertex1': 'v9x_1', // 三角形顶点 1 'Shape.Vertex2': 'w9x_1', // 三角形顶点 2 @@ -6568,6 +6569,7 @@ var FShapeName = Fld('Shape.Name', 'x9j_1'); // 形状名('hull-main') var FShapeCategory = Fld('Shape.Category', 'y9j_1'); // category 位组 var FShapeType = Fld('Shape.Type', 'v9j_1'); // 形状类型位组(8 = 三角形) + var FShapeClone = Fld('Shape.Clone', 'c9w_1'); // 类型 4 包装里的真实形状 var FShapeBody = Fld('Shape.Body', 'b9k_1'); // 形状 → 刚体 var FBodyOwner = Fld('Body.Owner', 'x9i_1'); // 刚体 → 拥有者 var FV0 = Fld('Shape.Vertex0', 'u9x_1'); // 三角形顶点 0 @@ -6646,14 +6648,23 @@ } // 三角形是否「陡」:法线 z 分量接近 0(墙/栅栏/悬崖立面) + // type 4 是「克隆包装」(hu: this.c9w_1 = 原形状.d21()),真实几何在 c9w_1 里,必须先解包 + function UnwrapShape(Shape) { + var S = Shape, Guard = 0; + while (S && S[FShapeType] === 4 && S[FShapeClone] && Guard++ < 4) S = S[FShapeClone]; + return S; + } + function IsTriangle(Shape) { - return !!(Shape && Shape[FShapeType] === TRIANGLE_TYPE); + var S = UnwrapShape(Shape); + return !!(S && S[FShapeType] === TRIANGLE_TYPE); } // 返回法线 z 分量(-1..1);读不到返回 null function TriangleNormalZ(Shape) { - if (!IsTriangle(Shape)) return null; - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (!S || S[FShapeType] !== TRIANGLE_TYPE) return null; + var A = S[FV0], B = S[FV1], C = S[FV2]; if (!A || !B || !C) return null; if (typeof A.f20_1 !== 'number' || typeof B.f20_1 !== 'number' || typeof C.f20_1 !== 'number') return null; var ABx = B.f20_1 - A.f20_1, ABy = B.g20_1 - A.g20_1, ABz = B.h20_1 - A.h20_1; @@ -6687,8 +6698,9 @@ } function ShapeMaxZ(Shape) { - if (IsTriangle(Shape)) { - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (S && S[FShapeType] === TRIANGLE_TYPE) { + var A = S[FV0], B = S[FV1], C = S[FV2]; if (!A || !B || !C) return null; var Max = Math.max(A.h20_1, B.h20_1, C.h20_1); return isFinite(Max) ? Max : null; @@ -6741,8 +6753,9 @@ function ShapePoint(Shape) { if (!Shape) return null; - if (IsTriangle(Shape)) { - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (S && S[FShapeType] === TRIANGLE_TYPE) { + var A = S[FV0], B = S[FV1], C = S[FV2]; if (A && B && C) { return { x: (A.f20_1 + B.f20_1 + C.f20_1) / 3, diff --git a/tools/hornet_noclip.js b/tools/hornet_noclip.js index f649a94..d1b4380 100644 --- a/tools/hornet_noclip.js +++ b/tools/hornet_noclip.js @@ -43,6 +43,7 @@ var FShapeName = Fld('Shape.Name', 'x9j_1'); // 形状名('hull-main') var FShapeCategory = Fld('Shape.Category', 'y9j_1'); // category 位组 var FShapeType = Fld('Shape.Type', 'v9j_1'); // 形状类型位组(8 = 三角形) + var FShapeClone = Fld('Shape.Clone', 'c9w_1'); // 类型 4 包装里的真实形状 var FShapeBody = Fld('Shape.Body', 'b9k_1'); // 形状 → 刚体 var FBodyOwner = Fld('Body.Owner', 'x9i_1'); // 刚体 → 拥有者 var FV0 = Fld('Shape.Vertex0', 'u9x_1'); // 三角形顶点 0 @@ -121,14 +122,23 @@ } // 三角形是否「陡」:法线 z 分量接近 0(墙/栅栏/悬崖立面) + // type 4 是「克隆包装」(hu: this.c9w_1 = 原形状.d21()),真实几何在 c9w_1 里,必须先解包 + function UnwrapShape(Shape) { + var S = Shape, Guard = 0; + while (S && S[FShapeType] === 4 && S[FShapeClone] && Guard++ < 4) S = S[FShapeClone]; + return S; + } + function IsTriangle(Shape) { - return !!(Shape && Shape[FShapeType] === TRIANGLE_TYPE); + var S = UnwrapShape(Shape); + return !!(S && S[FShapeType] === TRIANGLE_TYPE); } // 返回法线 z 分量(-1..1);读不到返回 null function TriangleNormalZ(Shape) { - if (!IsTriangle(Shape)) return null; - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (!S || S[FShapeType] !== TRIANGLE_TYPE) return null; + var A = S[FV0], B = S[FV1], C = S[FV2]; if (!A || !B || !C) return null; if (typeof A.f20_1 !== 'number' || typeof B.f20_1 !== 'number' || typeof C.f20_1 !== 'number') return null; var ABx = B.f20_1 - A.f20_1, ABy = B.g20_1 - A.g20_1, ABz = B.h20_1 - A.h20_1; @@ -162,8 +172,9 @@ } function ShapeMaxZ(Shape) { - if (IsTriangle(Shape)) { - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (S && S[FShapeType] === TRIANGLE_TYPE) { + var A = S[FV0], B = S[FV1], C = S[FV2]; if (!A || !B || !C) return null; var Max = Math.max(A.h20_1, B.h20_1, C.h20_1); return isFinite(Max) ? Max : null; @@ -216,8 +227,9 @@ function ShapePoint(Shape) { if (!Shape) return null; - if (IsTriangle(Shape)) { - var A = Shape[FV0], B = Shape[FV1], C = Shape[FV2]; + var S = UnwrapShape(Shape); + if (S && S[FShapeType] === TRIANGLE_TYPE) { + var A = S[FV0], B = S[FV1], C = S[FV2]; if (A && B && C) { return { x: (A.f20_1 + B.f20_1 + C.f20_1) / 3, diff --git a/tools/hornet_schema.js b/tools/hornet_schema.js index 0dbd4d2..ceb6269 100644 --- a/tools/hornet_schema.js +++ b/tools/hornet_schema.js @@ -75,7 +75,8 @@ 'Shape.Mask': 'z9j_1', // 愿意碰撞的分类位 'Shape.Ghost': 'g9k_1', // true = 只探测不产生碰撞响应 'Shape.Body': 'b9k_1', // 形状 → 所属刚体(Fn) - 'Shape.Type': 'v9j_1', // 形状类型位组(1/2/4/8/16/32;8 = 三角形) + 'Shape.Type': 'v9j_1', // 形状类型位组(1/2/4/8/16/32;8 = 三角形,4 = 克隆包装) + 'Shape.Clone': 'c9w_1', // 类型 4 的克隆包装:真实几何在 c9w_1 里 'Shape.Vertex0': 'u9x_1', // 三角形顶点 0 'Shape.Vertex1': 'v9x_1', // 三角形顶点 1 'Shape.Vertex2': 'w9x_1', // 三角形顶点 2