@adatechnology/game-weapons-three 0.4.0 → 0.5.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/CREDITS.md +1 -1
- package/assets/weapon-svg/credits.html +1 -1
- package/assets/weapon-svg/generated/cast_iron_skillet.svg +1 -0
- package/assets/weapon-svg/generated/chainsaw.svg +1 -0
- package/assets/weapon-svg/generated/hatchet.svg +1 -0
- package/assets/weapon-svg/generated/improvised_spear.svg +1 -0
- package/assets/weapon-svg/generated/iron_pipe.svg +1 -0
- package/assets/weapon-svg/generated/meat_cleaver.svg +1 -0
- package/assets/weapon-svg/generated/nail_bat.svg +1 -0
- package/assets/weapon-svg/generated/pickaxe.svg +1 -0
- package/assets/weapon-svg/generated/police_baton.svg +1 -0
- package/assets/weapon-svg/generated/recurve_bow.svg +1 -0
- package/assets/weapon-svg/generated/sickle.svg +1 -0
- package/assets/weapon-svg/generated/tactical_knife.svg +1 -0
- package/assets/weapon-svg/manifest.json +48 -0
- package/dist/index.d.ts +23 -2
- package/dist/index.global.js +619 -259
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +100 -51
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
package/dist/index.global.js
CHANGED
|
@@ -35,6 +35,7 @@ var GameWeaponsThree = (() => {
|
|
|
35
35
|
MOUNTED_M134_ITEM_ID: () => MOUNTED_M134_ITEM_ID,
|
|
36
36
|
WEAPON_ITEM_PREFIX: () => WEAPON_ITEM_PREFIX,
|
|
37
37
|
WEAPON_THUMBNAILS: () => WEAPON_THUMBNAILS,
|
|
38
|
+
WORLD_EFFECTS: () => WORLD_EFFECTS,
|
|
38
39
|
WORLD_EXPLOSIVE_IDS: () => WORLD_EXPLOSIVE_IDS,
|
|
39
40
|
WORLD_EXPLOSIVE_PREFIX: () => WORLD_EXPLOSIVE_PREFIX,
|
|
40
41
|
applyCondition: () => applyCondition,
|
|
@@ -50,6 +51,7 @@ var GameWeaponsThree = (() => {
|
|
|
50
51
|
createWeaponAudio: () => createWeaponAudio,
|
|
51
52
|
createWeaponFx: () => createWeaponFx,
|
|
52
53
|
createWeaponsTestModule: () => createWeaponsTestModule,
|
|
54
|
+
createWorldEffects: () => createWorldEffects,
|
|
53
55
|
deriveFrames: () => deriveFrames,
|
|
54
56
|
fitAttachmentModels: () => fitAttachmentModels,
|
|
55
57
|
hasWeaponModel: () => hasWeaponModel,
|
|
@@ -66,6 +68,199 @@ var GameWeaponsThree = (() => {
|
|
|
66
68
|
worldExplosiveItem: () => worldExplosiveItem
|
|
67
69
|
});
|
|
68
70
|
|
|
71
|
+
// ../game-contracts/dist/index.js
|
|
72
|
+
var TOOL_CLIP = {
|
|
73
|
+
DRAW: "draw",
|
|
74
|
+
SHOT: "shot",
|
|
75
|
+
MISFIRE: "misfire",
|
|
76
|
+
EMPTY: "empty",
|
|
77
|
+
CYCLE: "cycle",
|
|
78
|
+
RELOAD: "reload",
|
|
79
|
+
FEED: "feed",
|
|
80
|
+
FAULT: "fault",
|
|
81
|
+
CLEAR: "clear",
|
|
82
|
+
SAFETY_ON: "safety_on",
|
|
83
|
+
SAFETY_OFF: "safety_off",
|
|
84
|
+
MODE: "mode",
|
|
85
|
+
/** A throwable with the pin out, held until it is thrown. */
|
|
86
|
+
COOK: "cook",
|
|
87
|
+
/** The stock folds, unfolds, slides in or out (variants `fold`, `unfold`, `collapse`, `extend`). */
|
|
88
|
+
STOCK: "stock",
|
|
89
|
+
/** A light or a laser is switched (variants `on`, `off`). */
|
|
90
|
+
TOGGLE: "toggle"
|
|
91
|
+
};
|
|
92
|
+
var stockVariant = (event) => {
|
|
93
|
+
const isFolding = event.kind === void 0 ? false : event.kind.includes("fold");
|
|
94
|
+
if (event.state === "collapsed") return isFolding ? "fold" : "collapse";
|
|
95
|
+
return isFolding ? "unfold" : "extend";
|
|
96
|
+
};
|
|
97
|
+
var toolAnimationStep = (event) => {
|
|
98
|
+
switch (event.type) {
|
|
99
|
+
case "tool":
|
|
100
|
+
return { type: "play", clip: TOOL_CLIP.DRAW, ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
101
|
+
case "shot":
|
|
102
|
+
return { type: "play", clip: TOOL_CLIP.SHOT, repeat: Math.max(1, event.rounds ?? 1) };
|
|
103
|
+
case "misfire":
|
|
104
|
+
return { type: "play", clip: TOOL_CLIP.MISFIRE };
|
|
105
|
+
case "empty":
|
|
106
|
+
return { type: "play", clip: TOOL_CLIP.EMPTY };
|
|
107
|
+
case "mode":
|
|
108
|
+
return { type: "play", clip: TOOL_CLIP.MODE, variant: event.mode };
|
|
109
|
+
case "fault":
|
|
110
|
+
return { type: "play", clip: TOOL_CLIP.FAULT, variant: event.fault };
|
|
111
|
+
case "clear":
|
|
112
|
+
if (event.phase === "end") return { type: "finish", clip: TOOL_CLIP.CLEAR };
|
|
113
|
+
return { type: "play", clip: TOOL_CLIP.CLEAR, variant: event.fault, ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
114
|
+
case "safety":
|
|
115
|
+
return { type: "play", clip: event.on ? TOOL_CLIP.SAFETY_ON : TOOL_CLIP.SAFETY_OFF };
|
|
116
|
+
case "cycle":
|
|
117
|
+
if (event.phase === "end") return { type: "finish", clip: TOOL_CLIP.CYCLE };
|
|
118
|
+
return { type: "play", clip: TOOL_CLIP.CYCLE, ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
119
|
+
case "reload":
|
|
120
|
+
if (event.phase === "end") return { type: "finish", clip: TOOL_CLIP.RELOAD };
|
|
121
|
+
return { type: "play", clip: TOOL_CLIP.RELOAD, ...event.kind === void 0 ? {} : { variant: event.kind }, ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
122
|
+
case "stage":
|
|
123
|
+
return { type: "sync", stage: event.stage };
|
|
124
|
+
case "feed":
|
|
125
|
+
return { type: "play", clip: TOOL_CLIP.FEED };
|
|
126
|
+
case "cook":
|
|
127
|
+
if (event.phase === "start") return { type: "play", clip: TOOL_CLIP.COOK, duration: event.fuse };
|
|
128
|
+
return { type: "finish", clip: TOOL_CLIP.COOK };
|
|
129
|
+
case "stock":
|
|
130
|
+
return { type: "play", clip: TOOL_CLIP.STOCK, variant: stockVariant(event), ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
131
|
+
case "toggle":
|
|
132
|
+
return { type: "play", clip: TOOL_CLIP.TOGGLE, variant: event.on ? "on" : "off" };
|
|
133
|
+
default:
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
var STAGE_EVENT = "stage";
|
|
138
|
+
var scaleClip = (clip, duration) => {
|
|
139
|
+
const factor = clip.duration > 0 ? duration / clip.duration : 1;
|
|
140
|
+
return {
|
|
141
|
+
...clip,
|
|
142
|
+
duration,
|
|
143
|
+
keys: clip.keys.map((key) => ({ ...key, t: key.t * factor })),
|
|
144
|
+
...clip.events ? { events: clip.events.map((event) => ({ ...event, t: event.t * factor })) } : {}
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
var ZERO = [0, 0, 0];
|
|
148
|
+
var mix = (from, to, fraction) => [
|
|
149
|
+
(from[0] ?? 0) + ((to[0] ?? 0) - (from[0] ?? 0)) * fraction,
|
|
150
|
+
(from[1] ?? 0) + ((to[1] ?? 0) - (from[1] ?? 0)) * fraction,
|
|
151
|
+
(from[2] ?? 0) + ((to[2] ?? 0) - (from[2] ?? 0)) * fraction
|
|
152
|
+
];
|
|
153
|
+
var sampleClip = (clip, partId, time) => {
|
|
154
|
+
const points = clip.keys.map((key) => {
|
|
155
|
+
const pose = partId === void 0 ? key : key.parts?.[partId];
|
|
156
|
+
return { t: key.t, position: pose?.position ?? ZERO, rotation: pose?.rotation ?? ZERO };
|
|
157
|
+
});
|
|
158
|
+
const first = points[0];
|
|
159
|
+
if (!first || first.t > 0) points.unshift({ t: 0, position: ZERO, rotation: ZERO });
|
|
160
|
+
const last = points[points.length - 1];
|
|
161
|
+
if (!last) return { position: ZERO, rotation: ZERO };
|
|
162
|
+
if (time >= last.t) return { position: mix(last.position, last.position, 0), rotation: mix(last.rotation, last.rotation, 0) };
|
|
163
|
+
const index = Math.max(0, points.findIndex((point, i) => time >= point.t && time < (points[i + 1]?.t ?? Infinity)));
|
|
164
|
+
const from = points[index];
|
|
165
|
+
const to = points[index + 1];
|
|
166
|
+
if (!from || !to) return { position: ZERO, rotation: ZERO };
|
|
167
|
+
const fraction = to.t > from.t ? (time - from.t) / (to.t - from.t) : 0;
|
|
168
|
+
return { position: mix(from.position, to.position, fraction), rotation: mix(from.rotation, to.rotation, fraction) };
|
|
169
|
+
};
|
|
170
|
+
var createToolClipPlayer = (options) => {
|
|
171
|
+
const { clips, rig, onEvent } = options;
|
|
172
|
+
let instances = [];
|
|
173
|
+
const find = (clip, variant) => {
|
|
174
|
+
const name = variant !== void 0 && clips[`${clip}_${variant}`] ? `${clip}_${variant}` : clip;
|
|
175
|
+
const found = clips[name];
|
|
176
|
+
return found ? { name, clip: found } : void 0;
|
|
177
|
+
};
|
|
178
|
+
const render = (instance) => {
|
|
179
|
+
const time = Math.min(instance.time, instance.clip.duration);
|
|
180
|
+
const root = sampleClip(instance.clip, void 0, time);
|
|
181
|
+
if (instance.clip.keys.some((key) => key.position || key.rotation)) rig.setRootPose?.(root);
|
|
182
|
+
const touched = new Set(instance.clip.keys.flatMap((key) => Object.keys(key.parts ?? {})));
|
|
183
|
+
for (const id of touched) rig.setPartPose(id, sampleClip(instance.clip, id, time));
|
|
184
|
+
};
|
|
185
|
+
const fireEvents = (instance, upTo) => {
|
|
186
|
+
const events = instance.clip.events ?? [];
|
|
187
|
+
while (instance.fired < events.length && (events[instance.fired]?.t ?? Infinity) <= upTo + 1e-9) {
|
|
188
|
+
const event = events[instance.fired];
|
|
189
|
+
instance.fired += 1;
|
|
190
|
+
if (event) onEvent?.(event, instance.name);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
return {
|
|
194
|
+
apply(step) {
|
|
195
|
+
if (step.type === "sync") {
|
|
196
|
+
for (const instance of instances) {
|
|
197
|
+
const marker = (instance.clip.events ?? []).find((event) => event.type === STAGE_EVENT && event.data?.stage === step.stage);
|
|
198
|
+
if (marker && instance.time < marker.t) instance.time = marker.t;
|
|
199
|
+
}
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (step.type === "finish") {
|
|
203
|
+
for (const instance of instances) {
|
|
204
|
+
if (instance.name !== step.clip && !instance.name.startsWith(`${step.clip}_`)) continue;
|
|
205
|
+
fireEvents(instance, instance.clip.duration);
|
|
206
|
+
instance.time = instance.clip.duration;
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const found = find(step.clip, step.variant);
|
|
211
|
+
if (!found) return;
|
|
212
|
+
const clip = step.duration && step.duration > 0 ? scaleClip(found.clip, step.duration) : found.clip;
|
|
213
|
+
const interval = options.repeatInterval?.() ?? 0.1;
|
|
214
|
+
instances = instances.filter((existing) => existing.name !== found.name || existing.delay > 0);
|
|
215
|
+
for (let round2 = 0; round2 < (step.repeat ?? 1); round2++) {
|
|
216
|
+
instances.push({ name: found.name, clip, time: 0, delay: round2 * interval, fired: 0 });
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
update(dt) {
|
|
220
|
+
for (const instance of instances) {
|
|
221
|
+
const carried = instance.delay > 0 ? dt - instance.delay : dt;
|
|
222
|
+
if (instance.delay > 0) {
|
|
223
|
+
instance.delay = Math.max(0, instance.delay - dt);
|
|
224
|
+
if (instance.delay > 0) continue;
|
|
225
|
+
}
|
|
226
|
+
instance.time += carried;
|
|
227
|
+
fireEvents(instance, instance.time);
|
|
228
|
+
render(instance);
|
|
229
|
+
}
|
|
230
|
+
instances = instances.filter((instance) => instance.delay > 0 || instance.time < instance.clip.duration);
|
|
231
|
+
},
|
|
232
|
+
get playing() {
|
|
233
|
+
return instances.map((instance) => instance.name);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
238
|
+
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
239
|
+
var deepMerge = (base, patch) => {
|
|
240
|
+
if (!patch) return base;
|
|
241
|
+
const result2 = { ...base };
|
|
242
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
243
|
+
if (value === void 0 || UNSAFE_KEYS.has(key)) continue;
|
|
244
|
+
const current = result2[key];
|
|
245
|
+
result2[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value;
|
|
246
|
+
}
|
|
247
|
+
return result2;
|
|
248
|
+
};
|
|
249
|
+
var mergeById = (shipped, extra) => {
|
|
250
|
+
const entries = /* @__PURE__ */ new Map();
|
|
251
|
+
for (const entry of [...shipped, ...extra ?? []]) entries.set(entry.id, entry);
|
|
252
|
+
return entries;
|
|
253
|
+
};
|
|
254
|
+
var applyPatches = (entries, patches) => {
|
|
255
|
+
for (const [id, patch] of Object.entries(patches ?? {})) {
|
|
256
|
+
const entry = entries.get(id);
|
|
257
|
+
if (entry) entries.set(id, deepMerge(entry, patch));
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
var removeIds = (entries, ids) => {
|
|
261
|
+
for (const id of ids ?? []) entries.delete(id);
|
|
262
|
+
};
|
|
263
|
+
|
|
69
264
|
// ../game-weapons/dist/index.js
|
|
70
265
|
var __defProp2 = Object.defineProperty;
|
|
71
266
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -11138,69 +11333,270 @@ var GameWeaponsThree = (() => {
|
|
|
11138
11333
|
if (context.isCompatible && !context.isCompatible(def, attachment, fitted)) return { ok: false, reason: "rejected" };
|
|
11139
11334
|
return { ok: true, mount: place.kind };
|
|
11140
11335
|
};
|
|
11141
|
-
var
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
|
|
11188
|
-
|
|
11189
|
-
|
|
11190
|
-
|
|
11191
|
-
|
|
11192
|
-
|
|
11193
|
-
|
|
11194
|
-
|
|
11195
|
-
|
|
11196
|
-
|
|
11197
|
-
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11336
|
+
var melee_weapons_default = [
|
|
11337
|
+
{
|
|
11338
|
+
id: "tactical_knife",
|
|
11339
|
+
name: "Tactical knife",
|
|
11340
|
+
category: "melee_blade",
|
|
11341
|
+
action: {
|
|
11342
|
+
kind: "melee",
|
|
11343
|
+
damage: "slash",
|
|
11344
|
+
energy: 45,
|
|
11345
|
+
radius: 0.03,
|
|
11346
|
+
reach: 0.6,
|
|
11347
|
+
rpm: 100,
|
|
11348
|
+
noise: 1
|
|
11349
|
+
},
|
|
11350
|
+
mass: 0.3
|
|
11351
|
+
},
|
|
11352
|
+
{
|
|
11353
|
+
id: "meat_cleaver",
|
|
11354
|
+
name: "Meat cleaver",
|
|
11355
|
+
category: "melee_blade",
|
|
11356
|
+
action: {
|
|
11357
|
+
kind: "melee",
|
|
11358
|
+
damage: "slash",
|
|
11359
|
+
energy: 120,
|
|
11360
|
+
radius: 0.05,
|
|
11361
|
+
reach: 0.6,
|
|
11362
|
+
rpm: 70,
|
|
11363
|
+
noise: 2
|
|
11364
|
+
},
|
|
11365
|
+
mass: 0.6
|
|
11366
|
+
},
|
|
11367
|
+
{
|
|
11368
|
+
id: "hatchet",
|
|
11369
|
+
name: "Hatchet",
|
|
11370
|
+
category: "melee_blade",
|
|
11371
|
+
action: {
|
|
11372
|
+
kind: "melee",
|
|
11373
|
+
damage: "slash",
|
|
11374
|
+
energy: 180,
|
|
11375
|
+
radius: 0.06,
|
|
11376
|
+
reach: 0.7,
|
|
11377
|
+
rpm: 55,
|
|
11378
|
+
noise: 2
|
|
11379
|
+
},
|
|
11380
|
+
mass: 0.8
|
|
11381
|
+
},
|
|
11382
|
+
{
|
|
11383
|
+
id: "nail_bat",
|
|
11384
|
+
name: "Nail bat",
|
|
11385
|
+
category: "melee_blunt",
|
|
11386
|
+
action: {
|
|
11387
|
+
kind: "melee",
|
|
11388
|
+
damage: "blunt",
|
|
11389
|
+
energy: 170,
|
|
11390
|
+
radius: 0.1,
|
|
11391
|
+
reach: 1,
|
|
11392
|
+
rpm: 60,
|
|
11393
|
+
noise: 3
|
|
11394
|
+
},
|
|
11395
|
+
mass: 1.2
|
|
11396
|
+
},
|
|
11397
|
+
{
|
|
11398
|
+
id: "iron_pipe",
|
|
11399
|
+
name: "Iron pipe",
|
|
11400
|
+
category: "melee_blunt",
|
|
11401
|
+
action: {
|
|
11402
|
+
kind: "melee",
|
|
11403
|
+
damage: "blunt",
|
|
11404
|
+
energy: 140,
|
|
11405
|
+
radius: 0.06,
|
|
11406
|
+
reach: 1,
|
|
11407
|
+
rpm: 60,
|
|
11408
|
+
noise: 4
|
|
11409
|
+
},
|
|
11410
|
+
mass: 1.2
|
|
11411
|
+
},
|
|
11412
|
+
{
|
|
11413
|
+
id: "pickaxe",
|
|
11414
|
+
name: "Pickaxe",
|
|
11415
|
+
category: "melee_blade",
|
|
11416
|
+
action: {
|
|
11417
|
+
kind: "melee",
|
|
11418
|
+
damage: "slash",
|
|
11419
|
+
energy: 260,
|
|
11420
|
+
radius: 0.05,
|
|
11421
|
+
reach: 1,
|
|
11422
|
+
rpm: 40,
|
|
11423
|
+
noise: 4
|
|
11424
|
+
},
|
|
11425
|
+
mass: 2.8,
|
|
11426
|
+
tags: [
|
|
11427
|
+
"heavy"
|
|
11428
|
+
]
|
|
11429
|
+
},
|
|
11430
|
+
{
|
|
11431
|
+
id: "sickle",
|
|
11432
|
+
name: "Sickle",
|
|
11433
|
+
category: "melee_blade",
|
|
11434
|
+
action: {
|
|
11435
|
+
kind: "melee",
|
|
11436
|
+
damage: "slash",
|
|
11437
|
+
energy: 70,
|
|
11438
|
+
radius: 0.05,
|
|
11439
|
+
reach: 1.1,
|
|
11440
|
+
rpm: 70,
|
|
11441
|
+
noise: 2
|
|
11442
|
+
},
|
|
11443
|
+
mass: 1.2
|
|
11444
|
+
},
|
|
11445
|
+
{
|
|
11446
|
+
id: "police_baton",
|
|
11447
|
+
name: "Police baton",
|
|
11448
|
+
category: "melee_blunt",
|
|
11449
|
+
action: {
|
|
11450
|
+
kind: "melee",
|
|
11451
|
+
damage: "blunt",
|
|
11452
|
+
energy: 70,
|
|
11453
|
+
radius: 0.04,
|
|
11454
|
+
reach: 0.7,
|
|
11455
|
+
rpm: 90,
|
|
11456
|
+
noise: 3
|
|
11457
|
+
},
|
|
11458
|
+
mass: 0.6
|
|
11459
|
+
},
|
|
11460
|
+
{
|
|
11461
|
+
id: "cast_iron_skillet",
|
|
11462
|
+
name: "Cast iron skillet",
|
|
11463
|
+
category: "melee_blunt",
|
|
11464
|
+
action: {
|
|
11465
|
+
kind: "melee",
|
|
11466
|
+
damage: "blunt",
|
|
11467
|
+
energy: 110,
|
|
11468
|
+
radius: 0.12,
|
|
11469
|
+
reach: 0.6,
|
|
11470
|
+
rpm: 60,
|
|
11471
|
+
noise: 8
|
|
11472
|
+
},
|
|
11473
|
+
mass: 1.2
|
|
11474
|
+
},
|
|
11475
|
+
{
|
|
11476
|
+
id: "improvised_spear",
|
|
11477
|
+
name: "Improvised spear",
|
|
11478
|
+
category: "melee_blade",
|
|
11479
|
+
action: {
|
|
11480
|
+
kind: "melee",
|
|
11481
|
+
damage: "slash",
|
|
11482
|
+
energy: 90,
|
|
11483
|
+
radius: 0.02,
|
|
11484
|
+
reach: 1.6,
|
|
11485
|
+
rpm: 50,
|
|
11486
|
+
noise: 1
|
|
11487
|
+
},
|
|
11488
|
+
mass: 1.1
|
|
11489
|
+
},
|
|
11490
|
+
{
|
|
11491
|
+
id: "chainsaw",
|
|
11492
|
+
name: "Chainsaw",
|
|
11493
|
+
category: "melee_blade",
|
|
11494
|
+
action: {
|
|
11495
|
+
kind: "melee",
|
|
11496
|
+
damage: "slash",
|
|
11497
|
+
energy: 400,
|
|
11498
|
+
radius: 0.1,
|
|
11499
|
+
reach: 0.9,
|
|
11500
|
+
rpm: 300,
|
|
11501
|
+
noise: 120
|
|
11502
|
+
},
|
|
11503
|
+
mass: 6,
|
|
11504
|
+
tags: [
|
|
11505
|
+
"heavy"
|
|
11506
|
+
]
|
|
11507
|
+
},
|
|
11508
|
+
{
|
|
11509
|
+
id: "recurve_bow",
|
|
11510
|
+
name: "Recurve bow",
|
|
11511
|
+
category: "bow",
|
|
11512
|
+
action: {
|
|
11513
|
+
kind: "firearm",
|
|
11514
|
+
caliber: "arrow",
|
|
11515
|
+
rpm: 20,
|
|
11516
|
+
modes: [
|
|
11517
|
+
"single"
|
|
11518
|
+
],
|
|
11519
|
+
magazine: 1,
|
|
11520
|
+
reload: 1.5,
|
|
11521
|
+
barrel: 1,
|
|
11522
|
+
spreadDeg: 0.4,
|
|
11523
|
+
bloomDeg: 0.4,
|
|
11524
|
+
recoveryDegPerS: 2,
|
|
11525
|
+
recoil: [
|
|
11526
|
+
0.3,
|
|
11527
|
+
0.1
|
|
11528
|
+
],
|
|
11529
|
+
range: 40
|
|
11530
|
+
},
|
|
11531
|
+
mass: 1.2,
|
|
11532
|
+
tags: [
|
|
11533
|
+
"silent"
|
|
11534
|
+
]
|
|
11535
|
+
}
|
|
11536
|
+
];
|
|
11537
|
+
var findDuplicateIds = (kind, entries) => {
|
|
11538
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11539
|
+
const problems = [];
|
|
11540
|
+
for (const { id } of entries ?? []) {
|
|
11541
|
+
if (seen.has(id)) problems.push(`${kind} "${id}" is listed more than once`);
|
|
11542
|
+
seen.add(id);
|
|
11543
|
+
}
|
|
11544
|
+
return problems;
|
|
11545
|
+
};
|
|
11546
|
+
var checkRotary = (id, action) => {
|
|
11547
|
+
const problems = [];
|
|
11548
|
+
const { rpm, rpmRange, spin } = action;
|
|
11549
|
+
if (rpmRange && !(rpmRange[0] > 0 && rpmRange[0] <= rpmRange[1])) problems.push(`weapon "${id}" has an empty rate range ${rpmRange[0]}-${rpmRange[1]} rpm`);
|
|
11550
|
+
if (rpmRange && (rpm < rpmRange[0] || rpm > rpmRange[1])) problems.push(`weapon "${id}" fires at ${rpm} rpm, outside its range ${rpmRange[0]}-${rpmRange[1]}`);
|
|
11551
|
+
if (spin && !(spin.upSeconds >= 0 && spin.holdSeconds >= 0)) problems.push(`weapon "${id}" has a negative spin time`);
|
|
11552
|
+
return problems;
|
|
11553
|
+
};
|
|
11554
|
+
var checkFirearm = (def, calibers) => {
|
|
11555
|
+
if (def.action.kind !== "firearm") return [];
|
|
11556
|
+
const problems = [];
|
|
11557
|
+
for (const caliber of [def.action.caliber, ...def.action.acceptsCalibers ?? []]) {
|
|
11558
|
+
if (!calibers.has(caliber)) problems.push(`weapon "${def.id}" uses unknown calibre "${caliber}"`);
|
|
11559
|
+
}
|
|
11560
|
+
if (def.action.modes.length === 0) problems.push(`weapon "${def.id}" has no fire modes`);
|
|
11561
|
+
if (!(def.action.rpm > 0)) problems.push(`weapon "${def.id}" has a rate of fire of ${def.action.rpm} rpm`);
|
|
11562
|
+
if (!(def.action.reload > 0)) problems.push(`weapon "${def.id}" has a reload time of ${def.action.reload} s`);
|
|
11563
|
+
problems.push(...checkRotary(def.id, def.action));
|
|
11564
|
+
return problems;
|
|
11565
|
+
};
|
|
11566
|
+
var checkTimings = (def) => {
|
|
11567
|
+
const timings = "timings" in def.action ? def.action.timings : void 0;
|
|
11568
|
+
return Object.entries(timings ?? {}).filter(([, seconds]) => typeof seconds === "number" && !(seconds > 0)).map(([name, seconds]) => `weapon "${def.id}" has a ${name} time of ${seconds} s`);
|
|
11569
|
+
};
|
|
11570
|
+
var checkExplosiveReference = (def, explosives) => {
|
|
11571
|
+
const id = def.action.kind === "launcher" ? def.action.projectile : def.action.kind === "throwable" ? def.action.explosive : void 0;
|
|
11572
|
+
return id !== void 0 && !explosives.has(id) ? [`weapon "${def.id}" uses unknown explosive "${id}"`] : [];
|
|
11573
|
+
};
|
|
11574
|
+
var checkExplosiveNumbers = (explosive) => {
|
|
11575
|
+
const problems = [];
|
|
11576
|
+
const [low, high] = explosive.fuseRange ?? [1, 1];
|
|
11577
|
+
if (!(low > 0 && high >= low)) problems.push(`explosive "${explosive.id}" has a fuse range of ${low} to ${high} s`);
|
|
11578
|
+
if (explosive.fuseLength !== void 0 && !(explosive.fuseLength > 0)) problems.push(`explosive "${explosive.id}" has a fuse length of ${explosive.fuseLength} m`);
|
|
11579
|
+
if (explosive.burnRate !== void 0 && !(explosive.burnRate > 0)) problems.push(`explosive "${explosive.id}" has a burn rate of ${explosive.burnRate} s/m`);
|
|
11580
|
+
if (explosive.burnTolerance !== void 0 && !(explosive.burnTolerance >= 0 && explosive.burnTolerance < 1)) problems.push(`explosive "${explosive.id}" has a burn tolerance of ${explosive.burnTolerance}`);
|
|
11581
|
+
if (explosive.tripwire && !(explosive.tripwire.length > 0)) problems.push(`explosive "${explosive.id}" has a trip wire of ${explosive.tripwire.length} m`);
|
|
11582
|
+
return problems;
|
|
11583
|
+
};
|
|
11584
|
+
var STATS = /* @__PURE__ */ new Set(["noise", "spread", "hipSpreadExcess", "recoilVertical", "recoilHorizontal", "range", "muzzleSpeed", "mass", "capacity", "reload", "reloadEmpty", "draw", "aim", "faultChance", "heatPerShot"]);
|
|
11585
|
+
var INSTALLS = /* @__PURE__ */ new Set(["field", "tool", "bench"]);
|
|
11586
|
+
var checkAttachment = (attachment, weapons) => {
|
|
11587
|
+
const problems = [];
|
|
11588
|
+
if (attachment.launcher !== void 0 && weapons.get(attachment.launcher)?.action.kind !== "launcher") problems.push(`attachment "${attachment.id}" names "${attachment.launcher}" as its launcher, which is not a launcher weapon`);
|
|
11589
|
+
const label = `attachment "${attachment.id}"`;
|
|
11590
|
+
if (!INSTALLS.has(attachment.install)) problems.push(`${label} installs "${attachment.install}"`);
|
|
11591
|
+
if (attachment.mounts.length === 0) problems.push(`${label} has no mount`);
|
|
11592
|
+
if (attachment.interfaces.length === 0) problems.push(`${label} has no interface`);
|
|
11593
|
+
for (const effect of attachment.effects) {
|
|
11594
|
+
if (!STATS.has(effect.stat)) problems.push(`${label} changes the unknown stat "${effect.stat}"`);
|
|
11595
|
+
if (effect.mul !== void 0 && !(effect.mul > 0)) problems.push(`${label} multiplies ${effect.stat} by ${effect.mul}`);
|
|
11596
|
+
}
|
|
11597
|
+
return problems;
|
|
11598
|
+
};
|
|
11599
|
+
var checkFitted = (def, attachments) => {
|
|
11204
11600
|
if (!attachments) return [];
|
|
11205
11601
|
return (def.fitted ?? []).flatMap((part) => {
|
|
11206
11602
|
const problems = [];
|
|
@@ -11222,18 +11618,6 @@ var GameWeaponsThree = (() => {
|
|
|
11222
11618
|
...[...explosives.values()].flatMap(checkExplosiveNumbers),
|
|
11223
11619
|
...checkRuleDefaults(rules)
|
|
11224
11620
|
];
|
|
11225
|
-
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
11226
|
-
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
11227
|
-
var deepMerge = (base, patch) => {
|
|
11228
|
-
if (!patch) return base;
|
|
11229
|
-
const result2 = { ...base };
|
|
11230
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
11231
|
-
if (value === void 0 || UNSAFE_KEYS.has(key)) continue;
|
|
11232
|
-
const current = result2[key];
|
|
11233
|
-
result2[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value;
|
|
11234
|
-
}
|
|
11235
|
-
return result2;
|
|
11236
|
-
};
|
|
11237
11621
|
var modesEn = { single: "single action", semi: "semi-automatic", burst: "burst", auto: "automatic", pump: "pump action", bolt: "bolt action", lever: "lever action", break: "break action", volley: "volley" };
|
|
11238
11622
|
var categoriesEn = {
|
|
11239
11623
|
pistol: "pistol",
|
|
@@ -11425,20 +11809,6 @@ var GameWeaponsThree = (() => {
|
|
|
11425
11809
|
if (explosive.fuseRange) return explosive.fuseRange[0] + (explosive.fuseRange[1] - explosive.fuseRange[0]) * random();
|
|
11426
11810
|
return explosive.fuse;
|
|
11427
11811
|
};
|
|
11428
|
-
var mergeById = (shipped, extra) => {
|
|
11429
|
-
const entries = /* @__PURE__ */ new Map();
|
|
11430
|
-
for (const entry of [...shipped, ...extra ?? []]) entries.set(entry.id, entry);
|
|
11431
|
-
return entries;
|
|
11432
|
-
};
|
|
11433
|
-
var applyPatches = (entries, patches) => {
|
|
11434
|
-
for (const [id, patch] of Object.entries(patches ?? {})) {
|
|
11435
|
-
const entry = entries.get(id);
|
|
11436
|
-
if (entry) entries.set(id, deepMerge(entry, patch));
|
|
11437
|
-
}
|
|
11438
|
-
};
|
|
11439
|
-
var removeIds = (entries, ids) => {
|
|
11440
|
-
for (const id of ids ?? []) entries.delete(id);
|
|
11441
|
-
};
|
|
11442
11812
|
var resolveThrowables = (weapons, explosives) => {
|
|
11443
11813
|
for (const [id, def] of weapons) {
|
|
11444
11814
|
if (def.action.kind !== "throwable" || def.action.explosive === void 0) continue;
|
|
@@ -12674,6 +13044,7 @@ var GameWeaponsThree = (() => {
|
|
|
12674
13044
|
caliber: cal.diameter,
|
|
12675
13045
|
caliberId: cal.id,
|
|
12676
13046
|
speed,
|
|
13047
|
+
mass: cal.bulletGrams,
|
|
12677
13048
|
energyAt,
|
|
12678
13049
|
pellet: p,
|
|
12679
13050
|
weapon: this.def.id
|
|
@@ -12859,7 +13230,7 @@ var GameWeaponsThree = (() => {
|
|
|
12859
13230
|
var EXPLOSIVES = explosives_default;
|
|
12860
13231
|
var ARCHETYPES = archetypes_default;
|
|
12861
13232
|
var ARCHETYPE_IDS = ARCHETYPES.map((def) => def.id);
|
|
12862
|
-
var WEAPONS = [...ARCHETYPES, ...firearms_default, ...launchers_default, ...explosive_weapons_default];
|
|
13233
|
+
var WEAPONS = [...ARCHETYPES, ...firearms_default, ...launchers_default, ...explosive_weapons_default, ...melee_weapons_default];
|
|
12863
13234
|
var explosiveOf = (def, explosives) => {
|
|
12864
13235
|
const id = def.action.kind === "launcher" ? def.action.projectile : def.action.kind === "throwable" ? def.action.explosive : void 0;
|
|
12865
13236
|
return id === void 0 ? null : explosives.get(id) ?? null;
|
|
@@ -13605,7 +13976,68 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
13605
13976
|
};
|
|
13606
13977
|
};
|
|
13607
13978
|
|
|
13608
|
-
//
|
|
13979
|
+
// ../game-props3d/dist/index.js
|
|
13980
|
+
var T = (id, interior, w, d, h, y, solid2, group) => ({ id, interior, w, d, h, y, solid: solid2, group });
|
|
13981
|
+
var TYPE_DEFS = [
|
|
13982
|
+
T("ceiling_light", true, 0.4, 0.4, 0.07, 0, false, "ceiling"),
|
|
13983
|
+
T("pendant", true, 0.34, 0.34, 1, 0, false, "ceiling"),
|
|
13984
|
+
T("track_spot", true, 1.2, 0.1, 0.2, 0, false, "ceiling"),
|
|
13985
|
+
T("chandelier", true, 0.7, 0.7, 0.7, 0, false, "ceiling"),
|
|
13986
|
+
T("wall_ac", true, 0.9, 0.2, 0.28, 2.15, false, "wall"),
|
|
13987
|
+
T("picture_small", true, 0.35, 0.03, 0.45, 1.3, false, "wall"),
|
|
13988
|
+
T("picture_large", true, 1, 0.04, 0.7, 1.2, false, "wall"),
|
|
13989
|
+
T("mirror", true, 0.6, 0.03, 1.2, 0.9, false, "wall"),
|
|
13990
|
+
T("curtain", true, 1.6, 0.12, 2.3, 0.1, false, "wall"),
|
|
13991
|
+
T("blinds", true, 1.2, 0.08, 1.3, 1, false, "wall"),
|
|
13992
|
+
T("flat_tv", true, 1.2, 0.06, 0.7, 1, false, "wall"),
|
|
13993
|
+
T("floor_plant", true, 0.5, 0.5, 1.1, 0, true, "plants"),
|
|
13994
|
+
T("table_plant", true, 0.2, 0.2, 0.3, 0, false, "plants"),
|
|
13995
|
+
T("hanging_plant", true, 0.5, 0.5, 1, 0, false, "plants"),
|
|
13996
|
+
T("tv_stand", true, 1.6, 0.42, 1.05, 0, true, "furniture"),
|
|
13997
|
+
T("breakfast_bar", true, 2, 1.6, 0.95, 0, true, "furniture"),
|
|
13998
|
+
T("sofa_l", true, 2.8, 1.7, 0.85, 0, true, "furniture"),
|
|
13999
|
+
T("double_bed_modern", true, 1.6, 2.1, 1.2, 0, true, "furniture"),
|
|
14000
|
+
T("home_office", true, 1.4, 0.75, 1.2, 0, true, "furniture"),
|
|
14001
|
+
T("closet", true, 2.2, 0.6, 2.3, 0, true, "furniture"),
|
|
14002
|
+
T("vanity", true, 0.6, 0.45, 1.5, 0, true, "furniture"),
|
|
14003
|
+
T("ac_condenser", false, 0.8, 0.3, 0.55, 0.5, true, "yard"),
|
|
14004
|
+
T("lawn", false, 4, 4, 0.02, 0, false, "floor"),
|
|
14005
|
+
T("tile_floor", false, 4, 3, 0.03, 0, false, "floor"),
|
|
14006
|
+
T("concrete", false, 4, 4, 0.03, 0, false, "floor"),
|
|
14007
|
+
T("deck_floor", false, 4, 3, 0.04, 0, false, "floor"),
|
|
14008
|
+
T("dirt", false, 4, 4, 0.02, 0, false, "floor"),
|
|
14009
|
+
T("gourmet_counter", false, 4.2, 3, 2.9, 0, true, "yard"),
|
|
14010
|
+
T("sauna", false, 2, 1.8, 2.1, 0, true, "yard"),
|
|
14011
|
+
T("soaking_tub", false, 1.3, 1.3, 0.8, 0, true, "yard"),
|
|
14012
|
+
T("pool", false, 4.5, 2.8, 0.1, 0, true, "yard"),
|
|
14013
|
+
T("deck", false, 3.5, 3, 0.22, 0, true, "yard"),
|
|
14014
|
+
T("sun_lounger", false, 0.62, 1.9, 0.5, 0, true, "yard"),
|
|
14015
|
+
T("garden_bed", false, 2, 1, 0.9, 0, true, "yard"),
|
|
14016
|
+
T("fruit_tree", false, 2.4, 2.4, 3.2, 0, true, "yard"),
|
|
14017
|
+
T("palm_tree", false, 2, 2, 4.5, 0, true, "yard"),
|
|
14018
|
+
T("pergola", false, 3.5, 3, 2.4, 0, true, "yard"),
|
|
14019
|
+
T("slide", false, 0.8, 2.6, 1.5, 0, true, "yard"),
|
|
14020
|
+
T("swing", false, 2.2, 1.7, 2.2, 0, true, "yard"),
|
|
14021
|
+
T("bbq_simple", false, 0.9, 0.6, 1, 0, true, "yard"),
|
|
14022
|
+
T("garage_car", false, 1.8, 4.2, 1.45, 0, true, "yard"),
|
|
14023
|
+
T("window_boards", true, 1.2, 0.06, 1.15, 1, false, "house_state"),
|
|
14024
|
+
T("barricade", true, 1.5, 0.7, 1.8, 0, true, "house_state"),
|
|
14025
|
+
T("sandbags", false, 1.6, 0.5, 0.6, 0, true, "house_state"),
|
|
14026
|
+
T("barbed_wire", false, 4, 0.2, 0.6, 0, false, "house_state"),
|
|
14027
|
+
T("razor_wire", false, 4, 0.6, 0.6, 0, false, "house_state"),
|
|
14028
|
+
T("water_bottle_crates", true, 0.9, 0.6, 0.65, 0, true, "house_state"),
|
|
14029
|
+
T("canned_food", true, 0.4, 0.3, 0.3, 0, false, "house_state"),
|
|
14030
|
+
T("water_jug", true, 0.3, 0.3, 0.5, 0, true, "house_state"),
|
|
14031
|
+
T("floor_mattress", true, 0.9, 1.9, 0.3, 0, false, "house_state"),
|
|
14032
|
+
T("lantern", true, 0.16, 0.16, 0.3, 0, false, "house_state"),
|
|
14033
|
+
T("candles", true, 0.25, 0.25, 0.2, 0, false, "house_state"),
|
|
14034
|
+
T("open_suitcases", true, 1.5, 0.7, 0.6, 0, false, "house_state"),
|
|
14035
|
+
T("clothes_on_floor", true, 1.2, 1, 0.05, 0, false, "house_state"),
|
|
14036
|
+
T("fallen_chair", true, 0.5, 0.5, 0.5, 0, false, "house_state"),
|
|
14037
|
+
T("blood_stains", true, 1.2, 1.2, 0.01, 0, false, "house_state"),
|
|
14038
|
+
T("open_door", true, 0.9, 0.15, 2.15, 0, false, "house_state")
|
|
14039
|
+
];
|
|
14040
|
+
var DEFS = Object.fromEntries(TYPE_DEFS.map((t) => [t.id, t]));
|
|
13609
14041
|
var ATTRIBUTES = ["position", "normal", "uv"];
|
|
13610
14042
|
var isVisible = (object) => {
|
|
13611
14043
|
for (let node = object; node; node = node.parent) if (!node.visible) return false;
|
|
@@ -17026,173 +17458,6 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
17026
17458
|
};
|
|
17027
17459
|
}
|
|
17028
17460
|
|
|
17029
|
-
// ../game-contracts/dist/index.js
|
|
17030
|
-
var TOOL_CLIP = {
|
|
17031
|
-
DRAW: "draw",
|
|
17032
|
-
SHOT: "shot",
|
|
17033
|
-
MISFIRE: "misfire",
|
|
17034
|
-
EMPTY: "empty",
|
|
17035
|
-
CYCLE: "cycle",
|
|
17036
|
-
RELOAD: "reload",
|
|
17037
|
-
FEED: "feed",
|
|
17038
|
-
FAULT: "fault",
|
|
17039
|
-
CLEAR: "clear",
|
|
17040
|
-
SAFETY_ON: "safety_on",
|
|
17041
|
-
SAFETY_OFF: "safety_off",
|
|
17042
|
-
MODE: "mode",
|
|
17043
|
-
/** A throwable with the pin out, held until it is thrown. */
|
|
17044
|
-
COOK: "cook",
|
|
17045
|
-
/** The stock folds, unfolds, slides in or out (variants `fold`, `unfold`, `collapse`, `extend`). */
|
|
17046
|
-
STOCK: "stock",
|
|
17047
|
-
/** A light or a laser is switched (variants `on`, `off`). */
|
|
17048
|
-
TOGGLE: "toggle"
|
|
17049
|
-
};
|
|
17050
|
-
var stockVariant = (event) => {
|
|
17051
|
-
const isFolding = event.kind === void 0 ? false : event.kind.includes("fold");
|
|
17052
|
-
if (event.state === "collapsed") return isFolding ? "fold" : "collapse";
|
|
17053
|
-
return isFolding ? "unfold" : "extend";
|
|
17054
|
-
};
|
|
17055
|
-
var toolAnimationStep = (event) => {
|
|
17056
|
-
switch (event.type) {
|
|
17057
|
-
case "tool":
|
|
17058
|
-
return { type: "play", clip: TOOL_CLIP.DRAW, ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
17059
|
-
case "shot":
|
|
17060
|
-
return { type: "play", clip: TOOL_CLIP.SHOT, repeat: Math.max(1, event.rounds ?? 1) };
|
|
17061
|
-
case "misfire":
|
|
17062
|
-
return { type: "play", clip: TOOL_CLIP.MISFIRE };
|
|
17063
|
-
case "empty":
|
|
17064
|
-
return { type: "play", clip: TOOL_CLIP.EMPTY };
|
|
17065
|
-
case "mode":
|
|
17066
|
-
return { type: "play", clip: TOOL_CLIP.MODE, variant: event.mode };
|
|
17067
|
-
case "fault":
|
|
17068
|
-
return { type: "play", clip: TOOL_CLIP.FAULT, variant: event.fault };
|
|
17069
|
-
case "clear":
|
|
17070
|
-
if (event.phase === "end") return { type: "finish", clip: TOOL_CLIP.CLEAR };
|
|
17071
|
-
return { type: "play", clip: TOOL_CLIP.CLEAR, variant: event.fault, ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
17072
|
-
case "safety":
|
|
17073
|
-
return { type: "play", clip: event.on ? TOOL_CLIP.SAFETY_ON : TOOL_CLIP.SAFETY_OFF };
|
|
17074
|
-
case "cycle":
|
|
17075
|
-
if (event.phase === "end") return { type: "finish", clip: TOOL_CLIP.CYCLE };
|
|
17076
|
-
return { type: "play", clip: TOOL_CLIP.CYCLE, ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
17077
|
-
case "reload":
|
|
17078
|
-
if (event.phase === "end") return { type: "finish", clip: TOOL_CLIP.RELOAD };
|
|
17079
|
-
return { type: "play", clip: TOOL_CLIP.RELOAD, ...event.kind === void 0 ? {} : { variant: event.kind }, ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
17080
|
-
case "stage":
|
|
17081
|
-
return { type: "sync", stage: event.stage };
|
|
17082
|
-
case "feed":
|
|
17083
|
-
return { type: "play", clip: TOOL_CLIP.FEED };
|
|
17084
|
-
case "cook":
|
|
17085
|
-
if (event.phase === "start") return { type: "play", clip: TOOL_CLIP.COOK, duration: event.fuse };
|
|
17086
|
-
return { type: "finish", clip: TOOL_CLIP.COOK };
|
|
17087
|
-
case "stock":
|
|
17088
|
-
return { type: "play", clip: TOOL_CLIP.STOCK, variant: stockVariant(event), ...event.duration === void 0 ? {} : { duration: event.duration } };
|
|
17089
|
-
case "toggle":
|
|
17090
|
-
return { type: "play", clip: TOOL_CLIP.TOGGLE, variant: event.on ? "on" : "off" };
|
|
17091
|
-
default:
|
|
17092
|
-
return null;
|
|
17093
|
-
}
|
|
17094
|
-
};
|
|
17095
|
-
var STAGE_EVENT = "stage";
|
|
17096
|
-
var scaleClip = (clip, duration) => {
|
|
17097
|
-
const factor = clip.duration > 0 ? duration / clip.duration : 1;
|
|
17098
|
-
return {
|
|
17099
|
-
...clip,
|
|
17100
|
-
duration,
|
|
17101
|
-
keys: clip.keys.map((key) => ({ ...key, t: key.t * factor })),
|
|
17102
|
-
...clip.events ? { events: clip.events.map((event) => ({ ...event, t: event.t * factor })) } : {}
|
|
17103
|
-
};
|
|
17104
|
-
};
|
|
17105
|
-
var ZERO = [0, 0, 0];
|
|
17106
|
-
var mix = (from, to, fraction) => [
|
|
17107
|
-
(from[0] ?? 0) + ((to[0] ?? 0) - (from[0] ?? 0)) * fraction,
|
|
17108
|
-
(from[1] ?? 0) + ((to[1] ?? 0) - (from[1] ?? 0)) * fraction,
|
|
17109
|
-
(from[2] ?? 0) + ((to[2] ?? 0) - (from[2] ?? 0)) * fraction
|
|
17110
|
-
];
|
|
17111
|
-
var sampleClip = (clip, partId, time) => {
|
|
17112
|
-
const points = clip.keys.map((key) => {
|
|
17113
|
-
const pose = partId === void 0 ? key : key.parts?.[partId];
|
|
17114
|
-
return { t: key.t, position: pose?.position ?? ZERO, rotation: pose?.rotation ?? ZERO };
|
|
17115
|
-
});
|
|
17116
|
-
const first = points[0];
|
|
17117
|
-
if (!first || first.t > 0) points.unshift({ t: 0, position: ZERO, rotation: ZERO });
|
|
17118
|
-
const last = points[points.length - 1];
|
|
17119
|
-
if (!last) return { position: ZERO, rotation: ZERO };
|
|
17120
|
-
if (time >= last.t) return { position: mix(last.position, last.position, 0), rotation: mix(last.rotation, last.rotation, 0) };
|
|
17121
|
-
const index = Math.max(0, points.findIndex((point, i) => time >= point.t && time < (points[i + 1]?.t ?? Infinity)));
|
|
17122
|
-
const from = points[index];
|
|
17123
|
-
const to = points[index + 1];
|
|
17124
|
-
if (!from || !to) return { position: ZERO, rotation: ZERO };
|
|
17125
|
-
const fraction = to.t > from.t ? (time - from.t) / (to.t - from.t) : 0;
|
|
17126
|
-
return { position: mix(from.position, to.position, fraction), rotation: mix(from.rotation, to.rotation, fraction) };
|
|
17127
|
-
};
|
|
17128
|
-
var createToolClipPlayer = (options) => {
|
|
17129
|
-
const { clips, rig, onEvent } = options;
|
|
17130
|
-
let instances = [];
|
|
17131
|
-
const find = (clip, variant) => {
|
|
17132
|
-
const name = variant !== void 0 && clips[`${clip}_${variant}`] ? `${clip}_${variant}` : clip;
|
|
17133
|
-
const found = clips[name];
|
|
17134
|
-
return found ? { name, clip: found } : void 0;
|
|
17135
|
-
};
|
|
17136
|
-
const render = (instance) => {
|
|
17137
|
-
const time = Math.min(instance.time, instance.clip.duration);
|
|
17138
|
-
const root = sampleClip(instance.clip, void 0, time);
|
|
17139
|
-
if (instance.clip.keys.some((key) => key.position || key.rotation)) rig.setRootPose?.(root);
|
|
17140
|
-
const touched = new Set(instance.clip.keys.flatMap((key) => Object.keys(key.parts ?? {})));
|
|
17141
|
-
for (const id of touched) rig.setPartPose(id, sampleClip(instance.clip, id, time));
|
|
17142
|
-
};
|
|
17143
|
-
const fireEvents = (instance, upTo) => {
|
|
17144
|
-
const events = instance.clip.events ?? [];
|
|
17145
|
-
while (instance.fired < events.length && (events[instance.fired]?.t ?? Infinity) <= upTo + 1e-9) {
|
|
17146
|
-
const event = events[instance.fired];
|
|
17147
|
-
instance.fired += 1;
|
|
17148
|
-
if (event) onEvent?.(event, instance.name);
|
|
17149
|
-
}
|
|
17150
|
-
};
|
|
17151
|
-
return {
|
|
17152
|
-
apply(step) {
|
|
17153
|
-
if (step.type === "sync") {
|
|
17154
|
-
for (const instance of instances) {
|
|
17155
|
-
const marker = (instance.clip.events ?? []).find((event) => event.type === STAGE_EVENT && event.data?.stage === step.stage);
|
|
17156
|
-
if (marker && instance.time < marker.t) instance.time = marker.t;
|
|
17157
|
-
}
|
|
17158
|
-
return;
|
|
17159
|
-
}
|
|
17160
|
-
if (step.type === "finish") {
|
|
17161
|
-
for (const instance of instances) {
|
|
17162
|
-
if (instance.name !== step.clip && !instance.name.startsWith(`${step.clip}_`)) continue;
|
|
17163
|
-
fireEvents(instance, instance.clip.duration);
|
|
17164
|
-
instance.time = instance.clip.duration;
|
|
17165
|
-
}
|
|
17166
|
-
return;
|
|
17167
|
-
}
|
|
17168
|
-
const found = find(step.clip, step.variant);
|
|
17169
|
-
if (!found) return;
|
|
17170
|
-
const clip = step.duration && step.duration > 0 ? scaleClip(found.clip, step.duration) : found.clip;
|
|
17171
|
-
const interval = options.repeatInterval?.() ?? 0.1;
|
|
17172
|
-
instances = instances.filter((existing) => existing.name !== found.name || existing.delay > 0);
|
|
17173
|
-
for (let round2 = 0; round2 < (step.repeat ?? 1); round2++) {
|
|
17174
|
-
instances.push({ name: found.name, clip, time: 0, delay: round2 * interval, fired: 0 });
|
|
17175
|
-
}
|
|
17176
|
-
},
|
|
17177
|
-
update(dt) {
|
|
17178
|
-
for (const instance of instances) {
|
|
17179
|
-
const carried = instance.delay > 0 ? dt - instance.delay : dt;
|
|
17180
|
-
if (instance.delay > 0) {
|
|
17181
|
-
instance.delay = Math.max(0, instance.delay - dt);
|
|
17182
|
-
if (instance.delay > 0) continue;
|
|
17183
|
-
}
|
|
17184
|
-
instance.time += carried;
|
|
17185
|
-
fireEvents(instance, instance.time);
|
|
17186
|
-
render(instance);
|
|
17187
|
-
}
|
|
17188
|
-
instances = instances.filter((instance) => instance.delay > 0 || instance.time < instance.clip.duration);
|
|
17189
|
-
},
|
|
17190
|
-
get playing() {
|
|
17191
|
-
return instances.map((instance) => instance.name);
|
|
17192
|
-
}
|
|
17193
|
-
};
|
|
17194
|
-
};
|
|
17195
|
-
|
|
17196
17461
|
// src/animation/clip-builder.ts
|
|
17197
17462
|
var ROOT = "root";
|
|
17198
17463
|
var AXIS_INDEX = { x: 0, y: 1, z: 2 };
|
|
@@ -19087,6 +19352,10 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19087
19352
|
source: "generated",
|
|
19088
19353
|
file: "generated/carl_gustaf_m4.svg"
|
|
19089
19354
|
},
|
|
19355
|
+
cast_iron_skillet: {
|
|
19356
|
+
source: "generated",
|
|
19357
|
+
file: "generated/cast_iron_skillet.svg"
|
|
19358
|
+
},
|
|
19090
19359
|
cbc_122: {
|
|
19091
19360
|
source: "generated",
|
|
19092
19361
|
file: "generated/cbc_122.svg"
|
|
@@ -19099,6 +19368,10 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19099
19368
|
source: "generated",
|
|
19100
19369
|
file: "generated/cbc_pump_military_3_0.svg"
|
|
19101
19370
|
},
|
|
19371
|
+
chainsaw: {
|
|
19372
|
+
source: "generated",
|
|
19373
|
+
file: "generated/chainsaw.svg"
|
|
19374
|
+
},
|
|
19102
19375
|
cheytac_m200: {
|
|
19103
19376
|
source: "generated",
|
|
19104
19377
|
file: "generated/cheytac_m200.svg"
|
|
@@ -19255,6 +19528,10 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19255
19528
|
source: "generated",
|
|
19256
19529
|
file: "generated/hammer.svg"
|
|
19257
19530
|
},
|
|
19531
|
+
hatchet: {
|
|
19532
|
+
source: "generated",
|
|
19533
|
+
file: "generated/hatchet.svg"
|
|
19534
|
+
},
|
|
19258
19535
|
hk416: {
|
|
19259
19536
|
source: "generated",
|
|
19260
19537
|
file: "generated/hk416.svg"
|
|
@@ -19323,6 +19600,14 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19323
19600
|
source: "generated",
|
|
19324
19601
|
file: "generated/improvised_flamethrower.svg"
|
|
19325
19602
|
},
|
|
19603
|
+
improvised_spear: {
|
|
19604
|
+
source: "generated",
|
|
19605
|
+
file: "generated/improvised_spear.svg"
|
|
19606
|
+
},
|
|
19607
|
+
iron_pipe: {
|
|
19608
|
+
source: "generated",
|
|
19609
|
+
file: "generated/iron_pipe.svg"
|
|
19610
|
+
},
|
|
19326
19611
|
kel_tec_ksg: {
|
|
19327
19612
|
source: "generated",
|
|
19328
19613
|
file: "generated/kel_tec_ksg.svg"
|
|
@@ -19391,6 +19676,10 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19391
19676
|
source: "generated",
|
|
19392
19677
|
file: "generated/makarov_pm.svg"
|
|
19393
19678
|
},
|
|
19679
|
+
meat_cleaver: {
|
|
19680
|
+
source: "generated",
|
|
19681
|
+
file: "generated/meat_cleaver.svg"
|
|
19682
|
+
},
|
|
19394
19683
|
mg3: {
|
|
19395
19684
|
source: "generated",
|
|
19396
19685
|
file: "generated/mg3.svg"
|
|
@@ -19415,6 +19704,14 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19415
19704
|
source: "generated",
|
|
19416
19705
|
file: "generated/mossberg_500_cruiser.svg"
|
|
19417
19706
|
},
|
|
19707
|
+
nail_bat: {
|
|
19708
|
+
source: "generated",
|
|
19709
|
+
file: "generated/nail_bat.svg"
|
|
19710
|
+
},
|
|
19711
|
+
pickaxe: {
|
|
19712
|
+
source: "generated",
|
|
19713
|
+
file: "generated/pickaxe.svg"
|
|
19714
|
+
},
|
|
19418
19715
|
pipe_bomb: {
|
|
19419
19716
|
source: "generated",
|
|
19420
19717
|
file: "generated/pipe_bomb.svg"
|
|
@@ -19435,6 +19732,10 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19435
19732
|
source: "generated",
|
|
19436
19733
|
file: "generated/pkm.svg"
|
|
19437
19734
|
},
|
|
19735
|
+
police_baton: {
|
|
19736
|
+
source: "generated",
|
|
19737
|
+
file: "generated/police_baton.svg"
|
|
19738
|
+
},
|
|
19438
19739
|
pp19_bizon: {
|
|
19439
19740
|
source: "generated",
|
|
19440
19741
|
file: "generated/pp19_bizon.svg"
|
|
@@ -19447,6 +19748,10 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19447
19748
|
source: "generated",
|
|
19448
19749
|
file: "generated/pry_bar.svg"
|
|
19449
19750
|
},
|
|
19751
|
+
recurve_bow: {
|
|
19752
|
+
source: "generated",
|
|
19753
|
+
file: "generated/recurve_bow.svg"
|
|
19754
|
+
},
|
|
19450
19755
|
remington_700: {
|
|
19451
19756
|
source: "generated",
|
|
19452
19757
|
file: "generated/remington_700.svg"
|
|
@@ -19523,6 +19828,10 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19523
19828
|
source: "generated",
|
|
19524
19829
|
file: "generated/shotgun_semi_12.svg"
|
|
19525
19830
|
},
|
|
19831
|
+
sickle: {
|
|
19832
|
+
source: "generated",
|
|
19833
|
+
file: "generated/sickle.svg"
|
|
19834
|
+
},
|
|
19526
19835
|
sig_mpx: {
|
|
19527
19836
|
source: "generated",
|
|
19528
19837
|
file: "generated/sig_mpx.svg"
|
|
@@ -19575,6 +19884,10 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19575
19884
|
source: "generated",
|
|
19576
19885
|
file: "generated/sw_model_29.svg"
|
|
19577
19886
|
},
|
|
19887
|
+
tactical_knife: {
|
|
19888
|
+
source: "generated",
|
|
19889
|
+
file: "generated/tactical_knife.svg"
|
|
19890
|
+
},
|
|
19578
19891
|
taurus_82: {
|
|
19579
19892
|
source: "generated",
|
|
19580
19893
|
file: "generated/taurus_82.svg"
|
|
@@ -19673,7 +19986,7 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19673
19986
|
shape: shape.shape,
|
|
19674
19987
|
position: shape.position,
|
|
19675
19988
|
...SHELL,
|
|
19676
|
-
explodes: { energy: def.energy, radius: def.injuryRadius, ...def.chain ? { chain: { ...def.chain } } : {} }
|
|
19989
|
+
explodes: { energy: def.energy, radius: def.injuryRadius, effect: def.id, ...def.chain ? { chain: { ...def.chain } } : {} }
|
|
19677
19990
|
});
|
|
19678
19991
|
var meshOf = (THREE, shape) => {
|
|
19679
19992
|
const geometry = shape.shape.kind === "cylinder" ? new THREE.CylinderGeometry(shape.shape.radius, shape.shape.radius, shape.shape.height, 16) : shape.shape.kind === "box" ? new THREE.BoxGeometry(...shape.shape.size) : new THREE.SphereGeometry(0.2);
|
|
@@ -19701,6 +20014,51 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19701
20014
|
};
|
|
19702
20015
|
};
|
|
19703
20016
|
|
|
20017
|
+
// src/data/world-effects.json
|
|
20018
|
+
var world_effects_default = {
|
|
20019
|
+
pistol: { muzzle: "muzzle_glock", casing: "casing_brass" },
|
|
20020
|
+
tiny: { muzzle: "muzzle_glock", casing: "casing_brass" },
|
|
20021
|
+
rifle: { muzzle: "muzzle_ak", casing: "casing_brass" },
|
|
20022
|
+
shell: { muzzle: "muzzle_r870", casing: "casing_shell" },
|
|
20023
|
+
big: { muzzle: "muzzle_barrett", casing: "casing_50" }
|
|
20024
|
+
};
|
|
20025
|
+
|
|
20026
|
+
// src/world-effects.ts
|
|
20027
|
+
var WORLD_EFFECTS = world_effects_default;
|
|
20028
|
+
var PORT_BACK = 0.35;
|
|
20029
|
+
var PORT_RIGHT = 0.04;
|
|
20030
|
+
function createWorldEffects(options) {
|
|
20031
|
+
const ids = options.ids ?? WORLD_EFFECTS;
|
|
20032
|
+
const caseTypeOf = options.caseTypeOf ?? ((weapon) => {
|
|
20033
|
+
const def = options.arsenal.weapons.get(weapon);
|
|
20034
|
+
return def && def.action.kind === "firearm" ? options.arsenal.calibers.get(def.action.caliber)?.caseType : void 0;
|
|
20035
|
+
});
|
|
20036
|
+
let counter = 0;
|
|
20037
|
+
return {
|
|
20038
|
+
/** Plays what the event asks for and answers how many effects started. */
|
|
20039
|
+
handle(event, sink) {
|
|
20040
|
+
if (!sink || event.type !== "shot" || !event.origin) return 0;
|
|
20041
|
+
const caseType = caseTypeOf(event.weapon) ?? "rifle";
|
|
20042
|
+
const entry = ids[caseType];
|
|
20043
|
+
if (!entry) return 0;
|
|
20044
|
+
const direction = event.direction ?? [0, 0, -1];
|
|
20045
|
+
const seed = ++counter;
|
|
20046
|
+
let started = 0;
|
|
20047
|
+
for (let shot = 0; shot < Math.max(1, event.rounds ?? 1); shot++) {
|
|
20048
|
+
if (sink.play({ effect: entry.muzzle, point: event.origin, direction, seed: seed * 8 + shot }) !== null) started++;
|
|
20049
|
+
}
|
|
20050
|
+
const side = [direction[2], 0, -direction[0]];
|
|
20051
|
+
const port = [
|
|
20052
|
+
event.origin[0] - direction[0] * PORT_BACK + side[0] * PORT_RIGHT,
|
|
20053
|
+
event.origin[1] - direction[1] * PORT_BACK,
|
|
20054
|
+
event.origin[2] - direction[2] * PORT_BACK + side[2] * PORT_RIGHT
|
|
20055
|
+
];
|
|
20056
|
+
if (sink.play({ effect: entry.casing, point: port, direction, seed: seed * 8 + 7 }) !== null) started++;
|
|
20057
|
+
return started;
|
|
20058
|
+
}
|
|
20059
|
+
};
|
|
20060
|
+
}
|
|
20061
|
+
|
|
19704
20062
|
// src/area.ts
|
|
19705
20063
|
var WEAPON_ITEM_PREFIX = "weapon_";
|
|
19706
20064
|
var COUNTER_ITEM_ID = "counter_weapons";
|
|
@@ -19977,7 +20335,9 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
19977
20335
|
} else if (change.kind === "control" && change.id === "sound_distance" && typeof change.value === "number") soundDistance = change.value;
|
|
19978
20336
|
else if (change.kind === "control" && change.id === "fuse_length" && typeof change.value === "number") lent.configureTool?.({ fuse_length: String(change.value) });
|
|
19979
20337
|
});
|
|
20338
|
+
const worldEffects = createWorldEffects({ arsenal });
|
|
19980
20339
|
const offEvents = lent.on((event) => {
|
|
20340
|
+
worldEffects.handle(event, lent.effects);
|
|
19981
20341
|
if (event.type === "explosion") {
|
|
19982
20342
|
const away = Math.hypot(event.point[0] - camera.position.x, event.point[1] - camera.position.y, event.point[2] - camera.position.z);
|
|
19983
20343
|
audio?.play("explosion", Math.min(1, EXPLOSION_VOLUME_BASE + event.radius * EXPLOSION_VOLUME_PER_METRE), away);
|