@adatechnology/game-floorplan-structure 1.2.3 → 1.3.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 +7 -1
- package/dist/index.global.js +406 -34
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +20 -2
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.global.js
CHANGED
|
@@ -32,6 +32,7 @@ var GameFloorplanStructure = (() => {
|
|
|
32
32
|
FLAT_ROOF_DEFAULTS: () => FLAT_ROOF_DEFAULTS,
|
|
33
33
|
GROUND: () => GROUND,
|
|
34
34
|
MECHANICAL_DEFAULTS: () => MECHANICAL_DEFAULTS,
|
|
35
|
+
MEMBER_CAGE: () => MEMBER_CAGE,
|
|
35
36
|
PILE_AREA: () => PILE_AREA,
|
|
36
37
|
PILE_DEFAULTS: () => PILE_DEFAULTS,
|
|
37
38
|
PLATE_DEFAULTS: () => PLATE_DEFAULTS,
|
|
@@ -2791,7 +2792,9 @@ var GameFloorplanStructure = (() => {
|
|
|
2791
2792
|
const band = { c: [root.c[0], root.c[1], root.c[2]], s: [dims[0], dims[1], dims[2]] };
|
|
2792
2793
|
band.c[L] = (lo + hi) / 2;
|
|
2793
2794
|
band.s[L] = Math.max(hi - lo, 0.01);
|
|
2794
|
-
|
|
2795
|
+
if (inp.style === "snap") {
|
|
2796
|
+
for (const b of bsp(band, Math.max(3, Math.min(6, inp.maxFragments - out.length)), [0, 1, 2], inp.rnd)) out.push({ center: b.c, size: b.s, q: quat.identity(), shape: "chunk", weight: b.s[0] * b.s[1] * b.s[2] });
|
|
2797
|
+
} else for (const p of splinterBox(inp, band, Math.max(3, inp.maxFragments - out.length))) out.push(p);
|
|
2795
2798
|
return out;
|
|
2796
2799
|
};
|
|
2797
2800
|
var tearStack = (inp, root, t, u, v, n, sheet) => {
|
|
@@ -2822,6 +2825,7 @@ var GameFloorplanStructure = (() => {
|
|
|
2822
2825
|
const t = sorted[0];
|
|
2823
2826
|
const [u, v] = [sorted[1], sorted[2]].sort((a, b) => a - b);
|
|
2824
2827
|
if (style === "snap") {
|
|
2828
|
+
if (inp.cut) return severAt(inp, root, inp.cut.at, inp.cut.gap);
|
|
2825
2829
|
const n2 = Math.min(maxFragments, 2 + Math.floor(rnd() * 3));
|
|
2826
2830
|
for (const b of bsp(root, n2, [0, 1, 2], rnd)) out.push({ center: b.c, size: b.s, q: idq, shape: "slab", weight: b.s[0] * b.s[1] * b.s[2] });
|
|
2827
2831
|
return out;
|
|
@@ -2995,6 +2999,27 @@ var GameFloorplanStructure = (() => {
|
|
|
2995
2999
|
for (const x of spread(dims[u], COVER, spacing, MAX_BARS_PER_DIRECTION)) out.push(bar(v, dims[v] / 2 - 0.02, [[u, x], [thin, 0]]));
|
|
2996
3000
|
return out;
|
|
2997
3001
|
};
|
|
3002
|
+
var clipBarsToBox = (bars, u, v, center, size) => {
|
|
3003
|
+
const out = [];
|
|
3004
|
+
for (const [a, b] of bars) {
|
|
3005
|
+
const axis = a[u] !== b[u] ? u : v;
|
|
3006
|
+
const other = axis === u ? v : u;
|
|
3007
|
+
if (Math.abs(a[other] - center[other]) > size[other] / 2) continue;
|
|
3008
|
+
const lo = Math.max(Math.min(a[axis], b[axis]), center[axis] - size[axis] / 2), hi = Math.min(Math.max(a[axis], b[axis]), center[axis] + size[axis] / 2);
|
|
3009
|
+
if (hi - lo < 1e-6) continue;
|
|
3010
|
+
const p = [a[0], a[1], a[2]], q = [b[0], b[1], b[2]];
|
|
3011
|
+
p[axis] = lo;
|
|
3012
|
+
q[axis] = hi;
|
|
3013
|
+
out.push([p, q]);
|
|
3014
|
+
}
|
|
3015
|
+
return out;
|
|
3016
|
+
};
|
|
3017
|
+
var bendBar = ([a, b], thin, bow, i) => {
|
|
3018
|
+
const length = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
|
|
3019
|
+
const m = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2];
|
|
3020
|
+
m[thin] += (i % 2 === 0 ? 1 : -1) * bow * length;
|
|
3021
|
+
return [[a, m], [m, b]];
|
|
3022
|
+
};
|
|
2998
3023
|
var clipBarsToDisc = (bars, u, v, center, radius) => {
|
|
2999
3024
|
const out = [];
|
|
3000
3025
|
for (const [a, b] of bars) {
|
|
@@ -3915,14 +3940,21 @@ var GameFloorplanStructure = (() => {
|
|
|
3915
3940
|
smoke: "grey"
|
|
3916
3941
|
},
|
|
3917
3942
|
visual: {
|
|
3918
|
-
charColor: 1709072
|
|
3943
|
+
charColor: 1709072,
|
|
3944
|
+
innerColor: 14730131
|
|
3919
3945
|
},
|
|
3920
3946
|
tags: [
|
|
3921
3947
|
"wood",
|
|
3922
3948
|
"organic",
|
|
3923
3949
|
"flammable"
|
|
3924
3950
|
],
|
|
3925
|
-
compressive: 1e5
|
|
3951
|
+
compressive: 1e5,
|
|
3952
|
+
hits: {
|
|
3953
|
+
blunt: {
|
|
3954
|
+
tear: "splinters",
|
|
3955
|
+
tearJoules: 60
|
|
3956
|
+
}
|
|
3957
|
+
}
|
|
3926
3958
|
},
|
|
3927
3959
|
{
|
|
3928
3960
|
id: "wood_hard",
|
|
@@ -3952,14 +3984,21 @@ var GameFloorplanStructure = (() => {
|
|
|
3952
3984
|
smoke: "grey"
|
|
3953
3985
|
},
|
|
3954
3986
|
visual: {
|
|
3955
|
-
charColor: 1709072
|
|
3987
|
+
charColor: 1709072,
|
|
3988
|
+
innerColor: 13213802
|
|
3956
3989
|
},
|
|
3957
3990
|
tags: [
|
|
3958
3991
|
"wood",
|
|
3959
3992
|
"organic",
|
|
3960
3993
|
"flammable"
|
|
3961
3994
|
],
|
|
3962
|
-
compressive: 15e4
|
|
3995
|
+
compressive: 15e4,
|
|
3996
|
+
hits: {
|
|
3997
|
+
blunt: {
|
|
3998
|
+
tear: "splinters",
|
|
3999
|
+
tearJoules: 150
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
3963
4002
|
},
|
|
3964
4003
|
{
|
|
3965
4004
|
id: "plywood",
|
|
@@ -3989,14 +4028,24 @@ var GameFloorplanStructure = (() => {
|
|
|
3989
4028
|
smoke: "grey"
|
|
3990
4029
|
},
|
|
3991
4030
|
visual: {
|
|
3992
|
-
charColor: 1709072
|
|
4031
|
+
charColor: 1709072,
|
|
4032
|
+
innerColor: 14862234
|
|
3993
4033
|
},
|
|
3994
4034
|
tags: [
|
|
3995
4035
|
"wood",
|
|
3996
4036
|
"organic",
|
|
3997
4037
|
"flammable"
|
|
3998
4038
|
],
|
|
3999
|
-
compressive: 6e4
|
|
4039
|
+
compressive: 6e4,
|
|
4040
|
+
hits: {
|
|
4041
|
+
ballistic: {
|
|
4042
|
+
tear: "splinters"
|
|
4043
|
+
},
|
|
4044
|
+
blunt: {
|
|
4045
|
+
tear: "splinters",
|
|
4046
|
+
tearJoules: 80
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4000
4049
|
},
|
|
4001
4050
|
{
|
|
4002
4051
|
id: "mdf",
|
|
@@ -4023,14 +4072,25 @@ var GameFloorplanStructure = (() => {
|
|
|
4023
4072
|
smoke: "grey"
|
|
4024
4073
|
},
|
|
4025
4074
|
visual: {
|
|
4026
|
-
charColor: 1709072
|
|
4075
|
+
charColor: 1709072,
|
|
4076
|
+
innerColor: 12096362
|
|
4027
4077
|
},
|
|
4028
4078
|
tags: [
|
|
4029
4079
|
"wood",
|
|
4030
4080
|
"organic",
|
|
4031
4081
|
"flammable"
|
|
4032
4082
|
],
|
|
4033
|
-
compressive: 3e4
|
|
4083
|
+
compressive: 3e4,
|
|
4084
|
+
hits: {
|
|
4085
|
+
ballistic: {
|
|
4086
|
+
tear: "lumps",
|
|
4087
|
+
tearJoules: 120
|
|
4088
|
+
},
|
|
4089
|
+
blunt: {
|
|
4090
|
+
tear: "lumps",
|
|
4091
|
+
tearJoules: 20
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4034
4094
|
},
|
|
4035
4095
|
{
|
|
4036
4096
|
id: "glass",
|
|
@@ -4144,8 +4204,20 @@ var GameFloorplanStructure = (() => {
|
|
|
4144
4204
|
damageScale: {
|
|
4145
4205
|
explosive: 1.2
|
|
4146
4206
|
},
|
|
4207
|
+
hits: {
|
|
4208
|
+
ballistic: {
|
|
4209
|
+
unitJoules: 500,
|
|
4210
|
+
floor: 900,
|
|
4211
|
+
crater: true
|
|
4212
|
+
},
|
|
4213
|
+
blunt: {
|
|
4214
|
+
unitJoules: 1500,
|
|
4215
|
+
floor: 60
|
|
4216
|
+
}
|
|
4217
|
+
},
|
|
4147
4218
|
hitDebris: "chips",
|
|
4148
4219
|
breakDebris: "dust",
|
|
4220
|
+
visual: { innerColor: 10197652 },
|
|
4149
4221
|
thermal: {
|
|
4150
4222
|
conductivity: 0.15,
|
|
4151
4223
|
heatCapacity: 2.5
|
|
@@ -4176,6 +4248,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4176
4248
|
],
|
|
4177
4249
|
hitDebris: "chips",
|
|
4178
4250
|
breakDebris: "dust",
|
|
4251
|
+
visual: { innerColor: 12085567 },
|
|
4179
4252
|
thermal: {
|
|
4180
4253
|
conductivity: 0.15,
|
|
4181
4254
|
heatCapacity: 2.5
|
|
@@ -4206,6 +4279,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4206
4279
|
],
|
|
4207
4280
|
hitDebris: "dust",
|
|
4208
4281
|
breakDebris: "dust",
|
|
4282
|
+
visual: { innerColor: 14999507 },
|
|
4209
4283
|
thermal: {
|
|
4210
4284
|
conductivity: 0.1,
|
|
4211
4285
|
heatCapacity: 1.5
|
|
@@ -4231,6 +4305,7 @@ var GameFloorplanStructure = (() => {
|
|
|
4231
4305
|
],
|
|
4232
4306
|
hitDebris: "chips",
|
|
4233
4307
|
breakDebris: "dust",
|
|
4308
|
+
visual: { innerColor: 9407364 },
|
|
4234
4309
|
thermal: {
|
|
4235
4310
|
conductivity: 0.2,
|
|
4236
4311
|
heatCapacity: 2.5
|
|
@@ -4512,7 +4587,8 @@ var GameFloorplanStructure = (() => {
|
|
|
4512
4587
|
smoke: "white"
|
|
4513
4588
|
},
|
|
4514
4589
|
visual: {
|
|
4515
|
-
charColor: 1709072
|
|
4590
|
+
charColor: 1709072,
|
|
4591
|
+
innerColor: 14207126
|
|
4516
4592
|
},
|
|
4517
4593
|
tags: [
|
|
4518
4594
|
"plant",
|
|
@@ -4520,7 +4596,12 @@ var GameFloorplanStructure = (() => {
|
|
|
4520
4596
|
"organic",
|
|
4521
4597
|
"flammable"
|
|
4522
4598
|
],
|
|
4523
|
-
compressive: 6e4
|
|
4599
|
+
compressive: 6e4,
|
|
4600
|
+
hits: {
|
|
4601
|
+
blunt: {
|
|
4602
|
+
tear: "none"
|
|
4603
|
+
}
|
|
4604
|
+
}
|
|
4524
4605
|
},
|
|
4525
4606
|
{
|
|
4526
4607
|
id: "cactus",
|
|
@@ -4635,6 +4716,130 @@ var GameFloorplanStructure = (() => {
|
|
|
4635
4716
|
"masonry"
|
|
4636
4717
|
],
|
|
4637
4718
|
compressive: 2e4
|
|
4719
|
+
},
|
|
4720
|
+
{
|
|
4721
|
+
id: "asphalt",
|
|
4722
|
+
density: 2350,
|
|
4723
|
+
hpPerKg: 10,
|
|
4724
|
+
penetration: 14,
|
|
4725
|
+
penetrationClass: "concrete",
|
|
4726
|
+
penetrationScale: 0.8,
|
|
4727
|
+
ductility: 0.1,
|
|
4728
|
+
fracture: "crumble",
|
|
4729
|
+
fragmentSize: [
|
|
4730
|
+
0.03,
|
|
4731
|
+
0.15
|
|
4732
|
+
],
|
|
4733
|
+
hitDebris: "chips",
|
|
4734
|
+
breakDebris: "dust",
|
|
4735
|
+
thermal: {
|
|
4736
|
+
conductivity: 0.1,
|
|
4737
|
+
heatCapacity: 2,
|
|
4738
|
+
ignitionC: 400,
|
|
4739
|
+
burnRate: 2e-3,
|
|
4740
|
+
smoke: "black"
|
|
4741
|
+
},
|
|
4742
|
+
tags: [
|
|
4743
|
+
"masonry",
|
|
4744
|
+
"brittle"
|
|
4745
|
+
],
|
|
4746
|
+
compressive: 3e4
|
|
4747
|
+
},
|
|
4748
|
+
{
|
|
4749
|
+
id: "sand",
|
|
4750
|
+
density: 1600,
|
|
4751
|
+
hpPerKg: 2,
|
|
4752
|
+
penetration: 6,
|
|
4753
|
+
ductility: 0.4,
|
|
4754
|
+
fracture: "crumble",
|
|
4755
|
+
fragmentSize: [
|
|
4756
|
+
0.01,
|
|
4757
|
+
0.04
|
|
4758
|
+
],
|
|
4759
|
+
hitDebris: "dust",
|
|
4760
|
+
breakDebris: "dust",
|
|
4761
|
+
thermal: {
|
|
4762
|
+
conductivity: 0.1,
|
|
4763
|
+
heatCapacity: 2
|
|
4764
|
+
},
|
|
4765
|
+
tags: [
|
|
4766
|
+
"soil"
|
|
4767
|
+
],
|
|
4768
|
+
compressive: 1e4
|
|
4769
|
+
},
|
|
4770
|
+
{
|
|
4771
|
+
id: "gravel",
|
|
4772
|
+
density: 1800,
|
|
4773
|
+
hpPerKg: 3,
|
|
4774
|
+
penetration: 8,
|
|
4775
|
+
ductility: 0.3,
|
|
4776
|
+
fracture: "crumble",
|
|
4777
|
+
fragmentSize: [
|
|
4778
|
+
0.02,
|
|
4779
|
+
0.06
|
|
4780
|
+
],
|
|
4781
|
+
hitDebris: "chips",
|
|
4782
|
+
breakDebris: "dust",
|
|
4783
|
+
thermal: {
|
|
4784
|
+
conductivity: 0.1,
|
|
4785
|
+
heatCapacity: 2
|
|
4786
|
+
},
|
|
4787
|
+
tags: [
|
|
4788
|
+
"soil",
|
|
4789
|
+
"masonry"
|
|
4790
|
+
],
|
|
4791
|
+
compressive: 2e4
|
|
4792
|
+
},
|
|
4793
|
+
{
|
|
4794
|
+
id: "turf",
|
|
4795
|
+
density: 900,
|
|
4796
|
+
hpPerKg: 3,
|
|
4797
|
+
penetration: 4,
|
|
4798
|
+
ductility: 0.5,
|
|
4799
|
+
fracture: "crumble",
|
|
4800
|
+
fragmentSize: [
|
|
4801
|
+
0.03,
|
|
4802
|
+
0.1
|
|
4803
|
+
],
|
|
4804
|
+
hitDebris: "dust",
|
|
4805
|
+
breakDebris: "dust",
|
|
4806
|
+
thermal: {
|
|
4807
|
+
conductivity: 0.1,
|
|
4808
|
+
heatCapacity: 1.5,
|
|
4809
|
+
ignitionC: 250,
|
|
4810
|
+
burnRate: 0.03,
|
|
4811
|
+
smoke: "white"
|
|
4812
|
+
},
|
|
4813
|
+
tags: [
|
|
4814
|
+
"soil",
|
|
4815
|
+
"organic"
|
|
4816
|
+
],
|
|
4817
|
+
compressive: 15e3
|
|
4818
|
+
},
|
|
4819
|
+
{
|
|
4820
|
+
id: "mortar",
|
|
4821
|
+
density: 1900,
|
|
4822
|
+
hpPerKg: 10,
|
|
4823
|
+
penetration: 12,
|
|
4824
|
+
penetrationClass: "concrete",
|
|
4825
|
+
penetrationScale: 1.2,
|
|
4826
|
+
ductility: 0.03,
|
|
4827
|
+
fracture: "crumble",
|
|
4828
|
+
fragmentSize: [
|
|
4829
|
+
0.02,
|
|
4830
|
+
0.08
|
|
4831
|
+
],
|
|
4832
|
+
hitDebris: "chips",
|
|
4833
|
+
breakDebris: "dust",
|
|
4834
|
+
thermal: {
|
|
4835
|
+
conductivity: 0.15,
|
|
4836
|
+
heatCapacity: 2.5
|
|
4837
|
+
},
|
|
4838
|
+
tags: [
|
|
4839
|
+
"masonry",
|
|
4840
|
+
"brittle"
|
|
4841
|
+
],
|
|
4842
|
+
compressive: 1e5
|
|
4638
4843
|
}
|
|
4639
4844
|
];
|
|
4640
4845
|
var material_hints_default = {
|
|
@@ -4808,6 +5013,32 @@ var GameFloorplanStructure = (() => {
|
|
|
4808
5013
|
return (1 + 4 * (0.3 - ductility) / 0.3) * Math.min(25, Math.max(1, (0.02 / Math.max(thickness, 1e-4)) ** 2));
|
|
4809
5014
|
};
|
|
4810
5015
|
var THIN_SHEET_DISHING = 5e-3;
|
|
5016
|
+
var SWEEP_BACK = 0.01;
|
|
5017
|
+
function sweepOrigins(box2, d, spacing) {
|
|
5018
|
+
const origins = [];
|
|
5019
|
+
const line = (from, to) => {
|
|
5020
|
+
const n = Math.max(1, Math.ceil((to - from) / spacing));
|
|
5021
|
+
return Array.from({ length: n + 1 }, (_, i) => from + (to - from) * i / n);
|
|
5022
|
+
};
|
|
5023
|
+
for (const axis of [0, 1, 2]) {
|
|
5024
|
+
if (Math.abs(d[axis]) < 1e-3) continue;
|
|
5025
|
+
const lead = d[axis] > 0 ? box2.max[axis] - SWEEP_BACK : box2.min[axis] + SWEEP_BACK;
|
|
5026
|
+
const u = (axis + 1) % 3;
|
|
5027
|
+
const v = (axis + 2) % 3;
|
|
5028
|
+
for (const a of line(box2.min[u], box2.max[u])) {
|
|
5029
|
+
for (const b of line(box2.min[v], box2.max[v])) {
|
|
5030
|
+
const point = [0, 0, 0];
|
|
5031
|
+
point[axis] = lead;
|
|
5032
|
+
point[u] = a;
|
|
5033
|
+
point[v] = b;
|
|
5034
|
+
origins.push(point);
|
|
5035
|
+
}
|
|
5036
|
+
}
|
|
5037
|
+
}
|
|
5038
|
+
return origins;
|
|
5039
|
+
}
|
|
5040
|
+
var THIN_SHEET_CRUSH = 5e-4;
|
|
5041
|
+
var THIN_SHEET_CONTACT = 0.025;
|
|
4811
5042
|
var DMG_PER_J = 0.02;
|
|
4812
5043
|
var BLAST_COUPLING = 0.1;
|
|
4813
5044
|
var SHELTER_DEFAULTS = { k: 2800, brokenTransmission: 0.5, minPath: 5e-3 };
|
|
@@ -4824,11 +5055,15 @@ var GameFloorplanStructure = (() => {
|
|
|
4824
5055
|
var SEVER_BAND = 0.1;
|
|
4825
5056
|
var SEVER_ASPECT = 3;
|
|
4826
5057
|
var SEVER_BALLISTIC = 2;
|
|
5058
|
+
var TEAR_JOULES = 150;
|
|
5059
|
+
var tears = 0;
|
|
4827
5060
|
var SUPPORT_TOLERANCE = 0.05;
|
|
4828
5061
|
var UNIT_FRAGMENT_FACTOR = 4;
|
|
4829
5062
|
var BREACH_GRID_CAP = 4096;
|
|
4830
5063
|
var CHIP_ENERGY = 200;
|
|
4831
5064
|
var CHIP_SPLASH = 0.5;
|
|
5065
|
+
var BAR_BOW = 0.08;
|
|
5066
|
+
var BULLET_JOINT_SPAN = 0.3;
|
|
4832
5067
|
var CUT_SLICE = 1;
|
|
4833
5068
|
var cutFactorOf = (shape) => clamp22(Math.max(...shapeDims(shape)) / CUT_SLICE, 1, 50);
|
|
4834
5069
|
var clamp22 = (v, a, b) => Math.max(a, Math.min(b, v));
|
|
@@ -4838,8 +5073,24 @@ var GameFloorplanStructure = (() => {
|
|
|
4838
5073
|
return v === void 0 ? void 0 : v * (mat.penetrationScale ?? 1);
|
|
4839
5074
|
};
|
|
4840
5075
|
var capacityScale = (p) => {
|
|
4841
|
-
|
|
4842
|
-
|
|
5076
|
+
const residual = p.spec.reinforcement?.residualCapacity ?? RESIDUAL_CAPACITY;
|
|
5077
|
+
if (p.st.stripped) return residual;
|
|
5078
|
+
const kept = Math.min(p.rt.removed ? 1 - p.rt.removed / p.mass0 : 1, 1 - sectionLoss(p));
|
|
5079
|
+
return Math.max(p.spec.reinforcement ? residual : 0.05, kept);
|
|
5080
|
+
};
|
|
5081
|
+
var sectionLoss = (p) => {
|
|
5082
|
+
const cells = p.st.chipped;
|
|
5083
|
+
if (!cells?.length) return 0;
|
|
5084
|
+
const [u, v] = planeAxes(p.thin);
|
|
5085
|
+
const along = p.dims[u] >= p.dims[v] ? u : v;
|
|
5086
|
+
const across = along === u ? v : u;
|
|
5087
|
+
let worst = 0;
|
|
5088
|
+
for (const c of cells) {
|
|
5089
|
+
let gone = 0;
|
|
5090
|
+
for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6) gone += d.size[across];
|
|
5091
|
+
worst = Math.max(worst, gone / Math.max(p.dims[across], 1e-6));
|
|
5092
|
+
}
|
|
5093
|
+
return Math.min(1, worst);
|
|
4843
5094
|
};
|
|
4844
5095
|
var isLost = (p) => p.st.status === "broken" || p.st.status === "melted" || p.st.status === "ashes";
|
|
4845
5096
|
var clone = (v) => structuredClone(v);
|
|
@@ -5939,7 +6190,7 @@ var GameFloorplanStructure = (() => {
|
|
|
5939
6190
|
emit({ ...base(o, src), type: "crack", part: p.spec.id, crack, worldPoint: wp });
|
|
5940
6191
|
setStage(o, p, 1, {}, src);
|
|
5941
6192
|
};
|
|
5942
|
-
const debris = (o, p, kind, point, normal, count, speed, src) => emit({ ...base(o, src), type: "debris", part: p.spec.id, kind, point, normal, count, speed });
|
|
6193
|
+
const debris = (o, p, kind, point, normal, count, speed, src, material) => emit({ ...base(o, src), type: "debris", part: p.spec.id, kind, point, normal, count, speed, ...material && material !== p.spec.material ? { material } : {} });
|
|
5943
6194
|
const holeRate = (hole, pressurized) => (pressurized ? 0.5 : 0.1) * (hole.diameter / 9e-3);
|
|
5944
6195
|
const detachEvents = (o, opened, by, src) => {
|
|
5945
6196
|
for (const j of opened) emit({ ...base(o, src), type: "detach", joint: j.spec.id, parts: [j.spec.a, j.spec.b], by, groups: o.st.groups.map((g) => [...g]) });
|
|
@@ -5980,7 +6231,13 @@ var GameFloorplanStructure = (() => {
|
|
|
5980
6231
|
const small = pa.dims[0] * pa.dims[1] * pa.dims[2] <= pb.dims[0] * pb.dims[1] * pb.dims[2] ? pa : pb;
|
|
5981
6232
|
return Math.max(0.06, 0.5 * Math.min(small.dims[0], small.dims[1], small.dims[2]));
|
|
5982
6233
|
};
|
|
5983
|
-
const
|
|
6234
|
+
const jointLength = (o, j) => {
|
|
6235
|
+
const A = partWorldAabb(o, o.parts[j.ia]), B = partWorldAabb(o, o.parts[j.ib]);
|
|
6236
|
+
let len = 0;
|
|
6237
|
+
for (let k = 0; k < 3; k++) len = Math.max(len, Math.min(A.max[k], B.max[k]) - Math.max(A.min[k], B.min[k]));
|
|
6238
|
+
return len;
|
|
6239
|
+
};
|
|
6240
|
+
const wearJoints = (o, p, amount, near, radius = 0.06, src, split = false, span) => {
|
|
5984
6241
|
if (amount <= 0) return;
|
|
5985
6242
|
const mine = (o.byPart.get(p.spec.id) ?? []).filter((j) => !j.st.open);
|
|
5986
6243
|
if (split && mine.length) amount /= mine.length;
|
|
@@ -5988,7 +6245,7 @@ var GameFloorplanStructure = (() => {
|
|
|
5988
6245
|
if (j.st.open) continue;
|
|
5989
6246
|
if (j.spec.kind === "rebar" && (isReinforced(o.parts[j.ia].spec) || isReinforced(o.parts[j.ib].spec))) continue;
|
|
5990
6247
|
if (near && jointReach(o, j, near) > Math.max(radius, jointReachLimit(o, j))) continue;
|
|
5991
|
-
j.st.hp -= amount;
|
|
6248
|
+
j.st.hp -= span === void 0 ? amount : amount * Math.min(1, span / Math.max(jointLength(o, j), 1e-6));
|
|
5992
6249
|
if (j.st.hp <= 0) {
|
|
5993
6250
|
j.st.hp = 0;
|
|
5994
6251
|
j.st.open = true;
|
|
@@ -6017,7 +6274,13 @@ var GameFloorplanStructure = (() => {
|
|
|
6017
6274
|
if (spalls.length > MAX_SPALLS) spalls.shift();
|
|
6018
6275
|
markDamaged(p);
|
|
6019
6276
|
emit({ ...base(o, src), type: "spall", part: p.spec.id, layer: layer.index, point: wp, area: Math.PI * radius * radius });
|
|
6020
|
-
debris(o, p, layer.mat.hitDebris, wp, normal, 5, 2, src);
|
|
6277
|
+
debris(o, p, layer.mat.hitDebris, wp, normal, 5, 2, src, layer.mat.id);
|
|
6278
|
+
setStage(o, p, 1, {}, src);
|
|
6279
|
+
};
|
|
6280
|
+
const crater = (o, p, wp, normal, radius, src) => {
|
|
6281
|
+
markDamaged(p);
|
|
6282
|
+
emit({ ...base(o, src), type: "spall", part: p.spec.id, layer: -1, point: wp, area: Math.PI * radius * radius });
|
|
6283
|
+
debris(o, p, p.mat.breakDebris, wp, normal, 6, 1.5, src);
|
|
6021
6284
|
setStage(o, p, 1, {}, src);
|
|
6022
6285
|
};
|
|
6023
6286
|
const insideOpening = (o, p, objectPoint) => {
|
|
@@ -6096,9 +6359,13 @@ var GameFloorplanStructure = (() => {
|
|
|
6096
6359
|
const lp = toLocal(p.pos, p.q, objectPoint);
|
|
6097
6360
|
return cells.some((c) => Math.abs(lp[u] - c.center[u]) <= c.size[u] / 2 && Math.abs(lp[v] - c.center[v]) <= c.size[v] / 2);
|
|
6098
6361
|
};
|
|
6099
|
-
const chipUnits = (o, p, wp,
|
|
6362
|
+
const chipUnits = (o, p, kind, wp, hitEnergy, dir, radius, src) => {
|
|
6100
6363
|
var _a, _b;
|
|
6101
|
-
if (!p.spec.units ||
|
|
6364
|
+
if (!p.spec.units || !p.staged || chipEnergy <= 0 || p.st.stripped || isLost(p) || (p.st.stage ?? 0) >= 2) return;
|
|
6365
|
+
const rule = p.mat.hits?.[kind];
|
|
6366
|
+
const perKg = rule?.unitJoules ?? chipEnergy;
|
|
6367
|
+
const energy = hitEnergy - (rule?.floor ?? 0);
|
|
6368
|
+
if (perKg <= 0 || energy <= 0) return;
|
|
6102
6369
|
const [u, v] = planeAxes(p.thin);
|
|
6103
6370
|
const lp = toLocal(p.pos, p.q, objLocal(o, wp));
|
|
6104
6371
|
const grid = gridOf(p);
|
|
@@ -6112,7 +6379,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6112
6379
|
const share = gap === 0 ? 1 : CHIP_SPLASH * (1 - gap / radius);
|
|
6113
6380
|
const total = (worn[i] ?? 0) + energy * share;
|
|
6114
6381
|
const mass = p.mat.density * cell.size[0] * cell.size[1] * cell.size[2];
|
|
6115
|
-
if (total <
|
|
6382
|
+
if (total < perKg * mass) {
|
|
6116
6383
|
worn[i] = total;
|
|
6117
6384
|
continue;
|
|
6118
6385
|
}
|
|
@@ -6137,7 +6404,32 @@ var GameFloorplanStructure = (() => {
|
|
|
6137
6404
|
emit({ ...base(o, src), type: "chip", part: p.spec.id, center, size: [cell.size[0], cell.size[1], cell.size[2]], rotation: q, fragments });
|
|
6138
6405
|
debris(o, p, p.mat.breakDebris, center, vec.scale(dir ?? [0, 1, 0], -1), 6, 2, src);
|
|
6139
6406
|
}
|
|
6407
|
+
if (p.spec.reinforcement) exposeRebar(o, p, src);
|
|
6140
6408
|
for (const cell of out) addBreach(o, p, toWorld(c, q, cell.center), cell.size[u] * cell.size[v], energy, dir, src);
|
|
6409
|
+
if (p.structural && !isLost(p)) {
|
|
6410
|
+
solveStructure(o);
|
|
6411
|
+
collapseCheck(o, src);
|
|
6412
|
+
}
|
|
6413
|
+
};
|
|
6414
|
+
const exposeRebar = (o, p, src) => {
|
|
6415
|
+
const r = p.spec.reinforcement;
|
|
6416
|
+
if (!r) return;
|
|
6417
|
+
const [u, v] = planeAxes(p.thin);
|
|
6418
|
+
const all = rebarBars(p.dims, p.thin, r.spacing);
|
|
6419
|
+
let bars;
|
|
6420
|
+
if (p.st.stripped) bars = all;
|
|
6421
|
+
else {
|
|
6422
|
+
bars = [];
|
|
6423
|
+
for (const cell of p.st.chipped ?? []) bars.push(...clipBarsToBox(all, u, v, cell.center, cell.size));
|
|
6424
|
+
const op = p.st.opening;
|
|
6425
|
+
if (op) {
|
|
6426
|
+
const lc = toLocal(p.pos, p.q, op.center);
|
|
6427
|
+
bars.push(...clipBarsToDisc(all, u, v, [lc[u], lc[v]], op.radius + 0.05));
|
|
6428
|
+
}
|
|
6429
|
+
}
|
|
6430
|
+
const bow = clamp22(((p.st.stress ?? 0) - 1) / 0.5, 0, 1);
|
|
6431
|
+
if (bow > 0) bars = bars.flatMap((bar2, i) => bendBar(bar2, p.thin, bow * BAR_BOW, i));
|
|
6432
|
+
emit({ ...base(o, src), type: "expose", part: p.spec.id, bars: worldBars(o, p, bars) });
|
|
6141
6433
|
};
|
|
6142
6434
|
const openBreach = (o, p, center, total, energy, dir, src) => {
|
|
6143
6435
|
const [u, v] = planeAxes(p.thin);
|
|
@@ -6165,10 +6457,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6165
6457
|
setStage(o, p, 2, { opening: { center: worldCenter, radius }, fragments }, src);
|
|
6166
6458
|
debris(o, p, p.mat.breakDebris, worldCenter, vec.scale(dir ?? [0, 1, 0], -1), 14, 3, src);
|
|
6167
6459
|
const reinforcement = p.spec.reinforcement;
|
|
6168
|
-
if (reinforcement)
|
|
6169
|
-
const bars = worldBars(o, p, clipBarsToDisc(rebarBars(p.dims, p.thin, reinforcement.spacing), u, v, [lc[u], lc[v]], radius + 0.05));
|
|
6170
|
-
if (bars.length > 0) emit({ ...base(o, src), type: "expose", part: p.spec.id, bars });
|
|
6171
|
-
}
|
|
6460
|
+
if (reinforcement) exposeRebar(o, p, src);
|
|
6172
6461
|
if (p.structural) solveStructure(o);
|
|
6173
6462
|
};
|
|
6174
6463
|
const stripPart = (o, p, reinforcement, src) => {
|
|
@@ -6180,8 +6469,8 @@ var GameFloorplanStructure = (() => {
|
|
|
6180
6469
|
p.st.burning = false;
|
|
6181
6470
|
p.rt.jet = false;
|
|
6182
6471
|
markDamaged(p);
|
|
6183
|
-
emit({ ...base(o, src), type: "expose", part: p.spec.id, bars: worldBars(o, p, bars) });
|
|
6184
6472
|
solveStructure(o);
|
|
6473
|
+
exposeRebar(o, p, src);
|
|
6185
6474
|
collapseCheck(o, src);
|
|
6186
6475
|
};
|
|
6187
6476
|
const unitFragmentPlan = (p, cap) => {
|
|
@@ -6235,7 +6524,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6235
6524
|
const grain = p.spec.grain ? AXIS[p.spec.grain] : void 0;
|
|
6236
6525
|
const hitLocal = toLocal(c, q, hitW);
|
|
6237
6526
|
const unitPlan = p.spec.units ? unitFragmentPlan(p, maxFragments * UNIT_FRAGMENT_FACTOR) : [];
|
|
6238
|
-
const axis = style === "splinter" ? severAxis(p) : -1;
|
|
6527
|
+
const axis = style === "splinter" || style === "snap" ? severAxis(p) : -1;
|
|
6239
6528
|
const cutAt2 = axis < 0 ? void 0 : p.rt.cutAt ?? (origin ? hitLocal[axis] : void 0);
|
|
6240
6529
|
const plan = unitPlan.length > 0 ? unitPlan : planFragments({
|
|
6241
6530
|
style,
|
|
@@ -6307,7 +6596,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6307
6596
|
};
|
|
6308
6597
|
const CHAIN_TRIGGER_OF = { ballistic: "shot", explosive: "explosion" };
|
|
6309
6598
|
const severAxis = (p) => {
|
|
6310
|
-
if (p.mat.fracture !== "splinter" || p.spec.shape.kind !== "box") return -1;
|
|
6599
|
+
if (p.mat.fracture !== "splinter" && p.mat.fracture !== "snap" || p.spec.shape.kind !== "box") return -1;
|
|
6311
6600
|
const d = p.dims;
|
|
6312
6601
|
const order = [0, 1, 2].sort((a, b) => d[b] - d[a]);
|
|
6313
6602
|
return d[order[0]] >= SEVER_ASPECT * d[order[1]] && d[order[0]] >= 3 * SEVER_BAND ? order[0] : -1;
|
|
@@ -6368,6 +6657,49 @@ var GameFloorplanStructure = (() => {
|
|
|
6368
6657
|
}
|
|
6369
6658
|
}
|
|
6370
6659
|
};
|
|
6660
|
+
const tearOf = (mat, kind) => {
|
|
6661
|
+
const h = mat.hits?.[kind];
|
|
6662
|
+
const tear = h?.tear ?? (kind === "ballistic" && mat.penetrationClass === "wood" ? "splinters" : "none");
|
|
6663
|
+
return { tear, joules: h?.tearJoules ?? TEAR_JOULES };
|
|
6664
|
+
};
|
|
6665
|
+
const tearAt = (o, p, kind, entry2, exit, d, E, scale, src) => {
|
|
6666
|
+
const { tear, joules } = tearOf(p.mat, kind);
|
|
6667
|
+
if (tear === "none") return;
|
|
6668
|
+
const shot = kind === "ballistic";
|
|
6669
|
+
const n = shot ? exit ? clamp22(Math.round(E / joules), 1, 7) : 1 : clamp22(Math.floor(E / joules), 0, 5);
|
|
6670
|
+
if (n === 0) return;
|
|
6671
|
+
const fibre = tear === "lumps";
|
|
6672
|
+
const { q } = partXf(o, p);
|
|
6673
|
+
const along = (p.spec.grain ? AXIS[p.spec.grain] : void 0) ?? [0, 1, 2].sort((a, b) => p.dims[b] - p.dims[a])[0];
|
|
6674
|
+
const fragments = [];
|
|
6675
|
+
for (let i = 0; i < n; i++) {
|
|
6676
|
+
const back = !exit || i % 3 === 2;
|
|
6677
|
+
const len = scale * (fibre ? 1.2 + 1.2 * rnd() : 3 + 4 * rnd()), w = scale * (0.8 + 0.8 * rnd()), t = scale * (fibre ? 0.7 + 0.6 * rnd() : 0.4 + 0.4 * rnd());
|
|
6678
|
+
const size = [w, w, w];
|
|
6679
|
+
size[along] = len;
|
|
6680
|
+
size[(along + 1) % 3] = w;
|
|
6681
|
+
size[(along + 2) % 3] = t;
|
|
6682
|
+
const spread3 = [(rnd() - 0.5) * 0.8, (rnd() - 0.2) * 0.8, (rnd() - 0.5) * 0.8];
|
|
6683
|
+
const speed = shot ? back ? 1.5 + 2 * rnd() : 2 + 4 * rnd() : 0.8 + 1.2 * rnd();
|
|
6684
|
+
const v = vec.scale(vec.normalize(vec.add(back ? vec.scale(d, -1) : d, spread3)), speed);
|
|
6685
|
+
const mass = size[0] * size[1] * size[2] * p.mat.density;
|
|
6686
|
+
fragments.push({
|
|
6687
|
+
id: `${p.spec.id}#t${tears++}-${i}`,
|
|
6688
|
+
part: p.spec.id,
|
|
6689
|
+
material: p.spec.material,
|
|
6690
|
+
shape: fibre ? "chunk" : "splinter",
|
|
6691
|
+
center: back || !exit ? vec.madd(entry2, d, -0.01) : vec.madd(exit, d, 0.01),
|
|
6692
|
+
size,
|
|
6693
|
+
rotation: q,
|
|
6694
|
+
velocity: v,
|
|
6695
|
+
inner: true,
|
|
6696
|
+
angularVelocity: [(rnd() - 0.5) * 30, (rnd() - 0.5) * 30, (rnd() - 0.5) * 30],
|
|
6697
|
+
mass
|
|
6698
|
+
});
|
|
6699
|
+
}
|
|
6700
|
+
const patch = [scale * 4, scale * 4, scale * 4];
|
|
6701
|
+
emit({ ...base(o, src), type: "chip", part: p.spec.id, center: exit ?? entry2, size: patch, rotation: q, fragments });
|
|
6702
|
+
};
|
|
6371
6703
|
const ballistic = (o, p, entry2, n, d, E, caliber, pathLen, src, round3 = {}) => {
|
|
6372
6704
|
const mat = p.mat;
|
|
6373
6705
|
const piercing = round3.piercing ?? 1;
|
|
@@ -6396,6 +6728,7 @@ var GameFloorplanStructure = (() => {
|
|
|
6396
6728
|
return { penetrated: false, exitEnergy: 0, damage: dmg2 };
|
|
6397
6729
|
}
|
|
6398
6730
|
if (p.layers.length > 0) spallOuter(o, p, entry2, face, n, Math.max(0.03, caliber / 1e3 * 4), src);
|
|
6731
|
+
else if (mat.hits?.ballistic?.crater) crater(o, p, entry2, n, clamp22(0.02 + Math.sqrt(E) * 15e-4, 0.02, 0.15), src);
|
|
6399
6732
|
const brittle = mat.ductility < 0.3;
|
|
6400
6733
|
const ratio = Ep / Math.max(thr, 1e-6);
|
|
6401
6734
|
const crackLen = clamp22(0.03 + ratio * 0.2, 0.03, 0.8);
|
|
@@ -6428,9 +6761,11 @@ var GameFloorplanStructure = (() => {
|
|
|
6428
6761
|
if (mat.fracture !== "shatter") addHole(o, p, entry2, n, caliber / 1e3, false, void 0, src);
|
|
6429
6762
|
} else addHole(o, p, entry2, n, caliber / 1e3, false, void 0, src);
|
|
6430
6763
|
debris(o, p, mat.hitDebris, entry2, n, clamp22(Math.round(E / 60) + 2, 2, 14), clamp22(Math.sqrt(E) / 6, 1, 8), src);
|
|
6431
|
-
wearJoints(o, p, (penetrated ? thr : E) * 0.02, void 0, 0, src, true);
|
|
6432
|
-
const
|
|
6433
|
-
|
|
6764
|
+
wearJoints(o, p, (penetrated ? thr : E) * 0.02, void 0, 0, src, true, BULLET_JOINT_SPAN);
|
|
6765
|
+
const absorbed = penetrated && mat.ductility >= 0.5 && mat.fracture !== "tear" ? Math.min(E, thr) : E;
|
|
6766
|
+
const dmg = applyDamage(o, p, absorbed * DMG_PER_J * scale, "ballistic", entry2, d, absorbed * 0.1, 12, src);
|
|
6767
|
+
if (!isLost(p)) tearAt(o, p, "ballistic", entry2, penetrated ? exitPoint : void 0, d, E, caliber / 1e3, src);
|
|
6768
|
+
chipUnits(o, p, "ballistic", entry2, penetrated ? Math.min(E, Math.max(thr, E * 0.5)) : E, d, Math.max(0.05, caliber / 1e3 * 8), src);
|
|
6434
6769
|
return { penetrated, exitEnergy: penetrated ? penMm !== void 0 ? E * (1 - thr / Ep) : E - thr / (hard ? piercing : 1) : 0, exitPoint, damage: dmg };
|
|
6435
6770
|
};
|
|
6436
6771
|
const melee = (o, p, kind, E, point, n, d, contactR, src) => {
|
|
@@ -6438,14 +6773,20 @@ var GameFloorplanStructure = (() => {
|
|
|
6438
6773
|
const thrMm = mat.penetration * p.thickness * 1e3;
|
|
6439
6774
|
const fragile = kind === "blunt" ? fragility(mat.ductility, p.thickness) : 1;
|
|
6440
6775
|
const Ec = E * fragile;
|
|
6776
|
+
const sheet = mat.ductility >= 0.5 && p.thickness <= THIN_SHEET_CRUSH;
|
|
6777
|
+
const fold = sheet ? Math.min(4, Math.sqrt(1e-3 / p.thickness)) : 1;
|
|
6778
|
+
const patch = sheet ? Math.min(contactR, THIN_SHEET_CONTACT) : contactR;
|
|
6441
6779
|
if (E > 0) {
|
|
6442
6780
|
if (kind === "blunt") {
|
|
6443
|
-
if (mat.ductility >= 0.5) addDent(o, p, point, n, Math.max(
|
|
6781
|
+
if (mat.ductility >= 0.5) addDent(o, p, point, n, Math.max(patch, 0.015), clamp22(E * 1e-4 * fold, 1e-3, sheet ? Math.min(0.06, Math.min(...p.dims) * 0.45) : 0.06), src);
|
|
6444
6782
|
else if (mat.ductility < 0.3) {
|
|
6445
6783
|
if (Ec >= 5) addCrack(o, p, point, n, clamp22(0.04 + Math.min(Ec, E * 6) * 8e-4, 0.04, 0.6), src);
|
|
6446
6784
|
} else if (E >= thrMm * 0.2) addDent(o, p, point, n, Math.max(contactR, 0.015), clamp22(E * 6e-5, 1e-3, 0.04), src);
|
|
6447
6785
|
} else if (mat.fracture === "tear") {
|
|
6448
6786
|
addHole(o, p, point, n, clamp22(0.02 + E * 5e-4, 0.02, 0.3), true, void 0, src);
|
|
6787
|
+
} else if (mat.ductility >= 0.3 && E >= thrMm) {
|
|
6788
|
+
addHole(o, p, point, n, clamp22(contactR, 0.01, 0.08), true, void 0, src);
|
|
6789
|
+
if (sheet) addDent(o, p, point, n, Math.max(patch * 0.6, 0.01), clamp22(E * 4e-5 * fold, 5e-4, 0.02), src);
|
|
6449
6790
|
} else if (mat.ductility >= 0.5) {
|
|
6450
6791
|
addDent(o, p, point, n, Math.max(contactR, 0.01), clamp22(E * 4e-5, 5e-4, 0.02), src);
|
|
6451
6792
|
}
|
|
@@ -6458,7 +6799,8 @@ var GameFloorplanStructure = (() => {
|
|
|
6458
6799
|
const scale = mat.damageScale?.[kind] ?? 1;
|
|
6459
6800
|
const done = applyDamage(o, p, Ec * DMG_PER_J * scale * (kind === "slash" ? p.cutFactor : 1), kind, point, d, E * 0.1, 12, src);
|
|
6460
6801
|
addBreach(o, p, point, breachAreaOf(p, done, false), E, d, src);
|
|
6461
|
-
if (kind === "blunt") chipUnits(o, p, point, E, d, Math.max(contactR, 0.03), src);
|
|
6802
|
+
if (kind === "blunt") chipUnits(o, p, "blunt", point, E, d, Math.max(contactR, 0.03), src);
|
|
6803
|
+
if (E > 0 && !isLost(p)) tearAt(o, p, kind, point, void 0, d, E, clamp22(contactR * 0.2, 6e-3, 0.02), src);
|
|
6462
6804
|
return done;
|
|
6463
6805
|
};
|
|
6464
6806
|
const blastPart = (o, p, point, energy, radius, src, res, reachAt) => {
|
|
@@ -7037,6 +7379,7 @@ var GameFloorplanStructure = (() => {
|
|
|
7037
7379
|
if (p.rt.stressT <= 0) {
|
|
7038
7380
|
p.rt.stressT = 0.5;
|
|
7039
7381
|
emit({ ...base(o), type: "stress", part: p.spec.id, stress, load: p.st.load ?? 0 });
|
|
7382
|
+
if (p.spec.reinforcement && (p.st.stripped || p.st.chipped?.length || p.st.opening)) exposeRebar(o, p);
|
|
7040
7383
|
}
|
|
7041
7384
|
applyDamage(o, p, overloadRate(stress) * p.st.maxHp * dt, "blunt", null, null, 5, 3);
|
|
7042
7385
|
} else if (stress > 0.8 && p.mat.ductility < 0.3 && p.rt.stressT <= 0 && p.st.cracks.length < 6) {
|
|
@@ -7253,6 +7596,18 @@ var GameFloorplanStructure = (() => {
|
|
|
7253
7596
|
const r = raycastInternal(origin, direction, maxDistance);
|
|
7254
7597
|
return r ? { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: r.distance } : null;
|
|
7255
7598
|
},
|
|
7599
|
+
sweepBox(box2, direction, distance2, options2 = {}) {
|
|
7600
|
+
const d = vec.normalize(direction);
|
|
7601
|
+
const ignored = options2.ignore === void 0 ? void 0 : objects.get(options2.ignore);
|
|
7602
|
+
const ignore = ignored ? new Set(ignored.parts.map((p) => `${ignored.id}\0${p.spec.id}`)) : void 0;
|
|
7603
|
+
let best = null;
|
|
7604
|
+
for (const origin of sweepOrigins(box2, d, options2.spacing ?? 0.2)) {
|
|
7605
|
+
const r = raycastInternal(origin, d, distance2 + SWEEP_BACK, ignore);
|
|
7606
|
+
if (!r || best && r.distance >= best.distance) continue;
|
|
7607
|
+
best = { object: r.object, part: r.part, point: r.point, normal: r.normal, distance: Math.max(0, r.distance - SWEEP_BACK) };
|
|
7608
|
+
}
|
|
7609
|
+
return best;
|
|
7610
|
+
},
|
|
7256
7611
|
shoot(origin, direction, energy, caliber, source, round3) {
|
|
7257
7612
|
const extras = typeof round3 === "number" ? { piercing: round3 } : round3 ?? {};
|
|
7258
7613
|
return withCollapses(run(() => {
|
|
@@ -8677,7 +9032,24 @@ var GameFloorplanStructure = (() => {
|
|
|
8677
9032
|
}
|
|
8678
9033
|
return spec;
|
|
8679
9034
|
};
|
|
8680
|
-
var
|
|
9035
|
+
var MEMBER_CAGE = { spacing: 0.1, diameter: 8e-3, unit: 0.1 };
|
|
9036
|
+
var CAGED_ROLES = /* @__PURE__ */ new Set(["beam", "column"]);
|
|
9037
|
+
var caged = (spec, part, rebar) => {
|
|
9038
|
+
if (!rebar || part.material !== "concrete" || !CAGED_ROLES.has(part.role) || spec.reinforcement) return spec;
|
|
9039
|
+
const size = spec.shape.kind === "box" ? spec.shape.size : null;
|
|
9040
|
+
if (!size) return spec;
|
|
9041
|
+
const thin = Math.min(...size);
|
|
9042
|
+
return {
|
|
9043
|
+
...spec,
|
|
9044
|
+
reinforcement: { material: rebar, spacing: MEMBER_CAGE.spacing, diameter: MEMBER_CAGE.diameter },
|
|
9045
|
+
units: { size: [MEMBER_CAGE.unit, MEMBER_CAGE.unit, thin], bond: "stack", mortar: "concrete" }
|
|
9046
|
+
};
|
|
9047
|
+
};
|
|
9048
|
+
var partSpecOf = (part, capacity, detailed, rebar) => {
|
|
9049
|
+
if (detailed && part.assembly) return assemblySpec(part, capacity);
|
|
9050
|
+
const spec = boxSpec(part, capacity);
|
|
9051
|
+
return detailed ? caged(spec, part, rebar) : spec;
|
|
9052
|
+
};
|
|
8681
9053
|
function toDestructibleSpec(structure, options = {}) {
|
|
8682
9054
|
const { safety = 0.65, redundancy = 0.97, safetyOthers = 0.45 } = options;
|
|
8683
9055
|
const kept = structure.parts.filter((part) => !options.filter || options.filter(part));
|
|
@@ -8694,7 +9066,7 @@ var GameFloorplanStructure = (() => {
|
|
|
8694
9066
|
const sizing = { safety, redundancy, safetyOthers };
|
|
8695
9067
|
const sized = { ...panels, capacities: options.sized === false ? /* @__PURE__ */ new Map() : sizeCapacities(panels.parts, panels.supports, sizing) };
|
|
8696
9068
|
const { parts, supports, capacities } = detail === "units" ? applyUnits(sized, structure) : sized;
|
|
8697
|
-
const specs = parts.map((part) => partSpecOf(part, capacities.get(part.id), detail !== "coarse"));
|
|
9069
|
+
const specs = parts.map((part) => partSpecOf(part, capacities.get(part.id), detail !== "coarse", structure.construction.frame.rebar));
|
|
8698
9070
|
const margin = options.terrainMargin ?? TERRAIN_MARGIN;
|
|
8699
9071
|
const x0 = Math.min(...parts.map((part) => part.aabb[0]));
|
|
8700
9072
|
const z0 = Math.min(...parts.map((part) => part.aabb[1]));
|