diff --git a/scenes/gauntlet_hud.tscn b/scenes/gauntlet_hud.tscn new file mode 100644 index 0000000..7780464 --- /dev/null +++ b/scenes/gauntlet_hud.tscn @@ -0,0 +1,52 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="FontFile" uid="uid://xnjx058n4tsw" path="res://assets/fonts/Nougat-ExtraBlack.ttf" id="1_font"] + +[node name="GauntletHUD" type="CanvasLayer"] +layer = 5 +visible = false + +[node name="TopContainer" type="CenterContainer" parent="."] +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_top = 70.0 +grow_horizontal = 2 + +[node name="PhaseLabel" type="Label" parent="TopContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 24 +theme_override_colors/font_color = Color(1, 0.6, 0.8, 1) +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 6 +theme_override_fonts/font = ExtResource("1_font") +text = "🍬 OPEN ARENA" +horizontal_alignment = 1 + +[node name="BottomContainer" type="CenterContainer" parent="."] +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_top = -90.0 +grow_horizontal = 2 +grow_vertical = 0 + +[node name="CleanserHBox" type="HBoxContainer" parent="BottomContainer"] +layout_mode = 2 +theme_override_constants/separation = 6 + +[node name="CleanserIcon" type="TextureRect" parent="BottomContainer/CleanserHBox"] +layout_mode = 2 +custom_minimum_size = Vector2(20, 20) +stretch_mode = 5 + +[node name="CleanserLabel" type="Label" parent="BottomContainer/CleanserHBox"] +layout_mode = 2 +theme_override_font_sizes/font_size = 20 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 6 +theme_override_fonts/font = ExtResource("1_font") +text = "Cleanser: 0" +horizontal_alignment = 1 diff --git a/scenes/lobby.gd b/scenes/lobby.gd index 1a894d3..19525c7 100644 --- a/scenes/lobby.gd +++ b/scenes/lobby.gd @@ -498,6 +498,8 @@ func _on_mail_unread_count_changed(count: int) -> void: mail_badge.visible = false func _sync_room_profile_card() -> void: + if username_label: + username_label.text = UserProfileManager.get_display_name() if room_player_username: room_player_username.text = UserProfileManager.get_display_name() if room_player_score: diff --git a/scenes/main.gd b/scenes/main.gd index 9a1dd3b..935c76b 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -1854,18 +1854,16 @@ func randomize_item_at_position(grid_position: Vector2i): break if is_ground: - var new_item = 7 + var get_mode_specific_tile = func(): + if LobbyManager.game_mode != "Stop n Go" and LobbyManager.game_mode != "Tekton Doors" and LobbyManager.game_mode != "Candy Cannon Survival": + # 60% Chance for Common (7-10), 40% for PowerUp + if randf() <= 0.6: + return [7, 8, 9, 10].pick_random() + else: + return ScarcityModel.SPECIAL_TILES.pick_random() + return ScarcityController.get_random_tile_id() - var get_mode_specific_tile = func(): - if LobbyManager.game_mode != "Stop n Go" and LobbyManager.game_mode != "Tekton Doors" and LobbyManager.game_mode != "Candy Cannon Survival": - # 60% Chance for Common (7-10), 40% for PowerUp - if randf() <= 0.6: - return [7, 8, 9, 10].pick_random() - else: - return ScarcityModel.SPECIAL_TILES.pick_random() - return ScarcityController.get_random_tile_id() - - new_item = get_mode_specific_tile.call() + var new_item = get_mode_specific_tile.call() # If we are replacing an existing item, try to ensure it changes if current_item != -1: diff --git a/scripts/managers/camera_context_manager.gd b/scripts/managers/camera_context_manager.gd index c98b12e..c276897 100644 --- a/scripts/managers/camera_context_manager.gd +++ b/scripts/managers/camera_context_manager.gd @@ -16,6 +16,7 @@ var player: Node3D var bounds_freemode = { "min_x": 3.0, "max_x": 11.0, "min_z": 13.0, "max_z": 22.5 } var bounds_stop_n_go = { "min_x": 3.0, "max_x": 19.5, "min_z": 13.0, "max_z": 19.5 } var bounds_doors = { "min_x": 7.0, "max_x": 7.0, "min_z": 25.8, "max_z": 25.8 } # Static overlook +var bounds_gauntlet = { "min_x": 1.0, "max_x": 18.0, "min_z": 12.0, "max_z": 19.0 } # 20x20 arena func initialize(p_camera: Camera3D, _p_shake_manager: Node): camera = p_camera @@ -51,6 +52,8 @@ func _calculate_target_position() -> Vector3: elif mode == GameMode.Mode.TEKTON_DOORS: bounds = bounds_doors target_y = 32.3 # Doors uses a higher overlook + elif mode == GameMode.Mode.GAUNTLET: + bounds = bounds_gauntlet # Clamp X and Z target_x = clamp(target_x, bounds.min_x, bounds.max_x) diff --git a/scripts/managers/gauntlet_manager.gd b/scripts/managers/gauntlet_manager.gd index 922394d..9788190 100644 --- a/scripts/managers/gauntlet_manager.gd +++ b/scripts/managers/gauntlet_manager.gd @@ -131,6 +131,7 @@ var phase_label: Label var cleanser_label: Label var cleanser_icon: TextureRect var cleanser_count: int = 0 +var _gauntlet_hud_scene: PackedScene = preload("res://scenes/gauntlet_hud.tscn") # ============================================================================= # Lifecycle @@ -899,75 +900,29 @@ func sync_slowmo_end() -> void: # ============================================================================= func _setup_hud() -> void: - hud_layer = CanvasLayer.new() - hud_layer.layer = 5 + var hud_instance = _gauntlet_hud_scene.instantiate() + hud_layer = hud_instance hud_layer.visible = false add_child(hud_layer) - - var custom_font = load("res://assets/fonts/Nougat-ExtraBlack.ttf") - - # Phase label (top-center) - var top_container = CenterContainer.new() - top_container.set_anchors_preset(Control.PRESET_CENTER_TOP) - top_container.grow_horizontal = Control.GROW_DIRECTION_BOTH - top_container.grow_vertical = Control.GROW_DIRECTION_END - top_container.offset_top = 70 - hud_layer.add_child(top_container) - - phase_label = Label.new() - phase_label.text = "🍬 OPEN ARENA" - phase_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - if custom_font: phase_label.add_theme_font_override("font", custom_font) - phase_label.add_theme_font_size_override("font_size", 24) - phase_label.add_theme_color_override("font_outline_color", Color.BLACK) - phase_label.add_theme_constant_override("outline_size", 6) - phase_label.add_theme_color_override("font_color", Color(1.0, 0.6, 0.8)) # Candy pink - top_container.add_child(phase_label) - - # Cleanser HUD (bottom-center) with icon - var bottom_container = CenterContainer.new() - bottom_container.set_anchors_preset(Control.PRESET_CENTER_BOTTOM) - bottom_container.grow_horizontal = Control.GROW_DIRECTION_BOTH - bottom_container.grow_vertical = Control.GROW_DIRECTION_BEGIN - bottom_container.offset_bottom = -50 - hud_layer.add_child(bottom_container) - - var cleanser_hbox = HBoxContainer.new() - cleanser_hbox.add_theme_constant_override("separation", 6) - bottom_container.add_child(cleanser_hbox) - - # Cleanser icon (colored square as visual indicator) - cleanser_icon = TextureRect.new() - cleanser_icon.custom_minimum_size = Vector2(20, 20) - cleanser_icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED - # Generate a simple colored texture for the cleanser icon + phase_label = hud_layer.get_node("TopContainer/PhaseLabel") + cleanser_icon = hud_layer.get_node("BottomContainer/CleanserHBox/CleanserIcon") + cleanser_label = hud_layer.get_node("BottomContainer/CleanserHBox/CleanserLabel") + _generate_cleanser_icon() + +func _generate_cleanser_icon() -> void: var icon_img = Image.create(16, 16, false, Image.FORMAT_RGBA8) - icon_img.fill(Color(0.4, 0.9, 1.0)) # Cyan/teal for cleanser + icon_img.fill(Color(0.4, 0.9, 1.0)) icon_img.blend_rect(icon_img, Rect2i(2, 2, 12, 12), Vector2i(1, 1)) - # Add a darker border for x in range(16): icon_img.set_pixel(x, 0, Color(0.2, 0.6, 0.7)) icon_img.set_pixel(x, 15, Color(0.2, 0.6, 0.7)) for y in range(16): icon_img.set_pixel(0, y, Color(0.2, 0.6, 0.7)) icon_img.set_pixel(15, y, Color(0.2, 0.6, 0.7)) - # Add a cross/sparkle pattern for "cleansing" effect for i in range(4, 12): icon_img.set_pixel(i, 7, Color(1.0, 1.0, 1.0, 0.8)) icon_img.set_pixel(7, i, Color(1.0, 1.0, 1.0, 0.8)) - var icon_tex = ImageTexture.create_from_image(icon_img) - cleanser_icon.texture = icon_tex - cleanser_hbox.add_child(cleanser_icon) - - # Cleanser text label - cleanser_label = Label.new() - cleanser_label.text = "Cleanser: 0" - cleanser_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - if custom_font: cleanser_label.add_theme_font_override("font", custom_font) - cleanser_label.add_theme_font_size_override("font_size", 20) - cleanser_label.add_theme_color_override("font_outline_color", Color.BLACK) - cleanser_label.add_theme_constant_override("outline_size", 6) - cleanser_hbox.add_child(cleanser_label) + cleanser_icon.texture = ImageTexture.create_from_image(icon_img) func _update_hud_phase(phase_name: String) -> void: if phase_label: @@ -1089,12 +1044,12 @@ func _respawn_mission_tiles() -> void: for i in range(tiles_to_place): var pos = empty_cells[i] var tile_type = goal_items[randi() % goal_items.size()] - gridmap.set_cell_item(Vector3i(pos.x, 1, pos.z), tile_type) + gridmap.set_cell_item(Vector3i(pos.x, 1, pos.y), tile_type) tiles_spawned += 1 # Sync to clients if main_scene: - main_scene.rpc("sync_grid_item", pos.x, 1, pos.z, tile_type) + main_scene.rpc("sync_grid_item", pos.x, 1, pos.y, tile_type) print("[Gauntlet] Respawned %d mission tiles" % tiles_spawned) diff --git a/scripts/managers/lobby_manager.gd b/scripts/managers/lobby_manager.gd index 4ede2b3..bf43802 100644 --- a/scripts/managers/lobby_manager.gd +++ b/scripts/managers/lobby_manager.gd @@ -733,6 +733,8 @@ func sync_game_mode(mode: String) -> void: """Sync game mode selection from host to clients.""" game_mode = mode _update_available_areas(mode) + if selected_area not in available_areas: + selected_area = available_areas[0] emit_signal("game_mode_changed", mode) func start_game(force: bool = false) -> void: