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

Metin2 Quest Timer: gebruik en voorbeelden

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 kunt pc.*-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 blok when open_doos.timer zijn. 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.

Bu kategorideki tüm yazılar →

Devamı için