Conditional entries allow your dialogue to branch dynamically based on game state, player choices, or any other logic. Unlike text entries, conditional entries execute a callable that returns a boolean, then jump to different branches based on the result.
Conditional entries are created using add_conditional_entry() with a callable that returns bool:
extends DialogueEnginevar have_we_talked_before = falsefunc check_if_talked() -> bool: return have_we_talked_beforefunc _setup() -> void: add_text_entry("Hello!") # Add a conditional entry var condition_entry = add_conditional_entry(check_if_talked) # Set where to go based on the condition result var if_true = add_text_entry("Hey! We meet again!") var if_false = add_text_entry("It's nice to meet you!") condition_entry.set_condition_goto_ids(if_true.get_id(), if_false.get_id())
You must specify both the true and false paths for a conditional entry:
var condition_entry = add_conditional_entry(some_callable)# Set both pathsvar true_entry = add_text_entry("Condition was true")var false_entry = add_text_entry("Condition was false")condition_entry.set_condition_goto_ids(true_entry.get_id(), false_entry.get_id())# You can also get the current goto IDsvar goto_ids = condition_entry.get_condition_goto_ids()print(goto_ids[true]) # Entry ID for true pathprint(goto_ids[false]) # Entry ID for false path
Failing to set valid condition goto IDs will cause the dialogue to be canceled with a warning when the condition is reached.
You can modify conditional entries after creation:
var entry = add_conditional_entry(some_condition)# Check if entry has a conditionif entry.has_condition(): var condition = entry.get_condition()# Change the conditionentry.set_condition(different_condition)# Remove the condition (converts to text entry)entry.remove_condition()
You can chain conditional entries for complex logic:
func _setup() -> void: add_text_entry("Evaluating your character...") # First condition: Check reputation var rep_check = add_conditional_entry(func() -> bool: return reputation >= 50 ) # If high reputation, check gold var gold_check = add_conditional_entry(func() -> bool: return gold >= 100 ) # Different outcomes var rich_and_famous = add_text_entry("Welcome, honored guest!") var famous_only = add_text_entry("Welcome, friend!") var low_rep = add_text_entry("What do you want?") # Wire up the conditions rep_check.set_condition_goto_ids(gold_check.get_id(), low_rep.get_id()) gold_check.set_condition_goto_ids(rich_and_famous.get_id(), famous_only.get_id())
Conditional entries emit the entry_visited signal but not dialogue_continued:
# This fires for ALL entries (text and conditional)dialogue_engine.entry_visited.connect(func(entry: DialogueEntry) -> void: if entry.has_condition(): print("Condition evaluated!"))# This ONLY fires for text entriesdialogue_engine.dialogue_continued.connect(func(entry: DialogueEntry) -> void: print(entry.get_text()))
enum QuestState { NOT_STARTED, IN_PROGRESS, COMPLETED }var quest_state = QuestState.NOT_STARTEDfunc check_quest_started() -> bool: return quest_state != QuestState.NOT_STARTEDfunc check_quest_completed() -> bool: return quest_state == QuestState.COMPLETEDfunc _setup() -> void: var state_check = add_conditional_entry(check_quest_started) var not_started = add_text_entry("I need your help with something...") var started_check = add_conditional_entry(check_quest_completed) var in_progress = add_text_entry("How's the quest going?") var completed = add_text_entry("Thank you for your help!") state_check.set_condition_goto_ids(started_check.get_id(), not_started.get_id()) started_check.set_condition_goto_ids(completed.get_id(), in_progress.get_id())
var inventory = ["sword", "shield"]func has_key() -> bool: return "key" in inventoryfunc _setup() -> void: add_text_entry("The door is locked.") var key_check = add_conditional_entry(has_key) var with_key = add_text_entry("You unlock the door with your key.") var no_key = add_text_entry("You need a key to open this door.") key_check.set_condition_goto_ids(with_key.get_id(), no_key.get_id())
func is_daytime() -> bool: var hour = Time.get_time_dict_from_system()["hour"] return hour >= 6 and hour < 18func _setup() -> void: var time_check = add_conditional_entry(is_daytime) var day = add_text_entry("Good morning!") var night = add_text_entry("Good evening!") time_check.set_condition_goto_ids(day.get_id(), night.get_id())
The dialogue debugger shows conditional entries as special nodes in the graph, making it easy to visualize branching logic.
Conditions can be complex, so consider adding debug logging:
func check_complex_condition() -> bool: var result = (gold >= 100 and reputation >= 50) or has_special_item if OS.is_debug_build(): print("Condition result: ", result) return result