-- some helper lists for creating the formspecs and evaulating -- the player's answers -- general direction of what a prerequirement may be about local check_what = { "- please select -", "an internal state (i.e. of a quest)", -- 2 "a block somewhere", -- 3 "a trade", -- 4 "the inventory of the player", -- 5 "the inventory of the NPC", -- 6 } -- options for "a trade" local check_trade = { "- please select -", "The NPC has the item(s) he wants to sell in his inventory.", "The player has the item(s) needed to pay the price.", "The NPC ran out of stock.", "The player cannot afford the price.", } -- options for "the inventory of " (either player or NPC; perhaps blocks later on) local check_inv = { "- please select -", "The inventory contains the following item:", "The inventory *does not* contain the following item:", "There is room for the following item in the inventory:", "The inventory is empty.", } local check_block = { "- please select -", "The block is as it is now.", "There shall be air instead of this block.", "The block is diffrent from how it is now.", "I can't punch it. The block is as the block *above* the one I punched.", } -- comparison operators for variables local check_operator = { "- please select -", -- 1 "== (is equal)", -- 2 "~= (is not equal)", -- 3 ">= (is greater or equal)", -- 4 "> (is greater)", -- 5 "<= (is smaller or equal)", -- 6 "< (is smaller)", -- 7 "not (logically invert)", -- 8 "is_set (has a value)", -- 9 "is_unset (has no value)" -- 10 } -- some internal ones... local check_variable = { "- please select -", "(internal) hour of ingame day", "(internal) player's health points", } -- TODO: check inscription of a sign? -- TODO: invlist as dropdown of inventory lists at detected position -- TODO: variable as dropdown of allowed variables -- which diffrent types of preconditions are available? -- possible variables: -- item an inventory item or block (check if it exists) -- -> needs to be a minetest.registered_item[ item ] -- text some text -- pos a position in the world (not too far from the NPC) -- -> determined by punching -- variable name of a variable -- -- TODO: may all boil down to automaticly setting some lua code? -- -> better write a function for each one that can be called when needed yl_speak_up.input_fs_edit_preconditions = function(player, formname, fields) 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 p_id = yl_speak_up.speak_to[pname].p_id -- this only works in edit mode if(not(n_id) or yl_speak_up.edit_mode[pname] ~= n_id) then return end -- TODO: make delete work -- TODO: make save work -- TODO: check parameters if(fields.select_block_pos) then minetest.chat_send_player(pname, "Please punch the block you want to check in your precondition!") -- this formspec expects the block punch: yl_speak_up.speak_to[pname].expect_block_punch = "edit_preconditions" return end -- 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_prereq = { 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_prereq.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_prereq.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_prereq.block = nr -- select data regarding a variable elseif(fields.select_variable) then -- TODO: this needs to include player-specific variables local nr = table.indexof(check_variable, fields.select_variable) yl_speak_up.speak_to[pname].tmp_prereq.variable = nr -- 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_prereq.operator = nr end -- the player wants to change/edit a precondition if(not(fields.back) and (fields.change_prereq or fields.select_what or fields.select_trade or fields.select_inv or fields.select_block or fields.select_variable or fields.select_operator)) then yl_speak_up.show_fs(player, "edit_preconditions") 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="edit_precondition"}) end yl_speak_up.get_fs_edit_preconditions = function(player, table_click_result) 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 p_id = yl_speak_up.speak_to[pname].p_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 prereq = dialog.n_dialogs[d_id].d_options[o_id].o_prerequisites if(not(prereq)) then prereq = {} end -- did we arrive here through clicking on a prereq in the dialog edit options menu? if(table_click_result) then -- which precondition has the player selected? local sorted_key_list = yl_speak_up.sort_keys(prereq) local selected = minetest.explode_table_event(table_click_result) -- use "new" if nothing fits p_id = "new" if((selected.type == "CHG" or selected.type == "DLC") and selected.row <= #sorted_key_list) then p_id = sorted_key_list[ selected.row ] end -- store which prereq we are talking about yl_speak_up.speak_to[pname].p_id = p_id -- display the selected prereq if(p_id ~= "new") then return "formspec_version[3]".. "size[20,3]".. "bgcolor[#00000000;false]".. "label[0.2,0.5;Selected pre(C)ondition:]".. "tablecolumns[text;color,span=1;text;text]".. "table[0.2,0.8;19.6,0.7;table_of_preconditions;".. minetest.formspec_escape(prereq[ p_id ].p_id)..",#FFFF00,".. minetest.formspec_escape(prereq[ p_id ].p_type)..",".. minetest.formspec_escape(prereq[ p_id ].p_value)..";0]".. "button[2.0,1.8;1.5,0.9;delete_prereq;Delete]".. "button[4.0,1.8;1.5,0.9;change_prereq;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_prereq if(not(data) or not(data.what)) then data = { what = 1} end -- fallback if(not(p_id)) then p_id = "new" end local save_button = "button[5.0,9.0;1,0.7;save_prereq;Save]" local formspec = "formspec_version[3]".. "size[20,10]".. "label[5,0.5;Edit pre(C)ondition \""..minetest.formspec_escape(p_id).."\"]".. "label[0.2,1.5;What do you want to check in this precondition?]".. "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.0;1,0.7;back;Abort]" -- "an internal state (i.e. of a quest)", -- 2 if(data.what and data.what == 2) 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;;]" -- do not show value input field for unary operators if(not(data.operator) or data.operator == 1 or data.operator >= 8) then field_for_value = "label[11.2,5.1;- not used for this operator -]" end -- TODO: the list of available variables needs to be extended -- with the ones the player has read access to formspec = formspec.. "label[0.2,3.3;The following expression shall be true:]".. "label[0.2,4.3;Name of variable:]".. "dropdown[0.2,4.8;6.5,0.6;select_variable;".. table.concat(check_variable, ",")..";".. tostring(data.variable)..";]".. "label[7.0,4.3;Operator:]".. "dropdown[7.0,4.8;4.0,0.6;select_operator;".. table.concat(check_operator, ",")..";".. tostring(data.operator)..";]".. "label[11.2,4.3;Value to compare with:]".. field_for_value -- "a trade", -- 4 elseif(data.what 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 elseif(data.what 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;;]".. "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.]" -- "a block somewhere", -- 3 elseif(data.what and data.what == 3) 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 if(block_pos) then -- store for later usage data.block_pos = block_pos 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.", if(data.block and data.block == 5) then tmp_pos.y = block_pos.y + 1 end 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.", if(data.block 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 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;The following shall be true about the block:]".. "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.\n".. "After punching it, you will be returned to this menu.]" end return formspec..save_button end