Tips for implementing MMO quest mechanics?

What tools, patterns, or best practices would you recommend to implement the quest mechanics given below listed requirements?

I am talking about software architecture (how generic should you be) and choices for object wiring, event subscription, and representation of conditions. Mentioning of tools / libraries you have successfully used are welcome. Edit: If you are using scripting, what setup do you recommend?

Requirements:

• simple 2D mmo(rpg)
• all the game data, including quests, is stored in a relational database
• any event in the game could trigger a new quest for players or advancement of existing quests
• a quest can have an arbitrary number of conditions that must be met before the quest is available to players
• a quest can consist of an arbitrary number of sub-quests / steps with arbitrary conditions
• quests would range from simple:

talk to A - kill 5 B - talk to A - permanently increase health

• to quite involved:

use item in area X - go to area Y - a bot will spawn - kill bot without taking more than 10% damage - bot drops item - pick up item - portal unlocks - deliver item to J behind the portal - receive gold and experience - allow to pass portal once more - lock portal for this player

• level instances are a possibility (players can complete certain quests in teams or isolation which will spawn the level location just for those participants)

• Quests should preferably be manageable using a world editor without scripting or programming knowledge (Edit: not advocating against scripting in general though)
• I assume C++ as the language of implementation

I was thinking that if I could combine any chain of events and conditions we could model more complex and thus possibly more engaging quests. I experimented with rolling my own ECA (Events-Conditions-Actions) engine but that might be overkill. It has been particularly difficult to model generic conditions without using any sort of scripting.

• Is there any specific reason why you chose to skip any scripting? (such as lua/gamemonkey etc). – Simon Aug 10 '10 at 8:12
• Mostly due to lack of experience and due to (possibly unsound) assumptions of how this could negatively affect performance. Also I wanted to keep world editing as simple as possible. However, I am open for using scripting. – jmp97 Aug 10 '10 at 8:18
• I concur, without scripting support it will be difficult add variety to the quests without involving the engine programmers. – drxzcl Aug 10 '10 at 8:24
• Scripting languages tend to be fast enough that it's not a problem. I'd strongly recommend using them. That said, much of WoW's scripting is based around triggering spells and events. "Talk to A" would, behind the scenes, cause A to "cast a spell" on the player, and the quest would actually be coded "this succeeds when spell #55728 is cast on the player". Then you just need a little AI coding to get creatures to cast spells on the player and you're set. – ZorbaTHut Aug 10 '10 at 10:53
• Modern scripting languages (such as the Lua Vm) are probably fast enough for you. They're easy to use, easy to implement, you can reload the scripts in runtime, you can debug and step the scripts in runtime and you can iterate MUCH faster while making content. I strongly suggest looking into a scripting engine (examples: lua and gamemonkey) in order to script quests. – Simon Aug 10 '10 at 13:06

First a warning, then some advice.

Last time I needed to implement a system like this I was not using an engine originally intended for MMO-like applications. The quest system it shipped with was geared for single player endeavours, and could not be used.

I ended up having to stuff scripts on all the objects involved with the quests more or less by hand, like this (pseudocode):

Lever004_on_activate() {
if isOnQuest(player, QUEST_0012) do_something();
if isOnQuest(player, QUEST_0015) do_something_else();
}


This is a complete nightmare. There is no way to figure out how the quest works without scavenging all through the game. Do not do this.

I would recommend creating a system where the entire quest (line) is represented as a finite state machine, with events to check for transitions and scripts to react to said transition. That makes it easy to keep track of where you are in a given quest (line) and keeps all quest state neatly encapsulated.

If you want, you can make a library of scripts/script templates in your world editor for common occurrances (player talks to NPC, player kills mob, etc.)

I would not worry too much about script performance, as long as you do not fire your event scripts too often. As a rule of thumb, scripts should fire at least an order of magnitude less than the "core" game logic (animation, physics etc). They should react to events, instead of firing periodically to check if a condition has been met.

• Be warned though, statemachines tend to get very convoluted very fast if you want quest paths to be influenced by outside factors or if your quests are relatively complex. Also multiple quest statemachines (if multiple quests can be active) can be a nightmare. However, since in essence every program is a statemachine, it can be done. But complex problems remain complex no matter how you encapsulate them. A good example (imo) is Oblivion where some mods stop other mods from working - your pre and postconditions for states have to be either pretty solid, or extremely forgiving/error tolerant. – Kaj Aug 11 '10 at 5:48
• Yup, kaj is right. Just head over to the WoW forums right now and read about people complaining about unfinishable quests. It happens all the time, even in the major league. It's really hard to get everything right. – drxzcl Aug 11 '10 at 7:50

Our system basically involves running a an expression (custom mini scripting language but tcl/lua/python would work just as well, or make something yourself) each server frame for each mission step. This is for "personal missions" that are tied to a specific player. Each substep is then part of an FSM (finite state machine) for the mission itself (which might just be a substep of another mission). There are also "map missions" which have a single FSM and are tied to the map instead of a player (think WAR's public quests), but the substeps work basically the same.

What these expressions actually look at are events broadcast by the system like "NPC died" or "interaction complete". This means you can somewhat decouple the various parts, the gameplay systems just send out events as needed, which the mission scripts just listen to events and don't worry about where they come from. If you also layer on that you can have the mission FSMs interact with the world state (only show this contact when in mission state X) you can get a lot of power out of the system.