@adatechnology/game-test-room 0.28.2 → 0.29.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/README.md +2 -1
- package/dist/index.d.ts +18 -2
- package/dist/index.global.js +2455 -305
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +397 -83
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
package/dist/index.global.js
CHANGED
|
@@ -11226,7 +11226,8 @@ var GameTestRoom = (() => {
|
|
|
11226
11226
|
var EVENT_BUDGET = { particles: 400, debris: 40, blastLights: 4, fireLights: 2 };
|
|
11227
11227
|
var explosion_aliases_default = {
|
|
11228
11228
|
carl_gustaf_84mm: "at4_84mm",
|
|
11229
|
-
vog_25: "m79_40mm"
|
|
11229
|
+
vog_25: "m79_40mm",
|
|
11230
|
+
semtex: "c4"
|
|
11230
11231
|
};
|
|
11231
11232
|
var explosions_default = {
|
|
11232
11233
|
m67: {
|
|
@@ -26417,6 +26418,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
26417
26418
|
kick: "kick",
|
|
26418
26419
|
shove: "shove",
|
|
26419
26420
|
knife: "blade",
|
|
26421
|
+
kabar: "blade",
|
|
26422
|
+
katana: "blade",
|
|
26423
|
+
brass_knuckles: "punch",
|
|
26420
26424
|
machete: "blade",
|
|
26421
26425
|
utility_knife: "blade",
|
|
26422
26426
|
axe: "chop",
|
|
@@ -27468,6 +27472,60 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
27468
27472
|
sources: [
|
|
27469
27473
|
"Estimated from muzzle energy, bullet construction and the published anchors of this file (see _notes); refine with a datasheet."
|
|
27470
27474
|
]
|
|
27475
|
+
},
|
|
27476
|
+
{
|
|
27477
|
+
id: "7_62x25:fmj",
|
|
27478
|
+
caliber: "7_62x25",
|
|
27479
|
+
kind: "fmj",
|
|
27480
|
+
label: "7.62x25 Tokarev FMJ",
|
|
27481
|
+
core: "lead",
|
|
27482
|
+
jacket: "steel",
|
|
27483
|
+
penetration: {
|
|
27484
|
+
steel: 3.5,
|
|
27485
|
+
concrete: 30,
|
|
27486
|
+
brick: 60,
|
|
27487
|
+
wood: 100
|
|
27488
|
+
},
|
|
27489
|
+
basis: "estimated",
|
|
27490
|
+
sources: [
|
|
27491
|
+
"Estimated from muzzle energy, bullet construction and the published anchors of this file (see _notes); refine with a datasheet."
|
|
27492
|
+
]
|
|
27493
|
+
},
|
|
27494
|
+
{
|
|
27495
|
+
id: "7_92x57:fmj",
|
|
27496
|
+
caliber: "7_92x57",
|
|
27497
|
+
kind: "fmj",
|
|
27498
|
+
label: "7.92x57 s.S. ball",
|
|
27499
|
+
core: "lead",
|
|
27500
|
+
jacket: "gilding_metal",
|
|
27501
|
+
penetration: {
|
|
27502
|
+
steel: 5.5,
|
|
27503
|
+
concrete: 125,
|
|
27504
|
+
brick: 250,
|
|
27505
|
+
wood: 330
|
|
27506
|
+
},
|
|
27507
|
+
basis: "estimated",
|
|
27508
|
+
sources: [
|
|
27509
|
+
"Estimated from muzzle energy, bullet construction and the published anchors of this file (see _notes); refine with a datasheet."
|
|
27510
|
+
]
|
|
27511
|
+
},
|
|
27512
|
+
{
|
|
27513
|
+
id: "9x39:fmj",
|
|
27514
|
+
caliber: "9x39",
|
|
27515
|
+
kind: "fmj",
|
|
27516
|
+
label: "9x39 SP-5",
|
|
27517
|
+
core: "lead",
|
|
27518
|
+
jacket: "gilding_metal",
|
|
27519
|
+
penetration: {
|
|
27520
|
+
steel: 3,
|
|
27521
|
+
concrete: 30,
|
|
27522
|
+
brick: 70,
|
|
27523
|
+
wood: 130
|
|
27524
|
+
},
|
|
27525
|
+
basis: "estimated",
|
|
27526
|
+
sources: [
|
|
27527
|
+
"Estimated from muzzle energy, bullet construction and the published anchors of this file (see _notes); refine with a datasheet."
|
|
27528
|
+
]
|
|
27471
27529
|
}
|
|
27472
27530
|
]
|
|
27473
27531
|
};
|
|
@@ -30140,6 +30198,72 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
30140
30198
|
sources: [
|
|
30141
30199
|
"sdk"
|
|
30142
30200
|
]
|
|
30201
|
+
},
|
|
30202
|
+
{
|
|
30203
|
+
id: "7_62x25",
|
|
30204
|
+
label: "7.62\xD725 mm Tokarev",
|
|
30205
|
+
diameter: 7.85,
|
|
30206
|
+
bulletGrams: 5.5,
|
|
30207
|
+
muzzleSpeed: 488,
|
|
30208
|
+
dragPer100m: 0.12,
|
|
30209
|
+
kind: "fmj",
|
|
30210
|
+
noise: 300,
|
|
30211
|
+
caseType: "pistol",
|
|
30212
|
+
rim: "rimless",
|
|
30213
|
+
cartridge: {
|
|
30214
|
+
caseDiameter: 9.95,
|
|
30215
|
+
overallLength: 35.2,
|
|
30216
|
+
caseLength: 25,
|
|
30217
|
+
projectileDiameter: 7.85
|
|
30218
|
+
},
|
|
30219
|
+
sources: [
|
|
30220
|
+
"reference",
|
|
30221
|
+
"derived"
|
|
30222
|
+
]
|
|
30223
|
+
},
|
|
30224
|
+
{
|
|
30225
|
+
id: "7_92x57",
|
|
30226
|
+
label: "7.92\xD757 mm Mauser",
|
|
30227
|
+
diameter: 8.22,
|
|
30228
|
+
bulletGrams: 11.7,
|
|
30229
|
+
muzzleSpeed: 760,
|
|
30230
|
+
dragPer100m: 0.08,
|
|
30231
|
+
kind: "fmj",
|
|
30232
|
+
noise: 420,
|
|
30233
|
+
caseType: "rifle",
|
|
30234
|
+
rim: "rimless",
|
|
30235
|
+
cartridge: {
|
|
30236
|
+
caseDiameter: 11.95,
|
|
30237
|
+
overallLength: 82,
|
|
30238
|
+
caseLength: 57,
|
|
30239
|
+
projectileDiameter: 8.22
|
|
30240
|
+
},
|
|
30241
|
+
sources: [
|
|
30242
|
+
"reference",
|
|
30243
|
+
"derived"
|
|
30244
|
+
]
|
|
30245
|
+
},
|
|
30246
|
+
{
|
|
30247
|
+
id: "9x39",
|
|
30248
|
+
label: "9\xD739 mm SP-5",
|
|
30249
|
+
diameter: 9.27,
|
|
30250
|
+
bulletGrams: 16.1,
|
|
30251
|
+
muzzleSpeed: 290,
|
|
30252
|
+
dragPer100m: 0.2,
|
|
30253
|
+
kind: "fmj",
|
|
30254
|
+
noise: 300,
|
|
30255
|
+
caseType: "rifle",
|
|
30256
|
+
rim: "rimless",
|
|
30257
|
+
cartridge: {
|
|
30258
|
+
caseDiameter: 11.33,
|
|
30259
|
+
overallLength: 56,
|
|
30260
|
+
caseLength: 38.7,
|
|
30261
|
+
projectileDiameter: 9.27
|
|
30262
|
+
},
|
|
30263
|
+
sources: [
|
|
30264
|
+
"reference",
|
|
30265
|
+
"derived"
|
|
30266
|
+
]
|
|
30143
30267
|
}
|
|
30144
30268
|
];
|
|
30145
30269
|
var explosives_default = [
|
|
@@ -30594,6 +30718,59 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
30594
30718
|
"lab",
|
|
30595
30719
|
"derived"
|
|
30596
30720
|
]
|
|
30721
|
+
},
|
|
30722
|
+
{
|
|
30723
|
+
id: "semtex",
|
|
30724
|
+
name: "Semtex charge",
|
|
30725
|
+
kind: "blast",
|
|
30726
|
+
lethalRadius: 6,
|
|
30727
|
+
injuryRadius: 18,
|
|
30728
|
+
energy: 377400,
|
|
30729
|
+
tnt: 0.83,
|
|
30730
|
+
destructionLevel: 3,
|
|
30731
|
+
noise: 700,
|
|
30732
|
+
fuseLength: 0.23,
|
|
30733
|
+
burnRate: 131,
|
|
30734
|
+
burnTolerance: 0.1,
|
|
30735
|
+
triggers: [
|
|
30736
|
+
"remote",
|
|
30737
|
+
"timer"
|
|
30738
|
+
],
|
|
30739
|
+
mass: 0.5,
|
|
30740
|
+
sources: [
|
|
30741
|
+
"lab",
|
|
30742
|
+
"reference",
|
|
30743
|
+
"derived"
|
|
30744
|
+
]
|
|
30745
|
+
},
|
|
30746
|
+
{
|
|
30747
|
+
id: "smoke_grenade",
|
|
30748
|
+
name: "M18 colored smoke grenade",
|
|
30749
|
+
kind: "smoke",
|
|
30750
|
+
lethalRadius: 0,
|
|
30751
|
+
injuryRadius: 0,
|
|
30752
|
+
energy: 0,
|
|
30753
|
+
destructionLevel: 0,
|
|
30754
|
+
noise: 30,
|
|
30755
|
+
fuseRange: [
|
|
30756
|
+
1,
|
|
30757
|
+
2.3
|
|
30758
|
+
],
|
|
30759
|
+
smoke: {
|
|
30760
|
+
color: 4177738,
|
|
30761
|
+
seconds: [
|
|
30762
|
+
50,
|
|
30763
|
+
90
|
|
30764
|
+
]
|
|
30765
|
+
},
|
|
30766
|
+
triggers: [
|
|
30767
|
+
"timer"
|
|
30768
|
+
],
|
|
30769
|
+
mass: 0.54,
|
|
30770
|
+
sources: [
|
|
30771
|
+
"reference",
|
|
30772
|
+
"derived"
|
|
30773
|
+
]
|
|
30597
30774
|
}
|
|
30598
30775
|
];
|
|
30599
30776
|
var explosive_weapons_default = [
|
|
@@ -30695,6 +30872,54 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
30695
30872
|
"lab",
|
|
30696
30873
|
"reference"
|
|
30697
30874
|
]
|
|
30875
|
+
},
|
|
30876
|
+
{
|
|
30877
|
+
id: "semtex",
|
|
30878
|
+
name: "Semtex charge",
|
|
30879
|
+
category: "throwable",
|
|
30880
|
+
action: {
|
|
30881
|
+
kind: "throwable",
|
|
30882
|
+
explosive: "semtex",
|
|
30883
|
+
energy: 0,
|
|
30884
|
+
radius: 0,
|
|
30885
|
+
fuse: 0,
|
|
30886
|
+
throwSpeed: 0,
|
|
30887
|
+
noise: 0
|
|
30888
|
+
},
|
|
30889
|
+
mass: 0.5,
|
|
30890
|
+
tags: [
|
|
30891
|
+
"explosive",
|
|
30892
|
+
"placed"
|
|
30893
|
+
],
|
|
30894
|
+
archetype: "frag_grenade",
|
|
30895
|
+
sources: [
|
|
30896
|
+
"reference",
|
|
30897
|
+
"derived"
|
|
30898
|
+
]
|
|
30899
|
+
},
|
|
30900
|
+
{
|
|
30901
|
+
id: "smoke_grenade",
|
|
30902
|
+
name: "M18 colored smoke grenade",
|
|
30903
|
+
category: "throwable",
|
|
30904
|
+
action: {
|
|
30905
|
+
kind: "throwable",
|
|
30906
|
+
explosive: "smoke_grenade",
|
|
30907
|
+
energy: 0,
|
|
30908
|
+
radius: 0,
|
|
30909
|
+
fuse: 0,
|
|
30910
|
+
throwSpeed: 15,
|
|
30911
|
+
noise: 0
|
|
30912
|
+
},
|
|
30913
|
+
mass: 0.54,
|
|
30914
|
+
tags: [
|
|
30915
|
+
"explosive",
|
|
30916
|
+
"smoke"
|
|
30917
|
+
],
|
|
30918
|
+
archetype: "frag_grenade",
|
|
30919
|
+
sources: [
|
|
30920
|
+
"reference",
|
|
30921
|
+
"derived"
|
|
30922
|
+
]
|
|
30698
30923
|
}
|
|
30699
30924
|
];
|
|
30700
30925
|
var firearms_default = [
|
|
@@ -37758,8 +37983,1509 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37758
37983
|
barrel: 0.59,
|
|
37759
37984
|
emptyMass: 4.8
|
|
37760
37985
|
},
|
|
37761
|
-
archetype: "rifle_7_62x39",
|
|
37762
|
-
variantOf: "ak_47",
|
|
37986
|
+
archetype: "rifle_7_62x39",
|
|
37987
|
+
variantOf: "ak_47",
|
|
37988
|
+
sources: [
|
|
37989
|
+
"reference",
|
|
37990
|
+
"derived",
|
|
37991
|
+
"sdk"
|
|
37992
|
+
],
|
|
37993
|
+
mounts: [
|
|
37994
|
+
{
|
|
37995
|
+
kind: "muzzle",
|
|
37996
|
+
interfaces: [
|
|
37997
|
+
"thread_14x1lh"
|
|
37998
|
+
],
|
|
37999
|
+
sources: [
|
|
38000
|
+
"derived"
|
|
38001
|
+
]
|
|
38002
|
+
},
|
|
38003
|
+
{
|
|
38004
|
+
kind: "rail_bottom",
|
|
38005
|
+
interfaces: [
|
|
38006
|
+
"bipod_stud"
|
|
38007
|
+
],
|
|
38008
|
+
sources: [
|
|
38009
|
+
"gallery"
|
|
38010
|
+
]
|
|
38011
|
+
},
|
|
38012
|
+
{
|
|
38013
|
+
kind: "magazine",
|
|
38014
|
+
interfaces: [
|
|
38015
|
+
"mag_curved"
|
|
38016
|
+
],
|
|
38017
|
+
sources: [
|
|
38018
|
+
"gallery"
|
|
38019
|
+
]
|
|
38020
|
+
},
|
|
38021
|
+
{
|
|
38022
|
+
kind: "sling",
|
|
38023
|
+
interfaces: [
|
|
38024
|
+
"swivel"
|
|
38025
|
+
],
|
|
38026
|
+
sources: [
|
|
38027
|
+
"derived"
|
|
38028
|
+
]
|
|
38029
|
+
}
|
|
38030
|
+
],
|
|
38031
|
+
fitted: [
|
|
38032
|
+
{
|
|
38033
|
+
id: "bipod",
|
|
38034
|
+
mount: "rail_bottom"
|
|
38035
|
+
}
|
|
38036
|
+
]
|
|
38037
|
+
},
|
|
38038
|
+
{
|
|
38039
|
+
id: "sig_mpx",
|
|
38040
|
+
name: "SIG MPX",
|
|
38041
|
+
category: "smg",
|
|
38042
|
+
action: {
|
|
38043
|
+
kind: "firearm",
|
|
38044
|
+
caliber: "9x19",
|
|
38045
|
+
rpm: 850,
|
|
38046
|
+
modes: [
|
|
38047
|
+
"auto",
|
|
38048
|
+
"semi"
|
|
38049
|
+
],
|
|
38050
|
+
magazine: 30,
|
|
38051
|
+
magazineOptions: [
|
|
38052
|
+
20,
|
|
38053
|
+
35
|
|
38054
|
+
],
|
|
38055
|
+
reload: 2.6,
|
|
38056
|
+
spreadDeg: 1.5,
|
|
38057
|
+
bloomDeg: 0.35,
|
|
38058
|
+
recoveryDegPerS: 6,
|
|
38059
|
+
recoil: [
|
|
38060
|
+
0.72,
|
|
38061
|
+
0.4
|
|
38062
|
+
],
|
|
38063
|
+
range: 80,
|
|
38064
|
+
family: "magazine",
|
|
38065
|
+
timings: {
|
|
38066
|
+
draw: 0.35,
|
|
38067
|
+
reload: 2.6,
|
|
38068
|
+
clear: 1.2
|
|
38069
|
+
}
|
|
38070
|
+
},
|
|
38071
|
+
mass: 2.7,
|
|
38072
|
+
dimensions: {
|
|
38073
|
+
length: 0.61,
|
|
38074
|
+
barrel: 0.203,
|
|
38075
|
+
emptyMass: 2.7,
|
|
38076
|
+
lengthCollapsed: 0.425
|
|
38077
|
+
},
|
|
38078
|
+
archetype: "smg_9mm",
|
|
38079
|
+
sources: [
|
|
38080
|
+
"reference",
|
|
38081
|
+
"derived",
|
|
38082
|
+
"sdk"
|
|
38083
|
+
],
|
|
38084
|
+
mounts: [
|
|
38085
|
+
{
|
|
38086
|
+
kind: "rail_top",
|
|
38087
|
+
interfaces: [
|
|
38088
|
+
"picatinny"
|
|
38089
|
+
],
|
|
38090
|
+
sources: [
|
|
38091
|
+
"gallery"
|
|
38092
|
+
]
|
|
38093
|
+
},
|
|
38094
|
+
{
|
|
38095
|
+
kind: "rail_left",
|
|
38096
|
+
interfaces: [
|
|
38097
|
+
"picatinny"
|
|
38098
|
+
],
|
|
38099
|
+
sources: [
|
|
38100
|
+
"gallery"
|
|
38101
|
+
]
|
|
38102
|
+
},
|
|
38103
|
+
{
|
|
38104
|
+
kind: "rail_right",
|
|
38105
|
+
interfaces: [
|
|
38106
|
+
"picatinny"
|
|
38107
|
+
],
|
|
38108
|
+
sources: [
|
|
38109
|
+
"gallery"
|
|
38110
|
+
]
|
|
38111
|
+
},
|
|
38112
|
+
{
|
|
38113
|
+
kind: "rail_bottom",
|
|
38114
|
+
interfaces: [
|
|
38115
|
+
"picatinny"
|
|
38116
|
+
],
|
|
38117
|
+
sources: [
|
|
38118
|
+
"gallery"
|
|
38119
|
+
]
|
|
38120
|
+
},
|
|
38121
|
+
{
|
|
38122
|
+
kind: "magazine",
|
|
38123
|
+
interfaces: [
|
|
38124
|
+
"mag_box"
|
|
38125
|
+
],
|
|
38126
|
+
sources: [
|
|
38127
|
+
"gallery"
|
|
38128
|
+
]
|
|
38129
|
+
},
|
|
38130
|
+
{
|
|
38131
|
+
kind: "sling",
|
|
38132
|
+
interfaces: [
|
|
38133
|
+
"swivel"
|
|
38134
|
+
],
|
|
38135
|
+
sources: [
|
|
38136
|
+
"derived"
|
|
38137
|
+
]
|
|
38138
|
+
}
|
|
38139
|
+
],
|
|
38140
|
+
fitted: [],
|
|
38141
|
+
stock: {
|
|
38142
|
+
kind: "retract"
|
|
38143
|
+
}
|
|
38144
|
+
},
|
|
38145
|
+
{
|
|
38146
|
+
id: "mg3",
|
|
38147
|
+
name: "MG3",
|
|
38148
|
+
category: "machine_gun",
|
|
38149
|
+
action: {
|
|
38150
|
+
kind: "firearm",
|
|
38151
|
+
caliber: "7_62x51",
|
|
38152
|
+
rpm: 1100,
|
|
38153
|
+
modes: [
|
|
38154
|
+
"auto"
|
|
38155
|
+
],
|
|
38156
|
+
magazine: 100,
|
|
38157
|
+
reload: 8.5,
|
|
38158
|
+
muzzleSpeed: 820,
|
|
38159
|
+
spreadDeg: 0.8,
|
|
38160
|
+
bloomDeg: 0.35,
|
|
38161
|
+
recoveryDegPerS: 4.5,
|
|
38162
|
+
recoil: [
|
|
38163
|
+
0.77,
|
|
38164
|
+
0.41
|
|
38165
|
+
],
|
|
38166
|
+
range: 350,
|
|
38167
|
+
family: "belt",
|
|
38168
|
+
timings: {
|
|
38169
|
+
draw: 0.35,
|
|
38170
|
+
reload: 8.5,
|
|
38171
|
+
clear: 1.2
|
|
38172
|
+
}
|
|
38173
|
+
},
|
|
38174
|
+
mass: 11.5,
|
|
38175
|
+
dimensions: {
|
|
38176
|
+
length: 1.225,
|
|
38177
|
+
barrel: 0.565,
|
|
38178
|
+
emptyMass: 11.5
|
|
38179
|
+
},
|
|
38180
|
+
archetype: "rifle_7_62x39",
|
|
38181
|
+
sources: [
|
|
38182
|
+
"reference",
|
|
38183
|
+
"derived",
|
|
38184
|
+
"sdk"
|
|
38185
|
+
],
|
|
38186
|
+
mounts: [
|
|
38187
|
+
{
|
|
38188
|
+
kind: "rail_bottom",
|
|
38189
|
+
interfaces: [
|
|
38190
|
+
"bipod_stud"
|
|
38191
|
+
],
|
|
38192
|
+
sources: [
|
|
38193
|
+
"gallery"
|
|
38194
|
+
]
|
|
38195
|
+
},
|
|
38196
|
+
{
|
|
38197
|
+
kind: "sling",
|
|
38198
|
+
interfaces: [
|
|
38199
|
+
"swivel"
|
|
38200
|
+
],
|
|
38201
|
+
sources: [
|
|
38202
|
+
"derived"
|
|
38203
|
+
]
|
|
38204
|
+
},
|
|
38205
|
+
{
|
|
38206
|
+
kind: "feed",
|
|
38207
|
+
interfaces: [
|
|
38208
|
+
"belt"
|
|
38209
|
+
],
|
|
38210
|
+
sources: [
|
|
38211
|
+
"derived"
|
|
38212
|
+
]
|
|
38213
|
+
}
|
|
38214
|
+
],
|
|
38215
|
+
fitted: [
|
|
38216
|
+
{
|
|
38217
|
+
id: "bipod",
|
|
38218
|
+
mount: "rail_bottom"
|
|
38219
|
+
}
|
|
38220
|
+
]
|
|
38221
|
+
},
|
|
38222
|
+
{
|
|
38223
|
+
id: "pp19_bizon",
|
|
38224
|
+
name: "PP-19 Bizon",
|
|
38225
|
+
category: "smg",
|
|
38226
|
+
action: {
|
|
38227
|
+
kind: "firearm",
|
|
38228
|
+
caliber: "9x18",
|
|
38229
|
+
rpm: 680,
|
|
38230
|
+
modes: [
|
|
38231
|
+
"auto",
|
|
38232
|
+
"semi"
|
|
38233
|
+
],
|
|
38234
|
+
magazine: 64,
|
|
38235
|
+
reload: 2.5,
|
|
38236
|
+
muzzleSpeed: 320,
|
|
38237
|
+
spreadDeg: 1.5,
|
|
38238
|
+
bloomDeg: 0.35,
|
|
38239
|
+
recoveryDegPerS: 6,
|
|
38240
|
+
recoil: [
|
|
38241
|
+
0.58,
|
|
38242
|
+
0.32
|
|
38243
|
+
],
|
|
38244
|
+
range: 80,
|
|
38245
|
+
family: "magazine",
|
|
38246
|
+
timings: {
|
|
38247
|
+
draw: 0.35,
|
|
38248
|
+
reload: 2.5,
|
|
38249
|
+
clear: 1.2
|
|
38250
|
+
}
|
|
38251
|
+
},
|
|
38252
|
+
mass: 2.1,
|
|
38253
|
+
dimensions: {
|
|
38254
|
+
length: 0.66,
|
|
38255
|
+
barrel: 0.195,
|
|
38256
|
+
emptyMass: 2.1,
|
|
38257
|
+
lengthCollapsed: 0.425
|
|
38258
|
+
},
|
|
38259
|
+
archetype: "smg_9mm",
|
|
38260
|
+
sources: [
|
|
38261
|
+
"reference",
|
|
38262
|
+
"derived",
|
|
38263
|
+
"sdk"
|
|
38264
|
+
],
|
|
38265
|
+
mounts: [
|
|
38266
|
+
{
|
|
38267
|
+
kind: "magazine",
|
|
38268
|
+
interfaces: [
|
|
38269
|
+
"mag_helical"
|
|
38270
|
+
],
|
|
38271
|
+
sources: [
|
|
38272
|
+
"gallery"
|
|
38273
|
+
]
|
|
38274
|
+
},
|
|
38275
|
+
{
|
|
38276
|
+
kind: "sling",
|
|
38277
|
+
interfaces: [
|
|
38278
|
+
"swivel"
|
|
38279
|
+
],
|
|
38280
|
+
sources: [
|
|
38281
|
+
"derived"
|
|
38282
|
+
]
|
|
38283
|
+
}
|
|
38284
|
+
],
|
|
38285
|
+
fitted: [],
|
|
38286
|
+
stock: {
|
|
38287
|
+
kind: "fold",
|
|
38288
|
+
foldAxis: "left"
|
|
38289
|
+
}
|
|
38290
|
+
},
|
|
38291
|
+
{
|
|
38292
|
+
id: "vz61",
|
|
38293
|
+
name: "vz. 61 \u0160korpion",
|
|
38294
|
+
category: "smg",
|
|
38295
|
+
action: {
|
|
38296
|
+
kind: "firearm",
|
|
38297
|
+
caliber: "32acp",
|
|
38298
|
+
rpm: 850,
|
|
38299
|
+
modes: [
|
|
38300
|
+
"auto",
|
|
38301
|
+
"semi"
|
|
38302
|
+
],
|
|
38303
|
+
magazine: 20,
|
|
38304
|
+
magazineOptions: [
|
|
38305
|
+
10
|
|
38306
|
+
],
|
|
38307
|
+
reload: 2.4,
|
|
38308
|
+
muzzleSpeed: 320,
|
|
38309
|
+
spreadDeg: 1.5,
|
|
38310
|
+
bloomDeg: 0.35,
|
|
38311
|
+
recoveryDegPerS: 6,
|
|
38312
|
+
recoil: [
|
|
38313
|
+
0.7,
|
|
38314
|
+
0.39
|
|
38315
|
+
],
|
|
38316
|
+
range: 80,
|
|
38317
|
+
family: "magazine",
|
|
38318
|
+
timings: {
|
|
38319
|
+
draw: 0.35,
|
|
38320
|
+
reload: 2.4,
|
|
38321
|
+
clear: 1.2
|
|
38322
|
+
}
|
|
38323
|
+
},
|
|
38324
|
+
mass: 1.3,
|
|
38325
|
+
dimensions: {
|
|
38326
|
+
length: 0.517,
|
|
38327
|
+
barrel: 0.115,
|
|
38328
|
+
emptyMass: 1.3,
|
|
38329
|
+
lengthCollapsed: 0.27
|
|
38330
|
+
},
|
|
38331
|
+
archetype: "smg_9mm",
|
|
38332
|
+
sources: [
|
|
38333
|
+
"reference",
|
|
38334
|
+
"derived",
|
|
38335
|
+
"sdk"
|
|
38336
|
+
],
|
|
38337
|
+
mounts: [
|
|
38338
|
+
{
|
|
38339
|
+
kind: "magazine",
|
|
38340
|
+
interfaces: [
|
|
38341
|
+
"mag_curved"
|
|
38342
|
+
],
|
|
38343
|
+
sources: [
|
|
38344
|
+
"gallery"
|
|
38345
|
+
]
|
|
38346
|
+
},
|
|
38347
|
+
{
|
|
38348
|
+
kind: "sling",
|
|
38349
|
+
interfaces: [
|
|
38350
|
+
"swivel"
|
|
38351
|
+
],
|
|
38352
|
+
sources: [
|
|
38353
|
+
"derived"
|
|
38354
|
+
]
|
|
38355
|
+
}
|
|
38356
|
+
],
|
|
38357
|
+
fitted: [],
|
|
38358
|
+
stock: {
|
|
38359
|
+
kind: "fold",
|
|
38360
|
+
foldAxis: "over"
|
|
38361
|
+
}
|
|
38362
|
+
},
|
|
38363
|
+
{
|
|
38364
|
+
id: "m134",
|
|
38365
|
+
name: "M134 Minigun",
|
|
38366
|
+
category: "machine_gun",
|
|
38367
|
+
action: {
|
|
38368
|
+
kind: "firearm",
|
|
38369
|
+
caliber: "7_62x51",
|
|
38370
|
+
rpm: 3e3,
|
|
38371
|
+
modes: [
|
|
38372
|
+
"auto"
|
|
38373
|
+
],
|
|
38374
|
+
magazine: 200,
|
|
38375
|
+
reload: 8.5,
|
|
38376
|
+
muzzleSpeed: 853,
|
|
38377
|
+
spin: {
|
|
38378
|
+
upSeconds: 0.5,
|
|
38379
|
+
holdSeconds: 1
|
|
38380
|
+
},
|
|
38381
|
+
rpmRange: [
|
|
38382
|
+
2e3,
|
|
38383
|
+
6e3
|
|
38384
|
+
],
|
|
38385
|
+
spreadDeg: 0.8,
|
|
38386
|
+
bloomDeg: 0.35,
|
|
38387
|
+
recoveryDegPerS: 4.5,
|
|
38388
|
+
recoil: [
|
|
38389
|
+
0.25,
|
|
38390
|
+
0.13
|
|
38391
|
+
],
|
|
38392
|
+
range: 350,
|
|
38393
|
+
family: "belt",
|
|
38394
|
+
timings: {
|
|
38395
|
+
draw: 0.35,
|
|
38396
|
+
reload: 8.5,
|
|
38397
|
+
clear: 1.2
|
|
38398
|
+
}
|
|
38399
|
+
},
|
|
38400
|
+
mass: 39,
|
|
38401
|
+
dimensions: {
|
|
38402
|
+
length: 0.801,
|
|
38403
|
+
barrel: 0.559,
|
|
38404
|
+
emptyMass: 39,
|
|
38405
|
+
barrels: 6,
|
|
38406
|
+
barrelMass: 2
|
|
38407
|
+
},
|
|
38408
|
+
archetype: "rifle_7_62x39",
|
|
38409
|
+
sources: [
|
|
38410
|
+
"reference",
|
|
38411
|
+
"derived",
|
|
38412
|
+
"sdk"
|
|
38413
|
+
],
|
|
38414
|
+
mounts: [
|
|
38415
|
+
{
|
|
38416
|
+
kind: "underbarrel",
|
|
38417
|
+
interfaces: [
|
|
38418
|
+
"tripod"
|
|
38419
|
+
],
|
|
38420
|
+
sources: [
|
|
38421
|
+
"reference"
|
|
38422
|
+
]
|
|
38423
|
+
},
|
|
38424
|
+
{
|
|
38425
|
+
kind: "sling",
|
|
38426
|
+
interfaces: [
|
|
38427
|
+
"swivel"
|
|
38428
|
+
],
|
|
38429
|
+
sources: [
|
|
38430
|
+
"derived"
|
|
38431
|
+
]
|
|
38432
|
+
},
|
|
38433
|
+
{
|
|
38434
|
+
kind: "feed",
|
|
38435
|
+
interfaces: [
|
|
38436
|
+
"belt"
|
|
38437
|
+
],
|
|
38438
|
+
sources: [
|
|
38439
|
+
"derived"
|
|
38440
|
+
]
|
|
38441
|
+
}
|
|
38442
|
+
],
|
|
38443
|
+
fitted: []
|
|
38444
|
+
},
|
|
38445
|
+
{
|
|
38446
|
+
id: "aks_74u",
|
|
38447
|
+
name: "AKS-74U",
|
|
38448
|
+
category: "rifle",
|
|
38449
|
+
action: {
|
|
38450
|
+
kind: "firearm",
|
|
38451
|
+
caliber: "5_45x39",
|
|
38452
|
+
rpm: 700,
|
|
38453
|
+
modes: [
|
|
38454
|
+
"auto",
|
|
38455
|
+
"semi"
|
|
38456
|
+
],
|
|
38457
|
+
magazine: 30,
|
|
38458
|
+
reload: 2.6,
|
|
38459
|
+
muzzleSpeed: 735,
|
|
38460
|
+
spreadDeg: 0.6,
|
|
38461
|
+
bloomDeg: 0.25,
|
|
38462
|
+
recoveryDegPerS: 5,
|
|
38463
|
+
recoil: [
|
|
38464
|
+
0.66,
|
|
38465
|
+
0.4
|
|
38466
|
+
],
|
|
38467
|
+
range: 400,
|
|
38468
|
+
family: "magazine",
|
|
38469
|
+
timings: {
|
|
38470
|
+
draw: 0.35,
|
|
38471
|
+
reload: 2.6,
|
|
38472
|
+
reloadEmpty: 3.4,
|
|
38473
|
+
clear: 1.2
|
|
38474
|
+
}
|
|
38475
|
+
},
|
|
38476
|
+
mass: 2.7,
|
|
38477
|
+
dimensions: {
|
|
38478
|
+
length: 0.73,
|
|
38479
|
+
barrel: 0.206,
|
|
38480
|
+
emptyMass: 2.7,
|
|
38481
|
+
lengthCollapsed: 0.49
|
|
38482
|
+
},
|
|
38483
|
+
archetype: "rifle_5_56",
|
|
38484
|
+
variantOf: "ak_74",
|
|
38485
|
+
sources: [
|
|
38486
|
+
"reference",
|
|
38487
|
+
"derived",
|
|
38488
|
+
"sdk"
|
|
38489
|
+
],
|
|
38490
|
+
mounts: [
|
|
38491
|
+
{
|
|
38492
|
+
kind: "muzzle",
|
|
38493
|
+
interfaces: [
|
|
38494
|
+
"fixed_muzzle_device"
|
|
38495
|
+
],
|
|
38496
|
+
sources: [
|
|
38497
|
+
"derived"
|
|
38498
|
+
]
|
|
38499
|
+
},
|
|
38500
|
+
{
|
|
38501
|
+
kind: "magazine",
|
|
38502
|
+
interfaces: [
|
|
38503
|
+
"mag_curved"
|
|
38504
|
+
],
|
|
38505
|
+
sources: [
|
|
38506
|
+
"gallery"
|
|
38507
|
+
]
|
|
38508
|
+
},
|
|
38509
|
+
{
|
|
38510
|
+
kind: "sling",
|
|
38511
|
+
interfaces: [
|
|
38512
|
+
"swivel"
|
|
38513
|
+
],
|
|
38514
|
+
sources: [
|
|
38515
|
+
"derived"
|
|
38516
|
+
]
|
|
38517
|
+
}
|
|
38518
|
+
],
|
|
38519
|
+
fitted: [
|
|
38520
|
+
{
|
|
38521
|
+
id: "muzzle_brake",
|
|
38522
|
+
mount: "muzzle"
|
|
38523
|
+
}
|
|
38524
|
+
],
|
|
38525
|
+
stock: {
|
|
38526
|
+
kind: "fold",
|
|
38527
|
+
foldAxis: "left"
|
|
38528
|
+
}
|
|
38529
|
+
},
|
|
38530
|
+
{
|
|
38531
|
+
id: "fn_scar_l",
|
|
38532
|
+
name: "FN SCAR-L",
|
|
38533
|
+
maker: "FN",
|
|
38534
|
+
category: "dmr",
|
|
38535
|
+
action: {
|
|
38536
|
+
kind: "firearm",
|
|
38537
|
+
caliber: "5_56x45",
|
|
38538
|
+
rpm: 625,
|
|
38539
|
+
modes: [
|
|
38540
|
+
"auto",
|
|
38541
|
+
"semi"
|
|
38542
|
+
],
|
|
38543
|
+
magazine: 30,
|
|
38544
|
+
reload: 2.6,
|
|
38545
|
+
muzzleSpeed: 870,
|
|
38546
|
+
spreadDeg: 0.25,
|
|
38547
|
+
bloomDeg: 0.3,
|
|
38548
|
+
recoveryDegPerS: 3,
|
|
38549
|
+
recoil: [
|
|
38550
|
+
1.43,
|
|
38551
|
+
0.24
|
|
38552
|
+
],
|
|
38553
|
+
range: 800,
|
|
38554
|
+
family: "magazine",
|
|
38555
|
+
timings: {
|
|
38556
|
+
draw: 0.35,
|
|
38557
|
+
reload: 2.6,
|
|
38558
|
+
clear: 1.2
|
|
38559
|
+
}
|
|
38560
|
+
},
|
|
38561
|
+
mass: 3.29,
|
|
38562
|
+
dimensions: {
|
|
38563
|
+
length: 0.889,
|
|
38564
|
+
barrel: 0.351,
|
|
38565
|
+
emptyMass: 3.29,
|
|
38566
|
+
lengthCollapsed: 0.635
|
|
38567
|
+
},
|
|
38568
|
+
archetype: "rifle_bolt_308",
|
|
38569
|
+
variantOf: "fn_scar_h",
|
|
38570
|
+
sources: [
|
|
38571
|
+
"reference",
|
|
38572
|
+
"derived",
|
|
38573
|
+
"sdk"
|
|
38574
|
+
],
|
|
38575
|
+
mounts: [
|
|
38576
|
+
{
|
|
38577
|
+
kind: "rail_top",
|
|
38578
|
+
interfaces: [
|
|
38579
|
+
"picatinny"
|
|
38580
|
+
],
|
|
38581
|
+
sources: [
|
|
38582
|
+
"gallery"
|
|
38583
|
+
]
|
|
38584
|
+
},
|
|
38585
|
+
{
|
|
38586
|
+
kind: "rail_left",
|
|
38587
|
+
interfaces: [
|
|
38588
|
+
"picatinny"
|
|
38589
|
+
],
|
|
38590
|
+
sources: [
|
|
38591
|
+
"gallery"
|
|
38592
|
+
]
|
|
38593
|
+
},
|
|
38594
|
+
{
|
|
38595
|
+
kind: "rail_right",
|
|
38596
|
+
interfaces: [
|
|
38597
|
+
"picatinny"
|
|
38598
|
+
],
|
|
38599
|
+
sources: [
|
|
38600
|
+
"gallery"
|
|
38601
|
+
]
|
|
38602
|
+
},
|
|
38603
|
+
{
|
|
38604
|
+
kind: "rail_bottom",
|
|
38605
|
+
interfaces: [
|
|
38606
|
+
"picatinny"
|
|
38607
|
+
],
|
|
38608
|
+
sources: [
|
|
38609
|
+
"gallery"
|
|
38610
|
+
]
|
|
38611
|
+
},
|
|
38612
|
+
{
|
|
38613
|
+
kind: "magazine",
|
|
38614
|
+
interfaces: [
|
|
38615
|
+
"mag_box"
|
|
38616
|
+
],
|
|
38617
|
+
sources: [
|
|
38618
|
+
"gallery"
|
|
38619
|
+
]
|
|
38620
|
+
},
|
|
38621
|
+
{
|
|
38622
|
+
kind: "sling",
|
|
38623
|
+
interfaces: [
|
|
38624
|
+
"swivel"
|
|
38625
|
+
],
|
|
38626
|
+
sources: [
|
|
38627
|
+
"derived"
|
|
38628
|
+
]
|
|
38629
|
+
}
|
|
38630
|
+
],
|
|
38631
|
+
fitted: [
|
|
38632
|
+
{
|
|
38633
|
+
id: "acog_4x",
|
|
38634
|
+
mount: "rail_top"
|
|
38635
|
+
}
|
|
38636
|
+
],
|
|
38637
|
+
stock: {
|
|
38638
|
+
kind: "fold",
|
|
38639
|
+
foldAxis: "right"
|
|
38640
|
+
}
|
|
38641
|
+
},
|
|
38642
|
+
{
|
|
38643
|
+
id: "m1_garand",
|
|
38644
|
+
name: "M1 Garand",
|
|
38645
|
+
category: "rifle",
|
|
38646
|
+
action: {
|
|
38647
|
+
kind: "firearm",
|
|
38648
|
+
caliber: "30_06",
|
|
38649
|
+
rpm: 120,
|
|
38650
|
+
modes: [
|
|
38651
|
+
"semi"
|
|
38652
|
+
],
|
|
38653
|
+
magazine: 8,
|
|
38654
|
+
reload: 2.2,
|
|
38655
|
+
muzzleSpeed: 865,
|
|
38656
|
+
spreadDeg: 0.8,
|
|
38657
|
+
bloomDeg: 0.35,
|
|
38658
|
+
recoveryDegPerS: 4.5,
|
|
38659
|
+
recoil: [
|
|
38660
|
+
2.28,
|
|
38661
|
+
1.22
|
|
38662
|
+
],
|
|
38663
|
+
range: 350,
|
|
38664
|
+
family: "top_load_semi",
|
|
38665
|
+
timings: {
|
|
38666
|
+
draw: 0.35,
|
|
38667
|
+
reload: 2.2,
|
|
38668
|
+
clear: 1.2
|
|
38669
|
+
}
|
|
38670
|
+
},
|
|
38671
|
+
mass: 4.31,
|
|
38672
|
+
dimensions: {
|
|
38673
|
+
length: 1.1,
|
|
38674
|
+
barrel: 0.61,
|
|
38675
|
+
emptyMass: 4.31
|
|
38676
|
+
},
|
|
38677
|
+
archetype: "rifle_7_62x39",
|
|
38678
|
+
variantOf: "sks",
|
|
38679
|
+
sources: [
|
|
38680
|
+
"reference",
|
|
38681
|
+
"derived",
|
|
38682
|
+
"sdk"
|
|
38683
|
+
],
|
|
38684
|
+
mounts: [
|
|
38685
|
+
{
|
|
38686
|
+
kind: "sling",
|
|
38687
|
+
interfaces: [
|
|
38688
|
+
"swivel"
|
|
38689
|
+
],
|
|
38690
|
+
sources: [
|
|
38691
|
+
"derived"
|
|
38692
|
+
]
|
|
38693
|
+
}
|
|
38694
|
+
],
|
|
38695
|
+
fitted: []
|
|
38696
|
+
},
|
|
38697
|
+
{
|
|
38698
|
+
id: "accuracy_l96a1",
|
|
38699
|
+
name: "Accuracy L96A1",
|
|
38700
|
+
maker: "Accuracy",
|
|
38701
|
+
category: "sniper",
|
|
38702
|
+
action: {
|
|
38703
|
+
kind: "firearm",
|
|
38704
|
+
caliber: "7_62x51",
|
|
38705
|
+
rpm: 73.17,
|
|
38706
|
+
modes: [
|
|
38707
|
+
"bolt"
|
|
38708
|
+
],
|
|
38709
|
+
magazine: 10,
|
|
38710
|
+
reload: 3.2,
|
|
38711
|
+
muzzleSpeed: 840,
|
|
38712
|
+
spreadDeg: 0.25,
|
|
38713
|
+
bloomDeg: 0.3,
|
|
38714
|
+
recoveryDegPerS: 3,
|
|
38715
|
+
recoil: [
|
|
38716
|
+
1.64,
|
|
38717
|
+
0.27
|
|
38718
|
+
],
|
|
38719
|
+
range: 800,
|
|
38720
|
+
family: "bolt_magazine",
|
|
38721
|
+
timings: {
|
|
38722
|
+
draw: 0.35,
|
|
38723
|
+
reload: 3.2,
|
|
38724
|
+
cycle: 0.82,
|
|
38725
|
+
clear: 1.2
|
|
38726
|
+
}
|
|
38727
|
+
},
|
|
38728
|
+
mass: 6.5,
|
|
38729
|
+
dimensions: {
|
|
38730
|
+
length: 1.18,
|
|
38731
|
+
barrel: 0.66,
|
|
38732
|
+
emptyMass: 6.5
|
|
38733
|
+
},
|
|
38734
|
+
archetype: "rifle_bolt_308",
|
|
38735
|
+
variantOf: "accuracy_awm",
|
|
38736
|
+
sources: [
|
|
38737
|
+
"reference",
|
|
38738
|
+
"derived",
|
|
38739
|
+
"sdk"
|
|
38740
|
+
],
|
|
38741
|
+
mounts: [
|
|
38742
|
+
{
|
|
38743
|
+
kind: "muzzle",
|
|
38744
|
+
interfaces: [
|
|
38745
|
+
"fixed_muzzle_device"
|
|
38746
|
+
],
|
|
38747
|
+
sources: [
|
|
38748
|
+
"derived"
|
|
38749
|
+
]
|
|
38750
|
+
},
|
|
38751
|
+
{
|
|
38752
|
+
kind: "rail_top",
|
|
38753
|
+
interfaces: [
|
|
38754
|
+
"dovetail"
|
|
38755
|
+
],
|
|
38756
|
+
sources: [
|
|
38757
|
+
"derived"
|
|
38758
|
+
]
|
|
38759
|
+
},
|
|
38760
|
+
{
|
|
38761
|
+
kind: "rail_bottom",
|
|
38762
|
+
interfaces: [
|
|
38763
|
+
"bipod_stud"
|
|
38764
|
+
],
|
|
38765
|
+
sources: [
|
|
38766
|
+
"gallery"
|
|
38767
|
+
]
|
|
38768
|
+
},
|
|
38769
|
+
{
|
|
38770
|
+
kind: "magazine",
|
|
38771
|
+
interfaces: [
|
|
38772
|
+
"mag_box"
|
|
38773
|
+
],
|
|
38774
|
+
sources: [
|
|
38775
|
+
"gallery"
|
|
38776
|
+
]
|
|
38777
|
+
},
|
|
38778
|
+
{
|
|
38779
|
+
kind: "sling",
|
|
38780
|
+
interfaces: [
|
|
38781
|
+
"swivel"
|
|
38782
|
+
],
|
|
38783
|
+
sources: [
|
|
38784
|
+
"derived"
|
|
38785
|
+
]
|
|
38786
|
+
}
|
|
38787
|
+
],
|
|
38788
|
+
fitted: [
|
|
38789
|
+
{
|
|
38790
|
+
id: "muzzle_brake",
|
|
38791
|
+
mount: "muzzle"
|
|
38792
|
+
},
|
|
38793
|
+
{
|
|
38794
|
+
id: "scope_3_9x",
|
|
38795
|
+
mount: "rail_top"
|
|
38796
|
+
},
|
|
38797
|
+
{
|
|
38798
|
+
id: "bipod",
|
|
38799
|
+
mount: "rail_bottom"
|
|
38800
|
+
}
|
|
38801
|
+
]
|
|
38802
|
+
},
|
|
38803
|
+
{
|
|
38804
|
+
id: "mossberg_590",
|
|
38805
|
+
name: "Mossberg 590",
|
|
38806
|
+
maker: "Mossberg",
|
|
38807
|
+
category: "shotgun",
|
|
38808
|
+
action: {
|
|
38809
|
+
kind: "firearm",
|
|
38810
|
+
caliber: "12ga_00buck",
|
|
38811
|
+
rpm: 120,
|
|
38812
|
+
modes: [
|
|
38813
|
+
"pump"
|
|
38814
|
+
],
|
|
38815
|
+
magazine: 8,
|
|
38816
|
+
chamber: 1,
|
|
38817
|
+
reload: 0.55,
|
|
38818
|
+
perRound: true,
|
|
38819
|
+
muzzleSpeed: 400,
|
|
38820
|
+
spreadDeg: 1,
|
|
38821
|
+
bloomDeg: 0.5,
|
|
38822
|
+
recoveryDegPerS: 3,
|
|
38823
|
+
pelletSpreadDeg: 3,
|
|
38824
|
+
recoil: [
|
|
38825
|
+
3.62,
|
|
38826
|
+
0.91
|
|
38827
|
+
],
|
|
38828
|
+
range: 40,
|
|
38829
|
+
family: "pump",
|
|
38830
|
+
timings: {
|
|
38831
|
+
draw: 0.35,
|
|
38832
|
+
reload: 0.55,
|
|
38833
|
+
perRound: 0.55,
|
|
38834
|
+
cycle: 0.5,
|
|
38835
|
+
clear: 1.2
|
|
38836
|
+
}
|
|
38837
|
+
},
|
|
38838
|
+
mass: 3.3,
|
|
38839
|
+
dimensions: {
|
|
38840
|
+
length: 1.003,
|
|
38841
|
+
barrel: 0.508,
|
|
38842
|
+
emptyMass: 3.3
|
|
38843
|
+
},
|
|
38844
|
+
archetype: "shotgun_pump_12",
|
|
38845
|
+
variantOf: "mossberg_500",
|
|
38846
|
+
sources: [
|
|
38847
|
+
"reference",
|
|
38848
|
+
"derived",
|
|
38849
|
+
"sdk"
|
|
38850
|
+
],
|
|
38851
|
+
mounts: [
|
|
38852
|
+
{
|
|
38853
|
+
kind: "barrel",
|
|
38854
|
+
interfaces: [
|
|
38855
|
+
"barrel_swap"
|
|
38856
|
+
],
|
|
38857
|
+
sources: [
|
|
38858
|
+
"derived"
|
|
38859
|
+
]
|
|
38860
|
+
},
|
|
38861
|
+
{
|
|
38862
|
+
kind: "sling",
|
|
38863
|
+
interfaces: [
|
|
38864
|
+
"swivel"
|
|
38865
|
+
],
|
|
38866
|
+
sources: [
|
|
38867
|
+
"derived"
|
|
38868
|
+
]
|
|
38869
|
+
}
|
|
38870
|
+
],
|
|
38871
|
+
fitted: []
|
|
38872
|
+
},
|
|
38873
|
+
{
|
|
38874
|
+
id: "fn_m240b",
|
|
38875
|
+
name: "FN M240B",
|
|
38876
|
+
maker: "FN",
|
|
38877
|
+
category: "machine_gun",
|
|
38878
|
+
action: {
|
|
38879
|
+
kind: "firearm",
|
|
38880
|
+
caliber: "7_62x51",
|
|
38881
|
+
rpm: 750,
|
|
38882
|
+
modes: [
|
|
38883
|
+
"auto"
|
|
38884
|
+
],
|
|
38885
|
+
magazine: 100,
|
|
38886
|
+
reload: 8.5,
|
|
38887
|
+
muzzleSpeed: 853,
|
|
38888
|
+
spreadDeg: 0.8,
|
|
38889
|
+
bloomDeg: 0.35,
|
|
38890
|
+
recoveryDegPerS: 4.5,
|
|
38891
|
+
recoil: [
|
|
38892
|
+
0.77,
|
|
38893
|
+
0.41
|
|
38894
|
+
],
|
|
38895
|
+
range: 350,
|
|
38896
|
+
family: "belt",
|
|
38897
|
+
timings: {
|
|
38898
|
+
draw: 0.35,
|
|
38899
|
+
reload: 8.5,
|
|
38900
|
+
clear: 1.2
|
|
38901
|
+
}
|
|
38902
|
+
},
|
|
38903
|
+
mass: 12.5,
|
|
38904
|
+
dimensions: {
|
|
38905
|
+
length: 1.245,
|
|
38906
|
+
barrel: 0.63,
|
|
38907
|
+
emptyMass: 12.5
|
|
38908
|
+
},
|
|
38909
|
+
archetype: "rifle_7_62x39",
|
|
38910
|
+
sources: [
|
|
38911
|
+
"reference",
|
|
38912
|
+
"derived",
|
|
38913
|
+
"sdk"
|
|
38914
|
+
],
|
|
38915
|
+
mounts: [
|
|
38916
|
+
{
|
|
38917
|
+
kind: "rail_top",
|
|
38918
|
+
interfaces: [
|
|
38919
|
+
"picatinny"
|
|
38920
|
+
],
|
|
38921
|
+
sources: [
|
|
38922
|
+
"gallery"
|
|
38923
|
+
]
|
|
38924
|
+
},
|
|
38925
|
+
{
|
|
38926
|
+
kind: "rail_bottom",
|
|
38927
|
+
interfaces: [
|
|
38928
|
+
"bipod_stud"
|
|
38929
|
+
],
|
|
38930
|
+
sources: [
|
|
38931
|
+
"gallery"
|
|
38932
|
+
]
|
|
38933
|
+
},
|
|
38934
|
+
{
|
|
38935
|
+
kind: "sling",
|
|
38936
|
+
interfaces: [
|
|
38937
|
+
"swivel"
|
|
38938
|
+
],
|
|
38939
|
+
sources: [
|
|
38940
|
+
"derived"
|
|
38941
|
+
]
|
|
38942
|
+
},
|
|
38943
|
+
{
|
|
38944
|
+
kind: "feed",
|
|
38945
|
+
interfaces: [
|
|
38946
|
+
"belt"
|
|
38947
|
+
],
|
|
38948
|
+
sources: [
|
|
38949
|
+
"derived"
|
|
38950
|
+
]
|
|
38951
|
+
}
|
|
38952
|
+
],
|
|
38953
|
+
fitted: [
|
|
38954
|
+
{
|
|
38955
|
+
id: "bipod",
|
|
38956
|
+
mount: "rail_bottom"
|
|
38957
|
+
}
|
|
38958
|
+
]
|
|
38959
|
+
},
|
|
38960
|
+
{
|
|
38961
|
+
id: "sig_sauer_p320",
|
|
38962
|
+
name: "SIG Sauer P320",
|
|
38963
|
+
maker: "SIG Sauer",
|
|
38964
|
+
category: "pistol",
|
|
38965
|
+
action: {
|
|
38966
|
+
kind: "firearm",
|
|
38967
|
+
caliber: "9x19",
|
|
38968
|
+
rpm: 300,
|
|
38969
|
+
modes: [
|
|
38970
|
+
"semi"
|
|
38971
|
+
],
|
|
38972
|
+
magazine: 17,
|
|
38973
|
+
reload: 1.9,
|
|
38974
|
+
muzzleSpeed: 350,
|
|
38975
|
+
spreadDeg: 1,
|
|
38976
|
+
bloomDeg: 0.6,
|
|
38977
|
+
recoveryDegPerS: 4,
|
|
38978
|
+
recoil: [
|
|
38979
|
+
1.2,
|
|
38980
|
+
0.4
|
|
38981
|
+
],
|
|
38982
|
+
range: 50,
|
|
38983
|
+
family: "pistol",
|
|
38984
|
+
timings: {
|
|
38985
|
+
draw: 0.35,
|
|
38986
|
+
reload: 1.9,
|
|
38987
|
+
clear: 1.2
|
|
38988
|
+
},
|
|
38989
|
+
faultFactor: 0.8
|
|
38990
|
+
},
|
|
38991
|
+
mass: 0.83,
|
|
38992
|
+
dimensions: {
|
|
38993
|
+
length: 0.203,
|
|
38994
|
+
barrel: 0.12,
|
|
38995
|
+
emptyMass: 0.83
|
|
38996
|
+
},
|
|
38997
|
+
archetype: "pistol_9mm",
|
|
38998
|
+
variantOf: "sig_sauer_p226",
|
|
38999
|
+
sources: [
|
|
39000
|
+
"reference",
|
|
39001
|
+
"derived",
|
|
39002
|
+
"sdk"
|
|
39003
|
+
],
|
|
39004
|
+
mounts: [
|
|
39005
|
+
{
|
|
39006
|
+
kind: "magazine",
|
|
39007
|
+
interfaces: [
|
|
39008
|
+
"mag_pistol"
|
|
39009
|
+
],
|
|
39010
|
+
sources: [
|
|
39011
|
+
"derived"
|
|
39012
|
+
]
|
|
39013
|
+
}
|
|
39014
|
+
],
|
|
39015
|
+
fitted: []
|
|
39016
|
+
},
|
|
39017
|
+
{
|
|
39018
|
+
id: "hk_usp",
|
|
39019
|
+
name: "HK USP",
|
|
39020
|
+
maker: "HK",
|
|
39021
|
+
category: "pistol",
|
|
39022
|
+
action: {
|
|
39023
|
+
kind: "firearm",
|
|
39024
|
+
caliber: "9x19",
|
|
39025
|
+
rpm: 300,
|
|
39026
|
+
modes: [
|
|
39027
|
+
"semi"
|
|
39028
|
+
],
|
|
39029
|
+
magazine: 15,
|
|
39030
|
+
reload: 1.9,
|
|
39031
|
+
muzzleSpeed: 350,
|
|
39032
|
+
spreadDeg: 1,
|
|
39033
|
+
bloomDeg: 0.6,
|
|
39034
|
+
recoveryDegPerS: 4,
|
|
39035
|
+
recoil: [
|
|
39036
|
+
1.29,
|
|
39037
|
+
0.43
|
|
39038
|
+
],
|
|
39039
|
+
range: 50,
|
|
39040
|
+
family: "pistol",
|
|
39041
|
+
timings: {
|
|
39042
|
+
draw: 0.35,
|
|
39043
|
+
reload: 1.9,
|
|
39044
|
+
clear: 1.2
|
|
39045
|
+
},
|
|
39046
|
+
faultFactor: 0.8
|
|
39047
|
+
},
|
|
39048
|
+
mass: 0.77,
|
|
39049
|
+
dimensions: {
|
|
39050
|
+
length: 0.194,
|
|
39051
|
+
barrel: 0.108,
|
|
39052
|
+
emptyMass: 0.77
|
|
39053
|
+
},
|
|
39054
|
+
archetype: "pistol_9mm",
|
|
39055
|
+
variantOf: "sig_sauer_p226",
|
|
39056
|
+
sources: [
|
|
39057
|
+
"reference",
|
|
39058
|
+
"derived",
|
|
39059
|
+
"sdk"
|
|
39060
|
+
],
|
|
39061
|
+
mounts: [
|
|
39062
|
+
{
|
|
39063
|
+
kind: "magazine",
|
|
39064
|
+
interfaces: [
|
|
39065
|
+
"mag_pistol"
|
|
39066
|
+
],
|
|
39067
|
+
sources: [
|
|
39068
|
+
"derived"
|
|
39069
|
+
]
|
|
39070
|
+
}
|
|
39071
|
+
],
|
|
39072
|
+
fitted: []
|
|
39073
|
+
},
|
|
39074
|
+
{
|
|
39075
|
+
id: "walther_p99",
|
|
39076
|
+
name: "Walther P99",
|
|
39077
|
+
maker: "Walther",
|
|
39078
|
+
category: "pistol",
|
|
39079
|
+
action: {
|
|
39080
|
+
kind: "firearm",
|
|
39081
|
+
caliber: "9x19",
|
|
39082
|
+
rpm: 300,
|
|
39083
|
+
modes: [
|
|
39084
|
+
"semi"
|
|
39085
|
+
],
|
|
39086
|
+
magazine: 15,
|
|
39087
|
+
reload: 1.8,
|
|
39088
|
+
muzzleSpeed: 375,
|
|
39089
|
+
spreadDeg: 1,
|
|
39090
|
+
bloomDeg: 0.6,
|
|
39091
|
+
recoveryDegPerS: 4,
|
|
39092
|
+
recoil: [
|
|
39093
|
+
1.81,
|
|
39094
|
+
0.6
|
|
39095
|
+
],
|
|
39096
|
+
range: 50,
|
|
39097
|
+
family: "pistol",
|
|
39098
|
+
timings: {
|
|
39099
|
+
draw: 0.35,
|
|
39100
|
+
reload: 1.8,
|
|
39101
|
+
clear: 1.2
|
|
39102
|
+
},
|
|
39103
|
+
faultFactor: 0.7
|
|
39104
|
+
},
|
|
39105
|
+
mass: 0.63,
|
|
39106
|
+
dimensions: {
|
|
39107
|
+
length: 0.18,
|
|
39108
|
+
barrel: 0.102,
|
|
39109
|
+
emptyMass: 0.63
|
|
39110
|
+
},
|
|
39111
|
+
archetype: "pistol_9mm",
|
|
39112
|
+
variantOf: "glock_17",
|
|
39113
|
+
sources: [
|
|
39114
|
+
"reference",
|
|
39115
|
+
"derived",
|
|
39116
|
+
"sdk"
|
|
39117
|
+
],
|
|
39118
|
+
mounts: [
|
|
39119
|
+
{
|
|
39120
|
+
kind: "magazine",
|
|
39121
|
+
interfaces: [
|
|
39122
|
+
"mag_pistol"
|
|
39123
|
+
],
|
|
39124
|
+
sources: [
|
|
39125
|
+
"derived"
|
|
39126
|
+
]
|
|
39127
|
+
}
|
|
39128
|
+
],
|
|
39129
|
+
fitted: []
|
|
39130
|
+
},
|
|
39131
|
+
{
|
|
39132
|
+
id: "colt_python",
|
|
39133
|
+
name: "Colt Python",
|
|
39134
|
+
maker: "Colt",
|
|
39135
|
+
category: "revolver",
|
|
39136
|
+
action: {
|
|
39137
|
+
kind: "firearm",
|
|
39138
|
+
caliber: "357mag",
|
|
39139
|
+
rpm: 150,
|
|
39140
|
+
modes: [
|
|
39141
|
+
"single"
|
|
39142
|
+
],
|
|
39143
|
+
magazine: 6,
|
|
39144
|
+
reload: 2.4,
|
|
39145
|
+
muzzleSpeed: 430,
|
|
39146
|
+
spreadDeg: 0.8,
|
|
39147
|
+
bloomDeg: 1,
|
|
39148
|
+
recoveryDegPerS: 3,
|
|
39149
|
+
recoil: [
|
|
39150
|
+
3.13,
|
|
39151
|
+
0.94
|
|
39152
|
+
],
|
|
39153
|
+
range: 60,
|
|
39154
|
+
family: "revolver",
|
|
39155
|
+
timings: {
|
|
39156
|
+
draw: 0.35,
|
|
39157
|
+
reload: 2.4,
|
|
39158
|
+
perRound: 1,
|
|
39159
|
+
clear: 1.2
|
|
39160
|
+
}
|
|
39161
|
+
},
|
|
39162
|
+
mass: 1.23,
|
|
39163
|
+
dimensions: {
|
|
39164
|
+
length: 0.292,
|
|
39165
|
+
barrel: 0.152,
|
|
39166
|
+
emptyMass: 1.23
|
|
39167
|
+
},
|
|
39168
|
+
archetype: "revolver_357",
|
|
39169
|
+
variantOf: "sw_686",
|
|
39170
|
+
sources: [
|
|
39171
|
+
"reference",
|
|
39172
|
+
"derived",
|
|
39173
|
+
"sdk"
|
|
39174
|
+
],
|
|
39175
|
+
mounts: [],
|
|
39176
|
+
fitted: []
|
|
39177
|
+
},
|
|
39178
|
+
{
|
|
39179
|
+
id: "fn_ps90",
|
|
39180
|
+
name: "FN PS90",
|
|
39181
|
+
maker: "FN",
|
|
39182
|
+
category: "smg",
|
|
39183
|
+
action: {
|
|
39184
|
+
kind: "firearm",
|
|
39185
|
+
caliber: "5_7x28",
|
|
39186
|
+
rpm: 120,
|
|
39187
|
+
modes: [
|
|
39188
|
+
"semi"
|
|
39189
|
+
],
|
|
39190
|
+
magazine: 50,
|
|
39191
|
+
reload: 3,
|
|
39192
|
+
muzzleSpeed: 715,
|
|
39193
|
+
spreadDeg: 1.5,
|
|
39194
|
+
bloomDeg: 0.35,
|
|
39195
|
+
recoveryDegPerS: 6,
|
|
39196
|
+
recoil: [
|
|
39197
|
+
0.69,
|
|
39198
|
+
0.38
|
|
39199
|
+
],
|
|
39200
|
+
range: 80,
|
|
39201
|
+
family: "top_magazine",
|
|
39202
|
+
timings: {
|
|
39203
|
+
draw: 0.35,
|
|
39204
|
+
reload: 3,
|
|
39205
|
+
clear: 1.2
|
|
39206
|
+
}
|
|
39207
|
+
},
|
|
39208
|
+
mass: 2.86,
|
|
39209
|
+
dimensions: {
|
|
39210
|
+
length: 0.668,
|
|
39211
|
+
barrel: 0.407,
|
|
39212
|
+
emptyMass: 2.86
|
|
39213
|
+
},
|
|
39214
|
+
archetype: "smg_9mm",
|
|
39215
|
+
variantOf: "fn_p90",
|
|
39216
|
+
sources: [
|
|
39217
|
+
"reference",
|
|
39218
|
+
"derived",
|
|
39219
|
+
"sdk"
|
|
39220
|
+
],
|
|
39221
|
+
mounts: [
|
|
39222
|
+
{
|
|
39223
|
+
kind: "sling",
|
|
39224
|
+
interfaces: [
|
|
39225
|
+
"swivel"
|
|
39226
|
+
],
|
|
39227
|
+
sources: [
|
|
39228
|
+
"derived"
|
|
39229
|
+
]
|
|
39230
|
+
}
|
|
39231
|
+
],
|
|
39232
|
+
fitted: []
|
|
39233
|
+
},
|
|
39234
|
+
{
|
|
39235
|
+
id: "bt_mp9",
|
|
39236
|
+
name: "B&T MP9",
|
|
39237
|
+
maker: "B&T",
|
|
39238
|
+
category: "smg",
|
|
39239
|
+
action: {
|
|
39240
|
+
kind: "firearm",
|
|
39241
|
+
caliber: "9x19",
|
|
39242
|
+
rpm: 1100,
|
|
39243
|
+
modes: [
|
|
39244
|
+
"auto",
|
|
39245
|
+
"semi"
|
|
39246
|
+
],
|
|
39247
|
+
magazine: 30,
|
|
39248
|
+
reload: 2.4,
|
|
39249
|
+
muzzleSpeed: 400,
|
|
39250
|
+
spreadDeg: 1.5,
|
|
39251
|
+
bloomDeg: 0.35,
|
|
39252
|
+
recoveryDegPerS: 6,
|
|
39253
|
+
recoil: [
|
|
39254
|
+
1.66,
|
|
39255
|
+
0.92
|
|
39256
|
+
],
|
|
39257
|
+
range: 80,
|
|
39258
|
+
family: "magazine",
|
|
39259
|
+
timings: {
|
|
39260
|
+
draw: 0.35,
|
|
39261
|
+
reload: 2.4,
|
|
39262
|
+
clear: 1.2
|
|
39263
|
+
}
|
|
39264
|
+
},
|
|
39265
|
+
mass: 1.4,
|
|
39266
|
+
dimensions: {
|
|
39267
|
+
length: 0.523,
|
|
39268
|
+
barrel: 0.13,
|
|
39269
|
+
emptyMass: 1.4,
|
|
39270
|
+
lengthCollapsed: 0.303
|
|
39271
|
+
},
|
|
39272
|
+
archetype: "smg_9mm",
|
|
39273
|
+
variantOf: "uzi",
|
|
39274
|
+
sources: [
|
|
39275
|
+
"reference",
|
|
39276
|
+
"derived",
|
|
39277
|
+
"sdk"
|
|
39278
|
+
],
|
|
39279
|
+
mounts: [
|
|
39280
|
+
{
|
|
39281
|
+
kind: "rail_top",
|
|
39282
|
+
interfaces: [
|
|
39283
|
+
"picatinny"
|
|
39284
|
+
],
|
|
39285
|
+
sources: [
|
|
39286
|
+
"gallery"
|
|
39287
|
+
]
|
|
39288
|
+
},
|
|
39289
|
+
{
|
|
39290
|
+
kind: "magazine",
|
|
39291
|
+
interfaces: [
|
|
39292
|
+
"mag_box"
|
|
39293
|
+
],
|
|
39294
|
+
sources: [
|
|
39295
|
+
"gallery"
|
|
39296
|
+
]
|
|
39297
|
+
},
|
|
39298
|
+
{
|
|
39299
|
+
kind: "sling",
|
|
39300
|
+
interfaces: [
|
|
39301
|
+
"swivel"
|
|
39302
|
+
],
|
|
39303
|
+
sources: [
|
|
39304
|
+
"derived"
|
|
39305
|
+
]
|
|
39306
|
+
}
|
|
39307
|
+
],
|
|
39308
|
+
fitted: [],
|
|
39309
|
+
stock: {
|
|
39310
|
+
kind: "fold",
|
|
39311
|
+
foldAxis: "right"
|
|
39312
|
+
}
|
|
39313
|
+
},
|
|
39314
|
+
{
|
|
39315
|
+
id: "mp40",
|
|
39316
|
+
name: "MP40",
|
|
39317
|
+
category: "smg",
|
|
39318
|
+
action: {
|
|
39319
|
+
kind: "firearm",
|
|
39320
|
+
caliber: "9x19",
|
|
39321
|
+
rpm: 550,
|
|
39322
|
+
modes: [
|
|
39323
|
+
"auto",
|
|
39324
|
+
"semi"
|
|
39325
|
+
],
|
|
39326
|
+
magazine: 32,
|
|
39327
|
+
reload: 2.9,
|
|
39328
|
+
spreadDeg: 1.5,
|
|
39329
|
+
bloomDeg: 0.35,
|
|
39330
|
+
recoveryDegPerS: 6,
|
|
39331
|
+
recoil: [
|
|
39332
|
+
0.48,
|
|
39333
|
+
0.27
|
|
39334
|
+
],
|
|
39335
|
+
range: 80,
|
|
39336
|
+
family: "magazine",
|
|
39337
|
+
timings: {
|
|
39338
|
+
draw: 0.35,
|
|
39339
|
+
reload: 2.9,
|
|
39340
|
+
clear: 1.2
|
|
39341
|
+
}
|
|
39342
|
+
},
|
|
39343
|
+
mass: 4,
|
|
39344
|
+
dimensions: {
|
|
39345
|
+
length: 0.833,
|
|
39346
|
+
barrel: 0.251,
|
|
39347
|
+
emptyMass: 4,
|
|
39348
|
+
lengthCollapsed: 0.63
|
|
39349
|
+
},
|
|
39350
|
+
archetype: "smg_9mm",
|
|
39351
|
+
variantOf: "thompson_m1a1",
|
|
39352
|
+
sources: [
|
|
39353
|
+
"reference",
|
|
39354
|
+
"derived",
|
|
39355
|
+
"sdk"
|
|
39356
|
+
],
|
|
39357
|
+
mounts: [
|
|
39358
|
+
{
|
|
39359
|
+
kind: "magazine",
|
|
39360
|
+
interfaces: [
|
|
39361
|
+
"mag_box"
|
|
39362
|
+
],
|
|
39363
|
+
sources: [
|
|
39364
|
+
"gallery"
|
|
39365
|
+
]
|
|
39366
|
+
},
|
|
39367
|
+
{
|
|
39368
|
+
kind: "sling",
|
|
39369
|
+
interfaces: [
|
|
39370
|
+
"swivel"
|
|
39371
|
+
],
|
|
39372
|
+
sources: [
|
|
39373
|
+
"derived"
|
|
39374
|
+
]
|
|
39375
|
+
}
|
|
39376
|
+
],
|
|
39377
|
+
fitted: [],
|
|
39378
|
+
stock: {
|
|
39379
|
+
kind: "fold",
|
|
39380
|
+
foldAxis: "under"
|
|
39381
|
+
}
|
|
39382
|
+
},
|
|
39383
|
+
{
|
|
39384
|
+
id: "famas",
|
|
39385
|
+
name: "FAMAS",
|
|
39386
|
+
category: "rifle",
|
|
39387
|
+
action: {
|
|
39388
|
+
kind: "firearm",
|
|
39389
|
+
caliber: "5_56x45",
|
|
39390
|
+
rpm: 1e3,
|
|
39391
|
+
modes: [
|
|
39392
|
+
"auto",
|
|
39393
|
+
"semi"
|
|
39394
|
+
],
|
|
39395
|
+
magazine: 25,
|
|
39396
|
+
reload: 2.8,
|
|
39397
|
+
muzzleSpeed: 960,
|
|
39398
|
+
spreadDeg: 0.6,
|
|
39399
|
+
bloomDeg: 0.25,
|
|
39400
|
+
recoveryDegPerS: 5,
|
|
39401
|
+
recoil: [
|
|
39402
|
+
0.99,
|
|
39403
|
+
0.6
|
|
39404
|
+
],
|
|
39405
|
+
range: 400,
|
|
39406
|
+
family: "magazine",
|
|
39407
|
+
timings: {
|
|
39408
|
+
draw: 0.35,
|
|
39409
|
+
reload: 2.8,
|
|
39410
|
+
reloadEmpty: 3.4,
|
|
39411
|
+
clear: 1.2
|
|
39412
|
+
}
|
|
39413
|
+
},
|
|
39414
|
+
mass: 3.61,
|
|
39415
|
+
dimensions: {
|
|
39416
|
+
length: 0.757,
|
|
39417
|
+
barrel: 0.488,
|
|
39418
|
+
emptyMass: 3.61
|
|
39419
|
+
},
|
|
39420
|
+
archetype: "rifle_5_56",
|
|
39421
|
+
variantOf: "steyr_aug_a1",
|
|
39422
|
+
sources: [
|
|
39423
|
+
"reference",
|
|
39424
|
+
"derived",
|
|
39425
|
+
"sdk"
|
|
39426
|
+
],
|
|
39427
|
+
mounts: [
|
|
39428
|
+
{
|
|
39429
|
+
kind: "magazine",
|
|
39430
|
+
interfaces: [
|
|
39431
|
+
"mag_box"
|
|
39432
|
+
],
|
|
39433
|
+
sources: [
|
|
39434
|
+
"derived"
|
|
39435
|
+
]
|
|
39436
|
+
},
|
|
39437
|
+
{
|
|
39438
|
+
kind: "sling",
|
|
39439
|
+
interfaces: [
|
|
39440
|
+
"swivel"
|
|
39441
|
+
],
|
|
39442
|
+
sources: [
|
|
39443
|
+
"derived"
|
|
39444
|
+
]
|
|
39445
|
+
}
|
|
39446
|
+
],
|
|
39447
|
+
fitted: []
|
|
39448
|
+
},
|
|
39449
|
+
{
|
|
39450
|
+
id: "iwi_tavor",
|
|
39451
|
+
name: "IWI Tavor",
|
|
39452
|
+
maker: "IWI",
|
|
39453
|
+
category: "rifle",
|
|
39454
|
+
action: {
|
|
39455
|
+
kind: "firearm",
|
|
39456
|
+
caliber: "5_56x45",
|
|
39457
|
+
rpm: 850,
|
|
39458
|
+
modes: [
|
|
39459
|
+
"auto",
|
|
39460
|
+
"semi"
|
|
39461
|
+
],
|
|
39462
|
+
magazine: 30,
|
|
39463
|
+
reload: 2.8,
|
|
39464
|
+
muzzleSpeed: 910,
|
|
39465
|
+
spreadDeg: 0.6,
|
|
39466
|
+
bloomDeg: 0.25,
|
|
39467
|
+
recoveryDegPerS: 5,
|
|
39468
|
+
recoil: [
|
|
39469
|
+
0.98,
|
|
39470
|
+
0.59
|
|
39471
|
+
],
|
|
39472
|
+
range: 400,
|
|
39473
|
+
family: "magazine",
|
|
39474
|
+
timings: {
|
|
39475
|
+
draw: 0.35,
|
|
39476
|
+
reload: 2.8,
|
|
39477
|
+
reloadEmpty: 3.4,
|
|
39478
|
+
clear: 1.2
|
|
39479
|
+
}
|
|
39480
|
+
},
|
|
39481
|
+
mass: 3.27,
|
|
39482
|
+
dimensions: {
|
|
39483
|
+
length: 0.72,
|
|
39484
|
+
barrel: 0.46,
|
|
39485
|
+
emptyMass: 3.27
|
|
39486
|
+
},
|
|
39487
|
+
archetype: "rifle_5_56",
|
|
39488
|
+
variantOf: "steyr_aug_a1",
|
|
37763
39489
|
sources: [
|
|
37764
39490
|
"reference",
|
|
37765
39491
|
"derived",
|
|
@@ -37767,18 +39493,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37767
39493
|
],
|
|
37768
39494
|
mounts: [
|
|
37769
39495
|
{
|
|
37770
|
-
kind: "
|
|
37771
|
-
interfaces: [
|
|
37772
|
-
"thread_14x1lh"
|
|
37773
|
-
],
|
|
37774
|
-
sources: [
|
|
37775
|
-
"derived"
|
|
37776
|
-
]
|
|
37777
|
-
},
|
|
37778
|
-
{
|
|
37779
|
-
kind: "rail_bottom",
|
|
39496
|
+
kind: "rail_top",
|
|
37780
39497
|
interfaces: [
|
|
37781
|
-
"
|
|
39498
|
+
"picatinny"
|
|
37782
39499
|
],
|
|
37783
39500
|
sources: [
|
|
37784
39501
|
"gallery"
|
|
@@ -37787,10 +39504,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37787
39504
|
{
|
|
37788
39505
|
kind: "magazine",
|
|
37789
39506
|
interfaces: [
|
|
37790
|
-
"
|
|
39507
|
+
"mag_box"
|
|
37791
39508
|
],
|
|
37792
39509
|
sources: [
|
|
37793
|
-
"
|
|
39510
|
+
"derived"
|
|
37794
39511
|
]
|
|
37795
39512
|
},
|
|
37796
39513
|
{
|
|
@@ -37803,54 +39520,47 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37803
39520
|
]
|
|
37804
39521
|
}
|
|
37805
39522
|
],
|
|
37806
|
-
fitted: [
|
|
37807
|
-
{
|
|
37808
|
-
id: "bipod",
|
|
37809
|
-
mount: "rail_bottom"
|
|
37810
|
-
}
|
|
37811
|
-
]
|
|
39523
|
+
fitted: []
|
|
37812
39524
|
},
|
|
37813
39525
|
{
|
|
37814
|
-
id: "
|
|
37815
|
-
name: "
|
|
37816
|
-
category: "
|
|
39526
|
+
id: "l85a2",
|
|
39527
|
+
name: "L85A2",
|
|
39528
|
+
category: "rifle",
|
|
37817
39529
|
action: {
|
|
37818
39530
|
kind: "firearm",
|
|
37819
|
-
caliber: "
|
|
37820
|
-
rpm:
|
|
39531
|
+
caliber: "5_56x45",
|
|
39532
|
+
rpm: 700,
|
|
37821
39533
|
modes: [
|
|
37822
39534
|
"auto",
|
|
37823
39535
|
"semi"
|
|
37824
39536
|
],
|
|
37825
39537
|
magazine: 30,
|
|
37826
|
-
|
|
37827
|
-
|
|
37828
|
-
|
|
37829
|
-
|
|
37830
|
-
|
|
37831
|
-
spreadDeg: 1.5,
|
|
37832
|
-
bloomDeg: 0.35,
|
|
37833
|
-
recoveryDegPerS: 6,
|
|
39538
|
+
reload: 2.8,
|
|
39539
|
+
muzzleSpeed: 940,
|
|
39540
|
+
spreadDeg: 0.6,
|
|
39541
|
+
bloomDeg: 0.25,
|
|
39542
|
+
recoveryDegPerS: 5,
|
|
37834
39543
|
recoil: [
|
|
37835
|
-
0.
|
|
37836
|
-
0.
|
|
39544
|
+
0.9,
|
|
39545
|
+
0.54
|
|
37837
39546
|
],
|
|
37838
|
-
range:
|
|
39547
|
+
range: 400,
|
|
37839
39548
|
family: "magazine",
|
|
37840
39549
|
timings: {
|
|
37841
39550
|
draw: 0.35,
|
|
37842
|
-
reload: 2.
|
|
39551
|
+
reload: 2.8,
|
|
39552
|
+
reloadEmpty: 3.4,
|
|
37843
39553
|
clear: 1.2
|
|
37844
39554
|
}
|
|
37845
39555
|
},
|
|
37846
|
-
mass:
|
|
39556
|
+
mass: 3.82,
|
|
37847
39557
|
dimensions: {
|
|
37848
|
-
length: 0.
|
|
37849
|
-
barrel: 0.
|
|
37850
|
-
emptyMass:
|
|
37851
|
-
lengthCollapsed: 0.425
|
|
39558
|
+
length: 0.785,
|
|
39559
|
+
barrel: 0.518,
|
|
39560
|
+
emptyMass: 3.82
|
|
37852
39561
|
},
|
|
37853
|
-
archetype: "
|
|
39562
|
+
archetype: "rifle_5_56",
|
|
39563
|
+
variantOf: "steyr_aug_a1",
|
|
37854
39564
|
sources: [
|
|
37855
39565
|
"reference",
|
|
37856
39566
|
"derived",
|
|
@@ -37866,40 +39576,13 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37866
39576
|
"gallery"
|
|
37867
39577
|
]
|
|
37868
39578
|
},
|
|
37869
|
-
{
|
|
37870
|
-
kind: "rail_left",
|
|
37871
|
-
interfaces: [
|
|
37872
|
-
"picatinny"
|
|
37873
|
-
],
|
|
37874
|
-
sources: [
|
|
37875
|
-
"gallery"
|
|
37876
|
-
]
|
|
37877
|
-
},
|
|
37878
|
-
{
|
|
37879
|
-
kind: "rail_right",
|
|
37880
|
-
interfaces: [
|
|
37881
|
-
"picatinny"
|
|
37882
|
-
],
|
|
37883
|
-
sources: [
|
|
37884
|
-
"gallery"
|
|
37885
|
-
]
|
|
37886
|
-
},
|
|
37887
|
-
{
|
|
37888
|
-
kind: "rail_bottom",
|
|
37889
|
-
interfaces: [
|
|
37890
|
-
"picatinny"
|
|
37891
|
-
],
|
|
37892
|
-
sources: [
|
|
37893
|
-
"gallery"
|
|
37894
|
-
]
|
|
37895
|
-
},
|
|
37896
39579
|
{
|
|
37897
39580
|
kind: "magazine",
|
|
37898
39581
|
interfaces: [
|
|
37899
39582
|
"mag_box"
|
|
37900
39583
|
],
|
|
37901
39584
|
sources: [
|
|
37902
|
-
"
|
|
39585
|
+
"derived"
|
|
37903
39586
|
]
|
|
37904
39587
|
},
|
|
37905
39588
|
{
|
|
@@ -37912,62 +39595,54 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37912
39595
|
]
|
|
37913
39596
|
}
|
|
37914
39597
|
],
|
|
37915
|
-
fitted: []
|
|
37916
|
-
stock: {
|
|
37917
|
-
kind: "retract"
|
|
37918
|
-
}
|
|
39598
|
+
fitted: []
|
|
37919
39599
|
},
|
|
37920
39600
|
{
|
|
37921
|
-
id: "
|
|
37922
|
-
name: "
|
|
37923
|
-
|
|
39601
|
+
id: "winchester_1887",
|
|
39602
|
+
name: "Winchester 1887",
|
|
39603
|
+
maker: "Winchester",
|
|
39604
|
+
category: "hunting",
|
|
37924
39605
|
action: {
|
|
37925
39606
|
kind: "firearm",
|
|
37926
|
-
caliber: "
|
|
37927
|
-
rpm:
|
|
39607
|
+
caliber: "12ga_00buck",
|
|
39608
|
+
rpm: 109.09,
|
|
37928
39609
|
modes: [
|
|
37929
|
-
"
|
|
39610
|
+
"lever"
|
|
37930
39611
|
],
|
|
37931
|
-
magazine:
|
|
37932
|
-
reload:
|
|
37933
|
-
|
|
37934
|
-
spreadDeg: 0.
|
|
37935
|
-
bloomDeg: 0.
|
|
37936
|
-
recoveryDegPerS:
|
|
39612
|
+
magazine: 5,
|
|
39613
|
+
reload: 0.6,
|
|
39614
|
+
perRound: true,
|
|
39615
|
+
spreadDeg: 0.25,
|
|
39616
|
+
bloomDeg: 0.3,
|
|
39617
|
+
recoveryDegPerS: 3,
|
|
37937
39618
|
recoil: [
|
|
37938
|
-
|
|
37939
|
-
0.
|
|
39619
|
+
2.33,
|
|
39620
|
+
0.39
|
|
37940
39621
|
],
|
|
37941
|
-
range:
|
|
37942
|
-
family: "
|
|
39622
|
+
range: 800,
|
|
39623
|
+
family: "lever",
|
|
37943
39624
|
timings: {
|
|
37944
39625
|
draw: 0.35,
|
|
37945
|
-
reload:
|
|
39626
|
+
reload: 0.6,
|
|
39627
|
+
perRound: 0.6,
|
|
39628
|
+
cycle: 0.55,
|
|
37946
39629
|
clear: 1.2
|
|
37947
39630
|
}
|
|
37948
39631
|
},
|
|
37949
|
-
mass:
|
|
39632
|
+
mass: 3.6,
|
|
37950
39633
|
dimensions: {
|
|
37951
|
-
length: 1.
|
|
37952
|
-
barrel: 0.
|
|
37953
|
-
emptyMass:
|
|
39634
|
+
length: 1.016,
|
|
39635
|
+
barrel: 0.508,
|
|
39636
|
+
emptyMass: 3.6
|
|
37954
39637
|
},
|
|
37955
|
-
archetype: "
|
|
39638
|
+
archetype: "rifle_bolt_308",
|
|
39639
|
+
variantOf: "winchester_1894",
|
|
37956
39640
|
sources: [
|
|
37957
39641
|
"reference",
|
|
37958
39642
|
"derived",
|
|
37959
39643
|
"sdk"
|
|
37960
39644
|
],
|
|
37961
39645
|
mounts: [
|
|
37962
|
-
{
|
|
37963
|
-
kind: "rail_bottom",
|
|
37964
|
-
interfaces: [
|
|
37965
|
-
"bipod_stud"
|
|
37966
|
-
],
|
|
37967
|
-
sources: [
|
|
37968
|
-
"gallery"
|
|
37969
|
-
]
|
|
37970
|
-
},
|
|
37971
39646
|
{
|
|
37972
39647
|
kind: "sling",
|
|
37973
39648
|
interfaces: [
|
|
@@ -37976,62 +39651,51 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37976
39651
|
sources: [
|
|
37977
39652
|
"derived"
|
|
37978
39653
|
]
|
|
37979
|
-
},
|
|
37980
|
-
{
|
|
37981
|
-
kind: "feed",
|
|
37982
|
-
interfaces: [
|
|
37983
|
-
"belt"
|
|
37984
|
-
],
|
|
37985
|
-
sources: [
|
|
37986
|
-
"derived"
|
|
37987
|
-
]
|
|
37988
39654
|
}
|
|
37989
39655
|
],
|
|
37990
|
-
fitted: [
|
|
37991
|
-
{
|
|
37992
|
-
id: "bipod",
|
|
37993
|
-
mount: "rail_bottom"
|
|
37994
|
-
}
|
|
37995
|
-
]
|
|
39656
|
+
fitted: []
|
|
37996
39657
|
},
|
|
37997
39658
|
{
|
|
37998
|
-
id: "
|
|
37999
|
-
name: "
|
|
39659
|
+
id: "ppsh_41",
|
|
39660
|
+
name: "PPSh-41",
|
|
38000
39661
|
category: "smg",
|
|
38001
39662
|
action: {
|
|
38002
39663
|
kind: "firearm",
|
|
38003
|
-
caliber: "
|
|
38004
|
-
rpm:
|
|
39664
|
+
caliber: "7_62x25",
|
|
39665
|
+
rpm: 1250,
|
|
38005
39666
|
modes: [
|
|
38006
39667
|
"auto",
|
|
38007
39668
|
"semi"
|
|
38008
39669
|
],
|
|
38009
|
-
magazine:
|
|
38010
|
-
|
|
38011
|
-
|
|
39670
|
+
magazine: 71,
|
|
39671
|
+
magazineOptions: [
|
|
39672
|
+
35
|
|
39673
|
+
],
|
|
39674
|
+
reload: 2.9,
|
|
39675
|
+
muzzleSpeed: 488,
|
|
38012
39676
|
spreadDeg: 1.5,
|
|
38013
39677
|
bloomDeg: 0.35,
|
|
38014
39678
|
recoveryDegPerS: 6,
|
|
38015
39679
|
recoil: [
|
|
38016
|
-
0.
|
|
38017
|
-
0.
|
|
39680
|
+
0.7,
|
|
39681
|
+
0.39
|
|
38018
39682
|
],
|
|
38019
39683
|
range: 80,
|
|
38020
39684
|
family: "magazine",
|
|
38021
39685
|
timings: {
|
|
38022
39686
|
draw: 0.35,
|
|
38023
|
-
reload: 2.
|
|
39687
|
+
reload: 2.9,
|
|
38024
39688
|
clear: 1.2
|
|
38025
39689
|
}
|
|
38026
39690
|
},
|
|
38027
|
-
mass:
|
|
39691
|
+
mass: 3.63,
|
|
38028
39692
|
dimensions: {
|
|
38029
|
-
length: 0.
|
|
38030
|
-
barrel: 0.
|
|
38031
|
-
emptyMass:
|
|
38032
|
-
lengthCollapsed: 0.425
|
|
39693
|
+
length: 0.843,
|
|
39694
|
+
barrel: 0.269,
|
|
39695
|
+
emptyMass: 3.63
|
|
38033
39696
|
},
|
|
38034
39697
|
archetype: "smg_9mm",
|
|
39698
|
+
variantOf: "thompson_m1a1",
|
|
38035
39699
|
sources: [
|
|
38036
39700
|
"reference",
|
|
38037
39701
|
"derived",
|
|
@@ -38041,7 +39705,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38041
39705
|
{
|
|
38042
39706
|
kind: "magazine",
|
|
38043
39707
|
interfaces: [
|
|
38044
|
-
"
|
|
39708
|
+
"mag_drum"
|
|
38045
39709
|
],
|
|
38046
39710
|
sources: [
|
|
38047
39711
|
"gallery"
|
|
@@ -38057,53 +39721,47 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38057
39721
|
]
|
|
38058
39722
|
}
|
|
38059
39723
|
],
|
|
38060
|
-
fitted: []
|
|
38061
|
-
stock: {
|
|
38062
|
-
kind: "fold",
|
|
38063
|
-
foldAxis: "left"
|
|
38064
|
-
}
|
|
39724
|
+
fitted: []
|
|
38065
39725
|
},
|
|
38066
39726
|
{
|
|
38067
|
-
id: "
|
|
38068
|
-
name: "
|
|
38069
|
-
|
|
39727
|
+
id: "mauser_kar98k",
|
|
39728
|
+
name: "Mauser Kar98k",
|
|
39729
|
+
maker: "Mauser",
|
|
39730
|
+
category: "sniper",
|
|
38070
39731
|
action: {
|
|
38071
39732
|
kind: "firearm",
|
|
38072
|
-
caliber: "
|
|
38073
|
-
rpm:
|
|
39733
|
+
caliber: "7_92x57",
|
|
39734
|
+
rpm: 73.17,
|
|
38074
39735
|
modes: [
|
|
38075
|
-
"
|
|
38076
|
-
"semi"
|
|
38077
|
-
],
|
|
38078
|
-
magazine: 20,
|
|
38079
|
-
magazineOptions: [
|
|
38080
|
-
10
|
|
39736
|
+
"bolt"
|
|
38081
39737
|
],
|
|
39738
|
+
magazine: 5,
|
|
38082
39739
|
reload: 2.4,
|
|
38083
|
-
muzzleSpeed:
|
|
38084
|
-
spreadDeg:
|
|
38085
|
-
bloomDeg: 0.
|
|
38086
|
-
recoveryDegPerS:
|
|
39740
|
+
muzzleSpeed: 760,
|
|
39741
|
+
spreadDeg: 0.25,
|
|
39742
|
+
bloomDeg: 0.3,
|
|
39743
|
+
recoveryDegPerS: 3,
|
|
38087
39744
|
recoil: [
|
|
38088
|
-
|
|
38089
|
-
0.
|
|
39745
|
+
2.84,
|
|
39746
|
+
0.47
|
|
38090
39747
|
],
|
|
38091
|
-
range:
|
|
38092
|
-
family: "
|
|
39748
|
+
range: 800,
|
|
39749
|
+
family: "bolt",
|
|
38093
39750
|
timings: {
|
|
38094
39751
|
draw: 0.35,
|
|
38095
39752
|
reload: 2.4,
|
|
39753
|
+
cycle: 0.82,
|
|
38096
39754
|
clear: 1.2
|
|
38097
39755
|
}
|
|
38098
39756
|
},
|
|
38099
|
-
mass:
|
|
39757
|
+
mass: 3.7,
|
|
38100
39758
|
dimensions: {
|
|
38101
|
-
length:
|
|
38102
|
-
barrel: 0.
|
|
38103
|
-
emptyMass:
|
|
38104
|
-
lengthCollapsed: 0.27
|
|
39759
|
+
length: 1.11,
|
|
39760
|
+
barrel: 0.6,
|
|
39761
|
+
emptyMass: 3.7
|
|
38105
39762
|
},
|
|
38106
|
-
archetype: "
|
|
39763
|
+
archetype: "rifle_bolt_308",
|
|
39764
|
+
variantOf: "mosin_nagant_91_30",
|
|
38107
39765
|
sources: [
|
|
38108
39766
|
"reference",
|
|
38109
39767
|
"derived",
|
|
@@ -38111,14 +39769,61 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38111
39769
|
],
|
|
38112
39770
|
mounts: [
|
|
38113
39771
|
{
|
|
38114
|
-
kind: "
|
|
39772
|
+
kind: "sling",
|
|
38115
39773
|
interfaces: [
|
|
38116
|
-
"
|
|
39774
|
+
"swivel"
|
|
38117
39775
|
],
|
|
38118
39776
|
sources: [
|
|
38119
|
-
"
|
|
39777
|
+
"derived"
|
|
38120
39778
|
]
|
|
39779
|
+
}
|
|
39780
|
+
],
|
|
39781
|
+
fitted: []
|
|
39782
|
+
},
|
|
39783
|
+
{
|
|
39784
|
+
id: "mg42",
|
|
39785
|
+
name: "MG42",
|
|
39786
|
+
category: "machine_gun",
|
|
39787
|
+
action: {
|
|
39788
|
+
kind: "firearm",
|
|
39789
|
+
caliber: "7_92x57",
|
|
39790
|
+
rpm: 1200,
|
|
39791
|
+
modes: [
|
|
39792
|
+
"auto"
|
|
39793
|
+
],
|
|
39794
|
+
magazine: 50,
|
|
39795
|
+
reload: 8.5,
|
|
39796
|
+
muzzleSpeed: 740,
|
|
39797
|
+
spreadDeg: 0.8,
|
|
39798
|
+
bloomDeg: 0.35,
|
|
39799
|
+
recoveryDegPerS: 4.5,
|
|
39800
|
+
recoil: [
|
|
39801
|
+
0.75,
|
|
39802
|
+
0.4
|
|
39803
|
+
],
|
|
39804
|
+
range: 350,
|
|
39805
|
+
family: "belt",
|
|
39806
|
+
timings: {
|
|
39807
|
+
draw: 0.35,
|
|
39808
|
+
reload: 8.5,
|
|
39809
|
+
clear: 1.2
|
|
38121
39810
|
},
|
|
39811
|
+
faultFactor: 1.3
|
|
39812
|
+
},
|
|
39813
|
+
mass: 11.6,
|
|
39814
|
+
dimensions: {
|
|
39815
|
+
length: 1.22,
|
|
39816
|
+
barrel: 0.53,
|
|
39817
|
+
emptyMass: 11.6
|
|
39818
|
+
},
|
|
39819
|
+
archetype: "rifle_7_62x39",
|
|
39820
|
+
variantOf: "m60",
|
|
39821
|
+
sources: [
|
|
39822
|
+
"reference",
|
|
39823
|
+
"derived",
|
|
39824
|
+
"sdk"
|
|
39825
|
+
],
|
|
39826
|
+
mounts: [
|
|
38122
39827
|
{
|
|
38123
39828
|
kind: "sling",
|
|
38124
39829
|
interfaces: [
|
|
@@ -38129,58 +39834,52 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38129
39834
|
]
|
|
38130
39835
|
}
|
|
38131
39836
|
],
|
|
38132
|
-
fitted: []
|
|
38133
|
-
stock: {
|
|
38134
|
-
kind: "fold",
|
|
38135
|
-
foldAxis: "over"
|
|
38136
|
-
}
|
|
39837
|
+
fitted: []
|
|
38137
39838
|
},
|
|
38138
39839
|
{
|
|
38139
|
-
id: "
|
|
38140
|
-
name: "
|
|
38141
|
-
category: "
|
|
39840
|
+
id: "vss_vintorez",
|
|
39841
|
+
name: "VSS Vintorez",
|
|
39842
|
+
category: "dmr",
|
|
38142
39843
|
action: {
|
|
38143
39844
|
kind: "firearm",
|
|
38144
|
-
caliber: "
|
|
38145
|
-
rpm:
|
|
39845
|
+
caliber: "9x39",
|
|
39846
|
+
rpm: 850,
|
|
38146
39847
|
modes: [
|
|
38147
|
-
"auto"
|
|
39848
|
+
"auto",
|
|
39849
|
+
"semi"
|
|
38148
39850
|
],
|
|
38149
|
-
magazine:
|
|
38150
|
-
|
|
38151
|
-
|
|
38152
|
-
|
|
38153
|
-
upSeconds: 0.5,
|
|
38154
|
-
holdSeconds: 1
|
|
38155
|
-
},
|
|
38156
|
-
rpmRange: [
|
|
38157
|
-
2e3,
|
|
38158
|
-
6e3
|
|
39851
|
+
magazine: 10,
|
|
39852
|
+
magazineOptions: [
|
|
39853
|
+
20,
|
|
39854
|
+
30
|
|
38159
39855
|
],
|
|
39856
|
+
reload: 2.6,
|
|
39857
|
+
muzzleSpeed: 295,
|
|
39858
|
+
noise: 75,
|
|
38160
39859
|
spreadDeg: 0.8,
|
|
38161
39860
|
bloomDeg: 0.35,
|
|
38162
39861
|
recoveryDegPerS: 4.5,
|
|
38163
39862
|
recoil: [
|
|
38164
|
-
0.
|
|
38165
|
-
0.
|
|
39863
|
+
0.73,
|
|
39864
|
+
0.39
|
|
38166
39865
|
],
|
|
38167
39866
|
range: 350,
|
|
38168
|
-
family: "
|
|
39867
|
+
family: "magazine",
|
|
38169
39868
|
timings: {
|
|
38170
39869
|
draw: 0.35,
|
|
38171
|
-
reload:
|
|
39870
|
+
reload: 2.6,
|
|
39871
|
+
reloadEmpty: 3.4,
|
|
38172
39872
|
clear: 1.2
|
|
38173
39873
|
}
|
|
38174
39874
|
},
|
|
38175
|
-
mass:
|
|
39875
|
+
mass: 2.6,
|
|
38176
39876
|
dimensions: {
|
|
38177
|
-
length: 0.
|
|
38178
|
-
barrel: 0.
|
|
38179
|
-
emptyMass:
|
|
38180
|
-
barrels: 6,
|
|
38181
|
-
barrelMass: 2
|
|
39877
|
+
length: 0.894,
|
|
39878
|
+
barrel: 0.2,
|
|
39879
|
+
emptyMass: 2.6
|
|
38182
39880
|
},
|
|
38183
39881
|
archetype: "rifle_7_62x39",
|
|
39882
|
+
variantOf: "svd_dragunov",
|
|
38184
39883
|
sources: [
|
|
38185
39884
|
"reference",
|
|
38186
39885
|
"derived",
|
|
@@ -38188,9 +39887,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38188
39887
|
],
|
|
38189
39888
|
mounts: [
|
|
38190
39889
|
{
|
|
38191
|
-
kind: "
|
|
39890
|
+
kind: "muzzle",
|
|
38192
39891
|
interfaces: [
|
|
38193
|
-
"
|
|
39892
|
+
"integral"
|
|
38194
39893
|
],
|
|
38195
39894
|
sources: [
|
|
38196
39895
|
"reference"
|
|
@@ -38204,18 +39903,15 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38204
39903
|
sources: [
|
|
38205
39904
|
"derived"
|
|
38206
39905
|
]
|
|
38207
|
-
},
|
|
38208
|
-
{
|
|
38209
|
-
kind: "feed",
|
|
38210
|
-
interfaces: [
|
|
38211
|
-
"belt"
|
|
38212
|
-
],
|
|
38213
|
-
sources: [
|
|
38214
|
-
"derived"
|
|
38215
|
-
]
|
|
38216
39906
|
}
|
|
38217
39907
|
],
|
|
38218
|
-
fitted: [
|
|
39908
|
+
fitted: [
|
|
39909
|
+
{
|
|
39910
|
+
id: "integral_suppressor",
|
|
39911
|
+
mount: "muzzle",
|
|
39912
|
+
integral: true
|
|
39913
|
+
}
|
|
39914
|
+
]
|
|
38219
39915
|
}
|
|
38220
39916
|
];
|
|
38221
39917
|
var launchers_default = [
|
|
@@ -38552,6 +40248,46 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38552
40248
|
"reference",
|
|
38553
40249
|
"derived"
|
|
38554
40250
|
]
|
|
40251
|
+
},
|
|
40252
|
+
{
|
|
40253
|
+
id: "m32_mgl",
|
|
40254
|
+
name: "M32 multiple grenade launcher (Milkor MGL)",
|
|
40255
|
+
category: "launcher",
|
|
40256
|
+
action: {
|
|
40257
|
+
kind: "launcher",
|
|
40258
|
+
projectile: "m79_40mm",
|
|
40259
|
+
magazine: 6,
|
|
40260
|
+
reload: 9.2,
|
|
40261
|
+
timings: {
|
|
40262
|
+
draw: 0.35,
|
|
40263
|
+
reload: 9.2,
|
|
40264
|
+
clear: 1.2
|
|
40265
|
+
},
|
|
40266
|
+
family: "revolver",
|
|
40267
|
+
speed: 75,
|
|
40268
|
+
minArmDistance: 10,
|
|
40269
|
+
backblast: 0,
|
|
40270
|
+
recoil: [
|
|
40271
|
+
2.25,
|
|
40272
|
+
0.6
|
|
40273
|
+
]
|
|
40274
|
+
},
|
|
40275
|
+
mass: 6.68,
|
|
40276
|
+
dimensions: {
|
|
40277
|
+
length: 0.778,
|
|
40278
|
+
lengthCollapsed: 0.565,
|
|
40279
|
+
barrel: 0.3,
|
|
40280
|
+
emptyMass: 5.3
|
|
40281
|
+
},
|
|
40282
|
+
archetype: "shotgun_double_12",
|
|
40283
|
+
stock: {
|
|
40284
|
+
kind: "fold",
|
|
40285
|
+
foldAxis: "over"
|
|
40286
|
+
},
|
|
40287
|
+
sources: [
|
|
40288
|
+
"reference",
|
|
40289
|
+
"derived"
|
|
40290
|
+
]
|
|
38555
40291
|
}
|
|
38556
40292
|
];
|
|
38557
40293
|
var INSTALL_RANK = { field: 0, tool: 1, bench: 2 };
|
|
@@ -38787,6 +40523,69 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38787
40523
|
tags: [
|
|
38788
40524
|
"silent"
|
|
38789
40525
|
]
|
|
40526
|
+
},
|
|
40527
|
+
{
|
|
40528
|
+
id: "kabar",
|
|
40529
|
+
name: "KA-BAR combat knife",
|
|
40530
|
+
category: "melee_blade",
|
|
40531
|
+
action: {
|
|
40532
|
+
kind: "melee",
|
|
40533
|
+
damage: "slash",
|
|
40534
|
+
energy: 48,
|
|
40535
|
+
radius: 0.03,
|
|
40536
|
+
reach: 0.55,
|
|
40537
|
+
rpm: 100,
|
|
40538
|
+
noise: 1
|
|
40539
|
+
},
|
|
40540
|
+
mass: 0.32,
|
|
40541
|
+
sources: [
|
|
40542
|
+
"reference",
|
|
40543
|
+
"derived"
|
|
40544
|
+
]
|
|
40545
|
+
},
|
|
40546
|
+
{
|
|
40547
|
+
id: "katana",
|
|
40548
|
+
name: "Katana",
|
|
40549
|
+
category: "melee_blade",
|
|
40550
|
+
action: {
|
|
40551
|
+
kind: "melee",
|
|
40552
|
+
damage: "slash",
|
|
40553
|
+
energy: 230,
|
|
40554
|
+
radius: 0.04,
|
|
40555
|
+
reach: 1.1,
|
|
40556
|
+
rpm: 70,
|
|
40557
|
+
noise: 5
|
|
40558
|
+
},
|
|
40559
|
+
mass: 1.1,
|
|
40560
|
+
tags: [
|
|
40561
|
+
"two_handed"
|
|
40562
|
+
],
|
|
40563
|
+
sources: [
|
|
40564
|
+
"reference",
|
|
40565
|
+
"derived"
|
|
40566
|
+
]
|
|
40567
|
+
},
|
|
40568
|
+
{
|
|
40569
|
+
id: "brass_knuckles",
|
|
40570
|
+
name: "Brass knuckles",
|
|
40571
|
+
category: "melee_blunt",
|
|
40572
|
+
action: {
|
|
40573
|
+
kind: "melee",
|
|
40574
|
+
damage: "blunt",
|
|
40575
|
+
energy: 32,
|
|
40576
|
+
radius: 0.04,
|
|
40577
|
+
reach: 0.6,
|
|
40578
|
+
rpm: 120,
|
|
40579
|
+
noise: 5
|
|
40580
|
+
},
|
|
40581
|
+
mass: 0.15,
|
|
40582
|
+
tags: [
|
|
40583
|
+
"fists"
|
|
40584
|
+
],
|
|
40585
|
+
sources: [
|
|
40586
|
+
"reference",
|
|
40587
|
+
"derived"
|
|
40588
|
+
]
|
|
38790
40589
|
}
|
|
38791
40590
|
];
|
|
38792
40591
|
var findDuplicateIds = (kind, entries2) => {
|
|
@@ -38987,7 +40786,12 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38987
40786
|
improvised_spear: "Improvised spear",
|
|
38988
40787
|
chainsaw: "Chainsaw",
|
|
38989
40788
|
recurve_bow: "Recurve bow",
|
|
38990
|
-
m134: "M134 Minigun"
|
|
40789
|
+
m134: "M134 Minigun",
|
|
40790
|
+
semtex: "Semtex charge",
|
|
40791
|
+
smoke_grenade: "M18 smoke grenade",
|
|
40792
|
+
kabar: "KA-BAR combat knife",
|
|
40793
|
+
katana: "Katana",
|
|
40794
|
+
brass_knuckles: "Brass knuckles"
|
|
38991
40795
|
},
|
|
38992
40796
|
modes: modesEn,
|
|
38993
40797
|
categories: categoriesEn,
|
|
@@ -39000,6 +40804,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39000
40804
|
c4: "C4 charge",
|
|
39001
40805
|
claymore: "Claymore mine",
|
|
39002
40806
|
flashbang: "Flashbang",
|
|
40807
|
+
semtex: "Semtex charge",
|
|
40808
|
+
smoke_grenade: "M18 colored smoke grenade",
|
|
39003
40809
|
m79_40mm: "40 mm grenade",
|
|
39004
40810
|
m72_66mm: "66 mm HEAT rocket",
|
|
39005
40811
|
at4_84mm: "84 mm HEAT rocket",
|
|
@@ -39081,7 +40887,12 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39081
40887
|
improvised_spear: "lan\xE7a improvisada",
|
|
39082
40888
|
chainsaw: "motosserra",
|
|
39083
40889
|
recurve_bow: "arco recurvo",
|
|
39084
|
-
m134: "Minigun M134"
|
|
40890
|
+
m134: "Minigun M134",
|
|
40891
|
+
semtex: "Semtex com detonador",
|
|
40892
|
+
smoke_grenade: "granada de fuma\xE7a M18",
|
|
40893
|
+
kabar: "faca KA-BAR",
|
|
40894
|
+
katana: "espada katana",
|
|
40895
|
+
brass_knuckles: "soco ingl\xEAs"
|
|
39085
40896
|
},
|
|
39086
40897
|
modes: { single: "tiro \xFAnico", semi: "semiautom\xE1tico", burst: "rajada", auto: "autom\xE1tico", pump: "repeti\xE7\xE3o", bolt: "ferrolho", lever: "alavanca", break: "basculante", volley: "salva" },
|
|
39087
40898
|
categories: {
|
|
@@ -39117,6 +40928,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39117
40928
|
c4: "C4 com detonador",
|
|
39118
40929
|
claymore: "Mina Claymore",
|
|
39119
40930
|
flashbang: "Granada de luz",
|
|
40931
|
+
semtex: "Semtex com detonador",
|
|
40932
|
+
smoke_grenade: "Granada de fuma\xE7a M18",
|
|
39120
40933
|
m79_40mm: "Granada de 40 mm",
|
|
39121
40934
|
m72_66mm: "Foguete HEAT de 66 mm",
|
|
39122
40935
|
at4_84mm: "Foguete HEAT de 84 mm",
|
|
@@ -39228,6 +41041,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39228
41041
|
// the iron sights close the view in a little: more for a long gun, whose sights sit farther from the eye, than for a handgun
|
|
39229
41042
|
ironSightZoom: { pistol: 1.1, revolver: 1.1, smg: 1.2, carbine: 1.25, shotgun: 1.15, rifle: 1.3, hunting: 1.35, dmr: 1.4, sniper: 1.4, machine_gun: 1.2, launcher: 1.15, bow: 1.15, crossbow: 1.25 }
|
|
39230
41043
|
},
|
|
41044
|
+
// a weapon in each hand: the handguns, the machine pistols short and light enough for one hand, and the one-hand blades; one hand and no sight picture open the cone and lift the muzzle more
|
|
41045
|
+
dualWield: {
|
|
41046
|
+
categories: ["pistol", "revolver"],
|
|
41047
|
+
weapons: ["mini_uzi", "uzi", "mac_10", "vz61", "hk_mp7a1", "knife", "tactical_knife", "machete", "hatchet"],
|
|
41048
|
+
exclude: [],
|
|
41049
|
+
spread: 1.8,
|
|
41050
|
+
recoil: 1.35,
|
|
41051
|
+
// tucking a pistol in the belt and drawing it back is a short motion of one hand
|
|
41052
|
+
stowSeconds: 0.45
|
|
41053
|
+
},
|
|
39231
41054
|
// Arsenal §08/§11: coronha retrátil saca mais rápido, mais recuo; os números são padrões aprovados pelo dono (2026-10-24)
|
|
39232
41055
|
stock: {
|
|
39233
41056
|
seconds: 0.6,
|
|
@@ -39390,7 +41213,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39390
41213
|
destructionLevel: def.destructionLevel,
|
|
39391
41214
|
...def.cone ? { cone: def.cone } : {},
|
|
39392
41215
|
...def.stunSeconds !== void 0 ? { stunSeconds: def.stunSeconds } : {},
|
|
39393
|
-
...def.fire ? { fire: def.fire } : {}
|
|
41216
|
+
...def.fire ? { fire: def.fire } : {},
|
|
41217
|
+
...def.smoke ? { smoke: def.smoke } : {}
|
|
39394
41218
|
};
|
|
39395
41219
|
return { type: "detonate", at: at3, detonation };
|
|
39396
41220
|
}
|
|
@@ -39650,6 +41474,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39650
41474
|
return roll.ammoQuality.faultChance > 0 && roll.random() < roll.ammoQuality.faultChance ? "misfire" : null;
|
|
39651
41475
|
};
|
|
39652
41476
|
var isDudWithoutJam = (action, fault) => fault === "misfire" && action.kind === "firearm" && MISFIRE_ONLY.has(action.family);
|
|
41477
|
+
var ONE_HAND = { spread: 1, recoil: 1 };
|
|
39653
41478
|
var activeParts = (fitted, catalogue) => fitted.flatMap((part) => {
|
|
39654
41479
|
const def = catalogue.get(part.id);
|
|
39655
41480
|
const isOn = def?.kind !== "light" && def?.kind !== "laser" ? true : part.on === true;
|
|
@@ -39716,12 +41541,13 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39716
41541
|
const read = (name, base) => stat(name, base, sources, active);
|
|
39717
41542
|
const mass = read("mass", def.mass + parts.reduce((total, part) => total + part.mass, 0) - factory.reduce((total, part) => total + part.mass, 0));
|
|
39718
41543
|
const hipFactor = context.aiming ? 1 : 1 + (context.rules.aim.hipSpread - 1) * read("hipSpreadExcess", 1);
|
|
41544
|
+
const dual = context.dualWield && context.rules.dualWield ? context.rules.dualWield : ONE_HAND;
|
|
39719
41545
|
let action = def.action;
|
|
39720
41546
|
if (firearm) {
|
|
39721
41547
|
const baseNoise = firearm.noise ?? context.caliber?.noise;
|
|
39722
41548
|
const effects = {
|
|
39723
|
-
spread: read("spread", firearm.spreadDeg) * hipFactor,
|
|
39724
|
-
recoil: [read("recoilVertical", firearm.recoil[0]), read("recoilHorizontal", firearm.recoil[1])],
|
|
41549
|
+
spread: read("spread", firearm.spreadDeg) * hipFactor * dual.spread,
|
|
41550
|
+
recoil: [read("recoilVertical", firearm.recoil[0]) * dual.recoil, read("recoilHorizontal", firearm.recoil[1]) * dual.recoil],
|
|
39725
41551
|
range: read("range", firearm.range),
|
|
39726
41552
|
noise: baseNoise === void 0 ? void 0 : read("noise", baseNoise),
|
|
39727
41553
|
speed,
|
|
@@ -40090,6 +41916,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
40090
41916
|
__publicField4(this, "stockState", "extended");
|
|
40091
41917
|
__publicField4(this, "aiming", false);
|
|
40092
41918
|
__publicField4(this, "supportedStance", false);
|
|
41919
|
+
__publicField4(this, "dualStance", false);
|
|
40093
41920
|
__publicField4(this, "reloadCount", 0);
|
|
40094
41921
|
__publicField4(this, "catalogue");
|
|
40095
41922
|
__publicField4(this, "isCompatible");
|
|
@@ -40137,7 +41964,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
40137
41964
|
}
|
|
40138
41965
|
resolve() {
|
|
40139
41966
|
const supported = this.supportedStance;
|
|
40140
|
-
return resolveLoadout(this.def, this.fitted, this.catalogue, { aiming: this.aiming, supported, stock: this.stockState, caliber: this.caliber, rules: this.rules });
|
|
41967
|
+
return resolveLoadout(this.def, this.fitted, this.catalogue, { aiming: this.aiming, supported, stock: this.stockState, caliber: this.caliber, rules: this.rules, dualWield: this.dualStance });
|
|
40141
41968
|
}
|
|
40142
41969
|
/** Takes the numbers of the accessories on the weapon: the action, the capacity (what no longer fits goes back to the reserve) and the draw time. */
|
|
40143
41970
|
applyLoad() {
|
|
@@ -40310,9 +42137,12 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
40310
42137
|
setStance(stance) {
|
|
40311
42138
|
const aiming = stance.aiming ?? this.aiming;
|
|
40312
42139
|
const supported = stance.supported ?? this.supportedStance;
|
|
40313
|
-
|
|
40314
|
-
|
|
42140
|
+
const dual = stance.dualWield ?? this.dualStance;
|
|
42141
|
+
const aimed = dual ? false : aiming;
|
|
42142
|
+
if (aimed === this.aiming && supported === this.supportedStance && dual === this.dualStance) return;
|
|
42143
|
+
this.aiming = aimed;
|
|
40315
42144
|
this.supportedStance = supported;
|
|
42145
|
+
this.dualStance = dual;
|
|
40316
42146
|
this.applyLoad();
|
|
40317
42147
|
}
|
|
40318
42148
|
snapshot() {
|
|
@@ -40840,6 +42670,15 @@ ${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
|
40840
42670
|
const from = [use.origin[0], use.origin[1] + wire.height, use.origin[2]];
|
|
40841
42671
|
return { from, to: [from[0] + dx * wire.length, from[1], from[2] + dz * wire.length] };
|
|
40842
42672
|
};
|
|
42673
|
+
function canDualWield(arsenal, weaponId) {
|
|
42674
|
+
const def = arsenal.weapons.get(weaponId);
|
|
42675
|
+
if (!def) return false;
|
|
42676
|
+
return isDualWieldable(arsenal.rules.dualWield, weaponId, def.category);
|
|
42677
|
+
}
|
|
42678
|
+
var isDualWieldable = (rule, weaponId, category) => {
|
|
42679
|
+
if (rule.exclude.includes(weaponId)) return false;
|
|
42680
|
+
return rule.weapons.includes(weaponId) || rule.categories.includes(category);
|
|
42681
|
+
};
|
|
40843
42682
|
var isGenericKind = (kind, category) => kind === "firearm" && category !== "bow" && category !== "crossbow" || kind === "flame";
|
|
40844
42683
|
function genericWeapons(arsenal) {
|
|
40845
42684
|
const archetypes = new Set(ARCHETYPE_IDS);
|
|
@@ -47094,6 +48933,11 @@ void main(){
|
|
|
47094
48933
|
};
|
|
47095
48934
|
|
|
47096
48935
|
// src/explosives.ts
|
|
48936
|
+
var SMOKE_PUFFS_PER_SECOND = 36;
|
|
48937
|
+
var SMOKE_PUFF_LIFE = 3.2;
|
|
48938
|
+
var SMOKE_PUFF_SPEED = 1.7;
|
|
48939
|
+
var SMOKE_PUFF_SIZE = 5;
|
|
48940
|
+
var SMOKE_PUFF_ALPHA = 1.5;
|
|
47097
48941
|
var CONE_BLAST_RADIUS = 0.5;
|
|
47098
48942
|
var summarizeBlast = (results) => {
|
|
47099
48943
|
const reports = results.flatMap((r) => r.blast ? [r.blast] : []);
|
|
@@ -47109,6 +48953,8 @@ void main(){
|
|
|
47109
48953
|
function createExplosives(context) {
|
|
47110
48954
|
const { THREE, scene: scene2, camera: camera2, world, renderer, arsenal, translate, format, action } = context;
|
|
47111
48955
|
const projectiles = [];
|
|
48956
|
+
const smokeSources = [];
|
|
48957
|
+
const random = context.random ?? Math.random;
|
|
47112
48958
|
const meshes = [];
|
|
47113
48959
|
const up = new THREE.Vector3(0, 1, 0);
|
|
47114
48960
|
const drop = (objects) => {
|
|
@@ -47116,6 +48962,7 @@ void main(){
|
|
|
47116
48962
|
releaseObject3D(objects, { keep: scene2 });
|
|
47117
48963
|
};
|
|
47118
48964
|
const clear = () => {
|
|
48965
|
+
smokeSources.length = 0;
|
|
47119
48966
|
projectiles.length = 0;
|
|
47120
48967
|
drop(meshes);
|
|
47121
48968
|
meshes.length = 0;
|
|
@@ -47282,6 +49129,12 @@ void main(){
|
|
|
47282
49129
|
const detonate = (projectile, detonation) => {
|
|
47283
49130
|
const weaponName = context.toolName(projectile.weapon);
|
|
47284
49131
|
const reach = Math.max(detonation.injuryRadius, detonation.lethalRadius);
|
|
49132
|
+
if (detonation.smoke) {
|
|
49133
|
+
const [shortest, longest] = detonation.smoke.seconds;
|
|
49134
|
+
smokeSources.push({ point: detonation.point, left: shortest + (longest - shortest) * random(), owed: 0, color: detonation.smoke.color });
|
|
49135
|
+
action("smoke", translate("act.smoke", { weapon: weaponName, seconds: format(smokeSources[smokeSources.length - 1].left, 0) }), { data: { weapon: projectile.weapon, explosive: detonation.explosive, point: detonation.point } });
|
|
49136
|
+
return;
|
|
49137
|
+
}
|
|
47285
49138
|
const results = detonation.energy <= 0 || detonation.cone ? [] : world.explode(detonation.point, detonation.energy, reach, "player", context.blast());
|
|
47286
49139
|
const reached = detonation.energy <= 0 ? 0 : detonation.cone ? coneBlast(detonation) : results.length;
|
|
47287
49140
|
if (!detonation.cone) told(results);
|
|
@@ -47403,7 +49256,22 @@ void main(){
|
|
|
47403
49256
|
action("tripwire", translate("act.tripwire", { weapon: context.toolName(projectile.weapon), who: crosser }), { data: { weapon: projectile.weapon, body: crosser } });
|
|
47404
49257
|
detonate(projectile, event.detonation);
|
|
47405
49258
|
};
|
|
49259
|
+
const burnSmoke = (dt) => {
|
|
49260
|
+
for (let index = smokeSources.length - 1; index >= 0; index--) {
|
|
49261
|
+
const source = smokeSources[index];
|
|
49262
|
+
source.left -= dt;
|
|
49263
|
+
source.owed += SMOKE_PUFFS_PER_SECOND * dt;
|
|
49264
|
+
for (; source.owed >= 1; source.owed -= 1) {
|
|
49265
|
+
const angle = random() * Math.PI * 2;
|
|
49266
|
+
const speed = SMOKE_PUFF_SPEED * (0.4 + random());
|
|
49267
|
+
const velocity = [Math.cos(angle) * speed, 0.5 + random() * 0.8, Math.sin(angle) * speed];
|
|
49268
|
+
context.effects.spawn("smoke", [source.point[0], source.point[1] + 0.08, source.point[2]], velocity, { color: source.color, size: SMOKE_PUFF_SIZE, life: SMOKE_PUFF_LIFE, alpha: SMOKE_PUFF_ALPHA });
|
|
49269
|
+
}
|
|
49270
|
+
if (source.left <= 0) smokeSources.splice(index, 1);
|
|
49271
|
+
}
|
|
49272
|
+
};
|
|
47406
49273
|
const update = (dt) => {
|
|
49274
|
+
burnSmoke(dt);
|
|
47407
49275
|
for (let index = projectiles.length - 1; index >= 0; index--) {
|
|
47408
49276
|
const projectile = projectiles[index];
|
|
47409
49277
|
if (!projectile) continue;
|
|
@@ -47424,7 +49292,7 @@ void main(){
|
|
|
47424
49292
|
}
|
|
47425
49293
|
}
|
|
47426
49294
|
};
|
|
47427
|
-
return { throwUse, placeUse, backblastUse, detonateCharges, blastAt, update, clear };
|
|
49295
|
+
return { throwUse, placeUse, backblastUse, detonateCharges, blastAt, update, clear, smokeLeft: () => smokeSources.map((source) => source.left) };
|
|
47428
49296
|
}
|
|
47429
49297
|
|
|
47430
49298
|
// src/test-table.ts
|
|
@@ -47638,6 +49506,65 @@ void main(){
|
|
|
47638
49506
|
}
|
|
47639
49507
|
};
|
|
47640
49508
|
|
|
49509
|
+
// src/dual-reload.ts
|
|
49510
|
+
var otherHand = (hand) => hand === "R" ? "L" : "R";
|
|
49511
|
+
function createDualReload(host, stowSeconds) {
|
|
49512
|
+
let queue = [];
|
|
49513
|
+
let current = null;
|
|
49514
|
+
const next = () => {
|
|
49515
|
+
let hand = queue.shift();
|
|
49516
|
+
while (hand && !host.needs(hand)) hand = queue.shift();
|
|
49517
|
+
if (!hand) {
|
|
49518
|
+
current = null;
|
|
49519
|
+
return;
|
|
49520
|
+
}
|
|
49521
|
+
const seconds = stowSeconds();
|
|
49522
|
+
current = { hand, phase: "stow", left: seconds };
|
|
49523
|
+
host.stow(otherHand(hand), true, seconds);
|
|
49524
|
+
};
|
|
49525
|
+
const draw2 = (hand) => {
|
|
49526
|
+
const seconds = stowSeconds();
|
|
49527
|
+
current = { hand, phase: "draw", left: seconds };
|
|
49528
|
+
host.stow(otherHand(hand), false, seconds);
|
|
49529
|
+
};
|
|
49530
|
+
return {
|
|
49531
|
+
start(order) {
|
|
49532
|
+
if (current) return;
|
|
49533
|
+
queue = [...order];
|
|
49534
|
+
next();
|
|
49535
|
+
},
|
|
49536
|
+
step(dt) {
|
|
49537
|
+
if (!current) return;
|
|
49538
|
+
if (current.phase === "reload") {
|
|
49539
|
+
if (!host.reloading(current.hand)) draw2(current.hand);
|
|
49540
|
+
return;
|
|
49541
|
+
}
|
|
49542
|
+
current.left -= dt;
|
|
49543
|
+
if (current.left > 0) return;
|
|
49544
|
+
if (current.phase === "draw") {
|
|
49545
|
+
next();
|
|
49546
|
+
return;
|
|
49547
|
+
}
|
|
49548
|
+
current.phase = "reload";
|
|
49549
|
+
if (!host.startReload(current.hand)) draw2(current.hand);
|
|
49550
|
+
},
|
|
49551
|
+
get busy() {
|
|
49552
|
+
return current !== null;
|
|
49553
|
+
},
|
|
49554
|
+
get current() {
|
|
49555
|
+
return current ? { hand: current.hand, phase: current.phase } : null;
|
|
49556
|
+
},
|
|
49557
|
+
stowed(hand) {
|
|
49558
|
+
return current !== null && current.phase !== "draw" && otherHand(current.hand) === hand;
|
|
49559
|
+
},
|
|
49560
|
+
cancel() {
|
|
49561
|
+
if (current && current.phase !== "draw") host.stow(otherHand(current.hand), false, 0);
|
|
49562
|
+
current = null;
|
|
49563
|
+
queue = [];
|
|
49564
|
+
}
|
|
49565
|
+
};
|
|
49566
|
+
}
|
|
49567
|
+
|
|
47641
49568
|
// src/loading-view.ts
|
|
47642
49569
|
var LOADING_CLASS = "tr-loading";
|
|
47643
49570
|
var LOADING_CSS = [
|
|
@@ -49644,6 +51571,10 @@ void main(){
|
|
|
49644
51571
|
o.hooks.primaryDown();
|
|
49645
51572
|
};
|
|
49646
51573
|
const onMouseUp = (e) => {
|
|
51574
|
+
if (e.button === 2) {
|
|
51575
|
+
o.hooks.secondaryUp?.();
|
|
51576
|
+
return;
|
|
51577
|
+
}
|
|
49647
51578
|
if (e.button !== 0) return;
|
|
49648
51579
|
if (holdTimer) clearTimeout(holdTimer);
|
|
49649
51580
|
if (dragging) {
|
|
@@ -53517,7 +55448,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53517
55448
|
}
|
|
53518
55449
|
|
|
53519
55450
|
// src/avatar.ts
|
|
53520
|
-
var DEFAULT_STRIKE_CLIPS = { hand: "punch_right", fists: "punch_right", shove: "shove_two_hands", kick: "front_kick" };
|
|
55451
|
+
var DEFAULT_STRIKE_CLIPS = { hand: "punch_right", fists: "punch_right", brass_knuckles: "punch_right", shove: "shove_two_hands", kick: "front_kick" };
|
|
53521
55452
|
var DEFAULT_HAND_STANCES = { fists: "fists" };
|
|
53522
55453
|
var THIRD_PERSON_DEFAULTS = {
|
|
53523
55454
|
back: 3.8,
|
|
@@ -53690,6 +55621,12 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53690
55621
|
"act.clear": "Cleared the room",
|
|
53691
55622
|
"act.reset": "Repaired every object",
|
|
53692
55623
|
"act.tool": "Equipped {weapon}",
|
|
55624
|
+
"act.tool_left": "{weapon} in the left hand: left button fires the right one, right button the left one",
|
|
55625
|
+
"act.tool_left_off": "Left hand free: one weapon again",
|
|
55626
|
+
"act.stow": "{weapon} tucked against the body: the {hand} hand is free for the other magazine",
|
|
55627
|
+
"act.unstow": "{weapon} back in the {hand} hand",
|
|
55628
|
+
"hud.no_dual": "{weapon} does not go one in each hand",
|
|
55629
|
+
"hud.left": "L",
|
|
53693
55630
|
"act.shoot.hit": "{weapon}: shot, {energy} J, hit {where} at {dist} m",
|
|
53694
55631
|
"act.shoot.miss": "{weapon}: shot, {energy} J, hit nothing",
|
|
53695
55632
|
"act.shoot.pellets": "{weapon}: shot, {n} projectiles of up to {energy} J, {hits} hit {where} at {dist} m",
|
|
@@ -53719,6 +55656,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53719
55656
|
"hud.no_charges": "No charge set down waits for the remote detonator",
|
|
53720
55657
|
"blast.zone.lethal": "lethal",
|
|
53721
55658
|
"blast.zone.injury": "injury",
|
|
55659
|
+
"act.smoke": "{weapon}: smoke, burning for {seconds} s",
|
|
53722
55660
|
"act.explode": "{weapon}: exploded, {energy} J within {radius} m, {n} objects in range",
|
|
53723
55661
|
"act.molotov_fire": "{weapon}: fire on the ground, radius {radius} m for {seconds} s",
|
|
53724
55662
|
"act.tool.none": "{weapon}: nothing in reach",
|
|
@@ -53857,6 +55795,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53857
55795
|
"ui.clear_log": "Clear",
|
|
53858
55796
|
"ui.catalog": "Catalogue",
|
|
53859
55797
|
"ui.tool_menu": "Weapons",
|
|
55798
|
+
"ui.tool_menu.dual": "Shift+click: one in each hand",
|
|
53860
55799
|
"ui.tool_menu.search": "Search weapons and tools",
|
|
53861
55800
|
"ui.tool_menu.close": "Close",
|
|
53862
55801
|
"ui.tool_menu.results": "{n} found",
|
|
@@ -54060,6 +55999,12 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54060
55999
|
"act.clear": "Limpou a sala",
|
|
54061
56000
|
"act.reset": "Consertou todos os objetos",
|
|
54062
56001
|
"act.tool": "Equipou {weapon}",
|
|
56002
|
+
"act.tool_left": "{weapon} na m\xE3o esquerda: bot\xE3o esquerdo dispara a da direita, bot\xE3o direito a da esquerda",
|
|
56003
|
+
"act.tool_left_off": "M\xE3o esquerda livre: uma arma de novo",
|
|
56004
|
+
"act.stow": "{weapon} encostada no corpo: a m\xE3o {hand} fica livre para o outro carregador",
|
|
56005
|
+
"act.unstow": "{weapon} de volta na m\xE3o {hand}",
|
|
56006
|
+
"hud.no_dual": "{weapon} n\xE3o vai uma em cada m\xE3o",
|
|
56007
|
+
"hud.left": "E",
|
|
54063
56008
|
"act.shoot.hit": "{weapon}: disparo, {energy} J, acertou {where} a {dist} m",
|
|
54064
56009
|
"act.shoot.miss": "{weapon}: disparo, {energy} J, n\xE3o acertou nada",
|
|
54065
56010
|
"act.shoot.pellets": "{weapon}: disparo, {n} proj\xE9teis de at\xE9 {energy} J, {hits} acertaram {where} a {dist} m",
|
|
@@ -54089,6 +56034,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54089
56034
|
"hud.no_charges": "Nenhuma carga posta espera o detonador",
|
|
54090
56035
|
"blast.zone.lethal": "letal",
|
|
54091
56036
|
"blast.zone.injury": "de ferimento",
|
|
56037
|
+
"act.smoke": "{weapon}: fuma\xE7a, queima por {seconds} s",
|
|
54092
56038
|
"act.explode": "{weapon}: explodiu, {energy} J em {radius} m, {n} objetos ao alcance",
|
|
54093
56039
|
"act.molotov_fire": "{weapon}: fogo no ch\xE3o, raio de {radius} m por {seconds} s",
|
|
54094
56040
|
"act.tool.none": "{weapon}: nada ao alcance",
|
|
@@ -54227,6 +56173,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54227
56173
|
"ui.clear_log": "Limpar",
|
|
54228
56174
|
"ui.catalog": "Cat\xE1logo",
|
|
54229
56175
|
"ui.tool_menu": "Armas",
|
|
56176
|
+
"ui.tool_menu.dual": "Shift+clique: uma em cada m\xE3o",
|
|
54230
56177
|
"ui.tool_menu.search": "Buscar armas e ferramentas",
|
|
54231
56178
|
"ui.tool_menu.close": "Fechar",
|
|
54232
56179
|
"ui.tool_menu.results": "{n} encontradas",
|
|
@@ -54435,6 +56382,27 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54435
56382
|
return wrap;
|
|
54436
56383
|
};
|
|
54437
56384
|
let playhead = null;
|
|
56385
|
+
const sheetImage = (image) => {
|
|
56386
|
+
const figure = mk("figure", "tr-sheet-image");
|
|
56387
|
+
const picture = mk("img");
|
|
56388
|
+
picture.src = image.url;
|
|
56389
|
+
picture.alt = image.alt;
|
|
56390
|
+
picture.loading = "lazy";
|
|
56391
|
+
picture.referrerPolicy = "no-referrer";
|
|
56392
|
+
figure.appendChild(picture);
|
|
56393
|
+
if (image.credit || image.page) {
|
|
56394
|
+
const caption = mk("figcaption", "sub", image.credit ?? "");
|
|
56395
|
+
if (image.page) {
|
|
56396
|
+
const link = mk("a", void 0, image.credit ? " \u2197" : image.page);
|
|
56397
|
+
link.href = image.page;
|
|
56398
|
+
link.target = "_blank";
|
|
56399
|
+
link.rel = "noopener noreferrer";
|
|
56400
|
+
caption.appendChild(link);
|
|
56401
|
+
}
|
|
56402
|
+
figure.appendChild(caption);
|
|
56403
|
+
}
|
|
56404
|
+
return figure;
|
|
56405
|
+
};
|
|
54438
56406
|
const sheetCard = (sheet) => {
|
|
54439
56407
|
const card = mk("div", "tr-sheet");
|
|
54440
56408
|
if (sheet.kicker) card.appendChild(mk("div", "sub", sheet.kicker));
|
|
@@ -54486,6 +56454,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54486
56454
|
playhead = { node: head, metric, end: end3 };
|
|
54487
56455
|
card.appendChild(strip);
|
|
54488
56456
|
}
|
|
56457
|
+
if (sheet.image) card.appendChild(sheetImage(sheet.image));
|
|
54489
56458
|
if (sheet.note) card.appendChild(mk("p", "sub", sheet.note));
|
|
54490
56459
|
return card;
|
|
54491
56460
|
};
|
|
@@ -54719,7 +56688,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54719
56688
|
const close = mk3("button", "tr-btn", "\xD7");
|
|
54720
56689
|
close.type = "button";
|
|
54721
56690
|
close.title = o.t("ui.tool_menu.close");
|
|
54722
|
-
header.append(mk3("h3", void 0, o.t("ui.tool_menu")), search, close);
|
|
56691
|
+
header.append(mk3("h3", void 0, o.t("ui.tool_menu")), mk3("small", "tr-hint", o.t("ui.tool_menu.dual")), search, close);
|
|
54723
56692
|
const tabs = mk3("div", "tr-tabs");
|
|
54724
56693
|
const body = mk3("div", "tr-wmenu-body");
|
|
54725
56694
|
element.append(header, tabs, body);
|
|
@@ -54727,15 +56696,17 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54727
56696
|
let activeGroup = "";
|
|
54728
56697
|
let groups = [];
|
|
54729
56698
|
const toolButton = (tool, group) => {
|
|
54730
|
-
const
|
|
56699
|
+
const left = o.currentLeft?.() === tool.id;
|
|
56700
|
+
const button = mk3("button", tool.id === o.current() || left ? "tr-btn on" : "tr-btn");
|
|
54731
56701
|
button.type = "button";
|
|
54732
56702
|
button.title = tool.name;
|
|
56703
|
+
if (left) button.dataset.left = "";
|
|
54733
56704
|
button.dataset.tool = tool.id;
|
|
54734
56705
|
if (tool.thumbnail) button.appendChild(o.thumb(tool.thumbnail, tool.thumbnailCredit));
|
|
54735
56706
|
button.appendChild(mk3("span", void 0, tool.name));
|
|
54736
56707
|
if (group) button.appendChild(mk3("small", void 0, group));
|
|
54737
|
-
button.onclick = () => {
|
|
54738
|
-
o.onPick(tool.id);
|
|
56708
|
+
button.onclick = (event) => {
|
|
56709
|
+
o.onPick(tool.id, { second: event.shiftKey });
|
|
54739
56710
|
toggle(false);
|
|
54740
56711
|
};
|
|
54741
56712
|
return button;
|
|
@@ -54831,6 +56802,8 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54831
56802
|
.tr-prog b{display:block;font-weight:500;margin-bottom:3px}
|
|
54832
56803
|
.tr-sheet{margin-top:8px;padding:8px;border:1px solid #2a2e36;border-radius:6px;font-size:12px;line-height:1.4}
|
|
54833
56804
|
.tr-sheet h4{margin:2px 0 4px;font-size:13px}.tr-sheet p{margin:4px 0}
|
|
56805
|
+
/* the picture of a sheet floats over the scene, top centre, next to what it shows: the bench panel is too short to hold it */
|
|
56806
|
+
.tr-sheet-image{position:fixed;top:52px;left:50%;transform:translateX(-50%);width:min(400px,42vw);z-index:5;margin:0;padding:6px;background:rgba(18,20,24,.92);border:1px solid #2a2e36;border-radius:6px;pointer-events:auto}.tr-sheet-image img{display:block;width:100%;max-height:200px;object-fit:contain;background:#f4f4f2;border-radius:4px}.tr-sheet-image figcaption{margin-top:3px;font-size:11px}.tr-sheet-image a{color:#8ab4f8}
|
|
54834
56807
|
.tr-facts{display:grid;grid-template-columns:auto 1fr;gap:2px 8px;margin:4px 0}.tr-facts dt{opacity:.7}.tr-facts dd{margin:0}
|
|
54835
56808
|
.tr-steps{margin:4px 0;padding-left:16px}.tr-swatches{display:flex;flex-wrap:wrap;gap:6px}.tr-swatch i{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:4px}
|
|
54836
56809
|
.tr-timeline{position:relative;height:22px;margin:8px 0;background:#1b1e24;border-radius:4px;overflow:hidden}
|
|
@@ -54958,7 +56931,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54958
56931
|
bottom.append(held, hotbar);
|
|
54959
56932
|
let currentTool = "";
|
|
54960
56933
|
const menuOptions = o.toolMenu;
|
|
54961
|
-
const toolMenu = menuOptions ? createToolMenu({ t, groups: menuOptions.groups, current: () => currentTool, onPick: menuOptions.onPick, ...menuOptions.onOpen ? { onOpen: menuOptions.onOpen } : {}, thumb }) : null;
|
|
56934
|
+
const toolMenu = menuOptions ? createToolMenu({ t, groups: menuOptions.groups, current: () => currentTool, onPick: menuOptions.onPick, ...menuOptions.onOpen ? { onOpen: menuOptions.onOpen } : {}, ...menuOptions.currentLeft ? { currentLeft: menuOptions.currentLeft } : {}, thumb }) : null;
|
|
54962
56935
|
if (toolMenu && menuOptions) {
|
|
54963
56936
|
const menuButton = mk4("button", "tr-slot tr-menu-btn");
|
|
54964
56937
|
menuButton.type = "button";
|
|
@@ -55606,6 +57579,8 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
55606
57579
|
|
|
55607
57580
|
// src/room.ts
|
|
55608
57581
|
var FIXED_DT = 1 / 60;
|
|
57582
|
+
var LEFT_HAND_KEY = "#L";
|
|
57583
|
+
var OFF_HAND_SEED = 11;
|
|
55609
57584
|
var TOOL_MENU_KEY_LABELS = { Backquote: "'" };
|
|
55610
57585
|
var EXPLOSIVE_EFFECT_IDS = ["m67", "molotov", "pipe_bomb", "m79_40mm", "m72_66mm", "at4_84mm", "dynamite", "c4", "claymore"];
|
|
55611
57586
|
var DEFAULT_PARTICLE_LIMIT = 900;
|
|
@@ -55901,6 +57876,11 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
55901
57876
|
return s;
|
|
55902
57877
|
};
|
|
55903
57878
|
let tool = toolState(toolId);
|
|
57879
|
+
let offToolId = null;
|
|
57880
|
+
let offTool = null;
|
|
57881
|
+
let offHeld = false;
|
|
57882
|
+
let offFirst = false;
|
|
57883
|
+
let firedHand = "R";
|
|
55904
57884
|
const catalogMap = /* @__PURE__ */ new Map();
|
|
55905
57885
|
for (const i of options.catalog) catalogMap.set(i.id, i);
|
|
55906
57886
|
const catalog = [...options.catalog];
|
|
@@ -56110,9 +58090,19 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56110
58090
|
releaseTrigger();
|
|
56111
58091
|
},
|
|
56112
58092
|
secondary: () => {
|
|
58093
|
+
if (offTool && !heldEntry) {
|
|
58094
|
+
offHeld = true;
|
|
58095
|
+
offFirst = true;
|
|
58096
|
+
return;
|
|
58097
|
+
}
|
|
56113
58098
|
if (heldEntry) throwHeld();
|
|
56114
58099
|
else grab();
|
|
56115
58100
|
},
|
|
58101
|
+
secondaryUp: () => {
|
|
58102
|
+
if (!offHeld) return;
|
|
58103
|
+
offHeld = false;
|
|
58104
|
+
releaseTrigger("L");
|
|
58105
|
+
},
|
|
56116
58106
|
key: (code, down, e) => onKey(code, down, e),
|
|
56117
58107
|
wheel: (dir) => cycleTool(dir)
|
|
56118
58108
|
}
|
|
@@ -56651,6 +58641,10 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56651
58641
|
for (const listener of [...resetListeners]) listener();
|
|
56652
58642
|
tools.clear();
|
|
56653
58643
|
tool = toolState(toolId);
|
|
58644
|
+
dualReload.cancel();
|
|
58645
|
+
offTool = null;
|
|
58646
|
+
offToolId = null;
|
|
58647
|
+
firedHand = "R";
|
|
56654
58648
|
if (pristineWorld) {
|
|
56655
58649
|
for (const id of world.ids()) world.remove(id);
|
|
56656
58650
|
world.load(pristineWorld);
|
|
@@ -56916,12 +58910,13 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56916
58910
|
const pocketAt = new THREE.Vector3();
|
|
56917
58911
|
const aimTurn = new THREE.Quaternion();
|
|
56918
58912
|
const aimEuler = new THREE.Euler(0, 0, 0, "YXZ");
|
|
56919
|
-
const bodyHoldFrame = () => {
|
|
56920
|
-
const shoulder = avatar?.shoulder?.(
|
|
58913
|
+
const bodyHoldFrame = (hand = "R") => {
|
|
58914
|
+
const shoulder = avatar?.shoulder?.(hand);
|
|
56921
58915
|
if (!shoulder) return null;
|
|
56922
58916
|
shoulder.getWorldPosition(pocketAt);
|
|
56923
|
-
|
|
56924
|
-
pocketAt.
|
|
58917
|
+
const inward = hand === "L" ? -SHOULDER_POCKET_IN : SHOULDER_POCKET_IN;
|
|
58918
|
+
pocketAt.x -= Math.cos(player.yaw) * inward;
|
|
58919
|
+
pocketAt.z += Math.sin(player.yaw) * inward;
|
|
56925
58920
|
aimTurn.setFromEuler(aimEuler.set(player.pitch, player.yaw, 0, "YXZ"));
|
|
56926
58921
|
return { position: [pocketAt.x, pocketAt.y, pocketAt.z], quaternion: [aimTurn.x, aimTurn.y, aimTurn.z, aimTurn.w] };
|
|
56927
58922
|
};
|
|
@@ -57031,17 +59026,18 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57031
59026
|
rng = rng * 1664525 + 1013904223 >>> 0;
|
|
57032
59027
|
return rng / 4294967296;
|
|
57033
59028
|
};
|
|
57034
|
-
const muzzlePose = () => {
|
|
57035
|
-
const lent = muzzleSource?.();
|
|
57036
|
-
return lent ? { position: [...lent.position], drawsFlash: lent.drawsFlash } : { position: muzzle2(), drawsFlash: false };
|
|
59029
|
+
const muzzlePose = (hand = "R") => {
|
|
59030
|
+
const lent = muzzleSource?.(hand);
|
|
59031
|
+
return lent ? { position: [...lent.position], drawsFlash: lent.drawsFlash } : { position: muzzle2(hand), drawsFlash: false };
|
|
57037
59032
|
};
|
|
57038
|
-
const muzzle2 = () => {
|
|
59033
|
+
const muzzle2 = (hand = "R") => {
|
|
57039
59034
|
aim();
|
|
57040
59035
|
const e = camera2.matrixWorld.elements;
|
|
59036
|
+
const side = hand === "L" ? -0.16 : 0.16;
|
|
57041
59037
|
return [
|
|
57042
|
-
aimO[0] + aimD[0] * 0.45 + e[0] *
|
|
57043
|
-
aimO[1] + aimD[1] * 0.45 + e[1] *
|
|
57044
|
-
aimO[2] + aimD[2] * 0.45 + e[2] *
|
|
59038
|
+
aimO[0] + aimD[0] * 0.45 + e[0] * side - e[4] * 0.1,
|
|
59039
|
+
aimO[1] + aimD[1] * 0.45 + e[1] * side - e[5] * 0.1,
|
|
59040
|
+
aimO[2] + aimD[2] * 0.45 + e[2] * side - e[6] * 0.1
|
|
57045
59041
|
];
|
|
57046
59042
|
};
|
|
57047
59043
|
const tracers = [];
|
|
@@ -57221,10 +59217,10 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57221
59217
|
renderer.impulse(objectId, push2.impulse, push2.point);
|
|
57222
59218
|
}
|
|
57223
59219
|
};
|
|
57224
|
-
const fireShots = (shots, recoil) => {
|
|
59220
|
+
const fireShots = (shots, recoil, id = toolId, hand = "R") => {
|
|
57225
59221
|
if (shots.length === 0) return;
|
|
57226
|
-
const w = toolName();
|
|
57227
|
-
const { position: m, drawsFlash } = muzzlePose();
|
|
59222
|
+
const w = toolName(id);
|
|
59223
|
+
const { position: m, drawsFlash } = muzzlePose(hand);
|
|
57228
59224
|
if (!drawsFlash) {
|
|
57229
59225
|
renderer.emit("flash", m, [aimD[0], aimD[1], aimD[2]], 1, 0);
|
|
57230
59226
|
renderer.emit("sparks", m, [aimD[0], aimD[1], aimD[2]], 4, 6);
|
|
@@ -57263,7 +59259,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57263
59259
|
objectId: f?.object,
|
|
57264
59260
|
itemId: f ? entryOf(f.object)?.so.itemId : void 0,
|
|
57265
59261
|
part: f?.part,
|
|
57266
|
-
data: { weapon:
|
|
59262
|
+
data: { weapon: id, shots: shots.length, hits, energyJ: Math.round(energy), caliberMm: shots[0].caliber, distanceM: f ? Math.round(f.distance * 100) / 100 : null, ...hand === "L" ? { hand } : {} }
|
|
57267
59263
|
});
|
|
57268
59264
|
};
|
|
57269
59265
|
const fireRays = (u) => {
|
|
@@ -57367,7 +59363,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57367
59363
|
const kickLeg = options.kickLeg ?? "alternate";
|
|
57368
59364
|
let nextLeg = "right";
|
|
57369
59365
|
const punchHand = options.punchHand ?? "alternate";
|
|
57370
|
-
const punchTools = new Set(options.punchTools ?? ["hand", "fists"]);
|
|
59366
|
+
const punchTools = new Set(options.punchTools ?? ["hand", "fists", "brass_knuckles"]);
|
|
57371
59367
|
let nextHand = "right";
|
|
57372
59368
|
const combo = options.strikeCombo;
|
|
57373
59369
|
let comboOn = !!combo && options.strikeComboOn === true;
|
|
@@ -57381,16 +59377,16 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57381
59377
|
action("combo", t(on ? "act.combo.on" : "act.combo.off", { name }), { data: { combo: combo.id, on } });
|
|
57382
59378
|
say(t(on ? "act.combo.on" : "act.combo.off", { name }));
|
|
57383
59379
|
};
|
|
57384
|
-
const strikeUse = (u, id = toolId) => {
|
|
59380
|
+
const strikeUse = (u, id = toolId, side) => {
|
|
57385
59381
|
const stepIndex = comboOn && combo?.tools.includes(id) && combo.steps.length > 0 ? simTime - comboAt > combo.reset ? 0 : comboNext : null;
|
|
57386
59382
|
const step2 = stepIndex === null ? void 0 : combo.steps[stepIndex];
|
|
57387
59383
|
const clip = step2 ? step2.clip : strikeClips[id];
|
|
57388
59384
|
const leg = id === "kick" ? kickLeg === "alternate" ? nextLeg : kickLeg : void 0;
|
|
57389
|
-
const hand = step2 ? step2.hand : punchTools.has(id) ? punchHand === "alternate" ? nextHand : punchHand : void 0;
|
|
57390
|
-
const
|
|
57391
|
-
const seconds = clip === void 0 ? null : avatar?.strike?.(clip,
|
|
59385
|
+
const hand = side ? side.hand : step2 ? step2.hand : punchTools.has(id) ? punchHand === "alternate" ? nextHand : punchHand : void 0;
|
|
59386
|
+
const limb = leg ? { leg } : hand ? { hand } : void 0;
|
|
59387
|
+
const seconds = clip === void 0 ? null : avatar?.strike?.(clip, limb) ?? null;
|
|
57392
59388
|
if (leg && seconds !== null && kickLeg === "alternate") nextLeg = leg === "right" ? "left" : "right";
|
|
57393
|
-
if (!step2 && hand && seconds !== null && punchHand === "alternate") nextHand = hand === "right" ? "left" : "right";
|
|
59389
|
+
if (!step2 && !side && hand && seconds !== null && punchHand === "alternate") nextHand = hand === "right" ? "left" : "right";
|
|
57394
59390
|
if (step2 && stepIndex !== null) {
|
|
57395
59391
|
comboNext = (stepIndex + 1) % combo.steps.length;
|
|
57396
59392
|
comboAt = simTime;
|
|
@@ -57411,7 +59407,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57411
59407
|
data: { weapon: id, clip, impactIn: seconds, ...leg ? { leg } : {}, ...hand ? { hand } : {}, ...step2 ? { combo: combo.id, step: stepIndex } : {} }
|
|
57412
59408
|
});
|
|
57413
59409
|
strikes.push({
|
|
57414
|
-
key: id,
|
|
59410
|
+
key: side?.key ?? id,
|
|
57415
59411
|
remaining: seconds,
|
|
57416
59412
|
...swing && seconds > lead ? { swing, lead } : {},
|
|
57417
59413
|
land: () => {
|
|
@@ -57541,20 +59537,50 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57541
59537
|
say,
|
|
57542
59538
|
projectileModel: options.projectileModel
|
|
57543
59539
|
});
|
|
57544
|
-
const
|
|
59540
|
+
const toolOf = (hand) => hand === "L" ? offTool && offToolId ? { id: offToolId, state: offTool } : null : { id: toolId, state: tool };
|
|
59541
|
+
const dualReload = createDualReload(
|
|
59542
|
+
{
|
|
59543
|
+
needs: (hand) => {
|
|
59544
|
+
const state = toolOf(hand)?.state;
|
|
59545
|
+
return state !== void 0 && (state.def.action.kind === "firearm" || state.def.action.kind === "launcher") && state.ammo < state.capacity && state.reserve > 0;
|
|
59546
|
+
},
|
|
59547
|
+
startReload: (hand) => startReload(hand),
|
|
59548
|
+
reloading: (hand) => toolOf(hand)?.state.reloading ?? false,
|
|
59549
|
+
stow: (hand, on, seconds) => {
|
|
59550
|
+
const slot2 = toolOf(hand);
|
|
59551
|
+
if (!slot2) return;
|
|
59552
|
+
if (on) slot2.state.release();
|
|
59553
|
+
emitHost({ type: "stow", weapon: slot2.id, on, duration: seconds, ...hand === "L" ? { hand } : {} });
|
|
59554
|
+
action("stow", t(on ? "act.stow" : "act.unstow", { weapon: toolName(slot2.id), hand: t(hand === "L" ? "hand.left" : "hand.right") }), { data: { weapon: slot2.id, hand, on, seconds } });
|
|
59555
|
+
}
|
|
59556
|
+
},
|
|
59557
|
+
() => arsenal.rules.dualWield.stowSeconds
|
|
59558
|
+
);
|
|
59559
|
+
const strikeKeyOf = (id, hand) => hand === "L" ? `${id}${LEFT_HAND_KEY}` : id;
|
|
59560
|
+
const useTool = (dt, held, hand = "R") => {
|
|
57545
59561
|
aim();
|
|
57546
|
-
const
|
|
59562
|
+
const slot2 = toolOf(hand);
|
|
59563
|
+
if (!slot2) return "cooldown";
|
|
59564
|
+
const { id, state } = slot2;
|
|
59565
|
+
if (offTool && dualReload.busy) {
|
|
59566
|
+
if (!held) say(t("hud.reloading"));
|
|
59567
|
+
return "reloading";
|
|
59568
|
+
}
|
|
59569
|
+
const cat = state.def.category;
|
|
57547
59570
|
if (cat === "hand") {
|
|
57548
59571
|
if (strikes.some((strike) => strike.key === "hand" || strike.key === "fists")) return "cooldown";
|
|
57549
59572
|
strikeUse({ kind: "melee", damage: "blunt", energy: 25, radius: 0.1, reach: 0.8, origin: [aimO[0], aimO[1], aimO[2]], direction: [aimD[0], aimD[1], aimD[2]] }, "hand");
|
|
57550
59573
|
return "ok";
|
|
57551
59574
|
}
|
|
57552
|
-
if (strikes.some((strike) => strike.key ===
|
|
57553
|
-
const res =
|
|
57554
|
-
flushEvents(
|
|
59575
|
+
if (strikes.some((strike) => strike.key === strikeKeyOf(id, hand))) return "cooldown";
|
|
59576
|
+
const res = state.trigger([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], dt, held, "player");
|
|
59577
|
+
flushEvents(id, state, res.recoil, hand);
|
|
57555
59578
|
if (res.status === "empty") {
|
|
57556
|
-
if (!
|
|
57557
|
-
|
|
59579
|
+
if (!state.reloading && state.reserve > 0) {
|
|
59580
|
+
if (offTool) dualReload.start([hand, hand === "R" ? "L" : "R"]);
|
|
59581
|
+
else startReload(hand);
|
|
59582
|
+
}
|
|
59583
|
+
say(t(state.reloading ? "hud.reloading" : "hud.empty"));
|
|
57558
59584
|
return res.status;
|
|
57559
59585
|
}
|
|
57560
59586
|
if (res.status !== "ok") {
|
|
@@ -57564,15 +59590,18 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57564
59590
|
else if (res.status === "safe") say(t("hud.safe"));
|
|
57565
59591
|
return res.status;
|
|
57566
59592
|
}
|
|
57567
|
-
|
|
59593
|
+
firedHand = hand;
|
|
59594
|
+
applyUses(res, dt, hand);
|
|
57568
59595
|
return res.status;
|
|
57569
59596
|
};
|
|
57570
|
-
const applyUses = (res, dt) => {
|
|
57571
|
-
|
|
59597
|
+
const applyUses = (res, dt, hand = "R") => {
|
|
59598
|
+
const id = toolOf(hand)?.id ?? toolId;
|
|
59599
|
+
if (res.shots.length) fireShots(res.shots, res.recoil, id, hand);
|
|
57572
59600
|
for (const u of res.uses) {
|
|
57573
59601
|
switch (u.kind) {
|
|
57574
59602
|
case "melee":
|
|
57575
|
-
strikeUse(u);
|
|
59603
|
+
if (hand === "L") strikeUse(u, id, { hand: "left", key: strikeKeyOf(id, hand) });
|
|
59604
|
+
else strikeUse(u);
|
|
57576
59605
|
break;
|
|
57577
59606
|
case "flame":
|
|
57578
59607
|
heatRays(u, "fire");
|
|
@@ -57600,15 +59629,17 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57600
59629
|
}
|
|
57601
59630
|
}
|
|
57602
59631
|
};
|
|
57603
|
-
const releaseTrigger = () => {
|
|
57604
|
-
|
|
57605
|
-
|
|
59632
|
+
const releaseTrigger = (hand = "R") => {
|
|
59633
|
+
const slot2 = toolOf(hand);
|
|
59634
|
+
if (!slot2) return;
|
|
59635
|
+
if (!slot2.state.cooking) {
|
|
59636
|
+
slot2.state.release();
|
|
57606
59637
|
return;
|
|
57607
59638
|
}
|
|
57608
59639
|
aim();
|
|
57609
|
-
const res =
|
|
57610
|
-
flushEvents(
|
|
57611
|
-
if (res) applyUses(res, 0);
|
|
59640
|
+
const res = slot2.state.release([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]]);
|
|
59641
|
+
flushEvents(slot2.id, slot2.state, void 0, hand);
|
|
59642
|
+
if (res) applyUses(res, 0, hand);
|
|
57612
59643
|
};
|
|
57613
59644
|
const kick = () => {
|
|
57614
59645
|
if (!arsenal.weapons.has("kick") || strikes.some((strike) => strike.key === "kick")) return false;
|
|
@@ -57637,8 +59668,43 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57637
59668
|
}));
|
|
57638
59669
|
};
|
|
57639
59670
|
const toggleToolMenu = (open) => ui?.toolMenu(open) ?? false;
|
|
59671
|
+
const dropOffTool = () => {
|
|
59672
|
+
if (!offTool) return;
|
|
59673
|
+
releaseTrigger("L");
|
|
59674
|
+
offTool = null;
|
|
59675
|
+
offToolId = null;
|
|
59676
|
+
offHeld = false;
|
|
59677
|
+
offFirst = false;
|
|
59678
|
+
dualReload.cancel();
|
|
59679
|
+
firedHand = "R";
|
|
59680
|
+
tool.setStance({ dualWield: false });
|
|
59681
|
+
action("tool_left", t("act.tool_left_off"), { data: { hand: "L" } });
|
|
59682
|
+
emitHost({ type: "tool", weapon: "", hand: "L" });
|
|
59683
|
+
};
|
|
59684
|
+
const setOffTool = (id) => {
|
|
59685
|
+
if (id === null) {
|
|
59686
|
+
dropOffTool();
|
|
59687
|
+
return true;
|
|
59688
|
+
}
|
|
59689
|
+
if (!arsenal.weapons.has(id)) throw new Error(`game-test-room: unknown weapon "${id}"`);
|
|
59690
|
+
if (!canDualWield(arsenal, id) || !canDualWield(arsenal, toolId)) return false;
|
|
59691
|
+
if (offTool) releaseTrigger("L");
|
|
59692
|
+
const state = arsenal.create(id, { seed: OFF_HAND_SEED, reserve: 999, ...toolSettings });
|
|
59693
|
+
state.setFuseLength(fuseLength);
|
|
59694
|
+
state.refill();
|
|
59695
|
+
state.setStance({ dualWield: true });
|
|
59696
|
+
tool.setStance({ dualWield: true });
|
|
59697
|
+
offTool = state;
|
|
59698
|
+
offToolId = id;
|
|
59699
|
+
dualReload.cancel();
|
|
59700
|
+
action("tool_left", t("act.tool_left", { weapon: toolName(id) }), { data: { weapon: id, hand: "L" } });
|
|
59701
|
+
state.draw();
|
|
59702
|
+
flushEvents(id, state, void 0, "L");
|
|
59703
|
+
return true;
|
|
59704
|
+
};
|
|
57640
59705
|
const setTool = (id) => {
|
|
57641
59706
|
if (!arsenal.weapons.has(id)) throw new Error(`game-test-room: unknown weapon "${id}"`);
|
|
59707
|
+
dropOffTool();
|
|
57642
59708
|
releaseTrigger();
|
|
57643
59709
|
toolId = id;
|
|
57644
59710
|
const i = loadout.indexOf(id);
|
|
@@ -58131,15 +60197,13 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58131
60197
|
case "KeyR":
|
|
58132
60198
|
if (heldPiece) heldYaw += Math.PI / 8;
|
|
58133
60199
|
else {
|
|
58134
|
-
|
|
60200
|
+
reloadHands();
|
|
58135
60201
|
say(t("hud.reloading"));
|
|
58136
60202
|
}
|
|
58137
60203
|
break;
|
|
58138
|
-
case "KeyQ":
|
|
58139
|
-
|
|
58140
|
-
flushEvents(toolId, tool);
|
|
60204
|
+
case "KeyQ":
|
|
60205
|
+
cycleToolMode();
|
|
58141
60206
|
break;
|
|
58142
|
-
}
|
|
58143
60207
|
case "KeyX":
|
|
58144
60208
|
clearToolFault();
|
|
58145
60209
|
break;
|
|
@@ -58196,6 +60260,20 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58196
60260
|
if (!loadout.includes(weaponId)) loadout.push(weaponId);
|
|
58197
60261
|
setTool(weaponId);
|
|
58198
60262
|
};
|
|
60263
|
+
const pickTool = (weaponId, pick3 = { second: false }) => {
|
|
60264
|
+
if (!arsenal.weapons.has(weaponId)) return;
|
|
60265
|
+
if (!pick3.second) {
|
|
60266
|
+
equip(weaponId);
|
|
60267
|
+
return;
|
|
60268
|
+
}
|
|
60269
|
+
if (!canDualWield(arsenal, weaponId)) {
|
|
60270
|
+
equip(weaponId);
|
|
60271
|
+
say(t("hud.no_dual", { weapon: toolName(weaponId) }));
|
|
60272
|
+
return;
|
|
60273
|
+
}
|
|
60274
|
+
if (!offTool || !canDualWield(arsenal, toolId)) equip(weaponId);
|
|
60275
|
+
setOffTool(weaponId);
|
|
60276
|
+
};
|
|
58199
60277
|
let hudAimHit;
|
|
58200
60278
|
const inspectTarget = () => {
|
|
58201
60279
|
if (hudAimHit !== void 0) return hudAimHit;
|
|
@@ -58399,6 +60477,11 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58399
60477
|
s.update(dt);
|
|
58400
60478
|
flushEvents(id, s);
|
|
58401
60479
|
}
|
|
60480
|
+
if (offTool && offToolId) {
|
|
60481
|
+
offTool.update(dt);
|
|
60482
|
+
flushEvents(offToolId, offTool, void 0, "L");
|
|
60483
|
+
dualReload.step(dt);
|
|
60484
|
+
}
|
|
58402
60485
|
if (audio) {
|
|
58403
60486
|
const look = camera2.getWorldDirection(listenerDirection);
|
|
58404
60487
|
audio.setListener({ position: [camera2.position.x, camera2.position.y, camera2.position.z], yaw: Math.atan2(-look.x, -look.z) });
|
|
@@ -58444,6 +60527,10 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58444
60527
|
} else if (useHeld) useTool(dt, !useFirst);
|
|
58445
60528
|
useFirst = false;
|
|
58446
60529
|
}
|
|
60530
|
+
if ((offHeld || offFirst) && offTool && !isPaused && !push.active) {
|
|
60531
|
+
useTool(dt, !offFirst, "L");
|
|
60532
|
+
offFirst = false;
|
|
60533
|
+
}
|
|
58447
60534
|
if (!isPaused) followHeld(dt);
|
|
58448
60535
|
};
|
|
58449
60536
|
const updatePresent = (dt) => {
|
|
@@ -58470,12 +60557,18 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58470
60557
|
hudAimHit = void 0;
|
|
58471
60558
|
}
|
|
58472
60559
|
};
|
|
60560
|
+
const ammoText = (state) => {
|
|
60561
|
+
const kind = state.def.action.kind;
|
|
60562
|
+
if (kind === "firearm") return `${state.ammo}/${state.capacity}${state.reserve ? ` \xB7 ${state.reserve}` : ""}`;
|
|
60563
|
+
return kind === "hand" || kind === "melee" || kind === "tool" ? "" : `${num(state.ammo, 0)}`;
|
|
60564
|
+
};
|
|
58473
60565
|
const readHudState = () => {
|
|
58474
60566
|
const page = Math.floor(toolIndex / 10);
|
|
58475
60567
|
const slots = loadout.slice(page * 10, page * 10 + 10).map((id) => arsenal.name(id));
|
|
58476
|
-
const
|
|
60568
|
+
const left = offTool ? ammoText(offTool) : "";
|
|
60569
|
+
const ammo = `${ammoText(tool)}${left ? ` | ${t("hud.left")} ${left}` : ""}`;
|
|
58477
60570
|
return {
|
|
58478
|
-
toolName: toolName(),
|
|
60571
|
+
toolName: offToolId ? `${toolName()} + ${toolName(offToolId)}` : toolName(),
|
|
58479
60572
|
toolId,
|
|
58480
60573
|
ammo,
|
|
58481
60574
|
slots,
|
|
@@ -58665,26 +60758,53 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58665
60758
|
if (event.type === "explosion") knockPlayer(event);
|
|
58666
60759
|
for (const listener of hostListeners) listener(event);
|
|
58667
60760
|
}
|
|
58668
|
-
function flushEvents(id, state, recoil) {
|
|
60761
|
+
function flushEvents(id, state, recoil, hand = "R") {
|
|
58669
60762
|
const phase = state.phase;
|
|
58670
60763
|
for (const event of state.drain()) {
|
|
58671
60764
|
const hostEvent = toHostEvent(id, event, { ...recoil ? { recoil } : {}, phase });
|
|
58672
|
-
if (hostEvent) emitHost(hostEvent);
|
|
60765
|
+
if (hostEvent) emitHost(hand === "L" ? { ...hostEvent, hand } : hostEvent);
|
|
58673
60766
|
}
|
|
58674
60767
|
}
|
|
58675
|
-
function startReload() {
|
|
58676
|
-
|
|
58677
|
-
|
|
60768
|
+
function startReload(hand = "R") {
|
|
60769
|
+
const slot2 = toolOf(hand);
|
|
60770
|
+
if (!slot2) return false;
|
|
60771
|
+
const started = slot2.state.reload();
|
|
60772
|
+
flushEvents(slot2.id, slot2.state, void 0, hand);
|
|
60773
|
+
return started;
|
|
60774
|
+
}
|
|
60775
|
+
function reloadHands() {
|
|
60776
|
+
if (!offTool) {
|
|
60777
|
+
startReload();
|
|
60778
|
+
return;
|
|
60779
|
+
}
|
|
60780
|
+
dualReload.start(["R", "L"]);
|
|
58678
60781
|
}
|
|
60782
|
+
const commandHand = () => offTool ? firedHand : "R";
|
|
58679
60783
|
function clearToolFault() {
|
|
58680
|
-
|
|
58681
|
-
|
|
58682
|
-
|
|
60784
|
+
const order = offTool ? [firedHand, firedHand === "R" ? "L" : "R"] : ["R"];
|
|
60785
|
+
for (const hand of order) {
|
|
60786
|
+
const slot2 = toolOf(hand);
|
|
60787
|
+
if (!slot2?.state.fault || !slot2.state.clearFault()) continue;
|
|
60788
|
+
flushEvents(slot2.id, slot2.state, void 0, hand);
|
|
60789
|
+
say(t("hud.clearing"));
|
|
60790
|
+
return;
|
|
60791
|
+
}
|
|
58683
60792
|
}
|
|
58684
60793
|
function toggleSafety() {
|
|
58685
|
-
|
|
58686
|
-
|
|
58687
|
-
|
|
60794
|
+
const hand = commandHand();
|
|
60795
|
+
const slot2 = toolOf(hand);
|
|
60796
|
+
if (!slot2) return;
|
|
60797
|
+
slot2.state.setSafety(!slot2.state.safety);
|
|
60798
|
+
flushEvents(slot2.id, slot2.state, void 0, hand);
|
|
60799
|
+
say(`${t(slot2.state.safety ? "hud.safety_on" : "hud.safety_off")}${offTool ? ` (${toolName(slot2.id)}, ${t(hand === "L" ? "hand.left" : "hand.right")})` : ""}`);
|
|
60800
|
+
}
|
|
60801
|
+
function cycleToolMode() {
|
|
60802
|
+
const hand = commandHand();
|
|
60803
|
+
const slot2 = toolOf(hand);
|
|
60804
|
+
if (!slot2) return;
|
|
60805
|
+
slot2.state.cycleMode();
|
|
60806
|
+
flushEvents(slot2.id, slot2.state, void 0, hand);
|
|
60807
|
+
if (offTool) say(`${toolName(slot2.id)} (${t(hand === "L" ? "hand.left" : "hand.right")}): ${slot2.state.mode}`);
|
|
58688
60808
|
}
|
|
58689
60809
|
function runToolCommand(request) {
|
|
58690
60810
|
const work = (done) => done.ok ? { ok: true, seconds: done.seconds } : { ok: false, reason: done.reason };
|
|
@@ -58706,6 +60826,24 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58706
60826
|
return { ok: false, reason: "unknown" };
|
|
58707
60827
|
}
|
|
58708
60828
|
}
|
|
60829
|
+
const hostToolOf = (id, state) => ({
|
|
60830
|
+
weapon: id,
|
|
60831
|
+
category: state.def.category,
|
|
60832
|
+
ammo: state.ammo,
|
|
60833
|
+
capacity: state.capacity,
|
|
60834
|
+
reserve: state.reserve,
|
|
60835
|
+
reloading: state.reloading,
|
|
60836
|
+
mode: state.mode,
|
|
60837
|
+
...state.fault ? { fault: state.fault } : {},
|
|
60838
|
+
safety: state.safety,
|
|
60839
|
+
heat: state.heatLevel,
|
|
60840
|
+
attachments: state.attachments.map((part) => ({ id: part.id, mount: part.mount, ...part.integral ? { integral: true } : {}, ...part.on === void 0 ? {} : { on: part.on } })),
|
|
60841
|
+
stock: state.stock,
|
|
60842
|
+
suppressed: state.suppressed,
|
|
60843
|
+
underbarrelActive: state.underbarrelActive,
|
|
60844
|
+
mass: state.mass,
|
|
60845
|
+
aimSeconds: state.aimSeconds
|
|
60846
|
+
});
|
|
58709
60847
|
const host = {
|
|
58710
60848
|
THREE,
|
|
58711
60849
|
scene: scene2,
|
|
@@ -58732,22 +60870,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58732
60870
|
...options.blastShove ? { blastShove: options.blastShove } : {},
|
|
58733
60871
|
blastReach: (point, target, ignore) => world.blastReach(point, target, ignore ? { ignore } : {}),
|
|
58734
60872
|
tool: () => ({
|
|
58735
|
-
|
|
58736
|
-
|
|
58737
|
-
|
|
58738
|
-
capacity: tool.capacity,
|
|
58739
|
-
reserve: tool.reserve,
|
|
58740
|
-
reloading: tool.reloading,
|
|
58741
|
-
mode: tool.mode,
|
|
58742
|
-
...tool.fault ? { fault: tool.fault } : {},
|
|
58743
|
-
safety: tool.safety,
|
|
58744
|
-
heat: tool.heatLevel,
|
|
58745
|
-
attachments: tool.attachments.map((part) => ({ id: part.id, mount: part.mount, ...part.integral ? { integral: true } : {}, ...part.on === void 0 ? {} : { on: part.on } })),
|
|
58746
|
-
stock: tool.stock,
|
|
58747
|
-
suppressed: tool.suppressed,
|
|
58748
|
-
underbarrelActive: tool.underbarrelActive,
|
|
58749
|
-
mass: tool.mass,
|
|
58750
|
-
aimSeconds: tool.aimSeconds
|
|
60873
|
+
...hostToolOf(toolId, tool),
|
|
60874
|
+
...dualReload.stowed("R") ? { stowed: true } : {},
|
|
60875
|
+
...offTool && offToolId ? { offHand: { ...hostToolOf(offToolId, offTool), ...dualReload.stowed("L") ? { stowed: true } : {} } } : {}
|
|
58751
60876
|
}),
|
|
58752
60877
|
command(request) {
|
|
58753
60878
|
const result2 = runToolCommand(request);
|
|
@@ -58784,7 +60909,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58784
60909
|
onFrame(update, frameOptions) {
|
|
58785
60910
|
return scheduler.add((ctx) => update(ctx.dt), { phase: frameOptions?.phase ?? "lateSimulate", order: frameOptions?.order ?? 0, id: `module.frame#${moduleFrameCount++}` });
|
|
58786
60911
|
},
|
|
58787
|
-
holdFrame: () => bodyHoldFrame(),
|
|
60912
|
+
holdFrame: (hand) => bodyHoldFrame(hand),
|
|
58788
60913
|
reachFor(reach) {
|
|
58789
60914
|
if (!avatar) {
|
|
58790
60915
|
reach.onGrip?.();
|
|
@@ -59160,6 +61285,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
59160
61285
|
fluids,
|
|
59161
61286
|
film: filmBridge,
|
|
59162
61287
|
vfx: vfx.world,
|
|
61288
|
+
effects: vfx,
|
|
59163
61289
|
fluidRenderer: fluidView,
|
|
59164
61290
|
audio,
|
|
59165
61291
|
environment,
|
|
@@ -59175,6 +61301,29 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
59175
61301
|
clear,
|
|
59176
61302
|
resetAll,
|
|
59177
61303
|
setTool,
|
|
61304
|
+
setOffTool,
|
|
61305
|
+
get offTool() {
|
|
61306
|
+
return offTool;
|
|
61307
|
+
},
|
|
61308
|
+
useOff(hold = 0) {
|
|
61309
|
+
if (!offTool) return "cooldown";
|
|
61310
|
+
const status = useTool(FIXED_DT, false, "L");
|
|
61311
|
+
flush();
|
|
61312
|
+
let t0 = 0;
|
|
61313
|
+
while (t0 < hold) {
|
|
61314
|
+
useTool(FIXED_DT, true, "L");
|
|
61315
|
+
directStep = true;
|
|
61316
|
+
try {
|
|
61317
|
+
runHeadless(() => scheduler.advance(FIXED_DT));
|
|
61318
|
+
} finally {
|
|
61319
|
+
directStep = false;
|
|
61320
|
+
}
|
|
61321
|
+
t0 += FIXED_DT;
|
|
61322
|
+
}
|
|
61323
|
+
releaseTrigger("L");
|
|
61324
|
+
return status;
|
|
61325
|
+
},
|
|
61326
|
+
reload: () => reloadHands(),
|
|
59178
61327
|
useItem,
|
|
59179
61328
|
use(hold = 0) {
|
|
59180
61329
|
if (tool.def.category === "hand") {
|
|
@@ -59472,7 +61621,8 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
59472
61621
|
...options.toolMenu !== false ? {
|
|
59473
61622
|
toolMenu: {
|
|
59474
61623
|
groups: toolMenuGroups,
|
|
59475
|
-
onPick:
|
|
61624
|
+
onPick: pickTool,
|
|
61625
|
+
currentLeft: () => offToolId,
|
|
59476
61626
|
// the list takes clicks: the mouse leaves the view while it is open
|
|
59477
61627
|
onOpen: (open) => {
|
|
59478
61628
|
if (open && document.pointerLockElement) document.exitPointerLock?.();
|