Wolf den search steps into the valley when the rim is steep everywhere
This commit is contained in:
@@ -57,40 +57,53 @@ func _find_site(world: Node3D) -> Vector3:
|
||||
var space := world.get_world_3d().direct_space_state
|
||||
var box := BoxShape3D.new()
|
||||
box.size = Vector3(HALF_SIZE * 2.0, 6.0, HALF_SIZE * 2.0)
|
||||
var ex: Array[RID] = [terrain.get_node("TerrainBody").get_rid(), world.player.get_rid()]
|
||||
for step in range(52):
|
||||
var ang := deg_to_rad(start + step * 7.0)
|
||||
var dir := Vector2(cos(ang), sin(ang))
|
||||
# Walk inward from the rim until the den sits inside the walkable
|
||||
# area, a little way short of the wall.
|
||||
var r: float = terrain.play_radius + 10.0
|
||||
while r > terrain.play_radius - 40.0:
|
||||
var x := dir.x * r
|
||||
var z := dir.y * r
|
||||
if terrain.inside_boundary(x, z, 11.0):
|
||||
break
|
||||
r -= 1.0
|
||||
var c := Vector3(dir.x * r, 0, dir.y * r)
|
||||
if terrain.sea_weight(c.x, c.z) > 0.02 or Vector2(c.x, c.z).length() < 50.0:
|
||||
continue
|
||||
var hs: Array[float] = []
|
||||
for d in [Vector2(-1, -1), Vector2(1, -1), Vector2(-1, 1), Vector2(1, 1), Vector2.ZERO]:
|
||||
hs.append(terrain.sample_height(c.x + d.x * 4.0, c.z + d.y * 4.0))
|
||||
if hs.max() - hs.min() > 2.2 or hs.min() < terrain.water_level + 1.0:
|
||||
continue
|
||||
c.y = hs[4]
|
||||
# Trees and boulders in the way are cleared (_clear_area); just avoid
|
||||
# the thickest woods. Counted by position, because their colliders
|
||||
# were only just created and the physics space hasn't seen them yet.
|
||||
var crowd := 0
|
||||
for uid in world.props.resource_nodes:
|
||||
var n: Node3D = world.props.resource_nodes[uid]
|
||||
if Vector2(n.global_position.x - c.x, n.global_position.z - c.z).length() < HALF_SIZE:
|
||||
crowd += 1
|
||||
if crowd <= 5:
|
||||
return c
|
||||
# Pass 1 tries only the foot of the rim wall in each direction (the
|
||||
# original search, so islands that already had a den keep it in the same
|
||||
# place). Where the rim is steep all the way round (seed 777, seed 4),
|
||||
# pass 2 steps further into the valley, a few metres at a time.
|
||||
for pass_insets in [[0.0], [3.0, 6.0, 9.0, 12.0, 16.0, 20.0, 25.0, 30.0]]:
|
||||
for step in range(52):
|
||||
var ang := deg_to_rad(start + step * 7.0)
|
||||
var dir := Vector2(cos(ang), sin(ang))
|
||||
var r_foot := _rim_foot(dir)
|
||||
for inset in pass_insets:
|
||||
var c := _check_site(world, dir * (r_foot - inset))
|
||||
if c != Vector3.INF:
|
||||
return c
|
||||
return Vector3.INF
|
||||
|
||||
## Walks inward from the rim until the den sits inside the walkable area, a
|
||||
## little way short of the wall. Returns that distance from the centre.
|
||||
func _rim_foot(dir: Vector2) -> float:
|
||||
var r: float = terrain.play_radius + 10.0
|
||||
while r > terrain.play_radius - 40.0:
|
||||
if terrain.inside_boundary(dir.x * r, dir.y * r, 11.0):
|
||||
break
|
||||
r -= 1.0
|
||||
return r
|
||||
|
||||
## The site at `p` (x, z) with its height, or INF if it's no good: near the
|
||||
## sea or the spawn, too sloped, too low, or in thick woods.
|
||||
func _check_site(world: Node3D, p: Vector2) -> Vector3:
|
||||
if terrain.sea_weight(p.x, p.y) > 0.02 or p.length() < 50.0:
|
||||
return Vector3.INF
|
||||
var hs: Array[float] = []
|
||||
for d in [Vector2(-1, -1), Vector2(1, -1), Vector2(-1, 1), Vector2(1, 1), Vector2.ZERO]:
|
||||
hs.append(terrain.sample_height(p.x + d.x * 4.0, p.y + d.y * 4.0))
|
||||
if hs.max() - hs.min() > 2.2 or hs.min() < terrain.water_level + 1.0:
|
||||
return Vector3.INF
|
||||
# Trees and boulders in the way are cleared (_clear_area); just avoid
|
||||
# the thickest woods. Counted by position, because their colliders
|
||||
# were only just created and the physics space hasn't seen them yet.
|
||||
var crowd := 0
|
||||
for uid in world.props.resource_nodes:
|
||||
var n: Node3D = world.props.resource_nodes[uid]
|
||||
if Vector2(n.global_position.x - p.x, n.global_position.z - p.y).length() < HALF_SIZE:
|
||||
crowd += 1
|
||||
if crowd > 5:
|
||||
return Vector3.INF
|
||||
return Vector3(p.x, hs[4], p.y)
|
||||
|
||||
## Removes the trees, boulders, bushes and pickups the den is built over.
|
||||
## Deterministic (the site comes from the seed), and the other scenery keeps
|
||||
## its save ids because those come from creation order.
|
||||
|
||||
Reference in New Issue
Block a user