Add classic HUD, auto reload, furniture pathfinding and death flatline
This commit is contained in:
+45
-3
@@ -1,6 +1,12 @@
|
||||
extends CharacterBody3D
|
||||
signal killed(headshot: bool)
|
||||
var player: CharacterBody3D
|
||||
var navigation: Node
|
||||
var _path := PackedVector3Array()
|
||||
var _path_index := 0
|
||||
var _repath := 0.0
|
||||
var _direct := false
|
||||
var _nav_started := false
|
||||
var hp := 100.0
|
||||
var speed := 2.0
|
||||
var cooldown := 0.0
|
||||
@@ -30,6 +36,7 @@ func _ready() -> void:
|
||||
for area in model.find_children("*", "Area3D", true, false):
|
||||
area.collision_layer = 0
|
||||
speed = randf_range(1.6, 2.8)
|
||||
_repath = randf_range(0, 0.5)
|
||||
anim.play("walk")
|
||||
Audio.play(self, "zombie/zo_alert%d0.wav" % randi_range(1, 3), true, -15)
|
||||
|
||||
@@ -46,8 +53,10 @@ func _physics_process(dt: float) -> void:
|
||||
var distance := dir.length()
|
||||
if distance > 0.01:
|
||||
rotation.y = atan2(-dir.x, -dir.z)
|
||||
var walking := distance > 1.7
|
||||
var motion := dir.normalized() * speed if walking else Vector3.ZERO
|
||||
var walking := distance > 1.7 or not _attack_clear()
|
||||
var motion := _pursuit_direction(dt) * speed if walking else Vector3.ZERO
|
||||
if motion.length_squared() > 0.01:
|
||||
rotation.y = atan2(-motion.x, -motion.z)
|
||||
velocity.x = motion.x
|
||||
velocity.z = motion.z
|
||||
velocity.y = -1.0 if is_on_floor() else velocity.y - 20.0 * dt
|
||||
@@ -60,8 +69,41 @@ func _physics_process(dt: float) -> void:
|
||||
Audio.play(self, "zombie/zo_attack%d.wav" % randi_range(1, 2), true, -15)
|
||||
get_tree().create_timer(0.5).timeout.connect(_attack)
|
||||
|
||||
func _pursuit_direction(dt: float) -> Vector3:
|
||||
var target := player.global_position
|
||||
_repath -= dt
|
||||
if navigation != null and (_repath <= 0 or not _nav_started):
|
||||
_nav_started = true
|
||||
_repath = 0.55 + float(get_instance_id() % 7) * 0.02
|
||||
_direct = navigation.direct_clear(global_position, target)
|
||||
if not _direct:
|
||||
_path = navigation.route(global_position, target)
|
||||
_path_index = 0
|
||||
if _path.size() > 1 and navigation.direct_clear(global_position, _path[1]):
|
||||
_path_index = 1
|
||||
if navigation == null or _direct:
|
||||
var dir := target - global_position
|
||||
dir.y = 0
|
||||
return dir.normalized()
|
||||
while _path_index < _path.size():
|
||||
var dir := _path[_path_index] - global_position
|
||||
dir.y = 0
|
||||
if dir.length() > 0.22:
|
||||
return dir.normalized()
|
||||
_path_index += 1
|
||||
return Vector3.ZERO
|
||||
|
||||
func _attack_clear() -> bool:
|
||||
# Check below desk-top height: a chest-high ray can pass over a desk
|
||||
# even though the bodies cannot approach each other through it.
|
||||
var start := global_position + Vector3.UP * 0.6
|
||||
var end := player.global_position + Vector3.UP * 0.6
|
||||
var query := PhysicsRayQueryParameters3D.create(start, end, 1)
|
||||
query.exclude = [get_rid(), player.get_rid()]
|
||||
return get_world_3d().direct_space_state.intersect_ray(query).is_empty()
|
||||
|
||||
func _attack() -> void:
|
||||
if not dead and is_instance_valid(player) and player.hp > 0 and global_position.distance_to(player.global_position) < 2.3:
|
||||
if not dead and is_instance_valid(player) and player.hp > 0 and global_position.distance_to(player.global_position) < 2.3 and _attack_clear():
|
||||
player.take_damage(12)
|
||||
Audio.play(self, "zombie/claw_strike%d.wav" % randi_range(1, 3), true, -12)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user