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

Metin2 biologist-systeem: verzamel- en beloningsmechanica

Het Metin2 biologist-systeem is een klassieke loop waarbij een NPC de speler dagelijkse verzamelmissies geeft en gelaagde beloningen uitdeelt in ruil voor de ingeleverde materialen. De biologist (soms de "geleerde" genoemd) vraagt de speler om een bepaald jachtmateriaal in een bepaalde hoeveelheid; zodra de speler het verzamelt en inlevert, krijgt hij zijn beloning en gaat hij naar de volgende tier. In deze gids laat ik je stap voor stap zien hoe je het systeem vanaf nul bouwt met de quest-engine (Lua): de beloningstiers, de dagelijkse reset en een exploit-bestendig ontwerp.

Hoe werkt het biologist-systeem?

De logica is in wezen een eenvoudige verzamelen–inleveren–vooruitgaan-loop. Het systeem bestaat uit drie hoofdonderdelen:

  • De NPC — de biologist met wie de speler praat. Hij heeft een vnum, en de quest haakt in op de chat- en click-events van die vnum.
  • Het gevraagde materiaal — meestal een item_proto-record dat door monsters wordt gedropt (bijvoorbeeld een orgaan, een plant of een monster/specimen). Elke tier kan een ander materiaal en aantal vragen.
  • Voortgangsdata — in welke tier de speler zit en of hij zijn inlevering van vandaag heeft gebruikt. Dit bewaar je in quest-flags (pc.setqf/pc.getqf).

Wanneer de speler met de NPC praat, controleert de quest hoeveel van het materiaal hij in zijn inventaris heeft. Als het genoeg is, verwijdert hij het materiaal, geeft de beloning en verhoogt de tier met één. Zo niet, dan vertelt hij de speler hoeveel hij er nog nodig heeft. De hele flow kan in één Lua-bestand staan.

Basis quest-skelet

Hieronder staat een werkend quest-skelet voor de biologist met één tier. Laat 9001 de NPC-vnum zijn en 30301 de vnum van het gevraagde materiaal. We vragen de speler om 20 stuks van het materiaal:

quest biolog begin
    state start begin
        when 9001.chat."Biologist" begin
            say_title("Biologist:")
            say("Breng me 20 monsters,")
            say("en ik beloon je in ruil.")
            say("")

            local have = pc.count_item(30301)
            say("Monsters in bezit: "..have.."/20")

            local s = select("Inleveren", "Annuleren")
            if s == 2 then return end

            if pc.count_item(30301) < 20 then
                say_title("Biologist:")
                say("Je hebt nog niet genoeg monsters.")
                return
            end

            pc.remove_item(30301, 20)
            pc.give_item2(50300, 5)   -- beloning: 5 drankjes
            say_title("Biologist:")
            say("Bedankt! Hier is je beloning.")
        end
    end
end

Hier telt pc.count_item de hoeveelheid in de inventaris, verwijdert pc.remove_item het ingeleverde materiaal en geeft pc.give_item2 de beloning. say/select sturen de dialoogflow aan. Dit skelet werkt voor één missie; wat een echt biologist-systeem aantrekkelijk maakt, is het koppelen aan tiers en een dagelijkse loop.

Beloningstiers

In echte biologist-systemen groeien het gevraagde materiaal en de beloning na elke inlevering. De schoonste manier om dit te ontwerpen is datagedreven, met een Lua-tabel. Je bewaart de tier in een quest-flag en verhoogt die bij elke inlevering:

local TIERS = {
    -- {gevraagd_vnum, aantal, beloning_vnum, beloning_aantal}
    {30301, 20, 50300,  5},
    {30302, 30, 50301,  8},
    {30303, 40, 71001,  1},  -- zeldzame beloning bij de laatste tier
}

quest biolog begin
    state start begin
        when 9001.chat."Biologist" begin
            local step = pc.getqf("biolog_step")
            if step == 0 then step = 1 end
            if step > table.getn(TIERS) then
                say("Je hebt alle tiers voltooid!")
                return
            end

            local t = TIERS[step]
            local vnum, need = t[1], t[2]
            local have = pc.count_item(vnum)

            say_title("Biologist:")
            say("Tier "..step..": "..have.."/"..need)
            local s = select("Inleveren", "Annuleren")
            if s == 2 then return end

            if pc.count_item(vnum) < need then
                say("Je hebt nog niet genoeg materiaal.")
                return
            end

            pc.remove_item(vnum, need)
            pc.give_item2(t[3], t[4])
            pc.setqf("biolog_step", step + 1)
            say("Je bent doorgegaan naar de volgende tier!")
        end
    end
