aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Metin2

Dialogue PNJ Metin2 : ramifier avec select et confirm

Un dialogue PNJ Metin2 commence dès qu'un joueur ouvre la fenêtre de discussion avec un PNJ, et bien conçu, il ressemble à une petite histoire. Afficher une seule ligne de texte est facile ; le vrai travail consiste à proposer des choix au joueur et à ramifier la conversation selon la décision qu'il prend. Dans cet article, je détaille pas à pas la création de menus à choix multiples avec select, de fenêtres oui/non avec confirm, et la façon de les combiner dans une quête Lua propre et fonctionnelle.

Le squelette de base d'un dialogue

Chaque conversation avec un PNJ s'ouvre avec un déclencheur chat. Tu indiques le vnum du PNJ, tu donnes un titre à la fenêtre et tu déroules le texte ligne par ligne avec les fonctions say.

quest dialogue_villageois begin
    state start begin
        when 9003.chat."Parler au villageois" begin
            say_title("Vieux villageois")
            say("Bienvenue, voyageur.")
            say("")
            say("Qu'est-ce qui t'amène ici ?")
        end
    end
end

Ici, 9003 est le vnum du PNJ, say_title est l'en-tête de la fenêtre de dialogue, et say est le corps du texte. Un say("") vide sert à laisser une ligne blanche. Ce bloc est à sens unique : le joueur se contente de lire et clique sur « Fermer ». Pour ajouter de l'interaction, il faut passer aux mécanismes de sélection.

Menus à choix multiples avec select

select affiche au joueur une liste de boutons et renvoie l'indice de l'option choisie (à partir de 1). Tu récupères la valeur renvoyée dans une variable et tu ramifies avec if / elseif.

when 9003.chat."Parler au villageois" begin
    say_title("Vieux villageois")
    say("Comment puis-je t'aider ?")
    say("")
    local choix = select("Donne-moi une quête", "Acheter des biens", "Raconte ton histoire", "Laisse tomber")

    if choix == 1 then
        say("Alors écoute : débarrasse la forêt des loups.")
    elseif choix == 2 then
        say("Hélas, il ne me reste rien à vendre.")
    elseif choix == 3 then
        say("Il y a des années, ce village était bien différent...")
    else
        say("Bon voyage.")
    end
end

Quelques points à surveiller : en pratique, select reste confortable jusqu'à 6-7 options ; au-delà, elles ne tiennent plus dans la fenêtre de dialogue. Faire de la dernière option une sortie « Laisse tomber » est une bonne habitude, pour que le joueur ne reste jamais coincé dans le menu. Stocke toujours la valeur renvoyée dans une variable local, car si tu appelles un second select, la valeur précédente est perdue.

Confirmation oui/non avec confirm

Avant une action irréversible (supprimer un objet, se téléporter, dépenser des yang), tu veux demander confirmation au joueur. confirm("texte") sert exactement à cela : il ouvre une fenêtre « Oui / Non » au joueur et renvoie true s'il accepte et false s'il refuse.

when 9003.chat."Se téléporter en ville" begin
    say_title("Vieux villageois")
    say("Veux-tu que je t'envoie en ville ?")
    say("Cela coûte 50 000 yang.")
    say("")

    if confirm("Veux-tu te téléporter en ville ?") then
        if pc.get_money() >= 50000 then
            pc.change_money(-50000)
            pc.warp(469000, 964000)
        else
            say("Tu n'as pas assez de yang.")
        end
    else
        say("Une autre fois peut-être.")
    end
end

confirm peut être utilisé directement dans une condition if puisqu'il renvoie un booléen. Certaines versions proposent aussi confirm_with_button("question", "Libellé oui", "Libellé non") pour un texte de bouton personnalisé ; cependant, comme sa disponibilité dépend de ta source, reste sur le confirm standard si tu veux préserver la portabilité.

Enchaîner select et confirm

La vraie puissance apparaît quand tu imbriques les deux. Le joueur choisit d'abord dans un menu select, puis valide sa décision finale avec confirm à l'étape critique. Voici un exemple de PNJ coffre à récompenses :

