@adatechnology/game-items-three 0.7.6 → 0.7.8

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.
@@ -1561,6 +1561,26 @@ var GameItemsThree = (() => {
1561
1561
 
1562
1562
  // ../game-contracts/dist/index.js
1563
1563
  var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
1564
+ var NEAREST = 0.3;
1565
+ function sideOnImpulse(tnt, distance2) {
1566
+ if (!(tnt > 0)) return 0;
1567
+ const w3 = Math.cbrt(tnt);
1568
+ const z = Math.max(distance2, NEAREST) / w3;
1569
+ const scaled = 0.067 * Math.sqrt(1 + (z / 0.23) ** 4) / (z * z * Math.cbrt(1 + (z / 1.55) ** 3));
1570
+ return scaled * w3 * 100;
1571
+ }
1572
+ var ATMOSPHERE = 101325;
1573
+ function sideOnOverpressure(tnt, distance2) {
1574
+ if (!(tnt > 0)) return 0;
1575
+ const z = Math.max(distance2, NEAREST) / Math.cbrt(tnt);
1576
+ const ratio = 808 * (1 + (z / 4.5) ** 2) / (Math.sqrt(1 + (z / 0.048) ** 2) * Math.sqrt(1 + (z / 0.32) ** 2) * Math.sqrt(1 + (z / 1.35) ** 2));
1577
+ return ratio * ATMOSPHERE;
1578
+ }
1579
+ function bodyImpulse(tnt, distance2) {
1580
+ if (!(tnt > 0)) return 0;
1581
+ const z = Math.max(distance2, NEAREST) / Math.cbrt(tnt);
1582
+ return sideOnImpulse(tnt, distance2) * (2 + 4 / (1 + z * z));
1583
+ }
1564
1584
  var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
1565
1585
  var DEFAULT_IGNITION_RULES = {
1566
1586
  fillCurve: [
@@ -15854,9 +15874,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
15854
15874
  var BREACH_AREA = 0.25;
15855
15875
  var BREACH_BLAST_REACH = 0.12;
15856
15876
  var MEMBER_CUT_REACH = 0.5;
15877
+ var FAR_MEMBER_HP_FLOOR = 0.25;
15857
15878
  var BLAST_REFERENCE_RESISTANCE = 200 * 1900 * 0.13;
15858
15879
  var BLAST_EDGE_RAGGED = 0.3;
15859
15880
  var BLAST_EDGE_LOOSE = 1.35;
15881
+ var PANEL_PRESSURE = 7e4;
15882
+ var PANEL_IMPULSE = 150;
15883
+ var PANEL_PI = 6e6;
15884
+ var PANEL_POINTS = [[0, 0], [-0.3, 0], [0.3, 0], [0, -0.3], [0, 0.3]];
15885
+ var PANEL_POINTS_LOADED = 4;
15860
15886
  var BLAST_EDGE_WEAR = 0.6;
15861
15887
  var RESIDUAL_CAPACITY = 0.15;
15862
15888
  var SEVER_BAND = 0.1;
@@ -15881,23 +15907,42 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
15881
15907
  const v = table[mat.penetrationClass ?? mat.id] ?? table[mat.id];
15882
15908
  return v === void 0 ? void 0 : v * (mat.penetrationScale ?? 1);
15883
15909
  };
15884
- var capacityScale = (p) => {
15910
+ var BURIED_BLAST_REACH = 0.5;
15911
+ var GIVE_AT_CUT_HP = 0.5;
15912
+ var capacityScale = (p, borne, through) => {
15885
15913
  const residual = p.spec.reinforcement?.residualCapacity ?? RESIDUAL_CAPACITY;
15886
15914
  if (p.st.stripped) return residual;
15887
- const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, 1 - sectionLoss(p));
15915
+ const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, sectionKept(p, residual, borne, through));
15888
15916
  return Math.max(p.spec.reinforcement ? residual : 0.05, kept);
15889
15917
  };
15890
- var sectionLoss = (p) => {
15918
+ var sectionKept = (p, residual, borne, through) => {
15919
+ let kept = 1;
15920
+ forEachSection(p, borne, (c, along, gone) => {
15921
+ const share = through?.(c.center, along) ?? 1;
15922
+ if (share <= 0) return;
15923
+ kept = Math.min(kept, Math.max(p.spec.reinforcement ? residual : 0, 1 - gone) / share);
15924
+ });
15925
+ return kept;
15926
+ };
15927
+ var sectionLoss = (p, borne) => {
15928
+ let worst = 0;
15929
+ forEachSection(p, borne, (_c, _along, gone) => {
15930
+ worst = Math.max(worst, gone);
15931
+ });
15932
+ return Math.min(1, worst);
15933
+ };
15934
+ var forEachSection = (p, borne, visit) => {
15891
15935
  const cells = p.st.chipped;
15892
- if (!cells?.length) return 0;
15936
+ if (!cells?.length) return;
15893
15937
  const [u, v] = planeAxes(p.thin);
15894
15938
  const role = p.spec.structure?.role;
15895
15939
  const up = rotateVec(p.q, [0, 0, 0].map((_, k) => k === v ? 1 : 0));
15896
15940
  const upright = Math.abs(up[1]) > 0.7 ? v : Math.abs(rotateVec(p.q, [0, 0, 0].map((_, k) => k === u ? 1 : 0))[1]) > 0.7 ? u : -1;
15897
15941
  const along = (role === "wall" || role === "partition" || role === "column") && upright >= 0 ? upright : p.dims[u] >= p.dims[v] ? u : v;
15898
15942
  const across2 = along === u ? v : u;
15899
- let worst = 0;
15943
+ const lying = along !== upright || upright < 0;
15900
15944
  for (const c of cells) {
15945
+ if (lying && borne?.(c.center, along)) continue;
15901
15946
  const spans = [];
15902
15947
  for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6) spans.push([d.center[across2] - d.size[across2] / 2, d.center[across2] + d.size[across2] / 2]);
15903
15948
  spans.sort((a, b) => a[0] - b[0]);
@@ -15907,9 +15952,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
15907
15952
  gone += b - Math.max(a, end);
15908
15953
  end = b;
15909
15954
  }
15910
- worst = Math.max(worst, gone / Math.max(p.dims[across2], 1e-6));
15955
+ visit(c, along, Math.min(1, gone / Math.max(p.dims[across2], 1e-6)));
15911
15956
  }
15912
- return Math.min(1, worst);
15913
15957
  };
15914
15958
  var isLost = (p) => p.st.status === "broken" || p.st.status === "melted" || p.st.status === "ashes";
15915
15959
  var clone = (v) => structuredClone(v);
@@ -16220,6 +16264,26 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
16220
16264
  byTouching.set(support, { version: poseVersion, box: box4 });
16221
16265
  return box4;
16222
16266
  };
16267
+ const throughOf = (p) => {
16268
+ const load = p.st.load ?? 0;
16269
+ if (load <= 0) return void 0;
16270
+ const above = Math.max(0, load - p.st.mass);
16271
+ const up = rotateVec(p.q, [0, 1, 0]);
16272
+ return (local, along) => {
16273
+ const axis = [0, 0, 0];
16274
+ axis[along] = 1;
16275
+ const sign2 = Math.sign(rotateVec(p.q, axis)[1]);
16276
+ if (Math.abs(up[1]) < 0.7 && Math.abs(rotateVec(p.q, axis)[1]) < 0.7) return 1;
16277
+ const half = p.dims[along] / 2;
16278
+ const share = clamp2((half - sign2 * local[along]) / Math.max(p.dims[along], 1e-6), 0, 1);
16279
+ return (above + p.st.mass * share) / load;
16280
+ };
16281
+ };
16282
+ const borneOn = (p, supports) => {
16283
+ if (supports.length === 0) return void 0;
16284
+ const boxes = supports.map((support) => contactBox(p, support));
16285
+ return (local, along) => boxes.some(([lo, hi]) => local[along] >= lo[along] - SUPPORT_TOLERANCE && local[along] <= hi[along] + SUPPORT_TOLERANCE);
16286
+ };
16223
16287
  const measureContact = (p, support) => {
16224
16288
  const A = aabbOf(p.spec.shape, p.pos, p.q), B = aabbOf(support.spec.shape, support.pos, support.q);
16225
16289
  const lo = [0, 0, 0], hi = [0, 0, 0];
@@ -16427,7 +16491,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
16427
16491
  o.unsup[i] = o.anyAnchor && !isLost(p) && !p.orphan;
16428
16492
  continue;
16429
16493
  }
16430
- p.st.stress = p.st.load * structureSafety / (p.cap * capacityScale(p));
16494
+ p.st.stress = p.st.load * structureSafety / (p.cap * capacityScale(p, borneOn(p, (lowerOf.get(i) ?? []).map((k) => parts[k])), throughOf(p)));
16431
16495
  if (p.bend) {
16432
16496
  p.bendLoad = p.st.mass + bending[i];
16433
16497
  const bent = restFlexure(o, p, lowerOf.get(i) ?? []);
@@ -17412,7 +17476,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
17412
17476
  return BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1e3) * clamp2(Math.cbrt(BLAST_REFERENCE_RESISTANCE / resistance), 0.3, 2);
17413
17477
  };
17414
17478
  const blastUnits = (o, p, wp, energy, dist, src) => {
17415
- var _a, _b;
17479
+ var _a;
17416
17480
  if (!p.staged || p.st.stripped || isLost(p) || chipEnergy <= 0) return false;
17417
17481
  const reach = blastReachOf(p, energy);
17418
17482
  if (dist >= reach) return false;
@@ -17442,6 +17506,62 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
17442
17506
  }
17443
17507
  }
17444
17508
  if (out.length === 0) return false;
17509
+ return knockOutUnits(o, p, wp, energy, out, src);
17510
+ };
17511
+ const blastPanel = (o, p, point, energy, src) => {
17512
+ var _a;
17513
+ if (!p.staged || p.st.stripped || isLost(p) || !p.spec.units || p.spec.units.mortar === p.spec.material || p.spec.reinforcement) return false;
17514
+ const [u, v] = planeAxes(p.thin);
17515
+ const lp = toLocal(p.pos, p.q, objLocal(o, point));
17516
+ const half = p.dims[u] / 2;
17517
+ const posts = [];
17518
+ for (const m of o.parts) {
17519
+ if (m === p || !m.spec.reinforcement || isLost(m) || m.spec.shape.kind !== "box") continue;
17520
+ const mp = toLocal(p.pos, p.q, m.pos);
17521
+ if (Math.abs(mp[p.thin]) > p.dims[p.thin] + 0.15 || Math.abs(mp[u]) > half + 0.15 || m.dims[v] < p.dims[v] * 0.5) continue;
17522
+ posts.push(mp[u]);
17523
+ }
17524
+ let from = -half, to = half;
17525
+ for (const x of posts) {
17526
+ if (x <= lp[u] && x > from) from = x;
17527
+ if (x >= lp[u] && x < to) to = x;
17528
+ }
17529
+ if (to - from < 0.2) return false;
17530
+ const tnt = energy * DEFAULT_BLAST_IMPULSE.tntPerJoule;
17531
+ const centre = objLocal(o, point);
17532
+ const span = to - from, height = p.dims[v];
17533
+ let loaded = 0;
17534
+ for (const [fu, fv] of PANEL_POINTS) {
17535
+ const at2 = [0, 0, 0];
17536
+ at2[u] = (from + to) / 2 + fu * span;
17537
+ at2[v] = fv * height;
17538
+ at2[p.thin] = Math.sign(lp[p.thin]) * p.dims[p.thin] / 2;
17539
+ const r = vec.distance(toWorld(p.pos, p.q, at2), centre);
17540
+ const side = sideOnOverpressure(tnt, r);
17541
+ const reflected = 2 * side + 6 * side * side / (side + 7 * 101325);
17542
+ const impulse = bodyImpulse(tnt, r);
17543
+ if (reflected > PANEL_PRESSURE && impulse > PANEL_IMPULSE && (reflected - PANEL_PRESSURE) * (impulse - PANEL_IMPULSE) >= PANEL_PI) loaded++;
17544
+ }
17545
+ if (loaded < PANEL_POINTS_LOADED) return false;
17546
+ const grid = gridOf(p);
17547
+ const worn = (_a = p.rt).chips ?? (_a.chips = {});
17548
+ const out = [];
17549
+ for (let i = 0; i < grid.length; i++) {
17550
+ const cell = grid[i];
17551
+ if (worn[i] === -1) continue;
17552
+ if (cell.center[u] - cell.size[u] / 2 >= from - 1e-6 && cell.center[u] + cell.size[u] / 2 <= to + 1e-6) out.push(i);
17553
+ }
17554
+ if (out.length === 0) return false;
17555
+ for (const i of out) worn[i] = -1;
17556
+ return knockOutUnits(o, p, point, energy, out, src);
17557
+ };
17558
+ const knockOutUnits = (o, p, wp, energy, out, src) => {
17559
+ var _a, _b;
17560
+ const [u, v] = planeAxes(p.thin);
17561
+ const op = p.st.opening ? toLocal(p.pos, p.q, p.st.opening.center) : null;
17562
+ const grid = gridOf(p);
17563
+ const worn = (_a = p.rt).chips ?? (_a.chips = {});
17564
+ for (const i of out) worn[i] = -1;
17445
17565
  const loose = unsupportedCells(grid, p.thin, p.dims, (i) => worn[i] !== -1 && !(op && p.st.opening && Math.hypot(grid[i].center[u] - op[u], grid[i].center[v] - op[v]) <= p.st.opening.radius));
17446
17566
  for (const i of loose) worn[i] = -1;
17447
17567
  const blown = out.map((i) => grid[i]), fallen = loose.map((i) => grid[i]);
@@ -17517,6 +17637,27 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
17517
17637
  debris(o, p, p.mat.breakDebris, center, [0, -1, 0], 6, 1, src);
17518
17638
  return loose.length;
17519
17639
  };
