This week has been contrasted, with some stuffs taking way more time than it should, and others being quite hassle-free.
Starting with the later, I’ve implemented saving and loading my game, hopefully in a way that can be easily extended, I wanted to do that early enough to make sure that I would not need to change my data architecture if saving/loading proved too difficult with it.
It went surprisingly well. I took quite some time to read about the discussions related to the format you should use to save user data on Godot. The topic seems to be rather heated, reading comments on the documentation. Eventually, and as my game is essentially UI and basic data, JSON seemed the best option.
From there, the walkthrough in Godot’s documention was very clear and I could basically take some part of the code directly from it. It took me about two evenings (4 hours of work) to implement it, and I encountered very few bugs while doing so. Of course, as the game will expand, I will need to make sure that the functionnality continues to work. There will be some addition to make to it in any case (especially on the loading side, to make sure child nodes are added to parents when the parent is available), but for the time being, it is good enough.
On the other hand, I spent about the same amount of time to write those
func evaluate_ifs_from_current_node():
var var_dict:Dictionary = {
"hour" : GameWorld.current_hour,
"money" : player.current_money
}
for index in range(current_dialog_node.ifs.size()):
var expression:Expression = Expression.new()
expression.parse(current_dialog_node.ifs[index], var_dict.keys())
print(expression.execute(var_dict.values(), self))
if expression.execute(var_dict.values(), self) == true:
return index
return null
I suppose the reason for that is that it’s not a good solution to the problem I was trying to solve. Essentially, this is used to implement conditional dialogue lines in my dialogue engine. I wanted to have conditionnality at two levels:
- make some complete dialogues available under conditions. Think about getting a one-time dialogue once you reach a certain level of reputation.
- make some dialogue lines in the same dialogue vary based on parameters. Think about reacting to the time of the day when you get greeted. You will get greeted in any case, but not in the same way if you’re very early or late.
I am managing my dialogues in a dedicated Resource. To achieve the second type of conditionnality, I have an array with each of the possible Strings to be printed, and nother with the condition I want to apply. If a condition is met in the later Array, I use the index to show the correct String from the first Array. What i means, though is that my conditions are in fact also Strings that needs to be « converted » to code, something which I find always puzzling.
In order to make it happen, I used the Expression object. It took me two evenings to make it work, and to be honest, I am still not sure of what I was doing wrong. One of the thing that confused me the most was that it seems you can’t directly introduce variables in the string of the Expression to parse. Similarly to String formatting, you must use placeholders and replace them with variables through parsing/executing the Expression. I must say that compared to the convenience of f-strings in Python, this is particularly tedious.
I believe this tells me that I should be avoiding this mechanism alltogether. A solution could be to define the different type of conditions that could apply (« bigger than », small than », « equal to »,…), but it would mean essentially rebuilding the Expression functions in a slightly different way, so it seems a bit silly.
Truth to be told, it currently seems to be working well enough so I will leave it at this for now. But I found it funny how something that seemed really complex took me in the end the same time as something I imagined very simple.