Înapoi la blogToate tutorialele Metin2
Tutoriale Metin2 · Lecția 59 din 99

Quest flag-uri și condiții de nivel în Metin2: cum ține minte un quest ce a făcut jucătorul

2 noiembrie 2026 7 min de citit

Un quest are nevoie de memorie. Trebuie să știe dacă jucătorul a acceptat misiunea, câți monștri a omorât, dacă a luat deja recompensa, când a făcut-o ultima dată. Toată această memorie se ține în **quest flag-uri**. În lecțiile anterioare le-ai folosit deja (`ucisi`, `primit`). Acum le înțelegem complet, împreună cu condițiile de nivel, și construim o misiune care se poate face o dată la 24 de ore.

Pe scurt: pc.setqf("nume", valoare) salvează un număr pentru jucător în questul curent, pc.getqf("nume") îl citește (0 dacă nu există). Condițiile de nivel le pui în with pc.get_level() >= X și le verifici din nou înainte de recompensă. Flag-urile se scriu doar din acțiuni în joc, niciodată în when login.

Cuvinte pe care le vei întâlni

CuvântCe înseamnă
Quest flagUn număr întreg salvat pentru un jucător, legat de un quest.
Event flagUn număr salvat pentru tot serverul, nu pentru un jucător. Îl folosim la evenimente.
TimestampUn moment în timp scris ca număr de secunde. get_time() îți dă momentul de acum.
CooldownTimpul de așteptare până poți repeta ceva.

Trei feluri de „memorie” într-un quest

Ce foloseștiPentru cine ține minteExemplu
pc.setqf / pc.getqfUn jucător, în questul curentCâți lupi a omorât
pc.setf / pc.getfUn jucător, dar în alt questAi terminat misiunea „gheare_lup”?
game.set_event_flag / game.get_event_flagTot serverulEvenimentul e pornit?
set_state(...)Un jucător: etapa questului„vânează”, „predă”, „terminat”

Toate funcțiile de mai sus există în lista quest_functions a pachetului de referință. Event flag-urile le folosim în lecțiile despre NPC-ul care pornește un eveniment și evenimentul cu timer.

Cum se salvează un flag (și de ce nu redenumești questul)

În pachetul verificat, flag-ul se salvează în baza de date, în tabelul quest din baza player, sub numele questului plus numele flag-ului. Concret, pc.setqf("ucisi", 7) în questul vanatoare_lupi devine „vanatoare_lupi, ucisi, 7” pentru acel personaj.

Asta are trei urmări practice:

  1. Dacă redenumești questul, jucătorii își pierd progresul. Noul nume nu are niciun flag salvat.
  2. Flag-urile sunt numere întregi. Nu poți salva text. Pentru „da/nu” folosești 1 și 0.
  3. Valoarea 0 înseamnă „nimic”. În același pachet, un flag cu valoarea 0 este șters din baza de date, iar pc.getqf pe un flag inexistent întoarce 0. Deci „nesetat” și „0” sunt același lucru.

Păstrează numele scurte și fără spații sau diacritice: ucisi, primit, urmatoarea. În sursa verificată, numele questului are cel mult 32 de caractere.

Condițiile de nivel

Ai două locuri unde poți pune o condiție.

În rândul when, cu with: opțiunea nici nu apare dacă condiția nu e îndeplinită.

lua
when 20011.chat."Misiunea zilnica" with pc.get_level() >= 20 and pc.get_level() <= 60 begin

În interiorul blocului, cu if: opțiunea apare, dar NPC-ul îi explică jucătorului de ce nu poate.

lua
if pc.get_level() < 20 then
    say("Revino cand ai nivelul 20.")
    return
end

A doua variantă e mai prietenoasă: jucătorul află că misiunea există. Vei vedea în questurile din pachet și forma scurtă pc.level; în questlib.lua ea înseamnă exact pc.get_level().

Capcana levelup: questurile din pachet folosesc des when levelup with pc.level >= 30. Acest eveniment pornește doar în momentul în care jucătorul urcă un nivel. Un jucător care era deja la nivelul 45 când ai adăugat questul nu va declanșa nimic până la următorul nivel. Pentru misiunile noi, o condiție verificată la NPC e mai sigură.

Codul: misiune zilnică, pentru nivelurile 20–60

Jucătorul omoară 20 de Lupi albaștri (monstrul 104 în pachetul verificat), primește 20.000 yang și poate repeta misiunea după 24 de ore.

lua
quest zilnica_lupi begin
    state start begin
        when 20011.chat."Misiunea zilnica" with pc.get_level() >= 20 and pc.get_level() <= 60 begin
            say_title("Misiunea zilnica")
            local ramas = pc.getqf("urmatoarea") - get_time()
            if ramas > 0 then
                say(string.format("Revino peste %d minute.", math.ceil(ramas / 60)))
                return
            end
            if pc.getqf("activa") == 0 then
                say("Omoara 20 de Lupi albastri si revino.")
                pc.setqf("ucisi", 0)
                pc.setqf("activa", 1)
                return
            end
            if pc.getqf("ucisi") < 20 then
                say(string.format("Ai omorat %d din 20.", pc.getqf("ucisi")))
                return
            end
            pc.setqf("activa", 0)
            pc.setqf("urmatoarea", get_time() + 86400)
            pc.change_money(20000)
            say("Bravo! Iata 20.000 yang. Revino maine.")
        end

        when 104.kill with pc.getqf("activa") == 1 begin
            local n = pc.getqf("ucisi")
            if n < 20 then
                pc.setqf("ucisi", n + 1)
            end
        end
    end
