@adatechnology/game-test-room 0.13.0 → 0.15.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/README.md +16 -0
- package/dist/index.d.ts +165 -17
- package/dist/index.global.js +558 -98
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +510 -92
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.global.js
CHANGED
|
@@ -23,20 +23,26 @@ var GameTestRoom = (() => {
|
|
|
23
23
|
__export(index_exports, {
|
|
24
24
|
DEFAULT_HAND_STANCES: () => DEFAULT_HAND_STANCES,
|
|
25
25
|
DEFAULT_STRIKE_CLIPS: () => DEFAULT_STRIKE_CLIPS,
|
|
26
|
+
DEFAULT_TRIALS: () => DEFAULT_TRIALS,
|
|
26
27
|
LOADING_CLASS: () => LOADING_CLASS,
|
|
27
28
|
LOADING_CSS: () => LOADING_CSS,
|
|
28
29
|
MATERIAL_COLORS: () => MATERIAL_COLORS,
|
|
30
|
+
TRIAL_KINDS: () => TRIAL_KINDS,
|
|
29
31
|
brickWallSpec: () => brickWallSpec,
|
|
30
32
|
buildFromSpec: () => buildFromSpec,
|
|
31
33
|
createLoading: () => createLoading,
|
|
32
34
|
createLog: () => createLog,
|
|
33
35
|
createTestRoom: () => createTestRoom,
|
|
36
|
+
createTestTable: () => createTestTable,
|
|
34
37
|
decodeBenchState: () => decodeBenchState,
|
|
35
38
|
encodeBenchState: () => encodeBenchState,
|
|
39
|
+
fitRow: () => fitRow,
|
|
36
40
|
loadingMarkup: () => loadingMarkup,
|
|
37
41
|
locales: () => locales4,
|
|
38
42
|
nextPaint: () => nextPaint,
|
|
39
|
-
resolveStrings: () => resolveStrings5
|
|
43
|
+
resolveStrings: () => resolveStrings5,
|
|
44
|
+
rowCentres: () => rowCentres,
|
|
45
|
+
trialView: () => trialView
|
|
40
46
|
});
|
|
41
47
|
|
|
42
48
|
// ../game-contracts/dist/index.js
|
|
@@ -469,6 +475,13 @@ var GameTestRoom = (() => {
|
|
|
469
475
|
}
|
|
470
476
|
};
|
|
471
477
|
}
|
|
478
|
+
var KIT_ORIGIN_KEY = "kitOrigin";
|
|
479
|
+
function markKitOrigin(object, origin) {
|
|
480
|
+
const node = object;
|
|
481
|
+
node.userData = node.userData ?? {};
|
|
482
|
+
node.userData[KIT_ORIGIN_KEY] = { ...origin };
|
|
483
|
+
return object;
|
|
484
|
+
}
|
|
472
485
|
|
|
473
486
|
// ../game-destruction/dist/index.js
|
|
474
487
|
var FIRE_PRIME_C = 300;
|
|
@@ -799,6 +812,23 @@ var GameTestRoom = (() => {
|
|
|
799
812
|
return angle === 0 ? q : quat.mul(q, quat.fromAxisAngle([0, 0, 1], angle));
|
|
800
813
|
};
|
|
801
814
|
var clamp = (v, a, b) => Math.max(a, Math.min(b, v));
|
|
815
|
+
var tearStack = (inp, root, t, u, v, n, sheet) => {
|
|
816
|
+
const { dims, rnd: rnd2, maxFragments } = inp;
|
|
817
|
+
const layers = clamp(Math.ceil(dims[t] / STACK_LAYER), 2, 4);
|
|
818
|
+
const per = clamp(n, 3, Math.max(3, Math.floor(maxFragments / layers)));
|
|
819
|
+
const out = [];
|
|
820
|
+
for (let k = 0; k < layers; k++) {
|
|
821
|
+
const off = -dims[t] / 2 + (k + 0.5) * dims[t] / layers;
|
|
822
|
+
for (const b of bsp(root, per, [u, v], rnd2)) {
|
|
823
|
+
if (out.length >= maxFragments) return out;
|
|
824
|
+
const c = [b.c[0], b.c[1], b.c[2]];
|
|
825
|
+
c[t] = off;
|
|
826
|
+
out.push({ center: c, size: [b.s[u], b.s[v], sheet], q: frame(u, v, t, (rnd2() - 0.5) * 0.8), shape: "scrap", weight: b.s[u] * b.s[v], inner: out.length % 4 !== 0 });
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return out;
|
|
830
|
+
};
|
|
831
|
+
var STACK_LAYER = 0.012;
|
|
802
832
|
var planFragments = (inp) => {
|
|
803
833
|
const { style, dims, rnd: rnd2, maxFragments } = inp;
|
|
804
834
|
const [fmin, fmax] = inp.fragmentSize;
|
|
@@ -841,6 +871,8 @@ var GameTestRoom = (() => {
|
|
|
841
871
|
}
|
|
842
872
|
if (style === "tear") {
|
|
843
873
|
const n2 = clamp(Math.round(dims[u] * dims[v] / (mean * mean)), 3, maxFragments);
|
|
874
|
+
const sheet = inp.sheet ?? 0;
|
|
875
|
+
if (sheet > 0 && dims[t] > sheet * 4) return tearStack(inp, root, t, u, v, n2, sheet);
|
|
844
876
|
const th2 = Math.min(inp.thickness, dims[t]);
|
|
845
877
|
for (const b of bsp(root, n2, [u, v], rnd2)) {
|
|
846
878
|
out.push({ center: [b.c[0], b.c[1], b.c[2]], size: [b.s[u], b.s[v], th2], q: frame(u, v, t), shape: "scrap", weight: b.s[u] * b.s[v] });
|
|
@@ -2413,6 +2445,7 @@ var GameTestRoom = (() => {
|
|
|
2413
2445
|
0.03,
|
|
2414
2446
|
0.15
|
|
2415
2447
|
],
|
|
2448
|
+
sheet: 1e-3,
|
|
2416
2449
|
damageScale: {
|
|
2417
2450
|
slash: 3
|
|
2418
2451
|
},
|
|
@@ -2428,7 +2461,8 @@ var GameTestRoom = (() => {
|
|
|
2428
2461
|
smoke: "grey"
|
|
2429
2462
|
},
|
|
2430
2463
|
visual: {
|
|
2431
|
-
charColor: 1709072
|
|
2464
|
+
charColor: 1709072,
|
|
2465
|
+
innerColor: 15524048
|
|
2432
2466
|
},
|
|
2433
2467
|
tags: [
|
|
2434
2468
|
"fabric",
|
|
@@ -4146,7 +4180,8 @@ var GameTestRoom = (() => {
|
|
|
4146
4180
|
hit: hitLocal,
|
|
4147
4181
|
fragmentSize: p.mat.fragmentSize ?? [0.04, 0.2],
|
|
4148
4182
|
maxFragments,
|
|
4149
|
-
rnd: rnd2
|
|
4183
|
+
rnd: rnd2,
|
|
4184
|
+
sheet: p.mat.sheet
|
|
4150
4185
|
});
|
|
4151
4186
|
const holes = p.st.holes.length > 0 ? localHolesOf(p) : [];
|
|
4152
4187
|
const mass = p.st.mass;
|
|
@@ -4170,7 +4205,8 @@ var GameTestRoom = (() => {
|
|
|
4170
4205
|
velocity: [dv[0] * k, dv[1] * k + 0.5 * rnd2(), dv[2] * k],
|
|
4171
4206
|
angularVelocity: [(rnd2() - 0.5) * 12, (rnd2() - 0.5) * 12, (rnd2() - 0.5) * 12],
|
|
4172
4207
|
mass: mass * f.weight / totW,
|
|
4173
|
-
...marks.length > 0 ? { marks } : {}
|
|
4208
|
+
...marks.length > 0 ? { marks } : {},
|
|
4209
|
+
...f.inner ? { inner: true } : {}
|
|
4174
4210
|
};
|
|
4175
4211
|
});
|
|
4176
4212
|
const reinforcement = p.spec.reinforcement;
|
|
@@ -15510,7 +15546,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
15510
15546
|
for (const mesh2 of anchors.meshes) mesh2.material.dispose();
|
|
15511
15547
|
anchors = void 0;
|
|
15512
15548
|
};
|
|
15513
|
-
const root = new THREE.Group();
|
|
15549
|
+
const root = markKitOrigin(new THREE.Group(), { owner: "game-vfx-three", kind: "effect" });
|
|
15514
15550
|
options.scene.add(root);
|
|
15515
15551
|
const direction = new THREE.Vector3(...options.lightDirection ?? LAB_LIGHT_DIRECTION).normalize();
|
|
15516
15552
|
const sky = hexToLinearRgb(SKY_COLOR);
|
|
@@ -15735,6 +15771,9 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
15735
15771
|
const bl = Math.round(ab + ((b & 255) - ab) * t);
|
|
15736
15772
|
return r << 16 | g << 8 | bl;
|
|
15737
15773
|
}
|
|
15774
|
+
var SHEET_MAX = 4e-3;
|
|
15775
|
+
var SHEET_AIR = 2.5;
|
|
15776
|
+
var SHEET_SWAY = 3;
|
|
15738
15777
|
var FragmentSystem = class {
|
|
15739
15778
|
constructor(THREE, o) {
|
|
15740
15779
|
__publicField2(this, "THREE", THREE);
|
|
@@ -15840,7 +15879,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
15840
15879
|
asleep: false,
|
|
15841
15880
|
rest: 0,
|
|
15842
15881
|
fade: 1,
|
|
15843
|
-
dying: false
|
|
15882
|
+
dying: false,
|
|
15883
|
+
air: f.shape === "scrap" && sz[2] <= SHEET_MAX ? SHEET_AIR : 0
|
|
15844
15884
|
};
|
|
15845
15885
|
this.list.push(live);
|
|
15846
15886
|
let alive = this.list.reduce((n, l) => n + (l.dying ? 0 : 1), 0);
|
|
@@ -15924,6 +15964,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
15924
15964
|
}
|
|
15925
15965
|
} else {
|
|
15926
15966
|
f.ang.multiplyScalar(Math.exp(-0.15 * dt));
|
|
15967
|
+
if (f.air > 0) this.flutter(f, dt);
|
|
15927
15968
|
}
|
|
15928
15969
|
if (contact && f.vel.lengthSq() < 4) this.settle(f, dt);
|
|
15929
15970
|
const slow = f.vel.lengthSq() < 0.012 && f.ang.lengthSq() < 0.2;
|
|
@@ -15938,6 +15979,14 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
15938
15979
|
f.still = 0;
|
|
15939
15980
|
}
|
|
15940
15981
|
}
|
|
15982
|
+
/** A sheet in the air: drag slows it to a slow fall, and it sways and turns over as it goes. */
|
|
15983
|
+
flutter(f, dt) {
|
|
15984
|
+
f.vel.multiplyScalar(Math.exp(-f.air * dt));
|
|
15985
|
+
f.vel.x += (this.rng() - 0.5) * SHEET_SWAY * dt;
|
|
15986
|
+
f.vel.z += (this.rng() - 0.5) * SHEET_SWAY * dt;
|
|
15987
|
+
f.ang.x += (this.rng() - 0.5) * SHEET_SWAY * 4 * dt;
|
|
15988
|
+
f.ang.z += (this.rng() - 0.5) * SHEET_SWAY * 4 * dt;
|
|
15989
|
+
}
|
|
15941
15990
|
/** Tip the fragment towards lying on its flattest face. */
|
|
15942
15991
|
settle(f, dt) {
|
|
15943
15992
|
const mesh2 = f.mesh;
|
|
@@ -18218,6 +18267,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
18218
18267
|
const def = pv ? this.world.materials.get(pv.material) : void 0;
|
|
18219
18268
|
if (kind === "smoke") return { color: SMOKE_TONES[def?.thermal.smoke ?? "grey"] };
|
|
18220
18269
|
if (kind === "fibers" || kind === "leaves") {
|
|
18270
|
+
if (def?.visual?.innerColor !== void 0) return { color: def.visual.innerColor };
|
|
18221
18271
|
const c = pv ? this.visuals.baseColorHex(pv.meshes[0] ?? {}) : -1;
|
|
18222
18272
|
return c >= 0 ? { color: c } : void 0;
|
|
18223
18273
|
}
|
|
@@ -18366,7 +18416,8 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
18366
18416
|
for (let i = 0; i < ev.fragments.length; i += step) {
|
|
18367
18417
|
const fr = ev.fragments[i];
|
|
18368
18418
|
const fdef = this.world.materials.get(fr.material);
|
|
18369
|
-
const
|
|
18419
|
+
const tone2 = fr.inner && fdef?.visual?.innerColor !== void 0 ? fdef.visual.innerColor : fdef === def || !fdef ? color : fallbackColor(fr.material, fdef);
|
|
18420
|
+
const mat = this.fragments.materialFor(fr.material, tone2, transparent || fdef?.visual?.transparent === true, opacity);
|
|
18370
18421
|
this.fragments.spawn(fr, mat, ev.object, maxAlive);
|
|
18371
18422
|
}
|
|
18372
18423
|
const up = [0, 1, 0];
|
|
@@ -18384,7 +18435,7 @@ void main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a
|
|
|
18384
18435
|
this.vfx.burst("dust", ev.point, up, 5, 0.8, { color: 11901556 });
|
|
18385
18436
|
break;
|
|
18386
18437
|
case "tear":
|
|
18387
|
-
this.vfx.burst("fibers", ev.point, up, 12 * sizeK, 1.6, { color });
|
|
18438
|
+
this.vfx.burst("fibers", ev.point, up, 12 * sizeK, 1.6, { color: def?.visual?.innerColor ?? color });
|
|
18388
18439
|
break;
|
|
18389
18440
|
case "snap":
|
|
18390
18441
|
this.vfx.burst("chips", ev.point, up, 8 * sizeK, 3);
|
|
@@ -38143,7 +38194,7 @@ void main(){
|
|
|
38143
38194
|
return [...merged.entries()].map(([id, o]) => ({ id, spec: o.spec, position: o.position, rotationY: o.rotationY ?? 0, colors: o.colors, build: o.build, label: o.label, top: o.top, spout: o.spout }));
|
|
38144
38195
|
}
|
|
38145
38196
|
function createArena(THREE, size, scene2, scenery, tapOption) {
|
|
38146
|
-
const group = new THREE.Group();
|
|
38197
|
+
const group = markKitOrigin(new THREE.Group(), { owner: "game-test-room", kind: "room" });
|
|
38147
38198
|
group.name = "test-room-arena";
|
|
38148
38199
|
scene2.background = new THREE.Color(10466504);
|
|
38149
38200
|
group.add(new THREE.HemisphereLight(13624319, 7037527, 0.75));
|
|
@@ -38741,6 +38792,14 @@ void main(){
|
|
|
38741
38792
|
...projectile.fire ? { fire: projectile.fire } : {}
|
|
38742
38793
|
});
|
|
38743
38794
|
};
|
|
38795
|
+
const blastAt = (weapon, explosive, point) => {
|
|
38796
|
+
const def = arsenal.explosives.get(explosive);
|
|
38797
|
+
if (!def) return false;
|
|
38798
|
+
const event = new ExplosiveBody({ explosive: def, origin: point, triggers: ["remote"], rules: arsenal.rules.explosives }).trigger("remote");
|
|
38799
|
+
if (event?.type !== "detonate") return false;
|
|
38800
|
+
detonate({ weapon }, event.detonation);
|
|
38801
|
+
return true;
|
|
38802
|
+
};
|
|
38744
38803
|
const detonateCharges = () => {
|
|
38745
38804
|
let count = 0;
|
|
38746
38805
|
for (const projectile of [...projectiles]) {
|
|
@@ -38832,7 +38891,172 @@ void main(){
|
|
|
38832
38891
|
}
|
|
38833
38892
|
}
|
|
38834
38893
|
};
|
|
38835
|
-
return { throwUse, placeUse, backblastUse, detonateCharges, update, clear };
|
|
38894
|
+
return { throwUse, placeUse, backblastUse, detonateCharges, blastAt, update, clear };
|
|
38895
|
+
}
|
|
38896
|
+
|
|
38897
|
+
// src/test-table.ts
|
|
38898
|
+
var TRIAL_KINDS = ["shot", "punch", "stab", "fire", "blast"];
|
|
38899
|
+
var DEFAULT_TRIALS = {
|
|
38900
|
+
shot: { weapon: "pistol_9mm", distance: 2.5, lift: 0.5 },
|
|
38901
|
+
punch: { weapon: "fists", distance: 0.3, lift: 0.15 },
|
|
38902
|
+
stab: { weapon: "knife", distance: 0.22, lift: 0.1 },
|
|
38903
|
+
fire: { weapon: "flamethrower", distance: 1.6, lift: 0.4, hold: 0.8 },
|
|
38904
|
+
blast: { weapon: "frag_grenade", distance: 0.3, lift: 1, watch: 6 }
|
|
38905
|
+
};
|
|
38906
|
+
var resolveTrials = (overrides = {}) => Object.fromEntries(TRIAL_KINDS.map((kind) => [kind, { ...DEFAULT_TRIALS[kind], ...overrides[kind] }]));
|
|
38907
|
+
function fitRow(width, start, total, length3, gap) {
|
|
38908
|
+
let used = 0;
|
|
38909
|
+
let count = 0;
|
|
38910
|
+
for (let i = start; i < total; i++) {
|
|
38911
|
+
const w = width(i);
|
|
38912
|
+
const next = count === 0 ? w : used + gap + w;
|
|
38913
|
+
if (count > 0 && next > length3) break;
|
|
38914
|
+
used = next;
|
|
38915
|
+
count++;
|
|
38916
|
+
}
|
|
38917
|
+
return count;
|
|
38918
|
+
}
|
|
38919
|
+
function rowCentres(widths, centreX, gap) {
|
|
38920
|
+
const length3 = widths.reduce((sum2, w) => sum2 + w, 0) + gap * Math.max(0, widths.length - 1);
|
|
38921
|
+
let x = centreX - length3 / 2;
|
|
38922
|
+
return widths.map((w) => {
|
|
38923
|
+
const centre = x + w / 2;
|
|
38924
|
+
x += w + gap;
|
|
38925
|
+
return centre;
|
|
38926
|
+
});
|
|
38927
|
+
}
|
|
38928
|
+
function trialView(tool, kind, min2, max2) {
|
|
38929
|
+
const target = [(min2[0] + max2[0]) / 2, (min2[1] + max2[1]) / 2, (min2[2] + max2[2]) / 2];
|
|
38930
|
+
const away = kind === "blast" ? tool.watch ?? 6 : tool.distance;
|
|
38931
|
+
return { eye: [target[0], target[1] + tool.lift, max2[2] + away], target };
|
|
38932
|
+
}
|
|
38933
|
+
function createTestTable(context, options = {}) {
|
|
38934
|
+
const gap = options.gap ?? 0.12;
|
|
38935
|
+
const margin = options.margin ?? 0.1;
|
|
38936
|
+
const trials = resolveTrials(options.trials);
|
|
38937
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
38938
|
+
let current = null;
|
|
38939
|
+
const itemsOf = (group) => context.groups().get(group) ?? [];
|
|
38940
|
+
const emit2 = () => {
|
|
38941
|
+
const page = state();
|
|
38942
|
+
for (const listener of [...listeners]) listener(page);
|
|
38943
|
+
return page;
|
|
38944
|
+
};
|
|
38945
|
+
const state = () => {
|
|
38946
|
+
if (!current) return null;
|
|
38947
|
+
const total = itemsOf(current.group).length;
|
|
38948
|
+
const live = current.objects.filter((o) => context.box(o.objectId));
|
|
38949
|
+
return {
|
|
38950
|
+
group: current.group,
|
|
38951
|
+
page: current.page,
|
|
38952
|
+
first: current.first,
|
|
38953
|
+
total,
|
|
38954
|
+
objects: live,
|
|
38955
|
+
selected: current.selected,
|
|
38956
|
+
hasPrev: current.page > 0,
|
|
38957
|
+
hasNext: current.first + current.objects.length < total
|
|
38958
|
+
};
|
|
38959
|
+
};
|
|
38960
|
+
const bounds = /* @__PURE__ */ new Map();
|
|
38961
|
+
const widthOf = (itemId) => context.measure(itemId).w;
|
|
38962
|
+
const boundsUntil = (group, length3, until) => {
|
|
38963
|
+
const items = itemsOf(group);
|
|
38964
|
+
const known = bounds.get(group) ?? [0];
|
|
38965
|
+
bounds.set(group, known);
|
|
38966
|
+
while (known[known.length - 1] < items.length && !until(known)) {
|
|
38967
|
+
const first = known[known.length - 1];
|
|
38968
|
+
known.push(first + fitRow((i) => widthOf(items[i].id), first, items.length, length3, gap));
|
|
38969
|
+
}
|
|
38970
|
+
return known;
|
|
38971
|
+
};
|
|
38972
|
+
const lengthOf2 = (top) => top.maxX - top.minX - 2 * margin;
|
|
38973
|
+
const lay = (group, page, top) => {
|
|
38974
|
+
const items = itemsOf(group);
|
|
38975
|
+
const known = boundsUntil(group, lengthOf2(top), (b) => b.length > page + 1);
|
|
38976
|
+
const index = Math.max(0, Math.min(page, known.length - 2));
|
|
38977
|
+
const first = known[index];
|
|
38978
|
+
const laid = items.slice(first, known[index + 1]);
|
|
38979
|
+
context.clear();
|
|
38980
|
+
const sizes = laid.map((item) => context.measure(item.id));
|
|
38981
|
+
const centres = rowCentres(sizes.map((size) => size.w), (top.minX + top.maxX) / 2, gap);
|
|
38982
|
+
const objects = laid.map((item, i) => {
|
|
38983
|
+
const d = Math.min(sizes[i].d, top.maxZ - top.minZ);
|
|
38984
|
+
const { objectId } = context.spawn(item.id, [centres[i], top.top, top.maxZ - margin / 2 - d / 2]);
|
|
38985
|
+
return { objectId, itemId: item.id, name: item.name };
|
|
38986
|
+
});
|
|
38987
|
+
current = { group, page: index, first, objects, selected: objects[0]?.objectId ?? null };
|
|
38988
|
+
context.log("test_table", context.translate("act.test_table", { group, from: first + 1, to: first + laid.length, total: items.length }), { group, page: index, items: laid.map((i) => i.id) });
|
|
38989
|
+
return emit2();
|
|
38990
|
+
};
|
|
38991
|
+
const open = (group, page = 0) => {
|
|
38992
|
+
const top = context.top();
|
|
38993
|
+
if (!itemsOf(group).length || !top) return null;
|
|
38994
|
+
return lay(group, page, top);
|
|
38995
|
+
};
|
|
38996
|
+
const find = (itemId) => {
|
|
38997
|
+
const top = context.top();
|
|
38998
|
+
const group = [...context.groups()].find(([, items]) => items.some((i) => i.id === itemId))?.[0];
|
|
38999
|
+
if (group === void 0 || !top) return null;
|
|
39000
|
+
const index = itemsOf(group).findIndex((i) => i.id === itemId);
|
|
39001
|
+
const known = boundsUntil(group, lengthOf2(top), (b) => b[b.length - 1] > index);
|
|
39002
|
+
lay(group, known.findIndex((bound, i) => bound <= index && index < known[i + 1]), top);
|
|
39003
|
+
const target = current?.objects.find((o) => o.itemId === itemId);
|
|
39004
|
+
if (current && target) current.selected = target.objectId;
|
|
39005
|
+
return emit2();
|
|
39006
|
+
};
|
|
39007
|
+
const selected = (objectId) => {
|
|
39008
|
+
const id = objectId ?? current?.selected ?? null;
|
|
39009
|
+
return id && context.box(id) ? id : null;
|
|
39010
|
+
};
|
|
39011
|
+
const trial = (kind, objectId) => {
|
|
39012
|
+
const id = selected(objectId);
|
|
39013
|
+
const box2 = id ? context.box(id) : null;
|
|
39014
|
+
if (!id || !box2) return false;
|
|
39015
|
+
const tool = trials[kind];
|
|
39016
|
+
if (!context.equip(tool.weapon)) return false;
|
|
39017
|
+
const view = trialView(tool, kind, box2.min, box2.max);
|
|
39018
|
+
context.look(view.eye, view.target);
|
|
39019
|
+
const name = current?.objects.find((o) => o.objectId === id)?.name ?? id;
|
|
39020
|
+
context.log("trial", context.translate(`act.trial.${kind}`, { name }), { kind, objectId: id, weapon: tool.weapon });
|
|
39021
|
+
if (kind === "blast") {
|
|
39022
|
+
const point = [view.target[0], box2.min[1] + 0.05, box2.min[2] - tool.distance];
|
|
39023
|
+
return context.blastAt(tool.weapon, point);
|
|
39024
|
+
}
|
|
39025
|
+
context.use(tool.hold ?? 0);
|
|
39026
|
+
emit2();
|
|
39027
|
+
return true;
|
|
39028
|
+
};
|
|
39029
|
+
return {
|
|
39030
|
+
groups: () => [...context.groups()].filter(([, items]) => items.length > 0).map(([group]) => group),
|
|
39031
|
+
items: () => [...context.groups()].flatMap(([group, items]) => items.map((item) => ({ id: item.id, name: item.name, group }))),
|
|
39032
|
+
open,
|
|
39033
|
+
find,
|
|
39034
|
+
next: () => {
|
|
39035
|
+
const page = state();
|
|
39036
|
+
return page?.hasNext ? open(page.group, page.page + 1) : page;
|
|
39037
|
+
},
|
|
39038
|
+
prev: () => {
|
|
39039
|
+
const page = state();
|
|
39040
|
+
return page?.hasPrev ? open(page.group, page.page - 1) : page;
|
|
39041
|
+
},
|
|
39042
|
+
relay: () => {
|
|
39043
|
+
if (!current) return null;
|
|
39044
|
+
context.resetAll();
|
|
39045
|
+
return open(current.group, current.page);
|
|
39046
|
+
},
|
|
39047
|
+
state,
|
|
39048
|
+
select: (objectId) => {
|
|
39049
|
+
if (!current || !current.objects.some((o) => o.objectId === objectId) || !context.box(objectId)) return false;
|
|
39050
|
+
current.selected = objectId;
|
|
39051
|
+
emit2();
|
|
39052
|
+
return true;
|
|
39053
|
+
},
|
|
39054
|
+
trial,
|
|
39055
|
+
on: (listener) => {
|
|
39056
|
+
listeners.add(listener);
|
|
39057
|
+
return () => listeners.delete(listener);
|
|
39058
|
+
}
|
|
39059
|
+
};
|
|
38836
39060
|
}
|
|
38837
39061
|
|
|
38838
39062
|
// src/host-events.ts
|
|
@@ -40264,7 +40488,7 @@ void main(){
|
|
|
40264
40488
|
"hud.throw": "throw",
|
|
40265
40489
|
"hud.tilt": "tilt (hold)",
|
|
40266
40490
|
"hud.equip": "equip {weapon}",
|
|
40267
|
-
"ui.help": "Click: look \xB7 WASD: walk \xB7 Shift: run \xB7 C: crouch \xB7 Space: jump \xB7 1-0 / wheel: tool \xB7 LMB: use \xB7 E: grab/drop \xB7 G or RMB: throw \xB7 R: reload \xB7 Q: fire mode \xB7 X: clear a jam \xB7 B: safety \xB7 Y: detonate charges set down \xB7 Tab: panels \xB7 Esc: free the mouse",
|
|
40491
|
+
"ui.help": "Click: look \xB7 WASD: walk \xB7 Shift: run \xB7 C: crouch \xB7 Space: jump \xB7 1-0 / wheel: tool \xB7 LMB: use (bare hands: punch) \xB7 E: grab/drop \xB7 G or RMB: throw \xB7 R: reload \xB7 Q: fire mode \xB7 X: clear a jam \xB7 B: safety \xB7 Y: detonate charges set down \xB7 Tab: panels \xB7 Esc: free the mouse",
|
|
40268
40492
|
"ui.help.camera": "V: 1st/3rd person (Shift+V: kick)",
|
|
40269
40493
|
"camera.first": "1st person",
|
|
40270
40494
|
"camera.third": "3rd person",
|
|
@@ -40278,6 +40502,32 @@ void main(){
|
|
|
40278
40502
|
"ui.copy_json": "Copy JSON",
|
|
40279
40503
|
"ui.download_ndjson": "Download NDJSON",
|
|
40280
40504
|
"ui.download_txt": "Download TXT",
|
|
40505
|
+
"ui.test_table": "Test table",
|
|
40506
|
+
"ui.test_table.group": "Group to lay on the table",
|
|
40507
|
+
"ui.test_table.lay": "Lay",
|
|
40508
|
+
"ui.test_table.prev": "Previous items",
|
|
40509
|
+
"ui.test_table.next": "Next items",
|
|
40510
|
+
"ui.test_table.relay": "Put back",
|
|
40511
|
+
"ui.test_table.search": "Find an item to put on the table",
|
|
40512
|
+
"ui.test_table.hint": "Pick a group and lay it on the table, then pick an item and try it.",
|
|
40513
|
+
"ui.test_table.page": "Items {from}\u2013{to} of {total}. Pick one, then a trial:",
|
|
40514
|
+
"ui.trial.shot": "Shot",
|
|
40515
|
+
"ui.trial.punch": "Punch",
|
|
40516
|
+
"ui.trial.stab": "Knife",
|
|
40517
|
+
"ui.trial.fire": "Fire",
|
|
40518
|
+
"ui.trial.blast": "Blast",
|
|
40519
|
+
"ui.trial.shot.hint": "A 9 mm round from 2.5 m",
|
|
40520
|
+
"ui.trial.punch.hint": "A punch, up close",
|
|
40521
|
+
"ui.trial.stab.hint": "A knife blow, up close",
|
|
40522
|
+
"ui.trial.fire.hint": "A flamethrower burst from 1.6 m",
|
|
40523
|
+
"ui.trial.blast.hint": "A fragmentation grenade goes off just behind it (it reaches the neighbours too)",
|
|
40524
|
+
"act.test_table": "Test table: {group}, items {from}\u2013{to} of {total}",
|
|
40525
|
+
"act.trial.shot": "Trial: shooting {name}",
|
|
40526
|
+
"act.trial.punch": "Trial: punching {name}",
|
|
40527
|
+
"act.trial.stab": "Trial: stabbing {name}",
|
|
40528
|
+
"act.trial.fire": "Trial: setting fire to {name}",
|
|
40529
|
+
"act.trial.blast": "Trial: a blast beside {name}",
|
|
40530
|
+
"arena.test_table": "Test table",
|
|
40281
40531
|
"ui.clear_log": "Clear",
|
|
40282
40532
|
"ui.catalog": "Catalogue",
|
|
40283
40533
|
"ui.clear": "Clear",
|
|
@@ -40545,7 +40795,7 @@ void main(){
|
|
|
40545
40795
|
"hud.throw": "arremessar",
|
|
40546
40796
|
"hud.tilt": "inclinar (segurar)",
|
|
40547
40797
|
"hud.equip": "equipar {weapon}",
|
|
40548
|
-
"ui.help": "Clique: olhar \xB7 WASD: andar \xB7 Shift: correr \xB7 C: agachar \xB7 Espa\xE7o: pular \xB7 1-0 / roda: ferramenta \xB7 bot\xE3o esquerdo: usar \xB7 E: pegar/soltar \xB7 G ou bot\xE3o direito: arremessar \xB7 R: recarregar \xB7 Q: modo de tiro \xB7 X: destravar \xB7 B: trava \xB7 Y: detonar cargas postas \xB7 Tab: pain\xE9is \xB7 Esc: soltar o mouse",
|
|
40798
|
+
"ui.help": "Clique: olhar \xB7 WASD: andar \xB7 Shift: correr \xB7 C: agachar \xB7 Espa\xE7o: pular \xB7 1-0 / roda: ferramenta \xB7 bot\xE3o esquerdo: usar (m\xE3o livre: soco) \xB7 E: pegar/soltar \xB7 G ou bot\xE3o direito: arremessar \xB7 R: recarregar \xB7 Q: modo de tiro \xB7 X: destravar \xB7 B: trava \xB7 Y: detonar cargas postas \xB7 Tab: pain\xE9is \xB7 Esc: soltar o mouse",
|
|
40549
40799
|
"ui.help.camera": "V: 1\xAA/3\xAA pessoa (Shift+V: chute)",
|
|
40550
40800
|
"camera.first": "1\xAA pessoa",
|
|
40551
40801
|
"camera.third": "3\xAA pessoa",
|
|
@@ -40559,6 +40809,32 @@ void main(){
|
|
|
40559
40809
|
"ui.copy_json": "Copiar JSON",
|
|
40560
40810
|
"ui.download_ndjson": "Baixar NDJSON",
|
|
40561
40811
|
"ui.download_txt": "Baixar TXT",
|
|
40812
|
+
"ui.test_table": "Mesa de testes",
|
|
40813
|
+
"ui.test_table.group": "Grupo para p\xF4r na mesa",
|
|
40814
|
+
"ui.test_table.lay": "P\xF4r na mesa",
|
|
40815
|
+
"ui.test_table.prev": "Itens anteriores",
|
|
40816
|
+
"ui.test_table.next": "Pr\xF3ximos itens",
|
|
40817
|
+
"ui.test_table.relay": "Repor",
|
|
40818
|
+
"ui.test_table.search": "Buscar item para p\xF4r na mesa",
|
|
40819
|
+
"ui.test_table.hint": "Escolha um grupo e ponha na mesa; depois escolha um item e teste.",
|
|
40820
|
+
"ui.test_table.page": "Itens {from}\u2013{to} de {total}. Escolha um e um teste:",
|
|
40821
|
+
"ui.trial.shot": "Tiro",
|
|
40822
|
+
"ui.trial.punch": "Soco",
|
|
40823
|
+
"ui.trial.stab": "Faca",
|
|
40824
|
+
"ui.trial.fire": "Fogo",
|
|
40825
|
+
"ui.trial.blast": "Explos\xE3o",
|
|
40826
|
+
"ui.trial.shot.hint": "Um tiro de 9 mm a 2,5 m",
|
|
40827
|
+
"ui.trial.punch.hint": "Um soco, de perto",
|
|
40828
|
+
"ui.trial.stab.hint": "Um golpe de faca, de perto",
|
|
40829
|
+
"ui.trial.fire.hint": "Uma rajada de lan\xE7a-chamas a 1,6 m",
|
|
40830
|
+
"ui.trial.blast.hint": "Uma granada de fragmenta\xE7\xE3o explode logo atr\xE1s dele (pega os vizinhos tamb\xE9m)",
|
|
40831
|
+
"act.test_table": "Mesa de testes: {group}, itens {from}\u2013{to} de {total}",
|
|
40832
|
+
"act.trial.shot": "Teste: tiro em {name}",
|
|
40833
|
+
"act.trial.punch": "Teste: soco em {name}",
|
|
40834
|
+
"act.trial.stab": "Teste: faca em {name}",
|
|
40835
|
+
"act.trial.fire": "Teste: fogo em {name}",
|
|
40836
|
+
"act.trial.blast": "Teste: explos\xE3o ao lado de {name}",
|
|
40837
|
+
"arena.test_table": "Mesa de testes",
|
|
40562
40838
|
"ui.clear_log": "Limpar",
|
|
40563
40839
|
"ui.catalog": "Cat\xE1logo",
|
|
40564
40840
|
"ui.clear": "Limpar",
|
|
@@ -40900,6 +41176,122 @@ void main(){
|
|
|
40900
41176
|
};
|
|
40901
41177
|
}
|
|
40902
41178
|
|
|
41179
|
+
// src/test-table-panel.ts
|
|
41180
|
+
var TEST_TABLE_CSS = `
|
|
41181
|
+
.tr-table{flex:0 0 auto;max-height:42%}
|
|
41182
|
+
.tr-table .sub{color:#9aa3b2;margin:4px 0}
|
|
41183
|
+
.tr-table .list{display:flex;flex-wrap:wrap;gap:3px}
|
|
41184
|
+
.tr-table .list .tr-btn{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
41185
|
+
.tr-table select{flex:1;min-width:0;max-width:55%}
|
|
41186
|
+
.tr-table .tr-search{margin:6px 0 0}
|
|
41187
|
+
.tr-root .tr-table button.tr-btn.on{background:#3b3a14;border-color:#ffd23f;color:#fff}
|
|
41188
|
+
`;
|
|
41189
|
+
var mk2 = (tag, cls, text) => {
|
|
41190
|
+
const e = document.createElement(tag);
|
|
41191
|
+
if (cls) e.className = cls;
|
|
41192
|
+
if (text !== void 0) e.textContent = text;
|
|
41193
|
+
return e;
|
|
41194
|
+
};
|
|
41195
|
+
function createTestTablePanel(table, t) {
|
|
41196
|
+
const element = mk2("div", "tr-panel tr-table");
|
|
41197
|
+
element.appendChild(mk2("h3", void 0, t("ui.test_table")));
|
|
41198
|
+
const head = mk2("div", "tr-row");
|
|
41199
|
+
const select = mk2("select");
|
|
41200
|
+
select.setAttribute("aria-label", t("ui.test_table.group"));
|
|
41201
|
+
const lay = mk2("button", "tr-btn", t("ui.test_table.lay"));
|
|
41202
|
+
const prev = mk2("button", "tr-btn", "\u25C0");
|
|
41203
|
+
const next = mk2("button", "tr-btn", "\u25B6");
|
|
41204
|
+
prev.title = t("ui.test_table.prev");
|
|
41205
|
+
next.title = t("ui.test_table.next");
|
|
41206
|
+
for (const b of [lay, prev, next]) b.type = "button";
|
|
41207
|
+
head.append(select, lay, prev, next);
|
|
41208
|
+
const search = mk2("input", "tr-search");
|
|
41209
|
+
search.type = "search";
|
|
41210
|
+
search.placeholder = t("ui.test_table.search");
|
|
41211
|
+
const found = mk2("div", "list");
|
|
41212
|
+
const sub4 = mk2("div", "sub", t("ui.test_table.hint"));
|
|
41213
|
+
const list = mk2("div", "list");
|
|
41214
|
+
const trials = mk2("div", "tr-row");
|
|
41215
|
+
const trialButtons = TRIAL_KINDS.map((kind) => {
|
|
41216
|
+
const b = mk2("button", "tr-btn", t(`ui.trial.${kind}`));
|
|
41217
|
+
b.type = "button";
|
|
41218
|
+
b.dataset.trial = kind;
|
|
41219
|
+
b.title = t(`ui.trial.${kind}.hint`);
|
|
41220
|
+
b.onclick = () => table.trial(kind);
|
|
41221
|
+
trials.appendChild(b);
|
|
41222
|
+
return b;
|
|
41223
|
+
});
|
|
41224
|
+
const relay = mk2("button", "tr-btn", t("ui.test_table.relay"));
|
|
41225
|
+
relay.type = "button";
|
|
41226
|
+
relay.onclick = () => table.relay();
|
|
41227
|
+
trials.appendChild(relay);
|
|
41228
|
+
element.append(head, search, found, sub4, list, trials);
|
|
41229
|
+
const groups = () => {
|
|
41230
|
+
const keep = select.value;
|
|
41231
|
+
select.textContent = "";
|
|
41232
|
+
for (const group of table.groups()) {
|
|
41233
|
+
const op = mk2("option", void 0, group);
|
|
41234
|
+
op.value = group;
|
|
41235
|
+
select.appendChild(op);
|
|
41236
|
+
}
|
|
41237
|
+
if ([...select.options].some((o) => o.value === keep)) select.value = keep;
|
|
41238
|
+
};
|
|
41239
|
+
const render = (page) => {
|
|
41240
|
+
list.textContent = "";
|
|
41241
|
+
prev.disabled = !page?.hasPrev;
|
|
41242
|
+
next.disabled = !page?.hasNext;
|
|
41243
|
+
for (const b of [...trialButtons, relay]) b.disabled = !page?.selected;
|
|
41244
|
+
if (!page) {
|
|
41245
|
+
sub4.textContent = t("ui.test_table.hint");
|
|
41246
|
+
return;
|
|
41247
|
+
}
|
|
41248
|
+
if (select.value !== page.group) select.value = page.group;
|
|
41249
|
+
sub4.textContent = t("ui.test_table.page", { from: page.first + 1, to: page.first + page.objects.length, total: page.total });
|
|
41250
|
+
for (const o of page.objects) {
|
|
41251
|
+
const b = mk2("button", o.objectId === page.selected ? "tr-btn on" : "tr-btn", o.name);
|
|
41252
|
+
b.type = "button";
|
|
41253
|
+
b.title = o.itemId;
|
|
41254
|
+
b.onclick = () => table.select(o.objectId);
|
|
41255
|
+
list.appendChild(b);
|
|
41256
|
+
}
|
|
41257
|
+
};
|
|
41258
|
+
const fold2 = (text) => text.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
|
|
41259
|
+
search.oninput = () => {
|
|
41260
|
+
found.textContent = "";
|
|
41261
|
+
const term = fold2(search.value.trim());
|
|
41262
|
+
if (!term) return;
|
|
41263
|
+
const hits = table.items().filter((item) => fold2(`${item.name} ${item.id}`).includes(term)).slice(0, 8);
|
|
41264
|
+
for (const item of hits) {
|
|
41265
|
+
const b = mk2("button", "tr-btn", item.name);
|
|
41266
|
+
b.type = "button";
|
|
41267
|
+
b.title = `${item.group} \xB7 ${item.id}`;
|
|
41268
|
+
b.onclick = () => {
|
|
41269
|
+
search.value = "";
|
|
41270
|
+
found.textContent = "";
|
|
41271
|
+
table.find(item.id);
|
|
41272
|
+
};
|
|
41273
|
+
found.appendChild(b);
|
|
41274
|
+
}
|
|
41275
|
+
if (!hits.length) found.appendChild(mk2("div", "sub", t("ui.no_results")));
|
|
41276
|
+
};
|
|
41277
|
+
lay.onclick = () => table.open(select.value);
|
|
41278
|
+
prev.onclick = () => table.prev();
|
|
41279
|
+
next.onclick = () => table.next();
|
|
41280
|
+
select.onchange = () => table.open(select.value);
|
|
41281
|
+
for (const box2 of [select, search]) box2.addEventListener("keydown", (e) => e.stopPropagation());
|
|
41282
|
+
const off = table.on(render);
|
|
41283
|
+
groups();
|
|
41284
|
+
render(table.state());
|
|
41285
|
+
return {
|
|
41286
|
+
element,
|
|
41287
|
+
refresh: () => {
|
|
41288
|
+
groups();
|
|
41289
|
+
render(table.state());
|
|
41290
|
+
},
|
|
41291
|
+
dispose: off
|
|
41292
|
+
};
|
|
41293
|
+
}
|
|
41294
|
+
|
|
40903
41295
|
// src/ui.ts
|
|
40904
41296
|
var CSS = `
|
|
40905
41297
|
.tr-root{position:absolute;inset:0;pointer-events:none;font:12px/1.35 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;color:#e8eaee;overflow:hidden}
|
|
@@ -40978,7 +41370,7 @@ void main(){
|
|
|
40978
41370
|
@media (max-width:980px){.tr-left,.tr-right{display:none}.tr-root.open .tr-left,.tr-root.open .tr-right{display:flex}.tr-toggle{display:block;pointer-events:auto}.tr-root.open .tr-toggle{right:min(310px,34vw)}.tr-left{width:min(400px,46vw)}.tr-help{display:none}}
|
|
40979
41371
|
`;
|
|
40980
41372
|
var fold = (text) => text.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
|
|
40981
|
-
var
|
|
41373
|
+
var mk3 = (tag, cls, text) => {
|
|
40982
41374
|
const e = document.createElement(tag);
|
|
40983
41375
|
if (cls) e.className = cls;
|
|
40984
41376
|
if (text !== void 0) e.textContent = text;
|
|
@@ -40989,7 +41381,7 @@ void main(){
|
|
|
40989
41381
|
return source.replace(/["\\\n\r]/g, (char) => encodeURIComponent(char));
|
|
40990
41382
|
};
|
|
40991
41383
|
var thumb = (thumbnail, credit) => {
|
|
40992
|
-
const e =
|
|
41384
|
+
const e = mk3("span", "tr-thumb");
|
|
40993
41385
|
if (credit) e.title = credit;
|
|
40994
41386
|
else e.setAttribute("aria-hidden", "true");
|
|
40995
41387
|
e.style.setProperty("--tr-thumb", `url("${thumbSource(thumbnail)}")`);
|
|
@@ -41010,42 +41402,43 @@ void main(){
|
|
|
41010
41402
|
}
|
|
41011
41403
|
function createUi(o) {
|
|
41012
41404
|
const { t } = o;
|
|
41013
|
-
const style =
|
|
41014
|
-
style.textContent = CSS;
|
|
41015
|
-
const root =
|
|
41405
|
+
const style = mk3("style");
|
|
41406
|
+
style.textContent = CSS + (o.testTable ? TEST_TABLE_CSS : "");
|
|
41407
|
+
const root = mk3("div", "tr-root");
|
|
41016
41408
|
const pos = getComputedStyle?.(o.container)?.position;
|
|
41017
41409
|
if (!pos || pos === "static") o.container.style.position = "relative";
|
|
41018
41410
|
root.appendChild(style);
|
|
41019
41411
|
o.container.appendChild(root);
|
|
41020
|
-
const cross5 =
|
|
41021
|
-
cross5.appendChild(
|
|
41022
|
-
const top =
|
|
41023
|
-
const toolBox =
|
|
41024
|
-
const status =
|
|
41025
|
-
const prog =
|
|
41026
|
-
const progLabel =
|
|
41027
|
-
const progBar =
|
|
41028
|
-
const progFill =
|
|
41412
|
+
const cross5 = mk3("div", "tr-cross");
|
|
41413
|
+
cross5.appendChild(mk3("i"));
|
|
41414
|
+
const top = mk3("div", "tr-top");
|
|
41415
|
+
const toolBox = mk3("div", "tr-tool");
|
|
41416
|
+
const status = mk3("div", "tr-status");
|
|
41417
|
+
const prog = mk3("div", "tr-prog");
|
|
41418
|
+
const progLabel = mk3("b");
|
|
41419
|
+
const progBar = mk3("div", "tr-bar");
|
|
41420
|
+
const progFill = mk3("i");
|
|
41029
41421
|
progBar.appendChild(progFill);
|
|
41030
41422
|
prog.append(progLabel, progBar);
|
|
41031
41423
|
top.append(toolBox, status, prog);
|
|
41032
|
-
const bottom =
|
|
41033
|
-
const held =
|
|
41034
|
-
const hotbar =
|
|
41424
|
+
const bottom = mk3("div", "tr-bottom");
|
|
41425
|
+
const held = mk3("div", "tr-held");
|
|
41426
|
+
const hotbar = mk3("div", "tr-hotbar");
|
|
41035
41427
|
bottom.append(held, hotbar);
|
|
41036
|
-
const help =
|
|
41428
|
+
const help = mk3("div", "tr-help");
|
|
41037
41429
|
help.textContent = t("ui.help");
|
|
41038
|
-
const left =
|
|
41039
|
-
const insp =
|
|
41040
|
-
const logPanel =
|
|
41041
|
-
|
|
41042
|
-
|
|
41043
|
-
const
|
|
41044
|
-
const
|
|
41430
|
+
const left = mk3("div", "tr-left");
|
|
41431
|
+
const insp = mk3("div", "tr-panel tr-insp");
|
|
41432
|
+
const logPanel = mk3("div", "tr-panel tr-log");
|
|
41433
|
+
const tablePanel = o.testTable ? createTestTablePanel(o.testTable, t) : null;
|
|
41434
|
+
left.append(insp, ...tablePanel ? [tablePanel.element] : [], logPanel);
|
|
41435
|
+
const logTitle = mk3("h3", void 0, t("ui.log"));
|
|
41436
|
+
const logBar = mk3("div", "tr-logbar");
|
|
41437
|
+
const logBody = mk3("div", "tr-logbody");
|
|
41045
41438
|
const filters = { action: true, event: true, check: true };
|
|
41046
41439
|
const filterBtns = [];
|
|
41047
41440
|
for (const ch of ["action", "event", "check"]) {
|
|
41048
|
-
const b =
|
|
41441
|
+
const b = mk3("button", "tr-btn on", t(`ui.filter.${ch}`));
|
|
41049
41442
|
b.type = "button";
|
|
41050
41443
|
b.onclick = () => {
|
|
41051
41444
|
filters[ch] = !filters[ch];
|
|
@@ -41056,8 +41449,8 @@ void main(){
|
|
|
41056
41449
|
logBar.appendChild(b);
|
|
41057
41450
|
}
|
|
41058
41451
|
let autoscroll = true;
|
|
41059
|
-
const asLabel =
|
|
41060
|
-
const asBox =
|
|
41452
|
+
const asLabel = mk3("label");
|
|
41453
|
+
const asBox = mk3("input");
|
|
41061
41454
|
asBox.type = "checkbox";
|
|
41062
41455
|
asBox.checked = true;
|
|
41063
41456
|
asBox.onchange = () => {
|
|
@@ -41066,7 +41459,7 @@ void main(){
|
|
|
41066
41459
|
asLabel.append(asBox, document.createTextNode(" " + t("ui.autoscroll")));
|
|
41067
41460
|
logBar.appendChild(asLabel);
|
|
41068
41461
|
const logBtn = (label, fn) => {
|
|
41069
|
-
const b =
|
|
41462
|
+
const b = mk3("button", "tr-btn", label);
|
|
41070
41463
|
b.type = "button";
|
|
41071
41464
|
b.onclick = fn;
|
|
41072
41465
|
logBar.appendChild(b);
|
|
@@ -41074,7 +41467,7 @@ void main(){
|
|
|
41074
41467
|
logBtn(t("ui.copy_json"), () => {
|
|
41075
41468
|
const text = o.log.toJSON();
|
|
41076
41469
|
const select = () => {
|
|
41077
|
-
const ta =
|
|
41470
|
+
const ta = mk3("textarea");
|
|
41078
41471
|
ta.value = text;
|
|
41079
41472
|
ta.setAttribute("readonly", "");
|
|
41080
41473
|
ta.style.cssText = "position:fixed;left:8px;bottom:8px;width:min(480px,80vw);height:120px;z-index:99999";
|
|
@@ -41108,12 +41501,12 @@ void main(){
|
|
|
41108
41501
|
const fill = (n, e) => {
|
|
41109
41502
|
n.className = lineClass(e);
|
|
41110
41503
|
n.textContent = "";
|
|
41111
|
-
const tm =
|
|
41504
|
+
const tm = mk3("time", void 0, fmtTime(e.t));
|
|
41112
41505
|
n.append(tm, document.createTextNode(e.text));
|
|
41113
41506
|
};
|
|
41114
41507
|
const addNode = (e) => {
|
|
41115
41508
|
if (!filters[e.channel]) return;
|
|
41116
|
-
const n =
|
|
41509
|
+
const n = mk3("div");
|
|
41117
41510
|
fill(n, e);
|
|
41118
41511
|
nodes.set(e.seq, n);
|
|
41119
41512
|
logBody.appendChild(n);
|
|
@@ -41135,18 +41528,18 @@ void main(){
|
|
|
41135
41528
|
if (n) fill(n, e);
|
|
41136
41529
|
} else addNode(e);
|
|
41137
41530
|
});
|
|
41138
|
-
const right =
|
|
41139
|
-
const cat =
|
|
41140
|
-
const anim =
|
|
41141
|
-
const tests =
|
|
41531
|
+
const right = mk3("div", "tr-right");
|
|
41532
|
+
const cat = mk3("div", "tr-panel tr-cat");
|
|
41533
|
+
const anim = mk3("div", "tr-panel tr-anim");
|
|
41534
|
+
const tests = mk3("div", "tr-panel tr-tests");
|
|
41142
41535
|
const benchPanel = createBenchPanel({ t, num: (n, d) => num(n, d), onControl: o.onControl, onLayer: o.onLayer, onAction: o.onAction });
|
|
41143
41536
|
right.append(cat, anim, benchPanel.element, tests);
|
|
41144
|
-
cat.appendChild(
|
|
41145
|
-
const itemSearch =
|
|
41537
|
+
cat.appendChild(mk3("h3", void 0, t("ui.catalog")));
|
|
41538
|
+
const itemSearch = mk3("input", "tr-search");
|
|
41146
41539
|
itemSearch.type = "search";
|
|
41147
41540
|
itemSearch.placeholder = t("ui.search_items");
|
|
41148
|
-
const tabs =
|
|
41149
|
-
const items =
|
|
41541
|
+
const tabs = mk3("div", "tr-tabs");
|
|
41542
|
+
const items = mk3("div", "tr-items");
|
|
41150
41543
|
cat.append(itemSearch, tabs, items);
|
|
41151
41544
|
let activeGroup = "";
|
|
41152
41545
|
const visibleItems = () => {
|
|
@@ -41158,18 +41551,18 @@ void main(){
|
|
|
41158
41551
|
items.textContent = "";
|
|
41159
41552
|
const searching = itemSearch.value.trim() !== "";
|
|
41160
41553
|
const found = visibleItems();
|
|
41161
|
-
if (!found.length) items.appendChild(
|
|
41554
|
+
if (!found.length) items.appendChild(mk3("div", "tr-empty", t("ui.no_results")));
|
|
41162
41555
|
for (const { item: it, group } of found) {
|
|
41163
|
-
const wrap =
|
|
41164
|
-
const b =
|
|
41165
|
-
if (it.thumbnail) b.append(thumb(it.thumbnail),
|
|
41166
|
-
if (searching) b.appendChild(
|
|
41556
|
+
const wrap = mk3("div", "tr-item");
|
|
41557
|
+
const b = mk3("button", it.thumbnail ? "tr-btn has-thumb" : "tr-btn", it.thumbnail ? void 0 : it.name);
|
|
41558
|
+
if (it.thumbnail) b.append(thumb(it.thumbnail), mk3("span", "tr-name", it.name));
|
|
41559
|
+
if (searching) b.appendChild(mk3("small", void 0, group));
|
|
41167
41560
|
b.type = "button";
|
|
41168
41561
|
b.title = it.note ?? it.name;
|
|
41169
41562
|
b.onclick = () => o.onSpawn(it.id);
|
|
41170
41563
|
wrap.appendChild(b);
|
|
41171
41564
|
if (it.weapon) {
|
|
41172
|
-
const w =
|
|
41565
|
+
const w = mk3("button", "tr-btn", "\u2694");
|
|
41173
41566
|
w.type = "button";
|
|
41174
41567
|
w.title = t("ui.equip");
|
|
41175
41568
|
w.onclick = () => o.onEquip(it.id);
|
|
@@ -41183,7 +41576,7 @@ void main(){
|
|
|
41183
41576
|
const groupNames = [...o.groups().keys()];
|
|
41184
41577
|
if (!groupNames.includes(activeGroup)) activeGroup = groupNames[0] ?? "";
|
|
41185
41578
|
for (const g of groupNames) {
|
|
41186
|
-
const b =
|
|
41579
|
+
const b = mk3("button", g === activeGroup ? "tr-btn on" : "tr-btn", g);
|
|
41187
41580
|
b.type = "button";
|
|
41188
41581
|
b.onclick = () => {
|
|
41189
41582
|
activeGroup = g;
|
|
@@ -41196,9 +41589,9 @@ void main(){
|
|
|
41196
41589
|
renderTabs();
|
|
41197
41590
|
itemSearch.oninput = renderItems;
|
|
41198
41591
|
for (const box2 of [itemSearch]) box2.addEventListener("keydown", (e) => e.stopPropagation());
|
|
41199
|
-
const controls =
|
|
41592
|
+
const controls = mk3("div", "tr-row");
|
|
41200
41593
|
const ctl = (label, fn) => {
|
|
41201
|
-
const b =
|
|
41594
|
+
const b = mk3("button", "tr-btn", label);
|
|
41202
41595
|
b.type = "button";
|
|
41203
41596
|
b.onclick = () => fn(b);
|
|
41204
41597
|
controls.appendChild(b);
|
|
@@ -41223,29 +41616,29 @@ void main(){
|
|
|
41223
41616
|
fullscreenBtn.title = t("ui.fullscreen.hint");
|
|
41224
41617
|
const blastBtns = ["shelter", "fragmentHits", "confinement"].map((key) => ({ key, b: ctl(t(`ui.blast.${key}`), () => o.onBlast(key)) }));
|
|
41225
41618
|
for (const { key, b } of blastBtns) b.title = t(`ui.blast.${key}.hint`);
|
|
41226
|
-
const qSel =
|
|
41619
|
+
const qSel = mk3("select");
|
|
41227
41620
|
for (const q of ["low", "medium", "high"]) {
|
|
41228
|
-
const op =
|
|
41621
|
+
const op = mk3("option", void 0, t(`ui.quality.${q}`));
|
|
41229
41622
|
op.value = q;
|
|
41230
41623
|
qSel.appendChild(op);
|
|
41231
41624
|
}
|
|
41232
41625
|
qSel.value = o.quality;
|
|
41233
41626
|
qSel.onchange = () => o.onQuality(qSel.value);
|
|
41234
|
-
const qLabel =
|
|
41627
|
+
const qLabel = mk3("label", void 0, t("ui.quality") + " ");
|
|
41235
41628
|
qLabel.appendChild(qSel);
|
|
41236
41629
|
controls.appendChild(qLabel);
|
|
41237
|
-
const count =
|
|
41630
|
+
const count = mk3("span");
|
|
41238
41631
|
controls.appendChild(count);
|
|
41239
41632
|
cat.appendChild(controls);
|
|
41240
|
-
tests.appendChild(
|
|
41241
|
-
const runAll =
|
|
41633
|
+
tests.appendChild(mk3("h3", void 0, t("ui.tests")));
|
|
41634
|
+
const runAll = mk3("button", "tr-btn", t("ui.run_all"));
|
|
41242
41635
|
runAll.type = "button";
|
|
41243
|
-
const summary =
|
|
41244
|
-
const testSearch =
|
|
41636
|
+
const summary = mk3("div", "tr-summary");
|
|
41637
|
+
const testSearch = mk3("input", "tr-search");
|
|
41245
41638
|
testSearch.type = "search";
|
|
41246
41639
|
testSearch.placeholder = t("ui.search_tests");
|
|
41247
41640
|
testSearch.addEventListener("keydown", (e) => e.stopPropagation());
|
|
41248
|
-
const list =
|
|
41641
|
+
const list = mk3("div", "list");
|
|
41249
41642
|
tests.append(runAll, summary, testSearch, list);
|
|
41250
41643
|
testSearch.oninput = () => {
|
|
41251
41644
|
const term = fold(testSearch.value.trim());
|
|
@@ -41268,7 +41661,7 @@ void main(){
|
|
|
41268
41661
|
list.textContent = "";
|
|
41269
41662
|
scBtns.clear();
|
|
41270
41663
|
for (const s of o.scenarios()) {
|
|
41271
|
-
const b =
|
|
41664
|
+
const b = mk3("button", "tr-btn", s.name);
|
|
41272
41665
|
b.type = "button";
|
|
41273
41666
|
b.onclick = async () => {
|
|
41274
41667
|
if (busy) return;
|
|
@@ -41294,7 +41687,7 @@ void main(){
|
|
|
41294
41687
|
busy = false;
|
|
41295
41688
|
}
|
|
41296
41689
|
};
|
|
41297
|
-
const toggle =
|
|
41690
|
+
const toggle = mk3("button", "tr-btn tr-toggle", t("ui.panel"));
|
|
41298
41691
|
toggle.type = "button";
|
|
41299
41692
|
const togglePanels = () => {
|
|
41300
41693
|
root.classList.toggle("open");
|
|
@@ -41303,15 +41696,15 @@ void main(){
|
|
|
41303
41696
|
toggle.onclick = togglePanels;
|
|
41304
41697
|
root.append(cross5, top, bottom, help, left, right, toggle);
|
|
41305
41698
|
const bar2 = (value, max2, cls) => {
|
|
41306
|
-
const b =
|
|
41307
|
-
const i =
|
|
41699
|
+
const b = mk3("div", `tr-bar ${cls}`);
|
|
41700
|
+
const i = mk3("i");
|
|
41308
41701
|
i.style.width = `${Math.max(0, Math.min(100, value / Math.max(1e-9, max2) * 100))}%`;
|
|
41309
41702
|
b.appendChild(i);
|
|
41310
41703
|
return b;
|
|
41311
41704
|
};
|
|
41312
41705
|
const row = (k, v) => {
|
|
41313
|
-
const r =
|
|
41314
|
-
r.append(
|
|
41706
|
+
const r = mk3("div", "r");
|
|
41707
|
+
r.append(mk3("span", void 0, k), mk3("span", void 0, v));
|
|
41315
41708
|
return r;
|
|
41316
41709
|
};
|
|
41317
41710
|
const num = (n, d = 1) => {
|
|
@@ -41320,13 +41713,13 @@ void main(){
|
|
|
41320
41713
|
};
|
|
41321
41714
|
const renderInspector = (i) => {
|
|
41322
41715
|
insp.textContent = "";
|
|
41323
|
-
insp.appendChild(
|
|
41716
|
+
insp.appendChild(mk3("h3", void 0, t("ui.inspector")));
|
|
41324
41717
|
if (!i) {
|
|
41325
|
-
insp.appendChild(
|
|
41718
|
+
insp.appendChild(mk3("div", void 0, t("ui.aim_at_something")));
|
|
41326
41719
|
return;
|
|
41327
41720
|
}
|
|
41328
41721
|
if (i.thumbnail) insp.appendChild(thumb(i.thumbnail, i.thumbnailCredit));
|
|
41329
|
-
insp.appendChild(
|
|
41722
|
+
insp.appendChild(mk3("div", "t", `${i.object} \u203A ${i.part}`));
|
|
41330
41723
|
insp.appendChild(row(t("ins.material"), i.material));
|
|
41331
41724
|
insp.appendChild(row(t("ins.status"), i.status + (i.burning ? ` \xB7 ${t("ins.burning")}` : "")));
|
|
41332
41725
|
insp.appendChild(row(t("ins.hp"), `${num(i.hp, 0)} / ${num(i.maxHp, 0)}`));
|
|
@@ -41345,30 +41738,30 @@ void main(){
|
|
|
41345
41738
|
insp.appendChild(bar2(Math.min(i.stress, 1.2), 1.2, i.stress > 1 ? "bad" : i.stress > 0.7 ? "warn" : "hp"));
|
|
41346
41739
|
}
|
|
41347
41740
|
if (i.joints.length) {
|
|
41348
|
-
insp.appendChild(
|
|
41741
|
+
insp.appendChild(mk3("div", void 0, t("ins.joints") + ":"));
|
|
41349
41742
|
for (const j of i.joints) {
|
|
41350
41743
|
const tools = j.tools.length ? j.tools.join(", ") : t("tool.none");
|
|
41351
|
-
insp.appendChild(
|
|
41744
|
+
insp.appendChild(mk3("div", void 0, `\u2022 ${j.kind} (${j.id})${j.open ? ` \xB7 ${t("ins.open")}` : ` \u2192 ${tools}`}`));
|
|
41352
41745
|
}
|
|
41353
41746
|
}
|
|
41354
|
-
if (i.note) insp.appendChild(
|
|
41747
|
+
if (i.note) insp.appendChild(mk3("div", void 0, i.note));
|
|
41355
41748
|
};
|
|
41356
41749
|
let lastAnim = "";
|
|
41357
41750
|
const renderAnimations = (a) => {
|
|
41358
41751
|
anim.textContent = "";
|
|
41359
|
-
anim.appendChild(
|
|
41752
|
+
anim.appendChild(mk3("h3", void 0, t("ui.animations")));
|
|
41360
41753
|
if (!a) {
|
|
41361
|
-
anim.appendChild(
|
|
41754
|
+
anim.appendChild(mk3("div", "sub", t("ui.animations_aim")));
|
|
41362
41755
|
return;
|
|
41363
41756
|
}
|
|
41364
|
-
anim.appendChild(
|
|
41757
|
+
anim.appendChild(mk3("div", "sub", a.name));
|
|
41365
41758
|
if (a.clips.length === 0) {
|
|
41366
|
-
anim.appendChild(
|
|
41759
|
+
anim.appendChild(mk3("div", "sub", t("ui.animations_none")));
|
|
41367
41760
|
return;
|
|
41368
41761
|
}
|
|
41369
|
-
const l =
|
|
41762
|
+
const l = mk3("div", "list");
|
|
41370
41763
|
for (const c of a.clips) {
|
|
41371
|
-
const b =
|
|
41764
|
+
const b = mk3("button", a.playing === c.id ? "tr-btn on" : "tr-btn", `\u25B6 ${t(`anim.${c.id}`) === `anim.${c.id}` ? c.id : t(`anim.${c.id}`)} (${num(c.duration, 1)} s)`);
|
|
41372
41765
|
b.type = "button";
|
|
41373
41766
|
b.onclick = () => o.onPlay(a.objectId, c.id);
|
|
41374
41767
|
l.appendChild(b);
|
|
@@ -41385,8 +41778,8 @@ void main(){
|
|
|
41385
41778
|
hud(s) {
|
|
41386
41779
|
toolBox.textContent = "";
|
|
41387
41780
|
toolBox.append(document.createTextNode(s.toolName));
|
|
41388
|
-
if (s.ammo) toolBox.append(
|
|
41389
|
-
if (s.camera) toolBox.append(
|
|
41781
|
+
if (s.ammo) toolBox.append(mk3("small", void 0, s.ammo));
|
|
41782
|
+
if (s.camera) toolBox.append(mk3("small", void 0, t(`camera.${s.camera}`)));
|
|
41390
41783
|
const helpText = s.camera ? `${t("ui.help")} \xB7 ${t("ui.help.camera")}` : t("ui.help");
|
|
41391
41784
|
if (help.textContent !== helpText) help.textContent = helpText;
|
|
41392
41785
|
if (s.status) status.textContent = s.status;
|
|
@@ -41409,7 +41802,7 @@ void main(){
|
|
|
41409
41802
|
];
|
|
41410
41803
|
if (s.held.weapon) keys.push(["H", t("hud.equip", { weapon: s.held.weapon })]);
|
|
41411
41804
|
for (const [k, label] of keys) {
|
|
41412
|
-
held.append(
|
|
41805
|
+
held.append(mk3("kbd", void 0, k), document.createTextNode(` ${label} `));
|
|
41413
41806
|
}
|
|
41414
41807
|
} else held.style.display = "none";
|
|
41415
41808
|
const key = s.slots.join("|") + s.page;
|
|
@@ -41419,9 +41812,9 @@ void main(){
|
|
|
41419
41812
|
slotsEl.length = 0;
|
|
41420
41813
|
hudPage = s.page - 1;
|
|
41421
41814
|
s.slots.forEach((name, i) => {
|
|
41422
|
-
const b =
|
|
41815
|
+
const b = mk3("button", "tr-slot");
|
|
41423
41816
|
b.type = "button";
|
|
41424
|
-
b.append(
|
|
41817
|
+
b.append(mk3("b", void 0, String((i + 1) % 10)), document.createTextNode(name));
|
|
41425
41818
|
b.title = name;
|
|
41426
41819
|
b.onclick = () => o.onTool(hudPage * 10 + i);
|
|
41427
41820
|
hotbar.appendChild(b);
|
|
@@ -41453,6 +41846,7 @@ void main(){
|
|
|
41453
41846
|
refresh() {
|
|
41454
41847
|
renderTabs();
|
|
41455
41848
|
renderScenarios();
|
|
41849
|
+
tablePanel?.refresh();
|
|
41456
41850
|
},
|
|
41457
41851
|
showGroup(group) {
|
|
41458
41852
|
activeGroup = group;
|
|
@@ -41467,6 +41861,7 @@ void main(){
|
|
|
41467
41861
|
},
|
|
41468
41862
|
dispose() {
|
|
41469
41863
|
offLog();
|
|
41864
|
+
tablePanel?.dispose();
|
|
41470
41865
|
if (toastTimer) clearTimeout(toastTimer);
|
|
41471
41866
|
root.remove();
|
|
41472
41867
|
}
|
|
@@ -42656,6 +43051,10 @@ void main(){
|
|
|
42656
43051
|
heldPiece = null;
|
|
42657
43052
|
heldTilt = 0;
|
|
42658
43053
|
};
|
|
43054
|
+
const handUse = () => {
|
|
43055
|
+
if (heldPiece) grab();
|
|
43056
|
+
else useTool(FIXED_DT, false);
|
|
43057
|
+
};
|
|
42659
43058
|
const grab = () => {
|
|
42660
43059
|
if (heldPiece) {
|
|
42661
43060
|
const name = heldName;
|
|
@@ -43124,10 +43523,10 @@ void main(){
|
|
|
43124
43523
|
if (tiltKey || heldTilt > 0) {
|
|
43125
43524
|
heldTilt = Math.max(0, Math.min(2.4, heldTilt + (tiltKey ? 2.2 : -3) * dt));
|
|
43126
43525
|
}
|
|
43127
|
-
if (useHeld && !paused) {
|
|
43526
|
+
if ((useHeld || useFirst) && !paused) {
|
|
43128
43527
|
if (tool.def.category === "hand") {
|
|
43129
|
-
if (useFirst)
|
|
43130
|
-
} else useTool(dt, !useFirst);
|
|
43528
|
+
if (useFirst) handUse();
|
|
43529
|
+
} else if (useHeld) useTool(dt, !useFirst);
|
|
43131
43530
|
useFirst = false;
|
|
43132
43531
|
}
|
|
43133
43532
|
if (!paused) followHeld(dt);
|
|
@@ -43682,6 +44081,63 @@ void main(){
|
|
|
43682
44081
|
const row = (list, gap, z) => list.map((item, index) => spawn2(item.id, [(index - (list.length - 1) / 2) * gap, 0, z], 0));
|
|
43683
44082
|
return [...row(front, 1.6, 1.5), ...row(back, 4.5, -4)];
|
|
43684
44083
|
};
|
|
44084
|
+
const catalogGroups = () => {
|
|
44085
|
+
const m = /* @__PURE__ */ new Map();
|
|
44086
|
+
for (const i of catalog) {
|
|
44087
|
+
const g = m.get(i.group) ?? [];
|
|
44088
|
+
g.push(i);
|
|
44089
|
+
m.set(i.group, g);
|
|
44090
|
+
}
|
|
44091
|
+
return m;
|
|
44092
|
+
};
|
|
44093
|
+
const tableOptions = options.testTable === false ? {} : options.testTable ?? {};
|
|
44094
|
+
const tableScenery = tableOptions.scenery ?? "test_table";
|
|
44095
|
+
const measured = /* @__PURE__ */ new Map();
|
|
44096
|
+
const testTable = createTestTable(
|
|
44097
|
+
{
|
|
44098
|
+
groups: catalogGroups,
|
|
44099
|
+
top: () => {
|
|
44100
|
+
const top = arena.tops.find((x) => x.id === tableScenery);
|
|
44101
|
+
return top && topOk(top) ? top : null;
|
|
44102
|
+
},
|
|
44103
|
+
measure: (itemId) => {
|
|
44104
|
+
let size = measured.get(itemId);
|
|
44105
|
+
if (!size) {
|
|
44106
|
+
const item = catalogMap.get(itemId);
|
|
44107
|
+
const box2 = item ? new THREE.Box3().setFromObject(buildRoot(item)) : null;
|
|
44108
|
+
size = box2 && !box2.isEmpty() ? { w: box2.max.x - box2.min.x, d: box2.max.z - box2.min.z } : { w: 0.3, d: 0.3 };
|
|
44109
|
+
measured.set(itemId, size);
|
|
44110
|
+
}
|
|
44111
|
+
return size;
|
|
44112
|
+
},
|
|
44113
|
+
spawn: (itemId, position) => spawn2(itemId, position, 0),
|
|
44114
|
+
clear,
|
|
44115
|
+
resetAll,
|
|
44116
|
+
box: (objectId) => {
|
|
44117
|
+
const e = entries.get(objectId);
|
|
44118
|
+
if (!e || !world.has(objectId)) return null;
|
|
44119
|
+
const box2 = new THREE.Box3().setFromObject(e.so.root);
|
|
44120
|
+
return box2.isEmpty() ? null : { min: [box2.min.x, box2.min.y, box2.min.z], max: [box2.max.x, box2.max.y, box2.max.z] };
|
|
44121
|
+
},
|
|
44122
|
+
equip: (weapon) => {
|
|
44123
|
+
if (!arsenal.weapons.has(weapon)) return false;
|
|
44124
|
+
if (heldEntry) releaseHeld();
|
|
44125
|
+
equip(weapon);
|
|
44126
|
+
room.waitUntilReady();
|
|
44127
|
+
return true;
|
|
44128
|
+
},
|
|
44129
|
+
look: (eye, target) => player.look(eye, target),
|
|
44130
|
+
use: (hold) => room.use(hold),
|
|
44131
|
+
blastAt: (weapon, point) => {
|
|
44132
|
+
const def = arsenal.weapons.get(weapon);
|
|
44133
|
+
const explosive = def?.action.kind === "throwable" ? def.action.explosive : def?.action.kind === "launcher" ? def.action.projectile : void 0;
|
|
44134
|
+
return explosive !== void 0 && explosives.blastAt(weapon, explosive, point);
|
|
44135
|
+
},
|
|
44136
|
+
log: (type, text, data) => action(type, text, { data }),
|
|
44137
|
+
translate: t
|
|
44138
|
+
},
|
|
44139
|
+
tableOptions
|
|
44140
|
+
);
|
|
43685
44141
|
const room = {
|
|
43686
44142
|
world,
|
|
43687
44143
|
renderer,
|
|
@@ -43701,6 +44157,7 @@ void main(){
|
|
|
43701
44157
|
get scenarios() {
|
|
43702
44158
|
return allScenarios();
|
|
43703
44159
|
},
|
|
44160
|
+
testTable,
|
|
43704
44161
|
spawn: spawn2,
|
|
43705
44162
|
clear,
|
|
43706
44163
|
resetAll,
|
|
@@ -43708,7 +44165,8 @@ void main(){
|
|
|
43708
44165
|
useItem,
|
|
43709
44166
|
use(hold = 0) {
|
|
43710
44167
|
if (tool.def.category === "hand") {
|
|
43711
|
-
|
|
44168
|
+
handUse();
|
|
44169
|
+
flush();
|
|
43712
44170
|
return;
|
|
43713
44171
|
}
|
|
43714
44172
|
useTool(FIXED_DT, false);
|
|
@@ -43779,6 +44237,7 @@ void main(){
|
|
|
43779
44237
|
},
|
|
43780
44238
|
equip,
|
|
43781
44239
|
openArea,
|
|
44240
|
+
modules: () => [...modules.values()].map((m) => ({ id: m.id, name: m.name, group: m.group, hasArea: typeof m.area === "function" })),
|
|
43782
44241
|
openAreaAsync: (area) => loading.busy(t("loading.open_area", { area: areaLabel(area) }), () => openArea(area)),
|
|
43783
44242
|
loading,
|
|
43784
44243
|
busy: (label, work, busyOptions) => loading.busy(label, work, busyOptions),
|
|
@@ -43940,7 +44399,8 @@ void main(){
|
|
|
43940
44399
|
},
|
|
43941
44400
|
onAction: (id) => {
|
|
43942
44401
|
if (activeBench) slowly(activeBench, id, () => benches.get(activeBench)?.act(id));
|
|
43943
|
-
}
|
|
44402
|
+
},
|
|
44403
|
+
...options.testTable !== false && arena.tops.some((x) => x.id === tableScenery) ? { testTable } : {}
|
|
43944
44404
|
});
|
|
43945
44405
|
ui.hud(hudState());
|
|
43946
44406
|
showBench();
|