Animals stay off the cliffs (Gitea #6): nothing walks up or along ground steeper than 35 degrees, and a carcass on steep ground slides down to where it can be reached and butchered
This commit is contained in:
@@ -92,6 +92,13 @@ const KINDS := {
|
||||
"drops": {"raw_meat": [5, 7], "bear_hide": [1, 1], "bear_fat": [2, 3]}},
|
||||
}
|
||||
const CARCASS_SECONDS := 300.0
|
||||
## The steepest ground an animal walks up: 35 degrees (the ground's normal
|
||||
## at least this upright). The player's limit is about 45.
|
||||
const MAX_CLIMB_NY := 0.82
|
||||
const MAX_CLIMB_RISE := 0.7 ## (tan 35 degrees: metres up per metre along)
|
||||
## A carcass on ground steeper than this slides down to where it's flatter,
|
||||
## so it can be reached and butchered (Gitea #6).
|
||||
const CARCASS_REST_NY := 0.8
|
||||
|
||||
var kind := "deer"
|
||||
var def: Dictionary
|
||||
@@ -384,6 +391,18 @@ func _blocked(dir: Vector3) -> bool:
|
||||
return true
|
||||
if absf(h - global_position.y) > 1.1:
|
||||
return true
|
||||
# Nothing climbs steep ground, or walks along it (the mountain rim: Gitea
|
||||
# #6). Going down it is fine, so one that's somehow up there can always
|
||||
# come back.
|
||||
if h > global_position.y - 0.3:
|
||||
var run := Vector2(probe.x - global_position.x, probe.z - global_position.z).length()
|
||||
if (h - global_position.y) > run * MAX_CLIMB_RISE:
|
||||
return true
|
||||
# The slope along the way: just ahead, halfway, and at the probe.
|
||||
for f in [0.2, 0.5, 1.0]:
|
||||
var s: Vector3 = global_position.lerp(probe, f)
|
||||
if terrain.sample_normal(s.x, s.z).y < MAX_CLIMB_NY and terrain.sample_height(s.x, s.z) > global_position.y - 0.3 * f:
|
||||
return true
|
||||
# Trees, rocks and buildings at chest height (the terrain isn't on this test).
|
||||
var from := global_position + Vector3(0, 0.45, 0)
|
||||
var q := PhysicsRayQueryParameters3D.create(from, Vector3(probe.x, h + 0.45, probe.z), 1)
|
||||
@@ -468,6 +487,7 @@ func _die(from: Vector3) -> void:
|
||||
if puppet:
|
||||
_visual.rotation.z = -PI * 0.5
|
||||
return
|
||||
_settle()
|
||||
# Topple onto its side, away from the blow.
|
||||
var side := 1.0 if (global_position - from).dot(global_basis.x) > 0.0 else -1.0
|
||||
if is_inside_tree() and DisplayServer.get_name() != "headless":
|
||||
@@ -477,6 +497,28 @@ func _die(from: Vector3) -> void:
|
||||
_visual.rotation.z = -side * PI * 0.5
|
||||
died.emit(self)
|
||||
|
||||
## A carcass on steep ground (half into a cliff face, out of reach) slides
|
||||
## downhill, half a metre at a time, until the ground's flatter: up to 20 m,
|
||||
## and never out past the edge of the play area. Online the server does this
|
||||
## and players see it where it ends up.
|
||||
func _settle() -> void:
|
||||
if terrain == null:
|
||||
return
|
||||
var p := global_position
|
||||
for _i in range(40):
|
||||
var n: Vector3 = terrain.sample_normal(p.x, p.z)
|
||||
if n.y >= CARCASS_REST_NY:
|
||||
break
|
||||
var down := Vector3(n.x, 0.0, n.z) # (a slope's normal leans downhill)
|
||||
if down.length() < 0.001:
|
||||
break
|
||||
var q := p + down.normalized() * 0.5
|
||||
if not terrain.inside_boundary(q.x, q.z, 1.0):
|
||||
break
|
||||
p = Vector3(q.x, terrain.sample_height(q.x, q.z), q.z)
|
||||
if p.distance_to(global_position) > 0.01:
|
||||
global_position = p
|
||||
|
||||
## What butchering gives (rolled once).
|
||||
func butcher_drops() -> Dictionary:
|
||||
var out := {}
|
||||
|
||||
Reference in New Issue
Block a user