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
2016-08-03 12:59:54 +02: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 ( )
2016-08-03 12:59:54 +02:00
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
2016-08-03 12:59:54 +02:00
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
2016-08-03 12:59:54 +02:00
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
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-07-12 19:41:00 +02:00
end
2016-08-03 12:59:54 +02:00
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
2016-08-03 12:59:54 +02:00
function quests . new ( player , title , text )
2016-07-10 04:02:26 +01:00
local quest = {
title = title ,
done = false ,
goals = { } ,
2016-08-03 12:59:54 +02:00
xp = 0 ,
text = text or " " ,
2016-07-10 04:02:26 +01:00
}
return quest
end
2016-08-03 12:59:54 +02:00
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 ,
2016-08-03 12:59:54 +02:00
done = false ,
description = description or " " ,
ending = ending or nil
2016-07-10 04:02:26 +01:00
}
table.insert ( quest.goals , goal )
return goal
end
2016-08-03 12:59:54 +02:00
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 ,
2016-08-03 12:59:54 +02:00
done = false ,
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 . 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
2016-08-03 12:59:54 +02:00
goal.type == type then
for i = 1 , # goal.node do
if goal.node [ i ] == node then
goal.progress = goal.progress + 1
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 ..
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
2016-08-03 12:59:54 +02:00
--tutorial
2016-07-10 04:02:26 +01:00
local name = player : get_player_name ( )
2016-08-03 12:59:54 +02:00
local quest = quests.new ( name , " Tutorial " , " Hey you! \n I didnt see you before. Are you new here? \n Oh, Ok. \n I will help you to find the city \" NAME HERE \" . \n You will be save there. \n But first you need some basic equipment! " )
local q1 = quests.add_dig_goal ( quest , " Harvest dirt " , { " default:dirt " } , 10 , " You need to harvest some Dirt to get stones! " )
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 " } , 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! " , " Great! The tutorial ends here. If you want to know how to craft things just goto the RPGtest wiki. \n But I think cdqwertz will add a crafting guide soon. " )
q3.reward = " default:wood 3 "
2016-07-10 04:02:26 +01:00
q2.requires = q1
2016-08-03 12:59:54 +02:00
q3.requires = q2
q4.requires = q3
quest.xp = 10
2016-07-10 04:02:26 +01:00
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-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
} )