end

Explicat rând cu rând

RândCe înseamnă
with pc.get_level() >= 20 and pc.get_level() <= 60Opțiunea apare doar între nivelurile 20 și 60. and înseamnă „și”.
local ramas = pc.getqf("urmatoarea") - get_time()urmatoarea ține momentul de la care se poate repeta. Scădem momentul de acum: rezultatul e câte secunde mai sunt.
if ramas > 0 thenDacă încă n-a trecut timpul, îi spunem cât mai are și ne oprim. La prima vizită flag-ul e 0, deci ramas e negativ și trecem mai departe.
math.ceil(ramas / 60)Transformă secundele în minute, rotunjind în sus.
if pc.getqf("activa") == 0 thenN-a pornit încă misiunea azi: o pornim.
pc.setqf("ucisi", 0) și pc.setqf("activa", 1)Resetăm numărătoarea și marcăm misiunea ca activă.
if pc.getqf("ucisi") < 20 thenÎncă n-a terminat: îi arătăm progresul.
pc.setqf("activa", 0)Închidem misiunea înainte de recompensă.
pc.setqf("urmatoarea", get_time() + 86400)Următoarea dată posibilă: acum plus 86.400 de secunde (24 de ore).
pc.change_money(20000)Recompensa.
when 104.kill with pc.getqf("activa") == 1Lupii albaștri se numără doar cât timp misiunea e activă.

Aici n-am folosit etape (state), ci doar flag-uri: activa face aceeași treabă. Ambele variante sunt corecte. Etapele sunt mai clare pentru misiuni cu mulți pași; flag-urile sunt mai simple pentru misiuni repetabile.

Pachetul de referință folosește exact același model de „pauză” în misiunile de colectare ale biologului: un flag duration cu get_time() plus un număr de secunde.

Regula de aur: flag-urile nu se scriu la logare

Nu pune niciodată pc.setqf (și nici pc.setf) în when login. Există o problemă cunoscută în motorul Metin2: scrierea de quest flag-uri în timpul intrării în joc poate strica flag-urile jucătorului sau tabelul quest din baza de date. Vei vedea în pachet questuri care fac lucruri la login, de exemplu afișează scrisori. Afișarea e în regulă. Scrierea de flag-uri o faci doar din acțiuni în joc: dialog cu un NPC, un monstru omorât, un item folosit.

Dacă vrei „cadou la prima logare”, pune-l la un NPC din sat, cu o condiție pc.getqf("primit") == 0, ca în lecția despre recompense în inventar.

Testează

  1. Cu un personaj de nivel 19: opțiunea nu apare. La nivel 61, la fel.
  2. Pornește misiunea, omoară 5 lupi, ieși din joc, revino: trebuie să scrie 5 din 20.
  3. Termină misiunea și vorbește din nou cu NPC-ul: trebuie să-ți spună câte minute mai ai.
  4. Pe serverul de test, ca să nu aștepți 24 de ore, poți schimba temporar 86400 în 120 (2 minute). Nu uita să-l pui la loc înainte de a publica.

Greșeli des întâlnite

  • Flag scris în when login. Risc de date de quest stricate.
  • Questul redenumit după lansare. Toți jucătorii pierd progresul.
  • Condiție de nivel doar în with, nu și la recompensă, într-o misiune lungă. Pentru limite superioare (de exemplu „doar până la 60”), un jucător poate accepta la 59 și preda la 65. Decide dacă te deranjează și verifică din nou la predare.
  • Testul de 2 minute rămas pe serverul live. Misiunea zilnică devine „la fiecare 2 minute”.

Întrebări frecvente

Cum resetez misiunea pentru un singur jucător?

Pe serverul de test, cel mai sigur e din quest: o opțiune vizibilă doar pentru GM care pune flag-ul la 0. Nu edita tabelul quest pe serverul live cât timp jucătorul e conectat, pentru că serverul ține flag-urile și în memorie.

Pot citi flag-ul altui quest?

Da: pc.getf("gheare_lup", "nume_flag") citește un flag din questul gheare_lup. Util pentru „misiunea asta apare doar dacă ai terminat-o pe cealaltă”.

Ce e pc.delqf?

Șterge un flag din questul curent. În practică, pc.setqf("nume", 0) are același efect și e mai ușor de citit.

Ce urmează

Până acum am ținut minte lucruri pentru fiecare jucător. Următorul pas e memoria pentru tot serverul: un NPC care pornește un eveniment.

Toate lecțiile sunt în lista tutorialelor Metin2.

Server Metin2 gata de joc

Găzduire Metin2 în România, cu instalare de serverfiles, bază de date MySQL și protecție Anti-DDoS inclusă.

DiscordWhatsApp