@adatechnology/game-vfx-three 0.4.0 → 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.
@@ -45,6 +45,19 @@ var GameVfxThree = (() => {
45
45
  });
46
46
 
47
47
  // ../game-contracts/dist/index.js
48
+ var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
49
+ var DEFERRED_QUEUE_ID = {
50
+ DESTRUCTION_EVENTS: "destruction.events",
51
+ BREACH_PAINT: "floorplan.breach-paint",
52
+ AUDIO_VOICES: "audio.voices",
53
+ VEHICLE_CREASE: "vehicles.crease"
54
+ };
55
+ var DEFERRED_PRIORITY = {
56
+ [DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: "present" },
57
+ [DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: "present" },
58
+ [DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: "idle", reserveMs: 1 },
59
+ [DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: "idle" }
60
+ };
48
61
  var KIT_ORIGIN_KEY = "kitOrigin";
49
62
  function markKitOrigin(object, origin) {
50
63
  const node = object;
@@ -52,6 +65,42 @@ var GameVfxThree = (() => {
52
65
  node.userData[KIT_ORIGIN_KEY] = { ...origin };
53
66
  return object;
54
67
  }
68
+ var SURFACE_IDS = ["concrete", "asphalt", "wood", "tile", "dirt", "grass", "gravel", "sand", "metal", "water", "glass", "carpet"];
69
+ var GAIT_IDS = ["walk", "run"];
70
+ var LANDING_IDS = ["light", "heavy"];
71
+ var BODY_SOUND_IDS = [
72
+ "jump",
73
+ "cloth_rustle",
74
+ "body_fall",
75
+ "fall_damage",
76
+ "player_hurt",
77
+ "player_breath_run",
78
+ "player_death",
79
+ "bite",
80
+ "grab",
81
+ "punch_swing",
82
+ "punch_hit_body",
83
+ "punch_hit_face",
84
+ "punch_hit_object",
85
+ "kick_swing",
86
+ "kick_hit",
87
+ "kick_hit_object",
88
+ "shove_two_hands",
89
+ "knife_swing",
90
+ "knife_stab",
91
+ "knife_slash",
92
+ "knife_hit_object",
93
+ "blunt_swing",
94
+ "blunt_hit",
95
+ "blunt_hit_object",
96
+ "axe_swing",
97
+ "axe_chop",
98
+ "axe_hit_object"
99
+ ];
100
+ var footstepSoundId = (surface, gait) => `footstep_${surface}_${gait}`;
101
+ var FOOTSTEP_SOUND_IDS = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)));
102
+ var LAND_SOUND_IDS = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing) => `land_${surface}_${landing}`));
103
+ var BODY_FOLEY_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
55
104
 
56
105
  // ../game-vfx/dist/index.js
57
106
  var __defProp2 = Object.defineProperty;
@@ -2551,22 +2600,22 @@ var GameVfxThree = (() => {
2551
2600
  )
2552
2601
  ]
2553
2602
  };
2554
- function normalized(vector) {
2555
- const length = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]) || 1;
2603
+ function normalized(vector2) {
2604
+ const length = Math.sqrt(vector2[0] * vector2[0] + vector2[1] * vector2[1] + vector2[2] * vector2[2]) || 1;
2556
2605
  const inverse = 1 / length;
2557
- return [vector[0] * inverse, vector[1] * inverse, vector[2] * inverse];
2606
+ return [vector2[0] * inverse, vector2[1] * inverse, vector2[2] * inverse];
2558
2607
  }
