Mission system

Started by
8 comments, last by phil_t 10 years, 5 months ago

In my game I want to have missions/quests for the player to complete.

So I am thinking how I should proceed into implementing it.

As I understand it, there will be a Mission base class, where the other missions/quests will derive from, and implement some methods.

Some missions will be similar though, and I don't want to copy-paste code everywhere. My idea is to have some classes that are the most basic missions, e.g:

1) Bring an item somewhere or to someone

2) Kill one or more enemy

3) Escape from one or more enemy

4) Go from location A to location B (in a given time or not)

5) Drive an enemy away from a location

6) Make an enemy go to some location

7) Follow an ally

8) Avoiding being spotted by someone or for some time

Then I can combine those basic missions to make some more complex ones. E.g a mission where the player must bring an item to someone (1) while at the same time avoiding being spotted (8).

What do you think of this approach?

How are mission systems usually implemented?

Advertisement

I would have a class Mission from which nothing derives. It would contain things like a mission name, description, reward, and a list of goals. A goal is where I would use inheritance to achieve polymorphism. The interface of a goal should allow me to check if the goal is still open, if it has been fulfilled, or if it has failed (e.g., you had to protect some ally and he has been killed). Alternatively, the goal could issue signals when it has been fulfilled and when it has determined it cannot be fulfilled. You probably also want to have a way of checking progress, for goals like "kill 8 enemies of this type", so you can display (3/8) next to the goal.

Thanks a lot!

This is extremely game specific. If you're using a script language for your AI or other stuff, I'd advise you to use the same script for your missions.

But given your post, I assume you'll be doing it all on C++. Ideally, you'll want to create player's missions and, if that's the case, AI and enemies' missions. They can be both the same class and maybe define every mission, as you suggested, as a derivative of the first one. A better idea would be creating basic goals such as survive, stay close, stay away, get away, [...] and on top of those build a sequence of objectives. Of course, you'd want to have the power to apply more than one object at the same time, for an example: Follow the Tank and Protect the Tank, both simultaneously.

But, as a personal note, I'd tell you to start looking around scripting languages, I'm a C++ programmer myself, but I try to do as much as possible with scripting, since it usually helps me add content. There's plenty of learning resources on scripting for games over the internet; my personal languages are Lua and Python, but there are lots of them.

I would suggest that instead of making it actually "a class", you have some way of parametrically describing it, such as a number of defined conditions which need to be satisfied to complete the mission, combined with and/or as necessary, or use a scripting system.

You can then store those parameters in your mission description file (e.g. a text file)

I would have a class Mission from which nothing derives. It would contain things like a mission name, description, reward, and a list of goals. A goal is where I would use inheritance to achieve polymorphism. The interface of a goal should allow me to check if the goal is still open, if it has been fulfilled, or if it has failed (e.g., you had to protect some ally and he has been killed). Alternatively, the goal could issue signals when it has been fulfilled and when it has determined it cannot be fulfilled. You probably also want to have a way of checking progress, for goals like "kill 8 enemies of this type", so you can display (3/8) next to the goal.

This is the goal class (the code is in C#)


public abstract class Goal
	{
		public enum State
		{
			Accomplished,
			Failed,
			InProgress
		}
		
		public Goal()
		{
		}
		
		public abstract void Update(float dt);
		
		public abstract State GetState();
	}

I have figured out that sometimes I need some goals to happen:

  • simultaneously. E.g: Go to location x AND Keep someone alive at the same time
  • One after the other. E.g: Go to location x, then to location y, then to z, then kill someone etc

The first thing that came in my mind was this (This is in the Mission class by the way)

List<Goal> serialGoals; // goals that must be accomplished one after the other, in order

List<Goal> parallelGoals; // goals that none of them must fail (Failed state).

However the above design has the limitation that a particular goal cannot be linked with other parallel goals.

For example let's say I have the following serial goals:

Goal A) Go to location(x1, y1, z1)

Goal B) Kill the boss

