Metin2 Dungeon erstellen ist der Weg, Spielern ein privates Karten-Erlebnis zu bieten, das man als Gruppe betritt, bei dem Monster in Wellen anrücken und am Ende ein Boss mit Belohnungen wartet. In dieser Anleitung gehe ich den Aufbau eines Dungeons von Grund auf durch — Eintrittsbedingungen, das Teleportieren der Spieler in die Karte, das Wellensystem, die Boss-Phase, ein Zeitlimit und die Belohnungsverteilung — alles mit der Lua-Quest-Engine. Das Ziel ist kein Kopieren-Einfügen, sondern die Logik zu verstehen, damit du eigene Inhalte gestalten kannst.
Wie funktioniert ein Dungeon?
In Metin2 ist ein Dungeon eigentlich eine Karten-Instanz, die eigens für einen Spieler oder eine Gruppe erstellt wird. Während normale Karten von allen geteilt werden, entsteht ein Dungeon als separate Kopie für jede Gruppe, sodass zwei verschiedene Gruppen denselben Dungeon spielen, ohne sich zu sehen. Die Schicht, die diese Instanz erstellt und verwaltet, ist der d.-(Dungeon-)Namensraum in der Quest-Engine.
- Eintritts-NPC oder -Item — die Interaktion damit löst den Dungeon aus.
- Kartenindex (map_index) — die Nummer der leeren Karte, auf der der Dungeon läuft; sie muss in der
index-Datei definiert sein. - Regen-/Spawn-Dateien — Textdateien, die beschreiben, an welchem Punkt Monster spawnen.
- Dungeon-Flags — dungeon-spezifische Zähler (verbleibende Monster, Wellennummer, Startzeit), gehalten mit
d.setf/d.getf.
Die wichtige Unterscheidung: an den Spieler gebundene Daten werden mit pc.setqf gespeichert, an die Dungeon-Instanz gebundene Daten mit d.setf. Da die Wellenzahl die ganze Gruppe betrifft, gehört sie zum Dungeon, während der persönliche Fortschritt auf den Spieler geschrieben wird.
Eintrittsbedingungen und das Hineinteleportieren
Einen guten Dungeon betritt man zu fairen Bedingungen. Typische Prüfungen: ein Mindestlevel, die Voraussetzung, Gruppenleiter zu sein, eine Abklingzeit (Cooldown) und bei Bedarf ein Schlüssel-Item. Das Beispiel unten prüft die Bedingungen, wenn ein Spieler mit einem Eintritts-NPC spricht, und teleportiert die Gruppe in eine frische Dungeon-Instanz:
quest dungeon_eintritt begin
state start begin
when 20355.chat."Dungeon betreten" begin
if pc.get_level() < 40 then
say("Du musst mindestens Level 40 sein, um einzutreten.")
return
end
if party.is_party() and not party.is_leader() then
say("Nur der Gruppenleiter kann den Dungeon oeffnen.")
return
end
-- neue Instanz erstellen und die Gruppe teleportieren
d.new_jump_party(NEW_DUNGEON_MAP_INDEX, 32000, 32000)
end
end
end
Hier erstellt d.new_jump_party eine frische Karten-Instanz und bewegt alle in der Gruppe zur angegebenen Koordinate. Für einen Solo-Dungeon kannst du stattdessen d.new_jump_all verwenden. Die Koordinaten sind die lokalen Koordinaten der Karte, nicht die globalen Koordinaten, die die ganze Welt umspannen.
Das Wellensystem aufbauen
Das Herz eines Dungeons ist das Wellensystem: eine Gruppe Monster spawnt, die nächste Welle kommt, sobald alle tot sind, und der Boss erscheint zuletzt. Die Kernlogik hat zwei Teile — Spawnen (d.spawn_mob / d.regen_file) und Zählen (zum nächsten Schritt übergehen, wenn kein Monster mehr übrig ist). Hier ist das dungeon-spezifische Flag d.setf("wave", n) ein Lebensretter.
-- laeuft, wenn die Karten-Instanz erstellt wird
when <map_index>.enter begin
d.setf("wave", 1)
d.notice("Welle 1 beginnt!")
d.spawn_mob(101, 32000, 32000)
d.spawn_mob(101, 32050, 32010)
d.spawn_mob(101, 31980, 32030)
end
-- loest aus, wann immer ein Monster im Dungeon stirbt
when kill begin
if d.count_monster() > 0 then return end -- es leben noch Monster
local wave = d.getf("wave")
if wave == 1 then
d.setf("wave", 2)
d.notice("Welle 2 naht!")
d.spawn_mob(102, 32000, 32000)
d.spawn_mob(102, 32040, 32020)
elseif wave == 2 then
d.setf("wave", 3)
d.notice("Der Boss ist erschienen!")
d.set_unique("boss", d.spawn_mob(2493, 32000, 32000))
end
end
d.count_monster() liefert die Zahl der noch auf der Karte verbliebenen Monster; sobald sie null erreicht, löst du die nächste Welle aus. Den Boss mit d.set_unique zu benennen ist wichtig, um ihn separat verfolgen zu können — dazu kommen wir gleich.
Die Boss-Phase und den Dungeon abschließen
Die letzte Welle spawnt meist einen einzelnen Boss. Wenn dieser Boss stirbt, ist der Dungeon erfolgreich abgeschlossen: Belohnungen werden vergeben, ein kurzer Countdown wird gezeigt, und die Spieler werden hinausteleportiert. Da wir den Boss mit d.set_unique markiert haben, können wir seinen spezifischen Tod mit d.is_unique_dead abfangen.
when kill with d.is_unique_dead("boss") begin
d.notice("Dungeon abgeschlossen! Glueckwunsch.")
-- Belohnung: Yang und ein Item fuer die ganze Gruppe
d.kill_all() -- alles Uebrige beseitigen
d.spawn_mob(20356, 32000, 32000) -- Belohnungstruhen-NPC
d.exit_all_at_time(10) -- alle nach 10 s hinausteleportieren
end
Hier beseitigt d.kill_all() übrig gebliebene Monster, während d.exit_all_at_time alle Spieler nach der von dir angegebenen Sekundenzahl zurückteleportiert. Willst du die Belohnung direkt austeilen, durchlaufe beim Tod des Bosses die Gruppenmitglieder und lasse Beute über pc.give_item2 oder deine mob_drop-Einstellungen fallen.
Zeitlimit und Fehlschlagbedingung
Dungeons gewinnen durch Zeitdruck an Spannung. Setze einen Countdown; läuft er ab, gilt der Dungeon als gescheitert und die Spieler werden hinausgeworfen. Der Timer der Quest-Engine ist dafür ideal:
when <map_index>.enter begin
-- einen 15-Minuten-Timer starten
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("Zeit abgelaufen! Dungeon gescheitert.")
d.exit_all()
end
Willst du den Timer mit einem UI-Zähler anzeigen, kannst du den Spielern einen Aufruf im Stil von d.set_timer oder periodische Warnungen über notice senden. Wichtig ist, den Timer zu annullieren, sobald der Erfolg (der Tod des Bosses) eintritt; sonst kommt eine "Zeit abgelaufen"-Meldung herein, nachdem die Belohnung bereits abgeholt wurde.
Häufige Fehler
- Falsches Koordinatensystem: Gibst du globale Koordinaten an, fällt der Spieler außerhalb der Karte oder an die falsche Stelle. Verwende für Teleportationen innerhalb des Dungeons immer lokale Koordinaten.
- Zählfehler: Verringerst du deinen eigenen Zähler von Hand, statt
d.count_monster()zu nutzen, gerät die Zählung durcheinander, wenn ein Monster unerwartet stirbt (z. B. Fallschaden). Vertraue, wo möglich, dem von der Engine gezählten Wert. - Instanz-Leck: Wird die Dungeon-Instanz nicht bereinigt, wenn die Gruppe geht oder sich auflöst, häufen sich leere Karten an. Sowohl der Tod des Bosses als auch der Timeout müssen ihren Ausgang mit
d.exit_allschließen. - Flag-Verwechslung: Speicherst du die Wellennummer mit
pc.setqf, wird sie pro Spieler getrennt gezählt und das System bricht. Die Welle gehört zum Dungeon →d.setf.
Häufige Fragen
Brauche ich eine brandneue Karte für einen Dungeon?
Du brauchst einen Kartenindex, auf dem der Dungeon läuft, aber das muss keine von Grund auf gezeichnete Karte sein; du kannst ein bestehendes leeres Gebiet als Dungeon-Karte reservieren. Wichtig ist, dass der Index so definiert ist, dass er als Instanz dupliziert werden kann.
Kann ich Solo- und Gruppen-Dungeons aus demselben Code bauen?
Ja. Verzweige im Eintrittsteil mit party.is_party() und rufe d.new_jump_party für eine Gruppe und d.new_jump_all für einen Einzelspieler auf. Die Wellen- und Boss-Logik bleibt für beide identisch; du skalierst lediglich Monsteranzahl/Schwierigkeit an die Gruppengröße.
Wie schütze ich Belohnungen vor Missbrauch?
Vergib die Belohnung nur innerhalb des Boss-Tod-Auslösers, nachdem du das Dungeon-Flag als "abgeschlossen" markiert hast. Blockiere eine zweite Auszahlung in derselben Instanz mit einer d.getf("done")-Prüfung und füge neben dem Timer einen Eintritts-Cooldown hinzu.
Willst du einen vollständig ausbalancierten, exploit-sicheren Dungeon für deinen Server? Ich kann das Ganze aufbauen und testen — von den Eintrittsbedingungen über die Wellen- und Boss-Logik bis zum Belohnungs- und Zeitsystem. Um dein Projekt zu besprechen, nimm Kontakt mit mir auf.