Merge dev branch into master

This commit is contained in:
rubenwardy 2018-04-04 22:15:43 +01:00 committed by GitHub
commit 0574d0375e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1671 additions and 1825 deletions

171
README.md Normal file
View File

@ -0,0 +1,171 @@
# Awards
Adds achievements to Minetest (plus a very good API).
by [rubenwardy](https://rubenwardy.com),
with thanks to Wuzzy, kaeza, and MrIbby.
Majority of awards are back ported from Calinou's old fork in Carbone, under same license.
# API
## Registering Achievements
```lua
awards.register_achievement(name, {
description = "The title of the award",
-- Optional:
sound = {}, -- SimpleSoundSpec or false to play no sound
-- if not provided, uses default sound
image = "icon_image.png", -- uses default icon otherwise
background = "background_image.png", -- uses default background otherwise
trigger = { -- is only unlocked by direct calls to awards.unlock() otherwise
type = "trigger_type",
-- see specific docs on the trigger to see what else goes here
}
})
```
## Registering Trigger Types
```lua
local trigger = awards.register_trigger(name, {
type = "", -- type of trigger, defaults to custom
progress = "%2/%2"
auto_description = { "Mine: @2", "Mine: @1×@2" },
on_register = function(self, def) end
-- "counted_key" only, when no key is given (ie: a total)
auto_description_total = { "Mine @1 block.", "Mine @1 blocks." },
-- "counted_key" only, get key for particular award - return nil for a total
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.node] or def.trigger.node
end
})
```
Types:
* "custom" requires you handle the calling of awards.unlock() yourself. You also
need to implement on_register() yourself.
* "counted" stores a single counter for each player which is incremented by calling
trigger:notify(player). Good for homogenous actions like number of chat messages,
joins, and the like.
* "counted_key" stores a table of counters each indexed by a key. There is also
a total field (`__total`) which stores the sum of all counters. A counter is
incremented by calling trigger:notify(player, key). This is good for things like
placing nodes or crafting items, where the key will be the item or node name.
## Helper Functions
* awards.register_on_unlock(func(name, def))
* name is the player name
* def is the award def.
* return true to cancel HUD
* awards.unlock(name, award)
* gives an award to a player
* name is the player name
# Included in the Mod
The API, above, allows you to register awards
and triggers (things that look for events and unlock awards, they need
to be registered in order to get details from award_def.trigger).
However, all awards and triggers are separate from the API.
They can be found in init.lua and triggers.lua
## Triggers
Callbacks (register a function to be run)
"dig", "place", "craft", "death", "chat", "join" or "eat"
* dig type: Dig a node.
* node: the dug node type. If nil, all dug nodes are counted
* place type: Place a node.
* node: the placed node type. If nil, all placed nodes are counted
* eat type: Eat an item.
* item: the eaten item type. If nil, all eaten items are counted
* craft type: Craft something.
* item: the crafted item type. If nil, all crafted items are counted
* death type: Die.
* reason: the death reason, one of the types in PlayerHPChangeReason (see lua_api.txt)
or nil for total deaths.
* chat type: Write a chat message.
* join type: Join the server.
* (for all types) target - how many times to dig/place/craft/etc.
* See Triggers
### dig
trigger = {
type = "dig",
node = "default:dirt",
target = 50
}
### place
trigger = {
type = "place",
node = "default:dirt",
target = 50
}
### death
trigger = {
type = "death",
target = 5
}
### chat
trigger = {
type = "chat",
target = 100
}
### join
trigger = {
type = "join",
target = 100
}
### eat
trigger = {
type = "eat",
item = "default:apple",
target = 100
}
## Callbacks relating to triggers
* awards.register_on_dig(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_place(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_eat(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_death(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_chat(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_join(func(player, data)
* data is player data (see below)
* return award name or null

529
api.lua
View File

@ -14,50 +14,114 @@
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-- --
local S = awards.gettext local S, NS = awards.gettext, awards.ngettext
dofile(minetest.get_modpath("awards").."/api_helpers.lua") awards.registered_awards = {}
awards.on = {}
awards.on_unlock = {}
local storage = minetest.get_mod_storage()
-- Table Save Load Functions -- Table Save Load Functions
function awards.save() function awards.save()
local file = io.open(minetest.get_worldpath().."/awards.txt", "w") storage:set_string("player_data", minetest.write_json(awards.players))
if file then
file:write(minetest.serialize(awards.players))
file:close()
end
end end
function awards.init() local function convert_data()
awards.players = awards.load() minetest.log("warning", "Importing awards data from previous version")
awards.def = {}
awards.trigger_types = {} local old_players = awards.players
awards.on = {} awards.players = {}
awards.on_unlock = {} for name, data in pairs(old_players) do
while name.name do
name = name.name
end
data.name = name
print("Converting data for " .. name)
-- Just rename counted
local counted = {
chats = "chat",
deaths = "death",
joins = "join",
}
for from, to in pairs(counted) do
data[to] = data[from]
data[from] = nil
end
data.death = {
unknown = data.death,
__total = data.death,
}
-- Convert item db to new format
local counted_items = {
count = "dig",
place = "place",
craft = "craft",
}
for from, to in pairs(counted_items) do
local ret = {}
local count = 0
for modname, items in pairs(data[from]) do
for itemname, value in pairs(items) do
itemname = modname .. ":" .. itemname
local key = minetest.registered_aliases[itemname] or itemname
ret[key] = value
count = count + value
end
end
ret.__total = count
data[from] = nil
data[to] = ret
end
awards.players[name] = data
end
print(dump(awards.players))
end end
function awards.load() function awards.load()
local file = io.open(minetest.get_worldpath().."/awards.txt", "r") local old_save_path = minetest.get_worldpath().."/awards.txt"
local file = io.open(old_save_path, "r")
if file then if file then
local table = minetest.deserialize(file:read("*all")) local table = minetest.deserialize(file:read("*all"))
if type(table) == "table" then if type(table) == "table" then
return table awards.players = table
convert_data()
else
awards.players = {}
end end
end file:close()
return {} os.rename(old_save_path, minetest.get_worldpath().."/awards.bk.txt")
end awards.save()
else
function awards.register_trigger(name, tfunc) awards.players = minetest.parse_json(storage:get_string("player_data")) or {}
awards.trigger_types[name] = tfunc
awards.on[name] = {}
awards['register_on_'..name] = function(func)
table.insert(awards.on[name], func)
end end
end end
function awards.run_trigger_callbacks(player, data, trigger, table_func) function awards.player(name)
for i = 1, #awards.on[trigger] do local data = awards.players[name] or {}
awards.players[name] = data
data.name = data.name or name
data.unlocked = data.unlocked or {}
return data
end
function awards.player_or_nil(name)
return awards.players[name]
end
local default_def = {}
function default_def:run_callbacks(player, data, table_func)
for i = 1, #self.on do
local res = nil local res = nil
local entry = awards.on[trigger][i] local entry = self.on[i]
if type(entry) == "function" then if type(entry) == "function" then
res = entry(player, data) res = entry(player, data)
elseif type(entry) == "table" and entry.award then elseif type(entry) == "table" and entry.award then
@ -70,87 +134,185 @@ function awards.run_trigger_callbacks(player, data, trigger, table_func)
end end
end end
function awards.increment_item_counter(data, field, itemname, count) function awards.register_trigger(tname, tdef)
local name_split = string.split(itemname, ":") assert(type(tdef) == "table",
if #name_split ~= 2 then "Passing a callback to register_trigger is not supported in 3.0")
return false
tdef.name = tname
for key, value in pairs(default_def) do
tdef[key] = value
end end
local mod = name_split[1]
local item = name_split[2]
if data and field and mod and item then if tdef.type == "counted" then
awards.assertPlayer(data) local old_reg = tdef.on_register
awards.tbv(data, field)
awards.tbv(data[field], mod)
awards.tbv(data[field][mod], item, 0)
data[field][mod][item] = data[field][mod][item] + (count or 1) function tdef:on_register(def)
return true local tmp = {
award = def.name,
target = def.trigger.target,
}
tdef.register(tmp)
function def.getProgress(_, data)
local done = data[tname] or 0
return {
perc = done / tmp.target,
label = S(tdef.progress, done, tmp.target),
}
end
function def.getDefaultDescription(_)
local n = def.trigger.target
return NS(tdef.auto_description[1], tdef.auto_description[2], n, n)
end
if old_reg then
return old_reg(tdef, def)
end
end
function tdef.notify(player)
assert(player and player.is_player and player:is_player())
local name = player:get_player_name()
local data = awards.player(name)
print(dump(data))
-- Increment counter
local currentVal = (data[tname] or 0) + 1
data[tname] = currentVal
tdef:run_callbacks(player, data, function(entry)
if entry.target and entry.award and currentVal and
currentVal >= entry.target then
return entry.award
end
end)
end
awards["notify_" .. tname] = tdef.notify
elseif tdef.type == "counted_key" then
local old_reg = tdef.on_register
function tdef:on_register(def)
local tmp = {
award = def.name,
key = tdef:get_key(def),
target = def.trigger.target,
}
tdef.register(tmp)
function def.getProgress(_, data)
local done
data[tname] = data[tname] or {}
if tmp.key then
done = data[tname][tmp.key] or 0
else else
return false done = data[tname].__total or 0
end end
return {
perc = done / tmp.target,
label = S(tdef.progress, done, tmp.target),
}
end
function def.getDefaultDescription(_)
local n = def.trigger.target
if tmp.key then
local nname = tmp.key
return NS(tdef.auto_description[1],
tdef.auto_description[2], n, n, nname)
else
return NS(tdef.auto_description_total[1],
tdef.auto_description_total[2], n, n)
end
end
if old_reg then
return old_reg(tdef, def)
end
end
function tdef.notify(player, key, n)
n = n or 1
assert(player and player.is_player and player:is_player() and key)
local name = player:get_player_name()
local data = awards.player(name)
print(dump(data))
-- Increment counter
data[tname] = data[tname] or {}
local currentVal = (data[tname][key] or 0) + n
data[tname][key] = currentVal
data[tname].__total = (data[tname].__total or 0) + n
tdef:run_callbacks(player, data, function(entry)
local current
if entry.key == key then
current = currentVal
elseif entry.key == nil then
current = data[tname].__total
else
return
end
if current > entry.target then
return entry.award
end
end)
end
awards["notify_" .. tname] = tdef.notify
elseif tdef.type and tdef.type ~= "custom" then
error("Unrecognised trigger type " .. tdef.type)
end
awards.registered_triggers[tname] = tdef
tdef.on = {}
tdef.register = function(func)
table.insert(tdef.on, func)
end
-- Backwards compat
awards.on[tname] = tdef.on
awards['register_on_' .. tname] = tdef.register
return tdef
end
function awards.increment_item_counter(data, field, itemname, count)
itemname = minetest.registered_aliases[itemname] or itemname
data[field][itemname] = (data[field][itemname] or 0) + 1
end end
function awards.get_item_count(data, field, itemname) function awards.get_item_count(data, field, itemname)
local name_split = string.split(itemname, ":") itemname = minetest.registered_aliases[itemname] or itemname
if #name_split ~= 2 then return data[field][itemname] or 0
return false
end
local mod = name_split[1]
local item = name_split[2]
if data and field and mod and item then
awards.assertPlayer(data)
awards.tbv(data, field)
awards.tbv(data[field], mod)
awards.tbv(data[field][mod], item, 0)
return data[field][mod][item]
end
end end
function awards.get_total_item_count(data, field) function awards.get_total_keyed_count(data, field)
local i = 0 return data[field].__total or 0
if data and field then
awards.assertPlayer(data)
awards.tbv(data, field)
for mod,_ in pairs(data[field]) do
awards.tbv(data[field], mod)
for item,_ in pairs(data[field][mod]) do
awards.tbv(data[field][mod], item, 0)
i = i + data[field][mod][item]
end
end
end
return i
end end
function awards.register_on_unlock(func) function awards.register_on_unlock(func)
table.insert(awards.on_unlock, func) table.insert(awards.on_unlock, func)
end end
-- API Functions
function awards._additional_triggers(name, def)
-- Depreciated!
end
function awards.register_achievement(name, def) function awards.register_achievement(name, def)
def.name = name def.name = name
-- Add Triggers -- Add Triggers
if def.trigger and def.trigger.type then if def.trigger and def.trigger.type then
local func = awards.trigger_types[def.trigger.type] local tdef = awards.registered_triggers[def.trigger.type]
assert(tdef, "Trigger not found: " .. def.trigger.type)
if func then tdef:on_register(def)
func(def)
else
awards._additional_triggers(name, def)
end
end end
-- Add Award -- Add Award
awards.def[name] = def awards.registered_awards[name] = def
local tdef = awards.def[name] local tdef = awards.registered_awards[name]
if def.description == nil and tdef.getDefaultDescription then if def.description == nil and tdef.getDefaultDescription then
def.description = tdef:getDefaultDescription() def.description = tdef:getDefaultDescription()
end end
@ -183,23 +345,12 @@ end
-- award - the name of the award to give -- award - the name of the award to give
function awards.unlock(name, award) function awards.unlock(name, award)
-- Access Player Data -- Access Player Data
local data = awards.players[name] local data = awards.player(name)
local awdef = awards.def[award] local awdef = awards.registered_awards[award]
assert(awdef, "Unable to unlock an award which doesn't exist!")
-- Perform checks if data.disabled or
if not data then (data.unlocked[award] and data.unlocked[award] == award) then
return
end
if not awdef then
return
end
if data.disabled then
return
end
awards.tbv(data,"unlocked")
-- Don't give the achievement if it has already been given
if data.unlocked[award] and data.unlocked[award] == award then
return return
end end
@ -241,33 +392,18 @@ function awards.unlock(name, award)
-- Explicit check for nil because sound could be `false` to disable it -- Explicit check for nil because sound could be `false` to disable it
sound = {name="awards_got_generic", gain=0.25} sound = {name="awards_got_generic", gain=0.25}
end end
local custom_announce = awdef.custom_announce
if not custom_announce then
if awdef.secret then
custom_announce = S("Secret Achievement Unlocked:")
else
custom_announce = S("Achievement Unlocked:")
end
end
-- Do Notification -- Do Notification
if sound then if sound then
-- Enforce sound delay to prevent sound spamming -- Enforce sound delay to prevent sound spamming
local lastsound = awards.players[name].lastsound local lastsound = data.lastsound
if lastsound == nil or os.difftime(os.time(), lastsound) >= 1 then if lastsound == nil or os.difftime(os.time(), lastsound) >= 1 then
minetest.sound_play(sound, {to_player=name}) minetest.sound_play(sound, {to_player=name})
awards.players[name].lastsound = os.time() data.lastsound = os.time()
end end
end end
if awards.show_mode == "formspec" then if awards.show_mode == "chat" then
-- use a formspec to send it
minetest.show_formspec(name, "achievements:unlocked", "size[6,2]"..
"image_button_exit[0,0;6,2;"..background..";close1; ]"..
"image_button_exit[0.2,0.8;1,1;"..icon..";close2; ]"..
"label[1.1,1;"..title.."]"..
"label[0.3,0.1;"..custom_announce.."]")
elseif awards.show_mode == "chat" then
local chat_announce local chat_announce
if awdef.secret == true then if awdef.secret == true then
chat_announce = S("Secret Achievement Unlocked: %s") chat_announce = S("Secret Achievement Unlocked: %s")
@ -334,158 +470,6 @@ function awards.unlock(name, award)
end end
end end
-- Backwards compatibility
awards.give_achievement = awards.unlock
--[[minetest.register_chatcommand("gawd", {
params = "award name",
description = "gawd: give award to self",
func = function(name, param)
awards.unlock(name,param)
end
})]]--
function awards.getFormspec(name, to, sid)
local formspec = ""
local listofawards = awards._order_awards(name)
local playerdata = awards.players[name]
if #listofawards == 0 then
formspec = formspec .. "label[3.9,1.5;"..minetest.formspec_escape(S("Error: No awards available.")).."]"
formspec = formspec .. "button_exit[4.2,2.3;3,1;close;"..minetest.formspec_escape(S("OK")).."]"
return formspec
end
-- Sidebar
if sid then
local item = listofawards[sid+0]
local def = awards.def[item.name]
if def and def.secret and not item.got then
formspec = formspec .. "label[1,2.75;"..minetest.formspec_escape(S("(Secret Award)")).."]"..
"image[1,0;3,3;awards_unknown.png]"
if def and def.description then
formspec = formspec .. "textarea[0.25,3.25;4.8,1.7;;"..minetest.formspec_escape(S("Unlock this award to find out what it is."))..";]"
end
else
local title = item.name
if def and def.title then
title = def.title
end
local status = "%s"
if item.got then
status = S("%s (got)")
end
formspec = formspec .. "textarea[0.5,2.7;4.8,1.45;;" ..
string.format(status, minetest.formspec_escape(title)) ..
";]"
if def and def.icon then
formspec = formspec .. "image[1,0;3,3;" .. def.icon .. "]"
end
local barwidth = 4.6
local perc = nil
local label = nil
if def.getProgress and playerdata then
local res = def:getProgress(playerdata)
perc = res.perc
label = res.label
end
if perc then
if perc > 1 then
perc = 1
end
formspec = formspec .. "background[0,4.80;" .. barwidth ..",0.25;awards_progress_gray.png;false]"
formspec = formspec .. "background[0,4.80;" .. (barwidth * perc) ..",0.25;awards_progress_green.png;false]"
if label then
formspec = formspec .. "label[1.75,4.63;" .. minetest.formspec_escape(label) .. "]"
end
end
if def and def.description then
formspec = formspec .. "textarea[0.25,3.75;4.8,1.7;;"..minetest.formspec_escape(def.description)..";]"
end
end
end
-- Create list box
formspec = formspec .. "textlist[4.75,0;6,5;awards;"
local first = true
for _,award in pairs(listofawards) do
local def = awards.def[award.name]
if def then
if not first then
formspec = formspec .. ","
end
first = false
if def.secret and not award.got then
formspec = formspec .. "#707070"..minetest.formspec_escape(S("(Secret Award)"))
else
local title = award.name
if def and def.title then
title = def.title
end
if award.got then
formspec = formspec .. minetest.formspec_escape(title)
else
formspec = formspec .. "#ACACAC".. minetest.formspec_escape(title)
end
end
end
end
return formspec .. ";"..sid.."]"
end
function awards.show_to(name, to, sid, text)
if name == "" or name == nil then
name = to
end
if name == to and awards.player(to).disabled then
minetest.chat_send_player(S("You've disabled awards. Type /awards enable to reenable."))
return
end
if text then
local listofawards = awards._order_awards(name)
if #listofawards == 0 then
minetest.chat_send_player(to, S("Error: No awards available."))
return
elseif not awards.players[name] or not awards.players[name].unlocked then
minetest.chat_send_player(to, S("You have not unlocked any awards."))
return
end
minetest.chat_send_player(to, string.format(S("%ss awards:"), name))
for _, str in pairs(awards.players[name].unlocked) do
local def = awards.def[str]
if def then
if def.title then
if def.description then
minetest.chat_send_player(to, string.format(S("%s: %s"), def.title, def.description))
else
minetest.chat_send_player(to, def.title)
end
else
minetest.chat_send_player(to, str)
end
end
end
else
if sid == nil or sid < 1 then
sid = 1
end
local deco = ""
if minetest.global_exists("default") then
deco = default.gui_bg .. default.gui_bg_img
end
-- Show formspec to user
minetest.show_formspec(to,"awards:awards",
"size[11,5]" .. deco ..
awards.getFormspec(name, to, sid))
end
end
awards.showto = awards.show_to
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "awards:awards" then if formname ~= "awards:awards" then
return false return false
@ -504,12 +488,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
return true return true
end) end)
awards.init() awards.load()
minetest.register_on_newplayer(function(player)
local playern = player:get_player_name()
awards.assertPlayer(playern)
end)
minetest.register_on_shutdown(function() minetest.register_on_shutdown(function()
awards.save() awards.save()

View File

@ -1,58 +0,0 @@
function awards.tbv(tb,value,default)
if not default then
default = {}
end
if not tb or type(tb) ~= "table" then
if not value then
value = "[NULL]"
end
minetest.log("error", "awards.tbv - table "..dump(value).." is null, or not a table! Dump: "..dump(tb))
return
end
if not value then
error("[ERROR] awards.tbv was not used correctly!\n"..
"Value: '"..dump(value).."'\n"..
"Dump:"..dump(tb))
return
end
if not tb[value] then
tb[value] = default
end
end
function awards.assertPlayer(playern)
awards.tbv(awards.players, playern)
awards.tbv(awards.players[playern], "name", playern)
awards.tbv(awards.players[playern], "unlocked")
awards.tbv(awards.players[playern], "place")
awards.tbv(awards.players[playern], "count")
awards.tbv(awards.players[playern], "craft")
awards.tbv(awards.players[playern], "eat")
awards.tbv(awards.players[playern], "deaths", 0)
awards.tbv(awards.players[playern], "joins", 0)
awards.tbv(awards.players[playern], "chats", 0)
end
function awards.player(name)
return awards.players[name]
end
function awards._order_awards(name)
local done = {}
local retval = {}
local player = awards.player(name)
if player and player.unlocked then
for _,got in pairs(player.unlocked) do
if awards.def[got] then
done[got] = true
table.insert(retval,{name=got,got=true})
end
end
end
for _,def in pairs(awards.def) do
if not done[def.name] then
table.insert(retval,{name=def.name,got=false})
end
end
return retval
end

907
awards.lua Normal file
View File

@ -0,0 +1,907 @@
local S = awards.gettext
-- Saint-Maclou
if minetest.get_modpath("moreblocks") then
awards.register_achievement("award_saint_maclou",{
title = S("Saint-Maclou"),
description = S("Place 20 coal checkers."),
icon = "awards_novicebuilder.png",
trigger = {
type = "place",
node = "moreblocks:coal_checker",
target = 20
}
})
-- Castorama
awards.register_achievement("award_castorama",{
title = S("Castorama"),
description = S("Place 20 iron checkers."),
icon = "awards_novicebuilder.png",
trigger = {
type = "place",
node = "moreblocks:iron_checker",
target = 20
}
})
-- Sam the Trapper
awards.register_achievement("award_sam_the_trapper",{
title = S("Sam the Trapper"),
description = S("Place 2 trap stones."),
icon = "awards_novicebuilder.png",
trigger = {
type = "place",
node = "moreblocks:trap_stone",
target = 2
}
})
end
-- This award can't be part of Unified Inventory, it would make a circular dependency
if minetest.get_modpath("unified_inventory") then
if minetest.get_all_craft_recipes("unified_inventory:bag_large") ~= nil then
awards.register_achievement("awards_ui_bags", {
title = S("Backpacker"),
description = S("Craft 4 large bags."),
icon = "awards_ui_bags.png",
trigger = {
type = "craft",
item = "unified_inventory:bag_large",
target = 4
}
})
end
end
if minetest.get_modpath("fire") then
awards.register_achievement("awards_pyro", {
title = S("Pyromaniac"),
description = S("Craft 8 times flint and steel."),
icon = "fire_flint_steel.png",
trigger = {
type = "craft",
item = "fire:flint_and_steel",
target = 8
}
})
if minetest.settings:get_bool("disable_fire") ~= true then
awards.register_achievement("awards_firefighter", {
title = S("Firefighter"),
description = S("Put out 1000 fires."),
icon = "awards_firefighter.png",
trigger = {
type = "dig",
node = "fire:basic_flame",
target = 1000
}
})
end
end
if minetest.get_modpath("default") then
-- Light it up
awards.register_achievement("award_lightitup",{
title = S("Light It Up"),
description = S("Place 100 torches."),
icon = "awards_novicebuilder.png^awards_level1.png",
trigger = {
type = "place",
node = "default:torch",
target = 100
}
})
-- Light ALL the things!
awards.register_achievement("award_well_lit",{
title = S("Well Lit"),
description = S("Place 1,000 torches."),
icon = "awards_novicebuilder.png^awards_level2.png",
trigger = {
type = "place",
node = "default:torch",
target = 1000
}
})
awards.register_achievement("award_meselamp",{
title = S("Really Well Lit"),
description = S("Craft 10 mese lamps."),
icon = "default_meselamp.png",
trigger = {
type = "craft",
item = "default:meselamp",
target = 10
}
})
awards.register_achievement("awards_stonebrick", {
title = S("Outpost"),
description = S("Craft 200 stone bricks."),
icon = "default_stone_brick.png^awards_level1.png",
trigger = {
type = "craft",
item = "default:stonebrick",
target = 200
}
})
awards.register_achievement("awards_stonebrick2", {
title = S("Watchtower"),
description = S("Craft 800 stone bricks."),
icon = "default_stone_brick.png^awards_level2.png",
trigger = {
type = "craft",
item = "default:stonebrick",
target = 800
}
})
awards.register_achievement("awards_stonebrick3", {
title = S("Fortress"),
description = S("Craft 3,200 stone bricks."),
icon = "default_stone_brick.png^awards_level3.png",
trigger = {
type = "craft",
item = "default:stonebrick",
target = 3200
}
})
awards.register_achievement("awards_desert_stonebrick", {
title = S("Desert Dweller"),
description = S("Craft 400 desert stone bricks."),
icon = "default_desert_stone_brick.png",
trigger = {
type = "craft",
item = "default:desert_stonebrick",
target = 400
}
})
awards.register_achievement("awards_desertstonebrick", {
title = S("Pharaoh"),
description = S("Craft 100 sandstone bricks."),
icon = "default_sandstone_brick.png",
trigger = {
type = "craft",
item = "default:sandstonebrick",
target = 100
}
})
awards.register_achievement("awards_bookshelf", {
title = S("Little Library"),
description = S("Craft 7 bookshelves."),
icon = "default_bookshelf.png",
trigger = {
type = "craft",
item = "default:bookshelf",
target = 7
}
})
awards.register_achievement("awards_obsidian", {
title = S("Lava and Water"),
description = S("Mine your first obsidian."),
icon = "default_obsidian.png^awards_level1.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:obsidian",
target = 1
}
})
-- Obsessed with Obsidian
awards.register_achievement("award_obsessed_with_obsidian",{
title = S("Obsessed with Obsidian"),
description = S("Mine 50 obsidian."),
icon = "default_obsidian.png^awards_level2.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:obsidian",
target = 50
}
})
-- Proof that player has found lava
awards.register_achievement("award_lavaminer",{
title = S("Lava Miner"),
description = S("Mine any block while being very close to lava."),
background = "awards_bg_mining.png",
icon = "default_lava.png",
})
awards.register_on_dig(function(player,data)
local pos = player:get_pos()
if pos and (minetest.find_node_near(pos, 1, "default:lava_source") or
minetest.find_node_near(pos, 1, "default:lava_flowing")) then
return "award_lavaminer"
end
return nil
end)
-- On the way
awards.register_achievement("award_on_the_way", {
title = S("On The Way"),
description = S("Place 100 rails."),
icon = "carts_rail_straight.png",
trigger = {
type = "place",
node = "default:rail",
target = 100
}
})
awards.register_achievement("award_lumberjack_firstday", {
title = S("First Day in the Woods"),
description = S("Dig 6 tree blocks."),
icon = "default_tree.png^awards_level1.png",
trigger = {
type = "dig",
node = "default:tree",
target = 6
}
})
-- Lumberjack
awards.register_achievement("award_lumberjack", {
title = S("Lumberjack"),
description = S("Dig 36 tree blocks."),
icon = "default_tree.png^awards_level2.png",
trigger = {
type = "dig",
node = "default:tree",
target = 36
}
})
-- Semi-pro Lumberjack
awards.register_achievement("award_lumberjack_semipro", {
title = S("Semi-pro Lumberjack"),
description = S("Dig 216 tree blocks."),
icon = "default_tree.png^awards_level3.png",
trigger = {
type = "dig",
node = "default:tree",
target = 216
}
})
-- Professional Lumberjack
awards.register_achievement("award_lumberjack_professional", {
title = S("Professional Lumberjack"),
description = S("Dig 1,296 tree blocks."),
icon = "default_tree.png^awards_level4.png",
trigger = {
type = "dig",
node = "default:tree",
target = 1296
}
})
-- Junglebaby
awards.register_achievement("award_junglebaby", {
title = S("Junglebaby"),
description = S("Dig 100 jungle tree blocks."),
icon = "default_jungletree.png^awards_level1.png",
trigger = {
type = "dig",
node = "default:jungletree",
target = 100
}
})
-- Jungleman
awards.register_achievement("award_jungleman", {
title = S("Jungleman"),
description = S("Dig 1,000 jungle tree blocks."),
icon = "default_jungletree.png^awards_level2.png",
trigger = {
type = "dig",
node = "default:jungletree",
target = 1000
}
})
-- Found some Mese!
awards.register_achievement("award_mesefind", {
title = S("First Mese Find"),
description = S("Mine your first mese ore."),
icon = "default_stone.png^default_mineral_mese.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_mese",
target = 1
}
})
-- Mese Block
awards.register_achievement("award_meseblock", {
secret = true,
title = S("Mese Mastery"),
description = S("Mine a mese block."),
icon = "default_mese_block.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:mese",
target = 1
}
})
-- You're a copper
awards.register_achievement("award_youre_a_copper", {
title = S("Youre a copper"),
description = S("Dig 1,000 copper ores."),
icon = "default_stone.png^default_mineral_copper.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_copper",
target = 1000
}
})
-- Found a Nyan cat!
awards.register_achievement("award_nyanfind", {
secret = true,
title = S("A Cat in a Pop-Tart?!"),
description = S("Mine a nyan cat."),
icon = "nyancat_front.png",
trigger = {
type = "dig",
node = "default:nyancat",
target = 1
}
})
-- Mini Miner
awards.register_achievement("award_mine2", {
title = S("Mini Miner"),
description = S("Dig 100 stone blocks."),
icon = "awards_miniminer.png^awards_level1.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone",
target = 100
}
})
-- Hardened Miner
awards.register_achievement("award_mine3", {
title = S("Hardened Miner"),
description = S("Dig 1,000 stone blocks."),
icon = "awards_miniminer.png^awards_level2.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone",
target = 1000
}
})
-- Master Miner
awards.register_achievement("award_mine4", {
title = S("Master Miner"),
description = S("Dig 10,000 stone blocks."),
icon = "awards_miniminer.png^awards_level3.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone",
target = 10000
}
})
-- Marchand de sable
awards.register_achievement("award_marchand_de_sable", {
title = S("Marchand De Sable"),
description = S("Dig 1,000 sand."),
icon = "default_sand.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:sand",
target = 1000
}
})
awards.register_achievement("awards_crafter_of_sticks", {
title = S("Crafter of Sticks"),
description = S("Craft 100 sticks."),
icon = "default_stick.png",
trigger = {
type = "craft",
item = "default:stick",
target = 100
}
})
awards.register_achievement("awards_junglegrass", {
title = S("Jungle Discoverer"),
description = S("Mine your first jungle grass."),
icon = "default_junglegrass.png",
trigger = {
type = "dig",
node = "default:junglegrass",
target = 1
}
})
awards.register_achievement("awards_grass", {
title = S("Grasslands Discoverer"),
description = S("Mine some grass."),
icon = "default_grass_3.png",
trigger = {
type = "dig",
node = "default:grass_1",
target = 1
}
})
awards.register_achievement("awards_dry_grass", {
title = S("Savannah Discoverer"),
description = S("Mine some dry grass."),
icon = "default_dry_grass_3.png",
trigger = {
type = "dig",
node = "default:dry_grass_3",
target = 1
}
})
awards.register_achievement("awards_cactus", {
title = S("Desert Discoverer"),
description = S("Mine your first cactus."),
icon = "default_cactus_side.png",
trigger = {
type = "dig",
node = "default:cactus",
target = 1
}
})
awards.register_achievement("awards_dry_shrub", {
title = S("Far Lands"),
description = S("Mine your first dry shrub."),
icon = "default_dry_shrub.png",
trigger = {
type = "dig",
node = "default:dry_shrub",
target = 1
}
})
awards.register_achievement("awards_ice", {
title = S("Glacier Discoverer"),
description = S("Mine your first ice."),
icon = "default_ice.png",
trigger = {
type = "dig",
node = "default:ice",
target = 1
}
})
-- Proof that player visited snowy lands
awards.register_achievement("awards_snowblock", {
title = S("Very Simple Snow Man"),
description = S("Place two snow blocks."),
icon = "default_snow.png",
trigger = {
type = "place",
node = "default:snowblock",
target = 2
}
})
awards.register_achievement("awards_gold_ore", {
title = S("First Gold Find"),
description = S("Mine your first gold ore."),
icon = "default_stone.png^default_mineral_gold.png^awards_level1.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_gold",
target = 1
}
})
awards.register_achievement("awards_gold_rush", {
title = S("Gold Rush"),
description = S("Mine 45 gold ores."),
icon = "default_stone.png^default_mineral_gold.png^awards_level2.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_gold",
target = 45
}
})
awards.register_achievement("awards_diamond_ore", {
title = S("Wow, I am Diamonds!"),
description = S("Mine your first diamond ore."),
icon = "default_stone.png^default_mineral_diamond.png^awards_level1.png",
trigger = {
type = "dig",
node = "default:stone_with_diamond",
target = 1
}
})
awards.register_achievement("awards_diamond_rush", {
title = S("Girl's Best Friend"),
description = S("Mine 18 diamond ores."),
icon = "default_stone.png^default_mineral_diamond.png^awards_level2.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_diamond",
target = 18
}
})
awards.register_achievement("awards_diamondblock", {
title = S("Hardest Block on Earth"),
description = S("Craft a diamond block."),
icon = "default_diamond_block.png",
trigger = {
type = "craft",
item = "default:diamondblock",
target = 1
}
})
awards.register_achievement("awards_mossycobble", {
title = S("In the Dungeon"),
description = S("Mine a mossy cobblestone."),
icon = "default_mossycobble.png",
trigger = {
type = "dig",
node = "default:mossycobble",
target = 1
}
})
awards.register_achievement("award_furnace", {
title = S("Smelter"),
description = S("Craft 10 furnaces."),
icon = "default_furnace_front.png",
trigger = {
type = "craft",
item= "default:furnace",
target = 10
}
})
awards.register_achievement("award_chest", {
title = S("Treasurer"),
description = S("Craft 15 chests."),
icon = "default_chest_front.png",
trigger = {
type = "craft",
item= "default:chest",
target = 15
}
})
awards.register_achievement("award_chest2", {
title = S("Bankier"),
description = S("Craft 30 locked chests."),
icon = "default_chest_lock.png",
trigger = {
type = "craft",
item= "default:chest_locked",
target = 30
}
})
awards.register_achievement("award_brick", {
title = S("Bricker"),
description = S("Craft 200 brick blocks."),
icon = "default_brick.png",
trigger = {
type = "craft",
item= "default:brick",
target = 200
}
})
awards.register_achievement("award_obsidianbrick", {
title = S("House of Obsidian"),
description = S("Craft 100 obsidian bricks."),
icon = "default_obsidian_brick.png",
trigger = {
type = "craft",
item= "default:obsidianbrick",
target = 100
}
})
awards.register_achievement("award_placestone", {
title = S("Build a Cave"),
description = S("Place 100 stone."),
icon = "default_stone.png",
trigger = {
type = "place",
node = "default:stone",
target = 100
}
})
awards.register_achievement("award_woodladder", {
title = S("Long Ladder"),
description = S("Place 400 wooden ladders."),
icon = "default_ladder_wood.png",
trigger = {
type = "place",
node = "default:ladder_wood",
target = 400
}
})
awards.register_achievement("award_steelladder", {
title = S("Industrial Age"),
description = S("Place 40 steel ladders."),
icon = "default_ladder_steel.png",
trigger = {
type = "place",
node = "default:ladder_steel",
target = 40
}
})
awards.register_achievement("award_apples", {
title = S("Yummy!"),
description = S("Eat 80 apples."),
icon = "default_apple.png",
trigger = {
type = "eat",
item = "default:apple",
target = 80
}
})
end
if minetest.get_modpath("vessels") then
awards.register_achievement("award_vessels_shelf", {
title = S("Glasser"),
icon = "vessels_shelf.png",
description = S("Craft 14 vessels shelves."),
trigger = {
type = "craft",
item= "vessels:shelf",
target = 14
}
})
end
if minetest.get_modpath("farming") then
awards.register_achievement("awards_farmer", {
title = S("Farming Skills Acquired"),
description = S("Harvest a fully grown wheat plant."),
icon = "farming_wheat_8.png^awards_level1.png",
trigger = {
type = "dig",
node = "farming:wheat_8",
target = 1
}
})
awards.register_achievement("awards_farmer2", {
title = S("Field Worker"),
description = S("Harvest 25 fully grown wheat plants."),
icon = "farming_wheat_8.png^awards_level2.png",
trigger = {
type = "dig",
node = "farming:wheat_8",
target = 25
}
})
awards.register_achievement("awards_farmer3", {
title = S("Aspiring Farmer"),
description = S("Harvest 125 fully grown wheat plants."),
icon = "farming_wheat_8.png^awards_level3.png",
trigger = {
type = "dig",
node = "farming:wheat_8",
target = 125
}
})
awards.register_achievement("awards_farmer4", {
title = S("Wheat Magnate"),
description = S("Harvest 625 fully grown wheat plants."),
icon = "farming_wheat_8.png^awards_level4.png",
trigger = {
type = "dig",
node = "farming:wheat_8",
target = 625
}
})
awards.register_achievement("award_bread", {
title = S("Baker"),
description = S("Eat 10 loaves of bread."),
icon = "farming_bread.png",
trigger = {
type = "eat",
item = "farming:bread",
target = 10
}
})
end
if minetest.get_modpath("wool") and minetest.get_modpath("farming") then
awards.register_achievement("awards_wool", {
title = S("Wool Over Your Eyes"),
description = S("Craft 250 white wool."),
icon = "wool_white.png",
trigger = {
type = "craft",
item = "wool:white",
target = 250
}
})
end
if minetest.get_modpath("beds") then
awards.register_achievement("award_bed", {
title = S("Hotelier"),
description = S("Craft 15 fancy beds."),
icon = "beds_bed_fancy.png",
trigger = {
type = "craft",
item= "beds:fancy_bed_bottom",
target = 15
}
})
end
if minetest.get_modpath("stairs") then
awards.register_achievement("award_stairs_goldblock", {
title = S("Filthy Rich"),
description = S("Craft 24 gold block stairs."),
icon = "default_gold_block.png",
trigger = {
type = "craft",
item= "stairs:stair_goldblock",
target = 24
}
})
end
if minetest.get_modpath("dye") then
awards.register_achievement("awards_dye_red", {
title = S("Roses Are Red"),
description = S("Craft 400 red dyes."),
icon = "dye_red.png",
trigger = {
type = "craft",
item = "dye:red",
target = 400
}
})
awards.register_achievement("awards_dye_yellow", {
title = S("Dandelions are Yellow"),
description = S("Craft 400 yellow dyes."),
icon = "dye_yellow.png",
trigger = {
type = "craft",
item = "dye:yellow",
target = 400
}
})
awards.register_achievement("awards_dye_blue", {
title = S("Geraniums are Blue"),
description = S("Craft 400 blue dyes."),
icon = "dye_blue.png",
trigger = {
type = "craft",
item= "dye:blue",
target = 400
}
})
awards.register_achievement("awards_dye_white", {
title = S("White Color Stock"),
description = S("Craft 100 white dyes."),
icon = "dye_white.png",
trigger = {
type = "craft",
item= "dye:white",
target = 100
}
})
end
if minetest.get_modpath("flowers") then
awards.register_achievement("awards_brown_mushroom1", {
title = S("Tasty Mushrooms"),
description = S("Eat 3 brown mushrooms."),
icon = "flowers_mushroom_brown.png^awards_level1.png",
trigger = {
type = "eat",
item= "flowers:mushroom_brown",
target = 3,
}
})
awards.register_achievement("awards_brown_mushroom2", {
title = S("Mushroom Lover"),
description = S("Eat 33 brown mushrooms."),
icon = "flowers_mushroom_brown.png^awards_level2.png",
trigger = {
type = "eat",
item= "flowers:mushroom_brown",
target = 33,
}
})
awards.register_achievement("awards_brown_mushroom3", {
title = S("Underground Mushroom Farmer"),
description = S("Eat 333 brown mushrooms."),
icon = "flowers_mushroom_brown.png^awards_level3.png",
trigger = {
type = "eat",
item= "flowers:mushroom_brown",
target = 333,
}
})
end
-- This ensures the following code is executed after all items have been registered
minetest.after(0, function()
-- Check whether there is at least one node which can be built by the player
local building_is_possible = false
for _, def in pairs(minetest.registered_nodes) do
if (def.description and def.pointable ~= false and not def.groups.not_in_creative_inventory) then
building_is_possible = true
break
end
end
-- The following awards require at least one node which can be built
if not building_is_possible then
return
end
awards.register_achievement("awards_builder1", {
title = S("Builder"),
icon = "awards_house.png^awards_level1.png",
trigger = {
type = "place",
target = 1000,
},
})
awards.register_achievement("awards_builder2", {
title = S("Constructor"),
icon = "awards_house.png^awards_level2.png",
trigger = {
type = "place",
target = 5000,
},
})
awards.register_achievement("awards_builder3", {
title = S("Architect"),
icon = "awards_house.png^awards_level3.png",
trigger = {
type = "place",
target = 10000,
},
})
awards.register_achievement("awards_builder4", {
title = S("Master Architect"),
icon = "awards_house.png^awards_level4.png",
trigger = {
type = "place",
target = 25000,
},
})
end)

