T4 Modules Howto Guide/Achievements

From Tales of Maj'Eyal
Jump to: navigation, search

Work in progress. Not yet finished or tested.

Adding the World

T-Engine uses the WorldAchievements interface to track and grant achievements and stores achievements as part of the World object. To add these to your own module:

Add a World.lua file in your class directory. Sample contents (based on ToME's):

require "engine.class"
require "engine.World"
require "engine.interface.WorldAchievements"
local Savefile = require "engine.Savefile"

module(..., package.seeall, class.inherit(engine.World, engine.interface.WorldAchievements))

function _M:init()
    engine.World.init(self)
end

function _M:run()
    self:loadAchievements()
end

--- Requests the world to save
function _M:saveWorld(no_dialog)
    -- savefile_pipe is created as a global by the engine
    savefile_pipe:push("", "world", self)
end

Change load.lua to create a World object as well as a Game object. To do so, edit the last line. It should look something like this:

return { require "mod.class.Game" }

Replace it with this:

return { require "mod.class.Game", require "mod.class.World" }

Defining Achievements

Under your module's data directory, create an achievements directory. Create as many .lua files defining achievements within this directory as you like; each .lua file should call the T-Engine newAchievement function for each achievement to be created.

Here's a sample, based on ToME itself:

newAchievement{
    name = "Pyromancer",
    desc = [[Unlocked Archmage class and did over one million fire damage (with any item/talent/class).]],
    show = "full",
    mode = "world",
    can_gain = function(self, who, dam)
        self.nb = (self.nb or 0) + dam
        return self.nb > 1000000 and profile.mod.allow_build.mage
    end,
    track = function(self) return tstring{tostring(math.floor(self.nb or 0))," / 1000000"} end,
    on_gain = function(_, src, personal)
        game:setAllowedBuild("mage_pyromancer", true)
        local p = game.party:findMember{main=true}
        if p.descriptor.subclass == "Archmage"  then
            if p:knowTalentType("spell/wildfire") == nil then
                p:learnTalentType("spell/wildfire", false)
                p:setTalentTypeMastery("spell/wildfire", 1.3)
            end
        end
    end,
}

Parameters for newAchievement:

Parameter Description
name Name of the achievement
id Internal ID of the achievement. Optional. If not provided, then name will be used, uppercased and with spaces replaced with underscores.
desc Full description
image Optional filename for the achievement
mode "world", "game", "player", or "none". Indicates whether the achievement is tracked for the persistent World object, the game object, or the current player. For example, achievements that can only be gained once ever should be world achievements, while per-character achievements should be player.
huge If true, this achievement is a big deal and gets some extra emphasis when announced.
show Determines how this achievement is listed in the default ShowAchievements dialog:
  • false, nil, or not provided - The achievement is completely hidden. Only the "Achievements (#received/#total)" display at the top of the dialog gives any clue that it exists.
  • "none" - The achievement is listed as "???", and its description is "-- Unknown --".
  • "name" - The achievement's name is listed, but its description is "-- Unknown --".
  • "full" (or anything else) - Full details are listed, whether or not you have the achievement.
no_chat_broadcast If provided and true, then don't broadcast to the in-game chat when this achievement is gained.
can_gain

Optional function, taking (data, src, ...) arguments (where ... is whatever additional arguments were passed to gainAchievement or gainPersonalAchievement), to be called to check whether the achievement can be gained.

data is the persistent achievement data: either world.achievement_data, game.achievement_data, or player.achievement_data, depending on mode.

track Optional function, taking (data, src) arguments, giving progress towards the achievement (for display in the ShowAchievements dialog). Should return a tstring.
on_gain Optional function, taking (self, src, personal) arguments (where self is the achievement definition), to be called when an achievement is gained.

Once you're finished, add code to your load.lua to load the achievements.

local WorldAchievements = require "engine.interface.WorldAchievements"
WorldAchievements:loadDefinition("/data/achievements/")

Showing Achievements

In your Game.lua, you most likely have a call to engine.dialogs.GameMenu, where you pass in a list of menu items for the in-game main menu. Add "achievements" to the list of items here. Then, pressing Esc within the game will include a "Show Achievements" item where you can see the achievements you've defined and whether or not you've received them yet.