Khaligufzel / Dimensionfall

A survival game inspired by Cataclysm: Dark Days Ahead and Bright Nights.
GNU General Public License v3.0
15 stars 7 forks source link

Renaming area in mapeditor still fails sometimes #402

Closed snipercup closed 1 month ago

snipercup commented 2 months ago

Renaming an area in the mapeditor will fail sometimes. The area gets a new name, but the tiles that it covers do not have their assigned area renamed with them.

Steps to reproduce:

snipercup commented 2 months ago

The problem is that we're writing to mapeditortile.tiledata and to mapEditor.currentMap.levels. I think we need to change it so we only write to mapEditor.currentMap.levels and have the mapeditortile only visualize the data.

Here's a suggestion from chatgpt but he's using python instead of gdscript so we need modifications:

Based on your requirements, here's the relevant code with changes to make mapEditor.currentMap.levels the single source of data. The tiles now only display data from mapEditor.currentMap.levels and do not store or modify their own tileData.


Changes in the main script:

  1. Modify apply_paint_to_tile to update mapEditor.currentMap.levels directly:
# Function to apply paint or erase logic to a single tile
func apply_paint_to_tile(tile: Control, brush: Control, tilerotate: int):
    # Since the grid is always completely filled, the index should be reliable. This assumes
    # that mapEditor.currentMap.levels[currentLevel] assumes the same number of items as the grid.
    var index = tile.get_index() 
    if index == -1:
        return
    var tileData = mapEditor.currentMap.levels[currentLevel][index]

    if erase:
        if brush:
            if brush.entityType == "mob":
                tileData.erase("mob")
            elif brush.entityType == "furniture":
                tileData.erase("furniture")
            elif brush.entityType == "itemgroup":
                tileData.erase("itemgroups")
            else:
                tileData.erase("id")
                tileData.erase("rotation")
        else:
            tileData = {}
    elif brush:
        selected_brush = brushcomposer.get_random_brush()
        var tilerotation = brushcomposer.get_tilerotation(tilerotate)
        if brush.entityType == "mob":
            tileData.erase("furniture")
            tileData.erase("itemgroups")
            tileData["mob"] = {"id": brush.entityID, "rotation": tilerotation}
        elif brush.entityType == "furniture":
            tileData.erase("mob")
            tileData.erase("itemgroups")
            tileData["furniture"] = {"id": brush.entityID, "rotation": tilerotation}
            tileData["furniture"]["itemgroups"] = brushcomposer.get_itemgroup_entity_ids()
        elif brush.entityType == "itemgroup":
            tileData.erase("mob")
            tileData.erase("furniture")
            tileData["itemgroups"] = brushcomposer.get_itemgroup_entity_ids()
        else:
            tileData["id"] = brush.entityID
            tileData["rotation"] = tilerotation
    # Update the map data
    mapEditor.currentMap.levels[currentLevel][index] = tileData
    # Tell the tile to update its display
    tile.update_display(tileData)

Explanation:

  1. Assign an index to each tile in create_level_tiles:
# Helper function to create tiles for a specific level grid
func create_level_tiles(grid: GridContainer, connect_signals: bool):
    var index = 0
    for x in range(mapEditor.mapWidth):
        for y in range(mapEditor.mapHeight):
            var tile_instance = tileScene.instantiate()
            grid.add_child(tile_instance)
            tile_instance.tileIndex = index  # Assign index to tile
            index += 1
            if connect_signals:
                tile_instance.tile_clicked.connect(grid_tile_clicked)
            tile_instance.set_clickable(connect_signals)

Explanation:

  1. Update loadLevel to use update_display:
# Loads one of the levels into the grid
func loadLevel(level: int, grid: GridContainer) -> void:
    var levelData: Array = mapEditor.currentMap.levels[level]
    var i: int = 0
    for tile in grid.get_children():
        i = tile.get_index()
        var tileData = levelData[i] if i < levelData.size() else {}
        tile.update_display(tileData)

Explanation:

  1. Remove storeLevelData function:
# Remove this function as it's no longer needed
func storeLevelData() -> void:
    pass  # Function body is no longer necessary

Explanation:

  1. Adjust functions that previously accessed tile.get_tileData() or modified tile.tileData:

For example, in copy_selected_tiles_to_memory:

# Copy selected tiles to memory without accessing tile.get_tileData()
func copy_selected_tiles_to_memory():
    reset_rotation()
    reset_copied_tiles_info()
    var selection_dimensions = get_selection_dimensions(start_point, end_point)
    var selected_tiles = get_tiles_in_rectangle(start_point, end_point)
    copied_tiles_info["width"] = selection_dimensions["width"]
    copied_tiles_info["height"] = selection_dimensions["height"]

    for tile in selected_tiles:
        var index = tile.get_index()
        if index != -1:
            var tileData: Dictionary = mapEditor.currentMap.levels[currentLevel][index]
            copied_tiles_info["tiles_data"].append(tileData.duplicate())

Explanation:


Changes in the mapeditortile script:

  1. Remove tileData as a settable property and related methods:
# Remove tileData setter and related functions
var tileData: Dictionary  # Remove setter methods

# Remove methods like set_tile_id, set_mob_id, set_furniture_id, etc.

Explanation:

  1. Add update_display method to refresh the tile's visuals:
func update_display(tileData: Dictionary):
    if tileData.has("id") and tileData["id"] != "" and tileData["id"] != "null":
        $TileSprite.texture = Gamedata.tiles.sprite_by_id(tileData["id"])
        $TileSprite.rotation_degrees = tileData.get("rotation", 0)
        $ObjectSprite.hide()
        $ObjectSprite.rotation_degrees = 0
        $AreaSprite.hide()
        $AreaSprite.rotation_degrees = 0
        if tileData.has("mob"):
            if tileData["mob"].has("rotation"):
                $ObjectSprite.rotation_degrees = tileData["mob"]["rotation"]
            $ObjectSprite.texture = Gamedata.mobs.sprite_by_id(tileData["mob"]["id"])
            $ObjectSprite.show()
        elif tileData.has("furniture"):
            if tileData["furniture"].has("rotation"):
                $ObjectSprite.rotation_degrees = tileData["furniture"]["rotation"]
            $ObjectSprite.texture = Gamedata.furnitures.sprite_by_id(tileData["furniture"]["id"])
            $ObjectSprite.show()
        elif tileData.has("itemgroups"):
            var random_itemgroup: String = tileData["itemgroups"].pick_random()
            $ObjectSprite.texture = Gamedata.itemgroups.sprite_by_id(random_itemgroup)
            $ObjectSprite.show()
        if tileData.has("areas"):
            $AreaSprite.show()
    else:
        $TileSprite.texture = load(defaultTexture)
        $ObjectSprite.texture = null
        $ObjectSprite.hide()
        $AreaSprite.hide()
    set_tooltip(tileData)

Explanation:

  1. Adjust set_tooltip method to accept tileData:
func set_tooltip(tileData: Dictionary) -> void:
    # Use tileData to build tooltip text

Explanation:

  1. Remove methods that modify tileData directly:

Explanation:


General Explanation:


Note: Remember to adjust any other parts of your code that interact with tileData, ensuring they reference mapEditor.currentMap.levels instead.