17640
+ const giveAtCut = (o, p, src) => {
17641
+ if (!p.spec.reinforcement || !p.spec.units || !p.st.chipped?.length || sectionLoss(p) <= 0) return false;
17642
+ const opened = [];
17643
+ for (const j of o.byPart.get(p.spec.id) ?? []) {
17644
+ if (j.st.open) continue;
17645
+ const onIt = j.bears === "a_on_b" && j.spec.b === p.spec.id || j.bears === "b_on_a" && j.spec.a === p.spec.id;
17646
+ if (!onIt) continue;
17647
+ j.st.open = true;
17648
+ j.st.openedBy = "break";
17649
+ opened.push(j);
17650
+ }
17651
+ if (opened.length === 0) return false;
17652
+ p.st.hp = Math.max(p.st.hp, p.st.maxHp * GIVE_AT_CUT_HP);
17653
+ markDamaged(p);
17654
+ solveStructure(o);
17655
+ recomputeGroups(o);
17656
+ detachEvents(o, opened, "break", src);
17657
+ exposeRebar(o, p, src);
17658
+ collapseCheck(o, src);
17659
+ return true;
17660
+ };
17520
17661
  const stripPart = (o, p, reinforcement, src) => {
17521
17662
  const bars = rebarBars(p.dims, p.thin, reinforcement.spacing);
17522
17663
  p.st.stripped = true;
@@ -17574,6 +17715,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
17574
17715
  hingeDrop(o, p, src);
17575
17716
  return;
17576
17717
  }