end

Deze structuur schaalt: om een nieuwe tier toe te voegen, voeg je alleen één regel toe aan de TIERS-tabel. De logica één keer schrijven en de data uit een tabel voeden is veel gezonder voor onderhoud dan code dupliceren.

Dagelijkse reset

Het deel dat het biologist-systeem zijn "dagelijkse quest"-karakter geeft, is de reset. Het doel is de speler één inlevering per dag te laten doen. Daarvoor sla je de dag van de laatste inlevering op in een flag en vergelijk je die bij elk bezoek met de huidige dag. Je kunt de dag afleiden uit get_global_time() (deel de timestamp in seconden door 86400 voor een dagnummer):

local function vandaag()
    return math.floor(get_global_time() / 86400)
end

-- binnen de NPC-flow, voor de inlevering:
if pc.getqf("biolog_dag") == vandaag() then
    say_title("Biologist:")
    say("Je hebt vandaag al ingeleverd.")
    say("Kom morgen terug.")
    return
end

-- ... na een geslaagde inlevering:
pc.setqf("biolog_dag", vandaag())

Deze aanpak blijft consistent, zelfs als de server herstart, omdat hij de datum in de eigen flag van de speler opslaat. Desgewenst kun je de "dag"-berekening met een uur-offset verschuiven om bij de tijdzone van je server te passen (bijvoorbeeld een reset om 06:00 in plaats van middernacht).

Exploit-bestendig ontwerp

Verzamel-beloningssystemen staan open voor misbruik als ze niet zorgvuldig worden gebouwd. Let op deze punten:

  • Eerst controleren, dan verwijderen: Tel de hoeveelheid altijd opnieuw voordat je het materiaal met pc.remove_item verwijdert. Op het select-scherm kan de speler het item via een ander venster wegslepen.
  • Atomische flow: Voer de verwijder- en geefstappen direct na elkaar uit, zonder dialoog ertussen. Anders kan de speler het item droppen terwijl hij in de dialoog wacht.
  • Inventaris-overloop: Controleer op vrije ruimte voordat je de beloning geeft; is die vol, waarschuw de speler en draai de inlevering terug, anders gaat de beloning verloren.
  • Schrijf de dag-flag als laatste: Sla de dag pas op nadat de inlevering is geslaagd, zodat het recht niet bij een fout verloren gaat.

Dit systeem loggen is ook een goed idee: welke speler, op welke tier, leverde wanneer in? Abnormaal frequente inleveringen opsporen helpt je dupe-bugs vroeg te herkennen.

Veelgestelde vragen

Kan ik het biologist-systeem bouwen zonder de server-source aan te raken?

Ja. De hele flow wordt afgehandeld door de quest-engine (Lua); de enige "nieuwe" definities die je nodig hebt zijn de NPC-vnum en de item_proto-records. Je kunt een werkende biologist bouwen met alleen een quest-bestand en proto-aanpassingen, zonder de source te hercompileren.

Hoe bepaal ik welk materiaal wordt gevraagd?

Het materiaal is een gewoon item_proto-item. Het wordt meestal aan specifieke monsters gekoppeld als drop (mob_drop_item / drop-tabellen). Zo verzamelt de speler het materiaal door te jagen, wat het systeem in de farm-loop opneemt.

Kan de speler zien hoe ver hij is gevorderd?

Ja, je kunt de waarde pc.getqf("biolog_step") in de NPC-dialoog tonen. Veel servers tonen ook de resterende hoeveelheid en de volgende beloning via een quest-UI of een eenvoudige say-samenvatting.

Wil je een gelaagd, dagelijks resettend en exploit-bestendig biologist-systeem voor je server? Ik kan de quest-logica, de beloningstabellen en de dagelijkse loop van begin tot eind bouwen en testen. Neem contact op om over je project te praten.

Bu kategorideki tüm yazılar →

Devamı için