242 lines
6.1 KiB
Lua
Raw Normal View History

2016-01-21 16:48:41 +01:00
-- story quests
quests = {}
quests.player_quests = {}
2016-01-31 12:18:27 +01:00
quests.file = minetest.get_worldpath() .. "/quests"
2016-03-31 13:51:15 +02:00
quests.callback = nil
2016-01-31 12:18:27 +01:00
2016-07-10 02:57:03 +01:00
function quests.load()
2016-01-31 12:18:27 +01:00
local input = io.open(quests.file, "r")
if input then
local str = input:read("*all")
if str then
if minetest.deserialize(str) then
quests.player_quests = minetest.deserialize(str)
end
2016-07-10 02:57:03 +01:00
else
2016-01-31 12:18:27 +01:00
print("[WARNING] quest file is empty")
end
io.close(input)
else
print("[ERROR] couldnt find quest file")
end
end
2016-07-10 02:57:03 +01:00
function quests.save()
2016-01-31 12:18:27 +01:00
if quests.player_quests then
local output = io.open(quests.file, "w")
local str = minetest.serialize(quests.player_quests)
output:write(str)
io.close(output)
end
end
2016-01-21 16:48:41 +01:00
function quests.add_quest(player, quest)
if not quests.player_quests[player] then
quests.player_quests[player] = {}
end
2016-03-04 20:08:14 +01:00
print("[quests] add quest")
2016-01-21 16:48:41 +01:00
table.insert(quests.player_quests[player], quest)
2016-07-10 02:57:03 +01:00
quests.save()
2016-03-31 13:51:15 +02:00
return #quests.player_quests[player]
2016-01-21 16:48:41 +01:00
end
2016-07-10 02:57:03 +01:00
function quests.finish_quest(player, quest)
2016-07-12 19:41:00 +02:00
if not(quest.done) then
cmsg.push_message_player(minetest.get_player_by_name(player), "[quest] You completed a quest!")
end
2016-07-10 04:02:26 +01:00
xp.add_xp(minetest.get_player_by_name(player), quest.xp)
2016-07-10 02:57:03 +01:00
quest.done = true
2016-07-10 04:02:26 +01:00
if quests.callback then
2016-07-11 15:50:40 +02:00
quests.callback(minetest.get_player_by_name(player))
2016-07-10 04:02:26 +01:00
end
end
function quests.finish_goal(player, quest, goal)
2016-07-12 19:41:00 +02:00
if not(goal.done) then
cmsg.push_message_player(minetest.get_player_by_name(player), "[quest] You completed a goal!")
end
2016-07-10 04:02:26 +01:00
goal.done = true
if not quest.done then
local all_done = true
for i = 1, #quest.goals do
if not quest.goals[i].done then
all_done = false
break
end
end
if all_done then
quests.finish_quest(player, quest)
end
end
quests.save()
end
function quests.new(player, title)
local quest = {
title = title,
done = false,
goals = {},
xp = 0
}
return quest
end
function quests.add_dig_goal(quest, title, node, number)
local goal = {
title = title,
type = "dig",
node = node,
max = number,
progress = 0,
done = false
}
table.insert(quest.goals, goal)
return goal
end
function quests.add_place_goal(quest, title, node, number)
local goal = {
title = title,
type = "placenode",
node = node,
max = number,
progress = 0,
done = false
}
table.insert(quest.goals, goal)
return goal
end
function quests.process_node_count_goals(player, type, node)
local player_quests = quests.player_quests[player]
2016-07-12 19:41:00 +02:00
if not(player_quests) or #player_quests == 0 then return end
2016-07-10 04:02:26 +01:00
table.foreach(player_quests, function(_, quest)
2016-07-12 19:41:00 +02:00
if not(quest.goals) or #quest.goals == 0 then return end
2016-07-10 04:02:26 +01:00
table.foreach(quest.goals, function(_, goal)
if (not goal.requires or goal.requires.done) and
goal.type == type and goal.node == node then
goal.progress = goal.progress + 1
if goal.progress >= goal.max then
goal.progress = goal.max
2016-07-11 15:50:40 +02:00
goal.done = true
2016-07-10 04:02:26 +01:00
if goal.done then
quests.finish_goal(player, quest, goal)
end
end
quests.save()
end
end)
end)
2016-07-10 02:57:03 +01:00
end
quests.show_quests_form = "size[8,7.5;]" .. default.gui_colors ..
default.gui_bg .. "label[0,0;%s]"
2016-02-09 13:13:44 +01:00
2016-07-10 04:02:26 +01:00
function quests.format_goal(player, quest, goal)
-- TODO: support formatting for more than just digging and placing
if goal.done then
2016-07-12 19:41:00 +02:00
return " [x] " .. (goal.title or "[NO TITLE]") .. " (" .. tostring(goal.progress) ..
2016-07-10 04:02:26 +01:00
"/" .. tostring(goal.max) .. ")\n"
else
2016-07-12 19:41:00 +02:00
return " [ ] " .. (goal.title or "[NO TITLE]") .. " (" .. tostring(goal.progress) ..
2016-07-10 04:02:26 +01:00
"/" .. tostring(goal.max) .. ")\n"
end
end
2016-02-09 13:13:44 +01:00
minetest.register_chatcommand("quests", {
params = "",
description = "Shows your quests",
privs = {},
func = function(name, text)
2016-07-10 04:02:26 +01:00
local player_quests = quests.player_quests[name]
if not player_quests or #player_quests == 0 then
2016-02-09 13:13:44 +01:00
local s = quests.show_quests_form
s = string.format(s, "You have not got any quests yet.")
minetest.show_formspec(name, "quests:show_quests", s)
return
end
2016-07-10 04:02:26 +01:00
2016-02-09 13:13:44 +01:00
local s = quests.show_quests_form
local txt = ""
2016-07-10 04:02:26 +01:00
for _, quest in pairs(player_quests) do
if quest.done then
2016-07-12 19:41:00 +02:00
txt = txt .. " -> " .. (quest.title or "[NO TITLE]") .. " (Completed)\n"
2016-07-10 04:02:26 +01:00
else
2016-07-12 19:41:00 +02:00
txt = txt .. " -> " .. (quest.title or "[NO TITLE]") .. "\n"
2016-07-10 04:02:26 +01:00
for _, goal in pairs(quest.goals) do
if not goal.requires or goal.requires.done then
txt = txt .. quests.format_goal(name, quest, goal)
end
end
end
2016-02-09 13:13:44 +01:00
end
2016-07-10 04:02:26 +01:00
s = string.format(s, minetest.formspec_escape(txt))
2016-02-09 13:13:44 +01:00
minetest.show_formspec(name, "quests:show_quests", s)
return true, ""
end,
})
2016-01-21 16:48:41 +01:00
minetest.register_on_dignode(function(pos, oldnode, digger)
2016-07-10 02:57:03 +01:00
if not digger or not digger:is_player() or
not quests.player_quests[digger:get_player_name()] then
2016-01-21 16:48:41 +01:00
return
end
2016-07-10 02:57:03 +01:00
2016-07-10 04:02:26 +01:00
quests.process_node_count_goals(digger:get_player_name(), "dig", oldnode.name)
2016-01-21 16:48:41 +01:00
end)
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
2016-07-10 02:57:03 +01:00
if not placer or not placer:is_player() or
not quests.player_quests[placer:get_player_name()] then
2016-01-21 16:48:41 +01:00
return
end
2016-07-10 02:57:03 +01:00
2016-07-10 04:02:26 +01:00
quests.process_node_count_goals(placer:get_player_name(), "placenode", newnode.name)
2016-01-21 16:48:41 +01:00
end)
minetest.register_on_newplayer(function(player)
2016-07-11 15:50:40 +02:00
if not player then
return
end
2016-01-21 16:48:41 +01:00
quests.player_quests[player:get_player_name()] = {}
2016-07-10 04:02:26 +01:00
local name = player:get_player_name()
local quest = quests.new(name, "Quest 1")
local q1 = quests.add_dig_goal(quest, "Harvest dirt", "default:dirt", 5)
local q2 = quests.add_dig_goal(quest, "Harvest sand", "default:sand", 5)
q2.requires = q1
quests.add_quest(name, quest)
2016-01-21 16:48:41 +01:00
end)
2016-07-10 02:57:03 +01:00
quests.load()
2016-03-04 20:08:14 +01:00
2016-04-21 16:40:13 +02:00
-- exploring
2015-12-31 11:01:14 +01:00
minetest.register_node("quests:map", {
description = "Map",
2016-07-10 02:57:03 +01:00
tiles = {"quests_map_top.png", "quests_map_top.png", "quests_map.png", "quests_map.png", "quests_map.png", "quests_map.png"},
2015-12-31 11:01:14 +01:00
groups = {quest = 1, cracky = 3},
on_punch = function(pos, node, player, pointed_thing)
2016-01-08 12:54:36 +01:00
xp.add_xp(player, math.random(3, 30))
2015-12-31 11:01:14 +01:00
minetest.remove_node(pos)
end,
})
minetest.register_node("quests:ray", {
description = "Ray",
tiles = {"quests_glowing_ray.png"},
2016-04-21 16:40:13 +02:00
groups = {cracky = 1, ray=1},
2015-12-31 11:01:14 +01:00
paramtype = "light",
paramtype2 = "facedir",
drawtype = "nodebox",
light_source = 7,
node_box = {
type = "fixed",
fixed = {
{-0.2, -0.5, -0.2, 0.2, 0.5, 0.2},
},
},
2016-04-21 16:40:13 +02:00
drop = "",
2015-12-31 11:01:14 +01:00
})