@adatechnology/game-test-room 0.8.0 → 0.10.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.js CHANGED
@@ -322,6 +322,16 @@ var en = {
322
322
  "ui.slow": "Slow motion 0.25\xD7",
323
323
  "ui.fast": "Time \xD710",
324
324
  "ui.tap": "Tap",
325
+ "ui.blast.shelter": "Shelter",
326
+ "ui.blast.fragmentHits": "Fragments",
327
+ "ui.blast.confinement": "Confinement",
328
+ "ui.blast.shelter.hint": "Blasts: walls and other parts between the blast and the target take their share",
329
+ "ui.blast.fragmentHits.hint": "Blasts: the pieces of what breaks fly on and hit what is behind",
330
+ "ui.blast.confinement.hint": "Blasts: pressure builds up in an enclosed room",
331
+ "metric.blast_shelter": "Blast reaching (%)",
332
+ "metric.blast_confinement": "Blast pressure (x)",
333
+ "metric.blast_fragments": "Fragment hits",
334
+ "act.blast_report": "Blast: {shelter}% reached the most sheltered target, pressure x{confinement}, {fragments} fragment hits, {n} targets",
325
335
  "ui.quality": "Quality",
326
336
  "ui.quality.low": "low",
327
337
  "ui.quality.medium": "medium",
@@ -647,6 +657,16 @@ var ptBR = {
647
657
  "ui.slow": "C\xE2mera lenta 0,25\xD7",
648
658
  "ui.fast": "Tempo \xD710",
649
659
  "ui.tap": "Torneira",
660
+ "ui.blast.shelter": "Abrigo",
661
+ "ui.blast.fragmentHits": "Estilha\xE7os",
662
+ "ui.blast.confinement": "Confinamento",
663
+ "ui.blast.shelter.hint": "Explos\xF5es: paredes e outras partes entre a explos\xE3o e o alvo ficam com a sua parte",
664
+ "ui.blast.fragmentHits.hint": "Explos\xF5es: os peda\xE7os do que quebra voam e acertam o que est\xE1 atr\xE1s",
665
+ "ui.blast.confinement.hint": "Explos\xF5es: a press\xE3o sobe num ambiente fechado",
666
+ "metric.blast_shelter": "Explos\xE3o que chegou (%)",
667
+ "metric.blast_confinement": "Press\xE3o da explos\xE3o (x)",
668
+ "metric.blast_fragments": "Estilha\xE7os que acertaram",
669
+ "act.blast_report": "Explos\xE3o: {shelter}% chegou ao alvo mais abrigado, press\xE3o x{confinement}, {fragments} estilha\xE7os acertaram, {n} alvos",
650
670
  "ui.quality": "Qualidade",
651
671
  "ui.quality.low": "baixa",
652
672
  "ui.quality.medium": "m\xE9dia",
@@ -1372,6 +1392,16 @@ var segmentTouchesBox = (from, to, min, max) => {
1372
1392
 
1373
1393
  // src/explosives.ts
1374
1394
  var CONE_BLAST_RADIUS = 0.5;
1395
+ var summarizeBlast = (results) => {
1396
+ const reports = results.flatMap((r) => r.blast ? [r.blast] : []);
1397
+ if (reports.length === 0) return void 0;
1398
+ return {
1399
+ shelter: Math.min(...reports.map((r) => r.shelter)),
1400
+ confinement: reports[0].confinement,
1401
+ fragmentHits: reports.reduce((n, r) => n + r.fragmentHits, 0),
1402
+ targets: reports.length
1403
+ };
1404
+ };
1375
1405
  var toArray = (vector) => [vector.x, vector.y, vector.z];
1376
1406
  function createExplosives(context) {
1377
1407
  const { THREE, scene, camera, world, renderer, arsenal, translate, format, action } = context;
@@ -1518,17 +1548,27 @@ function createExplosives(context) {
1518
1548
  if (box2.isEmpty()) box2.expandByPoint(object.position);
1519
1549
  const at = mostExposedPoint(box2, detonation);
1520
1550
  if (!at) continue;
1521
- reached += world.explode(at, detonation.energy * blastEffect(detonation, at).falloff, CONE_BLAST_RADIUS, "player").length;
1551
+ const results = world.explode(at, detonation.energy * blastEffect(detonation, at).falloff, CONE_BLAST_RADIUS, "player", context.blast());
1552
+ reached += results.length;
1553
+ told(results);
1522
1554
  }
1523
1555
  return reached;
1524
1556
  };
1557
+ const told = (results) => {
1558
+ const summary = summarizeBlast(results);
1559
+ if (!summary) return;
1560
+ context.blasted(summary);
1561
+ action("blast_report", translate("act.blast_report", { shelter: format(summary.shelter * 100, 0), confinement: format(summary.confinement, 2), fragments: summary.fragmentHits, n: summary.targets }), { data: { ...summary } });
1562
+ };
1525
1563
  const detonate = (projectile, detonation) => {
1526
1564
  const weaponName = context.toolName(projectile.weapon);
1527
1565
  const reach = Math.max(detonation.injuryRadius, detonation.lethalRadius);
1528
- const reached = detonation.energy <= 0 ? 0 : detonation.cone ? coneBlast(detonation) : world.explode(detonation.point, detonation.energy, reach, "player").length;
1566
+ const results = detonation.energy <= 0 || detonation.cone ? [] : world.explode(detonation.point, detonation.energy, reach, "player", context.blast());
1567
+ const reached = detonation.energy <= 0 ? 0 : detonation.cone ? coneBlast(detonation) : results.length;
1568
+ if (!detonation.cone) told(results);
1529
1569
  if (detonation.energy > 0) {
1530
1570
  const isPlayed = context.effects.explosion(detonation.explosive, detonation.point, { direction: detonation.direction }) !== null;
1531
- renderer.explode(detonation.point, detonation.energy, reach, { visual: !isPlayed });
1571
+ renderer.explode(detonation.point, detonation.energy, reach, { visual: !isPlayed, report: results });
1532
1572
  }
1533
1573
  if (detonation.stunSeconds !== void 0) renderer.emit("flash", detonation.point, [0, 1, 0], 1, 1);
1534
1574
  const onPlayer = blastEffect(detonation, toArray(camera.position));
@@ -1825,7 +1865,7 @@ function createLog(options = {}) {
1825
1865
  }
1826
1866
 
1827
1867
  // src/metrics.ts
1828
- var ROOM_METRICS = ["fps", "frame_ms", "draw_calls", "triangles", "objects", "fragments", "particles", "decals"];
1868
+ var ROOM_METRICS = ["fps", "frame_ms", "draw_calls", "triangles", "objects", "fragments", "particles", "decals", "blast_shelter", "blast_confinement", "blast_fragments"];
1829
1869
  var WINDOW_S = 0.5;
1830
1870
  function createRoomMetrics(sources) {
1831
1871
  const wanted = new Set(sources.ids);
@@ -1862,6 +1902,12 @@ function createRoomMetrics(sources) {
1862
1902
  const render = ownsRender ? { calls, triangles } : gl.info?.render;
1863
1903
  put("draw_calls", render?.calls);
1864
1904
  put("triangles", render?.triangles);
1905
+ const blast = sources.blast?.();
1906
+ if (blast) {
1907
+ put("blast_shelter", blast.shelter * 100);
1908
+ put("blast_confinement", blast.confinement);
1909
+ put("blast_fragments", blast.fragmentHits);
1910
+ }
1865
1911
  if (!["objects", "fragments", "particles", "decals"].some((id) => wanted.has(id))) return out;
1866
1912
  const destruction = sources.destruction.stats();
1867
1913
  const fluids = sources.fluids.stats();
@@ -2415,6 +2461,9 @@ function createPlayer(THREE, o) {
2415
2461
  const blocked = (x, z) => {
2416
2462
  if (Math.abs(x) > o.limit - PLAYER_RADIUS || Math.abs(z) > o.limit - PLAYER_RADIUS) return true;
2417
2463
  for (const c of o.colliders) if (x > c[0] - PLAYER_RADIUS && x < c[2] + PLAYER_RADIUS && z > c[1] - PLAYER_RADIUS && z < c[3] + PLAYER_RADIUS) return true;
2464
+ if (o.blockers) {
2465
+ for (const blocked2 of o.blockers) if (blocked2(x, z, PLAYER_RADIUS)) return true;
2466
+ }
2418
2467
  return false;
2419
2468
  };
2420
2469
  const move = (dx, dz) => {
@@ -3544,6 +3593,8 @@ function createUi(o) {
3544
3593
  o.onFast(fast);
3545
3594
  });
3546
3595
  const tapBtn = ctl(t("ui.tap"), () => o.onTap());
3596
+ const blastBtns = ["shelter", "fragmentHits", "confinement"].map((key) => ({ key, b: ctl(t(`ui.blast.${key}`), () => o.onBlast(key)) }));
3597
+ for (const { key, b } of blastBtns) b.title = t(`ui.blast.${key}.hint`);
3547
3598
  const qSel = mk2("select");
3548
3599
  for (const q of ["low", "medium", "high"]) {
3549
3600
  const op = mk2("option", void 0, t(`ui.quality.${q}`));
@@ -3748,6 +3799,7 @@ function createUi(o) {
3748
3799
  }
3749
3800
  slotsEl.forEach((b, i) => b.classList.toggle("on", i === s.slot));
3750
3801
  tapBtn.classList.toggle("on", s.tap);
3802
+ for (const { key: key2, b } of blastBtns) b.classList.toggle("on", s.blast[key2]);
3751
3803
  count.textContent = t("ui.objects", { n: s.objects });
3752
3804
  const ak = JSON.stringify(s.animations);
3753
3805
  if (ak !== lastAnim) {
@@ -4061,10 +4113,12 @@ function createTestRoom(options) {
4061
4113
  log.setBeforeRead(flush);
4062
4114
  let useHeld = false;
4063
4115
  let useFirst = false;
4116
+ const blockers = /* @__PURE__ */ new Set();
4064
4117
  const player = createPlayer(THREE, {
4065
4118
  camera,
4066
4119
  dom,
4067
4120
  colliders: arena.colliders,
4121
+ blockers,
4068
4122
  limit: arenaSize,
4069
4123
  start: arena.playerStart,
4070
4124
  hooks: {
@@ -4247,8 +4301,10 @@ function createTestRoom(options) {
4247
4301
  film.clear();
4248
4302
  fluids.setTap(TAP_ID, false);
4249
4303
  };
4304
+ const clearListeners = /* @__PURE__ */ new Set();
4250
4305
  const clear = () => {
4251
4306
  clearEverything();
4307
+ for (const listener of [...clearListeners]) listener();
4252
4308
  restingTops.length = 0;
4253
4309
  pending = [];
4254
4310
  action("clear", t("act.clear"));
@@ -4629,6 +4685,12 @@ function createTestRoom(options) {
4629
4685
  bodies.push({ id: "player", box: new THREE.Box3(new THREE.Vector3(x - PLAYER_RADIUS, feet, z - PLAYER_RADIUS), new THREE.Vector3(x + PLAYER_RADIUS, y + 0.1, z + PLAYER_RADIUS)) });
4630
4686
  return bodies;
4631
4687
  }
4688
+ let blastOptions = { ...options.blast };
4689
+ let lastBlast;
4690
+ const blastOn = (key) => Boolean(blastOptions[key]);
4691
+ const toggleBlast = (key) => {
4692
+ blastOptions = { ...blastOptions, [key]: blastOn(key) ? false : true };
4693
+ };
4632
4694
  const explosives = createExplosives({
4633
4695
  THREE,
4634
4696
  scene,
@@ -4643,6 +4705,10 @@ function createTestRoom(options) {
4643
4705
  toolName,
4644
4706
  withoutHeld,
4645
4707
  groundAt,
4708
+ blast: () => blastOptions,
4709
+ blasted: (summary) => {
4710
+ lastBlast = summary;
4711
+ },
4646
4712
  translate: t,
4647
4713
  format: num,
4648
4714
  action,
@@ -5069,7 +5135,7 @@ function createTestRoom(options) {
5069
5135
  let metricsAcc = 0;
5070
5136
  let ownsLoop = false;
5071
5137
  const roomMetricIds = options.metrics === false ? [] : options.metrics ?? ROOM_METRICS;
5072
- const roomMetrics = createRoomMetrics({ gl, destruction: renderer, fluids: fluidView, effects: vfx.world, ids: roomMetricIds });
5138
+ const roomMetrics = createRoomMetrics({ gl, destruction: renderer, fluids: fluidView, effects: vfx.world, ids: roomMetricIds, blast: () => lastBlast });
5073
5139
  let qualityName = quality;
5074
5140
  const syncContainers = (sdt) => {
5075
5141
  for (const e of entries.values()) {
@@ -5188,6 +5254,7 @@ function createTestRoom(options) {
5188
5254
  timeScale,
5189
5255
  fast: fastForward,
5190
5256
  tap: isTapOn(),
5257
+ blast: { shelter: blastOn("shelter"), fragmentHits: blastOn("fragmentHits"), confinement: blastOn("confinement") },
5191
5258
  quality: qualityName,
5192
5259
  objects: [...entries.values()].filter((e) => !e.arena).length
5193
5260
  };
@@ -5436,6 +5503,14 @@ function createTestRoom(options) {
5436
5503
  },
5437
5504
  log(text, data) {
5438
5505
  action("module_note", text, { data });
5506
+ },
5507
+ addBlocker(blocked) {
5508
+ blockers.add(blocked);
5509
+ return () => blockers.delete(blocked);
5510
+ },
5511
+ onClear(listener) {
5512
+ clearListeners.add(listener);
5513
+ return () => clearListeners.delete(listener);
5439
5514
  }
5440
5515
  };
5441
5516
  const lendBench = (store) => ({
@@ -5703,6 +5778,10 @@ function createTestRoom(options) {
5703
5778
  heldTilt = rad;
5704
5779
  },
5705
5780
  toggleTap,
5781
+ blast: () => ({ ...blastOptions }),
5782
+ setBlast: (next) => {
5783
+ blastOptions = { ...blastOptions, ...next };
5784
+ },
5706
5785
  pause() {
5707
5786
  paused = true;
5708
5787
  },
@@ -5813,6 +5892,7 @@ function createTestRoom(options) {
5813
5892
  setTool(loadout[index]);
5814
5893
  },
5815
5894
  onTap: () => toggleTap(),
5895
+ onBlast: (key) => toggleBlast(key),
5816
5896
  onPlay: (objectId, clipId) => {
5817
5897
  playAnimation(clipId, objectId);
5818
5898
  },