diff --git a/config.lua b/config.lua index 7ac7078..5a6bd10 100644 --- a/config.lua +++ b/config.lua @@ -53,7 +53,7 @@ yl_speak_up.max_number_of_options_per_dialog = 15 -- how many rows and cols shall be used for the trade overview list? yl_speak_up.trade_max_rows = 10 -yl_speak_up.trade_max_cols = 4 +yl_speak_up.trade_max_cols = 12 -- how many prerequirements can the player define per dialog option? yl_speak_up.max_prerequirements = 12 diff --git a/trade_list.lua b/trade_list.lua index e1a7c0d..287b6cd 100644 --- a/trade_list.lua +++ b/trade_list.lua @@ -34,7 +34,9 @@ yl_speak_up.input_trade_list = function(player, formname, fields) -- normal mode: the player wants to see a particular trade for k,v in pairs(dialog.trades) do - if(fields[ k ]) then + -- the "_" is necessary for the price button so that offer and price + -- button can each have their tooltip *and* lead to the same dialog + if(fields[ k ] or fields[ k.."_" ]) then yl_speak_up.show_fs(player, "trade_simple", k) return end @@ -78,21 +80,152 @@ yl_speak_up.get_fs_trade_list = function(player, show_dialog_option_trades) 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 + if(not(yl_speak_up.may_edit_npc(player, n_id))) then -- do not show trades attached to dialog options for players who cannot edit the NPC show_dialog_option_trades = false end + + local dialog = yl_speak_up.speak_to[pname].dialog + local portrait = yl_speak_up.calculate_portrait(pname, n_id) + + -- show who owns the NPC (and is thus more or less responsible for what it says) + local owner_info = "" + if(yl_speak_up.npc_owner[ n_id ]) then + owner_info = "\n\n(owned by "..minetest.formspec_escape(yl_speak_up.npc_owner[ n_id ])..")" + end + + local fs_version = yl_speak_up.fs_version[pname] + + formspec = { + "size[57,33]", + "position[0,0.45]", + "anchor[0,0.45]", + "no_prepend[]", + "bgcolor[#00000000;false]", + -- Container + + "container[2,0.75]", + -- Background + + "background[0,0;20,23;yl_speak_up_bg_dialog.png;false]", + "background[0,24;54.5,7.5;yl_speak_up_bg_dialog.png;false]", + -- Frame Dialog + + "image[-0.25,-0.25;1,1;yl_speak_up_bg_dialog_tl.png]", + "image[-0.25,22.25;1,1;yl_speak_up_bg_dialog_bl.png]", + "image[19.25,-0.25;1,1;yl_speak_up_bg_dialog_tr.png]", + "image[19.25,22.25;1,1;yl_speak_up_bg_dialog_br.png]", + "image[-0.25,0.75;1,21.5;yl_speak_up_bg_dialog_hl.png]", + "image[19.25,0.75;1,21.5;yl_speak_up_bg_dialog_hr.png]", + "image[0.75,-0.25;18.5,1;yl_speak_up_bg_dialog_vt.png]", + "image[0.75,22.25;18.5,1;yl_speak_up_bg_dialog_vb.png]", + -- Frame Options + + "image[-0.25,23.75;1,1;yl_speak_up_bg_dialog_tl.png]", + "image[-0.25,30.75;1,1;yl_speak_up_bg_dialog_bl.png]", + "image[53.75,23.75;1,1;yl_speak_up_bg_dialog_tr.png]", + "image[53.75,30.75;1,1;yl_speak_up_bg_dialog_br.png]", + "image[-0.25,24.75;1,6;yl_speak_up_bg_dialog_hl.png]", + "image[53.75,24.75;1,6;yl_speak_up_bg_dialog_hr.png]", + "image[0.75,23.75;53,1;yl_speak_up_bg_dialog_vt.png]", + "image[0.75,30.75;53,1;yl_speak_up_bg_dialog_vb.png]", + + "label[0.3,0.6;", + minetest.formspec_escape(dialog.n_npc), + "]", + "label[0.3,1.8;", + minetest.formspec_escape(dialog.n_description)..owner_info, + "]", + "image[15.5,0.5;4,4;", + portrait, + "]", + } + + -- add those things that only exist in formspec_v >= 4 + if(fs_version > 2) then + table.insert(formspec, "style_type[button;bgcolor=#a37e45]") + table.insert(formspec, "style_type[button_exit;bgcolor=#a37e45]") -- Dialog + -- table.insert(formspec, "background[-1,-1;22,25;yl_speak_up_bg_dialog2.png;false]") + -- table.insert(formspec, "background[-1,23;58,10;yl_speak_up_bg_dialog2.png;false]") + -- table.insert(formspec, "style_type[button;bgcolor=#a37e45]") + end + + + local alternate_text = " I can offer you these trades.\n\n".. + "Select one trade and then choose \"buy\" to actually buy something.".. + "\n\nThere may be more trades then those shown in the first row. Please ".. + "look at all my offers [that is, scroll down a bit]!".. + "\n\n[$NPC_NAME$ looks expectantly at you.]" + local active_dialog = {} + active_dialog.d_text = "" + + -- display the window with the text the NPC is saying + if(alternate_text) then + alternate_text = string.gsub(alternate_text, "%$TEXT%$", active_dialog.d_text) + end + -- replace $NPC_NAME$ etc. + local t = minetest.formspec_escape(yl_speak_up.replace_vars_in_text( + (alternate_text or active_dialog.d_text), dialog, pname)) + if(fs_version > 2) then + yl_speak_up.add_formspec_element_with_tooltip_if(formspec, + "hypertext", "0.2,5;19.6,17.8", "d_text", + ""..t.."\n", + t:trim()..";#000000;#FFFFFF", + true) + else + yl_speak_up.add_formspec_element_with_tooltip_if(formspec, + "textarea", "0.2,5;19.6,17.8", "", + ";"..t.."\n", + t:trim(), + true) + end + + + + local pname_for_old_fs = nil + if(fs_version > 2) then + table.insert(formspec, "scrollbaroptions[min=0;max=14;smallstep=1;largestep=2;arrows=show]") + table.insert(formspec, "scrollbar[0.2,24.2;0.2,7;vertical;scr0;0]") + table.insert(formspec, "scroll_container[0,24;56,7;scr0;vertical;1]") + else + if(fs_version < 2) then + -- if the player has an older formspec version + minetest.log( "info", + "[MOD] yl_speak_up: User " .. pname .. " talked to NPC ID n_" .. n_id .. + " with an old formspec version!") + table.insert(formspec, + "box[0.3,20;19,2.6;red]".. + "label[0.7,20.3;"..yl_speak_up.text_version_warning.."]") + -- The up and down buttons are microscopic. Offer some (still small) + -- additional text buttons so that players have a chance to hit them. + table.insert(formspec, "button[49,23.1;6,0.9;button_down;^ Scroll Up ^]") + table.insert(formspec, "button[49,31.5;6,0.9;button_up;v Scroll Down v]") + table.insert(formspec, "button[1,23.1;6,0.9;button_down;^ Scroll Up ^]") + table.insert(formspec, "button[1,31.5;6,0.9;button_up;v Scroll Down v]") + end + -- old formspec versions need to remember somewhere extern how far the player scrolled + pname_for_old_fs = pname + yl_speak_up.speak_to[pname_for_old_fs].counter = 1 + table.insert(formspec, "container[0,24]") + if(fs_version < 2) then + -- very small, ugly, and difficult to hit + table.insert(formspec, "button[0.1,0;1,0.9;button_down;^]") + table.insert(formspec, "button[0.1,7.0;1,0.9;button_up;v]") + else + -- somewhat larger and quite usable (v2 is pretty ok) + table.insert(formspec, "button[0.1,0;1,3;button_down;^\nU\np]") + table.insert(formspec, "button[0.1,3.2;1,4.5;button_up;D\no\nw\nn\nv]") + table.insert(formspec, "button[53.5,0;1,3;button_down;^\nU\np]") + table.insert(formspec, "button[53.5,3.2;1,4.5;button_up;D\no\nw\nn\nv]") + end + end + h = -0.8 + + + + + -- arrange the offers in yl_speak_up.trade_max_cols columns horizontally -- and yl_speak_up.trade_max_rows row vertically local row = 0 @@ -107,13 +240,11 @@ yl_speak_up.get_fs_trade_list = function(player, show_dialog_option_trades) 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)) + if( (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]) @@ -125,25 +256,84 @@ yl_speak_up.get_fs_trade_list = function(player, show_dialog_option_trades) 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]") + local sold_out = not(npc_inv:contains_item("npc_main", buy_stack)) + local color = "#777777" + if(sold_out) then + color = "#333333" + -- still needs to contain kstr so that each button has a diffrent text + kstr = "sold out "..kstr end - row = row + 1 - if(row > yl_speak_up.trade_max_rows) then - row = 0 - col = col + 1 + table.insert(formspec, + "container["..tostring(0.5+(col*4.5))..",".. + tostring(0.3+(row*6)).."]".. + "box[0,0;4.2,5.6;"..color.."]".. + "item_image_button[1.0,0.2;3,3;".. + tostring(v.pay[1])..";"..kstr..";]".. + "item_image_button[2.0,3.4;2,2;".. + -- the "_" at the end is necessary; we need a diffrent name + -- here than kstr as that was used for another button (leading + -- to the same result) just above + tostring(v.buy[1])..";"..kstr.."_;]") + if(sold_out) then + table.insert(formspec, "label[0,1.9;Sold out]\ncontainer_end[]") + else + -- show the price label only when the offer is in stock + table.insert(formspec, "label[0,4.4;Price:]\ncontainer_end[]") + end + col = col + 1 + if(col >= yl_speak_up.trade_max_cols) then + col = 0 + row = row + 1 end end end + h = (row+1) * 6 - 0.6 + h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h, + "show_inventory", + "Access and manage the inventory of the NPC. This is used for adding trade ".. + "items, getting collected payments and managing quest items.", + "Show your inventory (only accessible to owner)!", + true, nil, nil, pname_for_old_fs) + + -- allow players with the right priv to switch view between dialog option trades + -- and those normal ones in the trade list + if(yl_speak_up.may_edit_npc(player, n_id)) then + if(not(show_dialog_option_trades)) then + text = "This is the trade list view (player view). ".. + "Show trades attached to dialog options." + h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h, + "show_dialog_option_trades", + text, text, + true, nil, nil, pname_for_old_fs) + else + text = "These are trades attached to dialog options. ".. + "Show trade list trades (player view)." + h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h, + "show_trade_list", + text, text, + true, nil, nil, pname_for_old_fs) + end + -- button "add trade" for those who can edit the NPC (entering edit mode is not required) + text = "Add a new trade." + h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h, + "trade_list_add_trade", + text, text, + true, nil, nil, pname_for_old_fs) + end + + local text = "That was all. Let's continue talking." + h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h, + "finished_trading", + text, text, + true, nil, nil, pname_for_old_fs) -- button_exit + + h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h, + "button_exit", + yl_speak_up.message_button_option_exit, + yl_speak_up.message_button_option_exit, + true, nil, true, pname_for_old_fs) -- button_exit + -- 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 @@ -151,20 +341,12 @@ yl_speak_up.get_fs_trade_list = function(player, show_dialog_option_trades) "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, "") + if(fs_version > 2) then + table.insert(formspec, "scroll_container_end[]") + else + table.insert(formspec, "container_end[]") + end + table.insert(formspec, "container_end[]") + return table.concat(formspec, "") end