feat: Add PortalModeManager and integrate it for the Tekton Doors game mode.

This commit is contained in:
Yogi Wiguna
2026-02-26 17:42:47 +08:00
parent f13ec4782b
commit 145a1a53dc
2 changed files with 41 additions and 20 deletions
+39 -18
View File
@@ -50,7 +50,14 @@ func initialize(p_main: Node, p_gridmap: Node):
# Connect to mission tracking
var gcm = main.get_node_or_null("GoalsCycleManager")
if gcm:
gcm.goal_count_updated.connect(_on_goal_count_updated)
gcm.global_timer_updated.connect(_on_global_timer_updated)
func _on_global_timer_updated(time_remaining: float):
if not multiplayer.is_server(): return
# Last 30 seconds: Reveal Finish Room
if time_remaining <= 30.0 and not finish_spawned:
_spawn_finish_room()
func start_game_mode():
if not multiplayer.is_server(): return
@@ -81,6 +88,11 @@ func setup_arena_locally():
_setup_arena_size()
_setup_room_partitions()
_spawn_portal_doors()
# PRE-FILL TILES: Ensure all floor tiles have items before the countdown starts
if multiplayer.is_server():
_refresh_tiles()
arena_setup_done = true
func _setup_arena_size():
@@ -291,29 +303,38 @@ func sync_portal_data(data: Array):
print("[PortalModeManager] Warning: Door index %d or %d out of range during sync" % [a_id, b_id])
func _on_goal_count_updated(_peer_id: int, count: int):
if not multiplayer.is_server(): return
if count >= missions_required and not finish_spawned:
_spawn_finish_room()
func _on_global_goal_count_updated(_peer_id: int, _count: int):
# Mission requirement removed in favor of time-based finish reveal
pass
func _spawn_finish_room():
print("[PortalModeManager] Missions complete! Spawning Finish Room...")
print("[PortalModeManager] Time is running out! Revealing Finish Room...")
finish_spawned = true
# Choose a random center room tile (X=3, Z=10 or similar in any room)
# Choose a random center room spawn point to place the finish tile
var room_centers = get_spawn_points()
var center = room_centers[randi() % room_centers.size()]
# Place finish tile (ID 3) on Floor 1 (Y=1)
# Check if this center is actually clear (not a wall accidentally)
if gridmap.get_cell_item(Vector3i(center.x, 0, center.y)) == 4:
# Fallback to any non-wall center if needed, but spawn points are usually safe
pass
# We use current_position as spawn point centers are guaranteed to be walkable
# IMPORTANT: Change the floor tile (Floor 0) to item ID 3 (Goal/Finish)
main.rpc("sync_grid_item", center.x, 0, center.y, 3)
# Clear any item on Floor 1 above the finish tile
main.rpc("sync_grid_item", center.x, 1, center.y, -1)
# Visual update for server
if gridmap.has_method("update_grid_data"):
gridmap.update_grid_data()
main.rpc("sync_grid_item", center.x, 1, center.y, 3)
main.get_node("EnhancedGridMap").update_grid_data()
main.rpc("display_message", "FINISH ROOM REVEALED!")
main.rpc("display_message", "[ALARM] THE FINISH ROOM HAS APPEARED!")
main.rpc("broadcast_message", "SYSTEM", "The Finish Tile is in Room %d!" % _get_room_index(center), 4) # 4 = MessageType.WARNING
func _get_room_index(pos: Vector2i) -> int:
if pos.x < 7 and pos.y < 7: return 0
if pos.x >= 7 and pos.y < 7: return 1
if pos.x < 7 and pos.y >= 7: return 2
return 3
func _on_swap_timer_timeout():
_randomize_connections()
@@ -336,11 +357,11 @@ func _refresh_tiles():
if gridmap.get_cell_item(Vector3i(x, 1, z)) != -1:
continue
# 3. Low chance to spawn a tile
if randf() < 0.1:
# 3. Spawn a tile (60% chance per valid floor cell)
if randf() < 0.6:
var weights = ScarcityModel.get_tile_weights()
var tile_id = _pick_weighted_tile(weights)
# Update GridMap Floor 1 via RPC for sync (call_local handles host)
# Update GridMap Floor 1 via RPC for sync
main.rpc("sync_grid_item", x, 1, z, tile_id)
func _pick_weighted_tile(weights: Dictionary) -> int: