feat: Implement core game logic, player script, and the Stop n Go game mode with its dedicated manager.

This commit is contained in:
Yogi Wiguna
2026-03-26 17:34:25 +08:00
parent 59950f7b31
commit b0188066b1
3 changed files with 52 additions and 10 deletions
+29 -4
View File
@@ -213,6 +213,15 @@ func start_game_mode():
# activate_client_side() can be called when first sync arrives
pass
func rotate_players_to_start():
"""Force all players to face East (towards finish line). Called before countdown."""
if not multiplayer.is_server(): return
var all_players = get_tree().get_nodes_in_group("Players")
for p in all_players:
if p.has_method("rpc"):
p.rpc("sync_rotation", PI/2)
func _start_phase(phase: Phase):
current_phase = phase
phase_timer = float(LobbyManager.sng_go_duration) if phase == Phase.GO else float(LobbyManager.sng_stop_duration)
@@ -226,7 +235,14 @@ func _start_phase(phase: Phase):
# --- STATIC SAFE ZONE: Penalize players outside the zone ---
var all_players = get_tree().get_nodes_in_group("Players")
for p in all_players:
if not _is_in_safe_zone(p.current_position):
# POSITION SYNC FIX: If player is currently moving on their client,
# the server's 'current_position' might still be the old one.
# Use 'target_position' if they are moving.
var check_pos = p.current_position
if p.get("is_player_moving") and p.get("target_position") != Vector2i(-1, -1):
check_pos = p.target_position
if not _is_in_safe_zone(check_pos):
_scatter_player_tiles(p)
# Refresh power-ups every STOP phase
@@ -550,7 +566,12 @@ func _is_in_safe_zone(pos: Vector2i) -> bool:
gridmap = get_node_or_null("/root/Main/EnhancedGridMap")
if not gridmap: return false
# Check Layer 2 (Overlay layer) for Safe Zone tile
# 1. Check Floor 0 for Start (3) or Finish (3) lines
var floor_tile = gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
if floor_tile == TILE_START or floor_tile == TILE_FINISH:
return true
# 2. Check Layer 2 (Overlay layer) for Dynamic Safe Zone tile
var overlay_tile = gridmap.get_cell_item(Vector3i(pos.x, 2, pos.y))
return overlay_tile == TILE_SAFE
@@ -715,7 +736,11 @@ func _scatter_player_tiles(player_node: Node):
main.rpc("sync_grid_item", drop_pos.x, 1, drop_pos.y, tile)
# Sync cleared playerboard to all clients
main.rpc("sync_playerboard", peer_id, playerboard)
# Sync cleared playerboard via the player's own RPC (more robust than Main lookup)
player_node.rpc("sync_playerboard", playerboard)
# FREEZE FIX: If they were caught outside, they should also be frozen like a movement violation
player_node.rpc("sync_stop_freeze", true)
# Notify the player
SfxManager.rpc("play_rpc", "tile_scatter")
@@ -725,7 +750,7 @@ func _scatter_player_tiles(player_node: Node):
if player_node.has_method("trigger_screen_shake") and can_rpc():
player_node.rpc("trigger_screen_shake", "heavy")
print("[StopNGo] Scattered %d tiles from Player %d" % [tiles_to_scatter.size(), peer_id])
print("[StopNGo] Caught outside: Scattered %d tiles from Player %d" % [tiles_to_scatter.size(), peer_id])
# =============================================================================
# OLD STATIC SAFE ZONE LOGIC (Retained for Reference)