extends Node class_name IsometricMapRenderer var map_data = null var isometric_map_layers = [] var highlighted_tiles = {} # Dictionary to store all currently highlighted tiles var TILE_SIZE_ISOMETRIC_X = 32 # in px var TILE_SIZE_ISOMETRIC_Y = 16 # in px var unit_is_hovered = false var unit_is_selected = false var darkening_active = false var original_modulates = {} func darken_all_except_player(player_node): darkening_active = true # Store original modulate values for layer in isometric_map_layers: original_modulates[layer] = layer.modulate # Darken the layer layer.modulate = Color(0.5, 0.5, 0.5, 1.0) # Keep player at normal brightness player_node.modulate = Color(1.0, 1.0, 1.0, 1.0) func reset_darkening(): darkening_active = false # Restore original modulate values for layer in isometric_map_layers: if layer in original_modulates: layer.modulate = original_modulates[layer] func set_unit_hover_state(is_hovered): unit_is_hovered = is_hovered func set_unit_selected_state(is_selected): unit_is_selected = is_selected # Initialize with reference to a map data object and a tilemap to use as template func _init(map_data_ref, tilemap_template): map_data = map_data_ref initialize_map_layers(tilemap_template) # Initialize all the map layers for different heights func initialize_map_layers(tilemap_template): # Clear any existing layers for layer in isometric_map_layers: if is_instance_valid(layer): layer.queue_free() isometric_map_layers.clear() # Create new layers for each height level for z in map_data.GRID_SIZE_HEIGHT: var new_layer = TileMapLayer.new() new_layer.set_name("IsometricMapLayer_" + str(z)) new_layer.tile_set = tilemap_template.tile_set new_layer.z_index = z # Set the z-index to match the layer's height tilemap_template.get_parent().add_child(new_layer) isometric_map_layers.append(new_layer) # Draw all visible tiles on the map func draw_visible_tiles(): # Clear all previously drawn tiles on each layer for layer in isometric_map_layers: layer.clear() # Draw the map for z in map_data.GRID_SIZE_HEIGHT: for y in map_data.GRID_SIZE_LENGTH: for x in map_data.GRID_SIZE_WIDTH: var tile = map_data.get_tile(x, y, z) if tile != null and tile["visibility"] and tile["atlas_base_position"] != null: # Use the layer that corresponds to the tile's z-value if z < isometric_map_layers.size(): isometric_map_layers[z].set_cell( Vector2i(tile["x"], tile["y"]), IsometricMapSystem.MAIN_SOURCE_ID, tile["atlas_base_position"] ) # Handle hovering over tiles func handle_hover(mouse_position): var hover_tile_position = isometric_map_layers[0].local_to_map(mouse_position) var new_highlighted_tiles = {} # Will store tiles to highlight this frame if unit_is_hovered: # De-highlight all tiles for tile_key in highlighted_tiles: var tile_data = highlighted_tiles[tile_key] var tile = map_data.get_tile(tile_data.x, tile_data.y, tile_data.z) if tile != null and tile["visibility"] and not tile["unit"]: if not tile["selected"]: if tile["atlas_base_position"] != null: isometric_map_layers[tile_data.z].set_cell( Vector2i(tile["x"], tile["y"]), IsometricMapSystem.MAIN_SOURCE_ID, tile["atlas_base_position"] ) tile["highlighted"] = false highlighted_tiles = {} return # First find all tiles that should be highlighted for z in map_data.GRID_SIZE_HEIGHT: for x in map_data.GRID_SIZE_WIDTH: for y in map_data.GRID_SIZE_LENGTH: var tile = map_data.get_tile(x, y, z) var tile_above = map_data.get_tile(x, y, z + 1) if tile_above != null and tile_above["visibility"] and not tile_above["unit"]: if tile["x"] == hover_tile_position.x and tile["y"] == hover_tile_position.y: # Store this tile for highlighting var tile_key = str(x) + "_" + str(y) + "_" + str(z) new_highlighted_tiles[tile_key] = { "x": x, "y": y, "z": z + 1 } elif tile != null and tile["visibility"] and not tile["unit"]: if tile["x"] == hover_tile_position.x and tile["y"] == hover_tile_position.y: # Store this tile for highlighting var tile_key = str(x) + "_" + str(y) + "_" + str(z) new_highlighted_tiles[tile_key] = { "x": x, "y": y, "z": z } # Highlight new tiles for tile_key in new_highlighted_tiles: var tile_data = new_highlighted_tiles[tile_key] var tile = map_data.get_tile(tile_data.x, tile_data.y, tile_data.z) if tile == null: continue if not tile["selected"] and not tile["unit"]: # Only set cell if we have a valid highlight position if tile["atlas_highlight_position"] != null: isometric_map_layers[tile_data.z].set_cell( Vector2i(tile["x"], tile["y"]), IsometricMapSystem.MAIN_SOURCE_ID, tile["atlas_highlight_position"] ) else: isometric_map_layers[tile_data.z].set_cell( Vector2i(tile["x"], tile["y"]), 1, Vector2i(3,1) # ) tile["highlighted"] = true # De-highlight tiles that are no longer under the cursor for tile_key in highlighted_tiles: if not (tile_key in new_highlighted_tiles): var tile_data = highlighted_tiles[tile_key] var tile = map_data.get_tile(tile_data.x, tile_data.y, tile_data.z) if tile != null and tile["visibility"] and not tile["unit"]: if not tile["selected"]: # Only set cell if we have a valid base position if tile["atlas_base_position"] != null: isometric_map_layers[tile_data.z].set_cell( Vector2i(tile["x"], tile["y"]), IsometricMapSystem.MAIN_SOURCE_ID, tile["atlas_base_position"] # Original appearance ) else: isometric_map_layers[tile_data.z].set_cell( Vector2i(tile["x"], tile["y"]), 1, Vector2i(0,1) # ) tile["highlighted"] = false # Update the highlighted tiles list highlighted_tiles = new_highlighted_tiles # Handle tile selection logic func handle_tile_selection(): if unit_is_selected: reset_darkening() unit_is_selected = false for z in map_data.GRID_SIZE_HEIGHT: for x in map_data.GRID_SIZE_WIDTH: for y in map_data.GRID_SIZE_LENGTH: var tile = map_data.get_tile(x, y, z) if tile == null or not tile["visibility"]: continue # Get valid coordinates var tile_x = tile["x"] var tile_y = tile["y"] if tile["selected"] and tile["highlighted"]: print("direct de selected: ", Vector2i(tile_x, tile_y)) isometric_map_layers[z].set_cell( Vector2i(tile_x, tile_y), IsometricMapSystem.MAIN_SOURCE_ID, IsometricMapSystem.SELECTED_BLUE_ISOMETRICTILE_ATLAS_POSITION ) tile["selected"] = false elif tile["selected"] and not tile["highlighted"]: print("old de selected: ", Vector2i(tile_x, tile_y)) # If there's a base position, restore it, otherwise use a default if tile["atlas_base_position"] != null: isometric_map_layers[z].set_cell( Vector2i(tile_x, tile_y), IsometricMapSystem.MAIN_SOURCE_ID, tile["atlas_base_position"] ) else: isometric_map_layers[z].set_cell( Vector2i(tile_x, tile_y), IsometricMapSystem.MAIN_SOURCE_ID, IsometricMapSystem.BLUE_ISOMETRICTILE_ATLAS_POSITION ) tile["selected"] = false elif not tile["selected"] and tile["highlighted"]: print("new selected: ", Vector2i(tile_x, tile_y)) isometric_map_layers[z].set_cell( Vector2i(tile_x, tile_y), IsometricMapSystem.MAIN_SOURCE_ID, IsometricMapSystem.SELECTED_WHITE_ISOMETRICTILE_ATLAS_POSITION ) tile["selected"] = true # Position a unit on the map visually func position_unit(unit, tile_x, tile_y, tile_z): var world_pos = IsometricMapSystem.iso_to_world( tile_x, tile_y, tile_z, TILE_SIZE_ISOMETRIC_X, TILE_SIZE_ISOMETRIC_Y ) unit.z_index = tile_z # Assuming unit has a set_unit_position method to handle actual positioning if unit.has_method("set_unit_position"): unit.set_unit_position(world_pos.x, world_pos.y, tile_z)