@tool class_name PlayerSpawnPoint extends Marker3D @export var spawn_index: int = 0: set = set_spawn_index @export_tool_button("Set unique index") var set_unique_index: Callable = func() -> void: for spawn_point: PlayerSpawnPoint in spawn_points: if spawn_point == self: continue if spawn_point.spawn_index == spawn_index: set_spawn_index(spawn_index + 1) set_unique_index.call() return update_configuration_warnings() @export var editor_auto_assign_unique_id: bool = true static var spawn_points: Array[PlayerSpawnPoint] = [] var idx_label: Label3D var config_warnings_hint: Label3D func _init() -> void: if Engine.is_editor_hint(): var player_scene: PackedScene = load("res://components/characters/player/player_character.tscn") add_child(player_scene.instantiate(), false, Node.INTERNAL_MODE_FRONT) # Setup labels. idx_label = Label3D.new() idx_label.billboard = BaseMaterial3D.BILLBOARD_ENABLED idx_label.shaded = false idx_label.font_size = 64 add_child(idx_label, false, Node.INTERNAL_MODE_FRONT) idx_label.position.y = 1.8 set_spawn_index(spawn_index) config_warnings_hint = Label3D.new() config_warnings_hint.billboard = BaseMaterial3D.BILLBOARD_ENABLED config_warnings_hint.shaded = false config_warnings_hint.no_depth_test = true config_warnings_hint.fixed_size = true config_warnings_hint.text = "!" config_warnings_hint.modulate = Color.RED add_child(config_warnings_hint, false, Node.INTERNAL_MODE_FRONT) config_warnings_hint.position.y = 1.0 var tween: Tween = create_tween().set_loops() tween.tween_property(config_warnings_hint, ^"scale", Vector3.ONE * 1.5, 0.075) tween.tween_property(config_warnings_hint, ^"scale", Vector3.ONE * 1.0, 0.075) update_configuration_warnings() func _enter_tree() -> void: if not spawn_points.has(self): spawn_points.append(self) if editor_auto_assign_unique_id and Engine.is_editor_hint(): set_unique_index.call_deferred() func _exit_tree() -> void: spawn_points.erase(self) func set_spawn_index(index: int) -> void: spawn_index = index update_configuration_warnings() if is_instance_valid(idx_label): idx_label.text = str(spawn_index) func make_current(do_autosave: bool = true) -> void: GameGlobals.spawn_index = spawn_index if do_autosave: SaveManager.save_game() static func get_spawn_point_by_index(index: int) -> PlayerSpawnPoint: for spawn_point: PlayerSpawnPoint in PlayerSpawnPoint.spawn_points: if spawn_point.spawn_index == index: return spawn_point return null func _get_configuration_warnings() -> PackedStringArray: var warnings: PackedStringArray = [] for spawn_point: PlayerSpawnPoint in spawn_points: if spawn_point.spawn_index == spawn_index and spawn_point != self: warnings.append(str(spawn_point, " has the same spawn index as us.")) spawn_point.config_warnings_hint.show() spawn_point.update_configuration_warnings() if warnings.is_empty(): config_warnings_hint.hide() return warnings