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

Création de donjon Metin2 : concevoir un donjon en Lua

La création de donjon Metin2 est le moyen d'offrir aux joueurs une expérience de carte privée, jouée en groupe, où les monstres arrivent par vagues et où un boss accompagné de récompenses attend à la fin. Dans ce guide, je détaille la construction d'un donjon de A à Z — conditions d'entrée, téléportation des joueurs dans la carte, système de vagues, phase de boss, limite de temps et distribution des récompenses — le tout avec le moteur de quêtes Lua. L'objectif n'est pas le copier-coller, mais comprendre la logique pour concevoir ton propre contenu.

Comment fonctionne un donjon ?

Dans Metin2, un donjon est en réalité une instance de carte créée spécifiquement pour un joueur ou un groupe. Alors que les cartes normales sont partagées par tous, un donjon apparaît comme une copie distincte pour chaque groupe : deux groupes différents jouent ainsi le même donjon sans se voir. La couche qui crée et gère cette instance est l'espace de noms d. (dungeon) du moteur de quêtes.

  • PNJ ou objet d'entrée — interagir avec lui déclenche le donjon.
  • Index de carte (map_index) — le numéro de la carte vide sur laquelle tourne le donjon ; il doit être défini dans le fichier index.
  • Fichiers de regen/spawn — des fichiers texte décrivant à quel endroit les monstres apparaissent.
  • Flags de donjon — des compteurs propres à ce donjon (monstres restants, numéro de vague, heure de départ) conservés avec d.setf/d.getf.

La distinction clé : les données liées au joueur sont stockées avec pc.setqf, et celles liées à l'instance du donjon avec d.setf. Comme le nombre de vagues concerne tout le groupe, il appartient au donjon, tandis que la progression personnelle est écrite sur le joueur.

Conditions d'entrée et téléportation

Un bon donjon se franchit à des conditions équitables. Vérifications typiques : un niveau minimum, l'exigence d'être chef de groupe, un temps de recharge (cooldown) et, au besoin, une clé. L'exemple ci-dessous vérifie les conditions lorsqu'un joueur parle à un PNJ d'entrée et téléporte le groupe dans une nouvelle instance :

quest dungeon_entree begin
    state start begin
        when 20355.chat."Entrer dans le donjon" begin
            if pc.get_level() < 40 then
                say("Il faut etre au moins niveau 40 pour entrer.")
                return
            end
            if party.is_party() and not party.is_leader() then
                say("Seul le chef de groupe peut ouvrir le donjon.")
                return
            end
            -- creer une nouvelle instance et teleporter le groupe
            d.new_jump_party(NEW_DUNGEON_MAP_INDEX, 32000, 32000)
        end
    end
end

Ici d.new_jump_party crée une instance de carte neuve et déplace tout le groupe à la coordonnée donnée. Pour un donjon solo, utilise plutôt d.new_jump_all. Les coordonnées sont les coordonnées locales de la carte, pas les coordonnées globales couvrant tout le monde.

Mettre en place le système de vagues

