feat: Add PlayerboardManager, SpecialTilesManager, PowerupInventoryUI, and new touch control/power tile assets.

This commit is contained in:
Yogi Wiguna
2026-02-02 18:01:42 +08:00
parent 614d678b84
commit 753757d273
20 changed files with 558 additions and 198 deletions
+39 -22
View File
@@ -15,9 +15,7 @@ func initialize(p_player: Node3D, p_gridmap: Node):
enhanced_gridmap = p_gridmap
func _normalize_tile(tile: int) -> int:
"""Convert holo tiles (11-14) to normal tiles (7-10) for goal comparison."""
if tile >= 11 and tile <= 14:
return tile - 4
"""Normal tiles 7-10 are goals. 11-14 are powerups and not goals."""
return tile
# =============================================================================
@@ -48,10 +46,15 @@ func grab_item(grid_position: Vector2i) -> bool:
return false
# === AUTO-ARRANGE LOGIC (Client-side pre-check) ===
var target_slot = find_best_goal_slot_for_item(item)
if target_slot == -1:
print("Player: No valid slot found for item.")
return false # no space
# If item is powerup (11-14), we don't need a slot.
var is_powerup = (item >= 11 and item <= 14)
var target_slot = -1
if not is_powerup:
target_slot = find_best_goal_slot_for_item(item)
if target_slot == -1:
print("Player: No valid slot found for item.")
return false # no space
if not player.is_multiplayer_authority():
return false
@@ -64,19 +67,22 @@ func grab_item(grid_position: Vector2i) -> bool:
# Apply changes locally first, server will validate/sync
enhanced_gridmap.set_cell_item(cell, -1) # Remove item visually immediately
# Handle Power-Up / Holo Tiles
# Holo Matrix: 11->7 (Heart), 12->8 (Diamond), 13->9 (Star), 14->10 (Coin)
# === Power-Up Consumption (Instant Unlock) ===
# IDs 11-14 are Ability Power-Ups. They are consumed on pickup, not placed on board.
if item >= 11 and item <= 14:
item = item - 4 # Convert to normal tile ID
# Check if it's a power up tile (7-10)
if item >= 7 and item <= 10:
var special_tiles_manager = player.get_node_or_null("SpecialTilesManager")
if special_tiles_manager:
# Add to inventory
special_tiles_manager.add_powerup_from_item(item)
# Animation for powerup?
# ...
# Skip adding to playerboard. Just consume.
else:
# Normal Tile: Add to playerboard
player.playerboard[target_slot] = item
player.playerboard[target_slot] = item # Add to playerboard immediately
# Update UI immediately for responsiveness
# Update UI immediately for responsiveness
var main = player.get_tree().get_root().get_node_or_null("Main")
@@ -137,11 +143,14 @@ func _execute_grab(grid_pos: Vector2i, cell: Vector3i, item_id: int):
return false
# 2. Server-side Auto-Arrange
var target_slot = find_best_goal_slot_for_item(item_id)
if target_slot == -1:
print("Server: Player has no valid slot for item.")
_force_sync_to_client(cell, server_item)
return false
var is_powerup = (item_id >= 11 and item_id <= 14)
var target_slot = -1
if not is_powerup:
target_slot = find_best_goal_slot_for_item(item_id)
if target_slot == -1:
print("Server: Player has no valid slot for item.")
_force_sync_to_client(cell, server_item)
return false
# 3. Server Executes the Action
@@ -149,14 +158,22 @@ func _execute_grab(grid_pos: Vector2i, cell: Vector3i, item_id: int):
main.rpc("sync_grid_item", cell.x, cell.y, cell.z, -1)
# 3b. Update playerboard state (on this server-side instance)
player.playerboard[target_slot] = item_id
if is_powerup:
var special_tiles_manager = player.get_node_or_null("SpecialTilesManager")
if special_tiles_manager:
special_tiles_manager.add_powerup_from_item(item_id)
# Do not add to playerboard
else:
player.playerboard[target_slot] = item_id
# 3c. Broadcast the new playerboard state to all clients
var peer_id = player.name.to_int()
main.rpc("sync_playerboard", peer_id, player.playerboard)
# 3d. Check if goal is completed (SERVER-SIDE - this triggers goal regeneration for clients!)
_check_goal_completion()
# Logic only runs if board changed, but theoretically powerup pickup shouldn't trigger goal
if not is_powerup:
_check_goal_completion()
# 3e. Consume action points
player.has_performed_action = true