yl_speak_up/fs_edit_options_dialog.lua

385 lines
15 KiB
Lua

-- process input from formspec created in get_fs_edit_option_dialog(..)
yl_speak_up.input_edit_option_dialog = function(player, formname, fields)
if formname ~= "yl_speak_up:edit_option_dialog" then
return
end
local pname = player:get_player_name()
-- Is the player working on this particular npc?
local edit_mode = (yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id)
if(not(edit_mode) or not(fields.o_id)) then
return
end
local n_id = yl_speak_up.speak_to[pname].n_id
local d_id = yl_speak_up.speak_to[pname].d_id
-- this is passed on as a hidden field
local o_id = fields.o_id
local dialog = yl_speak_up.speak_to[pname].dialog
local n_dialog = dialog.n_dialogs[d_id]
local d_option = n_dialog.d_options[o_id]
-- this meny is specific to an option for a dialog; if no dialog is selected, we really
-- can't know what to do
if(not(d_id)) then
return
end
-- handles changes to o_text_when_prerequisites_met, target dialog, adding of a new dialog
local result = yl_speak_up.edit_mode_apply_changes(pname, fields)
-- if a new option was added or the target dialog of this one changed, display the right new option
if(result and result["show_next_option"] and n_dialog.d_options[result["show_next_option"]]) then
yl_speak_up.show_fs(player, "edit_option_dialog",
{n_id = n_id, d_id = d_id, o_id = result["show_next_option"],
caller="show_next_option"})
return
end
-- back to the main dialog window?
-- (this also happens when the last option was deleted)
if(fields.show_current_dialog or fields.quit or fields.button_exit or not(d_option) or fields.del_option) then
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id})
return
end
-- for now, there's only trade as action
if(fields.table_of_actions) then
local trade_id = tostring(d_id).." "..tostring(o_id)
if(dialog.trades and dialog.trades[ trade_id ]) then
fields.effect_show_trade = true
else
fields.effect_add_trade = true
end
end
-- add or edit the trade associated with this dialog and option
if(fields.effect_add_trade) then
-- remember which option was selected
yl_speak_up.speak_to[pname].o_id = o_id
-- do not switch target dialog (we are in edit mode)
yl_speak_up.speak_to[pname].target_d_id = nil
-- create a new trade for this dialog and option - with ID "<d_id> <o_id>"
yl_speak_up.show_fs(player, "add_trade_simple", tostring(d_id).." "..tostring(o_id))
return
-- the player wants to see the previous option/answer
elseif(fields.edit_option_prev) then
-- sort all options by o_sort
local sorted_list = yl_speak_up.get_sorted_options(n_dialog.d_options, "o_sort")
local o_found = o_id
for i, o in ipairs(sorted_list) do
if(o == o_id and sorted_list[ i-1]) then
o_found = sorted_list[ i-1 ]
end
end
-- show that dialog; fallback: show the same (o_id) again
yl_speak_up.show_fs(player, "edit_option_dialog",
{n_id = n_id, d_id = d_id, o_id = o_found, caller="prev option"})
return
-- the player wants to see the next option/answer
elseif(fields.edit_option_next) then
-- sort all options by o_sort
local sorted_list = yl_speak_up.get_sorted_options(n_dialog.d_options, "o_sort")
local o_found = o_id
for i, o in ipairs(sorted_list) do
if(o == o_id and sorted_list[ i+1 ]) then
o_found = sorted_list[ i+1 ]
end
end
-- show that dialog; fallback: show the same (o_id) again
yl_speak_up.show_fs(player, "edit_option_dialog",
{n_id = n_id, d_id = d_id, o_id = o_found, caller="next option"})
return
-- show the trade associated with this dialog and option
elseif(fields.effect_show_trade) then
-- remember which option was selected
yl_speak_up.speak_to[pname].o_id = o_id
-- do not switch target dialog (we are in edit mode)
yl_speak_up.speak_to[pname].target_d_id = nil
-- show the trade with ID "<d_id> <o_id>"
yl_speak_up.show_fs(player, "trade_simple", tostring(d_id).." "..tostring(o_id))
return
-- the player clicked on a precondition
elseif(fields.table_of_preconditions) then
-- remember which option was selected
yl_speak_up.speak_to[pname].o_id = o_id
yl_speak_up.show_fs(player, "edit_preconditions", fields.table_of_preconditions)
return
-- the player clicked on an effect
elseif(fields.table_of_effects) then
-- remember which option was selected
yl_speak_up.speak_to[pname].o_id = o_id
yl_speak_up.show_fs(player, "edit_effects", fields.table_of_effects)
return
end
-- if ESC is pressed or anything else unpredicted happens: go back to the main dialog edit window
-- reason: don't loose any unsaved changes to the dialog
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id})
end
-- edit options (not via staff but via the "I am your owner" dialog)
yl_speak_up.get_fs_edit_option_dialog = function(player, n_id, d_id, o_id)
-- n_id, d_id and o_id have already been checked when this function is called
local pname = player:get_player_name()
local dialog = yl_speak_up.speak_to[pname].dialog
local n_dialog = dialog.n_dialogs[d_id]
local d_option = n_dialog.d_options[o_id]
-- currently no trade running (we're editing options)
yl_speak_up.trade[pname] = nil
yl_speak_up.speak_to[pname].trade_id = nil
if(not(d_option)) then
return "size[6,2]"..
"label[0.2,0.5;Ups! Option "..minetest.formspec_escape(tostring(o_id))..
" does not exist.]"..
"button_exit[2,1.5;1,0.9;exit;Exit]"
end
-- are there any preconditions?
local list_of_preconditions = ""
local prereq = d_option.o_prerequisites
local count_prereq = 0
if(prereq) then
local sorted_key_list = yl_speak_up.sort_keys(prereq)
for i, k in ipairs(sorted_key_list) do
local v = prereq[ k ]
list_of_preconditions = list_of_preconditions..
minetest.formspec_escape(v.p_id)..",#FFFF00,"..
minetest.formspec_escape(v.p_type)..","..
minetest.formspec_escape(
yl_speak_up.show_precondition(v))..","
count_prereq = count_prereq + 1
end
end
if(count_prereq < yl_speak_up.max_prerequirements) then
list_of_preconditions = list_of_preconditions..",#00FF00,add,Add a new pre(C)ondition"
else
list_of_preconditions = list_of_preconditions..",#AAAAAA,-,"..
"Maximum amount of pre(C)onditions per option reached!"
end
local list_of_actions = ""
if(dialog.trades and dialog.trades[ tostring(d_id).." "..tostring(o_id) ]) then
local tr = dialog.trades[ tostring(d_id).." "..tostring(o_id)]
-- show the trade in the result/effects list
list_of_actions = ",#FF8800,trade,"..
-- show a reasonable overview of what is traded for what
minetest.formspec_escape("NPC sells "..
table.concat(tr.buy, ";").." for "..
table.concat(tr.pay, ";"))
else
list_of_actions = ",#00FF00,add,Add a new (A)ction"
end
-- find the right target dialog for this option (if it exists)
local target_dialog = nil
-- and build the list of effects
local list_of_effects = ""
local results = d_option.o_results
local count_effects = 0
if(results) then
local sorted_key_list = yl_speak_up.sort_keys(results)
for i, k in ipairs(sorted_key_list) do
local v = results[ k ]
if v.r_type == "dialog" and dialog.n_dialogs[v.r_value] ~= nil then
list_of_effects = list_of_effects..
minetest.formspec_escape(v.r_id)..",#999999,"..
minetest.formspec_escape(v.r_type)..","..
minetest.formspec_escape(v.r_value)..","
-- there may be more than one in the data structure
target_dialog = v.r_value
elseif v.r_type ~= "dialog" then
list_of_effects = list_of_effects..
minetest.formspec_escape(v.r_id)..",#FFFF00,"..
minetest.formspec_escape(v.r_type)..","..
minetest.formspec_escape(v.r_value)..","
end
count_effects = count_effects + 1
end
end
if(count_effects < yl_speak_up.max_result_effects) then
list_of_effects = list_of_effects..",#00FF00,add,Add a new (Ef)fect"
else
list_of_effects = list_of_effects..",#AAAAAA,-,"..
"Maximum amount of allowed (Ef)fects per option reached!"
end
-- if no target dialog has been selected: default is to go to the dialog with d_sort 0
if(not(target_dialog) or target_dialog == "" or not(dialog.n_dialogs[target_dialog])) then
for d, v in pairs(dialog.n_dialogs) do
if(v.d_sort and tonumber(v.d_sort) == 0) then
target_dialog = d
end
end
end
-- this is the text the NPC will say in reaction to this answer
local next_text = ""
if(target_dialog and dialog.n_dialogs[target_dialog]) then
next_text = dialog.n_dialogs[target_dialog].d_text
end
-- build the list of available dialogs for the dropdown list(s)
local dialog_list = yl_speak_up.text_new_dialog_id
local dialog_selected = "1"
-- if there are dialogs defined
if(dialog and dialog.n_dialogs) then
-- the first entry will be "New dialog"
local n = 1
for k, v in pairs(dialog.n_dialogs) do
dialog_list = dialog_list .. "," .. minetest.formspec_escape(v.d_id)
-- which one is the current dialog?
n = n + 1
if(v.d_id == target_dialog) then
dialog_selected = tostring(n)
end
end
end
if(not(target_dialog)) then
target_dialog = "- none -"
end
-- offer the correct preselection for hidden/grey/show text
local alternate_answer_option = "3"
if(d_option.o_hide_when_prerequisites_not_met == "true") then
alternate_answer_option = "1"
elseif(d_option.o_grey_when_prerequisites_not_met == "true") then
alternate_answer_option = "2"
end
-- can the button "prev(ious)" be shown?
local button_prev = ""
-- can the button "next" be shown?
local button_next = ""
-- sort all options by o_sort
local sorted_list = yl_speak_up.get_sorted_options(n_dialog.d_options, "o_sort")
local o_found = o_id
local anz_options = 0
for i, o in ipairs(sorted_list) do
if(o == o_id and sorted_list[ i-1 ]) then
button_prev = ""..
"button[7.4,18.7;2.0,0.9;edit_option_prev;Prev]"..
"tooltip[edit_option_prev;Go to previous option/answer "..
"(according to o_sort).]"
end
if(o == o_id and sorted_list[ i+1 ]) then
button_next = ""..
"button[12.0,18.7;2.0,0.9;edit_option_next;Next]"..
"tooltip[edit_option_next;Go to next option/answer "..
"(according to o_sort).]"
end
anz_options = anz_options + 1
end
-- less than yl_speak_up.max_number_of_options_per_dialog options?
local button_add = ""..
"button[2.4,18.7;2.0,0.9;add_option;Add]"..
"tooltip[add_option;Add a new option/answer to this dialog.]"
if(anz_options >= yl_speak_up.max_number_of_options_per_dialog) then
button_add = ""
end
-- build up the formspec
local formspec = ""..
"formspec_version[3]"..
"size[21,20]"..
"bgcolor[#00000000;false]"..
-- button back to the current dialog (of which this is an option)
"button[15.8,0.2;5.0,0.9;show_current_dialog;Back to dialog "..
minetest.formspec_escape(d_id).."]"..
"tooltip[show_current_dialog;Go back to dialog "..
minetest.formspec_escape(d_id).." and continue editing that dialog.]"..
-- the text the NPC says
"label[0.2,0.6;NPC says:]"..
"hypertext[1.2,1.2;19.6,2.5;d_text;<normal>"..
minetest.formspec_escape(n_dialog.d_text) .. "\n</normal>".."]"..
"tooltip[1.2,1.2;19.6,3.0;This is what the NPC says to the player.]"..
-- list the preconditions
"label[0.2,4.2;If all of the following pre(C)onditions are fulfilled:]"..
"tablecolumns[text;color,span=1;text;text]"..
"table[1.2,4.5;19.6,2.0;table_of_preconditions;"..
list_of_preconditions..";0]"..
"tooltip[1.2,4.5;19.6,2.0;"..
"*All* pre(C)onditions need to be true in order\n"..
"for the option to be offered to the player.\n"..
"Please click on a pre(C)ondition in order\n"..
"to edit or delete it!]"..
-- answer of the player (the actual option)
"label[0.2,6.8;..the player may answer with this text:]"..
"label[1.2,7.6;A:]"..
"field[1.7,7.1;19.1,0.9;text_option_"..minetest.formspec_escape(o_id)..";;"..
minetest.formspec_escape(d_option.o_text_when_prerequisites_met).."]"..
"tooltip[option_text_met;This is the answer the player may choose if the "..
"preconditions are all fulfilled.]"..
-- dropdown for selecting weather to show the alternate answer or not
"label[0.2,8.6;..but if at least one pre(C)ondition is not fulfilled, then...]"..
"dropdown[12.0,8.2;8.6,0.9;hide_or_grey_or_alternate_answer;"..
"..hide this answer.,"..
"..grey out this answer.,"..
"..display the following alternate answer:;"..
alternate_answer_option..";]"..
-- alternate answer
"label[1.2,9.6;A:]"..
"field[1.7,9.1;19.1,0.9;option_text_not_met;;"..
minetest.formspec_escape(d_option.o_text_when_prerequisites_not_met).."]"..
"tooltip[option_text_not_met;This is the answer the player may choose if the "..
"preconditions are NOT all fulfilled.]"..
-- list of (A)ctions (there can only be one per option; i.e. a trade)
"label[0.2,10.6;When this answer has been selected, start the following (A)ction:]"..
"tablecolumns[text;color,span=1;text;text]"..
"table[1.2,10.9;19.6,0.7;table_of_actions;"..
list_of_actions..";0]"..
-- list of effects
"label[0.2,12.0;If the player completed the above action successfully, "..
"apply the following (Ef)fects:]"..
"tablecolumns[text;color,span=1;text;text]"..
"table[1.2,12.3;19.6,2.0;table_of_effects;"..
list_of_effects..";0]"..
"tooltip[1.2,12.3;19.6,2.0;"..
"*All* (Ef)fects are executed after the action (if there is\n"..
"one defined in this option) has been completed successfully\n"..
"by the player. If there is no action defined, then the\n"..
"(Ef)fects will always be executed when this option here is\n"..
"selected.\n"..
"Please click on an (Ef)fect in order to edit or delete it!]"..
-- ..and what the NPC will reply to that answer
"label[0.2,15.1;The NPC will react to this answer with the following dialog:]"..
"hypertext[1.2,15.7;19.6,2.5;d_text_next;<normal>"..
minetest.formspec_escape(next_text) .. "\n</normal>".."]"..
"tooltip[1.2,16.8;21.0,2.5;This is what the NPC will say next when the player has "..
"selected this answer here.]"..
-- allow to change the target dialog via a dropdown menu
"dropdown[14.8,14.7;5,0.9;d_id_"..minetest.formspec_escape(o_id)..";"..
dialog_list..";"..dialog_selected..",]"..
"tooltip[14.8,14.7;5,0.9;Select the target dialog with which the NPC shall react "..
"to this answer. Currently, dialog "..minetest.formspec_escape(target_dialog)..
" is beeing displayed.;#FFFFFF;#000000]"..
-- button: delete
"button[0.2,18.7;2.0,0.9;del_option;Delete]"..
"tooltip[del_option;Delete this option/answer.]"..
-- button: add new
button_add..
-- button: prev/next
button_prev..
button_next..
-- button: go back to dialog (repeated from top of the page)
"button[15.8,18.7;5.0,0.9;show_current_dialog;Back to dialog "..
minetest.formspec_escape(d_id).."]"..
"tooltip[show_current_dialog;Go back to dialog "..
minetest.formspec_escape(d_id).." and continue editing that dialog.]"..
-- allow to enter o_sort
"label[9.6,19.2;Sort:]"..
"field[10.6,18.7;1.0,0.9;edit_option_o_sort;;"..
minetest.formspec_escape(d_option.o_sort).."]"..
"tooltip[edit_option_o_sort;o_sort: The lower the number, the higher up in the "..
"list this option goes\nNegative values are ignored;#FFFFFF;#000000]"..
-- hidden field containing the value of o_id
"field[40,40;0.1,0.1;o_id;;"..minetest.formspec_escape(o_id).."]"
return formspec
end