Achievements - ThePix/QuestJS GitHub Wiki

An achievement in this context means the user has done something noteworthy, and furthermore that the list of things done is tracked across multiple play throughs. If you use Steam, this will be a very familiar concept. It is not suitable to all games, but it can help to make your game replayable - the first time the user plays it one way, the second time another way hoping to additional achievements.

Achievements are stored in the browser's "localStorage". They will get reset if the user clears the browser history. It would be a bad idea to rely on achievements being maintained.

Setting Up

Achievements are not a part of QuestJS by default. You will need to tell QuestJS to include them by adding this line to settings.js.

settings.libraries.push('achievements')

There are two approaches to creating achievements; you can either create it in advance, or on the fly as it happens. The important difference is that when the player does the ACHIEVEMENTS command, she will see outstanding achievements that were created in advance. Whether that is a good thing (it tells the player what to aim for) or a bad thing (spoilers) is up to you to decide. Achievements that are created in advance can have a condition to check for, or you can trigger them in code. For achievements that are set up on the fly, only the latter makes sense. This, then, gives us three types of achievements, and you can have a mixture of all three in your game.

All achievements are saved the same way, identified by a name; this name must therefore be unique.

On the fly, triggered

You can create a completed achievement by using the achievements.set function. You must pass it a name, and some details. A new achievement will be created and flagged as achieved. The player will see a message on screen.

achievements.set('win', 'You won the prize!')

If an achievement with that name already exists, and has already been achieved, this will do nothing.

In advance, triggered

Use the createAchievement function to create achievements in advance. This could be in code.js.

createAchievement({
  name:"win",
  details:"You won the prize!",
})

You can add a couple of other attributes.

createAchievement({
  name:"win",
  alias:"Win a prize",
  details:"See if you can win a prize!",
  afterDetails:"You won the biggest fish prize!",
})

To trigger the achievement, use the achievements.set function as before. You must pass it a name, and in this case the details are optional. If you do include details this string will be used in place of the one set above. The player will see a message on screen.

achievements.set('win')

achievements.set('win', 'You won the biggest fish prize with your huge cod!')

In advance, conditional

This is set up as before, but with an additional "condition" attribute; a function that returns a Boolean. The achievement will be triggered the first time this is true.

createAchievement({
  name:"Examine cloak",
  details:"Examine the cloak",
  afterDetails:"You examined the cloak",
  condition:function(){
    return w.cloak.examine_count > 0
  }
})

As usual, the player will see a message on screen.

Player commands

To see a list of achievements, the player can type ACHIEVEMENTS, ACHIEVEMENT, ACHIEVE or just ACH. She can see just outstanding or just completed with ACH OUT or ACHIEVEMENTS COMPLETED, etc.

Functions

There are various functions to support achievements.

Use achievements.set(name, details) to set an achievement when the player has done something, as described above.

Use achievements.get(flag) to get a list of achievements; if flag is true, achievements that have been done, otherwise achievements that are outstanding (and set up in advance). Use achievements.getAll() to get the lot.

Use achievements.list(array) to print the given array of achievements to screen.

Use achievements.reset() to clear the list (possibly only useful during development).

Customise

Achievements use the "achieve" css class; you can set that to change font, colour, etc. otherwise it will default to the style of meta-messages.

You can change how the message shown is displayed by changing achievements.setMsg. This is the default.

achievements.setMsg = function(achievement) {
  _msg("You got an achievement!|{show:ach:alias} - {show:ach:afterDetails}", {ach:achievement}, {cssClass:"meta achieve", tag:'p'})
}

You can customise the messages too. These examples hopefully show how.

  lang.ach_got_one_with_details = "You got an achievement!|{show:ach:alias} - {show:ach:afterDetails}",
  lang.ach_explain = "Use ACH ALL to see all achievements, ACH OUT to see just outstandings or ACH COM to just see completed.",
  lang.ach_none = "There are no achievements set up; perhaps you need to achieve them first?",
  lang.ach_no_out = "There are no outstanding achievements; you've done them all.",
  lang.ach_no_com = "There are no completed achievements; you've got them all to do (or there are none implemented).",