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

Recompense de dungeon fără pierderi sau dubluri: premiul dat o singură dată

2 noiembrie 2026 6 min de citit

Recompensa de la finalul dungeonului e motivul pentru care jucătorii intră. Tocmai de aceea e și ținta preferată a celor care caută bug-uri: apasă de două ori pe NPC, ies din joc în momentul potrivit sau intră cu inventarul plin ca să „forțeze” o eroare. Dacă premiul se poate lua de două ori, economia serverului se strică în câteva zile. Dacă se pierde, jucătorii se supără pe bună dreptate. În această lecție construim un premiu care se dă **exact o dată** fiecărui jucător.

Pe scurt: verifici, în ordine: bossul e mort, jucătorul n-a luat deja premiul, are loc în inventar. Abia apoi notezi că l-a luat și îi dai itemul, în aceeași bucată de cod, fără ferestre între ele.

Cuvinte pe care le vei întâlni

CuvântCe înseamnă
Dublare (dupe)Un item sau o recompensă primită de mai multe ori decât trebuia.
Semn (flag)O valoare salvată care spune „s-a întâmplat deja”.
pc.get_player_id()Numărul unic al personajului curent.
pc.enough_inventory(vnum)Verifică dacă e loc în inventar pentru un item.
pc.give_item2(vnum, nr)Dă un item în inventar.

Unde se strică de obicei

MomentulCe poate merge prost
Bossul moareEvenimentul de kill dă premiul, dar e declanșat de două ori.
Jucătorul vorbește cu NPC-ulDeschide dialogul din nou și ia încă o dată.
Inventarul e plinPremiul e „dat”, dar nu ajunge nicăieri.
Deconectare sau crashPremiul e dat, dar semnul nu apucă să fie salvat, sau invers.

Pasul 1: Bossul moare o singură dată

Primul lucru este ca moartea bossului să fie notată o singură dată și doar în etapa corectă:

lua
when BOSS.kill with pc.in_dungeon() and d.getf("boss_mort") == 0 begin
    d.setf("boss_mort", 1)
    d.setf("level", 4)
    d.notice("Bossul a cazut! Vorbiti cu Cufarul pentru recompensa.")
    d.spawn_mob(CUFAR_NPC, 690, 722)
    server_timer("iesire_dungeon", 120, d.get_map_index())
end

Condiția d.getf("boss_mort") == 0 face ca acest cod să nu ruleze a doua oară, chiar dacă ar exista un al doilea boss identic. Punerea unui singur NPC aici e în regulă (și Turnul Demonilor din pachet face așa); ce nu faci în when kill este ștergerea tuturor monștrilor, cum ai văzut în lecția despre etape. Ceasul iesire_dungeon scoate grupul după 2 minute (îl construiești cu d.exit_all(), ca în lecția despre etape).

Pasul 2: Fiecare jucător își ia premiul o dată

Premiul e dat de un NPC „cufăr” în instanță. Semnul îl punem pe instanță, dar cu numele personajului în cheie, ca fiecare membru să aibă semnul lui:

lua
when CUFAR_NPC.chat."Ia recompensa" with pc.in_dungeon() begin
    local cheie = "premiu_" .. pc.get_player_id()
    if d.getf("boss_mort") == 0 then
        say("Bossul inca traieste.")
        return
    end
    if d.getf(cheie) == 1 then
        say("Ti-ai luat deja recompensa.")
        return
    end
    if not pc.enough_inventory(PREMIU) then
        say("Fa loc in inventar si revino.")
        return
    end
    d.setf(cheie, 1)
    pc.give_item2(PREMIU, 1)
    say("Felicitari! Ai primit recompensa.")
end
BucatăCe face, pe românește
"premiu_" .. pc.get_player_id()Face o cheie unică pe personaj, de exemplu premiu_1043. Questurile din pachet folosesc la fel nume compuse, ca "fakedead" .. i.
d.getf("boss_mort") == 0Fără boss mort, fără premiu.
d.getf(cheie) == 1A luat deja? Atunci stop.
pc.enough_inventory(PREMIU)Are loc? Dacă nu, îi spunem să revină. Nu notăm nimic.
d.setf(cheie, 1)Notăm că l-a luat…
pc.give_item2(PREMIU, 1)…și imediat îi dăm itemul.

De ce ordinea contează atât de mult

Gândește-te la o casă de bilete. Casiera bifează numele tău pe listă și îți dă biletul în aceeași mișcare. Dacă ți-ar da biletul, apoi ar răspunde la telefon, ai putea cere încă unul înainte să te bifeze.

În quest e la fel. Între verificare și acțiune nu pune select(), wait() sau alte ferestre. În timpul unei ferestre deschise, jucătorul poate face orice: poate goli inventarul sau poate deschide altă cale spre același premiu. Dacă ai nevoie de o confirmare, pune-o înainte de verificări, nu între ele.

Verificarea inventarului vine înainte de semn. Așa, dacă inventarul e plin, jucătorul nu pierde nimic: semnul nu e pus și poate reveni.

Mai multe despre itemele date în inventar găsești în lecția recompense în inventar în siguranță.

Și dacă premiul trebuie să rămână și după dungeon?

Semnul d.setf dispare odată cu instanța. Pentru dungeon e perfect: la intrarea următoare, jucătorul poate primi iar premiul (cooldown-ul îl limitează, în lecția următoare). Dacă vrei un premiu o singură dată pe viață (de exemplu, „prima terminare”), ai nevoie de un semn pe personaj. În Turnul Demonilor din pachet, după bossul final se folosește d.setqf2("deviltower_zone", "9_done", 1), care pune semnul pe toți jucătorii aflați în instanță în acel moment.

Atenție: semnele pe personaj (pc.setqf) nu le scrii niciodată în when login. Există un bug cunoscut al motorului care poate strica datele questurilor. Scrie-le doar din acțiuni în joc: dialog, kill, folosirea unui item. Detalii în quest flag-uri și condiții de nivel.

Dropul bossului e altceva

Itemele care cad din boss prin mob_drop_item.txt nu trec prin quest. În sursa verificată, dropul primește ca „proprietar” jucătorul care a făcut cel mai mult damage, nu neapărat ultima lovitură. Asta e bine de știut când grupul se ceartă pe drop. Vezi și cum testezi dropul unui boss.

Pasul 3: Testele anti-dublare

Pe serverul de test, cu un GM și 2–3 personaje în grup:

  1. Ia premiul, apoi vorbește din nou cu cufărul. Trebuie să apară „Ti-ai luat deja recompensa”.
  2. Umple inventarul, încearcă, golește un loc, încearcă din nou. Primești premiul o singură dată.
  3. Ia premiul și ieși imediat din joc. La relogare, itemul e în inventar o singură dată.
  4. Doi jucători din grup vorbesc cu cufărul în același timp. Fiecare primește o dată.
  5. Verifică în baza de date sau în inventar numărul exact de iteme după fiecare test.

Ce ar trebui să vezi: fiecare membru are exact un premiu, oricâte încercări ar face.

Greșeli des întâlnite

  • Semnul se pune după un select(). Între fereastră și acțiune, jucătorul poate repeta pașii.
  • Semnul se pune pe instanță, fără ID-ul personajului. Primul jucător ia premiul, ceilalți nu mai pot.
  • Nu se verifică inventarul. Premiul se pierde, iar jucătorul nu mai poate cere altul.
  • Premiul se dă direct în when kill, la toți, prin bucle complicate. E greu de testat și ușor de dublat.
  • Recompensa se marchează doar în client. Clientul se poate modifica; serverul decide.

Întrebări frecvente

Pot da premiul automat, fără NPC?

Da, dar e mai greu de făcut sigur pentru tot grupul. NPC-ul cufăr e simplu: fiecare jucător vine singur, iar fiecare cerere e verificată separat.

Ce fac dacă un jucător reclamă că a pierdut premiul?

Caută în loguri și în inventarul lui. De aceea e bine să notezi într-un jurnal (changelog) ce recompense dă fiecare dungeon și ce teste ai făcut.

Pot folosi game.drop_item în loc de pc.give_item2?

Poți, dar itemul cade pe jos și îl poate lua oricine. Pentru premii personale, darea direct în inventar e mai sigură.

Ce urmează

Acum limităm de câte ori se poate face dungeonul: cooldown-uri pe personaj și pe grup. Pentru teste generale anti-dublare, vezi și cum testezi NPC-urile ca să nu dubleze recompense.

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