@adatechnology/game-test-room 0.27.0 → 0.28.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/index.d.ts +22 -2
- package/dist/index.global.js +166 -43
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +83 -4
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
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);
|
|
@@ -38174,7 +38175,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
38174
38175
|
dimensions: {
|
|
38175
38176
|
length: 0.801,
|
|
38176
38177
|
barrel: 0.559,
|
|
38177
|
-
emptyMass: 39
|
|
38178
|
+
emptyMass: 39,
|
|
38179
|
+
barrels: 6,
|
|
38180
|
+
barrelMass: 2
|
|
38178
38181
|
},
|
|
38179
38182
|
archetype: "rifle_7_62x39",
|
|
38180
38183
|
sources: [
|
|
@@ -39154,19 +39157,41 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39154
39157
|
}
|
|
39155
39158
|
};
|
|
39156
39159
|
var DEFAULT_HEAT = {
|
|
39157
|
-
cap:
|
|
39158
|
-
displayMax:
|
|
39159
|
-
|
|
39160
|
-
|
|
39161
|
-
|
|
39162
|
-
|
|
39163
|
-
|
|
39160
|
+
cap: 900,
|
|
39161
|
+
displayMax: 750,
|
|
39162
|
+
faultFrom: 350,
|
|
39163
|
+
faultSpan: 200,
|
|
39164
|
+
specificHeat: 490,
|
|
39165
|
+
barrelShare: { shell: 0.48, big: 0.48, tiny: 0.3, pistol: 0.3, rifle: 0.48 },
|
|
39166
|
+
barrelKilogramsPerMetre: {
|
|
39167
|
+
pistol: 1,
|
|
39168
|
+
revolver: 1.4,
|
|
39169
|
+
smg: 1.2,
|
|
39170
|
+
carbine: 1.6,
|
|
39171
|
+
rifle: 1.6,
|
|
39172
|
+
dmr: 2.4,
|
|
39173
|
+
sniper: 2.4,
|
|
39174
|
+
hunting: 2.4,
|
|
39175
|
+
machine_gun: 3,
|
|
39176
|
+
shotgun: 1.1
|
|
39177
|
+
},
|
|
39178
|
+
barrelFallback: { metres: 0.4, kilogramsPerMetre: 1.6 },
|
|
39179
|
+
cooling: { baseSeconds: 30, secondsPerKilogram: 250 },
|
|
39164
39180
|
perRocket: 35,
|
|
39165
|
-
visual: { smokeFrom:
|
|
39181
|
+
visual: { smokeFrom: 250, smokeSpan: 300, smokeSeconds: 2.5, glowFrom: 450, glowSpan: 300 }
|
|
39166
39182
|
};
|
|
39167
39183
|
var GALLERY_HEAT = {
|
|
39168
39184
|
...DEFAULT_HEAT,
|
|
39169
|
-
|
|
39185
|
+
cap: 140,
|
|
39186
|
+
displayMax: 120,
|
|
39187
|
+
faultFrom: 60,
|
|
39188
|
+
faultSpan: 40,
|
|
39189
|
+
visual: { smokeFrom: 70, smokeSpan: 100, smokeSeconds: 2.5, glowFrom: 80, glowSpan: 40 },
|
|
39190
|
+
gallery: {
|
|
39191
|
+
perShot: { shell: 6, big: 9, tiny: 1.2, pistol: 3, rifle: 4.5 },
|
|
39192
|
+
decayBase: 1.6,
|
|
39193
|
+
decayPerPoint: 0.03
|
|
39194
|
+
}
|
|
39170
39195
|
};
|
|
39171
39196
|
var defaultFaultChance = (context) => {
|
|
39172
39197
|
const factor = context.def.action.kind === "firearm" ? context.def.action.faultFactor ?? 1 : 1;
|
|
@@ -39449,17 +39474,55 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39449
39474
|
...explosive.stunSeconds !== void 0 ? { stunSeconds: explosive.stunSeconds } : {}
|
|
39450
39475
|
};
|
|
39451
39476
|
};
|
|
39477
|
+
var EPS22 = 1e-9;
|
|
39478
|
+
var MANUAL_MODES = /* @__PURE__ */ new Set(["pump", "bolt", "lever"]);
|
|
39479
|
+
var weaponSpeed = (action, caliber) => action.muzzleSpeed ?? caliber.muzzleSpeed * (action.barrel ?? 1);
|
|
39480
|
+
var weaponNoise = (action, caliber) => action.noise ?? caliber.noise ?? 0;
|
|
39481
|
+
var timingsOf = (action) => "timings" in action ? action.timings : void 0;
|
|
39482
|
+
var drawSeconds = (action, rules) => timingsOf(action)?.draw ?? rules.draw;
|
|
39483
|
+
var clearSeconds = (action, rules) => timingsOf(action)?.clear ?? rules.clear;
|
|
39484
|
+
var manualCycleSeconds = (action, mode) => MANUAL_MODES.has(mode) ? action.timings?.cycle ?? 0 : 0;
|
|
39485
|
+
var planRounds = (action, mode, ammo, firstAt, frameEnd) => {
|
|
39486
|
+
const interval = 60 / action.rpm;
|
|
39487
|
+
const times = [];
|
|
39488
|
+
if (mode === "auto") {
|
|
39489
|
+
for (let t = firstAt; times.length < ammo && (times.length === 0 ? t <= frameEnd + EPS22 : t < frameEnd - EPS22); t += interval) times.push(t);
|
|
39490
|
+
return times;
|
|
39491
|
+
}
|
|
39492
|
+
if (mode === "burst") {
|
|
39493
|
+
const count = Math.min(action.burst ?? 3, ammo);
|
|
39494
|
+
for (let k = 0; k < count; k++) times.push(firstAt + k * interval);
|
|
39495
|
+
return times;
|
|
39496
|
+
}
|
|
39497
|
+
if (mode === "volley") return Array.from({ length: Math.min(action.magazine, ammo) }, () => firstAt);
|
|
39498
|
+
return [firstAt];
|
|
39499
|
+
};
|
|
39452
39500
|
var SUBSTEP_SECONDS = 1 / 60;
|
|
39453
|
-
var
|
|
39501
|
+
var barrelMassOf = (def, rules) => {
|
|
39502
|
+
const dimensions = def.dimensions;
|
|
39503
|
+
const kilogramsPerMetre = rules.barrelKilogramsPerMetre[def.category] ?? rules.barrelFallback.kilogramsPerMetre;
|
|
39504
|
+
const single = dimensions?.barrelMass ?? (dimensions?.barrel ?? rules.barrelFallback.metres) * kilogramsPerMetre;
|
|
39505
|
+
return single * (dimensions?.barrels ?? 1);
|
|
39506
|
+
};
|
|
39507
|
+
var coolingTimeConstant = (barrelMass, rules) => rules.cooling.baseSeconds + rules.cooling.secondsPerKilogram * barrelMass;
|
|
39508
|
+
var decayHeat = (heat, seconds, barrelMass, rules) => {
|
|
39509
|
+
if (heat <= 0) return 0;
|
|
39510
|
+
if (rules.gallery) return decayGallery(heat, seconds, rules.gallery);
|
|
39511
|
+
return heat * Math.exp(-seconds / coolingTimeConstant(barrelMass, rules));
|
|
39512
|
+
};
|
|
39513
|
+
var decayGallery = (heat, seconds, gallery) => {
|
|
39454
39514
|
const steps = Math.max(1, Math.ceil(seconds / SUBSTEP_SECONDS - 1e-9));
|
|
39455
39515
|
const step = seconds / steps;
|
|
39456
39516
|
let current = heat;
|
|
39457
|
-
for (let i = 0; i < steps && current > 0; i++) current = Math.max(0, current - step * (
|
|
39517
|
+
for (let i = 0; i < steps && current > 0; i++) current = Math.max(0, current - step * (gallery.decayBase + current * gallery.decayPerPoint));
|
|
39458
39518
|
return current;
|
|
39459
39519
|
};
|
|
39460
|
-
var heatPerRound = (action, caliber, rules) => {
|
|
39520
|
+
var heatPerRound = ({ action, caliber, energy, barrelMass, rules }) => {
|
|
39461
39521
|
if (action.kind === "launcher") return rules.perRocket;
|
|
39462
|
-
|
|
39522
|
+
const caseType = caliber?.caseType;
|
|
39523
|
+
if (!caseType) return 0;
|
|
39524
|
+
if (rules.gallery) return rules.gallery.perShot[caseType];
|
|
39525
|
+
return rules.barrelShare[caseType] * energy / (barrelMass * rules.specificHeat);
|
|
39463
39526
|
};
|
|
39464
39527
|
var burstNoise = (base, recentShots, rules) => base * (1 + Math.min(rules.cap, rules.step * recentShots));
|
|
39465
39528
|
var magazineOut = { stage: "magazine_out", at: 0 };
|
|
@@ -39586,29 +39649,6 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39586
39649
|
return roll.ammoQuality.faultChance > 0 && roll.random() < roll.ammoQuality.faultChance ? "misfire" : null;
|
|
39587
39650
|
};
|
|
39588
39651
|
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
39652
|
var activeParts = (fitted, catalogue) => fitted.flatMap((part) => {
|
|
39613
39653
|
const def = catalogue.get(part.id);
|
|
39614
39654
|
const isOn = def?.kind !== "light" && def?.kind !== "laser" ? true : part.on === true;
|
|
@@ -39841,6 +39881,10 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39841
39881
|
get safety() {
|
|
39842
39882
|
return this._safety;
|
|
39843
39883
|
}
|
|
39884
|
+
/** Kg of steel that heat up with the shots. */
|
|
39885
|
+
get barrelMass() {
|
|
39886
|
+
return barrelMassOf(this.def, this.rules.heat);
|
|
39887
|
+
}
|
|
39844
39888
|
get heat() {
|
|
39845
39889
|
return this._heat;
|
|
39846
39890
|
}
|
|
@@ -39893,7 +39937,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
39893
39937
|
}
|
|
39894
39938
|
advance(seconds) {
|
|
39895
39939
|
if (seconds <= 0) return;
|
|
39896
|
-
this._heat = decayHeat(this._heat, seconds, this.rules.heat);
|
|
39940
|
+
this._heat = decayHeat(this._heat, seconds, this.barrelMass, this.rules.heat);
|
|
39897
39941
|
this.clock += seconds;
|
|
39898
39942
|
}
|
|
39899
39943
|
/** Complete what falls at or before `t`: scheduled events and the reload steps. */
|
|
@@ -40445,7 +40489,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
40445
40489
|
res.shots.push(shot);
|
|
40446
40490
|
}
|
|
40447
40491
|
this._ammo -= 1;
|
|
40448
|
-
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound(a, cal, this.rules.heat) * this.load.heatFactor);
|
|
40492
|
+
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
40493
|
this.readyAt = t + 60 / a.rpm;
|
|
40450
40494
|
this.extra = Math.min(bloomNow + (a.bloomDeg ?? 0), a.spreadDeg * (BLOOM_CAP - 1));
|
|
40451
40495
|
this.extraClock = t;
|
|
@@ -40534,7 +40578,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
40534
40578
|
}
|
|
40535
40579
|
const t = Math.max(start, this.readyAt);
|
|
40536
40580
|
this._ammo -= 1;
|
|
40537
|
-
this._heat = Math.min(this.rules.heat.cap, this._heat + heatPerRound(a, null, this.rules.heat));
|
|
40581
|
+
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
40582
|
this.emit({ type: "shot", shots: 0, rounds: 1, mode: this.mode, at: t });
|
|
40539
40583
|
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
40584
|
}
|
|
@@ -49409,6 +49453,7 @@ void main(){
|
|
|
49409
49453
|
}
|
|
49410
49454
|
|
|
49411
49455
|
// src/player.ts
|
|
49456
|
+
var RECOIL_RETURN = { share: 0.7, seconds: 0.25 };
|
|
49412
49457
|
var SLAM_MIN_SPEED2 = 1.5;
|
|
49413
49458
|
var LANDING_MIN_SPEED = 1;
|
|
49414
49459
|
var EYE = 1.7;
|
|
@@ -49438,6 +49483,18 @@ void main(){
|
|
|
49438
49483
|
const cam = o.camera;
|
|
49439
49484
|
let yaw = 0;
|
|
49440
49485
|
let pitch = 0;
|
|
49486
|
+
const recoilReturn = o.recoilReturn ?? RECOIL_RETURN;
|
|
49487
|
+
const recoilDebt = { pitch: 0, yaw: 0 };
|
|
49488
|
+
const returnRecoil = (dt) => {
|
|
49489
|
+
if (Math.abs(recoilDebt.pitch) + Math.abs(recoilDebt.yaw) < 1e-6) return;
|
|
49490
|
+
const k = 1 - Math.exp(-3 * dt / Math.max(1e-3, recoilReturn.seconds));
|
|
49491
|
+
const back = { pitch: recoilDebt.pitch * k, yaw: recoilDebt.yaw * k };
|
|
49492
|
+
recoilDebt.pitch -= back.pitch;
|
|
49493
|
+
recoilDebt.yaw -= back.yaw;
|
|
49494
|
+
pitch = Math.max(-1.5, Math.min(1.5, pitch - back.pitch));
|
|
49495
|
+
yaw -= back.yaw;
|
|
49496
|
+
apply();
|
|
49497
|
+
};
|
|
49441
49498
|
let y = 0;
|
|
49442
49499
|
let eye = EYE;
|
|
49443
49500
|
let crouch = 0;
|
|
@@ -49779,6 +49836,7 @@ void main(){
|
|
|
49779
49836
|
return stunLeft;
|
|
49780
49837
|
},
|
|
49781
49838
|
update(dt) {
|
|
49839
|
+
returnRecoil(dt);
|
|
49782
49840
|
if (stunLeft > 0) {
|
|
49783
49841
|
stunLeft = Math.max(0, stunLeft - dt);
|
|
49784
49842
|
stunPhase += dt * 2.4;
|
|
@@ -49827,6 +49885,8 @@ void main(){
|
|
|
49827
49885
|
},
|
|
49828
49886
|
setPose(position, yw, pt2) {
|
|
49829
49887
|
knocked = null;
|
|
49888
|
+
recoilDebt.pitch = 0;
|
|
49889
|
+
recoilDebt.yaw = 0;
|
|
49830
49890
|
px.x = position[0];
|
|
49831
49891
|
px.z = position[2];
|
|
49832
49892
|
floorLevel = floorHere();
|
|
@@ -49839,6 +49899,8 @@ void main(){
|
|
|
49839
49899
|
},
|
|
49840
49900
|
look(position, target) {
|
|
49841
49901
|
knocked = null;
|
|
49902
|
+
recoilDebt.pitch = 0;
|
|
49903
|
+
recoilDebt.yaw = 0;
|
|
49842
49904
|
px.x = position[0];
|
|
49843
49905
|
px.z = position[2];
|
|
49844
49906
|
floorLevel = floorHere();
|
|
@@ -49853,8 +49915,11 @@ void main(){
|
|
|
49853
49915
|
apply();
|
|
49854
49916
|
},
|
|
49855
49917
|
kick(pitchDeg, yawDeg) {
|
|
49918
|
+
const before = pitch;
|
|
49856
49919
|
pitch = Math.max(-1.5, Math.min(1.5, pitch + pitchDeg * Math.PI / 180));
|
|
49857
49920
|
yaw += yawDeg * Math.PI / 180;
|
|
49921
|
+
recoilDebt.pitch += (pitch - before) * recoilReturn.share;
|
|
49922
|
+
recoilDebt.yaw += yawDeg * Math.PI / 180 * recoilReturn.share;
|
|
49858
49923
|
apply();
|
|
49859
49924
|
},
|
|
49860
49925
|
moveBy(dx, dz) {
|
|
@@ -55519,6 +55584,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
55519
55584
|
const scene2 = options.scene ?? new THREE.Scene();
|
|
55520
55585
|
const camera2 = options.camera ?? new THREE.PerspectiveCamera(72, width() / height(), 0.05, 140);
|
|
55521
55586
|
if (!options.camera) scene2.add(camera2);
|
|
55587
|
+
camera2.layers.disable(FIRST_PERSON_LAYER);
|
|
55522
55588
|
const resize = () => {
|
|
55523
55589
|
const w = width();
|
|
55524
55590
|
const h = height();
|
|
@@ -56610,10 +56676,21 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56610
56676
|
return { ...pose, position: pose.at(camDistance), free: camDistance };
|
|
56611
56677
|
};
|
|
56612
56678
|
const thirdActive = () => cameraMode === "third" && avatar !== null;
|
|
56679
|
+
const firstPersonArms = options.firstPersonArms ?? null;
|
|
56680
|
+
if (firstPersonArms) {
|
|
56681
|
+
firstPersonArms.root.visible = cameraMode === "first";
|
|
56682
|
+
scene2.add(firstPersonArms.root);
|
|
56683
|
+
}
|
|
56613
56684
|
const syncAvatarVisible = () => {
|
|
56685
|
+
if (firstPersonArms) firstPersonArms.root.visible = cameraMode === "first";
|
|
56614
56686
|
if (!avatar) return;
|
|
56615
56687
|
avatar.root.visible = cameraMode === "third" || !!avatar.eye;
|
|
56616
|
-
avatar.setView?.(cameraMode, camera2);
|
|
56688
|
+
avatar.setView?.(cameraMode, camera2, { arms: firstPersonArms !== null });
|
|
56689
|
+
};
|
|
56690
|
+
const updateFirstPersonArms = (dt) => {
|
|
56691
|
+
if (!firstPersonArms || cameraMode !== "first") return;
|
|
56692
|
+
firstPersonArms.update(dt, { camera: camera2, targets: lastHand.targets, stance: lastHand.stance, speed: player.speed, running: avatarState.running, crouch: avatarState.crouch });
|
|
56693
|
+
firstPersonArms.root.traverse((node) => node.layers.set(FIRST_PERSON_LAYER));
|
|
56617
56694
|
};
|
|
56618
56695
|
const setCameraMode = (mode) => {
|
|
56619
56696
|
if (mode !== "first" && mode !== "third") return;
|
|
@@ -56697,6 +56774,39 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56697
56774
|
};
|
|
56698
56775
|
let handSource = null;
|
|
56699
56776
|
let muzzleSource = null;
|
|
56777
|
+
let viewmodelFov = null;
|
|
56778
|
+
const firstPersonCamera = new THREE.PerspectiveCamera(72, 1, 0.01, 30);
|
|
56779
|
+
firstPersonCamera.layers.set(FIRST_PERSON_LAYER);
|
|
56780
|
+
let firstPersonPasses = 0;
|
|
56781
|
+
const drawFirstPersonLayer = () => {
|
|
56782
|
+
if (!firstPersonArms && viewmodelFov === null) return;
|
|
56783
|
+
const renderer2 = gl;
|
|
56784
|
+
if (typeof renderer2.clearDepth !== "function" || typeof renderer2.render !== "function") return;
|
|
56785
|
+
if (firstPersonPasses++ % 60 === 0) {
|
|
56786
|
+
scene2.traverse((node) => {
|
|
56787
|
+
if (node.isLight) node.layers.enable(FIRST_PERSON_LAYER);
|
|
56788
|
+
});
|
|
56789
|
+
}
|
|
56790
|
+
firstPersonCamera.position.copy(camera2.position);
|
|
56791
|
+
firstPersonCamera.quaternion.copy(camera2.quaternion);
|
|
56792
|
+
const fov = viewmodelFov ?? camera2.fov;
|
|
56793
|
+
if (firstPersonCamera.fov !== fov || firstPersonCamera.aspect !== camera2.aspect) {
|
|
56794
|
+
firstPersonCamera.fov = fov;
|
|
56795
|
+
firstPersonCamera.aspect = camera2.aspect;
|
|
56796
|
+
firstPersonCamera.updateProjectionMatrix();
|
|
56797
|
+
}
|
|
56798
|
+
firstPersonCamera.updateMatrixWorld();
|
|
56799
|
+
const { autoClear } = renderer2;
|
|
56800
|
+
const { background, fog } = scene2;
|
|
56801
|
+
renderer2.autoClear = false;
|
|
56802
|
+
scene2.background = null;
|
|
56803
|
+
scene2.fog = null;
|
|
56804
|
+
renderer2.clearDepth();
|
|
56805
|
+
renderer2.render(scene2, firstPersonCamera);
|
|
56806
|
+
scene2.background = background;
|
|
56807
|
+
scene2.fog = fog;
|
|
56808
|
+
renderer2.autoClear = autoClear ?? true;
|
|
56809
|
+
};
|
|
56700
56810
|
let debugView = null;
|
|
56701
56811
|
let lastHand = { stance: "relaxed", triggerFinger: null, targets: null };
|
|
56702
56812
|
const strikeClips = options.strikeClips ?? DEFAULT_STRIKE_CLIPS;
|
|
@@ -56844,7 +56954,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56844
56954
|
const line = new THREE.Line(g, tracerMat);
|
|
56845
56955
|
line.frustumCulled = false;
|
|
56846
56956
|
scene2.add(line);
|
|
56847
|
-
tr = { line, life: 0 };
|
|
56957
|
+
tr = { line, life: 0, follows: false };
|
|
56848
56958
|
tracers.push(tr);
|
|
56849
56959
|
}
|
|
56850
56960
|
const attr = tr.line.geometry.getAttribute("position");
|
|
@@ -56853,6 +56963,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
56853
56963
|
attr.needsUpdate = true;
|
|
56854
56964
|
tr.line.visible = true;
|
|
56855
56965
|
tr.life = 0.07;
|
|
56966
|
+
tr.follows = muzzleSource !== null;
|
|
56856
56967
|
};
|
|
56857
56968
|
const fireZones = [];
|
|
56858
56969
|
const burningStains = [];
|
|
@@ -58168,10 +58279,16 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58168
58279
|
}
|
|
58169
58280
|
};
|
|
58170
58281
|
const simulateAfterModules = (dt) => {
|
|
58282
|
+
const drawn = tracers.some((tr) => tr.life > 0 && tr.follows) ? muzzleSource?.() ?? null : null;
|
|
58171
58283
|
for (const tr of tracers) {
|
|
58172
58284
|
if (tr.life > 0) {
|
|
58173
58285
|
tr.life -= dt;
|
|
58174
58286
|
if (tr.life <= 0) tr.line.visible = false;
|
|
58287
|
+
else if (tr.follows && drawn) {
|
|
58288
|
+
const attr = tr.line.geometry.getAttribute("position");
|
|
58289
|
+
attr.setXYZ(0, drawn.position[0], drawn.position[1], drawn.position[2]);
|
|
58290
|
+
attr.needsUpdate = true;
|
|
58291
|
+
}
|
|
58175
58292
|
}
|
|
58176
58293
|
}
|
|
58177
58294
|
flush();
|
|
@@ -58205,6 +58322,7 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58205
58322
|
};
|
|
58206
58323
|
const updatePresent = (dt) => {
|
|
58207
58324
|
reachAvatar();
|
|
58325
|
+
updateFirstPersonArms(dt);
|
|
58208
58326
|
if (progress && simTime - progress.at > 0.25) progress = null;
|
|
58209
58327
|
ui?.flushLog();
|
|
58210
58328
|
hudAcc += dt;
|
|
@@ -58554,6 +58672,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
58554
58672
|
if (handSource === source) handSource = null;
|
|
58555
58673
|
};
|
|
58556
58674
|
},
|
|
58675
|
+
setViewmodelFov(degrees) {
|
|
58676
|
+
viewmodelFov = degrees;
|
|
58677
|
+
},
|
|
58557
58678
|
setMuzzleSource(source) {
|
|
58558
58679
|
muzzleSource = source;
|
|
58559
58680
|
return () => {
|
|
@@ -59285,7 +59406,9 @@ ${SURFACE_GLSL}`).replace("#include <color_fragment>", "#include <color_fragment
|
|
|
59285
59406
|
for (const batcher of batchers.values()) batcher.update();
|
|
59286
59407
|
const restoreCamera = room.applyCamera();
|
|
59287
59408
|
graphics?.beforeRender(camera2);
|
|
59288
|
-
|
|
59409
|
+
const view = debugView ?? moduleViews.main(camera2);
|
|
59410
|
+
gl.render(scene2, view);
|
|
59411
|
+
if (view === camera2 && cameraMode === "first") drawFirstPersonLayer();
|
|
59289
59412
|
moduleViews.render(scene2);
|
|
59290
59413
|
graphics?.afterRender();
|
|
59291
59414
|
restoreCamera();
|