feat: Implement the core "Tekton Doors" game mode including arena setup, portal management, special tiles, and mission tracking HUD.
Tekton Armageddon V.0.8
This commit is contained in:
+82
-19
@@ -57,6 +57,24 @@ func _ready():
|
||||
# Ensure grid is randomized with Scarcity if server
|
||||
if multiplayer.is_server():
|
||||
randomize_game_grid()
|
||||
|
||||
# Setup global multiplayer spawners (Stands, etc.)
|
||||
_setup_multiplayer_spawners()
|
||||
|
||||
func _setup_multiplayer_spawners():
|
||||
# Setup MultiplayerSpawner for Static Tekton Stands
|
||||
# Create a container node for strict pathing
|
||||
if not has_node("Stands"):
|
||||
var stands_container = Node3D.new()
|
||||
stands_container.name = "Stands"
|
||||
add_child(stands_container)
|
||||
|
||||
if not has_node("StandSpawner"):
|
||||
var stand_spawner = MultiplayerSpawner.new()
|
||||
stand_spawner.name = "StandSpawner"
|
||||
stand_spawner.spawn_path = NodePath("../Stands") # Relative to Spawner, finding sibling
|
||||
stand_spawner.add_spawnable_scene("res://scenes/static_tekton_stand.tscn")
|
||||
add_child(stand_spawner)
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_portal_configs(configs: Array):
|
||||
@@ -70,18 +88,6 @@ func sync_portal_configs(configs: Array):
|
||||
var em = $EnhancedGridMap
|
||||
if em:
|
||||
em.cell_size = Vector3(1, 0.05, 1)
|
||||
|
||||
# Setup MultiplayerSpawner for Static Tekton Stands
|
||||
# Create a container node for strict pathing
|
||||
var stands_container = Node3D.new()
|
||||
stands_container.name = "Stands"
|
||||
add_child(stands_container)
|
||||
|
||||
var stand_spawner = MultiplayerSpawner.new()
|
||||
stand_spawner.name = "StandSpawner"
|
||||
stand_spawner.spawn_path = NodePath("../Stands") # Relative to Spawner, finding sibling
|
||||
stand_spawner.add_spawnable_scene("res://scenes/static_tekton_stand.tscn")
|
||||
add_child(stand_spawner)
|
||||
|
||||
func _on_goal_count_updated(peer_id: int, count: int):
|
||||
# Only update for local player
|
||||
@@ -1588,8 +1594,30 @@ func sync_grid_item(x: int, y: int, z: int, item: int):
|
||||
if enhanced_gridmap.has_method("update_grid_data"):
|
||||
enhanced_gridmap.update_grid_data()
|
||||
|
||||
# Sync grid update (no need to sync whole grid if we do it at start, but if we do it late we might need to sync)
|
||||
# For simplicity, we trust the grid syncs via normal mechanisms or initial state.
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_grid_items_batch(data: Array):
|
||||
# data is an array of dictionaries: [{x: int, y: int, z: int, item: int}, ...]
|
||||
var enhanced_gridmap = $EnhancedGridMap
|
||||
if not enhanced_gridmap:
|
||||
return
|
||||
|
||||
for entry in data:
|
||||
var x = entry.get("x", 0)
|
||||
var y = entry.get("y", 0)
|
||||
var z = entry.get("z", 0)
|
||||
var item = entry.get("item", -1)
|
||||
|
||||
# WALL-SAFETY CHECK
|
||||
if y == 1 and item >= 7 and item <= 20:
|
||||
var f0 = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z))
|
||||
if f0 == 4 or f0 == -1:
|
||||
continue
|
||||
|
||||
enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item)
|
||||
|
||||
# Force visual update ONCE after batch
|
||||
if enhanced_gridmap.has_method("update_grid_data"):
|
||||
enhanced_gridmap.update_grid_data()
|
||||
|
||||
func randomize_game_grid():
|
||||
if LobbyManager.game_mode == "Stop n Go" or LobbyManager.game_mode == "Tekton Doors":
|
||||
@@ -1762,7 +1790,7 @@ func sync_game_end_stop_n_go(winner_id: int):
|
||||
winner_name = player_node.display_name
|
||||
|
||||
# Broadcast win (Validation already done in check_win_condition)
|
||||
add_message_to_bar("MATCH COMPLETE", winner_name + " Wins with 3 Missions!", MessageType.GOAL)
|
||||
add_message_to_bar("MATCH COMPLETE", winner_name + " Wins with 8 Missions!", MessageType.GOAL)
|
||||
|
||||
# Stop logic
|
||||
if stop_n_go_manager:
|
||||
@@ -1800,10 +1828,42 @@ func _on_match_ended():
|
||||
var local_player = GameStateManager.local_player_character
|
||||
if local_player:
|
||||
local_player.action_points = 0
|
||||
|
||||
# Signal Global Game End (Stops Bot ticks and logic)
|
||||
GameStateManager.end_game()
|
||||
|
||||
# Freeze all game actors (Players, Bots, Tektons)
|
||||
_freeze_all_game_actors()
|
||||
|
||||
# Show game over overlay
|
||||
_show_game_over_panel()
|
||||
|
||||
func _freeze_all_game_actors():
|
||||
"""Manually stop all game entities from processing without pausing the UI."""
|
||||
print("[Main] Freezing all game actors recursively...")
|
||||
|
||||
var groups = ["Players", "Bots", "Tektons", "StaticTektonStands"]
|
||||
for group_name in groups:
|
||||
var nodes = get_tree().get_nodes_in_group(group_name)
|
||||
for node in nodes:
|
||||
_freeze_node_recursive(node)
|
||||
|
||||
func _freeze_node_recursive(node: Node):
|
||||
"""Recursively disable processing and stop tweens for a node and its children."""
|
||||
if node.has_method("set_physics_process"):
|
||||
node.set_physics_process(false)
|
||||
if node.has_method("set_process"):
|
||||
node.set_process(false)
|
||||
|
||||
# Kill movement tweens if it's a character
|
||||
if "_movement_tween" in node and node._movement_tween:
|
||||
node._movement_tween.kill()
|
||||
node._movement_tween = null
|
||||
|
||||
# Recursive call for all children
|
||||
for child in node.get_children():
|
||||
_freeze_node_recursive(child)
|
||||
|
||||
func _show_game_over_panel():
|
||||
"""Create and display the game over panel with final leaderboard."""
|
||||
# Check if panel already exists
|
||||
@@ -1818,6 +1878,9 @@ func _show_game_over_panel():
|
||||
|
||||
if stop_n_go_manager and stop_n_go_manager.hud_layer:
|
||||
stop_n_go_manager.hud_layer.hide()
|
||||
|
||||
if portal_mode_manager and portal_mode_manager.hud_layer:
|
||||
portal_mode_manager.hud_layer.hide()
|
||||
|
||||
# Create game over panel
|
||||
var panel = PanelContainer.new()
|
||||
@@ -1829,7 +1892,7 @@ func _show_game_over_panel():
|
||||
style.bg_color = Color(0.0, 0.0, 0.0, 0.85)
|
||||
panel.add_theme_stylebox_override("panel", style)
|
||||
|
||||
# Content container
|
||||
# CONTENT VBOX
|
||||
var vbox = VBoxContainer.new()
|
||||
vbox.name = "VBox"
|
||||
vbox.set_anchors_preset(Control.PRESET_CENTER)
|
||||
@@ -2209,13 +2272,13 @@ func _toggle_pause_menu():
|
||||
var pause_menu = get_node_or_null("PauseMenu")
|
||||
if pause_menu:
|
||||
pause_menu.visible = not pause_menu.visible
|
||||
get_tree().paused = pause_menu.visible
|
||||
# get_tree().paused = pause_menu.visible # Removed for multiplayer consistency
|
||||
|
||||
func _on_resume_pressed():
|
||||
var pause_menu = get_node_or_null("PauseMenu")
|
||||
if pause_menu:
|
||||
pause_menu.visible = false
|
||||
get_tree().paused = false
|
||||
# get_tree().paused = false # Removed for multiplayer consistency
|
||||
|
||||
func _on_how_to_play_pressed():
|
||||
var pause_menu = get_node_or_null("PauseMenu")
|
||||
@@ -2255,7 +2318,7 @@ func _on_settings_pressed():
|
||||
opacity_slider.set_value_no_signal(touch_controls.button_opacity)
|
||||
|
||||
func _on_quit_match_pressed():
|
||||
get_tree().paused = false
|
||||
get_tree().paused = false # Ensure unpaused when returning to menu
|
||||
# Properly disconnect from Nakama match
|
||||
_cleanup_multiplayer()
|
||||
# Return to lobby or main menu
|
||||
|
||||
+10
-2
@@ -9978,6 +9978,7 @@ horizontal_alignment = 1
|
||||
[node name="TabContainer" type="TabContainer" parent="HowToPlayPanel/Panel/VBox" unique_id=123456794]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
current_tab = 0
|
||||
|
||||
[node name="Free Mode" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456795]
|
||||
layout_mode = 2
|
||||
@@ -9985,6 +9986,7 @@ theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
metadata/_tab_index = 0
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Free Mode" unique_id=123456796]
|
||||
layout_mode = 2
|
||||
@@ -10003,6 +10005,7 @@ theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
metadata/_tab_index = 1
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Stop n Go" unique_id=123456798]
|
||||
layout_mode = 2
|
||||
@@ -10013,7 +10016,7 @@ text = "[b]Stop n Go[/b]
|
||||
- Move forward when the phase is [color=green][b]GO[/b][/color] (Green).
|
||||
- Stop completely when the phase is [color=red][b]STOP[/b][/color] (Red). Moving during a red phase will reset you to the start!
|
||||
- Your objective is to reach the mission tiles at the far end of the arena and safely carry them back to your starting zone.
|
||||
- The first player to complete 3 missions wins."
|
||||
- The first player to complete 8 missions and reach the finish floor wins."
|
||||
|
||||
[node name="Tekton Doors" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456799]
|
||||
visible = false
|
||||
@@ -10022,6 +10025,7 @@ theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
metadata/_tab_index = 2
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Tekton Doors" unique_id=123456800]
|
||||
layout_mode = 2
|
||||
@@ -10031,7 +10035,7 @@ text = "[b]Tekton Doors[/b]
|
||||
- Navigate a sprawling arena connected by color-coded portal doors.
|
||||
- Grab tiles and match goal patterns to earn mission completions.
|
||||
- Use doors to quickly teleport across rooms, but watch out for closures and traps.
|
||||
- The first player to complete 8 missions wins."
|
||||
- The first player to complete 8 missions and reach the finish room wins."
|
||||
|
||||
[node name="Controls" type="MarginContainer" parent="HowToPlayPanel/Panel/VBox/TabContainer" unique_id=123456805]
|
||||
visible = false
|
||||
@@ -10040,6 +10044,7 @@ theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
metadata/_tab_index = 3
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Controls" unique_id=123456806]
|
||||
layout_mode = 2
|
||||
@@ -10061,6 +10066,7 @@ theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
metadata/_tab_index = 4
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/The Grid" unique_id=123456808]
|
||||
layout_mode = 2
|
||||
@@ -10079,6 +10085,7 @@ theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
metadata/_tab_index = 5
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Tektons" unique_id=123456810]
|
||||
layout_mode = 2
|
||||
@@ -10095,6 +10102,7 @@ theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
metadata/_tab_index = 6
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HowToPlayPanel/Panel/VBox/TabContainer/Skills" unique_id=123456812]
|
||||
layout_mode = 2
|
||||
|
||||
Reference in New Issue
Block a user