diff --git a/addons/enhanced_gridmap/enhanced_gridmap.gd b/addons/enhanced_gridmap/enhanced_gridmap.gd index e0d6ba5..0d88762 100644 --- a/addons/enhanced_gridmap/enhanced_gridmap.gd +++ b/addons/enhanced_gridmap/enhanced_gridmap.gd @@ -266,7 +266,7 @@ func randomize_floor_custom(randomize_states: Array, floor_index: int): else: set_cell_item(cell_pos, normal_items[0], current_orientation) -# Improved neighbor checking system + #func get_neighbors(current_pos: Vector2i, floor_index: int) -> Array[NeighborInfo]: #var neighbors: Array[NeighborInfo] = [] # @@ -288,29 +288,36 @@ func randomize_floor_custom(randomize_states: Array, floor_index: int): #if is_position_valid(neighbor_pos): #var is_walkable = is_cell_walkable(neighbor_pos, floor_index) # + ## Check for obstacles - specifically for orthogonal movement + #if not is_diagonal_direction(dir) and is_blocked_by_obstacle(current_pos, neighbor_pos, 3): + #is_walkable = false + # + ## Special handling for diagonal movement #if is_diagonal_direction(dir): #var adjacent1: Vector2i #var adjacent2: Vector2i # #match dir: #Direction.NORTHWEST: - #adjacent1 = current_pos + Vector2i(-1, 0) - #adjacent2 = current_pos + Vector2i(0, -1) + #adjacent1 = current_pos + Vector2i(-1, 0) # West + #adjacent2 = current_pos + Vector2i(0, -1) # North #Direction.NORTHEAST: - #adjacent1 = current_pos + Vector2i(1, 0) - #adjacent2 = current_pos + Vector2i(0, -1) + #adjacent1 = current_pos + Vector2i(1, 0) # East + #adjacent2 = current_pos + Vector2i(0, -1) # North #Direction.SOUTHWEST: - #adjacent1 = current_pos + Vector2i(-1, 0) - #adjacent2 = current_pos + Vector2i(0, 1) + #adjacent1 = current_pos + Vector2i(-1, 0) # West + #adjacent2 = current_pos + Vector2i(0, 1) # South #Direction.SOUTHEAST: - #adjacent1 = current_pos + Vector2i(1, 0) - #adjacent2 = current_pos + Vector2i(0, 1) + #adjacent1 = current_pos + Vector2i(1, 0) # East + #adjacent2 = current_pos + Vector2i(0, 1) # South # + ## For diagonal movement, both adjacent cells must be walkable + ## AND the movements to those adjacent cells must not be blocked #is_walkable = is_walkable and \ - #is_position_valid(adjacent1) and is_cell_walkable(adjacent1, floor_index) and \ - #is_position_valid(adjacent2) and is_cell_walkable(adjacent2, floor_index) and \ - #not is_blocked_by_obstacle(current_pos, adjacent1, floor_index) and \ - #not is_blocked_by_obstacle(current_pos, adjacent2, floor_index) + #is_position_valid(adjacent1) and is_cell_walkable(adjacent1, floor_index) and \ + #is_position_valid(adjacent2) and is_cell_walkable(adjacent2, floor_index) and \ + #not is_blocked_by_obstacle(current_pos, adjacent1, 3) and \ + #not is_blocked_by_obstacle(current_pos, adjacent2, 3) # #if diagonal_movement or not is_diagonal_direction(dir): #neighbors.append(NeighborInfo.new(neighbor_pos, dir, is_walkable)) @@ -320,17 +327,21 @@ func randomize_floor_custom(randomize_states: Array, floor_index: int): func get_neighbors(current_pos: Vector2i, floor_index: int) -> Array[NeighborInfo]: var neighbors: Array[NeighborInfo] = [] + # Four orthogonal directions var directions = { - Direction.NORTHWEST: Vector2i(-1, -1), Direction.NORTH: Vector2i(0, -1), - Direction.NORTHEAST: Vector2i(1, -1), - Direction.WEST: Vector2i(-1, 0), Direction.EAST: Vector2i(1, 0), - Direction.SOUTHWEST: Vector2i(-1, 1), Direction.SOUTH: Vector2i(0, 1), - Direction.SOUTHEAST: Vector2i(1, 1) + Direction.WEST: Vector2i(-1, 0) } + # Add diagonal directions if enabled + if diagonal_movement: + directions[Direction.NORTHWEST] = Vector2i(-1, -1) + directions[Direction.NORTHEAST] = Vector2i(1, -1) + directions[Direction.SOUTHWEST] = Vector2i(-1, 1) + directions[Direction.SOUTHEAST] = Vector2i(1, 1) + for dir in directions: var offset = directions[dir] var neighbor_pos = current_pos + offset @@ -338,38 +349,22 @@ func get_neighbors(current_pos: Vector2i, floor_index: int) -> Array[NeighborInf if is_position_valid(neighbor_pos): var is_walkable = is_cell_walkable(neighbor_pos, floor_index) - # Check for obstacles - specifically for orthogonal movement - if not is_diagonal_direction(dir) and is_blocked_by_obstacle(current_pos, neighbor_pos, 3): + # Check if movement to this neighbor is blocked by obstacles + if not is_diagonal_direction(dir) and is_movement_blocked(current_pos, neighbor_pos, floor_index): is_walkable = false - # Special handling for diagonal movement if is_diagonal_direction(dir): - var adjacent1: Vector2i - var adjacent2: Vector2i + # For diagonal movement, check if both orthogonal paths are blocked + var mid1 = Vector2i(neighbor_pos.x, current_pos.y) + var mid2 = Vector2i(current_pos.x, neighbor_pos.y) - match dir: - Direction.NORTHWEST: - adjacent1 = current_pos + Vector2i(-1, 0) # West - adjacent2 = current_pos + Vector2i(0, -1) # North - Direction.NORTHEAST: - adjacent1 = current_pos + Vector2i(1, 0) # East - adjacent2 = current_pos + Vector2i(0, -1) # North - Direction.SOUTHWEST: - adjacent1 = current_pos + Vector2i(-1, 0) # West - adjacent2 = current_pos + Vector2i(0, 1) # South - Direction.SOUTHEAST: - adjacent1 = current_pos + Vector2i(1, 0) # East - adjacent2 = current_pos + Vector2i(0, 1) # South + var path1_blocked = is_movement_blocked(current_pos, mid1, floor_index) + var path2_blocked = is_movement_blocked(current_pos, mid2, floor_index) - # For diagonal movement, both adjacent cells must be walkable - # AND the movements to those adjacent cells must not be blocked - is_walkable = is_walkable and \ - is_position_valid(adjacent1) and is_cell_walkable(adjacent1, floor_index) and \ - is_position_valid(adjacent2) and is_cell_walkable(adjacent2, floor_index) and \ - not is_blocked_by_obstacle(current_pos, adjacent1, 3) and \ - not is_blocked_by_obstacle(current_pos, adjacent2, 3) + if path1_blocked and path2_blocked: + is_walkable = false - if diagonal_movement or not is_diagonal_direction(dir): + if is_walkable: neighbors.append(NeighborInfo.new(neighbor_pos, dir, is_walkable)) return neighbors @@ -490,6 +485,99 @@ func update_grid_data(): grid_data.append(floor_data) emit_signal("grid_updated") +# Check the obstacle on a cell +func has_obstacle_at(pos: Vector3i) -> bool: + var item = get_cell_item(pos) + return item in obstacle_items + +# Get orientation ( rotation ) +func get_cell_orientation(pos: Vector3i) -> int: + return get_cell_item_orientation(pos) + +# Get obstacle direction +# Get the direction of an obstacle at a specific position +func get_obstacle_direction(pos: Vector3i) -> Direction: + if obstacle_directions.has(pos): + return obstacle_directions[pos] + return Direction.CENTER + +#func is_movement_blocked(from_pos: Vector2i, to_pos: Vector2i, floor_index: int = 3) -> bool: + ## Must be adjacent cells + #if abs(from_pos.x - to_pos.x) + abs(from_pos.y - to_pos.y) != 1: + #return false + # + ## Determine which direction we're moving + #var direction: Direction + # + #if to_pos.y < from_pos.y: # Moving NORTH + #direction = Direction.NORTH + #elif to_pos.x > from_pos.x: # Moving EAST + #direction = Direction.EAST + #elif to_pos.y > from_pos.y: # Moving SOUTH + #direction = Direction.SOUTH + #elif to_pos.x < from_pos.x: # Moving WEST + #direction = Direction.WEST + # + ## Check if the current cell has an obstacle blocking the exit + #var from_obstacle_pos = Vector3i(from_pos.x, floor_index, from_pos.y) + #if has_obstacle_at(from_obstacle_pos): + #var obs_dir = get_obstacle_direction(from_obstacle_pos) + #if obs_dir == direction: # Obstacle blocks exit in this direction + #return true + # + ## Check if the destination cell has an obstacle blocking the entrance + #var to_obstacle_pos = Vector3i(to_pos.x, floor_index, to_pos.y) + #if has_obstacle_at(to_obstacle_pos): + #var opposite_dir: Direction + # + ## Calculate the opposite direction + #match direction: + #Direction.NORTH: opposite_dir = Direction.SOUTH + #Direction.EAST: opposite_dir = Direction.WEST + #Direction.SOUTH: opposite_dir = Direction.NORTH + #Direction.WEST: opposite_dir = Direction.EAST + # + #var obs_dir = get_obstacle_direction(to_obstacle_pos) + #if obs_dir == opposite_dir: # Obstacle blocks entrance from this direction + #return true + # + #return false + +func is_movement_blocked(from_pos: Vector2i, to_pos: Vector2i, floor_index: int = 3) -> bool: + # Must be adjacent cells + if abs(from_pos.x - to_pos.x) + abs(from_pos.y - to_pos.y) != 1: + return false + + # Determine movement direction + var direction: int + + if to_pos.y < from_pos.y: # Moving NORTH + direction = 0 # North + elif to_pos.x > from_pos.x: # Moving EAST + direction = 1 # East + elif to_pos.y > from_pos.y: # Moving SOUTH + direction = 2 # South + elif to_pos.x < from_pos.x: # Moving WEST + direction = 3 # West + + # Check if the current cell has an obstacle blocking the exit + var from_obstacle_pos = Vector3i(from_pos.x, floor_index, from_pos.y) + if has_obstacle_at(from_obstacle_pos): + var orientation = get_cell_orientation(from_obstacle_pos) + if orientation == direction: # Obstacle blocks exit in this direction + return true + + # Check if the destination cell has an obstacle blocking the entrance + var to_obstacle_pos = Vector3i(to_pos.x, floor_index, to_pos.y) + if has_obstacle_at(to_obstacle_pos): + var orientation = get_cell_orientation(to_obstacle_pos) + var opposite_dir = (direction + 2) % 4 # Opposite direction (0→2, 1→3, 2→0, 3→1) + + if orientation == opposite_dir: # Obstacle blocks entrance from this direction + return true + + return false + # Cell rotation handling func get_cell_rotation(position: Vector3i) -> int: return get_cell_item_orientation(position) @@ -586,122 +674,164 @@ func set_diagonal_movement(enable: bool): # #return false +#func is_blocked_by_obstacle(from_pos: Vector2i, to_pos: Vector2i, floor_index: int = 3) -> bool: + ## Determine movement direction (without using normalized for Vector2i) + #var diff_x = to_pos.x - from_pos.x + #var diff_y = to_pos.y - from_pos.y + # + ## Convert to direction based on sign + #var dir_x = 0 + #var dir_y = 0 + #if diff_x != 0: dir_x = 1 if diff_x > 0 else -1 + #if diff_y != 0: dir_y = 1 if diff_y > 0 else -1 + # + ## Check for obstacles at both cells + #var from_obstacle = get_cell_item(Vector3i(from_pos.x, floor_index, from_pos.y)) + #var to_obstacle = get_cell_item(Vector3i(to_pos.x, floor_index, to_pos.y)) + # + ## Check obstacle at starting position + #if from_obstacle in obstacle_items: + #var from_pos_3d = Vector3i(from_pos.x, floor_index, from_pos.y) + #var from_dir = Direction.CENTER + # + ## Use safe dictionary access + #if obstacle_directions.has(from_pos_3d): + #from_dir = obstacle_directions[from_pos_3d] + # + ## Block movement based on obstacle direction + #match from_dir: + #Direction.NORTH: # Blocks south movement + #if dir_y > 0: return true + #Direction.EAST: # Blocks west movement + #if dir_x < 0: return true + #Direction.SOUTH: # Blocks north movement + #if dir_y < 0: return true + #Direction.WEST: # Blocks east movement + #if dir_x > 0: return true + # + ## Check obstacle at destination position + #if to_obstacle in obstacle_items: + #var to_pos_3d = Vector3i(to_pos.x, floor_index, to_pos.y) + #var to_dir = Direction.CENTER + # + ## Use safe dictionary access + #if obstacle_directions.has(to_pos_3d): + #to_dir = obstacle_directions[to_pos_3d] + # + ## Block movement based on obstacle direction (from opposite side) + #match to_dir: + #Direction.NORTH: # Blocks south movement (coming from north) + #if dir_y < 0: return true + #Direction.EAST: # Blocks west movement (coming from east) + #if dir_x > 0: return true + #Direction.SOUTH: # Blocks north movement (coming from south) + #if dir_y > 0: return true + #Direction.WEST: # Blocks east movement (coming from west) + #if dir_x < 0: return true + # + ## Check intermediate cell for vertical/horizontal movement + #if from_pos.x != to_pos.x and from_pos.y == to_pos.y: # Horizontal movement + #var x_step = 1 if to_pos.x > from_pos.x else -1 + #var intermediate_x = from_pos.x + x_step + #while intermediate_x != to_pos.x: + #var inter_obstacle = get_cell_item(Vector3i(intermediate_x, floor_index, from_pos.y)) + #if inter_obstacle in obstacle_items: + #var inter_pos_3d = Vector3i(intermediate_x, floor_index, from_pos.y) + #var inter_dir = Direction.CENTER + # + ## Use safe dictionary access + #if obstacle_directions.has(inter_pos_3d): + #inter_dir = obstacle_directions[inter_pos_3d] + # + #if inter_dir == Direction.NORTH or inter_dir == Direction.SOUTH: + #return true + #intermediate_x += x_step + #elif from_pos.x == to_pos.x and from_pos.y != to_pos.y: # Vertical movement + #var y_step = 1 if to_pos.y > from_pos.y else -1 + #var intermediate_y = from_pos.y + y_step + #while intermediate_y != to_pos.y: + #var inter_obstacle = get_cell_item(Vector3i(from_pos.x, floor_index, intermediate_y)) + #if inter_obstacle in obstacle_items: + #var inter_pos_3d = Vector3i(from_pos.x, floor_index, intermediate_y) + #var inter_dir = Direction.CENTER + # + ## Use safe dictionary access + #if obstacle_directions.has(inter_pos_3d): + #inter_dir = obstacle_directions[inter_pos_3d] + # + #if inter_dir == Direction.EAST or inter_dir == Direction.WEST: + #return true + #intermediate_y += y_step + # + ## If none of the above conditions triggered, movement is allowed + #return false + +# Updated is_blocked_by_obstacle to check for each step in the path func is_blocked_by_obstacle(from_pos: Vector2i, to_pos: Vector2i, floor_index: int = 3) -> bool: - # Determine movement direction (without using normalized for Vector2i) - var diff_x = to_pos.x - from_pos.x - var diff_y = to_pos.y - from_pos.y - - # Convert to direction based on sign - var dir_x = 0 - var dir_y = 0 - if diff_x != 0: dir_x = 1 if diff_x > 0 else -1 - if diff_y != 0: dir_y = 1 if diff_y > 0 else -1 - - # Check for obstacles at both cells - var from_obstacle = get_cell_item(Vector3i(from_pos.x, floor_index, from_pos.y)) - var to_obstacle = get_cell_item(Vector3i(to_pos.x, floor_index, to_pos.y)) - - # Check obstacle at starting position - if from_obstacle in obstacle_items: - var from_pos_3d = Vector3i(from_pos.x, floor_index, from_pos.y) - var from_dir = Direction.CENTER + # For orthogonal movement (up, down, left, right) + if from_pos.x == to_pos.x or from_pos.y == to_pos.y: + # Check each step along the path + var dx = sign(to_pos.x - from_pos.x) + var dy = sign(to_pos.y - from_pos.y) - # Use safe dictionary access - if obstacle_directions.has(from_pos_3d): - from_dir = obstacle_directions[from_pos_3d] + var current = from_pos + while current != to_pos: + var next = Vector2i(current.x + dx, current.y + dy) + if is_movement_blocked(current, next, floor_index): + return true + current = next + else: + # For diagonal movement, check if both orthogonal paths are blocked + var mid1 = Vector2i(to_pos.x, from_pos.y) + var mid2 = Vector2i(from_pos.x, to_pos.y) - # Block movement based on obstacle direction - match from_dir: - Direction.NORTH: # Blocks south movement - if dir_y > 0: return true - Direction.EAST: # Blocks west movement - if dir_x < 0: return true - Direction.SOUTH: # Blocks north movement - if dir_y < 0: return true - Direction.WEST: # Blocks east movement - if dir_x > 0: return true - - # Check obstacle at destination position - if to_obstacle in obstacle_items: - var to_pos_3d = Vector3i(to_pos.x, floor_index, to_pos.y) - var to_dir = Direction.CENTER + var path1_blocked = is_blocked_by_obstacle(from_pos, mid1, floor_index) + var path2_blocked = is_blocked_by_obstacle(from_pos, mid2, floor_index) - # Use safe dictionary access - if obstacle_directions.has(to_pos_3d): - to_dir = obstacle_directions[to_pos_3d] - - # Block movement based on obstacle direction (from opposite side) - match to_dir: - Direction.NORTH: # Blocks south movement (coming from north) - if dir_y < 0: return true - Direction.EAST: # Blocks west movement (coming from east) - if dir_x > 0: return true - Direction.SOUTH: # Blocks north movement (coming from south) - if dir_y > 0: return true - Direction.WEST: # Blocks east movement (coming from west) - if dir_x < 0: return true + return path1_blocked and path2_blocked - # Check intermediate cell for vertical/horizontal movement - if from_pos.x != to_pos.x and from_pos.y == to_pos.y: # Horizontal movement - var x_step = 1 if to_pos.x > from_pos.x else -1 - var intermediate_x = from_pos.x + x_step - while intermediate_x != to_pos.x: - var inter_obstacle = get_cell_item(Vector3i(intermediate_x, floor_index, from_pos.y)) - if inter_obstacle in obstacle_items: - var inter_pos_3d = Vector3i(intermediate_x, floor_index, from_pos.y) - var inter_dir = Direction.CENTER - - # Use safe dictionary access - if obstacle_directions.has(inter_pos_3d): - inter_dir = obstacle_directions[inter_pos_3d] - - if inter_dir == Direction.NORTH or inter_dir == Direction.SOUTH: - return true - intermediate_x += x_step - elif from_pos.x == to_pos.x and from_pos.y != to_pos.y: # Vertical movement - var y_step = 1 if to_pos.y > from_pos.y else -1 - var intermediate_y = from_pos.y + y_step - while intermediate_y != to_pos.y: - var inter_obstacle = get_cell_item(Vector3i(from_pos.x, floor_index, intermediate_y)) - if inter_obstacle in obstacle_items: - var inter_pos_3d = Vector3i(from_pos.x, floor_index, intermediate_y) - var inter_dir = Direction.CENTER - - # Use safe dictionary access - if obstacle_directions.has(inter_pos_3d): - inter_dir = obstacle_directions[inter_pos_3d] - - if inter_dir == Direction.EAST or inter_dir == Direction.WEST: - return true - intermediate_y += y_step - - # If none of the above conditions triggered, movement is allowed return false -func place_obstacle(pos: Vector3i, obstacle_item: int, direction: Direction) -> bool: + +#func place_obstacle(pos: Vector3i, obstacle_item: int, direction: Direction) -> bool: + ## Always place on floor 3 + #pos.y = 3 + # + #if get_cell_item(pos) != -1: + #return false # Cell is already occupied + # + #set_cell_item(pos, obstacle_item) + # + ## Store the direction of the obstacle in the dictionary + #obstacle_directions[pos] = direction + # + ## Update the cell's orientation based on direction + #var orientation = 0 + #match direction: + #Direction.NORTH: + #orientation = 0 # Default orientation + #Direction.EAST: + #orientation = 1 # 90 degrees clockwise + #Direction.SOUTH: + #orientation = 2 # 180 degrees + #Direction.WEST: + #orientation = 3 # 270 degrees clockwise + # + #set_cell_item(pos, obstacle_item, orientation) + # + ## Re-initialize A* pathfinding to account for the new obstacle + #initialize_astar() + # + #return true + +func place_obstacle(pos: Vector3i, obstacle_item: int, orientation: int) -> bool: # Always place on floor 3 pos.y = 3 if get_cell_item(pos) != -1: return false # Cell is already occupied - set_cell_item(pos, obstacle_item) - - # Store the direction of the obstacle correctly in the dictionary - obstacle_directions[pos] = direction - - # Update the cell's orientation based on direction - var orientation = 0 - match direction: - Direction.NORTH: - orientation = 0 # Default orientation - Direction.EAST: - orientation = 1 # 90 degrees clockwise - Direction.SOUTH: - orientation = 2 # 180 degrees - Direction.WEST: - orientation = 3 # 270 degrees clockwise - + # Set the obstacle item with the specified orientation set_cell_item(pos, obstacle_item, orientation) # Re-initialize A* pathfinding to account for the new obstacle diff --git a/addons/enhanced_gridmap/meshlibrary/default.tres b/addons/enhanced_gridmap/meshlibrary/default.tres index e26bcde..d4e6d5b 100644 --- a/addons/enhanced_gridmap/meshlibrary/default.tres +++ b/addons/enhanced_gridmap/meshlibrary/default.tres @@ -95,7 +95,7 @@ item/11/navigation_mesh_transform = Transform3D(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, item/11/navigation_layers = 1 item/12/name = "obstacle_block_h" item/12/mesh = ExtResource("4_8v5xv") -item/12/mesh_transform = Transform3D(1.65, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, 0.5) +item/12/mesh_transform = Transform3D(1.65, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.4, 0.5) item/12/mesh_cast_shadow = 1 item/12/shapes = [] item/12/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) diff --git a/addons/enhanced_gridmap/plugin.cfg b/addons/enhanced_gridmap/plugin.cfg index da23124..0a41188 100644 --- a/addons/enhanced_gridmap/plugin.cfg +++ b/addons/enhanced_gridmap/plugin.cfg @@ -3,5 +3,5 @@ name="Enchaced Gridmap" description="" author="Bengski" -version="1.0" +version="1.4" script="plugin.gd" diff --git a/scenes/main.gd b/scenes/main.gd index 451766a..9a51adc 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -68,7 +68,7 @@ enum ActionState { # Obstacle # Add these properties to track the current obstacle direction -var current_obstacle_direction = EnhancedGridMap.Direction.NORTH # Default to NORTH +var current_obstacle_orientation = ObstacleOrientation.NORTH # Default to NORTH var current_obstacle_item = 12 # Starting with first obstacle item (12) enum ObstacleDirection { @@ -76,6 +76,13 @@ enum ObstacleDirection { HORIZONTAL } +enum ObstacleOrientation { + NORTH = 0, + EAST = 1, + SOUTH = 2, + WEST = 3 +} + var current_action_state = ActionState.NONE @onready var action_menu = $ActionMenu @@ -223,46 +230,92 @@ func set_action_state(new_state): local_player_character.highlight_valid_obstacle_cells() # Update the place_obstacle function for floor 3 +#func place_obstacle(grid_position: Vector2i): + #if not local_player_character or local_player_character.action_points < 1: + #return false + # + #var floor_index = 3 # Always place on floor 3 + #var direction = EnhancedGridMap.Direction.BLOCKED_NORTH + # + #match current_obstacle_direction: + #ObstacleDirection.VERTICAL: + #direction = EnhancedGridMap.Direction.BLOCKED_NORTH # Block movement along east-west axis + #ObstacleDirection.HORIZONTAL: + #direction = EnhancedGridMap.Direction.BLOCKED_EAST # Block movement along north-south axis + # + #var success = $EnhancedGridMap.place_obstacle( + #Vector3i(grid_position.x, floor_index, grid_position.y), + #current_obstacle_item, + #direction + #) + # + #if success: + #local_player_character.action_points -= 1 + #local_player_character.clear_highlights() + # + ## Don't exit the obstacle placement mode to allow multiple placements + #local_player_character.highlight_valid_obstacle_cells() + # + ## Exit obstacle placement mode and return to default state + #set_action_state(ActionState.NONE) + # + ## Sync the obstacle with other clients + #if is_multiplayer_authority(): + #rpc("sync_place_obstacle", grid_position.x, grid_position.y, floor_index, current_obstacle_item, direction) + # + #return true + #return false + func place_obstacle(grid_position: Vector2i): if not local_player_character or local_player_character.action_points < 1: return false - - var floor_index = 3 # Always place on floor 3 - var direction = EnhancedGridMap.Direction.BLOCKED_NORTH - match current_obstacle_direction: - ObstacleDirection.VERTICAL: - direction = EnhancedGridMap.Direction.BLOCKED_NORTH # Block movement along east-west axis - ObstacleDirection.HORIZONTAL: - direction = EnhancedGridMap.Direction.BLOCKED_EAST # Block movement along north-south axis + var floor_index = 3 # Always place on floor 3 var success = $EnhancedGridMap.place_obstacle( Vector3i(grid_position.x, floor_index, grid_position.y), current_obstacle_item, - direction + current_obstacle_orientation ) if success: local_player_character.action_points -= 1 - local_player_character.clear_highlights() - # Don't exit the obstacle placement mode to allow multiple placements - local_player_character.highlight_valid_obstacle_cells() + # Clear all highlights after placing obstacle + local_player_character.clear_highlights() # Exit obstacle placement mode and return to default state set_action_state(ActionState.NONE) # Sync the obstacle with other clients if is_multiplayer_authority(): - rpc("sync_place_obstacle", grid_position.x, grid_position.y, floor_index, current_obstacle_item, direction) + rpc("sync_place_obstacle", grid_position.x, grid_position.y, floor_index, current_obstacle_item, current_obstacle_orientation) return true return false +# Updated function to cycle through the four orientations +func cycle_obstacle_orientation(): + var orientations = [ObstacleOrientation.NORTH, ObstacleOrientation.EAST, ObstacleOrientation.SOUTH, ObstacleOrientation.WEST] + var current_index = orientations.find(current_obstacle_orientation) + current_index = (current_index + 1) % orientations.size() + current_obstacle_orientation = orientations[current_index] + + var direction_names = ["North", "East", "South", "West"] + return "Direction: " + direction_names[current_index] + +# Function to cycle through obstacle types +func cycle_obstacle_type(): + var obstacle_types = [12, 13, 14, 15] + var current_index = obstacle_types.find(current_obstacle_item) + current_index = (current_index + 1) % obstacle_types.size() + current_obstacle_item = obstacle_types[current_index] + return "Type: " + str(current_index + 1) + # Update the RPC for obstacle synchronization @rpc("any_peer", "call_local") -func sync_place_obstacle(x: int, y: int, floor_index: int, item_index: int, direction: int): - $EnhancedGridMap.place_obstacle(Vector3i(x, floor_index, y), item_index, direction) +func sync_place_obstacle(x: int, y: int, floor_index: int, item_index: int, orientation: int): + $EnhancedGridMap.place_obstacle(Vector3i(x, floor_index, y), item_index, orientation) func update_button_states(): if not local_player_character or local_player_character.is_in_group("Bots"): @@ -997,13 +1050,13 @@ func setup_obstacle_ui(): obstacle_button.pressed.connect(func(): set_action_state(ActionState.PLACING_OBSTACLE)) $ActionMenu/ActionButtonContainer.add_child(obstacle_button) - # Create the direction cycle button - var direction_button = Button.new() - direction_button.text = "Direction: North" - direction_button.pressed.connect(func(): - direction_button.text = cycle_obstacle_direction() + # Create the rotation/orientation cycle button + var orientation_button = Button.new() + orientation_button.text = "Direction: North" + orientation_button.pressed.connect(func(): + orientation_button.text = cycle_obstacle_orientation() ) - $ActionMenu/ActionButtonContainer.add_child(direction_button) + $ActionMenu/ActionButtonContainer.add_child(orientation_button) # Create the type cycle button var type_button = Button.new() @@ -1013,22 +1066,6 @@ func setup_obstacle_ui(): ) $ActionMenu/ActionButtonContainer.add_child(type_button) -# Add a function to cycle through obstacle types -func cycle_obstacle_type(): - var obstacle_types = [12, 13, 14, 15] - var current_index = obstacle_types.find(current_obstacle_item) - current_index = (current_index + 1) % obstacle_types.size() - current_obstacle_item = obstacle_types[current_index] - return "Type: " + str(current_index + 1) - -func cycle_obstacle_direction(): - var directions = [EnhancedGridMap.Direction.NORTH, EnhancedGridMap.Direction.EAST, EnhancedGridMap.Direction.SOUTH, EnhancedGridMap.Direction.WEST] - var current_index = directions.find(current_obstacle_direction) - current_index = (current_index + 1) % directions.size() - current_obstacle_direction = directions[current_index] - - var direction_names = ["North", "East", "South", "West"] - return "Direction: " + direction_names[current_index] func update_board_slot(board_ui: Node, slot_idx: int, value: int): var slot_node = board_ui.get_node_or_null("Slot%d" % (slot_idx + 1)) diff --git a/scenes/main.tscn b/scenes/main.tscn index 75eb2d4..53108c2 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -39,13 +39,12 @@ turn_based_mode = false mesh_library = ExtResource("1_110wo") cell_size = Vector3(1, 1, 1) data = { -"cells": PackedInt32Array(0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 0, 10, 0, 0, 11, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 1, 10, 0, 1, 11, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 2, 6, 0, 2, 7, 0, 2, 8, 0, 2, 9, 0, 2, 10, 0, 2, 11, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 3, 6, 0, 3, 7, 0, 3, 8, 0, 3, 9, 0, 3, 10, 0, 3, 11, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 4, 6, 0, 4, 7, 0, 4, 8, 0, 4, 9, 0, 4, 10, 0, 4, 11, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 5, 10, 0, 5, 11, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 6, 6, 0, 6, 7, 0, 6, 8, 0, 6, 9, 0, 6, 10, 0, 6, 11, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 7, 6, 0, 7, 7, 0, 7, 8, 0, 7, 9, 0, 7, 10, 0, 7, 11, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 8, 6, 0, 8, 7, 0, 8, 8, 0, 8, 9, 0, 8, 10, 0, 8, 11, 0, 9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 9, 6, 0, 9, 7, 0, 9, 8, 0, 9, 9, 0, 9, 10, 0, 9, 11, 0, 10, 0, 0, 10, 1, 0, 10, 2, 0, 10, 3, 0, 10, 4, 0, 10, 5, 0, 10, 6, 0, 10, 7, 0, 10, 8, 0, 10, 9, 0, 10, 10, 0, 10, 11, 0, 11, 0, 0, 11, 1, 0, 11, 2, 0, 11, 3, 0, 11, 4, 0, 11, 5, 0, 11, 6, 0, 11, 7, 0, 11, 8, 0, 11, 9, 0, 11, 10, 0, 11, 11, 0, 12, 0, 0, 12, 1, 0, 12, 2, 0, 12, 3, 0, 12, 4, 0, 12, 5, 0, 12, 6, 0, 12, 7, 0, 12, 8, 0, 12, 9, 0, 12, 10, 0, 12, 11, 0, 13, 0, 0, 13, 1, 0, 13, 2, 0, 13, 3, 0, 13, 4, 0, 13, 5, 0, 13, 6, 0, 13, 7, 0, 13, 8, 0, 13, 9, 0, 13, 10, 0, 13, 11, 0, 65537, 1, 9, 65537, 2, 9, 65537, 3, 10, 65537, 4, 7, 65537, 5, 10, 65537, 6, 7, 65537, 7, 7, 65537, 8, 8, 65537, 9, 7, 65537, 10, 10, 65537, 11, 8, 65538, 1, 8, 65538, 2, 8, 65538, 3, 10, 65538, 4, 8, 65538, 5, 10, 65538, 6, 8, 65538, 7, 9, 65538, 8, 9, 65538, 9, 7, 65538, 10, 7, 65538, 11, 9, 65539, 0, 8, 65539, 1, 9, 65539, 2, 7, 65539, 3, 10, 65539, 4, 9, 65539, 5, 7, 65539, 6, 8, 65539, 7, 9, 65539, 8, 7, 65539, 9, 7, 65539, 10, 7, 65539, 11, 9, 65540, 0, 9, 65540, 1, 9, 65540, 2, 10, 65540, 3, 8, 65540, 4, 9, 65540, 5, 10, 65540, 6, 7, 65540, 7, 10, 65540, 8, 9, 65540, 9, 10, 65540, 10, 9, 65540, 11, 10, 65541, 0, 8, 65541, 1, 8, 65541, 2, 8, 65541, 3, 10, 65541, 4, 7, 65541, 5, 9, 65541, 6, 8, 65541, 7, 10, 65541, 8, 9, 65541, 9, 8, 65541, 10, 10, 65541, 11, 9, 65542, 0, 7, 65542, 1, 8, 65542, 2, 9, 65542, 3, 10, 65542, 4, 9, 65542, 5, 10, 65542, 6, 10, 65542, 7, 7, 65542, 8, 7, 65542, 9, 10, 65542, 10, 7, 65542, 11, 7, 65543, 0, 9, 65543, 1, 8, 65543, 2, 10, 65543, 3, 7, 65543, 4, 7, 65543, 5, 10, 65543, 6, 9, 65543, 7, 8, 65543, 8, 9, 65543, 9, 7, 65543, 10, 7, 65543, 11, 9, 65544, 0, 7, 65544, 1, 7, 65544, 2, 10, 65544, 3, 10, 65544, 4, 7, 65544, 5, 7, 65544, 6, 9, 65544, 7, 10, 65544, 8, 7, 65544, 9, 7, 65544, 10, 8, 65544, 11, 9, 65545, 0, 9, 65545, 1, 10, 65545, 2, 9, 65545, 3, 9, 65545, 4, 9, 65545, 5, 9, 65545, 6, 9, 65545, 7, 9, 65545, 8, 10, 65545, 9, 7, 65545, 10, 7, 65545, 11, 9, 65546, 0, 8, 65546, 1, 8, 65546, 2, 7, 65546, 3, 10, 65546, 4, 7, 65546, 5, 9, 65546, 6, 9, 65546, 7, 9, 65546, 8, 7, 65546, 9, 9, 65546, 10, 10, 65546, 11, 10, 65547, 0, 10, 65547, 1, 8, 65547, 2, 7, 65547, 3, 8, 65547, 4, 10, 65547, 5, 7, 65547, 6, 10, 65547, 7, 7, 65547, 8, 10, 65547, 9, 8, 65547, 10, 7, 65547, 11, 8, 65548, 0, 7, 65548, 1, 9, 65548, 2, 10, 65548, 3, 9, 65548, 4, 7, 65548, 5, 9, 65548, 6, 8, 65548, 7, 10, 65548, 8, 10, 65548, 9, 8, 65548, 10, 9, 65548, 11, 9, 65538, 0, 10, 65537, 0, 7) +"cells": PackedInt32Array(0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 0, 10, 0, 0, 11, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 1, 10, 0, 1, 11, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 2, 6, 0, 2, 7, 0, 2, 8, 0, 2, 9, 0, 2, 10, 0, 2, 11, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 3, 6, 0, 3, 7, 0, 3, 8, 0, 3, 9, 0, 3, 10, 0, 3, 11, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 4, 6, 0, 4, 7, 0, 4, 8, 0, 4, 9, 0, 4, 10, 0, 4, 11, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 5, 10, 0, 5, 11, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 6, 6, 0, 6, 7, 0, 6, 8, 0, 6, 9, 0, 6, 10, 0, 6, 11, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 7, 6, 0, 7, 7, 0, 7, 8, 0, 7, 9, 0, 7, 10, 0, 7, 11, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 8, 6, 0, 8, 7, 0, 8, 8, 0, 8, 9, 0, 8, 10, 0, 8, 11, 0, 9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 9, 6, 0, 9, 7, 0, 9, 8, 0, 9, 9, 0, 9, 10, 0, 9, 11, 0, 10, 0, 0, 10, 1, 0, 10, 2, 0, 10, 3, 0, 10, 4, 0, 10, 5, 0, 10, 6, 0, 10, 7, 0, 10, 8, 0, 10, 9, 0, 10, 10, 0, 10, 11, 0, 11, 0, 0, 11, 1, 0, 11, 2, 0, 11, 3, 0, 11, 4, 0, 11, 5, 0, 11, 6, 0, 11, 7, 0, 11, 8, 0, 11, 9, 0, 11, 10, 0, 11, 11, 0, 12, 0, 0, 12, 1, 0, 12, 2, 0, 12, 3, 0, 12, 4, 0, 12, 5, 0, 12, 6, 0, 12, 7, 0, 12, 8, 0, 12, 9, 0, 12, 10, 0, 12, 11, 0, 13, 0, 0, 13, 1, 0, 13, 2, 0, 13, 3, 0, 13, 4, 0, 13, 5, 0, 13, 6, 0, 13, 7, 0, 13, 8, 0, 13, 9, 0, 13, 10, 0, 13, 11, 0, 65537, 1, 9, 65537, 2, 9, 65537, 3, 10, 65537, 4, 7, 65537, 5, 10, 65537, 6, 7, 65537, 7, 7, 65537, 8, 8, 65537, 9, 7, 65537, 10, 10, 65537, 11, 8, 65538, 1, 8, 65538, 2, 8, 65538, 3, 10, 65538, 4, 8, 65538, 5, 10, 65538, 6, 8, 65538, 7, 9, 65538, 8, 9, 65538, 9, 7, 65538, 10, 7, 65538, 11, 9, 65539, 0, 8, 65539, 1, 9, 65539, 2, 7, 65539, 3, 10, 65539, 4, 9, 65539, 5, 7, 65539, 6, 8, 65539, 7, 9, 65539, 8, 7, 65539, 9, 7, 65539, 10, 7, 65539, 11, 9, 65540, 0, 9, 65540, 1, 9, 65540, 2, 10, 65540, 3, 8, 65540, 4, 9, 65540, 5, 10, 65540, 6, 7, 65540, 7, 10, 65540, 8, 9, 65540, 9, 10, 65540, 10, 9, 65540, 11, 10, 65541, 0, 8, 65541, 1, 8, 65541, 2, 8, 65541, 3, 10, 65541, 4, 7, 65541, 5, 9, 65541, 6, 8, 65541, 7, 10, 65541, 8, 9, 65541, 9, 8, 65541, 10, 10, 65541, 11, 9, 65542, 0, 7, 65542, 1, 8, 65542, 2, 9, 65542, 3, 10, 65542, 4, 9, 65542, 5, 10, 65542, 6, 10, 65542, 7, 7, 65542, 8, 7, 65542, 9, 10, 65542, 10, 7, 65542, 11, 7, 65543, 0, 9, 65543, 1, 8, 65543, 2, 10, 65543, 3, 7, 65543, 4, 7, 65543, 5, 10, 65543, 6, 9, 65543, 7, 8, 65543, 8, 9, 65543, 9, 7, 65543, 10, 7, 65543, 11, 9, 65544, 0, 7, 65544, 1, 7, 65544, 2, 10, 65544, 3, 10, 65544, 4, 7, 65544, 5, 7, 65544, 6, 9, 65544, 7, 10, 65544, 8, 7, 65544, 9, 7, 65544, 10, 8, 65544, 11, 9, 65545, 0, 9, 65545, 1, 10, 65545, 2, 9, 65545, 3, 9, 65545, 4, 9, 65545, 5, 9, 65545, 6, 9, 65545, 7, 9, 65545, 8, 10, 65545, 9, 7, 65545, 10, 7, 65545, 11, 9, 65546, 0, 8, 65546, 1, 8, 65546, 2, 7, 65546, 3, 10, 65546, 4, 7, 65546, 5, 9, 65546, 6, 9, 65546, 7, 9, 65546, 8, 7, 65546, 9, 9, 65546, 10, 10, 65546, 11, 10, 65547, 0, 10, 65547, 1, 8, 65547, 2, 7, 65547, 3, 8, 65547, 4, 10, 65547, 5, 7, 65547, 6, 10, 65547, 7, 7, 65547, 8, 10, 65547, 9, 8, 65547, 10, 7, 65547, 11, 8, 65548, 0, 7, 65548, 1, 9, 65548, 2, 10, 65548, 3, 9, 65548, 4, 7, 65548, 5, 9, 65548, 6, 8, 65548, 7, 10, 65548, 8, 10, 65548, 9, 8, 65548, 10, 9, 65548, 11, 9, 65538, 0, 10, 65537, 0, 7, 131075, 8, 524300, 131075, 7, 524300) } script = ExtResource("2_hbe1v") columns = 14 rows = 12 obstacle_items = Array[int]([12]) -obstacle_directions = Array[int]([11, 10, 12, 13]) metadata/_editor_floor_ = Vector3(0, 2, 0) [node name="Camera3D" type="Camera3D" parent="."] diff --git a/scenes/player.gd b/scenes/player.gd index f57b3d4..a401aa6 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -851,9 +851,9 @@ func highlight_movement_range(): var cells_to_highlight = [] - # Only highlight cells within movement range that aren't blocked by obstacles - for x in range(enhanced_gridmap.columns): - for z in range(enhanced_gridmap.rows): + # For each position within movement range + for x in range(max(0, current_position.x - movement_range), min(enhanced_gridmap.columns, current_position.x + movement_range + 1)): + for z in range(max(0, current_position.y - movement_range), min(enhanced_gridmap.rows, current_position.y + movement_range + 1)): var test_pos = Vector2i(x, z) # Skip the current position @@ -864,10 +864,26 @@ func highlight_movement_range(): if is_within_movement_range(test_pos): var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) - # Check if cell is walkable and not occupied + # Basic walkability check if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items) and not is_position_occupied(test_pos): - # Most importantly, check if movement is blocked by obstacles - if not enhanced_gridmap.is_blocked_by_obstacle(current_position, test_pos, 3): + # Check if there's a direct path without obstacles + var path_blocked = false + + # For orthogonal movement + if test_pos.x == current_position.x or test_pos.y == current_position.y: + path_blocked = enhanced_gridmap.is_blocked_by_obstacle(current_position, test_pos, 3) + else: + # For diagonal movement, check if both orthogonal paths are blocked + var mid1 = Vector2i(test_pos.x, current_position.y) + var mid2 = Vector2i(current_position.x, test_pos.y) + + var path1_blocked = enhanced_gridmap.is_blocked_by_obstacle(current_position, mid1, 3) + var path2_blocked = enhanced_gridmap.is_blocked_by_obstacle(current_position, mid2, 3) + + # Only completely block if both paths are blocked + path_blocked = path1_blocked and path2_blocked + + if not path_blocked: cells_to_highlight.append(test_pos) highlight_cells_if_authorized(cells_to_highlight)