@adatechnology/game-weapons-three 0.16.0 → 0.17.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/dist/{chunk-KWJQO6JS.js → chunk-BDYIF7JD.js} +218 -53
- package/dist/chunk-BDYIF7JD.js.map +1 -0
- package/dist/index.d.ts +45 -3
- package/dist/index.global.js +320 -91
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/{testing-CEcZ-zzz.d.ts → testing-BKDGK6cq.d.ts} +15 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/package.json +8 -8
- package/dist/chunk-KWJQO6JS.js.map +0 -1
package/dist/index.global.js
CHANGED
|
@@ -44,6 +44,8 @@ var GameWeaponsThree = (() => {
|
|
|
44
44
|
P13_VALVE_MESH: () => P13_VALVE_MESH,
|
|
45
45
|
RELOAD_SAMPLE: () => RELOAD_SAMPLE,
|
|
46
46
|
RELOAD_SAMPLE_HITS: () => RELOAD_SAMPLE_HITS,
|
|
47
|
+
VIEW_HOLD: () => VIEW_HOLD,
|
|
48
|
+
VIEW_MOTION: () => VIEW_MOTION,
|
|
47
49
|
WEAPON_ITEM_PREFIX: () => WEAPON_ITEM_PREFIX,
|
|
48
50
|
WEAPON_THUMBNAILS: () => WEAPON_THUMBNAILS,
|
|
49
51
|
WEIGHT_INTENSITY: () => WEIGHT_INTENSITY,
|
|
@@ -91,6 +93,7 @@ var GameWeaponsThree = (() => {
|
|
|
91
93
|
registerWeaponItemModel: () => registerWeaponItemModel,
|
|
92
94
|
rigStock: () => rigStock,
|
|
93
95
|
rigUnderbarrel: () => rigUnderbarrel,
|
|
96
|
+
toWorldLens: () => toWorldLens,
|
|
94
97
|
weaponProp: () => weaponProp,
|
|
95
98
|
weaponSampleBank: () => weaponSampleBank,
|
|
96
99
|
weaponSampleDefaults: () => weaponSampleDefaults,
|
|
@@ -165,6 +168,7 @@ var GameWeaponsThree = (() => {
|
|
|
165
168
|
const flame = flameBase * (1 - rules.flameFillInfluence * (1 - k));
|
|
166
169
|
return 1 - (1 - Math.min(1, Math.max(0, spark))) * (1 - Math.min(1, Math.max(0, flame)));
|
|
167
170
|
};
|
|
171
|
+
var FIRST_PERSON_LAYER = 9;
|
|
168
172
|
var TOOL_CLIP = {
|
|
169
173
|
DRAW: "draw",
|
|
170
174
|
SHOT: "shot",
|
|
@@ -12148,7 +12152,9 @@ var GameWeaponsThree = (() => {
|
|
|
12148
12152
|
dimensions: {
|
|
12149
12153
|
length: 0.801,
|
|
12150
12154
|
barrel: 0.559,
|
|
12151
|
-
emptyMass: 39
|
|
12155
|
+
emptyMass: 39,
|
|
12156
|
+
barrels: 6,
|
|
12157
|
+
barrelMass: 2
|
|
12152
12158
|
},
|
|
12153
12159
|
archetype: "rifle_7_62x39",
|
|
12154
12160
|
sources: [
|
|
@@ -13128,19 +13134,41 @@ var GameWeaponsThree = (() => {
|
|
|
13128
13134
|
}
|
|
13129
13135
|
};
|
|
13130
13136
|
var DEFAULT_HEAT = {
|
|
13131
|
-
cap:
|
|
13132
|
-
displayMax:
|
|
13133
|
-
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13137
|
+
cap: 900,
|
|
13138
|
+
displayMax: 750,
|
|
13139
|
+
faultFrom: 350,
|
|
13140
|
+
faultSpan: 200,
|
|
13141
|
+
specificHeat: 490,
|
|
13142
|
+
barrelShare: { shell: 0.48, big: 0.48, tiny: 0.3, pistol: 0.3, rifle: 0.48 },
|
|
13143
|
+
barrelKilogramsPerMetre: {
|
|
13144
|
+
pistol: 1,
|
|
13145
|
+
revolver: 1.4,
|
|
13146
|
+
smg: 1.2,
|
|
13147
|
+
carbine: 1.6,
|
|
13148
|
+
rifle: 1.6,
|
|
13149
|
+
dmr: 2.4,
|
|
13150
|
+
sniper: 2.4,
|
|
13151
|
+
hunting: 2.4,
|
|
13152
|
+
machine_gun: 3,
|
|
13153
|
+
shotgun: 1.1
|
|
13154
|
+
},
|
|
13155
|
+
barrelFallback: { metres: 0.4, kilogramsPerMetre: 1.6 },
|
|
13156
|
+
cooling: { baseSeconds: 30, secondsPerKilogram: 250 },
|
|
13138
13157
|
perRocket: 35,
|
|
13139
|
-
visual: { smokeFrom:
|
|
13158
|
+
visual: { smokeFrom: 250, smokeSpan: 300, smokeSeconds: 2.5, glowFrom: 450, glowSpan: 300 }
|
|
13140
13159
|
};
|
|
13141
13160
|
var GALLERY_HEAT = {
|
|
13142
13161
|
...DEFAULT_HEAT,
|
|
13143
|
-
|
|
13162
|
+
cap: 140,
|
|
13163
|
+
displayMax: 120,
|
|
13164
|
+
faultFrom: 60,
|
|
13165
|
+
faultSpan: 40,
|
|
13166
|
+
visual: { smokeFrom: 70, smokeSpan: 100, smokeSeconds: 2.5, glowFrom: 80, glowSpan: 40 },
|
|
13167
|
+
gallery: {
|
|
13168
|
+
perShot: { shell: 6, big: 9, tiny: 1.2, pistol: 3, rifle: 4.5 },
|
|
13169
|
+
decayBase: 1.6,
|
|
13170
|
+
decayPerPoint: 0.03
|
|
13171
|
+
}
|
|
13144
13172
|
};
|
|
13145
13173
|
var defaultFaultChance = (context) => {
|
|
13146
13174
|
const factor = context.def.action.kind === "firearm" ? context.def.action.faultFactor ?? 1 : 1;
|
|
@@ -13423,17 +13451,76 @@ var GameWeaponsThree = (() => {
|
|
|
13423
13451
|
...explosive.stunSeconds !== void 0 ? { stunSeconds: explosive.stunSeconds } : {}
|
|
13424
13452
|
};
|
|
13425
13453
|
};
|
|
13454
|
+
var EPS2 = 1e-9;
|
|
13455
|
+
var MANUAL_MODES = /* @__PURE__ */ new Set(["pump", "bolt", "lever"]);
|
|
13456
|
+
var weaponSpeed = (action, caliber) => action.muzzleSpeed ?? caliber.muzzleSpeed * (action.barrel ?? 1);
|
|
13457
|
+
var weaponNoise = (action, caliber) => action.noise ?? caliber.noise ?? 0;
|
|
13458
|
+
var timingsOf = (action) => "timings" in action ? action.timings : void 0;
|
|
13459
|
+
var drawSeconds = (action, rules) => timingsOf(action)?.draw ?? rules.draw;
|
|
13460
|
+
var clearSeconds = (action, rules) => timingsOf(action)?.clear ?? rules.clear;
|
|
13461
|
+
var manualCycleSeconds = (action, mode) => MANUAL_MODES.has(mode) ? action.timings?.cycle ?? 0 : 0;
|
|
13462
|
+
var planRounds = (action, mode, ammo, firstAt, frameEnd) => {
|
|
13463
|
+
const interval = 60 / action.rpm;
|
|
13464
|
+
const times = [];
|
|
13465
|
+
if (mode === "auto") {
|
|
13466
|
+
for (let t = firstAt; times.length < ammo && (times.length === 0 ? t <= frameEnd + EPS2 : t < frameEnd - EPS2); t += interval) times.push(t);
|
|
13467
|
+
return times;
|
|
13468
|
+
}
|
|
13469
|
+
if (mode === "burst") {
|
|
13470
|
+
const count = Math.min(action.burst ?? 3, ammo);
|
|
13471
|
+
for (let k = 0; k < count; k++) times.push(firstAt + k * interval);
|
|
13472
|
+
return times;
|
|
13473
|
+
}
|
|
13474
|
+
if (mode === "volley") return Array.from({ length: Math.min(action.magazine, ammo) }, () => firstAt);
|
|
13475
|
+
return [firstAt];
|
|
13476
|
+
};
|
|
13426
13477
|
var SUBSTEP_SECONDS = 1 / 60;
|
|
13427
|
-
var
|
|
13478
|
+
var MAX_ROUNDS_SEARCHED = 1e5;
|
|
13479
|
+
var barrelMassOf = (def, rules) => {
|
|
13480
|
+
const dimensions = def.dimensions;
|
|
13481
|
+
const kilogramsPerMetre = rules.barrelKilogramsPerMetre[def.category] ?? rules.barrelFallback.kilogramsPerMetre;
|
|
13482
|
+
const single = dimensions?.barrelMass ?? (dimensions?.barrel ?? rules.barrelFallback.metres) * kilogramsPerMetre;
|
|
13483
|
+
return single * (dimensions?.barrels ?? 1);
|
|
13484
|
+
};
|
|
13485
|
+
var coolingTimeConstant = (barrelMass, rules) => rules.cooling.baseSeconds + rules.cooling.secondsPerKilogram * barrelMass;
|
|
13486
|
+
var decayHeat = (heat, seconds, barrelMass, rules) => {
|
|
13487
|
+
if (heat <= 0) return 0;
|
|
13488
|
+
if (rules.gallery) return decayGallery(heat, seconds, rules.gallery);
|
|
13489
|
+
return heat * Math.exp(-seconds / coolingTimeConstant(barrelMass, rules));
|
|
13490
|
+
};
|
|
13491
|
+
var decayGallery = (heat, seconds, gallery) => {
|
|
13428
13492
|
const steps = Math.max(1, Math.ceil(seconds / SUBSTEP_SECONDS - 1e-9));
|
|
13429
13493
|
const step = seconds / steps;
|
|
13430
13494
|
let current = heat;
|
|
13431
|
-
for (let i = 0; i < steps && current > 0; i++) current = Math.max(0, current - step * (
|
|
13495
|
+
for (let i = 0; i < steps && current > 0; i++) current = Math.max(0, current - step * (gallery.decayBase + current * gallery.decayPerPoint));
|
|
13432
13496
|
return current;
|
|
13433
13497
|
};
|
|
13434
|
-
var heatPerRound = (action, caliber, rules) => {
|
|
13498
|
+
var heatPerRound = ({ action, caliber, energy, barrelMass, rules }) => {
|
|
13435
13499
|
if (action.kind === "launcher") return rules.perRocket;
|
|
13436
|
-
|
|
13500
|
+
const caseType = caliber?.caseType;
|
|
13501
|
+
if (!caseType) return 0;
|
|
13502
|
+
if (rules.gallery) return rules.gallery.perShot[caseType];
|
|
13503
|
+
return rules.barrelShare[caseType] * energy / (barrelMass * rules.specificHeat);
|
|
13504
|
+
};
|
|
13505
|
+
var roundsToWarning = ({ def, caliber, energy, rpm, rules }) => {
|
|
13506
|
+
if (def.action.kind !== "firearm" || rpm <= 0) return Infinity;
|
|
13507
|
+
const barrelMass = barrelMassOf(def, rules);
|
|
13508
|
+
const perRound = heatPerRound({ action: def.action, caliber, energy: energy * (caliber.pellets ?? 1), barrelMass, rules });
|
|
13509
|
+
const interval = 60 / rpm;
|
|
13510
|
+
let heat = 0;
|
|
13511
|
+
for (let round5 = 1; round5 <= MAX_ROUNDS_SEARCHED; round5++) {
|
|
13512
|
+
heat = decayHeat(heat, round5 === 1 ? 0 : interval, barrelMass, rules) + perRound;
|
|
13513
|
+
if (heat >= rules.faultFrom) return round5;
|
|
13514
|
+
}
|
|
13515
|
+
return Infinity;
|
|
13516
|
+
};
|
|
13517
|
+
var roundsToWarningOf = (arsenal, weaponId) => {
|
|
13518
|
+
const def = arsenal.weapons.get(weaponId);
|
|
13519
|
+
if (!def || def.action.kind !== "firearm") return Infinity;
|
|
13520
|
+
const caliber = arsenal.calibers.get(def.action.caliber);
|
|
13521
|
+
if (!caliber) return Infinity;
|
|
13522
|
+
const energy = 0.5 * (caliber.bulletGrams / 1e3) * weaponSpeed(def.action, caliber) ** 2;
|
|
13523
|
+
return roundsToWarning({ def, caliber, energy, rpm: def.action.rpm, rules: arsenal.rules.heat });
|
|
13437
13524
|
};
|
|
13438
13525
|
var burstNoise = (base, recentShots, rules) => base * (1 + Math.min(rules.cap, rules.step * recentShots));
|
|
13439
13526
|
var magazineOut = { stage: "magazine_out", at: 0 };
|
|
@@ -13560,29 +13647,6 @@ var GameWeaponsThree = (() => {
|
|
|
13560
13647
|
return roll2.ammoQuality.faultChance > 0 && roll2.random() < roll2.ammoQuality.faultChance ? "misfire" : null;
|
|
13561
13648
|
};
|
|
13562
13649
|
var isDudWithoutJam = (action, fault) => fault === "misfire" && action.kind === "firearm" && MISFIRE_ONLY.has(action.family);
|
|
13563
|
-
var EPS2 = 1e-9;
|
|
13564
|
-
var MANUAL_MODES = /* @__PURE__ */ new Set(["pump", "bolt", "lever"]);
|
|
13565
|
-
var weaponSpeed = (action, caliber) => action.muzzleSpeed ?? caliber.muzzleSpeed * (action.barrel ?? 1);
|
|
13566
|
-
var weaponNoise = (action, caliber) => action.noise ?? caliber.noise ?? 0;
|
|
13567
|
-
var timingsOf = (action) => "timings" in action ? action.timings : void 0;
|
|
13568
|
-
var drawSeconds = (action, rules) => timingsOf(action)?.draw ?? rules.draw;
|
|
13569
|
-
var clearSeconds = (action, rules) => timingsOf(action)?.clear ?? rules.clear;
|
|
13570
|
-
var manualCycleSeconds = (action, mode) => MANUAL_MODES.has(mode) ? action.timings?.cycle ?? 0 : 0;
|
|
13571
|
-
var planRounds = (action, mode, ammo, firstAt, frameEnd) => {
|
|
13572
|
-
const interval = 60 / action.rpm;
|
|
13573
|
-
const times = [];
|
|
13574
|
-
if (mode === "auto") {
|
|
13575
|
-
for (let t = firstAt; times.length < ammo && (times.length === 0 ? t <= frameEnd + EPS2 : t < frameEnd - EPS2); t += interval) times.push(t);
|
|
13576
|
-
return times;
|
|
13577
|
-
}
|
|
13578
|
-
if (mode === "burst") {
|
|
13579
|
-
const count = Math.min(action.burst ?? 3, ammo);
|
|
13580
|
-
for (let k = 0; k < count; k++) times.push(firstAt + k * interval);
|
|
13581
|
-
return times;
|
|
13582
|
-
}
|
|
13583
|
-
if (mode === "volley") return Array.from({ length: Math.min(action.magazine, ammo) }, () => firstAt);
|
|
13584
|
-
return [firstAt];
|
|
13585
|
-
};
|
|
13586
13650
|
var activeParts = (fitted, catalogue) => fitted.flatMap((part) => {
|
|
13587
13651
|
const def = catalogue.get(part.id);
|
|
13588
13652
|
const isOn = def?.kind !== "light" && def?.kind !== "laser" ? true : part.on === true;
|
|
@@ -13815,6 +13879,10 @@ var GameWeaponsThree = (() => {
|
|
|
13815
13879
|
get safety() {
|
|
13816
13880
|
return this._safety;
|
|
13817
13881
|
}
|
|
13882
|
+
/** Kg of steel that heat up with the shots. */
|
|
13883
|
+
get barrelMass() {
|
|
13884
|
+
return barrelMassOf(this.def, this.rules.heat);
|
|
13885
|
+
}
|
|
13818
13886
|
get heat() {
|
|
13819
13887
|
return this._heat;
|
|
13820
13888
|
}
|
|
@@ -13867,7 +13935,7 @@ var GameWeaponsThree = (() => {
|
|
|
13867
13935
|
}
|
|
13868
13936
|
advance(seconds) {
|
|
13869
13937
|
if (seconds <= 0) return;
|
|
13870
|
-
this._heat = decayHeat(this._heat, seconds, this.rules.heat);
|
|
13938
|
+
this._heat = decayHeat(this._heat, seconds, this.barrelMass, this.rules.heat);
|
|
13871
13939
|
this.clock += seconds;
|
|
13872
13940
|
}
|
|
13873
13941
|
/** Complete what falls at or before `t`: scheduled events and the reload steps. */
|
|
@@ -14419,7 +14487,7 @@ var GameWeaponsThree = (() => {
|
|
|
14419
14487
|
res.shots.push(shot);
|
|
14420
14488
|
}
|
|
14421
14489
|
this._ammo -= 1;
|
|
14422
|
-
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound(a, cal, this.rules.heat) * this.load.heatFactor);
|
|
14490
|
+
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound({ action: a, caliber: cal, energy: energy * pellets, barrelMass: this.barrelMass, rules: this.rules.heat }) * this.load.heatFactor);
|
|
14423
14491
|
this.readyAt = t + 60 / a.rpm;
|
|
14424
14492
|
this.extra = Math.min(bloomNow + (a.bloomDeg ?? 0), a.spreadDeg * (BLOOM_CAP - 1));
|
|
14425
14493
|
this.extraClock = t;
|
|
@@ -14508,7 +14576,7 @@ var GameWeaponsThree = (() => {
|
|
|
14508
14576
|
}
|
|
14509
14577
|
const t = Math.max(start, this.readyAt);
|
|
14510
14578
|
this._ammo -= 1;
|
|
14511
|
-
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound(a, null, this.rules.heat));
|
|
14579
|
+
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound({ action: a, caliber: null, energy: 0, barrelMass: this.barrelMass, rules: this.rules.heat }));
|
|
14512
14580
|
this.emit({ type: "shot", shots: 0, rounds: 1, mode: this.mode, at: t });
|
|
14513
14581
|
return result("ok", { uses: launcherUses(a, this.explosive, origin, dir), recoil: [a.recoil[0], a.recoil[1]], noise: a.noise ?? 0, rounds: 1, roundTimes: [t - start] });
|
|
14514
14582
|
}
|
|
@@ -37549,6 +37617,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
37549
37617
|
signature = "";
|
|
37550
37618
|
});
|
|
37551
37619
|
return {
|
|
37620
|
+
get aimProgress() {
|
|
37621
|
+
return aimProgress;
|
|
37622
|
+
},
|
|
37552
37623
|
handleChange(change) {
|
|
37553
37624
|
if (change.kind === "action") return act(change.id);
|
|
37554
37625
|
if (change.kind === "control" && change.id === SUPPORTED_CONTROL_ID && typeof change.value === "boolean") {
|
|
@@ -43589,6 +43660,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
43589
43660
|
shoulderGripTo: 0.34,
|
|
43590
43661
|
/** The farthest apart two hands hold a long gun (a support hand past it slides back along the gun, toward the grip). */
|
|
43591
43662
|
supportSpan: 0.5,
|
|
43663
|
+
/** A gun carried at the hip (`carry: 'hip'`): its rear grip low at the right hip, a little ahead of it. */
|
|
43664
|
+
hipGrip: [0.25, -0.5, -0.24],
|
|
43592
43665
|
/** How much of the aim's pitch a tool held low in one hand follows. */
|
|
43593
43666
|
toolPitch: 0.5
|
|
43594
43667
|
};
|
|
@@ -43600,6 +43673,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
43600
43673
|
holder.scale.setScalar(1);
|
|
43601
43674
|
hand.position.set(...frame2.position);
|
|
43602
43675
|
hand.quaternion.set(...frame2.quaternion);
|
|
43676
|
+
if (placement.hip) return placeAtHip(placement);
|
|
43603
43677
|
const shouldered = !placement.handgun && placement.left !== null && placement.lengthMetres >= BODY_HOLD.shoulderedFrom;
|
|
43604
43678
|
if (shouldered) {
|
|
43605
43679
|
holder.position.set(0, BODY_HOLD.boreAbove, placement.rear);
|
|
@@ -43623,6 +43697,21 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
43623
43697
|
hand.position.add(want.sub(now));
|
|
43624
43698
|
hand.updateMatrixWorld(true);
|
|
43625
43699
|
};
|
|
43700
|
+
var placeAtHip = (placement) => {
|
|
43701
|
+
const { THREE, hand, holder } = placement;
|
|
43702
|
+
scratch.a ?? (scratch.a = new THREE.Vector3());
|
|
43703
|
+
scratch.b ?? (scratch.b = new THREE.Vector3());
|
|
43704
|
+
scratch.euler ?? (scratch.euler = new THREE.Euler());
|
|
43705
|
+
const turn2 = scratch.euler.setFromQuaternion(hand.quaternion, "YXZ");
|
|
43706
|
+
hand.quaternion.setFromEuler(turn2.set(turn2.x * BODY_HOLD.toolPitch, turn2.y, 0, "YXZ"));
|
|
43707
|
+
holder.position.set(0, 0, 0);
|
|
43708
|
+
hand.updateMatrixWorld(true);
|
|
43709
|
+
if (!placement.right) return;
|
|
43710
|
+
const want = scratch.a.set(...BODY_HOLD.hipGrip).applyQuaternion(hand.quaternion).add(hand.position);
|
|
43711
|
+
const now = placement.right.part.localToWorld(scratch.b.copy(placement.right.offset));
|
|
43712
|
+
hand.position.add(want.sub(now));
|
|
43713
|
+
hand.updateMatrixWorld(true);
|
|
43714
|
+
};
|
|
43626
43715
|
var limitSupportSpan = (targets) => {
|
|
43627
43716
|
const right = targets.R?.position;
|
|
43628
43717
|
const left = targets.L?.position;
|
|
@@ -43646,6 +43735,57 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
43646
43735
|
};
|
|
43647
43736
|
};
|
|
43648
43737
|
|
|
43738
|
+
// src/fx/view-hold.ts
|
|
43739
|
+
var VIEW_HOLD = {
|
|
43740
|
+
long: { grip: [0.2, -0.28, -0.38], fov: 84, sights: { distance: 0.34, fromRear: 0.3 } },
|
|
43741
|
+
handgun: { grip: [0.13, -0.15, -0.33], fov: 76, sights: { distance: 0.42, fromRear: 0.02 } },
|
|
43742
|
+
launcher: { grip: [0.2, -0.14, -0.3], fov: 84, sights: { distance: 0.18, fromRear: 0.25 } },
|
|
43743
|
+
tool: { grip: [0.21, -0.31, -0.36], fov: 84, sights: { distance: 0.3, fromRear: 0.1 }, tilt: 0.3 },
|
|
43744
|
+
// the gun at the hip, its rear grip low and to the right, the barrels ahead of the body; it has no sights to bring to the eye
|
|
43745
|
+
hip: { grip: [0.44, -0.32, -0.42], fov: 84, sights: { distance: 0.6, fromRear: 0.1 } }
|
|
43746
|
+
};
|
|
43747
|
+
var NO_GRIP_REAR = [0.2, -0.24, -0.12];
|
|
43748
|
+
var SIGHT_UNDER_EYE = 0.02;
|
|
43749
|
+
var scratch2 = { grip: null, hip: null, aimed: null, tilt: null };
|
|
43750
|
+
var ease = (k) => k * k * (3 - 2 * k);
|
|
43751
|
+
function placeInView(placement) {
|
|
43752
|
+
const { THREE, hand, holder, camera: camera2, right, box: box5, kind } = placement;
|
|
43753
|
+
const hold = VIEW_HOLD[kind];
|
|
43754
|
+
holder.scale.setScalar(1);
|
|
43755
|
+
hand.position.copy(camera2.position);
|
|
43756
|
+
hand.quaternion.copy(camera2.quaternion);
|
|
43757
|
+
if (hold.tilt) {
|
|
43758
|
+
scratch2.tilt ?? (scratch2.tilt = new THREE.Quaternion());
|
|
43759
|
+
hand.quaternion.multiply(scratch2.tilt.setFromAxisAngle(new THREE.Vector3(1, 0, 0), hold.tilt));
|
|
43760
|
+
}
|
|
43761
|
+
hand.scale.setScalar(1);
|
|
43762
|
+
holder.position.set(0, 0, 0);
|
|
43763
|
+
hand.updateMatrixWorld(true);
|
|
43764
|
+
scratch2.hip ?? (scratch2.hip = new THREE.Vector3());
|
|
43765
|
+
const hip = scratch2.hip;
|
|
43766
|
+
if (right) {
|
|
43767
|
+
scratch2.grip ?? (scratch2.grip = new THREE.Vector3());
|
|
43768
|
+
const grip = hand.worldToLocal(right.part.localToWorld(scratch2.grip.copy(right.offset)));
|
|
43769
|
+
hip.set(hold.grip[0] - grip.x, hold.grip[1] - grip.y, hold.grip[2] - grip.z);
|
|
43770
|
+
} else hip.set(NO_GRIP_REAR[0], NO_GRIP_REAR[1], NO_GRIP_REAR[2] + box5.min.x);
|
|
43771
|
+
const k = ease(Math.max(0, Math.min(1, placement.aim)));
|
|
43772
|
+
if (k > 0) {
|
|
43773
|
+
const along = box5.min.x + hold.sights.fromRear;
|
|
43774
|
+
scratch2.aimed ?? (scratch2.aimed = new THREE.Vector3());
|
|
43775
|
+
hip.lerp(scratch2.aimed.set(0, -SIGHT_UNDER_EYE - box5.max.y, along - hold.sights.distance), k);
|
|
43776
|
+
}
|
|
43777
|
+
holder.position.copy(hip).add(placement.offset);
|
|
43778
|
+
hand.updateMatrixWorld(true);
|
|
43779
|
+
}
|
|
43780
|
+
function toWorldLens(camera2, point, worldFov, lensFov) {
|
|
43781
|
+
const k = Math.tan(worldFov * Math.PI / 360) / Math.tan(lensFov * Math.PI / 360);
|
|
43782
|
+
camera2.updateMatrixWorld();
|
|
43783
|
+
camera2.worldToLocal(point);
|
|
43784
|
+
point.x *= k;
|
|
43785
|
+
point.y *= k;
|
|
43786
|
+
return camera2.localToWorld(point);
|
|
43787
|
+
}
|
|
43788
|
+
|
|
43649
43789
|
// src/fx/hand-hold.ts
|
|
43650
43790
|
var HAND_HOLD = {
|
|
43651
43791
|
/** Half the width of a pistol grip, the palm sits this far (plus the palm) off its middle. */
|
|
@@ -43724,6 +43864,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
43724
43864
|
const toRoot = (x, y, z) => V(THREE, inner.position.x + x * inner.scale.x, y, z);
|
|
43725
43865
|
const handgun = parts.family === "pistol" || parts.family === "revolver";
|
|
43726
43866
|
root.updateWorldMatrix(true, true);
|
|
43867
|
+
if (parts.holdRight || parts.holdLeft) return namedHold(THREE, model, holderScale);
|
|
43727
43868
|
let gripAt;
|
|
43728
43869
|
let up;
|
|
43729
43870
|
if (parts.grip) {
|
|
@@ -43770,6 +43911,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
43770
43911
|
gripLeft: HAND_HOLD.forend
|
|
43771
43912
|
};
|
|
43772
43913
|
}
|
|
43914
|
+
function namedHold(THREE, model, holderScale) {
|
|
43915
|
+
const { parts } = model;
|
|
43916
|
+
const on = (mark, fingers) => mark ? { part: mark, offset: V(THREE, 0, HAND_HOLD.palm, 0), quaternion: handFrame(THREE, fingers, V(THREE, 0, 1, 0)) } : null;
|
|
43917
|
+
return {
|
|
43918
|
+
right: on(parts.holdRight, V(THREE, 1, 0, 0)),
|
|
43919
|
+
left: on(parts.holdLeft, V(THREE, 0, 0, 1)),
|
|
43920
|
+
leftMagazine: null,
|
|
43921
|
+
scale: holderScale,
|
|
43922
|
+
grip: HAND_HOLD.closed,
|
|
43923
|
+
gripLeft: HAND_HOLD.closed
|
|
43924
|
+
};
|
|
43925
|
+
}
|
|
43773
43926
|
function holdOfProp(THREE, group, category, scale) {
|
|
43774
43927
|
const handle = group.getObjectByName("handle") ?? group.getObjectByName("body") ?? group;
|
|
43775
43928
|
const head = group.getObjectByName("head");
|
|
@@ -51237,6 +51390,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
51237
51390
|
const q2 = new THREE.Quaternion();
|
|
51238
51391
|
const pointForward = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
|
|
51239
51392
|
const frontOf = new THREE.Vector3();
|
|
51393
|
+
const restBox = new THREE.Box3();
|
|
51394
|
+
const noMotion = new THREE.Vector3();
|
|
51395
|
+
let inLens = false;
|
|
51396
|
+
const setLens = (on) => {
|
|
51397
|
+
if (on !== inLens) options.viewmodelFov?.(on ? VIEW_HOLD.tool.fov : null);
|
|
51398
|
+
inLens = on;
|
|
51399
|
+
const layer3 = on ? FIRST_PERSON_LAYER : 0;
|
|
51400
|
+
hand.traverse((node) => node.layers.set(layer3));
|
|
51401
|
+
};
|
|
51240
51402
|
const equip = (weapon) => {
|
|
51241
51403
|
if (model) hand.remove(model);
|
|
51242
51404
|
model = null;
|
|
@@ -51244,6 +51406,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
51244
51406
|
def = arsenal.weapons.get(weapon) ?? null;
|
|
51245
51407
|
if (!def || BODY_ACTIONS.has(def.id)) return;
|
|
51246
51408
|
model = buildWeaponModel(THREE, def, options.items);
|
|
51409
|
+
restBox.setFromObject(model);
|
|
51410
|
+
inLens = false;
|
|
51247
51411
|
const length2 = new THREE.Box3().setFromObject(model).getSize(v).x;
|
|
51248
51412
|
rear = new THREE.Box3().setFromObject(model).min.x;
|
|
51249
51413
|
lengthMetres = length2;
|
|
@@ -51344,6 +51508,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
51344
51508
|
return {
|
|
51345
51509
|
unequip() {
|
|
51346
51510
|
if (model) hand.remove(model);
|
|
51511
|
+
if (inLens) setLens(false);
|
|
51347
51512
|
model = null;
|
|
51348
51513
|
inHand = null;
|
|
51349
51514
|
hold = null;
|
|
@@ -51352,6 +51517,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
51352
51517
|
if (!model || !def || !SPOUTS.has(def.action.kind)) return null;
|
|
51353
51518
|
hand.updateMatrixWorld(true);
|
|
51354
51519
|
const at3 = model.localToWorld(v.copy(frontOf));
|
|
51520
|
+
if (inLens) toWorldLens(camera2, at3, camera2.fov ?? 72, VIEW_HOLD.tool.fov);
|
|
51355
51521
|
const along = v2.set(1, 0, 0).applyQuaternion(model.getWorldQuaternion(q2)).normalize();
|
|
51356
51522
|
return { position: [at3.x, at3.y, at3.z], direction: [along.x, along.y, along.z], drawsFlash: false };
|
|
51357
51523
|
},
|
|
@@ -51374,7 +51540,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
51374
51540
|
update(dt) {
|
|
51375
51541
|
kick *= Math.exp(-dt * 14);
|
|
51376
51542
|
dip += ((reloading ? 1 : 0) - dip) * Math.min(1, dt * 8);
|
|
51377
|
-
if (inHand && model) {
|
|
51543
|
+
if (inHand && model && options.firstPerson?.()) {
|
|
51544
|
+
setLens(true);
|
|
51545
|
+
placeInView({ THREE, hand, holder: model, camera: camera2, right: hold?.right ?? null, box: restBox, kind: "tool", aim: 0, offset: noMotion });
|
|
51546
|
+
hand.position.add(v.set(0, -0.12 * dip, 0.05 * kick).applyQuaternion(camera2.quaternion));
|
|
51547
|
+
hand.updateMatrixWorld(true);
|
|
51548
|
+
} else if (inHand && model) {
|
|
51549
|
+
if (inLens) setLens(false);
|
|
51378
51550
|
const handgun = def?.category === "pistol" || def?.category === "revolver";
|
|
51379
51551
|
placeOnBody({ THREE, hand, holder: model, frame: options.bodyHold?.() ?? eyeFrame(), rear, lengthMetres, handgun, right: hold?.right ?? null, left: hold?.left ?? null });
|
|
51380
51552
|
hand.position.add(v.set(0, -0.12 * dip, 0.05 * kick).applyQuaternion(camera2.quaternion));
|
|
@@ -53915,6 +54087,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
53915
54087
|
cylinderZ(group, 0.016, 0.07, M.poly, 0.06, -0.01, side * 0.2, 14);
|
|
53916
54088
|
}
|
|
53917
54089
|
parts.trigger = box5(group, 0.012, 0.02, 0.016, M.dark, 0.1, 0.085, 0.14, 0.3);
|
|
54090
|
+
parts.holdRight = kit.mark(group, 0.06, 6e-3, 0.2);
|
|
54091
|
+
parts.holdLeft = kit.mark(group, 0.22, 0.164, 0);
|
|
54092
|
+
parts.carry = "hip";
|
|
53918
54093
|
parts.safety = box5(group, 0.014, 6e-3, 0.01, M.dark, 0.2, 0.073, -0.076, 0.4);
|
|
53919
54094
|
}
|
|
53920
54095
|
function buildFeed(kit, parts, group) {
|
|
@@ -54346,7 +54521,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
54346
54521
|
var ROOT = "root";
|
|
54347
54522
|
var AXIS_INDEX = { x: 0, y: 1, z: 2 };
|
|
54348
54523
|
var EASE_STEPS = 10;
|
|
54349
|
-
var
|
|
54524
|
+
var ease2 = (progress) => progress < 0.5 ? 2 * progress * progress : 1 - (-2 * progress + 2) ** 2 / 2;
|
|
54350
54525
|
var move = (part, axis2, start, duration, from, to) => ({ part, channel: "position", axis: axis2, start, duration, from, to });
|
|
54351
54526
|
var turn = (part, axis2, start, duration, from, to) => ({ part, channel: "rotation", axis: axis2, start, duration, from, to });
|
|
54352
54527
|
var cue = (t, type, data) => ({ t, type, ...data ? { data } : {} });
|
|
@@ -54360,7 +54535,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
54360
54535
|
for (const tween of tweens) {
|
|
54361
54536
|
if (tween.start > t || tween.duration === 0 && (tween.start === t ? !includeInstants : false)) continue;
|
|
54362
54537
|
if (tween.duration === 0 || t >= tween.start + tween.duration) value = tween.to;
|
|
54363
|
-
else value = tween.from + (tween.to - tween.from) *
|
|
54538
|
+
else value = tween.from + (tween.to - tween.from) * ease2((t - tween.start) / tween.duration);
|
|
54364
54539
|
}
|
|
54365
54540
|
return value;
|
|
54366
54541
|
};
|
|
@@ -57287,7 +57462,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
57287
57462
|
var round4 = call("round");
|
|
57288
57463
|
var clamp3 = call("clamp");
|
|
57289
57464
|
var lerp2 = call("lerp");
|
|
57290
|
-
var
|
|
57465
|
+
var ease3 = call("ease");
|
|
57291
57466
|
var lt = call("lt");
|
|
57292
57467
|
var gt = call("gt");
|
|
57293
57468
|
var le = call("le");
|
|
@@ -64419,38 +64594,6 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
64419
64594
|
};
|
|
64420
64595
|
}
|
|
64421
64596
|
|
|
64422
|
-
// src/fx/view-hold.ts
|
|
64423
|
-
var VIEW_HOLD = {
|
|
64424
|
-
/** The right hand's grip, from the eye. */
|
|
64425
|
-
grip: [0.2, -0.2, -0.3],
|
|
64426
|
-
/** A handgun's grip: higher and nearer the middle, the arms out in front. */
|
|
64427
|
-
handgunGrip: [0.13, -0.15, -0.33],
|
|
64428
|
-
/** A rocket launcher's grip: its tube rides on the shoulder, so the hands are higher. */
|
|
64429
|
-
launcherGrip: [0.2, -0.14, -0.3],
|
|
64430
|
-
/** A gun with no grip anchor: the rear of its bore, from the eye. */
|
|
64431
|
-
rear: [0.2, -0.24, -0.12]
|
|
64432
|
-
};
|
|
64433
|
-
var scratch2 = { grip: null };
|
|
64434
|
-
function placeInView(placement) {
|
|
64435
|
-
const { THREE, hand, holder, camera: camera2, right } = placement;
|
|
64436
|
-
holder.scale.setScalar(1);
|
|
64437
|
-
hand.position.copy(camera2.position);
|
|
64438
|
-
hand.quaternion.copy(camera2.quaternion);
|
|
64439
|
-
hand.scale.setScalar(1);
|
|
64440
|
-
holder.position.set(0, 0, 0);
|
|
64441
|
-
hand.updateMatrixWorld(true);
|
|
64442
|
-
if (!right) {
|
|
64443
|
-
holder.position.set(VIEW_HOLD.rear[0], VIEW_HOLD.rear[1], VIEW_HOLD.rear[2] + placement.rear);
|
|
64444
|
-
hand.updateMatrixWorld(true);
|
|
64445
|
-
return;
|
|
64446
|
-
}
|
|
64447
|
-
scratch2.grip ?? (scratch2.grip = new THREE.Vector3());
|
|
64448
|
-
const grip = hand.worldToLocal(right.part.localToWorld(scratch2.grip.copy(right.offset)));
|
|
64449
|
-
const [x, y, z] = placement.kind === "handgun" ? VIEW_HOLD.handgunGrip : placement.kind === "launcher" ? VIEW_HOLD.launcherGrip : VIEW_HOLD.grip;
|
|
64450
|
-
holder.position.set(x - grip.x, y - grip.y, z - grip.z);
|
|
64451
|
-
hand.updateMatrixWorld(true);
|
|
64452
|
-
}
|
|
64453
|
-
|
|
64454
64597
|
// src/fx/heavy.ts
|
|
64455
64598
|
var PI14 = Math.PI;
|
|
64456
64599
|
var ROCKET_LIGHT_NAME = "rocket-light";
|
|
@@ -64835,11 +64978,12 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
64835
64978
|
switch (event.type) {
|
|
64836
64979
|
case "muzzle_flash":
|
|
64837
64980
|
if (data.at === "ugl") {
|
|
64838
|
-
if (parts.uglMuzzle && world.layers.muzzleFlash) effects.muzzleFlash(positionOf3(parts.uglMuzzle), root.getWorldQuaternion(new THREE.Quaternion()), UGL_FLASH);
|
|
64981
|
+
if (parts.uglMuzzle && world.layers.muzzleFlash) world.afterPose(() => parts.uglMuzzle && effects.muzzleFlash(positionOf3(parts.uglMuzzle), root.getWorldQuaternion(new THREE.Quaternion()), UGL_FLASH));
|
|
64839
64982
|
} else if (parts.muzzle && world.layers.muzzleFlash && (session.def.action.kind === "firearm" || session.def.action.kind === "launcher")) {
|
|
64840
64983
|
const profile = muzzleSmokeOf({ caliber: session.caliber, weapon: session.def, suppressed: session.suppressed });
|
|
64841
64984
|
const size = session.def.action.kind === "launcher" ? 2.2 : FLASH_BY_CASE[session.caseType];
|
|
64842
|
-
|
|
64985
|
+
const muzzle2 = parts.muzzle;
|
|
64986
|
+
world.afterPose(() => effects.muzzleFlash(positionOf3(muzzle2), root.getWorldQuaternion(new THREE.Quaternion()), size, profile));
|
|
64843
64987
|
}
|
|
64844
64988
|
break;
|
|
64845
64989
|
case "eject_casing":
|
|
@@ -65377,7 +65521,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65377
65521
|
|
|
65378
65522
|
// src/fx/viewmodel.ts
|
|
65379
65523
|
var PI16 = Math.PI;
|
|
65380
|
-
var HEAT_DISPLAY_MAX_FALLBACK =
|
|
65524
|
+
var HEAT_DISPLAY_MAX_FALLBACK = 750;
|
|
65525
|
+
var SMOKE_WISPS_PER_SECOND = 10;
|
|
65526
|
+
var SMOKE_THICKNESS_GAIN = 1.7;
|
|
65381
65527
|
var WALL_PULL = { margin: 0.03, max: 1.2, rate: 14, probe: 3 };
|
|
65382
65528
|
var HAND_IN_VIEW = { floor: -0.88, max: 0.3, rate: 10 };
|
|
65383
65529
|
var LAUNCH_VOLUME = 0.6;
|
|
@@ -65396,6 +65542,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65396
65542
|
const held = sinceShot < TRIGGER_FINGER.burstSeconds ? TRIGGER_FINGER.pulled - TRIGGER_FINGER.tremor * (0.5 + 0.5 * Math.sin(sinceShot * 220)) : 0;
|
|
65397
65543
|
return Math.max(ready + (TRIGGER_FINGER.pulled - ready) * pull, held);
|
|
65398
65544
|
};
|
|
65545
|
+
var VIEW_MOTION = { sway: 6e-3, swayMax: 0.02, swayRate: 9, bobX: 6e-3, bobY: 8e-3, run: 1.6, fullSpeed: 4, frequency: 3.2 };
|
|
65399
65546
|
function createViewmodel(options) {
|
|
65400
65547
|
const { THREE, scene, camera: camera2, arsenal, groundAt, audio } = options;
|
|
65401
65548
|
const kit = modelKit(THREE);
|
|
@@ -65403,6 +65550,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65403
65550
|
const layers = options.layers ?? createLayers();
|
|
65404
65551
|
const distance3 = () => options.soundDistance?.() ?? 0;
|
|
65405
65552
|
const particles = createParticles(THREE, scene, groundAt, options.particleLimit);
|
|
65553
|
+
const spawnParticle = particles.spawn.bind(particles);
|
|
65554
|
+
particles.spawn = (object2, velocity, particleOptions) => {
|
|
65555
|
+
if (lens2) toWorldLens(camera2, object2.position, worldFovOf(), lens2.fov);
|
|
65556
|
+
spawnParticle(object2, velocity, particleOptions);
|
|
65557
|
+
};
|
|
65406
65558
|
particles.onBounce = (kind, hit) => {
|
|
65407
65559
|
if (!audio || kind !== "casing" && kind !== "magazine") return;
|
|
65408
65560
|
const surface = hit ? options.surfaceAt?.(hit.object.position.x, hit.object.position.z) : void 0;
|
|
@@ -65415,7 +65567,16 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65415
65567
|
};
|
|
65416
65568
|
if (!options.effects) warnOnce("game-weapons-three.own-effects-world", "game-weapons-three made an effects world of its own because the host lent none (options.effects); pass the host effects so the effects share one budget");
|
|
65417
65569
|
const ownVfx = options.effects ? void 0 : createVfxRenderer(THREE, { scene, camera: camera2, vfx: { profile: "medium" }, ...options.lights ? { lights: options.lights } : {} });
|
|
65418
|
-
const
|
|
65570
|
+
const worldSink = options.effects ?? ownVfx;
|
|
65571
|
+
const lensSink = worldSink ? {
|
|
65572
|
+
play: (request) => {
|
|
65573
|
+
if (!lens2 || !request.point) return worldSink.play(request);
|
|
65574
|
+
const at3 = toWorldLens(camera2, lensPoint.set(...request.point), worldFovOf(), lens2.fov);
|
|
65575
|
+
return worldSink.play({ ...request, point: [at3.x, at3.y, at3.z] });
|
|
65576
|
+
},
|
|
65577
|
+
stop: (handle) => worldSink.stop(handle)
|
|
65578
|
+
} : void 0;
|
|
65579
|
+
const effects = createEffects(THREE, lensSink, random);
|
|
65419
65580
|
const hand = new THREE.Group();
|
|
65420
65581
|
hand.name = VIEWMODEL_NODE_NAME;
|
|
65421
65582
|
scene.add(hand);
|
|
@@ -65441,6 +65602,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65441
65602
|
const rootQuaternion = new THREE.Quaternion();
|
|
65442
65603
|
const muzzleAt = new THREE.Vector3();
|
|
65443
65604
|
const muzzleAlong = new THREE.Vector3();
|
|
65605
|
+
const posed = [];
|
|
65444
65606
|
const world = {
|
|
65445
65607
|
kit,
|
|
65446
65608
|
scene,
|
|
@@ -65454,13 +65616,17 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65454
65616
|
const played = audio?.cue(cue3, profile, lead);
|
|
65455
65617
|
options.onSound?.({ weapon, cue: cue3, profile, ...played ? { played } : {} });
|
|
65456
65618
|
},
|
|
65457
|
-
|
|
65619
|
+
afterPose: (emit2) => void posed.push(emit2),
|
|
65620
|
+
schedule: (delay, seconds, step, done) => void tasks.push({ delay, seconds, elapsed: 0, step: (progress) => step(ease2(progress)), done })
|
|
65458
65621
|
};
|
|
65459
65622
|
const heatMax = arsenal.rules.heat.displayMax || HEAT_DISPLAY_MAX_FALLBACK;
|
|
65460
65623
|
const visual = arsenal.rules.heat.visual;
|
|
65461
65624
|
const hasSuppressor = (parts) => parts.some((part) => arsenal.attachments.get(part.id)?.kind === "suppressor");
|
|
65462
65625
|
const release = () => {
|
|
65463
65626
|
if (!session) return;
|
|
65627
|
+
if (lens2) options.viewmodelFov?.(null);
|
|
65628
|
+
lens2 = null;
|
|
65629
|
+
lensLayer = -1;
|
|
65464
65630
|
session.attachments?.dispose();
|
|
65465
65631
|
discardObject3D(session.model.root);
|
|
65466
65632
|
player = null;
|
|
@@ -65500,6 +65666,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65500
65666
|
const modelBox = new THREE.Box3().setFromObject(model.root);
|
|
65501
65667
|
const length2 = modelBox.getSize(new THREE.Vector3()).x;
|
|
65502
65668
|
modelRear = modelBox.min.x;
|
|
65669
|
+
restBox.copy(modelBox);
|
|
65670
|
+
lens2 = null;
|
|
65671
|
+
lensLayer = -1;
|
|
65503
65672
|
holder.add(model.root);
|
|
65504
65673
|
const caliber = caliberOf(arsenal, def);
|
|
65505
65674
|
const dims = caliber?.cartridge;
|
|
@@ -65562,6 +65731,42 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65562
65731
|
let reach = 0;
|
|
65563
65732
|
let pull = 0;
|
|
65564
65733
|
let lift = 0;
|
|
65734
|
+
const restBox = new THREE.Box3();
|
|
65735
|
+
let lens2 = null;
|
|
65736
|
+
let lensLayer = -1;
|
|
65737
|
+
const lensPoint = new THREE.Vector3();
|
|
65738
|
+
const worldFovOf = () => camera2.fov ?? 72;
|
|
65739
|
+
const setLens = (kind) => {
|
|
65740
|
+
const fov = kind ? VIEW_HOLD[kind].fov : null;
|
|
65741
|
+
if ((lens2?.fov ?? null) !== fov) options.viewmodelFov?.(fov);
|
|
65742
|
+
lens2 = kind && fov !== null ? { kind, fov } : null;
|
|
65743
|
+
const layer3 = lens2 ? FIRST_PERSON_LAYER : 0;
|
|
65744
|
+
if (layer3 === lensLayer && !lens2) return;
|
|
65745
|
+
lensLayer = layer3;
|
|
65746
|
+
hand.traverse((node) => node.layers.set(layer3));
|
|
65747
|
+
};
|
|
65748
|
+
const motion = { phase: 0, swayX: 0, swayY: 0, lastYaw: Number.NaN, lastPitch: Number.NaN };
|
|
65749
|
+
const motionEuler = new THREE.Euler(0, 0, 0, "YXZ");
|
|
65750
|
+
const motionOffset = new THREE.Vector3();
|
|
65751
|
+
const viewMotion = (dt, aim) => {
|
|
65752
|
+
const moving = options.motion?.() ?? { speed: 0, running: false };
|
|
65753
|
+
const calm = 1 - 0.8 * Math.max(0, Math.min(1, aim));
|
|
65754
|
+
motionEuler.setFromQuaternion(camera2.quaternion, "YXZ");
|
|
65755
|
+
const turnYaw = Number.isNaN(motion.lastYaw) || dt <= 0 ? 0 : Math.atan2(Math.sin(motionEuler.y - motion.lastYaw), Math.cos(motionEuler.y - motion.lastYaw)) / dt;
|
|
65756
|
+
const turnPitch = Number.isNaN(motion.lastPitch) || dt <= 0 ? 0 : (motionEuler.x - motion.lastPitch) / dt;
|
|
65757
|
+
motion.lastYaw = motionEuler.y;
|
|
65758
|
+
motion.lastPitch = motionEuler.x;
|
|
65759
|
+
const follow = Math.min(1, dt * VIEW_MOTION.swayRate);
|
|
65760
|
+
motion.swayX += (Math.max(-VIEW_MOTION.swayMax, Math.min(VIEW_MOTION.swayMax, turnYaw * VIEW_MOTION.sway)) - motion.swayX) * follow;
|
|
65761
|
+
motion.swayY += (Math.max(-VIEW_MOTION.swayMax, Math.min(VIEW_MOTION.swayMax, -turnPitch * VIEW_MOTION.sway)) - motion.swayY) * follow;
|
|
65762
|
+
const stride = Math.min(1, moving.speed / VIEW_MOTION.fullSpeed) * (moving.running ? VIEW_MOTION.run : 1);
|
|
65763
|
+
motion.phase += dt * moving.speed * VIEW_MOTION.frequency;
|
|
65764
|
+
return motionOffset.set(
|
|
65765
|
+
(motion.swayX + Math.sin(motion.phase) * VIEW_MOTION.bobX * stride) * calm,
|
|
65766
|
+
(motion.swayY - Math.abs(Math.cos(motion.phase)) * VIEW_MOTION.bobY * stride) * calm,
|
|
65767
|
+
0
|
|
65768
|
+
);
|
|
65769
|
+
};
|
|
65565
65770
|
const ahead = new THREE.Vector3();
|
|
65566
65771
|
const up = new THREE.Vector3();
|
|
65567
65772
|
const seen = new THREE.Vector3();
|
|
@@ -65594,13 +65799,17 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65594
65799
|
const family = session.model.parts.family;
|
|
65595
65800
|
session.holderScale = 1;
|
|
65596
65801
|
if (options.firstPerson?.()) {
|
|
65597
|
-
|
|
65802
|
+
const kind = session.model.parts.carry === "hip" ? "hip" : family === "pistol" || family === "revolver" ? "handgun" : family === "rocket" ? "launcher" : "long";
|
|
65803
|
+
const aim = kind === "hip" ? 0 : options.aim?.() ?? 0;
|
|
65804
|
+
placeInView({ THREE, hand, holder, camera: camera2, right: hold?.right ?? null, box: restBox, kind, aim, offset: viewMotion(dt, aim) });
|
|
65805
|
+
setLens(kind);
|
|
65598
65806
|
lift = 0;
|
|
65599
|
-
|
|
65807
|
+
pull = 0;
|
|
65600
65808
|
return;
|
|
65601
65809
|
}
|
|
65810
|
+
setLens(null);
|
|
65602
65811
|
hand.scale.set(1, 1, 1);
|
|
65603
|
-
placeOnBody({ THREE, hand, holder, frame: options.bodyHold?.() ?? eyeFrame(), rear: modelRear, lengthMetres: session.lengthMetres, handgun: family === "pistol" || family === "revolver", right: hold?.right ?? null, left: hold?.left ?? null });
|
|
65812
|
+
placeOnBody({ THREE, hand, holder, frame: options.bodyHold?.() ?? eyeFrame(), rear: modelRear, lengthMetres: session.lengthMetres, handgun: family === "pistol" || family === "revolver", hip: session.model.parts.carry === "hip", right: hold?.right ?? null, left: hold?.left ?? null });
|
|
65604
65813
|
hand.updateMatrixWorld(true);
|
|
65605
65814
|
lift += (liftToKeepInView() - lift) * Math.min(1, dt * HAND_IN_VIEW.rate);
|
|
65606
65815
|
if (lift > 1e-4) hand.position.addScaledVector(up.set(0, 1, 0).applyQuaternion(camera2.quaternion), lift);
|
|
@@ -65676,6 +65885,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65676
65885
|
if (session) {
|
|
65677
65886
|
place(dt);
|
|
65678
65887
|
player?.update(dt);
|
|
65888
|
+
if (posed.length) {
|
|
65889
|
+
hand.updateMatrixWorld(true);
|
|
65890
|
+
for (const emit2 of posed.splice(0)) emit2();
|
|
65891
|
+
}
|
|
65679
65892
|
const wantsMagazine = reloading || options.tool?.().reloading === true;
|
|
65680
65893
|
magazineHand += ((wantsMagazine ? 1 : 0) - magazineHand) * Math.min(1, dt * HAND_HOLD.magRate);
|
|
65681
65894
|
const tool2 = options.tool?.();
|
|
@@ -65691,10 +65904,11 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65691
65904
|
}
|
|
65692
65905
|
secondsSinceShot += dt;
|
|
65693
65906
|
if (tool2 && tool2.heat !== void 0 && tool2.heat * heatMax > visual.smokeFrom && secondsSinceShot < visual.smokeSeconds && session.model.parts.muzzle) {
|
|
65694
|
-
|
|
65907
|
+
const smokeLevel = Math.min(1, (tool2.heat * heatMax - visual.smokeFrom) / visual.smokeSpan);
|
|
65908
|
+
smokeDebt += dt * smokeLevel * SMOKE_WISPS_PER_SECOND;
|
|
65695
65909
|
while (smokeDebt > 1) {
|
|
65696
65910
|
smokeDebt -= 1;
|
|
65697
|
-
const k = 0.5 +
|
|
65911
|
+
const k = 0.5 + smokeLevel * SMOKE_THICKNESS_GAIN;
|
|
65698
65912
|
effects.smoke(worldPositionOf(session, session.model.parts.muzzle, new THREE.Vector3()), new THREE.Vector3((random() - 0.5) * 0.015, 0.07 + random() * 0.08, (random() - 0.5) * 0.015), 4e-3 * k, 1.2 + random() * 0.6, Math.min(0.18, 0.06 + k * 0.04));
|
|
65699
65913
|
}
|
|
65700
65914
|
}
|
|
@@ -65721,6 +65935,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65721
65935
|
if (!session || !mark) return null;
|
|
65722
65936
|
hand.updateMatrixWorld(true);
|
|
65723
65937
|
const at3 = worldPositionOf(session, mark, muzzleAt);
|
|
65938
|
+
if (lens2) toWorldLens(camera2, at3, worldFovOf(), lens2.fov);
|
|
65724
65939
|
const along = muzzleAlong.set(1, 0, 0).applyQuaternion(session.model.root.getWorldQuaternion(rootQuaternion)).normalize();
|
|
65725
65940
|
const kind = session.def.action.kind;
|
|
65726
65941
|
return { position: [at3.x, at3.y, at3.z], direction: [along.x, along.y, along.z], drawsFlash: kind === "firearm" || kind === "launcher" };
|
|
@@ -65730,7 +65945,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65730
65945
|
hand.updateMatrixWorld(true);
|
|
65731
65946
|
const targets = targetsOf(THREE, hold, session.model.root.getWorldQuaternion(rootQuaternion), magazineHand, hold.works ? workWeights(hold.works, player?.running ?? []) : void 0);
|
|
65732
65947
|
const trigger = session.model.parts.trigger;
|
|
65733
|
-
if (
|
|
65948
|
+
if (session.model.parts.carry === "hip") targets.fingers = { index: 1 };
|
|
65949
|
+
else if (trigger) targets.fingers = { index: indexCurl(trigger.rotation.z - triggerRest, clock - lastShot) };
|
|
65734
65950
|
return limitSupportSpan(targets);
|
|
65735
65951
|
},
|
|
65736
65952
|
get inHand() {
|
|
@@ -65780,6 +65996,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
65780
65996
|
...options.contact ? { contact: options.contact } : {},
|
|
65781
65997
|
...options.bodyHold ? { bodyHold: options.bodyHold } : {},
|
|
65782
65998
|
...options.firstPerson ? { firstPerson: options.firstPerson } : {},
|
|
65999
|
+
...options.viewmodelFov ? { viewmodelFov: options.viewmodelFov } : {},
|
|
66000
|
+
...options.aim ? { aim: options.aim } : {},
|
|
66001
|
+
...options.motion ? { motion: options.motion } : {},
|
|
65783
66002
|
...options.effects ? { effects: options.effects } : {},
|
|
65784
66003
|
...options.flyRocket === void 0 ? {} : { flyRocket: options.flyRocket },
|
|
65785
66004
|
...options.particleLimit ? { particleLimit: options.particleLimit } : {},
|
|
@@ -66895,7 +67114,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
66895
67114
|
fuseLength: "Dynamite fuse length",
|
|
66896
67115
|
fuseLengthHint: "Metres of safety fuse (131 s per metre): a long one is set down lit, for a delayed trap",
|
|
66897
67116
|
layers: { muzzle_flash: "Muzzle flash", casings: "Ejected casings", magazines: "Dropped magazines" },
|
|
66898
|
-
metrics: { casings_live: "Casings in the scene", magazines_live: "Magazines in the scene", heat: "Barrel heat" }
|
|
67117
|
+
metrics: { casings_live: "Casings in the scene", magazines_live: "Magazines in the scene", heat: "Barrel temperature above ambient", rounds_to_warning: "Rounds to the heat warning (cyclic rate, from cold)" }
|
|
66899
67118
|
},
|
|
66900
67119
|
"pt-BR": {
|
|
66901
67120
|
group: "Armas",
|
|
@@ -66931,7 +67150,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
66931
67150
|
fuseLength: "Pavio da dinamite",
|
|
66932
67151
|
fuseLengthHint: "Metros de pavio de seguran\xE7a (131 s por metro): um longo \xE9 posto no ch\xE3o aceso, para armadilha com atraso",
|
|
66933
67152
|
layers: { muzzle_flash: "Clar\xE3o do cano", casings: "C\xE1psulas ejetadas", magazines: "Pentes que caem" },
|
|
66934
|
-
metrics: { casings_live: "C\xE1psulas na cena", magazines_live: "Pentes na cena", heat: "
|
|
67153
|
+
metrics: { casings_live: "C\xE1psulas na cena", magazines_live: "Pentes na cena", heat: "Temperatura do cano acima do ambiente", rounds_to_warning: "Tiros at\xE9 o aviso de calor (cad\xEAncia, a frio)" }
|
|
66935
67154
|
}
|
|
66936
67155
|
};
|
|
66937
67156
|
var textOf = (locale) => TEXT[locale] ?? TEXT.en;
|
|
@@ -67055,7 +67274,12 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
67055
67274
|
let host = null;
|
|
67056
67275
|
let soundDistance = 0;
|
|
67057
67276
|
let soundIndoors = false;
|
|
67058
|
-
const
|
|
67277
|
+
const barrelCelsius = () => (host?.tool().heat ?? 0) * arsenal.rules.heat.displayMax;
|
|
67278
|
+
const roundsToWarning2 = () => {
|
|
67279
|
+
const weaponId = host?.tool().weapon;
|
|
67280
|
+
const rounds = weaponId ? roundsToWarningOf(arsenal, weaponId) : Infinity;
|
|
67281
|
+
return Number.isFinite(rounds) ? rounds : "-";
|
|
67282
|
+
};
|
|
67059
67283
|
return {
|
|
67060
67284
|
id: "weapons_area",
|
|
67061
67285
|
name: text.name,
|
|
@@ -67108,7 +67332,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
67108
67332
|
metrics: () => [
|
|
67109
67333
|
{ id: "casings_live", name: text.metrics.casings_live, read: () => fx?.casings ?? 0 },
|
|
67110
67334
|
{ id: "magazines_live", name: text.metrics.magazines_live, read: () => fx?.magazines ?? 0 },
|
|
67111
|
-
{ id: "heat", name: text.metrics.heat, unit: "
|
|
67335
|
+
{ id: "heat", name: text.metrics.heat, unit: "\xB0C", max: arsenal.rules.heat.displayMax, digits: 0, read: barrelCelsius },
|
|
67336
|
+
{ id: "rounds_to_warning", name: text.metrics.rounds_to_warning, read: roundsToWarning2 },
|
|
67112
67337
|
...accessoryMetrics(accessoryText, () => host?.tool() ?? EMPTY_TOOL)
|
|
67113
67338
|
],
|
|
67114
67339
|
attach(lent) {
|
|
@@ -67151,6 +67376,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
67151
67376
|
contact: createLaserRaycast(lent.THREE, lent.scene, lent.camera, { now: () => simulatedMs }),
|
|
67152
67377
|
...lent.holdFrame ? { bodyHold: () => lent.holdFrame?.() ?? null } : {},
|
|
67153
67378
|
firstPerson: () => lent.player().cameraMode === "first",
|
|
67379
|
+
// the lens of the gun in first person, how far it is brought to the eye (the right button) and how the body moves (the bob and the sway follow it)
|
|
67380
|
+
...lent.setViewmodelFov ? { viewmodelFov: (degrees) => lent.setViewmodelFov?.(degrees) } : {},
|
|
67381
|
+
aim: () => accessories.aimProgress,
|
|
67382
|
+
motion: () => ({ speed: lent.player().speed, running: lent.player().running }),
|
|
67154
67383
|
...lent.effects ? { effects: lent.effects } : {},
|
|
67155
67384
|
...lent.particleLimit ? { particleLimit: lent.particleLimit } : {},
|
|
67156
67385
|
...isLightBudget(lent.lights) ? { lights: lent.lights } : {},
|