From ed6f243b93fcf223a9b5fdb61e51b297338a629a Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Fri, 14 Aug 2026 03:38:04 -0500 Subject: [PATCH] Refactor game mode scoring and win conditions * Add overridable hooks for sunk/reaped ball handling and turn behavior. * Implement default scoring and game-over messaging across game modes. * Add pretty game mode names for win-condition messages. * Update Free Ball, Last Ball, and Snooker modes to return win-condition messages. * Move the reset button lookup to the scene root for multiplayer setup. * Move camera controller scene to shared base UI. Move parts of it to new game_data UI node. * Add commented test state generation for end-state testing. --- controllers/game/modes/base_mode.gd | 127 ++++++++++++------ controllers/game/modes/free_ball.gd | 8 +- controllers/game/modes/last_ball_mode.gd | 6 +- controllers/game/modes/snooker.gd | 4 +- scenes/data/game_data.gd | 12 ++ scenes/game.gd | 2 +- scenes/game.tscn | 13 +- scenes/ui_controls/base_ui.gd | 25 ++++ scenes/ui_controls/base_ui.gd.uid | 1 + scenes/ui_controls/base_ui.tscn | 66 +++++++++ .../camera/camera_controller.gd | 18 --- .../camera/camera_controller.gd.uid | 0 .../camera/camera_controller.tscn | 53 ++------ scenes/ui_controls/game/data.gd | 33 +++++ scenes/ui_controls/game/data.gd.uid | 1 + scenes/ui_controls/game/data.tscn | 54 ++++++++ 16 files changed, 298 insertions(+), 125 deletions(-) create mode 100644 scenes/ui_controls/base_ui.gd create mode 100644 scenes/ui_controls/base_ui.gd.uid create mode 100644 scenes/ui_controls/base_ui.tscn rename scenes/{menus => ui_controls}/camera/camera_controller.gd (67%) rename scenes/{menus => ui_controls}/camera/camera_controller.gd.uid (100%) rename scenes/{menus => ui_controls}/camera/camera_controller.tscn (54%) create mode 100644 scenes/ui_controls/game/data.gd create mode 100644 scenes/ui_controls/game/data.gd.uid create mode 100644 scenes/ui_controls/game/data.tscn diff --git a/controllers/game/modes/base_mode.gd b/controllers/game/modes/base_mode.gd index 8222a61..d649541 100644 --- a/controllers/game/modes/base_mode.gd +++ b/controllers/game/modes/base_mode.gd @@ -27,19 +27,66 @@ var BALL_STATE: Dictionary = { "points": 0, } +# NOTE: Override when a mode doesn't award points for a sunk balls. +func score_sunk_balls() -> bool: + return true +# NOTE: Override when a mode shouldn't keep the player's turn after a legal sink. +func keep_turn_after_sink() -> bool: + return true + +func get_player() -> String: + return ( + "Player 1" + if Globals.game_data.client1 == + Globals.multiplayer_data.current_turn_player_id + else + "Player 2" + ) + + +# NOTE: Handled before 'handle_switch_user' for early bail out if invalid reap. +func reap_ball(ball: Node3D) -> void: + _record_ball(ball, "reaped", balls_reaped) + on_ball_reaped(ball) + +# NOTE: Override when a mode has extra processing such as +# checking if solid or striped ball. Or 8-ball not sunk last. +func on_ball_reaped(_ball: Node3D) -> void: + pass + +# NOTE: Handled in 'handle_switch_user' func _process_reaped_balls(player: String) -> void: for ball_name in balls_reaped: _add_points(player, -ball_states[ball_name]["points"]) balls_reaped.clear() + +# NOTE: Handled before 'handle_switch_user' for early bail out if invalid sink. +func process_ball(ball: Node3D) -> void: + _record_ball(ball, "sunk", balls_sunk) + on_ball_sunk(ball) + +# NOTE: Override when a mode has extra processing such as +# checking if solid or striped ball. Or 8-ball not sunk last. +func on_ball_sunk(_ball: Node3D) -> void: + pass + +# NOTE: Handled in 'handle_switch_user' func _process_sunk_balls(player: String) -> void: for ball_name in balls_sunk: _add_points(player, ball_states[ball_name]["points"]) balls_sunk.clear() + +func _add_points(player: String, amount: int) -> void: + if player == "Player 1": + player_1_points += amount + else: + player_2_points += amount + func _record_ball( ball: Node3D, state_key: String, @@ -51,48 +98,6 @@ func _record_ball( ball_states[ball.name]["player"] = get_player() ball_states[ball.name][state_key] = true -func _add_points(player: String, amount: int) -> void: - if player == "Player 1": - player_1_points += amount - else: - player_2_points += amount - - -func get_player() -> String: - return ( - "Player 1" - if Globals.game_data.client1 == - Globals.multiplayer_data.current_turn_player_id - else - "Player 2" - ) - -# NOTE: Override when a mode doesn't awards points for sunk balls. -func score_sunk_balls() -> bool: - return true - -# NOTE: Override when a mode shouldn't keep the player's turn after a legal sink. -func keep_turn_after_sink() -> bool: - return true - -# NOTE: Override when a modehas extra processing such as -# checking if solid or striped ball. -func on_ball_reaped(_ball: Node3D) -> void: - pass - -# NOTE: Override when a modehas extra processing such as -# checking if solid or striped ball. -func on_ball_sunk(_ball: Node3D) -> void: - pass - - -func reap_ball(ball: Node3D) -> void: - _record_ball(ball, "reaped", balls_reaped) - on_ball_reaped(ball) - -func process_ball(ball: Node3D) -> void: - _record_ball(ball, "sunk", balls_sunk) - on_ball_sunk(ball) func generate_ball_states() -> Dictionary: var state: Dictionary = {} @@ -104,6 +109,22 @@ func generate_ball_states() -> Dictionary: return state +# NOTE: For testing end state. Keep below commented out. +#func generate_ball_states() -> Dictionary: + #var state: Dictionary = {} +# + #for i: int in range(1, 16): + #var ball_name = "%02d_ball" % i + #state[ball_name] = BALL_STATE.duplicate_deep() + #state[ball_name]["turn"] = i + #state[ball_name]["player"] = "Player " + str( 1 if randi() % 2 else 2 ) + #state[ball_name]["sunk"] = true + #state[ball_name]["is_foul"] = (randi() % 10 == 0) + #state[ball_name]["points"] = i +# + #return state +# End for testing end state. Keep above commented out. + func handle_switch_user() -> void: push_warning("Balls reaped: ", balls_reaped.size() ) push_warning("Balls sunk: ", balls_sunk.size() ) @@ -133,5 +154,23 @@ func ball_states_finalized() -> bool: return true -func process_win_condition() -> void: - assert(false, "This method needs to be overridden...") +func process_win_condition() -> String: + var sub_message: String = \ + ( + "Player " + + str( 1 if player_1_points > player_2_points else 2 ) + + " Won!" + ) + + var message: String = \ + ( + "==================================================" + + "\n" + Globals.game_data.get_mode_pretty() + " Game Over\n" + + sub_message + + "\n==================================================" + ) + + push_warning(message) + MessageBus.emit_propagation_clients_only.rpc("declare_win_condition", message) + + return message diff --git a/controllers/game/modes/free_ball.gd b/controllers/game/modes/free_ball.gd index 550a460..add7a12 100644 --- a/controllers/game/modes/free_ball.gd +++ b/controllers/game/modes/free_ball.gd @@ -5,5 +5,9 @@ func _init() -> void: pass -func process_win_condition() -> void: - pass +func process_win_condition() -> String: + return super() + + #for ball_state in ball_states.values(): + #if ball_state["reaped"] or ball_state["sunk"]: + #continue diff --git a/controllers/game/modes/last_ball_mode.gd b/controllers/game/modes/last_ball_mode.gd index 3022368..5b1f6f7 100644 --- a/controllers/game/modes/last_ball_mode.gd +++ b/controllers/game/modes/last_ball_mode.gd @@ -12,5 +12,7 @@ func on_ball_sunk(ball: Node3D) -> void: if ball.name == final_ball_name: ball_states[ball.name]["is_foul"] = true -func process_win_condition() -> void: - pass +func process_win_condition() -> String: + var message: String = final_ball_name + " Win!" + push_warning(message) + return message diff --git a/controllers/game/modes/snooker.gd b/controllers/game/modes/snooker.gd index b2712b9..4b18327 100644 --- a/controllers/game/modes/snooker.gd +++ b/controllers/game/modes/snooker.gd @@ -40,5 +40,5 @@ func on_ball_sunk(ball: Node3D) -> void: func score_sunk_balls() -> bool: return true -func process_win_condition() -> void: - pass +func process_win_condition() -> String: + return super() diff --git a/scenes/data/game_data.gd b/scenes/data/game_data.gd index d04c6c3..3dc04d5 100644 --- a/scenes/data/game_data.gd +++ b/scenes/data/game_data.gd @@ -41,6 +41,18 @@ var SelectedGameMode: GameModeType = GameModeType.FREE_BALL func _init() -> void: Globals.game_data = self +func get_mode_pretty() -> String: + match game_mode: + "8ball": + return "8-Ball" + "9ball": + return "9-Ball" + "snooker": + return "Snooker" + "freeball": + return "Free Ball" + _: + return "" @rpc("authority", "reliable") func set_game_address(address: String) -> void: diff --git a/scenes/game.gd b/scenes/game.gd index 18f5efd..47be7e5 100644 --- a/scenes/game.gd +++ b/scenes/game.gd @@ -22,7 +22,7 @@ func setup_multiplayer() -> void: if not Globals.multiplayer_data.is_multiplayer_active: return Globals.game_state.reload_scene.disconnect(_reload_scene) - $camera_controller.find_child("reset_bttn", true, false).queue_free() + get_tree().root.find_child("reset_bttn", true, false).queue_free() func _reload_scene() -> void: Globals.game_state.set_game_scene("res://scenes/game.tscn") diff --git a/scenes/game.tscn b/scenes/game.tscn index 1ced94e..6101d55 100644 --- a/scenes/game.tscn +++ b/scenes/game.tscn @@ -4,7 +4,7 @@ [ext_resource type="PackedScene" uid="uid://djtq6hbp70kut" path="res://scenes/environments/base_environment.tscn" id="2_lbhrr"] [ext_resource type="PackedScene" uid="uid://b5idltq8s4srp" path="res://scenes/individual_parts/table/pool_table_manager.tscn" id="3_lnu2h"] [ext_resource type="PackedScene" uid="uid://bw7f8kunlxd2" path="res://controllers/game/modes/game_manager.tscn" id="4_iywne"] -[ext_resource type="PackedScene" uid="uid://w3vh1gj6t2k2" path="res://scenes/menus/camera/camera_controller.tscn" id="8_gee14"] +[ext_resource type="PackedScene" uid="uid://himb0o6py5pt" path="res://scenes/ui_controls/base_ui.tscn" id="7_u5sy4"] [node name="game" type="Node3D"] script = ExtResource("1_iywne") @@ -17,13 +17,4 @@ metadata/_edit_lock_ = true [node name="game_manager" parent="." instance=ExtResource("4_iywne")] -[node name="camera_controller" parent="." instance=ExtResource("8_gee14")] - -[node name="camera1" type="Camera3D" parent="camera_controller"] -transform = Transform3D(-4.371139e-08, 1, 4.371139e-08, 0, -4.371139e-08, 1, 1, 4.371139e-08, 1.9106855e-15, 0, 1.8, 0) - -[node name="camera2" type="Camera3D" parent="camera_controller"] -transform = Transform3D(0.03457907, -0.3120391, -0.9494398, 0, 0.9500079, -0.31222585, 0.999402, 0.010796479, 0.03285039, -0.35511678, 0.79579777, -0.83073556) - -[node name="cue_cam" type="Camera3D" parent="camera_controller"] -transform = Transform3D(1, 0, 0, 0, 1.0000001, 0, 0, 0, 1.0000001, 0, 0, 0) +[node name="base_ui" parent="." instance=ExtResource("7_u5sy4")] diff --git a/scenes/ui_controls/base_ui.gd b/scenes/ui_controls/base_ui.gd new file mode 100644 index 0000000..fe778dc --- /dev/null +++ b/scenes/ui_controls/base_ui.gd @@ -0,0 +1,25 @@ +extends Control + + +@onready var panel: Panel = $panel +@onready var win_message_lbl: RichTextLabel = $panel/win_message_lbl + + +func _ready() -> void: + setup_signals() + setup_multiplayer() + +func setup_signals() -> void: + MessageBus.subscribe("declare_win_condition", _on_declare_win_condition) + +func setup_multiplayer() -> void: + if not Globals.multiplayer_data.is_multiplayer_active: return + + +func _on_declare_win_condition(message: String) -> void: + panel.visible = true + win_message_lbl.text = message + + await get_tree().create_timer(5).timeout + + MessageBus.emit_local("game_peer_disconnected", null) diff --git a/scenes/ui_controls/base_ui.gd.uid b/scenes/ui_controls/base_ui.gd.uid new file mode 100644 index 0000000..9289b1a --- /dev/null +++ b/scenes/ui_controls/base_ui.gd.uid @@ -0,0 +1 @@ +uid://b3torx8lbkrj7 diff --git a/scenes/ui_controls/base_ui.tscn b/scenes/ui_controls/base_ui.tscn new file mode 100644 index 0000000..e47f370 --- /dev/null +++ b/scenes/ui_controls/base_ui.tscn @@ -0,0 +1,66 @@ +[gd_scene load_steps=4 format=3 uid="uid://himb0o6py5pt"] + +[ext_resource type="Script" uid="uid://b3torx8lbkrj7" path="res://scenes/ui_controls/base_ui.gd" id="1_4moq4"] +[ext_resource type="PackedScene" uid="uid://l3bve6miq8od" path="res://scenes/ui_controls/game/data.tscn" id="1_ff2ky"] +[ext_resource type="PackedScene" uid="uid://w3vh1gj6t2k2" path="res://scenes/ui_controls/camera/camera_controller.tscn" id="2_4moq4"] + +[node name="base_ui" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_4moq4") + +[node name="panel" type="Panel" parent="."] +visible = false +z_index = 10 +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -400.0 +offset_top = -300.0 +offset_right = 400.0 +offset_bottom = 300.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="win_message_lbl" type="RichTextLabel" parent="panel"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -240.0 +offset_top = -160.0 +offset_right = 240.0 +offset_bottom = 160.0 +grow_horizontal = 2 +grow_vertical = 2 +scroll_active = false +autowrap_mode = 0 +shortcut_keys_enabled = false +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="game_data" parent="." instance=ExtResource("1_ff2ky")] +z_index = 5 +layout_mode = 1 + +[node name="camera_controller" parent="." instance=ExtResource("2_4moq4")] +z_index = 5 +layout_mode = 1 + +[node name="camera1" type="Camera3D" parent="camera_controller"] +transform = Transform3D(-4.371139e-08, 1, 4.371139e-08, 0, -4.371139e-08, 1, 1, 4.371139e-08, 1.9106855e-15, 0, 1.8, 0) + +[node name="camera2" type="Camera3D" parent="camera_controller"] +transform = Transform3D(0.03457907, -0.3120391, -0.9494398, 0, 0.9500079, -0.31222585, 0.999402, 0.010796479, 0.03285039, -0.35511678, 0.79579777, -0.83073556) + +[node name="cue_cam" type="Camera3D" parent="camera_controller"] +transform = Transform3D(1, 0, 0, 0, 1.0000001, 0, 0, 0, 1.0000001, 0, 0, 0) diff --git a/scenes/menus/camera/camera_controller.gd b/scenes/ui_controls/camera/camera_controller.gd similarity index 67% rename from scenes/menus/camera/camera_controller.gd rename to scenes/ui_controls/camera/camera_controller.gd index fb0ac5c..6d7f53f 100644 --- a/scenes/menus/camera/camera_controller.gd +++ b/scenes/ui_controls/camera/camera_controller.gd @@ -1,15 +1,11 @@ class_name CameraController extends Control -@onready var player_lbl: Label = $margin_container/vbox/hbox/hbox/player_lbl @onready var prev_bttn: Button = $margin_container/vbox/hbox/hbox2/prev_bttn @onready var next_bttn: Button = $margin_container/vbox/hbox/hbox2/next_bttn -@onready var active_lbl: Label = $margin_container/vbox/hbox2/hbox/active_lbl -@onready var reset_bttn: Button = $margin_container/vbox/hbox2/hbox2/reset_bttn @export var cameras: Array[Camera3D] - var cue_cam: Camera3D var current_cam: Camera3D var current_cam_index: int = 0 @@ -26,26 +22,15 @@ func _ready() -> void: cue_cam = camera current_cam = cameras.get(current_cam_index) - MessageBus.emit_local("update_active_lbl", null) - func setup_signals() -> void: Globals.game_state.update_cue_cam_position.connect( _on_update_cue_cam_position ) - MessageBus.subscribe("update_active_lbl", _on_update_active_lbl) func setup_multiplayer() -> void: - player_lbl.text = Globals.game_data.player_id - if not Globals.multiplayer_data.is_multiplayer_active: return - reset_bttn.pressed.disconnect(_on_reset_bttn_pressed) - reset_bttn.visible = false - -func _on_update_active_lbl() -> void: - active_lbl.visible = \ - Globals.multiplayer_data.current_turn_player_id == multiplayer.get_unique_id() func _on_update_cue_cam_position(marker_rotation: Vector3, marker_position: Vector3) -> void: cue_cam.global_rotation = marker_rotation @@ -71,9 +56,6 @@ func _on_next_bttn_pressed() -> void: _set_active_camera() -func _on_reset_bttn_pressed() -> void: - Globals.game_state.reload_scene.emit() - func _set_active_camera(): current_cam.set_current(false) current_cam = cameras.get(current_cam_index) diff --git a/scenes/menus/camera/camera_controller.gd.uid b/scenes/ui_controls/camera/camera_controller.gd.uid similarity index 100% rename from scenes/menus/camera/camera_controller.gd.uid rename to scenes/ui_controls/camera/camera_controller.gd.uid diff --git a/scenes/menus/camera/camera_controller.tscn b/scenes/ui_controls/camera/camera_controller.tscn similarity index 54% rename from scenes/menus/camera/camera_controller.tscn rename to scenes/ui_controls/camera/camera_controller.tscn index cff96c4..22db4a5 100644 --- a/scenes/menus/camera/camera_controller.tscn +++ b/scenes/ui_controls/camera/camera_controller.tscn @@ -1,20 +1,20 @@ -[gd_scene load_steps=4 format=3 uid="uid://w3vh1gj6t2k2"] +[gd_scene load_steps=3 format=3 uid="uid://w3vh1gj6t2k2"] -[ext_resource type="Script" uid="uid://bpf107mmjiswh" path="res://scenes/menus/camera/camera_controller.gd" id="1_mvpa7"] +[ext_resource type="Script" uid="uid://bpf107mmjiswh" path="res://scenes/ui_controls/camera/camera_controller.gd" id="1_mvpa7"] [sub_resource type="LabelSettings" id="LabelSettings_mvpa7"] font_size = 24 -[sub_resource type="LabelSettings" id="LabelSettings_duxs1"] -font_color = Color(0, 1, 0.14117648, 1) - [node name="camera_controller" type="Control"] layout_mode = 3 -anchors_preset = 15 +anchors_preset = 12 +anchor_top = 1.0 anchor_right = 1.0 anchor_bottom = 1.0 +offset_top = -68.0 +offset_bottom = -68.0 grow_horizontal = 2 -grow_vertical = 2 +grow_vertical = 0 script = ExtResource("1_mvpa7") [node name="margin_container" type="MarginContainer" parent="."] @@ -34,17 +34,9 @@ layout_mode = 2 layout_mode = 2 size_flags_vertical = 3 -[node name="hbox" type="HBoxContainer" parent="margin_container/vbox/hbox"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="player_lbl" type="Label" parent="margin_container/vbox/hbox/hbox"] -layout_mode = 2 -size_flags_horizontal = 3 -text = "Player 1" - [node name="hbox2" type="HBoxContainer" parent="margin_container/vbox/hbox"] layout_mode = 2 +size_flags_horizontal = 10 [node name="prev_bttn" type="Button" parent="margin_container/vbox/hbox/hbox2"] z_index = 1 @@ -69,34 +61,5 @@ mouse_default_cursor_shape = 2 text = "" flat = true -[node name="hbox2" type="HBoxContainer" parent="margin_container/vbox"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="hbox" type="HBoxContainer" parent="margin_container/vbox/hbox2"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="active_lbl" type="Label" parent="margin_container/vbox/hbox2/hbox"] -visible = false -layout_mode = 2 -text = "Active" -label_settings = SubResource("LabelSettings_duxs1") -uppercase = true - -[node name="hbox2" type="HBoxContainer" parent="margin_container/vbox/hbox2"] -clip_contents = true -custom_minimum_size = Vector2(149, 0) -layout_mode = 2 - -[node name="reset_bttn" type="Button" parent="margin_container/vbox/hbox2/hbox2"] -layout_mode = 2 -focus_mode = 0 -mouse_default_cursor_shape = 2 -text = "Reset" -flat = true -alignment = 0 - [connection signal="pressed" from="margin_container/vbox/hbox/hbox2/prev_bttn" to="." method="_on_prev_bttn_pressed"] [connection signal="pressed" from="margin_container/vbox/hbox/hbox2/next_bttn" to="." method="_on_next_bttn_pressed"] -[connection signal="pressed" from="margin_container/vbox/hbox2/hbox2/reset_bttn" to="." method="_on_reset_bttn_pressed"] diff --git a/scenes/ui_controls/game/data.gd b/scenes/ui_controls/game/data.gd new file mode 100644 index 0000000..5d3a1ab --- /dev/null +++ b/scenes/ui_controls/game/data.gd @@ -0,0 +1,33 @@ +extends Control + + +@onready var player_lbl: Label = $vbox/hbox/hbox/player_lbl +@onready var active_lbl: Label = $vbox/hbox/hbox/active_lbl +@onready var reset_bttn: Button = $vbox/hbox/hbox2/reset_bttn + + +func _ready() -> void: + setup_signals() + setup_multiplayer() + + MessageBus.emit_local("update_active_lbl", null) + + +func setup_signals() -> void: + MessageBus.subscribe("update_active_lbl", _on_update_active_lbl) + +func setup_multiplayer() -> void: + player_lbl.text = Globals.game_data.player_id + + if not Globals.multiplayer_data.is_multiplayer_active: return + + reset_bttn.pressed.disconnect(_on_reset_bttn_pressed) + reset_bttn.visible = false + + +func _on_update_active_lbl() -> void: + active_lbl.visible = \ + Globals.multiplayer_data.current_turn_player_id == multiplayer.get_unique_id() + +func _on_reset_bttn_pressed() -> void: + Globals.game_state.reload_scene.emit() diff --git a/scenes/ui_controls/game/data.gd.uid b/scenes/ui_controls/game/data.gd.uid new file mode 100644 index 0000000..11dda00 --- /dev/null +++ b/scenes/ui_controls/game/data.gd.uid @@ -0,0 +1 @@ +uid://br6jmlm4poh62 diff --git a/scenes/ui_controls/game/data.tscn b/scenes/ui_controls/game/data.tscn new file mode 100644 index 0000000..b04a309 --- /dev/null +++ b/scenes/ui_controls/game/data.tscn @@ -0,0 +1,54 @@ +[gd_scene load_steps=3 format=3 uid="uid://l3bve6miq8od"] + +[ext_resource type="Script" uid="uid://br6jmlm4poh62" path="res://scenes/ui_controls/game/data.gd" id="1_s7215"] + +[sub_resource type="LabelSettings" id="LabelSettings_o1hjn"] +font_color = Color(0, 1, 0.14117648, 1) + +[node name="data" type="Control"] +layout_mode = 3 +anchors_preset = 10 +anchor_right = 1.0 +grow_horizontal = 2 +script = ExtResource("1_s7215") + +[node name="vbox" type="VBoxContainer" parent="."] +layout_mode = 0 +offset_left = 10.0 +offset_top = 5.0 +offset_right = 1142.0 +offset_bottom = 69.0 + +[node name="hbox" type="HBoxContainer" parent="vbox"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="hbox" type="HBoxContainer" parent="vbox/hbox"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="player_lbl" type="Label" parent="vbox/hbox/hbox"] +layout_mode = 2 +text = "Player 1" + +[node name="active_lbl" type="Label" parent="vbox/hbox/hbox"] +visible = false +layout_mode = 2 +text = "Active" +label_settings = SubResource("LabelSettings_o1hjn") +uppercase = true + +[node name="hbox2" type="HBoxContainer" parent="vbox/hbox"] +layout_mode = 2 +size_flags_horizontal = 8 +size_flags_vertical = 3 + +[node name="reset_bttn" type="Button" parent="vbox/hbox/hbox2"] +layout_mode = 2 +focus_mode = 0 +mouse_default_cursor_shape = 2 +text = "Reset" +flat = true +alignment = 0 + +[connection signal="pressed" from="vbox/hbox/hbox2/reset_bttn" to="." method="_on_reset_bttn_pressed"]