Commands let your Yarn Scripts tell your game to do something. Functions let them ask your game for a value. The scene below uses both.
In the scene, Rosa hears the door, walks over to the lamp and lights it, then gives the player a key if they don’t already have one. The panel in the top left lists each Command and Function as the dialogue reaches it, with what each Function returned.
The Yarn Script
title: CommandsFunctionsDemo
---
<<play_sound door_creak>>
Rosa: Oh! You gave me a fright.
Rosa: The lamp's been out for {days_since_lamp_lit()} days.
<<move Rosa 640 430>>
Rosa: Let me get it going again.
<<light_lamp>>
Rosa: There. Much better.
<<if not has_item("brass key")>>
Rosa: You'll need this to get up the stairs.
<<give_item "brass key">>
<<endif>>
<<if has_item("brass key")>>
Rosa: Now you've got the key. Up you go!
<<endif>>
===days_since_lamp_lit() returns 12, which is shown in the line.has_item("brass key") returns false, so Rosa hands over the key.true, because the player now has the key.The game code
The script on the scene’s root node adds the Commands and Functions when the scene starts:
func _ready():
dialogue_runner.add_command("play_sound", _play_sound)
dialogue_runner.add_command("light_lamp", _light_lamp)
dialogue_runner.add_command("give_item", _give_item)
dialogue_runner.add_function("days_since_lamp_lit", _days_since_lamp_lit, 0)
dialogue_runner.add_function("has_item", _has_item, 1)The Commands are ordinary methods. _light_lamp returns its tween’s finished signal, which is what makes the dialogue wait for the lamp:
func _light_lamp() -> Signal:
var tween := create_tween()
tween.tween_property(lamp, "color", Color(1.0, 0.85, 0.35), 0.8)
tween.parallel().tween_property(glow, "modulate:a", 1.0, 0.8)
return tween.finished
func _give_item(item_name: String) -> void:
_inventory.append(item_name)
_update_inventory()Signal, so the dialogue waits._update_inventory redraws the inventory.The Functions return a value, and the Dialogue Runner hands it back to the Yarn Script:
func _days_since_lamp_lit() -> int:
var days := 12
_log_function("days_since_lamp_lit()", days)
return days
func _has_item(item_name: String) -> bool:
var result := item_name in _inventory
_log_function('has_item("%s")' % item_name, result)
return result_log_function writes the call to the panel in the top left.<<give_item>> adds to, so its answer changes once the key has been given.<<move>> isn’t added in _ready. It’s a _yarn_command_move method in the script attached to Rosa, which the Dialogue Runner finds by itself:
extends Node2D
func _yarn_command_move(x: float, y: float) -> Signal:
var tween := create_tween()
tween.tween_property(self, "position", Vector2(x, y), 1.0)
return tween.finishedstatic, so it’s a Command on a node. In Yarn, the first argument, Rosa, says which node to call it on. x and y come from the other two arguments, converted to float.finished signal, so the dialogue waits until the move is done.What it shows
Every Command in the scene changes something on screen. Two of them, <<move>> and <<light_lamp>>, return a signal, so the next line waits for them. <<play_sound>> and <<give_item>> return nothing, and the dialogue carries on without waiting.
Each Function returns a value the Yarn Script uses: days_since_lamp_lit() puts a number in a line, and has_item() picks which lines Rosa says. The second has_item() check gives a different answer from the first because <<give_item>> has changed the inventory it reads.