6
\$\begingroup\$

I am looking into how to design an instance system for the game I am working on. I have always wondered how these are created in games like World of Warcraft, with its instances (dungeons/raids/etc). Areas that are separated from players other than those in your group, but have specific logic to them.

Specifically how can you reuse your existing code base and not have a bunch of checks like the following

if (isInstance) do x; else do y;

I don't know if this will make too much of a difference on any answers, but we're using a pretty classic "Object as pure aggregation" component system for our entities.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ From an OO point of view you would've a Game class that defines all the laws of your game (physical laws, AI behavior, possible player actions..). If you want to create an instance (think parallel universe), just create another instance of your Game class and assign all players entering a certain zone to it. Now you have two groups of players co-existing in parallel universes. \$\endgroup\$
    – Dave O.
    Feb 16, 2011 at 20:43

3 Answers 3

3
\$\begingroup\$

As you probably guessed, having a bunch of if statements in your code is just about the worst thing you could do. What you actually need, is to abstract different functionality in different "units" - be they classes, functions, scripts or whatever - and make them as self-contained as possible.

Here's how we do that. In our current game, characters can be either in an instance, or in town. We have so-called services, that run in their own threads and process players' requests and game logic. We have one town service and many instance services - one for each instance active on the server.

Thus, town service has logic to deal with town tasks, such as visiting a shop; instance service has logic to deal with instance tasks, such as casting spells. These are not the only services - for example, quests and achievements can happen both in town and in instance, and they're handled in a special quest service, that towns and instances communicate with.

But instance service doesn't contain all game logic pertaining to instances (for one thing, it would be enormous if it did). For example, there's MoveController that handles, you guessed it, movement in instance. This allows us to (theoretically) add some new logic to movement - like, for example, add flying - by just creating another MoveController-derived class. Not that we actually tried (-8

An example that is closer to your question: at start of development, we only had PvE instances, that closed whenever all mobs or all characters died. However, at some time we had to add PvP, which had a bunch of different rules about who won and who lost and when. That is, the game logic in PvP was the same as in PvE, except the finishing part. This is what we did: we created an object called ExitStrategy, whose responsibility was to decide whether instance was to end, and what characters received rewards afterwards. Than we made several different strategies: PvEExitStrategy, DuelExitStrategy, TeamBattleExitStrategy, etc. The instance service has an object of type ExitStrategy, that is created during set-up, based on what type of instance it is. Thus, there's only one place with a bunch of if's (switch actually), neatly tucked in a short method in the startup sequence.

I want to emphasize that we didn't subclass InstanceService instead. While this might seem like a logical thing to do, subclassing is actually bad decision in this case. Suppose we'd later want to add another type of instance - say, with some "mission objectives" to reach. If we used subclassing, we wouldn't be able to add this to both PvE and PvP instances without some code duplication. However, with aggregation we can easily add some ObjectiveManager or something.

To reiterate: you want to have different logic in different places, as independent as possible?, and combine it with aggregation. If you do, you can use whatever "common" game logic you need in the instance, and add or override parts you don't need.

Now, if you're anything like me, this approach would actually leave you with a lot of components that are just not independent enough, and tend to break if you push them too far, especially on first try. But that's still way better than huge inheritance hierarchy, code duplication or, heaven forbid, bunches of if's everywhere.

\$\endgroup\$
3
  • \$\begingroup\$ thanks for the insight on this. I especially liked your examples on the ExitStrategy. \$\endgroup\$
    – Kyle C
    Feb 17, 2011 at 18:14
  • \$\begingroup\$ I don't understand why you couldn't have a class PvX, parent of both PvE and PvP, of course containing the common code (thus avoiding duplication). \$\endgroup\$
    – o0'.
    Feb 18, 2011 at 22:21
  • \$\begingroup\$ @Lo'oris Because "PvE" and "PvP" are not small and self-contained. "PvpExitSttrategy", OTOH, is. \$\endgroup\$
    – Nevermind
    Feb 19, 2011 at 10:44
0
\$\begingroup\$

You wouldn't need a bunch of checks everywhere if you had lots of rooms, right? You just load the room, and do thing that belong to that room, while you're in the room. Leave the room, and these checks are never made again.

Instance logic is decoupled from game logic. Usually they're just the same, but the regular game just "plays" and the instances are scripted (or whatever.) Specially in WoW, where LUA dominates.

\$\endgroup\$
0
\$\begingroup\$

Design elements are generally data-driven, not done in code (at least not in the same code as the engine, some places use Lua or Python code for the gameplay bits).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .