Utiliser Loreline avec Godot

Loreline fournit un plugin GDExtension pour Godot 4.2+. Ce guide montre comment configurer votre projet, charger un script .lor, et gérer les dialogues, les choix et la fin du script en GDScript.

Installation

Téléchargez loreline-godot.zip depuis la page des releases GitHub. L'archive contient :

Pour ajouter Loreline à votre projet, copiez le dossier addons/loreline/ dans le répertoire addons/ de votre propre projet Godot.

Charger un script

Récupérez l'instance partagée de Loreline, puis appelez loreline.parse() avec le chemin de la ressource vers votre fichier .lor :

var loreline: Loreline = Loreline.shared()

func _ready() -> void:
    var script_data: LorelineScript = loreline.parse("res://story/CoffeeShop.lor")

Loreline gère automatiquement la lecture du fichier et la résolution des import.

Chargement personnalisé

Si vous avez besoin de contrôler la façon dont les fichiers sont chargés (par ex. fichiers chiffrés, ressources réseau), vous pouvez charger la source vous-même et la passer à parse(). Le deuxième argument est le chemin du fichier (utilisé pour résoudre les chemins relatifs des import), et le troisième est un callback appelé pour charger chaque fichier importé par le script :

var file := FileAccess.open("res://story/CoffeeShop.lor", FileAccess.READ)
var source := file.get_as_text()
file.close()

script_data = loreline.parse(source, "res://story/CoffeeShop.lor", _handle_file)

Le callback de fichier n'est pas utilisé pour le fichier racine (que vous chargez vous-même), mais pour chaque fichier référencé via import dans le script. Il reçoit le chemin résolu et retourne le contenu sous forme de chaîne :

func _handle_file(path: String) -> String:
    var f := FileAccess.open(path, FileAccess.READ)
    if f == null:
        return ""
    return f.get_as_text()

Gérer les dialogues

Lancez la lecture en appelant loreline.play() avec le script parsé et vos callbacks :

loreline.play(script_data, _on_dialogue, _on_choice, _on_finished)

Le callback de dialogue reçoit l'interpréteur, l'identifiant du personnage, le texte, un tableau de tags et un callable pour faire avancer le script. Appelez advance.call() pour passer à la ligne suivante :

func _on_dialogue(interp: LorelineInterpreter, character: String, text: String, tags: Array, advance: Callable) -> void:
    if character != "":
        var display_name: String = interp.get_character_field(character, "name")
        if display_name != "":
            character = display_name
        print(character + " : " + text)
    else:
        print(text)

    advance.call()

Gérer les choix

Le callback de choix reçoit l'interpréteur, un tableau de dictionnaires d'options et un callable pour sélectionner une option. Chaque option a un champ "text" et un champ "enabled". Appelez select.call(index) avec l'index du choix sélectionné :

func _on_choice(_interp: LorelineInterpreter, options: Array, select: Callable) -> void:
    var enabled_indices: Array[int] = []
    for i in range(options.size()):
        if options[i]["enabled"]:
            enabled_indices.append(i)
            print("  [" + str(enabled_indices.size()) + "] " + options[i]["text"])

    # Dans un vrai projet, attendez ici l'entrée du joueur.
    # Pour cet exemple, on sélectionne automatiquement le premier choix disponible :
    select.call(enabled_indices[0])

Gérer la fin du script

Le callback de fin est appelé quand le script atteint sa fin :

func _on_finished(_interp: LorelineInterpreter) -> void:
    print("--- Fin ---")

Démarrer depuis un beat spécifique

Par défaut, play() démarre depuis le début du script. Pour démarrer depuis un beat spécifique, passez son nom :

loreline.play(script_data, _on_dialogue, _on_choice, _on_finished, "MorningScene")

Options de l'interpréteur

Vous pouvez passer des options supplémentaires à play() pour enregistrer des fonctions personnalisées, appliquer des traductions ou activer l'accès strict aux variables :

var options := LorelineOptions.new()
options.set_function("roll", func(interp, args): return randi_range(1, int(args[0])))
options.set_strict_access(true)

loreline.play(script_data, _on_dialogue, _on_choice, _on_finished, null, options)

Exemple complet

Voici un GDScript minimal qui charge et exécute un script Loreline en affichant la sortie dans la console. Attachez ce script à n'importe quel Node :

extends Node

var loreline: Loreline = Loreline.shared()

var awaiting_choice := false
var enabled_indices: Array[int] = []
var pending_select: Callable

func _ready() -> void:
    var script_data := loreline.parse("res://story/CoffeeShop.lor")

    if script_data:
        loreline.play(script_data, _on_dialogue, _on_choice, _on_finished)

func _on_dialogue(interp: LorelineInterpreter, character: String, text: String, _tags: Array, advance: Callable) -> void:
    if character != "":
        var display_name: String = interp.get_character_field(character, "name")
        if display_name != "":
            character = display_name
        print(character + " : " + text)
    else:
        print(text)
    print("")
    advance.call()

func _on_choice(_interp: LorelineInterpreter, options: Array, select: Callable) -> void:
    enabled_indices.clear()
    for i in range(options.size()):
        if options[i]["enabled"]:
            enabled_indices.append(i)
            print("  " + str(enabled_indices.size()) + ". " + options[i]["text"])
    pending_select = select
    awaiting_choice = true

func _unhandled_input(event: InputEvent) -> void:
    if not awaiting_choice:
        return
    if event is InputEventKey and event.pressed:
        var num := event.keycode - KEY_1
        if num >= 0 and num < enabled_indices.size():
            awaiting_choice = false
            pending_select.call(enabled_indices[num])

func _on_finished(_interp: LorelineInterpreter) -> void:
    print("\n--- Fin ---")

Aller plus loin

Pour un projet Godot complet avec UI, animations et sortie stylisée, le dossier sample/ inclus dans le téléchargement loreline-godot.zip depuis les releases GitHub fournit un exemple fonctionnel complet.