Files
GameJamDungeon/Zennysoft.Game.Ma/addons/SimpleDungeons/utils/DungeonAStarGrid3D.gd

80 lines
4.1 KiB
GDScript

class_name DungeonAStar3D
extends AStar3D
var doors_list = []
var pt_id_to_vec3i = {}
var vec3i_to_pt_id = {}
var dungeon_generator : DungeonGenerator3D
var rooms_check_dict : Dictionary # Vector3i : DungeonRoom3D (Non-Corridor) instance
var corridors_check_dict : Dictionary # Vector3i : DungeonRoom3D (Corridor) instance
var cap_required_doors_phase := false
func can_walk_from_to(dungeon_generator : DungeonGenerator3D, pos_a : Vector3i, pos_b : Vector3i) -> bool:
if not dungeon_generator.get_grid_aabbi().contains_point(pos_a): return false
if not dungeon_generator.get_grid_aabbi().contains_point(pos_b): return false
var room_a = rooms_check_dict[pos_a] if rooms_check_dict.has(pos_a) else null
var room_b = rooms_check_dict[pos_b] if rooms_check_dict.has(pos_b) else null
if room_a == null and room_b == null: return pos_a.y == pos_b.y # Outside rooms, only move horizontal
if room_a == room_b: return true # Inside rooms, move anywhere, up and down, i.e. stairs
# Ensure walking through doorways if not a simple case:
var fits_room_a_door = room_a == null or room_a.get_doors_cached().filter(func(d): return d.grid_pos == pos_a and d.exit_pos_grid == pos_b).size() == 1
var fits_room_b_door = room_b == null or room_b.get_doors_cached().filter(func(d): return d.grid_pos == pos_b and d.exit_pos_grid == pos_a).size() == 1
return fits_room_a_door and fits_room_b_door
func _init(dungeon_generator : DungeonGenerator3D, rooms_check_dict : Dictionary, corridors_check_dict : Dictionary):
self.dungeon_generator = dungeon_generator
self.rooms_check_dict = rooms_check_dict
self.corridors_check_dict = corridors_check_dict
# Add points to the AStar3D grid
var point_id = 0
for x in range(dungeon_generator.dungeon_size.x):
for y in range(dungeon_generator.dungeon_size.y):
for z in range(dungeon_generator.dungeon_size.z):
add_point(point_id, Vector3(x,y,z))
pt_id_to_vec3i[point_id] = Vector3i(x,y,z)
vec3i_to_pt_id[Vector3i(x,y,z)] = point_id
point_id += 1
var xyz_dirs := [Vector3i(1,0,0), Vector3i(-1,0,0), Vector3i(0,0,1), Vector3i(0,0,-1), Vector3i(0,1,0), Vector3i(0,-1,0)] as Array[Vector3i]
# Connect points - allow walking in & out of all doors but don't connect where walls are.
for x in range(dungeon_generator.dungeon_size.x):
for y in range(dungeon_generator.dungeon_size.y):
for z in range(dungeon_generator.dungeon_size.z):
var cur_pt_id = get_closest_point(Vector3(x,y,z))
# Allow walk in/out of room, up & down too for stairs
for dir in xyz_dirs:
if can_walk_from_to(dungeon_generator, Vector3i(x,y,z), Vector3i(x,y,z) + dir):
connect_points(cur_pt_id, get_closest_point(Vector3(x,y,z) + Vector3(dir)))
func _estimate_cost(from_id : int, to_id : int) -> float:
if dungeon_generator.astar_heuristic == DungeonGenerator3D.AStarHeuristics.NONE_DIJKSTRAS:
return 0.0
elif dungeon_generator.astar_heuristic == DungeonGenerator3D.AStarHeuristics.MANHATTAN:
var diff := get_point_position(to_id) - get_point_position(from_id)
return (abs(diff.x) + abs(diff.y) + abs(diff.z)) * dungeon_generator.heuristic_scale
elif dungeon_generator.astar_heuristic == DungeonGenerator3D.AStarHeuristics.EUCLIDEAN:
var diff := get_point_position(to_id) - get_point_position(from_id)
return diff.length() * dungeon_generator.heuristic_scale
return 0.0
func _compute_cost(from_id : int, to_id : int) -> float:
var diff := get_point_position(to_id) - get_point_position(from_id)
var cost := diff.length()
if rooms_check_dict.has(Vector3i(get_point_position(to_id).round())):
if not cap_required_doors_phase:
cost *= dungeon_generator.room_cost_multiplier
else:
cost *= dungeon_generator.room_cost_at_end_for_required_doors
if corridors_check_dict.has(Vector3i(get_point_position(to_id).round())):
cost *= dungeon_generator.corridor_cost_multiplier
return cost
func get_vec3i_path(from : Vector3i, to : Vector3i) -> Array[Vector3i]:
var path = get_id_path(vec3i_to_pt_id[from], vec3i_to_pt_id[to])
var path_vec3i = Array(path).map(func(pt_id : int): return pt_id_to_vec3i[pt_id])
var typefix : Array[Vector3i] = [] as Array[Vector3i]
typefix.assign(path_vec3i)
return typefix