@adatechnology/game-weather-three 0.4.3 → 0.5.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.
@@ -42,7 +42,7 @@ var GameWeatherThree = (() => {
42
42
  WEATHER_LAYERS: () => WEATHER_LAYERS,
43
43
  ZONE_FOG_DEFAULTS: () => ZONE_FOG_DEFAULTS,
44
44
  ZONE_LIGHT: () => ZONE_LIGHT,
45
- createFog: () => createFog,
45
+ createFog: () => createFog2,
46
46
  createHeadlights: () => createHeadlights,
47
47
  createHeatHaze: () => createHeatHaze,
48
48
  createLightning: () => createLightning,
@@ -59,6 +59,77 @@ var GameWeatherThree = (() => {
59
59
  weatherVisualTextOf: () => weatherVisualTextOf
60
60
  });
61
61
 
62
+ // ../game-render-three/dist/index.js
63
+ var DEFAULT_ANGLE = Math.PI / 3;
64
+ var NEUTRAL_FOG_NEAR = 6e4;
65
+ var NEUTRAL_FOG_FAR = 64e3;
66
+ function isLinearFog(fog) {
67
+ return fog?.isFog === true;
68
+ }
69
+ function isExp2Fog(fog) {
70
+ return fog?.isFogExp2 === true;
71
+ }
72
+ function createFog(THREE, scene, options = {}) {
73
+ const original = scene.fog;
74
+ const hostLinear = isLinearFog(original) ? { color: original.color.getHex(), near: original.near, far: original.far } : void 0;
75
+ const resting = hostLinear ?? { color: options.color ?? 0, near: NEUTRAL_FOG_NEAR, far: NEUTRAL_FOG_FAR };
76
+ return {
77
+ useLinear(color, near, far) {
78
+ const current = scene.fog;
79
+ if (isLinearFog(current)) {
80
+ current.color.set(color);
81
+ current.near = near;
82
+ current.far = far;
83
+ return current;
84
+ }
85
+ const fog = new THREE.Fog(color, near, far);
86
+ scene.fog = fog;
87
+ return fog;
88
+ },
89
+ useExp2(color, density) {
90
+ const current = scene.fog;
91
+ if (isExp2Fog(current)) {
92
+ current.color.set(color);
93
+ current.density = density;
94
+ return current;
95
+ }
96
+ const fog = new THREE.FogExp2(color, density);
97
+ scene.fog = fog;
98
+ return fog;
99
+ },
100
+ clear() {
101
+ if (options.stable !== true) {
102
+ scene.fog = original;
103
+ return;
104
+ }
105
+ const current = scene.fog;
106
+ if (isLinearFog(current)) {
107
+ current.color.set(resting.color);
108
+ current.near = resting.near;
109
+ current.far = resting.far;
110
+ return;
111
+ }
112
+ scene.fog = new THREE.Fog(resting.color, resting.near, resting.far);
113
+ }
114
+ };
115
+ }
116
+ var LIGHT_PRIORITY = {
117
+ blast: 900,
118
+ rocket: 800,
119
+ muzzle: 750,
120
+ fire: 600,
121
+ flare: 500,
122
+ headlight: 400,
123
+ weaponLight: 400,
124
+ lamp: 200,
125
+ street: 150
126
+ };
127
+ function isLightBudget(value) {
128
+ const candidate = value;
129
+ return typeof candidate === "object" && candidate !== null && typeof candidate.acquire === "function" && typeof candidate.addSource === "function" && typeof candidate.lease === "function" && typeof candidate.present === "function";
130
+ }
131
+ var EFFECT_STEP_SECONDS = 1 / 50;
132
+
62
133
  // src/sky.ts
63
134
  var SKY_NIGHT = 724760;
64
135
  var SKY_DAY = 8885926;
@@ -98,7 +169,8 @@ var GameWeatherThree = (() => {
98
169
  if (sample.fogDensity >= expFrom) return { mode: "exp2", density: sample.fogDensity + (densityForFar(zoneFar) - sample.fogDensity) * weight };
99
170
  return { mode: "linear", near: FOG_NEAR + (FOG_ZONE_NEAR - FOG_NEAR) * weight, far: sample.fogFar + (zoneFar - sample.fogFar) * weight };
100
171
  }
101
- function createFog(THREE, scene, options = {}) {
172
+ function createFog2(THREE, scene, options = {}) {
173
+ if (options.stable) return stableFog(THREE, scene, options);
102
174
  const original = scene.fog;
103
175
  const kept = original && original.isFog ? original.clone() : original;
104
176
  return {
@@ -123,6 +195,18 @@ var GameWeatherThree = (() => {
123
195
  }
124
196
  };
125
197
  }
198
+ function stableFog(THREE, scene, options) {
199
+ const controller = createFog(THREE, scene, { stable: true });
200
+ return {
201
+ update(sample, sky, zone) {
202
+ const values = fogOf(sample, zone, options.expFrom);
203
+ if (values.mode === "linear") controller.useLinear(sky.getHex(), values.near, values.far);
204
+ else controller.useExp2(sky.getHex(), values.density);
205
+ scene.fog.color.copy(sky);
206
+ },
207
+ clear: () => controller.clear()
208
+ };
209
+ }
126
210
  var MIST = { box: { x: [-14, 10], y: [0.2, 1.1], z: [-3, 8] }, drift: [0.15, 0.35], life: [9, 13], size: [3, 5], grow: 1.4, color: 8227488, alpha: 0.13, fadeIn: 0.35 };
127
211
  var ASH = { box: { x: [-10, 8], y: [4, 6], z: [-3, 7] }, fall: -0.35, life: [8, 12], size: [0.025, 0.04], color: 10525328, alpha: 0.75, fadeIn: 0.1 };
128
212
  function emitAirborne(engine, sample, dt, camera2) {
@@ -181,18 +265,37 @@ var GameWeatherThree = (() => {
181
265
  const aimWorld = new THREE.Vector3();
182
266
  const forward = new THREE.Vector3();
183
267
  const rule = rules.lit ?? defaultHeadlightRule;
184
- const range = rules.lightRange ?? HEADLIGHTS.lightRange;
268
+ const range2 = rules.lightRange ?? HEADLIGHTS.lightRange;
269
+ const lights = rules.lights;
270
+ const forwardAxis = new THREE.Vector3(0, 0, -1);
271
+ function lampSource(side, car, targets) {
272
+ const lamp = new THREE.Object3D();
273
+ lamp.position.set(side * HEADLIGHTS.lamp[0], HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2]);
274
+ const aim = new THREE.Vector3(side * HEADLIGHTS.aim[0], HEADLIGHTS.aim[1], HEADLIGHTS.aim[2]).sub(lamp.position).normalize();
275
+ lamp.quaternion.setFromUnitVectors(forwardAxis, aim);
276
+ car.add(lamp);
277
+ targets.push(lamp);
278
+ const spot = HEADLIGHTS.spot;
279
+ return lights.addSource({ owner: "weather.headlight", kind: "spot", priority: LIGHT_PRIORITY.headlight, color: spot.color, intensity: 0, distance: spot.distance, decay: spot.decay, angle: spot.angle, penumbra: spot.penumbra, position: [0, 0, 0], follow: lamp });
280
+ }
281
+ function legacySpot(side, car, targets) {
282
+ const spot = new THREE.SpotLight(HEADLIGHTS.spot.color, 0, HEADLIGHTS.spot.distance, HEADLIGHTS.spot.angle, HEADLIGHTS.spot.penumbra, HEADLIGHTS.spot.decay);
283
+ spot.position.set(side * HEADLIGHTS.lamp[0], HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2]);
284
+ const target = new THREE.Object3D();
285
+ target.position.set(side * HEADLIGHTS.aim[0], HEADLIGHTS.aim[1], HEADLIGHTS.aim[2]);
286
+ car.add(spot, target);
287
+ spot.target = target;
288
+ targets.push(target);
289
+ return spot;
290
+ }
185
291
  function attach(car, lens2) {
186
292
  const spots = [];
187
293
  const cones = [];
188
294
  const targets = [];
295
+ const sources = [];
189
296
  for (const side of [-1, 1]) {
190
- const spot = new THREE.SpotLight(HEADLIGHTS.spot.color, 0, HEADLIGHTS.spot.distance, HEADLIGHTS.spot.angle, HEADLIGHTS.spot.penumbra, HEADLIGHTS.spot.decay);
191
- spot.position.set(side * HEADLIGHTS.lamp[0], HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2]);
192
- const target = new THREE.Object3D();
193
- target.position.set(side * HEADLIGHTS.aim[0], HEADLIGHTS.aim[1], HEADLIGHTS.aim[2]);
194
- car.add(spot, target);
195
- spot.target = target;
297
+ if (lights) sources.push(lampSource(side, car, targets));
298
+ else spots.push(legacySpot(side, car, targets));
196
299
  const geometry = new THREE.ConeGeometry(cone.radius, cone.length, cone.segments, 1, true);
197
300
  geometry.translate(0, -cone.length / 2, 0);
198
301
  geometry.rotateX(-Math.PI / 2);
@@ -201,11 +304,9 @@ var GameWeatherThree = (() => {
201
304
  beam.position.set(side * HEADLIGHTS.lamp[0], HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2]);
202
305
  beam.visible = false;
203
306
  car.add(beam);
204
- spots.push(spot);
205
307
  cones.push(beam);
206
- targets.push(target);
207
308
  }
208
- const rig = { car, spots, cones, lens: lens2, targets };
309
+ const rig = { car, spots, sources, cones, lens: lens2, targets };
209
310
  rigs.add(rig);
210
311
  return () => {
211
312
  rigs.delete(rig);
@@ -215,6 +316,7 @@ var GameWeatherThree = (() => {
215
316
  beam.material.dispose();
216
317
  }
217
318
  for (const spot of spots) spot.dispose();
319
+ for (const source of sources) source.remove();
218
320
  lens2?.color.setHex(HEADLIGHTS.lens.off);
219
321
  };
220
322
  }
@@ -226,8 +328,9 @@ var GameWeatherThree = (() => {
226
328
  for (const rig of rigs) {
227
329
  rig.car.updateWorldMatrix(true, false);
228
330
  lampWorld.set(0, HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2]).applyMatrix4(rig.car.matrixWorld);
229
- const near = Math.hypot(lampWorld.x - camera2[0], lampWorld.z - camera2[2]) <= range;
331
+ const near = Math.hypot(lampWorld.x - camera2[0], lampWorld.z - camera2[2]) <= range2;
230
332
  for (const spot of rig.spots) spot.intensity = on && near ? HEADLIGHTS.spot.intensity : 0;
333
+ for (const source of rig.sources) source.update({ intensity: on && near ? HEADLIGHTS.spot.intensity : 0 });
231
334
  for (const beam of rig.cones) beam.visible = on;
232
335
  rig.lens?.color.setHex(on ? HEADLIGHTS.lens.on : HEADLIGHTS.lens.off);
233
336
  if (!on || !engine || sample.rain <= 0 || !near) {
@@ -261,6 +364,7 @@ var GameWeatherThree = (() => {
261
364
  for (const rig of [...rigs]) {
262
365
  rigs.delete(rig);
263
366
  for (const object of [...rig.spots, ...rig.cones, ...rig.targets]) rig.car.remove(object);
367
+ for (const source of rig.sources) source.remove();
264
368
  }
265
369
  }
266
370
  };
@@ -294,10 +398,13 @@ var GameWeatherThree = (() => {
294
398
 
295
399
  // src/lightning.ts
296
400
  var LIGHTNING = { light: 3.2, background: [0.25, 0.27, 0.32], white: 0.12, skyColor: 3820650, groundColor: 723724 };
297
- function createLightning(THREE, scene, vfx) {
298
- const light = new THREE.HemisphereLight(LIGHTNING.skyColor, LIGHTNING.groundColor, 0);
401
+ function createLightning(THREE, scene, vfx, options = {}) {
402
+ const leased = options.lights?.leaseHemisphere("weather.lightning") ?? null;
403
+ const light = leased ?? new THREE.HemisphereLight(LIGHTNING.skyColor, LIGHTNING.groundColor, 0);
299
404
  light.name = "weather-lightning";
300
- scene.add(light);
405
+ light.color.setHex(LIGHTNING.skyColor);
406
+ light.groundColor.setHex(LIGHTNING.groundColor);
407
+ if (!options.lights) scene.add(light);
301
408
  return {
302
409
  light,
303
410
  update(sample, background) {
@@ -313,6 +420,8 @@ var GameWeatherThree = (() => {
313
420
  if (screen2) screen2.white = Math.max(screen2.white, flash2 * LIGHTNING.white);
314
421
  },
315
422
  dispose() {
423
+ light.intensity = 0;
424
+ if (options.lights) return;
316
425
  scene.remove(light);
317
426
  light.dispose();
318
427
  }
@@ -988,10 +1097,10 @@ var GameWeatherThree = (() => {
988
1097
  )
989
1098
  ]
990
1099
  };
991
- function normalized(vector) {
992
- const length = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]) || 1;
1100
+ function normalized(vector2) {
1101
+ const length = Math.sqrt(vector2[0] * vector2[0] + vector2[1] * vector2[1] + vector2[2] * vector2[2]) || 1;
993
1102
  const inverse = 1 / length;
994
- return [vector[0] * inverse, vector[1] * inverse, vector[2] * inverse];
1103
+ return [vector2[0] * inverse, vector2[1] * inverse, vector2[2] * inverse];
995
1104
  }
996
1105
  var FRAME_DUST = normalized([0, -0.3, 1]);
997
1106
  var SPLINTER_DIRECTION = normalized([0, 0.3, 1]);
@@ -2189,9 +2298,32 @@ var GameWeatherThree = (() => {
2189
2298
  /** The leak caught fire (an incendiary or tracer round, a spark, a fire near): the page's whole sequence, the fire running along the pool to the tank and the blast. */
2190
2299
  aliasOf(FUEL_LEAK, "vehicle_leak_ignited", {})
2191
2300
  ];
2301
+ var vector = [variable("vx"), variable("vy"), variable("vz")];
2302
+ var range = (name) => [variable(name), variable(name)];
2303
+ var singleParticle = (id, system) => ({
2304
+ id,
2305
+ pageId: `particle:${id}`,
2306
+ team: "world",
2307
+ budget: { particles: 1, lights: 0 },
2308
+ loop: 1e-3,
2309
+ timeline: [
2310
+ spawn(system, {
2311
+ p: [0, 0, 0],
2312
+ v: vector,
2313
+ life: range("life"),
2314
+ size: range("size"),
2315
+ grow: variable("grow"),
2316
+ c0: variable("color"),
2317
+ a: variable("alpha"),
2318
+ g: variable("gravity"),
2319
+ drag: variable("drag")
2320
+ })
2321
+ ]
2322
+ });
2323
+ var SINGLE_PARTICLE_EFFECTS = [singleParticle("particle_puff", "normal"), singleParticle("particle_glow", "add"), singleParticle("particle_streak", "streak")];
2192
2324
  var ALL_EFFECTS = [BLOOD_HIT, HEADSHOT, DISMEMBER, BLOATER_CLOUD, SCREAMER_SHRIEK, CORPSE_DECAY, REANIMATION, EYES_IN_FOG, MUZZLE_FLASH, IMPACT_BY_MATERIAL, PENETRATION, CASINGS_AND_MAGAZINE, MOLOTOV, GRENADE, EXPLOSIVE_BARREL, SHOPFRONT_GLASS, DOOR_STAGES, BUILDING_COLLAPSE, BLOCK_WALL, METAL_DOOR_EFFECT, IRON_RAILING, WOODEN_FENCE, HIT_POINT_BREAKAGE, PRESSURE_CYLINDERS, BUILDING_FIRE, RAIN_AND_PUDDLES, FOG_AND_ASH, SCRAPING_SPARKS, ENGINE_SMOKE, FUEL_LEAK, CAR_EXPLOSION, WINDSHIELD, HEADLIGHTS_IN_RAIN, DAMAGE_AND_BITE, INFECTION_PHASES, PANIC, BLOATER_BLINDNESS, CAMPFIRE, COUGH_AND_BREATH];
2193
2325
  var WORKSHOP_EFFECTS = Object.fromEntries(ALL_EFFECTS.map((effect) => [effect.id, effect]));
2194
- var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS].map((effect) => [effect.id, effect])) };
2326
+ var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS, ...SINGLE_PARTICLE_EFFECTS].map((effect) => [effect.id, effect])) };
2195
2327
  var QUARTER_TURN2 = Math.PI / 2;
2196
2328
  var SCRATCH = createVec3();
2197
2329
  var QUARTER_TURN3 = Math.PI / 2;
@@ -2281,9 +2413,9 @@ var GameWeatherThree = (() => {
2281
2413
  const haze = createHeatHaze(THREE);
2282
2414
  group.add(curtain.object, haze.object);
2283
2415
  const sky = createSky(THREE, scene);
2284
- const fog = createFog(THREE, scene);
2285
- const lightning = createLightning(THREE, scene, vfx);
2286
- const headlights = createHeadlights(THREE, options.headlights);
2416
+ const fog = createFog2(THREE, scene, { stable: options.lights !== void 0 });
2417
+ const lightning = createLightning(THREE, scene, vfx, options.lights ? { lights: options.lights } : {});
2418
+ const headlights = createHeadlights(THREE, options.lights ? { ...options.headlights, lights: options.lights } : options.headlights);
2287
2419
  const nearRain = createNearRain(vfx, { ...options.puddles ? { puddles: options.puddles } : {}, ...options.puddleAt ? { puddleAt: options.puddleAt } : {} });
2288
2420
  const on = new Map(WEATHER_LAYERS.map((id) => [id, options.layers?.[id] ?? true]));
2289
2421
  let zone = options.zone;
@@ -2349,6 +2481,19 @@ var GameWeatherThree = (() => {
2349
2481
  }
2350
2482
 
2351
2483
  // ../game-contracts/dist/index.js
2484
+ var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
2485
+ var DEFERRED_QUEUE_ID = {
2486
+ DESTRUCTION_EVENTS: "destruction.events",
2487
+ BREACH_PAINT: "floorplan.breach-paint",
2488
+ AUDIO_VOICES: "audio.voices",
2489
+ VEHICLE_CREASE: "vehicles.crease"
2490
+ };
2491
+ var DEFERRED_PRIORITY = {
2492
+ [DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: "present" },
2493
+ [DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: "present" },
2494
+ [DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: "idle", reserveMs: 1 },
2495
+ [DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: "idle" }
2496
+ };
2352
2497
  function footprintBlocker(object, footprint) {
2353
2498
  return (x, z, radius) => {
2354
2499
  const o = typeof object === "function" ? object() : object;
@@ -2365,6 +2510,42 @@ var GameWeatherThree = (() => {
2365
2510
  return lx > fp.minX - radius && lx < fp.maxX + radius && lz > fp.minZ - radius && lz < fp.maxZ + radius;
2366
2511
  };
2367
2512
  }
2513
+ var SURFACE_IDS = ["concrete", "asphalt", "wood", "tile", "dirt", "grass", "gravel", "sand", "metal", "water", "glass", "carpet"];
2514
+ var GAIT_IDS = ["walk", "run"];
2515
+ var LANDING_IDS = ["light", "heavy"];
2516
+ var BODY_SOUND_IDS = [
2517
+ "jump",
2518
+ "cloth_rustle",
2519
+ "body_fall",
2520
+ "fall_damage",
2521
+ "player_hurt",
2522
+ "player_breath_run",
2523
+ "player_death",
2524
+ "bite",
2525
+ "grab",
2526
+ "punch_swing",
2527
+ "punch_hit_body",
2528
+ "punch_hit_face",
2529
+ "punch_hit_object",
2530
+ "kick_swing",
2531
+ "kick_hit",
2532
+ "kick_hit_object",
2533
+ "shove_two_hands",
2534
+ "knife_swing",
2535
+ "knife_stab",
2536
+ "knife_slash",
2537
+ "knife_hit_object",
2538
+ "blunt_swing",
2539
+ "blunt_hit",
2540
+ "blunt_hit_object",
2541
+ "axe_swing",
2542
+ "axe_chop",
2543
+ "axe_hit_object"
2544
+ ];
2545
+ var footstepSoundId = (surface, gait) => `footstep_${surface}_${gait}`;
2546
+ var FOOTSTEP_SOUND_IDS = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)));
2547
+ var LAND_SOUND_IDS = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing) => `land_${surface}_${landing}`));
2548
+ var BODY_FOLEY_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
2368
2549
 
2369
2550
  // src/bench/text.ts
2370
2551
  var TEXTS = {
@@ -2413,7 +2594,8 @@ var GameWeatherThree = (() => {
2413
2594
  ...options.puddles ? { puddles: options.puddles } : {},
2414
2595
  ...options.puddleAt ? { puddleAt: options.puddleAt } : {},
2415
2596
  ...options.headlights ? { headlights: options.headlights } : {},
2416
- ...options.layers ? { layers: options.layers } : {}
2597
+ ...options.layers ? { layers: options.layers } : {},
2598
+ ...isLightBudget(host.lights) ? { lights: host.lights } : {}
2417
2599
  });
2418
2600
  const item = options.rigItem && host.addObject ? options.rigItem : void 0;
2419
2601
  return attachRig(THREE, host, renderer, options.rig === void 0 ? RIG_DEFAULT : options.rig, item ? void 0 : options.vehicles?.(THREE), options.rigVehicle ?? RIG_VEHICLE, item);