New to Godot coding, stuck on approach

Godot Version

4.5.1

Question

Greetings!

I’ve been practicing with GDScript for a few weeks and been trying to put together something to help with a later idea down the line. Here’s the issue:

I’ve been making a dynamic character sheet where you can input the name of the character, adjust stats and so forth. Even have it so the stats turn red if you put too much. The next step is to have a bunch of dropdown menus that you click on and choose an item or ability to alter stats. Trouble is, I am unsure of what the right approach to this nor how exactly to do this with a dropdown menu as finding this particular situation in the help section is difficult. Do I put all the code into one script on the control node and export the data to the OptionButtons? Or do I manually add the data into each dropdown information and manually create it?

So far I have the nodes like this.
Sheet(colorRec)
| →theme (Control)
| | → ColorRect
| | → ColorRect
| → Control (Script)
| → Strength
| → Strength Value
(repeated with other stats)
| → VBoxContainer (Choices)

So far, there’d be 3 different sections full of the dropdown menus. Each section would likely have a pool of ‘stuff’ to draw from. So the drop menus would have the same things in each section. Thinking of using a directory to do this with. What way could I use that won’t involve just copy and pasting the information into each OptionButton?

What do you want to do?

Personally, I’d take the time to load the data in. For an example of that, you can take a look at my Localization Plugin. I scan a directory looking for files, then load each one as an option in the language option button, and parse the language and locale to load up an image of the country flag for each language.

I enter all the translations in a Google Sheet and then load them that way - though Godot does the import for me, so you won’t be able to see a data access example in this. Still, maybe it will help.

1 Like

Alright, so the idea is that when you click on the dropdown and select the option, it would change the stats on the sheet. Like a “ring of strength” would increase strength by 2 or “thorn underwear” would improve endurance but reduce dexterity. That kind of thing.

The first step is to design a data structure that stores all the relevant data for the character. Next, implement that structure as a script class, typically a class that inherits built-in Resource class. This inheritance will get you the ability to create/edit data in the inspector and save it to disk. Once you have that you can create a gui scene and implement a function that reads in your resource object and populates the gui with the data found in that resource object.

1 Like

So something like:

var class_options := [
	{ "name": "Warrior", "mod": {"health": 3, "strength": 3, "magic": 0, "gold": -20} },
	{ "name": "Mage",    "mod": {"health": 0, "strength": 0, "magic": 5, "gold": -25} },
	{ "name": "Rogue",   "mod": {"health": 1, "strength": 2, "magic": 0, "gold": -10} },
]

I agree with @normalized. I’d recommend you make a paper version of your game. Take little pieces of paper to represent the various things, and then move them around on a table to see how the UI would look. Then move them around again to see how you might want to group the data together. That visualization can help you design this.

No. I would recommend against this in Godot. Instead, leverage the Resource class.

class_name CharacterClass extends Resource

@export var name: String
@export var modifiers: Dictionary[String, int]

Then class options:

var class_options: Dictionary[String, CharacterClass]

This will allow you to edit them all in the Godot editor.

1 Like

Ah, there seems to be some miscommunication.

I do have a idea of what to do in concept. This project is similar to filling out a DnD character sheet. Adding and rolling up the stats. A means to help me learn more about scripting and how Godot works. This isn’t part of a game, yet, but it will help towards it.

And it’s also something I’m doing to help a friend set up during game nights.

Ah, I didn’t realize Resource was a class. I thought it was just something to describe data.

Yeah I was getting that vibe. I just realized you put a text version of a node tree in there. Forgot about that.

I stand by my Resource recommendation. I’d extend the idea a little more though. Create a base class for CharacterSheet that displays all the values. (Which it sounds like you have.) Then @export a few variables.

class_name CharacterSheet extends Control

const CLASSES_DIR = "res://resources/classes/"
const ANCESTRIES_DIR = "res://resources/ancestries/"

@export var character_class: CharacterClass
@export var ancestry: CharacterAncestry # Going with the 5E updates

@onready var class_drop_down: OptionButton = $ClassDropDown
@onready var ancestry_drop_down: OptionButton = $AncestryDropDown

var classes: Array[CharacterClass]
var ancestries: Array[CharacterAncestry]

func _ready() -> void:
	load_options(class_drop_down, CLASSES_DIR, classes)
	load_options(ancestry_drop_down, ANCESTRIES_DIR, ancestries)


func load_options(button: OptionButton, directory_name: String, option_array: Array) -> void:
	## Iterate through the directory
	## Load each resource file and track an index
	## Assign the name to the option button
	## Assign the loaded Resource to the array

This way you can just create and save a new Resource to the directory every time your DM wants a new one.

Even better, if you want to allow them to later add their own, it’s really easy to make an interface for creating and editing the files and/or new ones.

1 Like

This would definitely help toward that goal. I didn’t know you could load in the option buttons as well in script.

While it’s not DnD (pathfinder), it does help set things in the right direction. Now I just have to add values to each selection so it changes the stats. Perhaps having the values as a sum instead of a static number to change when switching options… would that keep it from crashing?

