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

Metin2 Biologist System: Collection and Reward Mechanics

The Metin2 Biologist system is a classic loop where an NPC hands the player daily collection missions and pays out tiered rewards in exchange for the materials they turn in. The Biologist (sometimes called the "Scholar") asks the player for a certain hunting material in a certain quantity; once the player gathers and delivers it, they get their reward and advance to the next tier. In this guide I will walk you through building the system from scratch with the quest engine (Lua): the reward tiers, the daily reset and an exploit-proof design, step by step.

How does the Biologist system work?

The logic is essentially a simple collect–turn in–advance loop. The system has three main parts:

  • The NPC — the Biologist the player talks to. It has a vnum, and the quest hooks into that vnum's chat and click events.
  • The requested material — usually an item_proto record dropped by monsters (an organ, a plant or a specimen, for example). Each tier can ask for a different material and amount.
  • Progress data — which tier the player is on and whether they have used today's turn-in. You keep this in quest flags (pc.setqf/pc.getqf).

When the player talks to the NPC, the quest checks how many of the material they have in their inventory. If it is enough, it removes the material, grants the reward and bumps the tier by one. If not, it tells the player how many more they need. The whole flow can live in a single Lua file.

Basic quest skeleton

Below is a working, single-tier Biologist quest skeleton. Let 9001 be the NPC vnum and 30301 the requested material vnum. We ask the player for 20 of the material:

quest biolog begin
    state start begin
        when 9001.chat."Biologist" begin
            say_title("Biologist:")
            say("Bring me 20 specimens,")
            say("and I will reward you in return.")
            say("")

            local have = pc.count_item(30301)
            say("Specimens you hold: "..have.."/20")

            local s = select("Turn in", "Cancel")
            if s == 2 then return end

            if pc.count_item(30301) < 20 then
                say_title("Biologist:")
                say("You do not have enough specimens yet.")
                return
            end

            pc.remove_item(30301, 20)
            pc.give_item2(50300, 5)   -- reward: 5 potions
            say_title("Biologist:")
            say("Thank you! Here is your reward.")
        end
    end
end

Here pc.count_item counts the amount in the inventory, pc.remove_item deletes the turned-in material and pc.give_item2 grants the reward. say/select drive the dialog flow. This skeleton works for a single mission; what makes a real Biologist system appealing is wiring it into tiers and a daily loop.

Reward tiers

In real Biologist systems, the requested material and the reward grow after each turn-in. The cleanest way to design this is data-driven, with a Lua table. You keep the tier in a quest flag and increment it on every turn-in:

local TIERS = {
    -- {requested_vnum, amount, reward_vnum, reward_amount}
    {30301, 20, 50300,  5},
    {30302, 30, 50301,  8},
    {30303, 40, 71001,  1},  -- rare reward on the final 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("You have completed every tier!")
                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("Turn in", "Cancel")
            if s == 2 then return end

            if pc.count_item(vnum) < need then
                say("You do not have enough material yet.")
                return
            end

            pc.remove_item(vnum, need)
            pc.give_item2(t[3], t[4])
            pc.setqf("biolog_step", step + 1)
            say("You have advanced to the next tier!")
        end
    end
end

This structure scales: to add a new tier, you only add a single row to the TIERS table. Writing the logic once and feeding the data from a table is far healthier for maintenance than duplicating code.

Daily reset

The part that gives the Biologist system its "daily quest" character is the reset. The goal is to let the player turn in once per day. To do this, you store the last turn-in day in a flag and compare it with the current day on every visit. You can derive the day from get_global_time() (divide the timestamp in seconds by 86400 to get a day number):

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

-- inside the NPC flow, before the turn-in:
if pc.getqf("biolog_day") == today() then
    say_title("Biologist:")
    say("You have already turned in today.")
    say("Come back tomorrow.")
    return
end

-- ... after a successful turn-in:
pc.setqf("biolog_day", today())

This approach stays consistent even if the server restarts, because it stores the date in the player's own flag. If you like, you can shift the "day" calculation by an hour offset to match your server's time zone (for example resetting at 06:00 instead of midnight).

Exploit-proof design

Collection-reward systems are open to abuse if they are not built carefully. Watch for these points:

  • Check first, delete second: Always recount the amount before deleting the material with pc.remove_item. On the select screen the player can move the item out from another window.
  • Atomic flow: Run the remove and grant steps back to back, with no dialog in between. Otherwise the player can drop the item while waiting in the dialog.
  • Inventory overflow: Check for free space before granting the reward; if it is full, warn the player and roll back the turn-in, otherwise the reward is lost.
  • Write the daily flag last: Save the day only after the turn-in succeeds, so the entitlement is not wasted on an error.

Logging this system is also a good idea: which player, on which tier, turned in when? Catching abnormally frequent turn-ins helps you spot dupe bugs early.

Frequently Asked Questions

Can I build the Biologist system without touching the server source?

Yes. The entire flow is handled by the quest engine (Lua); the only "new" definitions you need are the NPC vnum and the item_proto records. You can build a working Biologist with just a quest file and proto edits, without recompiling the source.

How do I decide what material is requested?

The material is an ordinary item_proto item. It is usually tied to specific monsters as a drop (mob_drop_item / drop tables). That way the player gathers the material by hunting, which folds the system into the farming loop.

Can the player see how far they have progressed?

Yes, you can show the pc.getqf("biolog_step") value in the NPC dialog. Many servers also present the remaining amount and the next reward through a quest UI or a simple say summary.

Want a tiered, daily-resetting, exploit-proof Biologist system for your server? I can build and test the quest logic, the reward tables and the daily loop from start to finish. Get in touch to talk about your project.

Bu kategorideki tüm yazılar →

Devamı için