Anchor beetles to generated tree surfaces
This commit is contained in:
parent
f1c952f5d6
commit
5ed4cccf76
18 changed files with 446 additions and 71 deletions
|
|
@ -1131,49 +1131,36 @@ func _validate_tree_gatherable_anchors(
|
|||
decorations: Node3D,
|
||||
anchors: GatherableAnchorSet3D,
|
||||
) -> void:
|
||||
var eligible_props: Array[Node3D] = []
|
||||
var eligible_props: Dictionary[StringName, Node3D] = {}
|
||||
for child: Node in decorations.get_children():
|
||||
var prop := child as Node3D
|
||||
if prop == null:
|
||||
continue
|
||||
var prop_id := StringName(prop.get_meta(&"terrain_prop_id", &""))
|
||||
var definition := region.get_prop_catalog().definition_for_id(prop_id)
|
||||
if definition != null and definition.gatherable_anchor_height > 0.0:
|
||||
eligible_props.append(prop)
|
||||
if definition != null and definition.has_gatherable_surface():
|
||||
eligible_props[prop.name] = prop
|
||||
var positions := anchors.get_spawn_positions()
|
||||
assert(positions.size() == eligible_props.size())
|
||||
for prop: Node3D in eligible_props:
|
||||
assert(positions.size() >= 12)
|
||||
for child: Node in anchors.get_children():
|
||||
var anchor := child as Marker3D
|
||||
assert(anchor != null)
|
||||
assert(bool(anchor.get_meta(&"mesh_surface_sampled", false)))
|
||||
var prop_name := StringName(anchor.get_meta(&"terrain_prop_name", &""))
|
||||
assert(eligible_props.has(prop_name))
|
||||
var prop: Node3D = eligible_props[prop_name]
|
||||
var prop_id := StringName(prop.get_meta(&"terrain_prop_id", &""))
|
||||
var definition := region.get_prop_catalog().definition_for_id(prop_id)
|
||||
var visual_scale := float(
|
||||
prop.get_meta(&"terrain_prop_visual_scale", 1.0)
|
||||
)
|
||||
var nearest_anchor := Vector3(INF, INF, INF)
|
||||
var nearest_distance_squared := INF
|
||||
for position: Vector3 in positions:
|
||||
var distance_squared := position.distance_squared_to(
|
||||
prop.global_position
|
||||
)
|
||||
if distance_squared < nearest_distance_squared:
|
||||
nearest_distance_squared = distance_squared
|
||||
nearest_anchor = position
|
||||
assert(nearest_anchor.is_finite())
|
||||
var horizontal_distance := Vector2(
|
||||
nearest_anchor.x - prop.global_position.x,
|
||||
nearest_anchor.z - prop.global_position.z,
|
||||
).length()
|
||||
assert(definition != null and definition.has_gatherable_surface())
|
||||
var local_anchor := prop.to_local(anchor.global_position)
|
||||
assert(
|
||||
horizontal_distance
|
||||
>= definition.gatherable_anchor_surface_radius() * visual_scale
|
||||
local_anchor.y
|
||||
>= definition.gatherable_surface_minimum_height - 0.001
|
||||
)
|
||||
assert(
|
||||
absf(
|
||||
nearest_anchor.y
|
||||
- (
|
||||
prop.global_position.y
|
||||
+ definition.gatherable_anchor_height * visual_scale
|
||||
)
|
||||
) <= 0.001
|
||||
local_anchor.y
|
||||
<= definition.gatherable_surface_maximum_height + 0.001
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ const Gatherables: GatherableCatalog = preload(
|
|||
"res://gathering/catalog/gatherable_catalog.tres"
|
||||
)
|
||||
const FishCatalog: FishPool = preload("res://fish/pools/fish_catalog.tres")
|
||||
const MeshSurfaceAnchorSamplerType = preload(
|
||||
"res://world/generation/mesh_surface_anchor_sampler.gd"
|
||||
)
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
|
|
@ -15,6 +18,7 @@ func _initialize() -> void:
|
|||
|
||||
func _run() -> void:
|
||||
_validate_beetle_data()
|
||||
await _validate_mesh_surface_sampler()
|
||||
await _validate_tree_anchors()
|
||||
_validate_anchored_presentation()
|
||||
_validate_three_dimensional_targeting()
|
||||
|
|
@ -32,11 +36,74 @@ func _validate_beetle_data() -> void:
|
|||
assert(beetle.required_tool_id == &"crab_net")
|
||||
assert(beetle.spawn_anchor_set_id == &"starter_reachable_tree_trunks")
|
||||
assert(beetle.population == 3)
|
||||
assert(is_equal_approx(beetle.spawn_anchor_occupancy_ratio, 0.35))
|
||||
assert(beetle.maximum_anchor_population == 64)
|
||||
assert(beetle.target_population_for_anchor_count(8) == 3)
|
||||
assert(beetle.target_population_for_anchor_count(40) == 14)
|
||||
assert(beetle.target_population_for_anchor_count(400) == 64)
|
||||
assert(is_equal_approx(beetle.sprite_pixel_size, 0.005))
|
||||
assert(beetle.is_stationary_spawn())
|
||||
assert(not beetle.can_be_scared())
|
||||
|
||||
|
||||
func _validate_mesh_surface_sampler() -> void:
|
||||
var prop := Node3D.new()
|
||||
# The accessibility band is local to the planted prop, so the same tree on
|
||||
# a raised cliff remains reachable from that cliff's walkable surface.
|
||||
prop.position = Vector3(3.0, 12.0, -4.0)
|
||||
root.add_child(prop)
|
||||
var visual := MeshInstance3D.new()
|
||||
var box := BoxMesh.new()
|
||||
box.size = Vector3(2.0, 4.0, 2.0)
|
||||
var wood := StandardMaterial3D.new()
|
||||
wood.resource_name = "wood"
|
||||
box.material = wood
|
||||
visual.mesh = box
|
||||
visual.position.y = 2.0
|
||||
prop.add_child(visual)
|
||||
await process_frame
|
||||
var random := RandomNumberGenerator.new()
|
||||
random.seed = 115
|
||||
var sample: Dictionary = MeshSurfaceAnchorSamplerType.sample_vertical_surface(
|
||||
prop,
|
||||
prop,
|
||||
PackedStringArray(["wood"]),
|
||||
0.7,
|
||||
1.5,
|
||||
0.35,
|
||||
0.025,
|
||||
random,
|
||||
)
|
||||
assert(not sample.is_empty())
|
||||
var surface_position: Vector3 = sample["surface_position"]
|
||||
var anchor_position: Vector3 = sample["position"]
|
||||
assert(surface_position.y >= 0.7 and surface_position.y <= 1.5)
|
||||
var world_anchor_position := prop.to_global(anchor_position)
|
||||
assert(
|
||||
world_anchor_position.y >= 12.7
|
||||
and world_anchor_position.y <= 13.5
|
||||
)
|
||||
assert(is_equal_approx(
|
||||
maxf(absf(surface_position.x), absf(surface_position.z)),
|
||||
1.0,
|
||||
))
|
||||
assert(is_equal_approx(
|
||||
anchor_position.distance_to(surface_position),
|
||||
0.025,
|
||||
))
|
||||
assert(MeshSurfaceAnchorSamplerType.sample_vertical_surface(
|
||||
prop,
|
||||
prop,
|
||||
PackedStringArray(["leaf"]),
|
||||
0.7,
|
||||
1.5,
|
||||
0.35,
|
||||
0.025,
|
||||
random,
|
||||
).is_empty())
|
||||
prop.queue_free()
|
||||
|
||||
|
||||
func _validate_tree_anchors() -> void:
|
||||
var region := StarterIslandScene.instantiate() as WorldRegion
|
||||
root.add_child(region)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ func _validate_catalog_statuses() -> void:
|
|||
assert(beetle.catch_data.collection_method == FishData.CollectionMethod.NET)
|
||||
assert(beetle.required_tool_id == &"crab_net")
|
||||
assert(beetle.spawn_anchor_set_id == &"starter_reachable_tree_trunks")
|
||||
assert(is_equal_approx(beetle.spawn_anchor_occupancy_ratio, 0.35))
|
||||
assert(beetle.maximum_anchor_population == 64)
|
||||
assert(beetle.is_stationary_spawn())
|
||||
assert(not beetle.is_stationary_hotspot())
|
||||
assert(not beetle.requires_sneaking)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue