extends Node var dead_players: Dictionary = {} func _ready() -> void: EventBus.entity_died.connect(_on_entity_died) func _process(delta: float) -> void: for player in dead_players.keys(): if not is_instance_valid(player): dead_players.erase(player) continue dead_players[player] -= delta EventBus.respawn_tick.emit(dead_players[player]) if dead_players[player] <= 0: _respawn(player) func _on_entity_died(entity: Node) -> void: if not entity.is_in_group("player"): return if entity in dead_players: return var base: BaseStats = Stats.get_base(entity) var respawn_time: float = base.respawn_time if base is PlayerStats else 3.0 dead_players[entity] = respawn_time entity.velocity = Vector3.ZERO entity.get_node("Mesh").visible = false entity.get_node("CollisionShape3D").disabled = true entity.get_node("Movement").set_physics_process(false) entity.get_node("Combat").set_process_unhandled_input(false) entity.get_node("Targeting").set_process_unhandled_input(false) func _respawn(player: Node) -> void: dead_players.erase(player) player.global_position = Vector3(0, 1, -5) player.get_node("Mesh").visible = true player.get_node("CollisionShape3D").disabled = false player.get_node("Movement").set_physics_process(true) player.get_node("Combat").set_process_unhandled_input(true) player.get_node("Targeting").set_process_unhandled_input(true) var max_health: float = Stats.get_stat(player, "max_health") var max_shield: float = Stats.get_stat(player, "max_shield") Stats.set_stat(player, "health", max_health) Stats.set_stat(player, "shield", max_shield) Stats.set_stat(player, "alive", true) EventBus.health_changed.emit(player, max_health, max_health) EventBus.shield_changed.emit(player, max_shield, max_shield) EventBus.player_respawned.emit(player)