@adatechnology/game-weapons 0.0.0-stage → 0.1.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.
@@ -0,0 +1,1609 @@
1
+ "use strict";
2
+ var GameWeapons = (() => {
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
22
+
23
+ // src/index.ts
24
+ var index_exports = {};
25
+ __export(index_exports, {
26
+ CALIBERS: () => CALIBERS,
27
+ DEFAULT_LOADOUT: () => DEFAULT_LOADOUT,
28
+ WEAPONS: () => WEAPONS,
29
+ createArsenal: () => createArsenal,
30
+ locales: () => locales,
31
+ muzzleEnergy: () => muzzleEnergy,
32
+ resolveStrings: () => resolveStrings
33
+ });
34
+
35
+ // src/data/calibers.json
36
+ var calibers_default = [
37
+ {
38
+ id: "22lr",
39
+ label: ".22 LR",
40
+ diameter: 5.7,
41
+ bulletGrams: 2.6,
42
+ muzzleSpeed: 350,
43
+ dragPer100m: 0.15,
44
+ kind: "rimfire"
45
+ },
46
+ {
47
+ id: "9x19",
48
+ label: "9\xD719 mm",
49
+ diameter: 9,
50
+ bulletGrams: 7.5,
51
+ muzzleSpeed: 365,
52
+ dragPer100m: 0.2,
53
+ kind: "fmj"
54
+ },
55
+ {
56
+ id: "38spl",
57
+ label: ".38 Special",
58
+ diameter: 9.1,
59
+ bulletGrams: 10.2,
60
+ muzzleSpeed: 247,
61
+ dragPer100m: 0.2,
62
+ kind: "fmj"
63
+ },
64
+ {
65
+ id: "357mag",
66
+ label: ".357 Magnum",
67
+ diameter: 9.1,
68
+ bulletGrams: 10.2,
69
+ muzzleSpeed: 396,
70
+ dragPer100m: 0.18,
71
+ kind: "hp"
72
+ },
73
+ {
74
+ id: "40sw",
75
+ label: ".40 S&W",
76
+ diameter: 10.2,
77
+ bulletGrams: 11.7,
78
+ muzzleSpeed: 310,
79
+ dragPer100m: 0.2,
80
+ kind: "fmj"
81
+ },
82
+ {
83
+ id: "45acp",
84
+ label: ".45 ACP",
85
+ diameter: 11.5,
86
+ bulletGrams: 14.9,
87
+ muzzleSpeed: 254,
88
+ dragPer100m: 0.2,
89
+ kind: "fmj"
90
+ },
91
+ {
92
+ id: "380acp",
93
+ label: ".380 ACP",
94
+ diameter: 9,
95
+ bulletGrams: 6.2,
96
+ muzzleSpeed: 295,
97
+ dragPer100m: 0.22,
98
+ kind: "fmj"
99
+ },
100
+ {
101
+ id: "5_56x45",
102
+ label: "5.56\xD745 mm",
103
+ diameter: 5.7,
104
+ bulletGrams: 4,
105
+ muzzleSpeed: 935,
106
+ dragPer100m: 0.1,
107
+ kind: "fmj"
108
+ },
109
+ {
110
+ id: "7_62x39",
111
+ label: "7.62\xD739 mm",
112
+ diameter: 7.9,
113
+ bulletGrams: 8,
114
+ muzzleSpeed: 725,
115
+ dragPer100m: 0.1,
116
+ kind: "fmj"
117
+ },
118
+ {
119
+ id: "7_62x51",
120
+ label: "7.62\xD751 mm (.308)",
121
+ diameter: 7.8,
122
+ bulletGrams: 9.7,
123
+ muzzleSpeed: 850,
124
+ dragPer100m: 0.08,
125
+ kind: "fmj"
126
+ },
127
+ {
128
+ id: "338lapua",
129
+ label: ".338 Lapua Magnum",
130
+ diameter: 8.6,
131
+ bulletGrams: 16.2,
132
+ muzzleSpeed: 903,
133
+ dragPer100m: 0.06,
134
+ kind: "fmj"
135
+ },
136
+ {
137
+ id: "50bmg",
138
+ label: ".50 BMG",
139
+ diameter: 12.7,
140
+ bulletGrams: 42,
141
+ muzzleSpeed: 925,
142
+ dragPer100m: 0.05,
143
+ kind: "ap"
144
+ },
145
+ {
146
+ id: "12ga_00buck",
147
+ label: "12 ga 00 buck",
148
+ diameter: 8.4,
149
+ bulletGrams: 3.5,
150
+ muzzleSpeed: 414,
151
+ pellets: 9,
152
+ dragPer100m: 0.45,
153
+ kind: "buck"
154
+ },
155
+ {
156
+ id: "12ga_slug",
157
+ label: "12 ga slug",
158
+ diameter: 18.5,
159
+ bulletGrams: 28,
160
+ muzzleSpeed: 463,
161
+ dragPer100m: 0.3,
162
+ kind: "slug"
163
+ },
164
+ {
165
+ id: "12ga_birdshot",
166
+ label: "12 ga birdshot",
167
+ diameter: 2.4,
168
+ bulletGrams: 0.2,
169
+ muzzleSpeed: 400,
170
+ pellets: 90,
171
+ dragPer100m: 0.6,
172
+ kind: "birdshot"
173
+ },
174
+ {
175
+ id: "20ga_buck",
176
+ label: "20 ga buck",
177
+ diameter: 6.9,
178
+ bulletGrams: 1.3,
179
+ muzzleSpeed: 400,
180
+ pellets: 20,
181
+ dragPer100m: 0.5,
182
+ kind: "buck"
183
+ },
184
+ {
185
+ id: "arrow",
186
+ label: "Arrow (compound bow)",
187
+ diameter: 7,
188
+ bulletGrams: 25,
189
+ muzzleSpeed: 90,
190
+ dragPer100m: 0.12,
191
+ kind: "arrow"
192
+ },
193
+ {
194
+ id: "crossbow_bolt",
195
+ label: "Crossbow bolt",
196
+ diameter: 8,
197
+ bulletGrams: 20,
198
+ muzzleSpeed: 122,
199
+ dragPer100m: 0.12,
200
+ kind: "bolt"
201
+ }
202
+ ];
203
+
204
+ // src/data/weapons.json
205
+ var weapons_default = [
206
+ {
207
+ id: "hand",
208
+ name: "Hand",
209
+ category: "hand",
210
+ action: {
211
+ kind: "hand",
212
+ reach: 2
213
+ },
214
+ mass: 0,
215
+ tags: [
216
+ "grab"
217
+ ]
218
+ },
219
+ {
220
+ id: "pistol_9mm",
221
+ name: "9 mm service pistol",
222
+ category: "pistol",
223
+ action: {
224
+ kind: "firearm",
225
+ caliber: "9x19",
226
+ rpm: 300,
227
+ modes: [
228
+ "semi"
229
+ ],
230
+ magazine: 15,
231
+ reload: 2,
232
+ barrel: 1,
233
+ spreadDeg: 1,
234
+ bloomDeg: 0.6,
235
+ recoveryDegPerS: 4,
236
+ recoil: [
237
+ 1.2,
238
+ 0.4
239
+ ],
240
+ range: 50,
241
+ noise: 150
242
+ },
243
+ mass: 0.9,
244
+ tags: [
245
+ "sidearm"
246
+ ]
247
+ },
248
+ {
249
+ id: "pistol_45",
250
+ name: ".45 ACP pistol",
251
+ category: "pistol",
252
+ action: {
253
+ kind: "firearm",
254
+ caliber: "45acp",
255
+ rpm: 280,
256
+ modes: [
257
+ "semi"
258
+ ],
259
+ magazine: 8,
260
+ reload: 2.2,
261
+ barrel: 1,
262
+ spreadDeg: 1.1,
263
+ bloomDeg: 0.8,
264
+ recoveryDegPerS: 4,
265
+ recoil: [
266
+ 1.8,
267
+ 0.6
268
+ ],
269
+ range: 50,
270
+ noise: 160
271
+ },
272
+ mass: 1.1,
273
+ tags: [
274
+ "sidearm"
275
+ ]
276
+ },
277
+ {
278
+ id: "pistol_22",
279
+ name: ".22 LR pistol",
280
+ category: "pistol",
281
+ action: {
282
+ kind: "firearm",
283
+ caliber: "22lr",
284
+ rpm: 360,
285
+ modes: [
286
+ "semi"
287
+ ],
288
+ magazine: 10,
289
+ reload: 1.8,
290
+ barrel: 1,
291
+ spreadDeg: 0.9,
292
+ bloomDeg: 0.3,
293
+ recoveryDegPerS: 5,
294
+ recoil: [
295
+ 0.5,
296
+ 0.2
297
+ ],
298
+ range: 40,
299
+ noise: 90
300
+ },
301
+ mass: 0.7,
302
+ tags: [
303
+ "sidearm"
304
+ ]
305
+ },
306
+ {
307
+ id: "revolver_357",
308
+ name: ".357 Magnum revolver",
309
+ category: "revolver",
310
+ action: {
311
+ kind: "firearm",
312
+ caliber: "357mag",
313
+ rpm: 150,
314
+ modes: [
315
+ "single"
316
+ ],
317
+ magazine: 6,
318
+ reload: 4,
319
+ barrel: 1.05,
320
+ spreadDeg: 0.8,
321
+ bloomDeg: 1,
322
+ recoveryDegPerS: 3,
323
+ recoil: [
324
+ 3,
325
+ 0.9
326
+ ],
327
+ range: 60,
328
+ noise: 220
329
+ },
330
+ mass: 1.2,
331
+ tags: [
332
+ "sidearm"
333
+ ]
334
+ },
335
+ {
336
+ id: "revolver_38",
337
+ name: ".38 Special revolver",
338
+ category: "revolver",
339
+ action: {
340
+ kind: "firearm",
341
+ caliber: "38spl",
342
+ rpm: 160,
343
+ modes: [
344
+ "single"
345
+ ],
346
+ magazine: 6,
347
+ reload: 3.8,
348
+ barrel: 0.95,
349
+ spreadDeg: 0.9,
350
+ bloomDeg: 0.7,
351
+ recoveryDegPerS: 3.5,
352
+ recoil: [
353
+ 1.6,
354
+ 0.5
355
+ ],
356
+ range: 45,
357
+ noise: 170
358
+ },
359
+ mass: 0.9,
360
+ tags: [
361
+ "sidearm"
362
+ ]
363
+ },
364
+ {
365
+ id: "smg_9mm",
366
+ name: "9 mm submachine gun",
367
+ category: "smg",
368
+ action: {
369
+ kind: "firearm",
370
+ caliber: "9x19",
371
+ rpm: 800,
372
+ modes: [
373
+ "auto",
374
+ "burst",
375
+ "semi"
376
+ ],
377
+ burst: 3,
378
+ magazine: 30,
379
+ reload: 2.4,
380
+ barrel: 1.1,
381
+ spreadDeg: 1.5,
382
+ bloomDeg: 0.35,
383
+ recoveryDegPerS: 6,
384
+ recoil: [
385
+ 0.9,
386
+ 0.5
387
+ ],
388
+ range: 80,
389
+ noise: 180
390
+ },
391
+ mass: 2.6,
392
+ tags: [
393
+ "automatic"
394
+ ]
395
+ },
396
+ {
397
+ id: "carbine_22",
398
+ name: ".22 LR carbine",
399
+ category: "carbine",
400
+ action: {
401
+ kind: "firearm",
402
+ caliber: "22lr",
403
+ rpm: 300,
404
+ modes: [
405
+ "semi"
406
+ ],
407
+ magazine: 10,
408
+ reload: 2.2,
409
+ barrel: 1.4,
410
+ spreadDeg: 0.5,
411
+ bloomDeg: 0.15,
412
+ recoveryDegPerS: 5,
413
+ recoil: [
414
+ 0.4,
415
+ 0.15
416
+ ],
417
+ range: 80,
418
+ noise: 100
419
+ },
420
+ mass: 2.4,
421
+ tags: [
422
+ "small_game"
423
+ ]
424
+ },
425
+ {
426
+ id: "rifle_5_56",
427
+ name: "5.56 mm assault rifle",
428
+ category: "rifle",
429
+ action: {
430
+ kind: "firearm",
431
+ caliber: "5_56x45",
432
+ rpm: 750,
433
+ modes: [
434
+ "auto",
435
+ "burst",
436
+ "semi"
437
+ ],
438
+ burst: 3,
439
+ magazine: 30,
440
+ reload: 2.5,
441
+ barrel: 1,
442
+ spreadDeg: 0.6,
443
+ bloomDeg: 0.25,
444
+ recoveryDegPerS: 5,
445
+ recoil: [
446
+ 1,
447
+ 0.6
448
+ ],
449
+ range: 400,
450
+ noise: 300
451
+ },
452
+ mass: 3.4,
453
+ tags: [
454
+ "automatic"
455
+ ]
456
+ },
457
+ {
458
+ id: "rifle_7_62x39",
459
+ name: "7.62\xD739 mm assault rifle",
460
+ category: "rifle",
461
+ action: {
462
+ kind: "firearm",
463
+ caliber: "7_62x39",
464
+ rpm: 600,
465
+ modes: [
466
+ "auto",
467
+ "semi"
468
+ ],
469
+ magazine: 30,
470
+ reload: 2.8,
471
+ barrel: 1,
472
+ spreadDeg: 0.8,
473
+ bloomDeg: 0.35,
474
+ recoveryDegPerS: 4.5,
475
+ recoil: [
476
+ 1.5,
477
+ 0.8
478
+ ],
479
+ range: 350,
480
+ noise: 320
481
+ },
482
+ mass: 3.8,
483
+ tags: [
484
+ "automatic"
485
+ ]
486
+ },
487
+ {
488
+ id: "rifle_bolt_308",
489
+ name: ".308 bolt-action rifle",
490
+ category: "rifle",
491
+ action: {
492
+ kind: "firearm",
493
+ caliber: "7_62x51",
494
+ rpm: 40,
495
+ modes: [
496
+ "bolt"
497
+ ],
498
+ magazine: 5,
499
+ reload: 3.5,
500
+ barrel: 1.05,
501
+ spreadDeg: 0.25,
502
+ bloomDeg: 0.3,
503
+ recoveryDegPerS: 3,
504
+ recoil: [
505
+ 3,
506
+ 0.5
507
+ ],
508
+ range: 800,
509
+ noise: 350
510
+ },
511
+ mass: 4,
512
+ tags: [
513
+ "hunting"
514
+ ]
515
+ },
516
+ {
517
+ id: "sniper_338",
518
+ name: ".338 Lapua sniper rifle",
519
+ category: "sniper",
520
+ action: {
521
+ kind: "firearm",
522
+ caliber: "338lapua",
523
+ rpm: 35,
524
+ modes: [
525
+ "bolt"
526
+ ],
527
+ magazine: 5,
528
+ reload: 4,
529
+ barrel: 1.05,
530
+ spreadDeg: 0.1,
531
+ bloomDeg: 0.3,
532
+ recoveryDegPerS: 2.5,
533
+ recoil: [
534
+ 4.5,
535
+ 0.7
536
+ ],
537
+ range: 1500,
538
+ noise: 450
539
+ },
540
+ mass: 6.5,
541
+ tags: [
542
+ "long_range"
543
+ ]
544
+ },
545
+ {
546
+ id: "anti_materiel_50",
547
+ name: ".50 BMG anti-materiel rifle",
548
+ category: "sniper",
549
+ action: {
550
+ kind: "firearm",
551
+ caliber: "50bmg",
552
+ rpm: 30,
553
+ modes: [
554
+ "semi"
555
+ ],
556
+ magazine: 10,
557
+ reload: 4.5,
558
+ barrel: 1.05,
559
+ spreadDeg: 0.15,
560
+ bloomDeg: 0.5,
561
+ recoveryDegPerS: 2,
562
+ recoil: [
563
+ 7,
564
+ 1.2
565
+ ],
566
+ range: 1800,
567
+ noise: 600
568
+ },
569
+ mass: 12.5,
570
+ tags: [
571
+ "long_range",
572
+ "heavy"
573
+ ]
574
+ },
575
+ {
576
+ id: "shotgun_pump_12",
577
+ name: "12 gauge pump-action shotgun",
578
+ category: "shotgun",
579
+ action: {
580
+ kind: "firearm",
581
+ caliber: "12ga_00buck",
582
+ rpm: 60,
583
+ modes: [
584
+ "pump"
585
+ ],
586
+ magazine: 6,
587
+ reload: 0.6,
588
+ perRound: true,
589
+ barrel: 1,
590
+ spreadDeg: 1,
591
+ bloomDeg: 0.5,
592
+ recoveryDegPerS: 3,
593
+ pelletSpreadDeg: 3,
594
+ recoil: [
595
+ 4,
596
+ 1
597
+ ],
598
+ range: 40,
599
+ noise: 400
600
+ },
601
+ mass: 3.2,
602
+ tags: [
603
+ "shotgun"
604
+ ]
605
+ },
606
+ {
607
+ id: "shotgun_double_12",
608
+ name: "12 gauge double-barrel shotgun",
609
+ category: "shotgun",
610
+ action: {
611
+ kind: "firearm",
612
+ caliber: "12ga_00buck",
613
+ rpm: 120,
614
+ modes: [
615
+ "break"
616
+ ],
617
+ magazine: 2,
618
+ reload: 3.5,
619
+ barrel: 1,
620
+ spreadDeg: 1,
621
+ bloomDeg: 0.5,
622
+ recoveryDegPerS: 3,
623
+ pelletSpreadDeg: 3,
624
+ recoil: [
625
+ 4.5,
626
+ 1.2
627
+ ],
628
+ range: 35,
629
+ noise: 400
630
+ },
631
+ mass: 3,
632
+ tags: [
633
+ "shotgun"
634
+ ]
635
+ },
636
+ {
637
+ id: "shotgun_semi_12",
638
+ name: "12 gauge semi-automatic shotgun",
639
+ category: "shotgun",
640
+ action: {
641
+ kind: "firearm",
642
+ caliber: "12ga_00buck",
643
+ rpm: 180,
644
+ modes: [
645
+ "semi"
646
+ ],
647
+ magazine: 5,
648
+ reload: 0.7,
649
+ perRound: true,
650
+ barrel: 1,
651
+ spreadDeg: 1,
652
+ bloomDeg: 0.5,
653
+ recoveryDegPerS: 3,
654
+ pelletSpreadDeg: 3,
655
+ recoil: [
656
+ 3.4,
657
+ 1
658
+ ],
659
+ range: 40,
660
+ noise: 400
661
+ },
662
+ mass: 3.4,
663
+ tags: [
664
+ "shotgun"
665
+ ]
666
+ },
667
+ {
668
+ id: "bow_compound",
669
+ name: "Compound bow",
670
+ category: "bow",
671
+ action: {
672
+ kind: "firearm",
673
+ caliber: "arrow",
674
+ rpm: 20,
675
+ modes: [
676
+ "single"
677
+ ],
678
+ magazine: 1,
679
+ reload: 1.5,
680
+ barrel: 1,
681
+ spreadDeg: 0.4,
682
+ bloomDeg: 0.4,
683
+ recoveryDegPerS: 2,
684
+ recoil: [
685
+ 0.3,
686
+ 0.1
687
+ ],
688
+ range: 60,
689
+ noise: 20
690
+ },
691
+ mass: 1.8,
692
+ tags: [
693
+ "silent"
694
+ ]
695
+ },
696
+ {
697
+ id: "crossbow",
698
+ name: "Crossbow",
699
+ category: "crossbow",
700
+ action: {
701
+ kind: "firearm",
702
+ caliber: "crossbow_bolt",
703
+ rpm: 8,
704
+ modes: [
705
+ "single"
706
+ ],
707
+ magazine: 1,
708
+ reload: 4,
709
+ barrel: 1,
710
+ spreadDeg: 0.3,
711
+ bloomDeg: 0.3,
712
+ recoveryDegPerS: 2,
713
+ recoil: [
714
+ 0.5,
715
+ 0.1
716
+ ],
717
+ range: 70,
718
+ noise: 25
719
+ },
720
+ mass: 3,
721
+ tags: [
722
+ "silent"
723
+ ]
724
+ },
725
+ {
726
+ id: "hammer",
727
+ name: "Hammer",
728
+ category: "melee_blunt",
729
+ action: {
730
+ kind: "melee",
731
+ damage: "blunt",
732
+ energy: 60,
733
+ radius: 0.08,
734
+ reach: 0.7,
735
+ rpm: 70,
736
+ noise: 6
737
+ },
738
+ mass: 1
739
+ },
740
+ {
741
+ id: "sledgehammer",
742
+ name: "Sledgehammer",
743
+ category: "melee_blunt",
744
+ action: {
745
+ kind: "melee",
746
+ damage: "blunt",
747
+ energy: 300,
748
+ radius: 0.15,
749
+ reach: 1.1,
750
+ rpm: 30,
751
+ noise: 8
752
+ },
753
+ mass: 5.5,
754
+ tags: [
755
+ "heavy"
756
+ ]
757
+ },
758
+ {
759
+ id: "baseball_bat",
760
+ name: "Baseball bat",
761
+ category: "melee_blunt",
762
+ action: {
763
+ kind: "melee",
764
+ damage: "blunt",
765
+ energy: 150,
766
+ radius: 0.1,
767
+ reach: 1,
768
+ rpm: 60,
769
+ noise: 7
770
+ },
771
+ mass: 0.9
772
+ },
773
+ {
774
+ id: "crowbar",
775
+ name: "Crowbar",
776
+ category: "melee_blunt",
777
+ action: {
778
+ kind: "melee",
779
+ damage: "blunt",
780
+ energy: 120,
781
+ radius: 0.08,
782
+ reach: 0.9,
783
+ rpm: 60,
784
+ noise: 7
785
+ },
786
+ mass: 2,
787
+ tags: [
788
+ "pry"
789
+ ]
790
+ },
791
+ {
792
+ id: "machete",
793
+ name: "Machete",
794
+ category: "melee_blade",
795
+ action: {
796
+ kind: "melee",
797
+ damage: "slash",
798
+ energy: 140,
799
+ radius: 0.06,
800
+ reach: 0.8,
801
+ rpm: 80,
802
+ noise: 6
803
+ },
804
+ mass: 0.8
805
+ },
806
+ {
807
+ id: "axe",
808
+ name: "Axe",
809
+ category: "melee_blade",
810
+ action: {
811
+ kind: "melee",
812
+ damage: "slash",
813
+ energy: 250,
814
+ radius: 0.08,
815
+ reach: 0.9,
816
+ rpm: 45,
817
+ noise: 8
818
+ },
819
+ mass: 1.6
820
+ },
821
+ {
822
+ id: "knife",
823
+ name: "Knife",
824
+ category: "melee_blade",
825
+ action: {
826
+ kind: "melee",
827
+ damage: "slash",
828
+ energy: 40,
829
+ radius: 0.03,
830
+ reach: 0.4,
831
+ rpm: 100,
832
+ noise: 5
833
+ },
834
+ mass: 0.2
835
+ },
836
+ {
837
+ id: "fists",
838
+ name: "Fists",
839
+ category: "melee_blunt",
840
+ action: {
841
+ kind: "melee",
842
+ damage: "blunt",
843
+ energy: 25,
844
+ radius: 0.1,
845
+ reach: 0.6,
846
+ rpm: 120,
847
+ noise: 5
848
+ },
849
+ mass: 0
850
+ },
851
+ {
852
+ id: "lighter",
853
+ name: "Lighter",
854
+ category: "flame",
855
+ action: {
856
+ kind: "flame",
857
+ temperature: 400,
858
+ radius: 0.03,
859
+ range: 0.15,
860
+ fuelPerSecond: 0.02,
861
+ fuel: 60,
862
+ noise: 0
863
+ },
864
+ mass: 0.05,
865
+ tags: [
866
+ "fire"
867
+ ]
868
+ },
869
+ {
870
+ id: "flamethrower",
871
+ name: "Flamethrower",
872
+ category: "flame",
873
+ action: {
874
+ kind: "flame",
875
+ temperature: 900,
876
+ radius: 0.6,
877
+ range: 6,
878
+ fuelPerSecond: 1,
879
+ fuel: 20,
880
+ cone: true,
881
+ noise: 20
882
+ },
883
+ mass: 15,
884
+ tags: [
885
+ "fire"
886
+ ]
887
+ },
888
+ {
889
+ id: "molotov",
890
+ name: "Molotov cocktail",
891
+ category: "throwable",
892
+ action: {
893
+ kind: "throwable",
894
+ energy: 500,
895
+ radius: 1.5,
896
+ fuse: 0,
897
+ throwSpeed: 12,
898
+ fire: {
899
+ temperature: 700,
900
+ radius: 1.5,
901
+ seconds: 12
902
+ },
903
+ noise: 60
904
+ },
905
+ mass: 0.8,
906
+ tags: [
907
+ "fire",
908
+ "improvised"
909
+ ]
910
+ },
911
+ {
912
+ id: "cutting_torch",
913
+ name: "Oxy-fuel cutting torch",
914
+ category: "heat",
915
+ action: {
916
+ kind: "heat",
917
+ temperature: 3e3,
918
+ radius: 0.02,
919
+ range: 0.25,
920
+ fuelPerSecond: 0.05,
921
+ fuel: 30,
922
+ noise: 15
923
+ },
924
+ mass: 4,
925
+ tags: [
926
+ "fire",
927
+ "cutting"
928
+ ]
929
+ },
930
+ {
931
+ id: "blowtorch",
932
+ name: "Blowtorch",
933
+ category: "heat",
934
+ action: {
935
+ kind: "heat",
936
+ temperature: 1300,
937
+ radius: 0.04,
938
+ range: 0.3,
939
+ fuelPerSecond: 0.04,
940
+ fuel: 30,
941
+ noise: 10
942
+ },
943
+ mass: 0.6,
944
+ tags: [
945
+ "fire"
946
+ ]
947
+ },
948
+ {
949
+ id: "frag_grenade",
950
+ name: "Fragmentation grenade",
951
+ category: "throwable",
952
+ action: {
953
+ kind: "throwable",
954
+ energy: 2e5,
955
+ radius: 6,
956
+ fuse: 4,
957
+ throwSpeed: 15,
958
+ noise: 400
959
+ },
960
+ mass: 0.45,
961
+ tags: [
962
+ "explosive"
963
+ ]
964
+ },
965
+ {
966
+ id: "pipe_bomb",
967
+ name: "Pipe bomb",
968
+ category: "throwable",
969
+ action: {
970
+ kind: "throwable",
971
+ energy: 1e5,
972
+ radius: 4,
973
+ fuse: 3,
974
+ throwSpeed: 13,
975
+ noise: 350
976
+ },
977
+ mass: 0.7,
978
+ tags: [
979
+ "explosive",
980
+ "improvised"
981
+ ]
982
+ },
983
+ {
984
+ id: "screwdriver",
985
+ name: "Screwdriver",
986
+ category: "tool",
987
+ action: {
988
+ kind: "tool",
989
+ tool: "screwdriver",
990
+ reach: 0.5,
991
+ noise: 5
992
+ },
993
+ mass: 0.15
994
+ },
995
+ {
996
+ id: "wrench",
997
+ name: "Wrench",
998
+ category: "tool",
999
+ action: {
1000
+ kind: "tool",
1001
+ tool: "wrench",
1002
+ reach: 0.6,
1003
+ noise: 6
1004
+ },
1005
+ mass: 0.5
1006
+ },
1007
+ {
1008
+ id: "pry_bar",
1009
+ name: "Pry bar",
1010
+ category: "tool",
1011
+ action: {
1012
+ kind: "tool",
1013
+ tool: "pry_bar",
1014
+ reach: 0.8,
1015
+ noise: 8
1016
+ },
1017
+ mass: 0.8
1018
+ },
1019
+ {
1020
+ id: "hacksaw",
1021
+ name: "Hacksaw",
1022
+ category: "tool",
1023
+ action: {
1024
+ kind: "tool",
1025
+ tool: "saw",
1026
+ reach: 0.7,
1027
+ noise: 10
1028
+ },
1029
+ mass: 0.6
1030
+ },
1031
+ {
1032
+ id: "utility_knife",
1033
+ name: "Utility knife",
1034
+ category: "tool",
1035
+ action: {
1036
+ kind: "tool",
1037
+ tool: "knife",
1038
+ reach: 0.3,
1039
+ noise: 3
1040
+ },
1041
+ mass: 0.1
1042
+ },
1043
+ {
1044
+ id: "claw_hammer",
1045
+ name: "Claw hammer",
1046
+ category: "tool",
1047
+ action: {
1048
+ kind: "tool",
1049
+ tool: "hammer",
1050
+ reach: 0.5,
1051
+ noise: 8
1052
+ },
1053
+ mass: 0.7
1054
+ },
1055
+ {
1056
+ id: "extinguisher",
1057
+ name: "Fire extinguisher",
1058
+ category: "extinguisher",
1059
+ action: {
1060
+ kind: "extinguisher",
1061
+ range: 4,
1062
+ coolC: 300,
1063
+ charge: 12,
1064
+ noise: 25
1065
+ },
1066
+ mass: 5,
1067
+ tags: [
1068
+ "safety"
1069
+ ]
1070
+ }
1071
+ ];
1072
+
1073
+ // src/locale.ts
1074
+ var modesEn = { single: "single action", semi: "semi-automatic", burst: "burst", auto: "automatic", pump: "pump action", bolt: "bolt action", lever: "lever action", break: "break action" };
1075
+ var categoriesEn = {
1076
+ pistol: "pistol",
1077
+ revolver: "revolver",
1078
+ smg: "submachine gun",
1079
+ rifle: "rifle",
1080
+ carbine: "carbine",
1081
+ sniper: "sniper rifle",
1082
+ shotgun: "shotgun",
1083
+ bow: "bow",
1084
+ crossbow: "crossbow",
1085
+ melee_blunt: "blunt melee",
1086
+ melee_blade: "bladed melee",
1087
+ flame: "flame",
1088
+ heat: "heat",
1089
+ throwable: "throwable",
1090
+ tool: "tool",
1091
+ extinguisher: "extinguisher",
1092
+ hand: "hand"
1093
+ };
1094
+ var locales = {
1095
+ en: {
1096
+ weapons: {
1097
+ hand: "Hand",
1098
+ pistol_9mm: "9 mm service pistol",
1099
+ pistol_45: ".45 ACP pistol",
1100
+ pistol_22: ".22 LR pistol",
1101
+ revolver_357: ".357 Magnum revolver",
1102
+ revolver_38: ".38 Special revolver",
1103
+ smg_9mm: "9 mm submachine gun",
1104
+ carbine_22: ".22 LR carbine",
1105
+ rifle_5_56: "5.56 mm assault rifle",
1106
+ rifle_7_62x39: "7.62\xD739 mm assault rifle",
1107
+ rifle_bolt_308: ".308 bolt-action rifle",
1108
+ sniper_338: ".338 Lapua sniper rifle",
1109
+ anti_materiel_50: ".50 BMG anti-materiel rifle",
1110
+ shotgun_pump_12: "12 gauge pump-action shotgun",
1111
+ shotgun_double_12: "12 gauge double-barrel shotgun",
1112
+ shotgun_semi_12: "12 gauge semi-automatic shotgun",
1113
+ bow_compound: "Compound bow",
1114
+ crossbow: "Crossbow",
1115
+ hammer: "Hammer",
1116
+ sledgehammer: "Sledgehammer",
1117
+ baseball_bat: "Baseball bat",
1118
+ crowbar: "Crowbar",
1119
+ machete: "Machete",
1120
+ axe: "Axe",
1121
+ knife: "Knife",
1122
+ fists: "Fists",
1123
+ lighter: "Lighter",
1124
+ flamethrower: "Flamethrower",
1125
+ molotov: "Molotov cocktail",
1126
+ cutting_torch: "Oxy-fuel cutting torch",
1127
+ blowtorch: "Blowtorch",
1128
+ frag_grenade: "Fragmentation grenade",
1129
+ pipe_bomb: "Pipe bomb",
1130
+ screwdriver: "Screwdriver",
1131
+ wrench: "Wrench",
1132
+ pry_bar: "Pry bar",
1133
+ hacksaw: "Hacksaw",
1134
+ utility_knife: "Utility knife",
1135
+ claw_hammer: "Claw hammer",
1136
+ extinguisher: "Fire extinguisher"
1137
+ },
1138
+ modes: modesEn,
1139
+ categories: categoriesEn
1140
+ },
1141
+ "pt-BR": {
1142
+ weapons: {
1143
+ hand: "m\xE3o",
1144
+ pistol_9mm: "pistola 9 mm",
1145
+ pistol_45: "pistola .45",
1146
+ pistol_22: "pistola .22",
1147
+ revolver_357: "rev\xF3lver .357",
1148
+ revolver_38: "rev\xF3lver .38",
1149
+ smg_9mm: "submetralhadora 9 mm",
1150
+ carbine_22: "carabina .22",
1151
+ rifle_5_56: "fuzil 5,56",
1152
+ rifle_7_62x39: "fuzil 7,62\xD739",
1153
+ rifle_bolt_308: "fuzil de ferrolho .308",
1154
+ sniper_338: "fuzil de precis\xE3o .338",
1155
+ anti_materiel_50: "fuzil antimaterial .50",
1156
+ shotgun_pump_12: "espingarda de repeti\xE7\xE3o calibre 12",
1157
+ shotgun_double_12: "espingarda de dois canos calibre 12",
1158
+ shotgun_semi_12: "espingarda semiautom\xE1tica calibre 12",
1159
+ bow_compound: "arco composto",
1160
+ crossbow: "besta",
1161
+ hammer: "martelo",
1162
+ sledgehammer: "marreta",
1163
+ baseball_bat: "taco de beisebol",
1164
+ crowbar: "p\xE9 de cabra",
1165
+ machete: "fac\xE3o",
1166
+ axe: "machado",
1167
+ knife: "faca",
1168
+ fists: "punhos",
1169
+ lighter: "isqueiro",
1170
+ flamethrower: "lan\xE7a-chamas",
1171
+ molotov: "coquetel molotov",
1172
+ cutting_torch: "ma\xE7arico de corte",
1173
+ blowtorch: "ma\xE7arico",
1174
+ frag_grenade: "granada de fragmenta\xE7\xE3o",
1175
+ pipe_bomb: "bomba caseira",
1176
+ screwdriver: "chave de fenda",
1177
+ wrench: "chave inglesa",
1178
+ pry_bar: "alavanca",
1179
+ hacksaw: "serra de arco",
1180
+ utility_knife: "estilete",
1181
+ claw_hammer: "martelo de unha",
1182
+ extinguisher: "extintor"
1183
+ },
1184
+ modes: { single: "tiro \xFAnico", semi: "semiautom\xE1tico", burst: "rajada", auto: "autom\xE1tico", pump: "repeti\xE7\xE3o", bolt: "ferrolho", lever: "alavanca", break: "basculante" },
1185
+ categories: {
1186
+ pistol: "pistola",
1187
+ revolver: "rev\xF3lver",
1188
+ smg: "submetralhadora",
1189
+ rifle: "fuzil",
1190
+ carbine: "carabina",
1191
+ sniper: "fuzil de precis\xE3o",
1192
+ shotgun: "espingarda",
1193
+ bow: "arco",
1194
+ crossbow: "besta",
1195
+ melee_blunt: "corpo a corpo contundente",
1196
+ melee_blade: "corpo a corpo cortante",
1197
+ flame: "chama",
1198
+ heat: "calor",
1199
+ throwable: "arremess\xE1vel",
1200
+ tool: "ferramenta",
1201
+ extinguisher: "extintor",
1202
+ hand: "m\xE3o"
1203
+ }
1204
+ }
1205
+ };
1206
+ var resolveStrings = (locale) => locales[locale ?? "en"] ?? locales.en;
1207
+
1208
+ // src/rng.ts
1209
+ var createRng = (seed) => {
1210
+ let a = seed >>> 0;
1211
+ return () => {
1212
+ a = a + 1831565813 >>> 0;
1213
+ let t = a;
1214
+ t = Math.imul(t ^ t >>> 15, t | 1);
1215
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
1216
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
1217
+ };
1218
+ };
1219
+ var normalize = (v) => {
1220
+ const l = Math.hypot(v[0], v[1], v[2]);
1221
+ return l > 1e-12 ? [v[0] / l, v[1] / l, v[2] / l] : [0, 0, -1];
1222
+ };
1223
+ var cross = (a, b) => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
1224
+ var sampleCone = (dir, deg, rng) => {
1225
+ if (deg <= 0) return dir;
1226
+ const cosMax = Math.cos(deg * Math.PI / 180);
1227
+ const cosT = 1 - rng() * (1 - cosMax);
1228
+ const sinT = Math.sqrt(Math.max(0, 1 - cosT * cosT));
1229
+ const phi = rng() * Math.PI * 2;
1230
+ const helper = Math.abs(dir[1]) < 0.9 ? [0, 1, 0] : [1, 0, 0];
1231
+ const u = normalize(cross(helper, dir));
1232
+ const v = cross(dir, u);
1233
+ const cx = Math.cos(phi) * sinT;
1234
+ const cy = Math.sin(phi) * sinT;
1235
+ return normalize([
1236
+ u[0] * cx + v[0] * cy + dir[0] * cosT,
1237
+ u[1] * cx + v[1] * cy + dir[1] * cosT,
1238
+ u[2] * cx + v[2] * cy + dir[2] * cosT
1239
+ ]);
1240
+ };
1241
+
1242
+ // src/weapon.ts
1243
+ var EPS = 1e-9;
1244
+ var DEFAULT_THROWABLES = 3;
1245
+ var BLOOM_CAP = 4;
1246
+ var THROW_LIFT = 0.15;
1247
+ var muzzleEnergy = (caliber, barrel = 1) => {
1248
+ const v = caliber.muzzleSpeed * barrel;
1249
+ return 0.5 * (caliber.bulletGrams / 1e3) * v * v;
1250
+ };
1251
+ var result = (status, extra = {}) => ({
1252
+ shots: [],
1253
+ uses: [],
1254
+ status,
1255
+ recoil: [0, 0],
1256
+ noise: 0,
1257
+ ...extra
1258
+ });
1259
+ var WeaponRuntime = class {
1260
+ constructor(init) {
1261
+ __publicField(this, "def");
1262
+ __publicField(this, "caliber");
1263
+ __publicField(this, "reserve");
1264
+ __publicField(this, "mode");
1265
+ __publicField(this, "_ammo");
1266
+ __publicField(this, "_capacity");
1267
+ __publicField(this, "action");
1268
+ __publicField(this, "rng");
1269
+ __publicField(this, "initialReserve");
1270
+ __publicField(this, "clock", 0);
1271
+ /** Time already advanced by the other of update / trigger in the same frame (so calling both does not count `dt` twice). */
1272
+ __publicField(this, "pend", null);
1273
+ __publicField(this, "readyAt", 0);
1274
+ __publicField(this, "latched", false);
1275
+ __publicField(this, "_reloading", false);
1276
+ __publicField(this, "reloadEnd", 0);
1277
+ /** Bloom degrees at `extraClock`. */
1278
+ __publicField(this, "extra", 0);
1279
+ __publicField(this, "extraClock", 0);
1280
+ this.def = init.def;
1281
+ this.caliber = init.caliber;
1282
+ this.action = init.def.action;
1283
+ this.rng = createRng(init.seed);
1284
+ const a = this.action;
1285
+ this.mode = a.kind === "firearm" ? a.modes[0] ?? "single" : "single";
1286
+ switch (a.kind) {
1287
+ case "firearm":
1288
+ this._capacity = a.magazine;
1289
+ break;
1290
+ case "flame":
1291
+ case "heat":
1292
+ this._capacity = a.fuel;
1293
+ break;
1294
+ case "extinguisher":
1295
+ this._capacity = a.charge;
1296
+ break;
1297
+ case "throwable":
1298
+ this._capacity = a.count ?? DEFAULT_THROWABLES;
1299
+ break;
1300
+ default:
1301
+ this._capacity = 0;
1302
+ }
1303
+ this._ammo = this._capacity;
1304
+ this.initialReserve = init.reserve ?? (a.kind === "firearm" ? a.magazine * 3 : 0);
1305
+ this.reserve = this.initialReserve;
1306
+ }
1307
+ get ammo() {
1308
+ return this._ammo;
1309
+ }
1310
+ get capacity() {
1311
+ return this._capacity;
1312
+ }
1313
+ get reloading() {
1314
+ return this._reloading;
1315
+ }
1316
+ get spread() {
1317
+ if (this.action.kind !== "firearm") return 0;
1318
+ return this.action.spreadDeg + this.extraAt(this.clock);
1319
+ }
1320
+ extraAt(t) {
1321
+ if (this.action.kind !== "firearm") return 0;
1322
+ const rec = this.action.recoveryDegPerS ?? 4;
1323
+ return Math.max(0, this.extra - rec * Math.max(0, t - this.extraClock));
1324
+ }
1325
+ // --- time -----------------------------------------------------------------------------------------------------------------------
1326
+ update(dt) {
1327
+ const d = Math.max(0, dt);
1328
+ let eff = d;
1329
+ if (this.pend && this.pend.src === "trigger") {
1330
+ eff = Math.max(0, d - this.pend.amt);
1331
+ this.pend = null;
1332
+ } else {
1333
+ this.pend = { src: "update", amt: d };
1334
+ }
1335
+ this.clock += eff;
1336
+ this.settle(this.clock);
1337
+ }
1338
+ /** Complete the reload steps that finish at or before `t`. */
1339
+ settle(t) {
1340
+ const a = this.action;
1341
+ if (a.kind !== "firearm") return;
1342
+ while (this._reloading && this.reloadEnd <= t + EPS) {
1343
+ if (a.perRound) {
1344
+ if (this.reserve > 0 && this._ammo < this._capacity) {
1345
+ this._ammo += 1;
1346
+ this.reserve -= 1;
1347
+ }
1348
+ if (this._ammo >= this._capacity || this.reserve <= 0) this._reloading = false;
1349
+ else this.reloadEnd += a.reload;
1350
+ } else {
1351
+ const take = Math.min(this._capacity - this._ammo, this.reserve);
1352
+ this._ammo += take;
1353
+ this.reserve -= take;
1354
+ this._reloading = false;
1355
+ }
1356
+ }
1357
+ }
1358
+ // --- commands -------------------------------------------------------------------------------------------------------------------
1359
+ release() {
1360
+ this.latched = false;
1361
+ }
1362
+ reload() {
1363
+ const a = this.action;
1364
+ if (a.kind === "throwable") {
1365
+ if (this._ammo >= this._capacity || this.reserve <= 0) return false;
1366
+ this._ammo += 1;
1367
+ this.reserve -= 1;
1368
+ return true;
1369
+ }
1370
+ if (a.kind !== "firearm" || this._reloading) return false;
1371
+ if (this._ammo >= this._capacity || this.reserve <= 0) return false;
1372
+ this._reloading = true;
1373
+ this.reloadEnd = this.clock + a.reload;
1374
+ return true;
1375
+ }
1376
+ cycleMode() {
1377
+ if (this.action.kind !== "firearm") return this.mode;
1378
+ const modes = this.action.modes;
1379
+ const i = modes.indexOf(this.mode);
1380
+ this.mode = modes[(i + 1) % modes.length] ?? this.mode;
1381
+ return this.mode;
1382
+ }
1383
+ refill() {
1384
+ this._ammo = this._capacity;
1385
+ this.reserve = this.initialReserve;
1386
+ this._reloading = false;
1387
+ this.readyAt = this.clock;
1388
+ this.latched = false;
1389
+ this.extra = 0;
1390
+ }
1391
+ // --- trigger --------------------------------------------------------------------------------------------------------------------
1392
+ trigger(origin, direction, dt, held = false, source) {
1393
+ const d = Math.max(0, dt);
1394
+ let overlap = 0;
1395
+ if (this.pend && this.pend.src === "update") {
1396
+ overlap = Math.min(this.pend.amt, d);
1397
+ this.pend = null;
1398
+ } else {
1399
+ this.pend = { src: "trigger", amt: d };
1400
+ }
1401
+ const start = this.clock - overlap;
1402
+ const end = start + d;
1403
+ this.settle(start);
1404
+ const dir = normalize(direction);
1405
+ let res;
1406
+ const a = this.action;
1407
+ switch (a.kind) {
1408
+ case "firearm":
1409
+ res = this.fireFirearm(a, origin, dir, start, end, held, source);
1410
+ break;
1411
+ case "melee":
1412
+ res = this.fireMelee(a, origin, dir, start, end);
1413
+ break;
1414
+ case "flame":
1415
+ case "heat":
1416
+ res = this.fireFuel(a, origin, dir, d);
1417
+ break;
1418
+ case "extinguisher":
1419
+ res = this.fireExtinguisher(a, origin, dir, d);
1420
+ break;
1421
+ case "throwable":
1422
+ res = this.fireThrowable(a, origin, dir, held);
1423
+ break;
1424
+ case "tool":
1425
+ res = d > 0 ? result("ok", { uses: [{ kind: "tool", tool: a.tool, reach: a.reach, duration: d, origin, direction: dir }], noise: a.noise }) : result("ok");
1426
+ break;
1427
+ case "hand":
1428
+ res = this.oncePerPull(held) ? result("ok", { uses: [{ kind: "hand", reach: a.reach, origin, direction: dir }] }) : result("cooldown");
1429
+ break;
1430
+ }
1431
+ this.clock = Math.max(this.clock, end);
1432
+ this.settle(this.clock);
1433
+ return res;
1434
+ }
1435
+ /** Semi-style gating: a held trigger that already fired does nothing until `release()` or a new pull (`held` false). */
1436
+ oncePerPull(held) {
1437
+ if (!held) this.latched = false;
1438
+ if (this.latched) return false;
1439
+ this.latched = true;
1440
+ return true;
1441
+ }
1442
+ fireFirearm(a, origin, dir, start, end, held, source) {
1443
+ if (this._reloading) {
1444
+ if (a.perRound && this._ammo > 0) this._reloading = false;
1445
+ else return result("reloading");
1446
+ }
1447
+ const auto = this.mode === "auto";
1448
+ if (!auto && !this.oncePerPull(held)) return result("cooldown");
1449
+ if (this._ammo <= 0) return result("empty");
1450
+ const iv = 60 / a.rpm;
1451
+ const t0 = Math.max(start, this.readyAt);
1452
+ if (t0 > end + EPS) return result("cooldown");
1453
+ const res = result("ok");
1454
+ const fire = (t) => {
1455
+ this.fireOne(a, origin, dir, t, res, source);
1456
+ };
1457
+ if (auto) {
1458
+ for (let t = t0, n = 0; this._ammo > 0 && (n === 0 ? t <= end + EPS : t < end - EPS); t += iv, n++) fire(t);
1459
+ } else if (this.mode === "burst") {
1460
+ const count = Math.min(a.burst ?? 3, this._ammo);
1461
+ for (let k = 0; k < count; k++) fire(t0 + k * iv);
1462
+ } else {
1463
+ fire(t0);
1464
+ }
1465
+ return res;
1466
+ }
1467
+ fireOne(a, origin, dir, t, res, source) {
1468
+ const cal = this.caliber;
1469
+ const barrel = a.barrel ?? 1;
1470
+ const speed = cal.muzzleSpeed * barrel;
1471
+ const energy = muzzleEnergy(cal, barrel);
1472
+ const drag = cal.dragPer100m ?? 0.1;
1473
+ const energyAt = (distance) => {
1474
+ const f = Math.pow(1 - drag, Math.max(0, distance) / 100);
1475
+ return energy * f * f;
1476
+ };
1477
+ const bloomNow = this.extraAt(t);
1478
+ const spread = a.spreadDeg + bloomNow;
1479
+ const aim = sampleCone(dir, spread, this.rng);
1480
+ const pellets = cal.pellets ?? 1;
1481
+ const pelletSpread = pellets > 1 ? a.pelletSpreadDeg ?? 3 : 0;
1482
+ for (let p = 0; p < pellets; p++) {
1483
+ const shot = {
1484
+ origin: [origin[0], origin[1], origin[2]],
1485
+ direction: sampleCone(aim, pelletSpread, this.rng),
1486
+ energy,
1487
+ caliber: cal.diameter,
1488
+ caliberId: cal.id,
1489
+ speed,
1490
+ energyAt,
1491
+ pellet: p,
1492
+ weapon: this.def.id
1493
+ };
1494
+ if (source !== void 0) shot.source = source;
1495
+ res.shots.push(shot);
1496
+ }
1497
+ this._ammo -= 1;
1498
+ this.readyAt = t + 60 / a.rpm;
1499
+ this.extra = Math.min(bloomNow + (a.bloomDeg ?? 0), a.spreadDeg * (BLOOM_CAP - 1));
1500
+ this.extraClock = t;
1501
+ res.recoil = [res.recoil[0] + a.recoil[0], res.recoil[1] + (this.rng() * 2 - 1) * a.recoil[1]];
1502
+ res.noise = a.noise;
1503
+ }
1504
+ fireMelee(a, origin, dir, start, end) {
1505
+ const t0 = Math.max(start, this.readyAt);
1506
+ if (t0 > end + EPS) return result("cooldown");
1507
+ this.readyAt = t0 + 60 / a.rpm;
1508
+ const use = { kind: "melee", damage: a.damage, energy: a.energy, radius: a.radius, reach: a.reach, origin, direction: dir };
1509
+ return result("ok", { uses: [use], noise: a.noise });
1510
+ }
1511
+ fireFuel(a, origin, dir, dt) {
1512
+ if (this._ammo <= EPS) return result("no_fuel");
1513
+ if (dt <= 0) return result("ok");
1514
+ const need = a.fuelPerSecond * dt;
1515
+ let duration = dt;
1516
+ if (need > this._ammo) {
1517
+ duration = dt * (this._ammo / need);
1518
+ this._ammo = 0;
1519
+ } else {
1520
+ this._ammo -= need;
1521
+ }
1522
+ const use = a.kind === "flame" ? { kind: "flame", temperature: a.temperature, radius: a.radius, range: a.range, cone: a.cone ?? false, duration, origin, direction: dir } : { kind: "heat", temperature: a.temperature, radius: a.radius, range: a.range, duration, origin, direction: dir };
1523
+ return result("ok", { uses: [use], noise: a.noise });
1524
+ }
1525
+ fireExtinguisher(a, origin, dir, dt) {
1526
+ if (this._ammo <= EPS) return result("no_fuel");
1527
+ if (dt <= 0) return result("ok");
1528
+ const duration = Math.min(dt, this._ammo);
1529
+ this._ammo -= duration;
1530
+ return result("ok", { uses: [{ kind: "extinguish", range: a.range, coolC: a.coolC, duration, origin, direction: dir }], noise: a.noise });
1531
+ }
1532
+ fireThrowable(a, origin, dir, held) {
1533
+ if (!this.oncePerPull(held)) return result("cooldown");
1534
+ if (this._ammo <= 0) return result("empty");
1535
+ this._ammo -= 1;
1536
+ const velocity = [dir[0] * a.throwSpeed, dir[1] * a.throwSpeed + a.throwSpeed * THROW_LIFT, dir[2] * a.throwSpeed];
1537
+ const use = { kind: "throw", energy: a.energy, radius: a.radius, fuse: a.fuse, velocity, origin };
1538
+ if (a.fire) use.fire = { ...a.fire };
1539
+ return result("ok", { uses: [use], noise: a.noise });
1540
+ }
1541
+ };
1542
+
1543
+ // src/arsenal.ts
1544
+ var CALIBERS = calibers_default;
1545
+ var WEAPONS = weapons_default;
1546
+ var DEFAULT_LOADOUT = [
1547
+ "hand",
1548
+ "pistol_9mm",
1549
+ "revolver_357",
1550
+ "shotgun_pump_12",
1551
+ "rifle_5_56",
1552
+ "rifle_bolt_308",
1553
+ "hammer",
1554
+ "axe",
1555
+ "crowbar",
1556
+ "lighter",
1557
+ "flamethrower",
1558
+ "cutting_torch",
1559
+ "molotov",
1560
+ "frag_grenade",
1561
+ "screwdriver",
1562
+ "wrench",
1563
+ "pry_bar",
1564
+ "hacksaw",
1565
+ "extinguisher"
1566
+ ];
1567
+ var createArsenal = (options = {}) => {
1568
+ const calibers = /* @__PURE__ */ new Map();
1569
+ for (const c of [...CALIBERS, ...options.calibers ?? []]) calibers.set(c.id, c);
1570
+ const weapons = /* @__PURE__ */ new Map();
1571
+ for (const w of [...WEAPONS, ...options.weapons ?? []]) weapons.set(w.id, w);
1572
+ const strings = resolveStrings(options.locale);
1573
+ const baseSeed = options.seed ?? 1;
1574
+ let counter = 0;
1575
+ const create = (id, opts = {}) => {
1576
+ const def = weapons.get(id);
1577
+ if (!def) throw new Error(`game-weapons: unknown weapon "${id}"`);
1578
+ let caliber = null;
1579
+ if (def.action.kind === "firearm") {
1580
+ caliber = calibers.get(def.action.caliber) ?? null;
1581
+ if (!caliber) throw new Error(`game-weapons: weapon "${id}" uses unknown calibre "${def.action.caliber}"`);
1582
+ }
1583
+ counter += 1;
1584
+ const seed = opts.seed ?? baseSeed + Math.imul(counter, 2654435761) >>> 0;
1585
+ return new WeaponRuntime({ def, caliber, seed, reserve: opts.reserve });
1586
+ };
1587
+ return {
1588
+ calibers,
1589
+ weapons,
1590
+ create,
1591
+ muzzleEnergy(caliber, barrel = 1) {
1592
+ const c = calibers.get(caliber);
1593
+ if (!c) throw new Error(`game-weapons: unknown calibre "${caliber}"`);
1594
+ return muzzleEnergy(c, barrel);
1595
+ },
1596
+ name(id) {
1597
+ const w = weapons.get(id);
1598
+ if (w) return strings.weapons[id] ?? w.name ?? id;
1599
+ return strings.modes[id] ?? strings.categories[id] ?? calibers.get(id)?.label ?? id;
1600
+ },
1601
+ list(category) {
1602
+ const all = [...weapons.values()];
1603
+ return category ? all.filter((w) => w.category === category) : all;
1604
+ }
1605
+ };
1606
+ };
1607
+ return __toCommonJS(index_exports);
1608
+ })();
1609
+ //# sourceMappingURL=index.global.js.map