fix(app+core): Phase B.3 — Setup.StepUpHeight + scenery road exclusion
StepUpHeight: when Tab enters player mode, read Setup.StepUpHeight from the player entity's dat and apply it to the controller (fallback 2f for non-Setup entities or when the dat value is zero). Previously hardcoded to 5.0 which made step-up too permissive. Road exclusion: SceneryGenerator now skips terrain vertices where bits 0-1 of the raw terrain word are non-zero. These bits encode the road type (GetRoad() in ACViewer's Landblock.cs). Trees, rocks and bushes will no longer be placed on road surfaces. Added SceneryGenerator.IsRoadVertex(ushort) public helper + 9 unit tests (theory + fact) verifying the road-bit convention matches TerrainInfo.Road. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8252523b8b
commit
768a9a0619
2 changed files with 89 additions and 1 deletions
53
tests/AcDream.Core.Tests/World/SceneryGeneratorTests.cs
Normal file
53
tests/AcDream.Core.Tests/World/SceneryGeneratorTests.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using AcDream.Core.World;
|
||||
using DatReaderWriter.Types;
|
||||
|
||||
namespace AcDream.Core.Tests.World;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for SceneryGenerator road-exclusion logic.
|
||||
/// The full Generate() pipeline requires real dat files (Region, Scene, etc.)
|
||||
/// so road-check behavior is tested via the internal IsRoadVertex helper,
|
||||
/// which is the single gate that guards against placing trees on roads.
|
||||
/// </summary>
|
||||
public class SceneryGeneratorTests
|
||||
{
|
||||
// Terrain word layout (ushort):
|
||||
// bits 0-1 = Road (non-zero → on a road)
|
||||
// bits 2-6 = TerrainType
|
||||
// bits 11-15 = SceneType
|
||||
|
||||
[Theory]
|
||||
[InlineData(0x0000, false)] // no road bits
|
||||
[InlineData(0x0001, true)] // road bit 0 set
|
||||
[InlineData(0x0002, true)] // road bit 1 set
|
||||
[InlineData(0x0003, true)] // both road bits set
|
||||
[InlineData(0x007C, false)] // terrain type bits only, no road
|
||||
[InlineData(0xF800, false)] // scenery bits only, no road
|
||||
[InlineData(0xF803, true)] // road + scenery bits
|
||||
public void IsRoadVertex_CorrectlyIdentifiesRoadBits(ushort raw, bool expectedIsRoad)
|
||||
{
|
||||
Assert.Equal(expectedIsRoad, SceneryGenerator.IsRoadVertex(raw));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsRoadVertex_ZeroTerrain_IsNotRoad()
|
||||
{
|
||||
// A fully blank terrain entry (no type, no road, no scene) is not a road.
|
||||
Assert.False(SceneryGenerator.IsRoadVertex(0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsRoadVertex_MatchesTerrainInfoRoadProperty()
|
||||
{
|
||||
// Verify that IsRoadVertex agrees with the typed TerrainInfo.Road property
|
||||
// for a sample of raw values, ensuring the bit convention is consistent.
|
||||
for (ushort raw = 0; raw < 4; raw++)
|
||||
{
|
||||
TerrainInfo ti = raw;
|
||||
bool expectedFromStruct = ti.Road != 0;
|
||||
bool actual = SceneryGenerator.IsRoadVertex(raw);
|
||||
Assert.True(actual == expectedFromStruct,
|
||||
$"raw=0x{raw:X4}: IsRoadVertex={actual} but TerrainInfo.Road={ti.Road}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue