Chapter 10
Quests

The backbone of any good fantasy or sci-fi story is the quest the main character undertakes. It may be the lone knight journeying through the countryside and defeating all enemies who stand in his way until he gets to the castle where the evil king/knight/wizard is holding the princess. Or it could be a cave where the dragon that has been ravaging the land is hiding. Whatever it is, you know that a huge battle is going to happen near the end of the story.

Along the way, the character could have interesting little side adventures, or subquests. They might not have any effect on the main quest or they could be vital to its success. Saving a small village from a pack of orcs is an example of a subquest that might not affect the main quest. The character may think that undertaking the subquest could delay him from completing the main one or he may consider the fact that he might not survive a battle with the orcs so he decides not to accept it. Accepting or declining this subquest may have no effect on his completing the main quest, unless he dies, or there could be some side effects of his decision not to accept it.

Perhaps he’s a member of an organization that has made ridding the land of orcs its goal. If word gets back that he didn’t accept the subquest, he could face being kicked out of the organization. Or say the character is a paladin and one of his oaths is to protect the helpless. His church or god may not like the fact that he abandoned the village. Even if the character rescues the princess or kills the dragon, this fact may be overshadowed by the penalty of not accepting the side-quest.

What if the character has set out to slay a dragon and hears a rumor that it’s invulnerable to all weapons but a particular magic sword that has been lost for centuries? The character would have to first find that sword before he could face the dragon. This is an example of a subquest that must be completed before the main one can be finished. Or the subquest could be finding a key that unlocks the room holding the princess since the room has been magically sealed against all entry without the key.

Subquests may just make the story more interesting or may be one or more necessary steps in the completion of the main quest. Quests are a staple of most stories either way. The same is true for most good RPGs, whether they’re single player or multiplayer. Some of the MMORPGs that I’ve played — EverQuest, World of Warcraft, and Dark Age of Camelot among them — had hundreds of different types of quests that characters could undertake. The quests covered everything from running notes between different NPCs to slaying a monster for an item. Most of them had several steps that had to be completed before the quest was finished. Completing quests was one of the things that made playing the game so much fun. When you see a character run by with a flaming sword you would most likely say, “Wow, I have to get one of these!” and then spend the next couple of days or weeks figuring out the steps necessary to complete that quest. Oftentimes this consisted of sitting around waiting for a certain creature to appear. That was a big problem with the quests in those games. Some creatures only appeared once a day or week and then only at a certain time. If you couldn’t be online at that time, you missed your chance. In my opinion, that’s unacceptable and is one of the biggest problems with MMORPGs at this point.

The quest system we’ll implement here will be very basic, as it has to be. It will, however, cover quests in enough detail to allow you to understand how they work so that you can implement quests of your own with any number of steps and/or subquests. We’ll attempt to make it easy to change and expand on. I know you’re all impatient, so let’s dig in.

The Quest Class

Listing 10-1


public class Quest
{

private int _id;
private string _name;
private string _description;
private QuestType _type;
private QuestRewardType _rewardType;
private long _rewardItemID;
private string _requiredClasses;
private int _requiredLevel;
private bool _isMultipleAllowed;

// 0 means no limit
private long _timeBetweenQuests;

// total time in which quest must be completed, 0 for none
private long _timeLimit;

// is the reward known by the player when accepting the quest
private bool _isRewardShown;

// array of FactionAdjust
private List<KeyValuePair<int,int> _factions;

// array of QuestStep
private List<QuestStep> _steps = new List<QuestStep>();
}

As with other classes, the _id member will be used in Entity objects to find a quest. Why do I say “used in Entity objects”? Quests are usually given to and undertaken by entities. Sure, you could have a quest just lying around waiting for the player to come by and accept it (say, finding a piece of paper with a map to a treasure on it or a “Help Wanted” job board in the center of a town), but it’s easier to just have them come from an entity. You could certainly expand quests to come from places like the aforementioned map or job board, and I would encourage you to do so if you plan on creating a “real” world in your RPG.

A FedEx quest, named after the delivery company, is a quest in which the player has to deliver an item to an entity. The item could be given to the player by the entity giving the quest or it might have to be found by the player. In the latter case, the entity giving the quest could be who the item is delivered to or it could be another entity.

The _type member can be used to allow filtering of quests by the programmer, designer, or player. This can be useful in determining how many of what types of quests are available to players. If you’ve designed 100 FedEx quests and only 25 Kill quests, you may want to come up with more of the latter type quests. Currently this member may be one of the following:

Listing 10-2


public enum QuestType
{
FedEx,
Item,
KillMonster,
Rescue
}

There are probably more types of quests that could be implemented, but these will do for now and we’ll only actually implement one of them in our sample game.

Although a quest may be of a certain type, it can actually contain steps or even subquests of totally different types. How complex you make your quests is totally up to you. That’s not to say that the more complex a quest is, the better it is. Sometimes more is less. You could construct a quest that takes the player a month of playing time to complete, but making it interesting enough to make the player want to complete it could be difficult. If the player has to go all over the game world and listen to NPCs ramble on and on about things before getting the next step of the quest, which turns out to be nearly impossible to complete, players may just end up uninstalling your game and moving on to something “better.” I put the word in quotes because it’s a subjective word. What you think is good and works for a quest or your game might not be something that a majority of gamers like. If you are making your game with plans to sell it, you’ll need to be aware of your target audience. A game where your side-quests (or even the main quest) make Frodo’s journey in the Lord of the Rings trilogy seem like a trip to the corner store probably won’t be something most RPG enthusiasts will take the time to play through. If you’re making your game just for the experience and it’s something only you or other people like you will be playing, go for it.

Usually your game will contain one main quest that is the overall goal of the game, but along the way the player could undertake many other different quests. This is a good thing. If your game consists of only quests where the player acts as a courier or goes on a killing spree, again you run the risk of not attracting or holding the attention of players for very long. Mix it up; keep it interesting. If a player gets the opportunity to accept a quest in the middle of another one, you’re making him have to think and choose, especially if the quest he’s on has a time limit or has an unknown reward. Most RPG players enjoy this; if we wanted mindless activity we’d just play FPS games! A quest has to have a reward and the _rewardType member indicates what that reward is. It can be one of five different types:

Listing 10-3


public enum QuestRewardType
{
Armor,
Item,
Money,
Spell,
Weapon
}

The _rewardItemID member is used to indicate the specific item to be given to the player. This could be a generic item of that type or a unique item. In the case of money, this member is the amount given to the player. This member is used in conjunction with the _isRewardShown member and could be another useful filter for the player if you show the reward of the quest before the player has to accept it. If it’s an optional side-quest and the player can’t use the item that he’ll be given, he could just ignore the quest and move on to something else. You can also use it during development of your game to see how many of what types of items you’re offering to the player. If all your quests give out money, this could be another reason the player gets bored with your game. RPG players like money, but they also like unique, interesting items as well, especially if they’re things that can’t be bought with the money they acquire.

The _requiredClasses and _requiredLevel members allow the quest to be given only to certain characters. If the character doesn’t meet these criteria, the player may not even know certain quests exist, although you could set it up so that the entity that has the quest says something like “Oh dear, I really need a <some other class than the character>. Would you happen to know where I can find one?” or “I don’t think you’re ready to undertake such a difficult task. Come back to me when you’ve gotten some experience.” In the latter case, if you implement a log or note system, you could allow the player to create a reminder to himself that the entity has a quest and to come back when he’s increased in level. Note that the _requiredClasses member allows for more than one type of class to be given the quest. It’s simply the names of the classes separated by a comma. The logic for interacting with entities will figure out if the character can be presented with the quest.

You could change the way these two members will be used in order to allow different pairings of class and level. For instance, you could specify that a low-level fighter can complete the quest, but the same quest will require a higher level mage. This is a useful thing to implement and isn’t difficult to do, although it will take some effort to ensure it works nicely.

If the quest is a generic one, you can allow the player to undertake it more than once by setting the _isMultipleAllowed member to true. This is usually done for the Item or KillMonster quests since the other two types rely on something that is probably unique. You could create a FedEx quest to, say, deliver items from a warehouse to a storekeeper, however. It all depends on what you want to do. That’s the nice thing about a flexible system.

If a quest is allowed to be undertaken more than once, the _timeBetweenQuests member will need to be consulted to determine if the player can be presented with the task when he interacts with the entity after completing the quest the first time.

Although time isn’t usually a factor in most non-MMORPGs, the capability to require a quest be completed in a certain amount of time is there. The _timeLimit member will be used along with two members of another class to determine if the player has completed the quest in time. This is actual playing time, not real time.

