Metin2 quest functions are the core tools that drive everything in the Lua-based, server-side quest system. From talking to an NPC and handing out items to reading a player's level or warping them across maps, almost every action you write is a combination of these functions. In this article I break down the commands you will meet most often, grouped by the pc, npc, game and item namespaces, with working examples.
The skeleton of a quest
Before the functions, it helps to recall the general shape of a quest. Every quest contains a state, and each state hooks into trigger events (when). The most common trigger is opening a chat with an NPC.
quest greeting begin
state start begin
when 9003.chat."Hello friend" begin
say_title("Villager")
say("Welcome, traveller!")
say("")
say("I have a task for you.")
end
end
end
Here 9003 is the NPC's vnum, say_title sets the dialog window title, and say prints a line of text. An empty say("") is used to leave a blank line between paragraphs.
The pc namespace: reading and changing the player
Everything about the player goes through the pc namespace. The most used Metin2 quest functions live right here. A few examples:
pc.get_level()— returns the player's level.pc.get_name()— gives the character's name.pc.get_money()andpc.change_money(amount)— read yang and add/remove it.pc.give_item2(vnum, count)— adds an item to the inventory.pc.count_item(vnum)/pc.remove_item(vnum, count)— count and delete items.pc.give_exp2(amount)— grants experience points.pc.warp(x, y)— warps the player to a coordinate.
A typical reward flow looks like this:
when 9003.chat."I finished the task" begin
if pc.count_item(27001) >= 5 then
pc.remove_item(27001, 5)
pc.give_item2(11209, 1)
pc.give_exp2(50000)
pc.change_money(100000)
say("Thank you! Take your reward.")
else
say("You haven't brought 5 yet.")
end
end
The condition is checked with pc.count_item, then pc.remove_item consumes the materials and the item, experience and yang rewards are granted.
Quest flags: pc.setqf and pc.getqf
To store quest progress permanently you use a quest flag. pc.setqf("key", value) saves a value and pc.getqf("key") reads it, so you can remember which stage of the quest the player is on.
when 9003.chat."Start the quest" begin
if pc.getqf("stage") == 0 then
pc.setqf("stage", 1)
say("Quest started. Hunt 10 wolves.")
elseif pc.getqf("stage") == 1 then
say("You're still hunting wolves.")
end
end
Flags are per-player and stored in the database, so values survive logout and login. In complex quest chains they also serve as counters (for example, on every kill: pc.setqf("counter", pc.getqf("counter") + 1)).
The npc namespace: info about the NPC you're talking to
Inside a chat block, the npc namespace points to the NPC you are currently interacting with. Common ones:
npc.get_race()— returns the NPC's vnum/race number, ideal for telling several NPCs apart within a single quest.npc.getqf/npc.setqf— NPC-specific flags (for instance-based state).npc.purge()— removes the NPC from the scene, usually for temporary spawned NPCs.
when 20354.kill begin
if npc.get_race() == 20354 then
pc.give_exp2(10000)
say("You destroyed the Metin stone!")
end
end
Here the kill trigger fires when a monster dies, and npc.get_race() confirms which creature was killed.
The game namespace: interacting with the world
The game namespace covers general operations on the game world: showing notices, reading event flags and warping the player.
game.get_event_flag("name")— reads a server-wide event flag (for example whether an event is active).game.set_event_flag("name", value)— sets the global flags usually managed via GM commands.game.warp(x, y)andgame.warp(x, y, map)— teleport.game.drop_item(vnum, count)— drops an item on the ground.
when 9003.chat."Is there an event?" begin
if game.get_event_flag("jubilee") == 1 then
say("Yes, the event is on!")
else
say("No event right now.")
end
end
The item namespace: working on the selected item
When an item is clicked, or selected with item.select(vid), the item namespace binds to that item. It is the basis of the upgrade, socket and attribute systems.
item.get_vnum()anditem.get_count()— the item's vnum and quantity.item.get_name()— the item's name.item.remove()— deletes the selected item.item.get_socket(index)/item.set_socket(index, value)— read/write sockets.item.get_value(index)— reads the item's value fields.
when 11209.use begin
item.set_socket(0, 1)
say("Item activated successfully.")
end
Here the use trigger fires when the item is used, and item.set_socket updates the first socket. When working with sockets, remember that indexes start at 0.
Helper functions: say, select, wait
The helpers that drive the dialog flow are used just as often as the namespaces. select("Option 1", "Option 2") shows the player a menu and returns the number of the chosen option. wait() pauses the dialog and shows a "Next" button.
when 9003.chat."Make a choice" begin
say("Which reward do you want?")
local choice = select("Sword", "Armour", "Cancel")
if choice == 1 then
pc.give_item2(11209, 1)
elseif choice == 2 then
pc.give_item2(11949, 1)
end
end
Frequently Asked Questions
What's the difference between pc.give_item and pc.give_item2?
pc.give_item2(vnum, count) is the standard version used today and takes a count parameter. The older pc.give_item signatures can have a different parameter layout; for consistency, new quests prefer pc.give_item2.
Where are quest flags stored?
Per-player flags (pc.setqf) are kept in the database alongside the character's game state, so values persist even after logout and login. Event flags, on the other hand, are server-wide and usually managed by a GM.
Do I need to restart after editing a quest file?
Usually you compile the quests (with the quest compiler) and reload them to apply changes. Many servers have a dedicated reload mechanism for this; otherwise the game core needs to read the quests again.
Stuck on the quest system? If you need custom quest chains, event systems or debugging help for your Metin2 server, get in touch and we'll solve it together.