Le cœur d'un donjon est le système de vagues : un groupe de monstres apparaît, la vague suivante arrive une fois tous morts, et le boss apparaît en dernier. La logique de base comporte deux parties — l'apparition (d.spawn_mob / d.regen_file) et le comptage (passer à l'étape suivante quand il ne reste aucun monstre). Ici le flag propre au donjon d.setf("wave", n) sauve la mise.

-- s'execute a la creation de l'instance de carte
when <map_index>.enter begin
    d.setf("wave", 1)
    d.notice("La vague 1 commence !")
    d.spawn_mob(101, 32000, 32000)
    d.spawn_mob(101, 32050, 32010)
    d.spawn_mob(101, 31980, 32030)
end

-- se declenche chaque fois qu'un monstre du donjon meurt
when kill begin
    if d.count_monster() > 0 then return end  -- des monstres restent
    local wave = d.getf("wave")
    if wave == 1 then
        d.setf("wave", 2)
        d.notice("Vague 2 en approche !")
        d.spawn_mob(102, 32000, 32000)
        d.spawn_mob(102, 32040, 32020)
    elseif wave == 2 then
        d.setf("wave", 3)
        d.notice("Le boss est apparu !")
        d.set_unique("boss", d.spawn_mob(2493, 32000, 32000))
    end
end

d.count_monster() renvoie le nombre de monstres restant sur la carte ; quand il atteint zéro, tu déclenches la vague suivante. Nommer le boss avec d.set_unique est important pour pouvoir le suivre séparément — on y vient juste après.

La phase de boss et la fin du donjon

La dernière vague fait généralement apparaître un seul boss. Quand ce boss meurt, le donjon est terminé avec succès : les récompenses sont accordées, un court compte à rebours s'affiche et les joueurs sont téléportés dehors. Comme nous avons étiqueté le boss avec d.set_unique, nous pouvons capter sa mort précise avec d.is_unique_dead.

when kill with d.is_unique_dead("boss") begin
    d.notice("Donjon termine ! Felicitations.")
    -- recompense : yang et un objet pour tout le groupe
    d.kill_all()                      -- nettoyer ce qui reste
    d.spawn_mob(20356, 32000, 32000)  -- PNJ coffre de recompense
    d.exit_all_at_time(10)            -- teleporter tout le monde apres 10 s
end

Ici d.kill_all() élimine les monstres restants, tandis que d.exit_all_at_time téléporte tous les joueurs après le nombre de secondes indiqué. Pour distribuer la récompense directement, parcours les membres du groupe à la mort du boss et donne le butin via pc.give_item2 ou tes réglages mob_drop.

Limite de temps et condition d'échec

Les donjons gagnent en intensité grâce à la pression du temps. Place un compte à rebours ; à son expiration le donjon est considéré comme échoué et les joueurs sont expulsés. Le minuteur du moteur de quêtes est idéal pour cela :

when <map_index>.enter begin
    -- demarrer un minuteur de 15 minutes
    d.set_warp_location(NEW_DUNGEON_MAP_INDEX, 32000, 32000)
    server_timer("dungeon_timeout", 60 * 15, get_server_timer_arg())
end

when dungeon_timeout.server_timer begin
    d.notice("Temps ecoule ! Donjon echoue.")
    d.exit_all()
end

Pour afficher le minuteur via un compteur d'interface, tu peux envoyer aux joueurs un appel de type d.set_timer ou des avertissements périodiques via notice. L'essentiel est de penser à annuler le minuteur dès la réussite (la mort du boss) ; sinon un message « temps écoulé » tombe après que la récompense a déjà été obtenue.

Erreurs fréquentes

  • Mauvais système de coordonnées : donner des coordonnées globales fait tomber le joueur hors de la carte ou au mauvais endroit. Utilise toujours des coordonnées locales pour les téléportations à l'intérieur du donjon.
  • Erreur de comptage : si tu décrémentes ton propre compteur à la main au lieu d'utiliser d.count_monster(), le compte dérive quand un monstre meurt de façon inattendue (par ex. dégâts de chute). Quand c'est possible, fie-toi à la valeur comptée par le moteur.
  • Fuite d'instance : si l'instance du donjon n'est pas nettoyée quand le groupe part ou se dissout, des cartes vides s'accumulent. La mort du boss et l'expiration du temps doivent toutes deux fermer leur sortie avec d.exit_all.
  • Confusion de flags : si tu stockes le numéro de vague avec pc.setqf, il est compté séparément par joueur et le système casse. La vague appartient au donjon → d.setf.

Questions fréquentes

Faut-il une carte toute neuve pour un donjon ?

Il te faut un index de carte sur lequel le donjon tourne, mais ce n'est pas forcément une carte dessinée de zéro ; tu peux réserver une zone vide existante comme carte de donjon. Ce qui compte, c'est que l'index soit défini pour être dupliqué en instance.

Puis-je faire un donjon solo et un donjon de groupe avec le même code ?

Oui. Dans la partie entrée, fais un branchement avec party.is_party() et appelle d.new_jump_party pour un groupe et d.new_jump_all pour un joueur seul. La logique des vagues et du boss reste identique ; il suffit d'adapter le nombre de monstres/la difficulté à la taille du groupe.

Comment protéger les récompenses contre les abus ?

N'accorde la récompense qu'à l'intérieur du déclencheur de mort du boss, après avoir marqué le flag du donjon comme « terminé ». Bloque un second versement dans la même instance avec un contrôle d.getf("done"), et ajoute un cooldown d'entrée en plus du minuteur.

Tu veux un donjon entièrement équilibré et inviolable pour ton serveur ? Je peux construire et tester l'ensemble — des conditions d'entrée à la logique des vagues et du boss, en passant par le système de récompenses et de temps. Pour discuter de ton projet, contacte-moi.

Devamı için