De Metin2 quest timer is een van de krachtigste — en vaakst verkeerd gebruikte — onderdelen van het quest-systeem: hij laat je een gebeurtenis niet meteen, maar na een vastgestelde tijd activeren. Of je nu een aftel-quest wilt, een waarschuwing die zich met tussenpozen herhaalt, een boss-respawnvertraging, of een cooldown zoals "je kunt deze beloning eens per 24 uur ophalen" — timers vormen de kern van dit alles. In dit artikel lopen we stap voor stap door de twee belangrijkste timermechanismen in de Metin2 quest-engine: de aan de speler gebonden q.start_timer en de globale server_timer, met echte, werkende voorbeelden.
Wat een quest timer is en hoe hij werkt
De quest-engine is gebeurtenisgestuurd: when ... begin ... end-blokken reageren op specifieke gebeurtenissen (chat, kill, login). Een timer voegt een "vertraging" toe aan die logica. Wanneer je een timer start, registreert de engine hem, en bij afloop genereert hij een speciale gebeurtenis — die je opnieuw met een when-blok opvangt. Er zijn twee soorten:
- Aan de speler gebonden timer (
q.start_timer): de timer hoort bij een specifiek personage. Wanneer hij afgaat, draait het blok in de context van die speler, dus je kuntpc.*-functies rechtstreeks aanroepen. - Globale server timer (
server_timer): de timer hoort bij de server, niet bij een speler. Ideaal voor taken die aan niemand gebonden zijn, zoals boss-respawns of map-events.
Een aan de speler gebonden timer met q.start_timer
Dit is het meest voorkomende scenario: een speler praat met een NPC, en X seconden later gebeurt er iets. Je start hem met q.start_timer("naam", seconden) en vangt het resultaat op in een when naam.timer-blok.
quest geschenkdoos begin
state start begin
when 20095.chat."Open de doos" begin
say_title("Handelaar:")
say("De doos gaat over 10 seconden open, wacht...")
q.start_timer("open_doos", 10)
end
when open_doos.timer begin
say("De doos is open! Hier is je beloning.")
pc.give_item2(27003, 1) -- voorbeeld item-vnum
pc.give_exp2(5000)
end
end
end
Het belangrijkste punt: het open_doos.timer-blok draait al in de context van de juiste speler, omdat we de timer voor die speler hebben gestart. Als je q.start_timer opnieuw aanroept met een naam die al bestaat, wordt de oude door de nieuwe vervangen, wat handig per ongeluk dubbel afgaan voorkomt.
Globale vertraagde events met server_timer
Stel dat je wilt dat een boss een uur na zijn dood respawnt. Dat heeft niets met een specifieke speler te maken, dus gebruik je server_timer. De signatuur is server_timer("naam", seconden, arg). Je kunt een VID of getal als derde parameter meegeven en het teruglezen met get_server_timer_arg() wanneer de timer afgaat.
quest boss_respawn begin
state start begin
when 6091.kill begin
-- Boss dood, na 1 uur respawnen
local map_index = pc.get_map_index()
server_timer("boss_terug", 60 * 60, map_index)
notice_all("De boss is gevallen! Hij keert over 1 uur terug.")
end
when boss_terug.server_timer begin
local map_index = get_server_timer_arg()
regen_in_map(map_index, "data/boss_regen.txt")
notice_all("De boss is gerespawnd!")
end
end
end
Binnen een server_timer-blok is er geen standaard spelercontext. Als je op een specifieke speler moet inwerken, draag dan zijn PID via het argument mee en gebruik het patroon q.begin_other_pc_block(pid) ... q.end_other_pc_block().
Het cooldown-patroon
Timers zijn voor dingen die "binnenkort" afgaan, maar een blijvende cooldown zoals "haal deze beloning eens per 24 uur op" moet zelfs een serverherstart overleven. De juiste manier is geen timer, maar een tijdstempel in een spelerflag schrijven. get_global_time() geeft de huidige servertijd in seconden; je slaat die op met pc.setqf en vergelijkt later.
quest dagelijkse_beloning begin
state start begin
when 20095.chat."Dagelijkse beloning" begin
local now = get_global_time()
local last = pc.getqf("laatste_beloning")
local cooldown = 24 * 60 * 60 -- 24 uur
if now - last < cooldown then
local resterend = cooldown - (now - last)
say("Wacht nog " .. math.floor(resterend / 3600) .. " uur op de volgende beloning.")
return
end
pc.setqf("laatste_beloning", now)
pc.give_item2(50300, 1)
say("Je dagelijkse beloning is klaar!")
end
end
end
Het verschil is cruciaal: q.start_timer gaat verloren bij een serverherstart, maar het tijdstempel in een flag blijft in de database. Geef voor blijvende cooldowns altijd de voorkeur aan dit patroon.
Herhalende timers en ze annuleren
Voor een taak die zich met tussenpozen herhaalt (bijvoorbeeld een waarschuwing elke 30 seconden) her-arm je de timer binnen zijn eigen blok. Wil je stoppen, dan doorbreek je de lus met een quest-flag — want als je hem simpelweg niet herstart, stopt de lus vanzelf.
quest teller begin
state start begin
when login begin
pc.setqf("ronde", 0)
q.start_timer("tik", 30)
end
when tik.timer begin
local ronde = pc.getqf("ronde") + 1
pc.setqf("ronde", ronde)
chat("Ronde: " .. ronde)
if ronde < 5 then
q.start_timer("tik", 30) -- her-armen = doorgaan
else
chat("Teller klaar.") -- niet her-armen = stoppen
end
end
end
end
Moet je een aan de speler gebonden timer vroegtijdig annuleren, dan wist q.clear_timer() de lopende timers. Gebruik voor een globale timer q.clear_server_timer("naam", arg).
Veelgemaakte fouten en tips
- Timernaam komt niet overeen met het when-blok: als je
q.start_timer("open_doos", 10)hebt gestart, moet het blokwhen open_doos.timerzijn. De namen moeten exact gelijk zijn. - Een timer gebruiken voor een blijvende cooldown: de timer wordt bij een serverherstart gewist. Gebruik voor lange, blijvende periodes het patroon
get_global_time()+ flag. - pc.* aanroepen binnen server_timer: er is geen speler in de globale context; draag de PID via het argument mee en ga een
q.begin_other_pc_block-blok binnen. - Heel korte intervallen: vermijd werk onder een seconde; de quest-engine draait op secondenresolutie, en te vaak afgaande timers schaden de prestaties.
- Controleer syserr: gaat een timer niet af zoals verwacht, kijk dan eerst in
syserr.txt— Lua-fouten verschijnen daar meestal.
Veelgestelde vragen
Wat is het verschil tussen q.start_timer en server_timer?
q.start_timer hoort bij een specifieke speler en het blok draait in zijn context; hij vervalt als het personage uitlogt. server_timer hoort bij de server, is aan niemand gebonden en wordt gebruikt voor globale events zoals boss-respawns.
Wat gebeurt er met timers als de server herstart?
Timers in het geheugen gaan verloren. Daarom moet je wachttijden van uren of dagen niet met een timer beheren, maar door get_global_time() in een spelerflag te schrijven; de flag blijft in de database bestaan.
Kan ik meerdere timers tegelijk draaien?
Ja, geef elk een andere naam. Een nieuwe timer met dezelfde naam starten annuleert de oude en armt de nieuwe, wat soms bewust als een "reset"-mechanisme wordt gebruikt.
Vastgelopen op het quest-systeem? Heb je hulp nodig bij Metin2 quest-ontwikkeling — timergebaseerde quests, dungeon-logica of eigen event-systemen — neem contact op en laten we je project samen oplossen.