generated from krampus/template-godot4
63 lines
1.5 KiB
GDScript
63 lines
1.5 KiB
GDScript
class_name MeetSpookMob extends Node3D
|
|
## Mob spawned and controlled by a meet-spook event
|
|
|
|
enum State { WAITING, FREEZE, MOVING }
|
|
|
|
const RAY_MASK := 0b00000101
|
|
const BASE_SPEED := 6.0
|
|
|
|
@export var source: MeetSpook
|
|
@export var target: Node3D
|
|
@export var freeze_time: float
|
|
@export var lifespan: float
|
|
|
|
var state := State.WAITING
|
|
|
|
@onready var camera := get_viewport().get_camera_3d()
|
|
|
|
|
|
func activate() -> void:
|
|
print_debug(self, " spotted!")
|
|
state = State.FREEZE
|
|
get_tree().create_timer(freeze_time).timeout.connect(_unfreeze)
|
|
get_tree().create_timer(lifespan).timeout.connect(destroy)
|
|
source.resolve()
|
|
|
|
|
|
func is_active() -> bool:
|
|
return state != State.WAITING
|
|
|
|
|
|
func move_toward_target(delta: float) -> void:
|
|
# Should probably be overridden by implementations
|
|
global_position = global_position.move_toward(target.global_position, BASE_SPEED * delta)
|
|
|
|
|
|
func _unfreeze() -> void:
|
|
state = State.MOVING
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
match state:
|
|
State.WAITING:
|
|
# Not yet seen by the player
|
|
if camera.is_position_in_frustum(global_position):
|
|
var query := PhysicsRayQueryParameters3D.create(
|
|
camera.global_position, global_position, RAY_MASK
|
|
)
|
|
# TODO exceptions should include this mob's collision body
|
|
var raycast := get_world_3d().direct_space_state.intersect_ray(query)
|
|
if not raycast:
|
|
# Player has line-of-sight!
|
|
activate()
|
|
State.FREEZE:
|
|
# Just stand there for a sec
|
|
pass
|
|
State.MOVING:
|
|
move_toward_target(delta)
|
|
|
|
|
|
func destroy() -> void:
|
|
print_debug("Destroying ", self)
|
|
queue_free()
|