View File

@ -42,7 +42,7 @@ minetest.register_chatcommand("awd", {
params = S("<achievement ID>"), params = S("<achievement ID>"),
description = S("Show details of an achievement"), description = S("Show details of an achievement"),
func = function(name, param) func = function(name, param)
local def = awards.def[param] local def = awards.registered_awards[param]
if def then if def then
minetest.chat_send_player(name, string.format(S("%s: %s"), def.title, def.description)) minetest.chat_send_player(name, string.format(S("%s: %s"), def.title, def.description))
else else

View File

@ -1 +0,0 @@
Adds achievements to Minetest, and an API to register new ones.

199
gui.lua Normal file
View File

@ -0,0 +1,199 @@
local S = awards.gettext
local function order_awards(name)
local done = {}
local retval = {}
local player = awards.player(name)
if player and player.unlocked then
for _,got in pairs(player.unlocked) do
if awards.registered_awards[got] then
done[got] = true
table.insert(retval,{name=got,got=true})
end
end
end
for _,def in pairs(awards.registered_awards) do
if not done[def.name] then
table.insert(retval,{name=def.name,got=false})
end
end
return retval
end
function awards.get_formspec(name, to, sid)
local formspec = ""
local listofawards = order_awards(name)
local playerdata = awards.player(name)
if #listofawards == 0 then
formspec = formspec .. "label[3.9,1.5;"..minetest.formspec_escape(S("Error: No awards available.")).."]"
formspec = formspec .. "button_exit[4.2,2.3;3,1;close;"..minetest.formspec_escape(S("OK")).."]"
return formspec
end
-- Sidebar
if sid then
local item = listofawards[sid+0]
local def = awards.registered_awards[item.name]
if def and def.secret and not item.got then
formspec = formspec .. "label[1,2.75;"..minetest.formspec_escape(S("(Secret Award)")).."]"..
"image[1,0;3,3;awards_unknown.png]"
if def and def.description then
formspec = formspec .. "textarea[0.25,3.25;4.8,1.7;;"..minetest.formspec_escape(S("Unlock this award to find out what it is."))..";]"
end
else
local title = item.name
if def and def.title then
title = def.title
end
local status = "%s"
if item.got then
status = S("%s (got)")
end
formspec = formspec .. "textarea[0.5,2.7;4.8,1.45;;" ..
string.format(status, minetest.formspec_escape(title)) ..
";]"
if def and def.icon then
formspec = formspec .. "image[1,0;3,3;" .. def.icon .. "]"
end
local barwidth = 4.6
local perc = nil
local label = nil
if def.getProgress and playerdata then
local res = def:getProgress(playerdata)
perc = res.perc
label = res.label
end
if perc then
if perc > 1 then
perc = 1
end
formspec = formspec .. "background[0,4.80;" .. barwidth ..",0.25;awards_progress_gray.png;false]"
formspec = formspec .. "background[0,4.80;" .. (barwidth * perc) ..",0.25;awards_progress_green.png;false]"
if label then
formspec = formspec .. "label[1.75,4.63;" .. minetest.formspec_escape(label) .. "]"
end
end
if def and def.description then
formspec = formspec .. "textarea[0.25,3.75;4.8,1.7;;"..minetest.formspec_escape(def.description)..";]"
end
end
end
-- Create list box
formspec = formspec .. "textlist[4.75,0;6,5;awards;"
local first = true
for _,award in pairs(listofawards) do
local def = awards.registered_awards[award.name]
if def then
if not first then
formspec = formspec .. ","
end
first = false
if def.secret and not award.got then
formspec = formspec .. "#707070"..minetest.formspec_escape(S("(Secret Award)"))
else
local title = award.name
if def and def.title then
title = def.title
end
if award.got then
formspec = formspec .. minetest.formspec_escape(title)
else
formspec = formspec .. "#ACACAC".. minetest.formspec_escape(title)
end
end
end
end
return formspec .. ";"..sid.."]"
end
function awards.show_to(name, to, sid, text)
if name == "" or name == nil then
name = to
end
local data = awards.player(to)
if name == to and data.disabled then
minetest.chat_send_player(S("You've disabled awards. Type /awards enable to reenable."))
return
end
if text then
local listofawards = order_awards(name)
if #listofawards == 0 then
minetest.chat_send_player(to, S("Error: No awards available."))
return
elseif not data or not data.unlocked then
minetest.chat_send_player(to, S("You have not unlocked any awards."))
return
end
minetest.chat_send_player(to, string.format(S("%ss awards:"), name))
for _, str in pairs(data.unlocked) do
local def = awards.registered_awards[str]
if def then
if def.title then
if def.description then
minetest.chat_send_player(to, string.format(S("%s: %s"), def.title, def.description))
else
minetest.chat_send_player(to, def.title)
end
else
minetest.chat_send_player(to, str)
end
end
end
else
if sid == nil or sid < 1 then
sid = 1
end
local deco = ""
if minetest.global_exists("default") then
deco = default.gui_bg .. default.gui_bg_img
end
-- Show formspec to user
minetest.show_formspec(to,"awards:awards",
"size[11,5]" .. deco ..
awards.get_formspec(name, to, sid))
end
end
if minetest.get_modpath("sfinv") then
sfinv.register_page("awards:awards", {
title = S("Awards"),
on_enter = function(self, player, context)
context.awards_idx = 1
end,
get = function(self, player, context)
local name = player:get_player_name()
return sfinv.make_formspec(player, context,
awards.get_formspec(name, name, context.awards_idx or 1),
false, "size[11,5]")
end,
on_player_receive_fields = function(self, player, context, fields)
if fields.awards then
local event = minetest.explode_textlist_event(fields.awards)
if event.type == "CHG" then
context.awards_idx = event.index
sfinv.set_player_inventory_formspec(player, context)
end
end
end
})
end
if minetest.get_modpath("unified_inventory") ~= nil then
unified_inventory.register_button("awards", {
type = "image",
image = "awards_ui_icon.png",
tooltip = S("Awards"),
action = function(player)
local name = player:get_player_name()
awards.show_to(name, name, nil, false)
end,
})
end

930
init.lua
View File

@ -16,922 +16,28 @@
-- The global award namespace -- The global award namespace
awards = { awards = {
show_mode = "hud" show_mode = "hud",
registered_triggers = {},
} }
-- Internationalization support. -- Internationalization support.
local S, NS = dofile(minetest.get_modpath("awards").."/intllib.lua") awards.gettext, awards.ngettext = dofile(minetest.get_modpath("awards").."/intllib.lua")
awards.gettext, awards.ngettext = S, NS
-- Load files
dofile(minetest.get_modpath("awards").."/api.lua") dofile(minetest.get_modpath("awards").."/api.lua")
dofile(minetest.get_modpath("awards").."/chat_commands.lua") dofile(minetest.get_modpath("awards").."/chat_commands.lua")
dofile(minetest.get_modpath("awards").."/sfinv.lua") dofile(minetest.get_modpath("awards").."/gui.lua")
dofile(minetest.get_modpath("awards").."/unified_inventory.lua")
dofile(minetest.get_modpath("awards").."/triggers.lua") dofile(minetest.get_modpath("awards").."/triggers.lua")
dofile(minetest.get_modpath("awards").."/awards.lua")
-- Saint-Maclou
if minetest.get_modpath("moreblocks") then -- Backwards compatibility
awards.register_achievement("award_saint_maclou",{ awards.give_achievement = awards.unlock
title = S("Saint-Maclou"), awards.getFormspec = awards.get_formspec
description = S("Place 20 coal checkers."), awards.showto = awards.show_to
icon = "awards_novicebuilder.png", awards.register_onDig = awards.register_on_dig
trigger = { awards.register_onPlace = awards.register_on_place
type = "place", awards.register_onDeath = awards.register_on_death
node = "moreblocks:coal_checker", awards.register_onChat = awards.register_on_chat
target = 20 awards.register_onJoin = awards.register_on_join
} awards.register_onCraft = awards.register_on_craft
}) awards.def = awards.registered_awards
-- Castorama
awards.register_achievement("award_castorama",{
title = S("Castorama"),
description = S("Place 20 iron checkers."),
icon = "awards_novicebuilder.png",
trigger = {
type = "place",
node = "moreblocks:iron_checker",
target = 20
}
})
-- Sam the Trapper
awards.register_achievement("award_sam_the_trapper",{
title = S("Sam the Trapper"),
description = S("Place 2 trap stones."),
icon = "awards_novicebuilder.png",
trigger = {
type = "place",
node = "moreblocks:trap_stone",
target = 2
}
})
end
-- This award can't be part of Unified Inventory, it would make a circular dependency
if minetest.get_modpath("unified_inventory") then
if minetest.get_all_craft_recipes("unified_inventory:bag_large") ~= nil then
awards.register_achievement("awards_ui_bags", {
title = S("Backpacker"),
description = S("Craft 4 large bags."),
icon = "awards_ui_bags.png",
trigger = {
type = "craft",
item = "unified_inventory:bag_large",
target = 4
}
})
end
end
if minetest.get_modpath("fire") then
awards.register_achievement("awards_pyro", {
title = S("Pyromaniac"),
description = S("Craft 8 times flint and steel."),
icon = "fire_flint_steel.png",
trigger = {
type = "craft",
item = "fire:flint_and_steel",
target = 8
}
})
if minetest.settings:get_bool("disable_fire") ~= true then
awards.register_achievement("awards_firefighter", {
title = S("Firefighter"),
description = S("Put out 1000 fires."),
icon = "awards_firefighter.png",
trigger = {
type = "dig",
node = "fire:basic_flame",
target = 1000
}
})
end
end
if minetest.get_modpath("default") then
-- Light it up
awards.register_achievement("award_lightitup",{
title = S("Light It Up"),
description = S("Place 100 torches."),
icon = "awards_novicebuilder.png^awards_level1.png",
trigger = {
type = "place",
node = "default:torch",
target = 100
}
})
-- Light ALL the things!
awards.register_achievement("award_well_lit",{
title = S("Well Lit"),
description = S("Place 1,000 torches."),
icon = "awards_novicebuilder.png^awards_level2.png",
trigger = {
type = "place",
node = "default:torch",
target = 1000
}
})
awards.register_achievement("award_meselamp",{
title = S("Really Well Lit"),
description = S("Craft 10 mese lamps."),
icon = "default_meselamp.png",
trigger = {
type = "craft",
item = "default:meselamp",
target = 10
}
})
awards.register_achievement("awards_stonebrick", {
title = S("Outpost"),
description = S("Craft 200 stone bricks."),
icon = "default_stone_brick.png^awards_level1.png",
trigger = {
type = "craft",
item = "default:stonebrick",
target = 200
}
})
awards.register_achievement("awards_stonebrick2", {
title = S("Watchtower"),
description = S("Craft 800 stone bricks."),
icon = "default_stone_brick.png^awards_level2.png",
trigger = {
type = "craft",
item = "default:stonebrick",
target = 800
}
})
awards.register_achievement("awards_stonebrick3", {
title = S("Fortress"),
description = S("Craft 3,200 stone bricks."),
icon = "default_stone_brick.png^awards_level3.png",
trigger = {
type = "craft",
item = "default:stonebrick",
target = 3200
}
})
awards.register_achievement("awards_desert_stonebrick", {
title = S("Desert Dweller"),
description = S("Craft 400 desert stone bricks."),
icon = "default_desert_stone_brick.png",
trigger = {
type = "craft",
item = "default:desert_stonebrick",
target = 400
}
})
awards.register_achievement("awards_desertstonebrick", {
title = S("Pharaoh"),
description = S("Craft 100 sandstone bricks."),
icon = "default_sandstone_brick.png",
trigger = {
type = "craft",
item = "default:sandstonebrick",
target = 100
}
})
awards.register_achievement("awards_bookshelf", {
title = S("Little Library"),
description = S("Craft 7 bookshelves."),
icon = "default_bookshelf.png",
trigger = {
type = "craft",
item = "default:bookshelf",
target = 7
}
})
awards.register_achievement("awards_obsidian", {
title = S("Lava and Water"),
description = S("Mine your first obsidian."),
icon = "default_obsidian.png^awards_level1.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:obsidian",
target = 1
}
})
-- Obsessed with Obsidian
awards.register_achievement("award_obsessed_with_obsidian",{
title = S("Obsessed with Obsidian"),
description = S("Mine 50 obsidian."),
icon = "default_obsidian.png^awards_level2.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:obsidian",
target = 50
}
})
-- Proof that player has found lava
awards.register_achievement("award_lavaminer",{
title = S("Lava Miner"),
description = S("Mine any block while being very close to lava."),
background = "awards_bg_mining.png",
icon = "default_lava.png",
})
awards.register_on_dig(function(player,data)
local pos = player:getpos()
if pos and (minetest.find_node_near(pos, 1, "default:lava_source") ~= nil or
minetest.find_node_near(pos, 1, "default:lava_flowing") ~= nil) then
return "award_lavaminer"
end
return nil
end)
-- On the way
awards.register_achievement("award_on_the_way", {
title = S("On The Way"),
description = S("Place 100 rails."),
icon = "carts_rail_straight.png",
trigger = {
type = "place",
node = "default:rail",
target = 100
}
})
awards.register_achievement("award_lumberjack_firstday", {
title = S("First Day in the Woods"),
description = S("Dig 6 tree blocks."),
icon = "default_tree.png^awards_level1.png",
trigger = {
type = "dig",
node = "default:tree",
target = 6
}
})
-- Lumberjack
awards.register_achievement("award_lumberjack", {
title = S("Lumberjack"),
description = S("Dig 36 tree blocks."),
icon = "default_tree.png^awards_level2.png",
trigger = {
type = "dig",
node = "default:tree",
target = 36
}
})
-- Semi-pro Lumberjack
awards.register_achievement("award_lumberjack_semipro", {
title = S("Semi-pro Lumberjack"),
description = S("Dig 216 tree blocks."),
icon = "default_tree.png^awards_level3.png",
trigger = {
type = "dig",
node = "default:tree",
target = 216
}
})
-- Professional Lumberjack
awards.register_achievement("award_lumberjack_professional", {
title = S("Professional Lumberjack"),
description = S("Dig 1,296 tree blocks."),
icon = "default_tree.png^awards_level4.png",
trigger = {
type = "dig",
node = "default:tree",
target = 1296
}
})
-- Junglebaby
awards.register_achievement("award_junglebaby", {
title = S("Junglebaby"),
description = S("Dig 100 jungle tree blocks."),
icon = "default_jungletree.png^awards_level1.png",
trigger = {
type = "dig",
node = "default:jungletree",
target = 100
}
})
-- Jungleman
awards.register_achievement("award_jungleman", {
title = S("Jungleman"),
description = S("Dig 1,000 jungle tree blocks."),
icon = "default_jungletree.png^awards_level2.png",
trigger = {
type = "dig",
node = "default:jungletree",
target = 1000
}
})
-- Found some Mese!
awards.register_achievement("award_mesefind", {
title = S("First Mese Find"),
description = S("Mine your first mese ore."),
icon = "default_stone.png^default_mineral_mese.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_mese",
target = 1
}
})
-- Mese Block
awards.register_achievement("award_meseblock", {
secret = true,
title = S("Mese Mastery"),
description = S("Mine a mese block."),
icon = "default_mese_block.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:mese",
target = 1
}
})
-- You're a copper
awards.register_achievement("award_youre_a_copper", {
title = S("Youre a copper"),
description = S("Dig 1,000 copper ores."),
icon = "default_stone.png^default_mineral_copper.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_copper",
target = 1000
}
})
-- Found a Nyan cat!
awards.register_achievement("award_nyanfind", {
secret = true,
title = S("A Cat in a Pop-Tart?!"),
description = S("Mine a nyan cat."),
icon = "nyancat_front.png",
trigger = {
type = "dig",
node = "default:nyancat",
target = 1
}
})
-- Mini Miner
awards.register_achievement("award_mine2", {
title = S("Mini Miner"),
description = S("Dig 100 stone blocks."),
icon = "awards_miniminer.png^awards_level1.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone",
target = 100
}
})
-- Hardened Miner
awards.register_achievement("award_mine3", {
title = S("Hardened Miner"),
description = S("Dig 1,000 stone blocks."),
icon = "awards_miniminer.png^awards_level2.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone",
target = 1000
}
})
-- Master Miner
awards.register_achievement("award_mine4", {
title = S("Master Miner"),
description = S("Dig 10,000 stone blocks."),
icon = "awards_miniminer.png^awards_level3.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone",
target = 10000
}
})
-- Marchand de sable
awards.register_achievement("award_marchand_de_sable", {
title = S("Marchand De Sable"),
description = S("Dig 1,000 sand."),
icon = "default_sand.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:sand",
target = 1000
}
})
awards.register_achievement("awards_crafter_of_sticks", {
title = S("Crafter of Sticks"),
description = S("Craft 100 sticks."),
icon = "default_stick.png",
trigger = {
type = "craft",
item = "default:stick",
target = 100
}
})
awards.register_achievement("awards_junglegrass", {
title = S("Jungle Discoverer"),
description = S("Mine your first jungle grass."),
icon = "default_junglegrass.png",
trigger = {
type = "dig",
node = "default:junglegrass",
target = 1
}
})
awards.register_achievement("awards_grass", {
title = S("Grasslands Discoverer"),
description = S("Mine some grass."),
icon = "default_grass_3.png",
trigger = {
type = "dig",
node = "default:grass_1",
target = 1
}
})
awards.register_achievement("awards_dry_grass", {
title = S("Savannah Discoverer"),
description = S("Mine some dry grass."),
icon = "default_dry_grass_3.png",
trigger = {
type = "dig",
node = "default:dry_grass_3",
target = 1
}
})
awards.register_achievement("awards_cactus", {
title = S("Desert Discoverer"),
description = S("Mine your first cactus."),
icon = "default_cactus_side.png",
trigger = {
type = "dig",
node = "default:cactus",
target = 1
}
})
awards.register_achievement("awards_dry_shrub", {
title = S("Far Lands"),
description = S("Mine your first dry shrub."),
icon = "default_dry_shrub.png",
trigger = {
type = "dig",
node = "default:dry_shrub",
target = 1
}
})
awards.register_achievement("awards_ice", {
title = S("Glacier Discoverer"),
description = S("Mine your first ice."),
icon = "default_ice.png",
trigger = {
type = "dig",
node = "default:ice",
target = 1
}
})
-- Proof that player visited snowy lands
awards.register_achievement("awards_snowblock", {
title = S("Very Simple Snow Man"),
description = S("Place two snow blocks."),
icon = "default_snow.png",
trigger = {
type = "place",
node = "default:snowblock",
target = 2
}
})
awards.register_achievement("awards_gold_ore", {
title = S("First Gold Find"),
description = S("Mine your first gold ore."),
icon = "default_stone.png^default_mineral_gold.png^awards_level1.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_gold",
target = 1
}
})
awards.register_achievement("awards_gold_rush", {
title = S("Gold Rush"),
description = S("Mine 45 gold ores."),
icon = "default_stone.png^default_mineral_gold.png^awards_level2.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_gold",
target = 45
}
})
awards.register_achievement("awards_diamond_ore", {
title = S("Wow, I am Diamonds!"),
description = S("Mine your first diamond ore."),
icon = "default_stone.png^default_mineral_diamond.png^awards_level1.png",
trigger = {
type = "dig",
node = "default:stone_with_diamond",
target = 1
}
})
awards.register_achievement("awards_diamond_rush", {
title = S("Girl's Best Friend"),
description = S("Mine 18 diamond ores."),
icon = "default_stone.png^default_mineral_diamond.png^awards_level2.png",
background = "awards_bg_mining.png",
trigger = {
type = "dig",
node = "default:stone_with_diamond",
target = 18
}
})
awards.register_achievement("awards_diamondblock", {
title = S("Hardest Block on Earth"),
description = S("Craft a diamond block."),
icon = "default_diamond_block.png",
trigger = {
type = "craft",
item = "default:diamondblock",
target = 1
}
})
awards.register_achievement("awards_mossycobble", {
title = S("In the Dungeon"),
description = S("Mine a mossy cobblestone."),
icon = "default_mossycobble.png",
trigger = {
type = "dig",
node = "default:mossycobble",
target = 1
}
})
awards.register_achievement("award_furnace", {
title = S("Smelter"),
description = S("Craft 10 furnaces."),
icon = "default_furnace_front.png",
trigger = {
type = "craft",
item= "default:furnace",
target = 10
}
})
awards.register_achievement("award_chest", {
title = S("Treasurer"),
description = S("Craft 15 chests."),
icon = "default_chest_front.png",
trigger = {
type = "craft",
item= "default:chest",
target = 15
}
})
awards.register_achievement("award_chest2", {
title = S("Bankier"),
description = S("Craft 30 locked chests."),
icon = "default_chest_lock.png",
trigger = {
type = "craft",
item= "default:chest_locked",
target = 30
}
})
awards.register_achievement("award_brick", {
title = S("Bricker"),
description = S("Craft 200 brick blocks."),
icon = "default_brick.png",
trigger = {
type = "craft",
item= "default:brick",
target = 200
}
})
awards.register_achievement("award_obsidianbrick", {
title = S("House of Obsidian"),
description = S("Craft 100 obsidian bricks."),
icon = "default_obsidian_brick.png",
trigger = {
type = "craft",
item= "default:obsidianbrick",
target = 100
}
})
awards.register_achievement("award_placestone", {
title = S("Build a Cave"),
description = S("Place 100 stone."),
icon = "default_stone.png",
trigger = {
type = "place",
node = "default:stone",
target = 100
}
})
awards.register_achievement("award_woodladder", {
title = S("Long Ladder"),
description = S("Place 400 wooden ladders."),
icon = "default_ladder_wood.png",
trigger = {
type = "place",
node = "default:ladder_wood",
target = 400
}
})
awards.register_achievement("award_steelladder", {
title = S("Industrial Age"),
description = S("Place 40 steel ladders."),
icon = "default_ladder_steel.png",
trigger = {
type = "place",
node = "default:ladder_steel",
target = 40
}
})
awards.register_achievement("award_apples", {
title = S("Yummy!"),
description = S("Eat 80 apples."),
icon = "default_apple.png",
trigger = {
type = "eat",
item = "default:apple",
target = 80
}
})
end
if minetest.get_modpath("vessels") then
awards.register_achievement("award_vessels_shelf", {
title = S("Glasser"),
icon = "vessels_shelf.png",
description = S("Craft 14 vessels shelves."),
trigger = {
type = "craft",
item= "vessels:shelf",
target = 14
}
})
end
if minetest.get_modpath("farming") then
awards.register_achievement("awards_farmer", {
title = S("Farming Skills Acquired"),
description = S("Harvest a fully grown wheat plant."),
icon = "farming_wheat_8.png^awards_level1.png",
trigger = {
type = "dig",
node = "farming:wheat_8",
target = 1
}
})
awards.register_achievement("awards_farmer2", {
title = S("Field Worker"),
description = S("Harvest 25 fully grown wheat plants."),
icon = "farming_wheat_8.png^awards_level2.png",
trigger = {
type = "dig",
node = "farming:wheat_8",
target = 25
}
})
awards.register_achievement("awards_farmer3", {
title = S("Aspiring Farmer"),
description = S("Harvest 125 fully grown wheat plants."),
icon = "farming_wheat_8.png^awards_level3.png",
trigger = {
type = "dig",
node = "farming:wheat_8",
target = 125
}
})
awards.register_achievement("awards_farmer4", {
title = S("Wheat Magnate"),
description = S("Harvest 625 fully grown wheat plants."),
icon = "farming_wheat_8.png^awards_level4.png",
trigger = {
type = "dig",
node = "farming:wheat_8",
target = 625
}
})
awards.register_achievement("award_bread", {
title = S("Baker"),
description = S("Eat 10 loaves of bread."),
icon = "farming_bread.png",
trigger = {
type = "eat",
item = "farming:bread",
target = 10
}
})
end
if minetest.get_modpath("wool") and minetest.get_modpath("farming") then
awards.register_achievement("awards_wool", {
title = S("Wool Over Your Eyes"),
description = S("Craft 250 white wool."),
icon = "wool_white.png",
trigger = {
type = "craft",
item = "wool:white",
target = 250
}
})
end
if minetest.get_modpath("beds") then
awards.register_achievement("award_bed", {
title = S("Hotelier"),
description = S("Craft 15 fancy beds."),
icon = "beds_bed_fancy.png",
trigger = {
type = "craft",
item= "beds:fancy_bed_bottom",
target = 15
}
})
end
if minetest.get_modpath("stairs") then
awards.register_achievement("award_stairs_goldblock", {
title = S("Filthy Rich"),
description = S("Craft 24 gold block stairs."),
icon = "default_gold_block.png",
trigger = {
type = "craft",
item= "stairs:stair_goldblock",
target = 24
}
})
end
if minetest.get_modpath("dye") then
awards.register_achievement("awards_dye_red", {
title = S("Roses Are Red"),
description = S("Craft 400 red dyes."),
icon = "dye_red.png",
trigger = {
type = "craft",
item = "dye:red",
target = 400
}
})
awards.register_achievement("awards_dye_yellow", {
title = S("Dandelions are Yellow"),
description = S("Craft 400 yellow dyes."),
icon = "dye_yellow.png",
trigger = {
type = "craft",
item = "dye:yellow",
target = 400
}
})
awards.register_achievement("awards_dye_blue", {
title = S("Geraniums are Blue"),
description = S("Craft 400 blue dyes."),
icon = "dye_blue.png",
trigger = {
type = "craft",
item= "dye:blue",
target = 400
}
})
awards.register_achievement("awards_dye_white", {
title = S("White Color Stock"),
description = S("Craft 100 white dyes."),
icon = "dye_white.png",
trigger = {
type = "craft",
item= "dye:white",
target = 100
}
})
end
if minetest.get_modpath("flowers") then
awards.register_achievement("awards_brown_mushroom1", {
title = S("Tasty Mushrooms"),
description = S("Eat 3 brown mushrooms."),
icon = "flowers_mushroom_brown.png^awards_level1.png",
trigger = {
type = "eat",
item= "flowers:mushroom_brown",
target = 3,
}
})
awards.register_achievement("awards_brown_mushroom2", {
title = S("Mushroom Lover"),
description = S("Eat 33 brown mushrooms."),
icon = "flowers_mushroom_brown.png^awards_level2.png",
trigger = {
type = "eat",
item= "flowers:mushroom_brown",
target = 33,
}
})
awards.register_achievement("awards_brown_mushroom3", {
title = S("Underground Mushroom Farmer"),
description = S("Eat 333 brown mushrooms."),
icon = "flowers_mushroom_brown.png^awards_level3.png",
trigger = {
type = "eat",
item= "flowers:mushroom_brown",
target = 333,
}
})
end
-- This ensures the following code is executed after all items have been registered
minetest.after(0, function()
-- Check whether there is at least one node which can be built by the player
local building_is_possible = false
for _, def in pairs(minetest.registered_nodes) do
if (def.description and def.pointable ~= false and not def.groups.not_in_creative_inventory) then
building_is_possible = true
break
end
end
-- The following awards require at least one node which can be built
if not building_is_possible then
return
end
awards.register_achievement("awards_builder1", {
title = S("Builder"),
icon = "awards_house.png^awards_level1.png",
trigger = {
type = "place",
target = 1000,
},
})
awards.register_achievement("awards_builder2", {
title = S("Constructor"),
icon = "awards_house.png^awards_level2.png",
trigger = {
type = "place",
target = 5000,
},
})
awards.register_achievement("awards_builder3", {
title = S("Architect"),
icon = "awards_house.png^awards_level3.png",
trigger = {
type = "place",
target = 10000,
},
})
awards.register_achievement("awards_builder4", {
title = S("Master Architect"),
icon = "awards_house.png^awards_level4.png",
trigger = {
type = "place",
target = 25000,
},
})
end)