17718
+ if (!force && giveAtCut(o, p, src)) return;
17577
17719
  const ex = p.spec.explodes;
17578
17720
  const style = force ?? (p.snap ? "snap" : p.mat.fracture === "none" ? "snap" : p.mat.fracture);
17579
17721
  const { c, q } = partXf(o, p);
@@ -17902,12 +18044,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
17902
18044
  return reach;
17903
18045
  }
17904
18046
  if (Ein > 20 && p.layers.length > 0) spallOuter(o, p, wp, faceOf(o, p, wn), wn, clamp2(0.05 + Math.sqrt(Ein) * 2e-3, 0.05, 0.4), src);
17905
- const dealt = applyDamage(o, p, amount, "explosive", point, null, Ein * 0.3, 40, src);
18047
+ const breachReach = BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1e3);
18048
+ const farMember = Boolean(p.spec.reinforcement && p.spec.units) && dist > MEMBER_CUT_REACH * breachReach;
18049
+ const dealt = farMember ? applyDamage(o, p, Math.min(amount, Math.max(0, p.st.hp - p.st.maxHp * FAR_MEMBER_HP_FLOOR)), "explosive", null, null, Ein * 0.3, 40, src) : applyDamage(o, p, amount, "explosive", point, null, Ein * 0.3, 40, src);
17906
18050
  res.damage += dealt;
17907
18051
  if (p.bend && flexure.enabled) bendByBlast(o, p, point, energy, radius, reach, src);
17908
- const breachReach = BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1e3);
17909
- if (p.spec.units && p.spec.units.mortar !== p.spec.material) blastUnits(o, p, wp, energy, dist, src);
17910
- else if (p.spec.reinforcement && p.spec.units && dist > MEMBER_CUT_REACH * breachReach) blastUnits(o, p, wp, energy, dist, src);
18052
+ if (p.spec.units && p.spec.units.mortar !== p.spec.material) {
18053
+ blastPanel(o, p, point, energy, src);
18054
+ if (!isLost(p)) blastUnits(o, p, wp, energy, dist, src);
18055
+ } else if (farMember) blastUnits(o, p, wp, energy, dist, src);
17911
18056
  else if (dist <= breachReach) addBreach(o, p, wp, breachAreaOf(p, dealt, true), Ein, null, src);
17912
18057
  return reach;
17913
18058
  };
@@ -17920,7 +18065,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
17920
18065
  const dx = local[0] - p.pos[0];
17921
18066
  const dy = local[1] - p.pos[1];
17922
18067
  const dz = local[2] - p.pos[2];
17923
- if (dx * dx + dy * dy + dz * dz < reach * reach) near.push(p);
18068
+ if (dx * dx + dy * dy + dz * dz >= reach * reach) continue;
18069
+ if (p.spec.anchored && p.spec.structure?.role === "foundation" && distToPart(o, p, point) > BURIED_BLAST_REACH) continue;
18070
+ near.push(p);
17924
18071
  }
17925
18072
  blastProbe.partsTested += o.parts.length;
17926
18073
  blastProbe.partsNear += near.length;
@@ -21120,7 +21267,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21120
21267
  }
21121
21268
  var towerLocales = { en: { labels: en_default.labels }, "pt-BR": { labels: pt_BR_default.labels } };
21122
21269
 
21123
- // ../game-floorplan-three/dist/chunk-JZQA7G63.js
21270
+ // ../game-floorplan-three/dist/chunk-PJ4WEP6U.js
21124
21271
  var __defProp2 = Object.defineProperty;
21125
21272
  var __defNormalProp = (obj, key2, value) => key2 in obj ? __defProp2(obj, key2, { enumerable: true, configurable: true, writable: true, value }) : obj[key2] = value;
