View Single Post
  #8  
Old 10-01-2014, 01:44 AM
jdoran
Hill Giant
 
Join Date: Jul 2012
Posts: 212
Default

KLS, Thanks for your reply.

I don't think a separate parser will help. The parser interface is insufficient. Now if the parser interface was extended, a separate parser would be fine. There just isn't enough information passed to methods like EventNPC().

I do not need the *Event* name. I need a package name, which is derived from the quest-id.

I also need a subroutine name, which is based off of a trigger-id. Triggers are objects that can cause a quest to advance. They may need to fire multiple times in some cases (collect-n, kill-n). But the trigger decides when its preconditions are met. These cannot be based off an event, since the same event (EVENT_MERIT_KILL for example) might occur multiple places in a quest.

I mentioned in my last message that quests are represented as a graph. Each node in the graph has a set of triggers that must all fire before the quest is allowed to advance. One possible trigger is a subquest. I don't have a list of trigger types handy, but some are {match, subquest, assign, give, kill}. So a trigger might be named subquest_13 (which means the 13th trigger of the quest, which happens to be a subquest).

I should take a short moment to highlight one oddball requirement: quests do not need to be generated on the server which later runs them. They can be generated off-line. They can be generated on a remote machine and sent via email, since a quest is a single XML document. This quest can be loaded onto a server without affecting any other quest. It can be removed at any point without harm. (Actually there is a bug I've been meaning to deal with, but it is minor: Quest-specific items may be in inventory, and these are not scrubbed when a quest is removed. However, they get removed from inventory upon zoning, but the item is still in the inventory table. I'll fix this once I get everything ported to the current code base.)

One objection I have to using an object-id for a package name is that a single object (such as an NPC) may be involved in more than one quest. I require each quest to be in its own namespace. This is to avoid collisions in subroutine names, which are based off of "trigger" names. A trigger name such as "subquest_13" is not guaranteed to be server-unique. Multiple quests may have a similarly named trigger. Consider that if NPC 100000 is involved with two separate quests, and each has a trigger named "subquest_13", there would be two Perl subroutines with the same name in the same namespace. A separate namespace solves this problem. (Why use names like subquest_13 which could collide?? The quests may be generated on a machine with no knowledge of what subroutine names are available). At one point the generator named the triggers "trigger_1", "trigger_2" etc. The word "trigger" was later replaced with the trigger type as a debugging aid.

The quest-ids are assigned when a quest is imported into a server. This number is server-unique, but not globally unique. Each quest does have a GUID assigned, but this is too cumbersome to be used in subroutine/package names. I mainly use it to prevent the same quest from being added multiple times, and to remove a quest based on the XML document. When a quest is loaded onto the server, it is assigned an id such as 500200. From that point on, the runtime code uses this quest-id. When an event (such as our MERIT_KILL) occurs, it is passed to each trigger which registered that event type. If the trigger fires, it would pass the quest-d (500200) and the subroutine name (kill_21) to the parser.

By the way, clarifying these points is very helpful to me, so please point out anything that isn't clear. I am thinking of writing this up and presenting the generator at a conference. I will probably consult these forum posts when it comes time to decide what material to discuss.

Last edited by jdoran; 10-01-2014 at 01:50 AM.. Reason: Wanted to clarify a point regarding trigger names
Reply With Quote