diff --git a/fs_edit_preconditions.lua b/fs_edit_preconditions.lua index 7d0be79..cab5108 100644 --- a/fs_edit_preconditions.lua +++ b/fs_edit_preconditions.lua @@ -1,4 +1,82 @@ +-- 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 @@ -8,12 +86,65 @@ yl_speak_up.input_fs_edit_preconditions = function(player, formname, fields) 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(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"}) @@ -21,7 +152,7 @@ end yl_speak_up.get_fs_edit_preconditions = function(player, table_click_result) - if(not(player) or not(table_click_result)) then + if(not(player)) then return "" end local pname = player:get_player_name() @@ -29,6 +160,7 @@ yl_speak_up.get_fs_edit_preconditions = function(player, table_click_result) 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 @@ -47,17 +179,176 @@ yl_speak_up.get_fs_edit_preconditions = function(player, table_click_result) if(not(prereq)) then prereq = {} end - -- 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 - local 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 ] + + -- 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 - minetest.chat_send_player("singleplayer","input: "..minetest.serialize(table_click_result)) - return "size[4,1.5]label[0,0;Formspec: edit preconditions\n-> "..tostring(p_id).."]".. - "button[1,1.0;1,1.0;back;Back]" + -- 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