21126
21273
  var __publicField = (obj, key2, value) => __defNormalProp(obj, typeof key2 !== "symbol" ? key2 + "" : key2, value);
@@ -24019,8 +24166,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
24019
24166
  const defined = { electricalStructure, pipe2 };
24020
24167
  Object.assign(K, defined);
24021
24168
  }
24169
+ var BASEBOARD_TILES = { length: 0.6, joint: 3e-3, material: "ceramic", density: 2300 };
24170
+ var SIDEWALK_SLABS = { length: 1.2, joint: 0.01, material: "concrete", density: 2400 };
24022
24171
  function installHouseBaseboard(K, shared2) {
24023
- const { Y0, bx, cursor, sideOf } = K;
24172
+ const { Y0, bx, cursor, pieceRecord, sideOf } = K;
24024
24173
  const sh = (...a) => K.sh(...a);
24025
24174
  function baseboardAndSidewalk() {
24026
24175
  const R = shared2.ctx.r, W = 0.6, t = 0.012, ht = 0.35, color2 = sh(shared2.ctx.colors.facade != null ? shared2.ctx.colors.facade : 14209216, 0.62), y0 = Y0(0), cal = 13947078;
@@ -24042,15 +24191,29 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
24042
24191
  };
24043
24192
  for (const A of ws) for (const [side, sd] of [[A.w.sides[0], -1], [A.w.sides[1], 1]]) {
24044
24193
  if (!sideOf(side, false).exterior) continue;
24045
- const strip = (k, y1, y2, o0, o1, mat, c, y1b) => {
24194
+ const strip = (k, y1, y2, o0, o1, mat, c, piece2, laid = BASEBOARD_TILES) => {
24046
24195
  const ea = junction(A, A.a, sd) > 0 ? A.th / 2 + k : junction(A, A.a, sd) < 0 ? -A.th / 2 : 0, eb = junction(A, A.b, sd) > 0 ? A.th / 2 + k : junction(A, A.b, sd) < 0 ? -A.th / 2 : 0;
24047
24196
  const s0 = A.a - ea, s1 = A.b + eb, f0 = A.L + sd * (A.th / 2 + o0), f1 = A.L + sd * (A.th / 2 + o1), lo = Math.min(f0, f1), hi = Math.max(f0, f1);
24048
24197
  if (s1 - s0 < 1e-3) return;
24049
- if (A.au) bx(mat, s0, y1, lo, s1, y2, hi, c);
24050
- else bx(mat, lo, y1, s0, hi, y2, s1, c);
24198
+ const box4 = (a, b) => {
24199
+ if (A.au) bx(mat, a, y1, lo, b, y2, hi, c);
24200
+ else bx(mat, lo, y1, a, hi, y2, b, c);
24201
+ };
24202
+ const tag = laid === BASEBOARD_TILES ? "baseboard" : "sidewalk";
24203
+ const tile = (id, a, b) => {
24204
+ cursor.pc = pieceRecord(id, laid.material, null, { floor: 0, mass: Math.round((b - a) * (y2 - y1) * (hi - lo) * laid.density * 100) / 100, tags: [tag] });
24205
+ box4(a, b);
24206
+ };
24207
+ if (!piece2) box4(s0, s1);
24208
+ else if (shared2.ctx.baseboardBand) tile(piece2, s0, s1);
24209
+ else {
24210
+ const n = Math.max(1, Math.round((s1 - s0) / laid.length)), w = (s1 - s0) / n, j = laid.joint / 2;
24211
+ for (let i = 0; i < n; i++) tile(`${piece2}:${i}`, s0 + i * w + (i > 0 ? j : 0), s0 + (i + 1) * w - (i < n - 1 ? j : 0));
24212
+ }
24213
+ cursor.pc = null;
24051
24214
  };
24052
- strip(t, y0, y0 + ht, 0, t, "plaster", color2);
24053
- strip(W, y0, y0 + 0.045, 0, W, "sidewalk", cal);
24215
+ strip(t, y0, y0 + ht, 0, t, "plaster", color2, A.w.id ? `baseboard:${A.w.id}:${sd < 0 ? 0 : 1}` : void 0);
24216
+ strip(W, y0, y0 + 0.045, 0, W, "sidewalk", cal, A.w.id ? `sidewalk:${A.w.id}:${sd < 0 ? 0 : 1}` : void 0, SIDEWALK_SLABS);
24054
24217
  }
24055
24218
  }
24056
24219
  const defined = { baseboardAndSidewalk };
@@ -27420,7 +27583,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
27420
27583
  if (!b) continue;
27421
27584
  const vol = Math.max(1e-6, (b[3] - b[0]) * (b[4] - b[1]) * (b[5] - b[2]));
27422
27585
  const p = { id, role: "none", material: pc.mat, aabb: [b[0], b[2], b[3], b[5]], y0: b[1], y1: b[4], floor: pc.floor != null ? pc.floor : floorAtY(b[1] + 0.1), mass: pc.mass != null ? pc.mass : Math.max(0.5, vol * (DENSITY[pc.mat] || 800) * (pc.fill != null ? pc.fill : 0.15)), meshes: meshes.get(id).length, extra: true };
27423
- for (const k of ["contains", "explodes", "tags", "form", "thickness", "fill"]) if (pc[k] != null) p[k] = pc[k];
27586
+ for (const k of ["contains", "explodes", "tags", "form", "thickness", "fill", "units"]) if (pc[k] != null) p[k] = pc[k];
27424
27587
  parts.push(p);
27425
27588
  byId.set(id, p);
27426
27589
  }
