@adatechnology/game-test-room 0.28.1 → 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 +2543 -281
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +429 -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 = [
|
|
@@ -37832,25 +38057,1510 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
37832
38057
|
bloomDeg: 0.35,
|
|
37833
38058
|
recoveryDegPerS: 6,
|
|
37834
38059
|
recoil: [
|
|
37835
|
-
0.72,
|
|
37836
|
-
0.4
|
|
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",
|
|
39489
|
+
sources: [
|
|
39490
|
+
"reference",
|
|
39491
|
+
"derived",
|
|
39492
|
+
"sdk"
|
|
39493
|
+
],
|
|
39494
|
+
mounts: [
|
|
39495
|
+
{
|
|
39496
|
+
kind: "rail_top",
|
|
39497
|
+
interfaces: [
|
|
39498
|
+
"picatinny"
|
|
39499
|
+
],
|
|
39500
|
+
sources: [
|
|
39501
|
+
"gallery"
|
|
39502
|
+
]
|
|
39503
|
+
},
|
|
39504
|
+
{
|
|
39505
|
+
kind: "magazine",
|
|
39506
|
+
interfaces: [
|
|
39507
|
+
"mag_box"
|
|
39508
|
+
],
|
|
39509
|
+
sources: [
|
|
39510
|
+
"derived"
|
|
39511
|
+
]
|
|
39512
|
+
},
|
|
39513
|
+
{
|
|
39514
|
+
kind: "sling",
|
|
39515
|
+
interfaces: [
|
|
39516
|
+
"swivel"
|
|
39517
|
+
],
|
|
39518
|
+
sources: [
|
|
39519
|
+
"derived"
|
|
39520
|
+
]
|
|
39521
|
+
}
|
|
39522
|
+
],
|
|
39523
|
+
fitted: []
|
|
39524
|
+
},
|
|
39525
|
+
{
|
|
39526
|
+
id: "l85a2",
|
|
39527
|
+
name: "L85A2",
|
|
39528
|
+
category: "rifle",
|
|
39529
|
+
action: {
|
|
39530
|
+
kind: "firearm",
|
|
39531
|
+
caliber: "5_56x45",
|
|
39532
|
+
rpm: 700,
|
|
39533
|
+
modes: [
|
|
39534
|
+
"auto",
|
|
39535
|
+
"semi"
|
|
39536
|
+
],
|
|
39537
|
+
magazine: 30,
|
|
39538
|
+
reload: 2.8,
|
|
39539
|
+
muzzleSpeed: 940,
|
|
39540
|
+
spreadDeg: 0.6,
|
|
39541
|
+
bloomDeg: 0.25,
|
|
39542
|
+
recoveryDegPerS: 5,
|
|
39543
|
+
recoil: [
|
|
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) {
|
|
@@ -51106,6 +53037,8 @@ void main(){
|
|
|
51106
53037
|
{ id: "shallow_water", water: { liquid: "water", depth: 0.3, drag: 0.65, blowShare: WATER_BLOW_SHARE }, strata: [{ material: "mud", thickness: 0.15 }, { material: "soil", thickness: 1.5 }, { material: "stone", thickness: 0.5 }] }
|
|
51107
53038
|
];
|
|
51108
53039
|
var DEFAULT_BAR_YIELD_JOULES = 24e5;
|
|
53040
|
+
var DEFAULT_BAR_DIAMETER = 0.01;
|
|
53041
|
+
var DEFAULT_BAR_YIELD_PA = 5e8;
|
|
51109
53042
|
var DEFAULT_PROFILE = "concrete_slab";
|
|
51110
53043
|
function createRandom(seed) {
|
|
51111
53044
|
let state = seed | 0;
|
|
@@ -51387,6 +53320,7 @@ void main(){
|
|
|
51387
53320
|
var RIGID_WIDENING = 2.5;
|
|
51388
53321
|
var COLLAPSE_DEPTH_SHARE = 0.75;
|
|
51389
53322
|
var COLLAPSE_SPREAD_BEND = 0.5;
|
|
53323
|
+
var BARS_SHARE_REACH = 0.6;
|
|
51390
53324
|
var RIM_REACH = 1.45;
|
|
51391
53325
|
var FLAME_MINIMUM = 200;
|
|
51392
53326
|
var FLAME_REACH = 0.6;
|
|
@@ -51906,19 +53840,95 @@ void main(){
|
|
|
51906
53840
|
}
|
|
51907
53841
|
}
|
|
51908
53842
|
}
|
|
51909
|
-
if (collapsed)
|
|
51910
|
-
|
|
51911
|
-
|
|
51912
|
-
|
|
51913
|
-
|
|
51914
|
-
|
|
51915
|
-
|
|
51916
|
-
|
|
51917
|
-
|
|
53843
|
+
if (collapsed) giveWay({ x, z, reach, profile });
|
|
53844
|
+
return collapsed;
|
|
53845
|
+
}
|
|
53846
|
+
function giveWay(spec) {
|
|
53847
|
+
const { x, z, reach, profile } = spec;
|
|
53848
|
+
emitDeform(x, z, reach);
|
|
53849
|
+
if (profile.drop === void 0) return;
|
|
53850
|
+
const limit = maxDepthOfProfile(profile);
|
|
53851
|
+
const column0 = clampIndex(Math.floor((x - reach - x0) / cellSize), columns);
|
|
53852
|
+
const column1 = clampIndex(Math.ceil((x + reach - x0) / cellSize), columns);
|
|
53853
|
+
const row0 = clampIndex(Math.floor((z - reach - z0) / cellSize), rows);
|
|
53854
|
+
const row1 = clampIndex(Math.ceil((z + reach - z0) / cellSize), rows);
|
|
53855
|
+
for (let row = row0; row <= row1; row++) {
|
|
53856
|
+
for (let column = column0; column <= column1; column++) {
|
|
53857
|
+
const index = row * stride + column;
|
|
53858
|
+
if (barBend[index] >= COLLAPSE_SPREAD_BEND && dug[index] < limit + profile.drop) {
|
|
53859
|
+
dug[index] = limit + profile.drop;
|
|
53860
|
+
touchVertex(column, row);
|
|
51918
53861
|
}
|
|
51919
53862
|
}
|
|
51920
53863
|
}
|
|
51921
|
-
|
|
53864
|
+
}
|
|
53865
|
+
function barsOf(profile) {
|
|
53866
|
+
const bars = profile.strata.find((stratum) => stratum.reinforcement);
|
|
53867
|
+
if (!bars?.reinforcement) return null;
|
|
53868
|
+
let cover = bars.reinforcement.cover;
|
|
53869
|
+
for (const stratum of profile.strata) {
|
|
53870
|
+
if (stratum === bars) break;
|
|
53871
|
+
cover += stratum.thickness;
|
|
53872
|
+
}
|
|
53873
|
+
return { stratum: bars, cover };
|
|
53874
|
+
}
|
|
53875
|
+
function bearAll(loads) {
|
|
53876
|
+
const bends = /* @__PURE__ */ new Map();
|
|
53877
|
+
const touched2 = [];
|
|
53878
|
+
for (const load of loads) {
|
|
53879
|
+
const spread2 = spreadLoad(load, bends);
|
|
53880
|
+
if (spread2) touched2.push({ load, ...spread2 });
|
|
53881
|
+
}
|
|
53882
|
+
let opened = false;
|
|
53883
|
+
for (const [index, bend] of bends) {
|
|
53884
|
+
if (barBend[index] >= bend) continue;
|
|
53885
|
+
barBend[index] = bend;
|
|
53886
|
+
const column = index % stride;
|
|
53887
|
+
const row = (index - column) / stride;
|
|
53888
|
+
touchVertex(column, row);
|
|
53889
|
+
const profile = profileList[profileIndex[index]];
|
|
53890
|
+
const limit = maxDepthOfProfile(profile);
|
|
53891
|
+
if (bend >= 1 && profile.drop !== void 0 && dug[index] >= limit * COLLAPSE_DEPTH_SHARE && dug[index] < limit + profile.drop) {
|
|
53892
|
+
dug[index] = limit + profile.drop;
|
|
53893
|
+
opened = true;
|
|
53894
|
+
}
|
|
53895
|
+
}
|
|
53896
|
+
if (opened) for (const { load, reach, profile } of touched2) giveWay({ x: load.x, z: load.z, reach, profile });
|
|
53897
|
+
return opened;
|
|
53898
|
+
}
|
|
53899
|
+
function spreadLoad(load, bends) {
|
|
53900
|
+
if (!contains(load.x, load.z) || load.newtons <= 0) return null;
|
|
53901
|
+
const profile = profileList[profileIndex[vertexOf(load.x, load.z).index]];
|
|
53902
|
+
const bars = barsOf(profile);
|
|
53903
|
+
if (!bars) return null;
|
|
53904
|
+
const reinforcement = bars.stratum.reinforcement;
|
|
53905
|
+
const moment = (reinforcement.yieldPa ?? DEFAULT_BAR_YIELD_PA) * (reinforcement.diameter ?? DEFAULT_BAR_DIAMETER) ** 3 / 6;
|
|
53906
|
+
const holds2 = 8 * moment / reinforcement.spacing;
|
|
53907
|
+
const footprint = load.radius * Math.SQRT2 + cellSize;
|
|
53908
|
+
const reach = Math.max(footprint, BARS_SHARE_REACH);
|
|
53909
|
+
const column0 = clampIndex(Math.floor((load.x - reach - x0) / cellSize), columns);
|
|
53910
|
+
const column1 = clampIndex(Math.ceil((load.x + reach - x0) / cellSize), columns);
|
|
53911
|
+
const row0 = clampIndex(Math.floor((load.z - reach - z0) / cellSize), rows);
|
|
53912
|
+
const row1 = clampIndex(Math.ceil((load.z + reach - z0) / cellSize), rows);
|
|
53913
|
+
const bare = [];
|
|
53914
|
+
let under = 0;
|
|
53915
|
+
let onBars = 0;
|
|
53916
|
+
for (let row = row0; row <= row1; row++) {
|
|
53917
|
+
for (let column = column0; column <= column1; column++) {
|
|
53918
|
+
const distance4 = Math.hypot(x0 + column * cellSize - load.x, z0 + row * cellSize - load.z);
|
|
53919
|
+
if (distance4 >= reach) continue;
|
|
53920
|
+
const index = row * stride + column;
|
|
53921
|
+
const isBare = dug[index] >= bars.cover;
|
|
53922
|
+
if (isBare) bare.push(index);
|
|
53923
|
+
if (distance4 >= footprint) continue;
|
|
53924
|
+
under++;
|
|
53925
|
+
if (isBare) onBars++;
|
|
53926
|
+
}
|
|
53927
|
+
}
|
|
53928
|
+
if (onBars === 0) return null;
|
|
53929
|
+
const bend = load.newtons * (onBars / under) / holds2;
|
|
53930
|
+
for (const index of bare) bends.set(index, (bends.get(index) ?? 0) + bend);
|
|
53931
|
+
return { reach, profile };
|
|
51922
53932
|
}
|
|
51923
53933
|
const maxDepthOfProfile = (profile) => maxDepthOf[indexOfProfile.get(profile.id)];
|
|
51924
53934
|
function rebarShowing(profile, depth) {
|
|
@@ -52193,6 +54203,7 @@ void main(){
|
|
|
52193
54203
|
strike,
|
|
52194
54204
|
burn,
|
|
52195
54205
|
applyHit,
|
|
54206
|
+
bear: bearAll,
|
|
52196
54207
|
onDeform(listener) {
|
|
52197
54208
|
deformListeners.add(listener);
|
|
52198
54209
|
return () => deformListeners.delete(listener);
|
|
@@ -53437,7 +55448,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53437
55448
|
}
|
|
53438
55449
|
|
|
53439
55450
|
// src/avatar.ts
|
|
53440
|
-
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" };
|
|
53441
55452
|
var DEFAULT_HAND_STANCES = { fists: "fists" };
|
|
53442
55453
|
var THIRD_PERSON_DEFAULTS = {
|
|
53443
55454
|
back: 3.8,
|
|
@@ -53610,6 +55621,12 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53610
55621
|
"act.clear": "Cleared the room",
|
|
53611
55622
|
"act.reset": "Repaired every object",
|
|
53612
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",
|
|
53613
55630
|
"act.shoot.hit": "{weapon}: shot, {energy} J, hit {where} at {dist} m",
|
|
53614
55631
|
"act.shoot.miss": "{weapon}: shot, {energy} J, hit nothing",
|
|
53615
55632
|
"act.shoot.pellets": "{weapon}: shot, {n} projectiles of up to {energy} J, {hits} hit {where} at {dist} m",
|
|
@@ -53639,6 +55656,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53639
55656
|
"hud.no_charges": "No charge set down waits for the remote detonator",
|
|
53640
55657
|
"blast.zone.lethal": "lethal",
|
|
53641
55658
|
"blast.zone.injury": "injury",
|
|
55659
|
+
"act.smoke": "{weapon}: smoke, burning for {seconds} s",
|
|
53642
55660
|
"act.explode": "{weapon}: exploded, {energy} J within {radius} m, {n} objects in range",
|
|
53643
55661
|
"act.molotov_fire": "{weapon}: fire on the ground, radius {radius} m for {seconds} s",
|
|
53644
55662
|
"act.tool.none": "{weapon}: nothing in reach",
|
|
@@ -53652,6 +55670,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53652
55670
|
"act.throw": "Threw {name} at {speed} m/s",
|
|
53653
55671
|
"ground.name": "Ground",
|
|
53654
55672
|
"act.landing": "{name} landed at {speed} m/s: {energy} J",
|
|
55673
|
+
"act.ground_gave_way": "the bare bars could not hold the weight on them: the slab gave way",
|
|
53655
55674
|
"act.player_land": "You landed at {speed} m/s",
|
|
53656
55675
|
"act.bench_failed": "{name} failed: {error}",
|
|
53657
55676
|
"loading.working": "Working\u2026",
|
|
@@ -53776,6 +55795,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53776
55795
|
"ui.clear_log": "Clear",
|
|
53777
55796
|
"ui.catalog": "Catalogue",
|
|
53778
55797
|
"ui.tool_menu": "Weapons",
|
|
55798
|
+
"ui.tool_menu.dual": "Shift+click: one in each hand",
|
|
53779
55799
|
"ui.tool_menu.search": "Search weapons and tools",
|
|
53780
55800
|
"ui.tool_menu.close": "Close",
|
|
53781
55801
|
"ui.tool_menu.results": "{n} found",
|
|
@@ -53979,6 +55999,12 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
53979
55999
|
"act.clear": "Limpou a sala",
|
|
53980
56000
|
"act.reset": "Consertou todos os objetos",
|
|
53981
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",
|
|
53982
56008
|
"act.shoot.hit": "{weapon}: disparo, {energy} J, acertou {where} a {dist} m",
|
|
53983
56009
|
"act.shoot.miss": "{weapon}: disparo, {energy} J, n\xE3o acertou nada",
|
|
53984
56010
|
"act.shoot.pellets": "{weapon}: disparo, {n} proj\xE9teis de at\xE9 {energy} J, {hits} acertaram {where} a {dist} m",
|
|
@@ -54008,6 +56034,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54008
56034
|
"hud.no_charges": "Nenhuma carga posta espera o detonador",
|
|
54009
56035
|
"blast.zone.lethal": "letal",
|
|
54010
56036
|
"blast.zone.injury": "de ferimento",
|
|
56037
|
+
"act.smoke": "{weapon}: fuma\xE7a, queima por {seconds} s",
|
|
54011
56038
|
"act.explode": "{weapon}: explodiu, {energy} J em {radius} m, {n} objetos ao alcance",
|
|
54012
56039
|
"act.molotov_fire": "{weapon}: fogo no ch\xE3o, raio de {radius} m por {seconds} s",
|
|
54013
56040
|
"act.tool.none": "{weapon}: nada ao alcance",
|
|
@@ -54021,6 +56048,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54021
56048
|
"act.throw": "Arremessou {name} a {speed} m/s",
|
|
54022
56049
|
"ground.name": "Ch\xE3o",
|
|
54023
56050
|
"act.landing": "{name} caiu a {speed} m/s: {energy} J",
|
|
56051
|
+
"act.ground_gave_way": "os vergalh\xF5es expostos n\xE3o aguentaram o peso: a laje cedeu",
|
|
54024
56052
|
"act.player_land": "Voc\xEA aterrissou a {speed} m/s",
|
|
54025
56053
|
"act.bench_failed": "{name} falhou: {error}",
|
|
54026
56054
|
"loading.working": "Trabalhando\u2026",
|
|
@@ -54145,6 +56173,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54145
56173
|
"ui.clear_log": "Limpar",
|
|
54146
56174
|
"ui.catalog": "Cat\xE1logo",
|
|
54147
56175
|
"ui.tool_menu": "Armas",
|
|
56176
|
+
"ui.tool_menu.dual": "Shift+clique: uma em cada m\xE3o",
|
|
54148
56177
|
"ui.tool_menu.search": "Buscar armas e ferramentas",
|
|
54149
56178
|
"ui.tool_menu.close": "Fechar",
|
|
54150
56179
|
"ui.tool_menu.results": "{n} encontradas",
|
|
@@ -54353,6 +56382,27 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54353
56382
|
return wrap;
|
|
54354
56383
|
};
|
|
54355
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
|
+
};
|
|
54356
56406
|
const sheetCard = (sheet) => {
|
|
54357
56407
|
const card = mk("div", "tr-sheet");
|
|
54358
56408
|
if (sheet.kicker) card.appendChild(mk("div", "sub", sheet.kicker));
|
|
@@ -54404,6 +56454,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54404
56454
|
playhead = { node: head, metric, end: end3 };
|
|
54405
56455
|
card.appendChild(strip);
|
|
54406
56456
|
}
|
|
56457
|
+
if (sheet.image) card.appendChild(sheetImage(sheet.image));
|
|
54407
56458
|
if (sheet.note) card.appendChild(mk("p", "sub", sheet.note));
|
|
54408
56459
|
return card;
|
|
54409
56460
|
};
|
|
@@ -54637,7 +56688,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54637
56688
|
const close = mk3("button", "tr-btn", "\xD7");
|
|
54638
56689
|
close.type = "button";
|
|
54639
56690
|
close.title = o.t("ui.tool_menu.close");
|
|
54640
|
-
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);
|
|
54641
56692
|
const tabs = mk3("div", "tr-tabs");
|
|
54642
56693
|
const body = mk3("div", "tr-wmenu-body");
|
|
54643
56694
|
element.append(header, tabs, body);
|
|
@@ -54645,15 +56696,17 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54645
56696
|
let activeGroup = "";
|
|
54646
56697
|
let groups = [];
|
|
54647
56698
|
const toolButton = (tool, group) => {
|
|
54648
|
-
const
|
|
56699
|
+
const left = o.currentLeft?.() === tool.id;
|
|
56700
|
+
const button = mk3("button", tool.id === o.current() || left ? "tr-btn on" : "tr-btn");
|
|
54649
56701
|
button.type = "button";
|
|
54650
56702
|
button.title = tool.name;
|
|
56703
|
+
if (left) button.dataset.left = "";
|
|
54651
56704
|
button.dataset.tool = tool.id;
|
|
54652
56705
|
if (tool.thumbnail) button.appendChild(o.thumb(tool.thumbnail, tool.thumbnailCredit));
|
|
54653
56706
|
button.appendChild(mk3("span", void 0, tool.name));
|
|
54654
56707
|
if (group) button.appendChild(mk3("small", void 0, group));
|
|
54655
|
-
button.onclick = () => {
|
|
54656
|
-
o.onPick(tool.id);
|
|
56708
|
+
button.onclick = (event) => {
|
|
56709
|
+
o.onPick(tool.id, { second: event.shiftKey });
|
|
54657
56710
|
toggle(false);
|
|
54658
56711
|
};
|
|
54659
56712
|
return button;
|
|
@@ -54749,6 +56802,8 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54749
56802
|
.tr-prog b{display:block;font-weight:500;margin-bottom:3px}
|
|
54750
56803
|
.tr-sheet{margin-top:8px;padding:8px;border:1px solid #2a2e36;border-radius:6px;font-size:12px;line-height:1.4}
|
|
54751
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}
|
|
54752
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}
|
|
54753
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}
|
|
54754
56809
|
.tr-timeline{position:relative;height:22px;margin:8px 0;background:#1b1e24;border-radius:4px;overflow:hidden}
|
|
@@ -54876,7 +56931,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
54876
56931
|
bottom.append(held, hotbar);
|
|
54877
56932
|
let currentTool = "";
|
|
54878
56933
|
const menuOptions = o.toolMenu;
|
|
54879
|
-
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;
|
|
54880
56935
|
if (toolMenu && menuOptions) {
|
|
54881
56936
|
const menuButton = mk4("button", "tr-slot tr-menu-btn");
|
|
54882
56937
|
menuButton.type = "button";
|
|
@@ -55524,6 +57579,8 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
55524
57579
|
|
|
55525
57580
|
// src/room.ts
|
|
55526
57581
|
var FIXED_DT = 1 / 60;
|
|
57582
|
+
var LEFT_HAND_KEY = "#L";
|
|
57583
|
+
var OFF_HAND_SEED = 11;
|
|
55527
57584
|
var TOOL_MENU_KEY_LABELS = { Backquote: "'" };
|
|
55528
57585
|
var EXPLOSIVE_EFFECT_IDS = ["m67", "molotov", "pipe_bomb", "m79_40mm", "m72_66mm", "at4_84mm", "dynamite", "c4", "claymore"];
|
|
55529
57586
|
var DEFAULT_PARTICLE_LIMIT = 900;
|
|
@@ -55541,6 +57598,11 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
55541
57598
|
var TERRAIN_CELL = 0.1;
|
|
55542
57599
|
var GROUND_SPLASH_MAX_LITRES = 3;
|
|
55543
57600
|
var WATER_ENTRY_SPEED = 1.5;
|
|
57601
|
+
var LOAD_EVERY = 0.2;
|
|
57602
|
+
var RESTING_GAP = 0.06;
|
|
57603
|
+
var PLAYER_FOOTPRINT = 0.25;
|
|
57604
|
+
var RESTING_SPEED = 0.3;
|
|
57605
|
+
var GRAVITY_EARTH = 9.81;
|
|
55544
57606
|
var TERRAIN_MAX_CELLS = 1e3;
|
|
55545
57607
|
var GROUND_BURST_MAX = 28;
|
|
55546
57608
|
var GROUND_BURST_PER_METRE = 30;
|
|
@@ -55814,6 +57876,11 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
55814
57876
|
return s;
|
|
55815
57877
|
};
|
|
55816
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";
|
|
55817
57884
|
const catalogMap = /* @__PURE__ */ new Map();
|
|
55818
57885
|
for (const i of options.catalog) catalogMap.set(i.id, i);
|
|
55819
57886
|
const catalog = [...options.catalog];
|
|
@@ -56023,9 +58090,19 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56023
58090
|
releaseTrigger();
|
|
56024
58091
|
},
|
|
56025
58092
|
secondary: () => {
|
|
58093
|
+
if (offTool && !heldEntry) {
|
|
58094
|
+
offHeld = true;
|
|
58095
|
+
offFirst = true;
|
|
58096
|
+
return;
|
|
58097
|
+
}
|
|
56026
58098
|
if (heldEntry) throwHeld();
|
|
56027
58099
|
else grab();
|
|
56028
58100
|
},
|
|
58101
|
+
secondaryUp: () => {
|
|
58102
|
+
if (!offHeld) return;
|
|
58103
|
+
offHeld = false;
|
|
58104
|
+
releaseTrigger("L");
|
|
58105
|
+
},
|
|
56029
58106
|
key: (code, down, e) => onKey(code, down, e),
|
|
56030
58107
|
wheel: (dir) => cycleTool(dir)
|
|
56031
58108
|
}
|
|
@@ -56564,6 +58641,10 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56564
58641
|
for (const listener of [...resetListeners]) listener();
|
|
56565
58642
|
tools.clear();
|
|
56566
58643
|
tool = toolState(toolId);
|
|
58644
|
+
dualReload.cancel();
|
|
58645
|
+
offTool = null;
|
|
58646
|
+
offToolId = null;
|
|
58647
|
+
firedHand = "R";
|
|
56567
58648
|
if (pristineWorld) {
|
|
56568
58649
|
for (const id of world.ids()) world.remove(id);
|
|
56569
58650
|
world.load(pristineWorld);
|
|
@@ -56829,12 +58910,13 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56829
58910
|
const pocketAt = new THREE.Vector3();
|
|
56830
58911
|
const aimTurn = new THREE.Quaternion();
|
|
56831
58912
|
const aimEuler = new THREE.Euler(0, 0, 0, "YXZ");
|
|
56832
|
-
const bodyHoldFrame = () => {
|
|
56833
|
-
const shoulder = avatar?.shoulder?.(
|
|
58913
|
+
const bodyHoldFrame = (hand = "R") => {
|
|
58914
|
+
const shoulder = avatar?.shoulder?.(hand);
|
|
56834
58915
|
if (!shoulder) return null;
|
|
56835
58916
|
shoulder.getWorldPosition(pocketAt);
|
|
56836
|
-
|
|
56837
|
-
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;
|
|
56838
58920
|
aimTurn.setFromEuler(aimEuler.set(player.pitch, player.yaw, 0, "YXZ"));
|
|
56839
58921
|
return { position: [pocketAt.x, pocketAt.y, pocketAt.z], quaternion: [aimTurn.x, aimTurn.y, aimTurn.z, aimTurn.w] };
|
|
56840
58922
|
};
|
|
@@ -56944,17 +59026,18 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56944
59026
|
rng = rng * 1664525 + 1013904223 >>> 0;
|
|
56945
59027
|
return rng / 4294967296;
|
|
56946
59028
|
};
|
|
56947
|
-
const muzzlePose = () => {
|
|
56948
|
-
const lent = muzzleSource?.();
|
|
56949
|
-
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 };
|
|
56950
59032
|
};
|
|
56951
|
-
const muzzle2 = () => {
|
|
59033
|
+
const muzzle2 = (hand = "R") => {
|
|
56952
59034
|
aim();
|
|
56953
59035
|
const e = camera2.matrixWorld.elements;
|
|
59036
|
+
const side = hand === "L" ? -0.16 : 0.16;
|
|
56954
59037
|
return [
|
|
56955
|
-
aimO[0] + aimD[0] * 0.45 + e[0] *
|
|
56956
|
-
aimO[1] + aimD[1] * 0.45 + e[1] *
|
|
56957
|
-
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
|
|
56958
59041
|
];
|
|
56959
59042
|
};
|
|
56960
59043
|
const tracers = [];
|
|
@@ -57134,10 +59217,10 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57134
59217
|
renderer.impulse(objectId, push2.impulse, push2.point);
|
|
57135
59218
|
}
|
|
57136
59219
|
};
|
|
57137
|
-
const fireShots = (shots, recoil) => {
|
|
59220
|
+
const fireShots = (shots, recoil, id = toolId, hand = "R") => {
|
|
57138
59221
|
if (shots.length === 0) return;
|
|
57139
|
-
const w = toolName();
|
|
57140
|
-
const { position: m, drawsFlash } = muzzlePose();
|
|
59222
|
+
const w = toolName(id);
|
|
59223
|
+
const { position: m, drawsFlash } = muzzlePose(hand);
|
|
57141
59224
|
if (!drawsFlash) {
|
|
57142
59225
|
renderer.emit("flash", m, [aimD[0], aimD[1], aimD[2]], 1, 0);
|
|
57143
59226
|
renderer.emit("sparks", m, [aimD[0], aimD[1], aimD[2]], 4, 6);
|
|
@@ -57176,7 +59259,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57176
59259
|
objectId: f?.object,
|
|
57177
59260
|
itemId: f ? entryOf(f.object)?.so.itemId : void 0,
|
|
57178
59261
|
part: f?.part,
|
|
57179
|
-
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 } : {} }
|
|
57180
59263
|
});
|
|
57181
59264
|
};
|
|
57182
59265
|
const fireRays = (u) => {
|
|
@@ -57280,7 +59363,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57280
59363
|
const kickLeg = options.kickLeg ?? "alternate";
|
|
57281
59364
|
let nextLeg = "right";
|
|
57282
59365
|
const punchHand = options.punchHand ?? "alternate";
|
|
57283
|
-
const punchTools = new Set(options.punchTools ?? ["hand", "fists"]);
|
|
59366
|
+
const punchTools = new Set(options.punchTools ?? ["hand", "fists", "brass_knuckles"]);
|
|
57284
59367
|
let nextHand = "right";
|
|
57285
59368
|
const combo = options.strikeCombo;
|
|
57286
59369
|
let comboOn = !!combo && options.strikeComboOn === true;
|
|
@@ -57294,16 +59377,16 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57294
59377
|
action("combo", t(on ? "act.combo.on" : "act.combo.off", { name }), { data: { combo: combo.id, on } });
|
|
57295
59378
|
say(t(on ? "act.combo.on" : "act.combo.off", { name }));
|
|
57296
59379
|
};
|
|
57297
|
-
const strikeUse = (u, id = toolId) => {
|
|
59380
|
+
const strikeUse = (u, id = toolId, side) => {
|
|
57298
59381
|
const stepIndex = comboOn && combo?.tools.includes(id) && combo.steps.length > 0 ? simTime - comboAt > combo.reset ? 0 : comboNext : null;
|
|
57299
59382
|
const step2 = stepIndex === null ? void 0 : combo.steps[stepIndex];
|
|
57300
59383
|
const clip = step2 ? step2.clip : strikeClips[id];
|
|
57301
59384
|
const leg = id === "kick" ? kickLeg === "alternate" ? nextLeg : kickLeg : void 0;
|
|
57302
|
-
const hand = step2 ? step2.hand : punchTools.has(id) ? punchHand === "alternate" ? nextHand : punchHand : void 0;
|
|
57303
|
-
const
|
|
57304
|
-
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;
|
|
57305
59388
|
if (leg && seconds !== null && kickLeg === "alternate") nextLeg = leg === "right" ? "left" : "right";
|
|
57306
|
-
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";
|
|
57307
59390
|
if (step2 && stepIndex !== null) {
|
|
57308
59391
|
comboNext = (stepIndex + 1) % combo.steps.length;
|
|
57309
59392
|
comboAt = simTime;
|
|
@@ -57324,7 +59407,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57324
59407
|
data: { weapon: id, clip, impactIn: seconds, ...leg ? { leg } : {}, ...hand ? { hand } : {}, ...step2 ? { combo: combo.id, step: stepIndex } : {} }
|
|
57325
59408
|
});
|
|
57326
59409
|
strikes.push({
|
|
57327
|
-
key: id,
|
|
59410
|
+
key: side?.key ?? id,
|
|
57328
59411
|
remaining: seconds,
|
|
57329
59412
|
...swing && seconds > lead ? { swing, lead } : {},
|
|
57330
59413
|
land: () => {
|
|
@@ -57454,20 +59537,50 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57454
59537
|
say,
|
|
57455
59538
|
projectileModel: options.projectileModel
|
|
57456
59539
|
});
|
|
57457
|
-
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") => {
|
|
57458
59561
|
aim();
|
|
57459
|
-
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;
|
|
57460
59570
|
if (cat === "hand") {
|
|
57461
59571
|
if (strikes.some((strike) => strike.key === "hand" || strike.key === "fists")) return "cooldown";
|
|
57462
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");
|
|
57463
59573
|
return "ok";
|
|
57464
59574
|
}
|
|
57465
|
-
if (strikes.some((strike) => strike.key ===
|
|
57466
|
-
const res =
|
|
57467
|
-
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);
|
|
57468
59578
|
if (res.status === "empty") {
|
|
57469
|
-
if (!
|
|
57470
|
-
|
|
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"));
|
|
57471
59584
|
return res.status;
|
|
57472
59585
|
}
|
|
57473
59586
|
if (res.status !== "ok") {
|
|
@@ -57477,15 +59590,18 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57477
59590
|
else if (res.status === "safe") say(t("hud.safe"));
|
|
57478
59591
|
return res.status;
|
|
57479
59592
|
}
|
|
57480
|
-
|
|
59593
|
+
firedHand = hand;
|
|
59594
|
+
applyUses(res, dt, hand);
|
|
57481
59595
|
return res.status;
|
|
57482
59596
|
};
|
|
57483
|
-
const applyUses = (res, dt) => {
|
|
57484
|
-
|
|
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);
|
|
57485
59600
|
for (const u of res.uses) {
|
|
57486
59601
|
switch (u.kind) {
|
|
57487
59602
|
case "melee":
|
|
57488
|
-
strikeUse(u);
|
|
59603
|
+
if (hand === "L") strikeUse(u, id, { hand: "left", key: strikeKeyOf(id, hand) });
|
|
59604
|
+
else strikeUse(u);
|
|
57489
59605
|
break;
|
|
57490
59606
|
case "flame":
|
|
57491
59607
|
heatRays(u, "fire");
|
|
@@ -57513,15 +59629,17 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57513
59629
|
}
|
|
57514
59630
|
}
|
|
57515
59631
|
};
|
|
57516
|
-
const releaseTrigger = () => {
|
|
57517
|
-
|
|
57518
|
-
|
|
59632
|
+
const releaseTrigger = (hand = "R") => {
|
|
59633
|
+
const slot2 = toolOf(hand);
|
|
59634
|
+
if (!slot2) return;
|
|
59635
|
+
if (!slot2.state.cooking) {
|
|
59636
|
+
slot2.state.release();
|
|
57519
59637
|
return;
|
|
57520
59638
|
}
|
|
57521
59639
|
aim();
|
|
57522
|
-
const res =
|
|
57523
|
-
flushEvents(
|
|
57524
|
-
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);
|
|
57525
59643
|
};
|
|
57526
59644
|
const kick = () => {
|
|
57527
59645
|
if (!arsenal.weapons.has("kick") || strikes.some((strike) => strike.key === "kick")) return false;
|
|
@@ -57550,8 +59668,43 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57550
59668
|
}));
|
|
57551
59669
|
};
|
|
57552
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
|
+
};
|
|
57553
59705
|
const setTool = (id) => {
|
|
57554
59706
|
if (!arsenal.weapons.has(id)) throw new Error(`game-test-room: unknown weapon "${id}"`);
|
|
59707
|
+
dropOffTool();
|
|
57555
59708
|
releaseTrigger();
|
|
57556
59709
|
toolId = id;
|
|
57557
59710
|
const i = loadout.indexOf(id);
|
|
@@ -57981,6 +60134,30 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
57981
60134
|
for (const p of loose) floatPiece(p, dt);
|
|
57982
60135
|
};
|
|
57983
60136
|
const footprints = createFootprints(terrain);
|
|
60137
|
+
let loadClock = 0;
|
|
60138
|
+
const restingLoad = (piece) => {
|
|
60139
|
+
if (piece.held || Math.hypot(piece.velocity[0], piece.velocity[1], piece.velocity[2]) > RESTING_SPEED) return null;
|
|
60140
|
+
const box2 = tmpBox.setFromObject(piece.root);
|
|
60141
|
+
const centre = box2.getCenter(tmpV2);
|
|
60142
|
+
return { x: centre.x, z: centre.z, radius: Math.max(piece.halfExtents[0], piece.halfExtents[2]), newtons: piece.mass * GRAVITY_EARTH };
|
|
60143
|
+
};
|
|
60144
|
+
const updateLoads = (dt) => {
|
|
60145
|
+
loadClock += dt;
|
|
60146
|
+
if (loadClock < LOAD_EVERY) return;
|
|
60147
|
+
loadClock = 0;
|
|
60148
|
+
const loads = [];
|
|
60149
|
+
const [px, py, pz] = player.position;
|
|
60150
|
+
if (py - terrain.heightAt(px, pz) <= RESTING_GAP) loads.push({ x: px, z: pz, radius: PLAYER_FOOTPRINT, newtons: playerMass * GRAVITY_EARTH });
|
|
60151
|
+
for (const e of entries2.values()) {
|
|
60152
|
+
const load = e.piece ? restingLoad(e.piece) : null;
|
|
60153
|
+
if (load) loads.push(load);
|
|
60154
|
+
}
|
|
60155
|
+
for (const p of loose) {
|
|
60156
|
+
const load = restingLoad(p);
|
|
60157
|
+
if (load) loads.push(load);
|
|
60158
|
+
}
|
|
60159
|
+
if (loads.length > 0 && terrain.bear(loads)) action("ground_gave_way", t("act.ground_gave_way"));
|
|
60160
|
+
};
|
|
57984
60161
|
const prevVy = /* @__PURE__ */ new Map();
|
|
57985
60162
|
const tmpBox = new THREE.Box3();
|
|
57986
60163
|
const onKey = (code, down, e) => {
|
|
@@ -58020,15 +60197,13 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58020
60197
|
case "KeyR":
|
|
58021
60198
|
if (heldPiece) heldYaw += Math.PI / 8;
|
|
58022
60199
|
else {
|
|
58023
|
-
|
|
60200
|
+
reloadHands();
|
|
58024
60201
|
say(t("hud.reloading"));
|
|
58025
60202
|
}
|
|
58026
60203
|
break;
|
|
58027
|
-
case "KeyQ":
|
|
58028
|
-
|
|
58029
|
-
flushEvents(toolId, tool);
|
|
60204
|
+
case "KeyQ":
|
|
60205
|
+
cycleToolMode();
|
|
58030
60206
|
break;
|
|
58031
|
-
}
|
|
58032
60207
|
case "KeyX":
|
|
58033
60208
|
clearToolFault();
|
|
58034
60209
|
break;
|
|
@@ -58085,6 +60260,20 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58085
60260
|
if (!loadout.includes(weaponId)) loadout.push(weaponId);
|
|
58086
60261
|
setTool(weaponId);
|
|
58087
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
|
+
};
|
|
58088
60277
|
let hudAimHit;
|
|
58089
60278
|
const inspectTarget = () => {
|
|
58090
60279
|
if (hudAimHit !== void 0) return hudAimHit;
|
|
@@ -58279,6 +60468,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58279
60468
|
vfx.update(dt);
|
|
58280
60469
|
updateImpacts();
|
|
58281
60470
|
updateWater(dt);
|
|
60471
|
+
updateLoads(dt);
|
|
58282
60472
|
if (player.position[1] <= terrain.footAt(player.position[0], player.position[2]) + 0.15) footprints.update(player.position[0], player.position[2]);
|
|
58283
60473
|
fluidView.update(dt);
|
|
58284
60474
|
filmBridge.update(dt);
|
|
@@ -58287,6 +60477,11 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58287
60477
|
s.update(dt);
|
|
58288
60478
|
flushEvents(id, s);
|
|
58289
60479
|
}
|
|
60480
|
+
if (offTool && offToolId) {
|
|
60481
|
+
offTool.update(dt);
|
|
60482
|
+
flushEvents(offToolId, offTool, void 0, "L");
|
|
60483
|
+
dualReload.step(dt);
|
|
60484
|
+
}
|
|
58290
60485
|
if (audio) {
|
|
58291
60486
|
const look = camera2.getWorldDirection(listenerDirection);
|
|
58292
60487
|
audio.setListener({ position: [camera2.position.x, camera2.position.y, camera2.position.z], yaw: Math.atan2(-look.x, -look.z) });
|
|
@@ -58332,6 +60527,10 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58332
60527
|
} else if (useHeld) useTool(dt, !useFirst);
|
|
58333
60528
|
useFirst = false;
|
|
58334
60529
|
}
|
|
60530
|
+
if ((offHeld || offFirst) && offTool && !isPaused && !push.active) {
|
|
60531
|
+
useTool(dt, !offFirst, "L");
|
|
60532
|
+
offFirst = false;
|
|
60533
|
+
}
|
|
58335
60534
|
if (!isPaused) followHeld(dt);
|
|
58336
60535
|
};
|
|
58337
60536
|
const updatePresent = (dt) => {
|
|
@@ -58358,12 +60557,18 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58358
60557
|
hudAimHit = void 0;
|
|
58359
60558
|
}
|
|
58360
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
|
+
};
|
|
58361
60565
|
const readHudState = () => {
|
|
58362
60566
|
const page = Math.floor(toolIndex / 10);
|
|
58363
60567
|
const slots = loadout.slice(page * 10, page * 10 + 10).map((id) => arsenal.name(id));
|
|
58364
|
-
const
|
|
60568
|
+
const left = offTool ? ammoText(offTool) : "";
|
|
60569
|
+
const ammo = `${ammoText(tool)}${left ? ` | ${t("hud.left")} ${left}` : ""}`;
|
|
58365
60570
|
return {
|
|
58366
|
-
toolName: toolName(),
|
|
60571
|
+
toolName: offToolId ? `${toolName()} + ${toolName(offToolId)}` : toolName(),
|
|
58367
60572
|
toolId,
|
|
58368
60573
|
ammo,
|
|
58369
60574
|
slots,
|
|
@@ -58553,26 +60758,53 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58553
60758
|
if (event.type === "explosion") knockPlayer(event);
|
|
58554
60759
|
for (const listener of hostListeners) listener(event);
|
|
58555
60760
|
}
|
|
58556
|
-
function flushEvents(id, state, recoil) {
|
|
60761
|
+
function flushEvents(id, state, recoil, hand = "R") {
|
|
58557
60762
|
const phase = state.phase;
|
|
58558
60763
|
for (const event of state.drain()) {
|
|
58559
60764
|
const hostEvent = toHostEvent(id, event, { ...recoil ? { recoil } : {}, phase });
|
|
58560
|
-
if (hostEvent) emitHost(hostEvent);
|
|
60765
|
+
if (hostEvent) emitHost(hand === "L" ? { ...hostEvent, hand } : hostEvent);
|
|
58561
60766
|
}
|
|
58562
60767
|
}
|
|
58563
|
-
function startReload() {
|
|
58564
|
-
|
|
58565
|
-
|
|
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"]);
|
|
58566
60781
|
}
|
|
60782
|
+
const commandHand = () => offTool ? firedHand : "R";
|
|
58567
60783
|
function clearToolFault() {
|
|
58568
|
-
|
|
58569
|
-
|
|
58570
|
-
|
|
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
|
+
}
|
|
58571
60792
|
}
|
|
58572
60793
|
function toggleSafety() {
|
|
58573
|
-
|
|
58574
|
-
|
|
58575
|
-
|
|
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}`);
|
|
58576
60808
|
}
|
|
58577
60809
|
function runToolCommand(request) {
|
|
58578
60810
|
const work = (done) => done.ok ? { ok: true, seconds: done.seconds } : { ok: false, reason: done.reason };
|
|
@@ -58594,6 +60826,24 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58594
60826
|
return { ok: false, reason: "unknown" };
|
|
58595
60827
|
}
|
|
58596
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
|
+
});
|
|
58597
60847
|
const host = {
|
|
58598
60848
|
THREE,
|
|
58599
60849
|
scene: scene2,
|
|
@@ -58620,22 +60870,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58620
60870
|
...options.blastShove ? { blastShove: options.blastShove } : {},
|
|
58621
60871
|
blastReach: (point, target, ignore) => world.blastReach(point, target, ignore ? { ignore } : {}),
|
|
58622
60872
|
tool: () => ({
|
|
58623
|
-
|
|
58624
|
-
|
|
58625
|
-
|
|
58626
|
-
capacity: tool.capacity,
|
|
58627
|
-
reserve: tool.reserve,
|
|
58628
|
-
reloading: tool.reloading,
|
|
58629
|
-
mode: tool.mode,
|
|
58630
|
-
...tool.fault ? { fault: tool.fault } : {},
|
|
58631
|
-
safety: tool.safety,
|
|
58632
|
-
heat: tool.heatLevel,
|
|
58633
|
-
attachments: tool.attachments.map((part) => ({ id: part.id, mount: part.mount, ...part.integral ? { integral: true } : {}, ...part.on === void 0 ? {} : { on: part.on } })),
|
|
58634
|
-
stock: tool.stock,
|
|
58635
|
-
suppressed: tool.suppressed,
|
|
58636
|
-
underbarrelActive: tool.underbarrelActive,
|
|
58637
|
-
mass: tool.mass,
|
|
58638
|
-
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 } : {} } } : {}
|
|
58639
60876
|
}),
|
|
58640
60877
|
command(request) {
|
|
58641
60878
|
const result2 = runToolCommand(request);
|
|
@@ -58672,7 +60909,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58672
60909
|
onFrame(update, frameOptions) {
|
|
58673
60910
|
return scheduler.add((ctx) => update(ctx.dt), { phase: frameOptions?.phase ?? "lateSimulate", order: frameOptions?.order ?? 0, id: `module.frame#${moduleFrameCount++}` });
|
|
58674
60911
|
},
|
|
58675
|
-
holdFrame: () => bodyHoldFrame(),
|
|
60912
|
+
holdFrame: (hand) => bodyHoldFrame(hand),
|
|
58676
60913
|
reachFor(reach) {
|
|
58677
60914
|
if (!avatar) {
|
|
58678
60915
|
reach.onGrip?.();
|
|
@@ -59048,6 +61285,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
59048
61285
|
fluids,
|
|
59049
61286
|
film: filmBridge,
|
|
59050
61287
|
vfx: vfx.world,
|
|
61288
|
+
effects: vfx,
|
|
59051
61289
|
fluidRenderer: fluidView,
|
|
59052
61290
|
audio,
|
|
59053
61291
|
environment,
|
|
@@ -59063,6 +61301,29 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
59063
61301
|
clear,
|
|
59064
61302
|
resetAll,
|
|
59065
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(),
|
|
59066
61327
|
useItem,
|
|
59067
61328
|
use(hold = 0) {
|
|
59068
61329
|
if (tool.def.category === "hand") {
|
|
@@ -59360,7 +61621,8 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
59360
61621
|
...options.toolMenu !== false ? {
|
|
59361
61622
|
toolMenu: {
|
|
59362
61623
|
groups: toolMenuGroups,
|
|
59363
|
-
onPick:
|
|
61624
|
+
onPick: pickTool,
|
|
61625
|
+
currentLeft: () => offToolId,
|
|
59364
61626
|
// the list takes clicks: the mouse leaves the view while it is open
|
|
59365
61627
|
onOpen: (open) => {
|
|
59366
61628
|
if (open && document.pointerLockElement) document.exitPointerLock?.();
|