@adatechnology/game-floorplan-structure 2.0.0 → 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 +86 -25
- 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,7 +2384,7 @@ 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
|
|
@@ -5209,7 +5214,13 @@ var GameFloorplanStructure = (() => {
|
|
|
5209
5214
|
const typed = listeners.get(e.type);
|
|
5210
5215
|
if (typed) for (const fn of [...typed]) fn(e);
|
|
5211
5216
|
};
|
|
5212
|
-
|
|
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
|
+
});
|
|
5213
5224
|
const pendingCollapse = /* @__PURE__ */ new Map();
|
|
5214
5225
|
let runDepth = 0;
|
|
5215
5226
|
const drainBlasts = () => {
|
|
@@ -7354,7 +7365,17 @@ var GameFloorplanStructure = (() => {
|
|
|
7354
7365
|
res.events = cur.slice(start);
|
|
7355
7366
|
return res;
|
|
7356
7367
|
};
|
|
7357
|
-
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) => {
|
|
7358
7379
|
let point = hit.point;
|
|
7359
7380
|
let dir = hit.direction;
|
|
7360
7381
|
if (hit.space === "local") {
|
|
@@ -7793,6 +7814,44 @@ var GameFloorplanStructure = (() => {
|
|
|
7793
7814
|
blastProbe() {
|
|
7794
7815
|
return { ...blastProbe };
|
|
7795
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
|
+
},
|
|
7796
7855
|
explode(point, energy, radius, source, blast) {
|
|
7797
7856
|
blastProbe.partsTested = 0;
|
|
7798
7857
|
blastProbe.partsNear = 0;
|
|
@@ -7817,7 +7876,7 @@ var GameFloorplanStructure = (() => {
|
|
|
7817
7876
|
},
|
|
7818
7877
|
shoot(origin, direction, energy, caliber, source, round3) {
|
|
7819
7878
|
const extras = typeof round3 === "number" ? { piercing: round3 } : round3 ?? {};
|
|
7820
|
-
return withCollapses(run(() => {
|
|
7879
|
+
return withCollapses(run(withBlow("ballistic", () => {
|
|
7821
7880
|
const results = [];
|
|
7822
7881
|
const d = vec.normalize(direction);
|
|
7823
7882
|
const ignore = /* @__PURE__ */ new Set();
|
|
@@ -7828,10 +7887,12 @@ var GameFloorplanStructure = (() => {
|
|
|
7828
7887
|
if (!rh) break;
|
|
7829
7888
|
const im = impls.get(rh.object);
|
|
7830
7889
|
if (im) {
|
|
7831
|
-
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 } : {} });
|
|
7832
7892
|
r.part = rh.part;
|
|
7833
7893
|
r.point = rh.point;
|
|
7834
|
-
|
|
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;
|
|
7835
7896
|
results.push(r);
|
|
7836
7897
|
ignore.add(`${im.impl.id}\0${rh.part}`);
|
|
7837
7898
|
if (!r.penetrated) break;
|
|
@@ -7850,7 +7911,7 @@ var GameFloorplanStructure = (() => {
|
|
|
7850
7911
|
E = out.exitEnergy;
|
|
7851
7912
|
}
|
|
7852
7913
|
return results;
|
|
7853
|
-
}));
|
|
7914
|
+
})));
|
|
7854
7915
|
},
|
|
7855
7916
|
disassemble(objectId, jointId, tool, dt) {
|
|
7856
7917
|
const im = impls.get(objectId);
|