854 lines
31 KiB
Lua
854 lines
31 KiB
Lua
|
|
-- helper function; used by
|
|
-- * yl_speak_up.get_fs_edit_option_dialog and
|
|
-- * yl_speak_up.get_fs_edit_trade_limit
|
|
yl_speak_up.get_list_of_effects_and_target_dialog_and_effect = function(dialog, results, pname, target_dialog, target_effect)
|
|
local list_of_effects = ""
|
|
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 or v.r_value == "d_end" or v.r_value == "d_got_item") then
|
|
list_of_effects = list_of_effects..
|
|
minetest.formspec_escape(v.r_id)..",#999999,"..
|
|
minetest.formspec_escape(v.r_type)..","..
|
|
minetest.formspec_escape(
|
|
yl_speak_up.show_effect(v, pname))..","
|
|
-- there may be more than one in the data structure
|
|
target_dialog = v.r_value
|
|
target_effect = v
|
|
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(
|
|
yl_speak_up.show_effect(v, pname))..","
|
|
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
|
|
return {list = list_of_effects, target_dialog = target_dialog, target_effect = target_effect}
|
|
end
|
|
|
|
|
|
-- 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)) 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
|
|
local o_id = yl_speak_up.speak_to[pname].o_id
|
|
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
local n_dialog = dialog.n_dialogs[d_id]
|
|
if(not(n_dialog) or not(n_dialog.d_options)) then
|
|
return
|
|
end
|
|
local d_option = n_dialog.d_options[o_id]
|
|
if(not(d_option)) then
|
|
return
|
|
end
|
|
|
|
if(fields.assign_quest_step and fields.assign_quest_step ~= "") then
|
|
yl_speak_up.show_fs(player, "assign_quest_step",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id})
|
|
return
|
|
end
|
|
|
|
if(fields.switch_tab and fields.switch_tab == "2") then
|
|
yl_speak_up.show_fs(player, "edit_option_dialog",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id,
|
|
caller="show_if_action_failed"})
|
|
return
|
|
elseif(fields.switch_tab and fields.switch_tab == "1") then
|
|
yl_speak_up.show_fs(player, "edit_option_dialog",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id,
|
|
caller="show_if_action_succeeded"})
|
|
return
|
|
elseif(fields.switch_tab and fields.switch_tab == "3") then
|
|
yl_speak_up.show_fs(player, "edit_option_dialog",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id,
|
|
caller="show_tab_limit_guessing"})
|
|
return
|
|
elseif(fields.switch_tab and fields.switch_tab == "4") then
|
|
yl_speak_up.show_fs(player, "edit_option_dialog",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id,
|
|
caller="show_tab_limit_repeating"})
|
|
return
|
|
end
|
|
|
|
-- this menu is specific to an option for a dialog; if no dialog is selected, we really
|
|
-- can't know what to do
|
|
if(not(o_id) and d_id) then
|
|
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id})
|
|
elseif(not(d_id)) then
|
|
return
|
|
end
|
|
|
|
-- backwards compatibility to when this was a hidden field
|
|
fields.o_id = o_id
|
|
-- 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
|
|
|
|
if(fields.save_option) then
|
|
yl_speak_up.show_fs(player, "edit_option_dialog",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id, caller="save_option"})
|
|
return
|
|
end
|
|
|
|
-- want to edit the text that is shown when switching to the next dialog?
|
|
if(fields.button_edit_action_failed_dialog
|
|
or fields.button_edit_action_success_dialog
|
|
or fields.save_dialog_modification
|
|
or fields.button_edit_limit_action_failed_repeat
|
|
or fields.button_edit_limit_action_success_repeat
|
|
or fields.turn_alternate_text_into_new_dialog) then
|
|
if( yl_speak_up.handle_edit_actions_alternate_text(
|
|
-- x_id, id_prefix, target_element and tmp_data_cache are nil here
|
|
player, pname, n_id, d_id, o_id, nil, nil,
|
|
"edit_option_dialog", nil, fields, nil)) then
|
|
-- the function above showed a formspec already
|
|
return
|
|
else
|
|
yl_speak_up.show_fs(player, "edit_option_dialog",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id,
|
|
caller="back_from_edit_dialog_modifications"})
|
|
return
|
|
end
|
|
|
|
elseif(fields.back_from_edit_dialog_modification) then
|
|
-- no longer working on an alternate text
|
|
yl_speak_up.speak_to[pname].edit_alternate_text_for = nil
|
|
yl_speak_up.show_fs(player, "edit_option_dialog",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id, caller="back_from_edit_dialog_modifications"})
|
|
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
|
|
|
|
-- the player wants to see the previous option/answer
|
|
if(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
|
|
|
|
-- the player clicked on a precondition
|
|
elseif(fields.table_of_preconditions) then
|
|
yl_speak_up.show_fs(player, "edit_preconditions", fields.table_of_preconditions)
|
|
return
|
|
|
|
-- the player clicked on an action
|
|
elseif(fields.table_of_actions) then
|
|
yl_speak_up.show_fs(player, "edit_actions", fields.table_of_actions)
|
|
return
|
|
|
|
-- the player clicked on an effect
|
|
elseif(fields.table_of_effects) then
|
|
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, caller)
|
|
-- 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]
|
|
|
|
-- 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(n_dialog) or not(n_dialog.d_options) or not(n_dialog.d_options[o_id])) 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
|
|
local d_option = n_dialog.d_options[o_id]
|
|
|
|
-- if it is a quest step, then show that; else allow creating a quest step
|
|
local quest_step_text = "button[15.4,0.1;6.0,0.9;assign_quest_step;Turn this into a quest step]"
|
|
if( d_option.quest_id and d_option.quest_id ~= ""
|
|
and d_option.quest_step and d_option.quest_step ~= "") then
|
|
local q_id = ""
|
|
local quest_name = "["..tostring(d_option.quest_id).."] - unknown quest -"
|
|
for q_id, data in pairs(yl_speak_up.quests) do
|
|
if(data and data.var_name == d_option.quest_id) then
|
|
quest_name = "["..tostring(q_id)..": "..
|
|
tostring(yl_speak_up.strip_pname_from_var(data.var_name, pname))..
|
|
"] "..
|
|
tostring(data.name)
|
|
end
|
|
end
|
|
quest_step_text = table.concat({"box[4.9,0.0;14.0,1.1;#BB77BB]",
|
|
"label[0.2,0.3;This is quest step:]",
|
|
"label[5.0,0.3;",
|
|
minetest.colorize("#00FFFF",
|
|
minetest.formspec_escape(d_option.quest_step)),
|
|
"]",
|
|
"label[0.2,0.8;of the quest:]",
|
|
"label[5.0,0.8;",
|
|
minetest.colorize("#CCCCFF",
|
|
minetest.formspec_escape(quest_name)),
|
|
"]",
|
|
"button[19.4,0.1;2.0,0.9;assign_quest_step;Change]"
|
|
}, "")
|
|
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
|
|
|
|
local answer_mode = 0
|
|
-- shall this option be choosen automaticly?
|
|
if(d_option.o_autoanswer and d_option.o_autoanswer == 1) then
|
|
answer_mode = 1
|
|
-- or randomly?
|
|
elseif(n_dialog.o_random) then
|
|
answer_mode = 2
|
|
end
|
|
|
|
-- show an option only once
|
|
local visit_only_once = 0
|
|
if(d_option.o_visit_only_once and d_option.o_visit_only_once == 1) then
|
|
visit_only_once = 1
|
|
end
|
|
|
|
local answer_text =
|
|
-- answer of the player (the actual option)
|
|
"container[0.0,8.3]"..
|
|
"label[0.2,0.0;..the player may answer with this text"..
|
|
minetest.formspec_escape(" [dialog option \""..tostring(o_id).."\"]:").."]"..
|
|
"dropdown[13.3,-0.4;2.5,0.7;option_visits;"..
|
|
"often,*once*;"..tostring(visit_only_once + 1)..";]"..
|
|
"tooltip[option_visits;\"often\" allows to select this option whenever the\n"..
|
|
"\tpreconditions are fulfilled.\n"..
|
|
"\"*once*\" greys out the option after it has been selected\n"..
|
|
"\tone time successfully.\n"..
|
|
"Useful for visually marking options as read for the player.\n"..
|
|
"Talking to the NPC anew resets this option and it can be selected again.]"..
|
|
"dropdown[16.0,-0.4;5.3,0.7;option_autoanswer;"..
|
|
"by clicking on it,automaticly,randomly;"..tostring(answer_mode+1)..";]"
|
|
-- (automaticly *by fulfilling the prerequirements*)
|
|
if(d_id == "d_got_item" or d_id == "d_trade") then
|
|
answer_mode = 1
|
|
d_option.o_autoanswer = 1
|
|
answer_text =
|
|
"container[0.0,8.3]"..
|
|
"label[0.2,0.0;..this option will be selected automaticly.]"
|
|
end
|
|
if(answer_mode == 0 and (d_id ~= "d_got_item" and d_id ~= "d_trade")) then
|
|
answer_text = table.concat({answer_text,
|
|
"label[1.2,0.8;A:]",
|
|
"field[1.7,0.3;19.6,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,1.7;..but if at least one pre(C)ondition is not fulfilled, then...]",
|
|
"dropdown[12.0,1.3;9.3,0.7;hide_or_grey_or_alternate_answer;",
|
|
"..hide this answer.,",
|
|
"..grey out the following answer:,",
|
|
"..display the following alternate answer:;",
|
|
alternate_answer_option,
|
|
";]",
|
|
-- alternate answer
|
|
"label[1.2,2.5;A:]",
|
|
"field[1.7,2.0;19.6,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.]",
|
|
"container_end[]"
|
|
}, "")
|
|
elseif(answer_mode == 1) then
|
|
answer_text = answer_text..
|
|
"label[1.2,0.8;This option will not be shown but will be selected automaticly if all "..
|
|
"prerequirements are fullfilled.]"..
|
|
"label[1.2,1.4;The remaining options of this dialog will in this case not be evaluated.]"..
|
|
"label[1.2,2.0;The NPC will proceed as if this option was choosen manually.]"..
|
|
"label[1.2,2.6;"
|
|
if(d_id == "d_got_item") then
|
|
answer_text = answer_text..
|
|
"Note: This is used here to process items that the player gave to the NPC."
|
|
elseif(d_id == "d_trade") then
|
|
answer_text = answer_text..
|
|
"Note: This is useful for refilling stock by crafting new things when "..
|
|
"necessary, or for getting\nsupplies from a storage, or for storing "..
|
|
"traded goods in external storage chests."
|
|
else
|
|
answer_text = answer_text..
|
|
"This is i.e. useful for offering a diffrent start dialog depending on the "..
|
|
"player's progress in a quest."
|
|
end
|
|
answer_text = answer_text .. "]container_end[]"
|
|
elseif(answer_mode == 2) then
|
|
answer_text = answer_text..
|
|
"label[1.2,0.8;One option of the dialog - for example this one - will be selected randomly.]"..
|
|
"label[1.2,1.4;The other options of this dialog will be set to random as well.]"..
|
|
"label[1.2,2.0;The NPC will proceed as if this dialog was choosen manually.]"..
|
|
"label[1.2,2.6;Useful for small talk for generic NPC but usually not for quests.]"..
|
|
"container_end[]"
|
|
end
|
|
|
|
-- remember which option we are working at (better than a hidden field)
|
|
yl_speak_up.speak_to[pname].o_id = o_id
|
|
-- 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, pname))..","
|
|
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
|
|
|
|
-- build action list the same way as list of preconditions and effects
|
|
local list_of_actions = ""
|
|
local actions = d_option.actions
|
|
local count_actions = 0
|
|
local action_data = nil
|
|
-- if autoanswer or random is choosen, then there can be no action
|
|
if(answer_mode == 1 or answer_mode == 2) then
|
|
actions = nil
|
|
count_actions = 0
|
|
caller = ""
|
|
end
|
|
if(actions) then
|
|
local sorted_key_list = yl_speak_up.sort_keys(actions)
|
|
for i, k in ipairs(sorted_key_list) do
|
|
local v = actions[ k ]
|
|
list_of_actions = list_of_actions..
|
|
minetest.formspec_escape(v.a_id)..",#FFFF00,"..
|
|
minetest.formspec_escape(v.a_type)..","..
|
|
minetest.formspec_escape(
|
|
yl_speak_up.show_action(v))..","
|
|
count_actions = count_actions + 1
|
|
action_data = v
|
|
end
|
|
end
|
|
if(count_actions < yl_speak_up.max_actions) then
|
|
list_of_actions = list_of_actions..",#00FF00,add,Add a new (A)ction"
|
|
else
|
|
list_of_actions = list_of_actions..",#AAAAAA,-,"..
|
|
"Maximum amount of (A)ctions per option reached!"
|
|
end
|
|
|
|
-- list of (A)ctions (there can only be one per option; i.e. a trade)
|
|
local action_list_text =
|
|
"container[0.0,12.0]"..
|
|
"label[0.2,0.0;When this answer has been selected, start the following (A)ction:]"..
|
|
"tablecolumns[text;color,span=1;text;text]"
|
|
if(answer_mode == 1) then
|
|
action_list_text = action_list_text..
|
|
"label[1.2,0.6;No actions are executed because this option here is automaticly selected.]"..
|
|
"container_end[]"
|
|
elseif(answer_mode == 2) then
|
|
action_list_text = action_list_text..
|
|
"label[1.2,0.6;No actions are executed because this option here is selected randomly.]"..
|
|
"container_end[]"
|
|
else
|
|
action_list_text = action_list_text..
|
|
"table[1.2,0.3;20.2,0.7;table_of_actions;"..
|
|
list_of_actions..";0]"..
|
|
"container_end[]"
|
|
end
|
|
|
|
-- find the right target dialog for this option (if it exists)
|
|
local target_dialog = nil
|
|
-- which effect holds the information about the target dialog?
|
|
-- set this to a fallback for yl_speak_up.show_colored_dialog_text
|
|
local target_effect = {r_id = "-?-", r_type = "dialog"}
|
|
-- and build the list of effects
|
|
local results = d_option.o_results
|
|
-- create a new dialog type option if needed
|
|
if(not(results) or not(next(results))) then
|
|
target_dialog = yl_speak_up.prepare_new_dialog_for_option(
|
|
dialog, pname, n_id, d_id, o_id,
|
|
yl_speak_up.text_new_dialog_id,
|
|
results)
|
|
-- make sure we are up to date (a new option was inserted)
|
|
results = d_option.o_results
|
|
end
|
|
-- constructs the list_of_effects; may also update target_dialog and target_effect
|
|
local res = yl_speak_up.get_list_of_effects_and_target_dialog_and_effect(dialog, results, pname,
|
|
target_dialog, target_effect)
|
|
local list_of_effects = res.list
|
|
target_dialog = res.target_dialog
|
|
target_effect = res.target_effect
|
|
|
|
-- 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])
|
|
and target_dialog ~= "d_end"
|
|
and target_dialog ~= "d_got_item")) 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
|
|
-- 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
|
|
local d_name = (v.d_name or v.d_id or "?")
|
|
-- build the list of available dialogs for the dropdown list(s)
|
|
dialog_list = dialog_list..","..minetest.formspec_escape(d_name)
|
|
-- which one is the current dialog?
|
|
n = n + 1
|
|
if(v.d_id == target_dialog) then
|
|
dialog_selected = tostring(n)
|
|
end
|
|
end
|
|
if(target_dialog == "d_end") then
|
|
dialog_selected = tostring(n + 1)
|
|
end
|
|
end
|
|
dialog_list = dialog_list..",d_end"
|
|
if(not(target_dialog)) then
|
|
target_dialog = "- none -"
|
|
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
|
|
-- the buttons are inside a container; thus, Y is 0.0
|
|
if(o == o_id and sorted_list[ i-1 ]) then
|
|
button_prev = ""..
|
|
"button[7.9,0.0;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.5,0.0;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 = ""..
|
|
-- the buttons are inside a container; thus, Y is 0.0
|
|
"button[2.4,0.0;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
|
|
or target_dialog == "d_end") then
|
|
button_add = ""
|
|
end
|
|
|
|
-- make all following coordinates relative
|
|
local action_text = "container[0.2,14.0]"..
|
|
"box[0.25,0.0;21.0,6.7;#555555]"
|
|
local tab_list = "tabheader[0.2,0.0;switch_tab;"..
|
|
"If the action was successful:,"..
|
|
"If the action failed:,"..
|
|
"Limit guessing:,"..
|
|
"Limit repeating:"
|
|
-- show what happens if the action fails
|
|
if(caller == "show_if_action_failed") then
|
|
-- allow to switch between successful and failed actions
|
|
action_text = action_text..tab_list..";2;true;true]"..
|
|
"label[0.4,0.6;"..
|
|
"If the player *failed* to complete the above action correctly,]"
|
|
if(action_data and action_data.a_on_failure
|
|
and dialog.n_dialogs and dialog.n_dialogs[ action_data.a_on_failure]) then
|
|
action_text = action_text..
|
|
-- ..and what the NPC will reply to that answer
|
|
"tooltip[1.2,3.9;19.6,2.5;This is what the NPC will say next when "..
|
|
"the player has failed to complete the action.]"..
|
|
|
|
"container[0.0,3.2]"..
|
|
"label[0.4,0.4;..the NPC will react to this failed action with the "..
|
|
"following dialog \""..tostring(action_data.a_on_failure)..
|
|
"\""..
|
|
yl_speak_up.show_colored_dialog_text(
|
|
dialog,
|
|
action_data,
|
|
action_data.a_on_failure,
|
|
"1.2,0.7;19.6,2.5;d_text_next",
|
|
"with the *modified* text",
|
|
":]",
|
|
"button_edit_action_failed_dialog")..
|
|
"container_end[]"
|
|
else
|
|
action_text = action_text..
|
|
"label[0.4,3.6;..go back to the initial dialog.]"
|
|
end
|
|
-- show time-based restrictions (max guesses per time);
|
|
-- the values will be saved in function yl_speak_up.edit_mode_apply_changes
|
|
elseif( caller == "show_tab_limit_guessing") then
|
|
local timer_name = "timer_on_failure_"..tostring(d_id).."_"..tostring(o_id)
|
|
local timer_data = yl_speak_up.get_variable_metadata(timer_name, "parameter", true)
|
|
if(not(timer_data)) then
|
|
timer_data = {}
|
|
end
|
|
action_text = table.concat({action_text,
|
|
tab_list,
|
|
";3;true;true]",
|
|
-- allow to switch between successful and failed actions
|
|
"label[0.4,0.6;",
|
|
"Apply the following time-based restrictions to limit wild guessing:]",
|
|
-- timer for failed actions
|
|
"label[0.4,1.6;The player can make]",
|
|
"field[4.9,1.0;1.5,0.9;timer_max_attempts_on_failure;;",
|
|
tostring(timer_data[ "max_attempts" ] or 0),
|
|
"]",
|
|
"label[6.7,1.6;attempts to complete this action successfully each]",
|
|
"field[17.5,1.0;1.5,0.9;timer_max_seconds_on_failure;;",
|
|
tostring(timer_data[ "duration" ] or 0),
|
|
"]",
|
|
"label[19.2,1.6;seconds.]",
|
|
"label[0.4,2.2;Hint: 3 attempts per 1200 seconds (=20 minutes or one MineTest day)"..
|
|
" may be good values to\navoid wild guessing while not making the player "..
|
|
"having to wait too long to try again.]"..
|
|
"tooltip[timer_max_attempts_on_failure;How many tries shall the player have?"..
|
|
"\nA value of 0 disables this restriction.]"..
|
|
"tooltip[timer_max_seconds_on_failure;After which time can the player try again?"..
|
|
"\nA value of 0 disables this restriction.]"..
|
|
-- ..and what the NPC will explain in such a case
|
|
"tooltip[1.2,3.9;19.6,2.5;This is what the NPC will say next when "..
|
|
"\nthe player has failed to complete the action too"..
|
|
"\nmany times for the NPC's patience and the player"..
|
|
"\nhas to wait some time before guessing again.]"..
|
|
"container[0.0,3.2]"..
|
|
"label[0.4,0.4;The NPC will explain his unwillingness to accept more "..
|
|
"guesses ",
|
|
yl_speak_up.show_colored_dialog_text(
|
|
dialog,
|
|
{alternate_text = (timer_data[ "alternate_text" ]
|
|
or yl_speak_up.standard_text_if_action_failed_too_often)},
|
|
d_id, -- show the same dialog again
|
|
"1.2,0.7;19.6,2.5;d_text_next",
|
|
"with the following text",
|
|
":]",
|
|
"button_edit_limit_action_failed_repeat"),
|
|
"container_end[]"
|
|
}, "")
|
|
-- show time-based restrictions (time between repeating this action successfully)
|
|
elseif( caller == "show_tab_limit_repeating") then
|
|
local timer_name = "timer_on_success_"..tostring(d_id).."_"..tostring(o_id)
|
|
local timer_data = yl_speak_up.get_variable_metadata(timer_name, "parameter", true)
|
|
if(not(timer_data)) then
|
|
timer_data = {}
|
|
end
|
|
action_text = table.concat({action_text,
|
|
tab_list,
|
|
";4;true;true]",
|
|
"label[0.4,0.6;",
|
|
"Apply the following time-based restrictions to limit too quick repeating:]",
|
|
-- timer for successful actions
|
|
"label[0.4,1.6;If the player completed the action successfully, he shall have to"..
|
|
" wait]",
|
|
"field[15.0,1.0;1.5,0.9;timer_max_seconds_on_success;;",
|
|
tostring(timer_data[ "duration" ] or 0),
|
|
"]",
|
|
"label[16.7,1.6;seconds until he]",
|
|
"label[0.4,2.1;can repeat the action. Hint: 1200 seconds (=20 minutes or one ",
|
|
"MineTest day) may be a good value.]",
|
|
"tooltip[timer_max_seconds_on_success;",
|
|
minetest.formspec_escape(
|
|
"If you hand out a quest item, you may not want the player"..
|
|
"\nto immediately repeat the action countless times, thus"..
|
|
"\nemptying the NPC's storage and using the quest item for"..
|
|
"\nother purposes. On the other hand, quest items may get "..
|
|
"\nlost, so the player needs a way to repeat each step."..
|
|
"\n1200 seconds may be a good value here as well."),
|
|
"]",
|
|
-- ..and what the NPC will explain in such a case
|
|
"tooltip[1.2,3.9;19.6,2.5;",
|
|
minetest.formspec_escape(
|
|
"This is what the NPC will say next when the player"..
|
|
"\nwants to repeat the action too soon for the NPC's"..
|
|
"\ntaste - after all the NPC does not have infinite "..
|
|
"\ninventory ressources, and the player may abuse the "..
|
|
"\nquest item for entirely diffrent purposes.."),
|
|
"]",
|
|
"container[0.0,3.2]",
|
|
-- this will lead back to the same dialog
|
|
"label[0.4,0.4;The NPC will explain his unwillingness to repeat the "..
|
|
"action so soon ",
|
|
yl_speak_up.show_colored_dialog_text(
|
|
dialog,
|
|
{alternate_text = (timer_data[ "alternate_text" ]
|
|
or yl_speak_up.standard_text_if_action_repeated_too_soon)},
|
|
d_id, -- show the same dialog again
|
|
"1.2,0.7;19.6,2.5;d_text_next",
|
|
"with the following text",
|
|
":]",
|
|
"button_edit_limit_action_success_repeat"),
|
|
"container_end[]"
|
|
}, "")
|
|
-- show what happens if the action was successful
|
|
else
|
|
-- no action defined
|
|
if(count_actions == 0) then
|
|
-- do not show tabheader
|
|
action_text = action_text..
|
|
"label[0.4,0.6;"..
|
|
"There is no (A)ction defined. Directly apply the following (Ef)fects:]"
|
|
else
|
|
-- allow to switch between successful and failed actions
|
|
action_text = table.concat({action_text,
|
|
tab_list,
|
|
";1;true;true]",
|
|
"label[0.4,0.6;",
|
|
"If the player completed the above action successfully, "..
|
|
"apply the following (Ef)fects:]"
|
|
}, "")
|
|
end
|
|
action_text = table.concat({action_text,
|
|
-- list of effects
|
|
"tablecolumns[text;color,span=1;text;text]",
|
|
"table[1.2,0.9;19.6,2.0;table_of_effects;",
|
|
list_of_effects,
|
|
";0]",
|
|
"tooltip[1.2,0.9;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!]",
|
|
"container[0.0,3.2]",
|
|
"label[0.4,0.4;The NPC will react to this answer with dialog:]"
|
|
}, "")
|
|
if(d_id == "d_trade") then
|
|
action_text = action_text..
|
|
"label[13.5,0.4;..by showing his trade list.]"..
|
|
"container_end[]"
|
|
else
|
|
action_text = table.concat({action_text,
|
|
-- allow to change the target dialog via a dropdown menu
|
|
"dropdown[11,0.0;9.8,0.7;d_id_",
|
|
minetest.formspec_escape(o_id),
|
|
";",
|
|
dialog_list,
|
|
";",
|
|
dialog_selected,
|
|
",]",
|
|
"tooltip[10.2,0.0;3.0,0.7;Select the target dialog with which the NPC shall react "..
|
|
"to this answer.\nCurrently, dialog \"",
|
|
minetest.formspec_escape(target_dialog),
|
|
"\" is beeing displayed.;#FFFFFF;#000000]",
|
|
-- ..and what the NPC will reply to that answer
|
|
"tooltip[1.2,0.7;19.6,2.5;This is what the NPC will say next when the player has "..
|
|
"selected this answer here.]",
|
|
yl_speak_up.show_colored_dialog_text(
|
|
dialog,
|
|
-- this is either the "dialog" effect or an empty fallback
|
|
target_effect,
|
|
-- this is the text the NPC will say in reaction to this answer
|
|
target_dialog,
|
|
"1.2,0.7;19.6,2.5;d_text",
|
|
"label[13.5,0.4;with the following *modified* text:]",
|
|
"",
|
|
"button_edit_action_success_dialog"),
|
|
"container_end[]"
|
|
}, "")
|
|
end
|
|
end
|
|
action_text = action_text.."container_end[]"
|
|
|
|
-- build up the formspec
|
|
local formspec = table.concat({
|
|
"size[22,22]",
|
|
"bgcolor[#00000000;false]",
|
|
-- button back to the current dialog (of which this is an option)
|
|
"button[16.4,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.]",
|
|
-- tell the player what this formspec is about
|
|
"label[6.5,0.4;You are editing dialog option \"",
|
|
tostring(o_id),
|
|
"\":]",
|
|
|
|
-- the text the NPC says
|
|
"container[0.0,0.9]",
|
|
"label[0.2,0.0;NPC says ",
|
|
minetest.formspec_escape("[dialog \""..tostring(d_id).."\"]:"),
|
|
"]",
|
|
yl_speak_up.show_colored_dialog_text(
|
|
dialog,
|
|
{r_id = "", r_type = "dialog"},
|
|
d_id,
|
|
"1.2,0.3;20.2,2.5;d_text",
|
|
"", -- no modifications possible at this step
|
|
"",
|
|
""), -- no edit button here as this text cannot be changed here
|
|
"tooltip[1.2,0.3;20.2,3.0;This is what the NPC says to the player.]",
|
|
"container_end[]",
|
|
|
|
"container[0.0,3.9]",
|
|
quest_step_text,
|
|
"container_end[]",
|
|
|
|
-- list the preconditions
|
|
"container[0.0,5.4]",
|
|
"label[0.2,0.0;If all of the following pre(C)onditions are fulfilled:]",
|
|
"tablecolumns[text;color,span=1;text;text]",
|
|
"table[1.2,0.3;20.2,2.0;table_of_preconditions;",
|
|
list_of_preconditions,
|
|
";0]",
|
|
"tooltip[1.2,0.3;20.2,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!]",
|
|
"container_end[]",
|
|
|
|
-- answer of the player (the actual option)
|
|
answer_text,
|
|
|
|
-- list of (A)ctions (there can only be one per option; i.e. a trade)
|
|
action_list_text,
|
|
|
|
-- list effects and target dialog for successful - and target dialog for unsuccessful
|
|
-- actions (including a toggle button)
|
|
action_text,
|
|
|
|
-- container for the buttons/footer
|
|
"container[0.0,20.9]",
|
|
-- button: delete
|
|
"button[0.2,0.0;2.0,0.9;del_option;Delete]",
|
|
"tooltip[del_option;Delete this option/answer.]",
|
|
-- button: add new
|
|
button_add,
|
|
-- button: save
|
|
"button[4.6,0.0;2.0,0.9;save_option;Save]",
|
|
"tooltip[save_option;Save what you canged (or discard it).]",
|
|
-- button: prev/next
|
|
button_prev,
|
|
button_next,
|
|
-- button: go back to dialog (repeated from top of the page)
|
|
"button[15.8,0.0;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[10.1,0.5;Sort:]",
|
|
"field[11.1,0.0;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]",
|
|
"container_end[]"
|
|
}, "")
|
|
return formspec
|
|
end
|
|
|
|
|
|
yl_speak_up.get_fs_edit_option_dialog_wrapper = function(player, param)
|
|
if(not(param)) then
|
|
param = {}
|
|
end
|
|
local pname = player:get_player_name()
|
|
yl_speak_up.speak_to[pname].o_id = param.o_id
|
|
return yl_speak_up.get_fs_edit_option_dialog(player, param.n_id, param.d_id, param.o_id, param.caller)
|
|
end
|
|
|
|
|
|
yl_speak_up.register_fs("edit_option_dialog",
|
|
yl_speak_up.input_edit_option_dialog,
|
|
yl_speak_up.get_fs_edit_option_dialog_wrapper,
|
|
-- no special formspec required:
|
|
nil
|
|
)
|