8
\$\begingroup\$

Take for example Team Fortress 2. There are a huge load of achievements, and I'm wondering how the manages all of them. And since there's a lot of achievements, I'd also like to know how it "knows" you've achieved one.

Basically, how can the game handle a huge achievement system? Is there some special process? Are there hundreds and hundreds of boolean variables all over the code, waiting for certain conditions to be met, then ,Bam, achievement?

If there are several approaches, what are they?

\$\endgroup\$
4
  • \$\begingroup\$ There are lots of ways to handle this, and since TF2 isn't open source, we'll never know, although since it is a steam game, it must use their API, check it out... partner.steamgames.com/documentation... I guess the point is there is no right or wrong answer... \$\endgroup\$ Commented Mar 25, 2013 at 3:15
  • 1
    \$\begingroup\$ Is your real question: what is a good system to detect if a specific situation is happening? I'm also bazzled by the number of situations they have to track for all the TF2 achievements. \$\endgroup\$
    – Roy T.
    Commented Mar 25, 2013 at 7:03
  • \$\begingroup\$ you have to remember that you wont be able to achieve all the achievements all the time - so depending on your character choice / level / weapon etc... the total achievements available (while still impressively large) is still somewhat smaller than the total amount in the game \$\endgroup\$
    – MephistonX
    Commented Mar 25, 2013 at 10:02
  • \$\begingroup\$ @RoyT. Yeah. But my question came out worded wrong, sorry. \$\endgroup\$
    – yuritsuki
    Commented Mar 25, 2013 at 11:33

1 Answer 1

6
\$\begingroup\$

I think one method to implement something like this could be event-driven. This means, you will have points in your code where specific events are called. It must be somewhat extended to allow to pass parameters, but I think it’s not uncommon that event-systems can handle parameters.

First you will have to define some events in your code that can happen. This is the position where you thought of all the if-conditions. E.g. when a player kills somebody, an event for killing somebody will be raised.

I do not know Team Fortress 2, but it’s a shooter, so I choose some shooter examples. In the code examples the first parameters always is the event name and the later ones are an indefinite list of parameters (this event takes).

  • player kills another player (callEvent('kills-player', curPlayer))
  • player just disarmed a bomb (callEvent('disarms-bomb', curPlayer))
  • player reached point X (callEvent('reaches-point', curPlayer, somePointOnMap))
  • player saved another players live (callEvent('saved-player', curPlayer, rescuedPlayer))

So it’s not boolean variables throughout your code, but specific events that will be called.

It’s now up to a totally different programmer at a totally different position in the code to either use or not use these events (called listening to them). You might also save events in a database to be able to count them (and give awards when something occured 10 times). This will also be done by the programmer who catches the events with a method like the following. It takes:

  • the event-name as first parameter
  • a lambda-function to handle the event as the second parameter. The lambda-function can catch all arguments we passed to the event handler before.

Code example:

listenToEvent('kills-player', function(player) {
    database.incrementKillPlayerCount(player);

    if (database.killPlayerCount(player) == 10) {
        player.awardWithAchievement("You killed 10 enemies!");
    }
});

So this little function can now cope with events that were raised in a totally different place of th code. And it will award a player with the correct achievement if needed.

Addition

As it sounds like TF2's system was very flexible: You might also implement the event-system in a manner that it watches for several situations to occur within the same time or within a timespan. Of course you had to change it a little to maintain a small buffer or similar for several seconds or milliseconds and then map calls like listenToEvent(array('kills-player', 'disarms-bomb') function() {}) to the buffer.

\$\endgroup\$

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