@adatechnology/game-weapons 0.0.0-stage → 0.1.1

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/dist/index.js ADDED
@@ -0,0 +1,1624 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
5
+ // src/data/calibers.json
6
+ var calibers_default = [
7
+ {
8
+ id: "22lr",
9
+ label: ".22 LR",
10
+ diameter: 5.7,
11
+ bulletGrams: 2.6,
12
+ muzzleSpeed: 350,
13
+ dragPer100m: 0.15,
14
+ kind: "rimfire"
15
+ },
16
+ {
17
+ id: "9x19",
18
+ label: "9\xD719 mm",
19
+ diameter: 9,
20
+ bulletGrams: 7.5,
21
+ muzzleSpeed: 365,
22
+ dragPer100m: 0.2,
23
+ kind: "fmj"
24
+ },
25
+ {
26
+ id: "38spl",
27
+ label: ".38 Special",
28
+ diameter: 9.1,
29
+ bulletGrams: 10.2,
30
+ muzzleSpeed: 247,
31
+ dragPer100m: 0.2,
32
+ kind: "fmj"
33
+ },
34
+ {
35
+ id: "357mag",
36
+ label: ".357 Magnum",
37
+ diameter: 9.1,
38
+ bulletGrams: 10.2,
39
+ muzzleSpeed: 396,
40
+ dragPer100m: 0.18,
41
+ kind: "hp"
42
+ },
43
+ {
44
+ id: "40sw",
45
+ label: ".40 S&W",
46
+ diameter: 10.2,
47
+ bulletGrams: 11.7,
48
+ muzzleSpeed: 310,
49
+ dragPer100m: 0.2,
50
+ kind: "fmj"
51
+ },
52
+ {
53
+ id: "45acp",
54
+ label: ".45 ACP",
55
+ diameter: 11.5,
56
+ bulletGrams: 14.9,
57
+ muzzleSpeed: 254,
58
+ dragPer100m: 0.2,
59
+ kind: "fmj"
60
+ },
61
+ {
62
+ id: "380acp",
63
+ label: ".380 ACP",
64
+ diameter: 9,
65
+ bulletGrams: 6.2,
66
+ muzzleSpeed: 295,
67
+ dragPer100m: 0.22,
68
+ kind: "fmj"
69
+ },
70
+ {
71
+ id: "5_56x45",
72
+ label: "5.56\xD745 mm",
73
+ diameter: 5.7,
74
+ bulletGrams: 4,
75
+ muzzleSpeed: 935,
76
+ dragPer100m: 0.1,
77
+ kind: "fmj"
78
+ },
79
+ {
80
+ id: "7_62x39",
81
+ label: "7.62\xD739 mm",
82
+ diameter: 7.9,
83
+ bulletGrams: 8,
84
+ muzzleSpeed: 725,
85
+ dragPer100m: 0.1,
86
+ kind: "fmj"
87
+ },
88
+ {
89
+ id: "7_62x51",
90
+ label: "7.62\xD751 mm (.308)",
91
+ diameter: 7.8,
92
+ bulletGrams: 9.7,
93
+ muzzleSpeed: 850,
94
+ dragPer100m: 0.08,
95
+ kind: "fmj"
96
+ },
97
+ {
98
+ id: "338lapua",
99
+ label: ".338 Lapua Magnum",
100
+ diameter: 8.6,
101
+ bulletGrams: 16.2,
102
+ muzzleSpeed: 903,
103
+ dragPer100m: 0.06,
104
+ kind: "fmj"
105
+ },
106
+ {
107
+ id: "50bmg",
108
+ label: ".50 BMG",
109
+ diameter: 12.7,
110
+ bulletGrams: 42,
111
+ muzzleSpeed: 925,
112
+ dragPer100m: 0.05,
113
+ kind: "ap"
114
+ },
115
+ {
116
+ id: "12ga_00buck",
117
+ label: "12 ga 00 buck",
118
+ diameter: 8.4,
119
+ bulletGrams: 3.5,
120
+ muzzleSpeed: 414,
121
+ pellets: 9,
122
+ dragPer100m: 0.45,
123
+ kind: "buck"
124
+ },
125
+ {
126
+ id: "12ga_slug",
127
+ label: "12 ga slug",
128
+ diameter: 18.5,
129
+ bulletGrams: 28,
130
+ muzzleSpeed: 463,
131
+ dragPer100m: 0.3,
132
+ kind: "slug"
133
+ },
134
+ {
135
+ id: "12ga_birdshot",
136
+ label: "12 ga birdshot",
137
+ diameter: 2.4,
138
+ bulletGrams: 0.2,
139
+ muzzleSpeed: 400,
140
+ pellets: 90,
141
+ dragPer100m: 0.6,
142
+ kind: "birdshot"
143
+ },
144
+ {
145
+ id: "20ga_buck",
146
+ label: "20 ga buck",
147
+ diameter: 6.9,
148
+ bulletGrams: 1.3,
149
+ muzzleSpeed: 400,
150
+ pellets: 20,
151
+ dragPer100m: 0.5,
152
+ kind: "buck"
153
+ },
154
+ {
155
+ id: "arrow",
156
+ label: "Arrow (compound bow)",
157
+ diameter: 7,
158
+ bulletGrams: 25,
159
+ muzzleSpeed: 90,
160
+ dragPer100m: 0.12,
161
+ kind: "arrow"
162
+ },
163
+ {
164
+ id: "crossbow_bolt",
165
+ label: "Crossbow bolt",
166
+ diameter: 8,
167
+ bulletGrams: 20,
168
+ muzzleSpeed: 122,
169
+ dragPer100m: 0.12,
170
+ kind: "bolt"
171
+ }
172
+ ];
173
+
174
+ // src/data/weapons.json
175
+ var weapons_default = [
176
+ {
177
+ id: "hand",
178
+ name: "Hand",
179
+ category: "hand",
180
+ action: {
181
+ kind: "hand",
182
+ reach: 2
183
+ },
184
+ mass: 0,
185
+ tags: [
186
+ "grab"
187
+ ]
188
+ },
189
+ {
190
+ id: "kick",
191
+ name: "Kick",
192
+ category: "melee_blunt",
193
+ action: {
194
+ kind: "melee",
195
+ damage: "blunt",
196
+ energy: 250,
197
+ radius: 0.08,
198
+ reach: 1.1,
199
+ rpm: 60,
200
+ noise: 8
201
+ },
202
+ mass: 0
203
+ },
204
+ {
205
+ id: "shove",
206
+ name: "Shove",
207
+ category: "melee_blunt",
208
+ action: {
209
+ kind: "melee",
210
+ damage: "blunt",
211
+ energy: 80,
212
+ radius: 0.1,
213
+ reach: 1.5,
214
+ rpm: 90,
215
+ noise: 5
216
+ },
217
+ mass: 0
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
+ kick: "Kick",
1099
+ shove: "Shove",
1100
+ pistol_9mm: "9 mm service pistol",
1101
+ pistol_45: ".45 ACP pistol",
1102
+ pistol_22: ".22 LR pistol",
1103
+ revolver_357: ".357 Magnum revolver",
1104
+ revolver_38: ".38 Special revolver",
1105
+ smg_9mm: "9 mm submachine gun",
1106
+ carbine_22: ".22 LR carbine",
1107
+ rifle_5_56: "5.56 mm assault rifle",
1108
+ rifle_7_62x39: "7.62\xD739 mm assault rifle",
1109
+ rifle_bolt_308: ".308 bolt-action rifle",
1110
+ sniper_338: ".338 Lapua sniper rifle",
1111
+ anti_materiel_50: ".50 BMG anti-materiel rifle",
1112
+ shotgun_pump_12: "12 gauge pump-action shotgun",
1113
+ shotgun_double_12: "12 gauge double-barrel shotgun",
1114
+ shotgun_semi_12: "12 gauge semi-automatic shotgun",
1115
+ bow_compound: "Compound bow",
1116
+ crossbow: "Crossbow",
1117
+ hammer: "Hammer",
1118
+ sledgehammer: "Sledgehammer",
1119
+ baseball_bat: "Baseball bat",
1120
+ crowbar: "Crowbar",
1121
+ machete: "Machete",
1122
+ axe: "Axe",
1123
+ knife: "Knife",
1124
+ fists: "Fists",
1125
+ lighter: "Lighter",
1126
+ flamethrower: "Flamethrower",
1127
+ molotov: "Molotov cocktail",
1128
+ cutting_torch: "Oxy-fuel cutting torch",
1129
+ blowtorch: "Blowtorch",
1130
+ frag_grenade: "Fragmentation grenade",
1131
+ pipe_bomb: "Pipe bomb",
1132
+ screwdriver: "Screwdriver",
1133
+ wrench: "Wrench",
1134
+ pry_bar: "Pry bar",
1135
+ hacksaw: "Hacksaw",
1136
+ utility_knife: "Utility knife",
1137
+ claw_hammer: "Claw hammer",
1138
+ extinguisher: "Fire extinguisher"
1139
+ },
1140
+ modes: modesEn,
1141
+ categories: categoriesEn
1142
+ },
1143
+ "pt-BR": {
1144
+ weapons: {
1145
+ hand: "m\xE3o",
1146
+ kick: "chute",
1147
+ shove: "empurr\xE3o",
1148
+ pistol_9mm: "pistola 9 mm",
1149
+ pistol_45: "pistola .45",
1150
+ pistol_22: "pistola .22",
1151
+ revolver_357: "rev\xF3lver .357",
1152
+ revolver_38: "rev\xF3lver .38",
1153
+ smg_9mm: "submetralhadora 9 mm",
1154
+ carbine_22: "carabina .22",
1155
+ rifle_5_56: "fuzil 5,56",
1156
+ rifle_7_62x39: "fuzil 7,62\xD739",
1157
+ rifle_bolt_308: "fuzil de ferrolho .308",
1158
+ sniper_338: "fuzil de precis\xE3o .338",
1159
+ anti_materiel_50: "fuzil antimaterial .50",
1160
+ shotgun_pump_12: "espingarda de repeti\xE7\xE3o calibre 12",
1161
+ shotgun_double_12: "espingarda de dois canos calibre 12",
1162
+ shotgun_semi_12: "espingarda semiautom\xE1tica calibre 12",
1163
+ bow_compound: "arco composto",
1164
+ crossbow: "besta",
1165
+ hammer: "martelo",
1166
+ sledgehammer: "marreta",
1167
+ baseball_bat: "taco de beisebol",
1168
+ crowbar: "p\xE9 de cabra",
1169
+ machete: "fac\xE3o",
1170
+ axe: "machado",
1171
+ knife: "faca",
1172
+ fists: "punhos",
1173
+ lighter: "isqueiro",
1174
+ flamethrower: "lan\xE7a-chamas",
1175
+ molotov: "coquetel molotov",
1176
+ cutting_torch: "ma\xE7arico de corte",
1177
+ blowtorch: "ma\xE7arico",
1178
+ frag_grenade: "granada de fragmenta\xE7\xE3o",
1179
+ pipe_bomb: "bomba caseira",
1180
+ screwdriver: "chave de fenda",
1181
+ wrench: "chave inglesa",
1182
+ pry_bar: "alavanca",
1183
+ hacksaw: "serra de arco",
1184
+ utility_knife: "estilete",
1185
+ claw_hammer: "martelo de unha",
1186
+ extinguisher: "extintor"
1187
+ },
1188
+ modes: { single: "tiro \xFAnico", semi: "semiautom\xE1tico", burst: "rajada", auto: "autom\xE1tico", pump: "repeti\xE7\xE3o", bolt: "ferrolho", lever: "alavanca", break: "basculante" },
1189
+ categories: {
1190
+ pistol: "pistola",
1191
+ revolver: "rev\xF3lver",
1192
+ smg: "submetralhadora",
1193
+ rifle: "fuzil",
1194
+ carbine: "carabina",
1195
+ sniper: "fuzil de precis\xE3o",
1196
+ shotgun: "espingarda",
1197
+ bow: "arco",
1198
+ crossbow: "besta",
1199
+ melee_blunt: "corpo a corpo contundente",
1200
+ melee_blade: "corpo a corpo cortante",
1201
+ flame: "chama",
1202
+ heat: "calor",
1203
+ throwable: "arremess\xE1vel",
1204
+ tool: "ferramenta",
1205
+ extinguisher: "extintor",
1206
+ hand: "m\xE3o"
1207
+ }
1208
+ }
1209
+ };
1210
+ var resolveStrings = (locale) => locales[locale ?? "en"] ?? locales.en;
1211
+
1212
+ // src/rng.ts
1213
+ var createRng = (seed) => {
1214
+ let a = seed >>> 0;
1215
+ return () => {
1216
+ a = a + 1831565813 >>> 0;
1217
+ let t = a;
1218
+ t = Math.imul(t ^ t >>> 15, t | 1);
1219
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
1220
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
1221
+ };
1222
+ };
1223
+ var normalize = (v) => {
1224
+ const l = Math.hypot(v[0], v[1], v[2]);
1225
+ return l > 1e-12 ? [v[0] / l, v[1] / l, v[2] / l] : [0, 0, -1];
1226
+ };
1227
+ 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]];
1228
+ var sampleCone = (dir, deg, rng) => {
1229
+ if (deg <= 0) return dir;
1230
+ const cosMax = Math.cos(deg * Math.PI / 180);
1231
+ const cosT = 1 - rng() * (1 - cosMax);
1232
+ const sinT = Math.sqrt(Math.max(0, 1 - cosT * cosT));
1233
+ const phi = rng() * Math.PI * 2;
1234
+ const helper = Math.abs(dir[1]) < 0.9 ? [0, 1, 0] : [1, 0, 0];
1235
+ const u = normalize(cross(helper, dir));
1236
+ const v = cross(dir, u);
1237
+ const cx = Math.cos(phi) * sinT;
1238
+ const cy = Math.sin(phi) * sinT;
1239
+ return normalize([
1240
+ u[0] * cx + v[0] * cy + dir[0] * cosT,
1241
+ u[1] * cx + v[1] * cy + dir[1] * cosT,
1242
+ u[2] * cx + v[2] * cy + dir[2] * cosT
1243
+ ]);
1244
+ };
1245
+
1246
+ // src/weapon.ts
1247
+ var EPS = 1e-9;
1248
+ var DEFAULT_THROWABLES = 3;
1249
+ var BLOOM_CAP = 4;
1250
+ var THROW_LIFT = 0.15;
1251
+ var muzzleEnergy = (caliber, barrel = 1) => {
1252
+ const v = caliber.muzzleSpeed * barrel;
1253
+ return 0.5 * (caliber.bulletGrams / 1e3) * v * v;
1254
+ };
1255
+ var result = (status, extra = {}) => ({
1256
+ shots: [],
1257
+ uses: [],
1258
+ status,
1259
+ recoil: [0, 0],
1260
+ noise: 0,
1261
+ ...extra
1262
+ });
1263
+ var WeaponRuntime = class {
1264
+ constructor(init) {
1265
+ __publicField(this, "def");
1266
+ __publicField(this, "caliber");
1267
+ __publicField(this, "reserve");
1268
+ __publicField(this, "mode");
1269
+ __publicField(this, "_ammo");
1270
+ __publicField(this, "_capacity");
1271
+ __publicField(this, "action");
1272
+ __publicField(this, "rng");
1273
+ __publicField(this, "initialReserve");
1274
+ __publicField(this, "clock", 0);
1275
+ /** Time already advanced by the other of update / trigger in the same frame (so calling both does not count `dt` twice). */
1276
+ __publicField(this, "pend", null);
1277
+ __publicField(this, "readyAt", 0);
1278
+ __publicField(this, "latched", false);
1279
+ __publicField(this, "_reloading", false);
1280
+ __publicField(this, "reloadEnd", 0);
1281
+ /** Bloom degrees at `extraClock`. */
1282
+ __publicField(this, "extra", 0);
1283
+ __publicField(this, "extraClock", 0);
1284
+ this.def = init.def;
1285
+ this.caliber = init.caliber;
1286
+ this.action = init.def.action;
1287
+ this.rng = createRng(init.seed);
1288
+ const a = this.action;
1289
+ this.mode = a.kind === "firearm" ? a.modes[0] ?? "single" : "single";
1290
+ switch (a.kind) {
1291
+ case "firearm":
1292
+ this._capacity = a.magazine;
1293
+ break;
1294
+ case "flame":
1295
+ case "heat":
1296
+ this._capacity = a.fuel;
1297
+ break;
1298
+ case "extinguisher":
1299
+ this._capacity = a.charge;
1300
+ break;
1301
+ case "throwable":
1302
+ this._capacity = a.count ?? DEFAULT_THROWABLES;
1303
+ break;
1304
+ default:
1305
+ this._capacity = 0;
1306
+ }
1307
+ this._ammo = this._capacity;
1308
+ this.initialReserve = init.reserve ?? (a.kind === "firearm" ? a.magazine * 3 : 0);
1309
+ this.reserve = this.initialReserve;
1310
+ }
1311
+ get ammo() {
1312
+ return this._ammo;
1313
+ }
1314
+ get capacity() {
1315
+ return this._capacity;
1316
+ }
1317
+ get reloading() {
1318
+ return this._reloading;
1319
+ }
1320
+ get spread() {
1321
+ if (this.action.kind !== "firearm") return 0;
1322
+ return this.action.spreadDeg + this.extraAt(this.clock);
1323
+ }
1324
+ extraAt(t) {
1325
+ if (this.action.kind !== "firearm") return 0;
1326
+ const rec = this.action.recoveryDegPerS ?? 4;
1327
+ return Math.max(0, this.extra - rec * Math.max(0, t - this.extraClock));
1328
+ }
1329
+ // --- time -----------------------------------------------------------------------------------------------------------------------
1330
+ update(dt) {
1331
+ const d = Math.max(0, dt);
1332
+ let eff = d;
1333
+ if (this.pend && this.pend.src === "trigger") {
1334
+ eff = Math.max(0, d - this.pend.amt);
1335
+ this.pend = null;
1336
+ } else {
1337
+ this.pend = { src: "update", amt: d };
1338
+ }
1339
+ this.clock += eff;
1340
+ this.settle(this.clock);
1341
+ }
1342
+ /** Complete the reload steps that finish at or before `t`. */
1343
+ settle(t) {
1344
+ const a = this.action;
1345
+ if (a.kind !== "firearm") return;
1346
+ while (this._reloading && this.reloadEnd <= t + EPS) {
1347
+ if (a.perRound) {
1348
+ if (this.reserve > 0 && this._ammo < this._capacity) {
1349
+ this._ammo += 1;
1350
+ this.reserve -= 1;
1351
+ }
1352
+ if (this._ammo >= this._capacity || this.reserve <= 0) this._reloading = false;
1353
+ else this.reloadEnd += a.reload;
1354
+ } else {
1355
+ const take = Math.min(this._capacity - this._ammo, this.reserve);
1356
+ this._ammo += take;
1357
+ this.reserve -= take;
1358
+ this._reloading = false;
1359
+ }
1360
+ }
1361
+ }
1362
+ // --- commands -------------------------------------------------------------------------------------------------------------------
1363
+ release() {
1364
+ this.latched = false;
1365
+ }
1366
+ reload() {
1367
+ const a = this.action;
1368
+ if (a.kind === "throwable") {
1369
+ if (this._ammo >= this._capacity || this.reserve <= 0) return false;
1370
+ this._ammo += 1;
1371
+ this.reserve -= 1;
1372
+ return true;
1373
+ }
1374
+ if (a.kind !== "firearm" || this._reloading) return false;
1375
+ if (this._ammo >= this._capacity || this.reserve <= 0) return false;
1376
+ this._reloading = true;
1377
+ this.reloadEnd = this.clock + a.reload;
1378
+ return true;
1379
+ }
1380
+ cycleMode() {
1381
+ if (this.action.kind !== "firearm") return this.mode;
1382
+ const modes = this.action.modes;
1383
+ const i = modes.indexOf(this.mode);
1384
+ this.mode = modes[(i + 1) % modes.length] ?? this.mode;
1385
+ return this.mode;
1386
+ }
1387
+ refill() {
1388
+ this._ammo = this._capacity;
1389
+ this.reserve = this.initialReserve;
1390
+ this._reloading = false;
1391
+ this.readyAt = this.clock;
1392
+ this.latched = false;
1393
+ this.extra = 0;
1394
+ }
1395
+ // --- trigger --------------------------------------------------------------------------------------------------------------------
1396
+ trigger(origin, direction, dt, held = false, source) {
1397
+ const d = Math.max(0, dt);
1398
+ let overlap = 0;
1399
+ if (this.pend && this.pend.src === "update") {
1400
+ overlap = Math.min(this.pend.amt, d);
1401
+ this.pend = null;
1402
+ } else {
1403
+ this.pend = { src: "trigger", amt: d };
1404
+ }
1405
+ const start = this.clock - overlap;
1406
+ const end = start + d;
1407
+ this.settle(start);
1408
+ const dir = normalize(direction);
1409
+ let res;
1410
+ const a = this.action;
1411
+ switch (a.kind) {
1412
+ case "firearm":
1413
+ res = this.fireFirearm(a, origin, dir, start, end, held, source);
1414
+ break;
1415
+ case "melee":
1416
+ res = this.fireMelee(a, origin, dir, start, end);
1417
+ break;
1418
+ case "flame":
1419
+ case "heat":
1420
+ res = this.fireFuel(a, origin, dir, d);
1421
+ break;
1422
+ case "extinguisher":
1423
+ res = this.fireExtinguisher(a, origin, dir, d);
1424
+ break;
1425
+ case "throwable":
1426
+ res = this.fireThrowable(a, origin, dir, held);
1427
+ break;
1428
+ case "tool":
1429
+ res = d > 0 ? result("ok", { uses: [{ kind: "tool", tool: a.tool, reach: a.reach, duration: d, origin, direction: dir }], noise: a.noise }) : result("ok");
1430
+ break;
1431
+ case "hand":
1432
+ res = this.oncePerPull(held) ? result("ok", { uses: [{ kind: "hand", reach: a.reach, origin, direction: dir }] }) : result("cooldown");
1433
+ break;
1434
+ }
1435
+ this.clock = Math.max(this.clock, end);
1436
+ this.settle(this.clock);
1437
+ return res;
1438
+ }
1439
+ /** Semi-style gating: a held trigger that already fired does nothing until `release()` or a new pull (`held` false). */
1440
+ oncePerPull(held) {
1441
+ if (!held) this.latched = false;
1442
+ if (this.latched) return false;
1443
+ this.latched = true;
1444
+ return true;
1445
+ }
1446
+ fireFirearm(a, origin, dir, start, end, held, source) {
1447
+ if (this._reloading) {
1448
+ if (a.perRound && this._ammo > 0) this._reloading = false;
1449
+ else return result("reloading");
1450
+ }
1451
+ const auto = this.mode === "auto";
1452
+ if (!auto && !this.oncePerPull(held)) return result("cooldown");
1453
+ if (this._ammo <= 0) return result("empty");
1454
+ const iv = 60 / a.rpm;
1455
+ const t0 = Math.max(start, this.readyAt);
1456
+ if (t0 > end + EPS) return result("cooldown");
1457
+ const res = result("ok");
1458
+ const fire = (t) => {
1459
+ this.fireOne(a, origin, dir, t, res, source);
1460
+ };
1461
+ if (auto) {
1462
+ for (let t = t0, n = 0; this._ammo > 0 && (n === 0 ? t <= end + EPS : t < end - EPS); t += iv, n++) fire(t);
1463
+ } else if (this.mode === "burst") {
1464
+ const count = Math.min(a.burst ?? 3, this._ammo);
1465
+ for (let k = 0; k < count; k++) fire(t0 + k * iv);
1466
+ } else {
1467
+ fire(t0);
1468
+ }
1469
+ return res;
1470
+ }
1471
+ fireOne(a, origin, dir, t, res, source) {
1472
+ const cal = this.caliber;
1473
+ const barrel = a.barrel ?? 1;
1474
+ const speed = cal.muzzleSpeed * barrel;
1475
+ const energy = muzzleEnergy(cal, barrel);
1476
+ const drag = cal.dragPer100m ?? 0.1;
1477
+ const energyAt = (distance) => {
1478
+ const f = Math.pow(1 - drag, Math.max(0, distance) / 100);
1479
+ return energy * f * f;
1480
+ };
1481
+ const bloomNow = this.extraAt(t);
1482
+ const spread = a.spreadDeg + bloomNow;
1483
+ const aim = sampleCone(dir, spread, this.rng);
1484
+ const pellets = cal.pellets ?? 1;
1485
+ const pelletSpread = pellets > 1 ? a.pelletSpreadDeg ?? 3 : 0;
1486
+ for (let p = 0; p < pellets; p++) {
1487
+ const shot = {
1488
+ origin: [origin[0], origin[1], origin[2]],
1489
+ direction: sampleCone(aim, pelletSpread, this.rng),
1490
+ energy,
1491
+ caliber: cal.diameter,
1492
+ caliberId: cal.id,
1493
+ speed,
1494
+ energyAt,
1495
+ pellet: p,
1496
+ weapon: this.def.id
1497
+ };
1498
+ if (source !== void 0) shot.source = source;
1499
+ res.shots.push(shot);
1500
+ }
1501
+ this._ammo -= 1;
1502
+ this.readyAt = t + 60 / a.rpm;
1503
+ this.extra = Math.min(bloomNow + (a.bloomDeg ?? 0), a.spreadDeg * (BLOOM_CAP - 1));
1504
+ this.extraClock = t;
1505
+ res.recoil = [res.recoil[0] + a.recoil[0], res.recoil[1] + (this.rng() * 2 - 1) * a.recoil[1]];
1506
+ res.noise = a.noise;
1507
+ }
1508
+ fireMelee(a, origin, dir, start, end) {
1509
+ const t0 = Math.max(start, this.readyAt);
1510
+ if (t0 > end + EPS) return result("cooldown");
1511
+ this.readyAt = t0 + 60 / a.rpm;
1512
+ const use = { kind: "melee", damage: a.damage, energy: a.energy, radius: a.radius, reach: a.reach, origin, direction: dir };
1513
+ return result("ok", { uses: [use], noise: a.noise });
1514
+ }
1515
+ fireFuel(a, origin, dir, dt) {
1516
+ if (this._ammo <= EPS) return result("no_fuel");
1517
+ if (dt <= 0) return result("ok");
1518
+ const need = a.fuelPerSecond * dt;
1519
+ let duration = dt;
1520
+ if (need > this._ammo) {
1521
+ duration = dt * (this._ammo / need);
1522
+ this._ammo = 0;
1523
+ } else {
1524
+ this._ammo -= need;
1525
+ }
1526
+ 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 };
1527
+ return result("ok", { uses: [use], noise: a.noise });
1528
+ }
1529
+ fireExtinguisher(a, origin, dir, dt) {
1530
+ if (this._ammo <= EPS) return result("no_fuel");
1531
+ if (dt <= 0) return result("ok");
1532
+ const duration = Math.min(dt, this._ammo);
1533
+ this._ammo -= duration;
1534
+ return result("ok", { uses: [{ kind: "extinguish", range: a.range, coolC: a.coolC, duration, origin, direction: dir }], noise: a.noise });
1535
+ }
1536
+ fireThrowable(a, origin, dir, held) {
1537
+ if (!this.oncePerPull(held)) return result("cooldown");
1538
+ if (this._ammo <= 0) return result("empty");
1539
+ this._ammo -= 1;
1540
+ const velocity = [dir[0] * a.throwSpeed, dir[1] * a.throwSpeed + a.throwSpeed * THROW_LIFT, dir[2] * a.throwSpeed];
1541
+ const use = { kind: "throw", energy: a.energy, radius: a.radius, fuse: a.fuse, velocity, origin };
1542
+ if (a.fire) use.fire = { ...a.fire };
1543
+ return result("ok", { uses: [use], noise: a.noise });
1544
+ }
1545
+ };
1546
+
1547
+ // src/arsenal.ts
1548
+ var CALIBERS = calibers_default;
1549
+ var WEAPONS = weapons_default;
1550
+ var DEFAULT_LOADOUT = [
1551
+ "hand",
1552
+ "kick",
1553
+ "shove",
1554
+ "pistol_9mm",
1555
+ "revolver_357",
1556
+ "shotgun_pump_12",
1557
+ "rifle_5_56",
1558
+ "rifle_bolt_308",
1559
+ "hammer",
1560
+ "axe",
1561
+ "machete",
1562
+ "utility_knife",
1563
+ "crowbar",
1564
+ "lighter",
1565
+ "flamethrower",
1566
+ "cutting_torch",
1567
+ "molotov",
1568
+ "frag_grenade",
1569
+ "screwdriver",
1570
+ "wrench",
1571
+ "pry_bar",
1572
+ "hacksaw",
1573
+ "extinguisher"
1574
+ ];
1575
+ var createArsenal = (options = {}) => {
1576
+ const calibers = /* @__PURE__ */ new Map();
1577
+ for (const c of [...CALIBERS, ...options.calibers ?? []]) calibers.set(c.id, c);
1578
+ const weapons = /* @__PURE__ */ new Map();
1579
+ for (const w of [...WEAPONS, ...options.weapons ?? []]) weapons.set(w.id, w);
1580
+ const strings = resolveStrings(options.locale);
1581
+ const baseSeed = options.seed ?? 1;
1582
+ let counter = 0;
1583
+ const create = (id, opts = {}) => {
1584
+ const def = weapons.get(id);
1585
+ if (!def) throw new Error(`game-weapons: unknown weapon "${id}"`);
1586
+ let caliber = null;
1587
+ if (def.action.kind === "firearm") {
1588
+ caliber = calibers.get(def.action.caliber) ?? null;
1589
+ if (!caliber) throw new Error(`game-weapons: weapon "${id}" uses unknown calibre "${def.action.caliber}"`);
1590
+ }
1591
+ counter += 1;
1592
+ const seed = opts.seed ?? baseSeed + Math.imul(counter, 2654435761) >>> 0;
1593
+ return new WeaponRuntime({ def, caliber, seed, reserve: opts.reserve });
1594
+ };
1595
+ return {
1596
+ calibers,
1597
+ weapons,
1598
+ create,
1599
+ muzzleEnergy(caliber, barrel = 1) {
1600
+ const c = calibers.get(caliber);
1601
+ if (!c) throw new Error(`game-weapons: unknown calibre "${caliber}"`);
1602
+ return muzzleEnergy(c, barrel);
1603
+ },
1604
+ name(id) {
1605
+ const w = weapons.get(id);
1606
+ if (w) return strings.weapons[id] ?? w.name ?? id;
1607
+ return strings.modes[id] ?? strings.categories[id] ?? calibers.get(id)?.label ?? id;
1608
+ },
1609
+ list(category) {
1610
+ const all = [...weapons.values()];
1611
+ return category ? all.filter((w) => w.category === category) : all;
1612
+ }
1613
+ };
1614
+ };
1615
+ export {
1616
+ CALIBERS,
1617
+ DEFAULT_LOADOUT,
1618
+ WEAPONS,
1619
+ createArsenal,
1620
+ locales,
1621
+ muzzleEnergy,
1622
+ resolveStrings
1623
+ };
1624
+ //# sourceMappingURL=index.js.map