A metin2 level reward system is a small but engaging mechanic that automatically hands the player a prize every time they level up. By giving newcomers potions and gold at early levels, and more valuable items at higher ones, it strengthens the feeling of progress. The best part: you don't need to compile the server source for this. You can do it entirely with Metin2's quest scripting language by writing a single .quest file. In this article we build that quest from scratch with real, working code.
The logic: catching the levelup event
The Metin2 quest engine is event-based. The event we need is when levelup: it fires the moment a player gains a level. Inside it we read the current level with pc.get_level() and decide which reward to grant. The only thing to watch is not giving the same reward twice; for that we store progress in a quest flag.
pc.get_level()— returns the player's current level.pc.give_item2(vnum, count)— adds an item to the inventory.pc.change_gold(amount)— changes the player's yang (gold).pc.setqf("name", value)/pc.getqf("name")— writes/reads a persistent flag scoped to this quest.
A first working skeleton
The quest below rewards the player once when they reach level 10 and never hands out the same prize again. Save the file as level_reward.quest in the share/locale/.../quest folder and add it to the quest list.
quest level_reward begin
state start begin
when levelup begin
local level = pc.get_level()
-- level 10 reward, only once
if level == 10 and pc.getqf("lv10") == 0 then
pc.give_item2(27003, 5) -- Healing Potion, example vnum
pc.change_gold(50000)
pc.setqf("lv10", 1)
syschat("Congratulations! You received the level 10 reward.")
end
end
end
end
The 27003 here is only an example vnum; check the real value in your own item_proto table because item numbers differ from server to server.
Managing many levels with a single table
Writing a separate if block for every level gets messy fast. Instead, keep the rewards in a (Lua) table and use the level as the key. Adding a new reward then becomes a single line.
quest level_reward begin
state start begin
when levelup begin
local level = pc.get_level()
-- level = { item_vnum, count, yang }
local rewards = {
[10] = { 27003, 5, 50000 },
[20] = { 27005, 5, 100000 },
[30] = { 50300, 1, 200000 },
[40] = { 50300, 2, 400000 },
}
local r = rewards[level]
if r and pc.getqf("lv" .. level) == 0 then
pc.give_item2(r[1], r[2])
pc.change_gold(r[3])
pc.setqf("lv" .. level, 1)
syschat(string.format("Level %d reward added to your inventory!", level))
end
end
end
end
The table approach has two advantages: you manage the reward list from one place, and because pc.getqf("lv" .. level) gives each level its own flag, there is no risk of granting it twice. To guard against a full inventory you can add a pc.count_item(vnum) check or route the reward to the mailbox.
Preventing item loss when the inventory is full
A give_item2 call will silently drop or lose the item if there is no room in the inventory. At low levels that's a minor issue, but with valuable rewards it frustrates players. A simple safeguard is to check for free space and warn the player if there isn't any.
local function safe_give(vnum, count)
if pc.get_empty_inventory_count() < 1 then
syschat("Your inventory is full! Clear some space and try again.")
return false
end
pc.give_item2(vnum, count)
return true
end
In more robust solutions you send the reward directly to the player's mailbox, so it isn't lost even if the player is offline or their inventory is full. This is the preferred method for persistent event reward systems.
Testing and reloading
After saving the quest you need to compile it and apply it in-game. In most server builds you run a make or a script-based qc (quest compiler) step to rebuild the quests, then restart the game core or reload the quests. To test, give a character levels by command and verify that the event fires, the flags are written correctly, and the reward arrives.
- Try with a fresh character so the flags are clean.
- Confirm that reaching the same level again (for example after a reset) does not re-grant the reward.
- Observe the reward's behavior when the inventory is full.
Frequently Asked Questions
Does the levelup event fire on every level?
Yes, the when levelup block runs each time the player gains a level. For players who jump several levels at once it fires separately for each gain, which is why the table-based check is safe.
Where do I find item vnums?
You can look them up in the server's item_proto table or in the item_names.txt file. Since vnums can differ on every server, don't use the example numbers from this article directly — verify them against your own database.
Is sending the reward by mail better?
For valuable or event rewards, yes. Mail ensures the reward isn't lost even if the inventory is full or the player is offline; for simple potion/gold rewards, giving them straight to the inventory is enough.
Want a custom reward or event system for your server? If you need help with Metin2 quest and system development, get in touch with me — let's build mechanics that keep your players in the game.