@@ -27429,7 +27592,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
27429
27592
  return cx >= q.aabb[0] - m && cx <= q.aabb[2] + m && cz >= q.aabb[1] - m && cz <= q.aabb[3] + m && cy >= q.y0 - m && cy <= q.y1 + m;
27430
27593
  };
27431
27594
  for (const p of parts.slice(base)) {
27432
- if (!/^(window|window_pane|door|jamb|pipe|water_tank)/.test(p.id)) continue;
27595
+ if (/^sidewalk:/.test(p.id)) {
27596
+ supports.push({ part: p.id, on: "ground", joint: "mortar", extra: true });
27597
+ continue;
27598
+ }
27599
+ if (!/^(window|window_pane|door|jamb|pipe|water_tank|baseboard)/.test(p.id)) continue;
27433
27600
  const target = /^water_tank/.test(p.id) ? ["slab"] : ["wall", "partition"];
27434
27601
  let m = null, md = 1e9;
27435
27602
  for (const q of parts.slice(0, base)) {
@@ -27440,7 +27607,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
27440
27607
  m = q;
27441
27608
  }
27442
27609
  }
27443
- if (m) supports.push({ part: p.id, on: m.id, joint: /^(window|jamb)/.test(p.id) ? "glue" : "clip", bears: false, extra: true });
27610
+ if (m) supports.push({ part: p.id, on: m.id, joint: /^(window|jamb|baseboard)/.test(p.id) ? "glue" : "clip", bears: false, extra: true });
27444
27611
  }
27445
27612
  const specParts = parts.slice(), specSupports = supports.slice();
27446
27613
  if (view.panels.length) {
@@ -28536,6 +28703,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
28536
28703
  cursor.separate = opts.pieces === "meshes";
28537
28704
  cursor.pc = null;
28538
28705
  shared2.ctx.showPillars = opts.pillars !== "hidden";
28706
+ shared2.ctx.baseboardBand = opts.baseboard === "band";
28539
28707
  shared2.ctx.apartment = r.template === "apartment_modern";
28540
28708
  shared2.ctx.pa = Math.max(3, Math.min(20, pr.floors != null ? pr.floors : 5));
28541
28709
  shared2.ctx.pf = Math.max(1, Math.min(shared2.ctx.pa, pr.floor != null ? pr.floor : 3));