From 679961aa7774332a845d338bb2ce41976e380f84 Mon Sep 17 00:00:00 2001 From: adtpdn Date: Fri, 21 Mar 2025 11:44:12 +0800 Subject: [PATCH] update obstacles --- addons/enhanced_gridmap/enhanced_gridmap.gd | 369 +++++++------------- addons/enhanced_gridmap/plugin.gd | 3 +- project.godot | 2 +- scenes/main.gd | 57 +-- scenes/main.tscn | 4 +- scenes/player.gd | 215 ++++++++++-- 6 files changed, 323 insertions(+), 327 deletions(-) diff --git a/addons/enhanced_gridmap/enhanced_gridmap.gd b/addons/enhanced_gridmap/enhanced_gridmap.gd index 0d88762..c750291 100644 --- a/addons/enhanced_gridmap/enhanced_gridmap.gd +++ b/addons/enhanced_gridmap/enhanced_gridmap.gd @@ -27,6 +27,9 @@ var path = [] @export var obstacle_items: Array[int] = [12, 13, 14, 15] # Obstacle items in mesh library @export var obstacle_directions: Dictionary = {} # Store direction for each placed obstacle: {Vector3i position: Direction} +# Dictionary to store obstacle information: {cell_pos: orientation} +# orientation: 0=North, 1=East, 2=South, 3=West +var obstacles = {} # Direction and movement systems enum Direction { @@ -501,83 +504,108 @@ func get_obstacle_direction(pos: Vector3i) -> Direction: 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 get_obstacle_orientation(pos: Vector3i) -> int: + return get_cell_item_orientation(pos) func is_movement_blocked(from_pos: Vector2i, to_pos: Vector2i, floor_index: int = 3) -> bool: - # Must be adjacent cells + # Must be adjacent cells for direct blocking check if abs(from_pos.x - to_pos.x) + abs(from_pos.y - to_pos.y) != 1: return false - # Determine movement direction - var direction: int + # Get 3D positions for the cells + var from_pos3d = Vector3i(from_pos.x, floor_index, from_pos.y) + var to_pos3d = Vector3i(to_pos.x, floor_index, to_pos.y) - 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 + # Check if the starting cell has an obstacle + if has_obstacle_at(from_pos3d): + var orientation = get_obstacle_orientation(from_pos3d) + + # Check if the obstacle is blocking the requested movement direction + if from_pos.y > to_pos.y and orientation == 0: # Moving NORTH, obstacle faces NORTH + return true + elif from_pos.x < to_pos.x and orientation == 1: # Moving EAST, obstacle faces EAST + return true + elif from_pos.y < to_pos.y and orientation == 2: # Moving SOUTH, obstacle faces SOUTH + return true + elif from_pos.x > to_pos.x and orientation == 3: # Moving WEST, obstacle faces WEST 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) + # Check if the destination cell has an obstacle blocking entry + if has_obstacle_at(to_pos3d): + var orientation = get_obstacle_orientation(to_pos3d) - if orientation == opposite_dir: # Obstacle blocks entrance from this direction + # Check if the obstacle is blocking entry from the requested direction + if to_pos.y < from_pos.y and orientation == 2: # Coming from SOUTH, obstacle faces SOUTH + return true + elif to_pos.x > from_pos.x and orientation == 3: # Coming from WEST, obstacle faces WEST + return true + elif to_pos.y > from_pos.y and orientation == 0: # Coming from NORTH, obstacle faces NORTH + return true + elif to_pos.x < from_pos.x and orientation == 1: # Coming from EAST, obstacle faces EAST return true return false +# Function to check if a cell is blocked by any obstacles in its vicinity +func is_cell_blocked_by_obstacles(pos: Vector2i, floor_index: int = 3) -> bool: + var pos3d = Vector3i(pos.x, floor_index, pos.y) + + # Check if this cell itself has an obstacle + if has_obstacle_at(pos3d): + return true + + # Check all adjacent cells for obstacles that might block this cell + var adjacent_positions = [ + Vector2i(pos.x, pos.y - 1), # North + Vector2i(pos.x + 1, pos.y), # East + Vector2i(pos.x, pos.y + 1), # South + Vector2i(pos.x - 1, pos.y), # West + ] + + for adj_pos in adjacent_positions: + var adj_pos3d = Vector3i(adj_pos.x, floor_index, adj_pos.y) + + # Check if position is valid + if is_position_valid(adj_pos) and has_obstacle_at(adj_pos3d): + var orientation = get_obstacle_orientation(adj_pos3d) + + # Check if the obstacle is blocking this cell + if adj_pos.y < pos.y and orientation == 0: # Obstacle to NORTH facing NORTH + return true + elif adj_pos.x > pos.x and orientation == 1: # Obstacle to EAST facing EAST + return true + elif adj_pos.y > pos.y and orientation == 2: # Obstacle to SOUTH facing SOUTH + return true + elif adj_pos.x < pos.x and orientation == 3: # Obstacle to WEST facing WEST + return true + + return false + +# Function to get all cells blocked by an obstacle at a specific position +func get_cells_blocked_by_obstacle(obstacle_pos: Vector2i, orientation: int, floor_index: int = 3) -> Array: + var blocked_cells = [] + + # Determine which cells are blocked based on orientation + match orientation: + 0: # NORTH - blocks the row above + for x in range(max(0, obstacle_pos.x - 1), min(columns, obstacle_pos.x + 2)): + blocked_cells.append(Vector2i(x, obstacle_pos.y - 1)) + + 1: # EAST - blocks the column to the right + for y in range(max(0, obstacle_pos.y - 1), min(rows, obstacle_pos.y + 2)): + blocked_cells.append(Vector2i(obstacle_pos.x + 1, y)) + + 2: # SOUTH - blocks the row below + for x in range(max(0, obstacle_pos.x - 1), min(columns, obstacle_pos.x + 2)): + blocked_cells.append(Vector2i(x, obstacle_pos.y + 1)) + + 3: # WEST - blocks the column to the left + for y in range(max(0, obstacle_pos.y - 1), min(rows, obstacle_pos.y + 2)): + blocked_cells.append(Vector2i(obstacle_pos.x - 1, y)) + + # Filter out invalid positions + return blocked_cells.filter(func(pos): return is_position_valid(pos)) + # Cell rotation handling func get_cell_rotation(position: Vector3i) -> int: return get_cell_item_orientation(position) @@ -621,209 +649,45 @@ func set_diagonal_movement(enable: bool): diagonal_movement = enable initialize_astar() -# Add this function to check if a movement is blocked by an obstacle -#func is_blocked_by_obstacle(from_pos: Vector2i, to_pos: Vector2i, floor_index: int = 3) -> bool: - ## Detect movement direction - #var diff_x = to_pos.x - from_pos.x - #var diff_y = to_pos.y - from_pos.y - # - ## Case 1: Moving along X axis (horizontally) - #if diff_y == 0 and diff_x != 0: - ## Check if there's a vertical obstacle blocking horizontal movement - #var min_x = min(from_pos.x, to_pos.x) - #var max_x = max(from_pos.x, to_pos.x) - #for x in range(min_x, max_x + 1): - #var cell_pos = Vector3i(x, floor_index, from_pos.y) - #var cell_index = get_cell_item(cell_pos) - #if cell_index in obstacle_items: - #var obstacle_idx = obstacle_items.find(cell_index) - #if obstacle_idx != -1 and obstacle_idx < obstacle_directions.size(): - #var dir = obstacle_directions[obstacle_idx] - #if dir == Direction.BLOCKED_NORTH or dir == Direction.BLOCKED_SOUTH: - #return true - # - ## Case 2: Moving along Y axis (vertically) - #if diff_x == 0 and diff_y != 0: - ## Check if there's a horizontal obstacle blocking vertical movement - #var min_y = min(from_pos.y, to_pos.y) - #var max_y = max(from_pos.y, to_pos.y) - #for y in range(min_y, max_y + 1): - #var cell_pos = Vector3i(from_pos.x, floor_index, y) - #var cell_index = get_cell_item(cell_pos) - #if cell_index in obstacle_items: - #var obstacle_idx = obstacle_items.find(cell_index) - #if obstacle_idx != -1 and obstacle_idx < obstacle_directions.size(): - #var dir = obstacle_directions[obstacle_idx] - #if dir == Direction.BLOCKED_EAST or dir == Direction.BLOCKED_WEST: - #return true - # - ## Case 3: Diagonal movement - check if both direct paths are blocked - ## This will force the player to take the longer route - #if diff_x != 0 and diff_y != 0: - ## Check if moving horizontally first then vertically would be blocked - #var horiz_first = is_blocked_by_obstacle(from_pos, Vector2i(to_pos.x, from_pos.y), floor_index) - #var vert_second = is_blocked_by_obstacle(Vector2i(to_pos.x, from_pos.y), to_pos, floor_index) - # - ## Check if moving vertically first then horizontally would be blocked - #var vert_first = is_blocked_by_obstacle(from_pos, Vector2i(from_pos.x, to_pos.y), floor_index) - #var horiz_second = is_blocked_by_obstacle(Vector2i(from_pos.x, to_pos.y), to_pos, floor_index) - # - ## If both paths are blocked, then the diagonal movement is blocked - #if (horiz_first or vert_second) and (vert_first or horiz_second): - #return true - # - #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: - # For orthogonal movement (up, down, left, right) + # For direct orthogonal movement (up, down, left, right) + if (from_pos.x == to_pos.x and abs(from_pos.y - to_pos.y) == 1) or (from_pos.y == to_pos.y and abs(from_pos.x - to_pos.x) == 1): + return is_movement_blocked(from_pos, to_pos, floor_index) + + # For diagonal or longer distances, build a path and check each step + var path = [] + + # Simple path planning for orthogonal movement 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) - 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 + path.append([current, next]) current = next else: - # For diagonal movement, check if both orthogonal paths are blocked + # For diagonal movement, check both possible paths + # Path 1: Move horizontally first, then vertically var mid1 = Vector2i(to_pos.x, from_pos.y) + var path1_blocked = is_blocked_by_obstacle(from_pos, mid1, floor_index) or is_blocked_by_obstacle(mid1, to_pos, floor_index) + + # Path 2: Move vertically first, then horizontally var mid2 = Vector2i(from_pos.x, to_pos.y) + var path2_blocked = is_blocked_by_obstacle(from_pos, mid2, floor_index) or is_blocked_by_obstacle(mid2, to_pos, floor_index) - var path1_blocked = is_blocked_by_obstacle(from_pos, mid1, floor_index) - var path2_blocked = is_blocked_by_obstacle(from_pos, mid2, floor_index) - + # Movement is blocked if both paths are blocked return path1_blocked and path2_blocked + # Check each step in the path + for step in path: + if is_movement_blocked(step[0], step[1], floor_index): + return true + return false - -#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 - +# Place an obstacle at the specified position with a specific orientation func place_obstacle(pos: Vector3i, obstacle_item: int, orientation: int) -> bool: # Always place on floor 3 pos.y = 3 @@ -834,6 +698,9 @@ func place_obstacle(pos: Vector3i, obstacle_item: int, orientation: int) -> bool # Set the obstacle item with the specified orientation set_cell_item(pos, obstacle_item, orientation) + # Store the obstacle information + obstacles[pos] = orientation + # Re-initialize A* pathfinding to account for the new obstacle initialize_astar() diff --git a/addons/enhanced_gridmap/plugin.gd b/addons/enhanced_gridmap/plugin.gd index 90b412f..f548b0d 100644 --- a/addons/enhanced_gridmap/plugin.gd +++ b/addons/enhanced_gridmap/plugin.gd @@ -25,4 +25,5 @@ func _get_plugin_name(): func _edit(object): if dock and object is EnhancedGridMap: - dock.set_enhanced_gridmap(object) + if is_instance_valid(dock) and dock.has_method("set_enhanced_gridmap"): + dock.set_enhanced_gridmap(object) diff --git a/project.godot b/project.godot index 0eba99b..92f1c74 100644 --- a/project.godot +++ b/project.godot @@ -30,7 +30,7 @@ window/stretch/mode="viewport" [editor_plugins] -enabled=PackedStringArray("res://addons/beehave/plugin.cfg", "res://addons/enhanced_gridmap/plugin.cfg") +enabled=PackedStringArray("res://addons/enhanced_gridmap/plugin.cfg") [input] diff --git a/scenes/main.gd b/scenes/main.gd index 9a51adc..793c760 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -67,8 +67,8 @@ enum ActionState { } # Obstacle -# Add these properties to track the current obstacle direction -var current_obstacle_orientation = ObstacleOrientation.NORTH # Default to NORTH +# Add these properties to track current obstacle settings +var current_obstacle_orientation = ObstacleOrientation.NORTH var current_obstacle_item = 12 # Starting with first obstacle item (12) enum ObstacleDirection { @@ -77,10 +77,10 @@ enum ObstacleDirection { } enum ObstacleOrientation { - NORTH = 0, - EAST = 1, - SOUTH = 2, - WEST = 3 + NORTH = 0, # Blocks movement to the north (top) + EAST = 1, # Blocks movement to the east (right) + SOUTH = 2, # Blocks movement to the south (bottom) + WEST = 3 # Blocks movement to the west (left) } var current_action_state = ActionState.NONE @@ -229,43 +229,6 @@ func set_action_state(new_state): ActionState.PLACING_OBSTACLE: 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 @@ -294,9 +257,15 @@ func place_obstacle(grid_position: Vector2i): return true return false +# Updated function to cycle through the four orientations # Updated function to cycle through the four orientations func cycle_obstacle_orientation(): - var orientations = [ObstacleOrientation.NORTH, ObstacleOrientation.EAST, ObstacleOrientation.SOUTH, ObstacleOrientation.WEST] + 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] diff --git a/scenes/main.tscn b/scenes/main.tscn index 53108c2..487085f 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -39,13 +39,13 @@ 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, 131075, 8, 524300, 131075, 7, 524300) +"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, 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, 65539, 7, 9) } script = ExtResource("2_hbe1v") columns = 14 rows = 12 obstacle_items = Array[int]([12]) -metadata/_editor_floor_ = Vector3(0, 2, 0) +metadata/_editor_floor_ = Vector3(0, -2, 0) [node name="Camera3D" type="Camera3D" parent="."] transform = Transform3D(1, 0, 0, 0, 0.422618, 0.906308, 0, -0.906308, 0.422618, 7, 26, 17) diff --git a/scenes/player.gd b/scenes/player.gd index a401aa6..b341a65 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -844,50 +844,209 @@ func highlight_cells_if_authorized(cells_to_highlight: Array): enhanced_gridmap.hover_item ) -# Modify highlight functions to use the new authorized highlight method +## Update highlight_movement_range to respect obstacle blocking +#func highlight_movement_range(): + #if not is_multiplayer_authority() or is_bot or is_in_group("Bots"): + #return + # + #clear_highlights() + #var cells_to_highlight = [] + # + ## Get neighboring cells that are directly accessible (not blocked by obstacles) + #var direct_neighbors = [] + #var directions = [ + #Vector2i(0, -1), # North + #Vector2i(1, 0), # East + #Vector2i(0, 1), # South + #Vector2i(-1, 0), # West + #] + # + ## Add diagonal directions if enabled + #if enhanced_gridmap.diagonal_movement: + #directions.append(Vector2i(-1, -1)) # Northwest + #directions.append(Vector2i(1, -1)) # Northeast + #directions.append(Vector2i(-1, 1)) # Southwest + #directions.append(Vector2i(1, 1)) # Southeast + # + ## First, get direct neighbors that aren't blocked + #for dir in directions: + #var neighbor_pos = current_position + dir + # + ## Check if position is valid and walkable + #if enhanced_gridmap.is_position_valid(neighbor_pos) and \ + #enhanced_gridmap.is_cell_walkable(neighbor_pos, 0) and \ + #not is_position_occupied(neighbor_pos): + # + ## Check if movement is blocked by obstacle + #if not enhanced_gridmap.is_movement_blocked(current_position, neighbor_pos, 3): + #direct_neighbors.append(neighbor_pos) + # + ## Now, add all cells that are within movement range + ## and can be reached via the direct neighbors + #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 + #if test_pos == current_position: + #continue + # + ## Check if within movement range + #if is_within_movement_range(test_pos): + #var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + # + ## Basic walkability check + #if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items) and \ + #not is_position_occupied(test_pos): + # + ## Check if we can reach this position through one of our direct neighbors + #var can_reach = false + # + ## Direct neighbors are always reachable + #if test_pos in direct_neighbors: + #can_reach = true + #else: + ## For other cells, check if there's a valid path through direct neighbors + #for neighbor in direct_neighbors: + ## Check if we can move from the neighbor to the target position + ## without being blocked by an obstacle + #if not enhanced_gridmap.is_blocked_by_obstacle(neighbor, test_pos, 3): + #var manhattan_dist = abs(neighbor.x - test_pos.x) + abs(neighbor.y - test_pos.y) + #var remaining_range = movement_range - 1 # -1 for the first step + # + ## Check if the remaining distance is within our movement range + #if manhattan_dist <= remaining_range: + #can_reach = true + #break + # + #if can_reach: + #cells_to_highlight.append(test_pos) + # + #highlight_cells_if_authorized(cells_to_highlight) + +# Update highlight_movement_range to respect the expanded obstacle blocking func highlight_movement_range(): if not is_multiplayer_authority() or is_bot or is_in_group("Bots"): return + clear_highlights() var cells_to_highlight = [] - # 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)): + # First, identify all cells that are blocked by obstacles + var blocked_cells = [] + + # Check all cells for obstacles and get their blocked cells + for x in range(enhanced_gridmap.columns): + for z in range(enhanced_gridmap.rows): + var cell_pos = Vector2i(x, z) + var cell_pos3d = Vector3i(x, 3, z) + + if enhanced_gridmap.has_obstacle_at(cell_pos3d): + var orientation = enhanced_gridmap.get_obstacle_orientation(cell_pos3d) + blocked_cells.append_array(enhanced_gridmap.get_cells_blocked_by_obstacle(cell_pos, orientation, 3)) + + # Now highlight all cells within movement range that aren't blocked + 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 + # Skip current position if test_pos == current_position: continue - + # Check if within movement range if is_within_movement_range(test_pos): - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + # Skip if blocked by obstacle + if test_pos in blocked_cells: + continue - # Basic walkability check - if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items) and not is_position_occupied(test_pos): - # 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) + # Check basic walkability + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + if cell_item == -1 or cell_item in enhanced_gridmap.non_walkable_items or is_position_occupied(test_pos): + continue + + # Check if there's a valid path to this cell + if can_reach_cell(test_pos, blocked_cells): + cells_to_highlight.append(test_pos) highlight_cells_if_authorized(cells_to_highlight) +# Helper function to check if a cell can be reached given the blocked cells +func can_reach_cell(target_pos: Vector2i, blocked_cells: Array) -> bool: + # Simple BFS to find if there's a path + var queue = [current_position] + var visited = {current_position: true} + var steps = {current_position: 0} + + while not queue.is_empty(): + var current = queue.pop_front() + + # If we've found the target, check if it's within movement range + if current == target_pos: + return steps[current] <= movement_range + + # If we've used all movement, don't explore further + if steps[current] >= movement_range: + continue + + # Try all adjacent cells + var directions = [ + Vector2i(0, -1), # North + Vector2i(1, 0), # East + Vector2i(0, 1), # South + Vector2i(-1, 0), # West + ] + + # Add diagonal directions if enabled + if enhanced_gridmap.diagonal_movement: + directions.append(Vector2i(-1, -1)) # Northwest + directions.append(Vector2i(1, -1)) # Northeast + directions.append(Vector2i(-1, 1)) # Southwest + directions.append(Vector2i(1, 1)) # Southeast + + for dir in directions: + var next_pos = current + dir + + # Skip if already visited, blocked, or not valid + if visited.has(next_pos) or next_pos in blocked_cells: + continue + + if not enhanced_gridmap.is_position_valid(next_pos) or not enhanced_gridmap.is_cell_walkable(next_pos, 0): + continue + + if is_position_occupied(next_pos) and next_pos != target_pos: + continue + + # Check if movement between cells is blocked by an obstacle + if not is_diagonal_direction(dir) and enhanced_gridmap.is_movement_blocked(current, next_pos, 3): + continue + + # For diagonal movement, check if both orthogonal paths are blocked + if is_diagonal_direction(dir): + var mid1 = Vector2i(next_pos.x, current.y) + var mid2 = Vector2i(current.x, next_pos.y) + + var path1_blocked = mid1 in blocked_cells or enhanced_gridmap.is_movement_blocked(current, mid1, 3) + var path2_blocked = mid2 in blocked_cells or enhanced_gridmap.is_movement_blocked(current, mid2, 3) + + if path1_blocked and path2_blocked: + continue + + # Add to queue + queue.append(next_pos) + visited[next_pos] = true + steps[next_pos] = steps[current] + 1 + + return false + +# Helper function to check if a direction is diagonal +func is_diagonal_direction(direction: Vector2i) -> bool: + return direction.x != 0 and direction.y != 0 + func highlight_adjacent_cells(): if not is_multiplayer_authority() or is_bot or is_in_group("Bots"): return