Correct building stability calculation (from code)
I've seen various stability theories bandied about, but there's an objective solution you can get simply from reading the decompiled code of the game. I used DNSpy and the functions GetMaterialProperties and UpdateSupport to get the following:
First, every building component is made using one of the following material properties:
Type | MaxSupport | MinSupport | VerticalLoss | HorizontalLoss -----|------------|------------|--------------|---------------- Wood | 100 | 10 | 0.125 | 0.2 Stone | 1000 | 100 | 0.125 | 1 Iron | 1500 | 20 | 0.07692308 | 0.07692308 Hardwood | 140 | 10 | 0.1 | 0.16666667
These properties are used to calculate the "support" that a component has, which in turn decides whether the component should break.
- MaxSupport: the maximum amount of support a component can have. If it's blue (anchored to the ground), its support will be equal to its MaxSupport. Also if it's anchored to something with a much higher support value (e.g. wood on stone), its support is capped at this value. - MinSupport: the minimum amount of support a component can have. If it has less support than this, it will break. - VerticalLoss/HorizontalLoss: factors that dictate the ratio at which a component loses support (explained below).
Let's handle the purely vertical case first, for simplicity. The support a component has depends on the following:
- The support of the component it's anchored to (I will call this component the "parent") - Its maximum allowed support - Its Loss factor (in this case, VerticalLoss) - Its length - Its *parent's* length
The reason the parent's length is necessary is because the distance between the components is computed from the midpoint of each piece (this isn't explicitly in the code, by the way: I had to determine it through experiment). So here's the full formula to compute the support for a piece that's stacked vertically on another piece:
Support = Min( [MaxSupport], [Parent's Support] - [VerticalLoss] * ([Length]/2 + [Parent's Length]/2 + 0.1) * [Parent's Support] );
Note that "Min" here means to take the smaller of the two values. So, to take an example, the Wood pole 2m is a Wood component that's 2 meters long. If we put one on the ground, its support is therefore 100 (the max for Wood). If we then stack another on top of it, plugging the appropriate values into the equation, its support is:
73.75 = Min( 100, 100 - 0.125 * (2/2 + 2/2 + 0.1) * 100 )
As we stack more on top, we repeat the equation, each time taking the previous component's support as the next component's parent's support.
Piece # | Support --------|--------- 1 | 100 2 | 73.75 3 | 54.390625 4 | 40.11308594 5 | 29.58340088 6 | 21.81775815 7 | 16.09059663 8 | 11.86681502 9 | 8.751776076
The ninth piece from the ground has a support (8.75...) that is less than Wood's MinSupport (10). Therefore, after the structure settles, it will break.
NOTE: Since these numbers use floats, the equation shouldn't be considered exact. For example, the sixth "Log pole 4m" from the ground should have a support of 10.00894, but in my experiments it broke anyway. So be cautious when pushing the limits.
Now, for horizontal structures, the equation is essentially the same (using the Pythagorean theorem to compute the distance between midpoints), but it interpolates between VerticalLoss and HorizontalLoss depending on the angle between the two components' midpoints. If the angle is entirely horizontal, it uses HorizontalLoss. If the angle is 45°, it uses the average halfway between the two Loss values. If the angle is negative (for example, a diagonal piece attached at its top to a horizontal piece), it counts as entirely horizontal. Here's an example experiment I did:
Piece # | Type | Orientation | Support ---|---|---|--- 1 | Wood Pole 1m | Vertical | 100 2 | Log Pole 2m | Vertical | 84 3 | Wood Beam 1m | Horizontal | 63.5370288 4 | Wood Beam 2m | Horizontal | 41.81985633 5 | Wood Beam 2m | Horizontal | 24.25551667 6 | Wood Beam 2m | Horizontal | 14.06819967 7 | Wood Beam 1m | Horizontal | 9.566375775
As you can see, the last 1m beam broke soon after I placed it.
I hope with these formula, we can settle the issue of how structural stability works and start figuring out how to take advantage of it.