Der Metin2 Quest Timer ist einer der machtigsten — und am haufigsten falsch genutzten — Teile des Quest-Systems: Er erlaubt es, ein Ereignis nicht sofort, sondern nach einer festgelegten Zeit auszulosen. Ob du eine Countdown-Quest willst, eine Warnung, die sich in Intervallen wiederholt, eine Boss-Respawn-Verzogerung oder einen Cooldown wie "du kannst diese Belohnung einmal alle 24 Stunden abholen" — Timer bilden den Kern all dessen. In diesem Artikel gehen wir Schritt fur Schritt die beiden zentralen Timer-Mechanismen der Metin2 Quest-Engine durch: den an den Spieler gebundenen q.start_timer und den globalen server_timer, mit echten, funktionierenden Beispielen.
Was ein Quest Timer ist und wie er funktioniert
Die Quest-Engine ist ereignisgesteuert: when ... begin ... end-Blocke reagieren auf bestimmte Ereignisse (Dialog, Kill, Login). Ein Timer fugt dieser Logik eine "Verzogerung" hinzu. Wenn du einen Timer startest, registriert ihn die Engine, und bei Ablauf erzeugt er ein spezielles Ereignis — das du wieder mit einem when-Block abfangst. Es gibt zwei Arten:
- An den Spieler gebundener Timer (
q.start_timer): Der Timer gehort zu einem bestimmten Charakter. Wenn er auslost, lauft der Block im Kontext dieses Spielers, du kannst alsopc.*-Funktionen direkt aufrufen. - Globaler Server-Timer (
server_timer): Der Timer gehort dem Server, nicht einem Spieler. Ideal fur Aufgaben, die an niemanden gebunden sind, etwa Boss-Respawns oder Map-Events.
Ein an den Spieler gebundener Timer mit q.start_timer
Das ist das haufigste Szenario: Ein Spieler spricht mit einem NPC, und X Sekunden spater passiert etwas. Du startest ihn mit q.start_timer("name", sekunden) und fangst das Ergebnis in einem when name.timer-Block ab.
quest geschenkbox begin
state start begin
when 20095.chat."Box oeffnen" begin
say_title("Haendler:")
say("Die Box oeffnet sich in 10 Sekunden, warte...")
q.start_timer("box_oeffnen", 10)
end
when box_oeffnen.timer begin
say("Die Box ist offen! Hier ist deine Belohnung.")
pc.give_item2(27003, 1) -- Beispiel-Item-vnum
pc.give_exp2(5000)
end
end
end
Der entscheidende Punkt: Der box_oeffnen.timer-Block lauft bereits im Kontext des richtigen Spielers, weil wir den Timer fur diesen Spieler gestartet haben. Rufst du q.start_timer erneut mit einem bereits vorhandenen Namen auf, wird der alte durch den neuen ersetzt — das verhindert praktischerweise ein versehentliches doppeltes Auslosen.
Globale verzogerte Events mit server_timer
Angenommen, ein Boss soll eine Stunde nach seinem Tod respawnen. Das hat nichts mit einem bestimmten Spieler zu tun, also nutzt du server_timer. Die Signatur lautet server_timer("name", sekunden, arg). Du kannst als dritten Parameter eine VID oder Zahl ubergeben und sie beim Auslosen mit get_server_timer_arg() zuruucklesen.
quest boss_respawn begin
state start begin
when 6091.kill begin
-- Boss tot, nach 1 Stunde respawnen
local map_index = pc.get_map_index()
server_timer("boss_zurueck", 60 * 60, map_index)
notice_all("Der Boss ist gefallen! Er kehrt in 1 Stunde zurueck.")
end
when boss_zurueck.server_timer begin
local map_index = get_server_timer_arg()
regen_in_map(map_index, "data/boss_regen.txt")
notice_all("Der Boss ist respawnt!")
end
end
end
Innerhalb eines server_timer-Blocks gibt es keinen Standard-Spielerkontext. Musst du auf einen bestimmten Spieler einwirken, trage seine PID uber das Argument mit und nutze das Muster q.begin_other_pc_block(pid) ... q.end_other_pc_block().
Das Cooldown-Muster
Timer sind fur Dinge, die "bald" auslosen, aber ein dauerhafter Cooldown wie "diese Belohnung einmal alle 24 Stunden abholen" muss sogar einen Serverneustart uberleben. Der richtige Weg ist kein Timer, sondern das Schreiben eines Zeitstempels in ein Spieler-Flag. get_global_time() liefert die aktuelle Serverzeit in Sekunden; du speicherst sie mit pc.setqf und vergleichst spater.
quest taegliche_belohnung begin
state start begin
when 20095.chat."Taegliche Belohnung" begin
local now = get_global_time()
local last = pc.getqf("letzte_belohnung")
local cooldown = 24 * 60 * 60 -- 24 Stunden
if now - last < cooldown then
local rest = cooldown - (now - last)
say("Warte noch " .. math.floor(rest / 3600) .. " Stunden auf die naechste Belohnung.")
return
end
pc.setqf("letzte_belohnung", now)
pc.give_item2(50300, 1)
say("Deine taegliche Belohnung ist bereit!")
end
end
end
Der Unterschied ist entscheidend: q.start_timer geht beim Serverneustart verloren, aber der in ein Flag geschriebene Zeitstempel bleibt in der Datenbank. Bevorzuge fur dauerhafte Cooldowns immer dieses Muster.
Wiederholende Timer und ihr Abbrechen
Fur eine Aufgabe, die sich in Intervallen wiederholt (etwa eine Warnung alle 30 Sekunden), bewaffnest du den Timer innerhalb seines eigenen Blocks erneut. Willst du stoppen, durchbrichst du die Schleife mit einem Quest-Flag — denn wenn du ihn einfach nicht neu startest, stoppt die Schleife von selbst.
quest zaehler begin
state start begin
when login begin
pc.setqf("runde", 0)
q.start_timer("tick", 30)
end
when tick.timer begin
local runde = pc.getqf("runde") + 1
pc.setqf("runde", runde)
chat("Runde: " .. runde)
if runde < 5 then
q.start_timer("tick", 30) -- neu bewaffnen = weiter
else
chat("Zaehler beendet.") -- nicht neu bewaffnen = stopp
end
end
end
end
Musst du einen an den Spieler gebundenen Timer fruh abbrechen, loscht q.clear_timer() die laufenden Timer. Fur einen globalen Timer nutze q.clear_server_timer("name", arg).
Haufige Fehler und Tipps
- Timer-Name passt nicht zum when-Block: Hast du
q.start_timer("box_oeffnen", 10)gestartet, muss der Blockwhen box_oeffnen.timersein. Die Namen mussen exakt ubereinstimmen. - Einen Timer fur einen dauerhaften Cooldown nutzen: Der Timer wird beim Serverneustart geloscht. Nutze fur lange, dauerhafte Zeitraume das Muster
get_global_time()+ Flag. - pc.* innerhalb von server_timer aufrufen: Im globalen Kontext gibt es keinen Spieler; trage die PID uber das Argument mit und betritt einen
q.begin_other_pc_block-Block. - Sehr kurze Intervalle: Vermeide Arbeit unter einer Sekunde; die Quest-Engine lauft mit Sekundenauflosung, und zu haufig auslosende Timer schaden der Leistung.
- syserr prufen: Lost ein Timer nicht wie erwartet aus, sieh zuerst in
syserr.txtnach — Lua-Fehler erscheinen meist dort.
Haufig gestellte Fragen
Was ist der Unterschied zwischen q.start_timer und server_timer?
q.start_timer gehort zu einem bestimmten Spieler und der Block lauft in dessen Kontext; er fallt weg, wenn sich der Charakter ausloggt. server_timer gehort dem Server, ist an niemanden gebunden und wird fur globale Events wie Boss-Respawns genutzt.
Was passiert mit Timern, wenn der Server neu startet?
Timer im Speicher gehen verloren. Deshalb solltest du Wartezeiten von Stunden oder Tagen nicht mit einem Timer verwalten, sondern indem du get_global_time() in ein Spieler-Flag schreibst; das Flag bleibt in der Datenbank erhalten.
Kann ich mehrere Timer gleichzeitig laufen lassen?
Ja, gib jedem einfach einen anderen Namen. Einen neuen Timer mit demselben Namen zu starten bricht den alten ab und bewaffnet den neuen, was manchmal bewusst als "Reset"-Mechanismus genutzt wird.
Beim Quest-System festgefahren? Brauchst du Hilfe bei der Metin2 Quest-Entwicklung — timerbasierte Quests, Dungeon-Logik oder eigene Event-Systeme — melde dich und lass uns dein Projekt gemeinsam losen.