class_name CombatMap extends Node2D @export var tile_set: DLTileset @export var map_layout: MapLayout @onready var tile_map: TileMapLayer = %TerrainLayer @onready var highlight_map: GridOverlay = %OverlayLayer @onready var wall_renderer: WallRenderer = %WallRenderer @onready var fog_renderer: FogRenderer = %FogRenderer const DEPLOYED_UNIT_SCENE = preload("res://prefabs/deployed_unit.tscn") const SOURCE_ID: int = 0 var _pending_layout: String var _pending_units: Array[Dictionary] = [] func _ready() -> void: if _pending_layout: _apply_layout(_pending_layout) for entry in _pending_units: _apply_deploy(entry.deployed, entry.coords) _pending_units.clear() if map_layout: apply_layout(map_layout) func draw_wall(coords: Vector2i) -> void: draw_custom(coords, tile_set.wall_tile_coords) func draw_floor(coords: Vector2i) -> void: draw_custom(coords, tile_set.floor_tile_coords) func draw_custom(coords: Vector2i, tile_coords: Vector2i) -> void: tile_map.set_cell(coords, SOURCE_ID, tile_coords) func load_map(layout: String) -> void: if is_node_ready(): _apply_layout(layout) else: _pending_layout = layout func deploy_unit(unit: Unit, coords: Vector2i) -> void: var deployed: DeployedUnit = DEPLOYED_UNIT_SCENE.instantiate() deployed.unit = unit if is_node_ready(): _apply_deploy(deployed, coords) else: _pending_units.append({deployed = deployed, coords = coords}) func _apply_layout(layout: String) -> void: var rows := layout.split("\n") for y in rows.size(): for x in rows[y].length(): var coords := Vector2i(x, y) match rows[y][x]: "#": draw_wall(coords) ".": draw_floor(coords) func _apply_deploy(deployed: DeployedUnit, coords: Vector2i) -> void: deployed.position = BattleMapHelper.coords_to_world(coords) add_child(deployed) func remove_unit(deployed: DeployedUnit) -> void: if deployed.get_parent() == self: remove_child(deployed) func target_tile(coords: Vector2i) -> void: highlight_map.target_tile(coords) func apply_layout(layout: MapLayout) -> void: map_layout = layout map_layout.initialize() load_from_layout() draw_room_walls() draw_fog() func is_tile_passable(from: Vector2i, to: Vector2i) -> bool: assert(map_layout != null, "CombatMap.is_tile_passable called before map_layout was set") return map_layout.is_passable(from, to) func is_tile_valid(coords: Vector2i) -> bool: assert(map_layout != null, "CombatMap.is_tile_valid called before map_layout was set") return map_layout.is_tile_valid(coords) func draw_room_walls() -> void: if not map_layout: return wall_renderer.draw_walls_for_layout(map_layout) func draw_fog() -> void: if not map_layout: return fog_renderer.draw_fog_for_layout(map_layout) func get_map_rect() -> Rect2: if not map_layout: return Rect2() return Rect2(Vector2.ZERO, Vector2(map_layout.size) * BattleMapHelper.TILE_SIZE) func load_from_layout() -> void: if not map_layout: return for room in map_layout.rooms: for tile in room.tiles: draw_floor(tile)