How to reference a variable inside an inspector-modified resource?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Arzel

Hello, I hope the title make sense. I am a game artist with a very loose grasp on coding logic, and I am trying to make a dialog system based on the player’s input (a bit like Zorg, but only for exchanging with a character).

I have three scripts, and a customized ressource.

The first script is topics.gd. It’s a ressource storing the name of a discussion topic, its type, and a dialogue:

class_name Topic
extends Resource

export (String) var topic_name := "Topic name"
export (Types.TopicTypes) var topic_type := Types.TopicTypes.PERSON

export (String, MULTILINE) var question_about_this_topic

topic_type is stored in another script, a simple enumeration, types.gd:

extends Node

enum TopicTypes {
	PERSON,
	OBJECT,
	LOCATION,
	EVENT,
	CONCEPT,
}

I’ve read somewhere about cycle dependencies in godot or something (I don’t remember and I don’t understand it), but someone suggered to create a “base resource” out the resource script to circumvent the problem; So I did:
screenshot of topics.tres
Then, with topics.gd as its reference, I’ve created a ressource called guild_pin.tres:

My final script CommandProcessor.gd reads the player’s input, and match it to a command, and returns a string that can be read in the dialogue box:

extends Node

const Topics := preload("res://dialog/topics/topics.tres")

func process_command(input: String) -> String:
	var words = input.split(" ", false)
	if words.size() == 0:
		return "Error: No words were parsed."
	
	var first_word = words[0].to_lower()
	var second_word = ""
	var third_word = ""
	if words.size() > 1:
		second_word = words[1].to_lower()
	if words.size() > 2:
		third_word = words[2].to_lower()
	
	match first_word:
		"help":
			return help()
		"talk":
			if second_word == "about":
				return talk_about(third_word)
			else:
				return "Unrecognized command."
		_:
			return "Unrecognized command."

	

func talk_about(third_word: String) -> String:
	if third_word == "":
		return "Talk about what?"
	
	if third_word == Topics.topic_name.to_lower():
		return Topics.question_about_this_topic
		
	return "I don't know this Topic."

func help() -> String:
	return "You can use these words: go [location], help."

The game doesn’t crash, and the output works as intended, but it won’t return the multilines string stored in guild_pin.tres:
screenshot of the dialogue box

I know the solution is at my fingertip but I just don’t know enough to figure things out! Thank you for reading this long post, I hope someone can help.
Have a good one

const Topics := preload("res://dialog/topics/topics.tres")

Perhaps I’m missing something here, but you’re only loading topics.tres? This value Topics.topic_name.to_lower(): is “Topic name”. Perhaps you intend to have an array (dictionary?) of topics loaded so the third word is a key to the appropriate resource.

spaceyjase | 2023-03-24 17:00

Could you explain to me how to do that?
btw I tried to only preload guild_pin.tres and it returned me “I don’t know this Topic” :confused: I think my talk_about function is flawed…

Arzel | 2023-03-26 12:24

I think your talk_about function isn’t being passed the whole string; it is initially split by spaces which, for the input “talk about guild pin”, will break it up into talk, about, guild and pin. So the third word is just guild, so there’s a bug.

A dictionary might help with look up, e.g.

extends Node

export (Dictionary) var topics

func _ready():
	if topics.has("guild pin"): # e.g. the 'third_word' variable
		print(topics["guild pin"].question_about_this_topic)

And then you populate the dictionary in editor with all the topics you need. I hope that points you in the right direction.

spaceyjase | 2023-03-26 14:34