Improve gridmap item placement and UI logic

Enhanced the auto_put_item logic to better identify and place non-goal or excess tiles from the playerboard onto the grid. Updated gridmap and dock scripts for improved cell option handling and UI consistency. Adjusted mesh library item order and main scene cell data for better alignment. Expanded spawn and finish locations for player logic.
This commit is contained in:
2025-10-28 14:05:50 +08:00
parent f9f7d34f80
commit 65be1fcc63
5 changed files with 96 additions and 77 deletions
+5 -4
View File
@@ -638,12 +638,13 @@ func _update_cell_option_buttons():
set_cell_item(position, 0) set_cell_item(position, 0)
func _set(property, value): func _set(property, value):
if property == "mesh_library": if property.begins_with("data/cells") and Engine.is_editor_hint():
mesh_library = value call_deferred("_emit_grid_updated")
_on_mesh_library_changed()
return true
return false return false
func _emit_grid_updated():
emit_signal("grid_updated")
# Toggle diagonal movement # Toggle diagonal movement
func set_diagonal_movement(enable: bool): func set_diagonal_movement(enable: bool):
diagonal_movement = enable diagonal_movement = enable
@@ -121,6 +121,7 @@ func add_custom_item_state(name: String, id: int):
# #
#item_states_container.add_child(container) #item_states_container.add_child(container)
func add_item_state_ui(item_state: CustomItemState): func add_item_state_ui(item_state: CustomItemState):
var container = HBoxContainer.new() var container = HBoxContainer.new()
@@ -295,10 +296,14 @@ func _update_grid_ui():
# Ensure the selected item in the OptionButton corresponds to the current cell item # Ensure the selected item in the OptionButton corresponds to the current cell item
var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, current_floor, z)) var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, current_floor, z))
if cell_item != -1 and cell_item < option.get_item_count(): if cell_item == -1:
option.select(cell_item) option.select(0) # "Empty"
else: else:
option.select(0) # Select the first item if the cell is empty var item_index = cell_item + 1 # because "Empty" is index 0
if item_index < option.get_item_count():
option.select(item_index)
else:
option.select(0)
option.item_selected.connect(_on_cell_item_selected.bind(option)) option.item_selected.connect(_on_cell_item_selected.bind(option))
option.size_flags_horizontal = Control.SIZE_EXPAND_FILL option.size_flags_horizontal = Control.SIZE_EXPAND_FILL
@@ -324,7 +329,9 @@ func _update_grid_ui():
cell_container.add_child(rotation_option) cell_container.add_child(rotation_option)
row_container.add_child(cell_container) row_container.add_child(cell_container)
cell_options.append(option) cell_options.append(option)
enhanced_gridmap._update_cell_option_buttons()
# enhanced_gridmap._update_cell_option_buttons()
func _update_astar_ui(): func _update_astar_ui():
start_x_spin.max_value = enhanced_gridmap.columns - 1 start_x_spin.max_value = enhanced_gridmap.columns - 1
@@ -456,7 +463,7 @@ func _on_non_walkable_item_changed(value):
func _on_grid_updated(): func _on_grid_updated():
update_ui() update_ui()
enhanced_gridmap._update_cell_option_buttons() # enhanced_gridmap._update_cell_option_buttons()
func _on_cell_rotation_changed(index: int, option: OptionButton): func _on_cell_rotation_changed(index: int, option: OptionButton):
var position = option.get_meta("grid_position") var position = option.get_meta("grid_position")
@@ -51,22 +51,21 @@ item/5/mesh_cast_shadow = 1
item/5/shapes = [] item/5/shapes = []
item/5/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/5/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/5/navigation_layers = 1 item/5/navigation_layers = 1
item/6/name = "tile_coin" item/6/name = "empty"
item/6/mesh = ExtResource("4_76xkl")
item/6/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/6/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/6/mesh_cast_shadow = 1 item/6/mesh_cast_shadow = 1
item/6/shapes = [] item/6/shapes = []
item/6/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/6/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/6/navigation_layers = 1 item/6/navigation_layers = 1
item/7/name = "tile_diamond" item/7/name = "tile_heart"
item/7/mesh = ExtResource("5_j2mx0") item/7/mesh = ExtResource("6_ptqbt")
item/7/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/7/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/7/mesh_cast_shadow = 1 item/7/mesh_cast_shadow = 1
item/7/shapes = [] item/7/shapes = []
item/7/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/7/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/7/navigation_layers = 1 item/7/navigation_layers = 1
item/8/name = "tile_heart" item/8/name = "tile_diamond"
item/8/mesh = ExtResource("6_ptqbt") item/8/mesh = ExtResource("5_j2mx0")
item/8/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/8/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/8/mesh_cast_shadow = 1 item/8/mesh_cast_shadow = 1
item/8/shapes = [] item/8/shapes = []
@@ -79,3 +78,10 @@ item/9/mesh_cast_shadow = 1
item/9/shapes = [] item/9/shapes = []
item/9/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/9/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/9/navigation_layers = 1 item/9/navigation_layers = 1
item/10/name = "tile_coin"
item/10/mesh = ExtResource("4_76xkl")
item/10/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/10/mesh_cast_shadow = 1
item/10/shapes = []
item/10/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
item/10/navigation_layers = 1
+2 -1
View File
File diff suppressed because one or more lines are too long
+65 -61
View File
@@ -32,7 +32,15 @@ var spawn_locations = [
Vector2i(0, 2), # (0,1,2) Vector2i(0, 2), # (0,1,2)
Vector2i(0, 3), # (0,1,3) Vector2i(0, 3), # (0,1,3)
Vector2i(0, 4), # (0,1,4) Vector2i(0, 4), # (0,1,4)
Vector2i(0, 5) # (0,1,5) Vector2i(0, 5), # (0,1,5)
Vector2i(0, 6),
Vector2i(0, 7),
Vector2i(0, 8),
Vector2i(0, 9),
Vector2i(0, 10),
Vector2i(0, 11),
Vector2i(0, 12),
Vector2i(0, 13)
] ]
# Add these as class variables at the top of the file # Add these as class variables at the top of the file
@@ -42,7 +50,15 @@ var finish_locations = [
Vector2i(13, 2), # (13,0,2) Vector2i(13, 2), # (13,0,2)
Vector2i(13, 3), # (13,0,3) Vector2i(13, 3), # (13,0,3)
Vector2i(13, 4), # (13,0,4) Vector2i(13, 4), # (13,0,4)
Vector2i(13, 5) # (13,0,5) Vector2i(13, 5), # (13,0,5)
Vector2i(13, 6),
Vector2i(13, 7),
Vector2i(13, 8),
Vector2i(13, 9),
Vector2i(13, 10),
Vector2i(13, 11),
Vector2i(13, 12),
Vector2i(13, 13)
] ]
var spawn_point_selected = false var spawn_point_selected = false
@@ -184,8 +200,6 @@ func _ready():
if is_multiplayer_authority(): if is_multiplayer_authority():
rpc("sync_position", current_position) rpc("sync_position", current_position)
# Add function to check if position is at finish line # Add function to check if position is at finish line
func is_at_finish_line() -> bool: func is_at_finish_line() -> bool:
return current_position in finish_locations return current_position in finish_locations
@@ -1035,11 +1049,10 @@ func auto_put_item() -> bool:
# Step 1: Find empty adjacent (or current) grid cells # Step 1: Find empty adjacent (or current) grid cells
var valid_put_positions = [] var valid_put_positions = []
# Check current position
var current_cell_3d = Vector3i(current_position.x, 1, current_position.y) var current_cell_3d = Vector3i(current_position.x, 1, current_position.y)
if enhanced_gridmap.get_cell_item(current_cell_3d) == -1: if enhanced_gridmap.get_cell_item(current_cell_3d) == -1:
valid_put_positions.append(current_position) valid_put_positions.append(current_position)
# Check neighbors
var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) var neighbors = enhanced_gridmap.get_neighbors(current_position, 0)
for neighbor in neighbors: for neighbor in neighbors:
if neighbor.is_walkable: if neighbor.is_walkable:
@@ -1051,18 +1064,60 @@ func auto_put_item() -> bool:
if valid_put_positions.is_empty(): if valid_put_positions.is_empty():
return false return false
# Step 2: Find a playerboard tile that matches any goal # Step 2: Find a tile that should NOT be on the board
var put_slot = -1 var put_slot = -1
# Count how many times each goal item appears in central 3x3
var goal_counts = {}
for i in range(3):
for j in range(3):
var g = goals[i * 3 + j]
if g != -1:
goal_counts[g] = goal_counts.get(g, 0) + 1
# Now scan playerboard
for i in range(playerboard.size()): for i in range(playerboard.size()):
if playerboard[i] in goals: var item = playerboard[i]
if item == -1:
continue
# Case 1: Item is not in goals at all → definitely junk
if not item in goals:
put_slot = i put_slot = i
break break
# Case 2: Item is in goals, but we already have enough in correct spots
var current_count = 0
for r in range(1, 4): # central rows 1-3 (5x5 board)
for c in range(1, 4): # central cols 1-3
var idx = r * 5 + c
if playerboard[idx] == item:
current_count += 1
# If we already have all needed copies in central area, this is extra
if current_count >= goal_counts.get(item, 0):
put_slot = i
break
# If no junk found, fall back to any non-goal-matching tile outside center
if put_slot == -1: if put_slot == -1:
return false for i in range(playerboard.size()):
var item = playerboard[i]
if item == -1:
continue
var row = i / 5
var col = i % 5
# If it's outside the central 3x3, it shouldn't be there
if row < 1 or row > 3 or col < 1 or col > 3:
if not item in goals or playerboard[i] != goals[(row - 1) * 3 + (col - 1)]:
put_slot = i
break
if put_slot == -1:
return false # Nothing suitable to put
# Step 3: Perform the put # Step 3: Perform the put
var target_pos = valid_put_positions[0] # pick first valid var target_pos = valid_put_positions[0]
var item = playerboard[put_slot] var item = playerboard[put_slot]
var cell = Vector3i(target_pos.x, 1, target_pos.y) var cell = Vector3i(target_pos.x, 1, target_pos.y)
@@ -1079,57 +1134,6 @@ func auto_put_item() -> bool:
return true return true
# Disabled logic, due the auto put
#func put_item(grid_position: Vector2i = current_position) -> bool:
#if not enhanced_gridmap or action_points <= 0 or selected_playerboard_slot == -1:
#return false
#
#var cell = Vector3i(grid_position.x, 1, grid_position.y)
#if enhanced_gridmap.get_cell_item(cell) != -1:
#return false
#
## Check if position is adjacent or current position
#if grid_position != current_position:
#var is_adjacent = false
#var neighbors = enhanced_gridmap.get_neighbors(current_position, 0)
#for neighbor in neighbors:
#if neighbor.position == grid_position:
#is_adjacent = true
#break
#if not is_adjacent:
#return false
#
## Get the item to place first
#var item = playerboard[selected_playerboard_slot]
#
## For clients, we need to RPC to the server first, then let the server RPC back
#if is_multiplayer_authority() and not multiplayer.is_server():
## Client requests server to perform the put operation
#rpc_id(1, "request_server_put", grid_position, selected_playerboard_slot, cell.x, cell.y, cell.z, item)
#
## We'll return true and let the server handle the actual operation
## The server will RPC back to update our state if successful
#return true
#elif is_multiplayer_authority() and multiplayer.is_server():
## Server directly implements the change
#rpc("sync_grid_item", cell.x, cell.y, cell.z, item)
#playerboard[selected_playerboard_slot] = -1
#rpc("sync_playerboard", playerboard)
#
#has_performed_action = true
#consume_action_points(1)
#if not is_bot == true:
#clear_highlights()
#clear_playerboard_highlights()
#selected_playerboard_slot = -1
#
#var main = get_tree().get_root().get_node_or_null("Main")
#if main:
#main.set_action_state(main.ActionState.NONE)
#_after_action_completed()
#return true
#
#return false
@rpc("any_peer", "reliable") @rpc("any_peer", "reliable")
func request_server_put(grid_position: Vector2i, slot_index: int, x: int, y: int, z: int, item: int): func request_server_put(grid_position: Vector2i, slot_index: int, x: int, y: int, z: int, item: int):