when 9003.chat."Coffre à récompenses" begin
    say_title("Coffre mystérieux")
    say("Choisis une récompense à l'intérieur, mais sois prudent.")
    say("Aucun retour en arrière après ton choix.")
    say("")
    local recompense = select("Épée", "Armure", "Yang", "Plus tard")

    if recompense == 4 then
        say("Le coffre s'est refermé.")
        return
    end

    if not confirm("Es-tu sûr de ton choix ?") then
        say("Tu as hésité un instant devant le coffre.")
        return
    end

    if recompense == 1 then
        pc.give_item2(11209, 1)
        say("Tu as gagné une épée tranchante !")
    elseif recompense == 2 then
        pc.give_item2(11949, 1)
        say("Tu as gagné une armure solide !")
    elseif recompense == 3 then
        pc.change_money(500000)
        say("Tu as gagné 500 000 yang !")
    end
end

Trois techniques fonctionnent ensemble ici : select détermine la branche, un return anticipé gère proprement le cas « plus tard », et confirm place une dernière barrière de sécurité avant de remettre la récompense irréversible. Utiliser return évite les imbrications profondes de if et garde le code lisible.

Rendre le texte dynamique

Le texte statique devient vite ennuyeux. Pour insérer le nom du joueur, son niveau ou le nombre d'objets dans le texte, utilise la concaténation de chaînes à l'intérieur de say. En Lua, l'opérateur de concaténation est deux points (..).

when 9003.chat."Saluer" begin
    say_title("Vieux villageois")
    say("Bonjour "..pc.get_name()..", content de te voir.")
    say("Tu es niveau "..pc.get_level()..", tu as progressé vite.")
end

Ainsi, le même dialogue paraît personnel à chaque joueur. Quand tu insères des valeurs numériques (pc.get_level()) dans le texte, Lua les convertit automatiquement, tu n'as même pas besoin d'appeler tostring().

Erreurs courantes et astuces

  • Oublier de vérifier le résultat de select : le joueur peut fermer la fenêtre avec ÉCHAP ; définis une branche pour chaque option plus une sortie « laisse tomber ».
  • Écrire confirm comme un simple if et oublier les parenthèses : confirm(...) a toujours besoin d'un argument texte, ne le laisse pas vide.
  • Chaînes de say trop longues : après 4-5 lignes, affiche un bouton « Continuer » avec wait() ; sinon la fenêtre de texte déborde.
  • Caractères spéciaux : enregistre les fichiers de quête dans l'encodage attendu par le serveur (généralement UTF-8 ou la locale correspondante) ; un mauvais encodage apparaît comme des caractères corrompus dans le dialogue.
  • N'oublie pas de compiler et de recharger la quête après une modification ; sinon le game core continue d'afficher l'ancien texte.

Questions fréquentes

Combien d'options select prend-il en charge ?

Il n'y a pas de limite technique stricte, mais en pratique 6-7 options tiennent confortablement dans la fenêtre de dialogue. Si tu en as besoin de plus, répartis les options en catégories : affiche les groupes dans le premier menu, puis ouvre un second select selon le groupe choisi. C'est plus propre et reste lisible.

Puis-je changer le texte des boutons de la fenêtre confirm ?

Le confirm standard utilise des boutons « Oui/Non » fixes. Certaines sources incluent une version étendue qui permet de définir un texte de bouton personnalisé, mais cela dépend de ta version. Pour la portabilité, le plus sûr est de formuler clairement la vraie question avec say et de garder confirm simple.

Puis-je utiliser le résultat de select directement dans un if ?

Tu peux, mais ce n'est pas recommandé. select affiche le menu et renvoie la valeur ; si tu répètes le même appel dans deux branches if, le menu s'ouvre deux fois. Récupère plutôt le résultat dans une variable local, puis compare cette variable.

Bloqué sur les dialogues PNJ ? Si tu as besoin d'aide pour des chaînes de quêtes ramifiées, des systèmes de dialogue à plusieurs étapes ou la conception de menus pour ton serveur, contacte-moi — construisons-le ensemble.

Bu kategorideki tüm yazılar →

Devamı için