The _factions member is something I kind of “borrowed” from the MMO genre. There are probably single-player RPGs that use this type of idea, but it’s widely used in MMOs. A faction can be a race, a group of entities that belong to a guild or perform a type of job (such as blacksmiths), citizens of a city or country, or just about anything else you want to designate as a faction. It could even be every entity in your game that likes dogs — it’s whatever you decide.

An entity can belong to many factions, just like people in the real world can belong to many clubs or organizations. You’ll have to be careful with assigning factions to an entity, however. You could end up with a situation where entities will not associate with the player because the character’s status with one or more factions is not high or low enough to allow the entities to interact with him. This could lead to the player being unable to complete the game if interacting with certain entities is part of the gameplay. This is one area where having a complete design before you start development would be beneficial. It might not alleviate all problems, but it could allow you to catch them before you get too far into development.

The FactionAdjust structure that makes up the items that fill this list is a simple KeyValuePair where the key is the ID of the faction and the value is the positive or negative number to add to that entity’s “score” with that faction upon completion of the quest.

Every interaction with an entity will be preceded by a faction check, comparing all factions the entity belongs to with the value for the player’s character faction. Depending on the value, the entity might not interact with him or might be very helpful. How the entity reacts is up to you. The character will start out with this member having no items in it, which mean entities will interact with the character in whatever way you set by default. Most entities that are not creatures or monsters will interact positively, and most creatures and monsters will attack the character. You can also set up your game with this being switched around if you want. You would just have to create enough quests to set the scores for the different factions so that this occurs. This assumes that the player accepts and completes these quests, of course.

As was noted before, a quest is made up of one or more steps. The _steps member controls how the quest proceeds, helping to inform the player what he needs to do to move along in a quest. The QuestStep class that makes up the items that fill this member looks like this:

Listing 10-4


public class QuestStep
{
private string _stepName;
private int _giveItemIndex;
private int _getItemIndex;
private string _stepEntity;
private InteractionType _stepInteractionType;

// array of IDs of subquests
private List<int> _subQuests;

private List<Item> _requiredItems;

// required level to start the step,
//each step may have a different level
private byte _minimumLevel;

// number of minutes the step can take
private long _timeLimit;

private string _journalEntry;
}

The first five members should be used to create the _journalEntry member that will be shown in the player’s quest journal, which you will have to create as part of your GUI, so that the player knows what to do. When the step is created in the Quest Editor, the _journalEntry member will be able to be tweaked so it’s grammatically correct. This could be something like “Get the key. Talk to Bill. He will give you the key to return to Bob.” The _stepName would be “Get the key.” The _getItemID and _giveItemID members would point to an item named “key.” The _stepEntity would be “Bill” and the _stepInteractionType would be “Talk.” The only other type of interaction currently is Kill, as can be seen by looking at the enum:

Listing 10-5


public enum InteractionType
{
Talk,
Kill
}

If the entity for the step is friendly — a shopkeeper, town guard, barmaid, whatever — a check is done to see if the entity has a conversation to start with the character. We’ll discuss creating these conversations in the next chapter. The conversation manager will detect that the character has been assigned a quest and start the conversation to finish the step.

Like a quest itself, a quest step can contain subquests that have to be completed before the step can be completed. You may want to do it this way instead of just having the subquest as additional steps in the quest if the subquest is one that can be obtained outside of the current quest. An example is a quest where an entity wants an article of clothing made from the skin of some type of animal. The character goes to the store to buy the article, only to find out that the storekeeper doesn’t have the pelts to make the article. The character is then given the subquest to kill <x> number of that animal and retrieve the pelts. This Kill quest might also have been something the character could have obtained if he’d gone to the shopkeeper to buy or sell something before he’d accepted the current quest. Completing this subquest would then fulfill the requirement of the _requiredItems member, the pelts.

While it’s unlikely that most RPGs would do this, you can include the ability for a step to require a certain level, just like a quest itself could require a certain level. The _minimumLevel member allows you to do this. This level could be any number greater than either the previous step or the _requiredLevel member of the quest itself.

The _timeLimit member works just like the one for the Quest class. Note that this value isn’t added to the _timeLimit member of the Quest class. That member should be the time to complete the entire quest. The elapsed time will be tracked for both the quest and the current step.

When a player accepts a quest, an AssignedQuest object is added to the _quests list in the Entity object for the character. The AssignedQuest class looks like this:

Listing 10-6


public class AssignedQuest
{
private int _questID;
private int _curStep;
private long _timeStepStarted;
private long _timeStepFinished;
private long _timeQuestStarted;
private long _timeQuestFinished;
private string _questGiverName;
private bool _questFinished;
}

This class keeps track of the ID of the quest, the current step the player is on, the time the quest and current step started and finished, the ID of the entity that gave the player the quest, and whether or not the quest has been completed. The last member is used instead of just checking the _timeQuestFinished member because of the possibility of the quest not being finished. When the _timeStepFinished member is filled in, the value is compared with the time the step started and then the quest is checked to see if there was a time limit on the step. If so and the player exceeded that time, the quest is aborted, setting _questFinished to true but not filling in the _timeQuestFinished member.

Entity Class Changes

The entity class gets some new members for both the player character and NPCs:

Listing 10-7


private List<int> _npcQuestIDs;
private List<AssignedQuest> _assignedQuests;

The first member holds the quest IDs for any quests an NPC may have to give to the player and the second is the list of quests the player has accepted, which is only used in the player character Entity object. This list will be iterated through as part of the game’s update code to check timing of steps and the overall quest.

Creating Quests

Designing quests is something you’ll want to give some thought to so that they’re interesting and challenging, but actually creating them isn’t hard. It’s a simple matter of firing up the Quest Editor, filling in some controls, and saving. The following figure shows the application in the middle of entering some data for a quest:

Figure 10-1

When you start the application, it will load any existing quests that it finds in the application folder’s Quest folder and put the quest names in the Quests combo box. This means we need another function in the GlobalFunctions class to handle the loading of the quest data:

Listing 10-8


public static Quest LoadQuest(string filename)
{
XmlSerializer serializer = new XmlSerializer(typeof(Quest));

try
{
XmlReader reader = XmlReader.Create(new FileStream(
filename, FileMode.Open));

Quest quest = IntermediateSerializer.Deserialize<Quest>(
reader, null);

reader.Close();

return quest;
}
catch (Exception ex)
{
return null;
}
}

The controls will be empty (the combo boxes will have items in them, but nothing will be selected). You can start filling them out or select an existing quest from the combo box and the data for the quest will be filled in.

Clicking on the button to the right of the Factions Affected list box will display a small form where you can edit the factions affected by the quest:

Figure 10-2

If factions already exist, they’ll be passed to the form when it’s created. Clicking on a faction will display the Adjustment value in the Amount text box. If you want to change it, simply change the value or clear it out and go on to the next faction or click the OK button.

In looking at the quest shown in Figure 10-1, we would guess that it wouldn’t make dwarves very happy if they were to find out a character was killing their kinfolk. In this case the Dwarves faction would get a negative value for the amount. But if the dwarves were at war with the goblins (and when aren’t they in almost every fantasy novel out there?), the goblins would be happy with the character so that faction would get a positive value.

The form keeps track of everything that’s entered and, when you click the OK button, the Quest Editor form will get those values and update the Factions Affected list box.

The data on the Quest Editor form is just that — data for the quest itself, not for the steps that make up the quest. To edit the steps for the quest, click the Edit Steps button, which displays the following form:

Figure 10-3

Note that any subquests have to be created prior to creating the quest that uses them in order to populate the Subquests combo box. This should be obvious, but it’s worth pointing out. You can always go back and edit a step that requires subquests, but creating the subquests in advance will save time, which is always a good thing when developing an RPG if you haven’t figured that out by now.

Any items, either for a step or as a reward for the quest, will also have to be created to populate the Give Item and Get Item combo boxes as well as those in the Required Items area.

Make sure the Journal Entry data is clear and concise. The player will probably be depending on it to remind him what he has to do, especially if he has several quests going on at once.

Summary

I’m sure you have a lot of ideas for exciting, challenging, and fun quests and are anxious to get started creating them. Remember to take time when designing them as they’re arguably the most important part of an RPG. Before you go rushing out to create the next Fellowship of the Ring quest, you might want to check out the next couple of chapters, especially since the next one will help you give voice to your quests by explaining the building of conversations. Players will have to interact with NPCs in order to get to all the quests you have in your head, and conversations are the best way to interact with them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.196.172