Task System¶
The EQEmu Task System allows implementation of quests that utilize the clients Task Window (alt+Q). Many aspects of this system can be found throughout this wiki; this guide attempts to organize that information on a single page to inform the reader who wishes to understand and utilize the Task System.
Much of the Task System functionality can be found in /zones/task.cpp and should be referenced by those comfortable with looking at the EQEmu source code.
Info
While every attempt will be made to keep this page updated, please reference the additional supporting documentation found in the Database Schema, Quest API, and Changelog.
Section Description | Link |
---|---|
Database Schema: All of the DB tables for the task system | Database Schema |
GM Commands: in-game GM commands for the task system | GM Commands |
Task System Rules: server rules effecting the task system | Task System Rules |
Logging Options: use with the Logging System | Logging Options |
Quest API: quest methods and EVENT triggers relating to the task system | Quest API |
Database Schema¶
The most up to date information regarding the database schema can be found in the Database Schema Space for Tasks. The information presented here is current as of this writing.
Tasks Table¶
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
id | int | Unique Task Identifier; use 1 - 9999, a value of 0 should NOT be used |
type | tinyint | Task Type; 0=Task, 1=Shared, 2=Quest, 3=Expedition |
duration | int | Duration in seconds; if 0, the task has no time limit |
duration_code | tinyint | Duration Code; 0=None, 1=Short, 2=Medium, 3=Long |
title | varchar | Title |
description | text | Description; only the active task description displays |
reward | varchar | Reward Description |
rewardid | int | Item ID number, or a reference to a list of item ID numbers (from goallists table) |
cashreward | int | Cash Reward, listed in copper (system will convert to plat, gold, etc.) |
xpreward | int | Experience Reward; for level-based, set a negative value using the following formula: max level * 100 + experience percent |
rewardmethod | tinyint | Reward Method: 0 = Single Item ID, 1 = List of Items (in the goallist table), 2 = Quest Controlled (reward granted through NPC quest script) |
minlevel | tinyint | Minimum Level to obtain tasks |
maxlevel | tinyint | Maximum Level to obtain tasks |
repeatable | tinyint | Repeatable: 0 = False, 1 = True |
faction_reward | int | Faction Reward |
completion_emote | varchar | Completion Emote |
Task_Activities Table¶
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
taskid | int | Task Identifier (ID from Tasks table); each activity for a task will utilize the same ID. |
activityid | int | Activity Identifier: Starts at 0, must be sequential |
step | int | Step: 0 = Always Available, >0 = Must Complete Previous ("stepped" task) |
activitytype | tinyint | Activity Type (or see below) |
target_name | varchar | Target Name |
item_list | varchar | Item Identifier List |
skill_list | varchar | Skill Identifier List |
spell_list | varchar | Spell Identifier List |
description_override | varchar | Description Override |
goalid | int | Goal Identifier or Goal List Identifier |
goalmethod | int | Goal Method: 0 = Single Value (npc_type ID or item ID) 1 = List (refers to the goallist table to use a list of npc_type IDs or Item IDs) 2 = Under control of quest system |
goalcount | int | Goal Count (how many of the things in the goal id must be done) |
delivertonpc | int | Deliver To NPC: 0 = No Delivery NPC, >0 = npc_type ID |
zones | varchar | Zones List--use the zoneidnumber field; "0" displays "ALL". Activities will only be counted if completed in the assigned zone. Can also be used as "Touch" for visiting an assigned zone. |
optional | tinyint | Optional: 0 = False, 1 = True; if a task activity is optional, the task will be complete when all non-optional task activities are completed. |
Activity Types¶
Info
Please note that **quest::updatetaskactivity **could be used in many EVENT triggers if you did not want to use the task system as described in the table below.
Type ID | Type |
Information and usage |
---|---|---|
1 | Deliver | To have this activity automatically handled by the task system without the need to write any Perl quest code, set:
If you wish to allow the player to deliver any out of a group of items, then you can use a list. To do this, create a list in the goallist table containing the allowable items. Then set the goalmethod to 1 and put the list number in the goalid field. |
2 | Kill | To have this activity automatically handled by the task system without the need to write any Perl quest code, set:
If you wish to allow the player to kill any out of a group of NPC types, then you can use a list as described for the Deliver activity. For common mobs, you will probably always be using lists, since there are a lot of entries for mobs with the same name in the npc_types table which differ by level, etc. |
3 | Loot | To have this activity automatically handled by the task system without the need to write any Perl quest code, set:
If you wish to allow the player to loot any one of a group of items, then you can use a list as described for the Deliver activity. |
4 | Speak With | To have this activity automatically handled by the task system without the need to write any Perl quest code, set:
If you wish to allow the player to speak to any one of a group of NPCs, then you can use a list as described for the Deliver activity. |
5 | Explore | To have this activity automatically handled by the task system without the need to write any Perl quest code, you will need to add a row to the proximity table. Once you have added the row and given it a unique exploreid number, in the activity table, set:
It should be possible to set up multiple proximities in the same zone, using lists, such that any of the proximities will trigger the activity complete. |
6 | Tradeskill | To have this activity automatically handled by the task system, set:
If you wish to allow the player to create any one of a group of items, then you can use a list as described for the Deliver activity. Sometimes there are several items with the same name that can be created from a tradeskill, CLASS 1 Wood Point arrows being one of them. |
7 | Fish | To have this activity automatically handled by the task system, set:
If you wish to allow the player to fish any one of a group of items, then you can use a list as described for the Deliver activity. |
8 | Forage | To have this activity automatically handled by the task system, set:
If you wish to allow the player to forage any one of a group of items, then you can use a list as described for the Deliver activity. |
9 | Use | |
10 | Use | |
11 | Touch | To have this activity automatically handled by the task system, set:
Since the zoneid field is used to specify the zoneidnumber, the goalid field is not used. It is also not possible to specify a list of zones. |
100 | Give Cash | To have this activity automatically handled by the task system, set:
|
Character_Tasks Table¶
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
charid | int | Character Identifier; ID from character_data |
taskid | int | Task Identifier; ID from tasks table |
slot | int | Slot; the slot number (up to 19) that causes the activity to display in order to the client |
type | tinyint | Task Type; 0=Task, 1=Shared, 2=Quest, 3=Expedition |
acceptedtime | int | Accepted Time UNIX Timestamp |
Character_Activities Table¶
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
charid | int | Character Identifier; ID from character_data |
taskid | int | Task Identifier; ID from tasks table |
activityid | int | Activity Identifier, ID from tasks table |
donecount | int | Done Count (IE 'items looted', 'npcs killed', etc.) |
completed | tinyint | Completed: 0 = False, 1 = True |
Completed Tasks¶
Warning
If the rule TaskSystem:RecordCompletedTasks is set to false, then this table is not used.
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
charid | int | Character Identifier; ID from character_data table |
completedtime | int | Completed Time UNIX Timestamp |
taskid | int | Task Identifier; ID from tasks table |
activityid | int | Activity Identifier; ID from tasks table |
Info
This table may have duplicate entries for repeatable tasks. To display Optional Tasks, be sure to set the rule TaskSystem:RecordCompletedOptionalTasks to true.
Goallists Table¶
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
listid | int | Goal List Identifier; repeat ID for multiple entries |
entry | int | Entry Identifier; either npc_type id or item id |
Info
Example: list id 10 for a "kill" mission could have three rows, all with list id 10, and entries of 2001, 2102, and 2103 (for Fippy Darkpaw, Kraxz Darkpaw, and Grarrax Darkpaw).
Proximities Table¶
Warning
The rule TaskSystem:EnableTaskProximity must be set to **true **to allow the use of proximities independent of proximities defined by quest scripts for npcs (IE for "explore" tasks).
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
zoneid | int | Zone Identifier; use the zoneidnumber field |
exploreid | int | Explore Identifier; match the goalid in the activity table for type 5 (explore) activities |
minx | float | Minimum X Coordinate |
maxx | float | Maximum X Coordinate |
miny | float | Minimum Y Coordinate |
maxy | float | Maximum Y Coordinate |
minz | float | Minimum Z Coordinate |
maxz | float | Maximum Z Coordinate |
Danger
Overlapping proximities will only trigger proximity detection for the proximity with the lowest-numbered exploreid.
Tasksets Table¶
Info
Task Sets are intended to make it easier to write quest NPCs that can offer a lot of tasks. While this functionality can also be achieved with quest::assigntask, it is important to note that players can remove tasks when writing your scripts. A Task Set could require a series of tasks in a progression.
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
id | int | Unique Task Set Entry Identifier |
taskid | int | Task Identifier; ID from the tasks table |
Character_enabledtasks Table¶
Field Descriptions¶
Column | Data Type | Description |
---|---|---|
charid | int | Character Identifier; ID from character_data |
taskid | int | Task Identifier; ID from tasks table |
GM Commands¶
Command | Description |
---|---|
#task show | Shows the active tasks for the targeted client |
#task update [count] | Updates the specified activity by 1, or by [count] |
#task reloadall | Reload all information relating to tasks from DB (all zones) |
#task reload task | Reload all information for the specified task from the DB (all zones) |
#task reload lists | Reload all information from the goallists table (all zones) |
#task reload prox | Reload all information from the proximities table (all zones) |
#task reload sets | Reload task sets (all zones) |
Task System Rules¶
Rule Name | Default Value | Description |
---|---|---|
TaskSystem:KeepOneRecordPerCompletedTask | True | Keeps one record for each completed task (the client displays the most recent 50; use quest::istaskcompleted for lookups). |
TaskSystem:EnableTaskProximity | True | Makes use of the 'proximities' table, independent of quest::set_proximitiy |
TaskSystem:RecordCompletedOptionalActivities | True | Makes use of the 'character_activities' table for optional tasks |
TaskSystem:PeriodicCheckTimer | 5 | Seconds between checks for failed tasks. Also used by the 'Touch' activity |
TaskSystem:RecordCompletedTasks | True | Makes use of the 'character_activities' table for non-optional tasks |
TaskSystem:EnableTaskSystem | True | Globally enable or disable the Task system |
QueryServ:PlayerLogTaskUpdates | False | Logs Player Task Updates |
Logging Options¶
Info
These options are present in the Logging System through logsys_categories or in-game via command #logs set [output] [type] [level]
1 LOG_CATEGORY( TASKS )
2 LOG_TYPE( TASKS, GLOBALLOAD, DISABLED )
3 LOG_TYPE( TASKS, CLIENTLOAD, DISABLED )
4 LOG_TYPE( TASKS, UPDATE, DISABLED )
5 LOG_TYPE( TASKS, CLIENTSAVE, DISABLED )
6 LOG_TYPE( TASKS, PACKETS, DISABLED )
7 LOG_TYPE( TASKS, PROXIMITY, DISABLED )
TASKS UPDATE is used to print out debug information when checking if activities are completed.
Quest API (for the task system)¶
These are the quest::[methods] and EVENT triggers that are related to the Task System.
Info
Be sure to reference the Quest API in the event that functionality is expanded.
taskselector¶
**Parameter(s):**
task_id _(int)_
**Usage:**
Used to bring up the Task Selector Window with the specified tasks available for selection (from 1 to 40 task_id(s)). Note that when the task selector is brought up via this method, no check is made as to whether the character has the tasks enabled.
**Example:**
sub EVENT_SAY {
if ($text=~/hail/i) {
quest::say("Heyo! Looking for an exciting [task] to fill the time?");
}
if ($text=~/task/i) {
#:: Select task 103
quest::taskselector(103);
}
}
task_setselector¶
**Parameter(s):**
task_set_id _(int)_
**Usage:**
Sets the Task Set, by provided Task Set ID.
**Example:**
#:: Set task set 202
quest::task_setselector(202);
istaskactive¶
**Parameter(s):**
task_id _(int)_
**Usage:**
Used to determine if a task is active, by Task ID.
**Example:**
#:: Check if task 212 is active
quest::istaskactive(212); #:: Returns bool
istaskactivityactive¶
**Parameter(s):**
task_id _(int)_, activity_id _(int)_
**Usage:**
Used to determine if a task activity is active, by Task ID and Activity ID.
**Example:**
#:: Check if Activity 9 of Task 212 is active
quest::istaskactivityactive(212, 9); #:: Returns bool
updatetaskactivity¶
**Parameter(s):**
task_id _(int)_, activity_id _(int)_, count _(int)_, ignore_quest_update _(bool)_
**Usage:**
Used to increment the done count of the specified task is active. The parameter for ignore_quest_update is optional, and defaults to false; the parameter for count default to 1 (increase count by 1).
**Example:**
#:: Update Task ID 219 activity 9, by 1 count
quest::updatetaskactivity(216,9);
resettaskactivity¶
**Parameter(s):**
task_id _(int)_, activity_id _(int)_
**Usage:**
Sets the done count to 0 for the specified Task ID
**Example:**
#:: Reset the activity done count for task 202
quest::resettaskactivity(202);
taskexplorearea¶
**Parameter(s):**
explore_id _(int)_
**Usage:**
Used to mark any explore activities (type 5), which have the numeric value Explore ID in their Goal ID field, and for which the Zone ID of the activity is either 0 or this zone, as completed.
**Example:**
#:: Mark Task 21 complete
quest::taskexplorearea(21);
assigntask¶
**Parameter(s):**
task_id _(int)_, npcid _(int)_, enforce_level_requirement = false _(bool)_
**Usage:**
Used to assign a task to a client, optionally this can include the NPC ID and whether or not to enforce the level requirement specified in the DB.
**Example:**
#:: Assign Task 102
quest::assigntask(102);
#:: Assign Task 103 with level requirement enforced
quest::assigntask(103, 1);
#:: Assign Task 104 and include the NPC ID
$client->AssignTask(104, $npc->GetID());
#:: Assign Task 105, include the NPC ID with level requirement enforced
$client->AssignTask(105, $npc->GetID(), 1);
failtask¶
**Parameter(s):**
task_id _(int)_
**Usage:**
Fails the task, by Task ID, for the client character that triggered the event.
**Example:**
#:: Fail Task 216
quest::failtask(216);
tasktimeleft¶
**Parameter(s):**
task_id _(int)_
**Usage:**
Returns the amount of time left, in seconds, before the specified task runs out. -1 is returned if there is no time limit, or if the player does not have the task.
**Example:**
#:: Create a scalar variable to store the amount of time left for Task ID 22
$timeremaining = quest::tasktimeleft(22); #:: Returns int
if ($timeremaining => 1) {
quest::say("You have $timeremaining seconds left--better hurry!");
}
else {
quest::say("Sorry $name, but you're out of time!");
}
istaskcompleted¶
**Parameter(s):**
task_id (int)
**Usage:**
Used to determine if a task is completed, by Task ID.
**Example:**
#:: Check if task 212 is completed
quest::istaskcompleted(212); #:: Returns bool
enabletask¶
**Parameter(s):**
task_id _(int)_
**Usage:**
Enables a task.
**Example:**
#:: Match if the player has an active task
if ($task != 0) {
#:: Create a scalar variable to store the active speak-to activity
$activity = quest::activespeakactivity($task);
#:: Mark the activity as complete
quest::updatetaskactivity($task, $activity);
quest::say("Well done!");
#:: Offer the next task, if there is one
if (!quest::istaskactive($task)) {
#:: Disable the task so that it cannot be repeated
quest::disabletask($task);
#:: Match if there are tasks remaining in the Task Set
if ($task != quest::lasttaskinset(200)) {
quest::say("Well done, I have another task if you are willing.");
#:: Enable the next Task in the Task Set
quest::enabletask(quest::nexttaskinset(200, $task));
}
#:: Match if there are no tasks remaining in the task set
else {
quest::say("Thank you for cleansing Qeynos Hills!");
}
}
}
disabletask¶
**Parameter(s):**
task_id _(int)_
**Usage:**
Disables a task so that it is not available to a client character. Useful if you do not want someone to repeat a task.
**Example:**
#:: Match if the player has an active task
if ($task != 0) {
#:: Create a scalar variable to store the active speak-to activity
$activity = quest::activespeakactivity($task);
#:: Mark the activity as complete
quest::updatetaskactivity($task, $activity);
quest::say("Well done!");
#:: Offer the next task, if there is one
if (!quest::istaskactive($task)) {
#:: Disable the task so that it cannot be repeated
quest::disabletask($task);
#:: Match if there are tasks remaining in the Task Set
if ($task != quest::lasttaskinset(200)) {
quest::say("Well done, I have another task if you are willing.");
#:: Enable the next Task in the Task Set
quest::enabletask(quest::nexttaskinset(200, $task));
}
#:: Match if there are no tasks remaining in the task set
else {
quest::say("Thank you for cleansing Qeynos Hills!");
}
}
}
istaskenabled¶
**Parameter(s):**
task_id (int)
**Usage:**
Used to determine if a task is enabled, by Task ID.
**Example:**
#:: Check if task 212 is enabled
quest::istaskenabled(212); #:: Returns bool
enabledtaskcount¶
**Parameter(s):**
task_set _(int)_
**Usage:**
Counts the enabled tasks in the specified Task Set.
**Example:**
#:: Match if there are no enabled tasks in Task Set 10
if (quest::enabledtaskcount(10) == 0) {
quest::enabletask(50, 51, 52);
}
firsttaskinset¶
**Parameter(s):**
task_set _(int)_
**Usage:**
Returns the first task in the specified Task Set.
**Example:**
sub EVENT_SAY {
#:: If the player hasn't completed the last task in the Task Set
if (!quest::istaskcompleted(quest::lasttaskinset(200))) {
#:: If the player has no tasks enabled for this task set, enable the first one
if (quest::enabledtaskcount(200) == 0) {
quest::say("You have not done any of my tasks before!");
#:: Enable the first task in Task Set 200
quest::enabletask(quest::firsttaskinset(200));
}
}
}
lasttaskinset¶
**Parameter(s):**
task_set _(int)_
**Usage:**
Returns the last task in the specified Task Set.
**Example:**
#:: Find the Task ID of the last task in Task Set 200
quest::lasttaskinset(200); #:: Returns int
nexttaskinset¶
**Parameter(s):**
task_set _(int)_, task_id _(int)_
**Usage:**
Returns the next task in the specified Task Set that comes after the specified Task ID.
**Example:**
sub EVENT_SAY {
#:: Create a scalar variable to store a task integer
$task = quest::activespeaktask();
#:: Match if there is an active task to speak to the NPC
if ($task != 0) {
#:: Match if there are no active tasks for the current speaking task
if (!quest::istaskactive($task)) {
#:: Disable the current speaking task
quest::disabletask($task);
#:: Match if the current speaking task is NOT the last task in the Task Set
if ($task != quest::lasttaskinset(200)) {
quest::say("Well done, I have another task if you are willing.");
#:: Enable the next task in Task Set 200
quest::enabletask(quest::nexttaskinset(200, $task));
}
else {
quest::say("Thank you for cleansing Qeynos Hills!");
}
}
}
}
activespeaktask¶
**Parameter(s):**
None.
**Usage:**
Returns the Task ID of the lowest numbered task slot if the player who triggered the event has an active task with an active activity to speak to the NPC (returns 0 if not).
**Example:**
If you have task id 150: activity 0--kill three rats, activity 1--talk with NPC, activity 2--kill four fire beetles, activity 3--talk with NPC.
sub EVENT_SAY {
#:: Match text for hail, case insensitive
if ($text=~/hail/i) {
#:: Create a scalar variable to store the current task that has a speak activity
$speaktask = quest::activespeaktask(); #:: Returns int
#:: Match if there's an active task with a speak activity
if ($speaktask => 1) {
quest::say("You have a task to speak with me and its ID is $speaktask.");
}
#:: Match if there's NO active task with a speak activity
else {
quest::say("You do not have any tasks with a speaking activity at this time.");
}
}
}
activespeakactivity¶
**Parameter(s):**
task_id _(int)_
**Usage:**
Returns the Activity ID of the lowest numbered active activity to speak with an NPC in the specified task.
**Example:**
If you have task id 150: activity 0--kill three rats, activity 1--talk with NPC, activity 2--kill four fire beetles, activity 3--talk with NPC.
sub EVENT_SAY {
#:: Match text for hail, case insensitive
if ($text=~/hail/i) {
#:: Create a scalar variable to store the current speak activity for task 150
$speakactivity = quest::activespeakactivity(150); #:: Returns int
#:: Match if the player is on the first speak activity
if ($speakactivity == 1) {
quest::say("I really hate rats.");
}
#:: Match if the player is on the second speak activity
elsif ($speakactivity == 3) {
quest::say("I really hate fire beetles.");
}
}
}
activetasksinset¶
**Parameter(s):**
task_set _(int)_
**Usage:**
Returns the number of tasks in the given TaskSet that the player has active.
**Example:**
You have a TaskSet "20", which consists of three tasks--200, 201, 202.
sub EVENT_SAY {
#:: Create a scalar variable to store the number of active tasks in TaskSet 20
$activetaskcount = quest::activetasksinset(20); #:: returns int
#:: Match text for hail, case insensitive
if ($text=~/hail/i) {
quest::say("You have $activetaskcount tasks remaining.");
}
}
completedtasksinset¶
**Parameter(s):**
task_set _(int)_
**Usage:**
Returns the number of tasks in the given Task Set that the player has completed.
**Example:**
sub EVENT_SAY {
#:: Match text for "tasks", case insensitive
if ($text=~/tasks/i) {
#:: Create a scalar variable to store the count of completed tasks in task set "200"
my $TasksComplete = quest::completedtasksinset(200); #:: Returns int
quest::say("You have completed $TasksComplete tasks.");
}
}
EVENT_TASKACCEPTED¶
Trigger¶
- when a player accepts a task from the task selector window.
Info
If the assigntask(taskid) function is used to forcibly assign a task to a player, then this sub will also be called with task_id set to taskid if assigntask is successful.
EVENT_TASK_COMPLETE¶
Trigger¶
- when a player completes a task.
Exports¶
Name | Type | Usage |
---|---|---|
donecount | int | quest::say($donecount); # returns int |
activity_id | int | quest::say($activity_id); # returns int |
task_id | int | quest::say($task_id); # returns int |
EVENT_TASK_FAIL¶
Trigger¶
- When a player fails a task.
Exports¶
Name | Type | Usage |
---|---|---|
task_id | int | quest::say($task_id); # returns int |
EVENT_TASK_STAGE_COMPLETE¶
Trigger¶
- When a task stage is completed.
Exports¶
Name | Type | Usage |
---|---|---|
activity_id | int | quest::say($activity_id); # returns int |
task_id | int | quest::say($task_id); # returns int |
Example¶
- In this example, when a player completes a task, it triggers the event and tries to match with task ID 212; if it matches, a yellow message is displayed to the client.
sub EVENT_TASK_STAGE_COMPLETE {
#:: Match task id 212
if ($task_id == 212) {
$client->Message(15,"The zombie presence seems somewhat lessened, and perhaps they have been quelled...for the time being.");
}
}
function event_task_stage_complete(e)
--:: Match task id 212
if (e.task_id == 212) then
e.self:Message(15, "The zombie presence seems somewhat lessened, and perhaps they have been quelled...for the time being.");
end
end
EVENT_TASK_UPDATE¶
Trigger¶
- when a player's task is updated.
Exports¶
Name | Type | Usage |
---|---|---|
donecount | int | quest::say($donecount); # returns int |
activity_id | int | quest::say($activity_id); # returns int |
task_id | int | quest::say($task_id); # returns int |