feat: add tutorial section

This commit is contained in:
2026-04-10 05:17:30 +08:00
parent 222621139e
commit 5323aea5fb
16 changed files with 828 additions and 5 deletions
+27
View File
@@ -121,6 +121,18 @@ func _ready():
# Initial UI update
_on_profile_updated()
# Inject Tutorial button
var tutorial_btn = Button.new()
tutorial_btn.name = "TutorialBtn"
tutorial_btn.text = "PLAY TUTORIAL"
tutorial_btn.theme_type_variation = "FlatButton"
tutorial_btn.add_theme_font_size_override("font_size", 24)
tutorial_btn.pressed.connect(_on_tutorial_pressed)
var btn_section = main_menu_panel.get_node_or_null("VBoxContainer/ButtonSection")
if btn_section:
btn_section.add_child(tutorial_btn)
btn_section.move_child(tutorial_btn, 0)
# Connect button signals - Main Menu
create_room_btn.pressed.connect(_on_create_room_pressed)
browse_rooms_btn.pressed.connect(_on_browse_rooms_pressed)
@@ -333,6 +345,21 @@ func _show_panel(panel_name: String) -> void:
# Main Menu Button Handlers
# =============================================================================
func _on_tutorial_pressed() -> void:
if AuthManager.is_guest:
if LobbyManager.local_player_name.is_empty() or LobbyManager.local_player_name == "Player":
LobbyManager.local_player_name = NameGenerator.generate_guest_name()
else:
LobbyManager.local_player_name = UserProfileManager.get_display_name()
connection_status.text = "Starting Tutorial Scenario..."
_apply_loadout_character()
LobbyManager.start_tutorial("Freemode")
# Give the engine two frames for room_joined signal to settle,
# then immediately force-start the game — bypassing the lobby wait screen.
await get_tree().process_frame
await get_tree().process_frame
LobbyManager.start_game(true)
func _on_create_room_pressed() -> void:
# Use profile name for logged-in users, or guest for others
if AuthManager.is_guest:
+9
View File
@@ -101,6 +101,15 @@ func _ready():
if top_settings_btn:
if not top_settings_btn.pressed.is_connected(_toggle_pause_menu):
top_settings_btn.pressed.connect(_toggle_pause_menu)
# Tutorial Override
if LobbyManager.get("is_tutorial_mode"):
var tutorial_script = load("res://scripts/managers/tutorial_manager.gd")
if tutorial_script:
var tutorial_node = Node.new()
tutorial_node.set_script(tutorial_script)
tutorial_node.name = "TutorialManager"
add_child(tutorial_node)
func _setup_multiplayer_spawners():
# Setup MultiplayerSpawner for Static Tekton Stands
+3
View File
@@ -1644,6 +1644,9 @@ func start_movement_along_path(path: Array, clear_visual: bool = true, force: bo
if TurnManager.turn_based_mode:
end_turn()
_after_action_completed()
if movement_manager and movement_manager.has_method("_on_movement_finished"):
movement_manager.call_deferred("_on_movement_finished")
)
#func trigger_finish_line():
+31
View File
@@ -0,0 +1,31 @@
shader_type canvas_item;
// Spotlight rect in viewport pixel coordinates
// vec4(x, y, width, height) — set to vec4(0,0,0,0) to dim everything
uniform vec4 spotlight = vec4(0.0, 0.0, 0.0, 0.0);
uniform vec2 viewport_size = vec2(1366.0, 720.0);
uniform float dim_alpha : hint_range(0.0, 1.0) = 0.72;
uniform float padding : hint_range(0.0, 32.0) = 8.0;
void fragment() {
bool has_spotlight = spotlight.z > 1.0 && spotlight.w > 1.0;
if (has_spotlight) {
// Convert spotlight rect to UV space
float left = (spotlight.x - padding) / viewport_size.x;
float top = (spotlight.y - padding) / viewport_size.y;
float right = (spotlight.x + spotlight.z + padding) / viewport_size.x;
float bottom = (spotlight.y + spotlight.w + padding) / viewport_size.y;
bool in_hole = (UV.x >= left) && (UV.x <= right)
&& (UV.y >= top) && (UV.y <= bottom);
if (in_hole) {
COLOR = vec4(0.0, 0.0, 0.0, 0.0); // transparent — element shows through
} else {
COLOR = vec4(0.0, 0.0, 0.0, dim_alpha);
}
} else {
COLOR = vec4(0.0, 0.0, 0.0, dim_alpha);
}
}
@@ -0,0 +1 @@
uid://b74mlkt6hd88r
+159
View File
@@ -0,0 +1,159 @@
[gd_scene format=3 uid="uid://b457o3pea81nm"]
[ext_resource type="Script" uid="uid://bnhgqibcee442" path="res://scripts/managers/tutorial_overlay.gd" id="1_script"]
[ext_resource type="Shader" uid="uid://b74mlkt6hd88r" path="res://scenes/tutorial/dim_spotlight.gdshader" id="2_shader"]
[ext_resource type="Texture2D" uid="uid://brhn1dhp1gm13" path="res://assets/graphics/character_selection/sc_characters/sc_copper.png" id="3_portrait"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_dim"]
shader = ExtResource("2_shader")
shader_parameter/spotlight = Vector4(0, 0, 0, 0)
shader_parameter/viewport_size = Vector2(1366, 720)
shader_parameter/dim_alpha = 0.72
shader_parameter/padding = 10.0
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_border"]
bg_color = Color(0, 0, 0, 0)
border_width_left = 4
border_width_top = 4
border_width_right = 4
border_width_bottom = 4
border_color = Color(1, 0.85, 0.1, 1)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_panel"]
bg_color = Color(0.08, 0.08, 0.13, 0.97)
border_width_left = 4
border_width_top = 4
border_width_right = 4
border_width_bottom = 4
border_color = Color(0.4, 0.7, 1, 1)
corner_radius_top_left = 16
corner_radius_top_right = 16
corner_radius_bottom_right = 16
corner_radius_bottom_left = 16
[node name="TutorialOverlay" type="CanvasLayer" unique_id=1522233495]
layer = 100
script = ExtResource("1_script")
[node name="InputMask" type="Control" parent="." unique_id=441807788]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="DimRect" type="ColorRect" parent="." unique_id=1364863078]
material = SubResource("ShaderMaterial_dim")
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
color = Color(0, 0, 0, 1)
[node name="HighlightBorder" type="Panel" parent="." unique_id=25061739]
visible = false
offset_right = 100.0
offset_bottom = 100.0
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_border")
[node name="DialoguePanel" type="PanelContainer" parent="." unique_id=2001383324]
offset_left = 283.0
offset_top = 510.0
offset_right = 1083.0
offset_bottom = 690.0
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_panel")
[node name="MarginContainer" type="MarginContainer" parent="DialoguePanel" unique_id=1771861001]
layout_mode = 2
theme_override_constants/margin_left = 20
theme_override_constants/margin_top = 20
theme_override_constants/margin_right = 20
theme_override_constants/margin_bottom = 20
[node name="HBoxContainer" type="HBoxContainer" parent="DialoguePanel/MarginContainer" unique_id=357088930]
layout_mode = 2
theme_override_constants/separation = 20
[node name="Portrait" type="TextureRect" parent="DialoguePanel/MarginContainer/HBoxContainer" unique_id=1911601986]
custom_minimum_size = Vector2(120, 120)
layout_mode = 2
size_flags_vertical = 4
texture = ExtResource("3_portrait")
expand_mode = 2
stretch_mode = 6
[node name="VBoxContainer" type="VBoxContainer" parent="DialoguePanel/MarginContainer/HBoxContainer" unique_id=1395184995]
layout_mode = 2
size_flags_horizontal = 3
[node name="SpeakerName" type="Label" parent="DialoguePanel/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1999858404]
layout_mode = 2
theme_override_colors/font_color = Color(0.5, 0.8, 1, 1)
theme_override_font_sizes/font_size = 22
text = "COMMANDER COPPER"
[node name="DialogueText" type="RichTextLabel" parent="DialoguePanel/MarginContainer/HBoxContainer/VBoxContainer" unique_id=476321723]
layout_mode = 2
size_flags_vertical = 3
theme_override_font_sizes/normal_font_size = 19
bbcode_enabled = true
[node name="NextIndicator" type="Label" parent="DialoguePanel/MarginContainer/HBoxContainer/VBoxContainer" unique_id=554389315]
visible = false
layout_mode = 2
theme_override_colors/font_color = Color(1, 1, 0.5, 1)
theme_override_font_sizes/font_size = 15
text = "Click anywhere to continue ▼"
horizontal_alignment = 2
[node name="HighlightZones" type="Node" parent="." unique_id=2013793015]
metadata/_comment = "Visual-editor zones: open tutorial_overlay.tscn in Godot, drag each Control to match the game UI element you want highlighted. Positions are in 1366x720 viewport space."
[node name="PlayerBoard" type="Control" parent="HighlightZones" unique_id=461308610]
layout_mode = 3
anchors_preset = 0
offset_left = 36.0
offset_top = 87.0
offset_right = 301.0
offset_bottom = 374.0
[node name="PowerBar" type="Control" parent="HighlightZones" unique_id=421147912]
layout_mode = 3
anchors_preset = 0
offset_left = 30.0
offset_top = 339.0
offset_right = 317.0
offset_bottom = 415.0
[node name="GoalsTimer" type="Control" parent="HighlightZones" unique_id=1065585227]
layout_mode = 3
anchors_preset = 0
offset_left = 499.0
offset_top = 1.0
offset_right = 875.0
offset_bottom = 161.0
[node name="PowerUpItem" type="Control" parent="HighlightZones" unique_id=474081571]
layout_mode = 3
anchors_preset = 0
offset_left = 130.0
offset_top = 501.0
offset_right = 220.0
offset_bottom = 591.0
[node name="Leaderboard" type="Control" parent="HighlightZones" unique_id=1503191193]
layout_mode = 3
anchors_preset = 0
offset_left = 1080.0
offset_top = 96.0
offset_right = 1356.0
offset_bottom = 405.0