@adatechnology/game-test-room 0.27.0 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +22 -2
- package/dist/index.global.js +200 -63
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +86 -5
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
package/dist/index.d.ts
CHANGED
|
@@ -485,7 +485,9 @@ interface RoomAvatar {
|
|
|
485
485
|
*/
|
|
486
486
|
eye?(out?: THREE_NS.Vector3): THREE_NS.Vector3;
|
|
487
487
|
/** Hides the head and neck from `camera` while the view is `first` (shadows, mirrors and other cameras keep seeing them). */
|
|
488
|
-
setView?(mode: CameraMode, camera: THREE_NS.Object3D | null
|
|
488
|
+
setView?(mode: CameraMode, camera: THREE_NS.Object3D | null, options?: {
|
|
489
|
+
readonly arms?: boolean;
|
|
490
|
+
}): void;
|
|
489
491
|
/**
|
|
490
492
|
* Plays the strike `clipId` (on the body, in both views) and answers the seconds until its impact, or null when this avatar has no such clip. The room then waits that long
|
|
491
493
|
* before the blow lands (`strikeClips`); an avatar without `strike`, or one that answers null, gets the blow at the click.
|
|
@@ -704,6 +706,19 @@ interface SceneryTap {
|
|
|
704
706
|
/** Turn about the vertical axis, radians (default 0). */
|
|
705
707
|
rotationY?: number;
|
|
706
708
|
}
|
|
709
|
+
/** What the room needs of first-person arms: a root it puts in the scene, and the pose of each frame (the eye, the hand targets of the tool and the stance, how fast the body moves). */
|
|
710
|
+
interface RoomFirstPersonArms {
|
|
711
|
+
readonly root: THREE_NS.Object3D;
|
|
712
|
+
update(dt: number, state: {
|
|
713
|
+
camera: THREE_NS.Object3D;
|
|
714
|
+
targets?: HandTargets | null;
|
|
715
|
+
stance?: string;
|
|
716
|
+
speed?: number;
|
|
717
|
+
running?: boolean;
|
|
718
|
+
crouch?: boolean;
|
|
719
|
+
}): void;
|
|
720
|
+
dispose(): void;
|
|
721
|
+
}
|
|
707
722
|
interface TestRoomOptions {
|
|
708
723
|
THREE: ThreeNamespace;
|
|
709
724
|
/** Element the bench fills (canvas + HUD). */
|
|
@@ -790,6 +805,11 @@ interface TestRoomOptions {
|
|
|
790
805
|
ui?: boolean;
|
|
791
806
|
/** The player's body (see `TestRoom.setAvatar`). */
|
|
792
807
|
avatar?: RoomAvatar;
|
|
808
|
+
/**
|
|
809
|
+
* Arms drawn for the first-person view (the viewmodel arms, `createFirstPersonArms` of game-characters-three fits it): in first person the room hides the body's arms from the eye, draws
|
|
810
|
+
* these on `FIRST_PERSON_LAYER` with the tool in the hands, and brings their hands to the tool's grips. Absent: the body's arms are the ones seen.
|
|
811
|
+
*/
|
|
812
|
+
firstPersonArms?: RoomFirstPersonArms;
|
|
793
813
|
/** The view the room starts in (default `first`; the V key and `TestRoom.setCameraMode` change it). */
|
|
794
814
|
cameraMode?: CameraMode;
|
|
795
815
|
/**
|
|
@@ -1299,4 +1319,4 @@ declare function encodeBenchState(controls: readonly BenchControl[], layers: rea
|
|
|
1299
1319
|
/** Reads an encoded state as hostile input: unknown ids, NaN, options not offered and malformed pairs are dropped; numbers are clamped. */
|
|
1300
1320
|
declare function decodeBenchState(encoded: string, controls: readonly ModuleControl[], layers: readonly ModuleLayer[]): Map<string, ControlValue>;
|
|
1301
1321
|
|
|
1302
|
-
export { type AnimationInfo, type BenchControl, type BenchHandle, type BenchLayer, type BuildFromSpecOptions, type CameraMode, DEFAULT_HAND_STANCES, DEFAULT_STRIKE_CLIPS, DEFAULT_TRIALS, type HudState, type InspectInfo, type KickLeg, LOADING_CLASS, LOADING_CSS, type LoadingOptions, type LoadingState, type LogEntry, MATERIAL_COLORS, type ModuleReport, type NewEntry, type NewLogEntry, type ProjectileModel, type ProjectileQuery, type PunchHand, type RoomAvatar, type RoomAvatarState, type RoomDoorEvent, type RoomDoorState, type RoomFirstPersonState, type RoomGraphicsOptions, type RoomLoading, type RoomMetricId, type RoomPushEvent, type RoomPushState, type RoomReachView, type RoomSeat, type RoomStrings, type ScenarioContext, type ScenarioReport, type SceneryObject, type SceneryTap, type SpawnedObject, type StrikeComboOption, TRIAL_KINDS, type TestRoom, type TestRoomItem, type TestRoomLocale, type TestRoomLog, type TestRoomOptions, type TestRoomScenario, type TestTable, type TestTableContext, type TestTableObject, type TestTableOptions, type TestTablePage, type ThirdPersonOptions, type ThreeNamespace, type ToolMenuGroup, type ToolMenuSection, type ToolMenuTool, type TrialKind, type TrialTool, type UseStatus, type WritableLog, brickWallSpec, buildFromSpec, createLoading, createLog, createTestRoom, createTestTable, decodeBenchState, encodeBenchState, fitRow, loadingMarkup, locales, nextPaint, resolveStrings, rowCentres, trialView };
|
|
1322
|
+
export { type AnimationInfo, type BenchControl, type BenchHandle, type BenchLayer, type BuildFromSpecOptions, type CameraMode, DEFAULT_HAND_STANCES, DEFAULT_STRIKE_CLIPS, DEFAULT_TRIALS, type HudState, type InspectInfo, type KickLeg, LOADING_CLASS, LOADING_CSS, type LoadingOptions, type LoadingState, type LogEntry, MATERIAL_COLORS, type ModuleReport, type NewEntry, type NewLogEntry, type ProjectileModel, type ProjectileQuery, type PunchHand, type RoomAvatar, type RoomAvatarState, type RoomDoorEvent, type RoomDoorState, type RoomFirstPersonArms, type RoomFirstPersonState, type RoomGraphicsOptions, type RoomLoading, type RoomMetricId, type RoomPushEvent, type RoomPushState, type RoomReachView, type RoomSeat, type RoomStrings, type ScenarioContext, type ScenarioReport, type SceneryObject, type SceneryTap, type SpawnedObject, type StrikeComboOption, TRIAL_KINDS, type TestRoom, type TestRoomItem, type TestRoomLocale, type TestRoomLog, type TestRoomOptions, type TestRoomScenario, type TestTable, type TestTableContext, type TestTableObject, type TestTableOptions, type TestTablePage, type ThirdPersonOptions, type ThreeNamespace, type ToolMenuGroup, type ToolMenuSection, type ToolMenuTool, type TrialKind, type TrialTool, type UseStatus, type WritableLog, brickWallSpec, buildFromSpec, createLoading, createLog, createTestRoom, createTestTable, decodeBenchState, encodeBenchState, fitRow, loadingMarkup, locales, nextPaint, resolveStrings, rowCentres, trialView };
|
package/dist/index.global.js
CHANGED
|
@@ -473,6 +473,7 @@ var GameTestRoom = (() => {
|
|
|
473
473
|
if (!state.opened) return "sealed";
|
|
474
474
|
return void 0;
|
|
475
475
|
};
|
|
476
|
+
var FIRST_PERSON_LAYER = 9;
|
|
476
477
|
var TWIST_LIFT = 0.012;
|
|
477
478
|
var TURNING = 0.7;
|
|
478
479
|
var smooth = (k) => k * k * (3 - 2 * k);
|
|
@@ -16749,7 +16750,7 @@ var GameTestRoom = (() => {
|
|
|
16749
16750
|
const { core, def, random, x, y, z } = context;
|
|
16750
16751
|
const mark = def.mark;
|
|
16751
16752
|
const keepsMarks = !core.marklessAt?.(x, z);
|
|
16752
|
-
if (keepsMarks && mark.crater && mark.dent && y < 1.2) {
|
|
16753
|
+
if (keepsMarks && mark.crater && mark.dent && y < 1.2 && (core.cratersAt?.(x, z) ?? true)) {
|
|
16753
16754
|
core.emit({ type: "crater", x, z, radius: mark.crater, depth: mark.dent });
|
|
16754
16755
|
core.trace?.crater?.(x, z, mark.crater, mark.dent);
|
|
16755
16756
|
addCrater(core.marks, core.ground, random, { x, z, radius: mark.crater, depth: mark.dent, marks: core.layers.mark });
|
|
@@ -18515,6 +18516,7 @@ var GameTestRoom = (() => {
|
|
|
18515
18516
|
clock: { time: 0, lastBlast: -1, lod: 1, forcedLod: null },
|
|
18516
18517
|
groundAt,
|
|
18517
18518
|
...options.marklessAt ? { marklessAt: options.marklessAt } : {},
|
|
18519
|
+
...options.cratersAt ? { cratersAt: options.cratersAt } : {},
|
|
18518
18520
|
emit: (request) => options.onRequest?.(request)
|
|
18519
18521
|
};
|
|
18520
18522
|
function definitionOf(id) {
|
|
@@ -38174,7 +38176,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38174
38176
|
dimensions: {
|
|
38175
38177
|
length: 0.801,
|
|
38176
38178
|
barrel: 0.559,
|
|
38177
|
-
emptyMass: 39
|
|
38179
|
+
emptyMass: 39,
|
|
38180
|
+
barrels: 6,
|
|
38181
|
+
barrelMass: 2
|
|
38178
38182
|
},
|
|
38179
38183
|
archetype: "rifle_7_62x39",
|
|
38180
38184
|
sources: [
|
|
@@ -39154,19 +39158,41 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39154
39158
|
}
|
|
39155
39159
|
};
|
|
39156
39160
|
var DEFAULT_HEAT = {
|
|
39157
|
-
cap:
|
|
39158
|
-
displayMax:
|
|
39159
|
-
|
|
39160
|
-
|
|
39161
|
-
|
|
39162
|
-
|
|
39163
|
-
|
|
39161
|
+
cap: 900,
|
|
39162
|
+
displayMax: 750,
|
|
39163
|
+
faultFrom: 350,
|
|
39164
|
+
faultSpan: 200,
|
|
39165
|
+
specificHeat: 490,
|
|
39166
|
+
barrelShare: { shell: 0.48, big: 0.48, tiny: 0.3, pistol: 0.3, rifle: 0.48 },
|
|
39167
|
+
barrelKilogramsPerMetre: {
|
|
39168
|
+
pistol: 1,
|
|
39169
|
+
revolver: 1.4,
|
|
39170
|
+
smg: 1.2,
|
|
39171
|
+
carbine: 1.6,
|
|
39172
|
+
rifle: 1.6,
|
|
39173
|
+
dmr: 2.4,
|
|
39174
|
+
sniper: 2.4,
|
|
39175
|
+
hunting: 2.4,
|
|
39176
|
+
machine_gun: 3,
|
|
39177
|
+
shotgun: 1.1
|
|
39178
|
+
},
|
|
39179
|
+
barrelFallback: { metres: 0.4, kilogramsPerMetre: 1.6 },
|
|
39180
|
+
cooling: { baseSeconds: 30, secondsPerKilogram: 250 },
|
|
39164
39181
|
perRocket: 35,
|
|
39165
|
-
visual: { smokeFrom:
|
|
39182
|
+
visual: { smokeFrom: 250, smokeSpan: 300, smokeSeconds: 2.5, glowFrom: 450, glowSpan: 300 }
|
|
39166
39183
|
};
|
|
39167
39184
|
var GALLERY_HEAT = {
|
|
39168
39185
|
...DEFAULT_HEAT,
|
|
39169
|
-
|
|
39186
|
+
cap: 140,
|
|
39187
|
+
displayMax: 120,
|
|
39188
|
+
faultFrom: 60,
|
|
39189
|
+
faultSpan: 40,
|
|
39190
|
+
visual: { smokeFrom: 70, smokeSpan: 100, smokeSeconds: 2.5, glowFrom: 80, glowSpan: 40 },
|
|
39191
|
+
gallery: {
|
|
39192
|
+
perShot: { shell: 6, big: 9, tiny: 1.2, pistol: 3, rifle: 4.5 },
|
|
39193
|
+
decayBase: 1.6,
|
|
39194
|
+
decayPerPoint: 0.03
|
|
39195
|
+
}
|
|
39170
39196
|
};
|
|
39171
39197
|
var defaultFaultChance = (context) => {
|
|
39172
39198
|
const factor = context.def.action.kind === "firearm" ? context.def.action.faultFactor ?? 1 : 1;
|
|
@@ -39449,17 +39475,55 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39449
39475
|
...explosive.stunSeconds !== void 0 ? { stunSeconds: explosive.stunSeconds } : {}
|
|
39450
39476
|
};
|
|
39451
39477
|
};
|
|
39478
|
+
var EPS22 = 1e-9;
|
|
39479
|
+
var MANUAL_MODES = /* @__PURE__ */ new Set(["pump", "bolt", "lever"]);
|
|
39480
|
+
var weaponSpeed = (action, caliber) => action.muzzleSpeed ?? caliber.muzzleSpeed * (action.barrel ?? 1);
|
|
39481
|
+
var weaponNoise = (action, caliber) => action.noise ?? caliber.noise ?? 0;
|
|
39482
|
+
var timingsOf = (action) => "timings" in action ? action.timings : void 0;
|
|
39483
|
+
var drawSeconds = (action, rules) => timingsOf(action)?.draw ?? rules.draw;
|
|
39484
|
+
var clearSeconds = (action, rules) => timingsOf(action)?.clear ?? rules.clear;
|
|
39485
|
+
var manualCycleSeconds = (action, mode) => MANUAL_MODES.has(mode) ? action.timings?.cycle ?? 0 : 0;
|
|
39486
|
+
var planRounds = (action, mode, ammo, firstAt, frameEnd) => {
|
|
39487
|
+
const interval = 60 / action.rpm;
|
|
39488
|
+
const times = [];
|
|
39489
|
+
if (mode === "auto") {
|
|
39490
|
+
for (let t = firstAt; times.length < ammo && (times.length === 0 ? t <= frameEnd + EPS22 : t < frameEnd - EPS22); t += interval) times.push(t);
|
|
39491
|
+
return times;
|
|
39492
|
+
}
|
|
39493
|
+
if (mode === "burst") {
|
|
39494
|
+
const count = Math.min(action.burst ?? 3, ammo);
|
|
39495
|
+
for (let k = 0; k < count; k++) times.push(firstAt + k * interval);
|
|
39496
|
+
return times;
|
|
39497
|
+
}
|
|
39498
|
+
if (mode === "volley") return Array.from({ length: Math.min(action.magazine, ammo) }, () => firstAt);
|
|
39499
|
+
return [firstAt];
|
|
39500
|
+
};
|
|
39452
39501
|
var SUBSTEP_SECONDS = 1 / 60;
|
|
39453
|
-
var
|
|
39502
|
+
var barrelMassOf = (def, rules) => {
|
|
39503
|
+
const dimensions = def.dimensions;
|
|
39504
|
+
const kilogramsPerMetre = rules.barrelKilogramsPerMetre[def.category] ?? rules.barrelFallback.kilogramsPerMetre;
|
|
39505
|
+
const single = dimensions?.barrelMass ?? (dimensions?.barrel ?? rules.barrelFallback.metres) * kilogramsPerMetre;
|
|
39506
|
+
return single * (dimensions?.barrels ?? 1);
|
|
39507
|
+
};
|
|
39508
|
+
var coolingTimeConstant = (barrelMass, rules) => rules.cooling.baseSeconds + rules.cooling.secondsPerKilogram * barrelMass;
|
|
39509
|
+
var decayHeat = (heat, seconds, barrelMass, rules) => {
|
|
39510
|
+
if (heat <= 0) return 0;
|
|
39511
|
+
if (rules.gallery) return decayGallery(heat, seconds, rules.gallery);
|
|
39512
|
+
return heat * Math.exp(-seconds / coolingTimeConstant(barrelMass, rules));
|
|
39513
|
+
};
|
|
39514
|
+
var decayGallery = (heat, seconds, gallery) => {
|
|
39454
39515
|
const steps = Math.max(1, Math.ceil(seconds / SUBSTEP_SECONDS - 1e-9));
|
|
39455
39516
|
const step = seconds / steps;
|
|
39456
39517
|
let current = heat;
|
|
39457
|
-
for (let i = 0; i < steps && current > 0; i++) current = Math.max(0, current - step * (
|
|
39518
|
+
for (let i = 0; i < steps && current > 0; i++) current = Math.max(0, current - step * (gallery.decayBase + current * gallery.decayPerPoint));
|
|
39458
39519
|
return current;
|
|
39459
39520
|
};
|
|
39460
|
-
var heatPerRound = (action, caliber, rules) => {
|
|
39521
|
+
var heatPerRound = ({ action, caliber, energy, barrelMass, rules }) => {
|
|
39461
39522
|
if (action.kind === "launcher") return rules.perRocket;
|
|
39462
|
-
|
|
39523
|
+
const caseType = caliber?.caseType;
|
|
39524
|
+
if (!caseType) return 0;
|
|
39525
|
+
if (rules.gallery) return rules.gallery.perShot[caseType];
|
|
39526
|
+
return rules.barrelShare[caseType] * energy / (barrelMass * rules.specificHeat);
|
|
39463
39527
|
};
|
|
39464
39528
|
var burstNoise = (base, recentShots, rules) => base * (1 + Math.min(rules.cap, rules.step * recentShots));
|
|
39465
39529
|
var magazineOut = { stage: "magazine_out", at: 0 };
|
|
@@ -39586,29 +39650,6 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39586
39650
|
return roll.ammoQuality.faultChance > 0 && roll.random() < roll.ammoQuality.faultChance ? "misfire" : null;
|
|
39587
39651
|
};
|
|
39588
39652
|
var isDudWithoutJam = (action, fault) => fault === "misfire" && action.kind === "firearm" && MISFIRE_ONLY.has(action.family);
|
|
39589
|
-
var EPS22 = 1e-9;
|
|
39590
|
-
var MANUAL_MODES = /* @__PURE__ */ new Set(["pump", "bolt", "lever"]);
|
|
39591
|
-
var weaponSpeed = (action, caliber) => action.muzzleSpeed ?? caliber.muzzleSpeed * (action.barrel ?? 1);
|
|
39592
|
-
var weaponNoise = (action, caliber) => action.noise ?? caliber.noise ?? 0;
|
|
39593
|
-
var timingsOf = (action) => "timings" in action ? action.timings : void 0;
|
|
39594
|
-
var drawSeconds = (action, rules) => timingsOf(action)?.draw ?? rules.draw;
|
|
39595
|
-
var clearSeconds = (action, rules) => timingsOf(action)?.clear ?? rules.clear;
|
|
39596
|
-
var manualCycleSeconds = (action, mode) => MANUAL_MODES.has(mode) ? action.timings?.cycle ?? 0 : 0;
|
|
39597
|
-
var planRounds = (action, mode, ammo, firstAt, frameEnd) => {
|
|
39598
|
-
const interval = 60 / action.rpm;
|
|
39599
|
-
const times = [];
|
|
39600
|
-
if (mode === "auto") {
|
|
39601
|
-
for (let t = firstAt; times.length < ammo && (times.length === 0 ? t <= frameEnd + EPS22 : t < frameEnd - EPS22); t += interval) times.push(t);
|
|
39602
|
-
return times;
|
|
39603
|
-
}
|
|
39604
|
-
if (mode === "burst") {
|
|
39605
|
-
const count = Math.min(action.burst ?? 3, ammo);
|
|
39606
|
-
for (let k = 0; k < count; k++) times.push(firstAt + k * interval);
|
|
39607
|
-
return times;
|
|
39608
|
-
}
|
|
39609
|
-
if (mode === "volley") return Array.from({ length: Math.min(action.magazine, ammo) }, () => firstAt);
|
|
39610
|
-
return [firstAt];
|
|
39611
|
-
};
|
|
39612
39653
|
var activeParts = (fitted, catalogue) => fitted.flatMap((part) => {
|
|
39613
39654
|
const def = catalogue.get(part.id);
|
|
39614
39655
|
const isOn = def?.kind !== "light" && def?.kind !== "laser" ? true : part.on === true;
|
|
@@ -39841,6 +39882,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39841
39882
|
get safety() {
|
|
39842
39883
|
return this._safety;
|
|
39843
39884
|
}
|
|
39885
|
+
/** Kg of steel that heat up with the shots. */
|
|
39886
|
+
get barrelMass() {
|
|
39887
|
+
return barrelMassOf(this.def, this.rules.heat);
|
|
39888
|
+
}
|
|
39844
39889
|
get heat() {
|
|
39845
39890
|
return this._heat;
|
|
39846
39891
|
}
|
|
@@ -39893,7 +39938,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39893
39938
|
}
|
|
39894
39939
|
advance(seconds) {
|
|
39895
39940
|
if (seconds <= 0) return;
|
|
39896
|
-
this._heat = decayHeat(this._heat, seconds, this.rules.heat);
|
|
39941
|
+
this._heat = decayHeat(this._heat, seconds, this.barrelMass, this.rules.heat);
|
|
39897
39942
|
this.clock += seconds;
|
|
39898
39943
|
}
|
|
39899
39944
|
/** Complete what falls at or before `t`: scheduled events and the reload steps. */
|
|
@@ -40445,7 +40490,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
40445
40490
|
res.shots.push(shot);
|
|
40446
40491
|
}
|
|
40447
40492
|
this._ammo -= 1;
|
|
40448
|
-
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound(a, cal, this.rules.heat) * this.load.heatFactor);
|
|
40493
|
+
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);
|
|
40449
40494
|
this.readyAt = t + 60 / a.rpm;
|
|
40450
40495
|
this.extra = Math.min(bloomNow + (a.bloomDeg ?? 0), a.spreadDeg * (BLOOM_CAP - 1));
|
|
40451
40496
|
this.extraClock = t;
|
|
@@ -40534,7 +40579,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
40534
40579
|
}
|
|
40535
40580
|
const t = Math.max(start, this.readyAt);
|
|
40536
40581
|
this._ammo -= 1;
|
|
40537
|
-
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound(a, null, this.rules.heat));
|
|
40582
|
+
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound({ action: a, caliber: null, energy: 0, barrelMass: this.barrelMass, rules: this.rules.heat }));
|
|
40538
40583
|
this.emit({ type: "shot", shots: 0, rounds: 1, mode: this.mode, at: t });
|
|
40539
40584
|
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] });
|
|
40540
40585
|
}
|
|
@@ -49409,6 +49454,7 @@ void main(){
|
|
|
49409
49454
|
}
|
|
49410
49455
|
|
|
49411
49456
|
// src/player.ts
|
|
49457
|
+
var RECOIL_RETURN = { share: 0.7, seconds: 0.25 };
|
|
49412
49458
|
var SLAM_MIN_SPEED2 = 1.5;
|
|
49413
49459
|
var LANDING_MIN_SPEED = 1;
|
|
49414
49460
|
var EYE = 1.7;
|
|
@@ -49438,6 +49484,18 @@ void main(){
|
|
|
49438
49484
|
const cam = o.camera;
|
|
49439
49485
|
let yaw = 0;
|
|
49440
49486
|
let pitch = 0;
|
|
49487
|
+
const recoilReturn = o.recoilReturn ?? RECOIL_RETURN;
|
|
49488
|
+
const recoilDebt = { pitch: 0, yaw: 0 };
|
|
49489
|
+
const returnRecoil = (dt) => {
|
|
49490
|
+
if (Math.abs(recoilDebt.pitch) + Math.abs(recoilDebt.yaw) < 1e-6) return;
|
|
49491
|
+
const k = 1 - Math.exp(-3 * dt / Math.max(1e-3, recoilReturn.seconds));
|
|
49492
|
+
const back = { pitch: recoilDebt.pitch * k, yaw: recoilDebt.yaw * k };
|
|
49493
|
+
recoilDebt.pitch -= back.pitch;
|
|
49494
|
+
recoilDebt.yaw -= back.yaw;
|
|
49495
|
+
pitch = Math.max(-1.5, Math.min(1.5, pitch - back.pitch));
|
|
49496
|
+
yaw -= back.yaw;
|
|
49497
|
+
apply();
|
|
49498
|
+
};
|
|
49441
49499
|
let y = 0;
|
|
49442
49500
|
let eye = EYE;
|
|
49443
49501
|
let crouch = 0;
|
|
@@ -49779,6 +49837,7 @@ void main(){
|
|
|
49779
49837
|
return stunLeft;
|
|
49780
49838
|
},
|
|
49781
49839
|
update(dt) {
|
|
49840
|
+
returnRecoil(dt);
|
|
49782
49841
|
if (stunLeft > 0) {
|
|
49783
49842
|
stunLeft = Math.max(0, stunLeft - dt);
|
|
49784
49843
|
stunPhase += dt * 2.4;
|
|
@@ -49827,6 +49886,8 @@ void main(){
|
|
|
49827
49886
|
},
|
|
49828
49887
|
setPose(position, yw, pt2) {
|
|
49829
49888
|
knocked = null;
|
|
49889
|
+
recoilDebt.pitch = 0;
|
|
49890
|
+
recoilDebt.yaw = 0;
|
|
49830
49891
|
px.x = position[0];
|
|
49831
49892
|
px.z = position[2];
|
|
49832
49893
|
floorLevel = floorHere();
|
|
@@ -49839,6 +49900,8 @@ void main(){
|
|
|
49839
49900
|
},
|
|
49840
49901
|
look(position, target) {
|
|
49841
49902
|
knocked = null;
|
|
49903
|
+
recoilDebt.pitch = 0;
|
|
49904
|
+
recoilDebt.yaw = 0;
|
|
49842
49905
|
px.x = position[0];
|
|
49843
49906
|
px.z = position[2];
|
|
49844
49907
|
floorLevel = floorHere();
|
|
@@ -49853,8 +49916,11 @@ void main(){
|
|
|
49853
49916
|
apply();
|
|
49854
49917
|
},
|
|
49855
49918
|
kick(pitchDeg, yawDeg) {
|
|
49919
|
+
const before = pitch;
|
|
49856
49920
|
pitch = Math.max(-1.5, Math.min(1.5, pitch + pitchDeg * Math.PI / 180));
|
|
49857
49921
|
yaw += yawDeg * Math.PI / 180;
|
|
49922
|
+
recoilDebt.pitch += (pitch - before) * recoilReturn.share;
|
|
49923
|
+
recoilDebt.yaw += yawDeg * Math.PI / 180 * recoilReturn.share;
|
|
49858
49924
|
apply();
|
|
49859
49925
|
},
|
|
49860
49926
|
moveBy(dx, dz) {
|
|
@@ -51034,6 +51100,8 @@ void main(){
|
|
|
51034
51100
|
{ id: "dry_clay", strata: [{ material: "clay", thickness: 0.35 }, { material: "soil", thickness: 1.5 }, { material: "stone", thickness: 0.5 }] },
|
|
51035
51101
|
{ id: "snow", strata: [{ material: "snow", thickness: 0.3 }, { material: "soil", thickness: 1.5 }, { material: "stone", thickness: 0.5 }] },
|
|
51036
51102
|
{ id: "cobblestone", strata: [{ material: "cobble", thickness: 0.12 }, { material: "sand", thickness: 0.06 }, { material: "gravel", thickness: 0.2 }, { material: "soil", thickness: 1.2 }] },
|
|
51103
|
+
// rock at the surface (an outcrop, a quarry floor): a blast only spalls it and a shot chips it
|
|
51104
|
+
{ id: "bedrock", surfacePattern: "rock", strata: [{ material: "stone", thickness: 3 }] },
|
|
51037
51105
|
{ id: "paver_floor", strata: [{ material: "paver", thickness: 0.08 }, { material: "sand", thickness: 0.05 }, { material: "gravel", thickness: 0.15 }, { material: "soil", thickness: 1.2 }] },
|
|
51038
51106
|
{ 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 }] }
|
|
51039
51107
|
];
|
|
@@ -52268,7 +52336,7 @@ void main(){
|
|
|
52268
52336
|
}
|
|
52269
52337
|
};
|
|
52270
52338
|
}
|
|
52271
|
-
var TERRAIN_PATTERNS = ["plain", "grass", "soil", "sand", "asphalt", "concrete", "tile", "planks", "stone", "mud", "gravel", "clay", "snow", "cobble", "paver"];
|
|
52339
|
+
var TERRAIN_PATTERNS = ["plain", "grass", "soil", "sand", "asphalt", "concrete", "tile", "planks", "stone", "mud", "gravel", "clay", "snow", "cobble", "paver", "rock"];
|
|
52272
52340
|
var STRIDE = 0.72;
|
|
52273
52341
|
var FOOT_LENGTH = 0.15;
|
|
52274
52342
|
var FOOT_APART = 0.11;
|
|
@@ -52316,10 +52384,10 @@ void main(){
|
|
|
52316
52384
|
};
|
|
52317
52385
|
}
|
|
52318
52386
|
|
|
52319
|
-
// ../game-terrain-three/dist/chunk-
|
|
52387
|
+
// ../game-terrain-three/dist/chunk-6YHNPX3W.js
|
|
52320
52388
|
var PROFILE_NAMES = {
|
|
52321
|
-
en: { lawn: "Lawn", dirt: "Dirt", sand: "Sand", road: "Asphalt road", concrete_slab: "Concrete slab", suspended_slab: "Slab over a void", tile_floor: "Tile floor", wood_floor: "Wood floor", stone_paving: "Stone paving" },
|
|
52322
|
-
"pt-BR": { lawn: "Grama", dirt: "Terra", sand: "Areia", road: "Asfalto", concrete_slab: "Laje de concreto", suspended_slab: "Laje sobre v\xE3o", tile_floor: "Piso cer\xE2mico", wood_floor: "Assoalho", stone_paving: "Cal\xE7amento de pedra" }
|
|
52389
|
+
en: { lawn: "Lawn", dirt: "Dirt", sand: "Sand", road: "Asphalt road", concrete_slab: "Concrete slab", suspended_slab: "Slab over a void", tile_floor: "Tile floor", wood_floor: "Wood floor", stone_paving: "Stone paving", mud: "Mud", gravel_bed: "Gravel", dry_clay: "Dry clay", snow: "Snow", cobblestone: "Cobblestones", paver_floor: "Concrete pavers", shallow_water: "Shallow water", bedrock: "Bare rock" },
|
|
52390
|
+
"pt-BR": { lawn: "Grama", dirt: "Terra", sand: "Areia", road: "Asfalto", concrete_slab: "Laje de concreto", suspended_slab: "Laje sobre v\xE3o", tile_floor: "Piso cer\xE2mico", wood_floor: "Assoalho", stone_paving: "Cal\xE7amento de pedra", mud: "Lama", gravel_bed: "Cascalho", dry_clay: "Barro seco", snow: "Neve", cobblestone: "Paralelep\xEDpedo", paver_floor: "Bloquete", shallow_water: "\xC1gua rasa", bedrock: "Rocha" }
|
|
52323
52391
|
};
|
|
52324
52392
|
function terrainProfileName(profileId, localeId) {
|
|
52325
52393
|
return (PROFILE_NAMES[localeId] ?? PROFILE_NAMES.en)[profileId] ?? profileId;
|
|
@@ -52329,20 +52397,20 @@ void main(){
|
|
|
52329
52397
|
name: "Terrain",
|
|
52330
52398
|
group: "Terrain",
|
|
52331
52399
|
weight: "Concrete block (60 kg)",
|
|
52332
|
-
surfaces: { dirt: "Dirt", lawn: "Lawn", sand: "Sand", road: "Asphalt", concrete_slab: "Concrete slab", suspended_slab: "Slab over a void", wood_floor: "Wood floor", tile_floor: "Tile", stone_paving: "Stone paving", mud: "Mud", gravel_bed: "Gravel", dry_clay: "Dry clay", snow: "Snow", cobblestone: "Cobblestones", paver_floor: "Concrete pavers", shallow_water: "Shallow water" }
|
|
52400
|
+
surfaces: { dirt: "Dirt", lawn: "Lawn", sand: "Sand", road: "Asphalt", concrete_slab: "Concrete slab", suspended_slab: "Slab over a void", wood_floor: "Wood floor", tile_floor: "Tile", stone_paving: "Stone paving", mud: "Mud", gravel_bed: "Gravel", dry_clay: "Dry clay", snow: "Snow", cobblestone: "Cobblestones", paver_floor: "Concrete pavers", shallow_water: "Shallow water", bedrock: "Bare rock" }
|
|
52333
52401
|
},
|
|
52334
52402
|
"pt-BR": {
|
|
52335
52403
|
name: "Terreno",
|
|
52336
52404
|
group: "Terreno",
|
|
52337
52405
|
weight: "Bloco de concreto (60 kg)",
|
|
52338
|
-
surfaces: { dirt: "Terra", lawn: "Grama", sand: "Areia", road: "Asfalto", concrete_slab: "Laje de concreto", suspended_slab: "Laje sobre v\xE3o", wood_floor: "Assoalho", tile_floor: "Cer\xE2mica", stone_paving: "Pedra", mud: "Lama", gravel_bed: "Cascalho", dry_clay: "Barro seco", snow: "Neve", cobblestone: "Paralelep\xEDpedo", paver_floor: "Bloquete", shallow_water: "\xC1gua rasa" }
|
|
52406
|
+
surfaces: { dirt: "Terra", lawn: "Grama", sand: "Areia", road: "Asfalto", concrete_slab: "Laje de concreto", suspended_slab: "Laje sobre v\xE3o", wood_floor: "Assoalho", tile_floor: "Cer\xE2mica", stone_paving: "Pedra", mud: "Lama", gravel_bed: "Cascalho", dry_clay: "Barro seco", snow: "Neve", cobblestone: "Paralelep\xEDpedo", paver_floor: "Bloquete", shallow_water: "\xC1gua rasa", bedrock: "Rocha" }
|
|
52339
52407
|
}
|
|
52340
52408
|
};
|
|
52341
52409
|
var locale = (id) => LOCALES[id] ?? LOCALES.en;
|
|
52342
|
-
var TERRAIN_STRIPS = ["lawn", "dirt", "sand", "mud", "dry_clay", "gravel_bed", "snow", "shallow_water", "road", "cobblestone", "paver_floor", "stone_paving", "concrete_slab", "suspended_slab", "tile_floor", "wood_floor"];
|
|
52343
|
-
var LOT_WIDTH = 3
|
|
52410
|
+
var TERRAIN_STRIPS = ["lawn", "dirt", "sand", "mud", "dry_clay", "gravel_bed", "snow", "shallow_water", "bedrock", "road", "cobblestone", "paver_floor", "stone_paving", "concrete_slab", "suspended_slab", "tile_floor", "wood_floor"];
|
|
52411
|
+
var LOT_WIDTH = 3;
|
|
52344
52412
|
var LOT_DEPTH = 3.8;
|
|
52345
|
-
var LOTS_PER_ROW =
|
|
52413
|
+
var LOTS_PER_ROW = 9;
|
|
52346
52414
|
var LOTS_Z1 = -1.4;
|
|
52347
52415
|
var lotRect = (index) => {
|
|
52348
52416
|
const row = Math.floor(index / LOTS_PER_ROW);
|
|
@@ -52435,11 +52503,18 @@ vec3 terrainSurface(vec3 base, vec2 xz, float kind) {
|
|
|
52435
52503
|
float seam = max(tsLine(xz.y, 0.2, 0.014), tsLine(along, 0.3, 0.014));
|
|
52436
52504
|
return base * (0.72 + 0.6 * tsHash(cell)) * (0.82 + 0.36 * tsFbm(xz * 22.0)) * (1.0 - 0.8 * seam);
|
|
52437
52505
|
}
|
|
52438
|
-
|
|
52439
|
-
|
|
52440
|
-
|
|
52441
|
-
|
|
52442
|
-
|
|
52506
|
+
if (k < 14.5) {
|
|
52507
|
+
float row = floor(xz.y / 0.2);
|
|
52508
|
+
float along = xz.x - mod(abs(row), 2.0) * 0.1;
|
|
52509
|
+
vec2 cell = vec2(floor(along / 0.2), row);
|
|
52510
|
+
float seam = max(tsLine(xz.y, 0.2, 0.008), tsLine(along, 0.2, 0.008));
|
|
52511
|
+
return base * (0.86 + 0.26 * tsHash(cell)) * (0.92 + 0.16 * tsNoise(xz * 70.0)) * (1.0 - 0.7 * seam);
|
|
52512
|
+
}
|
|
52513
|
+
// bare rock: weathered blotches, lichen-dark patches and a few long joints, no grid
|
|
52514
|
+
float blotch = tsFbm(xz * 0.9) * 0.6 + tsFbm(xz * 4.0 + 2.0) * 0.4;
|
|
52515
|
+
float joint = 1.0 - smoothstep(0.0, 0.035, abs(tsNoise(xz * vec2(0.7, 1.9)) - 0.5));
|
|
52516
|
+
float grain = tsNoise(xz * 95.0);
|
|
52517
|
+
return base * (0.62 + 0.75 * blotch) * (0.88 + 0.24 * grain) * (1.0 - 0.6 * joint);
|
|
52443
52518
|
}
|
|
52444
52519
|
`
|
|
52445
52520
|
);
|
|
@@ -52468,9 +52543,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
52468
52543
|
const index = row * terrain.stride + column;
|
|
52469
52544
|
let material = terrain.vertexMaterial(column, row);
|
|
52470
52545
|
if (terrain.loose[index] > LOOSE_VISIBLE) {
|
|
52471
|
-
const
|
|
52472
|
-
const first =
|
|
52473
|
-
material = terrain.material(first.thickness < THIN_SKIN &&
|
|
52546
|
+
const profile2 = terrain.profileList[terrain.profileIndex[index]];
|
|
52547
|
+
const first = profile2.strata[0];
|
|
52548
|
+
material = terrain.material(first.thickness < THIN_SKIN && profile2.strata[1] ? profile2.strata[1].material : first.material);
|
|
52474
52549
|
}
|
|
52475
52550
|
const broken = material.pattern === "concrete" && terrain.dug[index] > BROKEN_DEPTH;
|
|
52476
52551
|
const tone = broken ? BROKEN_TONE : 1;
|
|
@@ -52479,7 +52554,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
52479
52554
|
base[2] = material.color[2] * tone;
|
|
52480
52555
|
shade[0] = Math.max(MIN_DEPTH_LIGHT, 1 - terrain.dug[index] / DEPTH_SHADE);
|
|
52481
52556
|
shade[1] = terrain.scorch[index];
|
|
52482
|
-
|
|
52557
|
+
const profile = terrain.profileList[terrain.profileIndex[index]];
|
|
52558
|
+
const untouched = profile.surfacePattern !== void 0 && terrain.dug[index] <= BROKEN_DEPTH && terrain.loose[index] <= LOOSE_VISIBLE;
|
|
52559
|
+
return patternIndex(broken ? "soil" : untouched ? profile.surfacePattern : material.pattern);
|
|
52483
52560
|
}
|
|
52484
52561
|
function chunkVertexCount(terrain, chunk, step) {
|
|
52485
52562
|
const lastColumn = Math.min(terrain.columns, chunk.column + chunk.cells);
|
|
@@ -55519,6 +55596,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
55519
55596
|
const scene2 = options.scene ?? new THREE.Scene();
|
|
55520
55597
|
const camera2 = options.camera ?? new THREE.PerspectiveCamera(72, width() / height(), 0.05, 140);
|
|
55521
55598
|
if (!options.camera) scene2.add(camera2);
|
|
55599
|
+
camera2.layers.disable(FIRST_PERSON_LAYER);
|
|
55522
55600
|
const resize = () => {
|
|
55523
55601
|
const w = width();
|
|
55524
55602
|
const h = height();
|
|
@@ -55625,7 +55703,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
55625
55703
|
profile: quality,
|
|
55626
55704
|
...options.debris?.particles ? { sprites: { kinds: patchSpriteKinds(SPRITE_KINDS, options.debris.particles) } } : {},
|
|
55627
55705
|
groundAt,
|
|
55628
|
-
marklessAt: (x, z) => terrain.waterAt(x, z) !== null
|
|
55706
|
+
marklessAt: (x, z) => terrain.waterAt(x, z) !== null,
|
|
55707
|
+
// the dirt crater of the effects only where the ground is loose; rock, asphalt and a slab keep the soot and the bowl the terrain itself dug
|
|
55708
|
+
cratersAt: (x, z) => terrain.material(terrain.columnAt(x, z).material).reposeDegrees !== void 0
|
|
55629
55709
|
})
|
|
55630
55710
|
});
|
|
55631
55711
|
const renderer = createDestructionRenderer(THREE, {
|
|
@@ -56610,10 +56690,21 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56610
56690
|
return { ...pose, position: pose.at(camDistance), free: camDistance };
|
|
56611
56691
|
};
|
|
56612
56692
|
const thirdActive = () => cameraMode === "third" && avatar !== null;
|
|
56693
|
+
const firstPersonArms = options.firstPersonArms ?? null;
|
|
56694
|
+
if (firstPersonArms) {
|
|
56695
|
+
firstPersonArms.root.visible = cameraMode === "first";
|
|
56696
|
+
scene2.add(firstPersonArms.root);
|
|
56697
|
+
}
|
|
56613
56698
|
const syncAvatarVisible = () => {
|
|
56699
|
+
if (firstPersonArms) firstPersonArms.root.visible = cameraMode === "first";
|
|
56614
56700
|
if (!avatar) return;
|
|
56615
56701
|
avatar.root.visible = cameraMode === "third" || !!avatar.eye;
|
|
56616
|
-
avatar.setView?.(cameraMode, camera2);
|
|
56702
|
+
avatar.setView?.(cameraMode, camera2, { arms: firstPersonArms !== null });
|
|
56703
|
+
};
|
|
56704
|
+
const updateFirstPersonArms = (dt) => {
|
|
56705
|
+
if (!firstPersonArms || cameraMode !== "first") return;
|
|
56706
|
+
firstPersonArms.update(dt, { camera: camera2, targets: lastHand.targets, stance: lastHand.stance, speed: player.speed, running: avatarState.running, crouch: avatarState.crouch });
|
|
56707
|
+
firstPersonArms.root.traverse((node) => node.layers.set(FIRST_PERSON_LAYER));
|
|
56617
56708
|
};
|
|
56618
56709
|
const setCameraMode = (mode) => {
|
|
56619
56710
|
if (mode !== "first" && mode !== "third") return;
|
|
@@ -56697,6 +56788,39 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56697
56788
|
};
|
|
56698
56789
|
let handSource = null;
|
|
56699
56790
|
let muzzleSource = null;
|
|
56791
|
+
let viewmodelFov = null;
|
|
56792
|
+
const firstPersonCamera = new THREE.PerspectiveCamera(72, 1, 0.01, 30);
|
|
56793
|
+
firstPersonCamera.layers.set(FIRST_PERSON_LAYER);
|
|
56794
|
+
let firstPersonPasses = 0;
|
|
56795
|
+
const drawFirstPersonLayer = () => {
|
|
56796
|
+
if (!firstPersonArms && viewmodelFov === null) return;
|
|
56797
|
+
const renderer2 = gl;
|
|
56798
|
+
if (typeof renderer2.clearDepth !== "function" || typeof renderer2.render !== "function") return;
|
|
56799
|
+
if (firstPersonPasses++ % 60 === 0) {
|
|
56800
|
+
scene2.traverse((node) => {
|
|
56801
|
+
if (node.isLight) node.layers.enable(FIRST_PERSON_LAYER);
|
|
56802
|
+
});
|
|
56803
|
+
}
|
|
56804
|
+
firstPersonCamera.position.copy(camera2.position);
|
|
56805
|
+
firstPersonCamera.quaternion.copy(camera2.quaternion);
|
|
56806
|
+
const fov = viewmodelFov ?? camera2.fov;
|
|
56807
|
+
if (firstPersonCamera.fov !== fov || firstPersonCamera.aspect !== camera2.aspect) {
|
|
56808
|
+
firstPersonCamera.fov = fov;
|
|
56809
|
+
firstPersonCamera.aspect = camera2.aspect;
|
|
56810
|
+
firstPersonCamera.updateProjectionMatrix();
|
|
56811
|
+
}
|
|
56812
|
+
firstPersonCamera.updateMatrixWorld();
|
|
56813
|
+
const { autoClear } = renderer2;
|
|
56814
|
+
const { background, fog } = scene2;
|
|
56815
|
+
renderer2.autoClear = false;
|
|
56816
|
+
scene2.background = null;
|
|
56817
|
+
scene2.fog = null;
|
|
56818
|
+
renderer2.clearDepth();
|
|
56819
|
+
renderer2.render(scene2, firstPersonCamera);
|
|
56820
|
+
scene2.background = background;
|
|
56821
|
+
scene2.fog = fog;
|
|
56822
|
+
renderer2.autoClear = autoClear ?? true;
|
|
56823
|
+
};
|
|
56700
56824
|
let debugView = null;
|
|
56701
56825
|
let lastHand = { stance: "relaxed", triggerFinger: null, targets: null };
|
|
56702
56826
|
const strikeClips = options.strikeClips ?? DEFAULT_STRIKE_CLIPS;
|
|
@@ -56844,7 +56968,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56844
56968
|
const line = new THREE.Line(g, tracerMat);
|
|
56845
56969
|
line.frustumCulled = false;
|
|
56846
56970
|
scene2.add(line);
|
|
56847
|
-
tr = { line, life: 0 };
|
|
56971
|
+
tr = { line, life: 0, follows: false };
|
|
56848
56972
|
tracers.push(tr);
|
|
56849
56973
|
}
|
|
56850
56974
|
const attr = tr.line.geometry.getAttribute("position");
|
|
@@ -56853,6 +56977,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56853
56977
|
attr.needsUpdate = true;
|
|
56854
56978
|
tr.line.visible = true;
|
|
56855
56979
|
tr.life = 0.07;
|
|
56980
|
+
tr.follows = muzzleSource !== null;
|
|
56856
56981
|
};
|
|
56857
56982
|
const fireZones = [];
|
|
56858
56983
|
const burningStains = [];
|
|
@@ -58168,10 +58293,16 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58168
58293
|
}
|
|
58169
58294
|
};
|
|
58170
58295
|
const simulateAfterModules = (dt) => {
|
|
58296
|
+
const drawn = tracers.some((tr) => tr.life > 0 && tr.follows) ? muzzleSource?.() ?? null : null;
|
|
58171
58297
|
for (const tr of tracers) {
|
|
58172
58298
|
if (tr.life > 0) {
|
|
58173
58299
|
tr.life -= dt;
|
|
58174
58300
|
if (tr.life <= 0) tr.line.visible = false;
|
|
58301
|
+
else if (tr.follows && drawn) {
|
|
58302
|
+
const attr = tr.line.geometry.getAttribute("position");
|
|
58303
|
+
attr.setXYZ(0, drawn.position[0], drawn.position[1], drawn.position[2]);
|
|
58304
|
+
attr.needsUpdate = true;
|
|
58305
|
+
}
|
|
58175
58306
|
}
|
|
58176
58307
|
}
|
|
58177
58308
|
flush();
|
|
@@ -58205,6 +58336,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58205
58336
|
};
|
|
58206
58337
|
const updatePresent = (dt) => {
|
|
58207
58338
|
reachAvatar();
|
|
58339
|
+
updateFirstPersonArms(dt);
|
|
58208
58340
|
if (progress && simTime - progress.at > 0.25) progress = null;
|
|
58209
58341
|
ui?.flushLog();
|
|
58210
58342
|
hudAcc += dt;
|
|
@@ -58554,6 +58686,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58554
58686
|
if (handSource === source) handSource = null;
|
|
58555
58687
|
};
|
|
58556
58688
|
},
|
|
58689
|
+
setViewmodelFov(degrees) {
|
|
58690
|
+
viewmodelFov = degrees;
|
|
58691
|
+
},
|
|
58557
58692
|
setMuzzleSource(source) {
|
|
58558
58693
|
muzzleSource = source;
|
|
58559
58694
|
return () => {
|
|
@@ -59285,7 +59420,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
59285
59420
|
for (const batcher of batchers.values()) batcher.update();
|
|
59286
59421
|
const restoreCamera = room.applyCamera();
|
|
59287
59422
|
graphics?.beforeRender(camera2);
|
|
59288
|
-
|
|
59423
|
+
const view = debugView ?? moduleViews.main(camera2);
|
|
59424
|
+
gl.render(scene2, view);
|
|
59425
|
+
if (view === camera2 && cameraMode === "first") drawFirstPersonLayer();
|
|
59289
59426
|
moduleViews.render(scene2);
|
|
59290
59427
|
graphics?.afterRender();
|
|
59291
59428
|
restoreCamera();
|