looks like much, but only extracted yl_speak_up.save_element_p_or_a_or_e from yl_speak_up.input_fs_edit_option_related and adjusted identation

This commit is contained in:
Sokomine 2021-07-02 20:58:35 +02:00
parent b03ab2e6b5
commit c44ee99fbc

View File

@ -193,6 +193,476 @@ yl_speak_up.delete_element_p_or_a_or_e = function(
end
-- helper function for yl_speak_up.input_fs_edit_option_related
yl_speak_up.save_element_p_or_a_or_e = function(
player, pname, n_id, d_id, o_id, x_id, id_prefix, tmp_data_cache,
element_list_name, element_desc, max_entries_allowed,
values_what, values_operator, values_block, values_trade, values_inv,
formspec_input_to, data, fields)
-- 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
-- "give item (created out of thin air) to player (requires npc_master priv)", -- 7
-- "take item from player and destroy it (requires npc_master priv)", -- 8
elseif(data.what and id_prefix == "r_" and (data.what == 7 or data.what == 8)) then
if(not(data.inv_stack_name) or data.inv_stack_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 provide the name of the "..
"\nitem you want to give or take!]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
if(not(minetest.check_player_privs(player, {npc_master=true}))) then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: You need the \"npc_master\" priv "..
" in order to set this effect.]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
v[ "r_value" ] = data.inv_stack_name
-- "move the player to a given position (requires npc_master priv)", -- 9
elseif(data.what and id_prefix == "r_" and data.what == 9) then
if(not(data.move_to_x) or not(data.move_to_y) or not(data.move_to_z)) then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: Please provide valid coordinates "..
" x, y and z!]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
if(not(minetest.check_player_privs(player, {npc_master=true}))) then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: You need the \"npc_master\" priv "..
" in order to set this effect.]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
v[ "r_value" ] = minetest.pos_to_string(
{x = data.move_to_x, y = data.move_to_y, z = data.move_to_z})
-- effect "execute Lua code (requires npc_master priv)", -- precondition: 7; effect: 10
elseif((data.what and id_prefix == "p_" and data.what == 7)
or (data.what and id_prefix == "r_" and data.what == 10)) then
if(not(data.lua_code) or data.lua_code == "") then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: Please enter the Lua code you want "..
"to execute!]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
if(not(minetest.check_player_privs(player, {npc_master=true}))) then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: You need the \"npc_master\" priv "..
" in order to set this.]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
v[ id_prefix.."value" ] = data.lua_code
-- "NPC crafts something", -- 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
-- "Normal trade - one item(stack) for another item(stack).", -- 3
-- (only for actions)
elseif(data.what and id_prefix == "a_" and data.what == 3) 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
-- just to make sure that the trade_id is properly set...
if(not(data.trade_id)) 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: Missing trade ID.]"..
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
return
end
-- the button is called store_trade_simple instead of save_element in
-- the trade simple function(s); we want to store a trade
fields.store_trade_simple = true
local res = yl_speak_up.input_add_trade_simple(player, "", fields)
-- the above function sets:
-- dialog.trades[ trade_id ] = {pay={ps},buy={bs}, d_id = d_id, o_id = o_id}
-- store the trade as an action:
local dialog = yl_speak_up.speak_to[pname].dialog
if(res and dialog.trades and dialog.trades[ data.trade_id ]) then
v[ "a_value" ] = data.trade_id
v[ "a_pay" ] = dialog.trades[ data.trade_id ].pay
v[ "a_buy" ] = dialog.trades[ data.trade_id ].buy
v[ "a_on_failure" ] = ""
if(data.action_failure_dialog) then
local dialog = yl_speak_up.speak_to[pname].dialog
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
end
end
-- "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" ] = ""
if(data.action_failure_dialog) then
local dialog = yl_speak_up.speak_to[pname].dialog
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
end
-- 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()
-- for displaying as a background image
data.item_string = v[ "a_value" ]
if(data.what == 5) then
-- try to reconstruct $PLAYER_NAME$ (may not always work)
local item_was_for = meta:get_string("yl_speak_up:quest_item_for")
local new_desc = meta:get_string("description")
if(item_was_for and item_was_for ~= "") then
new_desc = string.gsub(new_desc, item_was_for, "$PLAYER_NAME$")
end
data.item_desc = new_desc
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]"
return
-- "The player has to manually enter a password or passphrase or some other text.", -- 6
elseif(data.what and id_prefix == "a_" and data.what == 6) then
if(not(data.quest_question)) then
data.quest_question = "Your answer:"
end
v[ "a_question" ] = data.quest_question
-- the player setting this up needs to provide the correct answer
if(not(data.quest_answer)) 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: Please provide the correct answer!\n"..
"The answer the player gives is checked against this.]"..
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
return
end
v[ "a_value" ] = data.quest_answer
if(not(data.action_failure_dialog)) 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: Please provide a target dialog if "..
"the player gives the wrong answer.]"..
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
return
end
local dialog = yl_speak_up.speak_to[pname].dialog
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
-- "Call custom functions that are supposed to be overridden by the server.", --
-- precondition: 8; action: 7; effect: 11
elseif(data.what
and ((id_prefix == "a_" and data.what == 7)
or (id_prefix == "p_" and data.what == 8)
or (id_prefix == "r_" and data.what == 11))) then
v[ id_prefix.."value" ] = data.custom_param
if(id_prefix == "a_") then
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
end
end
v[ "alternate_text" ] = data.alternate_text
-- 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
else
-- make sure the player is informed that saving failed
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: There is no \""..tostring(id_prefix)..
"value\" set.\n"..
"\nCould not save.]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
end
-- These two functions
-- * yl_speak_up.input_fs_edit_option_related and
-- * yl_speak_up.get_fs_edit_option_related
@ -383,458 +853,15 @@ yl_speak_up.input_fs_edit_option_related = function(player, formname, fields,
-- 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
-- "give item (created out of thin air) to player (requires npc_master priv)", -- 7
-- "take item from player and destroy it (requires npc_master priv)", -- 8
elseif(data.what and id_prefix == "r_" and (data.what == 7 or data.what == 8)) then
if(not(data.inv_stack_name) or data.inv_stack_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 provide the name of the "..
"\nitem you want to give or take!]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
if(not(minetest.check_player_privs(player, {npc_master=true}))) then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: You need the \"npc_master\" priv "..
" in order to set this effect.]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
v[ "r_value" ] = data.inv_stack_name
-- "move the player to a given position (requires npc_master priv)", -- 9
elseif(data.what and id_prefix == "r_" and data.what == 9) then
if(not(data.move_to_x) or not(data.move_to_y) or not(data.move_to_z)) then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: Please provide valid coordinates "..
" x, y and z!]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
if(not(minetest.check_player_privs(player, {npc_master=true}))) then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: You need the \"npc_master\" priv "..
" in order to set this effect.]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
v[ "r_value" ] = minetest.pos_to_string(
{x = data.move_to_x, y = data.move_to_y, z = data.move_to_z})
-- effect "execute Lua code (requires npc_master priv)", -- precondition: 7; effect: 10
elseif((data.what and id_prefix == "p_" and data.what == 7)
or (data.what and id_prefix == "r_" and data.what == 10)) then
if(not(data.lua_code) or data.lua_code == "") then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: Please enter the Lua code you want "..
"to execute!]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
if(not(minetest.check_player_privs(player, {npc_master=true}))) then
yl_speak_up.show_fs(player, "msg", {
input_to = "yl_speak_up:"..formspec_input_to,
formspec = "size[9,2]"..
"label[0.2,0.5;Error: You need the \"npc_master\" priv "..
" in order to set this.]"..
"button[1.5,1.5;2,0.9;back_from_error_msg;Back]"})
return
end
v[ id_prefix.."value" ] = data.lua_code
-- "NPC crafts something", -- 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
-- "Normal trade - one item(stack) for another item(stack).", -- 3
-- (only for actions)
elseif(data.what and id_prefix == "a_" and data.what == 3) 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
-- just to make sure that the trade_id is properly set...
if(not(data.trade_id)) 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: Missing trade ID.]"..
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
return
end
-- the button is called store_trade_simple instead of save_element in
-- the trade simple function(s); we want to store a trade
fields.store_trade_simple = true
local res = yl_speak_up.input_add_trade_simple(player, "", fields)
-- the above function sets:
-- dialog.trades[ trade_id ] = {pay={ps},buy={bs}, d_id = d_id, o_id = o_id}
-- store the trade as an action:
local dialog = yl_speak_up.speak_to[pname].dialog
if(res and dialog.trades and dialog.trades[ data.trade_id ]) then
v[ "a_value" ] = data.trade_id
v[ "a_pay" ] = dialog.trades[ data.trade_id ].pay
v[ "a_buy" ] = dialog.trades[ data.trade_id ].buy
v[ "a_on_failure" ] = ""
if(data.action_failure_dialog) then
local dialog = yl_speak_up.speak_to[pname].dialog
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
end
end
-- "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" ] = ""
if(data.action_failure_dialog) then
local dialog = yl_speak_up.speak_to[pname].dialog
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
end
-- 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()
-- for displaying as a background image
data.item_string = v[ "a_value" ]
if(data.what == 5) then
-- try to reconstruct $PLAYER_NAME$ (may not always work)
local item_was_for = meta:get_string("yl_speak_up:quest_item_for")
local new_desc = meta:get_string("description")
if(item_was_for and item_was_for ~= "") then
new_desc = string.gsub(new_desc, item_was_for, "$PLAYER_NAME$")
end
data.item_desc = new_desc
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]"
return
-- "The player has to manually enter a password or passphrase or some other text.", -- 6
elseif(data.what and id_prefix == "a_" and data.what == 6) then
if(not(data.quest_question)) then
data.quest_question = "Your answer:"
end
v[ "a_question" ] = data.quest_question
-- the player setting this up needs to provide the correct answer
if(not(data.quest_answer)) 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: Please provide the correct answer!\n"..
"The answer the player gives is checked against this.]"..
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
return
end
v[ "a_value" ] = data.quest_answer
if(not(data.action_failure_dialog)) 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: Please provide a target dialog if "..
"the player gives the wrong answer.]"..
"button[1.5,2.0;2,0.9;back_from_error_msg;Back]"})
return
end
local dialog = yl_speak_up.speak_to[pname].dialog
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
-- "Call custom functions that are supposed to be overridden by the server.", --
-- precondition: 8; action: 7; effect: 11
elseif(data.what
and ((id_prefix == "a_" and data.what == 7)
or (id_prefix == "p_" and data.what == 8)
or (id_prefix == "r_" and data.what == 11))) then
v[ id_prefix.."value" ] = data.custom_param
if(id_prefix == "a_") then
local sorted_dialog_list = yl_speak_up.sort_keys(dialog.n_dialogs)
v[ "a_on_failure" ] = sorted_dialog_list[ data.action_failure_dialog ]
end
end
v[ "alternate_text" ] = data.alternate_text
-- 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
local v = yl_speak_up.save_element_p_or_a_or_e(
player, pname, n_id, d_id, o_id, x_id, id_prefix, tmp_data_cache,
element_list_name, element_desc, max_entries_allowed,
values_what, values_operator, values_block, values_trade, values_inv,
formspec_input_to, data, fields)
return
end
-- selections in a dropdown menu (they trigger sending the formspec)
-- select a general direction/type first