The editor's resource value calculation logic was fixed in #21820 to
match actual gameplay. The map generator logic originally copied the
editor logic from EditorResourceLayer rather than ResourceLayer and
associated game logic. As such, it inherited incorrect calculations.
This change updates the map generator logic to match the now
consistent logic in both ResourceLayer classes. Map generator resource
settings are also adjusted -25% to continue roughly matching the
previous resource output.
For awkward symmetries (where there is mirroring and/or non-grid
aligned rotations), road planning now runs an extra filtering step so
that only sufficiently symmetric road plans make it to the tiling
stage.
Road planning also now extends out-of-map-bounds to more accurately
accommodate awkward rotations, improving the symmetry of pre-filtered
road plans.
A previous filter, which removes nearly horizontal or vertical roads
is now removed, as this is not fair to all rotations. This step is
less importance since the introduction of relaxed tiling.
Note that roads may be dropped entirely if the plans come out highly
asymmetric. This is not uncommon for awkward rotations. This is
preferred over presenting a map with asymmetric roads.
CnC map generation previously only supported maps with water/beaches
for the DESERT tileset, as it is the only tileset with a complete set
of beach tiles. This change adds support for the other tilesets
(TEMPERAT, SNOW, WINTER) by adding fake beach templates constructed
from actors and other templates' tiles that look reasonable in both
original and remastered graphics.
This means all CnC tilesets have feature parity in the map generator.
This generalizes TilingPath to accept MultiBrushes instead of templates
and makes the output also a MultiBrush. As a result:
- Composite or faked templates can be used in tiling. This will (in a
later change) be used to support CnC beaches outside of the desert
tileset.
- The tiling result can be previewed without committing it onto the map,
making it more viable for adoption as an editor tool.
- The full shape of the tiling result can be inspected without messily
reading it back off of the map, simplifying some map generator logic.
- Separates map generation-specific segment definitions from the core
template definitions.
- As MultiBrushes can be many-to-one with templates, there is no need to
have a one-to-many template-segment relationship. Multi-segment
templates, such as roads, now use multiple brushes instead. This
simplifies the logic of segment consumers.
Previously, MultiBrushes which contained no offset information in their
definitions were automatically aligned such that the first tile was
under 0,0. This is no longer the case. This was previously done for use
in MultiBrush.PaintArea to improve tile packing success, but the
alignment is now handled automatically by PaintArea instead.
Due to some impure refactoring which changes the randomization of
tiling choices, map generation results may change.
Whilst TilingPath has always allowed deviating from the path points
between the start and end point, it didn't allow deviation from the
start or end points themselves. This change allows the end point to
deviate if the tiling would otherwise fail. The start point remains
strictly positioned, as before. Loop end points (which must necessarily
match the start) also remain strict.
The ExperimentalMapGenerator is modified to benefit from the relaxed
tiling constraints. As a result, failed map generation due to tiling
failures is much rarer, and will make some otherwise very inflexible
template categories viable for tiling.
Includes some impure refactoring around the treatment of start,
intermediate, and end segments. As such, this changes map generation
output, even for maps which already tiled perfectly.
A previous workaround used for CnC road templates, whereby additional
segments were defined for road ending templates, is now redundant and
cleaned up.
Previously, the MiniYaml.From* helpers such as FromStream would consume the entire input and then return a list of top-level nodes. Now, the input is processed using deferred execution and top-level nodes are yielded as they are resolved from the input.
The motivating use-case is MapCache, which currently manually buffers nodes before passing to MiniYaml.FromString in order to improve responsiveness when large payloads are processed. Now that MiniYaml.FromStream yields results back as they come in, we can switch to that without disadvantage.
The maintains the performance where map cache can update search results as each node comes in over the network rather than having to wait for the entire batch to be transferred. Now we can also remove the string buffer that captures each node, reducing memory pressure and simplifying the code.
This override allows quantization to be disabled, and is used by the TS mod as the voxel based actors can be rotated to any orientation/facing. To prevent a divide by zero error for these actors, we need to return early from QuantizeFacing just like we do in QuantizeOrientation.
However, when QuantizedFacings is not explicitly set to zero, we still want to catch errors when artwork sequences have zero facings. The new check would cause such errors to be hidden. To prevent this add some exceptions with a detailed error message.
Currently removal nodes in MiniYaml are only applied whilst resolving inherited nodes. When merging collections to override existing nodes the removals are not resolved, resulting in duplicate key errors if you remove a node to then add it back with different values.
Now, removal nodes are also resolved when merging, allowing nodes to be removed as overridden during merging just like they can be with inheritance.
When the solution is built, previously the Test and WindowsLauncher projects were excluded. Now only the WindowsLauncher project is excluded. This avoids needing to build the Test project separately after building the solution.
This tileset was community content, and does not have remastered assets.
There is no realistic prospect to creating equivalent remastered assets,
which leaves removal in order to achieve parity between classic and
remastered modes.
This rule recommends use of primary constructors. Apply the suggestions on simple POCOs, adjusting some to readonly/structs/records at the same time. For more complex classes, the use of primary constructors is more distracting than helpful, so silence the rule. IDEs can still offer fixes for using primary constructors, but it will not show up as a build issue.