@adatechnology/game-weapons-three 0.14.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/weapon-svg/generated/m79.svg +1 -1
- package/dist/{chunk-PRC75VKC.js → chunk-GBO6L7CQ.js} +1639 -1406
- package/dist/chunk-GBO6L7CQ.js.map +1 -0
- package/dist/index.d.ts +31 -6
- package/dist/index.global.js +2146 -1043
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +23 -2
- package/dist/index.js.map +1 -1
- package/dist/{testing-DnPjEPC5.d.ts → testing-Cf1M1sWN.d.ts} +27 -25
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/package.json +9 -9
- package/dist/chunk-PRC75VKC.js.map +0 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// src/test-area/area.ts
|
|
2
|
-
import { markKitOrigin as
|
|
3
|
-
import { createArsenal } from "@adatechnology/game-weapons";
|
|
2
|
+
import { markKitOrigin as markKitOrigin6 } from "@adatechnology/game-contracts";
|
|
3
|
+
import { createArsenal, genericWeapons } from "@adatechnology/game-weapons";
|
|
4
4
|
import { furnitureSpec } from "@adatechnology/game-floorplan-three";
|
|
5
5
|
import { isLightBudget, isRenderPools } from "@adatechnology/game-render-three";
|
|
6
6
|
|
|
7
|
+
// src/test-area/accessory-bench.ts
|
|
8
|
+
import { aimZoomOf } from "@adatechnology/game-weapons";
|
|
9
|
+
|
|
7
10
|
// src/attachments-key.ts
|
|
8
11
|
var attachmentsKey = (parts) => {
|
|
9
12
|
if (!parts) return "";
|
|
@@ -119,11 +122,11 @@ function createAccessoryBench(options) {
|
|
|
119
122
|
else return false;
|
|
120
123
|
return true;
|
|
121
124
|
};
|
|
122
|
-
const zoomOf = (tool) =>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
const zoomOf = (tool) => aimZoomOf(arsenal, tool.weapon, tool.attachments?.map((part) => part.id));
|
|
126
|
+
const aims = (tool) => {
|
|
127
|
+
const kind = arsenal.weapons.get(tool.weapon)?.action.kind;
|
|
128
|
+
return kind === "firearm" || kind === "launcher";
|
|
125
129
|
};
|
|
126
|
-
const isFirearm = (tool) => arsenal.weapons.get(tool.weapon)?.action.kind === "firearm";
|
|
127
130
|
const setAim = (on) => {
|
|
128
131
|
if (on === aiming) return;
|
|
129
132
|
aiming = on;
|
|
@@ -141,6 +144,7 @@ function createAccessoryBench(options) {
|
|
|
141
144
|
camera.updateProjectionMatrix();
|
|
142
145
|
};
|
|
143
146
|
const onKeyDown = (event) => {
|
|
147
|
+
if (host.playerHeld?.()) return;
|
|
144
148
|
if (event.repeat || event.ctrlKey || event.metaKey || event.altKey || TEXT_FIELDS.has(event.target?.tagName ?? "")) return;
|
|
145
149
|
const handled2 = event.code === ACCESSORY_KEYS.light ? act(ACTION_IDS.light) : event.code === ACCESSORY_KEYS.laser ? act(ACTION_IDS.laser) : event.code === ACCESSORY_KEYS.underbarrel ? act(ACTION_IDS.underbarrel) : event.code === ACCESSORY_KEYS.stock && toggleStock();
|
|
146
150
|
if (!handled2) return;
|
|
@@ -149,7 +153,7 @@ function createAccessoryBench(options) {
|
|
|
149
153
|
};
|
|
150
154
|
const isOnRoom = (event) => Boolean(document.pointerLockElement) || event.target instanceof HTMLCanvasElement;
|
|
151
155
|
const onMouseDown = (event) => {
|
|
152
|
-
if (event.button !== SECONDARY_BUTTON || !isOnRoom(event) || !
|
|
156
|
+
if (event.button !== SECONDARY_BUTTON || !isOnRoom(event) || !aims(host.tool())) return;
|
|
153
157
|
event.preventDefault();
|
|
154
158
|
event.stopImmediatePropagation();
|
|
155
159
|
setAim(true);
|
|
@@ -2832,6 +2836,279 @@ function drawItemWeapon({ THREE, def, items, itemId, turn: turn2, flip }) {
|
|
|
2832
2836
|
return group;
|
|
2833
2837
|
}
|
|
2834
2838
|
|
|
2839
|
+
// src/models/explosives.ts
|
|
2840
|
+
import { markKitOrigin as markKitOrigin2 } from "@adatechnology/game-contracts";
|
|
2841
|
+
|
|
2842
|
+
// src/models/kit.ts
|
|
2843
|
+
import { markShared, shapeGeometries as shapeGeometries2 } from "@adatechnology/game-shapes-three";
|
|
2844
|
+
|
|
2845
|
+
// src/models/rounded-box.ts
|
|
2846
|
+
var uvAlong = (THREE, faceDirection, normal, uvAxis, projectionAxis, radius, sideLength) => {
|
|
2847
|
+
const arcLength = 2 * Math.PI * radius / 4;
|
|
2848
|
+
const centerLength = Math.max(sideLength - 2 * radius, 0);
|
|
2849
|
+
const halfArc = Math.PI / 4;
|
|
2850
|
+
const projected = new THREE.Vector3().copy(normal);
|
|
2851
|
+
projected[projectionAxis] = 0;
|
|
2852
|
+
projected.normalize();
|
|
2853
|
+
const arcUvRatio = 0.5 * arcLength / (arcLength + centerLength);
|
|
2854
|
+
const arcAngleRatio = 1 - projected.angleTo(faceDirection) / halfArc;
|
|
2855
|
+
if (Math.sign(projected[uvAxis]) === 1) return arcAngleRatio * arcUvRatio;
|
|
2856
|
+
const centerUv = centerLength / (arcLength + centerLength);
|
|
2857
|
+
return centerUv + arcUvRatio + arcUvRatio * (1 - arcAngleRatio);
|
|
2858
|
+
};
|
|
2859
|
+
var FACES = [
|
|
2860
|
+
{ direction: [1, 0, 0], u: ["z", "y", false], v: ["y", "z", true] },
|
|
2861
|
+
{ direction: [-1, 0, 0], u: ["z", "y", true], v: ["y", "z", true] },
|
|
2862
|
+
{ direction: [0, 1, 0], u: ["x", "z", true], v: ["z", "x", false] },
|
|
2863
|
+
{ direction: [0, -1, 0], u: ["x", "z", true], v: ["z", "x", true] },
|
|
2864
|
+
{ direction: [0, 0, 1], u: ["x", "y", true], v: ["y", "x", true] },
|
|
2865
|
+
{ direction: [0, 0, -1], u: ["x", "y", false], v: ["y", "x", true] }
|
|
2866
|
+
];
|
|
2867
|
+
function createRoundedBoxGeometry(THREE, width, height, depth, segments, radius) {
|
|
2868
|
+
const count = segments * 2 + 1;
|
|
2869
|
+
const rounding = Math.min(width / 2, height / 2, depth / 2, radius);
|
|
2870
|
+
const geometry = new THREE.BoxGeometry(1, 1, 1, count, count, count);
|
|
2871
|
+
const flat2 = geometry.toNonIndexed();
|
|
2872
|
+
geometry.setIndex(null);
|
|
2873
|
+
geometry.setAttribute("position", flat2.attributes.position);
|
|
2874
|
+
geometry.setAttribute("normal", flat2.attributes.normal);
|
|
2875
|
+
geometry.setAttribute("uv", flat2.attributes.uv);
|
|
2876
|
+
const position = new THREE.Vector3();
|
|
2877
|
+
const normal = new THREE.Vector3();
|
|
2878
|
+
const box2 = new THREE.Vector3(width, height, depth).divideScalar(2).subScalar(rounding);
|
|
2879
|
+
const positions = geometry.attributes.position.array;
|
|
2880
|
+
const normals = geometry.attributes.normal.array;
|
|
2881
|
+
const uvs = geometry.attributes.uv.array;
|
|
2882
|
+
const faceTriangles = positions.length / 6;
|
|
2883
|
+
const halfSegment = 0.5 / count;
|
|
2884
|
+
const sides = { x: width, y: height, z: depth };
|
|
2885
|
+
for (let i = 0, j = 0; i < positions.length; i += 3, j += 2) {
|
|
2886
|
+
position.fromArray(positions, i);
|
|
2887
|
+
normal.copy(position);
|
|
2888
|
+
normal.x -= Math.sign(normal.x) * halfSegment;
|
|
2889
|
+
normal.y -= Math.sign(normal.y) * halfSegment;
|
|
2890
|
+
normal.z -= Math.sign(normal.z) * halfSegment;
|
|
2891
|
+
normal.normalize();
|
|
2892
|
+
positions[i] = box2.x * Math.sign(position.x) + normal.x * rounding;
|
|
2893
|
+
positions[i + 1] = box2.y * Math.sign(position.y) + normal.y * rounding;
|
|
2894
|
+
positions[i + 2] = box2.z * Math.sign(position.z) + normal.z * rounding;
|
|
2895
|
+
normals[i] = normal.x;
|
|
2896
|
+
normals[i + 1] = normal.y;
|
|
2897
|
+
normals[i + 2] = normal.z;
|
|
2898
|
+
const face = FACES[Math.floor(i / faceTriangles)];
|
|
2899
|
+
if (!face) continue;
|
|
2900
|
+
const direction = new THREE.Vector3(...face.direction);
|
|
2901
|
+
for (const [offset, [uvAxis, projectionAxis, mirrored]] of [[0, face.u], [1, face.v]]) {
|
|
2902
|
+
const value = uvAlong(THREE, direction, normal, uvAxis, projectionAxis, rounding, sides[uvAxis]);
|
|
2903
|
+
uvs[j + offset] = mirrored ? 1 - value : value;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
return geometry;
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2909
|
+
// src/models/kit.ts
|
|
2910
|
+
var PI = Math.PI;
|
|
2911
|
+
var createMaterials = (THREE) => {
|
|
2912
|
+
const standard = (color, roughness = 0.7, metalness = 0.2, extra = {}) => new THREE.MeshStandardMaterial({ color, roughness, metalness, ...extra });
|
|
2913
|
+
const basic = (color, extra = {}) => new THREE.MeshBasicMaterial({ color, ...extra });
|
|
2914
|
+
const additive = { transparent: true, opacity: 0.95, blending: THREE.AdditiveBlending, depthWrite: false };
|
|
2915
|
+
const materials = {
|
|
2916
|
+
metal: standard(3422010, 0.42, 0.75),
|
|
2917
|
+
steel: standard(7106418, 0.32, 0.85),
|
|
2918
|
+
steelL: standard(9080208, 0.28, 0.9),
|
|
2919
|
+
dark: standard(1711133, 0.55, 0.5),
|
|
2920
|
+
poly: standard(2369058, 0.8, 0.05),
|
|
2921
|
+
olive: standard(4936241, 0.8, 0.05),
|
|
2922
|
+
tan: standard(10259043, 0.8, 0.05),
|
|
2923
|
+
wood: standard(4860951, 0.55, 0),
|
|
2924
|
+
woodL: standard(6175263, 0.55, 0),
|
|
2925
|
+
brass: standard(12819013, 0.28, 0.9),
|
|
2926
|
+
copper: standard(11561531, 0.3, 0.85),
|
|
2927
|
+
lead: standard(7171955, 0.5, 0.5),
|
|
2928
|
+
shell: standard(10692380, 0.5, 0.05),
|
|
2929
|
+
glass: standard(8364968, 0.05, 0.1, { transparent: true, opacity: 0.42 }),
|
|
2930
|
+
lens: standard(2311770, 0.05, 0.3, { transparent: true, opacity: 0.9, emissive: 399392 }),
|
|
2931
|
+
rubber: standard(1381653, 0.85, 0),
|
|
2932
|
+
white: standard(13617332, 0.8, 0),
|
|
2933
|
+
hole: standard(526343, 1, 0),
|
|
2934
|
+
bake: standard(5911072, 0.55, 0),
|
|
2935
|
+
rust: standard(7027230, 0.95, 0.3),
|
|
2936
|
+
rustD: standard(4860440, 0.95, 0.25),
|
|
2937
|
+
worn: standard(5593178, 0.6, 0.6),
|
|
2938
|
+
fire: basic(16742946),
|
|
2939
|
+
fire2: basic(16764762),
|
|
2940
|
+
flashA: basic(16757575, additive),
|
|
2941
|
+
flashB: basic(16773568, additive),
|
|
2942
|
+
smokeP: standard(9079430, 1, 0, { transparent: true, opacity: 0.35, depthWrite: false }),
|
|
2943
|
+
/** Launcher paints. */
|
|
2944
|
+
yellow: standard(11570978, 0.6, 0),
|
|
2945
|
+
red: standard(9313300, 0.45, 0.1),
|
|
2946
|
+
redPaint: standard(10691354, 0.35, 0.2),
|
|
2947
|
+
tape: standard(9079944, 0.9, 0),
|
|
2948
|
+
pipe: standard(10115634, 0.35, 0.8),
|
|
2949
|
+
green: standard(3818536, 0.75, 0.05),
|
|
2950
|
+
/** Explosive finishes: the molotov's bottle, the dynamite's paper, the C4's putty and the detonator's wire. */
|
|
2951
|
+
bottle: standard(3103284, 0.1, 0.1, { transparent: true, opacity: 0.72 }),
|
|
2952
|
+
dynamite: standard(10365471, 0.7, 0),
|
|
2953
|
+
c4: standard(7170636, 0.95, 0),
|
|
2954
|
+
wire: standard(11542560, 0.5, 0),
|
|
2955
|
+
/** Magazine finishes named by the options. */
|
|
2956
|
+
bakelite: standard(6958620, 0.6, 0),
|
|
2957
|
+
polyMag: standard(2763302, 0.85, 0)
|
|
2958
|
+
};
|
|
2959
|
+
markShared(...Object.values(materials));
|
|
2960
|
+
return materials;
|
|
2961
|
+
};
|
|
2962
|
+
var kits = /* @__PURE__ */ new WeakMap();
|
|
2963
|
+
function modelKit(host) {
|
|
2964
|
+
const cached = kits.get(host);
|
|
2965
|
+
if (cached) return cached;
|
|
2966
|
+
const THREE = shapeGeometries2(host);
|
|
2967
|
+
const geometries = /* @__PURE__ */ new Map();
|
|
2968
|
+
const shadowed = (mesh) => {
|
|
2969
|
+
mesh.castShadow = true;
|
|
2970
|
+
mesh.receiveShadow = true;
|
|
2971
|
+
return mesh;
|
|
2972
|
+
};
|
|
2973
|
+
const place = (parent, mesh, x, y, z) => {
|
|
2974
|
+
mesh.position.set(x, y, z);
|
|
2975
|
+
parent.add(mesh);
|
|
2976
|
+
return mesh;
|
|
2977
|
+
};
|
|
2978
|
+
const kit = {
|
|
2979
|
+
THREE,
|
|
2980
|
+
M: createMaterials(THREE),
|
|
2981
|
+
roundness: null,
|
|
2982
|
+
group: () => new THREE.Group(),
|
|
2983
|
+
box(parent, w, h, d, material, x, y, z, rz = 0, ry = 0, rx = 0) {
|
|
2984
|
+
const radius = Math.min(w, h, d) * (kit.roundness ?? 0.2);
|
|
2985
|
+
const key = `${w.toFixed(4)},${h.toFixed(4)},${d.toFixed(4)},${radius.toFixed(5)}`;
|
|
2986
|
+
let geometry = geometries.get(key);
|
|
2987
|
+
if (!geometry) {
|
|
2988
|
+
geometry = radius > 25e-5 ? createRoundedBoxGeometry(THREE, w, h, d, 2, radius) : new THREE.BoxGeometry(w, h, d);
|
|
2989
|
+
markShared(geometry);
|
|
2990
|
+
geometries.set(key, geometry);
|
|
2991
|
+
}
|
|
2992
|
+
const mesh = place(parent, shadowed(new THREE.Mesh(geometry, material)), x, y, z);
|
|
2993
|
+
mesh.rotation.set(rx, ry, rz);
|
|
2994
|
+
return mesh;
|
|
2995
|
+
},
|
|
2996
|
+
cylinderX(parent, radius, length, material, x, y, z, segments = 16, radiusEnd) {
|
|
2997
|
+
const mesh = shadowed(new THREE.Mesh(new THREE.CylinderGeometry(radiusEnd ?? radius, radius, length, segments), material));
|
|
2998
|
+
mesh.rotation.z = -PI / 2;
|
|
2999
|
+
return place(parent, mesh, x, y, z);
|
|
3000
|
+
},
|
|
3001
|
+
cylinderY(parent, radius, height, material, x, y, z, segments = 16, radiusEnd) {
|
|
3002
|
+
return place(parent, shadowed(new THREE.Mesh(new THREE.CylinderGeometry(radiusEnd ?? radius, radius, height, segments), material)), x, y, z);
|
|
3003
|
+
},
|
|
3004
|
+
cylinderZ(parent, radius, length, material, x, y, z, segments = 16) {
|
|
3005
|
+
const mesh = shadowed(new THREE.Mesh(new THREE.CylinderGeometry(radius, radius, length, segments), material));
|
|
3006
|
+
mesh.rotation.x = PI / 2;
|
|
3007
|
+
return place(parent, mesh, x, y, z);
|
|
3008
|
+
},
|
|
3009
|
+
sphere(parent, radius, material, x, y, z, detail = 1) {
|
|
3010
|
+
return place(parent, shadowed(new THREE.Mesh(new THREE.IcosahedronGeometry(radius, detail), material)), x, y, z);
|
|
3011
|
+
},
|
|
3012
|
+
torus: (parent, geometry, material, x, y, z) => place(parent, shadowed(new THREE.Mesh(geometry, material)), x, y, z),
|
|
3013
|
+
mark(parent, x, y, z) {
|
|
3014
|
+
const object = new THREE.Object3D();
|
|
3015
|
+
object.position.set(x, y, z);
|
|
3016
|
+
parent.add(object);
|
|
3017
|
+
return object;
|
|
3018
|
+
},
|
|
3019
|
+
pivot(parent, x = 0, y = 0, z = 0) {
|
|
3020
|
+
const group = new THREE.Group();
|
|
3021
|
+
group.position.set(x, y, z);
|
|
3022
|
+
parent.add(group);
|
|
3023
|
+
return group;
|
|
3024
|
+
}
|
|
3025
|
+
};
|
|
3026
|
+
kits.set(host, kit);
|
|
3027
|
+
return kit;
|
|
3028
|
+
}
|
|
3029
|
+
function heatify(glow, mesh) {
|
|
3030
|
+
mesh.material = mesh.material.clone();
|
|
3031
|
+
glow.push(mesh);
|
|
3032
|
+
return mesh;
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
// src/models/explosives.ts
|
|
3036
|
+
var grenade = (kit, group) => {
|
|
3037
|
+
const { M, sphere, cylinderY, box: box2, torus, THREE } = kit;
|
|
3038
|
+
sphere(group, 0.032, M.olive, 0, 0.032, 0, 1);
|
|
3039
|
+
cylinderY(group, 0.011, 0.022, M.metal, 0, 0.072, 0);
|
|
3040
|
+
box2(group, 0.012, 0.07, 6e-3, M.metal, 0.016, 0.05, 0, 0.2);
|
|
3041
|
+
torus(group, new THREE.TorusGeometry(85e-4, 16e-4, 6, 12), M.steel, -0.012, 0.082, 0);
|
|
3042
|
+
kit.mark(group, 0, 0.032, 0).name = "handle";
|
|
3043
|
+
};
|
|
3044
|
+
var molotov = (kit, group) => {
|
|
3045
|
+
const { M, cylinderY, box: box2 } = kit;
|
|
3046
|
+
cylinderY(group, 0.036, 0.17, M.bottle, 0, 0.085, 0, 10);
|
|
3047
|
+
cylinderY(group, 0.012, 0.06, M.bottle, 0, 0.2, 0, 8, 0.036);
|
|
3048
|
+
box2(group, 0.03, 0.08, 0.02, M.white, 5e-3, 0.25, 0, 0.3);
|
|
3049
|
+
cylinderY(group, 0.02, 0.07, M.fire, 0.01, 0.31, 0, 6, 0).userData.flame = true;
|
|
3050
|
+
kit.mark(group, 0, 0.085, 0).name = "handle";
|
|
3051
|
+
};
|
|
3052
|
+
var pipeBomb = (kit, group) => {
|
|
3053
|
+
const { M, cylinderX, cylinderY } = kit;
|
|
3054
|
+
cylinderX(group, 0.025, 0.2, M.metal, 0, 0.03, 0, 8);
|
|
3055
|
+
cylinderX(group, 0.031, 0.025, M.dark, -0.1, 0.03, 0, 6);
|
|
3056
|
+
cylinderX(group, 0.031, 0.025, M.dark, 0.1, 0.03, 0, 6);
|
|
3057
|
+
cylinderY(group, 2e-3, 0.06, M.white, 0.1, 0.07, 0);
|
|
3058
|
+
kit.mark(group, 0, 0.03, 0).name = "handle";
|
|
3059
|
+
};
|
|
3060
|
+
var dynamite = (kit, group) => {
|
|
3061
|
+
const { M, cylinderX } = kit;
|
|
3062
|
+
for (const [z, y] of [[-0.015, 0], [0.015, 0], [0, 0.026]]) cylinderX(group, 0.014, 0.2, M.dynamite, 0, 0.016 + y, z, 8);
|
|
3063
|
+
cylinderX(group, 0.031, 0.03, M.dark, -0.04, 0.025, 0, 8);
|
|
3064
|
+
cylinderX(group, 0.031, 0.03, M.dark, 0.05, 0.025, 0, 8);
|
|
3065
|
+
cylinderX(group, 2e-3, 0.1, M.white, 0.14, 0.03, 0, 4);
|
|
3066
|
+
kit.mark(group, 0, 0.025, 0).name = "handle";
|
|
3067
|
+
};
|
|
3068
|
+
var c4 = (kit, group) => {
|
|
3069
|
+
const { M, box: box2, cylinderY } = kit;
|
|
3070
|
+
box2(group, 0.28, 0.05, 0.11, M.c4, 0, 0.025, 0);
|
|
3071
|
+
box2(group, 0.05, 0.03, 0.04, M.dark, 0.06, 0.065, 0);
|
|
3072
|
+
cylinderY(group, 4e-3, 0.05, M.metal, 0.03, 0.07, 0);
|
|
3073
|
+
box2(group, 0.24, 3e-3, 3e-3, M.wire, 0.18, 0.055, 0.02);
|
|
3074
|
+
box2(group, 0.24, 3e-3, 3e-3, M.metal, 0.18, 0.055, 0.03);
|
|
3075
|
+
kit.mark(group, 0, 0.025, 0).name = "handle";
|
|
3076
|
+
};
|
|
3077
|
+
var claymore = (kit, group) => {
|
|
3078
|
+
const { M, box: box2 } = kit;
|
|
3079
|
+
for (const i of [-1, 0, 1]) box2(group, 0.075, 0.083, 0.035, M.olive, i * 0.072, 0.12, Math.abs(i) * 0.012, 0, -i * 0.25);
|
|
3080
|
+
for (const [x, z] of [[-0.07, 0.03], [-0.07, -0.03], [0.07, 0.03], [0.07, -0.03]]) box2(group, 4e-3, 0.09, 4e-3, M.metal, x, 0.04, z, x > 0 ? -0.25 : 0.25);
|
|
3081
|
+
kit.mark(group, 0, 0.12, 0).name = "handle";
|
|
3082
|
+
};
|
|
3083
|
+
var flashbang = (kit, group) => {
|
|
3084
|
+
const { M, cylinderY, box: box2 } = kit;
|
|
3085
|
+
cylinderY(group, 0.022, 0.13, M.olive, 0, 0.065, 0, 10);
|
|
3086
|
+
for (let i = 0; i < 4; i++) cylinderY(group, 0.023, 8e-3, M.dark, 0, 0.025 + i * 0.028, 0, 10);
|
|
3087
|
+
cylinderY(group, 0.012, 0.02, M.metal, 0, 0.14, 0);
|
|
3088
|
+
box2(group, 0.01, 0.08, 5e-3, M.metal, 0.024, 0.1, 0, 0.15);
|
|
3089
|
+
kit.mark(group, 0, 0.065, 0).name = "handle";
|
|
3090
|
+
};
|
|
3091
|
+
var BUILDERS = {
|
|
3092
|
+
m67: grenade,
|
|
3093
|
+
molotov,
|
|
3094
|
+
pipe_bomb: pipeBomb,
|
|
3095
|
+
dynamite,
|
|
3096
|
+
c4,
|
|
3097
|
+
claymore,
|
|
3098
|
+
flashbang
|
|
3099
|
+
};
|
|
3100
|
+
var EXPLOSIVE_MODEL_IDS = Object.keys(BUILDERS);
|
|
3101
|
+
var hasExplosiveModel = (explosiveId) => explosiveId in BUILDERS;
|
|
3102
|
+
function buildExplosiveModel(THREE, explosiveId) {
|
|
3103
|
+
const builder = BUILDERS[explosiveId];
|
|
3104
|
+
if (!builder) return void 0;
|
|
3105
|
+
const kit = modelKit(THREE);
|
|
3106
|
+
const group = markKitOrigin2(kit.group(), { owner: "game-weapons-three", kind: "explosive", id: explosiveId });
|
|
3107
|
+
group.name = explosiveId;
|
|
3108
|
+
builder(kit, group);
|
|
3109
|
+
return group;
|
|
3110
|
+
}
|
|
3111
|
+
|
|
2835
3112
|
// src/weapon-item-model.ts
|
|
2836
3113
|
var SHIPPED_WEAPON_ITEM_MODELS = [
|
|
2837
3114
|
["wrench", { item: "adjustable_wrench" }],
|
|
@@ -2840,8 +3117,12 @@ var SHIPPED_WEAPON_ITEM_MODELS = [
|
|
|
2840
3117
|
["crossbow", { turn: 1 }],
|
|
2841
3118
|
["knife", { flip: true }],
|
|
2842
3119
|
["meat_cleaver", { flip: true }],
|
|
2843
|
-
["screwdriver", { flip: true }]
|
|
3120
|
+
["screwdriver", { flip: true }],
|
|
3121
|
+
// the Itens do Vale Cinzento hammer is a claw hammer: the head and the two-pronged claw
|
|
3122
|
+
["claw_hammer", { item: "hammer" }]
|
|
2844
3123
|
];
|
|
3124
|
+
var hasThrowableModel = (def) => def.action?.kind === "throwable" && def.action.explosive !== void 0 && hasExplosiveModel(def.action.explosive);
|
|
3125
|
+
var buildThrowableModel = (THREE, def) => def.action?.kind === "throwable" && def.action.explosive !== void 0 ? buildExplosiveModel(THREE, def.action.explosive) : void 0;
|
|
2845
3126
|
var weaponPropsOver = (models) => {
|
|
2846
3127
|
const itemModelOf = (weaponId, items) => {
|
|
2847
3128
|
const id = models.get(weaponId)?.item ?? weaponId;
|
|
@@ -2857,7 +3138,7 @@ var weaponPropsOver = (models) => {
|
|
|
2857
3138
|
get: (weaponId) => models.get(weaponId),
|
|
2858
3139
|
itemModelOf,
|
|
2859
3140
|
buildItemModel,
|
|
2860
|
-
buildModel: (THREE, def, items) => buildItemModel(THREE, def, items) ?? buildProp(THREE, weaponProp(def))
|
|
3141
|
+
buildModel: (THREE, def, items) => buildItemModel(THREE, def, items) ?? buildThrowableModel(THREE, def) ?? buildProp(THREE, weaponProp(def))
|
|
2861
3142
|
};
|
|
2862
3143
|
};
|
|
2863
3144
|
var defaultProps;
|
|
@@ -2869,6 +3150,7 @@ var buildWeaponModel = (THREE, def, items) => defaultWeaponProps().buildModel(TH
|
|
|
2869
3150
|
|
|
2870
3151
|
// src/box-fx.ts
|
|
2871
3152
|
var EJECTS_ON_SHOT = /* @__PURE__ */ new Set(["pistol", "smg", "carbine", "rifle", "sniper", "shotgun"]);
|
|
3153
|
+
var SPOUTS = /* @__PURE__ */ new Set(["firearm", "flame", "heat", "extinguisher"]);
|
|
2872
3154
|
var DROPS_MAGAZINE = /* @__PURE__ */ new Set(["pistol", "smg", "carbine", "rifle", "sniper"]);
|
|
2873
3155
|
var CYCLES = /* @__PURE__ */ new Set(["shotgun_pump_12", "rifle_bolt_308"]);
|
|
2874
3156
|
var FALLBACK_ENERGY = 300;
|
|
@@ -2903,6 +3185,7 @@ function createBoxFx(options) {
|
|
|
2903
3185
|
const q = new THREE.Quaternion();
|
|
2904
3186
|
const q2 = new THREE.Quaternion();
|
|
2905
3187
|
const pointForward = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
|
|
3188
|
+
const frontOf = new THREE.Vector3();
|
|
2906
3189
|
const equip = (weapon) => {
|
|
2907
3190
|
if (model) hand.remove(model);
|
|
2908
3191
|
model = null;
|
|
@@ -2913,6 +3196,7 @@ function createBoxFx(options) {
|
|
|
2913
3196
|
const length = new THREE.Box3().setFromObject(model).getSize(v).x;
|
|
2914
3197
|
rear = new THREE.Box3().setFromObject(model).min.x;
|
|
2915
3198
|
lengthMetres = length;
|
|
3199
|
+
frontOf.copy(new THREE.Box3().setFromObject(model).getCenter(v)).setX(rear + length);
|
|
2916
3200
|
model.quaternion.copy(pointForward);
|
|
2917
3201
|
hand.add(model);
|
|
2918
3202
|
inHand = def.id;
|
|
@@ -3013,6 +3297,13 @@ function createBoxFx(options) {
|
|
|
3013
3297
|
inHand = null;
|
|
3014
3298
|
hold = null;
|
|
3015
3299
|
},
|
|
3300
|
+
muzzle() {
|
|
3301
|
+
if (!model || !def || !SPOUTS.has(def.action.kind)) return null;
|
|
3302
|
+
hand.updateMatrixWorld(true);
|
|
3303
|
+
const at = model.localToWorld(v.copy(frontOf));
|
|
3304
|
+
const along = v2.set(1, 0, 0).applyQuaternion(model.getWorldQuaternion(q2)).normalize();
|
|
3305
|
+
return { position: [at.x, at.y, at.z], direction: [along.x, along.y, along.z], drawsFlash: false };
|
|
3306
|
+
},
|
|
3016
3307
|
handTargets() {
|
|
3017
3308
|
if (!model || !hold) return null;
|
|
3018
3309
|
hand.updateMatrixWorld(true);
|
|
@@ -3064,7 +3355,7 @@ function createBoxFx(options) {
|
|
|
3064
3355
|
}
|
|
3065
3356
|
|
|
3066
3357
|
// src/models/index.ts
|
|
3067
|
-
import { markKitOrigin as
|
|
3358
|
+
import { markKitOrigin as markKitOrigin3 } from "@adatechnology/game-contracts";
|
|
3068
3359
|
import { WEAPONS } from "@adatechnology/game-weapons";
|
|
3069
3360
|
|
|
3070
3361
|
// src/data/models.json
|
|
@@ -4617,302 +4908,74 @@ var models_default = {
|
|
|
4617
4908
|
options: {
|
|
4618
4909
|
rpm: 3e3
|
|
4619
4910
|
}
|
|
4911
|
+
},
|
|
4912
|
+
m79: {
|
|
4913
|
+
builder: "breakLauncher",
|
|
4914
|
+
caliber: "40\xD746",
|
|
4915
|
+
length: 730,
|
|
4916
|
+
barrel: 356,
|
|
4917
|
+
options: {
|
|
4918
|
+
stock: "fixed",
|
|
4919
|
+
wood: 1,
|
|
4920
|
+
mag: "none",
|
|
4921
|
+
hg: "wood",
|
|
4922
|
+
hgFrac: 0.4,
|
|
4923
|
+
br: 0.022,
|
|
4924
|
+
hR: 0.05
|
|
4925
|
+
}
|
|
4620
4926
|
}
|
|
4621
4927
|
};
|
|
4622
4928
|
|
|
4623
|
-
// src/models/
|
|
4624
|
-
|
|
4929
|
+
// src/models/break-action.ts
|
|
4930
|
+
function buildBreakAction(kit, options) {
|
|
4931
|
+
const { M, box: box2, cylinderX, sphere } = kit;
|
|
4932
|
+
const group = kit.group();
|
|
4933
|
+
const L = (options.L ?? 0) / 1e3;
|
|
4934
|
+
const barrel = (options.B ?? 0) / 1e3;
|
|
4935
|
+
const parts = { family: "break", kick: 1.6, glow: [] };
|
|
4936
|
+
box2(group, 0.09, 0.05, 0.042, M.steel, L - barrel - 0.04, -5e-3, 0);
|
|
4937
|
+
for (let i = 0; i < 4; i++) box2(group, 0.05, 2e-3, 0.043, M.dark, L - barrel - 0.04, 0.01 - i * 8e-3, 0);
|
|
4938
|
+
const barrels = kit.pivot(group, L - barrel, -0.01, 0);
|
|
4939
|
+
parts.barrels = barrels;
|
|
4940
|
+
heatify(parts.glow, cylinderX(barrels, 0.0105, barrel, M.steel, barrel / 2, 0.01, 0.011, 18));
|
|
4941
|
+
heatify(parts.glow, cylinderX(barrels, 0.0105, barrel, M.steel, barrel / 2, 0.01, -0.011, 18));
|
|
4942
|
+
box2(barrels, barrel, 4e-3, 8e-3, M.metal, barrel / 2, 0.022, 0);
|
|
4943
|
+
sphere(barrels, 2e-3, M.white, barrel - 0.01, 0.026, 0, 1);
|
|
4944
|
+
cylinderX(barrels, 75e-4, 4e-3, M.hole, barrel + 1e-3, 0.01, 0.011, 12);
|
|
4945
|
+
cylinderX(barrels, 75e-4, 4e-3, M.hole, barrel + 1e-3, 0.01, -0.011, 12);
|
|
4946
|
+
box2(barrels, 0.22, 0.03, 0.038, M.wood, 0.12, -0.01, 0);
|
|
4947
|
+
parts.breech = [kit.mark(barrels, 4e-3, 0.01, 0.011), kit.mark(barrels, 4e-3, 0.01, -0.011)];
|
|
4948
|
+
box2(group, 0.12, 0.042, 0.032, M.wood, L - barrel - 0.14, -0.022, 0, 0.14);
|
|
4949
|
+
box2(group, 0.28, 0.07, 0.036, M.wood, 0.15, -0.05, 0, 0.08);
|
|
4950
|
+
box2(group, 0.012, 0.13, 0.04, M.rubber, 6e-3, -0.06, 0);
|
|
4951
|
+
box2(group, 4e-3, 0.014, 4e-3, M.dark, L - barrel - 0.05, -0.04, 0);
|
|
4952
|
+
parts.trigger = box2(group, 4e-3, 0.014, 4e-3, M.dark, L - barrel - 0.035, -0.04, 0);
|
|
4953
|
+
box2(group, 0.04, 4e-3, 0.01, M.steel, L - barrel - 0.045, -0.05, 0);
|
|
4954
|
+
box2(group, 0.012, 0.016, 6e-3, M.dark, L - barrel - 0.08, 0.022, 0.012, 0.5);
|
|
4955
|
+
box2(group, 0.012, 0.016, 6e-3, M.dark, L - barrel - 0.08, 0.022, -0.012, 0.5);
|
|
4956
|
+
parts.safety = box2(group, 0.02, 6e-3, 8e-3, M.steel, L - barrel - 0.07, 0.025, 0);
|
|
4957
|
+
parts.muzzle = kit.mark(barrels, barrel + 0.01, 0.01, 0);
|
|
4958
|
+
parts.eject = parts.breech[0];
|
|
4959
|
+
return { group, parts };
|
|
4960
|
+
}
|
|
4625
4961
|
|
|
4626
|
-
// src/models/
|
|
4627
|
-
|
|
4628
|
-
const
|
|
4629
|
-
const
|
|
4630
|
-
const
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
projected.normalize();
|
|
4634
|
-
const arcUvRatio = 0.5 * arcLength / (arcLength + centerLength);
|
|
4635
|
-
const arcAngleRatio = 1 - projected.angleTo(faceDirection) / halfArc;
|
|
4636
|
-
if (Math.sign(projected[uvAxis]) === 1) return arcAngleRatio * arcUvRatio;
|
|
4637
|
-
const centerUv = centerLength / (arcLength + centerLength);
|
|
4638
|
-
return centerUv + arcUvRatio + arcUvRatio * (1 - arcAngleRatio);
|
|
4639
|
-
};
|
|
4640
|
-
var FACES = [
|
|
4641
|
-
{ direction: [1, 0, 0], u: ["z", "y", false], v: ["y", "z", true] },
|
|
4642
|
-
{ direction: [-1, 0, 0], u: ["z", "y", true], v: ["y", "z", true] },
|
|
4643
|
-
{ direction: [0, 1, 0], u: ["x", "z", true], v: ["z", "x", false] },
|
|
4644
|
-
{ direction: [0, -1, 0], u: ["x", "z", true], v: ["z", "x", true] },
|
|
4645
|
-
{ direction: [0, 0, 1], u: ["x", "y", true], v: ["y", "x", true] },
|
|
4646
|
-
{ direction: [0, 0, -1], u: ["x", "y", false], v: ["y", "x", true] }
|
|
4647
|
-
];
|
|
4648
|
-
function createRoundedBoxGeometry(THREE, width, height, depth, segments, radius) {
|
|
4649
|
-
const count = segments * 2 + 1;
|
|
4650
|
-
const rounding = Math.min(width / 2, height / 2, depth / 2, radius);
|
|
4651
|
-
const geometry = new THREE.BoxGeometry(1, 1, 1, count, count, count);
|
|
4652
|
-
const flat2 = geometry.toNonIndexed();
|
|
4653
|
-
geometry.setIndex(null);
|
|
4654
|
-
geometry.setAttribute("position", flat2.attributes.position);
|
|
4655
|
-
geometry.setAttribute("normal", flat2.attributes.normal);
|
|
4656
|
-
geometry.setAttribute("uv", flat2.attributes.uv);
|
|
4657
|
-
const position = new THREE.Vector3();
|
|
4658
|
-
const normal = new THREE.Vector3();
|
|
4659
|
-
const box2 = new THREE.Vector3(width, height, depth).divideScalar(2).subScalar(rounding);
|
|
4660
|
-
const positions = geometry.attributes.position.array;
|
|
4661
|
-
const normals = geometry.attributes.normal.array;
|
|
4662
|
-
const uvs = geometry.attributes.uv.array;
|
|
4663
|
-
const faceTriangles = positions.length / 6;
|
|
4664
|
-
const halfSegment = 0.5 / count;
|
|
4665
|
-
const sides = { x: width, y: height, z: depth };
|
|
4666
|
-
for (let i = 0, j = 0; i < positions.length; i += 3, j += 2) {
|
|
4667
|
-
position.fromArray(positions, i);
|
|
4668
|
-
normal.copy(position);
|
|
4669
|
-
normal.x -= Math.sign(normal.x) * halfSegment;
|
|
4670
|
-
normal.y -= Math.sign(normal.y) * halfSegment;
|
|
4671
|
-
normal.z -= Math.sign(normal.z) * halfSegment;
|
|
4672
|
-
normal.normalize();
|
|
4673
|
-
positions[i] = box2.x * Math.sign(position.x) + normal.x * rounding;
|
|
4674
|
-
positions[i + 1] = box2.y * Math.sign(position.y) + normal.y * rounding;
|
|
4675
|
-
positions[i + 2] = box2.z * Math.sign(position.z) + normal.z * rounding;
|
|
4676
|
-
normals[i] = normal.x;
|
|
4677
|
-
normals[i + 1] = normal.y;
|
|
4678
|
-
normals[i + 2] = normal.z;
|
|
4679
|
-
const face = FACES[Math.floor(i / faceTriangles)];
|
|
4680
|
-
if (!face) continue;
|
|
4681
|
-
const direction = new THREE.Vector3(...face.direction);
|
|
4682
|
-
for (const [offset, [uvAxis, projectionAxis, mirrored]] of [[0, face.u], [1, face.v]]) {
|
|
4683
|
-
const value = uvAlong(THREE, direction, normal, uvAxis, projectionAxis, rounding, sides[uvAxis]);
|
|
4684
|
-
uvs[j + offset] = mirrored ? 1 - value : value;
|
|
4685
|
-
}
|
|
4686
|
-
}
|
|
4687
|
-
return geometry;
|
|
4688
|
-
}
|
|
4689
|
-
|
|
4690
|
-
// src/models/kit.ts
|
|
4691
|
-
var PI = Math.PI;
|
|
4692
|
-
var createMaterials = (THREE) => {
|
|
4693
|
-
const standard = (color, roughness = 0.7, metalness = 0.2, extra = {}) => new THREE.MeshStandardMaterial({ color, roughness, metalness, ...extra });
|
|
4694
|
-
const basic = (color, extra = {}) => new THREE.MeshBasicMaterial({ color, ...extra });
|
|
4695
|
-
const additive = { transparent: true, opacity: 0.95, blending: THREE.AdditiveBlending, depthWrite: false };
|
|
4696
|
-
const materials = {
|
|
4697
|
-
metal: standard(3422010, 0.42, 0.75),
|
|
4698
|
-
steel: standard(7106418, 0.32, 0.85),
|
|
4699
|
-
steelL: standard(9080208, 0.28, 0.9),
|
|
4700
|
-
dark: standard(1711133, 0.55, 0.5),
|
|
4701
|
-
poly: standard(2369058, 0.8, 0.05),
|
|
4702
|
-
olive: standard(4936241, 0.8, 0.05),
|
|
4703
|
-
tan: standard(10259043, 0.8, 0.05),
|
|
4704
|
-
wood: standard(4860951, 0.55, 0),
|
|
4705
|
-
woodL: standard(6175263, 0.55, 0),
|
|
4706
|
-
brass: standard(12819013, 0.28, 0.9),
|
|
4707
|
-
copper: standard(11561531, 0.3, 0.85),
|
|
4708
|
-
lead: standard(7171955, 0.5, 0.5),
|
|
4709
|
-
shell: standard(10692380, 0.5, 0.05),
|
|
4710
|
-
glass: standard(8364968, 0.05, 0.1, { transparent: true, opacity: 0.42 }),
|
|
4711
|
-
lens: standard(2311770, 0.05, 0.3, { transparent: true, opacity: 0.9, emissive: 399392 }),
|
|
4712
|
-
rubber: standard(1381653, 0.85, 0),
|
|
4713
|
-
white: standard(13617332, 0.8, 0),
|
|
4714
|
-
hole: standard(526343, 1, 0),
|
|
4715
|
-
bake: standard(5911072, 0.55, 0),
|
|
4716
|
-
rust: standard(7027230, 0.95, 0.3),
|
|
4717
|
-
rustD: standard(4860440, 0.95, 0.25),
|
|
4718
|
-
worn: standard(5593178, 0.6, 0.6),
|
|
4719
|
-
fire: basic(16742946),
|
|
4720
|
-
fire2: basic(16764762),
|
|
4721
|
-
flashA: basic(16757575, additive),
|
|
4722
|
-
flashB: basic(16773568, additive),
|
|
4723
|
-
smokeP: standard(9079430, 1, 0, { transparent: true, opacity: 0.35, depthWrite: false }),
|
|
4724
|
-
/** Launcher paints. */
|
|
4725
|
-
yellow: standard(11570978, 0.6, 0),
|
|
4726
|
-
red: standard(9313300, 0.45, 0.1),
|
|
4727
|
-
redPaint: standard(10691354, 0.35, 0.2),
|
|
4728
|
-
tape: standard(9079944, 0.9, 0),
|
|
4729
|
-
pipe: standard(10115634, 0.35, 0.8),
|
|
4730
|
-
green: standard(3818536, 0.75, 0.05),
|
|
4731
|
-
/** Magazine finishes named by the options. */
|
|
4732
|
-
bakelite: standard(6958620, 0.6, 0),
|
|
4733
|
-
polyMag: standard(2763302, 0.85, 0)
|
|
4734
|
-
};
|
|
4735
|
-
markShared(...Object.values(materials));
|
|
4736
|
-
return materials;
|
|
4737
|
-
};
|
|
4738
|
-
var kits = /* @__PURE__ */ new WeakMap();
|
|
4739
|
-
function modelKit(host) {
|
|
4740
|
-
const cached = kits.get(host);
|
|
4741
|
-
if (cached) return cached;
|
|
4742
|
-
const THREE = shapeGeometries2(host);
|
|
4743
|
-
const geometries = /* @__PURE__ */ new Map();
|
|
4744
|
-
const shadowed = (mesh) => {
|
|
4745
|
-
mesh.castShadow = true;
|
|
4746
|
-
mesh.receiveShadow = true;
|
|
4747
|
-
return mesh;
|
|
4748
|
-
};
|
|
4749
|
-
const place = (parent, mesh, x, y, z) => {
|
|
4750
|
-
mesh.position.set(x, y, z);
|
|
4751
|
-
parent.add(mesh);
|
|
4752
|
-
return mesh;
|
|
4753
|
-
};
|
|
4754
|
-
const kit = {
|
|
4755
|
-
THREE,
|
|
4756
|
-
M: createMaterials(THREE),
|
|
4757
|
-
roundness: null,
|
|
4758
|
-
group: () => new THREE.Group(),
|
|
4759
|
-
box(parent, w, h, d, material, x, y, z, rz = 0, ry = 0, rx = 0) {
|
|
4760
|
-
const radius = Math.min(w, h, d) * (kit.roundness ?? 0.2);
|
|
4761
|
-
const key = `${w.toFixed(4)},${h.toFixed(4)},${d.toFixed(4)},${radius.toFixed(5)}`;
|
|
4762
|
-
let geometry = geometries.get(key);
|
|
4763
|
-
if (!geometry) {
|
|
4764
|
-
geometry = radius > 25e-5 ? createRoundedBoxGeometry(THREE, w, h, d, 2, radius) : new THREE.BoxGeometry(w, h, d);
|
|
4765
|
-
markShared(geometry);
|
|
4766
|
-
geometries.set(key, geometry);
|
|
4767
|
-
}
|
|
4768
|
-
const mesh = place(parent, shadowed(new THREE.Mesh(geometry, material)), x, y, z);
|
|
4769
|
-
mesh.rotation.set(rx, ry, rz);
|
|
4770
|
-
return mesh;
|
|
4771
|
-
},
|
|
4772
|
-
cylinderX(parent, radius, length, material, x, y, z, segments = 16, radiusEnd) {
|
|
4773
|
-
const mesh = shadowed(new THREE.Mesh(new THREE.CylinderGeometry(radiusEnd ?? radius, radius, length, segments), material));
|
|
4774
|
-
mesh.rotation.z = -PI / 2;
|
|
4775
|
-
return place(parent, mesh, x, y, z);
|
|
4776
|
-
},
|
|
4777
|
-
cylinderY(parent, radius, height, material, x, y, z, segments = 16, radiusEnd) {
|
|
4778
|
-
return place(parent, shadowed(new THREE.Mesh(new THREE.CylinderGeometry(radiusEnd ?? radius, radius, height, segments), material)), x, y, z);
|
|
4779
|
-
},
|
|
4780
|
-
cylinderZ(parent, radius, length, material, x, y, z, segments = 16) {
|
|
4781
|
-
const mesh = shadowed(new THREE.Mesh(new THREE.CylinderGeometry(radius, radius, length, segments), material));
|
|
4782
|
-
mesh.rotation.x = PI / 2;
|
|
4783
|
-
return place(parent, mesh, x, y, z);
|
|
4784
|
-
},
|
|
4785
|
-
sphere(parent, radius, material, x, y, z, detail = 1) {
|
|
4786
|
-
return place(parent, shadowed(new THREE.Mesh(new THREE.IcosahedronGeometry(radius, detail), material)), x, y, z);
|
|
4787
|
-
},
|
|
4788
|
-
torus: (parent, geometry, material, x, y, z) => place(parent, shadowed(new THREE.Mesh(geometry, material)), x, y, z),
|
|
4789
|
-
mark(parent, x, y, z) {
|
|
4790
|
-
const object = new THREE.Object3D();
|
|
4791
|
-
object.position.set(x, y, z);
|
|
4792
|
-
parent.add(object);
|
|
4793
|
-
return object;
|
|
4794
|
-
},
|
|
4795
|
-
pivot(parent, x = 0, y = 0, z = 0) {
|
|
4796
|
-
const group = new THREE.Group();
|
|
4797
|
-
group.position.set(x, y, z);
|
|
4798
|
-
parent.add(group);
|
|
4799
|
-
return group;
|
|
4800
|
-
}
|
|
4801
|
-
};
|
|
4802
|
-
kits.set(host, kit);
|
|
4803
|
-
return kit;
|
|
4804
|
-
}
|
|
4805
|
-
function heatify(glow, mesh) {
|
|
4806
|
-
mesh.material = mesh.material.clone();
|
|
4807
|
-
glow.push(mesh);
|
|
4808
|
-
return mesh;
|
|
4809
|
-
}
|
|
4810
|
-
|
|
4811
|
-
// src/models/break-action.ts
|
|
4812
|
-
function buildBreakAction(kit, options) {
|
|
4813
|
-
const { M, box: box2, cylinderX, sphere } = kit;
|
|
4814
|
-
const group = kit.group();
|
|
4815
|
-
const L = (options.L ?? 0) / 1e3;
|
|
4816
|
-
const barrel = (options.B ?? 0) / 1e3;
|
|
4817
|
-
const parts = { family: "break", kick: 1.6, glow: [] };
|
|
4818
|
-
box2(group, 0.09, 0.05, 0.042, M.steel, L - barrel - 0.04, -5e-3, 0);
|
|
4819
|
-
for (let i = 0; i < 4; i++) box2(group, 0.05, 2e-3, 0.043, M.dark, L - barrel - 0.04, 0.01 - i * 8e-3, 0);
|
|
4820
|
-
const barrels = kit.pivot(group, L - barrel, -0.01, 0);
|
|
4821
|
-
parts.barrels = barrels;
|
|
4822
|
-
heatify(parts.glow, cylinderX(barrels, 0.0105, barrel, M.steel, barrel / 2, 0.01, 0.011, 18));
|
|
4823
|
-
heatify(parts.glow, cylinderX(barrels, 0.0105, barrel, M.steel, barrel / 2, 0.01, -0.011, 18));
|
|
4824
|
-
box2(barrels, barrel, 4e-3, 8e-3, M.metal, barrel / 2, 0.022, 0);
|
|
4825
|
-
sphere(barrels, 2e-3, M.white, barrel - 0.01, 0.026, 0, 1);
|
|
4826
|
-
cylinderX(barrels, 75e-4, 4e-3, M.hole, barrel + 1e-3, 0.01, 0.011, 12);
|
|
4827
|
-
cylinderX(barrels, 75e-4, 4e-3, M.hole, barrel + 1e-3, 0.01, -0.011, 12);
|
|
4828
|
-
box2(barrels, 0.22, 0.03, 0.038, M.wood, 0.12, -0.01, 0);
|
|
4829
|
-
parts.breech = [kit.mark(barrels, 4e-3, 0.01, 0.011), kit.mark(barrels, 4e-3, 0.01, -0.011)];
|
|
4830
|
-
box2(group, 0.12, 0.042, 0.032, M.wood, L - barrel - 0.14, -0.022, 0, 0.14);
|
|
4831
|
-
box2(group, 0.28, 0.07, 0.036, M.wood, 0.15, -0.05, 0, 0.08);
|
|
4832
|
-
box2(group, 0.012, 0.13, 0.04, M.rubber, 6e-3, -0.06, 0);
|
|
4833
|
-
box2(group, 4e-3, 0.014, 4e-3, M.dark, L - barrel - 0.05, -0.04, 0);
|
|
4834
|
-
parts.trigger = box2(group, 4e-3, 0.014, 4e-3, M.dark, L - barrel - 0.035, -0.04, 0);
|
|
4835
|
-
box2(group, 0.04, 4e-3, 0.01, M.steel, L - barrel - 0.045, -0.05, 0);
|
|
4836
|
-
box2(group, 0.012, 0.016, 6e-3, M.dark, L - barrel - 0.08, 0.022, 0.012, 0.5);
|
|
4837
|
-
box2(group, 0.012, 0.016, 6e-3, M.dark, L - barrel - 0.08, 0.022, -0.012, 0.5);
|
|
4838
|
-
parts.safety = box2(group, 0.02, 6e-3, 8e-3, M.steel, L - barrel - 0.07, 0.025, 0);
|
|
4839
|
-
parts.muzzle = kit.mark(barrels, barrel + 0.01, 0.01, 0);
|
|
4840
|
-
parts.eject = parts.breech[0];
|
|
4841
|
-
return { group, parts };
|
|
4962
|
+
// src/models/attachments/muzzle-brake.ts
|
|
4963
|
+
function buildBrake(kit, parent, kind, x, y, barrelRadius, heat = () => void 0) {
|
|
4964
|
+
const { M, box: box2, cylinderX } = kit;
|
|
4965
|
+
const scale = kind === 2 ? 3.2 : 2;
|
|
4966
|
+
const length = kind === 2 ? 0.12 : 0.06;
|
|
4967
|
+
heat(cylinderX(parent, barrelRadius * scale, length, M.dark, x - length / 2, y, 0, kind === 2 ? 8 : 16));
|
|
4968
|
+
for (let i = 0; i < 3; i++) box2(parent, length * 0.16, barrelRadius * scale * 1.3, barrelRadius * scale * 2.2, M.hole, x - length * 0.25 - i * length * 0.25, y, 0);
|
|
4842
4969
|
}
|
|
4843
4970
|
|
|
4844
|
-
// src/models/
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
var RECEIVER_HEIGHT_FRACTION = 0.4;
|
|
4850
|
-
var DEFAULT_GRIP_OFFSET = 0.07;
|
|
4851
|
-
var HANDGUARD_FRACTION = 0.5;
|
|
4852
|
-
function deriveFrames(THREE, model) {
|
|
4853
|
-
const { root, inner, parts } = model;
|
|
4854
|
-
root.updateMatrixWorld(true);
|
|
4855
|
-
const box2 = new THREE.Box3().setFromObject(root);
|
|
4856
|
-
const span = box2.max.x - box2.min.x;
|
|
4857
|
-
const toInnerX = (x) => (x - inner.position.x) / inner.scale.x;
|
|
4858
|
-
const muzzle = parts.muzzle?.position;
|
|
4859
|
-
const length = muzzle ? muzzle.x - 0.01 : toInnerX(box2.max.x);
|
|
4860
|
-
const receiverStart = toInnerX(box2.min.x + span * RECEIVER_START_FRACTION);
|
|
4861
|
-
const receiverEnd = toInnerX(box2.min.x + span * RECEIVER_END_FRACTION);
|
|
4862
|
-
return {
|
|
4863
|
-
length,
|
|
4864
|
-
barrelY: muzzle?.y ?? (box2.max.y + box2.min.y) / 2,
|
|
4865
|
-
barrelRadius: DEFAULT_BARREL_RADIUS,
|
|
4866
|
-
receiverStart,
|
|
4867
|
-
receiverEnd,
|
|
4868
|
-
receiverHeight: (box2.max.y - box2.min.y) * RECEIVER_HEIGHT_FRACTION,
|
|
4869
|
-
receiverWidth: Math.min(DEFAULT_RECEIVER_WIDTH, box2.max.z - box2.min.z),
|
|
4870
|
-
handguardEnd: receiverEnd + (length - receiverEnd) * HANDGUARD_FRACTION,
|
|
4871
|
-
magazineX: parts.mag ? parts.mag.position.x : (receiverStart + receiverEnd) / 2,
|
|
4872
|
-
gripX: receiverStart + DEFAULT_GRIP_OFFSET,
|
|
4873
|
-
hasRail: false
|
|
4874
|
-
};
|
|
4971
|
+
// src/models/capture.ts
|
|
4972
|
+
function captured(parent, draw) {
|
|
4973
|
+
const before = parent.children.length;
|
|
4974
|
+
draw();
|
|
4975
|
+
return parent.children.slice(before);
|
|
4875
4976
|
}
|
|
4876
|
-
function
|
|
4877
|
-
|
|
4878
|
-
if (!frames) return void 0;
|
|
4879
|
-
const { inner } = model;
|
|
4880
|
-
const toRoot = (x, y, z) => [inner.position.x + x * inner.scale.x, y, z];
|
|
4881
|
-
const handguardHeight = frames.receiverHeight * 0.8;
|
|
4882
|
-
const railTopY = frames.receiverHeight / 2 + (frames.hasRail ? 6e-3 : 0);
|
|
4883
|
-
const forendMiddle = (frames.receiverEnd + frames.handguardEnd) / 2;
|
|
4884
|
-
const base = { mount, barrelRadius: frames.barrelRadius, receiverWidth: frames.receiverWidth, receiverHeight: frames.receiverHeight, hasRail: frames.hasRail };
|
|
4885
|
-
switch (mount) {
|
|
4886
|
-
case "muzzle":
|
|
4887
|
-
return { ...base, position: toRoot(frames.length, frames.barrelY, 0), side: 0 };
|
|
4888
|
-
case "rail_top":
|
|
4889
|
-
return { ...base, position: toRoot((frames.receiverStart + frames.receiverEnd) / 2 + 0.03, railTopY, 0), side: 0 };
|
|
4890
|
-
case "rail_bottom":
|
|
4891
|
-
return { ...base, position: toRoot(forendMiddle, frames.barrelY - handguardHeight / 2, 0), side: 0 };
|
|
4892
|
-
case "rail_left":
|
|
4893
|
-
return { ...base, position: toRoot(forendMiddle, frames.barrelY, -(frames.receiverWidth * 0.54 + 4e-3)), side: -1 };
|
|
4894
|
-
case "rail_right":
|
|
4895
|
-
return { ...base, position: toRoot(forendMiddle, frames.barrelY, frames.receiverWidth * 0.54 + 4e-3), side: 1 };
|
|
4896
|
-
case "underbarrel": {
|
|
4897
|
-
const [x, y] = frames.underbarrel ?? [frames.receiverEnd + (frames.handguardEnd - frames.receiverEnd) * 0.25, frames.barrelY - handguardHeight / 2 - 0.02];
|
|
4898
|
-
return { ...base, position: toRoot(x, y, 0), side: 0 };
|
|
4899
|
-
}
|
|
4900
|
-
case "magazine":
|
|
4901
|
-
return { ...base, position: toRoot(frames.magazineX, -frames.receiverHeight / 2, 0), side: 0 };
|
|
4902
|
-
case "feed": {
|
|
4903
|
-
const belt = model.parts.belt?.position;
|
|
4904
|
-
return { ...base, position: belt ? toRoot(belt.x, belt.y, belt.z) : toRoot(frames.magazineX + 0.02, -frames.receiverHeight / 2 - 0.05, -0.045), side: -1 };
|
|
4905
|
-
}
|
|
4906
|
-
case "sling":
|
|
4907
|
-
return {
|
|
4908
|
-
...base,
|
|
4909
|
-
position: toRoot(frames.receiverEnd + (frames.length - frames.receiverEnd) * 0.45, -frames.receiverHeight / 2 - 0.03, 0),
|
|
4910
|
-
secondary: toRoot(0.08, -0.09, 0),
|
|
4911
|
-
side: 0
|
|
4912
|
-
};
|
|
4913
|
-
default:
|
|
4914
|
-
return void 0;
|
|
4915
|
-
}
|
|
4977
|
+
function recordFitting(parts, id, parent, draw) {
|
|
4978
|
+
parts.fittings = { ...parts.fittings, [id]: captured(parent, draw) };
|
|
4916
4979
|
}
|
|
4917
4980
|
|
|
4918
4981
|
// src/models/details.ts
|
|
@@ -4945,1153 +5008,1231 @@ function scope(kit, parent, kind, cx, cy, cz = 0) {
|
|
|
4945
5008
|
cylinderX(parent, 0.017, 2e-3, M.lens, cx + 0.073, cy + 0.032, cz, 18);
|
|
4946
5009
|
cylinderY(parent, 7e-3, 0.012, M.dark, cx, cy + 0.052, cz, 12);
|
|
4947
5010
|
box2(parent, 0.03, 0.01, 0.012, M.dark, cx - 0.01, cy + 0.054, cz);
|
|
4948
|
-
return;
|
|
4949
|
-
}
|
|
4950
|
-
const sleeve = kind === 4 ? 0.2 : 0.32;
|
|
4951
|
-
cylinderX(parent, 0.0135, sleeve * 0.55, M.dark, cx, cy + 0.045, cz, 18);
|
|
4952
|
-
cylinderX(parent, 0.0135, sleeve * 0.25, M.dark, cx + sleeve * 0.36, cy + 0.045, cz, 18, 0.026);
|
|
4953
|
-
cylinderX(parent, 0.026, 0.05, M.dark, cx + sleeve * 0.5, cy + 0.045, cz, 18);
|
|
4954
|
-
cylinderX(parent, 0.024, 2e-3, M.lens, cx + sleeve * 0.5 + 0.026, cy + 0.045, cz, 18);
|
|
4955
|
-
cylinderX(parent, 0.019, 0.06, M.dark, cx - sleeve * 0.38, cy + 0.045, cz, 18, 0.0135);
|
|
4956
|
-
cylinderX(parent, 0.019, 0.035, M.rubber, cx - sleeve * 0.38 - 0.045, cy + 0.045, cz, 18);
|
|
4957
|
-
cylinderX(parent, 0.017, 2e-3, M.lens, cx - sleeve * 0.38 - 0.063, cy + 0.045, cz, 18);
|
|
4958
|
-
cylinderY(parent, 0.01, 0.022, M.dark, cx, cy + 0.066, cz, 14);
|
|
4959
|
-
cylinderY(parent, 0.011, 4e-3, M.metal, cx, cy + 0.078, cz, 14);
|
|
4960
|
-
cylinderZ(parent, 0.01, 0.022, M.dark, cx, cy + 0.045, cz + 0.022, 14);
|
|
4961
|
-
for (const offset of [-0.07, 0.07]) {
|
|
4962
|
-
const ring = kit.torus(parent, new THREE.TorusGeometry(0.0155, 3e-3, 8, 20), M.dark, cx + offset, cy + 0.045, cz);
|
|
4963
|
-
ring.rotation.y = PI2 / 2;
|
|
4964
|
-
box2(parent, 0.016, 0.03, 0.022, M.dark, cx + offset, cy + 0.018, cz);
|
|
4965
|
-
}
|
|
4966
|
-
}
|
|
4967
|
-
var buttpad = (kit, parent, x, y, height, width) => void kit.box(parent, 0.012, height, width, kit.M.rubber, x, y, 0);
|
|
4968
|
-
var swivel = (kit, parent, x, y) => void kit.torus(parent, new kit.THREE.TorusGeometry(6e-3, 15e-4, 6, 12), kit.M.metal, x, y, 0);
|
|
4969
|
-
|
|
4970
|
-
// src/models/bullpup.ts
|
|
4971
|
-
function buildBullpup(kit, options) {
|
|
4972
|
-
const { M, box: box2, cylinderX } = kit;
|
|
4973
|
-
const group = kit.group();
|
|
4974
|
-
const L = (options.L ?? 0) / 1e3;
|
|
4975
|
-
const barrel = (options.B ?? 0) / 1e3;
|
|
4976
|
-
const bodyLength = Math.max(0.32, L - barrel * 0.72);
|
|
4977
|
-
const body = options.shot ? M.poly : M.olive;
|
|
4978
|
-
const parts = { family: options.shot ? "pump" : "rifle", stroke: 0.06, glow: [] };
|
|
4979
|
-
box2(group, bodyLength, 0.075, 0.042, body, bodyLength / 2, 0, 0);
|
|
4980
|
-
box2(group, bodyLength * 0.9, 0.02, 0.044, M.dark, bodyLength * 0.5, -0.02, 0);
|
|
4981
|
-
box2(group, 0.032, 0.13, 0.044, M.rubber, 0.016, -0.025, 0);
|
|
4982
|
-
const gx = bodyLength * 0.8;
|
|
4983
|
-
const grip = kit.pivot(group, gx, -0.085, 0);
|
|
4984
|
-
grip.rotation.z = -0.25;
|
|
4985
|
-
parts.grip = grip;
|
|
4986
|
-
box2(grip, 0.03, 0.1, 0.03, M.poly, 0, 0, 0);
|
|
4987
|
-
box2(group, 0.1, 6e-3, 0.03, body, gx + 0.01, -0.06, 0);
|
|
4988
|
-
parts.trigger = box2(group, 4e-3, 0.016, 4e-3, M.dark, gx + 0.02, -0.05, 0, 0.15);
|
|
4989
|
-
heatify(parts.glow, cylinderX(group, options.shot ? 0.0105 : 85e-4, barrel, M.metal, L - barrel / 2, 0.012, 0, 16));
|
|
4990
|
-
cylinderX(group, 6e-3, 4e-3, M.hole, L + 1e-3, 0.012, 0, 12);
|
|
4991
|
-
box2(group, 0.05, 0.024, 4e-3, M.hole, bodyLength * 0.25, 5e-3, 0.0212);
|
|
4992
|
-
const bolt = kit.pivot(group);
|
|
4993
|
-
parts.bolt = bolt;
|
|
4994
|
-
box2(bolt, 0.044, 0.02, 6e-3, M.steelL, bodyLength * 0.25, 5e-3, 0.02);
|
|
4995
|
-
if (options.shot) {
|
|
4996
|
-
cylinderX(group, 0.012, bodyLength * 0.75, M.metal, bodyLength * 0.55, -0.025, 0.014, 14);
|
|
4997
|
-
cylinderX(group, 0.012, bodyLength * 0.75, M.metal, bodyLength * 0.55, -0.025, -0.014, 14);
|
|
4998
|
-
const pump = kit.pivot(group);
|
|
4999
|
-
parts.pump = pump;
|
|
5000
|
-
box2(pump, 0.15, 0.045, 0.052, M.poly, bodyLength + 0.06, -0.015, 0);
|
|
5001
|
-
for (let i = 0; i < 6; i++) box2(pump, 6e-3, 0.047, 0.054, M.dark, bodyLength + 5e-3 + i * 0.022, -0.015, 0);
|
|
5002
|
-
rail(kit, group, bodyLength * 0.15, bodyLength * 0.8, 0.04, 0, 0.02);
|
|
5003
|
-
parts.loadPort = kit.mark(group, bodyLength * 0.2, -0.04, 0);
|
|
5004
|
-
} else {
|
|
5005
|
-
const magazine = kit.pivot(group, gx - 0.11, -0.03, 0);
|
|
5006
|
-
magazine.rotation.z = 0.14;
|
|
5007
|
-
parts.mag = magazine;
|
|
5008
|
-
box2(magazine, 0.05, 0.14, 0.026, M.glass, 0, -0.07, 0);
|
|
5009
|
-
for (let i = 0; i < 6; i++) cylinderX(magazine, 3e-3, 0.04, M.brass, 0, -0.01 - i * 0.02, 0, 6);
|
|
5010
|
-
parts.magDrop = 0.18;
|
|
5011
|
-
scope(kit, group, 2, bodyLength * 0.5, 0.04, 0);
|
|
5012
|
-
box2(group, 0.2, 0.03, 0.02, body, bodyLength * 0.62, 0.048, 0);
|
|
5013
|
-
box2(group, 0.026, 0.075, 0.026, body, bodyLength + 0.05, -0.05, 0, 0.1);
|
|
5014
|
-
}
|
|
5015
|
-
parts.muzzle = kit.mark(group, L + 0.01, 0.012, 0);
|
|
5016
|
-
parts.eject = kit.mark(group, bodyLength * 0.25, 5e-3, 0.03);
|
|
5017
|
-
return { group, parts };
|
|
5018
|
-
}
|
|
5019
|
-
|
|
5020
|
-
// src/models/launcher-flame.ts
|
|
5021
|
-
var hose = (kit, group, points, radius, material) => {
|
|
5022
|
-
const { THREE } = kit;
|
|
5023
|
-
const curve = new THREE.CatmullRomCurve3(points.map((point) => new THREE.Vector3(...point)));
|
|
5024
|
-
const tube = new THREE.Mesh(new THREE.TubeGeometry(curve, 40, radius, 8, false), material);
|
|
5025
|
-
tube.castShadow = tube.receiveShadow = true;
|
|
5026
|
-
group.add(tube);
|
|
5027
|
-
};
|
|
5028
|
-
var pilot = (kit, group, x, y) => {
|
|
5029
|
-
const { M, cylinderX } = kit;
|
|
5030
|
-
cylinderX(group, 6e-3, 0.03, M.fire2, x + 0.015, y, 0, 6, 0).userData.flame = 1;
|
|
5031
|
-
cylinderX(group, 4e-3, 0.022, M.fire, x + 0.012, y, 0, 6, 0).userData.flame = 1;
|
|
5032
|
-
};
|
|
5033
|
-
function buildFlamethrower(kit, group, parts) {
|
|
5034
|
-
const { M, box: box2, cylinderX, cylinderY, sphere } = kit;
|
|
5035
|
-
parts.kick = 0.15;
|
|
5036
|
-
heatify(parts.glow, cylinderX(group, 0.016, 0.62, M.steel, 0.42, 0, 0, 14));
|
|
5037
|
-
cylinderX(group, 0.022, 0.1, M.dark, 0.78, 0, 0, 14);
|
|
5038
|
-
heatify(parts.glow, cylinderX(group, 0.013, 0.1, M.steel, 0.88, 0, 0, 12, 9e-3));
|
|
5039
|
-
cylinderX(group, 0.018, 0.02, M.metal, 0.73, 0, 0, 14);
|
|
5040
|
-
cylinderX(group, 0.012, 0.06, M.metal, 0.84, -0.025, 0, 10);
|
|
5041
|
-
pilot(kit, group, 0.92, -0.012);
|
|
5042
|
-
const foreGrip = kit.pivot(group, 0.6, -0.02, 0);
|
|
5043
|
-
foreGrip.rotation.z = -0.1;
|
|
5044
|
-
box2(foreGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5045
|
-
const lever = kit.pivot(group, 0.62, -0.02, 0);
|
|
5046
|
-
parts.trigger = box2(lever, 8e-3, 0.05, 6e-3, M.metal, 0.02, -0.03, 0, 0.3);
|
|
5047
|
-
const rearGrip = kit.pivot(group, 0.17, -0.02, 0);
|
|
5048
|
-
rearGrip.rotation.z = -0.28;
|
|
5049
|
-
box2(rearGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5050
|
-
box2(group, 0.05, 4e-3, 0.012, M.metal, 0.2, -0.035, 0);
|
|
5051
|
-
cylinderX(group, 0.02, 0.04, M.metal, 0.1, 0, 0, 12);
|
|
5052
|
-
hose(kit, group, [[0.08, 0, 0], [0, -0.04, 0], [-0.08, -0.2, 0.05], [-0.18, -0.32, 0.08], [-0.25, -0.33, 0.08]], 0.011, M.rubber);
|
|
5053
|
-
for (const z of [-0.1, 0.1]) {
|
|
5054
|
-
cylinderY(group, 0.085, 0.5, M.olive, -0.3, -0.05, z, 20);
|
|
5055
|
-
sphere(group, 0.085, M.olive, -0.3, 0.2, z, 2).scale.y = 0.45;
|
|
5056
|
-
sphere(group, 0.085, M.olive, -0.3, -0.3, z, 2).scale.y = 0.45;
|
|
5057
|
-
cylinderY(group, 0.03, 0.03, M.metal, -0.3, 0.24, z, 12);
|
|
5058
|
-
}
|
|
5059
|
-
sphere(group, 0.075, M.olive, -0.3, 0.1, 0, 2).position.x = -0.39;
|
|
5060
|
-
box2(group, 0.03, 0.6, 0.24, M.dark, -0.4, -0.05, 0);
|
|
5061
|
-
cylinderY(group, 0.03, 0.012, M.metal, -0.39, 0.18, 0, 14);
|
|
5062
|
-
const gauge = kit.pivot(group, -0.39, 0.18, 3e-3);
|
|
5063
|
-
parts.gauge = gauge;
|
|
5064
|
-
box2(gauge, 2e-3, 0.022, 2e-3, M.red, 0, 8e-3, 0.012);
|
|
5065
|
-
parts.muzzle = kit.pivot(group, 0.94, 0, 0);
|
|
5066
|
-
parts.rear = kit.pivot(group, 0.1, 0, 0);
|
|
5067
|
-
}
|
|
5068
|
-
function buildImprovisedFlamethrower(kit, group, parts) {
|
|
5069
|
-
const { M, box: box2, cylinderX, cylinderY, sphere } = kit;
|
|
5070
|
-
parts.kick = 0.12;
|
|
5071
|
-
heatify(parts.glow, cylinderX(group, 0.011, 0.66, M.pipe, 0.38, 0, 0, 12));
|
|
5072
|
-
heatify(parts.glow, cylinderX(group, 0.015, 0.06, M.steel, 0.74, 0, 0, 12, 0.01));
|
|
5073
|
-
cylinderX(group, 6e-3, 0.05, M.metal, 0.735, -0.02, 0, 8);
|
|
5074
|
-
pilot(kit, group, 0.77, -0.02);
|
|
5075
|
-
cylinderY(group, 0.012, 0.04, M.redPaint, 0.72, -0.055, 0, 10);
|
|
5076
|
-
box2(group, 0.02, 0.03, 0.012, M.dark, 0.72, -0.085, 0);
|
|
5077
|
-
cylinderX(group, 0.06, 0.42, M.redPaint, 0.3, -0.09, 0, 22);
|
|
5078
|
-
sphere(group, 0.06, M.redPaint, 0.51, -0.09, 0, 2).scale.x = 0.5;
|
|
5079
|
-
sphere(group, 0.06, M.redPaint, 0.09, -0.09, 0, 2).scale.x = 0.5;
|
|
5080
|
-
cylinderX(group, 0.02, 0.04, M.dark, 0.04, -0.09, 0, 12);
|
|
5081
|
-
box2(group, 0.02, 0.06, 5e-3, M.white, 0.3, -0.09, 0.06);
|
|
5082
|
-
for (const x of [0.15, 0.3, 0.45]) cylinderX(group, 0.063, 0.03, M.tape, x, -0.09, 0, 22);
|
|
5083
|
-
cylinderX(group, 0.016, 0.03, M.tape, 0.3, 0, 0, 12);
|
|
5084
|
-
hose(kit, group, [[0.04, -0.09, 0], [-0.02, -0.06, 0.02], [0, 0, 0.02], [0.05, 0, 0]], 7e-3, M.rubber);
|
|
5085
|
-
const rearGrip = kit.pivot(group, 0.12, -0.01, 0);
|
|
5086
|
-
rearGrip.rotation.z = -0.3;
|
|
5087
|
-
box2(rearGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5088
|
-
const lever = kit.pivot(group, 0.17, -0.02, 0);
|
|
5089
|
-
parts.trigger = box2(lever, 8e-3, 0.04, 6e-3, M.metal, 0, -0.02, 0, 0.2);
|
|
5090
|
-
parts.muzzle = kit.pivot(group, 0.78, 0, 0);
|
|
5091
|
-
parts.rear = kit.pivot(group, 0.05, 0, 0);
|
|
5092
|
-
}
|
|
5093
|
-
|
|
5094
|
-
// src/models/launcher-rounds.ts
|
|
5095
|
-
var PI3 = Math.PI;
|
|
5096
|
-
function buildRocketGrenade(kit) {
|
|
5097
|
-
const { M, cylinderX } = kit;
|
|
5098
|
-
const round2 = kit.group();
|
|
5099
|
-
cylinderX(round2, 0.018, 0.15, M.olive, -0.05, 0, 0, 14);
|
|
5100
|
-
cylinderX(round2, 0.02, 0.07, M.olive, 0.035, 0, 0, 18, 0.0425);
|
|
5101
|
-
cylinderX(round2, 0.0425, 0.12, M.olive, 0.13, 0, 0, 20);
|
|
5102
|
-
cylinderX(round2, 0.0428, 0.012, M.dark, 0.09, 0, 0, 20);
|
|
5103
|
-
cylinderX(round2, 0.0425, 0.13, M.olive, 0.255, 0, 0, 20, 0.011);
|
|
5104
|
-
cylinderX(round2, 0.011, 0.03, M.metal, 0.335, 0, 0, 10, 4e-3);
|
|
5105
|
-
return round2;
|
|
5106
|
-
}
|
|
5107
|
-
function buildRecoillessRound(kit) {
|
|
5108
|
-
const { M, cylinderX } = kit;
|
|
5109
|
-
const round2 = kit.group();
|
|
5110
|
-
cylinderX(round2, 0.041, 0.32, M.green, -0.16, 0, 0, 20);
|
|
5111
|
-
cylinderX(round2, 0.0415, 0.02, M.yellow, -0.05, 0, 0, 20);
|
|
5112
|
-
cylinderX(round2, 0.041, 0.12, M.green, 0.06, 0, 0, 20, 0.012);
|
|
5113
|
-
cylinderX(round2, 0.043, 0.03, M.brass, -0.33, 0, 0, 20);
|
|
5114
|
-
return round2;
|
|
5115
|
-
}
|
|
5116
|
-
function buildFlyingRocket(kit, launcherType) {
|
|
5117
|
-
const { M, box: box2, cylinderX } = kit;
|
|
5118
|
-
const rocket = kit.group();
|
|
5119
|
-
const diameter = launcherType === "at4" || launcherType === "carl" ? 0.041 : 0.032;
|
|
5120
|
-
cylinderX(rocket, diameter * 0.5, 0.2, M.dark, -0.1, 0, 0, 10);
|
|
5121
|
-
cylinderX(rocket, diameter, 0.3, M.olive, 0.15, 0, 0, 18);
|
|
5122
|
-
cylinderX(rocket, diameter, 0.12, M.olive, 0.36, 0, 0, 18, diameter * 0.25);
|
|
5123
|
-
for (let i = 0; i < 4; i++) {
|
|
5124
|
-
const fin = box2(rocket, 0.06, 2e-3, diameter * 1.4, M.metal, -0.17, 0, 0);
|
|
5125
|
-
fin.rotation.x = i * PI3 / 4;
|
|
5011
|
+
return;
|
|
5012
|
+
}
|
|
5013
|
+
const sleeve = kind === 4 ? 0.2 : 0.32;
|
|
5014
|
+
cylinderX(parent, 0.0135, sleeve * 0.55, M.dark, cx, cy + 0.045, cz, 18);
|
|
5015
|
+
cylinderX(parent, 0.0135, sleeve * 0.25, M.dark, cx + sleeve * 0.36, cy + 0.045, cz, 18, 0.026);
|
|
5016
|
+
cylinderX(parent, 0.026, 0.05, M.dark, cx + sleeve * 0.5, cy + 0.045, cz, 18);
|
|
5017
|
+
cylinderX(parent, 0.024, 2e-3, M.lens, cx + sleeve * 0.5 + 0.026, cy + 0.045, cz, 18);
|
|
5018
|
+
cylinderX(parent, 0.019, 0.06, M.dark, cx - sleeve * 0.38, cy + 0.045, cz, 18, 0.0135);
|
|
5019
|
+
cylinderX(parent, 0.019, 0.035, M.rubber, cx - sleeve * 0.38 - 0.045, cy + 0.045, cz, 18);
|
|
5020
|
+
cylinderX(parent, 0.017, 2e-3, M.lens, cx - sleeve * 0.38 - 0.063, cy + 0.045, cz, 18);
|
|
5021
|
+
cylinderY(parent, 0.01, 0.022, M.dark, cx, cy + 0.066, cz, 14);
|
|
5022
|
+
cylinderY(parent, 0.011, 4e-3, M.metal, cx, cy + 0.078, cz, 14);
|
|
5023
|
+
cylinderZ(parent, 0.01, 0.022, M.dark, cx, cy + 0.045, cz + 0.022, 14);
|
|
5024
|
+
for (const offset of [-0.07, 0.07]) {
|
|
5025
|
+
const ring = kit.torus(parent, new THREE.TorusGeometry(0.0155, 3e-3, 8, 20), M.dark, cx + offset, cy + 0.045, cz);
|
|
5026
|
+
ring.rotation.y = PI2 / 2;
|
|
5027
|
+
box2(parent, 0.016, 0.03, 0.022, M.dark, cx + offset, cy + 0.018, cz);
|
|
5126
5028
|
}
|
|
5127
|
-
return rocket;
|
|
5128
5029
|
}
|
|
5030
|
+
var buttpad = (kit, parent, x, y, height, width) => void kit.box(parent, 0.012, height, width, kit.M.rubber, x, y, 0);
|
|
5031
|
+
var swivel = (kit, parent, x, y) => void kit.torus(parent, new kit.THREE.TorusGeometry(6e-3, 15e-4, 6, 12), kit.M.metal, x, y, 0);
|
|
5129
5032
|
|
|
5130
|
-
// src/models/
|
|
5131
|
-
function
|
|
5033
|
+
// src/models/attachments/bipod.ts
|
|
5034
|
+
function buildBipod(kit, parent, x, y) {
|
|
5132
5035
|
const { M, box: box2, cylinderX } = kit;
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
cylinderX(group, 0.024, 0.02, M.metal, 0.94, 0, 0, 16);
|
|
5141
|
-
box2(group, 0.09, 0.03, 0.032, M.metal, 0.46, -0.028, 0);
|
|
5142
|
-
const frontGrip = kit.pivot(group, 0.4, -0.04, 0);
|
|
5143
|
-
frontGrip.rotation.z = -0.22;
|
|
5144
|
-
box2(frontGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5145
|
-
const rearGrip = kit.pivot(group, 0.5, -0.04, 0);
|
|
5146
|
-
rearGrip.rotation.z = -0.18;
|
|
5147
|
-
box2(rearGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5148
|
-
box2(group, 0.06, 4e-3, 0.012, M.metal, 0.53, -0.05, 0);
|
|
5149
|
-
box2(group, 4e-3, 0.025, 0.012, M.metal, 0.56, -0.04, 0);
|
|
5150
|
-
parts.trigger = box2(group, 4e-3, 0.018, 4e-3, M.dark, 0.535, -0.045, 0, 0.15);
|
|
5151
|
-
const hammer = kit.pivot(group, 0.44, -0.012, 0);
|
|
5152
|
-
parts.hammer = hammer;
|
|
5153
|
-
box2(hammer, 0.012, 0.02, 0.01, M.dark, 0, 0, 0);
|
|
5154
|
-
box2(group, 6e-3, 0.03, 6e-3, M.dark, 0.78, 0.032, 0);
|
|
5155
|
-
box2(group, 0.02, 0.022, 0.014, M.dark, 0.46, 0.032, 0);
|
|
5156
|
-
box2(group, 0.12, 0.042, 0.032, M.dark, 0.5, 0.04, -0.04);
|
|
5157
|
-
cylinderX(group, 0.013, 0.05, M.rubber, 0.42, 0.048, -0.04, 14);
|
|
5158
|
-
cylinderX(group, 0.016, 4e-3, M.lens, 0.565, 0.048, -0.04, 14);
|
|
5159
|
-
box2(group, 0.04, 0.012, 0.012, M.metal, 0.5, 0.016, -0.03);
|
|
5160
|
-
const round2 = buildRocketGrenade(kit);
|
|
5161
|
-
round2.position.x = 0.95;
|
|
5162
|
-
group.add(round2);
|
|
5163
|
-
parts.round = round2;
|
|
5164
|
-
parts.roundRest = 0.95;
|
|
5165
|
-
parts.makeRound = () => buildRocketGrenade(kit);
|
|
5166
|
-
parts.muzzle = kit.pivot(group, 0.95, 0, 0);
|
|
5167
|
-
parts.rear = kit.pivot(group, 0, 0, 0);
|
|
5168
|
-
}
|
|
5169
|
-
function buildM72(kit, group, parts) {
|
|
5170
|
-
const { M, box: box2, cylinderX, cylinderY } = kit;
|
|
5171
|
-
parts.kick = 1.1;
|
|
5172
|
-
parts.disposable = true;
|
|
5173
|
-
heatify(parts.glow, cylinderX(group, 0.0365, 0.6, M.olive, 0.58, 0, 0, 20));
|
|
5174
|
-
cylinderX(group, 0.032, 0.32, M.olive, 0.16, 0, 0, 20);
|
|
5175
|
-
cylinderX(group, 0.039, 0.03, M.rubber, 0.866, 0, 0, 20);
|
|
5176
|
-
cylinderX(group, 0.035, 0.025, M.rubber, 0.012, 0, 0, 20);
|
|
5177
|
-
cylinderX(group, 0.037, 0.015, M.yellow, 0.8, 0, 0, 20);
|
|
5178
|
-
cylinderX(group, 0.037, 0.012, M.dark, 0.3, 0, 0, 20);
|
|
5179
|
-
box2(group, 4e-3, 0.05, 0.05, M.dark, 0.79, 0.055, 0);
|
|
5180
|
-
box2(group, 4e-3, 6e-3, 0.04, M.dark, 0.79, 0.078, 0);
|
|
5181
|
-
box2(group, 4e-3, 0.035, 0.024, M.dark, 0.38, 0.05, 0);
|
|
5182
|
-
cylinderY(group, 4e-3, 6e-3, M.lens, 0.38, 0.064, 0, 8);
|
|
5183
|
-
parts.trigger = box2(group, 0.05, 0.016, 0.024, M.rubber, 0.5, 0.042, 0);
|
|
5184
|
-
box2(group, 0.1, 0.01, 0.03, M.dark, 0.47, 0.036, 0);
|
|
5185
|
-
box2(group, 0.02, 0.03, 0.01, M.dark, 0.66, -0.035, 0.03);
|
|
5186
|
-
box2(group, 8e-3, 0.03, 8e-3, M.metal, 0.25, -0.04, 0.03);
|
|
5187
|
-
parts.muzzle = kit.pivot(group, 0.881, 0, 0);
|
|
5188
|
-
parts.rear = kit.pivot(group, 0, 0, 0);
|
|
5036
|
+
cylinderX(parent, 8e-3, 0.02, M.dark, x, y, 0, 12);
|
|
5037
|
+
for (const side of [-1, 1]) {
|
|
5038
|
+
const leg = kit.pivot(parent, x, y, side * 0.012);
|
|
5039
|
+
leg.rotation.set(side * 0.15, 0, -0.35);
|
|
5040
|
+
box2(leg, 6e-3, 0.2, 6e-3, M.dark, 0, -0.1, 0);
|
|
5041
|
+
box2(leg, 0.01, 6e-3, 0.01, M.rubber, 0, -0.2, 0);
|
|
5042
|
+
}
|
|
5189
5043
|
}
|
|
5190
|
-
|
|
5191
|
-
const
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5044
|
+
var buildBipodModel = ({ kit }) => {
|
|
5045
|
+
const group = kit.group();
|
|
5046
|
+
buildBipod(kit, group, 0, 0);
|
|
5047
|
+
return group;
|
|
5048
|
+
};
|
|
5049
|
+
|
|
5050
|
+
// src/models/rifle-fittings.ts
|
|
5051
|
+
var SCOPE_IDS = { 1: "red_dot", 2: "acog_4x", 3: "scope_3_9x", 4: "scope_6_24x" };
|
|
5052
|
+
function buildFittings(context, gripX) {
|
|
5053
|
+
const { kit, group, parts, options: o, furniture: furn, length: L, receiverStart: x0, receiverEnd: x1, receiverHeight: hR, receiverWidth: wR, barrelRadius: r, barrelY: by } = context;
|
|
5054
|
+
const { M, box: box2, cylinderX, cylinderZ, sphere } = kit;
|
|
5055
|
+
const middle = (x0 + x1) / 2;
|
|
5056
|
+
if (o.scope) recordFitting(parts, SCOPE_IDS[o.scope] ?? "scope", group, () => scope(kit, group, o.scope, middle + 0.03, hR / 2 + (o.rail ? 6e-3 : 0), o.scope === 4 ? -0.02 : 0));
|
|
5057
|
+
if (o.carry) {
|
|
5058
|
+
box2(group, 0.15, 0.026, 0.014, M.metal, middle, hR / 2 + 0.03, 0);
|
|
5059
|
+
box2(group, 0.012, 0.03, 0.014, M.metal, middle + 0.07, hR / 2 + 0.014, 0);
|
|
5060
|
+
box2(group, 0.012, 0.03, 0.014, M.metal, middle - 0.07, hR / 2 + 0.014, 0);
|
|
5061
|
+
}
|
|
5062
|
+
if (o.bipod) recordFitting(parts, "bipod", group, () => buildBipod(kit, group, x1 + (L - x1) * 0.45 + 0.04, by - 0.012));
|
|
5063
|
+
if (o.bolt) {
|
|
5064
|
+
const handle = kit.pivot(group, x1 - 0.045, by, 0);
|
|
5065
|
+
parts.boltHandle = handle;
|
|
5066
|
+
parts.boltHandleRest = handle.position.x;
|
|
5067
|
+
cylinderZ(handle, 42e-4, 0.05, M.steelL, 0, 0, wR / 2 + 0.022, 12);
|
|
5068
|
+
sphere(handle, 95e-4, M.dark, 0, -4e-3, wR / 2 + 0.048, 1);
|
|
5069
|
+
cylinderX(group, hR * 0.3, 0.03, M.steel, x0 + 5e-3, by, 0, 16);
|
|
5070
|
+
}
|
|
5071
|
+
if (o.lever) {
|
|
5072
|
+
const lever = kit.pivot(group, gripX - 0.02, -hR / 2 - 0.01, 0);
|
|
5073
|
+
parts.lever = lever;
|
|
5074
|
+
box2(lever, 0.11, 6e-3, 0.012, M.metal, 0.055, -0.052, 0);
|
|
5075
|
+
box2(lever, 6e-3, 0.05, 0.012, M.metal, 3e-3, -0.028, 0);
|
|
5076
|
+
box2(lever, 6e-3, 0.05, 0.012, M.metal, 0.108, -0.028, 0);
|
|
5077
|
+
box2(lever, 0.04, 6e-3, 0.012, M.metal, 0.08, -2e-3, 0);
|
|
5078
|
+
box2(group, 0.03, 0.012, 3e-3, M.dark, x1 - 0.04, by, wR / 2 + 1e-3);
|
|
5079
|
+
}
|
|
5080
|
+
if (o.tube) {
|
|
5081
|
+
const tubeLength = (L - x1) * (o.tubeLen || 0.8);
|
|
5082
|
+
cylinderX(group, 0.0105, tubeLength, M.metal, x1 + tubeLength / 2, by - 0.023, 0, 16);
|
|
5083
|
+
cylinderX(group, 0.0125, 0.02, M.dark, x1 + tubeLength + 6e-3, by - 0.023, 0, 16);
|
|
5084
|
+
}
|
|
5085
|
+
if (o.pump) {
|
|
5086
|
+
const pump = kit.pivot(group);
|
|
5087
|
+
parts.pump = pump;
|
|
5088
|
+
box2(pump, 0.17, 0.042, 0.046, furn, x1 + 0.14, by - 0.022, 0);
|
|
5089
|
+
for (let i = 0; i < 8; i++) box2(pump, 6e-3, 0.044, 0.048, M.dark, x1 + 0.07 + i * 0.02, by - 0.022, 0);
|
|
5090
|
+
}
|
|
5091
|
+
if (o.heat) {
|
|
5092
|
+
cylinderX(group, r * 1.75, (L - x1) * 0.7, M.dark, x1 + (L - x1) * 0.4, by, 0, 12);
|
|
5093
|
+
for (let i = 0; i < 10; i++) box2(group, 8e-3, r * 1.5, 4e-3, M.hole, x1 + (L - x1) * (0.1 + i * 0.06), by + r * 0.8, r * 1.5);
|
|
5094
|
+
}
|
|
5095
|
+
if (o.bayo) box2(group, 0.025, 8e-3, 0.01, M.metal, L - 0.07, by - 0.016, 0);
|
|
5096
|
+
if (o.rod) cylinderX(group, 3e-3, (L - x1) * 0.85, M.steel, x1 + (L - x1) * 0.45, by - 0.014, 0, 8);
|
|
5211
5097
|
}
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
const
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5098
|
+
|
|
5099
|
+
// src/models/rifle-forend.ts
|
|
5100
|
+
var PI3 = Math.PI;
|
|
5101
|
+
function buildForend(context) {
|
|
5102
|
+
const { kit, group, options: o, furniture: furn, length: L, receiverEnd: x1, receiverHeight: hR, receiverWidth: wR, barrelRadius: r, barrelY: by } = context;
|
|
5103
|
+
const { M, box: box2 } = kit;
|
|
5104
|
+
const hasLongScope = (o.scope ?? 0) >= 3;
|
|
5105
|
+
if (!context.isTraditional && o.hg !== "none") {
|
|
5106
|
+
const handguardLength = (L - x1) * (o.hgFrac || 0.5);
|
|
5107
|
+
const hx = x1 + handguardLength / 2;
|
|
5108
|
+
const hh = hR * 0.8;
|
|
5109
|
+
if (o.hg === "rail") {
|
|
5110
|
+
box2(group, handguardLength, hh, wR * 1.04, M.dark, hx, by - 2e-3, 0);
|
|
5111
|
+
rail(kit, group, x1, handguardLength, by + hh / 2, 0, wR * 0.66);
|
|
5112
|
+
rail(kit, group, x1 + 0.01, handguardLength - 0.02, by - 2e-3, wR * 0.54, wR * 0.4, PI3 / 2);
|
|
5113
|
+
rail(kit, group, x1 + 0.01, handguardLength - 0.02, by - 2e-3, -wR * 0.54, wR * 0.4, -PI3 / 2);
|
|
5114
|
+
rail(kit, group, x1 + 0.01, handguardLength - 0.02, by - hh / 2, 0, wR * 0.6, PI3);
|
|
5115
|
+
} else {
|
|
5116
|
+
const material = o.hg === "wood" ? M.wood : furn;
|
|
5117
|
+
if (o.ak) {
|
|
5118
|
+
box2(group, handguardLength, hh * 0.55, wR * 1.08, material, hx, by - hh * 0.22, 0);
|
|
5119
|
+
box2(group, handguardLength * 0.75, hh * 0.35, wR * 0.7, material, hx - handguardLength * 0.1, by + r * 2.2, 0);
|
|
5120
|
+
} else {
|
|
5121
|
+
box2(group, handguardLength, hh, wR * 1.08, material, hx, by - 2e-3, 0);
|
|
5122
|
+
vents(kit, group, x1 + 0.01, handguardLength - 0.02, by + hh * 0.15, wR * 0.54 + 1e-3, Math.round(handguardLength / 0.025), hh * 0.3);
|
|
5123
|
+
vents(kit, group, x1 + 0.01, handguardLength - 0.02, by + hh * 0.15, -wR * 0.54 - 1e-3, Math.round(handguardLength / 0.025), hh * 0.3);
|
|
5124
|
+
}
|
|
5125
|
+
}
|
|
5126
|
+
if (!hasLongScope && !o.rail && o.ak) {
|
|
5127
|
+
box2(group, 0.03, 0.016, wR * 0.6, M.metal, x1 + 0.02, by + r * 2.5 + 0.01, 0);
|
|
5128
|
+
box2(group, 0.012, 4e-3, wR * 0.5, M.dark, x1 + 0.03, by + r * 2.5 + 0.019, 0);
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
5131
|
+
if (hasLongScope) return;
|
|
5132
|
+
const sightX = L - (o.ak ? 0.06 : 0.08);
|
|
5133
|
+
if (o.ak) {
|
|
5134
|
+
box2(group, 0.022, 0.022, wR * 0.6, M.metal, sightX, by + 8e-3, 0);
|
|
5135
|
+
box2(group, 6e-3, 0.024, 4e-3, M.metal, sightX, by + 0.026, 8e-3);
|
|
5136
|
+
box2(group, 6e-3, 0.024, 4e-3, M.metal, sightX, by + 0.026, -8e-3);
|
|
5137
|
+
box2(group, 3e-3, 0.016, 3e-3, M.dark, sightX, by + 0.022, 0);
|
|
5138
|
+
} else if (!o.rail || o.carry) {
|
|
5139
|
+
box2(group, 0.018, 0.014, wR * 0.55, M.dark, sightX, by + 8e-3, 0);
|
|
5140
|
+
box2(group, 0.012, 0.034, 8e-3, M.dark, sightX, by + 0.03, 0, -0.25);
|
|
5141
|
+
} else box2(group, 0.012, 0.024, 0.012, M.dark, sightX - 0.04, by + hR * 0.4 + 0.012, 0);
|
|
5241
5142
|
}
|
|
5242
|
-
var ROCKET_BUILDERS = {
|
|
5243
|
-
rpg: buildRpg,
|
|
5244
|
-
m72: buildM72,
|
|
5245
|
-
at4: buildAt4,
|
|
5246
|
-
carl: buildCarlGustaf
|
|
5247
|
-
};
|
|
5248
5143
|
|
|
5249
|
-
// src/models/
|
|
5250
|
-
function
|
|
5251
|
-
const
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
parts.eject = parts.muzzle;
|
|
5259
|
-
return { group, parts };
|
|
5144
|
+
// src/models/attachments/belt-box.ts
|
|
5145
|
+
function buildBeltBox(kit, belt) {
|
|
5146
|
+
const { M, box: box2, cylinderX } = kit;
|
|
5147
|
+
box2(belt, 0.11, 0.1, 0.08, M.olive, 0, 0, 0);
|
|
5148
|
+
box2(belt, 0.112, 0.012, 0.082, M.dark, 0, 0.046, 0);
|
|
5149
|
+
for (let i = 0; i < 7; i++) {
|
|
5150
|
+
cylinderX(belt, 42e-4, 0.034, M.brass, -0.04 + i * 0.012, 0.07, 0.035, 10);
|
|
5151
|
+
box2(belt, 6e-3, 6e-3, 0.012, M.metal, -0.04 + i * 0.012, 0.066, 0.035);
|
|
5152
|
+
}
|
|
5260
5153
|
}
|
|
5261
5154
|
|
|
5262
|
-
// src/models/
|
|
5155
|
+
// src/models/attachments/drum.ts
|
|
5156
|
+
function buildDrum(kit, magazine) {
|
|
5157
|
+
const { M, box: box2, cylinderZ } = kit;
|
|
5158
|
+
cylinderZ(magazine, 0.075, 0.07, M.dark, 0.02, -0.085, 0, 22);
|
|
5159
|
+
cylinderZ(magazine, 0.05, 0.074, M.metal, 0.02, -0.085, 0, 18);
|
|
5160
|
+
box2(magazine, 0.05, 0.04, 0.03, M.dark, 0, -0.02, 0);
|
|
5161
|
+
}
|
|
5162
|
+
|
|
5163
|
+
// src/models/helical-magazine.ts
|
|
5263
5164
|
var PI4 = Math.PI;
|
|
5264
|
-
var
|
|
5265
|
-
var
|
|
5266
|
-
var
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
const { M, cylinderX } = kit;
|
|
5270
|
-
const
|
|
5271
|
-
|
|
5272
|
-
const
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5165
|
+
var LENGTH = 0.26;
|
|
5166
|
+
var RADIUS = 0.026;
|
|
5167
|
+
var TURNS = 11;
|
|
5168
|
+
function buildHelicalMagazine(context) {
|
|
5169
|
+
const { kit, group, parts, receiverEnd, barrelY, barrelRadius } = context;
|
|
5170
|
+
const { M, cylinderX, box: box2 } = kit;
|
|
5171
|
+
const x = receiverEnd + LENGTH / 2 + 0.02;
|
|
5172
|
+
const y = barrelY - barrelRadius - RADIUS - 0.012;
|
|
5173
|
+
const magazine = kit.pivot(group, x, y, 0);
|
|
5174
|
+
parts.mag = magazine;
|
|
5175
|
+
cylinderX(magazine, RADIUS, LENGTH, M.dark, 0, 0, 0, 20);
|
|
5176
|
+
cylinderX(magazine, RADIUS * 1.06, 0.01, M.metal, -LENGTH / 2, 0, 0, 20);
|
|
5177
|
+
cylinderX(magazine, RADIUS * 1.06, 0.01, M.metal, LENGTH / 2, 0, 0, 20);
|
|
5178
|
+
for (let i = 0; i < TURNS; i++) box2(magazine, 0.012, RADIUS * 2.15, 0.014, M.metal, -LENGTH / 2 + (i + 0.5) * LENGTH / TURNS, 0, 0, 0, 0, i * PI4 / 4);
|
|
5179
|
+
box2(magazine, 0.05, 0.03, 0.03, M.dark, -LENGTH / 2 - 0.02, RADIUS * 0.4, 0);
|
|
5180
|
+
parts.magDrop = 0.16;
|
|
5181
|
+
return x;
|
|
5182
|
+
}
|
|
5183
|
+
|
|
5184
|
+
// src/models/rifle-controls.ts
|
|
5185
|
+
function buildGrip(context) {
|
|
5186
|
+
const { kit, group, parts, options: o, furniture: furn, receiverStart: x0, receiverHeight: hR, receiverWidth: wR } = context;
|
|
5187
|
+
const { M, box: box2 } = kit;
|
|
5188
|
+
const gx = x0 + (o.gripAt || 0.07);
|
|
5189
|
+
if (!context.isTraditional && o.grip !== "none") {
|
|
5190
|
+
const grip = kit.pivot(group, gx - 0.012, -hR / 2 - 0.046, 0);
|
|
5191
|
+
grip.rotation.z = -0.3;
|
|
5192
|
+
parts.grip = grip;
|
|
5193
|
+
box2(grip, 0.032, 0.105, 0.028, furn, 0, 0, 0);
|
|
5194
|
+
for (let i = 0; i < 3; i++) box2(grip, 6e-3, 0.012, 0.026, furn, 0.017, 0.022 - i * 0.02, 0);
|
|
5195
|
+
box2(grip, 0.034, 8e-3, 0.03, furn, 0, -0.052, 0);
|
|
5282
5196
|
}
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5197
|
+
box2(group, 0.06, 4e-3, 0.01, M.metal, gx + 0.03, -hR / 2 - 0.024, 0);
|
|
5198
|
+
box2(group, 4e-3, 0.022, 0.01, M.metal, gx + 0.06, -hR / 2 - 0.013, 0);
|
|
5199
|
+
parts.trigger = box2(group, 4e-3, 0.016, 4e-3, M.dark, gx + 0.024, -hR / 2 - 0.012, 0, 0.15);
|
|
5200
|
+
if (o.sel) parts.safety = box2(group, 0.016, 5e-3, 3e-3, M.dark, gx + 5e-3, -hR * 0.15, -wR / 2 - 2e-3, 0.4);
|
|
5201
|
+
return gx;
|
|
5286
5202
|
}
|
|
5287
|
-
function
|
|
5288
|
-
const {
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5203
|
+
function buildMagazine(context, gx) {
|
|
5204
|
+
const { kit, group, parts, options: o, receiverStart: x0, receiverHeight: hR, receiverWidth: wR, receiverLength: RL } = context;
|
|
5205
|
+
const { M, box: box2 } = kit;
|
|
5206
|
+
if (o.mag === "helical") return buildHelicalMagazine(context);
|
|
5207
|
+
const mx = o.magAt != null ? x0 + o.magAt : gx + 0.075;
|
|
5208
|
+
const scale = o.magLen || 1;
|
|
5209
|
+
const magazine = kit.pivot(group, mx, -hR / 2, 0);
|
|
5210
|
+
parts.mag = magazine;
|
|
5211
|
+
const finish = o.magMat === "bakelite" ? M.bakelite : o.magMat === "poly" ? M.polyMag : void 0;
|
|
5212
|
+
if (o.mag === "curved") {
|
|
5213
|
+
let px = 0;
|
|
5214
|
+
let py = 0;
|
|
5215
|
+
const material = finish ?? M.metal;
|
|
5216
|
+
for (const angle of [0.06, 0.22, 0.38]) {
|
|
5217
|
+
const length = 0.07 * scale;
|
|
5218
|
+
const cx = px + Math.sin(angle) * length / 2;
|
|
5219
|
+
const cy = py - Math.cos(angle) * length / 2;
|
|
5220
|
+
box2(magazine, 0.052, length + 4e-3, 0.024, material, cx, cy, 0, angle);
|
|
5221
|
+
box2(magazine, 0.04, length * 0.8, 0.026, M.dark, cx, cy, 0, angle);
|
|
5222
|
+
px += Math.sin(angle) * length;
|
|
5223
|
+
py -= Math.cos(angle) * length;
|
|
5224
|
+
}
|
|
5225
|
+
box2(magazine, 0.058, 8e-3, 0.028, material, px, py, 0, 0.38);
|
|
5226
|
+
parts.magDrop = 0.07 * scale * 3 + 0.04;
|
|
5227
|
+
} else if (o.mag === "box") {
|
|
5228
|
+
const length = 0.13 * scale;
|
|
5229
|
+
const curve = o.curve || 0;
|
|
5230
|
+
const segment = length / 3;
|
|
5231
|
+
const material = finish ?? M.dark;
|
|
5232
|
+
let px = 0;
|
|
5233
|
+
let py = 0;
|
|
5234
|
+
let angle = 0.08;
|
|
5235
|
+
for (let i = 0; i < 3; i++) {
|
|
5236
|
+
angle = 0.08 + curve * i;
|
|
5237
|
+
const cx = px + Math.sin(angle) * segment / 2;
|
|
5238
|
+
const cy = py - Math.cos(angle) * segment / 2;
|
|
5239
|
+
box2(magazine, 0.05, segment + 4e-3, 0.024, material, cx, cy, 0, angle);
|
|
5240
|
+
box2(magazine, 0.04, 3e-3, 0.026, M.metal, cx, cy, 0, angle);
|
|
5241
|
+
px += Math.sin(angle) * segment;
|
|
5242
|
+
py -= Math.cos(angle) * segment;
|
|
5243
|
+
}
|
|
5244
|
+
box2(magazine, 0.056, 7e-3, 0.028, material, px, py - 2e-3, 0, angle);
|
|
5245
|
+
parts.magDrop = length + 0.03;
|
|
5246
|
+
} else if (o.mag === "drum") {
|
|
5247
|
+
buildDrum(kit, magazine);
|
|
5248
|
+
parts.magDrop = 0.2;
|
|
5249
|
+
} else if (o.mag === "internal") {
|
|
5250
|
+
box2(group, 0.08, 0.025, 0.03, context.isTraditional ? context.furniture : M.metal, mx, -hR / 2 - 0.012, 0);
|
|
5251
|
+
parts.mag = null;
|
|
5252
|
+
} else parts.mag = null;
|
|
5253
|
+
if (o.mag === "belt") {
|
|
5254
|
+
const belt = kit.pivot(group, mx + 0.02, -hR / 2 - 0.05, -0.045);
|
|
5255
|
+
parts.belt = belt;
|
|
5256
|
+
buildBeltBox(kit, belt);
|
|
5257
|
+
const cover = kit.pivot(group, x0 + 0.01, hR / 2, 0);
|
|
5258
|
+
parts.cover = cover;
|
|
5259
|
+
box2(cover, RL - 0.03, 0.014, wR * 1.05, M.metal, (RL - 0.03) / 2, 7e-3, 0);
|
|
5260
|
+
box2(cover, 0.02, 0.012, wR * 0.6, M.dark, RL - 0.04, 0.016, 0);
|
|
5300
5261
|
}
|
|
5301
|
-
|
|
5302
|
-
parts.safety = box2(group, 0.014, 6e-3, 0.01, M.dark, 0.2, 0.073, -0.076, 0.4);
|
|
5262
|
+
return mx;
|
|
5303
5263
|
}
|
|
5304
|
-
|
|
5264
|
+
|
|
5265
|
+
// src/models/rifle-stock.ts
|
|
5266
|
+
function buildStock(context, magazineX) {
|
|
5267
|
+
const { kit, group, options: o, furniture: furn, length: L, stockLength: S, receiverStart: x0, receiverEnd: x1, receiverHeight: hR } = context;
|
|
5305
5268
|
const { M, box: box2, cylinderX } = kit;
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
};
|
|
5341
|
-
parts.muzzle = kit.mark(group, BARREL_END + 0.01, 0, 0);
|
|
5342
|
-
parts.eject = kit.mark(group, 0.3, -0.07, 0.08);
|
|
5343
|
-
return { group, parts };
|
|
5269
|
+
if (context.isTraditional) {
|
|
5270
|
+
buttpad(kit, group, 6e-3, -0.04, 0.13, 0.038);
|
|
5271
|
+
box2(group, 0.03, 0.13, 0.038, furn, 0.024, -0.04, 0);
|
|
5272
|
+
box2(group, S, 0.055, 0.034, furn, S / 2, -0.012, 0, 0.06);
|
|
5273
|
+
box2(group, 0.09, 0.05, 0.032, furn, x0 - 0.02, -0.035, 0, 0.25);
|
|
5274
|
+
const forendLength = x1 - x0 + (L - x1) * (o.fore ?? 0.62);
|
|
5275
|
+
if (forendLength > 0) box2(group, forendLength, 0.045, 0.04, furn, x0 + forendLength / 2, -hR / 2 + 4e-3, 0);
|
|
5276
|
+
if (o.stock === "straight") box2(group, 0.15, 0.04, 0.035, furn, x1 + 0.08, -hR / 2, 0);
|
|
5277
|
+
box2(group, 0.04, 4e-3, 0.03, M.metal, magazineX, -hR / 2 - 0.022, 0);
|
|
5278
|
+
swivel(kit, group, 0.2, -0.08);
|
|
5279
|
+
swivel(kit, group, x1 + (L - x1) * 0.45, -hR / 2 - 0.03);
|
|
5280
|
+
if (o.bands) for (const fraction of [0.35, 0.75]) cylinderX(group, 0.024, 8e-3, M.metal, x1 + (L - x1) * fraction * (o.fore || 0.62), -4e-3, 0, 16);
|
|
5281
|
+
} else if (o.stock === "fixed" || o.stock === "wood") {
|
|
5282
|
+
box2(group, S, 0.05, 0.03, furn, S / 2, -8e-3, 0, 0.05);
|
|
5283
|
+
box2(group, 0.03, 0.13, 0.036, furn, 0.022, -0.035, 0);
|
|
5284
|
+
buttpad(kit, group, 4e-3, -0.035, 0.13, 0.036);
|
|
5285
|
+
if (o.stock === "wood") box2(group, S * 0.6, 0.03, 0.028, furn, S * 0.55, -0.045, 0, 0.2);
|
|
5286
|
+
swivel(kit, group, 0.08, -0.09);
|
|
5287
|
+
} else if (o.stock === "skeleton") {
|
|
5288
|
+
box2(group, S, 0.014, 0.026, furn, S / 2, 0.012, 0, 0.03);
|
|
5289
|
+
box2(group, S, 0.014, 0.026, furn, S / 2, -0.05, 0, -0.08);
|
|
5290
|
+
box2(group, 0.03, 0.12, 0.034, furn, 0.02, -0.025, 0);
|
|
5291
|
+
buttpad(kit, group, 4e-3, -0.025, 0.12, 0.034);
|
|
5292
|
+
} else if (o.stock === "retract") {
|
|
5293
|
+
cylinderX(group, 0.013, S, M.metal, S / 2, 0, 0, 16);
|
|
5294
|
+
for (let i = 0; i < 5; i++) box2(group, 3e-3, 3e-3, 8e-3, M.dark, S * 0.2 + i * 0.015, -0.013, 0);
|
|
5295
|
+
box2(group, 0.034, 0.11, 0.036, furn, 0.02, -0.025, 0);
|
|
5296
|
+
box2(group, S * 0.55, 0.032, 0.03, furn, S * 0.35, 0, 0);
|
|
5297
|
+
buttpad(kit, group, 3e-3, -0.025, 0.11, 0.036);
|
|
5298
|
+
} else if (o.stock === "fold") {
|
|
5299
|
+
box2(group, S, 6e-3, 6e-3, M.metal, S / 2, 0.01, 0.012);
|
|
5300
|
+
box2(group, S, 6e-3, 6e-3, M.metal, S / 2, -0.04, 0.012, -0.12);
|
|
5301
|
+
box2(group, 0.012, 0.1, 0.03, M.metal, 6e-3, -0.02, 0.012);
|
|
5302
|
+
}
|
|
5344
5303
|
}
|
|
5345
5304
|
|
|
5346
|
-
// src/models/
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
const group =
|
|
5350
|
-
const
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5305
|
+
// src/models/rifle.ts
|
|
5306
|
+
var PI5 = Math.PI;
|
|
5307
|
+
function buildReceiver(context) {
|
|
5308
|
+
const { kit, group, parts, options: o, length: L, receiverStart: x0, receiverEnd: x1, receiverHeight: hR, receiverWidth: wR, receiverLength: RL, barrelY: by } = context;
|
|
5309
|
+
const { M, box: box2, cylinderX, cylinderY, cylinderZ, sphere } = kit;
|
|
5310
|
+
const receiverMaterial = o.tan ? M.tan : M.metal;
|
|
5311
|
+
const middle = (x0 + x1) / 2;
|
|
5312
|
+
if (o.round) {
|
|
5313
|
+
cylinderX(group, hR * 0.36, RL, M.steel, middle, by, 0, 20);
|
|
5314
|
+
cylinderX(group, hR * 0.32, 0.05, M.steel, x0 - 0.01, by, 0, 18);
|
|
5315
|
+
} else if (o.ar) {
|
|
5316
|
+
box2(group, RL, hR * 0.5, wR, receiverMaterial, middle, hR * 0.25, 0);
|
|
5317
|
+
box2(group, RL * 0.92, hR * 0.52, wR * 0.96, receiverMaterial, middle - RL * 0.02, -hR * 0.24, 0);
|
|
5318
|
+
box2(group, 0.05, 0.03, wR * 1.15, receiverMaterial, x0 + RL * 0.62, -hR * 0.5 - 0.01, 0);
|
|
5319
|
+
cylinderZ(group, 6e-3, 0.012, M.metal, x1 - 0.03, hR * 0.28, wR / 2 + 6e-3, 12);
|
|
5320
|
+
box2(group, 0.012, 0.01, 0.012, M.metal, x1 - 0.05, hR * 0.12, wR / 2 + 6e-3);
|
|
5321
|
+
box2(group, 0.03, 8e-3, 0.012, M.dark, x0 + 0.02, hR / 2 + 4e-3, 0);
|
|
5322
|
+
box2(group, 0.012, 6e-3, 4e-3, M.dark, x0 + RL * 0.55, -hR * 0.15, -wR / 2 - 2e-3);
|
|
5323
|
+
} else box2(group, RL, hR, wR, receiverMaterial, middle, 0, 0);
|
|
5324
|
+
if (o.ak) {
|
|
5325
|
+
box2(group, RL * 0.86, hR * 0.28, wR * 0.95, M.metal, middle - 8e-3, hR / 2 + 4e-3, 0);
|
|
5326
|
+
for (let i = 0; i < 3; i++) box2(group, 4e-3, hR * 0.3, wR * 0.97, M.dark, x0 + RL * 0.25 + i * 0.02, hR / 2 + 4e-3, 0);
|
|
5327
|
+
box2(group, RL * 0.5, 0.012, 3e-3, M.metal, x0 + RL * 0.55, -hR * 0.02, wR / 2 + 15e-4, -0.05);
|
|
5328
|
+
box2(group, 0.012, 0.014, 3e-3, M.dark, x0 + RL * 0.32, -hR * 0.05, wR / 2 + 2e-3);
|
|
5329
|
+
}
|
|
5330
|
+
if (o.g3) {
|
|
5331
|
+
cylinderX(group, 9e-3, (L - x1) * 0.6, M.metal, x1 + (L - x1) * 0.28, hR * 0.48, 0, 14);
|
|
5332
|
+
box2(group, 0.012, 0.024, 8e-3, M.dark, x1 + (L - x1) * 0.5, hR * 0.48, -0.012);
|
|
5333
|
+
cylinderY(group, 0.012, 0.016, M.dark, x0 + 0.03, hR / 2 + 8e-3, 0, 12);
|
|
5334
|
+
}
|
|
5335
|
+
const ejectX = x1 - (o.ejectBack || 0.07);
|
|
5336
|
+
const ejectY = o.ar ? hR * 0.2 : by;
|
|
5337
|
+
box2(group, 0.05, hR * 0.36, 4e-3, M.hole, ejectX, ejectY, wR / 2 - 4e-4);
|
|
5368
5338
|
const bolt = kit.pivot(group);
|
|
5369
5339
|
parts.bolt = bolt;
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
box2(
|
|
5377
|
-
|
|
5378
|
-
parts.muzzle = kit.mark(group, 1.72, 0.01, 0);
|
|
5379
|
-
parts.eject = kit.mark(group, 0.3, -0.07, 0);
|
|
5380
|
-
return { group, parts };
|
|
5340
|
+
parts.stroke = Math.min(0.1, RL * 0.32);
|
|
5341
|
+
box2(bolt, 0.044, hR * 0.26, 6e-3, M.steelL, ejectX, ejectY, wR / 2 - 12e-4);
|
|
5342
|
+
if (o.charge) {
|
|
5343
|
+
box2(bolt, 0.012, 0.01, 0.03, M.metal, ejectX + 0.04, ejectY + 4e-3, wR / 2 + 0.012);
|
|
5344
|
+
sphere(bolt, 65e-4, M.metal, ejectX + 0.04, ejectY + 4e-3, wR / 2 + 0.028, 1);
|
|
5345
|
+
}
|
|
5346
|
+
if (o.ar) box2(group, 0.012, 0.016, 6e-3, receiverMaterial, ejectX - 0.03, ejectY + 4e-3, wR / 2 + 4e-3);
|
|
5347
|
+
if (o.rail) rail(kit, group, x0 - 5e-3, RL + 0.07, hR / 2 + (o.ar ? 0 : 3e-3), 0, wR * 0.68);
|
|
5381
5348
|
}
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
function buildP90(kit) {
|
|
5349
|
+
function buildBarrel(context) {
|
|
5350
|
+
const { kit, group, parts, options: o, length: L, barrelLength: Bl, receiverEnd: x1, barrelRadius: r, barrelY: by } = context;
|
|
5385
5351
|
const { M, box: box2, cylinderX } = kit;
|
|
5352
|
+
heatify(parts.glow, cylinderX(group, r, Bl, M.metal, L - Bl / 2, by, 0, 16));
|
|
5353
|
+
if (o.jacket) {
|
|
5354
|
+
cylinderX(group, r * 2, (L - x1) * 0.6, M.dark, x1 + (L - x1) * 0.3, by, 0, 16);
|
|
5355
|
+
for (let i = 0; i < 6; i++) cylinderX(group, r * 2.15, 4e-3, M.metal, x1 + (L - x1) * (0.05 + i * 0.09), by, 0, 16);
|
|
5356
|
+
}
|
|
5357
|
+
if (o.gas) cylinderX(group, r * 0.75, (L - x1) * 0.55, M.metal, x1 + (L - x1) * 0.3, by + r * 2.2, 0, 14);
|
|
5358
|
+
if (o.brake) {
|
|
5359
|
+
const kind = o.brake === 2 ? 2 : 1;
|
|
5360
|
+
recordFitting(parts, kind === 2 ? "muzzle_brake_heavy" : "muzzle_brake", group, () => buildBrake(kit, group, kind, L, by, r, (body) => void heatify(parts.glow, body)));
|
|
5361
|
+
} else if (!o.noFH) {
|
|
5362
|
+
recordFitting(parts, "muzzle_default", group, () => {
|
|
5363
|
+
heatify(parts.glow, cylinderX(group, r * 1.45, 0.042, M.dark, L - 0.021, by, 0, 16));
|
|
5364
|
+
for (let i = 0; i < 4; i++) {
|
|
5365
|
+
const angle = i * PI5 / 2 + PI5 / 4;
|
|
5366
|
+
box2(group, 0.026, 25e-4, 4e-3, M.hole, L - 0.02, by + Math.cos(angle) * r * 1.42, Math.sin(angle) * r * 1.42, 0, 0, angle);
|
|
5367
|
+
}
|
|
5368
|
+
});
|
|
5369
|
+
}
|
|
5370
|
+
cylinderX(group, r * 0.55, 4e-3, M.hole, L + 5e-4, by, 0, 12);
|
|
5371
|
+
}
|
|
5372
|
+
var familyOf = (o) => {
|
|
5373
|
+
if (o.mag === "belt") return "belt";
|
|
5374
|
+
if (o.pump) return "pump";
|
|
5375
|
+
if (o.lever) return "lever";
|
|
5376
|
+
if (o.tube) return "semi12";
|
|
5377
|
+
if (o.bolt) return o.mag === "box" ? "boltmag" : "bolt";
|
|
5378
|
+
return o.mag === "internal" ? "semiint" : "rifle";
|
|
5379
|
+
};
|
|
5380
|
+
function buildRifle(kit, options) {
|
|
5381
|
+
const { M } = kit;
|
|
5386
5382
|
const group = kit.group();
|
|
5387
|
-
const parts = { family: "
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
const
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5383
|
+
const parts = { family: "rifle", glow: [] };
|
|
5384
|
+
const length = (options.L ?? 0) / 1e3;
|
|
5385
|
+
const barrelLength = (options.B ?? 0) / 1e3;
|
|
5386
|
+
const isTraditional = options.stock === "trad" || options.stock === "straight";
|
|
5387
|
+
const stockLength = options.stock === "none" ? 0 : options.stockLen || Math.min(0.36, Math.max(0.2, 0.3 * length));
|
|
5388
|
+
const receiverStart = stockLength;
|
|
5389
|
+
const receiverEnd = Math.max(receiverStart + 0.12, length - barrelLength * 0.92);
|
|
5390
|
+
const receiverHeight = options.hR || 0.06;
|
|
5391
|
+
const context = {
|
|
5392
|
+
kit,
|
|
5393
|
+
group,
|
|
5394
|
+
parts,
|
|
5395
|
+
options,
|
|
5396
|
+
furniture: options.wood ? M.wood : options.olive ? M.olive : options.tan ? M.tan : M.poly,
|
|
5397
|
+
isTraditional,
|
|
5398
|
+
length,
|
|
5399
|
+
barrelLength,
|
|
5400
|
+
stockLength,
|
|
5401
|
+
receiverStart,
|
|
5402
|
+
receiverEnd,
|
|
5403
|
+
receiverHeight,
|
|
5404
|
+
receiverWidth: options.wR || 0.034,
|
|
5405
|
+
barrelRadius: options.br || 85e-4,
|
|
5406
|
+
barrelY: receiverHeight * 0.15,
|
|
5407
|
+
receiverLength: receiverEnd - receiverStart
|
|
5408
|
+
};
|
|
5409
|
+
buildReceiver(context);
|
|
5410
|
+
buildBarrel(context);
|
|
5411
|
+
buildForend(context);
|
|
5412
|
+
const gripX = buildGrip(context);
|
|
5413
|
+
const magazineX = buildMagazine(context, gripX);
|
|
5414
|
+
parts.stockMeshes = context.isTraditional ? [] : captured(group, () => buildStock(context, magazineX));
|
|
5415
|
+
if (context.isTraditional) buildStock(context, magazineX);
|
|
5416
|
+
buildFittings(context, gripX);
|
|
5417
|
+
const hasHandguard = !context.isTraditional && options.hg !== "none";
|
|
5418
|
+
parts.frames = {
|
|
5419
|
+
length,
|
|
5420
|
+
barrelY: context.barrelY,
|
|
5421
|
+
barrelRadius: context.barrelRadius,
|
|
5422
|
+
receiverStart,
|
|
5423
|
+
receiverEnd,
|
|
5424
|
+
receiverHeight,
|
|
5425
|
+
receiverWidth: context.receiverWidth,
|
|
5426
|
+
handguardEnd: receiverEnd + (length - receiverEnd) * (hasHandguard ? options.hgFrac || 0.5 : 0.4),
|
|
5427
|
+
magazineX,
|
|
5428
|
+
gripX,
|
|
5429
|
+
hasRail: Boolean(options.rail)
|
|
5430
|
+
};
|
|
5431
|
+
const { barrelY: by, receiverWidth: wR } = context;
|
|
5432
|
+
const ejectX = receiverEnd - (options.ejectBack || 0.07);
|
|
5433
|
+
const ejectY = options.ar ? receiverHeight * 0.2 : by;
|
|
5434
|
+
parts.muzzle = kit.mark(group, length + 0.01, by, 0);
|
|
5435
|
+
parts.eject = kit.mark(group, ejectX, ejectY, wR / 2 + 6e-3);
|
|
5436
|
+
parts.loadPort = kit.mark(group, receiverEnd - 0.05, -receiverHeight / 2 - 4e-3, 0);
|
|
5437
|
+
parts.topLoad = kit.mark(group, ejectX, receiverHeight / 2 + 4e-3, 0);
|
|
5438
|
+
parts.family = familyOf(options);
|
|
5407
5439
|
return { group, parts };
|
|
5408
5440
|
}
|
|
5409
5441
|
|
|
5410
|
-
// src/models/
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
const
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5442
|
+
// src/models/break-launcher.ts
|
|
5443
|
+
function buildBreakLauncher(kit, options) {
|
|
5444
|
+
const built = buildRifle(kit, options);
|
|
5445
|
+
const { group, parts } = built;
|
|
5446
|
+
const frames = parts.frames;
|
|
5447
|
+
if (!frames) return built;
|
|
5448
|
+
const hingeY = frames.barrelY - frames.barrelRadius;
|
|
5449
|
+
const barrels = kit.pivot(group, frames.receiverEnd, hingeY, 0);
|
|
5450
|
+
group.updateMatrixWorld(true);
|
|
5451
|
+
const centre = new kit.THREE.Vector3();
|
|
5452
|
+
for (const child of [...group.children]) {
|
|
5453
|
+
if (child === barrels) continue;
|
|
5454
|
+
const mesh = child;
|
|
5455
|
+
const isAhead = mesh.isMesh ? new kit.THREE.Box3().setFromObject(mesh).getCenter(centre).x > frames.receiverEnd : child === parts.muzzle;
|
|
5456
|
+
if (isAhead) barrels.attach(child);
|
|
5417
5457
|
}
|
|
5418
|
-
parts.
|
|
5419
|
-
parts.
|
|
5420
|
-
|
|
5458
|
+
parts.barrels = barrels;
|
|
5459
|
+
parts.breech = [kit.mark(barrels, 4e-3, frames.barrelY - hingeY, 0)];
|
|
5460
|
+
parts.eject = parts.breech[0];
|
|
5461
|
+
parts.family = "break";
|
|
5462
|
+
return built;
|
|
5421
5463
|
}
|
|
5422
5464
|
|
|
5423
|
-
// src/models/
|
|
5424
|
-
var
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
box2
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5465
|
+
// src/models/attachments/mount-frames.ts
|
|
5466
|
+
var DEFAULT_BARREL_RADIUS = 85e-4;
|
|
5467
|
+
var DEFAULT_RECEIVER_WIDTH = 0.034;
|
|
5468
|
+
var RECEIVER_START_FRACTION = 0.25;
|
|
5469
|
+
var RECEIVER_END_FRACTION = 0.55;
|
|
5470
|
+
var RECEIVER_HEIGHT_FRACTION = 0.4;
|
|
5471
|
+
var DEFAULT_GRIP_OFFSET = 0.07;
|
|
5472
|
+
var HANDGUARD_FRACTION = 0.5;
|
|
5473
|
+
function deriveFrames(THREE, model) {
|
|
5474
|
+
const { root, inner, parts } = model;
|
|
5475
|
+
root.updateMatrixWorld(true);
|
|
5476
|
+
const box2 = new THREE.Box3().setFromObject(root);
|
|
5477
|
+
const span = box2.max.x - box2.min.x;
|
|
5478
|
+
const toInnerX = (x) => (x - inner.position.x) / inner.scale.x;
|
|
5479
|
+
const muzzle = parts.muzzle?.position;
|
|
5480
|
+
const length = muzzle ? muzzle.x - 0.01 : toInnerX(box2.max.x);
|
|
5481
|
+
const receiverStart = toInnerX(box2.min.x + span * RECEIVER_START_FRACTION);
|
|
5482
|
+
const receiverEnd = toInnerX(box2.min.x + span * RECEIVER_END_FRACTION);
|
|
5483
|
+
return {
|
|
5484
|
+
length,
|
|
5485
|
+
barrelY: muzzle?.y ?? (box2.max.y + box2.min.y) / 2,
|
|
5486
|
+
barrelRadius: DEFAULT_BARREL_RADIUS,
|
|
5487
|
+
receiverStart,
|
|
5488
|
+
receiverEnd,
|
|
5489
|
+
receiverHeight: (box2.max.y - box2.min.y) * RECEIVER_HEIGHT_FRACTION,
|
|
5490
|
+
receiverWidth: Math.min(DEFAULT_RECEIVER_WIDTH, box2.max.z - box2.min.z),
|
|
5491
|
+
handguardEnd: receiverEnd + (length - receiverEnd) * HANDGUARD_FRACTION,
|
|
5492
|
+
magazineX: parts.mag ? parts.mag.position.x : (receiverStart + receiverEnd) / 2,
|
|
5493
|
+
gripX: receiverStart + DEFAULT_GRIP_OFFSET,
|
|
5494
|
+
hasRail: false
|
|
5495
|
+
};
|
|
5496
|
+
}
|
|
5497
|
+
function mountFrame(model, mount) {
|
|
5498
|
+
const frames = model.parts.frames;
|
|
5499
|
+
if (!frames) return void 0;
|
|
5500
|
+
const { inner } = model;
|
|
5501
|
+
const toRoot = (x, y, z) => [inner.position.x + x * inner.scale.x, y, z];
|
|
5502
|
+
const handguardHeight = frames.receiverHeight * 0.8;
|
|
5503
|
+
const railTopY = frames.receiverHeight / 2 + (frames.hasRail ? 6e-3 : 0);
|
|
5504
|
+
const forendMiddle = (frames.receiverEnd + frames.handguardEnd) / 2;
|
|
5505
|
+
const base = { mount, barrelRadius: frames.barrelRadius, receiverWidth: frames.receiverWidth, receiverHeight: frames.receiverHeight, hasRail: frames.hasRail };
|
|
5506
|
+
switch (mount) {
|
|
5507
|
+
case "muzzle":
|
|
5508
|
+
return { ...base, position: toRoot(frames.length, frames.barrelY, 0), side: 0 };
|
|
5509
|
+
case "rail_top":
|
|
5510
|
+
return { ...base, position: toRoot((frames.receiverStart + frames.receiverEnd) / 2 + 0.03, railTopY, 0), side: 0 };
|
|
5511
|
+
case "rail_bottom":
|
|
5512
|
+
return { ...base, position: toRoot(forendMiddle, frames.barrelY - handguardHeight / 2, 0), side: 0 };
|
|
5513
|
+
case "rail_left":
|
|
5514
|
+
return { ...base, position: toRoot(forendMiddle, frames.barrelY, -(frames.receiverWidth * 0.54 + 4e-3)), side: -1 };
|
|
5515
|
+
case "rail_right":
|
|
5516
|
+
return { ...base, position: toRoot(forendMiddle, frames.barrelY, frames.receiverWidth * 0.54 + 4e-3), side: 1 };
|
|
5517
|
+
case "underbarrel": {
|
|
5518
|
+
const [x, y] = frames.underbarrel ?? [frames.receiverEnd + (frames.handguardEnd - frames.receiverEnd) * 0.25, frames.barrelY - handguardHeight / 2 - 0.02];
|
|
5519
|
+
return { ...base, position: toRoot(x, y, 0), side: 0 };
|
|
5520
|
+
}
|
|
5521
|
+
case "magazine":
|
|
5522
|
+
return { ...base, position: toRoot(frames.magazineX, -frames.receiverHeight / 2, 0), side: 0 };
|
|
5523
|
+
case "feed": {
|
|
5524
|
+
const belt = model.parts.belt?.position;
|
|
5525
|
+
return { ...base, position: belt ? toRoot(belt.x, belt.y, belt.z) : toRoot(frames.magazineX + 0.02, -frames.receiverHeight / 2 - 0.05, -0.045), side: -1 };
|
|
5526
|
+
}
|
|
5527
|
+
case "sling":
|
|
5528
|
+
return {
|
|
5529
|
+
...base,
|
|
5530
|
+
position: toRoot(frames.receiverEnd + (frames.length - frames.receiverEnd) * 0.45, -frames.receiverHeight / 2 - 0.03, 0),
|
|
5531
|
+
secondary: toRoot(0.08, -0.09, 0),
|
|
5532
|
+
side: 0
|
|
5533
|
+
};
|
|
5534
|
+
default:
|
|
5535
|
+
return void 0;
|
|
5463
5536
|
}
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5537
|
+
}
|
|
5538
|
+
|
|
5539
|
+
// src/models/bullpup.ts
|
|
5540
|
+
function buildBullpup(kit, options) {
|
|
5541
|
+
const { M, box: box2, cylinderX } = kit;
|
|
5542
|
+
const group = kit.group();
|
|
5543
|
+
const L = (options.L ?? 0) / 1e3;
|
|
5544
|
+
const barrel = (options.B ?? 0) / 1e3;
|
|
5545
|
+
const bodyLength = Math.max(0.32, L - barrel * 0.72);
|
|
5546
|
+
const body = options.shot ? M.poly : M.olive;
|
|
5547
|
+
const parts = { family: options.shot ? "pump" : "rifle", stroke: 0.06, glow: [] };
|
|
5548
|
+
box2(group, bodyLength, 0.075, 0.042, body, bodyLength / 2, 0, 0);
|
|
5549
|
+
box2(group, bodyLength * 0.9, 0.02, 0.044, M.dark, bodyLength * 0.5, -0.02, 0);
|
|
5550
|
+
box2(group, 0.032, 0.13, 0.044, M.rubber, 0.016, -0.025, 0);
|
|
5551
|
+
const gx = bodyLength * 0.8;
|
|
5552
|
+
const grip = kit.pivot(group, gx, -0.085, 0);
|
|
5553
|
+
grip.rotation.z = -0.25;
|
|
5554
|
+
parts.grip = grip;
|
|
5555
|
+
box2(grip, 0.03, 0.1, 0.03, M.poly, 0, 0, 0);
|
|
5556
|
+
box2(group, 0.1, 6e-3, 0.03, body, gx + 0.01, -0.06, 0);
|
|
5557
|
+
parts.trigger = box2(group, 4e-3, 0.016, 4e-3, M.dark, gx + 0.02, -0.05, 0, 0.15);
|
|
5558
|
+
heatify(parts.glow, cylinderX(group, options.shot ? 0.0105 : 85e-4, barrel, M.metal, L - barrel / 2, 0.012, 0, 16));
|
|
5559
|
+
cylinderX(group, 6e-3, 4e-3, M.hole, L + 1e-3, 0.012, 0, 12);
|
|
5560
|
+
box2(group, 0.05, 0.024, 4e-3, M.hole, bodyLength * 0.25, 5e-3, 0.0212);
|
|
5561
|
+
const bolt = kit.pivot(group);
|
|
5562
|
+
parts.bolt = bolt;
|
|
5563
|
+
box2(bolt, 0.044, 0.02, 6e-3, M.steelL, bodyLength * 0.25, 5e-3, 0.02);
|
|
5564
|
+
if (options.shot) {
|
|
5565
|
+
cylinderX(group, 0.012, bodyLength * 0.75, M.metal, bodyLength * 0.55, -0.025, 0.014, 14);
|
|
5566
|
+
cylinderX(group, 0.012, bodyLength * 0.75, M.metal, bodyLength * 0.55, -0.025, -0.014, 14);
|
|
5567
|
+
const pump = kit.pivot(group);
|
|
5568
|
+
parts.pump = pump;
|
|
5569
|
+
box2(pump, 0.15, 0.045, 0.052, M.poly, bodyLength + 0.06, -0.015, 0);
|
|
5570
|
+
for (let i = 0; i < 6; i++) box2(pump, 6e-3, 0.047, 0.054, M.dark, bodyLength + 5e-3 + i * 0.022, -0.015, 0);
|
|
5571
|
+
rail(kit, group, bodyLength * 0.15, bodyLength * 0.8, 0.04, 0, 0.02);
|
|
5572
|
+
parts.loadPort = kit.mark(group, bodyLength * 0.2, -0.04, 0);
|
|
5474
5573
|
} else {
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
const selector = box2(slide2, 0.01, 8e-3, 3e-3, M.dark, 0.014, -slideHeight * 0.2, slideWidth / 2 + 14e-4);
|
|
5485
|
-
parts.safety ?? (parts.safety = selector);
|
|
5574
|
+
const magazine = kit.pivot(group, gx - 0.11, -0.03, 0);
|
|
5575
|
+
magazine.rotation.z = 0.14;
|
|
5576
|
+
parts.mag = magazine;
|
|
5577
|
+
box2(magazine, 0.05, 0.14, 0.026, M.glass, 0, -0.07, 0);
|
|
5578
|
+
for (let i = 0; i < 6; i++) cylinderX(magazine, 3e-3, 0.04, M.brass, 0, -0.01 - i * 0.02, 0, 6);
|
|
5579
|
+
parts.magDrop = 0.18;
|
|
5580
|
+
scope(kit, group, 2, bodyLength * 0.5, 0.04, 0);
|
|
5581
|
+
box2(group, 0.2, 0.03, 0.02, body, bodyLength * 0.62, 0.048, 0);
|
|
5582
|
+
box2(group, 0.026, 0.075, 0.026, body, bodyLength + 0.05, -0.05, 0, 0.1);
|
|
5486
5583
|
}
|
|
5584
|
+
parts.muzzle = kit.mark(group, L + 0.01, 0.012, 0);
|
|
5585
|
+
parts.eject = kit.mark(group, bodyLength * 0.25, 5e-3, 0.03);
|
|
5586
|
+
return { group, parts };
|
|
5487
5587
|
}
|
|
5488
5588
|
|
|
5489
|
-
// src/models/
|
|
5490
|
-
var
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
sig: { rf: 0.14, ga: -0.3, grip: "rubber", guard: "hook", hammer: "spur", sight: "3dot", port: 0.19, decock: "frame", rail: 1, tall: 1.12, frame: "metal" },
|
|
5497
|
-
cz: { rf: 0.32, ga: -0.3, grip: "rubber", guard: "round", hammer: "spur", sight: "3dot", port: 0.15, inset: 1, safety: "thumb", frame: "metal" },
|
|
5498
|
-
m1911: { rf: 0.24, ga: -0.2, grip: "wood", guard: "round", hammer: "ring", sight: "small", port: 0.12, bushing: 1, beaver: 1, safety: "thumb", slideStop: 1, frame: "metal" },
|
|
5499
|
-
makarov: { rf: 0.48, ga: -0.24, grip: "star", guard: "round", hammer: "ring", sight: "small", port: 0.14, flush: 1, safety: "slide", lanyard: 1, frame: "metal" },
|
|
5500
|
-
fiveseven: { rf: 0.2, ga: -0.4, grip: "chunky", guard: "square", rail: 1, sight: "3dot", port: 0.18, slope: 1, frame: "poly" },
|
|
5501
|
-
deagle: { rf: 0.08, ga: -0.28, grip: "rubber", guard: "round", hammer: "big", sight: "small", port: 0.16, tri: 1, safety: "slide", frame: "metal" }
|
|
5589
|
+
// src/models/launcher-flame.ts
|
|
5590
|
+
var hose = (kit, group, points, radius, material) => {
|
|
5591
|
+
const { THREE } = kit;
|
|
5592
|
+
const curve = new THREE.CatmullRomCurve3(points.map((point) => new THREE.Vector3(...point)));
|
|
5593
|
+
const tube = new THREE.Mesh(new THREE.TubeGeometry(curve, 40, radius, 8, false), material);
|
|
5594
|
+
tube.castShadow = tube.receiveShadow = true;
|
|
5595
|
+
group.add(tube);
|
|
5502
5596
|
};
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
const
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
kit.
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
const grip = kit.pivot(group, gx, gy, 0);
|
|
5534
|
-
grip.rotation.z = style.ga;
|
|
5535
|
-
parts.grip = grip;
|
|
5536
|
-
const gripWidth = style.grip === "chunky" ? w * 1.18 : w * 1.06;
|
|
5537
|
-
const gripDepth = style.grip === "chunky" ? 0.036 : 0.032;
|
|
5538
|
-
kit.roundness = 0.3;
|
|
5539
|
-
if (style.grip === "wood" || style.grip === "star") {
|
|
5540
|
-
box2(grip, gripDepth * 0.86, gripLength, w * 0.9, fm, 0, 0, 0);
|
|
5541
|
-
box2(grip, gripDepth * 0.8, gripLength * 0.86, 4e-3, materials.grip, 1e-3, -2e-3, w * 0.47);
|
|
5542
|
-
box2(grip, gripDepth * 0.8, gripLength * 0.86, 4e-3, materials.grip, 1e-3, -2e-3, -w * 0.47);
|
|
5543
|
-
if (style.grip === "wood") {
|
|
5544
|
-
for (let i = 0; i < 6; i++) for (let j = 0; j < 2; j++) box2(grip, 3e-3, 3e-3, 12e-4, M.woodL, -6e-3 + j * 0.012, -gripLength * 0.3 + i * 0.012, w * 0.495, 0, 0, 0);
|
|
5545
|
-
cylinderZ(grip, 35e-4, 15e-4, M.brass, 0, gripLength * 0.25, w * 0.5, 10);
|
|
5546
|
-
cylinderZ(grip, 35e-4, 15e-4, M.brass, 0, -gripLength * 0.3, w * 0.5, 10);
|
|
5547
|
-
} else cylinderZ(grip, 8e-3, 15e-4, M.dark, 0, gripLength * 0.1, w * 0.5, 5);
|
|
5548
|
-
} else box2(grip, gripDepth, gripLength, gripWidth, materials.grip, 0, 0, 0);
|
|
5549
|
-
kit.roundness = null;
|
|
5550
|
-
if (style.grip === "finger") {
|
|
5551
|
-
for (let i = 0; i < 3; i++) box2(grip, 6e-3, 0.012, gripWidth * 0.98, materials.grip, gripDepth / 2 + 2e-3, gripLength * 0.18 - i * 0.022, 0);
|
|
5552
|
-
for (let i = 0; i < 5; i++) for (let j = 0; j < 3; j++) box2(grip, 3e-3, 3e-3, 12e-4, M.dark, -8e-3 + j * 8e-3, -gripLength * 0.25 + i * 0.012, gripWidth / 2 + 4e-4);
|
|
5553
|
-
}
|
|
5554
|
-
if (style.grip === "panel" || style.grip === "rubber" || style.grip === "chunky") for (let i = 0; i < 6; i++) box2(grip, gripDepth * 0.75, 25e-4, gripWidth + 1e-3, M.dark, 2e-3, -gripLength / 2 + 0.018 + i * 0.013, 0);
|
|
5555
|
-
if (style.grip === "chunky") box2(grip, 8e-3, gripLength * 0.8, gripWidth * 0.9, materials.grip, gripDepth / 2 + 2e-3, -4e-3, 0);
|
|
5556
|
-
if (style.beaver) {
|
|
5557
|
-
box2(group, 0.026, 8e-3, w * 0.9, fm, -4e-3, -h / 2 - 4e-3, 0, 0.25);
|
|
5558
|
-
box2(grip, 6e-3, gripLength * 0.55, w * 0.9, fm, -gripDepth * 0.5 - 2e-3, gripLength * 0.18, 0);
|
|
5559
|
-
} else box2(group, 0.02, 9e-3, w * 0.9, fm, 4e-3, -h / 2 - 6e-3, 0);
|
|
5560
|
-
if (style.lanyard) {
|
|
5561
|
-
const ring = kit.torus(grip, new kit.THREE.TorusGeometry(5e-3, 13e-4, 6, 12), M.dark, -0.012, -gripLength / 2 + 4e-3, 0);
|
|
5562
|
-
ring.position.set(-0.012, -gripLength / 2 + 4e-3, 0);
|
|
5597
|
+
var pilot = (kit, group, x, y) => {
|
|
5598
|
+
const { M, cylinderX } = kit;
|
|
5599
|
+
cylinderX(group, 6e-3, 0.03, M.fire2, x + 0.015, y, 0, 6, 0).userData.flame = 1;
|
|
5600
|
+
cylinderX(group, 4e-3, 0.022, M.fire, x + 0.012, y, 0, 6, 0).userData.flame = 1;
|
|
5601
|
+
};
|
|
5602
|
+
function buildFlamethrower(kit, group, parts) {
|
|
5603
|
+
const { M, box: box2, cylinderX, cylinderY, sphere } = kit;
|
|
5604
|
+
parts.kick = 0.15;
|
|
5605
|
+
heatify(parts.glow, cylinderX(group, 0.016, 0.62, M.steel, 0.42, 0, 0, 14));
|
|
5606
|
+
cylinderX(group, 0.022, 0.1, M.dark, 0.78, 0, 0, 14);
|
|
5607
|
+
heatify(parts.glow, cylinderX(group, 0.013, 0.1, M.steel, 0.88, 0, 0, 12, 9e-3));
|
|
5608
|
+
cylinderX(group, 0.018, 0.02, M.metal, 0.73, 0, 0, 14);
|
|
5609
|
+
cylinderX(group, 0.012, 0.06, M.metal, 0.84, -0.025, 0, 10);
|
|
5610
|
+
pilot(kit, group, 0.92, -0.012);
|
|
5611
|
+
const foreGrip = kit.pivot(group, 0.6, -0.02, 0);
|
|
5612
|
+
foreGrip.rotation.z = -0.1;
|
|
5613
|
+
box2(foreGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5614
|
+
const lever = kit.pivot(group, 0.62, -0.02, 0);
|
|
5615
|
+
parts.trigger = box2(lever, 8e-3, 0.05, 6e-3, M.metal, 0.02, -0.03, 0, 0.3);
|
|
5616
|
+
const rearGrip = kit.pivot(group, 0.17, -0.02, 0);
|
|
5617
|
+
rearGrip.rotation.z = -0.28;
|
|
5618
|
+
box2(rearGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5619
|
+
box2(group, 0.05, 4e-3, 0.012, M.metal, 0.2, -0.035, 0);
|
|
5620
|
+
cylinderX(group, 0.02, 0.04, M.metal, 0.1, 0, 0, 12);
|
|
5621
|
+
hose(kit, group, [[0.08, 0, 0], [0, -0.04, 0], [-0.08, -0.2, 0.05], [-0.18, -0.32, 0.08], [-0.25, -0.33, 0.08]], 0.011, M.rubber);
|
|
5622
|
+
for (const z of [-0.1, 0.1]) {
|
|
5623
|
+
cylinderY(group, 0.085, 0.5, M.olive, -0.3, -0.05, z, 20);
|
|
5624
|
+
sphere(group, 0.085, M.olive, -0.3, 0.2, z, 2).scale.y = 0.45;
|
|
5625
|
+
sphere(group, 0.085, M.olive, -0.3, -0.3, z, 2).scale.y = 0.45;
|
|
5626
|
+
cylinderY(group, 0.03, 0.03, M.metal, -0.3, 0.24, z, 12);
|
|
5563
5627
|
}
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5628
|
+
sphere(group, 0.075, M.olive, -0.3, 0.1, 0, 2).position.x = -0.39;
|
|
5629
|
+
box2(group, 0.03, 0.6, 0.24, M.dark, -0.4, -0.05, 0);
|
|
5630
|
+
cylinderY(group, 0.03, 0.012, M.metal, -0.39, 0.18, 0, 14);
|
|
5631
|
+
const gauge = kit.pivot(group, -0.39, 0.18, 3e-3);
|
|
5632
|
+
parts.gauge = gauge;
|
|
5633
|
+
box2(gauge, 2e-3, 0.022, 2e-3, M.red, 0, 8e-3, 0.012);
|
|
5634
|
+
parts.muzzle = kit.pivot(group, 0.94, 0, 0);
|
|
5635
|
+
parts.rear = kit.pivot(group, 0.1, 0, 0);
|
|
5572
5636
|
}
|
|
5573
|
-
function
|
|
5574
|
-
const { M, box: box2 } = kit;
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
const
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
const guard = kit.torus(group, new kit.THREE.TorusGeometry(0.019, 22e-4, 6, 16, PI6), frameMetal, gx + 0.05, ty - 0.014, 0);
|
|
5598
|
-
guard.rotation.z = PI6;
|
|
5599
|
-
guard.scale.set(1.2, 1, 1);
|
|
5600
|
-
}
|
|
5601
|
-
const isGlock = options.st === "glock" || !options.st;
|
|
5602
|
-
parts.trigger = box2(group, 4e-3, 0.014, 4e-3, isGlock ? M.dark : M.steel, gx + 0.042, ty - 0.022, 0, 0.2);
|
|
5603
|
-
if (isGlock) box2(parts.trigger, 15e-4, 8e-3, 45e-4, M.metal, 0, -1e-3, 0);
|
|
5604
|
-
if (style.hammer) {
|
|
5605
|
-
const hammer = kit.pivot(group, 3e-3, h / 2 - 8e-3, 0);
|
|
5606
|
-
parts.hammer = hammer;
|
|
5607
|
-
if (style.hammer === "ring") {
|
|
5608
|
-
box2(hammer, 6e-3, 0.012, 6e-3, M.dark, -2e-3, 4e-3, 0, 0.3);
|
|
5609
|
-
kit.torus(hammer, new kit.THREE.TorusGeometry(45e-4, 16e-4, 6, 12), M.dark, -4e-3, 0.012, 0);
|
|
5610
|
-
} else if (style.hammer === "big") box2(hammer, 0.014, 0.02, 9e-3, M.dark, -4e-3, 7e-3, 0, 0.35);
|
|
5611
|
-
else {
|
|
5612
|
-
box2(hammer, 8e-3, 0.016, 7e-3, M.dark, -2e-3, 6e-3, 0, 0.3);
|
|
5613
|
-
box2(hammer, 8e-3, 4e-3, 8e-3, M.dark, -6e-3, 0.013, 0, 0.3);
|
|
5614
|
-
}
|
|
5615
|
-
}
|
|
5616
|
-
parts.muzzle = kit.mark(group, L + 6e-3, style.tri ? h * 0.08 : 2e-3, 0);
|
|
5617
|
-
parts.eject = kit.mark(group, L * 0.6, h / 2, w * 0.25);
|
|
5618
|
-
return { group, parts };
|
|
5637
|
+
function buildImprovisedFlamethrower(kit, group, parts) {
|
|
5638
|
+
const { M, box: box2, cylinderX, cylinderY, sphere } = kit;
|
|
5639
|
+
parts.kick = 0.12;
|
|
5640
|
+
heatify(parts.glow, cylinderX(group, 0.011, 0.66, M.pipe, 0.38, 0, 0, 12));
|
|
5641
|
+
heatify(parts.glow, cylinderX(group, 0.015, 0.06, M.steel, 0.74, 0, 0, 12, 0.01));
|
|
5642
|
+
cylinderX(group, 6e-3, 0.05, M.metal, 0.735, -0.02, 0, 8);
|
|
5643
|
+
pilot(kit, group, 0.77, -0.02);
|
|
5644
|
+
cylinderY(group, 0.012, 0.04, M.redPaint, 0.72, -0.055, 0, 10);
|
|
5645
|
+
box2(group, 0.02, 0.03, 0.012, M.dark, 0.72, -0.085, 0);
|
|
5646
|
+
cylinderX(group, 0.06, 0.42, M.redPaint, 0.3, -0.09, 0, 22);
|
|
5647
|
+
sphere(group, 0.06, M.redPaint, 0.51, -0.09, 0, 2).scale.x = 0.5;
|
|
5648
|
+
sphere(group, 0.06, M.redPaint, 0.09, -0.09, 0, 2).scale.x = 0.5;
|
|
5649
|
+
cylinderX(group, 0.02, 0.04, M.dark, 0.04, -0.09, 0, 12);
|
|
5650
|
+
box2(group, 0.02, 0.06, 5e-3, M.white, 0.3, -0.09, 0.06);
|
|
5651
|
+
for (const x of [0.15, 0.3, 0.45]) cylinderX(group, 0.063, 0.03, M.tape, x, -0.09, 0, 22);
|
|
5652
|
+
cylinderX(group, 0.016, 0.03, M.tape, 0.3, 0, 0, 12);
|
|
5653
|
+
hose(kit, group, [[0.04, -0.09, 0], [-0.02, -0.06, 0.02], [0, 0, 0.02], [0.05, 0, 0]], 7e-3, M.rubber);
|
|
5654
|
+
const rearGrip = kit.pivot(group, 0.12, -0.01, 0);
|
|
5655
|
+
rearGrip.rotation.z = -0.3;
|
|
5656
|
+
box2(rearGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5657
|
+
const lever = kit.pivot(group, 0.17, -0.02, 0);
|
|
5658
|
+
parts.trigger = box2(lever, 8e-3, 0.04, 6e-3, M.metal, 0, -0.02, 0, 0.2);
|
|
5659
|
+
parts.muzzle = kit.pivot(group, 0.78, 0, 0);
|
|
5660
|
+
parts.rear = kit.pivot(group, 0.05, 0, 0);
|
|
5619
5661
|
}
|
|
5620
5662
|
|
|
5621
|
-
// src/models/
|
|
5622
|
-
var
|
|
5623
|
-
|
|
5624
|
-
|
|
5663
|
+
// src/models/launcher-rounds.ts
|
|
5664
|
+
var PI6 = Math.PI;
|
|
5665
|
+
function buildRocketGrenade(kit) {
|
|
5666
|
+
const { M, cylinderX } = kit;
|
|
5667
|
+
const round2 = kit.group();
|
|
5668
|
+
cylinderX(round2, 0.018, 0.15, M.olive, -0.05, 0, 0, 14);
|
|
5669
|
+
cylinderX(round2, 0.02, 0.07, M.olive, 0.035, 0, 0, 18, 0.0425);
|
|
5670
|
+
cylinderX(round2, 0.0425, 0.12, M.olive, 0.13, 0, 0, 20);
|
|
5671
|
+
cylinderX(round2, 0.0428, 0.012, M.dark, 0.09, 0, 0, 20);
|
|
5672
|
+
cylinderX(round2, 0.0425, 0.13, M.olive, 0.255, 0, 0, 20, 0.011);
|
|
5673
|
+
cylinderX(round2, 0.011, 0.03, M.metal, 0.335, 0, 0, 10, 4e-3);
|
|
5674
|
+
return round2;
|
|
5675
|
+
}
|
|
5676
|
+
function buildRecoillessRound(kit) {
|
|
5677
|
+
const { M, cylinderX } = kit;
|
|
5678
|
+
const round2 = kit.group();
|
|
5679
|
+
cylinderX(round2, 0.041, 0.32, M.green, -0.16, 0, 0, 20);
|
|
5680
|
+
cylinderX(round2, 0.0415, 0.02, M.yellow, -0.05, 0, 0, 20);
|
|
5681
|
+
cylinderX(round2, 0.041, 0.12, M.green, 0.06, 0, 0, 20, 0.012);
|
|
5682
|
+
cylinderX(round2, 0.043, 0.03, M.brass, -0.33, 0, 0, 20);
|
|
5683
|
+
return round2;
|
|
5684
|
+
}
|
|
5685
|
+
function buildFlyingRocket(kit, launcherType) {
|
|
5625
5686
|
const { M, box: box2, cylinderX } = kit;
|
|
5626
|
-
const
|
|
5627
|
-
const
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
const crane = kit.pivot(group, 0.077, -0.024, 0);
|
|
5635
|
-
parts.crane = crane;
|
|
5636
|
-
const cylinder = kit.pivot(crane, 0, 0.022, 0);
|
|
5637
|
-
parts.cylinder = cylinder;
|
|
5638
|
-
cylinderX(cylinder, 0.0215, 0.042, metal2, 0, 0, 0, 24);
|
|
5639
|
-
for (let i = 0; i < chambers; i++) {
|
|
5640
|
-
const angle = i * 2 * PI7 / chambers;
|
|
5641
|
-
box2(cylinder, 0.026, 5e-3, 5e-3, M.dark, 0, Math.cos(angle) * 0.0205, Math.sin(angle) * 0.0205, 0, 0, angle);
|
|
5642
|
-
}
|
|
5643
|
-
parts.chambers = [];
|
|
5644
|
-
for (let i = 0; i < chambers; i++) {
|
|
5645
|
-
const angle = i * 2 * PI7 / chambers + PI7 / chambers;
|
|
5646
|
-
parts.chambers.push(kit.mark(cylinder, -0.022, Math.cos(angle) * 0.013, Math.sin(angle) * 0.013));
|
|
5647
|
-
cylinderX(cylinder, 46e-4, 2e-3, M.brass, -0.0215, Math.cos(angle) * 0.013, Math.sin(angle) * 0.013, 12);
|
|
5687
|
+
const rocket = kit.group();
|
|
5688
|
+
const diameter = launcherType === "at4" || launcherType === "carl" ? 0.041 : 0.032;
|
|
5689
|
+
cylinderX(rocket, diameter * 0.5, 0.2, M.dark, -0.1, 0, 0, 10);
|
|
5690
|
+
cylinderX(rocket, diameter, 0.3, M.olive, 0.15, 0, 0, 18);
|
|
5691
|
+
cylinderX(rocket, diameter, 0.12, M.olive, 0.36, 0, 0, 18, diameter * 0.25);
|
|
5692
|
+
for (let i = 0; i < 4; i++) {
|
|
5693
|
+
const fin = box2(rocket, 0.06, 2e-3, diameter * 1.4, M.metal, -0.17, 0, 0);
|
|
5694
|
+
fin.rotation.x = i * PI6 / 4;
|
|
5648
5695
|
}
|
|
5649
|
-
|
|
5650
|
-
box2(group, barrel * 0.92, 0.015, 0.013, metal2, 0.112 + barrel * 0.46, -5e-3, 0);
|
|
5651
|
-
cylinderX(group, 4e-3, 5e-3, M.hole, 0.112 + barrel + 15e-4, 9e-3, 0, 12);
|
|
5652
|
-
box2(group, 0.012, 9e-3, 4e-3, M.dark, 0.112 + barrel - 8e-3, 0.021, 0, -0.3);
|
|
5653
|
-
box2(group, 0.012, 6e-3, 0.012, M.dark, 0.105, 0.031, 0);
|
|
5654
|
-
const hammer = kit.pivot(group, 0.036, 0.018, 0);
|
|
5655
|
-
box2(hammer, 0.01, 0.02, 8e-3, M.dark, -4e-3, 8e-3, 0, 0.45);
|
|
5656
|
-
parts.hammer = hammer;
|
|
5657
|
-
const grip = kit.pivot(group, 0.024, -0.062, 0);
|
|
5658
|
-
grip.rotation.z = -0.38;
|
|
5659
|
-
parts.grip = grip;
|
|
5660
|
-
box2(grip, 0.034, 0.1, 0.031, options.wood ? M.wood : M.rubber, 0, 0, 0);
|
|
5661
|
-
if (!options.wood) for (let i = 0; i < 4; i++) box2(grip, 6e-3, 0.07, 0.033, M.dark, -0.012 + i * 8e-3, 0, 0);
|
|
5662
|
-
box2(group, 0.038, 4e-3, 8e-3, metal2, 0.062, -0.036, 0);
|
|
5663
|
-
box2(group, 4e-3, 0.022, 8e-3, metal2, 0.08, -0.026, 0, 0.2);
|
|
5664
|
-
parts.trigger = box2(group, 4e-3, 0.015, 4e-3, M.dark, 0.06, -0.027, 0, 0.2);
|
|
5665
|
-
parts.muzzle = kit.mark(group, 0.112 + barrel + 6e-3, 9e-3, 0);
|
|
5666
|
-
parts.eject = kit.mark(group, 0.077, 0, 0);
|
|
5667
|
-
return { group, parts };
|
|
5696
|
+
return rocket;
|
|
5668
5697
|
}
|
|
5669
5698
|
|
|
5670
|
-
// src/models/
|
|
5671
|
-
function
|
|
5699
|
+
// src/models/launcher-rocket.ts
|
|
5700
|
+
function buildRpg(kit, group, parts) {
|
|
5672
5701
|
const { M, box: box2, cylinderX } = kit;
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5702
|
+
parts.kick = 1.6;
|
|
5703
|
+
cylinderX(group, 0.036, 0.13, M.dark, 0.065, 0, 0, 20, 0.021);
|
|
5704
|
+
cylinderX(group, 0.038, 0.012, M.metal, 0, 0, 0, 20);
|
|
5705
|
+
heatify(parts.glow, cylinderX(group, 0.021, 0.83, M.steel, 0.545, 0, 0, 18));
|
|
5706
|
+
cylinderX(group, 0.03, 0.3, M.wood, 0.47, 0, 0, 16);
|
|
5707
|
+
cylinderX(group, 0.031, 0.012, M.metal, 0.32, 0, 0, 16);
|
|
5708
|
+
cylinderX(group, 0.031, 0.012, M.metal, 0.62, 0, 0, 16);
|
|
5709
|
+
cylinderX(group, 0.024, 0.02, M.metal, 0.94, 0, 0, 16);
|
|
5710
|
+
box2(group, 0.09, 0.03, 0.032, M.metal, 0.46, -0.028, 0);
|
|
5711
|
+
const frontGrip = kit.pivot(group, 0.4, -0.04, 0);
|
|
5712
|
+
frontGrip.rotation.z = -0.22;
|
|
5713
|
+
box2(frontGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5714
|
+
const rearGrip = kit.pivot(group, 0.5, -0.04, 0);
|
|
5715
|
+
rearGrip.rotation.z = -0.18;
|
|
5716
|
+
box2(rearGrip, 0.03, 0.1, 0.03, M.wood, 0, -0.05, 0);
|
|
5717
|
+
box2(group, 0.06, 4e-3, 0.012, M.metal, 0.53, -0.05, 0);
|
|
5718
|
+
box2(group, 4e-3, 0.025, 0.012, M.metal, 0.56, -0.04, 0);
|
|
5719
|
+
parts.trigger = box2(group, 4e-3, 0.018, 4e-3, M.dark, 0.535, -0.045, 0, 0.15);
|
|
5720
|
+
const hammer = kit.pivot(group, 0.44, -0.012, 0);
|
|
5721
|
+
parts.hammer = hammer;
|
|
5722
|
+
box2(hammer, 0.012, 0.02, 0.01, M.dark, 0, 0, 0);
|
|
5723
|
+
box2(group, 6e-3, 0.03, 6e-3, M.dark, 0.78, 0.032, 0);
|
|
5724
|
+
box2(group, 0.02, 0.022, 0.014, M.dark, 0.46, 0.032, 0);
|
|
5725
|
+
box2(group, 0.12, 0.042, 0.032, M.dark, 0.5, 0.04, -0.04);
|
|
5726
|
+
cylinderX(group, 0.013, 0.05, M.rubber, 0.42, 0.048, -0.04, 14);
|
|
5727
|
+
cylinderX(group, 0.016, 4e-3, M.lens, 0.565, 0.048, -0.04, 14);
|
|
5728
|
+
box2(group, 0.04, 0.012, 0.012, M.metal, 0.5, 0.016, -0.03);
|
|
5729
|
+
const round2 = buildRocketGrenade(kit);
|
|
5730
|
+
round2.position.x = 0.95;
|
|
5731
|
+
group.add(round2);
|
|
5732
|
+
parts.round = round2;
|
|
5733
|
+
parts.roundRest = 0.95;
|
|
5734
|
+
parts.makeRound = () => buildRocketGrenade(kit);
|
|
5735
|
+
parts.muzzle = kit.pivot(group, 0.95, 0, 0);
|
|
5736
|
+
parts.rear = kit.pivot(group, 0, 0, 0);
|
|
5684
5737
|
}
|
|
5685
|
-
function
|
|
5686
|
-
|
|
5738
|
+
function buildM72(kit, group, parts) {
|
|
5739
|
+
const { M, box: box2, cylinderX, cylinderY } = kit;
|
|
5740
|
+
parts.kick = 1.1;
|
|
5741
|
+
parts.disposable = true;
|
|
5742
|
+
heatify(parts.glow, cylinderX(group, 0.0365, 0.6, M.olive, 0.58, 0, 0, 20));
|
|
5743
|
+
cylinderX(group, 0.032, 0.32, M.olive, 0.16, 0, 0, 20);
|
|
5744
|
+
cylinderX(group, 0.039, 0.03, M.rubber, 0.866, 0, 0, 20);
|
|
5745
|
+
cylinderX(group, 0.035, 0.025, M.rubber, 0.012, 0, 0, 20);
|
|
5746
|
+
cylinderX(group, 0.037, 0.015, M.yellow, 0.8, 0, 0, 20);
|
|
5747
|
+
cylinderX(group, 0.037, 0.012, M.dark, 0.3, 0, 0, 20);
|
|
5748
|
+
box2(group, 4e-3, 0.05, 0.05, M.dark, 0.79, 0.055, 0);
|
|
5749
|
+
box2(group, 4e-3, 6e-3, 0.04, M.dark, 0.79, 0.078, 0);
|
|
5750
|
+
box2(group, 4e-3, 0.035, 0.024, M.dark, 0.38, 0.05, 0);
|
|
5751
|
+
cylinderY(group, 4e-3, 6e-3, M.lens, 0.38, 0.064, 0, 8);
|
|
5752
|
+
parts.trigger = box2(group, 0.05, 0.016, 0.024, M.rubber, 0.5, 0.042, 0);
|
|
5753
|
+
box2(group, 0.1, 0.01, 0.03, M.dark, 0.47, 0.036, 0);
|
|
5754
|
+
box2(group, 0.02, 0.03, 0.01, M.dark, 0.66, -0.035, 0.03);
|
|
5755
|
+
box2(group, 8e-3, 0.03, 8e-3, M.metal, 0.25, -0.04, 0.03);
|
|
5756
|
+
parts.muzzle = kit.pivot(group, 0.881, 0, 0);
|
|
5757
|
+
parts.rear = kit.pivot(group, 0, 0, 0);
|
|
5687
5758
|
}
|
|
5688
|
-
|
|
5689
|
-
// src/models/attachments/bipod.ts
|
|
5690
|
-
function buildBipod(kit, parent, x, y) {
|
|
5759
|
+
function buildAt4(kit, group, parts) {
|
|
5691
5760
|
const { M, box: box2, cylinderX } = kit;
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5761
|
+
parts.kick = 1.3;
|
|
5762
|
+
parts.disposable = true;
|
|
5763
|
+
heatify(parts.glow, cylinderX(group, 0.05, 0.86, M.olive, 0.51, 0, 0, 24));
|
|
5764
|
+
cylinderX(group, 0.056, 0.08, M.dark, 0.98, 0, 0, 24);
|
|
5765
|
+
cylinderX(group, 0.058, 0.07, M.dark, 0.04, 0, 0, 24, 0.05);
|
|
5766
|
+
cylinderX(group, 0.051, 0.015, M.yellow, 0.86, 0, 0, 24);
|
|
5767
|
+
box2(group, 0.16, 0.026, 0.05, M.dark, 0.42, 0.058, 0);
|
|
5768
|
+
box2(group, 0.03, 0.012, 0.016, M.red, 0.47, 0.075, 0);
|
|
5769
|
+
parts.trigger = box2(group, 0.022, 0.012, 0.018, M.rubber, 0.5, 0.074, 0);
|
|
5770
|
+
box2(group, 0.012, 0.07, 0.02, M.dark, 0.35, 0.09, -0.035);
|
|
5771
|
+
box2(group, 0.012, 0.05, 0.02, M.dark, 0.71, 0.08, -0.035);
|
|
5772
|
+
const grip = kit.pivot(group, 0.68, -0.05, 0);
|
|
5773
|
+
grip.rotation.z = -0.15;
|
|
5774
|
+
parts.grip = grip;
|
|
5775
|
+
box2(grip, 0.035, 0.11, 0.032, M.dark, 0, -0.05, 0);
|
|
5776
|
+
box2(group, 0.14, 0.035, 0.06, M.rubber, 0.32, -0.06, 0);
|
|
5777
|
+
box2(group, 0.3, 0.012, 0.055, M.dark, 0.5, -0.05, 0);
|
|
5778
|
+
parts.muzzle = kit.pivot(group, 1.02, 0, 0);
|
|
5779
|
+
parts.rear = kit.pivot(group, 0, 0, 0);
|
|
5699
5780
|
}
|
|
5700
|
-
|
|
5701
|
-
const
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
const
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
parts.lever = lever;
|
|
5730
|
-
box2(lever, 0.11, 6e-3, 0.012, M.metal, 0.055, -0.052, 0);
|
|
5731
|
-
box2(lever, 6e-3, 0.05, 0.012, M.metal, 3e-3, -0.028, 0);
|
|
5732
|
-
box2(lever, 6e-3, 0.05, 0.012, M.metal, 0.108, -0.028, 0);
|
|
5733
|
-
box2(lever, 0.04, 6e-3, 0.012, M.metal, 0.08, -2e-3, 0);
|
|
5734
|
-
box2(group, 0.03, 0.012, 3e-3, M.dark, x1 - 0.04, by, wR / 2 + 1e-3);
|
|
5735
|
-
}
|
|
5736
|
-
if (o.tube) {
|
|
5737
|
-
const tubeLength = (L - x1) * (o.tubeLen || 0.8);
|
|
5738
|
-
cylinderX(group, 0.0105, tubeLength, M.metal, x1 + tubeLength / 2, by - 0.023, 0, 16);
|
|
5739
|
-
cylinderX(group, 0.0125, 0.02, M.dark, x1 + tubeLength + 6e-3, by - 0.023, 0, 16);
|
|
5740
|
-
}
|
|
5741
|
-
if (o.pump) {
|
|
5742
|
-
const pump = kit.pivot(group);
|
|
5743
|
-
parts.pump = pump;
|
|
5744
|
-
box2(pump, 0.17, 0.042, 0.046, furn, x1 + 0.14, by - 0.022, 0);
|
|
5745
|
-
for (let i = 0; i < 8; i++) box2(pump, 6e-3, 0.044, 0.048, M.dark, x1 + 0.07 + i * 0.02, by - 0.022, 0);
|
|
5746
|
-
}
|
|
5747
|
-
if (o.heat) {
|
|
5748
|
-
cylinderX(group, r * 1.75, (L - x1) * 0.7, M.dark, x1 + (L - x1) * 0.4, by, 0, 12);
|
|
5749
|
-
for (let i = 0; i < 10; i++) box2(group, 8e-3, r * 1.5, 4e-3, M.hole, x1 + (L - x1) * (0.1 + i * 0.06), by + r * 0.8, r * 1.5);
|
|
5750
|
-
}
|
|
5751
|
-
if (o.bayo) box2(group, 0.025, 8e-3, 0.01, M.metal, L - 0.07, by - 0.016, 0);
|
|
5752
|
-
if (o.rod) cylinderX(group, 3e-3, (L - x1) * 0.85, M.steel, x1 + (L - x1) * 0.45, by - 0.014, 0, 8);
|
|
5781
|
+
function buildCarlGustaf(kit, group, parts) {
|
|
5782
|
+
const { M, box: box2, cylinderX } = kit;
|
|
5783
|
+
parts.kick = 1.4;
|
|
5784
|
+
heatify(parts.glow, cylinderX(group, 0.045, 0.72, M.dark, 0.59, 0, 0, 24));
|
|
5785
|
+
cylinderX(group, 0.05, 0.04, M.rubber, 0.93, 0, 0, 24);
|
|
5786
|
+
const breech = kit.pivot(group, 0.21, 0, 0.05);
|
|
5787
|
+
parts.breech = [breech];
|
|
5788
|
+
cylinderX(breech, 0.06, 0.16, M.dark, -0.1, 0, -0.05, 24, 0.046);
|
|
5789
|
+
cylinderX(breech, 0.062, 0.015, M.metal, -0.18, 0, -0.05, 24);
|
|
5790
|
+
box2(group, 0.025, 0.03, 0.02, M.metal, 0.22, 0, 0.052);
|
|
5791
|
+
const foreGrip = kit.pivot(group, 0.62, -0.05, 0);
|
|
5792
|
+
foreGrip.rotation.z = -0.2;
|
|
5793
|
+
box2(foreGrip, 0.035, 0.11, 0.034, M.dark, 0, -0.05, 0);
|
|
5794
|
+
parts.trigger = box2(group, 4e-3, 0.018, 4e-3, M.dark, 0.66, -0.06, 0, 0.15);
|
|
5795
|
+
box2(group, 0.06, 4e-3, 0.012, M.metal, 0.66, -0.07, 0);
|
|
5796
|
+
const rearGrip = kit.pivot(group, 0.4, -0.05, 0);
|
|
5797
|
+
rearGrip.rotation.z = -0.25;
|
|
5798
|
+
box2(rearGrip, 0.035, 0.1, 0.034, M.dark, 0, -0.05, 0);
|
|
5799
|
+
box2(group, 0.13, 0.04, 0.07, M.rubber, 0.28, -0.065, 0);
|
|
5800
|
+
box2(group, 0.16, 0.05, 0.045, M.dark, 0.56, 0.07, -0.035);
|
|
5801
|
+
cylinderX(group, 0.016, 0.05, M.rubber, 0.46, 0.075, -0.035, 14);
|
|
5802
|
+
cylinderX(group, 0.02, 4e-3, M.lens, 0.645, 0.075, -0.035, 14);
|
|
5803
|
+
box2(group, 0.06, 0.02, 0.02, M.metal, 0.56, 0.04, -0.03);
|
|
5804
|
+
box2(group, 0.22, 0.01, 0.02, M.dark, 0.6, 0.06, 0.03);
|
|
5805
|
+
box2(group, 0.01, 0.03, 0.02, M.dark, 0.5, 0.05, 0.03);
|
|
5806
|
+
box2(group, 0.01, 0.03, 0.02, M.dark, 0.7, 0.05, 0.03);
|
|
5807
|
+
parts.makeRound = () => buildRecoillessRound(kit);
|
|
5808
|
+
parts.muzzle = kit.pivot(group, 0.95, 0, 0);
|
|
5809
|
+
parts.rear = kit.pivot(group, 0.05, 0, 0);
|
|
5753
5810
|
}
|
|
5811
|
+
var ROCKET_BUILDERS = {
|
|
5812
|
+
rpg: buildRpg,
|
|
5813
|
+
m72: buildM72,
|
|
5814
|
+
at4: buildAt4,
|
|
5815
|
+
carl: buildCarlGustaf
|
|
5816
|
+
};
|
|
5754
5817
|
|
|
5755
|
-
// src/models/
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
const
|
|
5759
|
-
const
|
|
5760
|
-
const
|
|
5761
|
-
if (
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
box2(group, handguardLength, hh, wR * 1.04, M.dark, hx, by - 2e-3, 0);
|
|
5767
|
-
rail(kit, group, x1, handguardLength, by + hh / 2, 0, wR * 0.66);
|
|
5768
|
-
rail(kit, group, x1 + 0.01, handguardLength - 0.02, by - 2e-3, wR * 0.54, wR * 0.4, PI8 / 2);
|
|
5769
|
-
rail(kit, group, x1 + 0.01, handguardLength - 0.02, by - 2e-3, -wR * 0.54, wR * 0.4, -PI8 / 2);
|
|
5770
|
-
rail(kit, group, x1 + 0.01, handguardLength - 0.02, by - hh / 2, 0, wR * 0.6, PI8);
|
|
5771
|
-
} else {
|
|
5772
|
-
const material = o.hg === "wood" ? M.wood : furn;
|
|
5773
|
-
if (o.ak) {
|
|
5774
|
-
box2(group, handguardLength, hh * 0.55, wR * 1.08, material, hx, by - hh * 0.22, 0);
|
|
5775
|
-
box2(group, handguardLength * 0.75, hh * 0.35, wR * 0.7, material, hx - handguardLength * 0.1, by + r * 2.2, 0);
|
|
5776
|
-
} else {
|
|
5777
|
-
box2(group, handguardLength, hh, wR * 1.08, material, hx, by - 2e-3, 0);
|
|
5778
|
-
vents(kit, group, x1 + 0.01, handguardLength - 0.02, by + hh * 0.15, wR * 0.54 + 1e-3, Math.round(handguardLength / 0.025), hh * 0.3);
|
|
5779
|
-
vents(kit, group, x1 + 0.01, handguardLength - 0.02, by + hh * 0.15, -wR * 0.54 - 1e-3, Math.round(handguardLength / 0.025), hh * 0.3);
|
|
5780
|
-
}
|
|
5781
|
-
}
|
|
5782
|
-
if (!hasLongScope && !o.rail && o.ak) {
|
|
5783
|
-
box2(group, 0.03, 0.016, wR * 0.6, M.metal, x1 + 0.02, by + r * 2.5 + 0.01, 0);
|
|
5784
|
-
box2(group, 0.012, 4e-3, wR * 0.5, M.dark, x1 + 0.03, by + r * 2.5 + 0.019, 0);
|
|
5785
|
-
}
|
|
5786
|
-
}
|
|
5787
|
-
if (hasLongScope) return;
|
|
5788
|
-
const sightX = L - (o.ak ? 0.06 : 0.08);
|
|
5789
|
-
if (o.ak) {
|
|
5790
|
-
box2(group, 0.022, 0.022, wR * 0.6, M.metal, sightX, by + 8e-3, 0);
|
|
5791
|
-
box2(group, 6e-3, 0.024, 4e-3, M.metal, sightX, by + 0.026, 8e-3);
|
|
5792
|
-
box2(group, 6e-3, 0.024, 4e-3, M.metal, sightX, by + 0.026, -8e-3);
|
|
5793
|
-
box2(group, 3e-3, 0.016, 3e-3, M.dark, sightX, by + 0.022, 0);
|
|
5794
|
-
} else if (!o.rail || o.carry) {
|
|
5795
|
-
box2(group, 0.018, 0.014, wR * 0.55, M.dark, sightX, by + 8e-3, 0);
|
|
5796
|
-
box2(group, 0.012, 0.034, 8e-3, M.dark, sightX, by + 0.03, 0, -0.25);
|
|
5797
|
-
} else box2(group, 0.012, 0.024, 0.012, M.dark, sightX - 0.04, by + hR * 0.4 + 0.012, 0);
|
|
5818
|
+
// src/models/launcher.ts
|
|
5819
|
+
function buildLauncher(kit, options) {
|
|
5820
|
+
const group = kit.group();
|
|
5821
|
+
const type = options.lt ?? "";
|
|
5822
|
+
const isFlame = type === "flame" || type === "flameDIY";
|
|
5823
|
+
const parts = { family: isFlame ? "flame" : "rocket", launcherType: type, glow: [] };
|
|
5824
|
+
if (type === "flame") buildFlamethrower(kit, group, parts);
|
|
5825
|
+
else if (type === "flameDIY") buildImprovisedFlamethrower(kit, group, parts);
|
|
5826
|
+
else ROCKET_BUILDERS[type]?.(kit, group, parts);
|
|
5827
|
+
parts.eject = parts.muzzle;
|
|
5828
|
+
return { group, parts };
|
|
5798
5829
|
}
|
|
5799
5830
|
|
|
5800
|
-
// src/models/
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5831
|
+
// src/models/m134.ts
|
|
5832
|
+
var PI7 = Math.PI;
|
|
5833
|
+
var BARRELS = 6;
|
|
5834
|
+
var CLUSTER_RADIUS = 0.03;
|
|
5835
|
+
var BARREL_RADIUS = 78e-4;
|
|
5836
|
+
var BARREL_END = 0.8;
|
|
5837
|
+
function buildBarrelCluster(kit, parts, group) {
|
|
5838
|
+
const { M, cylinderX } = kit;
|
|
5839
|
+
const barrels = kit.pivot(group, 0, 0, 0);
|
|
5840
|
+
parts.barrels = barrels;
|
|
5841
|
+
const length = BARREL_END - 0.3;
|
|
5842
|
+
let heated;
|
|
5843
|
+
for (let i = 0; i < BARRELS; i++) {
|
|
5844
|
+
const angle = i * 2 * PI7 / BARRELS;
|
|
5845
|
+
const y = Math.cos(angle) * CLUSTER_RADIUS;
|
|
5846
|
+
const z = Math.sin(angle) * CLUSTER_RADIUS;
|
|
5847
|
+
const barrel = cylinderX(barrels, BARREL_RADIUS, length, M.metal, 0.3 + length / 2, y, z, 14);
|
|
5848
|
+
if (heated) barrel.material = heated;
|
|
5849
|
+
else heated = heatify(parts.glow, barrel).material;
|
|
5850
|
+
cylinderX(barrels, BARREL_RADIUS * 0.55, 4e-3, M.hole, BARREL_END + 5e-4, y, z, 10);
|
|
5808
5851
|
}
|
|
5852
|
+
cylinderX(barrels, 0.012, length, M.steel, 0.3 + length / 2, 0, 0, 12);
|
|
5853
|
+
for (const x of [0.42, 0.58, 0.74]) cylinderX(barrels, CLUSTER_RADIUS + BARREL_RADIUS * 1.6, 0.014, M.steel, x, 0, 0, 24);
|
|
5854
|
+
cylinderX(barrels, CLUSTER_RADIUS + BARREL_RADIUS * 1.8, 0.03, M.dark, BARREL_END - 0.015, 0, 0, 24);
|
|
5809
5855
|
}
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
box2(
|
|
5856
|
+
function buildHousing(kit, parts, group) {
|
|
5857
|
+
const { M, box: box2, cylinderX, cylinderZ } = kit;
|
|
5858
|
+
box2(group, 0.3, 0.14, 0.15, M.metal, 0.18, 0, 0);
|
|
5859
|
+
cylinderX(group, 0.052, 0.12, M.dark, 0.06, 0, 0, 20);
|
|
5860
|
+
cylinderX(group, 0.062, 0.2, M.dark, 0.38, 0, 0, 22);
|
|
5861
|
+
for (let i = 0; i < 4; i++) cylinderX(group, 0.064, 8e-3, M.steel, 0.3 + i * 0.05, 0, 0, 22);
|
|
5862
|
+
box2(group, 0.04, 0.05, 0.2, M.dark, 0.1, 0.095, 0);
|
|
5863
|
+
box2(group, 0.2, 0.012, 0.045, M.dark, 0.22, 0.158, 0);
|
|
5864
|
+
box2(group, 0.012, 0.05, 0.045, M.dark, 0.13, 0.13, 0);
|
|
5865
|
+
box2(group, 0.012, 0.05, 0.045, M.dark, 0.31, 0.13, 0);
|
|
5866
|
+
for (const side of [-1, 1]) {
|
|
5867
|
+
box2(group, 0.03, 0.03, 0.1, M.poly, 0.06, -0.01, side * 0.14);
|
|
5868
|
+
cylinderZ(group, 0.016, 0.07, M.poly, 0.06, -0.01, side * 0.2, 14);
|
|
5869
|
+
}
|
|
5870
|
+
parts.trigger = box2(group, 0.012, 0.02, 0.016, M.dark, 0.1, 0.085, 0.14, 0.3);
|
|
5871
|
+
parts.safety = box2(group, 0.014, 6e-3, 0.01, M.dark, 0.2, 0.073, -0.076, 0.4);
|
|
5817
5872
|
}
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
const
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
const
|
|
5830
|
-
parts.
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
parts
|
|
5837
|
-
|
|
5873
|
+
function buildFeed(kit, parts, group) {
|
|
5874
|
+
const { M, box: box2, cylinderX } = kit;
|
|
5875
|
+
const belt = kit.pivot(group, 0.2, -0.13, -0.16);
|
|
5876
|
+
parts.belt = belt;
|
|
5877
|
+
box2(belt, 0.16, 0.12, 0.1, M.olive, 0, 0, 0);
|
|
5878
|
+
box2(belt, 0.162, 0.012, 0.102, M.dark, 0, 0.056, 0);
|
|
5879
|
+
for (let i = 0; i < 8; i++) cylinderX(belt, 46e-4, 0.04, M.brass, -0.07 + i * 0.02, 0.075, 0.04, 10);
|
|
5880
|
+
box2(group, 0.1, 0.03, 0.1, M.metal, 0.22, -0.06, -0.1, 0, 0, 0.5);
|
|
5881
|
+
const cover = kit.pivot(group, 0.1, 0.075, 0);
|
|
5882
|
+
parts.cover = cover;
|
|
5883
|
+
box2(cover, 0.24, 0.012, 0.15, M.metal, 0.12, 6e-3, 0);
|
|
5884
|
+
const bolt = kit.pivot(group);
|
|
5885
|
+
parts.bolt = bolt;
|
|
5886
|
+
parts.stroke = 0.03;
|
|
5887
|
+
box2(bolt, 0.03, 0.012, 0.012, M.steelL, 0.28, 0.02, 0.078);
|
|
5888
|
+
}
|
|
5889
|
+
function buildM134(kit) {
|
|
5890
|
+
const group = kit.group();
|
|
5891
|
+
const parts = { family: "belt", kick: 0.9, glow: [] };
|
|
5892
|
+
buildHousing(kit, parts, group);
|
|
5893
|
+
buildBarrelCluster(kit, parts, group);
|
|
5894
|
+
buildFeed(kit, parts, group);
|
|
5895
|
+
parts.frames = {
|
|
5896
|
+
length: BARREL_END,
|
|
5897
|
+
barrelY: 0,
|
|
5898
|
+
barrelRadius: BARREL_RADIUS,
|
|
5899
|
+
receiverStart: 0.06,
|
|
5900
|
+
receiverEnd: 0.48,
|
|
5901
|
+
receiverHeight: 0.14,
|
|
5902
|
+
receiverWidth: 0.15,
|
|
5903
|
+
handguardEnd: 0.6,
|
|
5904
|
+
magazineX: 0.2,
|
|
5905
|
+
gripX: 0.06,
|
|
5906
|
+
hasRail: false,
|
|
5907
|
+
// the tripod head, where the gun balances (the tripod of the counters joins here too)
|
|
5908
|
+
underbarrel: [0.4, -0.1]
|
|
5909
|
+
};
|
|
5910
|
+
parts.muzzle = kit.mark(group, BARREL_END + 0.01, 0, 0);
|
|
5911
|
+
parts.eject = kit.mark(group, 0.3, -0.07, 0.08);
|
|
5912
|
+
return { group, parts };
|
|
5838
5913
|
}
|
|
5839
5914
|
|
|
5840
|
-
// src/models/
|
|
5841
|
-
function
|
|
5842
|
-
const {
|
|
5843
|
-
const
|
|
5844
|
-
const
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
box2(group, 0.06,
|
|
5854
|
-
|
|
5855
|
-
parts.
|
|
5856
|
-
|
|
5857
|
-
|
|
5915
|
+
// src/models/m2.ts
|
|
5916
|
+
function buildM2(kit) {
|
|
5917
|
+
const { M, box: box2, cylinderX, cylinderZ } = kit;
|
|
5918
|
+
const group = kit.group();
|
|
5919
|
+
const parts = { family: "belt", kick: 2.2, stroke: 0.08, glow: [] };
|
|
5920
|
+
box2(group, 0.52, 0.13, 0.12, M.metal, 0.36, 0, 0);
|
|
5921
|
+
for (let i = 0; i < 5; i++) cylinderZ(group, 6e-3, 0.124, M.dark, 0.15 + i * 0.1, -0.03, 0, 10);
|
|
5922
|
+
heatify(parts.glow, cylinderX(group, 0.016, 1.14, M.metal, 1.14, 0.01, 0, 16));
|
|
5923
|
+
cylinderX(group, 0.034, 0.24, M.dark, 0.74, 0.01, 0, 16);
|
|
5924
|
+
for (let i = 0; i < 6; i++) cylinderX(group, 0.036, 0.012, M.metal, 0.66 + i * 0.035, 0.01, 0, 16);
|
|
5925
|
+
cylinderX(group, 0.022, 0.05, M.dark, 1.69, 0.01, 0, 16);
|
|
5926
|
+
box2(group, 0.04, 0.09, 0.03, M.wood, 0.05, -0.02, 0.05);
|
|
5927
|
+
box2(group, 0.04, 0.09, 0.03, M.wood, 0.05, -0.02, -0.05);
|
|
5928
|
+
box2(group, 0.06, 0.02, 0.12, M.metal, 0.09, -0.02, 0);
|
|
5929
|
+
const belt = kit.pivot(group, 0.38, -0.05, -0.12);
|
|
5930
|
+
parts.belt = belt;
|
|
5931
|
+
box2(belt, 0.16, 0.12, 0.09, M.olive, 0, 0, 0);
|
|
5932
|
+
for (let i = 0; i < 8; i++) cylinderX(belt, 6e-3, 0.05, M.brass, -0.08 + i * 0.02, 0.08, 0.04, 8);
|
|
5933
|
+
const cover = kit.pivot(group, 0.12, 0.065, 0);
|
|
5934
|
+
parts.cover = cover;
|
|
5935
|
+
box2(cover, 0.4, 0.012, 0.12, M.metal, 0.2, 6e-3, 0);
|
|
5936
|
+
box2(group, 0.04, 0.05, 0.04, M.dark, 0.66, 0.1, 0);
|
|
5937
|
+
const bolt = kit.pivot(group);
|
|
5938
|
+
parts.bolt = bolt;
|
|
5939
|
+
box2(bolt, 0.03, 0.03, 0.02, M.metal, 0.5, 0, 0.07);
|
|
5940
|
+
const tripod = kit.group();
|
|
5941
|
+
tripod.position.set(0.42, -0.1, 0);
|
|
5942
|
+
group.add(tripod);
|
|
5943
|
+
box2(tripod, 0.03, 0.06, 0.03, M.metal, 0, 0, 0);
|
|
5944
|
+
box2(tripod, 0.012, 0.62, 0.012, M.metal, -0.2, -0.25, 0, 0.75);
|
|
5945
|
+
box2(tripod, 0.012, 0.62, 0.012, M.metal, 0.22, -0.25, 0.16, -0.75, 0, 0.3);
|
|
5946
|
+
box2(tripod, 0.012, 0.62, 0.012, M.metal, 0.22, -0.25, -0.16, -0.75, 0, -0.3);
|
|
5947
|
+
parts.muzzle = kit.mark(group, 1.72, 0.01, 0);
|
|
5948
|
+
parts.eject = kit.mark(group, 0.3, -0.07, 0);
|
|
5949
|
+
return { group, parts };
|
|
5858
5950
|
}
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
const
|
|
5864
|
-
const
|
|
5865
|
-
|
|
5951
|
+
|
|
5952
|
+
// src/models/p90.ts
|
|
5953
|
+
function buildP90(kit) {
|
|
5954
|
+
const { M, box: box2, cylinderX } = kit;
|
|
5955
|
+
const group = kit.group();
|
|
5956
|
+
const parts = { family: "p90", stroke: 0.04, kick: 0.6, glow: [] };
|
|
5957
|
+
box2(group, 0.4, 0.07, 0.055, M.poly, 0.2, 0, 0);
|
|
5958
|
+
box2(group, 0.12, 0.075, 0.05, M.poly, 0.2, -0.07, 0);
|
|
5959
|
+
box2(group, 0.08, 0.04, 0.03, M.hole, 0.21, -0.06, 0);
|
|
5960
|
+
box2(group, 0.06, 0.13, 0.056, M.poly, 0.03, -0.03, 0);
|
|
5961
|
+
box2(group, 0.05, 0.03, 0.056, M.poly, 0.33, -0.04, 0);
|
|
5962
|
+
heatify(parts.glow, cylinderX(group, 8e-3, 0.09, M.metal, 0.43, 0, 0, 16));
|
|
5963
|
+
const magazine = kit.pivot(group, 0.22, 0.047, 0);
|
|
5866
5964
|
parts.mag = magazine;
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
const
|
|
5887
|
-
|
|
5888
|
-
let px = 0;
|
|
5889
|
-
let py = 0;
|
|
5890
|
-
let angle = 0.08;
|
|
5891
|
-
for (let i = 0; i < 3; i++) {
|
|
5892
|
-
angle = 0.08 + curve * i;
|
|
5893
|
-
const cx = px + Math.sin(angle) * segment / 2;
|
|
5894
|
-
const cy = py - Math.cos(angle) * segment / 2;
|
|
5895
|
-
box2(magazine, 0.05, segment + 4e-3, 0.024, material, cx, cy, 0, angle);
|
|
5896
|
-
box2(magazine, 0.04, 3e-3, 0.026, M.metal, cx, cy, 0, angle);
|
|
5897
|
-
px += Math.sin(angle) * segment;
|
|
5898
|
-
py -= Math.cos(angle) * segment;
|
|
5899
|
-
}
|
|
5900
|
-
box2(magazine, 0.056, 7e-3, 0.028, material, px, py - 2e-3, 0, angle);
|
|
5901
|
-
parts.magDrop = length + 0.03;
|
|
5902
|
-
} else if (o.mag === "drum") {
|
|
5903
|
-
buildDrum(kit, magazine);
|
|
5904
|
-
parts.magDrop = 0.2;
|
|
5905
|
-
} else if (o.mag === "internal") {
|
|
5906
|
-
box2(group, 0.08, 0.025, 0.03, context.isTraditional ? context.furniture : M.metal, mx, -hR / 2 - 0.012, 0);
|
|
5907
|
-
parts.mag = null;
|
|
5908
|
-
} else parts.mag = null;
|
|
5909
|
-
if (o.mag === "belt") {
|
|
5910
|
-
const belt = kit.pivot(group, mx + 0.02, -hR / 2 - 0.05, -0.045);
|
|
5911
|
-
parts.belt = belt;
|
|
5912
|
-
buildBeltBox(kit, belt);
|
|
5913
|
-
const cover = kit.pivot(group, x0 + 0.01, hR / 2, 0);
|
|
5914
|
-
parts.cover = cover;
|
|
5915
|
-
box2(cover, RL - 0.03, 0.014, wR * 1.05, M.metal, (RL - 0.03) / 2, 7e-3, 0);
|
|
5916
|
-
box2(cover, 0.02, 0.012, wR * 0.6, M.dark, RL - 0.04, 0.016, 0);
|
|
5965
|
+
parts.magDir = 1;
|
|
5966
|
+
parts.magDrop = 0.08;
|
|
5967
|
+
box2(magazine, 0.3, 0.022, 0.05, M.glass, 0, 0, 0);
|
|
5968
|
+
for (let i = 0; i < 12; i++) cylinderX(magazine, 28e-4, 0.02, M.brass, -0.12 + i * 0.022, 0, 0, 6);
|
|
5969
|
+
scope(kit, group, 1, 0.24, 0.06, 0);
|
|
5970
|
+
const bolt = kit.pivot(group);
|
|
5971
|
+
parts.bolt = bolt;
|
|
5972
|
+
box2(bolt, 0.02, 0.012, 0.012, M.dark, 0.3, 0.02, 0.03);
|
|
5973
|
+
parts.trigger = box2(group, 4e-3, 0.016, 4e-3, M.dark, 0.24, -0.045, 0);
|
|
5974
|
+
parts.muzzle = kit.mark(group, 0.48, 0, 0);
|
|
5975
|
+
parts.eject = kit.mark(group, 0.2, -0.07, 0);
|
|
5976
|
+
return { group, parts };
|
|
5977
|
+
}
|
|
5978
|
+
|
|
5979
|
+
// src/models/part-registry.ts
|
|
5980
|
+
var SINGLE_PARTS = ["slide", "bolt", "boltHandle", "mag", "trigger", "hammer", "lever", "pump", "belt", "cover", "crane", "cylinder", "barrels", "safety", "muzzle", "eject", "loadPort", "topLoad", "rear", "round", "gauge", "stock", "ugl"];
|
|
5981
|
+
function partRegistry(parts) {
|
|
5982
|
+
const registry = /* @__PURE__ */ new Map();
|
|
5983
|
+
for (const key of SINGLE_PARTS) {
|
|
5984
|
+
const part = parts[key];
|
|
5985
|
+
if (part) registry.set(key, part);
|
|
5917
5986
|
}
|
|
5918
|
-
|
|
5987
|
+
parts.breech?.forEach((part, index) => registry.set(`breech_${index}`, part));
|
|
5988
|
+
parts.chambers?.forEach((part, index) => registry.set(`chamber_${index}`, part));
|
|
5989
|
+
return registry;
|
|
5919
5990
|
}
|
|
5920
5991
|
|
|
5921
|
-
// src/models/
|
|
5922
|
-
|
|
5923
|
-
|
|
5992
|
+
// src/models/pistol-slide.ts
|
|
5993
|
+
var PI8 = Math.PI;
|
|
5994
|
+
function buildSlide(kit, slide2, parts, options, style, size, metal2) {
|
|
5924
5995
|
const { M, box: box2, cylinderX } = kit;
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
box2(
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
box2(
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
box2(
|
|
5956
|
-
box2(
|
|
5957
|
-
|
|
5996
|
+
const { length: L, width: w } = size;
|
|
5997
|
+
const slideHeight = style.inset ? size.height * 0.92 : size.height;
|
|
5998
|
+
const slideWidth = style.inset ? w * 0.86 : w;
|
|
5999
|
+
kit.roundness = style.rf;
|
|
6000
|
+
if (style.tri) box2(slide2, L * 0.42, slideHeight, slideWidth, metal2, L * 0.21, 0, 0);
|
|
6001
|
+
else if (style.open) {
|
|
6002
|
+
box2(slide2, L * 0.45, slideHeight, slideWidth, metal2, L * 0.225, 0, 0);
|
|
6003
|
+
box2(slide2, L * 0.55, slideHeight * 0.62, slideWidth, metal2, L * 0.72, -slideHeight * 0.19, 0);
|
|
6004
|
+
} else box2(slide2, L, slideHeight, slideWidth, metal2, L / 2, 0, 0);
|
|
6005
|
+
if (style.slope) box2(slide2, L * 0.25, slideHeight * 0.5, slideWidth * 0.98, metal2, L * 0.86, slideHeight * 0.35, 0, -0.22);
|
|
6006
|
+
kit.roundness = null;
|
|
6007
|
+
for (let i = 0; i < (style.flush ? 9 : 7); i++) box2(slide2, 22e-4, slideHeight * 0.72, slideWidth + 14e-4, M.dark, 7e-3 + i * 52e-4, -2e-3, 0, 0);
|
|
6008
|
+
if (style.frontSer) for (let i = 0; i < 5; i++) box2(slide2, 22e-4, slideHeight * 0.6, slideWidth + 14e-4, M.dark, L * 0.76 + i * 52e-4, -3e-3, 0);
|
|
6009
|
+
if (style.port) {
|
|
6010
|
+
box2(slide2, L * style.port, 4e-3, slideWidth * 0.55, M.hole, L * 0.6, slideHeight / 2 - 1e-3, slideWidth * 0.12);
|
|
6011
|
+
box2(slide2, L * style.port * 0.85, 3e-3, slideWidth * 0.4, M.steelL, L * 0.6, slideHeight / 2 - 4e-4, slideWidth * 0.1);
|
|
6012
|
+
box2(slide2, 0.012, 4e-3, 2e-3, M.dark, L * 0.55, slideHeight * 0.15, slideWidth / 2 + 8e-4);
|
|
6013
|
+
}
|
|
6014
|
+
if (style.open) {
|
|
6015
|
+
heatify(parts.glow, cylinderX(slide2, 62e-4, L * 0.56, M.steelL, L * 0.7, slideHeight * 0.12, 0, 18));
|
|
6016
|
+
box2(slide2, 0.03, 4e-3, slideWidth * 0.6, M.hole, L * 0.48, slideHeight / 2 - 1e-3, 0);
|
|
6017
|
+
}
|
|
6018
|
+
if (style.tri) {
|
|
6019
|
+
const tube = new kit.THREE.Mesh(new kit.THREE.CylinderGeometry(0.016, 0.016, L * 0.6, 3), metal2);
|
|
6020
|
+
tube.castShadow = tube.receiveShadow = true;
|
|
6021
|
+
tube.rotation.set(0, 0, -PI8 / 2);
|
|
6022
|
+
tube.rotateY(PI8 / 6);
|
|
6023
|
+
tube.position.set(L * 0.7, slideHeight * 0.08, 0);
|
|
6024
|
+
slide2.add(tube);
|
|
6025
|
+
heatify(parts.glow, tube);
|
|
6026
|
+
box2(slide2, L * 0.6, 6e-3, 0.012, metal2, L * 0.7, slideHeight * 0.38, 0);
|
|
6027
|
+
for (let i = 0; i < 6; i++) box2(slide2, 8e-3, 3e-3, 0.013, M.hole, L * 0.45 + i * 0.04, slideHeight * 0.41, 0);
|
|
6028
|
+
}
|
|
6029
|
+
if (style.bushing) {
|
|
6030
|
+
heatify(parts.glow, cylinderX(slide2, 78e-4, 6e-3, M.steelL, L + 2e-3, 1e-3, 0, 18));
|
|
6031
|
+
cylinderX(slide2, 45e-4, 4e-3, M.steel, L + 2e-3, -0.012, 0, 12);
|
|
6032
|
+
}
|
|
6033
|
+
const muzzleY = style.tri ? slideHeight * 0.08 : 2e-3;
|
|
6034
|
+
heatify(parts.glow, cylinderX(slide2, style.tri ? 72e-4 : 62e-4, 4e-3, M.dark, L + 15e-4, muzzleY, 0, 18));
|
|
6035
|
+
cylinderX(slide2, 34e-4, 5e-3, M.hole, L + 25e-4, muzzleY, 0, 12);
|
|
6036
|
+
const top = slideHeight / 2;
|
|
6037
|
+
if (style.sight === "u" || style.sight === "3dot") {
|
|
6038
|
+
box2(slide2, 4e-3, 7e-3, 4e-3, M.dark, L - 8e-3, top + 35e-4, 0);
|
|
6039
|
+
box2(slide2, 22e-4, 22e-4, 46e-4, M.white, L - 8e-3, top + 58e-4, 0);
|
|
6040
|
+
box2(slide2, 8e-3, 7e-3, 0.016, M.dark, 9e-3, top + 35e-4, 0);
|
|
6041
|
+
if (style.sight === "u") box2(slide2, 4e-3, 2e-3, 0.0122, M.white, 9e-3, top + 6e-3, 0);
|
|
6042
|
+
else box2(slide2, 22e-4, 22e-4, 0.0166, M.white, 9e-3, top + 58e-4, 0);
|
|
6043
|
+
} else {
|
|
6044
|
+
box2(slide2, 6e-3, 4e-3, 3e-3, M.dark, L - 6e-3, top + 2e-3, 0);
|
|
6045
|
+
box2(slide2, 6e-3, 4e-3, 0.012, M.dark, 8e-3, top + 2e-3, 0);
|
|
6046
|
+
}
|
|
6047
|
+
if (style.decock === "slide") {
|
|
6048
|
+
box2(slide2, 0.012, 8e-3, 4e-3, M.dark, 0.02, slideHeight * 0.15, slideWidth / 2 + 2e-3, 0.3);
|
|
6049
|
+
box2(slide2, 0.012, 8e-3, 4e-3, M.dark, 0.02, slideHeight * 0.15, -slideWidth / 2 - 2e-3, 0.3);
|
|
6050
|
+
}
|
|
6051
|
+
if (style.safety === "slide") parts.safety = box2(slide2, 0.012, 8e-3, 4e-3, M.dark, 0.018, slideHeight * 0.1, -slideWidth / 2 - 2e-3, 0.2);
|
|
6052
|
+
if (options.sel) {
|
|
6053
|
+
const selector = box2(slide2, 0.01, 8e-3, 3e-3, M.dark, 0.014, -slideHeight * 0.2, slideWidth / 2 + 14e-4);
|
|
6054
|
+
parts.safety ?? (parts.safety = selector);
|
|
5958
6055
|
}
|
|
5959
6056
|
}
|
|
5960
6057
|
|
|
5961
|
-
// src/models/
|
|
5962
|
-
var
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
box2(group,
|
|
5984
|
-
box2(group, 0.
|
|
6058
|
+
// src/models/pistol-style.ts
|
|
6059
|
+
var STYLES = {
|
|
6060
|
+
glock: { rf: 0.07, ga: -0.36, grip: "finger", guard: "square", rail: 1, sight: "u", port: 0.2, slideM: "metal", frame: "poly" },
|
|
6061
|
+
taurus: { rf: 0.16, ga: -0.3, grip: "panel", guard: "square", rail: 1, sight: "3dot", port: 0.18, frontSer: 1, frame: "poly" },
|
|
6062
|
+
g2c: { rf: 0.2, ga: -0.3, grip: "panel", guard: "round", rail: 0, sight: "3dot", port: 0.17, frame: "poly", safety: "thumb" },
|
|
6063
|
+
beretta: { rf: 0.28, ga: -0.27, grip: "wood", guard: "round", hammer: "spur", sight: "3dot", open: 1, decock: "slide", port: 0, frame: "metal" },
|
|
6064
|
+
pt100: { rf: 0.25, ga: -0.27, grip: "rubber", guard: "round", hammer: "spur", sight: "3dot", port: 0.17, decock: "frame", frame: "metal" },
|
|
6065
|
+
sig: { rf: 0.14, ga: -0.3, grip: "rubber", guard: "hook", hammer: "spur", sight: "3dot", port: 0.19, decock: "frame", rail: 1, tall: 1.12, frame: "metal" },
|
|
6066
|
+
cz: { rf: 0.32, ga: -0.3, grip: "rubber", guard: "round", hammer: "spur", sight: "3dot", port: 0.15, inset: 1, safety: "thumb", frame: "metal" },
|
|
6067
|
+
m1911: { rf: 0.24, ga: -0.2, grip: "wood", guard: "round", hammer: "ring", sight: "small", port: 0.12, bushing: 1, beaver: 1, safety: "thumb", slideStop: 1, frame: "metal" },
|
|
6068
|
+
makarov: { rf: 0.48, ga: -0.24, grip: "star", guard: "round", hammer: "ring", sight: "small", port: 0.14, flush: 1, safety: "slide", lanyard: 1, frame: "metal" },
|
|
6069
|
+
fiveseven: { rf: 0.2, ga: -0.4, grip: "chunky", guard: "square", rail: 1, sight: "3dot", port: 0.18, slope: 1, frame: "poly" },
|
|
6070
|
+
deagle: { rf: 0.08, ga: -0.28, grip: "rubber", guard: "round", hammer: "big", sight: "small", port: 0.16, tri: 1, safety: "slide", frame: "metal" }
|
|
6071
|
+
};
|
|
6072
|
+
|
|
6073
|
+
// src/models/pistol.ts
|
|
6074
|
+
var PI9 = Math.PI;
|
|
6075
|
+
function buildFrame(kit, group, parts, options, style, size, materials) {
|
|
6076
|
+
const { M, box: box2, cylinderZ, sphere } = kit;
|
|
6077
|
+
const { length: L, height: h, width: w } = size;
|
|
6078
|
+
const fm = materials.frame;
|
|
6079
|
+
if (style.inset) {
|
|
6080
|
+
box2(group, L * 0.9, h * 0.35, w * 0.12, fm, L * 0.47, -h * 0.32, w * 0.47);
|
|
6081
|
+
box2(group, L * 0.9, h * 0.35, w * 0.12, fm, L * 0.47, -h * 0.32, -w * 0.47);
|
|
5985
6082
|
}
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
6083
|
+
const frameLength = style.tri ? L * 0.66 : L * 0.8;
|
|
6084
|
+
kit.roundness = style.rf;
|
|
6085
|
+
box2(group, frameLength, 0.016, w * 0.92, fm, frameLength / 2 + L * 0.06, -h / 2 - 8e-3, 0);
|
|
6086
|
+
kit.roundness = null;
|
|
6087
|
+
if (style.rail) for (let i = 0; i < (style.slope ? 5 : 3); i++) box2(group, 4e-3, 3e-3, w * 0.96, M.dark, L * 0.62 + i * 9e-3, -h / 2 - 0.017, 0);
|
|
6088
|
+
const isGlock = options.st === "glock" || !options.st;
|
|
6089
|
+
if (isGlock) {
|
|
6090
|
+
box2(group, 8e-3, 4e-3, 3e-3, M.dark, L * 0.5, -h / 2 - 3e-3, -w / 2 - 12e-4);
|
|
6091
|
+
box2(group, 8e-3, 4e-3, 3e-3, M.dark, L * 0.5, -h / 2 - 3e-3, w / 2 + 12e-4);
|
|
6092
|
+
}
|
|
6093
|
+
if (style.slideStop) {
|
|
6094
|
+
box2(group, 0.03, 6e-3, 3e-3, M.dark, L * 0.42, -h / 2 - 2e-3, -w / 2 - 14e-4);
|
|
6095
|
+
sphere(group, 28e-4, M.dark, L * 0.55, -h / 2 - 3e-3, w / 2 + 1e-3, 1);
|
|
6096
|
+
} else box2(group, 0.012, 4e-3, 3e-3, M.dark, L * 0.45, -h / 2 - 3e-3, -w / 2 - 12e-4);
|
|
6097
|
+
if (style.decock === "frame") box2(group, 0.01, 0.012, 3e-3, M.dark, L * 0.38, -h / 2 - 0.012, -w / 2 - 14e-4, 0.6);
|
|
6098
|
+
if (style.safety === "thumb") parts.safety = box2(group, 0.014, 6e-3, 4e-3, M.dark, 0.02, -h / 2 - 2e-3, -w / 2 - 16e-4);
|
|
6099
|
+
const gripLength = options.gl ?? 0.105;
|
|
6100
|
+
const gx = 0.034 + (L - 0.2) * 0.15;
|
|
6101
|
+
const gy = -h / 2 - gripLength / 2 + 6e-3;
|
|
6102
|
+
const grip = kit.pivot(group, gx, gy, 0);
|
|
6103
|
+
grip.rotation.z = style.ga;
|
|
6104
|
+
parts.grip = grip;
|
|
6105
|
+
const gripWidth = style.grip === "chunky" ? w * 1.18 : w * 1.06;
|
|
6106
|
+
const gripDepth = style.grip === "chunky" ? 0.036 : 0.032;
|
|
6107
|
+
kit.roundness = 0.3;
|
|
6108
|
+
if (style.grip === "wood" || style.grip === "star") {
|
|
6109
|
+
box2(grip, gripDepth * 0.86, gripLength, w * 0.9, fm, 0, 0, 0);
|
|
6110
|
+
box2(grip, gripDepth * 0.8, gripLength * 0.86, 4e-3, materials.grip, 1e-3, -2e-3, w * 0.47);
|
|
6111
|
+
box2(grip, gripDepth * 0.8, gripLength * 0.86, 4e-3, materials.grip, 1e-3, -2e-3, -w * 0.47);
|
|
6112
|
+
if (style.grip === "wood") {
|
|
6113
|
+
for (let i = 0; i < 6; i++) for (let j = 0; j < 2; j++) box2(grip, 3e-3, 3e-3, 12e-4, M.woodL, -6e-3 + j * 0.012, -gripLength * 0.3 + i * 0.012, w * 0.495, 0, 0, 0);
|
|
6114
|
+
cylinderZ(grip, 35e-4, 15e-4, M.brass, 0, gripLength * 0.25, w * 0.5, 10);
|
|
6115
|
+
cylinderZ(grip, 35e-4, 15e-4, M.brass, 0, -gripLength * 0.3, w * 0.5, 10);
|
|
6116
|
+
} else cylinderZ(grip, 8e-3, 15e-4, M.dark, 0, gripLength * 0.1, w * 0.5, 5);
|
|
6117
|
+
} else box2(grip, gripDepth, gripLength, gripWidth, materials.grip, 0, 0, 0);
|
|
6118
|
+
kit.roundness = null;
|
|
6119
|
+
if (style.grip === "finger") {
|
|
6120
|
+
for (let i = 0; i < 3; i++) box2(grip, 6e-3, 0.012, gripWidth * 0.98, materials.grip, gripDepth / 2 + 2e-3, gripLength * 0.18 - i * 0.022, 0);
|
|
6121
|
+
for (let i = 0; i < 5; i++) for (let j = 0; j < 3; j++) box2(grip, 3e-3, 3e-3, 12e-4, M.dark, -8e-3 + j * 8e-3, -gripLength * 0.25 + i * 0.012, gripWidth / 2 + 4e-4);
|
|
5990
6122
|
}
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
sphere(bolt, 65e-4, M.metal, ejectX + 0.04, ejectY + 4e-3, wR / 2 + 0.028, 1);
|
|
6123
|
+
if (style.grip === "panel" || style.grip === "rubber" || style.grip === "chunky") for (let i = 0; i < 6; i++) box2(grip, gripDepth * 0.75, 25e-4, gripWidth + 1e-3, M.dark, 2e-3, -gripLength / 2 + 0.018 + i * 0.013, 0);
|
|
6124
|
+
if (style.grip === "chunky") box2(grip, 8e-3, gripLength * 0.8, gripWidth * 0.9, materials.grip, gripDepth / 2 + 2e-3, -4e-3, 0);
|
|
6125
|
+
if (style.beaver) {
|
|
6126
|
+
box2(group, 0.026, 8e-3, w * 0.9, fm, -4e-3, -h / 2 - 4e-3, 0, 0.25);
|
|
6127
|
+
box2(grip, 6e-3, gripLength * 0.55, w * 0.9, fm, -gripDepth * 0.5 - 2e-3, gripLength * 0.18, 0);
|
|
6128
|
+
} else box2(group, 0.02, 9e-3, w * 0.9, fm, 4e-3, -h / 2 - 6e-3, 0);
|
|
6129
|
+
if (style.lanyard) {
|
|
6130
|
+
const ring = kit.torus(grip, new kit.THREE.TorusGeometry(5e-3, 13e-4, 6, 12), M.dark, -0.012, -gripLength / 2 + 4e-3, 0);
|
|
6131
|
+
ring.position.set(-0.012, -gripLength / 2 + 4e-3, 0);
|
|
6001
6132
|
}
|
|
6002
|
-
|
|
6003
|
-
|
|
6133
|
+
const magazine = kit.pivot(grip);
|
|
6134
|
+
parts.mag = magazine;
|
|
6135
|
+
parts.magDrop = gripLength * 1.15;
|
|
6136
|
+
box2(magazine, 0.022, gripLength * 0.94, w * 0.72, M.dark, 3e-3, -4e-3, 0);
|
|
6137
|
+
if (style.grip === "chunky") box2(magazine, 0.04, 0.01, gripWidth * 1.02, M.poly, 3e-3, -gripLength / 2 - 4e-3, 0);
|
|
6138
|
+
else if (style.flush || style.grip === "wood") box2(magazine, 0.028, 4e-3, w * 0.9, M.steel, 3e-3, -gripLength / 2 - 1e-3, 0);
|
|
6139
|
+
else box2(magazine, 0.031, 6e-3, gripWidth * 1.02, M.dark, 3e-3, -gripLength / 2 - 2e-3, 0);
|
|
6140
|
+
return { gx, ty: -h / 2 };
|
|
6004
6141
|
}
|
|
6005
|
-
function
|
|
6006
|
-
const {
|
|
6007
|
-
const {
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6142
|
+
function buildPistol(kit, options) {
|
|
6143
|
+
const { M, box: box2 } = kit;
|
|
6144
|
+
const style = { ...STYLES[options.st ?? "glock"] };
|
|
6145
|
+
const group = kit.group();
|
|
6146
|
+
const parts = { family: "pistol", kick: options.deagle ? 1.8 : 0.6, glow: [] };
|
|
6147
|
+
const size = { length: (options.L ?? 0) / 1e3 * 0.97, height: (options.h ?? 0.031) * (style.tall ?? 1), width: options.deagle ? 0.032 : style.flush ? 0.024 : 0.025 };
|
|
6148
|
+
const { length: L, height: h, width: w } = size;
|
|
6149
|
+
const slideMetal = options.steel ? M.steel : options.stain ? M.steelL : M.metal;
|
|
6150
|
+
const frameMetal = style.frame === "poly" ? M.poly : slideMetal;
|
|
6151
|
+
const gripMaterial = style.grip === "wood" ? M.wood : style.grip === "star" ? M.bake : style.grip === "rubber" ? M.rubber : M.poly;
|
|
6152
|
+
const slide2 = kit.pivot(group);
|
|
6153
|
+
parts.slide = slide2;
|
|
6154
|
+
parts.stroke = L * 0.15;
|
|
6155
|
+
buildSlide(kit, slide2, parts, options, style, size, slideMetal);
|
|
6156
|
+
const { gx, ty } = buildFrame(kit, group, parts, options, style, size, { frame: frameMetal, grip: gripMaterial });
|
|
6157
|
+
if (style.guard === "square") {
|
|
6158
|
+
box2(group, 0.046, 4e-3, 9e-3, frameMetal, gx + 0.05, ty - 0.034, 0);
|
|
6159
|
+
box2(group, 4e-3, 0.03, 9e-3, frameMetal, gx + 0.074, ty - 0.02, 0);
|
|
6160
|
+
box2(group, 6e-3, 4e-3, 9e-3, frameMetal, gx + 0.075, ty - 0.034, 0);
|
|
6161
|
+
} else if (style.guard === "hook") {
|
|
6162
|
+
box2(group, 0.046, 4e-3, 9e-3, frameMetal, gx + 0.05, ty - 0.034, 0);
|
|
6163
|
+
box2(group, 4e-3, 0.03, 9e-3, frameMetal, gx + 0.073, ty - 0.02, 0, 0.2);
|
|
6164
|
+
box2(group, 8e-3, 6e-3, 9e-3, frameMetal, gx + 0.074, ty - 0.037, 0, 0.4);
|
|
6165
|
+
} else {
|
|
6166
|
+
const guard = kit.torus(group, new kit.THREE.TorusGeometry(0.019, 22e-4, 6, 16, PI9), frameMetal, gx + 0.05, ty - 0.014, 0);
|
|
6167
|
+
guard.rotation.z = PI9;
|
|
6168
|
+
guard.scale.set(1.2, 1, 1);
|
|
6012
6169
|
}
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6170
|
+
const isGlock = options.st === "glock" || !options.st;
|
|
6171
|
+
parts.trigger = box2(group, 4e-3, 0.014, 4e-3, isGlock ? M.dark : M.steel, gx + 0.042, ty - 0.022, 0, 0.2);
|
|
6172
|
+
if (isGlock) box2(parts.trigger, 15e-4, 8e-3, 45e-4, M.metal, 0, -1e-3, 0);
|
|
6173
|
+
if (style.hammer) {
|
|
6174
|
+
const hammer = kit.pivot(group, 3e-3, h / 2 - 8e-3, 0);
|
|
6175
|
+
parts.hammer = hammer;
|
|
6176
|
+
if (style.hammer === "ring") {
|
|
6177
|
+
box2(hammer, 6e-3, 0.012, 6e-3, M.dark, -2e-3, 4e-3, 0, 0.3);
|
|
6178
|
+
kit.torus(hammer, new kit.THREE.TorusGeometry(45e-4, 16e-4, 6, 12), M.dark, -4e-3, 0.012, 0);
|
|
6179
|
+
} else if (style.hammer === "big") box2(hammer, 0.014, 0.02, 9e-3, M.dark, -4e-3, 7e-3, 0, 0.35);
|
|
6180
|
+
else {
|
|
6181
|
+
box2(hammer, 8e-3, 0.016, 7e-3, M.dark, -2e-3, 6e-3, 0, 0.3);
|
|
6182
|
+
box2(hammer, 8e-3, 4e-3, 8e-3, M.dark, -6e-3, 0.013, 0, 0.3);
|
|
6183
|
+
}
|
|
6025
6184
|
}
|
|
6026
|
-
|
|
6185
|
+
parts.muzzle = kit.mark(group, L + 6e-3, style.tri ? h * 0.08 : 2e-3, 0);
|
|
6186
|
+
parts.eject = kit.mark(group, L * 0.6, h / 2, w * 0.25);
|
|
6187
|
+
return { group, parts };
|
|
6027
6188
|
}
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
return o.mag === "internal" ? "semiint" : "rifle";
|
|
6035
|
-
};
|
|
6036
|
-
function buildRifle(kit, options) {
|
|
6037
|
-
const { M } = kit;
|
|
6189
|
+
|
|
6190
|
+
// src/models/revolver.ts
|
|
6191
|
+
var PI10 = Math.PI;
|
|
6192
|
+
var DEFAULT_CHAMBERS = 6;
|
|
6193
|
+
function buildRevolver(kit, options) {
|
|
6194
|
+
const { M, box: box2, cylinderX } = kit;
|
|
6038
6195
|
const group = kit.group();
|
|
6039
|
-
const parts = { family: "
|
|
6040
|
-
const
|
|
6041
|
-
const
|
|
6042
|
-
const
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
const
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
const
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
receiverEnd,
|
|
6080
|
-
receiverHeight,
|
|
6081
|
-
receiverWidth: context.receiverWidth,
|
|
6082
|
-
handguardEnd: receiverEnd + (length - receiverEnd) * (hasHandguard ? options.hgFrac || 0.5 : 0.4),
|
|
6083
|
-
magazineX,
|
|
6084
|
-
gripX,
|
|
6085
|
-
hasRail: Boolean(options.rail)
|
|
6086
|
-
};
|
|
6087
|
-
const { barrelY: by, receiverWidth: wR } = context;
|
|
6088
|
-
const ejectX = receiverEnd - (options.ejectBack || 0.07);
|
|
6089
|
-
const ejectY = options.ar ? receiverHeight * 0.2 : by;
|
|
6090
|
-
parts.muzzle = kit.mark(group, length + 0.01, by, 0);
|
|
6091
|
-
parts.eject = kit.mark(group, ejectX, ejectY, wR / 2 + 6e-3);
|
|
6092
|
-
parts.loadPort = kit.mark(group, receiverEnd - 0.05, -receiverHeight / 2 - 4e-3, 0);
|
|
6093
|
-
parts.topLoad = kit.mark(group, ejectX, receiverHeight / 2 + 4e-3, 0);
|
|
6094
|
-
parts.family = familyOf(options);
|
|
6196
|
+
const parts = { family: "revolver", kick: options.cal === ".44 Magnum" ? 1.5 : 0.9, glow: [] };
|
|
6197
|
+
const barrel = (options.B ?? 0) / 1e3;
|
|
6198
|
+
const chambers = options.chambers ?? DEFAULT_CHAMBERS;
|
|
6199
|
+
const metal2 = options.steel ? M.steel : M.metal;
|
|
6200
|
+
box2(group, 0.08, 0.044, 0.024, metal2, 0.07, 0, 0);
|
|
6201
|
+
box2(group, 0.036, 0.012, 0.022, metal2, 0.096, 0.022, 0);
|
|
6202
|
+
box2(group, 0.024, 0.012, 4e-3, M.dark, 0.055, 6e-3, -0.013);
|
|
6203
|
+
const crane = kit.pivot(group, 0.077, -0.024, 0);
|
|
6204
|
+
parts.crane = crane;
|
|
6205
|
+
const cylinder = kit.pivot(crane, 0, 0.022, 0);
|
|
6206
|
+
parts.cylinder = cylinder;
|
|
6207
|
+
cylinderX(cylinder, 0.0215, 0.042, metal2, 0, 0, 0, 24);
|
|
6208
|
+
for (let i = 0; i < chambers; i++) {
|
|
6209
|
+
const angle = i * 2 * PI10 / chambers;
|
|
6210
|
+
box2(cylinder, 0.026, 5e-3, 5e-3, M.dark, 0, Math.cos(angle) * 0.0205, Math.sin(angle) * 0.0205, 0, 0, angle);
|
|
6211
|
+
}
|
|
6212
|
+
parts.chambers = [];
|
|
6213
|
+
for (let i = 0; i < chambers; i++) {
|
|
6214
|
+
const angle = i * 2 * PI10 / chambers + PI10 / chambers;
|
|
6215
|
+
parts.chambers.push(kit.mark(cylinder, -0.022, Math.cos(angle) * 0.013, Math.sin(angle) * 0.013));
|
|
6216
|
+
cylinderX(cylinder, 46e-4, 2e-3, M.brass, -0.0215, Math.cos(angle) * 0.013, Math.sin(angle) * 0.013, 12);
|
|
6217
|
+
}
|
|
6218
|
+
heatify(parts.glow, cylinderX(group, 88e-4, barrel, metal2, 0.112 + barrel / 2, 9e-3, 0, 18));
|
|
6219
|
+
box2(group, barrel * 0.92, 0.015, 0.013, metal2, 0.112 + barrel * 0.46, -5e-3, 0);
|
|
6220
|
+
cylinderX(group, 4e-3, 5e-3, M.hole, 0.112 + barrel + 15e-4, 9e-3, 0, 12);
|
|
6221
|
+
box2(group, 0.012, 9e-3, 4e-3, M.dark, 0.112 + barrel - 8e-3, 0.021, 0, -0.3);
|
|
6222
|
+
box2(group, 0.012, 6e-3, 0.012, M.dark, 0.105, 0.031, 0);
|
|
6223
|
+
const hammer = kit.pivot(group, 0.036, 0.018, 0);
|
|
6224
|
+
box2(hammer, 0.01, 0.02, 8e-3, M.dark, -4e-3, 8e-3, 0, 0.45);
|
|
6225
|
+
parts.hammer = hammer;
|
|
6226
|
+
const grip = kit.pivot(group, 0.024, -0.062, 0);
|
|
6227
|
+
grip.rotation.z = -0.38;
|
|
6228
|
+
parts.grip = grip;
|
|
6229
|
+
box2(grip, 0.034, 0.1, 0.031, options.wood ? M.wood : M.rubber, 0, 0, 0);
|
|
6230
|
+
if (!options.wood) for (let i = 0; i < 4; i++) box2(grip, 6e-3, 0.07, 0.033, M.dark, -0.012 + i * 8e-3, 0, 0);
|
|
6231
|
+
box2(group, 0.038, 4e-3, 8e-3, metal2, 0.062, -0.036, 0);
|
|
6232
|
+
box2(group, 4e-3, 0.022, 8e-3, metal2, 0.08, -0.026, 0, 0.2);
|
|
6233
|
+
parts.trigger = box2(group, 4e-3, 0.015, 4e-3, M.dark, 0.06, -0.027, 0, 0.2);
|
|
6234
|
+
parts.muzzle = kit.mark(group, 0.112 + barrel + 6e-3, 9e-3, 0);
|
|
6235
|
+
parts.eject = kit.mark(group, 0.077, 0, 0);
|
|
6095
6236
|
return { group, parts };
|
|
6096
6237
|
}
|
|
6097
6238
|
|
|
@@ -6107,13 +6248,14 @@ var ARCHETYPE_MODELS = (() => {
|
|
|
6107
6248
|
}
|
|
6108
6249
|
return chosen;
|
|
6109
6250
|
})();
|
|
6110
|
-
var
|
|
6251
|
+
var BUILDERS2 = {
|
|
6111
6252
|
pistol: buildPistol,
|
|
6112
6253
|
revolver: buildRevolver,
|
|
6113
6254
|
rifle: buildRifle,
|
|
6114
6255
|
bullpup: buildBullpup,
|
|
6115
6256
|
p90: (kit) => buildP90(kit),
|
|
6116
6257
|
break: buildBreakAction,
|
|
6258
|
+
breakLauncher: buildBreakLauncher,
|
|
6117
6259
|
m2: (kit) => buildM2(kit),
|
|
6118
6260
|
m134: (kit) => buildM134(kit),
|
|
6119
6261
|
launcher: buildLauncher
|
|
@@ -6137,7 +6279,7 @@ function buildWeaponModelById(THREE, id) {
|
|
|
6137
6279
|
const kit = modelKit(THREE);
|
|
6138
6280
|
const options = { L: entry.length, B: entry.barrel, cal: entry.caliber, ...entry.options };
|
|
6139
6281
|
if (id in ARCHETYPE_MODELS) delete options.chambers;
|
|
6140
|
-
const built =
|
|
6282
|
+
const built = BUILDERS2[entry.builder](kit, options);
|
|
6141
6283
|
nameParts(built.parts);
|
|
6142
6284
|
let root;
|
|
6143
6285
|
if (entry.builder === "launcher") {
|
|
@@ -6146,7 +6288,7 @@ function buildWeaponModelById(THREE, id) {
|
|
|
6146
6288
|
built.group.position.x = -new THREE.Box3().setFromObject(built.group).min.x;
|
|
6147
6289
|
} else root = fitLength(kit, built.group, entry.length / 1e3);
|
|
6148
6290
|
root.name = id;
|
|
6149
|
-
|
|
6291
|
+
markKitOrigin3(root, { owner: "game-weapons-three", kind: "weapon", id });
|
|
6150
6292
|
const model = { id, root, inner: built.group, parts: built.parts };
|
|
6151
6293
|
if (!built.parts.frames) built.parts.frames = deriveFrames(THREE, model);
|
|
6152
6294
|
return model;
|
|
@@ -6379,9 +6521,17 @@ function revolverReload(kind) {
|
|
|
6379
6521
|
if (kind !== "one_by_one") events.push(cue(0.7, "move_in", { from: "chambers" }), sound2(0.7, "speedloader"));
|
|
6380
6522
|
return { tweens: [turn("crane", "x", 0, 0.22, 0, -1.25), turn("crane", "x", 1.05, 0.2, -1.25, 0)], events, end: 1.3 };
|
|
6381
6523
|
}
|
|
6382
|
-
var breakReload = () => ({
|
|
6524
|
+
var breakReload = (chambers) => ({
|
|
6383
6525
|
tweens: [turn("barrels", "z", 0, 0.2, 0, -0.5), turn("barrels", "z", 1, 0.15, -0.5, 0)],
|
|
6384
|
-
events: [
|
|
6526
|
+
events: [
|
|
6527
|
+
sound2(0, "barrels_open"),
|
|
6528
|
+
cue(0.25, "eject_casing", { from: "breech", down: false }),
|
|
6529
|
+
sound2(0.25, "casings_eject"),
|
|
6530
|
+
cue(0.65, "move_in", { from: "breech" }),
|
|
6531
|
+
sound2(0.65, "shell_insert"),
|
|
6532
|
+
...chambers > 1 ? [sound2(0.8, "shell_insert")] : [],
|
|
6533
|
+
sound2(1.13, "barrels_close")
|
|
6534
|
+
],
|
|
6385
6535
|
end: 1.2
|
|
6386
6536
|
});
|
|
6387
6537
|
var beltReload = (context) => ({
|
|
@@ -6454,7 +6604,7 @@ function draftFor(context, kind) {
|
|
|
6454
6604
|
if (family === "rocket" || family === "flame") return heavyReload(context);
|
|
6455
6605
|
if (parts.mag) return magazineReload(context, kind);
|
|
6456
6606
|
if (family === "revolver" && parts.crane) return revolverReload(kind);
|
|
6457
|
-
if (family === "break" && parts.barrels) return breakReload();
|
|
6607
|
+
if (family === "break" && parts.barrels) return breakReload(parts.breech?.length ?? 2);
|
|
6458
6608
|
if (family === "belt" && parts.cover && parts.belt) return beltReload(context);
|
|
6459
6609
|
if (isTube(context)) return tubeReload(context, kind);
|
|
6460
6610
|
if (family === "bolt") return boltReload(context);
|
|
@@ -7154,7 +7304,7 @@ function applyCondition(kit, model, condition) {
|
|
|
7154
7304
|
}
|
|
7155
7305
|
|
|
7156
7306
|
// src/models/cartridge.ts
|
|
7157
|
-
import { markKitOrigin as
|
|
7307
|
+
import { markKitOrigin as markKitOrigin4 } from "@adatechnology/game-contracts";
|
|
7158
7308
|
var BOTTLENECK_RATIO = 0.8;
|
|
7159
7309
|
function cartridgeShape(caliber, dims) {
|
|
7160
7310
|
if (caliber.caseType === "shell" || caliber.rim === "shell") return "shell";
|
|
@@ -7166,7 +7316,7 @@ function cartridgeShape(caliber, dims) {
|
|
|
7166
7316
|
}
|
|
7167
7317
|
function buildCartridge(kit, dims, shape) {
|
|
7168
7318
|
const { M, cylinderY } = kit;
|
|
7169
|
-
const group =
|
|
7319
|
+
const group = markKitOrigin4(kit.group(), { owner: "game-weapons-three", kind: "ammunition", id: shape });
|
|
7170
7320
|
const radius = dims.caseDiameter / 2;
|
|
7171
7321
|
const bulletRadius = dims.projectileDiameter / 2;
|
|
7172
7322
|
const caseLength = dims.caseLength;
|
|
@@ -7198,7 +7348,7 @@ function buildCartridge(kit, dims, shape) {
|
|
|
7198
7348
|
}
|
|
7199
7349
|
function buildCasing(kit, dims, shape) {
|
|
7200
7350
|
const { M, cylinderX } = kit;
|
|
7201
|
-
const group =
|
|
7351
|
+
const group = markKitOrigin4(kit.group(), { owner: "game-weapons-three", kind: "ammunition", id: shape });
|
|
7202
7352
|
const radius = dims.caseDiameter / 2e3;
|
|
7203
7353
|
const length = dims.caseLength / 1e3;
|
|
7204
7354
|
if (shape === "shell") {
|
|
@@ -7214,7 +7364,7 @@ function buildCasing(kit, dims, shape) {
|
|
|
7214
7364
|
return { group, radius, length };
|
|
7215
7365
|
}
|
|
7216
7366
|
function buildRound(kit, dims, shape) {
|
|
7217
|
-
const group =
|
|
7367
|
+
const group = markKitOrigin4(kit.group(), { owner: "game-weapons-three", kind: "ammunition", id: shape });
|
|
7218
7368
|
const cartridge = buildCartridge(kit, dims, shape);
|
|
7219
7369
|
cartridge.scale.setScalar(1e-3);
|
|
7220
7370
|
cartridge.rotation.z = -Math.PI / 2;
|
|
@@ -7251,6 +7401,38 @@ function createEffects(THREE, sink, random) {
|
|
|
7251
7401
|
};
|
|
7252
7402
|
}
|
|
7253
7403
|
|
|
7404
|
+
// src/fx/view-hold.ts
|
|
7405
|
+
var VIEW_HOLD = {
|
|
7406
|
+
/** The right hand's grip, from the eye. */
|
|
7407
|
+
grip: [0.2, -0.2, -0.3],
|
|
7408
|
+
/** A handgun's grip: higher and nearer the middle, the arms out in front. */
|
|
7409
|
+
handgunGrip: [0.13, -0.15, -0.33],
|
|
7410
|
+
/** A rocket launcher's grip: its tube rides on the shoulder, so the hands are higher. */
|
|
7411
|
+
launcherGrip: [0.2, -0.14, -0.3],
|
|
7412
|
+
/** A gun with no grip anchor: the rear of its bore, from the eye. */
|
|
7413
|
+
rear: [0.2, -0.24, -0.12]
|
|
7414
|
+
};
|
|
7415
|
+
var scratch2 = { grip: null };
|
|
7416
|
+
function placeInView(placement) {
|
|
7417
|
+
const { THREE, hand, holder, camera, right } = placement;
|
|
7418
|
+
holder.scale.setScalar(1);
|
|
7419
|
+
hand.position.copy(camera.position);
|
|
7420
|
+
hand.quaternion.copy(camera.quaternion);
|
|
7421
|
+
hand.scale.setScalar(1);
|
|
7422
|
+
holder.position.set(0, 0, 0);
|
|
7423
|
+
hand.updateMatrixWorld(true);
|
|
7424
|
+
if (!right) {
|
|
7425
|
+
holder.position.set(VIEW_HOLD.rear[0], VIEW_HOLD.rear[1], VIEW_HOLD.rear[2] + placement.rear);
|
|
7426
|
+
hand.updateMatrixWorld(true);
|
|
7427
|
+
return;
|
|
7428
|
+
}
|
|
7429
|
+
scratch2.grip ?? (scratch2.grip = new THREE.Vector3());
|
|
7430
|
+
const grip = hand.worldToLocal(right.part.localToWorld(scratch2.grip.copy(right.offset)));
|
|
7431
|
+
const [x, y, z] = placement.kind === "handgun" ? VIEW_HOLD.handgunGrip : placement.kind === "launcher" ? VIEW_HOLD.launcherGrip : VIEW_HOLD.grip;
|
|
7432
|
+
holder.position.set(x - grip.x, y - grip.y, z - grip.z);
|
|
7433
|
+
hand.updateMatrixWorld(true);
|
|
7434
|
+
}
|
|
7435
|
+
|
|
7254
7436
|
// src/fx/heavy.ts
|
|
7255
7437
|
import { LIGHT_PRIORITY as LIGHT_PRIORITY2, geometryKey, materialKey } from "@adatechnology/game-render-three";
|
|
7256
7438
|
import { discardObject3D } from "@adatechnology/game-shapes-three";
|
|
@@ -8243,6 +8425,8 @@ function createViewmodel(options) {
|
|
|
8243
8425
|
let triggerRest = 0;
|
|
8244
8426
|
let feedCued = false;
|
|
8245
8427
|
const rootQuaternion = new THREE.Quaternion();
|
|
8428
|
+
const muzzleAt = new THREE.Vector3();
|
|
8429
|
+
const muzzleAlong = new THREE.Vector3();
|
|
8246
8430
|
const world = {
|
|
8247
8431
|
kit,
|
|
8248
8432
|
scene,
|
|
@@ -8342,6 +8526,7 @@ function createViewmodel(options) {
|
|
|
8342
8526
|
if (model.parts.stockMove && onTool?.stock === "collapsed") rig.setPartPose("stock", collapsedStockPose(model.parts.stockMove));
|
|
8343
8527
|
applyCondition(kit, model, condition);
|
|
8344
8528
|
lastAmmo = options.tool?.().ammo ?? 0;
|
|
8529
|
+
void audio?.loadSamples();
|
|
8345
8530
|
hand.updateMatrixWorld(true);
|
|
8346
8531
|
hold = holdOfModel(THREE, model, 1);
|
|
8347
8532
|
hold = { ...hold, works: handWorkOf(THREE, model, weapon, hold.right) };
|
|
@@ -8394,12 +8579,22 @@ function createViewmodel(options) {
|
|
|
8394
8579
|
if (!session) return;
|
|
8395
8580
|
const family = session.model.parts.family;
|
|
8396
8581
|
session.holderScale = 1;
|
|
8582
|
+
if (options.firstPerson?.()) {
|
|
8583
|
+
placeInView({ THREE, hand, holder, camera, right: hold?.right ?? null, rear: modelRear, kind: family === "pistol" || family === "revolver" ? "handgun" : family === "rocket" ? "launcher" : "long" });
|
|
8584
|
+
lift = 0;
|
|
8585
|
+
pullFromWall(dt);
|
|
8586
|
+
return;
|
|
8587
|
+
}
|
|
8588
|
+
hand.scale.set(1, 1, 1);
|
|
8397
8589
|
placeOnBody({ THREE, hand, holder, frame: options.bodyHold?.() ?? eyeFrame(), rear: modelRear, lengthMetres: session.lengthMetres, handgun: family === "pistol" || family === "revolver", right: hold?.right ?? null, left: hold?.left ?? null });
|
|
8398
8590
|
hand.updateMatrixWorld(true);
|
|
8399
8591
|
lift += (liftToKeepInView() - lift) * Math.min(1, dt * HAND_IN_VIEW.rate);
|
|
8400
8592
|
if (lift > 1e-4) hand.position.addScaledVector(up.set(0, 1, 0).applyQuaternion(camera.quaternion), lift);
|
|
8401
8593
|
hand.updateMatrixWorld(true);
|
|
8402
|
-
|
|
8594
|
+
pullFromWall(dt);
|
|
8595
|
+
};
|
|
8596
|
+
const pullFromWall = (dt) => {
|
|
8597
|
+
if (!options.contact || !session) return;
|
|
8403
8598
|
ahead.set(0, 0, -1).applyQuaternion(camera.quaternion);
|
|
8404
8599
|
if (reach === 0) reach = Math.max(0.01, measureReach(session));
|
|
8405
8600
|
const free = options.contact(camera.position, ahead, WALL_PULL.probe);
|
|
@@ -8430,7 +8625,7 @@ function createViewmodel(options) {
|
|
|
8430
8625
|
}
|
|
8431
8626
|
const action = current.def.action;
|
|
8432
8627
|
if (action.kind === "launcher") {
|
|
8433
|
-
launchRocket(heavy(current), options.flyRocket !== false);
|
|
8628
|
+
if (current.model.parts.family === "rocket") launchRocket(heavy(current), options.flyRocket !== false);
|
|
8434
8629
|
audio?.play("explosion", LAUNCH_VOLUME, distance());
|
|
8435
8630
|
}
|
|
8436
8631
|
if (action.kind !== "firearm") return;
|
|
@@ -8507,6 +8702,15 @@ function createViewmodel(options) {
|
|
|
8507
8702
|
condition = next;
|
|
8508
8703
|
if (session) applyCondition(kit, session.model, condition);
|
|
8509
8704
|
},
|
|
8705
|
+
muzzle() {
|
|
8706
|
+
const mark = session?.model.parts.muzzle;
|
|
8707
|
+
if (!session || !mark) return null;
|
|
8708
|
+
hand.updateMatrixWorld(true);
|
|
8709
|
+
const at = worldPositionOf(session, mark, muzzleAt);
|
|
8710
|
+
const along = muzzleAlong.set(1, 0, 0).applyQuaternion(session.model.root.getWorldQuaternion(rootQuaternion)).normalize();
|
|
8711
|
+
const kind = session.def.action.kind;
|
|
8712
|
+
return { position: [at.x, at.y, at.z], direction: [along.x, along.y, along.z], drawsFlash: kind === "firearm" || kind === "launcher" };
|
|
8713
|
+
},
|
|
8510
8714
|
handTargets() {
|
|
8511
8715
|
if (!session || !hold) return null;
|
|
8512
8716
|
hand.updateMatrixWorld(true);
|
|
@@ -8561,6 +8765,7 @@ function createWeaponFx(options) {
|
|
|
8561
8765
|
...options.raycast ? { raycast: options.raycast } : {},
|
|
8562
8766
|
...options.contact ? { contact: options.contact } : {},
|
|
8563
8767
|
...options.bodyHold ? { bodyHold: options.bodyHold } : {},
|
|
8768
|
+
...options.firstPerson ? { firstPerson: options.firstPerson } : {},
|
|
8564
8769
|
...options.effects ? { effects: options.effects } : {},
|
|
8565
8770
|
...options.flyRocket === void 0 ? {} : { flyRocket: options.flyRocket },
|
|
8566
8771
|
...options.particleLimit ? { particleLimit: options.particleLimit } : {},
|
|
@@ -8583,6 +8788,7 @@ function createWeaponFx(options) {
|
|
|
8583
8788
|
},
|
|
8584
8789
|
setCondition: (condition) => model.setCondition(condition),
|
|
8585
8790
|
handTargets: () => model.handTargets() ?? box2.handTargets(),
|
|
8791
|
+
muzzle: () => model.inHand !== null ? model.muzzle() : box2.muzzle(),
|
|
8586
8792
|
layers,
|
|
8587
8793
|
get inHand() {
|
|
8588
8794
|
return model.inHand ?? box2.inHand;
|
|
@@ -8604,17 +8810,17 @@ function createWeaponFx(options) {
|
|
|
8604
8810
|
}
|
|
8605
8811
|
|
|
8606
8812
|
// src/modeled-prop.ts
|
|
8607
|
-
import { markKitOrigin as
|
|
8813
|
+
import { markKitOrigin as markKitOrigin5 } from "@adatechnology/game-contracts";
|
|
8608
8814
|
import { mergeByMaterial } from "@adatechnology/game-shapes-three";
|
|
8609
8815
|
var MODEL_BODY = "body";
|
|
8610
8816
|
function buildModeledProp(THREE, def, name, decorate, items, props = defaultWeaponProps()) {
|
|
8611
8817
|
const model = buildWeaponModelById(THREE, def.id) ?? (() => {
|
|
8612
|
-
const root = props.buildItemModel(THREE, def, items);
|
|
8818
|
+
const root = props.buildItemModel(THREE, def, items) ?? buildThrowableModel(THREE, def);
|
|
8613
8819
|
return root ? { root } : void 0;
|
|
8614
8820
|
})();
|
|
8615
8821
|
if (!model) return void 0;
|
|
8616
8822
|
decorate?.(model.root);
|
|
8617
|
-
const group =
|
|
8823
|
+
const group = markKitOrigin5(new THREE.Group(), { owner: "game-weapons-three", kind: "weapon", id: def.id });
|
|
8618
8824
|
group.name = name;
|
|
8619
8825
|
const box2 = new THREE.Box3().setFromObject(model.root);
|
|
8620
8826
|
const center = box2.getCenter(new THREE.Vector3());
|
|
@@ -9752,7 +9958,7 @@ var targetProp = (id, name) => {
|
|
|
9752
9958
|
};
|
|
9753
9959
|
var weaponItem = (def, name, items, props = defaultWeaponProps()) => {
|
|
9754
9960
|
const id = `${WEAPON_ITEM_PREFIX}${def.id}`;
|
|
9755
|
-
if (!hasWeaponModel(def.id) && !props.itemModelOf(def.id, items)) return asItem(id, name, weaponProp(def, name), { weapon: def.id, movable: true });
|
|
9961
|
+
if (!hasWeaponModel(def.id) && !props.itemModelOf(def.id, items) && !hasThrowableModel(def)) return asItem(id, name, weaponProp(def, name), { weapon: def.id, movable: true });
|
|
9756
9962
|
return {
|
|
9757
9963
|
id,
|
|
9758
9964
|
name,
|
|
@@ -9772,7 +9978,7 @@ var mountedM134Item = (def, name, items, props) => ({
|
|
|
9772
9978
|
});
|
|
9773
9979
|
var targetItem = (id, name) => {
|
|
9774
9980
|
const prop = targetProp(id, name);
|
|
9775
|
-
return { id, name, build: (THREE) =>
|
|
9981
|
+
return { id, name, build: (THREE) => markKitOrigin6(buildProp(THREE, prop), { owner: "game-weapons-three", kind: "target", id }), spec: prop.spec, movable: false };
|
|
9776
9982
|
};
|
|
9777
9983
|
var asItem = (id, name, prop, extra = {}) => ({
|
|
9778
9984
|
id,
|
|
@@ -9812,7 +10018,8 @@ function createWeaponsTestModule(options = {}) {
|
|
|
9812
10018
|
const seedOption = options.seed === void 0 ? {} : { seed: options.seed };
|
|
9813
10019
|
let audio;
|
|
9814
10020
|
const ownAudio = () => audio === void 0 ? audio = options.sound === false ? null : createWeaponAudio(void 0, { ...seedOption, ...options.samples ? { samples: options.samples } : {} }) : audio;
|
|
9815
|
-
const
|
|
10021
|
+
const generics = genericWeapons(arsenal);
|
|
10022
|
+
const weaponDefs = [...arsenal.weapons.values()].filter((def) => !BODY_ACTIONS.has(def.id) && !generics.has(def.id));
|
|
9816
10023
|
const thumbnailBase = options.thumbnailBase ?? DEFAULT_THUMBNAIL_BASE;
|
|
9817
10024
|
const withThumbnail = (item, key) => {
|
|
9818
10025
|
const thumbnail = thumbnailBase === false ? void 0 : weaponThumbnailUrl(key, thumbnailBase);
|
|
@@ -9929,6 +10136,7 @@ function createWeaponsTestModule(options = {}) {
|
|
|
9929
10136
|
// the weapon against a wall asks as often as the laser, on the clock of the simulation (so a fast-forwarded room measures as often per frame)
|
|
9930
10137
|
contact: createLaserRaycast(lent.THREE, lent.scene, lent.camera, { now: () => simulatedMs }),
|
|
9931
10138
|
...lent.holdFrame ? { bodyHold: () => lent.holdFrame?.() ?? null } : {},
|
|
10139
|
+
firstPerson: () => lent.player().cameraMode === "first",
|
|
9932
10140
|
...lent.effects ? { effects: lent.effects } : {},
|
|
9933
10141
|
...lent.particleLimit ? { particleLimit: lent.particleLimit } : {},
|
|
9934
10142
|
...isLightBudget(lent.lights) ? { lights: lent.lights } : {},
|
|
@@ -9979,6 +10187,7 @@ function createWeaponsTestModule(options = {}) {
|
|
|
9979
10187
|
});
|
|
9980
10188
|
const offFrame = lent.onFrame((dt) => created.update(dt));
|
|
9981
10189
|
const offHands = lent.setHandTargets?.(() => created.handTargets());
|
|
10190
|
+
const offMuzzle = lent.setMuzzleSource?.(() => created.muzzle());
|
|
9982
10191
|
created.handle({ type: "tool", weapon: lent.tool().weapon }, lent.tool());
|
|
9983
10192
|
return () => {
|
|
9984
10193
|
accessories.dispose();
|
|
@@ -9987,6 +10196,7 @@ function createWeaponsTestModule(options = {}) {
|
|
|
9987
10196
|
offFrame();
|
|
9988
10197
|
offClock();
|
|
9989
10198
|
offHands?.();
|
|
10199
|
+
offMuzzle?.();
|
|
9990
10200
|
created.dispose();
|
|
9991
10201
|
audio?.dispose();
|
|
9992
10202
|
fx = null;
|
|
@@ -10002,7 +10212,7 @@ import { createArsenal as createArsenal2 } from "@adatechnology/game-weapons";
|
|
|
10002
10212
|
|
|
10003
10213
|
// src/test-area/explosives-bench.ts
|
|
10004
10214
|
import { discardObject3D as discardObject3D4 } from "@adatechnology/game-shapes-three";
|
|
10005
|
-
import { markKitOrigin as
|
|
10215
|
+
import { markKitOrigin as markKitOrigin7 } from "@adatechnology/game-contracts";
|
|
10006
10216
|
|
|
10007
10217
|
// src/test-area/explosives-text.ts
|
|
10008
10218
|
var EXPLOSIVES_TEXT = {
|
|
@@ -10265,7 +10475,7 @@ function createExplosivesBench(options) {
|
|
|
10265
10475
|
return new (T()).LineLoop(geometry, new (T()).LineBasicMaterial({ color: colour }));
|
|
10266
10476
|
};
|
|
10267
10477
|
const drawRings = (vessel) => {
|
|
10268
|
-
const group =
|
|
10478
|
+
const group = markKitOrigin7(new (T()).Group(), { owner: "game-weapons-three", kind: "aid" });
|
|
10269
10479
|
group.name = "blast_rings";
|
|
10270
10480
|
const lethal = lethalOf(vessel);
|
|
10271
10481
|
const injury = injuryOf(vessel);
|
|
@@ -10725,6 +10935,7 @@ var SHELTERED = 0.5;
|
|
|
10725
10935
|
var SHELTERED_MOST = 1;
|
|
10726
10936
|
var CHEST = 1.1;
|
|
10727
10937
|
var MIDDLE = 0.3;
|
|
10938
|
+
var AIM_SEARCH = 1.5;
|
|
10728
10939
|
var HEAVY_ITEMS = ["camp_table"];
|
|
10729
10940
|
var PERSON_MASS = 70;
|
|
10730
10941
|
var GROUND_FRICTION = 7;
|
|
@@ -10784,6 +10995,27 @@ function pushScenario(all, bench, mode) {
|
|
|
10784
10995
|
}
|
|
10785
10996
|
const partsBefore = new Map(placed.map((body) => [body.objectId, partsOf(body.objectId)]));
|
|
10786
10997
|
expect(placed.length > 0, fillText2(text.push_found, { n: placed.length, kinds: [...new Set(placed.map((body) => body.kind))].join(", ") }), { placed: placed.map((body) => body.itemId) });
|
|
10998
|
+
const aimOf = new Map(
|
|
10999
|
+
placed.map((body) => {
|
|
11000
|
+
const from = origin.get(body.objectId) ?? body.from;
|
|
11001
|
+
if (body.kind === "zombie" || body.kind === "survivor") return [body.objectId, [from[0], from[1] + CHEST, from[2]]];
|
|
11002
|
+
const boxes = room.renderer.solidsNear?.(from[0], from[2], AIM_SEARCH).filter((box2) => box2.objectId === body.objectId) ?? [];
|
|
11003
|
+
if (boxes.length === 0) return [body.objectId, [from[0], from[1] + MIDDLE, from[2]]];
|
|
11004
|
+
const low = [0, 1, 2].map((axis) => Math.min(...boxes.map((box2) => box2.min[axis])));
|
|
11005
|
+
const high = [0, 1, 2].map((axis) => Math.max(...boxes.map((box2) => box2.max[axis])));
|
|
11006
|
+
return [body.objectId, [0, 1, 2].map((axis) => (low[axis] + high[axis]) / 2)];
|
|
11007
|
+
})
|
|
11008
|
+
);
|
|
11009
|
+
const coverAt = (point) => new Map(
|
|
11010
|
+
placed.map((body) => {
|
|
11011
|
+
const ignore = source ? [source, body.objectId] : [body.objectId];
|
|
11012
|
+
return [body.objectId, room.world.blastReach?.(point, aimOf.get(body.objectId) ?? body.from, { ignore }) ?? 1];
|
|
11013
|
+
})
|
|
11014
|
+
);
|
|
11015
|
+
let coverOf;
|
|
11016
|
+
const stopListening = room.world.on("*", (event) => {
|
|
11017
|
+
if ((event.type === "explode" || event.type === "blast") && !coverOf) coverOf = coverAt(event.point);
|
|
11018
|
+
});
|
|
10787
11019
|
if (mode === "p13") bench.actions.shoot();
|
|
10788
11020
|
else {
|
|
10789
11021
|
room.setTool("frag_grenade");
|
|
@@ -10796,17 +11028,11 @@ function pushScenario(all, bench, mode) {
|
|
|
10796
11028
|
step(0.05);
|
|
10797
11029
|
waited += 0.05;
|
|
10798
11030
|
}
|
|
11031
|
+
stopListening();
|
|
10799
11032
|
const blast = bench.lastBlast();
|
|
10800
11033
|
expect(!!blast, text.push_told, { waited });
|
|
10801
11034
|
if (!blast) return;
|
|
10802
|
-
const
|
|
10803
|
-
placed.map((body) => {
|
|
10804
|
-
const from = origin.get(body.objectId) ?? body.from;
|
|
10805
|
-
const person = body.kind === "zombie" || body.kind === "survivor";
|
|
10806
|
-
const ignore = source ? [source, body.objectId] : [body.objectId];
|
|
10807
|
-
return [body.objectId, room.world.blastReach?.(blast.point, [from[0], from[1] + (person ? CHEST : MIDDLE), from[2]], { ignore }) ?? 1];
|
|
10808
|
-
})
|
|
10809
|
-
);
|
|
11035
|
+
const cover = coverOf ?? coverAt(blast.point);
|
|
10810
11036
|
step(PUSH_READ_AT);
|
|
10811
11037
|
const rows = placed.map((body) => {
|
|
10812
11038
|
const from = origin.get(body.objectId) ?? body.from;
|
|
@@ -10814,16 +11040,18 @@ function pushScenario(all, bench, mode) {
|
|
|
10814
11040
|
const distance = flat(from, blast.point);
|
|
10815
11041
|
const away = Math.max(1e-6, distance);
|
|
10816
11042
|
const outward = ((now[0] - from[0]) * (from[0] - blast.point[0]) + (now[2] - from[2]) * (from[2] - blast.point[2])) / away;
|
|
10817
|
-
return { ...body, distance, outward, moved: flat(now, from), cover:
|
|
11043
|
+
return { ...body, distance, outward, moved: flat(now, from), cover: cover.get(body.objectId) ?? 1 };
|
|
10818
11044
|
});
|
|
10819
11045
|
const torn = (row) => (PUSH_KINDS.some((entry) => entry.kind === row.kind) || HEAVY_ITEMS.includes(row.kind)) && partsOf(row.objectId) < (partsBefore.get(row.objectId) ?? 0);
|
|
10820
11046
|
const inReach = rows.filter((row) => row.distance < blast.radius * 0.85 && !torn(row));
|
|
11047
|
+
const isPerson = (row) => row.kind === "survivor" || row.kind === "zombie";
|
|
11048
|
+
const reached = inReach.filter((row) => row.cover >= SHELTERED && !isPerson(row));
|
|
10821
11049
|
const sheltered = inReach.filter((row) => row.cover < SHELTERED);
|
|
10822
11050
|
for (const row of sheltered) {
|
|
10823
|
-
|
|
11051
|
+
const open = reached.filter((other) => other.kind === row.kind && other.distance <= row.distance).map((other) => other.outward);
|
|
11052
|
+
const most = Math.max(SHELTERED_MOST, row.cover * Math.max(0, ...open));
|
|
11053
|
+
expect(row.outward < most, fillText2(text.push_sheltered, { what: things[row.kind] ?? row.kind, distance: row.distance.toFixed(1), cover: (row.cover * 100).toFixed(0), moved: Math.max(0, row.outward).toFixed(2) }), { row: { kind: row.kind, distance: row.distance, outward: row.outward, cover: row.cover, most } });
|
|
10824
11054
|
}
|
|
10825
|
-
const isPerson = (row) => row.kind === "survivor" || row.kind === "zombie";
|
|
10826
|
-
const reached = inReach.filter((row) => row.cover >= SHELTERED && !isPerson(row));
|
|
10827
11055
|
const movedAway = reached.filter((row) => row.outward >= MOVED);
|
|
10828
11056
|
const least = reached.length === 0 ? 0 : Math.min(...reached.map((row) => row.outward));
|
|
10829
11057
|
expect(reached.length > 0 && movedAway.length === reached.length, fillText2(text.push_outward, { moved: movedAway.length, n: reached.length, least: least.toFixed(2) }), { rows: reached.map((row) => ({ kind: row.kind, distance: row.distance, outward: row.outward })), torn: rows.filter(torn).map((row) => row.objectId) });
|
|
@@ -11013,14 +11241,19 @@ export {
|
|
|
11013
11241
|
BODY_ACTIONS,
|
|
11014
11242
|
weaponProp,
|
|
11015
11243
|
buildProp,
|
|
11244
|
+
modelKit,
|
|
11245
|
+
EXPLOSIVE_MODEL_IDS,
|
|
11246
|
+
hasExplosiveModel,
|
|
11247
|
+
buildExplosiveModel,
|
|
11016
11248
|
SHIPPED_WEAPON_ITEM_MODELS,
|
|
11249
|
+
hasThrowableModel,
|
|
11250
|
+
buildThrowableModel,
|
|
11017
11251
|
weaponPropsOver,
|
|
11018
11252
|
defaultWeaponProps,
|
|
11019
11253
|
registerWeaponItemModel,
|
|
11020
11254
|
itemModelOfWeapon,
|
|
11021
11255
|
buildItemWeaponModel,
|
|
11022
11256
|
buildWeaponModel,
|
|
11023
|
-
modelKit,
|
|
11024
11257
|
deriveFrames,
|
|
11025
11258
|
mountFrame,
|
|
11026
11259
|
buildFlyingRocket,
|
|
@@ -11066,4 +11299,4 @@ export {
|
|
|
11066
11299
|
DEFAULT_EXPLOSIVES_SCENE,
|
|
11067
11300
|
createExplosivesTestModule
|
|
11068
11301
|
};
|
|
11069
|
-
//# sourceMappingURL=chunk-
|
|
11302
|
+
//# sourceMappingURL=chunk-GBO6L7CQ.js.map
|