class_name CombatMap extends Node2D @export var tile_set: DLTileset @onready var tile_map: TileMapLayer = %TerrainLayer @onready var highlight_map: GridOverlay = %OverlayLayer const TILE_SIZE := 100.0 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.unit, entry.coords) _pending_units.clear() func snap_to_grid(pos: Vector2) -> Vector2: return Vector2(floorf(pos.x / TILE_SIZE), floorf(pos.y / TILE_SIZE)) * TILE_SIZE func world_to_coords(pos: Vector2) -> Vector2i: return Vector2i(snap_to_grid(pos) / TILE_SIZE) func coords_to_world(coords: Vector2i) -> Vector2: return Vector2(coords) * TILE_SIZE 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: if is_node_ready(): _apply_deploy(unit, coords) else: _pending_units.append({unit = unit, 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(unit: Unit, coords: Vector2i) -> void: unit.position = coords_to_world(coords) add_child(unit) func is_wall(coords: Vector2i) -> bool: return tile_map.get_cell_atlas_coords(coords) == tile_set.wall_tile_coords func remove_unit(unit: Unit) -> void: if unit.get_parent() == self: remove_child(unit) func target_tile(coords: Vector2i) -> void: highlight_map.target_tile(coords)