Add quest goals

This commit is contained in:
rubenwardy 2016-07-10 04:02:26 +01:00
parent 7d282c7bf8
commit c50fdcc4d0
2 changed files with 149 additions and 25 deletions

37
mods/quests/README.md Normal file
View File

@ -0,0 +1,37 @@
# Quests
Mod to manage tasks.
Todo:
* Add support for more goals than digging and placing
* Multiple goal.requires
* Call backs on quest completion
## Creating quests
Here is a basic quest:
```lua
local quest = quests.new(name, "Preparing a small feast")
quests.add_dig_goal(quest, "Harvest wheat", "farming:wheat_8", 5)
quests.add_dig_goal(quest, "Harvest apples", "default:apple", 3)
quests.add_quest(name, quest)
```
This will show up in the quest menu as:
-> Preparing a small feast
[ ] Harvest wheat (0/5)
[ ] Harvest apples (0/3)
For longer quests, certain goals need to be done in an order.
To do this, use goal.require:
```lua
local quest = quests.new(name, "Breaking Bread")
local g1 = quests.add_dig_goal(quest, "Harvest wheat", "treasure:raregem", 1)
local g2 = quests.add_give_goal(quest, "Return to Bob the Farmer", bob, "treasure:raregem", 1)
g2.requires = g1
quest.next = quest2
```

View File

@ -42,31 +42,128 @@ function quests.add_quest(player, quest)
end
function quests.finish_quest(player, quest)
xp.add_xp(digger, quest.xp)
xp.add_xp(minetest.get_player_by_name(player), quest.xp)
quest.done = true
quests.callback(player)
if quests.callback then
quests.callback(player)
end
end
function quests.finish_goal(player, quest, goal)
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]
table.foreach(player_quests, function(_, quest)
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
if goal.done then
quests.finish_goal(player, quest, goal)
end
end
quests.save()
end
end)
end)
end
quests.show_quests_form = "size[8,7.5;]" .. default.gui_colors ..
default.gui_bg .. "label[0,0;%s]"
function quests.format_goal(player, quest, goal)
-- TODO: support formatting for more than just digging and placing
if goal.done then
return " [x] " .. goal.title .. " (" .. tostring(goal.progress) ..
"/" .. tostring(goal.max) .. ")\n"
else
return " [ ] " .. goal.title .. " (" .. tostring(goal.progress) ..
"/" .. tostring(goal.max) .. ")\n"
end
end
minetest.register_chatcommand("quests", {
params = "",
description = "Shows your quests",
privs = {},
func = function(name, text)
if not quests.player_quests[name] then
local player_quests = quests.player_quests[name]
if not player_quests or #player_quests == 0 then
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
local s = quests.show_quests_form
local txt = ""
for k, v in pairs(quests.player_quests[name]) do
txt = txt .. " -> " .. v.quest_type .. " " .. v.node .. " (" .. tostring(v.progress) .. "/" .. tostring(v.max) .. ")\n"
for _, quest in pairs(player_quests) do
if quest.done then
txt = txt .. " -> " .. quest.title .. " (Completed)\n"
else
txt = txt .. " -> " .. quest.title .. "\n"
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
end
s = string.format(s, txt)
s = string.format(s, minetest.formspec_escape(txt))
minetest.show_formspec(name, "quests:show_quests", s)
return true, ""
end,
@ -78,16 +175,7 @@ minetest.register_on_dignode(function(pos, oldnode, digger)
return
end
table.foreach(quests.player_quests[digger:get_player_name()], function(k, v)
print("[quests] run quest " .. v.quest_type .. ", " .. v.node)
if v.quest_type == "dignode" and oldnode.name == v.node then
v.progress = v.progress + 1
if v.progress > (v.max-1) and not v.done then
quests.finish_quest(digger, v)
end
quests.save()
end
end)
quests.process_node_count_goals(digger:get_player_name(), "dig", oldnode.name)
end)
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
@ -96,19 +184,18 @@ minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack
return
end
table.foreach(quests.player_quests[placer:get_player_name()], function(k, v)
if v.quest_type == "placenode" and newnode.name == v.node then
v.progress = v.progress + 1
if v.progress > (v.max-1) and not v.done then
quests.finish_quest(placer, v)
end
quests.save()
end
end)
quests.process_node_count_goals(placer:get_player_name(), "placenode", newnode.name)
end)
minetest.register_on_newplayer(function(player)
quests.player_quests[player:get_player_name()] = {}
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)
end)
quests.load()