asobi_quests_lua (asobi_quests v0.2.2)

View Source

The game.quests.* surface, for game scripts.

function init(state)
    game.quests.define({
        quest_key = "daily_kills", title = "Ten kills",
        counter = "kills", target = 10, period = "daily",
        reward_currency = "gold", reward_amount = 100
    })
    return state
end

function on_kill(player_id, state)
    local result = game.quests.progress(player_id, "kills", 1)
    for _, q in ipairs(result.ok) do
        if q.newly_completed then
            game.broadcast("quest_complete", { player = player_id, quest = q.quest_key })
        end
    end
    return state
end

The calling convention is assumed, not specified

The lua callback of asobi_extension declares mfa, args, effects and vms, and core has no injector that reads it yet (asobi_lua_api:install/2 installs exactly asobi_lua_surface:reserved_namespaces/0). So the shape of these functions is inferred from the manifest rather than from anything that calls them:

  • Each function is a plain Erlang function of length(args) arguments, already decoded from Lua. It never sees the Luerl state, so it cannot encode a table itself.
  • It returns {ok, Term} or {error, Binary}, which the injector is assumed to wrap in core's { ok = ... } / { error = "..." } envelope. That envelope is produced by asobi_lua_api's unexported wrap_result/2, so an extension cannot produce it and must not try.
  • Nothing carries VM context. A binding cannot know which match it was called from. Quests does not need it; something like game.clans.broadcast would.

Every one of those is a gap, not a design. See the README.

Summary

Functions

game.quests.claim(player_id, quest_key) - grant a completed quest's reward.

game.quests.define(spec) - declare or update a quest. Idempotent.

game.quests.progress(player_id, counter, amount) - advance every quest on that counter.

game.quests.status(player_id) - every active quest's state for a player.

Normalise a quest spec as it arrives from Lua into asobi_quests params.

Functions

claim/2

-spec claim(binary(), binary()) -> {ok, map()} | {error, binary()}.

game.quests.claim(player_id, quest_key) - grant a completed quest's reward.

define(Spec)

-spec define(map() | [{binary(), term()}]) -> {ok, map()} | {error, binary()}.

game.quests.define(spec) - declare or update a quest. Idempotent.

progress/3

-spec progress(binary(), binary(), number()) -> {ok, [map()]} | {error, binary()}.

game.quests.progress(player_id, counter, amount) - advance every quest on that counter.

status/1

-spec status(binary()) -> {ok, [map()]} | {error, binary()}.

game.quests.status(player_id) - every active quest's state for a player.

to_params/1

-spec to_params(term()) -> {ok, map()} | error.

Normalise a quest spec as it arrives from Lua into asobi_quests params.

Luerl decodes a Lua table to a proplist keyed by binaries, so both that and a plain map arrive here. Exported because the translation is the whole of what this adapter does that is worth testing without a database.