@adatechnology/game-items-three 0.7.0 → 0.7.2
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.global.js +238 -160
- package/dist/index.global.js.map +1 -1
- package/package.json +9 -9
package/dist/index.global.js
CHANGED
|
@@ -89,7 +89,7 @@ var GameItemsThree = (() => {
|
|
|
89
89
|
wearableMaterials: () => wearableMaterials
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
// ../game-shapes/dist/chunk-
|
|
92
|
+
// ../game-shapes/dist/chunk-M5N2SHNL.js
|
|
93
93
|
function canonicalJson(value) {
|
|
94
94
|
if (value === null) return "null";
|
|
95
95
|
if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
|
|
@@ -1246,13 +1246,13 @@ var GameItemsThree = (() => {
|
|
|
1246
1246
|
uvArray.push(x);
|
|
1247
1247
|
uvArray.push(y);
|
|
1248
1248
|
};
|
|
1249
|
-
const
|
|
1249
|
+
const at2 = (index, axis) => verticesArray[index * 3 + axis];
|
|
1250
1250
|
const f3 = (a, b, c) => {
|
|
1251
1251
|
addVertex(a);
|
|
1252
1252
|
addVertex(b);
|
|
1253
1253
|
addVertex(c);
|
|
1254
1254
|
const nextIndex = verticesArray.length / 3;
|
|
1255
|
-
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(
|
|
1255
|
+
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(at2(index, 0), at2(index, 1));
|
|
1256
1256
|
};
|
|
1257
1257
|
const f4 = (a, b, c, d) => {
|
|
1258
1258
|
addVertex(a);
|
|
@@ -1266,8 +1266,8 @@ var GameItemsThree = (() => {
|
|
|
1266
1266
|
const iB = nextIndex - 3;
|
|
1267
1267
|
const iC = nextIndex - 2;
|
|
1268
1268
|
const iD = nextIndex - 1;
|
|
1269
|
-
const byX = Math.abs(
|
|
1270
|
-
const uv = (index) => [byX ?
|
|
1269
|
+
const byX = Math.abs(at2(iA, 1) - at2(iB, 1)) < Math.abs(at2(iA, 0) - at2(iB, 0));
|
|
1270
|
+
const uv = (index) => [byX ? at2(index, 0) : at2(index, 1), 1 - at2(index, 2)];
|
|
1271
1271
|
const uvs = [uv(iA), uv(iB), uv(iC), uv(iD)];
|
|
1272
1272
|
for (const k of [0, 1, 3, 1, 2, 3]) addUV(...uvs[k]);
|
|
1273
1273
|
};
|
|
@@ -1372,8 +1372,8 @@ var GameItemsThree = (() => {
|
|
|
1372
1372
|
groups: []
|
|
1373
1373
|
};
|
|
1374
1374
|
}
|
|
1375
|
-
function make(
|
|
1376
|
-
switch (kind) {
|
|
1375
|
+
function make(p) {
|
|
1376
|
+
switch (p.kind) {
|
|
1377
1377
|
case "box": {
|
|
1378
1378
|
const size = p.size ?? [1, 1, 1];
|
|
1379
1379
|
const segments = p.segments ?? [1, 1, 1];
|
|
@@ -1402,7 +1402,7 @@ var GameItemsThree = (() => {
|
|
|
1402
1402
|
case "mesh":
|
|
1403
1403
|
return mesh(p);
|
|
1404
1404
|
default:
|
|
1405
|
-
throw new Error(`game-shapes: unknown primitive kind "${String(kind)}"`);
|
|
1405
|
+
throw new Error(`game-shapes: unknown primitive kind "${String(p.kind)}"`);
|
|
1406
1406
|
}
|
|
1407
1407
|
}
|
|
1408
1408
|
var templates = /* @__PURE__ */ new Map();
|
|
@@ -1410,7 +1410,7 @@ var GameItemsThree = (() => {
|
|
|
1410
1410
|
var stats = { hits: 0, misses: 0 };
|
|
1411
1411
|
function buildPrimitive(node, options = {}) {
|
|
1412
1412
|
const parameters = primitiveParameters(node, options);
|
|
1413
|
-
if (node.kind === "mesh" || templateLimit === 0) return make(node
|
|
1413
|
+
if (node.kind === "mesh" || templateLimit === 0) return make({ ...node, ...parameters });
|
|
1414
1414
|
const key2 = `${node.kind}:${canonicalJson(parameters)}`;
|
|
1415
1415
|
const cached = templates.get(key2);
|
|
1416
1416
|
if (cached) {
|
|
@@ -1420,7 +1420,7 @@ var GameItemsThree = (() => {
|
|
|
1420
1420
|
return cached;
|
|
1421
1421
|
}
|
|
1422
1422
|
stats.misses++;
|
|
1423
|
-
const built = make(node
|
|
1423
|
+
const built = make({ ...node, ...parameters });
|
|
1424
1424
|
templates.set(key2, built);
|
|
1425
1425
|
if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
|
|
1426
1426
|
return built;
|
|
@@ -1518,7 +1518,7 @@ var GameItemsThree = (() => {
|
|
|
1518
1518
|
const positions2 = new Float32Array(total * 3);
|
|
1519
1519
|
const normals = new Float32Array(total * 3);
|
|
1520
1520
|
const uvs = new Float32Array(total * 2);
|
|
1521
|
-
let
|
|
1521
|
+
let at2 = 0;
|
|
1522
1522
|
for (const piece2 of pieces) {
|
|
1523
1523
|
const e = piece2.matrix;
|
|
1524
1524
|
const nm = normalMatrix(e);
|
|
@@ -1532,15 +1532,15 @@ var GameItemsThree = (() => {
|
|
|
1532
1532
|
if (piece2.normals) n[k * 3 + c] = piece2.normals[i * 3 + c];
|
|
1533
1533
|
}
|
|
1534
1534
|
if (piece2.uvs) {
|
|
1535
|
-
uvs[(
|
|
1536
|
-
uvs[(
|
|
1535
|
+
uvs[(at2 + k) * 2] = piece2.uvs[i * 2];
|
|
1536
|
+
uvs[(at2 + k) * 2 + 1] = piece2.uvs[i * 2 + 1];
|
|
1537
1537
|
}
|
|
1538
1538
|
}
|
|
1539
1539
|
for (let k = 0; k < count; k++) {
|
|
1540
1540
|
const q = transformPoint(e, p[k * 3], p[k * 3 + 1], p[k * 3 + 2]);
|
|
1541
|
-
positions2[(
|
|
1542
|
-
positions2[(
|
|
1543
|
-
positions2[(
|
|
1541
|
+
positions2[(at2 + k) * 3] = q[0];
|
|
1542
|
+
positions2[(at2 + k) * 3 + 1] = q[1];
|
|
1543
|
+
positions2[(at2 + k) * 3 + 2] = q[2];
|
|
1544
1544
|
const x = n[k * 3];
|
|
1545
1545
|
const y = n[k * 3 + 1];
|
|
1546
1546
|
const z = n[k * 3 + 2];
|
|
@@ -1548,16 +1548,17 @@ var GameItemsThree = (() => {
|
|
|
1548
1548
|
const vy = nm[1] * x + nm[4] * y + nm[7] * z;
|
|
1549
1549
|
const vz = nm[2] * x + nm[5] * y + nm[8] * z;
|
|
1550
1550
|
const s = 1 / (Math.sqrt(vx * vx + vy * vy + vz * vz) || 1);
|
|
1551
|
-
normals[(
|
|
1552
|
-
normals[(
|
|
1553
|
-
normals[(
|
|
1551
|
+
normals[(at2 + k) * 3] = vx * s;
|
|
1552
|
+
normals[(at2 + k) * 3 + 1] = vy * s;
|
|
1553
|
+
normals[(at2 + k) * 3 + 2] = vz * s;
|
|
1554
1554
|
}
|
|
1555
|
-
|
|
1555
|
+
at2 += count;
|
|
1556
1556
|
}
|
|
1557
1557
|
return { positions: positions2, normals, uvs };
|
|
1558
1558
|
}
|
|
1559
1559
|
|
|
1560
1560
|
// ../game-contracts/dist/index.js
|
|
1561
|
+
var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
|
|
1561
1562
|
var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
|
|
1562
1563
|
var DEFAULT_IGNITION_RULES = {
|
|
1563
1564
|
fillCurve: [
|
|
@@ -11385,17 +11386,17 @@ var GameItemsThree = (() => {
|
|
|
11385
11386
|
const index = geometry2.index ? geometry2.index.array : null;
|
|
11386
11387
|
const count = index ? index.length : position.count;
|
|
11387
11388
|
for (let item = 0; item < count; item++) {
|
|
11388
|
-
const
|
|
11389
|
-
vertex.fromBufferAttribute(position,
|
|
11389
|
+
const at2 = index ? index[item] : item;
|
|
11390
|
+
vertex.fromBufferAttribute(position, at2).applyMatrix4(matrix);
|
|
11390
11391
|
positions2.push(vertex.x, vertex.y, vertex.z);
|
|
11391
|
-
if (normalAttribute) normal.fromBufferAttribute(normalAttribute,
|
|
11392
|
+
if (normalAttribute) normal.fromBufferAttribute(normalAttribute, at2).applyMatrix3(normalMatrix2).normalize();
|
|
11392
11393
|
else normal.set(0, 1, 0);
|
|
11393
11394
|
normals.push(normal.x, normal.y, normal.z);
|
|
11394
11395
|
color2.copy(material2.color || color2.set(1, 1, 1)).convertLinearToSRGB();
|
|
11395
11396
|
if (sample && uv && material2.map) {
|
|
11396
11397
|
const repeat = material2.map.repeat;
|
|
11397
|
-
const u = (uv.getX(
|
|
11398
|
-
const v = (uv.getY(
|
|
11398
|
+
const u = (uv.getX(at2) * repeat.x % 1 + 1) % 1;
|
|
11399
|
+
const v = (uv.getY(at2) * repeat.y % 1 + 1) % 1;
|
|
11399
11400
|
const pixelX = Math.min(sample.width - 1, u * sample.width | 0);
|
|
11400
11401
|
const pixelY = Math.min(sample.height - 1, (1 - v) * sample.height | 0);
|
|
11401
11402
|
const offset = (pixelY * sample.width + pixelX) * 4;
|
|
@@ -12073,8 +12074,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12073
12074
|
// was `maquina`
|
|
12074
12075
|
});
|
|
12075
12076
|
var OWN_TYPES = Object.freeze({ lamp: true, gas_piped: true });
|
|
12077
|
+
var sourceOf = (result) => result;
|
|
12076
12078
|
var ADAPTER_VERSION = "0.3.0";
|
|
12077
12079
|
var r3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
12080
|
+
var at = (it) => ({ x: it.x ?? 0, z: it.z ?? 0, ry: it.ry ?? 0 });
|
|
12078
12081
|
function mergeRegistry(base, extra) {
|
|
12079
12082
|
const out = { ...base };
|
|
12080
12083
|
if (extra) {
|
|
@@ -12093,14 +12096,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12093
12096
|
});
|
|
12094
12097
|
function create2(options = {}) {
|
|
12095
12098
|
const opts = options || {};
|
|
12096
|
-
const GI = opts.GameInteractables;
|
|
12097
|
-
const HH = opts.GameInteractablesHousehold;
|
|
12098
12099
|
const locale = opts.locale || "pt-BR";
|
|
12099
12100
|
const msg = createTranslator(locale, opts.messages);
|
|
12100
|
-
if (!
|
|
12101
|
+
if (!opts.GameInteractables || !opts.GameInteractablesHousehold) throw new Error(msg("error.missingKit"));
|
|
12102
|
+
const GI = opts.GameInteractables;
|
|
12103
|
+
const HH = opts.GameInteractablesHousehold;
|
|
12101
12104
|
const region = opts.region || "br";
|
|
12102
12105
|
const hh = HH.createHousehold({ locale, region });
|
|
12103
12106
|
const householdTypes = new Set(hh.types.map((t) => t.id));
|
|
12107
|
+
const recorderApi = () => HH.createRecorder().api;
|
|
12104
12108
|
const worlds = /* @__PURE__ */ new WeakMap();
|
|
12105
12109
|
const typeMap = mergeRegistry(TYPE_MAP, opts.typeMap);
|
|
12106
12110
|
const contentMap = mergeRegistry(CONTENT_MAP, opts.contentMap);
|
|
@@ -12136,7 +12140,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12136
12140
|
function colorOf(res, color2) {
|
|
12137
12141
|
if (color2 == null) return void 0;
|
|
12138
12142
|
if (typeof color2 === "number") return color2;
|
|
12139
|
-
const v = res.colors && res.colors[color2];
|
|
12143
|
+
const v = res.colors && res.colors[String(color2)];
|
|
12140
12144
|
return typeof v === "number" ? v : void 0;
|
|
12141
12145
|
}
|
|
12142
12146
|
function paletteOf(res) {
|
|
@@ -12165,17 +12169,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12165
12169
|
drawerItem: (s) => drawerItems.has(s.itemId)
|
|
12166
12170
|
};
|
|
12167
12171
|
const itemOfContent = (c) => {
|
|
12168
|
-
const
|
|
12172
|
+
const group = stackGroup(c);
|
|
12173
|
+
const id = contentMap[c.itemId] || (hh.items[c.itemId] ? c.itemId : null) || (group != null ? contentByGroup[group] : void 0) || contentFallback;
|
|
12169
12174
|
return hh.items[id] ? id : contentFallback;
|
|
12170
12175
|
};
|
|
12171
12176
|
const volume = (d) => d.size[0] * d.size[1] * d.size[2];
|
|
12172
12177
|
const candidates = (id, objectType) => {
|
|
12173
12178
|
const def = hh.items[id];
|
|
12174
|
-
const siblings = Object.values(hh.items).filter((i) => i.category === def
|
|
12179
|
+
const siblings = Object.values(hh.items).filter((i) => i.category === def?.category && i.id !== id).sort((a, b) => volume(a) - volume(b) || (a.id < b.id ? -1 : 1));
|
|
12175
12180
|
return [id].concat(siblings.map((i) => i.id), substitutes[objectType] || []);
|
|
12176
12181
|
};
|
|
12177
12182
|
function distribute(type, probeItem, stacks) {
|
|
12178
|
-
const spec = hh.build(type, probeItem,
|
|
12183
|
+
const spec = hh.build(type, probeItem, recorderApi());
|
|
12179
12184
|
const conts = spec.containers || [];
|
|
12180
12185
|
const contents = {};
|
|
12181
12186
|
for (const c of conts) contents[c.id] = c.slots.map(() => null);
|
|
@@ -12206,8 +12211,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12206
12211
|
}
|
|
12207
12212
|
return { contents, rejected };
|
|
12208
12213
|
}
|
|
12209
|
-
function plan(
|
|
12210
|
-
|
|
12214
|
+
function plan(source, options2 = {}) {
|
|
12215
|
+
const res = sourceOf(source);
|
|
12216
|
+
const popts = options2 || {};
|
|
12211
12217
|
const o = { ox: popts.originX || 0, oz: popts.originZ || 0, inw: popts.inw || 1, base: popts.base || 0 };
|
|
12212
12218
|
const K = conv(o);
|
|
12213
12219
|
const floorSel = popts.floor;
|
|
@@ -12271,7 +12277,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12271
12277
|
const item = {
|
|
12272
12278
|
x: K.x(m.x),
|
|
12273
12279
|
z: K.z(m.z),
|
|
12274
|
-
ry: m.frontU != null ? K.ry(m.frontU, m.frontV) : r3(m.ry || 0),
|
|
12280
|
+
ry: m.frontU != null ? K.ry(m.frontU, m.frontV ?? 0) : r3(m.ry || 0),
|
|
12275
12281
|
w: m.w,
|
|
12276
12282
|
d: m.d,
|
|
12277
12283
|
h: m.h,
|
|
@@ -12284,7 +12290,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12284
12290
|
return item;
|
|
12285
12291
|
}
|
|
12286
12292
|
function entry2(id, type, item, origin, floor, extra) {
|
|
12287
|
-
|
|
12293
|
+
const e = { id, type, item, origin, floor, floorY: floorYOf(res, o, floor), connections: {} };
|
|
12294
|
+
return Object.assign(e, extra || {});
|
|
12288
12295
|
}
|
|
12289
12296
|
function store(targets, stacks) {
|
|
12290
12297
|
let rest2 = stacks || [];
|
|
@@ -12297,10 +12304,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12297
12304
|
}
|
|
12298
12305
|
const hidden = [];
|
|
12299
12306
|
function distRect(c, x, z) {
|
|
12300
|
-
const
|
|
12301
|
-
const
|
|
12302
|
-
const
|
|
12303
|
-
const
|
|
12307
|
+
const ci = at(c.item);
|
|
12308
|
+
const dx = x - ci.x;
|
|
12309
|
+
const dz = z - ci.z;
|
|
12310
|
+
const s = Math.sin(ci.ry);
|
|
12311
|
+
const co = Math.cos(ci.ry);
|
|
12304
12312
|
const lx = dx * co - dz * s;
|
|
12305
12313
|
const lz = dx * s + dz * co;
|
|
12306
12314
|
return Math.hypot(Math.max(Math.abs(lx) - (c.item.w || 0) / 2, 0), Math.max(Math.abs(lz) - (c.item.d || 0) / 2, 0));
|
|
@@ -12308,9 +12316,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12308
12316
|
function hideCylinders() {
|
|
12309
12317
|
for (const b of hidden) {
|
|
12310
12318
|
let target = null;
|
|
12319
|
+
const bi = at(b.item);
|
|
12311
12320
|
for (const c2 of result.items) {
|
|
12312
12321
|
if (c2.type !== "kitchen_cabinet_base" || c2.floor !== b.floor) continue;
|
|
12313
|
-
const dist = distRect(c2,
|
|
12322
|
+
const dist = distRect(c2, bi.x, bi.z);
|
|
12314
12323
|
if (!target || dist < target.dist) target = { c: c2, dist };
|
|
12315
12324
|
}
|
|
12316
12325
|
if (!target) {
|
|
@@ -12318,16 +12327,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12318
12327
|
continue;
|
|
12319
12328
|
}
|
|
12320
12329
|
const c = target.c;
|
|
12321
|
-
const spec = hh.build(c.type, c.item,
|
|
12322
|
-
const
|
|
12323
|
-
const
|
|
12330
|
+
const spec = hh.build(c.type, c.item, recorderApi());
|
|
12331
|
+
const ci = at(c.item);
|
|
12332
|
+
const sn = Math.sin(ci.ry);
|
|
12333
|
+
const cs = Math.cos(ci.ry);
|
|
12324
12334
|
let door = null;
|
|
12325
12335
|
for (const it of spec.interactions || []) {
|
|
12326
|
-
const
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
const
|
|
12330
|
-
const
|
|
12336
|
+
const action = it.action;
|
|
12337
|
+
const pt = action.do === "toggle_part" ? (spec.parts || []).find((q) => q.id === action.part) : null;
|
|
12338
|
+
if (!pt || !pt.motion || pt.motion.kind !== "hinge") continue;
|
|
12339
|
+
const wx = ci.x + it.pos[0] * cs + it.pos[2] * sn;
|
|
12340
|
+
const wz = ci.z - it.pos[0] * sn + it.pos[2] * cs;
|
|
12341
|
+
const dist = Math.hypot(wx - bi.x, wz - bi.z);
|
|
12331
12342
|
if (!door || dist < door.dist) door = { id: pt.id, dist };
|
|
12332
12343
|
}
|
|
12333
12344
|
if (!door) {
|
|
@@ -12357,9 +12368,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12357
12368
|
const campCylinder = firstOfType("gas_canister");
|
|
12358
12369
|
function planFireplace(m, e, item) {
|
|
12359
12370
|
const def = hh.types.find((t) => t.id === "fireplace");
|
|
12360
|
-
const lack = (def.d - m.d) / 2;
|
|
12361
|
-
|
|
12362
|
-
item.
|
|
12371
|
+
const lack = ((def ? def.d : m.d) - m.d) / 2;
|
|
12372
|
+
const p = at(item);
|
|
12373
|
+
item.x = r3(p.x + Math.sin(p.ry) * lack);
|
|
12374
|
+
item.z = r3(p.z + Math.cos(p.ry) * lack);
|
|
12363
12375
|
const room = (res.rooms || []).find((c) => c.id === m.room && c.floor === m.floor);
|
|
12364
12376
|
const f = (res.floors || []).find((x) => x.index === m.floor);
|
|
12365
12377
|
item.h = r3(room && room.ceiling || f && f.ceiling || 2.6);
|
|
@@ -12387,7 +12399,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12387
12399
|
e.connections.gas = m.gas || "cylinder";
|
|
12388
12400
|
e.connections.cylinder = m.cylinder || null;
|
|
12389
12401
|
}
|
|
12390
|
-
if (map.type === "gas_bottle") result.cylinders.push({ id: e.id, stove: m.link
|
|
12402
|
+
if (map.type === "gas_bottle") result.cylinders.push({ id: e.id, stove: typeof m.link === "string" ? m.link : null, place: m.placement || null });
|
|
12391
12403
|
if (map.type === "gas_canister") {
|
|
12392
12404
|
result.canisters.push(e.id);
|
|
12393
12405
|
if (campCylinder && campCylinder.id === m.id && campStove2) result.cylinders.push({ id: e.id, stove: campStove2.id, place: null });
|
|
@@ -12411,7 +12423,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12411
12423
|
push(e);
|
|
12412
12424
|
}
|
|
12413
12425
|
function planCompound(m, kind) {
|
|
12414
|
-
const ry = m.frontU != null ? K.ry(m.frontU, m.frontV) : r3(m.ry || 0);
|
|
12426
|
+
const ry = m.frontU != null ? K.ry(m.frontU, m.frontV ?? 0) : r3(m.ry || 0);
|
|
12415
12427
|
const cx = K.x(m.x);
|
|
12416
12428
|
const cz = K.z(m.z);
|
|
12417
12429
|
const part = (id, type, w, d, h, y, lx, lz) => {
|
|
@@ -12463,11 +12475,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12463
12475
|
} else {
|
|
12464
12476
|
const basin = part(m.id, "sink_bathroom", m.w, m.d, m.h + 0.2, 0, 0, 0);
|
|
12465
12477
|
list2.push(basin);
|
|
12466
|
-
|
|
12467
|
-
|
|
12478
|
+
const own = contents[m.id];
|
|
12479
|
+
if (own) {
|
|
12480
|
+
if (own.length) {
|
|
12468
12481
|
const cabinet = part(m.id + "#cabinet", "bathroom_cabinet", Math.max(0.45, Math.min(0.6, m.w)), 0.15, 0.75, 1.3, 0, -(m.d / 2) + 0.075);
|
|
12469
12482
|
list2.push(cabinet);
|
|
12470
|
-
store([["bathroom_cabinet", cabinet.item], ["sink_bathroom", basin.item]],
|
|
12483
|
+
store([["bathroom_cabinet", cabinet.item], ["sink_bathroom", basin.item]], own);
|
|
12471
12484
|
} else {
|
|
12472
12485
|
store([["sink_bathroom", basin.item]], []);
|
|
12473
12486
|
}
|
|
@@ -12507,7 +12520,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12507
12520
|
result.chairs = [];
|
|
12508
12521
|
if (opts.chairs !== false && popts.chairs !== false) {
|
|
12509
12522
|
const blocked = blockedOf(res, { originX: o.ox, originZ: o.oz, inw: o.inw });
|
|
12510
|
-
const floorKind = (q) => !q.decor && !q.flat && (q.y || 0) < 0.9 && q.aabb;
|
|
12523
|
+
const floorKind = (q) => !q.decor && !q.flat && (q.y || 0) < 0.9 && !!q.aabb;
|
|
12511
12524
|
const placed = [];
|
|
12512
12525
|
const free = (m, cu, cv, half) => {
|
|
12513
12526
|
const a = [cu - half + 0.03, cv - half + 0.03, cu + half - 0.03, cv + half - 0.03];
|
|
@@ -12523,8 +12536,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12523
12536
|
for (const m of res.items || []) {
|
|
12524
12537
|
const mode = chairTables[m.type];
|
|
12525
12538
|
if (!mode || !onFloor(m.floor, m.outdoor) || m.frontU == null) continue;
|
|
12526
|
-
const
|
|
12527
|
-
const
|
|
12539
|
+
const fv = m.frontV ?? 0;
|
|
12540
|
+
const f = [m.frontU, fv];
|
|
12541
|
+
const pp = [-fv, m.frontU];
|
|
12528
12542
|
const seats = [];
|
|
12529
12543
|
if (mode === "dining") {
|
|
12530
12544
|
const n = Math.max(1, Math.min(3, Math.floor((m.w - 0.1) / 0.55)));
|
|
@@ -12593,8 +12607,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12593
12607
|
const item = { x: K.x(s.u), z: K.z(s.v), ry: K.ry(s.frontU, s.frontV), y: s.y, seed: seedOf2(s.id) };
|
|
12594
12608
|
item.controls = (s.controls || []).map((id) => id + ":lamp");
|
|
12595
12609
|
const e = entry2(s.id, "wall_switch", item, s.id, s.floor);
|
|
12596
|
-
|
|
12597
|
-
e.
|
|
12610
|
+
const controls = (s.controls || []).slice();
|
|
12611
|
+
e.connections.controls = controls;
|
|
12612
|
+
e.lit = controls.some((id) => result.items.find((x) => x.id === id)?.lit === true);
|
|
12598
12613
|
if (floorSel == null) {
|
|
12599
12614
|
for (const id of s.controls || []) if (!lights.has(id)) result.warnings.push(msg("warn.switchUnknownLamp", { id: s.id, lamp: id }));
|
|
12600
12615
|
}
|
|
@@ -12634,7 +12649,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12634
12649
|
seed: seedOf2("panel"),
|
|
12635
12650
|
circuits: circuits.map((c) => ({ id: c.id, label: c.room }))
|
|
12636
12651
|
};
|
|
12637
|
-
if (!item.circuits
|
|
12652
|
+
if (!item.circuits?.length) delete item.circuits;
|
|
12638
12653
|
const e = entry2("panel", "electrical_panel", item, "panel", q.floor);
|
|
12639
12654
|
push(e);
|
|
12640
12655
|
result.panel = e.id;
|
|
@@ -12656,10 +12671,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12656
12671
|
}
|
|
12657
12672
|
}
|
|
12658
12673
|
const piped = result.items.filter((e) => e.type === "stove" && e.connections.gas === "piped");
|
|
12659
|
-
|
|
12674
|
+
const firstPiped = piped[0];
|
|
12675
|
+
if (firstPiped) {
|
|
12660
12676
|
const med = utilities.gas && utilities.gas.meter;
|
|
12661
|
-
const ref = med ? { x: K.x(med.u), z: K.z(med.v), y: med.y || 1 } : { x:
|
|
12662
|
-
const e = entry2("piped_gas", "gas_piped", { x: ref.x, z: ref.z, ry: 0, y: ref.y, seed: seedOf2("piped_gas") }, "piped_gas",
|
|
12677
|
+
const ref = med ? { x: K.x(med.u), z: K.z(med.v), y: med.y || 1 } : { x: firstPiped.item.x, z: firstPiped.item.z, y: 0.3 };
|
|
12678
|
+
const e = entry2("piped_gas", "gas_piped", { x: ref.x, z: ref.z, ry: 0, y: ref.y, seed: seedOf2("piped_gas") }, "piped_gas", firstPiped.floor);
|
|
12663
12679
|
e.floorY = o.base;
|
|
12664
12680
|
push(e);
|
|
12665
12681
|
for (const f of piped) f.connections.fuel = "piped_gas:gas";
|
|
@@ -12706,9 +12722,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12706
12722
|
for (const dv of spec.devices || []) if (L.outlet && dv.socket === "auto") dv.socket = L.outlet + ":socket";
|
|
12707
12723
|
} else {
|
|
12708
12724
|
const sh = L.shower || {};
|
|
12709
|
-
const
|
|
12725
|
+
const devices = spec.devices || [];
|
|
12726
|
+
const heater = devices.find((d) => d.id === "heater");
|
|
12710
12727
|
if (heater && sh.electric === false) {
|
|
12711
|
-
spec.devices =
|
|
12728
|
+
spec.devices = devices.filter((d) => d !== heater);
|
|
12712
12729
|
for (const f of spec.fixtures || []) if (f.heater === "heater") delete f.heater;
|
|
12713
12730
|
} else if (heater) {
|
|
12714
12731
|
if (sh.powerW) heater.watts = sh.powerW;
|
|
@@ -12719,7 +12736,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12719
12736
|
for (const b of spec.burners || []) if (b.fuel === "auto") b.fuel = L.fuel;
|
|
12720
12737
|
}
|
|
12721
12738
|
if (entry2.type === "fireplace" && L.chimneyTop) {
|
|
12722
|
-
const it = entry2.item;
|
|
12739
|
+
const it = at(entry2.item);
|
|
12723
12740
|
const dx = L.chimneyTop[0] - it.x;
|
|
12724
12741
|
const dz = L.chimneyTop[2] - it.z;
|
|
12725
12742
|
const lx = Math.cos(it.ry) * dx - Math.sin(it.ry) * dz;
|
|
@@ -12738,8 +12755,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12738
12755
|
}
|
|
12739
12756
|
return spec;
|
|
12740
12757
|
}
|
|
12741
|
-
function createWorld(
|
|
12742
|
-
|
|
12758
|
+
function createWorld(source, options2 = {}) {
|
|
12759
|
+
const res = sourceOf(source);
|
|
12760
|
+
const copts = options2 || {};
|
|
12743
12761
|
const info = { points: /* @__PURE__ */ new Map(), water: copts.water || null, lightsOn: copts.lightsOn };
|
|
12744
12762
|
const electrical = res.utilities && res.utilities.electrical;
|
|
12745
12763
|
const world = GI.createWorld({
|
|
@@ -12767,8 +12785,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12767
12785
|
const info = worlds.get(world);
|
|
12768
12786
|
return info ? info.points.get(fixtureId) : void 0;
|
|
12769
12787
|
}
|
|
12770
|
-
function blockedOf(
|
|
12771
|
-
|
|
12788
|
+
function blockedOf(source, options2 = {}) {
|
|
12789
|
+
const res = sourceOf(source);
|
|
12790
|
+
const bopts = options2 || {};
|
|
12772
12791
|
const ox = bopts.originX || 0;
|
|
12773
12792
|
const oz = bopts.originZ || 0;
|
|
12774
12793
|
const inw = bopts.inw || 1;
|
|
@@ -12803,33 +12822,33 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12803
12822
|
return false;
|
|
12804
12823
|
};
|
|
12805
12824
|
}
|
|
12806
|
-
function add(world, planned,
|
|
12807
|
-
aopts =
|
|
12825
|
+
function add(world, planned, options2 = {}) {
|
|
12826
|
+
const aopts = options2 || {};
|
|
12808
12827
|
const info = worlds.get(world);
|
|
12809
|
-
const build = aopts.build || ((type, item) => hh.build(type, item,
|
|
12828
|
+
const build = aopts.build || ((type, item) => hh.build(type, item, recorderApi()));
|
|
12810
12829
|
const isBlocked = aopts.isBlocked || null;
|
|
12811
12830
|
const out = { added: 0, parts: [], hinges: {}, moved: {}, warnings: [] };
|
|
12812
12831
|
const override = aopts.lightsOn !== void 0 ? aopts.lightsOn : info && info.lightsOn;
|
|
12813
12832
|
if (override !== void 0) {
|
|
12814
12833
|
for (const e of planned.items) if (e.type === "lamp") e.lit = typeof override === "function" ? !!override(e.id, e) : !!override;
|
|
12815
12834
|
for (const e of planned.items) if (e.type === "lantern_lamp") e.lit = typeof override === "function" ? !!override(e.id, e) : !!override;
|
|
12816
|
-
for (const e of planned.items) if (e.type === "wall_switch") e.lit = (e.connections.controls || []).some((id) =>
|
|
12835
|
+
for (const e of planned.items) if (e.type === "wall_switch") e.lit = (e.connections.controls || []).some((id) => planned.items.find((x) => x.id === id)?.lit === true);
|
|
12817
12836
|
}
|
|
12818
12837
|
for (const e of planned.items) if (e.type === "lantern_lamp") e.item.on = !!e.lit;
|
|
12819
12838
|
let scratch = null;
|
|
12820
|
-
function probe(e, hinge, setback) {
|
|
12839
|
+
function probe(e, hinge, setback, blockedAt) {
|
|
12821
12840
|
if (!scratch) scratch = GI.createWorld({ locale, strings: hh.strings, items: hh.items, loot: hh.loot, grid: false });
|
|
12822
|
-
const it = e.item;
|
|
12841
|
+
const it = at(e.item);
|
|
12823
12842
|
const x = it.x + Math.sin(it.ry) * setback;
|
|
12824
12843
|
const z = it.z + Math.cos(it.ry) * setback;
|
|
12825
|
-
const spec = hh.build(e.type, Object.assign({},
|
|
12844
|
+
const spec = hh.build(e.type, Object.assign({}, e.item, { hinge }), recorderApi());
|
|
12826
12845
|
scratch.add("__probe", spec, { x, y: e.floorY, z, ry: it.ry });
|
|
12827
|
-
const blocks = (px, pz) =>
|
|
12846
|
+
const blocks = (px, pz) => blockedAt(px, pz, e.floor);
|
|
12828
12847
|
let sum = 0;
|
|
12829
12848
|
let min = 1;
|
|
12830
12849
|
let n = 0;
|
|
12831
12850
|
for (const p of spec.parts || []) {
|
|
12832
|
-
if (p.motion.kind !== "hinge" || !(p.bounds || p.sweep)) continue;
|
|
12851
|
+
if (!p.motion || p.motion.kind !== "hinge" || !(p.bounds || p.sweep)) continue;
|
|
12833
12852
|
const t = scratch.fitSweep("__probe", p.id, blocks);
|
|
12834
12853
|
sum += t;
|
|
12835
12854
|
min = Math.min(min, t);
|
|
@@ -12841,12 +12860,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12841
12860
|
const better = (a, b) => a.sum > b.sum + 1e-9 || Math.abs(a.sum - b.sum) <= 1e-9 && a.min > b.min + 1e-9;
|
|
12842
12861
|
function fitDoors(e) {
|
|
12843
12862
|
if (!isBlocked || !householdTypes.has(e.type)) return;
|
|
12844
|
-
const standard = probe(e, void 0, 0);
|
|
12863
|
+
const standard = probe(e, void 0, 0, isBlocked);
|
|
12845
12864
|
if (!standard.n || standard.min >= 1) return;
|
|
12846
12865
|
let bestSide;
|
|
12847
12866
|
let m = standard;
|
|
12848
12867
|
for (const side of ["left", "right"]) {
|
|
12849
|
-
const r = probe(e, side, 0);
|
|
12868
|
+
const r = probe(e, side, 0, isBlocked);
|
|
12850
12869
|
if (better(r, m)) {
|
|
12851
12870
|
m = r;
|
|
12852
12871
|
bestSide = side;
|
|
@@ -12859,13 +12878,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12859
12878
|
if (m.min >= 1) return;
|
|
12860
12879
|
let target = { setback: 0, r: m };
|
|
12861
12880
|
for (const setback of [0.01, 0.02, 0.03, 0.04]) {
|
|
12862
|
-
const r = probe(e, bestSide, setback);
|
|
12881
|
+
const r = probe(e, bestSide, setback, isBlocked);
|
|
12863
12882
|
if (better(r, target.r)) target = { setback, r };
|
|
12864
12883
|
if (r.min >= 1) break;
|
|
12865
12884
|
}
|
|
12866
12885
|
if (target.setback > 0 && target.r.sum > m.sum + 0.2) {
|
|
12867
|
-
|
|
12868
|
-
e.item.
|
|
12886
|
+
const p = at(e.item);
|
|
12887
|
+
e.item.x = r3(p.x + Math.sin(p.ry) * target.setback);
|
|
12888
|
+
e.item.z = r3(p.z + Math.cos(p.ry) * target.setback);
|
|
12869
12889
|
e.moved = target.setback;
|
|
12870
12890
|
out.moved[e.id] = target.setback;
|
|
12871
12891
|
}
|
|
@@ -12888,7 +12908,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
12888
12908
|
}
|
|
12889
12909
|
}
|
|
12890
12910
|
connect(e, spec);
|
|
12891
|
-
|
|
12911
|
+
const pose = at(e.item);
|
|
12912
|
+
world.add(e.id, spec, { x: pose.x, y: e.floorY, z: pose.z, ry: pose.ry });
|
|
12892
12913
|
out.added++;
|
|
12893
12914
|
if (!isBlocked) continue;
|
|
12894
12915
|
for (const p of spec.parts || []) {
|
|
@@ -13251,11 +13272,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
13251
13272
|
}
|
|
13252
13273
|
return pieces.slice(0, limit).map((p) => ({ center: p.c, size: [p.s[g], p.s[a], p.s[b]], q: frame(g, a, b), shape: "splinter", weight: p.s[0] * p.s[1] * p.s[2] }));
|
|
13253
13274
|
};
|
|
13254
|
-
var severAt = (inp, root,
|
|
13275
|
+
var severAt = (inp, root, at2, gap) => {
|
|
13255
13276
|
const dims = root.s;
|
|
13256
13277
|
const L = [0, 1, 2].sort((x, y) => dims[y] - dims[x])[0];
|
|
13257
13278
|
const half = dims[L] / 2;
|
|
13258
|
-
const lo = clamp(
|
|
13279
|
+
const lo = clamp(at2 - gap / 2, -half, half), hi = clamp(at2 + gap / 2, -half, half);
|
|
13259
13280
|
const out = [];
|
|
13260
13281
|
const stub = (from, to) => {
|
|
13261
13282
|
if (to - from < 0.02) return;
|
|
@@ -15637,7 +15658,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15637
15658
|
const typed = listeners.get(e.type);
|
|
15638
15659
|
if (typed) for (const fn of [...typed]) fn(e);
|
|
15639
15660
|
};
|
|
15640
|
-
|
|
15661
|
+
let blow;
|
|
15662
|
+
const base = (o, source) => ({
|
|
15663
|
+
object: o.id,
|
|
15664
|
+
time,
|
|
15665
|
+
...source === void 0 ? {} : { source },
|
|
15666
|
+
...blow === void 0 ? {} : { blow }
|
|
15667
|
+
});
|
|
15641
15668
|
const pendingCollapse = /* @__PURE__ */ new Map();
|
|
15642
15669
|
let runDepth = 0;
|
|
15643
15670
|
const drainBlasts = () => {
|
|
@@ -15907,9 +15934,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15907
15934
|
const [lo, hi] = contactBox(p, above);
|
|
15908
15935
|
return toWorld(p.pos, p.q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2]);
|
|
15909
15936
|
};
|
|
15910
|
-
const overSupportAt = (o, p,
|
|
15937
|
+
const overSupportAt = (o, p, at2, lower) => {
|
|
15911
15938
|
const g = p.bend;
|
|
15912
|
-
const local = toLocal(p.pos, p.q,
|
|
15939
|
+
const local = toLocal(p.pos, p.q, at2);
|
|
15913
15940
|
const depth = g.gravity >= 0 ? g.dims[g.gravity] : Math.min(...g.depthAxes.map((a) => g.dims[a]));
|
|
15914
15941
|
let best = -1;
|
|
15915
15942
|
let bestGap = depth;
|
|
@@ -16063,10 +16090,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16063
16090
|
const incoming = new Array(n).fill(0);
|
|
16064
16091
|
const bending = new Array(n).fill(0);
|
|
16065
16092
|
const through = parts.map(() => []);
|
|
16066
|
-
const pass = (k,
|
|
16067
|
-
const over = overSupportAt(o, parts[k],
|
|
16093
|
+
const pass = (k, at2, mass) => {
|
|
16094
|
+
const over = overSupportAt(o, parts[k], at2, lowerOf.get(k) ?? []);
|
|
16068
16095
|
if (over < 0) bending[k] += mass;
|
|
16069
|
-
else through[k].push({ at, mass, over });
|
|
16096
|
+
else through[k].push({ at: at2, mass, over });
|
|
16070
16097
|
};
|
|
16071
16098
|
for (let h = queue.length - 1; h >= 0; h--) {
|
|
16072
16099
|
const i = queue[h];
|
|
@@ -16133,7 +16160,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16133
16160
|
const terrain = cfg.terrains.get(cfg.terrain);
|
|
16134
16161
|
if (!terrain) throw new Error(`unknown wind terrain "${cfg.terrain}"`);
|
|
16135
16162
|
const inputs = [];
|
|
16136
|
-
const
|
|
16163
|
+
const at2 = /* @__PURE__ */ new Map();
|
|
16137
16164
|
const keep = [];
|
|
16138
16165
|
let ground = Infinity, foundationTop = -Infinity;
|
|
16139
16166
|
o.parts.forEach((p, i) => {
|
|
@@ -16142,7 +16169,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16142
16169
|
const role = p.spec.structure?.role;
|
|
16143
16170
|
const e = p.mat.strength?.elasticGPa;
|
|
16144
16171
|
const kind = role === "wall" ? "wall" : role === "column" ? "column" : role === "beam" ? "beam" : role === "foundation" ? "foundation" : "other";
|
|
16145
|
-
|
|
16172
|
+
at2.set(i, inputs.length);
|
|
16146
16173
|
keep.push(i);
|
|
16147
16174
|
ground = Math.min(ground, box4.min[1]);
|
|
16148
16175
|
if (kind === "foundation") foundationTop = Math.max(foundationTop, box4.max[1]);
|
|
@@ -16153,7 +16180,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16153
16180
|
const beams = [];
|
|
16154
16181
|
for (const j of o.byPart.get(o.parts[i].spec.id)) {
|
|
16155
16182
|
if (j.st.open) continue;
|
|
16156
|
-
const b =
|
|
16183
|
+
const b = at2.get(j.ia === i ? j.ib : j.ia);
|
|
16157
16184
|
if (b !== void 0 && inputs[b].kind === "beam") beams.push(b);
|
|
16158
16185
|
}
|
|
16159
16186
|
inputs[k].beams = beams;
|
|
@@ -16969,7 +16996,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16969
16996
|
}
|
|
16970
16997
|
};
|
|
16971
16998
|
const tornToEdge = (o) => {
|
|
16972
|
-
const { p, cell, a, b, at, crater: crater2, reach, gone } = o;
|
|
16999
|
+
const { p, cell, a, b, at: at2, crater: crater2, reach, gone } = o;
|
|
16973
17000
|
const half = p.dims[a] / 2;
|
|
16974
17001
|
const lo = cell.center[a] - cell.size[a] / 2, hi = cell.center[a] + cell.size[a] / 2;
|
|
16975
17002
|
const free = (side, sign2) => {
|
|
@@ -16977,8 +17004,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16977
17004
|
const probe = side + sign2 * 1e-3;
|
|
16978
17005
|
return gridOf(p).some((c, k) => gone(k) && Math.abs(probe - c.center[a]) <= c.size[a] / 2 && Math.abs(cell.center[b] - c.center[b]) <= c.size[b] / 2);
|
|
16979
17006
|
};
|
|
16980
|
-
if (
|
|
16981
|
-
if (hi -
|
|
17007
|
+
if (at2 - lo <= reach && free(lo, -1)) return [lo, Math.max(crater2[1], lo)];
|
|
17008
|
+
if (hi - at2 <= reach && free(hi, 1)) return [Math.min(crater2[0], hi), hi];
|
|
16982
17009
|
return crater2;
|
|
16983
17010
|
};
|
|
16984
17011
|
const craterAcross = (energy) => clamp2(0.03 + 12e-4 * Math.sqrt(Math.max(0, energy)), 0.03, 0.14);
|
|
@@ -17188,7 +17215,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17188
17215
|
return;
|
|
17189
17216
|
}
|
|
17190
17217
|
if (ex) {
|
|
17191
|
-
emit({ ...base(o, src), type: "explode", part: p.spec.id, point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, ...ex.effect !== void 0 ? { effect: ex.effect } : {} });
|
|
17218
|
+
emit({ ...base(o, src), type: "explode", part: p.spec.id, point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, ...ex.tnt !== void 0 ? { tnt: ex.tnt } : {}, ...ex.effect !== void 0 ? { effect: ex.effect } : {} });
|
|
17192
17219
|
blasts.push({ point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, source: src });
|
|
17193
17220
|
}
|
|
17194
17221
|
partLost(o, p, src);
|
|
@@ -17782,7 +17809,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17782
17809
|
res.events = cur.slice(start);
|
|
17783
17810
|
return res;
|
|
17784
17811
|
};
|
|
17785
|
-
const
|
|
17812
|
+
const withBlow = (type, fn) => () => {
|
|
17813
|
+
const outer = blow;
|
|
17814
|
+
blow = type;
|
|
17815
|
+
try {
|
|
17816
|
+
return fn();
|
|
17817
|
+
} finally {
|
|
17818
|
+
blow = outer;
|
|
17819
|
+
}
|
|
17820
|
+
};
|
|
17821
|
+
const doHit = (o, hit, only) => withBlow(hit.type, () => resolveHit(o, hit, only))();
|
|
17822
|
+
const resolveHit = (o, hit, only) => {
|
|
17786
17823
|
let point = hit.point;
|
|
17787
17824
|
let dir = hit.direction;
|
|
17788
17825
|
if (hit.space === "local") {
|
|
@@ -18221,6 +18258,44 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
18221
18258
|
blastProbe() {
|
|
18222
18259
|
return { ...blastProbe };
|
|
18223
18260
|
},
|
|
18261
|
+
blastReach(point, target, options2 = {}) {
|
|
18262
|
+
const L = vec.distance(point, target);
|
|
18263
|
+
if (L < 1e-4) return 1;
|
|
18264
|
+
const shelter = { ...SHELTER_DEFAULTS, ...options2.shelter };
|
|
18265
|
+
const ignore = new Set(options2.ignore ?? []);
|
|
18266
|
+
const d = vec.scale(vec.sub(target, point), 1 / L);
|
|
18267
|
+
let t = 1;
|
|
18268
|
+
for (const o of objects.values()) {
|
|
18269
|
+
if (ignore.has(o.id) || raySphereMiss(point, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, L)) continue;
|
|
18270
|
+
for (const p of o.parts) {
|
|
18271
|
+
if (isLost(p) || p.st.stripped) continue;
|
|
18272
|
+
const r = rayPart(o, p, point, d);
|
|
18273
|
+
if (!r) continue;
|
|
18274
|
+
const t0 = Math.max(r.t0, 0);
|
|
18275
|
+
const path = Math.min(r.t1, L) - t0;
|
|
18276
|
+
if (path < shelter.minPath) continue;
|
|
18277
|
+
if (p.st.opening && insideOpening(o, p, toLocal(o.st.position, o.st.rotation, vec.madd(point, d, t0 + path / 2)))) continue;
|
|
18278
|
+
t *= Math.exp(-(p.mat.hpPerKg * p.mat.density * path * (p.mat.damageScale?.shelter ?? 1)) / shelter.k);
|
|
18279
|
+
if (t < 1e-4) return 0;
|
|
18280
|
+
}
|
|
18281
|
+
}
|
|
18282
|
+
for (const im of impls.values()) {
|
|
18283
|
+
if (ignore.has(im.impl.id)) continue;
|
|
18284
|
+
for (const ps of im.impl.describe().parts) {
|
|
18285
|
+
const mat = materials.get(ps.material);
|
|
18286
|
+
if (!mat) continue;
|
|
18287
|
+
const ov = im.poses.get(ps.id);
|
|
18288
|
+
const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...ps.rotation ?? [0, 0, 0]), point, d, ov?.pos);
|
|
18289
|
+
if (!r || r.t1 < 0 || r.t0 > L) continue;
|
|
18290
|
+
let path = Math.min(r.t1, L) - Math.max(r.t0, 0);
|
|
18291
|
+
if (ps.thickness !== void 0 && ps.thickness > 0) path = Math.min(path, 2 * ps.thickness);
|
|
18292
|
+
else if (path < shelter.minPath) continue;
|
|
18293
|
+
t *= Math.exp(-(mat.hpPerKg * mat.density * path * (mat.damageScale?.shelter ?? 1)) / shelter.k);
|
|
18294
|
+
if (t < 1e-4) return 0;
|
|
18295
|
+
}
|
|
18296
|
+
}
|
|
18297
|
+
return t;
|
|
18298
|
+
},
|
|
18224
18299
|
explode(point, energy, radius, source, blast) {
|
|
18225
18300
|
blastProbe.partsTested = 0;
|
|
18226
18301
|
blastProbe.partsNear = 0;
|
|
@@ -18245,7 +18320,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
18245
18320
|
},
|
|
18246
18321
|
shoot(origin, direction, energy, caliber, source, round3) {
|
|
18247
18322
|
const extras = typeof round3 === "number" ? { piercing: round3 } : round3 ?? {};
|
|
18248
|
-
return withCollapses(run(() => {
|
|
18323
|
+
return withCollapses(run(withBlow("ballistic", () => {
|
|
18249
18324
|
const results = [];
|
|
18250
18325
|
const d = vec.normalize(direction);
|
|
18251
18326
|
const ignore = /* @__PURE__ */ new Set();
|
|
@@ -18256,10 +18331,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
18256
18331
|
if (!rh) break;
|
|
18257
18332
|
const im = impls.get(rh.object);
|
|
18258
18333
|
if (im) {
|
|
18259
|
-
const
|
|
18334
|
+
const scaled = extras.penetration && E < energy ? { ...extras, penetration: Object.fromEntries(Object.entries(extras.penetration).map(([k, mm]) => [k, mm * (E / energy)])) } : extras;
|
|
18335
|
+
const r = implHit(im, { type: "ballistic", point: rh.point, part: rh.part, normal: rh.normal, direction: d, energy: E, caliber, ...scaled, ...source !== void 0 ? { source } : {} });
|
|
18260
18336
|
r.part = rh.part;
|
|
18261
18337
|
r.point = rh.point;
|
|
18262
|
-
|
|
18338
|
+
const left = r.events.find((e) => e.type === "hole" && e.energyLeft !== void 0);
|
|
18339
|
+
r.exitEnergy = r.penetrated ? left?.energyLeft ?? E * 0.5 : 0;
|
|
18263
18340
|
results.push(r);
|
|
18264
18341
|
ignore.add(`${im.impl.id}\0${rh.part}`);
|
|
18265
18342
|
if (!r.penetrated) break;
|
|
@@ -18278,7 +18355,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
18278
18355
|
E = out.exitEnergy;
|
|
18279
18356
|
}
|
|
18280
18357
|
return results;
|
|
18281
|
-
}));
|
|
18358
|
+
})));
|
|
18282
18359
|
},
|
|
18283
18360
|
disassemble(objectId, jointId, tool2, dt) {
|
|
18284
18361
|
const im = impls.get(objectId);
|
|
@@ -18586,8 +18663,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
18586
18663
|
list: () => defs,
|
|
18587
18664
|
get,
|
|
18588
18665
|
register(def) {
|
|
18589
|
-
const
|
|
18590
|
-
if (
|
|
18666
|
+
const at2 = defs.findIndex((a) => a.id === def.id);
|
|
18667
|
+
if (at2 >= 0) defs[at2] = def;
|
|
18591
18668
|
else defs.push(def);
|
|
18592
18669
|
},
|
|
18593
18670
|
part: (assemblyId, options) => buildAssemblyPart(get(assemblyId), assemblyId, options)
|
|
@@ -26450,22 +26527,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26450
26527
|
A.stats.external = Ne;
|
|
26451
26528
|
let shadows = 0;
|
|
26452
26529
|
for (let i = 0; i < N; i++) {
|
|
26453
|
-
const g = asg[i],
|
|
26530
|
+
const g = asg[i], at2 = slotOf(i), b0 = LZU.uRB0.value, b1 = LZU.uRB1.value, b2 = LZU.uRB2.value, by = LZU.uRBY.value, ex = LZU.uREx.value;
|
|
26454
26531
|
A.crates[i] = g ? { k: g.k, rects: g.rects, y: g.y, exterior: !!g.exterior, exclusion: g.exclusion || null, d: g.d } : null;
|
|
26455
26532
|
if (!g) {
|
|
26456
26533
|
put(i, { intensity: 0 });
|
|
26457
|
-
for (const a of [b0, b1, b2, ex]) a.set(EMPTY,
|
|
26458
|
-
by.set([0, 0],
|
|
26534
|
+
for (const a of [b0, b1, b2, ex]) a.set(EMPTY, at2 * 4);
|
|
26535
|
+
by.set([0, 0], at2 * 2);
|
|
26459
26536
|
continue;
|
|
26460
26537
|
}
|
|
26461
26538
|
const lamp = g.exterior ? { intensity: g.lumens, distance: g.dist, decay: g.decay } : { intensity: (7 + g.range * 0.8) * lim(1 + 0.4 * (Math.sqrt(g.n) - 1), 1, 2.2), distance: Math.max(3, g.dm * 1.3 + 0.5), decay: 1.6 };
|
|
26462
26539
|
put(i, { position: g.pos, color: g.color, ...lamp });
|
|
26463
26540
|
const rs = g.rects;
|
|
26464
|
-
b0.set(rs[0] || EMPTY,
|
|
26465
|
-
b1.set(rs[1] || EMPTY,
|
|
26466
|
-
b2.set(rs[2] || EMPTY,
|
|
26467
|
-
by.set(g.y,
|
|
26468
|
-
ex.set(g.exclusion || EMPTY,
|
|
26541
|
+
b0.set(rs[0] || EMPTY, at2 * 4);
|
|
26542
|
+
b1.set(rs[1] || EMPTY, at2 * 4);
|
|
26543
|
+
b2.set(rs[2] || EMPTY, at2 * 4);
|
|
26544
|
+
by.set(g.y, at2 * 2);
|
|
26545
|
+
ex.set(g.exclusion || EMPTY, at2 * 4);
|
|
26469
26546
|
if (i < NS) {
|
|
26470
26547
|
shadows++;
|
|
26471
26548
|
const s2 = g.house.group.uuid + "|" + g.k + "|" + g.pos.map((v) => v.toFixed(2)).join(",");
|
|
@@ -26540,10 +26617,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26540
26617
|
for (const p of list2 || []) {
|
|
26541
26618
|
if (isDoor && !(open.has(p.id) ? open.get(p.id) : !!p.open)) continue;
|
|
26542
26619
|
const alongU = p.axis === "u", y = house.y0(p.floor) + (isDoor ? 1 : ((p.y0 != null ? p.y0 : 0.9) + (p.y1 != null ? p.y1 : 2)) / 2);
|
|
26543
|
-
const
|
|
26544
|
-
if (
|
|
26620
|
+
const at2 = (side) => _p.set(alongU ? p.at : p.pos + side, y, alongU ? p.pos + side : p.at).applyMatrix4(M).clone();
|
|
26621
|
+
if (at2(0).distanceTo(P0) > OPENING_REACH) continue;
|
|
26545
26622
|
for (const side of [-OPENING_SIDE, OPENING_SIDE]) {
|
|
26546
|
-
const w =
|
|
26623
|
+
const w = at2(side), hit = boxAt(boxes, w.x, w.y, w.z);
|
|
26547
26624
|
if (hit) into.set(hit.c, hit);
|
|
26548
26625
|
}
|
|
26549
26626
|
}
|
|
@@ -26551,11 +26628,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26551
26628
|
reach(house.r.doors, true);
|
|
26552
26629
|
reach(house.r.windows, false);
|
|
26553
26630
|
};
|
|
26554
|
-
const clear = (
|
|
26555
|
-
for (const key2 of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[key2].value.set(EMPTY,
|
|
26556
|
-
LZU.uRBY.value.set([0, 0],
|
|
26631
|
+
const clear = (at2) => {
|
|
26632
|
+
for (const key2 of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[key2].value.set(EMPTY, at2 * 4);
|
|
26633
|
+
LZU.uRBY.value.set([0, 0], at2 * 2);
|
|
26557
26634
|
};
|
|
26558
|
-
const write = (
|
|
26635
|
+
const write = (at2, into) => {
|
|
26559
26636
|
const rs = [];
|
|
26560
26637
|
let lo = 1e9, hi = -1e9;
|
|
26561
26638
|
for (const q of into.values()) {
|
|
@@ -26567,21 +26644,21 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26567
26644
|
const r23 = rs.pop(), r1 = rs[rs.length - 1];
|
|
26568
26645
|
rs[rs.length - 1] = [Math.min(r1[0], r23[0]), Math.min(r1[1], r23[1]), Math.max(r1[2], r23[2]), Math.max(r1[3], r23[3])];
|
|
26569
26646
|
}
|
|
26570
|
-
LZU.uRB0.value.set(rs[0] || EMPTY,
|
|
26571
|
-
LZU.uRB1.value.set(rs[1] || EMPTY,
|
|
26572
|
-
LZU.uRB2.value.set(rs[2] || EMPTY,
|
|
26573
|
-
LZU.uRBY.value.set([lo, hi],
|
|
26574
|
-
LZU.uREx.value.set(EMPTY,
|
|
26647
|
+
LZU.uRB0.value.set(rs[0] || EMPTY, at2 * 4);
|
|
26648
|
+
LZU.uRB1.value.set(rs[1] || EMPTY, at2 * 4);
|
|
26649
|
+
LZU.uRB2.value.set(rs[2] || EMPTY, at2 * 4);
|
|
26650
|
+
LZU.uRBY.value.set([lo, hi], at2 * 2);
|
|
26651
|
+
LZU.uREx.value.set(EMPTY, at2 * 4);
|
|
26575
26652
|
};
|
|
26576
26653
|
const A = {
|
|
26577
26654
|
/** Once per frame, after the budget's `present`: points the mask of every lit slot that is not the house's at the rooms its light reaches. */
|
|
26578
26655
|
update(houses) {
|
|
26579
26656
|
const indoors = cfg.effectLightsIndoors !== false, list2 = (Array.isArray(houses) ? houses : [houses]).filter(Boolean), cache2 = /* @__PURE__ */ new Map();
|
|
26580
|
-
for (let
|
|
26581
|
-
if (ours.has(
|
|
26582
|
-
const light = budget.group.children[
|
|
26657
|
+
for (let at2 = 0; at2 < size; at2++) {
|
|
26658
|
+
if (ours.has(at2)) continue;
|
|
26659
|
+
const light = budget.group.children[at2];
|
|
26583
26660
|
if (!indoors || !light || !light.isPointLight || !(light.intensity > 0) || !light.visible) {
|
|
26584
|
-
clear(
|
|
26661
|
+
clear(at2);
|
|
26585
26662
|
continue;
|
|
26586
26663
|
}
|
|
26587
26664
|
const into = /* @__PURE__ */ new Map();
|
|
@@ -26596,8 +26673,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26596
26673
|
if (here) into.set(here.c, here);
|
|
26597
26674
|
openingSides(house, M, boxes, into);
|
|
26598
26675
|
}
|
|
26599
|
-
if (into.size) write(
|
|
26600
|
-
else clear(
|
|
26676
|
+
if (into.size) write(at2, into);
|
|
26677
|
+
else clear(at2);
|
|
26601
26678
|
}
|
|
26602
26679
|
}
|
|
26603
26680
|
};
|
|
@@ -27080,17 +27157,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27080
27157
|
for (const { c, part, units: units2, thick, mid } of shown) {
|
|
27081
27158
|
if (!near(c)) continue;
|
|
27082
27159
|
const centre = mask.start + (c.a + c.b) / 2, y = (c.y0 + c.y1) / 2, len = c.b - c.a, h = c.y1 - c.y0;
|
|
27083
|
-
const
|
|
27160
|
+
const at2 = (s, dy, d, colour) => {
|
|
27084
27161
|
const unit = clipToBox({ x: mask.alongU ? centre : mid, y, z: mask.alongU ? mid : centre, sx: mask.alongU ? s : d, sy: dy, sz: mask.alongU ? d : s, colour }, view.bounds);
|
|
27085
27162
|
if (unit) list2.push(unit);
|
|
27086
27163
|
};
|
|
27087
27164
|
const base = fragmentMaterial(part.material).color.getHex();
|
|
27088
27165
|
const n = noise2(centre * 3.1, y * 2.7, 0.07);
|
|
27089
27166
|
if (units2.mortar === "concrete") {
|
|
27090
|
-
|
|
27167
|
+
at2(len, h, thick - 2 * COVER2, tone(base, 0.9 + 0.04 * n));
|
|
27091
27168
|
} else {
|
|
27092
|
-
|
|
27093
|
-
|
|
27169
|
+
at2(len, h, thick - 2 * COVER2 - 0.012, 10327948);
|
|
27170
|
+
at2(len - 0.012, h - 0.012, thick - 2 * COVER2, tone(base, 0.8 + 0.35 * n));
|
|
27094
27171
|
}
|
|
27095
27172
|
}
|
|
27096
27173
|
if (view.units) {
|
|
@@ -27404,11 +27481,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27404
27481
|
};
|
|
27405
27482
|
const extract = (it) => {
|
|
27406
27483
|
const g0 = it.mesh.geometry, src = it.mesh.userData._p0 || g0.attributes.position.array, g = new THREE.BufferGeometry();
|
|
27407
|
-
const
|
|
27408
|
-
|
|
27409
|
-
|
|
27410
|
-
|
|
27411
|
-
|
|
27484
|
+
const at2 = (name, k, arr) => g.setAttribute(name, new THREE.BufferAttribute((arr || g0.attributes[name].array).slice(it.v0 * k, it.v1 * k), k));
|
|
27485
|
+
at2("position", 3, src);
|
|
27486
|
+
at2("normal", 3);
|
|
27487
|
+
at2("color", 3);
|
|
27488
|
+
at2("uv", 2);
|
|
27412
27489
|
const ix = g0.index.array.slice(it.i0, it.i1);
|
|
27413
27490
|
for (let k = 0; k < ix.length; k++) ix[k] -= it.v0;
|
|
27414
27491
|
g.setIndex(new THREE.BufferAttribute(ix, 1));
|
|
@@ -28121,9 +28198,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28121
28198
|
shared2.vegMaterials.setActors(focus ? [{ x: focus.x, y: focus.y, z: focus.z, radius: 0.9 }] : []);
|
|
28122
28199
|
}
|
|
28123
28200
|
if (focus && cfg.lod !== false) {
|
|
28124
|
-
const L = Object.assign({ interior: 45, hide: 220 }, cfg.lod), d = distance2(focus),
|
|
28201
|
+
const L = Object.assign({ interior: 45, hide: 220 }, cfg.lod), d = distance2(focus), at2 = h.lodCurrent;
|
|
28125
28202
|
let n = d > L.hide ? 2 : d > L.interior ? 1 : 0;
|
|
28126
|
-
if (n <
|
|
28203
|
+
if (n < at2) n = d < (at2 === 2 ? L.hide : L.interior) * 0.92 ? n : at2;
|
|
28127
28204
|
applyLod(Math.max(n, h.lodMin));
|
|
28128
28205
|
}
|
|
28129
28206
|
},
|
|
@@ -28743,8 +28820,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28743
28820
|
facadeExtra: (f, rng3, w, d, op) => {
|
|
28744
28821
|
f.roof = "slab";
|
|
28745
28822
|
f.finish = rng3() < 0.55 ? "exposed_block" : "partial_plaster";
|
|
28746
|
-
|
|
28747
|
-
|
|
28823
|
+
const slab = { exposedRebar: true, waterTank: { u: r22(0.5 + rng3() * (w - 1.5)), v: r22(1 + rng3() * (d - 2)) }, annex: rng3() < 0.55 ? { rect: [0, 0, r22(w * (0.5 + rng3() * 0.3)), r22(d * 0.4)], state: "exposed_brick" } : null };
|
|
28824
|
+
f.slab = slab;
|
|
28825
|
+
if (floorsOf(op) > 1) slab.exposedRebar = rng3() < 0.6;
|
|
28748
28826
|
}
|
|
28749
28827
|
};
|
|
28750
28828
|
}
|
|
@@ -29456,13 +29534,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
29456
29534
|
function apartment(strip, floor, k, from, to, plate, ceiling, win) {
|
|
29457
29535
|
const wide = to - from, depth = strip.depth, facade = r22(depth * 0.56);
|
|
29458
29536
|
const id = (name) => `apt_${floor}_${strip.id}_${k}_${name}`;
|
|
29459
|
-
const
|
|
29537
|
+
const at2 = (f0, f1, b0, b1) => boxOf2(strip, r22(from + wide * f0), r22(from + wide * f1), b0, b1);
|
|
29460
29538
|
const rooms = [
|
|
29461
|
-
{ id: id("living"), type: "living", label: "living", library: "living_tower", rect:
|
|
29462
|
-
{ id: id("bedroom"), type: "bedroom", label: "bedroom", rect:
|
|
29463
|
-
{ id: id("kitchen"), type: "kitchen", label: "kitchen", library: "kitchen_integrated", rect:
|
|
29464
|
-
{ id: id("hall"), type: "hall", label: "hall", rect:
|
|
29465
|
-
{ id: id("bath"), type: "bathroom", label: "bathroom", library: "bathroom_wc", rect:
|
|
29539
|
+
{ id: id("living"), type: "living", label: "living", library: "living_tower", rect: at2(0, 0.58, 0, facade) },
|
|
29540
|
+
{ id: id("bedroom"), type: "bedroom", label: "bedroom", rect: at2(0.58, 1, 0, facade) },
|
|
29541
|
+
{ id: id("kitchen"), type: "kitchen", label: "kitchen", library: "kitchen_integrated", rect: at2(0, 0.4, facade, depth) },
|
|
29542
|
+
{ id: id("hall"), type: "hall", label: "hall", rect: at2(0.4, 0.78, facade, depth) },
|
|
29543
|
+
{ id: id("bath"), type: "bathroom", label: "bathroom", library: "bathroom_wc", rect: at2(0.78, 1, facade, depth) }
|
|
29466
29544
|
];
|
|
29467
29545
|
const doors = [
|
|
29468
29546
|
stripDoor(id("hall"), strip, floor, 0.95),
|
|
@@ -29495,8 +29573,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
29495
29573
|
if (strip.id !== "south") return apartments(plan)(strip, context);
|
|
29496
29574
|
const { floor, plate, ceiling } = context;
|
|
29497
29575
|
const lobby = `lobby_${floor}_entrance`, concierge = `concierge_${floor}`, bikes = `bike_room_${floor}`;
|
|
29498
|
-
const
|
|
29499
|
-
const [left, middle, right] = [
|
|
29576
|
+
const at2 = (f0, f1) => boxOf2(strip, r22(strip.length * f0), r22(strip.length * f1), 0, strip.depth);
|
|
29577
|
+
const [left, middle, right] = [at2(0, 0.3), at2(0.3, 0.7), at2(0.7, 1)];
|
|
29500
29578
|
const rooms = [
|
|
29501
29579
|
{ id: concierge, type: "office", label: "concierge", rect: left },
|
|
29502
29580
|
{ id: lobby, type: "hall", label: "lobby_entrance", rect: middle },
|
|
@@ -30883,10 +30961,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
30883
30961
|
run: ({ expect }) => {
|
|
30884
30962
|
const food = catalog.list().find((item) => item.shelfLife !== void 0 && item.shelfLife > 0);
|
|
30885
30963
|
if (!food) return expect(false, "the catalog has a food that spoils");
|
|
30886
|
-
const
|
|
30964
|
+
const at2 = (storage, days2) => freshness(food, { ageDays: 0, since: 0, storage, storedAt: 0 }, days2, { rules: catalog.rules });
|
|
30887
30965
|
const days = food.shelfLife * 1.2;
|
|
30888
|
-
expect(
|
|
30889
|
-
if ("fridge" in catalog.rules.storage) expect(
|
|
30966
|
+
expect(at2("ambient", days) !== "fresh", "at room temperature it is past its best", { food: food.id });
|
|
30967
|
+
if ("fridge" in catalog.rules.storage) expect(at2("fridge", days) !== at2("ambient", days) || at2("fridge", days) === "fresh", "in the fridge it keeps better", { food: food.id });
|
|
30890
30968
|
}
|
|
30891
30969
|
},
|
|
30892
30970
|
{
|