1 Like

Pathfinder is literally open source D&D, yo. (And much superior when it comes to game balance.) And they actually are the ones that used ancestries so I nailed it!

Well now that I know it’s Pathfinder, here’s how I would do it. Create each stat with a base value. This is what the player chooses with point buy or rolls at the beginning of the game. Then have a list of modifiers and store those as a Dictionary. For example:

@export var base_strength: int = 3:
	set(value):
		 # Starting/base  value can never be below 3 or
		 #  above 18.
		base_strength = clamp(value, 3, 18)
## Every time you add or remove a modifier, it will be automatically calculated.
@export var strength_modifiers: Dictionary[String, int]
	set(value):
		strength_modifiers = value
		_modified_strength = base_strength
		for modifier in strength_modifiers:
			_modified_strength += strength_modifiers[modifier]

# Making this a var, not an @export var, and prepending it
# with an underscore to indicate that it is a private
# variable and only to be modified internally.
var _modified_strength: int = 3

Then, whenever you select a class or ancestry, create a function to go through each modifier and look for where it applies, and add it there. Then if you remove or change the class, before setting the new value in set(), go remove them from all the places they are. Then set the new ones.

Yup! Was surprised by that. XD

This would keep from having the stats compounding when a player selects an option from the dropdown repeatedly?

You’re too focused on gui. Gui is the least important thing here. Your primary focus should be designing data structures and implementing functions that do required stuff with that data. Such system should function properly without any guis. That’s what programming is all about - data structures and their relationships. Once you have that in place, setting up gui to control it will be trivial.

Yes, because each time a value is selected, you would replace the old one with the new one, and wipe out the old values, so that it would only have the intended effect.

While I don’t disagree about data structures, I think it’s easier to visualize and plan once you have some experience with Godot. My first few games I planned all sorts of stuff that didn’t leverage the engine and its features. so I personally think when one is learning Godot it can be helpful to play around with the visible aspects as one learns how to move data around efficiently.

Game engines are not a god place to take a first (or second) step with programming. Imo, the OP should build this little system in Python. It’s a pure data structuring problem. Gui is just a distraction from things that really matter here.

Yeah… I know… I’m the high priest of unpopular opinions :wink:

1 Like

Well, except that the stated goal in the original post is and in OP’s profile is: learning Godot to make cool games. And this project is an opportunity to have something to do IN Godot. So I kinda think if the options were make this in Python or don’t make it at all, the latter option would be chosen. And it’s very motivating to have a project to use to learn.

“Learning Godot” without first learning the programming fundamentals equals tutorial hell. Especially if motivation is to “make cool games”.

It could be argued that, because there’s colorful stuff popping on the screen, learning fundamentals “with Godot” is more fun and therefore easier. But I beg to differ. It may not be obvious at first, but the game engine makes it harder due to various reasons. Just look at all the confused people getting stuck with bare fundamentals non-specific to Godot, asking for help here on the daily basis.

There’s this widespread bogus logic that “games are fun to play so they must be equally fun to make”. This can’t be further from the truth. Making games is nothing like playing them. I’d go as far as saying that they are “diametrically opposite” types of mental activities in almost every respect.

Implying that game making process is (or should be) as fun as playing games is grossly misleading. Unfortunately, people tend to express this notion all the time, some more directly than others. In my book, this falls under the wider umbrella of toxic positivity.

4 Likes

Interesting take. You have some valid points. I think we’ve discussed this before though - in my experience teaching people to program, they have a much easier time when they have a problem to apply it to that they are motivated to solve. It isn’t about the game being fun, it’s about the motivation to get something accomplished that helps drive the discovery of solutions.

I do agree that a fundamental understanding is really helpful, but there are a few things I have noticed. People are more motivated to learn how to do things the right way after they done the thing the wrong way and learned their limitations.

Secondly, some people never get it. I remember spending hours whiteboarding how to take a one-file spaghetti-code and turn it into something that was OO and much easier to explain, and the guy I was explaining it to just didn’t get it. I ended up developing a parallel green field project myself.

To your point about making games not being the same kind of fun as playing games, I partially agree. I find it a LOT like playing the Sims or Minecraft, or the crafting part of any game that allows crafting. Programming just opens up this world of endless possibilities when it comes to creation.

But I also enjoyed logic problems in crossword puzzle books the most as a kid. I find a similar joy in solving problems. Like that example project I did for that guy yesterday. That was just fun for me. I view coding as something both right and left brained. I think there’s a lot of artistry in how one chooses to code their programs. And ultimately I think that’s what separates out real software architects from “coders” who just follow what other people say.

You and I are software architects. Most people are never going to get there, and “good enough” is going to be whatever helps them accomplish their goal. Not everyone wants to become a software architect and so the motivation to be learning for learning’s sake, or the delayed gratification of “it’ll make your life easier in the long run” just isn’t there for the average person. To me this is evident of the number of people who come here and post one question, get their answer and go away never to return.

3 Likes