mirror of
https://gitea.your-land.de/Sokomine/yl_speak_up.git
synced 2025-06-20 22:28:02 +02:00
1045 lines
42 KiB
Lua
1045 lines
42 KiB
Lua
|
|
-- store which player is monitoring the NPC (for preconditions and
|
|
-- effects)
|
|
yl_speak_up.debug_mode_set_by_player = {}
|
|
|
|
-- for sending debug information about preconditions and effects to
|
|
-- the player who is monitoring the NPC
|
|
-- (sometimes it is not easy/obvious to see why something failed)
|
|
yl_speak_up.debug_msg = function(player, n_id, o_id, text)
|
|
local dname = yl_speak_up.debug_mode_set_by_player[ n_id ]
|
|
-- nobody cares
|
|
if(not(dname)) then
|
|
return
|
|
end
|
|
local pname = player:get_player_name()
|
|
local d_id = yl_speak_up.speak_to[pname].d_id
|
|
minetest.chat_send_player(dname, "[NPC "..tostring(n_id)..": "..
|
|
tostring(pname).."] <"..tostring(d_id).." "..tostring(o_id)..
|
|
"> "..tostring(text))
|
|
end
|
|
|
|
|
|
-- a chat command for entering and leaving debug mode; needs to be a chat command
|
|
-- because the player may have wandered off from his NPC and get too many messages
|
|
-- without a quick way to get rid of them otherwise
|
|
minetest.register_chatcommand( 'npc_talk_debug', {
|
|
description = "Sets you as debugger for the yl_speak_up-NPC with the ID <n_id>.\n"..
|
|
" <list> lists the NPC you are currently debugging.\n"..
|
|
" <off> turns debug mode off again.",
|
|
privs = {npc_talk_owner},
|
|
func = function(pname, param)
|
|
if(param and param == "off") then
|
|
local count = 0
|
|
for k, v in pairs(yl_speak_up.debug_mode_set_by_player) do
|
|
if(v and v == pname) then
|
|
yl_speak_up.debug_mode_set_by_player[ k ] = nil
|
|
count = count + 1
|
|
minetest.chat_send_player(pname, "You are no longer "..
|
|
"debugging the NPC with the ID "..tostring(k)..".")
|
|
end
|
|
end
|
|
minetest.chat_send_player(pname, "Removed you as debugger of "..
|
|
tostring(count).." NPCs.")
|
|
return
|
|
elseif(not(param) or param == "" or param == "list") then
|
|
local count = 0
|
|
local text = "You are currently debugging the NPCs with the following IDs:\n"
|
|
for k, v in pairs(yl_speak_up.debug_mode_set_by_player) do
|
|
if(v and v == pname) then
|
|
count = count + 1
|
|
text = text.." "..tostring(k)
|
|
end
|
|
end
|
|
if(count == 0) then
|
|
text = text.." - none -"
|
|
else
|
|
text = text.."\nTo turn debugging off, call this command with the "..
|
|
"parameter <off>."
|
|
end
|
|
minetest.chat_send_player(pname, text)
|
|
return
|
|
elseif(not(yl_speak_up.may_edit_npc(minetest.get_player_by_name(pname), param))) then
|
|
minetest.chat_send_player(pname, "You do not have the necessary privs to "..
|
|
"edit that NPC.")
|
|
return
|
|
else
|
|
yl_speak_up.debug_mode_set_by_player[ param ] = pname
|
|
minetest.chat_send_player(pname, "You are now receiving debug information "..
|
|
"for NPC "..tostring(param)..".\nTo turn that off, type "..
|
|
"\"/npc_talk_debug off\".")
|
|
end
|
|
end
|
|
});
|
|
|
|
|
|
-- evaluate those preconditions of type "function" (set by the staff)
|
|
-- and execute those effects/results of type "function" (set by the staff)
|
|
-- WARNING: This is extremly powerful!
|
|
-- The code is taken out of the function
|
|
-- calculate_displayable_options(..)
|
|
-- (written by AliasAlreadyTaken).
|
|
-- It requires the npc_master priv to add or edit this prereq.
|
|
-- The function is called by
|
|
-- * yl_speak_up.eval_precondition and
|
|
-- * yl_speak_up.eval_effect.
|
|
yl_speak_up.eval_and_execute_function = function(player, x_v, id_prefix)
|
|
local pname = player:get_player_name()
|
|
|
|
--minetest.chat_send_all("this is in a single prereq or effect: "..dump(x_v))
|
|
local x_id = x_v[ id_prefix.. "id" ]
|
|
if x_v[ id_prefix.."type" ] ~= "function" then
|
|
return true
|
|
end
|
|
|
|
local code = x_v[ id_prefix.."value" ]
|
|
if code:byte(1) == 27 then
|
|
local obj = yl_speak_up.speak_to[pname].obj
|
|
local n_id = yl_speak_up.speak_to[pname].n_id
|
|
local npc = get_number_from_id(n_id)
|
|
if obj:get_luaentity() and tonumber(npc) then
|
|
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not compile the content of "..x_id.." :"..dump(code) .. " because of illegal bytecode for player "..pname)
|
|
else
|
|
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not compile the content of "..x_id.." :"..dump(code) .. " for player unknown because of illegal bytecode")
|
|
end
|
|
end
|
|
|
|
local param = "playername"
|
|
if( id_prefix == "r_") then
|
|
param = "player"
|
|
end
|
|
local f, msg = loadstring("return function("..param..") " .. code .. " end")
|
|
|
|
if not f then
|
|
local obj = yl_speak_up.speak_to[pname].obj
|
|
local n_id = yl_speak_up.speak_to[pname].n_id
|
|
local npc = get_number_from_id(n_id)
|
|
if obj:get_luaentity() and tonumber(npc) then
|
|
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not compile the content of "..x_id.." :"..dump(code) .. " for player "..pname)
|
|
else
|
|
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not compile the content of "..x_id.." :"..dump(code) .. " for player unknown")
|
|
end
|
|
else
|
|
local func = f()
|
|
|
|
local ok, ret = pcall(func,pname)
|
|
|
|
if not ok then
|
|
local obj = yl_speak_up.speak_to[pname].obj
|
|
local n_id = yl_speak_up.speak_to[pname].n_id
|
|
local npc = get_number_from_id(n_id)
|
|
if obj:get_luaentity() and tonumber(npc) then
|
|
minetest.log("error","[MOD] yl_speak_up: NPC with ID n_"..npc.." at position "..minetest.pos_to_string(obj:get_pos(),0).." could not execute the content of "..x_id.." :"..dump(code) .. " for player "..pname)
|
|
else
|
|
minetest.log("error","[MOD] yl_speak_up: NPC with ID unknown could not execute the content of "..x_id.." :"..dump(code) .. " for player unknown")
|
|
end
|
|
end
|
|
|
|
if type(ret) == "boolean" then
|
|
return ret
|
|
end
|
|
end
|
|
-- fallback
|
|
return false
|
|
end
|
|
|
|
|
|
-- These two functions
|
|
-- * yl_speak_up.input_fs_edit_option_related and
|
|
-- * yl_speak_up.get_fs_edit_option_related
|
|
-- are very similar for preconditions and effects. Therefore they're called here
|
|
-- with a lot of parameters. fs_edit_preconditions.lua and fs_edit_effects.lua
|
|
-- contain only wrappers.
|
|
|
|
yl_speak_up.input_fs_edit_option_related = function(player, formname, fields,
|
|
id_prefix, element_list_name, max_entries_allowed,
|
|
element_desc, tmp_data_cache,
|
|
text_ask_for_punching,
|
|
values_what, values_operator, values_block, values_trade, values_inv,
|
|
check_what, check_operator, check_block, check_trade, check_inv,
|
|
get_sorted_player_var_list_function,
|
|
formspec_input_to
|
|
)
|
|
if(not(player)) then
|
|
return
|
|
end
|
|
local pname = player:get_player_name()
|
|
-- what are we talking about?
|
|
local n_id = yl_speak_up.speak_to[pname].n_id
|
|
local d_id = yl_speak_up.speak_to[pname].d_id
|
|
local o_id = yl_speak_up.speak_to[pname].o_id
|
|
local x_id = yl_speak_up.speak_to[pname][ id_prefix.."id"]
|
|
|
|
-- this only works in edit mode
|
|
if(not(n_id) or yl_speak_up.edit_mode[pname] ~= n_id) then
|
|
return
|
|
end
|
|
|
|
-- delete precondition
|
|
if(fields.delete_element) then
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
if(dialog and dialog.n_dialogs
|
|
and x_id
|
|
and dialog.n_dialogs[d_id]
|
|
and dialog.n_dialogs[d_id].d_options
|
|
and dialog.n_dialogs[d_id].d_options[o_id]) then
|
|
-- actually delete the element
|
|
dialog.n_dialogs[d_id].d_options[o_id][ element_list_name ][ x_id ] = nil
|
|
-- record this as a change, but do not save do disk yet
|
|
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
|
"Dialog "..tostring(d_id)..": "..element_desc.." "..tostring( x_id )..
|
|
" deleted for option "..tostring(o_id)..".")
|
|
-- TODO: when trying to save: save to disk as well?
|
|
-- show the new/changed element
|
|
-- go back to the edit option dialog (after all we just deleted the prerequirement)
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[6,2]"..
|
|
"label[0.2,0.5;"..element_desc.." \""..
|
|
minetest.formspec_escape(tostring( x_id ))..
|
|
"\" has been deleted.]"..
|
|
"button[1.5,1.5;2,0.9;back_from_delete_element;Back]"})
|
|
return
|
|
end
|
|
end
|
|
|
|
if(fields.select_block_pos) then
|
|
minetest.chat_send_player(pname, text_ask_for_punching)
|
|
-- this formspec expects the block punch:
|
|
yl_speak_up.speak_to[pname].expect_block_punch = formspec_input_to
|
|
return
|
|
end
|
|
|
|
-- field inputs: those do not trigger a sending of the formspec on their own
|
|
|
|
-- are we talking about an inventory?
|
|
-- (inventory only applies to preconditions; not effects)
|
|
local data = yl_speak_up.speak_to[pname][ tmp_data_cache ]
|
|
if(fields.inv_stack_name and fields.inv_stack_name ~= ""
|
|
and id_prefix == "p_"
|
|
and data and data.what and data.what >= 5 and data.what <= 6) then
|
|
local parts = fields.inv_stack_name:split(" ")
|
|
local size = 1
|
|
if(parts and #parts > 1) then
|
|
size = tonumber(parts[2])
|
|
if(not(size) or size < 1) then
|
|
size = 1
|
|
end
|
|
end
|
|
-- does the item exist?
|
|
if(minetest.registered_items[ parts[1] ]) then
|
|
data.inv_stack_name = parts[1].." "..tostring(size)
|
|
else
|
|
-- show error message
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[8,2]"..
|
|
"label[0.2,0.5;Error: \""..
|
|
minetest.formspec_escape(fields.inv_stack_name)..
|
|
"\" is not a valid item(stack).]"..
|
|
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
|
|
-- comparison value for a variable (same for both preconditions and effects)
|
|
elseif(fields.var_cmp_value
|
|
and data and data.what and data.what == 2 and id_prefix ~= "a_") then
|
|
data.var_cmp_value = fields.var_cmp_value
|
|
|
|
-- text for a chat message
|
|
elseif(fields.chat_msg_text
|
|
and data and data.what and data.what == 6 and id_prefix == "r_") then
|
|
data.chat_msg_text = fields.chat_msg_text
|
|
|
|
elseif(fields.action_item_quest_id
|
|
and fields.action_item_quest_id ~= ""
|
|
and fields.action_item_quest_id ~= "- none set -"
|
|
and data and data.what and data.what == 4 and id_prefix == "a_") then
|
|
data.item_quest_id = fields.action_item_quest_id
|
|
end
|
|
-- action_item_quest_id and action_item_desc can be set at the same time
|
|
if(fields.action_item_desc
|
|
and fields.action_item_desc ~= ""
|
|
and fields.action_item_desc ~= "- no item set -"
|
|
and data and data.what and data.what == 4 and id_prefix == "a_") then
|
|
-- TODO: check if it diffrent from the default one of the stack
|
|
data.item_desc = fields.action_item_desc
|
|
end
|
|
|
|
-- the save button was pressed
|
|
if(fields.save_element and data and data.what and values_what[ data.what ]) then
|
|
-- for creating the new prerequirement; normal elements: p_type, p_value, p_id
|
|
local v = {}
|
|
-- determine p_type
|
|
v[ id_prefix.."type" ] = values_what[ data.what ]
|
|
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
if(not(dialog) or not(dialog.n_dialogs)
|
|
or not(dialog.n_dialogs[d_id])
|
|
or not(dialog.n_dialogs[d_id].d_options)
|
|
or not(dialog.n_dialogs[d_id].d_options[o_id])) then
|
|
-- this really should not happen during the normal course of operation
|
|
-- (only if the player sends forged formspec data or a bug occoured)
|
|
minetest.chat_send_player(pname, "Dialog or option does not exist.")
|
|
return
|
|
end
|
|
local elements = dialog.n_dialogs[d_id].d_options[o_id][ element_list_name ]
|
|
if(not(elements)) then
|
|
dialog.n_dialogs[d_id].d_options[o_id][ element_list_name ] = {}
|
|
elements = dialog.n_dialogs[d_id].d_options[o_id][ element_list_name ]
|
|
x_id = "new"
|
|
end
|
|
-- set x_id appropriately
|
|
if(not(x_id) or x_id == "new") then
|
|
x_id = id_prefix..yl_speak_up.find_next_id(elements)
|
|
end
|
|
v[ id_prefix.."id" ] = x_id
|
|
|
|
-- if needed: show a message after successful save so that the player can take
|
|
-- his items back from the trade_inv slots
|
|
local show_save_msg = nil
|
|
local sorted_key_list = yl_speak_up.sort_keys(elements)
|
|
if( x_id == "new" and #sorted_key_list >= max_entries_allowed) then
|
|
-- this really should not happen during the normal course of operation
|
|
-- (only if the player sends forged formspec data or a bug occoured)
|
|
minetest.chat_send_player(pname, "Maximum number of allowed entries exceeded.")
|
|
return
|
|
end
|
|
-- "an internal state (i.e. of a quest)", -- 2
|
|
if(data.what == 2 and id_prefix ~= "a_") then
|
|
v[ id_prefix.."value" ] = "expression"
|
|
v[ id_prefix.."operator" ] = values_operator[ data.operator ]
|
|
v[ id_prefix.."var_cmp_value" ] = (data.var_cmp_value or "")
|
|
v[ id_prefix.."variable" ] = data.variable_name
|
|
|
|
-- "a block somewhere", -- 3
|
|
elseif(data.what == 3 and id_prefix ~= "a_") then
|
|
v[ id_prefix.."value" ] = values_block[ data.block ]
|
|
if(not(data.block_pos) or not(data.node_data) or not(data.node_data.name)) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[8,2]"..
|
|
"label[0.2,0.5;Error: Please select a block first!]"..
|
|
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
-- for "node_is_air", there is no need to store node name and parameter
|
|
if(v[ id_prefix.."value" ]
|
|
and (v[ id_prefix.."value" ] == "node_is_like"
|
|
or v[ id_prefix.."value" ] == "node_is_diffrent_from")
|
|
or v[ id_prefix.."value" ] == "place"
|
|
or v[ id_prefix.."value" ] == "dig"
|
|
or v[ id_prefix.."value" ] == "punch"
|
|
or v[ id_prefix.."value" ] == "right-click") then
|
|
v[ id_prefix.."node" ] = data.node_data.name
|
|
v[ id_prefix.."param2" ] = data.node_data.param2
|
|
end
|
|
-- preconditions can be applied to all blocks; effects may be more limited
|
|
if(id_prefix == "r_"
|
|
and yl_speak_up.check_blacklisted(v[id_prefix.."value"],
|
|
-- we don't know yet which node will be there later on
|
|
data.node_data.name, data.node_data.name)) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[8,2]"..
|
|
"label[0.2,0.5;Error: Blocks of type \""..
|
|
tostring(data.node_data.name).."\" do not allow\n"..
|
|
"interaction of type \""..tostring(v[id_prefix.."value"])..
|
|
"\" for NPC.]"..
|
|
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
-- we also need to store the position of the node
|
|
v[ id_prefix.."pos" ] = {x = data.block_pos.x, y = data.block_pos.y, z = data.block_pos.z }
|
|
-- "I can't punch it. The block is as the block *above* the one I punched.",
|
|
if(id_prefix == "p_" and data.block == 5) then
|
|
v.p_pos.y = v.p_pos.y + 1
|
|
end
|
|
|
|
-- "a trade", -- 4
|
|
-- (only for preconditions; not for effects)
|
|
elseif(data.what == 4 and id_prefix == "p_") then
|
|
-- this depends on the trade associated with that option; therefore,
|
|
-- it does not need any more parameters (they come dynamicly from the
|
|
-- trade)
|
|
v.p_value = values_trade[ data.trade ]
|
|
|
|
-- "the inventory of the player", -- 5
|
|
-- "the inventory of the NPC", -- 6
|
|
-- (only for preconditions; not for effects)
|
|
elseif((data.what == 5 or data.what == 6) and id_prefix == "p_") then
|
|
v.p_value = values_inv[ data.inv ]
|
|
if(v.p_value and v.p_value ~= "inv_is_empty") then
|
|
-- we have checked this value earlier on
|
|
v[ "p_itemstack" ] = data.inv_stack_name
|
|
end
|
|
|
|
-- "NPC crafts soemthing", -- 4
|
|
-- (only for effects; not for preconditions)
|
|
elseif(data.what and id_prefix == "r_" and data.what == 4) then
|
|
local player_inv = player:get_inventory()
|
|
if(player_inv:get_stack("craftpreview", 1):is_empty()) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[8,2]"..
|
|
"label[0.2,0.5;Error: Please prepare your craft grid first!"..
|
|
"\nYour NPC needs to know what to craft.]"..
|
|
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
-- store the craft result (Note: the craft result may change in the future
|
|
-- if the server changes its craft result, making this craft invalid)
|
|
v[ "r_value" ] = player_inv:get_stack("craftpreview", 1):to_string()
|
|
v[ "r_craft_grid"] = {}
|
|
for i = 1, 9 do
|
|
-- store all the indigrents of the craft grid
|
|
table.insert( v[ "r_craft_grid" ],
|
|
player_inv:get_stack("craft", i):to_string())
|
|
end
|
|
|
|
-- "go to other dialog if the *previous* effect failed", -- 5
|
|
-- (only for effects; not for preconditions)
|
|
elseif(data.what and id_prefix == "r_" and data.what == 5) then
|
|
v[ "r_value" ] = data.on_failure
|
|
|
|
-- "send a chat message to all players", -- 6
|
|
-- (only for effects; not for preconditions)
|
|
elseif(data.what and id_prefix == "r_" and data.what == 6) then
|
|
data.chat_msg_text = fields.chat_msg_text
|
|
-- allow saving only if the placeholders are all present
|
|
-- (reason for requiring them: players and server owners ought to
|
|
-- be able to see who is responsible for a message)
|
|
if(not(string.find(data.chat_msg_text, "%$NPC_NAME%$"))
|
|
or not(string.find(data.chat_msg_text, "%$PLAYER_NAME%$"))
|
|
or not(string.find(data.chat_msg_text, "%$OWNER_NAME%$"))) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[9,2.5]"..
|
|
"label[0.2,0.5;Error: Your chat message needs to contain "..
|
|
"the following\nplaceholders: $NPC_NAME$, "..
|
|
"$PLAYER_NAME$ and $OWNER_NAME$.\nThat way, other "..
|
|
"players will know who sent the message.]"..
|
|
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
v[ "r_value" ] = data.chat_msg_text
|
|
|
|
-- "The NPC gives something to the player (i.e. a quest item).", -- 4
|
|
-- "The player is expected to give something to the NPC (i.e. a quest item).", -- 5
|
|
-- (only for actions)
|
|
elseif(data.what and id_prefix == "a_" and (data.what == 4 or data.what == 5)) then
|
|
local trade_inv_list = "npc_gives"
|
|
if(data.what == 5) then
|
|
trade_inv_list = "npc_wants"
|
|
end
|
|
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
|
if(not(trade_inv) or trade_inv:is_empty( trade_inv_list )) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[9,2.5]"..
|
|
"label[0.2,0.5;Please insert an item first! Your NPC"..
|
|
"needs\nto know what it shall give to the player.]"..
|
|
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
v[ "a_on_failure" ] = data.action_failure_dialog
|
|
-- change the node in the slot
|
|
local stack = trade_inv:get_stack( trade_inv_list, 1)
|
|
if(not(stack) or not(minetest.registered_items[ stack:get_name() ])) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[9,2.5]"..
|
|
"label[0.2,0.5;This item is unkown. Please use only known"..
|
|
"items.]"..
|
|
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
-- is this particular item blacklisted on this server?
|
|
if(yl_speak_up.blacklist_action_quest_item[ stack:get_name() ]) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[9,2.5]"..
|
|
"label[0.2,0.5;Sorry. This item is blacklisted on this "..
|
|
"server.\nYou can't use it as a quest item.]"..
|
|
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
local meta = stack:get_meta()
|
|
-- what does the NPC want to give?
|
|
v[ "a_value" ] = stack:get_name().." "..stack:get_count()
|
|
if(data.what == 5) then
|
|
data.item_desc = meta:get_string("description")
|
|
end
|
|
-- set new description if there is one set (optional)
|
|
if(data.item_desc
|
|
and data.item_desc ~= ""
|
|
and data.item_desc ~= "- none set -") then
|
|
if(data.what == 4) then
|
|
meta:set_string("description", data.item_desc)
|
|
end
|
|
v[ "a_item_desc" ] = data.item_desc
|
|
end
|
|
if(data.what == 5) then
|
|
data.item_quest_id = meta:get_string("yl_speak_up:quest_id")
|
|
end
|
|
-- set special ID (optional)
|
|
if(data.item_quest_id
|
|
and data.item_quest_id ~= ""
|
|
and data.item_quest_id ~= "- no item set -") then
|
|
if(data.what == 4) then
|
|
-- which player got this quest item?
|
|
meta:set_string("yl_speak_up:quest_item_for", pname)
|
|
-- include the NPC id so that we know which NPC gave it
|
|
meta:set_string("yl_speak_up:quest_item_from", tostring(n_id))
|
|
-- extend quest_id by NPC id so that it becomes more uniq
|
|
meta:set_string("yl_speak_up:quest_id",
|
|
tostring(n_id).." "..tostring(data.item_quest_id))
|
|
end
|
|
v[ "a_item_quest_id" ] = data.item_quest_id
|
|
end
|
|
if( v["a_item_quest_id"] and not(v[ "a_item_desc"]) and data.what == 4) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[9,2.5]"..
|
|
"label[0.2,0.5;You can't set a special quest ID without "..
|
|
"also changing\nthe description. The player would be "..
|
|
"unable to tell\nthe quest item and normal items "..
|
|
"apartapart.]"..
|
|
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
local player_inv = player:get_inventory()
|
|
if(not(player_inv:room_for_item("main", stack))) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = "size[9,2.5]"..
|
|
"label[0.2,0.5;You have no room in your inventory for "..
|
|
"the example\nitem. Please make room so that it can be"..
|
|
"given back to you!]"..
|
|
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
|
|
return
|
|
end
|
|
player_inv:add_item("main", stack)
|
|
trade_inv:remove_item(trade_inv_list, stack)
|
|
-- just send a message that the save was successful and give the player time to
|
|
-- take his items back
|
|
show_save_msg = "size[9,2.5]"..
|
|
"label[0.2,0.5;The information was saved successfully.\n"..
|
|
"The item has been returned to your inventory.]"..
|
|
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"
|
|
end
|
|
|
|
-- only save if something was actually selected
|
|
if(v[ id_prefix.."value"]) then
|
|
if(not(dialog.n_dialogs[d_id].d_options[o_id][ element_list_name ])) then
|
|
dialog.n_dialogs[d_id].d_options[o_id][ element_list_name ] = {}
|
|
end
|
|
-- store the change in the dialog
|
|
dialog.n_dialogs[d_id].d_options[o_id][ element_list_name ][ x_id ] = v
|
|
-- clear up data
|
|
yl_speak_up.speak_to[pname][ id_prefix.."id" ] = nil
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ] = nil
|
|
-- record this as a change, but do not save do disk yet
|
|
table.insert(yl_speak_up.npc_was_changed[ n_id ],
|
|
"Dialog "..tostring(d_id)..": "..element_desc.." "..tostring(x_id)..
|
|
" added/changed for option "..tostring(o_id)..".")
|
|
if(show_save_msg) then
|
|
yl_speak_up.show_fs(player, "msg", {
|
|
input_to = "yl_speak_up:"..formspec_input_to,
|
|
formspec = show_save_msg})
|
|
return
|
|
end
|
|
-- TODO: when trying to save: save to disk as well?
|
|
-- show the new/changed precondition
|
|
yl_speak_up.show_fs(player, formspec_input_to, x_id)
|
|
return
|
|
end
|
|
end
|
|
|
|
|
|
-- selections in a dropdown menu (they trigger sending the formspec)
|
|
|
|
-- select a general direction/type first
|
|
if(fields.select_what) then
|
|
local nr = table.indexof(check_what, fields.select_what)
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ] = { what = nr }
|
|
|
|
-- select a subtype for the "a trade" selection
|
|
elseif(fields.select_trade) then
|
|
local nr = table.indexof(check_trade, fields.select_trade)
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ].trade = nr
|
|
|
|
-- select a subtype for the inventory selection (player or NPC)
|
|
elseif(fields.select_inv) then
|
|
local nr = table.indexof(check_inv, fields.select_inv)
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ].inv = nr
|
|
|
|
-- select data regarding a block
|
|
elseif(fields.select_block) then
|
|
local nr = table.indexof(check_block, fields.select_block)
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ].block = nr
|
|
|
|
-- select data regarding a variable
|
|
elseif(fields.select_variable) then
|
|
-- get the list of available variables (with the same elements
|
|
-- and the same sort order as when the dropdown was displayed)
|
|
local var_list = get_sorted_player_var_list_function(pname)
|
|
local nr = table.indexof(var_list, fields.select_variable)
|
|
if(nr) then
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ].variable = nr
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ].variable_name = var_list[ nr ]
|
|
end
|
|
|
|
-- select data regarding an operator
|
|
elseif(fields.select_operator) then
|
|
local nr = table.indexof(check_operator, fields.select_operator)
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ].operator = nr
|
|
|
|
elseif(fields.select_on_failure) then
|
|
-- in this case we really want the name of the target dialog
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ].on_failure = fields.select_on_failure
|
|
|
|
elseif(fields.select_on_action_failure
|
|
and data and data.what and (data.what == 4 or data.what == 5) and id_prefix == "a_") then
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
|
|
local nr = table.indexof(sorted_dialog_list, fields.select_on_action_failure)
|
|
yl_speak_up.speak_to[pname][ tmp_data_cache ].action_failure_dialog = nr
|
|
end
|
|
|
|
-- "Normal trade - one item(stack) for another item(stack).", -- 3
|
|
-- (only for actions)
|
|
-- TODO: this needs to be adjusted
|
|
if(data and data.what == 3 and id_prefix == "a_") 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
|
|
end
|
|
|
|
-- the player wants to change/edit a precondition or effect
|
|
if(not(fields.back)
|
|
and (fields.change_element or fields.select_what or fields.select_trade
|
|
or fields.select_inv or fields.select_block
|
|
or fields.select_variable or fields.select_operator
|
|
or fields.select_on_failure
|
|
or fields.select_on_action_failure
|
|
or fields.back_from_error_msg)) then
|
|
yl_speak_up.show_fs(player, formspec_input_to)
|
|
return
|
|
end
|
|
|
|
-- go back to the edit option dialog
|
|
yl_speak_up.show_fs(player, "edit_option_dialog",
|
|
{n_id = n_id, d_id = d_id, o_id = o_id, caller= formspec_input_to})
|
|
end
|
|
|
|
|
|
yl_speak_up.get_fs_edit_option_related = function(player, table_click_result,
|
|
id_prefix, element_list_name, max_entries_allowed,
|
|
element_desc, tmp_data_cache,
|
|
what_do_you_want_txt,
|
|
check_what, check_operator, check_block, check_trade, check_inv,
|
|
get_sorted_player_var_list_function,
|
|
show_element_function,
|
|
table_of_name,
|
|
text_variable, text_select_operator, text_select_value,
|
|
text_block_position)
|
|
if(not(player)) then
|
|
return ""
|
|
end
|
|
local pname = player:get_player_name()
|
|
-- what are we talking about?
|
|
local n_id = yl_speak_up.speak_to[pname].n_id
|
|
local d_id = yl_speak_up.speak_to[pname].d_id
|
|
local o_id = yl_speak_up.speak_to[pname].o_id
|
|
local x_id = yl_speak_up.speak_to[pname][ id_prefix.."id" ]
|
|
|
|
-- this only works in edit mode
|
|
if(not(n_id) or yl_speak_up.edit_mode[pname] ~= n_id) then
|
|
return "size[1,1]label[0,0;You cannot edit this NPC.]"
|
|
end
|
|
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
if(not(dialog) or not(dialog.n_dialogs)
|
|
or not(dialog.n_dialogs[d_id])
|
|
or not(dialog.n_dialogs[d_id].d_options)
|
|
or not(dialog.n_dialogs[d_id].d_options[o_id])) then
|
|
return "size[4,1]label[0,0;Dialog option does not exist.]"
|
|
end
|
|
|
|
local elements = dialog.n_dialogs[d_id].d_options[o_id][ element_list_name ]
|
|
if(not(elements)) then
|
|
elements = {}
|
|
end
|
|
|
|
-- did we arrive here through clicking on an element in the dialog edit options menu?
|
|
if(table_click_result or elements[ table_click_result ]) then
|
|
if(not(elements[ table_click_result ])) then
|
|
-- which element has the player selected?
|
|
local sorted_key_list = yl_speak_up.sort_keys(elements)
|
|
local selected = minetest.explode_table_event(table_click_result)
|
|
-- use "new" if nothing fits
|
|
x_id = "new"
|
|
if((selected.type == "CHG" or selected.type == "DLC")
|
|
and selected.row <= #sorted_key_list) then
|
|
x_id = sorted_key_list[ selected.row ]
|
|
end
|
|
|
|
if( x_id == "new" and #sorted_key_list >= max_entries_allowed) then
|
|
return "size[9,1.5]"..
|
|
"label[0.2,0.0;There are only up to "..
|
|
minetest.formspec_escape(yl_speak_up.max_result_effects)..
|
|
" "..element_desc.."s allowed per dialog option.]"..
|
|
"button[2.0,0.8;1.0,0.9;back;Back]"
|
|
end
|
|
else
|
|
-- allow to directly specify a x_id to show
|
|
x_id = table_click_result
|
|
end
|
|
|
|
-- store which element we are talking about
|
|
yl_speak_up.speak_to[pname][ id_prefix.."id" ] = x_id
|
|
-- display the selected element
|
|
if(x_id ~= "new") then
|
|
return "formspec_version[3]"..
|
|
"size[20,3]"..
|
|
"bgcolor[#00000000;false]"..
|
|
"label[0.2,0.5;Selected "..element_desc..":]"..
|
|
"tablecolumns[text;color,span=1;text;text]"..
|
|
"table[0.2,0.8;19.6,0.7;"..table_of_name..";"..
|
|
minetest.formspec_escape(elements[ x_id ][ id_prefix.."id"])..
|
|
",#FFFF00,"..
|
|
minetest.formspec_escape(elements[ x_id ][ id_prefix.."type"])..
|
|
","..
|
|
minetest.formspec_escape(
|
|
show_element_function(elements[ x_id ]))..";0]"..
|
|
"button[2.0,1.8;1.5,0.9;delete_element;Delete]"..
|
|
"button[4.0,1.8;1.5,0.9;change_element;Change]"..
|
|
"button[6.0,1.8;1,0.9;back;Back]"
|
|
end
|
|
end
|
|
|
|
-- did the player get here through punching a block in the meantime?
|
|
local block_pos = yl_speak_up.speak_to[pname].block_punched
|
|
yl_speak_up.speak_to[pname].block_punched = nil
|
|
|
|
local data = yl_speak_up.speak_to[pname][ tmp_data_cache ]
|
|
if(not(data) or not(data.what)) then
|
|
data = { what = 1}
|
|
end
|
|
-- fallback
|
|
if(not(x_id)) then
|
|
x_id = "new"
|
|
end
|
|
local save_button = "button[5.0,9.8;1,0.7;save_element;Save]"
|
|
local formspec =
|
|
"formspec_version[3]"..
|
|
"size[20,11]"..
|
|
"label[5,0.5;Edit "..element_desc.." \""..minetest.formspec_escape(x_id).."\"]"..
|
|
"label[0.2,1.5;"..what_do_you_want_txt.."]"..
|
|
"label[0.2,2.0;Something regarding...]"..
|
|
"dropdown[4.0,1.8;14.0,0.6;select_what;"..
|
|
table.concat(check_what, ",")..";"..
|
|
tostring(data.what)..";]"..
|
|
"button[3.0,9.8;1,0.7;back;Abort]"
|
|
|
|
if(id_prefix ~= "a_") then
|
|
formspec = formspec..
|
|
"label[1,9.0;If you are unsure if your setup of pre(C)onditions and (Ef)fects "..
|
|
"works as intended,\ntype \"/npc_talk_debug "..tostring(n_id).."\" "..
|
|
"in chat in order to enter debug mode. You can leave it with "..
|
|
"\"/npc_talk_debug off\".]"
|
|
end
|
|
|
|
-- "an internal state (i.e. of a quest)", -- 2
|
|
-- (state is the second offered option in both preconditions and effects list)
|
|
if(data.what and data.what == 2 and id_prefix ~= "a_") then
|
|
if(not(data.variable) or data.variable == 1) then
|
|
data.variable = 1
|
|
-- not enough selected yet for saving
|
|
save_button = ""
|
|
elseif(not(data.operator) or data.operator == 1) then
|
|
data.operator = 1
|
|
save_button = ""
|
|
end
|
|
local field_for_value = "field[11.2,4.8;7.0,0.6;var_cmp_value;;"..
|
|
minetest.formspec_escape(data.var_cmp_value or "- enter value -").."]"
|
|
-- do not show value input field for unary operators
|
|
-- (unary operators are diffrent for prerequirements and effects)
|
|
if(not(data.operator)
|
|
or (id_prefix == "p_" and (data.operator == 1 or data.operator >= 8))
|
|
or (id_prefix == "r_" and (data.operator == 3))) then
|
|
field_for_value = "label[11.2,5.1;- not used for this operator -]"
|
|
end
|
|
-- the list of available variables needs to be extended with the ones
|
|
-- the player has read access to, and the order has to be constant
|
|
-- (because dropdown just returns an index)
|
|
local var_list = get_sorted_player_var_list_function(pname)
|
|
formspec = formspec..
|
|
"label[0.2,3.3;"..text_variable.."]"..
|
|
"label[0.2,4.3;Name of variable:]"..
|
|
"dropdown[0.2,4.8;6.5,0.6;select_variable;"..
|
|
table.concat(var_list, ",")..";"..
|
|
tostring(data.variable)..";]"..
|
|
"label[7.0,4.3;"..text_select_operator.."]"..
|
|
"dropdown[7.0,4.8;4.0,0.6;select_operator;"..
|
|
table.concat(check_operator, ",")..";"..
|
|
tostring(data.operator)..";]"..
|
|
"label[11.2,4.3;"..text_select_value.."]"..
|
|
field_for_value
|
|
|
|
-- "a block somewhere", -- 3
|
|
-- (block is the third offered option in both preconditions and effects list)
|
|
elseif(data.what and data.what == 3 and id_prefix ~= "a_") then
|
|
local block_pos_str = "- none set -"
|
|
local node = {name = "- unknown -", param2 = "- unkown -"}
|
|
if(not(block_pos) and data and data.block_pos) then
|
|
block_pos = data.block_pos
|
|
end
|
|
local error_is_protected = ""
|
|
if(block_pos) then
|
|
-- store for later usage
|
|
data.block_pos = block_pos
|
|
local tmp_pos = {x=block_pos.x, y=block_pos.y, z=block_pos.z}
|
|
-- "I can't punch it. The block is as the block *above* the one I punched.",
|
|
-- (only valid for preconditions; not for effects - because the player and
|
|
-- his NPC need to be able to build there)
|
|
if(data.block and id_prefix == "p_" and data.block == 5) then
|
|
tmp_pos.y = block_pos.y + 1
|
|
end
|
|
-- effects (and, likewise, preconditions): the player at least has to be able to
|
|
-- build at that position - check that
|
|
if(minetest.is_protected(tmp_pos, pname)) then
|
|
error_is_protected = "label[0.2,7.8;Error: "..
|
|
"The position you punched is protected. It cannot be used by "..
|
|
"your NPC for checks or building. Please select a diffrent block!]"
|
|
block_pos = nil
|
|
data.block_pos = nil
|
|
else
|
|
block_pos_str = minetest.pos_to_string(tmp_pos)
|
|
node = minetest.get_node_or_nil(tmp_pos)
|
|
if(not(node)) then
|
|
node = {name = "- unknown -", param2 = "- unkown -"}
|
|
end
|
|
-- "There shall be air instead of this block.",
|
|
-- (only valid for preconditions)
|
|
if(data.block and id_prefix == "p_" and data.block == 3) then
|
|
node = {name = "air", param2 = 0}
|
|
end
|
|
-- cache that (in case a sapling grows or someone else changes it)
|
|
data.node_data = node
|
|
end
|
|
end
|
|
if(node.name == "- unknown -") then
|
|
save_button = ""
|
|
end
|
|
if(not(data.block) or data.block == 1) then
|
|
data.block = 1
|
|
-- not enough selected yet for saving
|
|
save_button = ""
|
|
end
|
|
formspec = formspec..
|
|
"label[0.2,3.3;"..text_block_position.."]"..
|
|
"dropdown[4.0,3.5;16.0,0.6;select_block;"..
|
|
table.concat(check_block, ",")..";"..
|
|
tostring(data.block)..";]"..
|
|
"label[0.2,4.8;Position of the block:]"..
|
|
"label[4.0,4.8;"..minetest.formspec_escape(block_pos_str).."]"..
|
|
"label[0.2,5.8;Name of block:]"..
|
|
"label[4.0,5.8;"..minetest.formspec_escape(node.name).."]"..
|
|
"label[0.2,6.8;Orientation (param2):]"..
|
|
"label[4.0,6.8;"..minetest.formspec_escape(node.param2).."]"..
|
|
"button_exit[10.0,5.5;4.0,0.7;select_block_pos;Set position of block]"..
|
|
"tooltip[select_block_pos;Click on this button to select a block.\n"..
|
|
"This menu will close and you will be asked to punch\n"..
|
|
"the block at the position you want to check or change.\n"..
|
|
"After punching it, you will be returned to this menu.]"..
|
|
error_is_protected
|
|
|
|
-- "a trade", -- 4
|
|
-- (trade - only for preconditions; effects have something else here)
|
|
elseif(data.what and id_prefix == "p_" and data.what == 4) then
|
|
if(not(data.trade) or data.trade == 1) then
|
|
data.trade = 1
|
|
-- not enough selected yet for saving
|
|
save_button = ""
|
|
end
|
|
formspec = formspec..
|
|
"label[0.2,3.3;If the action is a trade, the following shall be true:]"..
|
|
"dropdown[4.0,3.5;16.0,0.6;select_trade;"..
|
|
table.concat(check_trade, ",")..";"..
|
|
tostring(data.trade)..";]"
|
|
|
|
-- "the inventory of the player", -- 5
|
|
-- "the inventory of the NPC", -- 6
|
|
-- (inventory - only for preconditions; effects have something else here)
|
|
elseif(data.what and id_prefix == "p_" and data.what >= 5 and data.what <= 6) then
|
|
if(not(data.inv) or data.inv == 1) then
|
|
data.inv = 1
|
|
-- not enough selected yet for saving
|
|
save_button = ""
|
|
end
|
|
formspec = formspec..
|
|
"label[0.2,3.3;The following shall be true about the inventory:]"..
|
|
"dropdown[4.0,3.5;16.0,0.6;select_inv;"..
|
|
table.concat(check_inv, ",")..";"..
|
|
tostring(data.inv)..";]"..
|
|
"label[0.2,4.5;Name of the item(stack):]"..
|
|
"field[4.0,4.3;16.0,0.6;inv_stack_name;;"..(data.inv_stack_name or "").."]"..
|
|
"tooltip[inv_stack_name;Enter name of the block and amount.\n"..
|
|
"Example: \"default:apple 3\" for three apples,\n"..
|
|
" \"farming:bread\" for a bread.]"
|
|
|
|
-- "NPC crafts soemthing", -- 4
|
|
-- (craft - only for effects - not for preconditions)
|
|
elseif(data.what and id_prefix == "r_" and data.what == 4) then
|
|
formspec = formspec..
|
|
"label[8,2.6;Your invnetory:]"..
|
|
"list[current_player;main;8,3;8,4;]"..
|
|
"label[1,3.1;Your craft grid:]"..
|
|
"list[current_player;craft;1,3.5;3,3;]"..
|
|
"list[current_player;craftpreview;5.8,4.75;1,1;]"..
|
|
"image[4.6,4.8;1,1;gui_furnace_arrow_bg.png^[transformR270]"..
|
|
"label[1,8.0;Use your craft grid to show your NPC what to craft "..
|
|
"and how. Click on \"Save\" to save.]"
|
|
|
|
-- "go to other dialog if the *previous* effect failed", -- 5
|
|
-- (on_failure - only for effects - not for preconditions)
|
|
elseif(data.what and id_prefix == "r_" and data.what == 5) then
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
|
|
local nr = 1
|
|
if(not(data) or not(data.on_failure)) then
|
|
save_button = ""
|
|
else
|
|
nr = table.indexof(sorted_dialog_list, data.on_failure)
|
|
end
|
|
formspec = formspec..
|
|
"label[0.2,3.3;If the *previous* effect failed,]"..
|
|
"label[0.2,3.8;switch to the following dialog:]"..
|
|
"dropdown[5.0,3.5;6.5,0.6;select_on_failure;"..
|
|
table.concat(sorted_dialog_list, ",")..";"..
|
|
tostring(nr)..";]"
|
|
|
|
-- "send a chat message to all players" -- 6
|
|
elseif(data.what and id_prefix == "r_" and data.what == 6) then
|
|
local text = "$NPC_NAME$ (owned by $OWNER_NAME$) announces: $PLAYER_NAME$ "..
|
|
"- example; please enter the text -"
|
|
if(data and data.chat_msg_text) then
|
|
text = data.chat_msg_text
|
|
end
|
|
formspec = formspec..
|
|
"label[0.2,3.3;Send the following chat message to *all* players:]"..
|
|
"label[0.2,4.1;Message:]"..
|
|
"field[2.0,3.8;16.0,0.6;chat_msg_text;;"..
|
|
minetest.formspec_escape(tostring(text)).."]"..
|
|
"label[0.2,5.3;Note: Your chat message needs to contain the following placeholders,"..
|
|
" which will be replaced automaticly like in dialog texts:"..
|
|
"\n$NPC_NAME$, $PLAYER_NAME$ and $OWNER_NAME$.]"
|
|
|
|
-- "The NPC gives something to the player (i.e. a quest item).", -- 4
|
|
-- (only for actions)
|
|
elseif(data.what and id_prefix == "a_" and data.what == 4) then
|
|
local pname = player:get_player_name()
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
local item_quest_id = "- none set -"
|
|
if(data and data.item_quest_id) then
|
|
item_quest_id = data.item_quest_id
|
|
end
|
|
local item_desc = "- no item set -"
|
|
if(data and data.item_desc) then
|
|
item_desc = data.item_desc
|
|
end
|
|
local nr = 1
|
|
if(data and data.action_failure_dialog) then
|
|
nr = data.action_failure_dialog + 1
|
|
end
|
|
local stack_name = ""
|
|
if(data and data.item_node_name) then
|
|
stack_name = data.item_node_name
|
|
end
|
|
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
|
|
formspec = formspec..
|
|
"label[8,2.6;Your invnetory:]"..
|
|
"list[current_player;main;8,3;8,4;]"..
|
|
"label[1,3.1;"..minetest.formspec_escape(dialog.n_npc or "?").." gives:]"..
|
|
"list[detached:yl_speak_up_player_"..pname..";npc_gives;2,3.5;1,1;]"..
|
|
"label[3.2,4.0;"..minetest.formspec_escape(stack_name).."]"..
|
|
"label[1,4.9;The player shall take this offered item.\n"..
|
|
"If he doesn't, go to dialog:]"..
|
|
"dropdown[5.0,5.1;2.8,0.6;select_on_action_failure;"..
|
|
"- current one -,"..
|
|
table.concat(sorted_dialog_list, ",")..";"..tostring(nr)..";]"..
|
|
"label[0.2,6.1;Set a description to turn the item into a special\n"..
|
|
"quest item. Set a special ID (short text) so that\n"..
|
|
"the player cannot create a fake item. Click on \n"..
|
|
"\"Save\" to apply the changes.]"..
|
|
"label[0.2,8.3;Special ID to set:]"..
|
|
"field[3.2,8.0;14.5,0.6;action_item_quest_id;;"..
|
|
minetest.formspec_escape(tostring(item_quest_id)).."]"..
|
|
"tooltip[action_item_quest_id;"..
|
|
"Set this to a text that helps *you* to remember what this\n"..
|
|
"special quest item is for (i.e. \"quest_deliver_augusts_"..
|
|
"letter\").\n"..
|
|
"The ID will be extended with the ID of the NPC and the\n"..
|
|
"name of the player who got this item from the NPC.]"..
|
|
"label[0.2,9.0;Description to set:]"..
|
|
"field[3.2,8.7;14.5,0.6;action_item_desc;;"..
|
|
minetest.formspec_escape(tostring(item_desc)).."]"..
|
|
"tooltip[action_item_desc;"..
|
|
"Set this to a text that helps the *player* to remember what\n"..
|
|
"this special quest item is for (i.e. \"Letter from August to\n"..
|
|
"Frederike\" for a piece of paper).\n"..
|
|
"This description is shown in the inventory on mouseover.]"
|
|
|
|
|
|
-- "The player is expected to give something to the NPC (i.e. a quest item).", -- 5
|
|
-- (only for actions)
|
|
elseif(data.what and id_prefix == "a_" and data.what == 5) then
|
|
local pname = player:get_player_name()
|
|
local dialog = yl_speak_up.speak_to[pname].dialog
|
|
local item_quest_id = "- none set -"
|
|
if(data and data.item_quest_id) then
|
|
item_quest_id = data.item_quest_id
|
|
end
|
|
local item_desc = "- no item set -"
|
|
if(data and data.item_desc) then
|
|
item_desc = data.item_desc
|
|
end
|
|
local nr = 1
|
|
if(data and data.action_failure_dialog) then
|
|
nr = data.action_failure_dialog + 1
|
|
end
|
|
local stack_name = ""
|
|
if(data and data.item_node_name) then
|
|
stack_name = data.item_node_name
|
|
end
|
|
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
|
|
formspec = formspec..
|
|
"label[8,2.6;Your invnetory:]"..
|
|
"list[current_player;main;8,3;8,4;]"..
|
|
"label[1,3.1;"..minetest.formspec_escape(dialog.n_npc or "?").." wants:]"..
|
|
"list[detached:yl_speak_up_player_"..pname..";npc_wants;2,3.5;1,1;]"..
|
|
"label[3.2,4.0;"..minetest.formspec_escape(stack_name).."]"..
|
|
"label[1,4.9;The player shall give the NPC this item.\n"..
|
|
"If he doesn't, go to dialog:]"..
|
|
"dropdown[5.0,5.1;2.8,0.6;select_on_action_failure;"..
|
|
"- current one -,"..
|
|
table.concat(sorted_dialog_list, ",")..";"..tostring(nr)..";]"..
|
|
"label[0.2,6.1;If you want a special ID and description, create\n"..
|
|
"those via the \"NPC gives something to the player\"\n"..
|
|
"menu option first and insert that item here.]"..
|
|
"label[0.2,8.3;Expected special ID:]"..
|
|
"label[4.0,8.3;"..
|
|
minetest.formspec_escape(tostring(item_quest_id)).."]"..
|
|
"label[0.2,9.0;Expected description:]"..
|
|
"label[4.0,9.0;"..
|
|
minetest.formspec_escape(tostring(item_desc)).."]"
|
|
end
|
|
return formspec..save_button
|
|
end
|