mirror of
https://gitea.your-land.de/Sokomine/yl_speak_up.git
synced 2025-06-16 05:38:06 +02:00
636 lines
23 KiB
Lua
636 lines
23 KiB
Lua
-- This is the main talkdialog the NPC shows when right-clicked.
|
|
-- Returns o (selected dialog option) if fields.just_return_selected_option
|
|
-- is set (useful for edit_mode).
|
|
yl_speak_up.input_talk = function(player, formname, fields)
|
|
if formname ~= "yl_speak_up:talk" then
|
|
return
|
|
end
|
|
|
|
local pname = player:get_player_name()
|
|
|
|
-- error: not talking?
|
|
if(not(yl_speak_up.speak_to[pname])) 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 dialog = yl_speak_up.speak_to[pname].dialog
|
|
|
|
-- the NPC needs to be configured first; route input to the configuration dialog
|
|
if(not(dialog)
|
|
or not(dialog.n_npc)
|
|
or not(d_id)) then
|
|
yl_speak_up.input_fs_initial_config(player, formname, fields)
|
|
return
|
|
end
|
|
|
|
if(fields.show_log) then
|
|
-- show a log
|
|
yl_speak_up.show_fs(player, "show_log", {log_type = "full"})
|
|
return
|
|
end
|
|
|
|
-- mobs_redo based NPC may follow their owner, stand or wander around
|
|
local new_move_order = ""
|
|
if(fields.order_stand) then
|
|
new_move_order = "stand"
|
|
elseif(fields.order_follow) then
|
|
new_move_order = "follow"
|
|
elseif(fields.order_wander) then
|
|
new_move_order = "wander"
|
|
end
|
|
if(new_move_order ~= "") then
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
yl_speak_up.set_npc_property(pname, "self.order", new_move_order, "move_order")
|
|
minetest.chat_send_player(pname,
|
|
tostring(dialog.n_npc or "NPC").." tells you: "..
|
|
"Ok. I will "..tostring(new_move_order)..".")
|
|
yl_speak_up.stop_talking(pname)
|
|
return
|
|
end
|
|
|
|
-- useful for i.e. picking up the mob
|
|
if(fields.order_custom) then
|
|
local obj = yl_speak_up.speak_to[pname].obj
|
|
-- some precautions - someone else might have eliminated the NPC in the meantime
|
|
local luaentity = nil
|
|
if(obj) then
|
|
luaentity = obj:get_luaentity()
|
|
end
|
|
if(luaentity and luaentity.name and yl_speak_up.add_on_rightclick_entry[luaentity.name]) then
|
|
local m = yl_speak_up.add_on_rightclick_entry[luaentity.name]
|
|
local ret = m.execute_function(luaentity, player)
|
|
end
|
|
yl_speak_up.stop_talking(pname)
|
|
return
|
|
end
|
|
|
|
-- normal mode + edit_mode (not exclusive to edit_mode):
|
|
if fields.quit or fields.button_exit then
|
|
-- if there are any changes done: ask first and don't quit yet
|
|
yl_speak_up.show_fs(player, "quit", nil)
|
|
return
|
|
end
|
|
|
|
-- allow the player to take the item back
|
|
if(fields.show_player_offers_item and fields.show_player_offers_item ~= "") then
|
|
yl_speak_up.show_fs(player, "player_offers_item", nil)
|
|
return
|
|
end
|
|
|
|
-- the player wants to give something to the NPC
|
|
-- (less complex outside edit mode)
|
|
if(fields.player_offers_item) then
|
|
-- normal mode: take the item the player wants to offer
|
|
yl_speak_up.show_fs(player, "player_offers_item", nil)
|
|
return
|
|
end
|
|
|
|
-- the player wants to access the inventory of the NPC
|
|
if(fields.show_inventory and yl_speak_up.may_edit_npc(player, n_id)) then
|
|
-- the inventory is just an inventory with a back button; come back to this dialog here
|
|
yl_speak_up.show_fs(player, "inventory")
|
|
return
|
|
end
|
|
|
|
-- the player wants to see the trade list
|
|
if(fields.show_trade_list) then
|
|
yl_speak_up.show_fs(player, "trade_list", nil)
|
|
return
|
|
end
|
|
|
|
-- allow some basic editing (name, description, owner) even without editor mod installed:
|
|
if(fields.button_edit_basics) then
|
|
yl_speak_up.show_fs(player, "initial_config",
|
|
{n_id = n_id, d_id = d_id, false})
|
|
return
|
|
end
|
|
|
|
|
|
if fields.button_up then
|
|
yl_speak_up.speak_to[pname].option_index =
|
|
yl_speak_up.speak_to[pname].option_index + yl_speak_up.max_number_of_buttons
|
|
yl_speak_up.show_fs(player, "talk", {n_id = yl_speak_up.speak_to[pname].n_id,
|
|
d_id = yl_speak_up.speak_to[pname].d_id})
|
|
return
|
|
elseif fields.button_down then --and yl_speak_up.speak_to[pname].option_index > yl_speak_up.max_number_of_buttons then
|
|
yl_speak_up.speak_to[pname].option_index =
|
|
yl_speak_up.speak_to[pname].option_index - yl_speak_up.max_number_of_buttons
|
|
if yl_speak_up.speak_to[pname].option_index < 0 then
|
|
yl_speak_up.speak_to[pname].option_index = 1
|
|
end
|
|
yl_speak_up.show_fs(player, "talk", {n_id = yl_speak_up.speak_to[pname].n_id,
|
|
d_id = yl_speak_up.speak_to[pname].d_id})
|
|
return
|
|
else
|
|
yl_speak_up.speak_to[pname].option_index = 1
|
|
end
|
|
|
|
|
|
-- has an option/answer been selected?
|
|
local o = ""
|
|
for k, v in pairs(fields) do
|
|
-- only split into 2 parts at max
|
|
local s = string.split(k, "_", false, 2)
|
|
|
|
if(s[1] == "button"
|
|
and s[2] ~= nil and s[2] ~= "" and s[2] ~= "exit" and s[2] ~= "back" and s[3] ~= nil
|
|
and s[2] ~= "up" and s[2] ~= "down") then
|
|
o = s[2] .. "_" .. s[3]
|
|
end
|
|
end
|
|
-- this is for edit mode - we need a diffrent reaction there, not executing actions
|
|
if(fields.just_return_selected_option) then
|
|
return o
|
|
end
|
|
-- nothing selected
|
|
if(o == "") then
|
|
return
|
|
end
|
|
|
|
-- Let's check if the button was among the "allowed buttons". Only those may be executed
|
|
if(not(yl_speak_up.speak_to[pname].allowed) or not(yl_speak_up.speak_to[pname].allowed[o])) then
|
|
return
|
|
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
|
|
|
|
-- abort if the option does not exist
|
|
if(not(selected_option)) then
|
|
return
|
|
end
|
|
yl_speak_up.speak_to[pname].o_id = o
|
|
-- store this a bit longer than o_id above (for yl_speak_up.generate_next_dynamic_dialog):
|
|
yl_speak_up.speak_to[pname].selected_o_id = o
|
|
-- start with executing the first action
|
|
yl_speak_up.execute_next_action(player, nil, true, formname)
|
|
return
|
|
end
|
|
|
|
|
|
-- helper function for yl_speak_up.get_fs_talkdialog:
|
|
-- shows the text the NPC "speaks"
|
|
-- (this is pretty boring; the more intresting stuff happens in edit_mode)
|
|
yl_speak_up.get_fs_talkdialog_main_text = function(pname, formspec, h, dialog, dialog_list, c_d_id, active_dialog, alternate_text)
|
|
local fs_version = yl_speak_up.fs_version[pname]
|
|
formspec = yl_speak_up.show_fs_npc_text(pname, formspec, dialog, alternate_text, active_dialog, fs_version)
|
|
return {h = h, formspec = formspec, 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 mode - not in edit_mode
|
|
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 in edit_mode and not used here
|
|
active_dialog, dialog_list, d_id_to_dropdown_index,
|
|
current_index, anz_options)
|
|
|
|
local t = "- no text given -"
|
|
local t_alt = nil
|
|
-- the preconditions are fulfilled; showe the option
|
|
if(allowed[sb_v.o_id] == true) then
|
|
-- replace $NPC_NAME$ etc.
|
|
t = minetest.formspec_escape(yl_speak_up.replace_vars_in_text(
|
|
sb_v.o_text_when_prerequisites_met, dialog, pname))
|
|
-- precondition not fulfilled? the option shall be hidden
|
|
elseif(sb_v.o_hide_when_prerequisites_not_met == "true") then
|
|
-- show nothing; t_alt remains nil
|
|
t = nil
|
|
-- precondition not fulfilled, and autoanswer active? Then hide this option.
|
|
elseif(sb_v.o_autoanswer) then
|
|
-- show nothing; t_alt remains nil
|
|
t = nil
|
|
-- precondition not fulfilled? the option shall be greyed out
|
|
-- default to greyed out (this option cannot be selected)
|
|
elseif(sb_v.o_grey_when_prerequisites_not_met == "true") then
|
|
local text = sb_v.o_text_when_prerequisites_not_met
|
|
if(not(text) or text == "") then
|
|
text = t or yl_speak_up.message_button_option_prerequisites_not_met_default
|
|
end
|
|
t = nil
|
|
-- replace $NPC_NAME$ etc.
|
|
t_alt = minetest.formspec_escape(yl_speak_up.replace_vars_in_text(
|
|
text, dialog, pname))
|
|
elseif(sb_v.o_grey_when_prerequisites_not_met == "false"
|
|
and sb_v.o_text_when_prerequisites_not_met ~= "") then
|
|
-- show in normal coor
|
|
t = minetest.formspec_escape(yl_speak_up.replace_vars_in_text(
|
|
sb_v.o_text_when_prerequisites_not_met, dialog, pname))
|
|
end
|
|
if(t or t_alt) then
|
|
-- some options can be visited only once; talking to the NPC anew resets that
|
|
-- (not stored persistently)
|
|
if(t and sb_v.visits and sb_v.visits > 0
|
|
and sb_v.o_visit_only_once and sb_v.o_visit_only_once == 1) then
|
|
t_alt = minetest.formspec_escape("[Done] ")..t
|
|
t = nil
|
|
end
|
|
-- actually show the button
|
|
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"button_" .. oid,
|
|
t,
|
|
t,
|
|
(t and not(t_alt)),
|
|
t_alt,
|
|
nil, pname_for_old_fs)
|
|
end
|
|
return {h = h, formspec = formspec}
|
|
end
|
|
|
|
|
|
-- at least allow editing name, description and owner - even without the editor mod installed
|
|
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)
|
|
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"button_edit_basics",
|
|
"Edit name, description and owner of your NPC.\n"..
|
|
"For more editing, install npc_talk_edit!",
|
|
-- chat option: "[Edit name, description and owner.]"
|
|
minetest.formspec_escape("[Edit name, description and owner.]"),
|
|
true, nil, false, pname_for_old_fs) -- *not* an exit button
|
|
return {h = h, formspec = formspec}
|
|
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*
|
|
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)
|
|
-- outside edit mode: nothing to add here
|
|
if(not(may_edit_npc)) then
|
|
return {h = h, formspec = formspec}
|
|
end
|
|
|
|
if(is_a_start_dialog) then
|
|
-- show the "show your inventory"-button even when not in edit mode
|
|
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"show_inventory",
|
|
"Access and manage the inventory of the NPC. This is used for adding trade "..
|
|
"items, getting collected payments and managing quest items.",
|
|
"Show your inventory (only accessible to owner)!",
|
|
true, nil, nil, pname_for_old_fs)
|
|
end
|
|
|
|
-- mobs_redo based NPC can follow, stand or wander around
|
|
if(luaentity and luaentity.order and may_edit_npc
|
|
-- not all mobs need or support this feature
|
|
and table.indexof(yl_speak_up.emulate_orders_on_rightclick, luaentity.name) > -1) then
|
|
if(luaentity.order ~= "follow") then
|
|
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"order_follow",
|
|
"The NPC will follow you.",
|
|
"New order: Follow me!",
|
|
((luaentity.owner == pname) and (luaentity.order ~= "follow")),
|
|
"New order: Follow me. (Only available for owner).",
|
|
nil, pname_for_old_fs)
|
|
end
|
|
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"order_stand",
|
|
"The NPC will wait here.",
|
|
"New order: Stand here.",
|
|
(luaentity.order ~= "stand"), nil, nil, pname_for_old_fs)
|
|
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"order_wander",
|
|
"The NPC will wander around randomly.",
|
|
"New order: Wander around a bit on your own.",
|
|
(luaentity.order ~= "walking"), nil, nil, pname_for_old_fs)
|
|
end
|
|
|
|
-- some mobs may need additional things in on_rightclick (i.e. beeing picked up)
|
|
if(luaentity and may_edit_npc
|
|
and yl_speak_up.add_on_rightclick_entry[luaentity.name]) then
|
|
local m = yl_speak_up.add_on_rightclick_entry[luaentity.name]
|
|
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"order_custom",
|
|
minetest.formspec_escape(m.text_if_false),
|
|
minetest.formspec_escape(m.text_if_true),
|
|
(m.condition), nil, nil, pname_for_old_fs)
|
|
end
|
|
local res = yl_speak_up.get_fs_talkdialog_add_basic_edit(
|
|
pname, formspec, h, pname_for_old_fs, is_a_start_dialog,
|
|
active_dialog, luaentity, may_edit_npc, anz_options)
|
|
h = res.h
|
|
return {h = h, formspec = formspec}
|
|
end
|
|
|
|
|
|
-- apply autoanswer, random dialog switching and d_got_item if needed;
|
|
-- returns the new formspec if any automatic switching happened
|
|
-- (this will not be done if in edit_mode)
|
|
yl_speak_up.apply_autoanswer_and_random_and_d_got_item = function(player, pname, d_id, dialog, allowed, active_dialog, recursion_depth)
|
|
-- autoanswer or o_random may force to select a particular dialog
|
|
local go_to_next_dialog = nil
|
|
-- abort here if needed - the autoanswer/autoselection did choose an option for us alread
|
|
if(allowed and allowed["autoanswer"] and allowed["autoanswer"] ~= "") then
|
|
go_to_next_dialog = allowed["autoanswer"]
|
|
-- randomly select an answer
|
|
elseif(allowed and active_dialog.o_random
|
|
and (recursion_depth < yl_speak_up.max_allowed_recursion_depth)) then
|
|
local liste = {}
|
|
-- only allowed options can be randomly selected from
|
|
for o_id, v in pairs(allowed) do
|
|
if(v) then
|
|
table.insert(liste, o_id)
|
|
end
|
|
end
|
|
-- randomly select one of the possible dialogs
|
|
if(#liste > 0) then
|
|
go_to_next_dialog = liste[math.random(1, #liste)]
|
|
end
|
|
end
|
|
|
|
if(go_to_next_dialog and go_to_next_dialog ~= "") then
|
|
-- no actions shall be executed
|
|
local o_id = go_to_next_dialog
|
|
local effects = active_dialog.d_options[o_id].o_results
|
|
local d_option = active_dialog.d_options[o_id]
|
|
-- execute all effects/results
|
|
local res = yl_speak_up.execute_all_relevant_effects(player, effects, o_id, true, d_option)
|
|
local target_dialog = res.next_dialog
|
|
yl_speak_up.speak_to[pname].o_id = nil
|
|
yl_speak_up.speak_to[pname].a_id = nil
|
|
-- end the conversation?
|
|
if(target_dialog and target_dialog == "d_end") then
|
|
yl_speak_up.stop_talking(pname)
|
|
-- a formspec is expected here; provide one that has an exit button only
|
|
return "size[2,1]"..
|
|
"button_exit[0,0;1,1;Exit;exit]"
|
|
end
|
|
if(not(target_dialog)
|
|
or target_dialog == ""
|
|
or not(dialog.n_dialogs[target_dialog])) then
|
|
target_dialog = yl_speak_up.speak_to[pname].d_id
|
|
end
|
|
-- show the new target dialog and exit
|
|
-- the recursion_depth will be increased by one (we did autoselect here and need to
|
|
-- avoid infinite loops)
|
|
return yl_speak_up.get_fs_talkdialog(player,
|
|
yl_speak_up.speak_to[pname].n_id, target_dialog, res.alternate_text,
|
|
recursion_depth + 1)
|
|
end
|
|
|
|
-- is the player comming back from trying to offer something to the NPC?
|
|
-- And is the NPC trying to return the item?
|
|
if(d_id == "d_got_item") then
|
|
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
|
if(not(trade_inv:is_empty("npc_wants"))) then
|
|
return table.concat({"formspec_version[1]",
|
|
yl_speak_up.show_fs_simple_deco(8, 2.5),
|
|
"label[0.5,0.5;",
|
|
minetest.formspec_escape(dialog.n_npc or "- ? -"),
|
|
" does not seem to be intrested in that.\n"..
|
|
"Please take your item back and try something else.]"..
|
|
"button[3.5,1.5;1.5,1.0;show_player_offers_item;Ok]"
|
|
}, "")
|
|
end
|
|
end
|
|
-- no automatic switching happened
|
|
return nil
|
|
end
|
|
|
|
|
|
yl_speak_up.get_fs_talkdialog_add_player_offers_item = function(pname, formspec, h, dialog, add_text, pname_for_old_fs)
|
|
return yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"player_offers_item",
|
|
"If you want to give something (items) to this NPC\n"..
|
|
"- either because he requested it or as a present -\n"..
|
|
"click here. The NPC will return items he doesn't want.",
|
|
(add_text or "").."I want to give you something.",
|
|
-- show this in edit mode and when the NPC actually accepts items
|
|
(add_text or dialog.n_dialogs["d_got_item"]), nil, nil, pname_for_old_fs)
|
|
end
|
|
|
|
|
|
-- recursion_depth is increased each time autoanswer is automaticly selected
|
|
yl_speak_up.get_fs_talkdialog = function(player, n_id, d_id, alternate_text, recursion_depth)
|
|
local pname = player:get_player_name()
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
local context_d_id = yl_speak_up.speak_to[pname].d_id
|
|
local active_dialog
|
|
|
|
if(not(dialog)) then
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"unconfigured NPC beeing talked to at "..
|
|
minetest.pos_to_string(player:get_pos()), "action")
|
|
return yl_speak_up.get_error_message()
|
|
end
|
|
|
|
-- currently no trade running (we're editing options)
|
|
yl_speak_up.trade[pname] = nil
|
|
yl_speak_up.speak_to[pname].trade_id = nil
|
|
|
|
-- add a d_trade dialog if necessary
|
|
if(dialog and dialog.trades and dialog.n_dialogs and not(dialog.n_dialogs["d_trade"])) then
|
|
yl_speak_up.add_new_dialog(dialog, pname, "trade", "[no text]")
|
|
end
|
|
|
|
--[[ If we have an explicit call for a certain d_id, we grab it from parameters.
|
|
If not, we grab in from context.
|
|
When neither are present, we grab it from d_sort
|
|
]]--
|
|
|
|
local c_d_id
|
|
-- the generic start dialog contains only those options that are generic;
|
|
-- choose the right start dialog of the NPC
|
|
if(d_id ~= nil and d_id ~= "d_generic_start_dialog") then
|
|
active_dialog = dialog.n_dialogs[d_id]
|
|
c_d_id = d_id
|
|
elseif(d_id and d_id ~= "d_generic_start_dialog" and yl_speak_up.speak_to[pname].d_id ~= nil) then
|
|
c_d_id = yl_speak_up.speak_to[pname].d_id
|
|
active_dialog = dialog.n_dialogs[c_d_id]
|
|
-- do this only if the dialog is already configured/created_at:
|
|
elseif dialog.n_dialogs ~= nil and dialog.created_at then
|
|
-- Find the dialog with d_sort = 0
|
|
c_d_id = yl_speak_up.get_start_dialog_id(dialog)
|
|
if(c_d_id) then
|
|
active_dialog = dialog.n_dialogs[c_d_id]
|
|
end
|
|
else
|
|
-- it may be possible that this player can initialize this npc
|
|
yl_speak_up.log_change(pname, n_id,
|
|
"unconfigured NPC beeing talked to at "..
|
|
minetest.pos_to_string(player:get_pos()), "action")
|
|
-- this is the initial config
|
|
-- (input ends up at yl_speak_up.input_talk and needs to be rerouted)
|
|
return yl_speak_up.get_fs_initial_config(player, n_id, d_id, true)
|
|
end
|
|
|
|
if c_d_id == nil then return yl_speak_up.get_error_message() end
|
|
|
|
-- show the player a dynamic dialog text:
|
|
if(c_d_id == "d_dynamic") then
|
|
-- the dialog will be modified for this player only:
|
|
-- (pass on all the known parameters in case they're relevant):
|
|
yl_speak_up.generate_next_dynamic_dialog(player, n_id, d_id, alternate_text, recursion_depth)
|
|
-- just to make sure that the right dialog is loaded:
|
|
active_dialog = dialog.n_dialogs[c_d_id]
|
|
end
|
|
|
|
yl_speak_up.speak_to[pname].d_id = c_d_id
|
|
|
|
-- Now we have a dialog to display to the user
|
|
|
|
-- do not crash in case of error
|
|
if(not(active_dialog)) then
|
|
return "size[10,3]"..
|
|
"label[0.2,0.5;Ups! Something went wrong. No dialog found.\n"..
|
|
"Please talk to the NPC by right-clicking again.]"..
|
|
"button_exit[4.5,1.6;1,0.9;exit;Exit]"
|
|
end
|
|
|
|
-- how often has the player visted this dialog?
|
|
yl_speak_up.count_visits_to_dialog(pname)
|
|
|
|
-- evaluate the preconditions of each option and check if the option can be offered
|
|
local allowed = yl_speak_up.calculate_displayable_options(pname, active_dialog.d_options,
|
|
-- avoid loops by limiting max recoursion depths for autoanswers
|
|
(recursion_depth < yl_speak_up.max_allowed_recursion_depth))
|
|
|
|
|
|
-- apply autoanswer, random dialog switching and d_got_item if needed
|
|
local show_other_dialog_fs = yl_speak_up.apply_autoanswer_and_random_and_d_got_item(
|
|
player, pname, d_id, dialog, allowed, active_dialog, recursion_depth)
|
|
if(show_other_dialog_fs) then
|
|
return show_other_dialog_fs
|
|
end
|
|
|
|
|
|
yl_speak_up.speak_to[pname].allowed = allowed
|
|
|
|
|
|
local pname_for_old_fs = yl_speak_up.get_pname_for_old_fs(pname)
|
|
local fs_version = yl_speak_up.fs_version[pname]
|
|
local formspec = {}
|
|
local h
|
|
|
|
-- this is used to build a list of all available dialogs for a dropdown menu in edit mode
|
|
-- (only relevant in edit mode)
|
|
local dialog_list = yl_speak_up.text_new_dialog_id
|
|
-- allow to change skin, wielded items etc.
|
|
-- display the window with the text the NPC is saying (diffrent in *edit_mode*)
|
|
local res_edit_top = yl_speak_up.get_fs_talkdialog_main_text(
|
|
pname, formspec, h, dialog, dialog_list, c_d_id, active_dialog,
|
|
alternate_text)
|
|
-- we are finished with adding buttons and text etc. to the left side of the formspec
|
|
local left_window_fs = table.concat(res_edit_top.formspec, "")
|
|
dialog_list = res_edit_top.dialog_list
|
|
-- find the right index for the dialog_list dropdown above
|
|
local d_id_to_dropdown_index = res_edit_top.d_id_to_dropdown_index
|
|
|
|
-- empty formspec for the bottom part
|
|
formspec = {}
|
|
|
|
h = -0.8
|
|
|
|
-- allow to delete entries that have no options later on
|
|
local anz_options = 0
|
|
-- Let's sort the options by o_sort
|
|
if active_dialog ~= nil and active_dialog.d_options ~= nil then
|
|
local sorted_o_list = yl_speak_up.get_sorted_options(active_dialog.d_options, "o_sort")
|
|
for _, sb_v in ipairs(sorted_o_list) do
|
|
anz_options = anz_options + 1
|
|
end
|
|
|
|
for i, s_o_id in ipairs(sorted_o_list) do
|
|
local sb_v = active_dialog.d_options[s_o_id]
|
|
local oid = minetest.formspec_escape(sb_v.o_id)
|
|
local res = {}
|
|
-- normal mode: show an option if the prerequirements (if any are defined) are met
|
|
res = yl_speak_up.get_fs_talkdialog_line(
|
|
formspec, h, pname_for_old_fs, oid, sb_v,
|
|
dialog, allowed, pname,
|
|
-- these additional parameters are needed in edit_mode
|
|
active_dialog, dialog_list, d_id_to_dropdown_index, i, #sorted_o_list)
|
|
formspec = res.formspec
|
|
h = res.h
|
|
end
|
|
end
|
|
|
|
-- with automatic selection from the start dialog, it is possible that the
|
|
-- real start dialog is never shown; thus, add those buttons which need to
|
|
-- be shown just once to all dialogs with is_a_start_dialog set
|
|
local is_a_start_dialog = (active_dialog and active_dialog.d_sort
|
|
and (tonumber(active_dialog.d_sort) == 0
|
|
or active_dialog.is_a_start_dialog))
|
|
-- add a "I want to give you something" button to the first dialog if the NPC accepts items
|
|
if(is_a_start_dialog) then
|
|
h = yl_speak_up.get_fs_talkdialog_add_player_offers_item(pname, formspec, h,
|
|
dialog, nil, pname_for_old_fs)
|
|
end
|
|
|
|
|
|
-- add a Let's trade button to the first dialog if the NPC has trades
|
|
local has_trades = nil
|
|
if(is_a_start_dialog and dialog.trades) then
|
|
for k, v in pairs(dialog.trades) do
|
|
-- has the NPC any *public* trades that are not effects/results?
|
|
if(not(v.hide) and not(v.d_id)) then
|
|
has_trades = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if(has_trades) then
|
|
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
|
|
"show_trade_list",
|
|
"Show a list of trades the NPC has to offer.",
|
|
"Let's trade!",
|
|
(has_trades), nil, nil, pname_for_old_fs)
|
|
end
|
|
|
|
|
|
-- can the player edit this NPC?
|
|
local may_edit_npc = yl_speak_up.may_edit_npc(player, n_id)
|
|
-- for muting and for checking the owner/order, the luaentity is needed
|
|
local obj = yl_speak_up.speak_to[pname].obj
|
|
-- some precautions - someone else might have eliminated the NPC in the meantime
|
|
local luaentity = nil
|
|
if(obj) then
|
|
luaentity = obj:get_luaentity()
|
|
end
|
|
|
|
|
|
-- If in edit mode, add new menu entries: "add new options", "end edit mode" and what else is needed.
|
|
-- Else allow to enter edit mode
|
|
-- also covers commands for mobs_npc (walk, stand, follow), custom commands and inventory access
|
|
local res = yl_speak_up.get_fs_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
|
|
|
|
|
|
-- we are finished with adding buttons to the bottom of the formspec
|
|
local bottom_window_fs = table.concat(formspec, "\n")
|
|
|
|
return yl_speak_up.show_fs_decorated(pname, true, h, alternate_text,
|
|
left_window_fs, bottom_window_fs,
|
|
active_dialog, h)
|
|
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",
|
|
yl_speak_up.input_talk,
|
|
yl_speak_up.get_fs_talk_wrapper,
|
|
-- no special formspec required:
|
|
nil
|
|
)
|