feat: Add PlayerboardManager, SpecialTilesManager, PowerupInventoryUI, and new touch control/power tile assets.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user