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 dechat- enclick-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_itemverwijdert. Op hetselect-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.