373 lines
11 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.show_text(text, player)
local parts = text:split("\n")
for i,txt in ipairs(parts) do
minetest.after(2.9*i, function (txt, player)
if not(minetest.get_player_by_name(player)) then return end
cmsg.push_message_player(minetest.get_player_by_name(player), txt)
end, txt, player)
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()
if #quest.goals > 0 then
quests.show_text(quest.text .. "\n" .. quest.goals[1].description, player)
else
quests.show_text(quest.text, player)
end
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 " .. quest.title)
2016-07-12 19:41:00 +02:00
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
for i = 1, #quest.goals do
if quest.goals[i].requires and quest.goals[i].requires.title == goal.title then
if quest.goals[i].description then
quests.show_text(quest.goals[i].description, player)
end
end
end
2016-09-06 12:14:28 +02:00
if goal.reward then
minetest.get_player_by_name(player):get_inventory():add_item("main", goal.reward)
cmsg.push_message_player(minetest.get_player_by_name(player), goal.ending or "[quest] You completed a goal and you got a reward!")
else
cmsg.push_message_player(minetest.get_player_by_name(player), goal.ending or "[quest] You completed a goal!")
end
2016-09-06 12:14:28 +02:00
if goal.xp then
xp.add_xp(minetest.get_player_by_name(player), goal.xp)
end
2016-07-12 19:41:00 +02:00
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, text)
2016-07-10 04:02:26 +01:00
local quest = {
title = title,
done = false,
goals = {},
xp = 0,
text = text or "",
2016-07-10 04:02:26 +01:00
}
return quest
end
function quests.add_dig_goal(quest, title, node, number, description, ending)
2016-07-10 04:02:26 +01:00
local goal = {
title = title,
type = "dig",
node = node,
max = number,
progress = 0,
done = false,
2016-09-06 12:14:28 +02:00
xp = 0,
description = description or "",
ending = ending or nil
2016-07-10 04:02:26 +01:00
}
table.insert(quest.goals, goal)
return goal
end
function quests.add_place_goal(quest, title, node, number, description, ending)
2016-07-10 04:02:26 +01:00
local goal = {
title = title,
type = "placenode",
node = node,
max = number,
progress = 0,
done = false,
2016-09-06 12:14:28 +02:00
xp = 0,
description = description or "",
ending = ending or nil
2016-07-10 04:02:26 +01:00
}
table.insert(quest.goals, goal)
return goal
end
function quests.add_craft_goal(quest, title, item, number, description, ending)
local goal = {
title = title,
type = "craft",
item = item,
node = item,
max = number,
progress = 0,
done = false,
2016-09-06 12:14:28 +02:00
xp = 0,
description = description or "",
ending = ending or nil
}
table.insert(quest.goals, goal)
return goal
end
function quests.process_node_count_goals(player, type, node, count)
count = count or 1
2016-07-10 04:02:26 +01:00
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 then
for i=1,#goal.node do
if goal.node[i] == node then
goal.progress = goal.progress + count
if goal.progress >= goal.max then
goal.progress = goal.max
quests.finish_goal(player, quest, goal)
goal.done = true
end
quests.save()
2016-07-10 04:02:26 +01:00
end
end
end
end)
end)
2016-07-10 02:57:03 +01:00
end
quests.show_quests_form = "size[8,7.5;]" .. default.gui_colors ..
2016-09-11 13:15:13 +02:00
default.gui_bg .. "textlist[-0.1,-0.1;8,7.75;quests;%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-09-11 13:15:13 +02:00
return "#999999 \\[x\\] " .. (goal.title or "\\[NO TITLE\\]") .. " (" .. tostring(goal.progress) ..
"/" .. tostring(goal.max) .. ")"
2016-07-10 04:02:26 +01:00
else
2016-09-11 13:15:13 +02:00
return " \\[ \\] " .. (goal.title or "\\[NO TITLE\\]") .. " (" .. tostring(goal.progress) ..
"/" .. tostring(goal.max) .. ")"
2016-07-10 04:02:26 +01:00
end
end
function quests.get_formspec(name)
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.")
return s
end
local s = quests.show_quests_form
local txt = ""
for _, quest in pairs(player_quests) do
if quest.done then
2016-09-11 13:15:13 +02:00
txt = txt .. "#999999 -> " .. (quest.title or "\\[NO TITLE\\]") .. " (Completed),"
else
2016-09-11 13:15:13 +02:00
txt = txt .. " -> " .. (quest.title or "\\[NO TITLE\\]") .. ","
for _, goal in pairs(quest.goals) do
if not goal.requires or goal.requires.done then
2016-09-11 13:15:13 +02:00
txt = txt .. quests.format_goal(name, quest, goal) .. ","
end
end
end
end
2016-09-11 13:15:13 +02:00
s = string.format(s, txt)
return s
end
2016-02-09 13:13:44 +01:00
minetest.register_chatcommand("quests", {
params = "",
description = "Shows your quests",
privs = {},
func = function(name, text)
minetest.show_formspec(name, "quests:show_quests", quests.get_formspec(name))
2016-02-09 13:13:44 +01:00
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_craft(function(itemstack, player, old_craft_grid, craft_inv)
if not player or not player:is_player() or
not quests.player_quests[player:get_player_name()] then
return
end
quests.process_node_count_goals(player:get_player_name(), "craft", itemstack:get_name(),itemstack:get_count())
end)
2016-01-21 16:48:41 +01:00
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()
--tutorial
do
local quest = quests.new(name, "Tutorial", "Hey you!\nI didnt see you before. Are you new here?\nOh, Ok.\nI will help you to find the city \"NAME HERE\".\nYou will be save there.\n But first you need some basic equipment!")
local q1 = quests.add_dig_goal(quest, "Harvest Dirt/Grass", {"default:dirt", "default:grass", "default:wet_grass"}, 10, "You need to harvest some Dirt to get stones!")
2016-09-06 12:14:28 +02:00
local q2 = quests.add_dig_goal(quest, "Harvest Grass", {"default:plant_grass", "default:plant_grass_2", "default:plant_grass_3", "default:plant_grass_4", "default:plant_grass_5", "default:liana", "default:grass", "default:wet_grass"}, 12, "Now you need to get some Grass to craft strings.")
local q3 = quests.add_dig_goal(quest, "Harvest Leaves", {"default:leaves_1", "default:leaves_2", "default:leaves_3" ,"default:leaves_4"}, 6, "Harvest some leaves to craft twigs.")
local q4 = quests.add_place_goal(quest, "Place Workbench", {"default:workbench"}, 1, "You should craft a workbench and place it in front of you!", "If you want to know how to craft things,\n just open the crafting guide I gave you.\nYou can find all craftable items there!")
local q5 = quests.add_craft_goal(quest, "Craft Stone Axe", {"default:axe_stone"}, 1, "Now you can craft a Stone Axe.")
local q6 = quests.add_dig_goal(quest, "Harvest Logs", {"default:log","default:log_1","default:log_2","default:log_3", "default:jungle_tree"}, 20, "You can use the Stone Axe to harvest logs.")
local q7 = quests.add_dig_goal(quest, "Mine Stone", {"default:stone"}, 20, "You can also mine Stone with your Stone Axe.")
2016-09-11 13:15:13 +02:00
local q8 = quests.add_craft_goal(quest, "Craft a Flint Pick", {"default:flint_pick"}, 1, "Craft a Flint Pick!", "You can use the flint pick to dig harder blocks.")
local q9 = quests.add_dig_goal(quest, "Mine Iron", {"default:stone_with_iron"}, 2, "Your Flint Pick is strong enough to mine Iron.", "Great! You should be on level 2 now.\nEvery time you level up you can upgrade on of your skills.\nTry out /skill warrior or /skill miner\n")
q3.reward = "default:wood 3"
q4.reward = "crafting_guide:book"
q2.requires = q1
q3.requires = q2
q4.requires = q3
q5.requires = q4
q6.requires = q5
2016-09-11 13:15:13 +02:00
q7.requires = q6
q8.requires = q7
2016-09-11 13:15:13 +02:00
q9.requires = q8
2016-09-11 13:15:13 +02:00
q5.xp = 10
q9.xp = 10
quest.xp = 10
quests.add_quest(name, quest)
end
do
local quest = quests.new(name, "Lets mine!", "")
local q1 = quests.add_dig_goal(quest, "Mine Stone", {"default:stone"}, 10, "")
local q2 = quests.add_dig_goal(quest, "Mine Coal", {"default:stone_with_coal"}, 10, "")
local q3 = quests.add_dig_goal(quest, "Mine Iron", {"default:stone_with_iron"}, 10, "")
local q4 = quests.add_dig_goal(quest, "Mine Copper", {"default:stone_with_copper"}, 10, "")
local q5 = quests.add_dig_goal(quest, "Mine Diamond", {"default:stone_with_diamond"}, 10, "")
2016-09-05 14:52:25 +02:00
q1.reward = "torch:torch 10"
2016-09-06 12:14:28 +02:00
q1.xp = 10
2016-09-05 14:52:25 +02:00
q2.reward = "farming:apple 30"
2016-09-06 12:14:28 +02:00
q2.xp = 15
q3.reward = "default:pick"
2016-09-06 12:14:28 +02:00
q3.xp = 30
q4.reward = "default:torch 99"
2016-09-06 12:14:28 +02:00
q4.xp = 40
q5.reward = "default:torch 99"
2016-09-06 12:14:28 +02:00
q5.xp = xp.get_xp(5, 1)
quest.xp = 0
quests.add_quest(name, quest)
end
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-07-30 13:02:18 +02: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
})