@adatechnology/game-floorplan-structure 1.3.3 → 2.0.1
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.d.ts +253 -4
- package/dist/index.global.js +176 -34
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +24 -19
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { FloorplanEngine, ViewerLayer, RoomDef, DoorDef, WindowDef, FloorDef } from '@adatechnology/game-floorplan';
|
|
1
|
+
import { FloorplanEngine, ViewerLayer, RoomDef, DoorDef, WindowDef, FloorDef, PlanAxis } from '@adatechnology/game-floorplan';
|
|
2
|
+
export { LotPath } from '@adatechnology/game-floorplan';
|
|
2
3
|
import { MaterialId, JointKind, StructureRole, SoilProfile, PileSpec, DestructibleSpec, WindExposure } from '@adatechnology/game-contracts';
|
|
3
4
|
import { SoilDef, FrameOptions, WindOptions, SizeStructureOptions } from '@adatechnology/game-destruction';
|
|
4
5
|
|
|
@@ -256,7 +257,7 @@ interface StructureSource {
|
|
|
256
257
|
link?: {
|
|
257
258
|
from: number;
|
|
258
259
|
to: number;
|
|
259
|
-
} | null;
|
|
260
|
+
} | string | null;
|
|
260
261
|
}[];
|
|
261
262
|
facade: {
|
|
262
263
|
roof?: string;
|
|
@@ -313,7 +314,7 @@ interface SourceDoor {
|
|
|
313
314
|
u: number;
|
|
314
315
|
v: number;
|
|
315
316
|
width: number;
|
|
316
|
-
side?: string;
|
|
317
|
+
side?: string | null;
|
|
317
318
|
axis: 'u' | 'v';
|
|
318
319
|
steps?: number;
|
|
319
320
|
}
|
|
@@ -1159,6 +1160,254 @@ declare const towerLocales: {
|
|
|
1159
1160
|
};
|
|
1160
1161
|
};
|
|
1161
1162
|
|
|
1163
|
+
/** A point in the world: `[u, v, y]` (y is the absolute height). */
|
|
1164
|
+
type Point3 = [number, number, number];
|
|
1165
|
+
/** Something fixed to the inner face of a wall of a room: a socket, a switch, the panel. */
|
|
1166
|
+
interface WallFixture {
|
|
1167
|
+
id: string;
|
|
1168
|
+
room: string;
|
|
1169
|
+
floor: number;
|
|
1170
|
+
u: number;
|
|
1171
|
+
v: number;
|
|
1172
|
+
/** Height above the storey floor. */
|
|
1173
|
+
y: number;
|
|
1174
|
+
/** Position along the wall. */
|
|
1175
|
+
c: number;
|
|
1176
|
+
axis: PlanAxis;
|
|
1177
|
+
pos: number;
|
|
1178
|
+
frontU: number;
|
|
1179
|
+
frontV: number;
|
|
1180
|
+
}
|
|
1181
|
+
interface Outlet extends WallFixture {
|
|
1182
|
+
type: string;
|
|
1183
|
+
voltage: number;
|
|
1184
|
+
}
|
|
1185
|
+
interface LightSwitch extends WallFixture {
|
|
1186
|
+
door: string;
|
|
1187
|
+
/** On the latch side of the door. */
|
|
1188
|
+
latchSide: boolean;
|
|
1189
|
+
/** Lamp ids it turns on. */
|
|
1190
|
+
controls: string[];
|
|
1191
|
+
}
|
|
1192
|
+
interface ElectricalPanel extends WallFixture {
|
|
1193
|
+
w: number;
|
|
1194
|
+
h: number;
|
|
1195
|
+
breakers: number;
|
|
1196
|
+
}
|
|
1197
|
+
interface ElectricMeter {
|
|
1198
|
+
id: string;
|
|
1199
|
+
place: string;
|
|
1200
|
+
u: number;
|
|
1201
|
+
v: number;
|
|
1202
|
+
y: number;
|
|
1203
|
+
side: string;
|
|
1204
|
+
w: number;
|
|
1205
|
+
d: number;
|
|
1206
|
+
h: number;
|
|
1207
|
+
}
|
|
1208
|
+
/** Pole, drop, meter, descent and the run to the panel; a tap has no meter and a bare connection instead. */
|
|
1209
|
+
interface ServiceEntrance {
|
|
1210
|
+
pole: {
|
|
1211
|
+
u: number;
|
|
1212
|
+
v: number;
|
|
1213
|
+
h: number;
|
|
1214
|
+
};
|
|
1215
|
+
drop: Point3[];
|
|
1216
|
+
meter: ElectricMeter | null;
|
|
1217
|
+
descent: Point3[];
|
|
1218
|
+
internalRun: Point3[] | null;
|
|
1219
|
+
tap?: boolean;
|
|
1220
|
+
connection?: {
|
|
1221
|
+
u: number;
|
|
1222
|
+
v: number;
|
|
1223
|
+
y: number;
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
interface Circuit {
|
|
1227
|
+
id: string;
|
|
1228
|
+
room: string;
|
|
1229
|
+
floor: number;
|
|
1230
|
+
outlets: string[];
|
|
1231
|
+
switches: string[];
|
|
1232
|
+
lamps: string[];
|
|
1233
|
+
exposed: boolean;
|
|
1234
|
+
gauge_mm2: number;
|
|
1235
|
+
}
|
|
1236
|
+
interface Conduit {
|
|
1237
|
+
id: string;
|
|
1238
|
+
circuit: string;
|
|
1239
|
+
from: string;
|
|
1240
|
+
to: string;
|
|
1241
|
+
exposed: boolean;
|
|
1242
|
+
diameter: number;
|
|
1243
|
+
points: Point3[];
|
|
1244
|
+
}
|
|
1245
|
+
interface OutdoorLamp {
|
|
1246
|
+
id: string;
|
|
1247
|
+
u: number;
|
|
1248
|
+
v: number;
|
|
1249
|
+
y: number;
|
|
1250
|
+
door: string;
|
|
1251
|
+
switch: string | null;
|
|
1252
|
+
}
|
|
1253
|
+
interface PlumbingPoint {
|
|
1254
|
+
id: string;
|
|
1255
|
+
kind: string;
|
|
1256
|
+
item: string;
|
|
1257
|
+
room: string | null;
|
|
1258
|
+
floor: number;
|
|
1259
|
+
u: number;
|
|
1260
|
+
v: number;
|
|
1261
|
+
y: number;
|
|
1262
|
+
flowLpm: number | undefined;
|
|
1263
|
+
run: string | null;
|
|
1264
|
+
}
|
|
1265
|
+
interface PlumbingRun {
|
|
1266
|
+
id: string;
|
|
1267
|
+
from: string;
|
|
1268
|
+
/** A point, a room, or `ceiling`. */
|
|
1269
|
+
to: string | null;
|
|
1270
|
+
points: Point3[];
|
|
1271
|
+
diameter: number;
|
|
1272
|
+
exposed: string;
|
|
1273
|
+
}
|
|
1274
|
+
interface Plumbing {
|
|
1275
|
+
tank: 'water_tank' | null;
|
|
1276
|
+
capacityL: number;
|
|
1277
|
+
points: PlumbingPoint[];
|
|
1278
|
+
visibleRuns: PlumbingRun[];
|
|
1279
|
+
}
|
|
1280
|
+
interface SolarPanel {
|
|
1281
|
+
id: string;
|
|
1282
|
+
u: number;
|
|
1283
|
+
v: number;
|
|
1284
|
+
w: number;
|
|
1285
|
+
d: number;
|
|
1286
|
+
length: number;
|
|
1287
|
+
}
|
|
1288
|
+
interface Inverter {
|
|
1289
|
+
id: string;
|
|
1290
|
+
u: number;
|
|
1291
|
+
v: number;
|
|
1292
|
+
y: number;
|
|
1293
|
+
side: string;
|
|
1294
|
+
w: number;
|
|
1295
|
+
d: number;
|
|
1296
|
+
h: number;
|
|
1297
|
+
outdoor: boolean;
|
|
1298
|
+
link: string;
|
|
1299
|
+
}
|
|
1300
|
+
interface Solar {
|
|
1301
|
+
type: 'slab_rack' | 'roof';
|
|
1302
|
+
orientation: string;
|
|
1303
|
+
north: 'front' | 'back';
|
|
1304
|
+
slopeSide: 'front' | 'back' | null;
|
|
1305
|
+
tilt: number;
|
|
1306
|
+
area: number[];
|
|
1307
|
+
areaM2: number;
|
|
1308
|
+
count: number;
|
|
1309
|
+
floor: number;
|
|
1310
|
+
y: number;
|
|
1311
|
+
panels: SolarPanel[];
|
|
1312
|
+
inverter: Inverter | null;
|
|
1313
|
+
}
|
|
1314
|
+
/** A door or a window in the wall of an outbuilding. */
|
|
1315
|
+
interface OutbuildingOpening {
|
|
1316
|
+
id: string;
|
|
1317
|
+
axis: PlanAxis;
|
|
1318
|
+
pos: number;
|
|
1319
|
+
at: number;
|
|
1320
|
+
u: number;
|
|
1321
|
+
v: number;
|
|
1322
|
+
width: number;
|
|
1323
|
+
side: string;
|
|
1324
|
+
height?: number;
|
|
1325
|
+
exterior?: boolean;
|
|
1326
|
+
y0?: number;
|
|
1327
|
+
y1?: number;
|
|
1328
|
+
/** Swing area of a door. */
|
|
1329
|
+
zone?: Rect;
|
|
1330
|
+
}
|
|
1331
|
+
interface OutbuildingWall {
|
|
1332
|
+
axis: PlanAxis;
|
|
1333
|
+
u0: number;
|
|
1334
|
+
v0: number;
|
|
1335
|
+
u1: number;
|
|
1336
|
+
v1: number;
|
|
1337
|
+
thickness: number;
|
|
1338
|
+
h: number;
|
|
1339
|
+
side: string;
|
|
1340
|
+
}
|
|
1341
|
+
interface OutbuildingItem {
|
|
1342
|
+
type: string;
|
|
1343
|
+
category: string;
|
|
1344
|
+
u: number;
|
|
1345
|
+
v: number;
|
|
1346
|
+
w: number;
|
|
1347
|
+
d: number;
|
|
1348
|
+
h: number;
|
|
1349
|
+
ry: number;
|
|
1350
|
+
frontU: number;
|
|
1351
|
+
frontV: number;
|
|
1352
|
+
aabb: Rect;
|
|
1353
|
+
}
|
|
1354
|
+
interface Outbuilding {
|
|
1355
|
+
id: string;
|
|
1356
|
+
type: 'outbuilding';
|
|
1357
|
+
use: string;
|
|
1358
|
+
floor: number;
|
|
1359
|
+
aabb: Rect;
|
|
1360
|
+
interior: Rect[];
|
|
1361
|
+
ceiling: number;
|
|
1362
|
+
thickness: number;
|
|
1363
|
+
front: [number, number];
|
|
1364
|
+
walls: OutbuildingWall[];
|
|
1365
|
+
doors: OutbuildingOpening[];
|
|
1366
|
+
windows: OutbuildingOpening[];
|
|
1367
|
+
items: OutbuildingItem[];
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
type EnergyMode = 'grid' | 'tap' | 'offgrid';
|
|
1371
|
+
/** What a template says about its energy (a shack taps the grid without a meter, a cabin may run off-grid on solar). */
|
|
1372
|
+
interface EnergyConfig {
|
|
1373
|
+
mode: EnergyMode;
|
|
1374
|
+
solar?: boolean;
|
|
1375
|
+
}
|
|
1376
|
+
interface Electrical {
|
|
1377
|
+
mode: EnergyMode;
|
|
1378
|
+
serviceEntrance: ServiceEntrance | null;
|
|
1379
|
+
panel: ElectricalPanel | null;
|
|
1380
|
+
outlets: Outlet[];
|
|
1381
|
+
switches: LightSwitch[];
|
|
1382
|
+
circuits: Circuit[];
|
|
1383
|
+
conduits: Conduit[];
|
|
1384
|
+
exposed: boolean;
|
|
1385
|
+
outdoorLamps: OutdoorLamp[];
|
|
1386
|
+
source?: 'solar' | 'lamp';
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
interface GasMeter {
|
|
1390
|
+
id: 'gas.meter';
|
|
1391
|
+
u: number;
|
|
1392
|
+
v: number;
|
|
1393
|
+
y: number;
|
|
1394
|
+
side: string;
|
|
1395
|
+
w: number;
|
|
1396
|
+
d: number;
|
|
1397
|
+
h: number;
|
|
1398
|
+
}
|
|
1399
|
+
interface Gas {
|
|
1400
|
+
type: 'piped' | 'cylinder';
|
|
1401
|
+
meter: GasMeter | null;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
interface Utilities {
|
|
1405
|
+
gas: Gas | null;
|
|
1406
|
+
electrical: Electrical;
|
|
1407
|
+
solar: Solar | null;
|
|
1408
|
+
plumbing: Plumbing;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1162
1411
|
declare const version = "0.1.0";
|
|
1163
1412
|
|
|
1164
|
-
export { CONSTRUCTIONS, CONSTRUCTION_SYSTEMS, CORE_DEFAULTS, CURTAIN_DEFAULTS, type ChaletOptions, type Chimney, type Construction, type ConstructionBuild, type ConstructionBuilder, type ConstructionSystem, type ConstructionSystemDef, type CoreOptions, type CurtainWallOptions, DAMPER_DEFAULTS, DENSITY, type DamperOptions, type DestructibleSpecOptions, FLAT_ROOF_DEFAULTS, type FlatRoofOptions, type FoundationType, GROUND, MECHANICAL_DEFAULTS, MEMBER_CAGE, type MechanicalFloorOptions, type Opening, PILE_AREA, PILE_DEFAULTS, PLATE_DEFAULTS, PUNCHED_DEFAULTS, type PartRole, type PileDesign, type PlanContext, type PlateOptions, type PlateRect, type PlateStrip, type PunchedFacadeOptions, RAFT_THICKNESS, REBAR_RATIOS, ROOF_COVERINGS, type Rect, type Roof, type RoofCoveringDef, type RoofPane, type RoofShape, SKYSCRAPER_DEFAULTS, SKYSCRAPER_MAX_STOREYS, SLAB_PANEL_DEFAULTS, type ShackOptions, type SkyscraperLayout, type SkyscraperOptions, type SkyscraperPreset, type SlabPanelOptions, type SourceDoor, type SourceWall, type SourceWindow, type StoreyContext, type StoreyKind, type StripFill, type StripFiller, type StripId, type Structure, type StructureExtras, type StructureOptions, type StructurePackOptions, type StructurePart, type StructureSource, type Support, TOWER_DEFAULTS, type TankPlanOptions, type TankPlatform, type Tent, type TowerGeometry, type TowerMechanicalOptions, type TowerOptions, type TowerPlanOptions, type TowerPlate, type WallDetail, type WallMaterials, type WallSpecimenOptions, type WaterTank, type WoodFrameOptions, addCore, addCurtainWall, addFlatRoof, addMechanicalFloor, addPunchedFacade, addTunedMassDamper, applySlabPanels, beamDepthFor, beamSpan, buildSkyscraper, buildStructure, buildTower, buildWallSpecimen, campConstruction, chaletConstruction, constructionOfSystem, coreSize, damperMass, exteriorWindows, logCabinConstruction, masonryConstruction, mechanicalStoreys, pilesFor, planToSpace, planWaterTank, register, registerConstruction, registerConstructionSystem, registerRoofCovering, resolveSlabPanels, shackConstruction, skyscraperLayout, slabPanelView, slabPanelsOf, splitStrip, storeyKinds, stripDoor, structureLayer, toDestructibleSpec, towerFloors, towerLocales, towerPlate, towerWater, version, windExposureOf, woodFrameConstruction };
|
|
1413
|
+
export { CONSTRUCTIONS, CONSTRUCTION_SYSTEMS, CORE_DEFAULTS, CURTAIN_DEFAULTS, type ChaletOptions, type Chimney, type Circuit, type Conduit, type Construction, type ConstructionBuild, type ConstructionBuilder, type ConstructionSystem, type ConstructionSystemDef, type CoreOptions, type CurtainWallOptions, DAMPER_DEFAULTS, DENSITY, type DamperOptions, type DestructibleSpecOptions, type ElectricMeter, type Electrical, type ElectricalPanel, type EnergyConfig, type EnergyMode, FLAT_ROOF_DEFAULTS, type FlatRoofOptions, type FoundationType, GROUND, type Gas, type GasMeter, type Inverter, type LightSwitch, MECHANICAL_DEFAULTS, MEMBER_CAGE, type MechanicalFloorOptions, type Opening, type Outbuilding, type OutbuildingItem, type OutbuildingOpening, type OutbuildingWall, type OutdoorLamp, type Outlet, PILE_AREA, PILE_DEFAULTS, PLATE_DEFAULTS, PUNCHED_DEFAULTS, type PartRole, type PileDesign, type PlanContext, type PlateOptions, type PlateRect, type PlateStrip, type Plumbing, type PlumbingPoint, type PlumbingRun, type Point3, type PunchedFacadeOptions, RAFT_THICKNESS, REBAR_RATIOS, ROOF_COVERINGS, type Rect, type Roof, type RoofCoveringDef, type RoofPane, type RoofShape, SKYSCRAPER_DEFAULTS, SKYSCRAPER_MAX_STOREYS, SLAB_PANEL_DEFAULTS, type ServiceEntrance, type ShackOptions, type SkyscraperLayout, type SkyscraperOptions, type SkyscraperPreset, type SlabPanelOptions, type Solar, type SolarPanel, type SourceDoor, type SourceWall, type SourceWindow, type StoreyContext, type StoreyKind, type StripFill, type StripFiller, type StripId, type Structure, type StructureExtras, type StructureOptions, type StructurePackOptions, type StructurePart, type StructureSource, type Support, TOWER_DEFAULTS, type TankPlanOptions, type TankPlatform, type Tent, type TowerGeometry, type TowerMechanicalOptions, type TowerOptions, type TowerPlanOptions, type TowerPlate, type Utilities, type WallDetail, type WallFixture, type WallMaterials, type WallSpecimenOptions, type WaterTank, type WoodFrameOptions, addCore, addCurtainWall, addFlatRoof, addMechanicalFloor, addPunchedFacade, addTunedMassDamper, applySlabPanels, beamDepthFor, beamSpan, buildSkyscraper, buildStructure, buildTower, buildWallSpecimen, campConstruction, chaletConstruction, constructionOfSystem, coreSize, damperMass, exteriorWindows, logCabinConstruction, masonryConstruction, mechanicalStoreys, pilesFor, planToSpace, planWaterTank, register, registerConstruction, registerConstructionSystem, registerRoofCovering, resolveSlabPanels, shackConstruction, skyscraperLayout, slabPanelView, slabPanelsOf, splitStrip, storeyKinds, stripDoor, structureLayer, toDestructibleSpec, towerFloors, towerLocales, towerPlate, towerWater, version, windExposureOf, woodFrameConstruction };
|
package/dist/index.global.js
CHANGED
|
@@ -1037,9 +1037,10 @@ var GameFloorplanStructure = (() => {
|
|
|
1037
1037
|
}
|
|
1038
1038
|
|
|
1039
1039
|
// src/structure/stairs.ts
|
|
1040
|
+
var isStair = (item) => item.category === "stairs" && typeof item.link === "object" && item.link !== null;
|
|
1040
1041
|
function flightsOf(items) {
|
|
1041
1042
|
const flights = /* @__PURE__ */ new Map();
|
|
1042
|
-
for (const item of items.filter(
|
|
1043
|
+
for (const item of items.filter(isStair)) {
|
|
1043
1044
|
const key = `${item.link.from}_${item.link.to}`;
|
|
1044
1045
|
if (!flights.has(key) || item.floor === item.link.from) flights.set(key, item);
|
|
1045
1046
|
}
|
|
@@ -1617,12 +1618,12 @@ var GameFloorplanStructure = (() => {
|
|
|
1617
1618
|
const rect = lot.rect;
|
|
1618
1619
|
const poleU = clamp(gate ? gate.u + 3 : plan.w / 2, rect[0] + 0.5, rect[2] - 0.5);
|
|
1619
1620
|
const poleV = rect[1] - 0.6;
|
|
1620
|
-
let
|
|
1621
|
+
let placed;
|
|
1621
1622
|
if (gate) {
|
|
1622
1623
|
const direction = gate.u - gate.width / 2 - 0.4 >= rect[0] + 0.3 ? -1 : 1;
|
|
1623
|
-
|
|
1624
|
-
} else
|
|
1625
|
-
meter.id
|
|
1624
|
+
placed = { place: "gate_pillar", u: round22(gate.u + direction * (gate.width / 2 + 0.25)), v: round22(gate.v), y: 1.4, side: "front", ...METER_SIZE };
|
|
1625
|
+
} else placed = { place: "facade", u: round22(door ? door.at + 1.2 : plan.w / 2), v: -0.1, y: 1.4, side: "front", ...METER_SIZE };
|
|
1626
|
+
const meter = Object.assign(placed, { id: "meter" });
|
|
1626
1627
|
electrical.serviceEntrance = { pole: { u: round22(poleU), v: round22(poleV), h: 7.5 }, drop: [[round22(poleU), round22(poleV), 6.5], [meter.u, meter.v, 2.6]], meter, descent: [[meter.u, meter.v, 2.6], [meter.u, meter.v, 1.65]], internalRun: null };
|
|
1627
1628
|
} else if (lot === null || plan.style === "commercial") {
|
|
1628
1629
|
const front = door ? { u: round22(door.at + 1), v: -0.1 } : { u: round22(plan.w / 2), v: -0.1 };
|
|
@@ -1656,7 +1657,8 @@ var GameFloorplanStructure = (() => {
|
|
|
1656
1657
|
}
|
|
1657
1658
|
if (electrical.serviceEntrance && electrical.panel) {
|
|
1658
1659
|
const entrance = electrical.serviceEntrance;
|
|
1659
|
-
|
|
1660
|
+
const meterOf = entrance.meter;
|
|
1661
|
+
entrance.internalRun = [[meterOf.u, meterOf.v, 0.1], [electrical.panel.u, electrical.panel.v, heightOf(plan, electrical.panel.floor, electrical.panel.y)]];
|
|
1660
1662
|
}
|
|
1661
1663
|
}
|
|
1662
1664
|
|
|
@@ -1745,9 +1747,9 @@ var GameFloorplanStructure = (() => {
|
|
|
1745
1747
|
placePanel(layout);
|
|
1746
1748
|
addSwitches(layout);
|
|
1747
1749
|
addConduits(layout);
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1750
|
+
const entrance = electrical.serviceEntrance;
|
|
1751
|
+
const meter = entrance?.meter;
|
|
1752
|
+
if (mode === "tap" && entrance && meter) {
|
|
1751
1753
|
entrance.tap = true;
|
|
1752
1754
|
entrance.connection = { u: meter.u, v: meter.v, y: 2.6 };
|
|
1753
1755
|
entrance.meter = null;
|
|
@@ -1778,11 +1780,11 @@ var GameFloorplanStructure = (() => {
|
|
|
1778
1780
|
};
|
|
1779
1781
|
}
|
|
1780
1782
|
function besideStove(context, stove, room, solids, doorZones) {
|
|
1781
|
-
const t = [-stove.frontV, stove.frontU];
|
|
1783
|
+
const t = [-(stove.frontV ?? 1), stove.frontU ?? 0];
|
|
1782
1784
|
const parts = room.parts.map(inner);
|
|
1783
1785
|
for (const s of context.rng() < 0.5 ? [1, -1] : [-1, 1]) {
|
|
1784
|
-
const cx = stove.x + t[0] * s * (stove.w / 2 + CYLINDER.w / 2 + 0.03) - stove.frontU * (stove.d - CYLINDER.d) / 2;
|
|
1785
|
-
const cz = stove.z + t[1] * s * (stove.w / 2 + CYLINDER.w / 2 + 0.03) - stove.frontV * (stove.d - CYLINDER.d) / 2;
|
|
1786
|
+
const cx = stove.x + t[0] * s * (stove.w / 2 + CYLINDER.w / 2 + 0.03) - (stove.frontU ?? 0) * (stove.d - CYLINDER.d) / 2;
|
|
1787
|
+
const cz = stove.z + t[1] * s * (stove.w / 2 + CYLINDER.w / 2 + 0.03) - (stove.frontV ?? 1) * (stove.d - CYLINDER.d) / 2;
|
|
1786
1788
|
const rect = [cx - CYLINDER.w / 2, cz - CYLINDER.d / 2, cx + CYLINDER.w / 2, cz + CYLINDER.d / 2].map(round22);
|
|
1787
1789
|
const inside = parts.some((q) => rect[0] >= q[0] - 0.011 && rect[2] <= q[2] + 0.011 && rect[1] >= q[1] - 0.011 && rect[3] <= q[3] + 0.011);
|
|
1788
1790
|
if (inside && !solids.some((o) => overlaps(rect, o, 0.011)) && !doorZones.some((z) => overlaps(rect, z, 0.011))) return { mode: "beside", x: cx, z: cz, rect };
|
|
@@ -1838,8 +1840,8 @@ var GameFloorplanStructure = (() => {
|
|
|
1838
1840
|
d: CYLINDER.d,
|
|
1839
1841
|
h: CYLINDER.h,
|
|
1840
1842
|
y: 0,
|
|
1841
|
-
frontU: -stove.frontU,
|
|
1842
|
-
frontV: -stove.frontV,
|
|
1843
|
+
frontU: -(stove.frontU ?? 0),
|
|
1844
|
+
frontV: -(stove.frontV ?? 1),
|
|
1843
1845
|
room: stove.room,
|
|
1844
1846
|
floor: stove.floor,
|
|
1845
1847
|
outdoor: !!spot.outdoor,
|
|
@@ -2099,9 +2101,11 @@ var GameFloorplanStructure = (() => {
|
|
|
2099
2101
|
for (const item of items.filter((m) => m.category === "outbuilding")) {
|
|
2100
2102
|
const rng = context.rngFor(streamOf(item.id));
|
|
2101
2103
|
const [a0, a1, a2, a3] = item.aabb;
|
|
2102
|
-
const
|
|
2103
|
-
const
|
|
2104
|
-
const
|
|
2104
|
+
const frontU = item.frontU ?? 0;
|
|
2105
|
+
const frontV = item.frontV ?? 1;
|
|
2106
|
+
const n = [frontU, frontV];
|
|
2107
|
+
const t = [-frontV, frontU];
|
|
2108
|
+
const horizontal = Math.abs(frontU) === 1;
|
|
2105
2109
|
const cx = (a0 + a2) / 2;
|
|
2106
2110
|
const cz = (a1 + a3) / 2;
|
|
2107
2111
|
const depth = horizontal ? a2 - a0 : a3 - a1;
|
|
@@ -2338,7 +2342,7 @@ var GameFloorplanStructure = (() => {
|
|
|
2338
2342
|
}
|
|
2339
2343
|
function structureExtension(context) {
|
|
2340
2344
|
const cache = cacheOf(context.result);
|
|
2341
|
-
const options = { construction: cache.build.construction, extras: cache.build.extras ?? {}, tank: context
|
|
2345
|
+
const options = { construction: cache.build.construction, extras: cache.build.extras ?? {}, tank: tankOf(context), wallDetail: context.options.wallDetail ?? "panels" };
|
|
2342
2346
|
const { roof, ...structure } = buildStructure(context.result, options);
|
|
2343
2347
|
cache.roof = roof;
|
|
2344
2348
|
for (const part of structure.parts) {
|
|
@@ -2349,6 +2353,7 @@ var GameFloorplanStructure = (() => {
|
|
|
2349
2353
|
return structure;
|
|
2350
2354
|
}
|
|
2351
2355
|
var COOKING_CYLINDER = { type: "cooking_gas_cylinder", category: "cooking_gas_cylinder", w: 0.36, d: 0.36, h: 0.48 };
|
|
2356
|
+
var tankOf = (context) => context.result.waterTank ?? null;
|
|
2352
2357
|
function energyOf(context) {
|
|
2353
2358
|
const energy = context.plan.tpl.energy;
|
|
2354
2359
|
return typeof energy === "function" ? energy(context.options, context.plan.w, context.plan.d) : void 0;
|
|
@@ -2379,10 +2384,11 @@ var GameFloorplanStructure = (() => {
|
|
|
2379
2384
|
if (context.result.lot) addOutbuildingPaths(context.result.lot, outbuildings, context.result.items);
|
|
2380
2385
|
return outbuildings;
|
|
2381
2386
|
}, { after: ["contents"] });
|
|
2382
|
-
engine.registerResultExtension("utilities", (context) => planUtilities({ plan: context.plan, items: context.result.items, stateItems: context.result.stateItems, tank: context
|
|
2387
|
+
engine.registerResultExtension("utilities", (context) => planUtilities({ plan: context.plan, items: context.result.items, stateItems: context.result.stateItems, tank: tankOf(context), ...energyOf(context) ? { energy: energyOf(context) } : {}, rngFor: (key) => engine.createRng(context.seed, key) }), { after: ["outbuildings", "waterTank"] });
|
|
2383
2388
|
}
|
|
2384
2389
|
|
|
2385
2390
|
// ../game-contracts/dist/index.js
|
|
2391
|
+
var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
|
|
2386
2392
|
var DEFAULT_IGNITION_RULES = {
|
|
2387
2393
|
fillCurve: [
|
|
2388
2394
|
[0, 0.6],
|
|
@@ -2426,6 +2432,54 @@ var GameFloorplanStructure = (() => {
|
|
|
2426
2432
|
const flame = flameBase * (1 - rules.flameFillInfluence * (1 - k));
|
|
2427
2433
|
return 1 - (1 - Math.min(1, Math.max(0, spark))) * (1 - Math.min(1, Math.max(0, flame)));
|
|
2428
2434
|
};
|
|
2435
|
+
var DEFERRED_QUEUE_ID = {
|
|
2436
|
+
DESTRUCTION_EVENTS: "destruction.events",
|
|
2437
|
+
BREACH_PAINT: "floorplan.breach-paint",
|
|
2438
|
+
AUDIO_VOICES: "audio.voices",
|
|
2439
|
+
VEHICLE_CREASE: "vehicles.crease"
|
|
2440
|
+
};
|
|
2441
|
+
var DEFERRED_PRIORITY = {
|
|
2442
|
+
[DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: "present" },
|
|
2443
|
+
[DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: "present" },
|
|
2444
|
+
[DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: "idle", reserveMs: 1 },
|
|
2445
|
+
[DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: "idle" }
|
|
2446
|
+
};
|
|
2447
|
+
var SURFACE_IDS = ["concrete", "asphalt", "wood", "tile", "dirt", "grass", "gravel", "sand", "metal", "water", "glass", "carpet"];
|
|
2448
|
+
var GAIT_IDS = ["walk", "run"];
|
|
2449
|
+
var LANDING_IDS = ["light", "heavy"];
|
|
2450
|
+
var BODY_SOUND_IDS = [
|
|
2451
|
+
"jump",
|
|
2452
|
+
"cloth_rustle",
|
|
2453
|
+
"body_fall",
|
|
2454
|
+
"fall_damage",
|
|
2455
|
+
"player_hurt",
|
|
2456
|
+
"player_breath_run",
|
|
2457
|
+
"player_death",
|
|
2458
|
+
"bite",
|
|
2459
|
+
"grab",
|
|
2460
|
+
"punch_swing",
|
|
2461
|
+
"punch_hit_body",
|
|
2462
|
+
"punch_hit_face",
|
|
2463
|
+
"punch_hit_object",
|
|
2464
|
+
"kick_swing",
|
|
2465
|
+
"kick_hit",
|
|
2466
|
+
"kick_hit_object",
|
|
2467
|
+
"shove_two_hands",
|
|
2468
|
+
"knife_swing",
|
|
2469
|
+
"knife_stab",
|
|
2470
|
+
"knife_slash",
|
|
2471
|
+
"knife_hit_object",
|
|
2472
|
+
"blunt_swing",
|
|
2473
|
+
"blunt_hit",
|
|
2474
|
+
"blunt_hit_object",
|
|
2475
|
+
"axe_swing",
|
|
2476
|
+
"axe_chop",
|
|
2477
|
+
"axe_hit_object"
|
|
2478
|
+
];
|
|
2479
|
+
var footstepSoundId = (surface, gait) => `footstep_${surface}_${gait}`;
|
|
2480
|
+
var FOOTSTEP_SOUND_IDS = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)));
|
|
2481
|
+
var LAND_SOUND_IDS = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing) => `land_${surface}_${landing}`));
|
|
2482
|
+
var BODY_FOLEY_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
|
|
2429
2483
|
|
|
2430
2484
|
// ../game-destruction/dist/index.js
|
|
2431
2485
|
var FIRE_PRIME_C = 300;
|
|
@@ -5137,6 +5191,7 @@ var GameFloorplanStructure = (() => {
|
|
|
5137
5191
|
const ignitionRules = resolveIgnitionRules(options.ignition);
|
|
5138
5192
|
const breachBlastFactor = options.breach?.blastFactor ?? BREACH_BLAST_FACTOR;
|
|
5139
5193
|
const chipEnergy = options.breach?.chipEnergy ?? CHIP_ENERGY;
|
|
5194
|
+
const chainLinkCap = options.chainLinksPerUpdate !== void 0 && options.chainLinksPerUpdate >= 1 ? Math.floor(options.chainLinksPerUpdate) : Infinity;
|
|
5140
5195
|
const rng = createRng(options.seed ?? 1);
|
|
5141
5196
|
const rnd = () => rng.next();
|
|
5142
5197
|
let time = 0;
|
|
@@ -5159,7 +5214,13 @@ var GameFloorplanStructure = (() => {
|
|
|
5159
5214
|
const typed = listeners.get(e.type);
|
|
5160
5215
|
if (typed) for (const fn of [...typed]) fn(e);
|
|
5161
5216
|
};
|
|
5162
|
-
|
|
5217
|
+
let blow;
|
|
5218
|
+
const base = (o, source) => ({
|
|
5219
|
+
object: o.id,
|
|
5220
|
+
time,
|
|
5221
|
+
...source === void 0 ? {} : { source },
|
|
5222
|
+
...blow === void 0 ? {} : { blow }
|
|
5223
|
+
});
|
|
5163
5224
|
const pendingCollapse = /* @__PURE__ */ new Map();
|
|
5164
5225
|
let runDepth = 0;
|
|
5165
5226
|
const drainBlasts = () => {
|
|
@@ -6084,7 +6145,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6084
6145
|
if (disc < 0) return true;
|
|
6085
6146
|
return -b - Math.sqrt(disc) > maxDist;
|
|
6086
6147
|
};
|
|
6087
|
-
const raycastInternal = (origin, dir, maxDist, ignore, worldOnly = false) => {
|
|
6148
|
+
const raycastInternal = (origin, dir, maxDist, ignore, worldOnly = false, precise = false) => {
|
|
6088
6149
|
const d = vec.normalize(dir);
|
|
6089
6150
|
let best = null;
|
|
6090
6151
|
for (const o of objects.values()) {
|
|
@@ -6099,13 +6160,25 @@ var GameFloorplanStructure = (() => {
|
|
|
6099
6160
|
}
|
|
6100
6161
|
}
|
|
6101
6162
|
for (const im of worldOnly ? [] : impls.values()) {
|
|
6163
|
+
let boxHit = null;
|
|
6102
6164
|
for (const ps of im.impl.describe().parts) {
|
|
6103
6165
|
if (ignore?.has(`${im.impl.id}\0${ps.id}`)) continue;
|
|
6104
6166
|
const ov = im.poses.get(ps.id);
|
|
6105
6167
|
const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...ps.rotation ?? [0, 0, 0]), origin, d, ov?.pos);
|
|
6106
|
-
if (!r || r.
|
|
6107
|
-
if (
|
|
6168
|
+
if (!r || r.t1 < 0 || r.t0 > maxDist) continue;
|
|
6169
|
+
if (r.t0 < 0) {
|
|
6170
|
+
if (precise && im.impl.surfaceRay) boxHit = boxHit ?? { object: im.impl.id, part: ps.id, point: origin, normal: r.n, distance: 0, pathLen: r.t1 };
|
|
6171
|
+
continue;
|
|
6172
|
+
}
|
|
6173
|
+
if (!boxHit || r.t0 < boxHit.distance) boxHit = { object: im.impl.id, part: ps.id, point: vec.madd(origin, d, r.t0), normal: r.n, distance: r.t0, pathLen: r.t1 - r.t0 };
|
|
6108
6174
|
}
|
|
6175
|
+
if (!boxHit) continue;
|
|
6176
|
+
if (precise && im.impl.surfaceRay) {
|
|
6177
|
+
const far = best ? Math.min(maxDist, best.distance) : maxDist;
|
|
6178
|
+
const implId = im.impl.id;
|
|
6179
|
+
const s = im.impl.surfaceRay({ origin, direction: d, maxDistance: far, ...ignore ? { ignored: (part) => ignore.has(`${implId}\0${part}`) } : {} });
|
|
6180
|
+
if (s && (!best || s.distance < best.distance)) best = { object: implId, part: s.part, point: s.point, normal: s.normal, distance: s.distance, pathLen: s.pathLen };
|
|
6181
|
+
} else if (!best || boxHit.distance < best.distance) best = boxHit;
|
|
6109
6182
|
}
|
|
6110
6183
|
return best;
|
|
6111
6184
|
};
|
|
@@ -7292,7 +7365,17 @@ var GameFloorplanStructure = (() => {
|
|
|
7292
7365
|
res.events = cur.slice(start);
|
|
7293
7366
|
return res;
|
|
7294
7367
|
};
|
|
7295
|
-
const
|
|
7368
|
+
const withBlow = (type, fn) => () => {
|
|
7369
|
+
const outer = blow;
|
|
7370
|
+
blow = type;
|
|
7371
|
+
try {
|
|
7372
|
+
return fn();
|
|
7373
|
+
} finally {
|
|
7374
|
+
blow = outer;
|
|
7375
|
+
}
|
|
7376
|
+
};
|
|
7377
|
+
const doHit = (o, hit, only) => withBlow(hit.type, () => resolveHit(o, hit, only))();
|
|
7378
|
+
const resolveHit = (o, hit, only) => {
|
|
7296
7379
|
let point = hit.point;
|
|
7297
7380
|
let dir = hit.direction;
|
|
7298
7381
|
if (hit.space === "local") {
|
|
@@ -7589,7 +7672,9 @@ var GameFloorplanStructure = (() => {
|
|
|
7589
7672
|
};
|
|
7590
7673
|
const detonatePrimed = (until) => {
|
|
7591
7674
|
const end = time;
|
|
7592
|
-
|
|
7675
|
+
let fired = 0;
|
|
7676
|
+
for (let next = nextPrimed(until); next && fired < chainLinkCap; next = nextPrimed(until)) {
|
|
7677
|
+
fired++;
|
|
7593
7678
|
primed.delete(next.p);
|
|
7594
7679
|
time = Math.max(0, Math.min(end, next.p.rt.chainDue));
|
|
7595
7680
|
next.p.rt.chainDue = void 0;
|
|
@@ -7659,6 +7744,7 @@ var GameFloorplanStructure = (() => {
|
|
|
7659
7744
|
updateBound(o);
|
|
7660
7745
|
},
|
|
7661
7746
|
remove(id) {
|
|
7747
|
+
impls.get(id)?.impl.dispose?.();
|
|
7662
7748
|
objects.delete(id);
|
|
7663
7749
|
impls.delete(id);
|
|
7664
7750
|
},
|
|
@@ -7728,13 +7814,51 @@ var GameFloorplanStructure = (() => {
|
|
|
7728
7814
|
blastProbe() {
|
|
7729
7815
|
return { ...blastProbe };
|
|
7730
7816
|
},
|
|
7817
|
+
blastReach(point, target, options2 = {}) {
|
|
7818
|
+
const L = vec.distance(point, target);
|
|
7819
|
+
if (L < 1e-4) return 1;
|
|
7820
|
+
const shelter = { ...SHELTER_DEFAULTS, ...options2.shelter };
|
|
7821
|
+
const ignore = new Set(options2.ignore ?? []);
|
|
7822
|
+
const d = vec.scale(vec.sub(target, point), 1 / L);
|
|
7823
|
+
let t = 1;
|
|
7824
|
+
for (const o of objects.values()) {
|
|
7825
|
+
if (ignore.has(o.id) || raySphereMiss(point, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, L)) continue;
|
|
7826
|
+
for (const p of o.parts) {
|
|
7827
|
+
if (isLost(p) || p.st.stripped) continue;
|
|
7828
|
+
const r = rayPart(o, p, point, d);
|
|
7829
|
+
if (!r) continue;
|
|
7830
|
+
const t0 = Math.max(r.t0, 0);
|
|
7831
|
+
const path = Math.min(r.t1, L) - t0;
|
|
7832
|
+
if (path < shelter.minPath) continue;
|
|
7833
|
+
if (p.st.opening && insideOpening(o, p, toLocal(o.st.position, o.st.rotation, vec.madd(point, d, t0 + path / 2)))) continue;
|
|
7834
|
+
t *= Math.exp(-(p.mat.hpPerKg * p.mat.density * path * (p.mat.damageScale?.shelter ?? 1)) / shelter.k);
|
|
7835
|
+
if (t < 1e-4) return 0;
|
|
7836
|
+
}
|
|
7837
|
+
}
|
|
7838
|
+
for (const im of impls.values()) {
|
|
7839
|
+
if (ignore.has(im.impl.id)) continue;
|
|
7840
|
+
for (const ps of im.impl.describe().parts) {
|
|
7841
|
+
const mat = materials.get(ps.material);
|
|
7842
|
+
if (!mat) continue;
|
|
7843
|
+
const ov = im.poses.get(ps.id);
|
|
7844
|
+
const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...ps.rotation ?? [0, 0, 0]), point, d, ov?.pos);
|
|
7845
|
+
if (!r || r.t1 < 0 || r.t0 > L) continue;
|
|
7846
|
+
let path = Math.min(r.t1, L) - Math.max(r.t0, 0);
|
|
7847
|
+
if (ps.thickness !== void 0 && ps.thickness > 0) path = Math.min(path, 2 * ps.thickness);
|
|
7848
|
+
else if (path < shelter.minPath) continue;
|
|
7849
|
+
t *= Math.exp(-(mat.hpPerKg * mat.density * path * (mat.damageScale?.shelter ?? 1)) / shelter.k);
|
|
7850
|
+
if (t < 1e-4) return 0;
|
|
7851
|
+
}
|
|
7852
|
+
}
|
|
7853
|
+
return t;
|
|
7854
|
+
},
|
|
7731
7855
|
explode(point, energy, radius, source, blast) {
|
|
7732
7856
|
blastProbe.partsTested = 0;
|
|
7733
7857
|
blastProbe.partsNear = 0;
|
|
7734
7858
|
return withCollapses(run(() => blastWorld(point, energy, radius, source, blast)));
|
|
7735
7859
|
},
|
|
7736
7860
|
raycast(origin, direction, maxDistance = Infinity) {
|
|
7737
|
-
const r = raycastInternal(origin, direction, maxDistance);
|
|
7861
|
+
const r = raycastInternal(origin, direction, maxDistance, void 0, false, true);
|
|
7738
7862
|
return r ? { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: r.distance } : null;
|
|
7739
7863
|
},
|
|
7740
7864
|
sweepBox(box2, direction, distance2, options2 = {}) {
|
|
@@ -7752,21 +7876,23 @@ var GameFloorplanStructure = (() => {
|
|
|
7752
7876
|
},
|
|
7753
7877
|
shoot(origin, direction, energy, caliber, source, round3) {
|
|
7754
7878
|
const extras = typeof round3 === "number" ? { piercing: round3 } : round3 ?? {};
|
|
7755
|
-
return withCollapses(run(() => {
|
|
7879
|
+
return withCollapses(run(withBlow("ballistic", () => {
|
|
7756
7880
|
const results = [];
|
|
7757
7881
|
const d = vec.normalize(direction);
|
|
7758
7882
|
const ignore = /* @__PURE__ */ new Set();
|
|
7759
7883
|
let org = origin;
|
|
7760
7884
|
let E = energy;
|
|
7761
7885
|
for (let i = 0; i < 4 && E > 0; i++) {
|
|
7762
|
-
const rh = raycastInternal(org, d, Infinity, ignore);
|
|
7886
|
+
const rh = raycastInternal(org, d, Infinity, ignore, false, true);
|
|
7763
7887
|
if (!rh) break;
|
|
7764
7888
|
const im = impls.get(rh.object);
|
|
7765
7889
|
if (im) {
|
|
7766
|
-
const
|
|
7890
|
+
const scaled = extras.penetration && E < energy ? { ...extras, penetration: Object.fromEntries(Object.entries(extras.penetration).map(([k, mm]) => [k, mm * (E / energy)])) } : extras;
|
|
7891
|
+
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 } : {} });
|
|
7767
7892
|
r.part = rh.part;
|
|
7768
7893
|
r.point = rh.point;
|
|
7769
|
-
|
|
7894
|
+
const left = r.events.find((e) => e.type === "hole" && e.energyLeft !== void 0);
|
|
7895
|
+
r.exitEnergy = r.penetrated ? left?.energyLeft ?? E * 0.5 : 0;
|
|
7770
7896
|
results.push(r);
|
|
7771
7897
|
ignore.add(`${im.impl.id}\0${rh.part}`);
|
|
7772
7898
|
if (!r.penetrated) break;
|
|
@@ -7785,7 +7911,7 @@ var GameFloorplanStructure = (() => {
|
|
|
7785
7911
|
E = out.exitEnergy;
|
|
7786
7912
|
}
|
|
7787
7913
|
return results;
|
|
7788
|
-
}));
|
|
7914
|
+
})));
|
|
7789
7915
|
},
|
|
7790
7916
|
disassemble(objectId, jointId, tool, dt) {
|
|
7791
7917
|
const im = impls.get(objectId);
|
|
@@ -8085,12 +8211,27 @@ var GameFloorplanStructure = (() => {
|
|
|
8085
8211
|
breach: { area: 0.1 }
|
|
8086
8212
|
}
|
|
8087
8213
|
];
|
|
8214
|
+
var SHIPPED = structuredClone(assemblies_default);
|
|
8088
8215
|
var ASSEMBLIES = assemblies_default;
|
|
8089
|
-
var
|
|
8216
|
+
var assembliesOver = (defs) => {
|
|
8217
|
+
const get = (id) => defs.find((a) => a.id === id);
|
|
8218
|
+
return {
|
|
8219
|
+
list: () => defs,
|
|
8220
|
+
get,
|
|
8221
|
+
register(def) {
|
|
8222
|
+
const at2 = defs.findIndex((a) => a.id === def.id);
|
|
8223
|
+
if (at2 >= 0) defs[at2] = def;
|
|
8224
|
+
else defs.push(def);
|
|
8225
|
+
},
|
|
8226
|
+
part: (assemblyId, options) => buildAssemblyPart(get(assemblyId), assemblyId, options)
|
|
8227
|
+
};
|
|
8228
|
+
};
|
|
8229
|
+
var defaultSet;
|
|
8230
|
+
var defaultAssemblies = () => defaultSet ?? (defaultSet = assembliesOver(ASSEMBLIES));
|
|
8231
|
+
var getAssembly = (id) => defaultAssemblies().get(id);
|
|
8090
8232
|
var faceCount = (layer) => layer.faces === "both" ? 2 : 1;
|
|
8091
8233
|
var assemblyDepth = (def) => def.depth ?? def.core.thickness + (def.layers ?? []).reduce((sum, l) => sum + l.thickness * faceCount(l), 0);
|
|
8092
|
-
var
|
|
8093
|
-
const def = getAssembly(assemblyId);
|
|
8234
|
+
var buildAssemblyPart = (def, assemblyId, options) => {
|
|
8094
8235
|
if (!def) throw new Error(`unknown assembly "${assemblyId}"`);
|
|
8095
8236
|
const densityOf2 = (id) => {
|
|
8096
8237
|
const m = options.materials?.get(id) ?? MATERIALS.find((x) => x.id === id);
|
|
@@ -8117,6 +8258,7 @@ var GameFloorplanStructure = (() => {
|
|
|
8117
8258
|
...options.extra
|
|
8118
8259
|
};
|
|
8119
8260
|
};
|
|
8261
|
+
var assemblyPart = (assemblyId, options) => defaultAssemblies().part(assemblyId, options);
|
|
8120
8262
|
var buildFrame = (o = {}) => {
|
|
8121
8263
|
const spanX = o.spanX ?? 8, spanZ = o.spanZ ?? 8;
|
|
8122
8264
|
const nx = Math.max(2, o.columnsX ?? 3), nz = Math.max(2, o.columnsZ ?? 3);
|