test: harden jajce terrain navigation
This commit is contained in:
@@ -623,11 +623,16 @@ Completed:
|
|||||||
6. `JajceWorld` runtime integration with bindings and regression coverage.
|
6. `JajceWorld` runtime integration with bindings and regression coverage.
|
||||||
7. Bounded Jajce beauty baseline with six terrain layers, water, atmosphere,
|
7. Bounded Jajce beauty baseline with six terrain layers, water, atmosphere,
|
||||||
foliage motion, building blockouts, and smoke.
|
foliage motion, building blockouts, and smoke.
|
||||||
|
8. Base Terrain3D collision/navigation guardrails: runtime tests now keep
|
||||||
|
Terrain3D collision enabled, keep the old greybox ground out of physics, and
|
||||||
|
verify required navigation paths track the authored height field.
|
||||||
|
|
||||||
Next:
|
Next:
|
||||||
|
|
||||||
1. Capture and visually review “Jajce Lookdev 01.”
|
1. Continue replacing the temporary greybox navigation source with baked
|
||||||
2. Add the cinematic/debug toggle and repeatable demo reset.
|
Terrain3D-derived navigation for the sculpted playable loop.
|
||||||
|
|
||||||
|
2. Capture and visually review “Jajce Lookdev 01.”
|
||||||
3. Capture “Simulation Garden 01.”
|
3. Capture “Simulation Garden 01.”
|
||||||
|
|
||||||
Do not start with GIS data, a full city, a large asset pack, or more NPC
|
Do not start with GIS data, a full city, a large asset pack, or more NPC
|
||||||
|
|||||||
@@ -670,6 +670,10 @@ Recently completed:
|
|||||||
- Activity-site capacity enforcement for rest, study, and patrol target
|
- Activity-site capacity enforcement for rest, study, and patrol target
|
||||||
resolution, derived from NPC target claims rather than presentation-only
|
resolution, derived from NPC target claims rather than presentation-only
|
||||||
counters.
|
counters.
|
||||||
|
- Terrain3D collision/navigation hardening began: scaffold and runtime tests
|
||||||
|
now assert Terrain3D collision remains enabled, the hidden greybox ground no
|
||||||
|
longer provides physics collision, and tested navigation routes stay close to
|
||||||
|
the authored Terrain3D height field.
|
||||||
|
|
||||||
This order strengthens the simulation while regularly producing visible
|
This order strengthens the simulation while regularly producing visible
|
||||||
progress suitable for public development updates.
|
progress suitable for public development updates.
|
||||||
|
|||||||
@@ -193,7 +193,8 @@ study, and patrol target typed activity sites. The migration is documented in
|
|||||||
- **Main scene:** `res://main.tscn`
|
- **Main scene:** `res://main.tscn`
|
||||||
- **Terrain:** Terrain3D 1.0.2 is installed and enabled
|
- **Terrain:** Terrain3D 1.0.2 is installed and enabled
|
||||||
- **Jajce runtime:** reusable 512 m Terrain3D seed, greybox landmarks, stable
|
- **Jajce runtime:** reusable 512 m Terrain3D seed, greybox landmarks, stable
|
||||||
ResourceNode placement, lookdev camera, and tested runtime navigation
|
ResourceNode placement, lookdev camera, tested runtime navigation, and base
|
||||||
|
Terrain3D collision/navigation guardrails
|
||||||
- **Terrain compatibility floor:** Godot 4.4 according to the bundled extension
|
- **Terrain compatibility floor:** Godot 4.4 according to the bundled extension
|
||||||
- **Version control:** Git
|
- **Version control:** Git
|
||||||
- **Primary branch:** `main`
|
- **Primary branch:** `main`
|
||||||
@@ -328,6 +329,9 @@ distance with resource `safety_risk`, `comfort_distance`, and
|
|||||||
- eight ResourceNodes preserving stable food/wood discovery IDs;
|
- eight ResourceNodes preserving stable food/wood discovery IDs;
|
||||||
- typed village pantry storage and typed guard, study, and rest activity sites;
|
- typed village pantry storage and typed guard, study, and rest activity sites;
|
||||||
- a temporary baked navigation loop with 24 tested routes;
|
- a temporary baked navigation loop with 24 tested routes;
|
||||||
|
- base collision/navigation guardrails that keep Terrain3D collision enabled,
|
||||||
|
keep the hidden greybox ground out of runtime physics, and compare required
|
||||||
|
navigation paths against the Terrain3D height field;
|
||||||
- a look-development scene and camera.
|
- a look-development scene and camera.
|
||||||
|
|
||||||
This is a runtime integration proof, not the final terrain composition.
|
This is a runtime integration proof, not the final terrain composition.
|
||||||
@@ -534,6 +538,9 @@ These are expected prototype constraints, not necessarily isolated bugs:
|
|||||||
mutation APIs, but selection, execution, target resolution, and active-world
|
mutation APIs, but selection, execution, target resolution, and active-world
|
||||||
queries now have focused collaborators.
|
queries now have focused collaborators.
|
||||||
- Path failure and interruption emit a `navigation_failed` signal and send the NPC to wander; this is functional but not yet polished.
|
- Path failure and interruption emit a `navigation_failed` signal and send the NPC to wander; this is functional but not yet polished.
|
||||||
|
- The old greybox navigation source remains temporary; current tests now guard
|
||||||
|
against collision/nav regressions, but the next terrain base phase is a
|
||||||
|
Terrain3D-derived bake for the sculpted playable loop.
|
||||||
- Terrain3D and the bounded Jajce beauty baseline now run in the main game
|
- Terrain3D and the bounded Jajce beauty baseline now run in the main game
|
||||||
scene; final visual review and character/profession readability remain.
|
scene; final visual review and character/profession readability remain.
|
||||||
- Combat, companions, factions, politics, trade, rumours, quests, persistence,
|
- Combat, companions, factions, politics, trade, rumours, quests, persistence,
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ func _run() -> void:
|
|||||||
terrain.get_camera() == main_scene.get_node("CameraRig/Camera3D"),
|
terrain.get_camera() == main_scene.get_node("CameraRig/Camera3D"),
|
||||||
"Runtime Terrain3D should bind to the gameplay camera"
|
"Runtime Terrain3D should bind to the gameplay camera"
|
||||||
)
|
)
|
||||||
|
_check(terrain.collision_mode != 0, "Runtime Terrain3D collision should be enabled")
|
||||||
|
var greybox_ground := main_scene.get_node("JajceWorld/NavigationRegion3D/GreyboxGround") as StaticBody3D
|
||||||
|
_check(
|
||||||
|
greybox_ground.collision_layer == 0 and greybox_ground.collision_mask == 0,
|
||||||
|
"Runtime GreyboxGround should not provide physics collision"
|
||||||
|
)
|
||||||
_check(
|
_check(
|
||||||
(
|
(
|
||||||
not main_scene.has_node("World")
|
not main_scene.has_node("World")
|
||||||
@@ -73,6 +79,9 @@ func _run() -> void:
|
|||||||
not path.is_empty(),
|
not path.is_empty(),
|
||||||
"Navigation path should exist from %s to %s" % [origin, destination]
|
"Navigation path should exist from %s to %s" % [origin, destination]
|
||||||
)
|
)
|
||||||
|
_check_path_tracks_terrain(
|
||||||
|
terrain, path, "Runtime navigation path should track Terrain3D height"
|
||||||
|
)
|
||||||
|
|
||||||
var village := SimVillage.new()
|
var village := SimVillage.new()
|
||||||
var worker := SimNPC.new(100, "BaselineWorker", SimulationIds.PROFESSION_SCHOLAR, 5.0, 5.0)
|
var worker := SimNPC.new(100, "BaselineWorker", SimulationIds.PROFESSION_SCHOLAR, 5.0, 5.0)
|
||||||
@@ -126,3 +135,20 @@ func _wait_for_navigation_map(navigation_map: RID) -> void:
|
|||||||
func _check(condition: bool, message: String) -> void:
|
func _check(condition: bool, message: String) -> void:
|
||||||
if not condition:
|
if not condition:
|
||||||
failures.append(message)
|
failures.append(message)
|
||||||
|
|
||||||
|
|
||||||
|
func _check_path_tracks_terrain(terrain: Terrain3D, path: PackedVector3Array, message: String) -> void:
|
||||||
|
if path.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
for point in path:
|
||||||
|
var terrain_height: float = terrain.data.get_height(point)
|
||||||
|
if is_nan(terrain_height):
|
||||||
|
failures.append("%s: missing terrain height at %s" % [message, point])
|
||||||
|
return
|
||||||
|
if absf(point.y - terrain_height) > 0.85:
|
||||||
|
failures.append(
|
||||||
|
"%s: path point %s is too far from terrain height %.2f"
|
||||||
|
% [message, point, terrain_height]
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ func _run() -> void:
|
|||||||
terrain.data_directory == "res://terrain/jajce/data",
|
terrain.data_directory == "res://terrain/jajce/data",
|
||||||
"Terrain3D should use dedicated Jajce data"
|
"Terrain3D should use dedicated Jajce data"
|
||||||
)
|
)
|
||||||
|
_check(terrain.collision_mode != 0, "Terrain3D collision should be enabled for gameplay")
|
||||||
|
var greybox_ground := world.get_node("NavigationRegion3D/GreyboxGround") as StaticBody3D
|
||||||
|
_check(
|
||||||
|
greybox_ground.collision_layer == 0 and greybox_ground.collision_mask == 0,
|
||||||
|
"GreyboxGround should not provide runtime physics collision"
|
||||||
|
)
|
||||||
_check(
|
_check(
|
||||||
configured_texture_count == 6,
|
configured_texture_count == 6,
|
||||||
(
|
(
|
||||||
@@ -215,6 +221,9 @@ func _run() -> void:
|
|||||||
not path.is_empty(),
|
not path.is_empty(),
|
||||||
"Jajce navigation path should exist from %s to %s" % [origin, destination]
|
"Jajce navigation path should exist from %s to %s" % [origin, destination]
|
||||||
)
|
)
|
||||||
|
_check_path_tracks_terrain(
|
||||||
|
terrain, path, "Jajce navigation path should track Terrain3D height"
|
||||||
|
)
|
||||||
|
|
||||||
var adapter := ActiveWorldAdapter.new()
|
var adapter := ActiveWorldAdapter.new()
|
||||||
adapter.pantry_storage = pantry
|
adapter.pantry_storage = pantry
|
||||||
@@ -304,3 +313,20 @@ func _wait_for_navigation_map(navigation_map: RID) -> void:
|
|||||||
func _check(condition: bool, message: String) -> void:
|
func _check(condition: bool, message: String) -> void:
|
||||||
if not condition:
|
if not condition:
|
||||||
failures.append(message)
|
failures.append(message)
|
||||||
|
|
||||||
|
|
||||||
|
func _check_path_tracks_terrain(terrain: Terrain3D, path: PackedVector3Array, message: String) -> void:
|
||||||
|
if path.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
for point in path:
|
||||||
|
var terrain_height: float = terrain.data.get_height(point)
|
||||||
|
if is_nan(terrain_height):
|
||||||
|
failures.append("%s: missing terrain height at %s" % [message, point])
|
||||||
|
return
|
||||||
|
if absf(point.y - terrain_height) > 0.85:
|
||||||
|
failures.append(
|
||||||
|
"%s: path point %s is too far from terrain height %.2f"
|
||||||
|
% [message, point, terrain_height]
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user