But while Goal A is InProgress, I would like to have a parallel goal that would be:

  • Keep guy G alive.

The above goal must go away when Goal A is accomplished. With the design above it cannot be done.

So this is what I thought for this:

The goal class would contain a List<Goal> that would be the parallel goals that must hold true while this one is in progress. I think this is much better and will suffice for a lot of uses.

Is this design good? Do I have to consider more things?

Thanks in advance.

To my mind, the timing of the goals is related to how often the mission's status is checked and updated, not so much the real-time active/inactive state of a goal that has been initiated, is in progress, or has been completed. It might be easier to have a variable (like a bool or enum) in Goal to mark if a goal has been activated or not, and then on each mission-status-check cycle you run through all of the active Goals in the goal list to see their statuses. This might be cleaner because it means that instantiated Goals always indicate one objective, rather than one or any number of objectives. This could also allow for optional goals because the success of each individual objective can be tallied after the mission is completed.

Regardless, your design as stated above seems like it would work just fine if that's the approach you prefer.

-------R.I.P.-------

Selective Quote

~Too Late - Too Soon~

The way I’d do parallel vs serial goals is to have multiple triggers/missions and allow for some of them to be dependent on others. Parallel goals are simply the normal list of goals in the mission class that are && together, while serial goals would be represented by two or more missions where one is dependent on the previous ones.

For that example, it might be something like this:

Mission 1 (aka Mission part A) Conditions:

Goal 1: Go to location(x1,y1,z1) (state can be in progress or accomplished)

Goal 2: Guy G is alive (state can be accomplished or failed)

Mission 2 (aka Mission part B) Conditions:

Goal1: Trigger 1 has been accomplished (state can be accomplished, in progress, or failed)

Goal2: Kill the boss (state can be in progress or accomplished)

Only once Mission 2 is accomplished, will the player be given the reward or whatever other actions you want to trigger for the overall mission. This way, everything isn’t necessarily organized in the same object (although you could have a container class that contains the various serial goals that make up a mission) but it will give you a lot of flexibility in creating missions with many stages, continuing conditions, and dependencies.

The way I’d do parallel vs serial goals is to have multiple triggers/missions and allow for some of them to be dependent on others. Parallel goals are simply the normal list of goals in the mission class that are && together, while serial goals would be represented by two or more missions where one is dependent on the previous ones.

For that example, it might be something like this:

Mission 1 (aka Mission part A) Conditions:

Goal 1: Go to location(x1,y1,z1) (state can be in progress or accomplished)

Goal 2: Guy G is alive (state can be accomplished or failed)

Mission 2 (aka Mission part B) Conditions:

Goal1: Trigger 1 has been accomplished (state can be accomplished, in progress, or failed)

Goal2: Kill the boss (state can be in progress or accomplished)

Only once Mission 2 is accomplished, will the player be given the reward or whatever other actions you want to trigger for the overall mission. This way, everything isn’t necessarily organized in the same object (although you could have a container class that contains the various serial goals that make up a mission) but it will give you a lot of flexibility in creating missions with many stages, continuing conditions, and dependencies.

I scrapped the parallel/serial goals to a cleaner design, similar to what you suggested.

Now I have three classes:

Goal

SubMission - A container of Goals. (this serves as the parallel goals I had earlier)

Mission - A container of SubMissions, which must be completed one after the other (this serves as the serial goals).


Now I have three classes:
Goal
SubMission - A container of Goals. (this serves as the parallel goals I had earlier)
Mission - A container of SubMissions, which must be completed one after the other (this serves as the serial goals).

Have you considered having the parallel/serial thing just be an implementation of Goal subclasses?

Mission - container of Goals

ParallelGoal : Goal - Goal with container of Goals that get accomplished in parallel

SerialGoal : Goal - Goal with container of Goals that get accomplished one after the other

This is a more flexible design that what you have above because it allows for an arbitrary level of nested goals (you basically have a Goal tree with parent nodes implementing serial or parallel functionality).

This topic is closed to new replies.

Advertisement