2559
- function plus(vector, x, y, z) {
2560
- return [vector[0] + x, vector[1] + y, vector[2] + z];
2608
+ function plus(vector2, x, y, z) {
2609
+ return [vector2[0] + x, vector2[1] + y, vector2[2] + z];
2561
2610
  }
2562
- function scaledBy(vector, factor) {
2563
- return [vector[0] * factor, vector[1] * factor, vector[2] * factor];
2611
+ function scaledBy(vector2, factor) {
2612
+ return [vector2[0] * factor, vector2[1] * factor, vector2[2] * factor];
2564
2613
  }
2565
- function plusScaled(vector, direction, factor) {
2566
- return [vector[0] + direction[0] * factor, vector[1] + direction[1] * factor, vector[2] + direction[2] * factor];
2614
+ function plusScaled(vector2, direction, factor) {
2615
+ return [vector2[0] + direction[0] * factor, vector2[1] + direction[1] * factor, vector2[2] + direction[2] * factor];
2567
2616
  }
2568
- function negated(vector) {
2569
- return [-vector[0], -vector[1], -vector[2]];
2617
+ function negated(vector2) {
2618
+ return [-vector2[0], -vector2[1], -vector2[2]];
2570
2619
  }
2571
2620
  var FRAME_DUST = normalized([0, -0.3, 1]);
2572
2621
  var SPLINTER_DIRECTION = normalized([0, 0.3, 1]);
@@ -3869,9 +3918,32 @@ var GameVfxThree = (() => {
3869
3918
  /** 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. */
3870
3919
  aliasOf(FUEL_LEAK, "vehicle_leak_ignited", {})
3871
3920
  ];
3921
+ var vector = [variable("vx"), variable("vy"), variable("vz")];
3922
+ var range = (name) => [variable(name), variable(name)];
3923
+ var singleParticle = (id, system) => ({
3924
+ id,
3925
+ pageId: `particle:${id}`,
3926
+ team: "world",
3927
+ budget: { particles: 1, lights: 0 },
3928
+ loop: 1e-3,
3929
+ timeline: [
3930
+ spawn(system, {
3931
+ p: [0, 0, 0],
3932
+ v: vector,
3933
+ life: range("life"),
3934
+ size: range("size"),
3935
+ grow: variable("grow"),
3936
+ c0: variable("color"),
3937
+ a: variable("alpha"),
3938
+ g: variable("gravity"),
3939
+ drag: variable("drag")
3940
+ })
3941
+ ]
3942
+ });
3943
+ var SINGLE_PARTICLE_EFFECTS = [singleParticle("particle_puff", "normal"), singleParticle("particle_glow", "add"), singleParticle("particle_streak", "streak")];
3872
3944
  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];
3873
3945
  var WORKSHOP_EFFECTS = Object.fromEntries(ALL_EFFECTS.map((effect) => [effect.id, effect]));
3874
- var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS].map((effect) => [effect.id, effect])) };
3946
+ var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS, ...SINGLE_PARTICLE_EFFECTS].map((effect) => [effect.id, effect])) };
3875
3947
  var TABLE = {
3876
3948
  concrete: { dust: 9078138, chip: 7236195, spark: 2 },
3877
3949
  metal: { dust: 0, chip: 0, spark: 18 },
@@ -4541,8 +4613,8 @@ var GameVfxThree = (() => {
4541
4613
  var UP12 = [0, 1, 0];
4542
4614
  var ZERO = [0, 0, 0];
4543
4615
  var FULL_TURN_DRAWN = 6.283;
4544
- function scaledSizes(range, factor) {
4545
- return [range[0] * Math.sqrt(factor), range[1] * Math.sqrt(factor)];
4616
+ function scaledSizes(range2, factor) {
4617
+ return [range2[0] * Math.sqrt(factor), range2[1] * Math.sqrt(factor)];
4546
4618
  }
4547
4619
  function fireEmit(engine, key, dt, centre, radius, factor, options = {}) {
4548
4620
  const wind = options.wind ?? ZERO;
@@ -6396,9 +6468,9 @@ var GameVfxThree = (() => {
6396
6468
  var TWO_PI_ROUNDED = 6.2832;
6397
6469
  var WIDE_CONE = 3.1;
6398
6470
  var UP13 = [0, 1, 0];
6399
- function drawRange(random, range) {
6400
- if (Array.isArray(range)) return random.between(range[0], range[1]);
6401
- return range || 0;
6471
+ function drawRange(random, range2) {
6472
+ if (Array.isArray(range2)) return random.between(range2[0], range2[1]);
6473
+ return range2 || 0;
6402
6474
  }
6403
6475
  function randomUnit(random, out) {
6404
6476
  const up = random.next() * 2 - 1;
@@ -7165,13 +7237,13 @@ var GameVfxThree = (() => {
7165
7237
  return [origin[0] + cos2 * x + sin2 * z, origin[1] + point[1] - anchor[1], origin[2] - sin2 * x + cos2 * z];
7166
7238
  }
7167
7239
  /** A direction or velocity of the recipe's space in the world. */
7168
- turn(vector) {
7240
+ turn(vector2) {
7169
7241
  const placement = this.placement;
7170
- if (!placement) return vector;
7171
- if (placement.orientation) return rotate(placement.orientation, vector);
7242
+ if (!placement) return vector2;
7243
+ if (placement.orientation) return rotate(placement.orientation, vector2);
7172
7244
  const cos2 = Math.cos(placement.yaw);
7173
7245
  const sin2 = Math.sin(placement.yaw);
7174
- return [cos2 * vector[0] + sin2 * vector[2], vector[1], -sin2 * vector[0] + cos2 * vector[2]];
7246
+ return [cos2 * vector2[0] + sin2 * vector2[2], vector2[1], -sin2 * vector2[0] + cos2 * vector2[2]];
7175
7247
  }
7176
7248
  placed(options) {
7177
7249
  if (!this.placement) return options;
@@ -8631,9 +8703,42 @@ void main(){
8631
8703
  };
8632
8704
  }
8633
8705
 
8706
+ // ../game-render-three/dist/index.js
8707
+ var DEFAULT_ANGLE = Math.PI / 3;
8708
+ var LIGHT_PRIORITY = {
8709
+ blast: 900,
8710
+ rocket: 800,
8711
+ muzzle: 750,
8712
+ fire: 600,
8713
+ flare: 500,
8714
+ headlight: 400,
8715
+ weaponLight: 400,
8716
+ lamp: 200,
8717
+ street: 150
8718
+ };
8719
+ var EFFECT_STEP_SECONDS = 1 / 50;
8720
+
8634
8721
  // src/lights.ts
8635
- function createLightLayer(THREE, pool, scale) {
8722
+ var LIGHT_ON_THRESHOLD = 0.05;
8723
+ var FIRE_COLOR = 16742954;
8724
+ var FIRE_DECAY = 2;
8725
+ var BLAST_DECAY = 2;
8726
+ function followEntry(budget, handles, index, entry, request) {
8727
+ const handle = handles[index] ?? null;
8728
+ if (entry.intensity <= LIGHT_ON_THRESHOLD) {
8729
+ handle?.release({ fadeMs: 0 });
8730
+ handles[index] = null;
8731
+ return;
8732
+ }
8733
+ if (handle?.alive) {
8734
+ handle.update({ color: request.color, intensity: request.intensity, distance: request.distance, position: request.position });
8735
+ return;
8736
+ }
8737
+ handles[index] = budget.acquire(request);
8738
+ }
8739
+ function createLightLayer(THREE, pool, scale, budget) {
8636
8740
  const group = new THREE.Group();
8741
+ if (budget) return createBudgetedLightLayer(group, pool, scale, budget);
8637
8742
  const blast = pool.blast.map(() => {
8638
8743
  const light = new THREE.PointLight(16752720, 0, 30, 2);
8639
8744
  light.position.set(0, -50, 0);
@@ -8672,6 +8777,30 @@ void main(){
8672
8777
  }
8673
8778
  };
8674
8779
  }
8780
+ function createBudgetedLightLayer(group, pool, scale, budget) {
8781
+ const blast = pool.blast.map(() => null);
8782
+ const fire = pool.fire.map(() => null);
8783
+ return {
8784
+ group,
8785
+ sync() {
8786
+ let lit = 0;
8787
+ pool.blast.forEach((entry, index) => {
8788
+ const request = { owner: "vfx.blast", priority: LIGHT_PRIORITY.blast, urgent: true, color: entry.color, intensity: entry.intensity * scale, distance: entry.distance, decay: BLAST_DECAY, position: [entry.x, entry.y, entry.z] };
8789
+ followEntry(budget, blast, index, entry, request);
8790
+ if (entry.intensity > LIGHT_ON_THRESHOLD) lit++;
8791
+ });
8792
+ pool.fire.forEach((entry, index) => {
8793
+ const request = { owner: "vfx.fire", priority: LIGHT_PRIORITY.fire, color: FIRE_COLOR, intensity: entry.intensity * scale, distance: entry.distance, decay: FIRE_DECAY, position: [entry.x, entry.y, entry.z] };
8794
+ followEntry(budget, fire, index, entry, request);
8795
+ if (entry.intensity > LIGHT_ON_THRESHOLD) lit++;
8796
+ });
8797
+ return lit;
8798
+ },
8799
+ dispose() {
8800
+ for (const handle of [...blast, ...fire]) handle?.release({ fadeMs: 0 });
8801
+ }
8802
+ };
8803
+ }
8675
8804
 
8676
8805
  // src/canvas.ts
8677
8806
  var SCORCH_SEED = 5;
@@ -8809,6 +8938,7 @@ void main(){
8809
8938
  group.add(mesh2);
8810
8939
  return mesh2;
8811
8940
  }
8941
+ let probeGeometry;
8812
8942
  const groundMarks = [];
8813
8943
  const spareGeometries = [];
8814
8944
  const blood = [];
@@ -8914,6 +9044,15 @@ void main(){
8914
9044
  rockMesh();
8915
9045
  plateMesh();
8916
9046
  },
9047
+ probes() {
9048
+ probeGeometry ?? (probeGeometry = new THREE.PlaneGeometry(1e-3, 1e-3).rotateX(-Math.PI / 2));
9049
+ return [...scorchMaterials, dirtMaterial].map((material) => {
9050
+ const mesh2 = new THREE.Mesh(probeGeometry, material);
9051
+ mesh2.receiveShadow = true;
9052
+ mesh2.frustumCulled = false;
9053
+ return mesh2;
9054
+ });
9055
+ },
8917
9056
  update(dt) {
8918
9057
  for (let index = 0; index < blood.length; index++) {
8919
9058
  const drawn = blood[index];
@@ -8926,6 +9065,7 @@ void main(){
8926
9065
  dispose() {
8927
9066
  clearMarks();
8928
9067
  for (const mesh2 of [instanced.blood, instanced.rock, instanced.plate]) mesh2?.dispose();
9068
+ probeGeometry?.dispose();
8929
9069
  for (const item of owned) item.dispose();
8930
9070
  }
8931
9071
  };
@@ -9517,7 +9657,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
9517
9657
  }
9518
9658
  };
9519
9659
  }
9520
- function createWorkshopLayers(THREE, engine, pointScale, lightScale) {
9660
+ function createWorkshopLayers(THREE, engine, pointScale, lightScale, budget) {
9521
9661
  const group = new THREE.Group();
9522
9662
  group.name = "workshop";
9523
9663
  const layers = [
@@ -9532,15 +9672,30 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
9532
9672
  for (const layer2 of layers) group.add(layer2.object);
9533
9673
  const meshes = createMeshLayer(THREE, engine.meshes);
9534
9674
  group.add(meshes.group);
9535
- const flashLights = engine.lights.lights.map(() => new THREE.PointLight(16760944, 0, 14));
9536
- const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE));
9537
- for (const light of [...flashLights, ...fireLights]) group.add(light);
9675
+ const lights = budget ? budgetedLights(engine, lightScale, budget) : legacyLights(THREE, engine, lightScale, group);
9538
9676
  return {
9539
9677
  group,
9540
9678
  sync() {
9541
9679
  let drawCalls = 0;
9542
9680
  for (const layer2 of layers) if (layer2.sync()) drawCalls++;
9543
9681
  drawCalls += meshes.sync();
9682
+ lights.sync();
9683
+ return drawCalls;
9684
+ },
9685
+ dispose() {
9686
+ for (const layer2 of layers) layer2.dispose();
9687
+ meshes.dispose();
9688
+ lights.dispose();
9689
+ group.clear();
9690
+ }
9691
+ };
9692
+ }
9693
+ function legacyLights(THREE, engine, lightScale, group) {
9694
+ const flashLights = engine.lights.lights.map(() => new THREE.PointLight(16760944, 0, 14));
9695
+ const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE));
9696
+ for (const light of [...flashLights, ...fireLights]) group.add(light);
9697
+ return {
9698
+ sync() {
9544
9699
  engine.lights.lights.forEach((source, index) => {
9545
9700
  const light = flashLights[index];
9546
9701
  light.position.set(source.x, source.y, source.z);
@@ -9553,12 +9708,27 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
9553
9708
  light.position.set(source.x, source.y, source.z);
9554
9709
  light.intensity = source.intensity * lightScale;
9555
9710
  });
9556
- return drawCalls;
9557
9711
  },
9558
9712
  dispose() {
9559
- for (const layer2 of layers) layer2.dispose();
9560
- meshes.dispose();
9561
- group.clear();
9713
+ }
9714
+ };
9715
+ }
9716
+ function budgetedLights(engine, lightScale, budget) {
9717
+ const flash2 = engine.lights.lights.map(() => null);
9718
+ const fire = engine.lights.fire.map(() => null);
9719
+ return {
9720
+ sync() {
9721
+ engine.lights.lights.forEach((source, index) => {
9722
+ const request = { owner: "vfx.workshop", priority: LIGHT_PRIORITY.blast, urgent: true, color: source.color, intensity: source.intensity * lightScale, distance: source.distance, position: [source.x, source.y, source.z] };
9723
+ followEntry(budget, flash2, index, source, request);
9724
+ });
9725
+ engine.lights.fire.forEach((source, index) => {
9726
+ const request = { owner: "vfx.workshop", priority: LIGHT_PRIORITY.fire, color: FIRE_LIGHT_COLOR, intensity: source.intensity * lightScale, distance: FIRE_LIGHT_DISTANCE, position: [source.x, source.y, source.z] };
9727
+ followEntry(budget, fire, index, source, request);
9728
+ });
9729
+ },
9730
+ dispose() {
9731
+ for (const handle of [...flash2, ...fire]) handle?.release({ fadeMs: 0 });
9562
9732
  }
9563
9733
  };
9564
9734
  }
@@ -9619,7 +9789,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
9619
9789
  const chunks = createChunkLayer(THREE, pools.chunks, { rock: rockGeometry, plate: plateGeometry }, colorOfChunk);
9620
9790
  const shocks = createShockLayer(THREE, pools.shocks);
9621
9791
  const sprites = createSpriteLayer(THREE, world.sprites(), options.pointScale ?? 700);
9622
- const lights = createLightLayer(THREE, pools.lights, options.lightScale ?? Math.PI);
9792
+ const lights = createLightLayer(THREE, pools.lights, options.lightScale ?? Math.PI, options.lights);
9623
9793
  const marks = createMarkLayer(THREE, { ground: pools.ground, createCanvas: options.createCanvas, rockGeometry, plateGeometry, ...options.markLimits });
9624
9794
  root.add(puffs.mesh, sparks.mesh, glows.mesh, chunks.rocks, chunks.plates, shocks.group, lights.group, sprites.additive, sprites.normal, marks.group);
9625
9795
  const stopMarks = world.onMarks((event) => marks.handle(event));
@@ -9652,7 +9822,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
9652
9822
  workshopLayers?.dispose();
9653
9823
  if (workshopLayers) root.remove(workshopLayers.group);
9654
9824
  workshopEngine = engine;
9655
- workshopLayers = createWorkshopLayers(THREE, engine, options.pointScale ?? 700, 1);
9825
+ workshopLayers = createWorkshopLayers(THREE, engine, options.pointScale ?? 700, 1, options.lights);
9656
9826
  root.add(workshopLayers.group);
9657
9827
  applyLayers();
9658
9828
  }
@@ -9725,7 +9895,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
9725
9895
  const meshes = createMeshLayerProbes(THREE);
9726
9896
  for (const mesh2 of meshes) mesh2.frustumCulled = false;
9727
9897
  const group = new THREE.Group();
9728
- group.add(...meshes);
9898
+ group.add(...meshes, ...marks.probes());
9729
9899
  anchors = { meshes, group };
9730
9900
  return { group, dispose: () => {
9731
9901
  } };