View File

@ -2,6 +2,7 @@ name = awards
title = Achievements title = Achievements
author = rubenwardy author = rubenwardy
description = Adds achievements to Minetest, and an API to register new ones. description = Adds achievements to Minetest, and an API to register new ones.
license = LGPL 2.1 or later optional_depends = intllib,sfinv,unified_inventory,default,stairs,farming,dye,beds,wool,vessels,moreblocks,fire,flowers
license = LGPLv2.1+
forum = https://forum.minetest.net/viewtopic.php?t=4870 forum = https://forum.minetest.net/viewtopic.php?t=4870
version = 2.3.0 version = 2.3.0

163
readme.md
View File

@ -1,163 +0,0 @@
# Awards
by [rubenwardy](https://rubenwardy.com), with lots of awesome contributions
from Wuzzy, kaeza, MrIbby, and Traxie21.
This mod adds achievements to Minetest.
Majority of awards are back ported from Calinou's
old fork in Carbone, under same license.
# Basic API
* awards.register_achievement(name, def)
* name
* desciption
* sound [optional] - set a custom sound (SimpleSoundSpec) or `false` to play no sound.
If not specified, a default sound is played
* image [optional] - texture name, eg: award_one.png
* background [optional] - texture name, eg: award_one.png
* trigger [optional] [table]
* type - "dig", "place", "craft", "death", "chat", "join" or "eat"
* dig type: Dig a node.
* node: the dug node type. If nil, all dug nodes are counted
* place type: Place a node.
* node: the placed node type. If nil, all placed nodes are counted
* eat type: Eat an item.
* item: the eaten item type. If nil, all eaten items are counted
* craft type: Craft something.
* item: the crafted item type. If nil, all crafted items are counted
* death type: Die.
* chat type: Write a chat message.
* join type: Join the server.
* (for all types) target - how many times to dig/place/craft/etc.
* See Triggers
* secret [optional] - if true, then player needs to unlock to find out what it is.
* on_unlock [optional] - func(name, def)
* name is player name
* return true to cancel register_on_unlock callbacks and HUD
* awards.register_trigger(name, func(awardname, def))
* Note: awards.on[name] is automatically created for triggers
* awards.run_trigger_callbacks(player, data, trigger, table_func(entry))
* Goes through and checks all triggers registered to a trigger type,
unlocking the award if conditions are met.
* data is the player's award data, ie: awards.players[player_name]
* trigger is the name of the trigger type. Ie: awards.on[trigger]
* table_func is called if the trigger is a table - simply return an
award name to unlock it
* See triggers.lua for examples
* awards.increment_item_counter(data, field, itemname)
* add to an item's statistic count
* for example, (data, "place", "default:stone") will add 1 to the number of
times default:stone has been placed.
* data is the player's award data, ie: awards.players[player_name]
* returns true on success, false on failure (eg: cannot get modname and item from itemname)
* awards.register_on_unlock(func(name, def))
* name is the player name
* def is the award def.
* return true to cancel HUD
* awards.unlock(name, award)
* gives an award to a player
* name is the player name
# Included in the Mod
The API, above, allows you to register awards
and triggers (things that look for events and unlock awards, they need
to be registered in order to get details from award_def.trigger).
However, all awards and triggers are separate from the API.
They can be found in init.lua and triggers.lua
## Triggers
Callbacks (register a function to be run)
### dig
trigger = {
type = "dig",
node = "default:dirt",
target = 50
}
### place
trigger = {
type = "place",
node = "default:dirt",
target = 50
}
### death
trigger = {
type = "death",
target = 5
}
### chat
trigger = {
type = "chat",
target = 100
}
### join
trigger = {
type = "join",
target = 100
}
### eat
trigger = {
type = "eat",
item = "default:apple",
target = 100
}
## Callbacks relating to triggers
* awards.register_on_dig(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_place(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_eat(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_death(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_chat(func(player, data))
* data is player data (see below)
* return award name or null
* awards.register_on_join(func(player, data)
* data is player data (see below)
* return award name or null
# Player Data
A list of data referenced/hashed by the player's name.
* player name
* name [string]
* count [table] - dig counter
* modname [table]
* itemname [int]
* place [table] - place counter
* modname [table]
* itemname [int]
* craft [table] - craft counter
* modname [table]
* itemname [int]
* eat [table] - eat counter
* modname [table]
* itemname [int]
* deaths
* chats
* joins

View File

@ -1,25 +0,0 @@
if minetest.get_modpath("sfinv") then
local S = awards.gettext
sfinv.register_page("awards:awards", {
title = S("Awards"),
on_enter = function(self, player, context)
context.awards_idx = 1
end,
get = function(self, player, context)
local name = player:get_player_name()
return sfinv.make_formspec(player, context,
awards.getFormspec(name, name, context.awards_idx or 1),
false, "size[11,5]")
end,
on_player_receive_fields = function(self, player, context, fields)
if fields.awards then
local event = minetest.explode_textlist_event(fields.awards)
if event.type == "CHG" then
context.awards_idx = event.index
sfinv.set_player_inventory_formspec(player, context)
end
end
end
})
end

View File

@ -14,381 +14,124 @@
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-- --
local S, NS = awards.gettext, awards.ngettext
awards.register_trigger("dig", function(def)
local tmp = {
award = def.name,
node = def.trigger.node,
target = def.trigger.target,
}
table.insert(awards.on.dig, tmp)
def.getProgress = function(self, data)
local itemcount
if tmp.node then
itemcount = awards.get_item_count(data, "count", tmp.node) or 0
else
itemcount = awards.get_total_item_count(data, "count")
end
return {
perc = itemcount / tmp.target,
label = S("@1/@2 dug", itemcount, tmp.target),
}
end
def.getDefaultDescription = function(self)
local n = self.trigger.target
if self.trigger.node then
local nname = minetest.registered_nodes[self.trigger.node].description
if nname == nil then
nname = self.trigger.node
end
-- Translators: @1 is count, @2 is description.
return NS("Mine: @2", "Mine: @1×@2", n, n, nname)
else
return NS("Mine @1 block.", "Mine @1 blocks.", n, n)
end
end
end)
awards.register_trigger("place", function(def)
local tmp = {
award = def.name,
node = def.trigger.node,
target = def.trigger.target,
}
table.insert(awards.on.place, tmp)
def.getProgress = function(self, data)
local itemcount
if tmp.node then
itemcount = awards.get_item_count(data, "place", tmp.node) or 0
else
itemcount = awards.get_total_item_count(data, "place")
end
return {
perc = itemcount / tmp.target,
label = S("@1/@2 placed", itemcount, tmp.target),
}
end
def.getDefaultDescription = function(self)
local n = self.trigger.target
if self.trigger.node then
local nname = minetest.registered_nodes[self.trigger.node].description
if nname == nil then
nname = self.trigger.node
end
-- Translators: @1 is count, @2 is description.
return NS("Place: @2", "Place: @1×@2", n, n, nname)
else
return NS("Place a block.", "Place @1 blocks.", n, n)
end
end
end)
awards.register_trigger("eat", function(def)
local tmp = {
award = def.name,
item = def.trigger.item,
target = def.trigger.target,
}
table.insert(awards.on.eat, tmp)
def.getProgress = function(self, data)
local itemcount
if tmp.item then
itemcount = awards.get_item_count(data, "eat", tmp.item) or 0
else
itemcount = awards.get_total_item_count(data, "eat")
end
return {
perc = itemcount / tmp.target,
label = S("@1/@2 eaten", itemcount, tmp.target),
}
end
def.getDefaultDescription = function(self)
local n = self.trigger.target
if self.trigger.item then
local iname = minetest.registered_items[self.trigger.item].description
if iname == nil then
iname = self.trigger.iode
end
-- Translators: @1 is count, @2 is description.
return NS("Eat: @2", "Eat: @1×@2", n, n, iname)
else
return NS("Eat an item.", "Eat @1 items.", n, n)
end
end
end)
awards.register_trigger("death", function(def)
local tmp = {
award = def.name,
target = def.trigger.target,
}
table.insert(awards.on.death, tmp)
def.getProgress = function(self, data)
local itemcount = data.deaths or 0
return {
perc = itemcount / tmp.target,
label = S("@1/@2 deaths", itemcount, tmp.target),
}
end
def.getDefaultDescription = function(self)
local n = self.trigger.target
return NS("Die.", "Die @1 times.", n, n)
end
end)
awards.register_trigger("chat", function(def)
local tmp = {
award = def.name,
target = def.trigger.target,
}
table.insert(awards.on.chat, tmp)
def.getProgress = function(self, data)
local itemcount = data.chats or 0
return {
perc = itemcount / tmp.target,
label = S("@1/@2 chat messages", itemcount, tmp.target),
}
end
def.getDefaultDescription = function(self)
local n = self.trigger.target
return NS("Write something in chat.", "Write @1 chat messages.", n, n)
end
end)
awards.register_trigger("join", function(def)
local tmp = {
award = def.name,
target = def.trigger.target,
}
table.insert(awards.on.join, tmp)
def.getProgress = function(self, data)
local itemcount = data.joins or 0
return {
perc = itemcount / tmp.target,
label = S("@1/@2 game joins", itemcount, tmp.target),
}
end
def.getDefaultDescription = function(self)
local n = self.trigger.target
return NS("Join the game.", "Join the game @1 times.", n, n)
end
end)
awards.register_trigger("craft", function(def)
local tmp = {
award = def.name,
item = def.trigger.item,
target = def.trigger.target,
}
table.insert(awards.on.craft, tmp)
def.getProgress = function(self, data)
local itemcount
if tmp.item then
itemcount = awards.get_item_count(data, "craft", tmp.item) or 0
else
itemcount = awards.get_total_item_count(data, "craft")
end
return {
perc = itemcount / tmp.target,
label = S("@1/@2 crafted", itemcount, tmp.target),
}
end
def.getDefaultDescription = function(self)
local n = self.trigger.target
if self.trigger.item then
local iname = minetest.registered_items[self.trigger.item].description
if iname == nil then
iname = self.trigger.item
end
-- Translators: @1 is count, @2 is description.
return NS("Craft: @2", "Craft: @1×@2", n, n, iname)
else
return NS("Craft an item.", "Craft @1 items.", n)
end
end
end)
-- Backwards compatibility
awards.register_onDig = awards.register_on_dig
awards.register_onPlace = awards.register_on_place
awards.register_onDeath = awards.register_on_death
awards.register_onChat = awards.register_on_chat
awards.register_onJoin = awards.register_on_join
awards.register_onCraft = awards.register_on_craft
-- Trigger Handles
minetest.register_on_dignode(function(pos, oldnode, digger)
if not digger or not pos or not oldnode then
return
end
local data = awards.players[digger:get_player_name()]
if not awards.increment_item_counter(data, "count", oldnode.name) then
return
end
awards.run_trigger_callbacks(digger, data, "dig", function(entry)
if entry.target then
if entry.node then
local tnodedug = string.split(entry.node, ":")
local tmod = tnodedug[1]
local titem = tnodedug[2]
if not (not tmod or not titem or not data.count[tmod] or
not data.count[tmod][titem]) and
data.count[tmod][titem] > entry.target-1 then
return entry.award
end
elseif awards.get_total_item_count(data, "count") > entry.target-1 then
return entry.award
end
end
end)
end)
minetest.register_on_placenode(function(pos, node, digger)
if not digger or not pos or not node or not digger:get_player_name() or digger:get_player_name()=="" then
return
end
local data = awards.players[digger:get_player_name()]
if not awards.increment_item_counter(data, "place", node.name) then
return
end
awards.run_trigger_callbacks(digger, data, "place", function(entry)
if entry.target then
if entry.node then
local tnodedug = string.split(entry.node, ":")
local tmod = tnodedug[1]
local titem = tnodedug[2]
if not (not tmod or not titem or not data.place[tmod] or
not data.place[tmod][titem]) and
data.place[tmod][titem] > entry.target-1 then
return entry.award
end
elseif awards.get_total_item_count(data, "place") > entry.target-1 then
return entry.award
end
end
end)
end)
minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing)
if not user or not itemstack or not user:get_player_name() or user:get_player_name()=="" then
return
end
local data = awards.players[user:get_player_name()]
if not awards.increment_item_counter(data, "eat", itemstack:get_name()) then
return
end
awards.run_trigger_callbacks(user, data, "eat", function(entry)
if entry.target then
if entry.item then
local titemstring = string.split(entry.item, ":")
local tmod = titemstring[1]
local titem = titemstring[2]
if not (not tmod or not titem or not data.eat[tmod] or
not data.eat[tmod][titem]) and
data.eat[tmod][titem] > entry.target-1 then
return entry.award
end
elseif awards.get_total_item_count(data, "eat") > entry.target-1 then
return entry.award
end
end
end)
end)
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
if not player or not itemstack then
return
end
local data = awards.players[player:get_player_name()]
if not awards.increment_item_counter(data, "craft", itemstack:get_name(), itemstack:get_count()) then
return
end
awards.run_trigger_callbacks(player, data, "craft", function(entry)
if entry.target then
if entry.item then
local titemcrafted = string.split(entry.item, ":")
local tmod = titemcrafted[1]
local titem = titemcrafted[2]
if not (not tmod or not titem or not data.craft[tmod] or
not data.craft[tmod][titem]) and
data.craft[tmod][titem] > entry.target-1 then
return entry.award
end
elseif awards.get_total_item_count(data, "craft") > entry.target-1 then
return entry.award
end
end
end)
end)
minetest.register_on_dieplayer(function(player)
-- Run checks
local name = player:get_player_name()
if not player or not name or name=="" then
return
end
-- Get player
awards.assertPlayer(name)
local data = awards.players[name]
-- Increment counter
data.deaths = data.deaths + 1
awards.run_trigger_callbacks(player, data, "death", function(entry)
if entry.target and entry.award and data.deaths and
data.deaths >= entry.target then
return entry.award
end
end)
end)
minetest.register_on_joinplayer(function(player)
-- Run checks
local name = player:get_player_name()
if not player or not name or name=="" then
return
end
-- Get player
awards.assertPlayer(name)
local data = awards.players[name]
-- Increment counter
data.joins = data.joins + 1
awards.run_trigger_callbacks(player, data, "join", function(entry)
if entry.target and entry.award and data.joins and
data.joins >= entry.target then
return entry.award
end
end)
end)
awards.register_trigger("chat", {
type = "counted",
progress = "@1/@2 chat messages",
auto_description = { "Send a chat message", "Chat @1 times" },
})
minetest.register_on_chat_message(function(name, message) minetest.register_on_chat_message(function(name, message)
-- Run checks local player = minetest.get_player_by_name(name)
local idx = string.find(message,"/") if not player or string.find(message, "/") then
if not name or (idx ~= nil and idx <= 1) then
return return
end end
-- Get player awards.notify_chat(player)
awards.assertPlayer(name) end)
local data = awards.players[name]
local player = minetest.get_player_by_name(name)
awards.register_trigger("join", {
-- Increment counter type = "counted",
data.chats = data.chats + 1 progress = "@1/@2 joins",
auto_description = { "Join once", "Join @1 times" },
awards.run_trigger_callbacks(player, data, "chat", function(entry) })
if entry.target and entry.award and data.chats and minetest.register_on_joinplayer(awards.notify_join)
data.chats >= entry.target then
return entry.award
end awards.register_trigger("death", {
end) type = "counted_key",
progress = "@1/@2 deaths",
auto_description = { "Die once of @2", "Die @1 times of @2" },
auto_description_total = { "Die @1 times.", "Mine @1 times" },
get_key = function(self, def)
return def.trigger.reason
end,
})
minetest.register_on_dieplayer(function(player, reason)
if reason then
reason = reason.type
else
reason = "unknown"
end
awards.notify_death(player, reason)
end)
awards.register_trigger("dig", {
type = "counted_key",
progress = "@1/@2 dug",
auto_description = { "Mine: @2", "Mine: @1×@2" },
auto_description_total = { "Mine @1 block.", "Mine @1 blocks." },
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.node] or def.trigger.node
end
})
minetest.register_on_dignode(function(pos, node, player)
if not player or not pos or not node then
return
end
local node_name = node.name
node_name = minetest.registered_aliases[node_name] or node_name
awards.notify_dig(player, node_name)
end)
awards.register_trigger("place", {
type = "counted_key",
progress = "@1/@2 placed",
auto_description = { "Place: @2", "Place: @1×@2" },
auto_description_total = { "Place @1 block.", "Place @1 blocks." },
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.node] or def.trigger.node
end
})
minetest.register_on_placenode(function(pos, node, player)
if not player or not pos or not node then
return
end
local node_name = node.name
node_name = minetest.registered_aliases[node_name] or node_name
awards.notify_place(player, node_name)
end)
awards.register_trigger("craft", {
type = "counted_key",
progress = "@1/@2 crafted",
auto_description = { "Craft: @2", "Craft: @1×@2" },
auto_description_total = { "Craft @1 item", "Craft @1 items." },
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.item] or def.trigger.item
end
})
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
if not player or itemstack:empty() then
return
end
local itemname = itemstack:get_name()
itemname = minetest.registered_aliases[itemname] or itemname
awards.notify_craft(player, itemname, itemstack:get_count())
end)
awards.register_trigger("eat", {
type = "counted_key",
progress = "@1/@2 eaten",
auto_description = { "Eat @2", "Eat @1×@2" },
auto_description_total = { "Eat @1 item", "Eat @1 items." },
get_key = function(self, def)
return minetest.registered_aliases[def.trigger.item] or def.trigger.item
end
})
minetest.register_on_item_eat(function(_, _, itemstack, player, _)
if not player or itemstack:empty() then
return
end
local itemname = itemstack:get_name()
itemname = minetest.registered_aliases[itemname] or itemname
awards.notify_craft(player, itemname, itemstack:get_count())
end) end)

View File

@ -1,13 +0,0 @@
if minetest.get_modpath("unified_inventory") ~= nil then
local S = awards.gettext
unified_inventory.register_button("awards", {
type = "image",
image = "awards_ui_icon.png",
tooltip = S("Awards"),
action = function(player)
local name = player:get_player_name()
awards.show_to(name, name, nil, false)
end,
})
end