-- show a list of all trades -- the player is accessing the trade list yl_speak_up.input_trade_list = function(player, formname, fields) local pname = player:get_player_name() local d_id = yl_speak_up.speak_to[pname].d_id local n_id = yl_speak_up.speak_to[pname].n_id local dialog = yl_speak_up.speak_to[pname].dialog if(not(dialog.trades)) then dialog.trades = {} end -- the player wants to add a new trade if(fields.trade_list_add_trade) then -- show the trade config dialog for a new trade yl_speak_up.show_fs(player, "add_trade_simple", "new") return end -- toggle between view of dialog option trades and trade list trades if(fields.show_dialog_option_trades or fields.show_trade_list) then yl_speak_up.show_fs(player, "trade_list", fields.show_dialog_option_trades) return end -- go back to the main dialog if(fields.finished_trading) then yl_speak_up.show_fs(player, "talk", {n_id = n_id, d_id = d_id}) return end -- normal mode: the player wants to see a particular trade for k,v in pairs(dialog.trades) do if(fields[ k ]) then yl_speak_up.show_fs(player, "trade_simple", k) return end end -- show the inventory of the NPC if(fields.show_inventory) then yl_speak_up.show_fs(player, "inventory") return end -- TODO: and otherwise? end -- show a list of all trades the NPC has to offer -- if show_dialog_option_trades is set: show only those trades that are attached to options of dialogs; -- otherwise show only those trades attached to the trade list yl_speak_up.get_fs_trade_list = function(player, show_dialog_option_trades) if(not(player)) then return "" end local pname = player:get_player_name() -- which NPC is the player talking to? local n_id = yl_speak_up.speak_to[pname].n_id local dialog = yl_speak_up.speak_to[pname].dialog -- do we have all the necessary data? if(not(n_id) or not(dialog.n_npc)) then return "size[6,2]".. "label[0.2,0.5;Ups! This NPC lacks ID or name.]".. "button_exit[2,1.5;1,0.9;exit;Exit]" end -- make sure the NPC has that table defined if(not(dialog.trades)) then dialog.trades = {} end yl_speak_up.load_npc_inventory(n_id) local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(n_id)}) local formspec = {} if(yl_speak_up.may_edit_npc(player, n_id)) then -- allow players with the right priv to switch view between dialog option trades -- and those normal ones in the trade list if(not(show_dialog_option_trades)) then table.insert(formspec, "button[3.0,-0.5;5.0,0.9;show_dialog_option_trades;".. "Show trades attached to dialog options]") else table.insert(formspec, "button[3.0,-0.5;5.0,0.9;show_trade_list;".. "Show trade list trades (player view)]") end else -- do not show trades attached to dialog options for players who cannot edit the NPC show_dialog_option_trades = false end -- arrange the offers in yl_speak_up.trade_max_cols columns horizontally -- and yl_speak_up.trade_max_rows row vertically local row = 0 local col = 0 local anz_trades = 0 -- the order in which the trades appear shall not change each time; -- but lua cannot sort the keys of a table by itself... local sorted_trades = {} for k in pairs(dialog.trades) do table.insert(sorted_trades, k) end table.sort(sorted_trades) -- TODO: handle multiple pages? for i, k in ipairs(sorted_trades) do v = dialog.trades[ k ] if(col < yl_speak_up.trade_max_cols -- needs both to be negated because show_dialog_option_trades will most of the time be nil -- and the actual value of v.d_id isn't of intrest here either and (not(show_dialog_option_trades) == not(v.d_id)) and v.pay and v.pay[1] and v.pay[1] ~= "" and v.buy and v.buy[1] and v.buy[1] ~= "") then local pay_stack = ItemStack(v.pay[1]) local buy_stack = ItemStack(v.buy[1]) -- do not show trades with nonexistant items if( not(minetest.registered_items[ pay_stack:get_name() ]) or not(minetest.registered_items[ buy_stack:get_name() ])) then break end anz_trades = anz_trades + 1 local kstr = tostring(minetest.formspec_escape(k)) table.insert(formspec, "item_image_button["..tostring(1+(col*4))..","..tostring(1+row)..";1,1;".. tostring(v.pay[1])..";"..kstr..";]".. "image_button["..tostring(1.8+(col*4))..","..tostring(1+row)..";1,1;".. "gui_furnace_arrow_bg.png^[transformR270;"..kstr..";]".. "item_image_button["..tostring(2.6+(col*4))..","..tostring(1+row)..";1,1;".. tostring(v.buy[1])..";"..kstr..";]") if(not(npc_inv:contains_item("npc_main", buy_stack))) then table.insert(formspec, "label["..tostring(1.7+(col*4))..","..tostring(1.2+row)..";Sold out]") end row = row + 1 if(row > yl_speak_up.trade_max_rows) then row = 0 col = col + 1 end end end -- if there are no trades, at least print a hint that there could be some here -- (a mostly empty formspec looks too boring and could irritate players) if(anz_trades == 0) then table.insert(formspec, "label[1,1;Sorry. There are currently no offers available.]") end -- button "add trade" for those who can edit the NPC (entering edit mode is not required) -- also add a quick way to access the inventory of the npc if(yl_speak_up.may_edit_npc(player, n_id)) then table.insert(formspec, "button["..tostring(yl_speak_up.trade_max_cols * 4 - 2.2).. ",0.2;2.0,0.9;trade_list_add_trade;Add trade]".. "button["..tostring(yl_speak_up.trade_max_cols * 4 - 4.2).. ",-0.5;4.0,0.9;show_inventory;Show inventory of NPC]") end return "size[".. tostring(yl_speak_up.trade_max_cols * 4)..",".. tostring(yl_speak_up.trade_max_rows + 2).."]".. "button[0.2,0.0;2.0,0.9;finished_trading;Back to talk]".. "label[3.0,0.2;"..tostring(dialog.n_npc).." offers you these trades:]".. table.concat(formspec, "") end