Actions, Items and Datasets

It's been a busy couple of weeks. Had a nice Easter long weekend with family and then back onto the GameDev grind! A lot was accomplished in a relatively short period of time.
Actions
The base framework for in-game actions is now in place. The player will correctly switch states based on the requested action—whether it's moving, moving to a target, attacking when in range, or attempting to interact when in range. While the actual interactions and combat mechanics aren’t fully implemented yet, the groundwork is laid. With several other core systems now fleshed out, those features will be coming very soon.
Items and Datasets
Itemization is... complete? Well, as complete as it ever is in game development—there’s always room for change. That said, the system is now implemented and fully tested for all in-game items. I ended up pivoting from my original plan and I’m really glad I did. Rather than using Godot’s built-in Resource
system (similar to Unity’s ScriptableObject
), I decided to handle all datasets—starting with Items—using Google Sheets.
func _parse_json_file(path: String, type: String = "item") -> Dictionary:
var file = FileAccess.get_file_as_string(path)
var json = JSON.new()
var json_error: Error = json.parse(file)
if json_error == OK:
var data_received = json.data
if typeof(data_received) == TYPE_DICTIONARY:
var dictionary_data: Dictionary = data_received
for key in dictionary_data.keys():
if type == "item":
_assign_icon_file_path(key, dictionary_data)
_convert_dictionary_keys_to_int(key, dictionary_data)
print(">>> Loaded %s successfully. For total %s %s(s)." % [path, data_received.size(), type])
return dictionary_data
else:
print("Unexpected data type received from %s" % [path])
return {}
else:
if (FileAccess.get_open_error() != OK):
print("FileAccess encountered an error accessing %s, ERROR CODE: %s" % [file, FileAccess.get_open_error()])
print("JSON Parse Error: ", json.get_error_message(), " in ", file, " at line ", json.get_error_line())
return {}
func _assign_icon_file_path(key: Variant, dictionary_data: Dictionary) -> void:
var path_to_check: String = "%s%s" % [Global.FILE_PATH_ITEM_ICON, dictionary_data[key]["icon"]]
if FileAccess.file_exists(path_to_check):
dictionary_data[key]["icon"] = path_to_check
else:
dictionary_data[key]["icon"] = Global.FILE_PATH_NO_ITEM_ICON
func _convert_dictionary_keys_to_int(key: Variant, dictionary_data: Dictionary) -> void:
var key_int: int = int(key)
dictionary_data[key_int] = dictionary_data[key]
dictionary_data.erase(key)
I’m using a free plugin to convert my sheets to JSON. From there, I export the data and run a custom script in the engine to parse everything into a Dictionary. Items are then created by ID: if the Dictionary doesn't recognize the ID, it prints a debug message; if it does, the item references the dataset by ID, allows for overrides, and always pulls the most up-to-date data from the sheet. This ensures saved game data remains compatible and dynamic, even after updates to the dataset.
After confirming everything was working properly, I built the Inventory and Paper Doll systems. For anyone unfamiliar, the "Paper Doll" is just the character's equipable slot layout in an RPG. I also developed a detailed debug function to test all inventory features and verify that the dataset remains in sync. Once I was confident with everything, I called it complete and moved on to the next phase.
Looking Ahead
Since the last update, I’ve implemented four major systems—each required a fair bit of brainstorming to get right. I still plan to rework the Stat system eventually. It works as intended for now, so it’s on the back burner—mainly because a full refactor could eat up a week or more.
Next up, I want to build out a simple UI so I can see the inventory, paper doll, and current stats in real time (no more living in debug logs). After that, I’ll be fleshing out the Combat Class to handle calculations and finally bring proper combat to life. Those are some key milestones I’m really looking forward to hitting.
Once those are done, it’ll be time to dive into the Skill System and start shaping the rest of the RPG framework.
Until next time—shouting into the void!