2018-05-08 15:28:01 +02:00
|
|
|
local has_xp_redo_mod = minetest.get_modpath("xp_redo")
|
2018-05-07 13:35:14 +02:00
|
|
|
|
|
|
|
missions.is_book = function(stack)
|
|
|
|
return stack:get_count() == 1 and stack:get_name() == "default:book_written"
|
|
|
|
end
|
|
|
|
|
2018-05-07 16:07:51 +02:00
|
|
|
missions.pos_equal = function(pos1, pos2)
|
|
|
|
return pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z
|
|
|
|
end
|
|
|
|
|
2018-05-07 13:35:14 +02:00
|
|
|
missions.save_missions = function()
|
|
|
|
-- TODO
|
|
|
|
end
|
|
|
|
|
|
|
|
missions.load_missions = function()
|
|
|
|
-- TODO
|
|
|
|
end
|
|
|
|
|
2018-06-29 14:06:49 +02:00
|
|
|
-- create a book for given pos and title
|
|
|
|
missions.pos_to_book = function(pos, title)
|
|
|
|
minetest.pos_to_string(pos)
|
|
|
|
|
|
|
|
local stack = ItemStack("default:book_written")
|
|
|
|
local stackMeta = stack:get_meta()
|
|
|
|
|
|
|
|
local data = {}
|
|
|
|
|
|
|
|
data.owner = "missions"
|
|
|
|
data.title = title or "Coordinate"
|
|
|
|
data.description = data.title
|
|
|
|
data.text = minetest.serialize({x=pos.x, y=pos.y, z=pos.z, title=data.title})
|
|
|
|
data.page = 1
|
|
|
|
data.page_max = 1
|
|
|
|
|
|
|
|
stack:get_meta():from_table({ fields = data })
|
|
|
|
|
|
|
|
return stack
|
|
|
|
end
|
|
|
|
|
|
|
|
-- parse a position from a book stack (returns pos+title)
|
|
|
|
missions.book_to_pos = function(bookstack)
|
|
|
|
if not bookstack or not missions.is_book(bookstack) then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local meta = bookstack:get_meta()
|
|
|
|
if not meta:get_string("owner") == "missions" then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
return minetest.deserialize(meta:get_string("text"))
|
|
|
|
end
|
|
|
|
|
2018-05-07 13:35:14 +02:00
|
|
|
missions.start_mission = function(player, mission)
|
|
|
|
|
2018-06-29 14:36:01 +02:00
|
|
|
local playername = player:get_player_name()
|
|
|
|
|
2018-05-16 15:27:27 +02:00
|
|
|
-- mark start of mission
|
2018-06-29 14:36:01 +02:00
|
|
|
local now = os.time(os.date("!*t"))
|
|
|
|
mission.start = now
|
|
|
|
|
|
|
|
if mission.cooldown and mission.cooldown > 0 then
|
|
|
|
-- check cooldown timer
|
|
|
|
last_time = missions.cooldown_get(mission.name, playername)
|
|
|
|
|
|
|
|
if last_time > 0 and last_time < mission.cooldown then
|
|
|
|
local remaining = mission.cooldown - last_time
|
|
|
|
minetest.chat_send_player(playername, "Mission not cooled down, wait " .. remaining .. " seconds")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
2018-05-16 15:27:27 +02:00
|
|
|
|
2018-05-09 10:55:24 +02:00
|
|
|
-- print(dump(mission)) --XXX
|
|
|
|
|
2018-06-29 15:54:12 +02:00
|
|
|
if mission.type == "transport" then
|
|
|
|
-- TODO: check chest(s) for reward first
|
|
|
|
end
|
2018-05-08 15:28:01 +02:00
|
|
|
|
|
|
|
if has_xp_redo_mod and mission.entryxp then
|
|
|
|
local xp = xp_redo.get_xp(playername)
|
|
|
|
if xp < mission.entryxp then
|
|
|
|
minetest.chat_send_player(playername, "Not enough xp for mission, needed: " .. mission.entryxp)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-07 13:35:14 +02:00
|
|
|
local playermissions = missions.list[playername]
|
|
|
|
if playermissions == nil then playermissions = {} end
|
|
|
|
|
|
|
|
for i,m in pairs(playermissions) do
|
2018-05-16 15:27:27 +02:00
|
|
|
if m.name == mission.name then
|
|
|
|
minetest.chat_send_player(playername, "Mission already running: " .. mission.name)
|
2018-05-07 13:35:14 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
table.insert(playermissions, mission)
|
|
|
|
|
|
|
|
missions.list[playername] = playermissions
|
|
|
|
missions.save_missions()
|
|
|
|
end
|
|
|
|
|
2018-05-07 14:59:11 +02:00
|
|
|
missions.remove_mission = function(player, mission)
|
|
|
|
local playername = player:get_player_name()
|
|
|
|
local playermissions = missions.list[playername]
|
|
|
|
if playermissions == nil then playermissions = {} end
|
2018-05-07 13:35:14 +02:00
|
|
|
|
2018-05-07 14:59:11 +02:00
|
|
|
for i,m in pairs(playermissions) do
|
2018-05-16 15:27:27 +02:00
|
|
|
if m.name == mission.name then
|
2018-05-07 14:59:11 +02:00
|
|
|
table.remove(playermissions, i)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-05-07 13:35:14 +02:00
|
|
|
|
|
|
|
|
2018-05-07 16:07:51 +02:00
|
|
|
|
|
|
|
local check_player_mission = function(player, mission, remaining)
|
2018-05-07 14:59:11 +02:00
|
|
|
if remaining <= 0 then
|
|
|
|
-- mission timed-out
|
|
|
|
missions.hud_remove_mission(player, mission)
|
|
|
|
missions.remove_mission(player, mission)
|
2018-05-16 15:27:27 +02:00
|
|
|
minetest.chat_send_player(player:get_player_name(), "Mission timed out!: " .. mission.name)
|
|
|
|
minetest.log("action", "[missions] " .. player:get_player_name() .. " -- mission timed out: " .. mission.name)
|
2018-05-07 16:07:51 +02:00
|
|
|
|
2018-05-19 12:17:50 +02:00
|
|
|
if has_xp_redo_mod and mission.xp and mission.xp.penalty ~= nil then
|
2018-05-19 17:28:15 +02:00
|
|
|
xp_redo.add_xp(player:get_player_name(), -mission.xp.penalty)
|
2018-05-08 15:28:01 +02:00
|
|
|
end
|
|
|
|
|
2018-05-07 16:07:51 +02:00
|
|
|
end
|
|
|
|
|
2018-05-16 15:27:27 +02:00
|
|
|
local finished = false;
|
2018-06-29 15:54:12 +02:00
|
|
|
local aborted = false;
|
2018-05-16 15:27:27 +02:00
|
|
|
|
2018-05-28 09:53:37 +02:00
|
|
|
if mission.type == "transport" or mission.type == "build" or mission.type == "dig" or mission.type == "craft" then
|
2018-06-29 15:54:12 +02:00
|
|
|
|
|
|
|
-- check if reward is still there, otherwise abort
|
|
|
|
--TODO
|
|
|
|
|
|
|
|
-- check context list
|
2018-05-16 15:27:27 +02:00
|
|
|
local openCount = 0
|
2018-05-28 09:04:34 +02:00
|
|
|
for i,itemStr in pairs(mission.context.list) do
|
2018-05-16 15:27:27 +02:00
|
|
|
-- check if items placed
|
|
|
|
local stack = ItemStack(itemStr)
|
|
|
|
if not stack:is_empty() then
|
|
|
|
openCount = openCount + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if openCount == 0 then
|
|
|
|
finished = true
|
2018-05-07 16:07:51 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-16 15:27:27 +02:00
|
|
|
if finished then
|
2018-05-07 16:07:51 +02:00
|
|
|
-- mission finished
|
|
|
|
|
2018-06-29 14:36:01 +02:00
|
|
|
-- reset cooldown timer
|
|
|
|
missions.cooldown_reset(mission.name, player:get_player_name())
|
2018-05-07 16:07:51 +02:00
|
|
|
|
|
|
|
missions.hud_remove_mission(player, mission)
|
|
|
|
missions.remove_mission(player, mission)
|
2018-05-16 15:27:27 +02:00
|
|
|
minetest.chat_send_player(player:get_player_name(), "Mission finished: " .. mission.name)
|
|
|
|
minetest.log("action", "[missions] " .. player:get_player_name() .. " -- mission finished: " .. mission.name)
|
2018-05-07 16:07:51 +02:00
|
|
|
|
2018-05-08 08:40:24 +02:00
|
|
|
minetest.sound_play({name="missions_generic", gain=0.25}, {to_player=player:get_player_name()})
|
|
|
|
|
|
|
|
|
|
|
|
local one = player:hud_add({
|
|
|
|
hud_elem_type = "image",
|
|
|
|
name = "award_bg",
|
|
|
|
scale = {x = 2, y = 1},
|
|
|
|
text = "missions_bg_default.png",
|
|
|
|
position = {x = 0.5, y = 0},
|
|
|
|
offset = {x = 0, y = 138},
|
|
|
|
alignment = {x = 0, y = -1}
|
|
|
|
})
|
|
|
|
|
|
|
|
local two = player:hud_add({
|
|
|
|
hud_elem_type = "text",
|
|
|
|
name = "award_au",
|
|
|
|
number = 0xFFFFFF,
|
|
|
|
scale = {x = 100, y = 20},
|
|
|
|
text = "Mission complete!",
|
|
|
|
position = {x = 0.5, y = 0},
|
|
|
|
offset = {x = 0, y = 40},
|
|
|
|
alignment = {x = 0, y = -1}
|
|
|
|
})
|
|
|
|
|
|
|
|
local three = player:hud_add({
|
|
|
|
hud_elem_type = "text",
|
|
|
|
name = "award_title",
|
|
|
|
number = 0xFFFFFF,
|
|
|
|
scale = {x = 100, y = 20},
|
2018-05-16 15:27:27 +02:00
|
|
|
text = mission.name,
|
2018-05-08 08:40:24 +02:00
|
|
|
position = {x = 0.5, y = 0},
|
|
|
|
offset = {x = 30, y = 100},
|
|
|
|
alignment = {x = 0, y = -1}
|
|
|
|
})
|
|
|
|
|
|
|
|
local four = player:hud_add({
|
|
|
|
hud_elem_type = "image",
|
|
|
|
name = "award_icon",
|
|
|
|
scale = {x = 4, y = 4},
|
2018-05-08 15:28:01 +02:00
|
|
|
text = "default_gold_ingot.png",
|
2018-05-08 08:40:24 +02:00
|
|
|
position = {x = 0.4, y = 0},
|
|
|
|
offset = {x = -81.5, y = 126},
|
|
|
|
alignment = {x = 0, y = -1}
|
|
|
|
})
|
|
|
|
|
|
|
|
minetest.after(4, function()
|
|
|
|
player:hud_remove(one)
|
|
|
|
player:hud_remove(two)
|
|
|
|
player:hud_remove(three)
|
|
|
|
player:hud_remove(four)
|
|
|
|
end)
|
|
|
|
|
2018-05-16 14:21:01 +02:00
|
|
|
if has_xp_redo_mod and mission.xp and mission.xp.reward then
|
|
|
|
xp_redo.add_xp(player:get_player_name(), mission.xp.reward)
|
2018-05-08 15:28:01 +02:00
|
|
|
end
|
|
|
|
|
2018-05-07 16:07:51 +02:00
|
|
|
|
|
|
|
local inv = player:get_inventory()
|
|
|
|
for i,stackStr in pairs(mission.reward.list) do
|
|
|
|
-- reward player
|
|
|
|
local stack = ItemStack(stackStr)
|
|
|
|
inv:add_item("main", stack)
|
|
|
|
end
|
2018-05-07 14:59:11 +02:00
|
|
|
end
|
2018-05-07 13:35:14 +02:00
|
|
|
end
|
|
|
|
|
2018-05-28 09:04:34 +02:00
|
|
|
-- timeout check
|
2018-05-07 13:35:14 +02:00
|
|
|
local timer = 0
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
|
|
timer = timer + dtime;
|
|
|
|
if timer >= 1 then
|
|
|
|
local now = os.time(os.date("!*t"))
|
|
|
|
local players = minetest.get_connected_players()
|
|
|
|
for i,player in pairs(players) do
|
|
|
|
local playername = player:get_player_name()
|
|
|
|
local playermissions = missions.list[playername]
|
|
|
|
if playermissions ~= nil then
|
|
|
|
for j,mission in pairs(playermissions) do
|
2018-05-07 14:59:11 +02:00
|
|
|
local remaining = mission.time - (now - mission.start)
|
2018-05-07 13:35:14 +02:00
|
|
|
|
2018-05-07 16:07:51 +02:00
|
|
|
check_player_mission(player, mission, remaining)
|
2018-05-07 13:35:14 +02:00
|
|
|
end
|
|
|
|
end
|
2018-05-07 14:59:11 +02:00
|
|
|
missions.hud_update(player, playermissions)
|
2018-05-07 13:35:14 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
timer = 0
|
|
|
|
end
|
2018-05-07 14:59:11 +02:00
|
|
|
end)
|
|
|
|
|
2018-05-28 09:04:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
-- transport, dig, craft, build mission
|
|
|
|
-- returns count of items moved to target (if any)
|
|
|
|
missions.update_mission = function(player, mission, stack)
|
|
|
|
|
|
|
|
minetest.log("action", "[missions] " .. player:get_player_name() .. " updates context items: " .. stack:to_string())
|
|
|
|
local count = 0
|
|
|
|
|
|
|
|
for i,targetStackStr in pairs(mission.context.list) do
|
|
|
|
local targetStack = ItemStack(targetStackStr)
|
|
|
|
|
|
|
|
if targetStack:get_name() == stack:get_name() then
|
|
|
|
-- same type
|
|
|
|
local takenStack = targetStack:take_item(stack:get_count())
|
|
|
|
|
|
|
|
-- update current stack
|
|
|
|
stack:set_count(stack:get_count() - takenStack:get_count())
|
|
|
|
|
|
|
|
-- update return stack
|
|
|
|
count = count + takenStack:get_count()
|
|
|
|
|
|
|
|
-- save remaining stack
|
|
|
|
mission.context.list[i] = targetStack:to_string()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return count
|
|
|
|
end
|
|
|
|
|