Misiunile de vânătoare sunt primele pe care le vrea orice server: „omoară 10 lupi și primești o recompensă”. Partea grea nu e să numeri lupii, ci să **ții minte** numărul. Dacă jucătorul iese din joc după 7 lupi, la revenire trebuie să vadă tot 7, nu 0. Iar recompensa trebuie să o primească o singură dată. În lecția asta facem împreună o astfel de misiune, completă, pornind de la ce ai învățat în [primul tău quest Lua](/blog/tutorial-quest-lua-metin2/).
pc.setqf (un „caiet de notițe” al fiecărui jucător), se citește cu pc.getqf, crește în evenimentul when 102.kill, iar questul trece prin etape (state) ca să nu poată fi luat sau predat de două ori.Cuvinte pe care le vei întâlni
| Cuvânt | Ce înseamnă |
|---|---|
| Quest flag | O valoare numerică salvată pentru un jucător, într-un anumit quest. Ca o notiță: „ucisi = 7”. |
pc.setqf / pc.getqf | Scrie, respectiv citește un quest flag. Valorile rămân salvate și după ieșirea din joc. |
| State (etapă) | Starea în care se află questul pentru un jucător: „neînceput”, „vânează”, „predă”. |
Eveniment kill | Momentul în care jucătorul omoară un monstru. Questul poate reacționa la el. |
| Scrisoare de quest | Iconița din stânga ecranului care îi amintește jucătorului ce are de făcut. |
Ce face misiunea noastră
- Jucătorul (nivel 5 sau mai mare) vorbește cu Uriel (NPC-ul
20011) și acceptă misiunea. - Omoară 10 lupi (monstrul
102, „Wolf” în pachetul verificat). La fiecare lup vede în chat „Lupi omorâți: 3/10”. - După al zecelea lup, se întoarce la Uriel și primește 5.000 yang.
- Misiunea nu mai poate fi făcută a doua oară.
VNUM-urile 20011 și 102 sunt cele din pachetul de referință. La tine verifică-le în mob_names.txt, cum ai învățat în lecția despre VNUM.
Codul complet
Creează în Notepad++ fișierul vanatoare_lupi.quest:
quest vanatoare_lupi begin
state start begin
when 20011.chat."Vanatoare de lupi" with pc.get_level() >= 5 begin
say_title("Vanatoare de lupi")
say("Lupii ataca drumurile satului.")
say("Omoara 10 lupi si intoarce-te la mine.")
local alegere = select("Accept", "Nu acum")
if alegere == 1 then
pc.setqf("ucisi", 0)
set_state(vanatoare)
end
end
end
state vanatoare begin
when letter begin
send_letter("Vanatoare de lupi")
end
when button or info begin
say_title("Vanatoare de lupi")
say(string.format("Lupi omorati: %d din 10", pc.getqf("ucisi")))
end
when 102.kill begin
local n = pc.getqf("ucisi")
if n < 10 then
n = n + 1
pc.setqf("ucisi", n)
syschat(string.format("Lupi omorati: %d/10", n))
end
if n >= 10 then
syschat("Ai omorat destui lupi. Intoarce-te la Uriel.")
set_state(predare)
end
end
end
state predare begin
when letter begin
send_letter("Intoarce-te la Uriel")
end
when 20011.chat."Am terminat vanatoarea" begin
say_title("Vanatoare de lupi")
say("Multumesc! Iata 5.000 yang.")
clear_letter()
set_state(terminat)
pc.change_money(5000)
end
end
state terminat begin
end
endExplicat rând cu rând
Primul bloc (state start) e cel din L15, cu o singură noutate: condiția de nivel.
| Rând | Ce înseamnă |
|---|---|
with pc.get_level() >= 5 | Opțiunea apare la NPC doar dacă jucătorul are cel puțin nivelul 5. Cei mai mici nici nu o văd. |
pc.setqf("ucisi", 0) | Pornim numărătoarea de la zero. Notița se numește ucisi. |
set_state(vanatoare) | Mutăm questul, pentru acest jucător, în etapa „vânătoare”. Din acest moment opțiunea „Vanatoare de lupi” dispare, pentru că ea există doar în etapa start. |
Etapa vanatoare:
| Rând | Ce înseamnă |
|---|---|
when letter begin | Se execută când jucătorul intră în joc sau ajunge în această etapă. Aici doar afișăm scrisoarea. |
send_letter("...") | Pune iconița de quest în stânga ecranului, cu titlul dat. |
when button or info begin | Când jucătorul apasă pe scrisoare. Îi arătăm progresul. |
string.format("... %d din 10", ...) | Pune numărul în locul lui %d. E un mod mai curat de a lipi text cu numere decât ... |
when 102.kill begin | „Când jucătorul omoară un monstru cu VNUM-ul 102…” |
local n = pc.getqf("ucisi") | Citim cât avea notat până acum. |
if n < 10 then | Creștem doar dacă n-a ajuns încă la 10. Așa numărul nu sare niciodată peste limită. |
pc.setqf("ucisi", n) | Salvăm noul număr. |
syschat(...) | Scrie un mesaj în chat, doar pentru acest jucător. |
set_state(predare) | La 10 lupi, questul trece în etapa de predare. Lupii omorâți de acum nu mai contează, pentru că evenimentul 102.kill există doar în etapa vanatoare. |
Etapa predare și terminat:
| Rând | Ce înseamnă |
|---|---|
when 20011.chat."Am terminat vanatoarea" | Opțiune nouă la Uriel, vizibilă doar celor aflați în etapa predare. |
clear_letter() | Scoate scrisoarea de pe ecran. |
set_state(terminat) | Mutăm questul în etapa finală înainte de a da banii. |
pc.change_money(5000) | Dă 5.000 yang. Yang-ul nu ocupă loc în inventar, deci nu avem nimic de verificat aici. |
state terminat begin end | O etapă goală: nimic nu se mai întâmplă. Misiunea nu mai apare la NPC. |
Numără end-urile: fiecare begin și fiecare if are nevoie de unul. Este cea mai des întâlnită eroare la compilare.
De ce așa: trei reguli care te scapă de probleme
1. Etapele sunt protecția ta împotriva dublării. Recompensa există doar în etapa predare. Imediat ce o dăm, mutăm questul în terminat. Dacă jucătorul redeschide dialogul, opțiunea nu mai există. Fără etape, un jucător ar putea apăsa de zece ori pe „Am terminat” și ar lua de zece ori banii.
2. Schimbi etapa în același bloc în care dai recompensa. Între set_state(terminat) și pc.change_money nu există niciun select() sau wait(), adică niciun moment în care questul așteaptă jucătorul. Totul se execută dintr-o bucată.
3. Nu scrii flag-uri la logare. S-ar putea să fii tentat să pui pc.setqf(...) într-un when login, de exemplu ca să „resetezi” ceva când intră jucătorul. Nu o face. Există o problemă cunoscută în motorul Metin2: scrierea de quest flag-uri în momentul logării poate strica datele questurilor jucătorului. Scrie flag-uri doar din acțiuni făcute în joc: dialog, kill, folosirea unui item.
Două lucruri pe care puțini le știu despre kill
- La party, numără doar unul. În sursa pachetului verificat, evenimentul
killajunge la jucătorul care a făcut cele mai multe daune monstrului, nu la tot grupul. Dacă vrei să numere pentru toți membrii, ai nevoie de altă abordare (există și evenimentulparty_kill, dar e un subiect mai avansat). - Monstrul trebuie să dea EXP. Tot în acel pachet, dacă un monstru are EXP 0 în
mob_proto, evenimentulkillnu mai pleacă. Dacă misiunea nu numără deloc, verifică întâi asta. Vezi și lecția despre HP, EXP și yang la monștri.
La tine, dacă pachetul are sursa modificată, comportamentul poate diferi. Testează cu doi jucători în party înainte de lansare.
Pune questul pe server
Pașii sunt aceiași ca în L15, pe scurt:
- Fă backup la folderul de questuri.
- Copiază
vanatoare_lupi.questîn folder (în pachetul verificat:share/locale/english/quest). - Adaugă numele fișierului pe un rând nou în lista de questuri. În pachetul verificat lista se numește
locale_list; în altele,quest_list. - Compilează (în pachetul verificat, cu
python make.py, care rulează programulqcpe fiecare quest din listă). - În joc, cu GM-ul, dai
/reload q.
Ce ar trebui să vezi: la Uriel apare „Vanatoare de lupi”; după ce accepți, apare scrisoarea în stânga; la fiecare lup, mesajul „Lupi omorati: X/10” în chat; după 10, opțiunea „Am terminat vanatoarea”.
Testul care contează: ieși din joc la jumătate
- Acceptă misiunea și omoară 4 lupi.
- Ieși complet din joc și intră din nou.
- Apasă pe scrisoare. Trebuie să scrie „Lupi omorati: 4 din 10”.
- Termină misiunea, ia recompensa, apoi vorbește din nou cu Uriel: nu trebuie să mai apară nicio opțiune.
Greșeli des întâlnite
| Ce vezi | De ce se întâmplă | Ce faci |
|---|---|---|
| Opțiunea nu apare la NPC | Nivelul e prea mic sau questul nu e în listă | Verifică nivelul și locale_list / quest_list |
| Lupii nu se numără | VNUM greșit, monstrul nu dă EXP sau lovește mai tare alt jucător | Verifică VNUM-ul în mob_names.txt și EXP-ul în mob_proto |
| Progresul revine la 0 | Ai pus pc.setqf("ucisi", 0) într-un loc care se execută des | Pune resetul doar la acceptarea misiunii |
| Recompensa se poate lua de mai multe ori | Etapa nu se schimbă la predare | set_state(terminat) în același bloc cu recompensa |
| Ai redenumit questul și jucătorii au pierdut progresul | Flag-urile sunt salvate sub numele questului | Nu redenumi un quest care rulează deja pe server |
Întrebări frecvente
Pot număra mai multe tipuri de monștri?
Da. Adaugi încă un bloc, de exemplu when 103.kill begin ... end, cu propriul flag (ucisi_alfa). Ține fiecare număr separat, e mai ușor de verificat.
Unde se vede flag-ul în baza de date?
În tabelul quest din baza player, cu numele questului și numele flag-ului. Uită-te acolo doar pe serverul de test și doar cu SELECT. Detalii în lecția despre testarea la relogare și restart.
Pot da iteme în loc de yang?
Da, dar atunci trebuie să verifici întâi locul din inventar. Asta are o lecție separată: recompense în inventar în siguranță.
Ce urmează
Acum că știi să numeri, trecem la misiunile în care jucătorul aduce obiecte: misiunea de colectat și predat obiecte. Dacă ai sărit peste capitolul despre NPC-uri, aruncă o privire la NPC-ul nou cu dialog și recompensă.
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ă.