Hello everyone, long time no see.

I'm having less of a problem and more of an uncertainty about 'Godot's game design', and was hoping to hear some advice.
I'm making a card game (similar to slay the spire) in which the player can create a basic deck in the menu, but the deck changes along the run. For now I made the Card Database as a Dictionary as follows:
all_cards = {
'strike' : { 'name' : 'Strike', 'cost' : 2},
'bash' : { 'name' : 'Bash', 'cost' : 3}
}

The initial, user created deck is just an Array with the card names like: deck_list = ['strike', 'strike', 'strike', 'strike']
At the beginning of the run the game search the database with the card names, and creates another Array of the "card contents". Like so:
deck_cards = [{ 'name' : 'Strike', 'cost' : 2}, { 'name' : 'Strike', 'cost' : 2}, { 'name' : 'Strike', 'cost' : 2}, { 'name' : 'Strike', 'cost' : 2}]
With this I can modify cards, add more cards or remove them independent if they started as the same card.


Recently I was presented with the idea of using resources for the Card Database. Basically create a CardBase.gd, and for each card save a .tres file extending this base resource. So to have a folder of files where each file is a card.
The initial, user created deck would still be a list of names like before. Based on the docs at runtime I would simply create a Dictionary where each card is an instantiated resource, like:

export var deck_res = {
'card01' : 'strike.tres',
'card02' : 'strike.tres',
'card03' : 'strike.tres',
'card04' : 'strike.tres'}

From early test each card in this dictionary has an unique resource, and can be manipulated separately from one another.

So here my question: Should I refactor my game to use this resource approach or just keep the original Dictionary Database approach?

Cheers

    Either way can work. However, I found using external files as better for a database. You can use .json or even a spreadsheet exported to .csv. I was making a sort of card game, and I edited the database with LibreOffice Calc (or you could use Excel) and then imported to Godot. This was better for me as it was easier to manage large amounts of data in a spreadsheet app, rather than editing long files in the Godot editor. But any way is valid.

    Daishishi Dictionaries and Arrays are in GDscript because GDscript is at the end of the day a programming language and those two things are perhaps the most useful constructs in programming. If I were you I'd be thinking more from a game design perspective than a strictly programming one. Personally, every time I introduce similar sorts of databases in my games I eventually replace them with objects which can extend root classes and simplify the task of creating complex mechanics.
    Personally, when I am navigating godot, I find that I naturally want to be able to open up scenes to make edits to individual object's export variables.

    This isn't really a dilemma since resources are only a way to save structured data to disk. You can have your dictionaries, put them all into a resource class and save it. So, organize your data structures in a way that best suits the game and your workflow, then serialize them into a custom Resource derived object so you can edit them without making changes to the source code. This is preferable solution in the long run because size and complexity of the data stays easily scalable as the project grows over time.

    Hey, I'm the guy from the reddit thread, I think I have the Resource solution to this figured out.

    First, you have to set up the folders (Cards > Attributes) and the class (card_attributes.gd).

    Then the actual Resource (Knight.tres). Right click and Add Resource to your sub folder (Attributes) and find and select the class you just made. Then name the resource.

    Once you do that, click on your new Resource and you can edit the values in the Inspector.

    Now, to make your array of cards, you can just straight up make the array with these resources:
    const PLAYER_CARDS: Array[CardAttributes] = [preload("res://Cards/Attributes/Knight.tres"), preload("res://Cards/Attributes/Knight.tres")]

    ...and then reference them like this:
    print(PLAYER_CARDS[0].name)
    print(PLAYER_CARDS[0].power)

    Which in my case would be:

    "Knight"
    "1"

    Anyway, I think I'm going to continue doing it this way myself. I do like the idea of having each card be a file, that I can use the inspector to edit them, and referencing them this way seems to make a little more sense to me now I guess. That said, I don't think the way we were doing it with a dictionary is bad or bad practice, but idk much lol. Hopefully this helps you, though!

      That's actually pretty cool to be able to edit it in the inspector. I still think for large amounts of data you want an external database, but for a small amount of config settings that looks easier.

        cybereality I think it depends on the data, if it's something that you're constantly tweaking back and forth as you develop the game, such as an enemy's attack power, it's nice to have that attribute next to the other related ones on the character in the inspector. Most of the time you're developing the game, after all, you're going to be in the engine anyway, not the spreadsheet. I sometimes go too far though, I even have my language translations in code in dictionaries where obviously it's better to just have CSV sheet.

        When I was doing it it was sort of a visual novel type of strategy game, so lots of text but also connected with stats, so it made sense to put them all in the same place.

        a year later

        blankk

        I'm currently facing that problem too. I am following the same workflow as you (for the "screenshoted" part) but when it comes to accessing those resource in a safe manner that wouldn't end up by putting literal filepaths in code, I feel like something is missing in Godot. Obviously, exportable typed dictionaries or structs (if I get the nature of that last thing right) would be the lightweight, typed and keyed solution many people are searching for.

        I ended up, after many different attempts to find a good solution, with something like that :

        data.gd and data.tscn inspector

        This is a PackedScene as a "Data" autoload with a bunch of arrays for each of my custom resources types.

        The data can be called with a lamba function exist that returns the actual resource or returns a default one if the data requested doesn't exist.

        Character.gd

        Then it can be called like that in any script when the resource is needed.

        It implies that a custom name has been set in the inspector for the resource and it implies using a singleton 🫣

        To avoid that, small "data sets" (i.e. "Resource of resources") could be set as exported variables in each nodes that needs them, have a script that extends a CustomResource script that would use a similar "retrieve" function as the lambda one shown above.