yl_speak_up/editor/fs/fs_assign_quest_step.lua

344 lines
14 KiB
Lua

-- assign a quest step to a dialog option/answe
-- This is the formspec where this is handled.
-- small helper function
local show_error_fs = function(player, text)
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:assign_quest_step",
formspec = yl_speak_up.build_fs_quest_edit_error(text, "back_from_error_msg")})
end
-- small helper function
yl_speak_up.get_choose_until_step_list = function(pname, q_id, quest_step)
local choose_until_step = {
" - the player restarts the quest -",
" - this quest step -",
" - the quest step immediately following this one -"
}
local cdata = yl_speak_up.quests[q_id].step_data[quest_step]
for step_name, d in pairs(yl_speak_up.quests[q_id].step_data or {}) do
if(step_name ~= quest_step
and cdata
-- exclude steps that quest_step depends on
and table.indexof(cdata.one_step_required or {}, step_name) == -1
and table.indexof(cdata.all_steps_required or {}, step_name) == -1) then
table.insert(choose_until_step, minetest.formspec_escape(step_name))
end
end
return choose_until_step
end
yl_speak_up.input_fs_assign_quest_step = function(player, formname, fields)
if(not(player)) then
return ""
end
local pname = player:get_player_name()
-- what are we talking about?
local n_id = yl_speak_up.speak_to[pname].n_id
local d_id = yl_speak_up.speak_to[pname].d_id
local o_id = yl_speak_up.speak_to[pname].o_id
if(not(n_id) or yl_speak_up.edit_mode[pname] ~= n_id) then
return
end
local dialog = yl_speak_up.speak_to[pname].dialog
if(not(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id))) then
return
end
-- go back to edit options field
if((fields and fields.quit)
or (fields and fields.back and fields.back ~= "")) then
yl_speak_up.show_fs(player, "edit_option_dialog",
{n_id = n_id, d_id = d_id, o_id = o_id})
return
elseif(fields and fields.back_from_error_msg) then
yl_speak_up.show_fs(player, "assign_quest_step", nil)
return
-- show manage quests formspec
elseif(fields and fields.manage_quests) then
-- store information so that the back button can work
yl_speak_up.speak_to[pname][ "working_at" ] = "assign_quest_step"
yl_speak_up.show_fs(player, "manage_quests", nil)
return
elseif(fields and fields.show_quest) then
local q_id = yl_speak_up.speak_to[pname].q_id
local quest_var_name = nil
if(q_id and yl_speak_up.quests[q_id]) then
quest_var_name = yl_speak_up.strip_pname_from_var(yl_speak_up.quests[q_id].var_name, pname)
end
yl_speak_up.show_fs(player, "manage_quests", quest_var_name)
return
elseif(fields and fields.select_quest_id and fields.select_quest_id ~= "") then
local parts = string.split(fields.select_quest_id, " ")
if(parts and parts[1] and yl_speak_up.quests[parts[1]]) then
-- TODO: check if the player has access rights to that quest
-- TODO: check if the NPC has been added to that quest
yl_speak_up.speak_to[pname].q_id = parts[1]
yl_speak_up.show_fs(player, "add_quest_steps", "assign_quest_step")
return
end
elseif(fields and fields.show_step) then
yl_speak_up.show_fs(player, "manage_quest_steps", yl_speak_up.speak_to[pname].quest_step)
return
elseif(fields and fields.change_show_until) then
yl_speak_up.show_fs(player, "assign_quest_step", "change_show_until")
return
elseif(fields and fields.store_show_until and fields.select_show_until) then
local res = yl_speak_up.player_is_working_on_quest(player)
if(res.error_msg) then
return yl_speak_up.build_fs_quest_edit_error(res.error_msg, "back")
end
local choose_until_step = yl_speak_up.get_choose_until_step_list(
res.pname, res.q_id, yl_speak_up.speak_to[pname].quest_step)
local index = table.indexof(choose_until_step, fields.select_show_until or "")
if(index ~= -1) then
local dialog = yl_speak_up.speak_to[pname].dialog
if(not(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id))) then
return
end
table.insert(yl_speak_up.npc_was_changed[ n_id ],
tostring(d_id).." "..tostring(o_id)..
" quest step will be offered until player reached step \""..
tostring(fields.select_show_until).."\".")
if(fields.select_show_until == " - the player restarts the quest -") then
fields.select_show_until = nil
elseif(fields.select_show_until == " - this quest step -") then
fields.select_show_until = yl_speak_up.speak_to[pname].quest_step
elseif(fields.select_show_until == " - the quest step immediately following this one -") then
fields.select_show_until = " next_step"
end
dialog.n_dialogs[d_id].d_options[o_id].quest_show_until = fields.select_show_until
end
yl_speak_up.show_fs(player, "assign_quest_step")
return
elseif(fields.delete_assignment and fields.delete_assignment ~= "") then
local n_id = yl_speak_up.speak_to[pname].n_id
local d_id = yl_speak_up.speak_to[pname].d_id
local o_id = yl_speak_up.speak_to[pname].o_id
-- load the dialog (which may be diffrent from what the player is working on)
local stored_dialog = yl_speak_up.load_dialog(n_id, false)
-- check if the dialog exists
if(not(yl_speak_up.check_if_dialog_has_option(stored_dialog, d_id, o_id))) then
return show_error_fs(player, "Dialog or option not found.")
end
local quest_step_name = dialog.n_dialogs[d_id].d_options[o_id].quest_step
local var_name = dialog.n_dialogs[d_id].d_options[o_id].quest_id
local q_id = yl_speak_up.get_quest_id_by_var_name(var_name, pname)
-- we will ignore the return value so that this connection can be deleted even if
-- something went wrong (quest deleted, no write access to quest etc.)
local msg = yl_speak_up.quest_step_del_where(pname, q_id, quest_step_name,
{n_id = n_id, d_id = d_id, o_id = o_id})
if(not(n_id)) then
return show_error_fs(player, "NPC or location not found.")
end
-- log the change
yl_speak_up.log_change(pname, n_id,
"Dialog "..tostring(d_id)..": Option "..tostring(o_id)..
" no longer sets quest step \""..
tostring(dialog.n_dialogs[d_id].d_options[o_id].quest_step)..
"\" of quest \""..
tostring(dialog.n_dialogs[d_id].d_options[o_id].quest_id).."\".")
-- we have updated the quest step data - we need to update the NPC as well
local dialog = yl_speak_up.load_dialog(n_id, false)
if(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id)) then
-- ok - the tables exist, so we can delete the connection
-- (if it doesn't exist there's no need to change the stored NPC)
dialog.n_dialogs[d_id].d_options[o_id].quest_id = nil
dialog.n_dialogs[d_id].d_options[o_id].quest_step = nil
-- write it back to disc
yl_speak_up.save_dialog(n_id, dialog)
end
-- the player is working on the NPC - thus, the NPC may be in a modified stage
-- that hasn't been written to disc yet, and we need to adjust this stage as well
dialog = yl_speak_up.speak_to[pname].dialog
-- delete the connection
dialog.n_dialogs[d_id].d_options[o_id].quest_id = nil
dialog.n_dialogs[d_id].d_options[o_id].quest_step = nil
yl_speak_up.show_fs(player, "edit_option_dialog",
{n_id = n_id, d_id = d_id, o_id = o_id})
return
elseif(not(fields) or not(fields.save)) then
return
end
-- actually store the data
local error_msg = ""
-- check if the quest exists
local quest_list = yl_speak_up.get_sorted_quest_list(pname)
local idx = table.indexof(quest_list, fields.quest_id or "")
if(not(fields.quest_id) or fields.quest_id == "" or idx < 1) then
error_msg = "Quest not found."
elseif(not(fields.quest_step)
or string.len(fields.quest_step) < 1
or string.len(fields.quest_step) > 80) then
error_msg = "The name of the quest step has to be between\n"..
"1 and 80 characters long."
end
if(error_msg ~= "") then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:assign_quest_step",
formspec = "size[9,2]"..
"label[0.2,0.5;Error: "..minetest.formspec_escape(error_msg).."]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
-- we identify quests by their var_name - not by their q_id
-- (makes it easier to transfer quests from one server to another later)
dialog.n_dialogs[d_id].d_options[o_id].quest_id = yl_speak_up.add_pname_to_var(fields.quest_id, pname)
dialog.n_dialogs[d_id].d_options[o_id].quest_step = fields.quest_step
if(not(yl_speak_up.npc_was_changed[ n_id ])) then
yl_speak_up.npc_was_changed[ n_id ] = {}
end
table.insert(yl_speak_up.npc_was_changed[ n_id ],
"Dialog "..d_id..": Option "..tostring(o_id)..
" has been set as quest step \""..
tostring(fields.quest_step).."\" for quest \""..tostring(fields.quest_id).."\".")
yl_speak_up.show_fs(player, "edit_option_dialog",
{n_id = n_id, d_id = d_id, o_id = o_id})
end
yl_speak_up.get_fs_assign_quest_step = function(player, param)
if(not(player)) then
return ""
end
local pname = player:get_player_name()
local n_id = yl_speak_up.speak_to[pname].n_id
local d_id = yl_speak_up.speak_to[pname].d_id
local o_id = yl_speak_up.speak_to[pname].o_id
-- this only works in edit mode
if(not(n_id) or yl_speak_up.edit_mode[pname] ~= n_id) then
return "size[1,1]label[0,0;You cannot edit this NPC.]"
end
local dialog = yl_speak_up.speak_to[pname].dialog
if(not(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o_id))) then
return "size[4,1]label[0,0;Dialog option does not exist.]"
end
local d_option = dialog.n_dialogs[d_id].d_options[o_id]
local quest_id = d_option.quest_id or ""
local quest_step = d_option.quest_step or ""
local quest_show_until = d_option.quest_show_until or " - the player restarts the quest -"
if(quest_show_until == quest_step) then
quest_show_until = " - this quest step -"
-- players cannot create quest steps with leading blanks
elseif(quest_show_until == " next_step") then
quest_show_until = " - the quest step immediately following this one -"
end
-- has a quest been selected?
local q_id = yl_speak_up.get_quest_id_by_var_name(quest_id, pname)
if(not(q_id)) then
local npc_id = tonumber(string.sub(n_id, 3))
local quest_list = {}
for id, d in pairs(yl_speak_up.quests) do
if(table.indexof(d.npcs or {}, npc_id) ~= -1) then
table.insert(quest_list, minetest.formspec_escape(
tostring(id).." "..tostring(d.name)))
end
end
if(#quest_list < 1) then
return "size[14,4]"..
"label[4.0,0.5;Using this option/answer shall be a quest step.]"..
"label[0.2,1.4;"..
"This NPC "..tostring(n_id).." has not been added to a quest yet.\n"..
"Please add him to the NPC list of one of your quests first!\n"..
"Search the \"Edit\" button for \"NPC that (may) participate:\" "..
"while viewing the desired quest.]"..
"button[0.2,3.0;3.6,0.8;manage_quests;Manage Quests]"..
"button[9.5,3.0;4.0,0.8;back;Back to edit option "..tostring(o_id).."]"
end
local selected = 1
-- local quest_list = yl_speak_up.get_sorted_quest_list(pname)
-- for i, v in ipairs(quest_list) do
-- quest_list[i] = minetest.formspec_escape(v)
-- if(quest_id and v == quest_id) then
-- selected = i
-- end
-- end
return "size[14,4]"..
"label[4.0,0.5;Using this option/answer shall be a quest step.]"..
"label[0.2,1.4;Select a quest:]"..
"dropdown[4.0,1.0;9.5,0.8;select_quest_id;"..
table.concat(quest_list, ',')..";"..
tostring(selected)..",]"..
"label[0.2,2.1;If you want to use a quest not mentionned here or a new one, "..
"click on \"Manage Quests\"\n"..
"and search the \"Edit\" button for \"NPC that (may) participate:\".]"..
"button[0.2,3.0;3.6,0.8;manage_quests;Manage Quests]"..
"button[9.5,3.0;4.0,0.8;back;Back to edit option "..tostring(o_id).."]"
end
-- this is the currently relevant quest
yl_speak_up.speak_to[pname].q_id = q_id
yl_speak_up.speak_to[pname].quest_step = quest_step
local choose_until_step = {}
local show_until = ""
if(param and param == "change_show_until") then
local choose_until_step = yl_speak_up.get_choose_until_step_list(pname, q_id, quest_step)
local index = table.indexof(choose_until_step, quest_show_until or "")
if(index == -1) then
index = 1
end
show_until = "dropdown[3.0,5.1;10,0.5;select_show_until;"..
table.concat(choose_until_step, ",")..";"..tostring(index)..";]"..
"button[13.5,4.8;4.3,0.8;store_show_until;Store]"
else
show_until = "label[3.0,5.4;"..minetest.colorize("#AAFFAA",
minetest.formspec_escape(quest_show_until)).."]"..
"button[13.5,4.8;4.3,0.8;change_show_until;Edit]"
end
local formspec = {
"size[18,7]"..
"label[3.0,0.5;Using this option/answer shall be a quest step.]"..
"label[0.2,1.4;Quest ID:]"..
"label[0.2,1.9;Quest name:]"..
"label[0.2,3.4;quest step:]"..
"button[13.5,3.1;4.3,0.8;show_step;Show this quest step]"..
"label[0.2,3.9;"..
"This quest step will be set for the player after the effects of "..
"the dialog option are executed.]"..
"label[0.2,4.9;"..
"This dialog option will be shown until the player has reached the "..
"following quest step:]"..
"button[0.2,0.2;2.0,0.8;delete_assignment;Delete]"..
"tooltip[delete_assignment;"..
"Delete the assignment of this quest step to this dialog option.\n"..
"Neither the quest step nor the dialog option will be deleted.\n"..
"Just their connection. Afterwards, you can assign a new or\n"..
"diffrent quest step to the dialog option.]"..
"button[13.5,6.0;4.3,0.8;manage_quests;Manage quests]"
}
table.insert(formspec, "label[3.0,1.4;")
table.insert(formspec, minetest.formspec_escape(q_id))
table.insert(formspec, "]")
table.insert(formspec, "label[3.0,1.9;")
table.insert(formspec, minetest.formspec_escape(yl_speak_up.quests[q_id].name or "- ? -"))
table.insert(formspec, "]")
table.insert(formspec, "button[13.5,1.0;4.3,0.8;show_quest;Show this quest ")
table.insert(formspec, tostring(q_id))
table.insert(formspec, "]")
table.insert(formspec, "label[0.2,2.9;This option here (")
table.insert(formspec, tostring(o_id))
table.insert(formspec, ") will be available once the player has reached all required ".. "quest steps for the following]")
table.insert(formspec, "label[3.0,3.4;")
table.insert(formspec, minetest.colorize("#FFFF00", minetest.formspec_escape(quest_step)))
table.insert(formspec, "]")
table.insert(formspec, "button[6.0,6.0;6.0,0.8;back;Back to edit option ")
table.insert(formspec, tostring(o_id))
table.insert(formspec, "]")
table.insert(formspec, show_until)
return table.concat(formspec, " ")
end
yl_speak_up.register_fs("assign_quest_step",
yl_speak_up.input_fs_assign_quest_step,
yl_speak_up.get_fs_assign_quest_step,
-- no special formspec required:
nil
)