46 lines
1.3 KiB
GDScript
46 lines
1.3 KiB
GDScript
class_name PlayerWaterTrigger
|
|
extends Area3D
|
|
|
|
signal recovery_requested(player: Player, surface_height: float)
|
|
|
|
@export var surface_height: float = 0.2
|
|
@export_range(0.0, 2.0, 0.05) var entry_depth_threshold: float = 0.35
|
|
|
|
var _tracked_players: Array[Player] = []
|
|
var _triggered_players: Dictionary[StringName, bool] = {}
|
|
|
|
|
|
func _ready() -> void:
|
|
body_entered.connect(_on_body_entered)
|
|
body_exited.connect(_on_body_exited)
|
|
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
for player: Player in _tracked_players.duplicate():
|
|
if not is_instance_valid(player):
|
|
_tracked_players.erase(player)
|
|
continue
|
|
var player_key: StringName = StringName(str(player.get_instance_id()))
|
|
if _triggered_players.has(player_key):
|
|
continue
|
|
if (
|
|
player.get_body_center_position().y
|
|
<= surface_height - entry_depth_threshold
|
|
):
|
|
_triggered_players[player_key] = true
|
|
recovery_requested.emit(player, surface_height)
|
|
|
|
|
|
func _on_body_entered(body: Node3D) -> void:
|
|
var player: Player = body as Player
|
|
if player == null or player in _tracked_players:
|
|
return
|
|
_tracked_players.append(player)
|
|
|
|
|
|
func _on_body_exited(body: Node3D) -> void:
|
|
var player: Player = body as Player
|
|
if player == null:
|
|
return
|
|
_tracked_players.erase(player)
|
|
_triggered_players.erase(StringName(str(player.get_instance_id())))
|