Quote:
Originally Posted by KLS
Actually it would probably be harder to integrate it into an old system than to create a new one as the system would probably be fairly straight forward really.
|
Yes, I was looking at the quest system this morning, and that was my thought.
While I am at work, I thought I would start sketching out how to implement this,
and welcome any thoughts you have on my tentative design choices.
First the tables. Global tables for the stuff that doesn't change (once the task is written),
and character tables to record their progress.
Code:
CREATE TABLE GlobalTasks (
id int(11) unsigned NOT NULL,
duration int(11) unsgined NOT NULL,
description varchar(4000) NOT NULL,
reward varchar(100) NOT NULL,
startzone int(11) NOT NULL,
PRIMARY KEY(id)
)
CREATE TABLE GlobalActivities (
id int(11) unsigned NOT NULL,
activityid int(11) unsigned default '0',
activitytype tinyint unsigned, // Kill, Loot, Deliver, Explore, etc
text1 VARCHAR(100) default '', // For Deliver tasks, this is the NPC name to deliver to, or name of mob for kill tasks etc
text2 VARCHAR(100) default '', // For Deliver tasks, this is the text name of the item to deliver, or item to loot for loot tasks
itemid int(11), // item number for loot tasks.
npcid int(11), // npcid for kill tasks
exploreid int(11) default 0, // For explore tasks, this is a unique number to identify the proximity event that needs to be triggered
goalcount tinyint default 1, // How many things to kill, deliver, loot, etc
zoneid int(11), // The ID number of the zone that this task is performed in
PRIMARY KEY(id, activityid)
)
I am unsure as to whether the text1/text2 fields are required,
or whether I should just pull the npc name/item name as
required based on their id. The npc name/item name is sent as
text in the Task packets. Keeping the text fields as well would
allow the Task designer to be a bit vaguer/ more 'roleplay' in
their objectives if they wished, e.g. 'Kill the master of Karnor'
rather than 'Kill Venril Sathir'.
CREATE TABLE CharacterTasks (
charid int(11) unsigned NOT NULL,
taskid int(11) unsigned NOT NULL,
acceptedtime int(11) unsigned, // Timestamp of when the player accepted the task
completedtime int(11) unsigned default '0', // 0 for an unfished task
PRIMARY KEY(charid, taskid)
)
CREATE TABLE CharacterActivities (
charid int(11) unsigned NOT NULL,
taskid int(11) unsigned NOT NULL,
activityid int(11) unsigned,
donecount tinyint default '0',
completed tinyint(1) default '0', // Not strictly needed, but probably quicker than cross referencing the Global Activity table to check if an activity is complete
PRIMARY KEY(charid, taskid, activityid)
)
The active and completed task information is not retained by the client, certainly not across
logins, and probably not across zoning, so needs to be resent after zoning.
As I see it, zone will need to load the global task and activity tables in their entirety on
zone bootup. This may become an issue later on if their are lots of tasks written. As this is
global static data, it could be a candidate for shared memory, but I will leave that for the
future.
The next issue is how to represent the Tasks in memory. Each Task has a unique ID. I am leaning
toward #defining a MAXTASKID (say 10000 ?), and using a fixed size array ...
TaskInformation* Tasks[MAXTASKID]
The benefit I see of doing this is fast cross referencing to the Task/Activity information from
the per-character data. I think this would also make it easier to #reloadtask a single task
during development.
Onto the per-character info. Should I restrict a character to a maximum number of active tasks, e.g. 20 ?
The benefit I see to this is it constrains the amount of checking that needs to be done on killing/looting
to see if there is a matching goal in the characters active activities.
Pseudo Code:
On NPC Kill or Loot:
for each active task the character has:
for each open activity in that Task:
if ActivityGoal == Kill This NPCType or Loot this item.id Increment Goal Count
It did occur to me that an extra flag could be added to the npc_types and item tables, 'involvedintask',
so that the code could check this flag and if it is set to No, not bother checking the characters
active tasks.
Task initiation will be done through the existing Perl quest system, so the usual checks
for class, race, faction can be done before the NPC initiates the Task Chooser. (Also provide
a function so that a check can be made in Perl to see if the player has already completed
a particular task, so as not to offer it again).
I also see Task Completion/Reward as being handled by the Perl quest system, i.e. the last
activity in a Task would be go speak to an NPC who would then do something along the lines
of:
Code:
if quest::ActiveTask(1234) && quest::TaskActivityComplete(1234,10) .... give reward, quest::TaskComplete(1234)
I would be interested in any links to quests on Alla that use the Task system. I've
been using
http://everquest.allakhazam.com/db/q...tml?quest=3237 as a guide, as
that is the one in the packet collect I was looking at.