yl_speak_up/editor/fs/fs_talkdialog_edit_mode.lua
2024-02-14 01:58:18 +01:00

728 lines
31 KiB
Lua

-- we have a better version of this in the editor - so not offer this particular entry:
yl_speak_up.get_fs_talkdialog_add_basic_edit = function(
pname, formspec, h, pname_for_old_fs, is_a_start_dialog,
active_dialog, luaentity, may_edit_npc, anz_options)
return {h = h, formspec = formspec}
end
-- This is the main talkdialog the NPC shows when right-clicked. (now in edit_mode)
local old_input_talk = yl_speak_up.input_talk
yl_speak_up.input_talk = function(player, formname, fields)
local pname = player:get_player_name()
-- Is the player working on this particular npc?
local edit_mode = yl_speak_up.in_edit_mode(pname)
-- if not: do the normal things outside edit mode
if(not(edit_mode) and not(fields.button_start_edit_mode)) then
return old_input_talk(player, formname, fields)
end
-- selected option/answer
local o = ""
-- do all the processing and executing old_input_talk (in non-edit_mode)
-- can do - but do not execute any actions; just return o
fields.just_return_selected_option = true
o = old_input_talk(player, formname, fields)
-- old_input_talk handled it (including some error detection like
-- wrong formname, not talking to npc, npc not configured)
-- if in edit mode: detect if something was changed;
local result = yl_speak_up.edit_mode_apply_changes(pname, fields)
-- o is only nil if the old function returned nil; it does that
-- when it found a fitting reaction to a button press
if(not(o) and not(fields.button_start_edit_mode)) then
return
end
local n_id = yl_speak_up.speak_to[pname].n_id
-- start edit mode (requires npc_talk_owner)
if fields.button_start_edit_mode then
-- check if this particular NPC is really owned by this player or if the player has global privs
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
minetest.chat_send_player(pname, "Sorry. You do not have the npc_talk_owner or npc_talk_master priv.")
return
end
-- the staff allows to create multiple target dialogs as result; this makes no sense
-- and is too disambigous
if(yl_speak_up.check_for_disambigous_results(n_id, pname)) then
-- this needs to be fixed by someone with a staff; we don't know which dialog is the right
-- result
return
end
-- for older formspec versions: reset scroll counter
yl_speak_up.speak_to[pname].counter = 1
yl_speak_up.speak_to[pname].option_index = 1
-- enter edit mode with that particular NPC
yl_speak_up.edit_mode[pname] = yl_speak_up.speak_to[pname].n_id
-- load the NPC dialog anew - but only what the NPC itself has to say, no generic dialogs
yl_speak_up.speak_to[pname].dialog = yl_speak_up.load_dialog(n_id, false)
-- start a new chat - but this time in edit mode
yl_speak_up.speak_to[pname].d_id = nil
yl_speak_up.show_fs(player, "talk", {n_id = yl_speak_up.speak_to[pname].n_id, d_id = nil})
return
-- end edit mode (does not require the priv; will only switch back to normal behaviour)
elseif fields.button_end_edit_mode then
-- if there are any changes done: ask first and don't end edit mode yet
yl_speak_up.show_fs(player, "quit", nil)
return
end
-- show which dialogs point to this one
if(fields.show_what_points_to_this_dialog) then
local dialog = yl_speak_up.speak_to[pname].dialog
local d_id = yl_speak_up.speak_to[pname].d_id
yl_speak_up.show_fs(player, "show_what_points_to_this_dialog",
yl_speak_up.speak_to[pname].d_id)
return
end
-- the player wants to change name and description; show the formspec
if(fields.button_edit_name_and_description) then
-- this is not the initial config - but the same formspec can be used
yl_speak_up.show_fs(player, "initial_config",
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, false})
return
end
-- change skin, cape and wielded items
if(fields.edit_skin) then
local dialog = yl_speak_up.speak_to[pname].dialog
-- necessary so that the fashin formspec can be created
yl_speak_up.speak_to[pname].n_npc = dialog.n_npc
yl_speak_up.show_fs(player, "fashion")
return
end
if(fields.button_save_dialog) then
yl_speak_up.show_fs(player, "talk",
{n_id = n_id, d_id = yl_speak_up.speak_to[pname].d_id, do_save = true})
return
end
if(fields.button_export_dialog) then
yl_speak_up.show_fs(player, "export")
return
end
if(fields.button_edit_notes) then
yl_speak_up.show_fs(player, "notes")
return
end
-- the player wants to give something to the NPC
-- (more complex in edit mode)
if(fields.player_offers_item) then
local dialog = yl_speak_up.speak_to[pname].dialog
local future_d_id = "d_got_item"
-- make sure this dialog exists; create if needed
if(not(dialog.n_dialogs[ future_d_id ])) then
dialog.n_dialogs[future_d_id] = {
d_id = future_d_id,
d_type = "text",
d_text = "",
d_sort = 9999 -- make this the last option
}
end
-- in edit mode: allow to edit the options
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = future_d_id})
return
end
-- button was clicked, now let's execute the results
local d_id = yl_speak_up.speak_to[pname].d_id
local dialog = yl_speak_up.speak_to[pname].dialog
-- all three buttons (pre(C)onditions, (Ef)fects, edit option) lead to the same new formspec
local n_dialog = dialog.n_dialogs[d_id]
if(n_dialog and n_dialog.d_options) then
for o_id,v in pairs(n_dialog.d_options) do
if( fields["edit_option_"..o_id]
or fields["conditions_"..o_id]
or fields["actions_"..o_id]
or fields["quests_"..o_id]
or fields["effects_"..o_id]) then
-- store which option we want to edit
yl_speak_up.speak_to[pname].o_id = o_id
-- if something was changed: ask for confirmation
yl_speak_up.show_fs(player, "edit_option_dialog",
{n_id = yl_speak_up.speak_to[pname].n_id,
d_id = d_id, o_id = o_id, caller="button"})
return
end
end
end
-- we may soon need actions and o_results from the selected_option
local selected_option = {}
if(yl_speak_up.check_if_dialog_has_option(dialog, d_id, o)) then
selected_option = dialog.n_dialogs[d_id].d_options[o]
end
-- in edit mode: has another dialog been selected?
-- if nothing better can be found: keep the old dialog
local show_dialog = d_id
-- an option button was selected;
-- since we do not execute actions and effects in edit mode, we need to find out the
-- right target dialog manually (and assume all went correct)
if( o ~= "" ) then
-- find out the normal target dialog of this option
if(selected_option and selected_option.o_results) then
for k, v in pairs(selected_option.o_results) do
if(v and v.r_type == "dialog") then
show_dialog = v.r_value
end
end
end
-- dropdown menu was used; provided the dialog exists (and it's not the "New dialog" option)
-- (if a new dialog was added using the "+" button, fields.d_id gets set accordingly)
elseif(fields.d_id and fields.d_id ~= show_dialog and dialog.n_dialogs[fields.d_id]) then
show_dialog = fields.d_id
-- in edit mode: prev_dialog_../next_dialog_.. was selected
else
for k,v in pairs(dialog.n_dialogs) do
if(fields["prev_dialog_"..k]) then
show_dialog = k
elseif(fields["next_dialog_"..k]) then
show_dialog = k
end
end
end
yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = show_dialog})
-- no option was selected - so we need to end this here
return
end
-- in edit mode, *all* options are displayed
local old_calculate_displayable_options = yl_speak_up.calculate_displayable_options
yl_speak_up.calculate_displayable_options = function(pname, d_options, allow_recursion)
-- no options - nothing to do
if(not(d_options)) then
return {}
end
if(yl_speak_up.in_edit_mode(pname)) then
-- in edit mode: show all options (but sort them first)
local retval = {}
local sorted_list = yl_speak_up.get_sorted_options(d_options, "o_sort")
for i, o_k in ipairs(sorted_list) do
retval[o_k] = true
end
return retval
end
-- outside edit mode: really calculate what can be displayed
return old_calculate_displayable_options(pname, d_options, allow_recursion)
end
-- in edit mode, autoanswer, random dialogs and d_got_item play no role and are *not* applied
-- (we want to see and edit all options regardless of preconditions)
local old_apply_autoanswer_etc = yl_speak_up.apply_autoanswer_and_random_and_d_got_item
yl_speak_up.apply_autoanswer_and_random_and_d_got_item = function(player, pname, d_id, dialog, allowed, active_dialog, recursion_depth)
-- no automatic switching in edit_mode
if(yl_speak_up.in_edit_mode(pname)) then
return
end
return old_apply_autoanswer_etc(player, pname, d_id, dialog, allowed, active_dialog, recursion_depth)
end
-- helper function for yl_speak_up.get_fs_talkdialog:
-- shows the text the NPC "speaks" and adds edit and navigation buttons
-- (all only in *edit_mode*)
local old_talkdialog_main_text = yl_speak_up.get_fs_talkdialog_main_text
yl_speak_up.get_fs_talkdialog_main_text = function(pname, formspec, h, dialog, dialog_list, c_d_id, active_dialog, alternate_text)
if(not(yl_speak_up.in_edit_mode(pname))) then
return old_talkdialog_main_text(pname, formspec, h, dialog, dialog_list, c_d_id, active_dialog, alternate_text)
end
local d_id_to_dropdown_index = {}
-- allow to change skin, wielded items etc.
table.insert(formspec, "button[15.75,3.5;3.5,0.9;edit_skin;Edit Skin]")
if(not(dialog) or not(dialog.n_dialogs)) then
return {h = h, formspec = formspec, d_id_to_dropdown_index = {}, dialog_list = dialog_list}
end
-- display the window with the text the NPC is saying
-- sort all dialogs by d_sort
local sorted_list = yl_speak_up.get_sorted_options(dialog.n_dialogs, "d_sort")
-- add buttons for previous/next dialog
for i, d in ipairs(sorted_list) do
-- build the list of available dialogs for the dropdown list(s)
dialog_list = dialog_list..","..minetest.formspec_escape(d)
if(d == c_d_id) then
local prev_dialog = tostring(minetest.formspec_escape(sorted_list[i-1]))
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", "8.5,4.0;2,0.9", "prev_dialog_"..prev_dialog,
"<",
"Go to previous dialog "..prev_dialog..".",
(sorted_list[ i-1 ]))
local next_dialog = tostring(minetest.formspec_escape(sorted_list[i+1]))
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", "11,4.0;2,0.9", "next_dialog_"..next_dialog,
">",
"Go to next dialog "..next_dialog..".",
(sorted_list[ i+1 ]))
end
d_id_to_dropdown_index[d] = i + 1
end
dialog_list = dialog_list..",d_end"
d_id_to_dropdown_index["d_end"] = #sorted_list + 2
table.insert(formspec, "label[0.2,4.6;Dialog:]") -- "..minetest.formspec_escape(c_d_id)..":]")
table.insert(formspec, "dropdown[3.0,4.0;5,1;d_id;"..dialog_list..";"..
(d_id_to_dropdown_index[c_d_id] or "1")..",]")
table.insert(formspec, "tooltip[3.0,4.0;5,1;"..
"Select the dialog you want to edit. Currently, dialog "..c_d_id..
" is beeing displayed.;#FFFFFF;#000000]")
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", "13.9,4.0;1,0.9", "show_new_dialog",
"+",
"Create a new dialog.",
true)
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", "11.0,0.3;2,1.0", "button_edit_notes",
"Notes",
"Keep notes of what this NPC is for, how his character is etc.",
true)
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", "13.2,0.3;2,0.9", "button_edit_name_and_description",
"Edit",
"Edit name and description of your NPC.",
true)
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", "15.4,0.3;2,0.9", "button_save_dialog",
"Save",
"Save this dialog.",
true)
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", "17.5,0.3;2.4,0.9", "button_export_dialog",
"Export",
"Export: Show the dialog in .json format which you can copy and store on your computer.",
true)
-- static help text instead of text input field for d_got_item
if(c_d_id == "d_got_item") then
table.insert(formspec, "hypertext[0.2,5;19.6,17.8;d_text;"..
"<normal>Note:\nThis is a special dialog. "..
"It will be called when the player clicks on "..
"<b>I want to give you something</b>."..
"\nMost of the things listed below will be added automaticly when you add a "..
"new option to this dialog. In most cases you may just have to edit the "..
"<b>precondition</b> so that the <i>right item</i> is accepted, and then "..
"set the <b>target dialog</b> <i>according to your needs</i>. Please also "..
"edit the <b>alternate text</b> so that it fits your <i>item</i>!"..
"\nThis is how it works in detail:"..
"\n<b>Each option</b> you add here ought to deal with one item(stack) that "..
"the NPC expects from the player, i.e. <i>farming:bread 2</i>. "..
"Each option needs to be selected <b>automaticly</b> and ought to contain:"..
"\n* a <b>precondition</b> regarding "..
"<b>an item the player offered/gave to the NPC</b> "..
"(shown as <b>player_offered_item</b> in overview) "..
"where you define which item(stack) is relevant for this option"..
"\n* an <b>effect</b> regarding <b>an item the player offered to the NPC</b> "..
"(shown as <b>deal_with_offered_item</b> in overview) "..
"where you define what shall happen to the offered item. Usually "..
"the NPC will accept the item and put it into its inventory."..
"\n* Don't forget to set a suitable target dialog for the <b>effect</b>! "..
"Your NPC ought to comment on what he got, i.e. "..
"<i>Thank you for those two breads! You saved me from starving.</i>"..
"You can also work with an alternate text here (as is done in the "..
"default setup when adding a new option here)."..
"\n</normal>]")
-- static help text instead of text input field for d_trade
elseif(c_d_id == "d_trade") then
table.insert(formspec, "hypertext[0.2,5;19.6,17.8;d_text;"..
"<normal>Note:\nThis is a special dialog. "..
"It will be called when the player clicks on "..
"<b>Let's trade!</b>."..
"\nSome of the things listed below will be added automaticly when you add a "..
"new option to this dialog. In most cases you may just have to edit the "..
"<b>precondition</b> so that the <i>right item(stack)</i> is beeing "..
"searched for, and you need to add suitable effects. The ones added "..
"automaticly are just an example."..
"\nNote that once the NPC found a matching precondition, it will execute the "..
"relevant effects and present the player the trade list. Any further options "..
"that might also fit will not be executed this time. Only <b>one</b> option "..
"(or none) will be selected each time."..
"\nThis is how it works in detail:"..
"\n<b>Each option</b> you add here ought to deal with one item(stack) that "..
"the NPC might or might not have in its inventory, "..
"i.e. <i>default:stick 4</i>. "..
"Each option needs to be selected <b>automaticly</b> and ought to contain:"..
"\n* at least one <b>precondition</b> regarding "..
"<b>the inventory of the NPC</b> "..
"where you define which item(stack) is relevant for this option "..
"(you can add multiple such preconditions for each option)"..
"\n* at least one <b>effect</b> regarding what the NPC shall do if the "..
"precondition matches. In most cases, <b>NPC crafts something</b>, "..
"<b>put item from the NPC's inventory into a chest etc.</b> or "..
"<b>take item from a chest etc. and put it into the NPC's inventory</b> "..
"will be what you are looking for. More than one effect is possible."..
"\n* In this particular case, no target dialog needs to be selected. After "..
"executing the effect(s), the trade list view will be shown to the "..
"player."..
"\n</normal>]")
elseif(c_d_id == "d_dynamic") then
table.insert(formspec, "hypertext[0.2,5;19.6,17.8;d_text;"..
"<normal>Note:\nThis is a special dialog. "..
"Each time right before this special dialog is displayed, a "..
"function is called that can fill the <b>d_dynamic</b> dialog "..
"with text and options."..
"\nThat function has to decide <b>based on NPC, player and context</b> what "..
"it wants to display this time."..
"\nThe d_dynamic dialog is <b>never saved</b> as part of the dialog. "..
"It has to be dynamicly created by your function each time it is needed."..
"\nThe d_dynamic dialog will always be available as a <b>legitimate target "..
"dialog</b> of a dialog option. Its options can do all that options of "..
"other dialogs can do. Its options they can lead back to normal static "..
"parts of the dialog."..
"\n</normal>]")
elseif(active_dialog and active_dialog.d_text) then
table.insert(formspec, "textarea[0.2,5;19.6,17.8;d_text;;"..
minetest.formspec_escape(active_dialog.d_text or "?")..
"]")
else
table.insert(formspec, "textarea[0.2,5;19.6,17.8;d_text;;"..
minetest.formspec_escape("[no text]")..
"]")
end
return {h = h, formspec = formspec, d_id_to_dropdown_index = d_id_to_dropdown_index,
dialog_list = dialog_list}
end
-- helper function for yl_speak_up.get_fs_talkdialog:
-- prints one entry (option/answer) in normal and *edit_mode*
local old_talkdialog_line = yl_speak_up.get_fs_talkdialog_line
yl_speak_up.get_fs_talkdialog_line = function(
formspec, h, pname_for_old_fs, oid, sb_v,
dialog, allowed, pname,
-- these additional parameters are needed *here*, in edit_mode:
active_dialog, dialog_list, d_id_to_dropdown_index,
current_index, anz_options)
if(not(yl_speak_up.in_edit_mode(pname))) then
-- in normal mode:
return old_talkdialog_line(formspec, h, pname_for_old_fs, oid, sb_v,
dialog, allowed, pname,
active_dialog, dialog_list, d_id_to_dropdown_index,
current_index, anz_options)
end
-- in edit mode:
local offset = 0.0
local field_length = 43.8
if(pname_for_old_fs) then
offset = 0.7
field_length = 41.8
end
h = h + 1
-- add a button "o_<nr>:" that leads to an edit formspec for this option
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", tostring(2.9+offset).."," .. h .. ";2,0.9", "edit_option_" .. oid,
oid,
"Edit target dialog, pre(C)onditions and (Ef)fects for option "..oid..".",
true)
-- find the right target dialog for this option (if it exists):
local target_dialog = nil
local results = active_dialog.d_options[sb_v.o_id].o_results
-- has this option more results/effects than just switching to another dialog?
local has_other_results = false
if(results ~= nil) then
for k, v in pairs(results) do
if v.r_type == "dialog"
and (dialog.n_dialogs[v.r_value] ~= nil
or v.r_value == "d_end"
or v.r_value == "d_trade"
or v.r_value == "d_got_item") then
-- there may be more than one in the data structure
target_dialog = v.r_value
elseif v.r_type ~= "dialog" then
has_other_results = true
end
end
end
-- add a button "-> d_<nr>" that leads to the target dialog (if one is set)
-- selecting an option this way MUST NOT execute the pre(C)onditions or (Ef)fects!
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", tostring(9.6+offset)..","..h..";1,0.9", "button_" .. oid,
"->",
"Go to target dialog "..minetest.formspec_escape(target_dialog or "")..
" that will be shown when this option ("..oid..") is selected.",
(target_dialog))
-- allow to set a new target dialog
table.insert(formspec, "dropdown["..tostring(5.0+offset)..","..h..";4.7,1;d_id_"..
oid..";"..
dialog_list..";"..
(d_id_to_dropdown_index[(target_dialog or "?")] or "0")..",]")
-- add a tooltip "Change target dialog"
table.insert(formspec, "tooltip[5.0,"..h..";4.7,1;"..
"Change target dialog for option "..oid..".;#FFFFFF;#000000]")
-- are there any prerequirements?
local prereq = active_dialog.d_options[sb_v.o_id].o_prerequisites
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", tostring(0.5+offset)..","..h..";0.5,0.9", "conditions_"..oid,
"C",
"There are pre(C)onditions required for showing this option. Display them.",
(prereq and next(prereq)))
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", tostring(1.6+offset)..","..h..";0.6,0.9", "effects_"..oid,
"Ef",
"There are further (Ef)fects (apart from switching\n"..
"to a new dialog) set for this option. Display them.",
(has_other_results))
local d_option = active_dialog.d_options[sb_v.o_id]
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", tostring(2.25+offset)..","..h..";0.6,0.9", "quests_"..oid,
"Q",
"This option sets a (Q)est step if possible.\n"..
"A special precondition is evaluated automaticly\n"..
"to check if the quest step can be set.",
(d_option and d_option.quest_id and d_option.quest_step))
-- are there any actions defined?
local actions = active_dialog.d_options[sb_v.o_id].actions
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", tostring(1.05+offset)..","..h..";0.5,0.9", "actions_"..oid,
"A",
"There is an (A)ction (i.e. a trade) that will happen\n"..
"when switching to a new dialog. Display actions and\n"..
"trade of this option.",
(actions and next(actions)))
if(sb_v.o_autoanswer) then
table.insert(formspec,
"label["..tostring(10.5+offset+0.2)..","..tostring(h+0.5)..";"..
minetest.formspec_escape("[Automaticly selected if preconditions are met] "..
tostring(sb_v.o_text_when_prerequisites_met))..
"]")
elseif(active_dialog.o_random) then
table.insert(formspec,
"label["..tostring(10.5+offset+0.2)..","..tostring(h+0.5)..";"..
minetest.formspec_escape("[One of these options is randomly selected] "..
tostring(sb_v.o_text_when_prerequisites_met))..
"]")
else
-- show the actual text for the option
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"field", tostring(10.5+offset)..","..h..";"..
tostring(field_length-2.3)..",0.9",
"text_option_" .. oid,
";"..minetest.formspec_escape(sb_v.o_text_when_prerequisites_met),
"Edit the text that is displayed on button "..oid..".",
true)
end
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
"button", tostring(10.5+offset+field_length-2.2)..","..h..";1.0,0.9", "delete_option_"..oid,
"Del",
"Delete this option/answer.",
true)
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
-- "image_button", tostring(9.9+offset+field_length-0.5)..","..h..";0.5,0.9"..
-- ";gui_furnace_arrow_bg.png^[transformR180",
"button", tostring(10.5+offset+field_length-1.1)..","..h..";0.5,0.9",
"option_move_down_"..oid,
"v",
"Move this option/answer one down.",
(current_index < anz_options))
yl_speak_up.add_formspec_element_with_tooltip_if(formspec,
-- "image_button", tostring(9.9+offset+field_length-1.0)..","..h..";0.5,0.9"..
-- ";gui_furnace_arrow_bg.png",
"button", tostring(10.5+offset+field_length-0.5)..","..h..";0.5,0.9",
"option_move_up_"..oid,
"^",
"Move this option/answer one up.",
(current_index > 1))
return {h = h, formspec = formspec}
end
-- add a prefix to "I want to give you something." dialog option in edit_mode:
local old_talkdialog_offers_item = yl_speak_up.get_fs_talkdialog_add_player_offers_item
yl_speak_up.get_fs_talkdialog_add_player_offers_item = function(pname, formspec, h, dialog, add_text, pname_for_old_fs)
local offer_item_add_text = nil
if(yl_speak_up.in_edit_mode(pname)) then
-- force showing the "I want to give you something"-text
offer_item_add_text = minetest.formspec_escape("[dialog d_got_item] -> ")
end
return old_talkdialog_offers_item(pname, formspec, h, dialog, offer_item_add_text, pname_for_old_fs)
end
-- helper function for yl_speak_up.get_fs_talkdialog:
-- if the player can edit the NPC,
-- either add a button for entering edit mode
-- or add the buttons needed to edit the dialog when in *edit mode*
local old_talkdialog_add_edit_and_command_buttons = yl_speak_up.get_fs_talkdialog_add_edit_and_command_buttons
yl_speak_up.get_fs_talkdialog_add_edit_and_command_buttons = function(
pname, formspec, h, pname_for_old_fs, is_a_start_dialog,
active_dialog, luaentity, may_edit_npc, anz_options)
-- add the buttons that are added to all editable NPC *first*:
-- inventory access, commands for mobs_npc, custom commands
local res = old_talkdialog_add_edit_and_command_buttons(
pname, formspec, h, pname_for_old_fs, is_a_start_dialog,
active_dialog, luaentity, may_edit_npc, anz_options)
formspec = res.formspec
h = res.h
-- if the player cannot *enter* edit_mode:
if(not(may_edit_npc)) then
return res
end
local edit_mode = yl_speak_up.in_edit_mode(pname)
-- button "show log" for those who can edit the NPC (entering edit mode is not required)
local text = minetest.formspec_escape(
"[Log] Show me your log.")
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"show_log",
text, text,
true, nil, nil, pname_for_old_fs)
-- Offer to enter edit mode if the player has the npc_talk_owner priv OR is allowed to edit the NPC.
-- The npc_talk_master priv allows to edit all NPC.
if(not(edit_mode)) then
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"button_start_edit_mode",
"Enters edit mode. In this mode, you can edit the texts the NPC says and the "..
"answers that can be given.",
-- chat option: "I am your owner. I have new orders for you.
"I am your owner. I have new orders for you.",
true, nil, true, pname_for_old_fs) -- is button_exit
return {h = h, formspec = formspec}
end
local offset = 0.0
-- If in edit mode, add new menu entries: "add new options", "end edit mode" and what else is needed.
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"add_option",
-- chat option: "Add a new answer/option to this dialog."
"Adds a new option to this dialog. You can delete options via the option edit menu.",
"Add a new option/answer to this dialog. You can delete options via the option "..
"edit menu.",
-- the amount of allowed options/answers has been reached
(anz_options < yl_speak_up.max_number_of_options_per_dialog),
"Maximum number of allowed answers/options reached. No further options/answers "..
"can be added.", nil, pname_for_old_fs)
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"delete_this_empty_dialog",
-- chat option: "Delete this dialog."
"Dialogs can only be deleted when they are empty and have no more "..
"options/answers. This is the case here, so the dialog can be deleted.",
"Delete this empty dialog.",
(active_dialog and active_dialog.d_text == "" and anz_options == 0),
-- (but only show this option if the dialog is empty)
"If you want to delete this dialog, you need to delete all options and its "..
"text first.", nil, pname_for_old_fs)
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"show_what_points_to_this_dialog",
-- chat option: "Show what points to this dialog."
"Show which other dialog options or failed actions\n"..
"or effects lead the player to this dialog here.",
"Show what points to this dialog.",
-- there is no alternate text to show
true, nil, nil, pname_for_old_fs)
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"make_first_option",
-- chat option: "Make this dialog the first one shown when starting to talk."
"The NPC has to start with one dialog when he is right-clicked. "..
"Make this dialog the one shown.",
"Make this dialog the first one shown when starting a conversation.",
(active_dialog and active_dialog.d_sort and tonumber(active_dialog.d_sort) ~= 0),
-- (but only show this option if it's not already the first one)
"This dialog will be shown whenever a conversation is started.", nil,pname_for_old_fs)
local b_text = "Turn this into"
if(is_a_start_dialog) then
b_text = "This shall no longer be"
end
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"turn_into_a_start_dialog",
"With automatic selection of options, it is possible that the real\n"..
"start dialog will never be shown to the player. However, we need\n"..
"to add some buttons to that start dialog for i.e. giving items\n"..
"to the NPC and for trading. Therefore, dialogs can be marked as\n"..
"*a* start dialog so that these buttons will be added to those dialogs.",
b_text.." *a* start dialog where buttons for trade etc. are shown.",
not(active_dialog and active_dialog.d_sort and tonumber(active_dialog.d_sort) == 0),
"The start dialog automaticly counts as *a* start dialog where buttons for "..
"trade etc. are shown.", nil, pname_for_old_fs)
-- chat option: Mute/Unmute NPC
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"mute_npc",
-- chat option: mute the NPC
"The NPC will no longer show his dialogs when he is right-clicked. This is "..
"useful while you edit the NPC and don't want players to see "..
"unfinished entries and/or quests.",
"State: Not muted. Stop talking to other players while I give you new orders.",
(luaentity and luaentity.yl_speak_up.talk), nil, nil, pname_for_old_fs)
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"un_mute_npc",
-- unmute the NPC
"The NPC will show his dialogs to other players when he is right-clicked. "..
"This is the normal mode of operation. Choose this when you are "..
"finished editing.",
"State: You are currently muted. Talk to anyone again who wants to talk to you.",
-- the NPC has to be there
(luaentity and not(luaentity.yl_speak_up.talk)), nil, nil, pname_for_old_fs)
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"button_end_edit_mode",
"Ends edit mode. From now on, your NPC will talk to you like he talks to other "..
"players. You can always give him new orders by entering edit mode again.",
-- chat option:"That was all. I'm finished with giving you new orders. Remember them!"
"That was all. I'm finished with giving you new orders. Remember them!",
true, nil, true, pname_for_old_fs) -- is button_exit
return {h = h, formspec = formspec}
end
-- apply force_edit_mode if necessary
local old_get_fs_talkdialog = yl_speak_up.get_fs_talkdialog
yl_speak_up.get_fs_talkdialog = function(player, n_id, d_id, alternate_text, recursion_depth)
if(not(player)) then
return
end
local pname = player:get_player_name()
-- are we in force edit mode, and can the player edit this NPC?
if(yl_speak_up.force_edit_mode[pname]
-- not already in edit mode?
and (not(yl_speak_up.edit_mode[pname]) or yl_speak_up.edit_mode[pname] ~= n_id)
and yl_speak_up.may_edit_npc(player, n_id)) then
yl_speak_up.edit_mode[pname] = n_id
end
return old_get_fs_talkdialog(player, n_id, d_id, alternate_text, recursion_depth)
end
--[[
yl_speak_up.get_fs_talk_wrapper = function(player, param)
if(not(param)) then
param = {}
end
-- recursion depth from autoanswer: 0 (the player selected manually)
return yl_speak_up.get_fs_talkdialog(player, param.n_id, param.d_id, param.alternate_text,0)
end
--]]
yl_speak_up.register_fs("talk",
-- this function is changed here:
yl_speak_up.input_talk,
-- the underlying function is changed as well - but the wrapper calls that already; so ok:
yl_speak_up.get_fs_talk_wrapper,
-- no special formspec required:
nil
)