Improve nearby water recovery and camera prompts
Recover players on generated worlds to the nearest safe grass or sand surface. Use the active gameplay camera when positioning shop and storage prompts.
This commit is contained in:
parent
ae802493a0
commit
4575830857
10 changed files with 396 additions and 25 deletions
|
|
@ -416,6 +416,12 @@ func _run() -> void:
|
|||
)
|
||||
assert(normal_camera.is_position_behind(chat_anchor))
|
||||
assert(not free_camera.is_position_behind(chat_anchor))
|
||||
var shop_prompt := game_ui.get_node("%ShopPrompt") as Control
|
||||
var storage_prompt := game_ui.get_node("%StoragePrompt") as Control
|
||||
game_ui.set_shop_prompt_visible(true, chat_anchor)
|
||||
game_ui.set_storage_prompt_visible(true, chat_anchor)
|
||||
assert(shop_prompt.visible)
|
||||
assert(storage_prompt.visible)
|
||||
chat_ui.show_local_speech("hello there friend")
|
||||
await process_frame
|
||||
assert(bool(player.get("_speech_mouth_active")))
|
||||
|
|
|
|||
|
|
@ -265,6 +265,15 @@ func _run() -> void:
|
|||
assert(bool(water_recovery.get("_prior_movement_enabled")))
|
||||
assert(bool(water_recovery.get("_prior_camera_input_enabled")))
|
||||
assert(not pause_menu.visible)
|
||||
var test_world := main.get_node("TestWorld") as TestWorld
|
||||
assert(test_world != null)
|
||||
var recovery_entry := water_recovery.get("_entry_position") as Vector3
|
||||
var resolved_recovery := water_recovery.call(
|
||||
"_resolve_recovery_position"
|
||||
) as Vector3
|
||||
assert(resolved_recovery.is_equal_approx(
|
||||
test_world.get_water_recovery_position(recovery_entry)
|
||||
))
|
||||
water_recovery.call("_finish_recovery")
|
||||
assert(player.is_movement_enabled())
|
||||
|
||||
|
|
|
|||
|
|
@ -536,6 +536,11 @@ func _validate_generated_region(
|
|||
-INF,
|
||||
0.35,
|
||||
)
|
||||
_validate_water_recovery_positions(
|
||||
region,
|
||||
grass_prop_surface_triangles,
|
||||
sand_prop_surface_triangles,
|
||||
)
|
||||
var anchors := region.get_node(
|
||||
"GatherableAnchors/ReachableTreeTrunks"
|
||||
) as GatherableAnchorSet3D
|
||||
|
|
@ -1268,6 +1273,76 @@ func _triangle_surface_height_at(
|
|||
return highest
|
||||
|
||||
|
||||
func _validate_water_recovery_positions(
|
||||
region: GeneratedWorldRegion,
|
||||
grass_triangles: Array[PackedVector3Array],
|
||||
sand_triangles: Array[PackedVector3Array],
|
||||
) -> void:
|
||||
var fresh_water_root := region.get_node(
|
||||
"WaterBodies/FreshWaterBodies"
|
||||
) as Node3D
|
||||
assert(fresh_water_root != null and fresh_water_root.get_child_count() > 0)
|
||||
var fresh_water := fresh_water_root.get_child(0) as WaterBodyAuthoring
|
||||
assert(fresh_water != null)
|
||||
var entry_position := fresh_water.global_position
|
||||
var fallback_position := region.get_player_spawn_transform().origin
|
||||
var recovery_position := region.get_water_recovery_position(
|
||||
entry_position,
|
||||
fallback_position,
|
||||
)
|
||||
assert(recovery_position.is_finite())
|
||||
assert(
|
||||
_horizontal_distance_squared(entry_position, recovery_position)
|
||||
< _horizontal_distance_squared(entry_position, fallback_position),
|
||||
"Fresh-water recovery returned the distant generated-world spawn.",
|
||||
)
|
||||
assert(
|
||||
recovery_position.y
|
||||
> GeneratedWorldRegion.WATER_HEIGHT
|
||||
+ GeneratedWorldRegion.WATER_RECOVERY_MINIMUM_GROUND_CLEARANCE
|
||||
)
|
||||
var recovery_triangles: Array[PackedVector3Array] = []
|
||||
recovery_triangles.append_array(grass_triangles)
|
||||
recovery_triangles.append_array(sand_triangles)
|
||||
var center_height := _triangle_surface_height_at(
|
||||
recovery_position,
|
||||
recovery_triangles,
|
||||
)
|
||||
assert(center_height > -INF)
|
||||
assert(absf(center_height - recovery_position.y) <= 0.01)
|
||||
for direction: Vector2 in GeneratedWorldRegion.PROP_SURFACE_SAMPLE_DIRECTIONS:
|
||||
var footprint_position := recovery_position + Vector3(
|
||||
direction.x * GeneratedWorldRegion.WATER_RECOVERY_FOOTPRINT_RADIUS,
|
||||
0.0,
|
||||
direction.y * GeneratedWorldRegion.WATER_RECOVERY_FOOTPRINT_RADIUS,
|
||||
)
|
||||
var footprint_height := _triangle_surface_height_at(
|
||||
footprint_position,
|
||||
recovery_triangles,
|
||||
)
|
||||
assert(footprint_height > -INF)
|
||||
assert(
|
||||
absf(footprint_height - recovery_position.y)
|
||||
<= GeneratedWorldRegion.PROP_MAXIMUM_SUPPORT_HEIGHT_DIFFERENCE
|
||||
)
|
||||
assert(
|
||||
region.get_water_recovery_position(
|
||||
entry_position,
|
||||
fallback_position,
|
||||
).is_equal_approx(recovery_position)
|
||||
)
|
||||
assert(
|
||||
region.get_water_recovery_position(
|
||||
Vector3(INF, 0.0, 0.0),
|
||||
fallback_position,
|
||||
).is_equal_approx(fallback_position)
|
||||
)
|
||||
|
||||
|
||||
func _horizontal_distance_squared(a: Vector3, b: Vector3) -> float:
|
||||
return Vector2(a.x - b.x, a.z - b.z).length_squared()
|
||||
|
||||
|
||||
func _validate_tree_gatherable_anchors(
|
||||
region: GeneratedWorldRegion,
|
||||
decorations: Node3D,
|
||||
|
|
|
|||
|
|
@ -100,6 +100,14 @@ func _validate_world_switching() -> void:
|
|||
assert(world.get_fishing_shop() != null)
|
||||
assert(world.get_player_storage() != null)
|
||||
assert(not world.get_fishable_water_regions().is_empty())
|
||||
var starter_safe_points := world.get_safe_respawn_points()
|
||||
assert(not starter_safe_points.is_empty())
|
||||
var authored_safe_point: SafeRespawnPoint = starter_safe_points.back()
|
||||
assert(
|
||||
world.get_water_recovery_position(
|
||||
authored_safe_point.global_position
|
||||
).is_equal_approx(authored_safe_point.global_position)
|
||||
)
|
||||
assert(world.activate_world(WorldLayout.GENERATED, 24680))
|
||||
assert(world.get_world_layout() == WorldLayout.GENERATED)
|
||||
assert(world.get_generation_seed() == 24680)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue