show stock in trade_via_buy_button
This commit is contained in:
parent
d5fe15a7c7
commit
7adabf312d
@ -12,25 +12,57 @@ yl_speak_up.get_trade_item_desc = function(item)
|
||||
end
|
||||
|
||||
|
||||
-- helper function; returns how often a trade can be done
|
||||
-- stock_buy how much of the buy stack does the NPC have in storage?
|
||||
-- stock_pay how much of the price stack does the NPC have in storage?
|
||||
-- buy_stack stack containing the item the NPC sells
|
||||
-- pay_stack stack containing the price for said item
|
||||
-- min_storage how many items of the buy stack items shall the NPC keep?
|
||||
-- max_storage how many items of the pay stack items can the NPC accept?
|
||||
yl_speak_up.get_trade_amount_available = function(stock_buy, stock_pay, buy_stack, pay_stack, min_storage, max_storage)
|
||||
local stock = 0
|
||||
-- the NPC shall not sell more than this
|
||||
if(min_storage and min_storage > 0) then
|
||||
stock_buy = math.max(0, stock_buy - min_storage)
|
||||
end
|
||||
stock = math.floor(stock_buy / buy_stack:get_count())
|
||||
-- the NPC shall not buy more than this
|
||||
if(max_storage and max_storage < 10000) then
|
||||
stock_pay = math.min(max_storage - stock_pay, 10000)
|
||||
stock = math.min(stock, math.floor(stock_pay / pay_stack:get_count()))
|
||||
end
|
||||
return stock
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- helper function; also used by trade_list.lua
|
||||
yl_speak_up.get_sorted_trade_id_list = function(dialog)
|
||||
yl_speak_up.get_sorted_trade_id_list = function(dialog, show_dialog_option_trades)
|
||||
-- make sure all fields exist
|
||||
yl_speak_up.setup_trade_limits(dialog)
|
||||
local keys = {}
|
||||
for k, v in pairs(dialog.trades) do
|
||||
if(k ~= "limits" and k ~= "") then
|
||||
-- structure of the indices: sell name amount for name amount
|
||||
local parts = string.split(k, " ")
|
||||
if(parts and #parts == 6 and parts[4] == "for"
|
||||
and v.pay and v.pay[1] ~= "" and v.pay[1] == parts[5].." "..parts[6]
|
||||
and v.buy and v.buy[1] ~= "" and v.buy[1] == parts[2].." "..parts[3]
|
||||
and minetest.registered_items[parts[5]]
|
||||
and minetest.registered_items[parts[2]]
|
||||
and tonumber(parts[6]) > 0
|
||||
and tonumber(parts[3]) > 0) then
|
||||
if(show_dialog_option_trades) then
|
||||
for k, v in pairs(dialog.trades) do
|
||||
if(k ~= "limits" and k ~= "" and v.d_id) then
|
||||
table.insert(keys, k)
|
||||
end
|
||||
end
|
||||
else
|
||||
for k, v in pairs(dialog.trades) do
|
||||
if(k ~= "limits" and k ~= "") then
|
||||
-- structure of the indices: sell name amount for name amount
|
||||
local parts = string.split(k, " ")
|
||||
if(parts and #parts == 6 and parts[4] == "for"
|
||||
and v.pay and v.pay[1] ~= "" and v.pay[1] == parts[5].." "..parts[6]
|
||||
and v.buy and v.buy[1] ~= "" and v.buy[1] == parts[2].." "..parts[3]
|
||||
and minetest.registered_items[parts[5]]
|
||||
and minetest.registered_items[parts[2]]
|
||||
and tonumber(parts[6]) > 0
|
||||
and tonumber(parts[3]) > 0) then
|
||||
table.insert(keys, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(keys)
|
||||
return keys
|
||||
@ -42,13 +74,13 @@ yl_speak_up.input_trade_via_buy_button = function(player, formname, fields)
|
||||
|
||||
if(fields.buy_directly) then
|
||||
local trade_id = yl_speak_up.speak_to[pname].trade_id
|
||||
local error_msg = yl_speak_up.check_trade_via_buy_button(player, trade_id, true)
|
||||
local res = yl_speak_up.check_trade_via_buy_button(player, trade_id, true)
|
||||
|
||||
if(error_msg ~= "OK") then
|
||||
if(res.msg ~= "OK") then
|
||||
yl_speak_up.show_fs(player, "msg", {
|
||||
input_to = "yl_speak_up:trade_via_buy_button",
|
||||
formspec = "size[6,2.5]"..
|
||||
"label[0.2,-0.2;"..error_msg.."\nTrade aborted.]"..
|
||||
"label[0.2,-0.2;"..res.msg.."\nTrade aborted.]"..
|
||||
"button[2,1.5;1,0.9;back_from_error_msg;Back]"})
|
||||
return
|
||||
end
|
||||
@ -80,8 +112,23 @@ yl_speak_up.input_trade_via_buy_button = function(player, formname, fields)
|
||||
end
|
||||
-- TODO: delete button if(fields.delete_trade_via_buy_button) then
|
||||
|
||||
-- the owner wants to go back to the trade list from a dialog trade (action) view
|
||||
if(fields.back_to_trade_list_dialog_trade) then
|
||||
yl_speak_up.show_fs(player, "trade_list", true)
|
||||
return
|
||||
-- a dialog trade (action) was displayed; go back to the corresponding dialog
|
||||
elseif(fields.back_to_dialog) then
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
local trade_id = yl_speak_up.speak_to[pname].trade_id
|
||||
local new_d_id = dialog.trades[ trade_id ].d_id
|
||||
yl_speak_up.speak_to[pname].d_id = new_d_id
|
||||
yl_speak_up.speak_to[pname].trade_list = {}
|
||||
yl_speak_up.show_fs(player, "talk") -- TODO parameters
|
||||
return
|
||||
-- show the trade list
|
||||
if(fields.back_to_trade_list or fields.quit
|
||||
elseif(fields.back_to_trade_list or fields.quit
|
||||
or not(yl_speak_up.speak_to[pname].trade_id)) then
|
||||
yl_speak_up.show_fs(player, "trade_list")
|
||||
return
|
||||
@ -96,6 +143,7 @@ end
|
||||
-- if do_trade is false: check only if the trade would be possible and return
|
||||
-- error message if not; return "OK" when trade is possible
|
||||
-- if do_trade is true: if possible, execute the trade; return the same as above
|
||||
-- also returns how many times the trade could be done (stock= ..)
|
||||
yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade)
|
||||
local pname = player:get_player_name()
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
@ -108,11 +156,11 @@ yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade)
|
||||
-- the NPCs' inventory
|
||||
local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(n_id)})
|
||||
if(not(this_trade)) then
|
||||
return "Trade not found."
|
||||
return {msg = "Trade not found.", stock=0}
|
||||
elseif(not(player_inv)) then
|
||||
return "Couldn't find player's inventory."
|
||||
return {msg = "Couldn't find player's inventory.", stock=0}
|
||||
elseif(not(npc_inv)) then
|
||||
return "Couldn't find the NPC's inventory."
|
||||
return {msg = "Couldn't find the NPC's inventory.", stock=0}
|
||||
end
|
||||
-- store which trade we're doing
|
||||
yl_speak_up.speak_to[pname].trade_id = trade_id
|
||||
@ -125,47 +173,62 @@ yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade)
|
||||
|
||||
-- can the NPC provide his part?
|
||||
if(not(npc_inv:contains_item("npc_main", buy_stack))) then
|
||||
return "Out of stock" --"Sorry. "..npc_name.." ran out of stock.\nPlease come back later."
|
||||
return {msg = "Out of stock", stock = 0}
|
||||
-- return {msg = "Sorry. "..npc_name.." ran out of stock.\nPlease come back later.", stock=0}
|
||||
-- has the NPC room for the payment?
|
||||
elseif(not(npc_inv:room_for_item("npc_main", pay_stack))) then
|
||||
return npc_name.." has no room left!"
|
||||
return {npc_name.." has no room left!", stock = 0}
|
||||
-- return "Sorry. "..npc_name.." ran out of inventory space.\n"..
|
||||
-- "There is no room to store your payment!"
|
||||
end
|
||||
|
||||
local counted_npc_inv = yl_speak_up.count_npc_inv(n_id)
|
||||
local stock_pay = counted_npc_inv[ pay_stack:get_name() ] or 0
|
||||
local stock_buy = counted_npc_inv[ buy_stack:get_name() ] or 0
|
||||
-- are there any limits which we have to take into account?
|
||||
local min_storage = dialog.trades.limits.sell_if_more[ buy_stack:get_name() ]
|
||||
local max_storage = dialog.trades.limits.buy_if_less[ pay_stack:get_name() ]
|
||||
if((min_storage and min_storage > 0)
|
||||
or (max_storage and max_storage < 10000)) then
|
||||
local counted_npc_inv = yl_speak_up.count_npc_inv(n_id)
|
||||
local stock_pay = counted_npc_inv[ pay_stack:get_name() ] or 0
|
||||
local stock_buy = counted_npc_inv[ buy_stack:get_name() ] or 0
|
||||
-- trade limit: is enough left after the player buys the item?
|
||||
if( min_storage and min_storage > stock_buy - buy_stack:get_count()) then
|
||||
return "Sorry. "..npc_name.." currently does not want to\nsell that much."..
|
||||
-- return "Stock too low. Only "..tostring(stock_buy)..
|
||||
-- " left, want to keep "..tostring(min_storage).."."
|
||||
return {msg = "Sorry. "..npc_name.." currently does not want to\nsell that much."..
|
||||
" Current stock: "..tostring(stock_buy)..
|
||||
" (min: "..tostring(min_storage).."). Perhaps later?"
|
||||
" (min: "..tostring(min_storage).."). Perhaps later?",
|
||||
stock = 0}
|
||||
-- trade limit: make sure the bought amount does not exceed the desired maximum
|
||||
elseif(max_storage and max_storage < stock_pay + pay_stack:get_count()) then
|
||||
return "Sorry. "..npc_name.." currently does not want to\n"..
|
||||
return {msg = "Sorry. "..npc_name.." currently does not want to\n"..
|
||||
"buy that much."..
|
||||
" Current stock: "..tostring(stock_pay)..
|
||||
" (max: "..tostring(max_storage).."). Perhaps later?"
|
||||
" (max: "..tostring(max_storage).."). Perhaps later?",
|
||||
stock = 0}
|
||||
end
|
||||
-- the NPC shall not sell more than this
|
||||
if(min_storage and min_storage > 0) then
|
||||
stock_buy = math.max(0, stock_buy - min_storage)
|
||||
end
|
||||
end
|
||||
-- how often can this trade be done?
|
||||
local stock = yl_speak_up.get_trade_amount_available(
|
||||
stock_buy, stock_pay,
|
||||
buy_stack, pay_stack,
|
||||
min_storage, max_storage)
|
||||
-- can the player pay?
|
||||
if(not(player_inv:contains_item("main", pay_stack))) then
|
||||
-- both slots will remain empty
|
||||
return "You can't pay the price."
|
||||
return {msg = "You can't pay the price.", stock = stock}
|
||||
elseif(not(player_inv:room_for_item("main", buy_stack))) then
|
||||
-- the player has no room for the sold item; give a warning
|
||||
return "You don't have enough free inventory\nspace to store your purchase."
|
||||
return {msg = "You don't have enough free inventory\nspace to store your purchase.",
|
||||
stock = stock}
|
||||
end
|
||||
|
||||
-- was it a dry run to check if the trade is possible?
|
||||
if(not(do_trade)) then
|
||||
return "OK"
|
||||
return {msg = "OK", stock = stock}
|
||||
end
|
||||
|
||||
-- actually do the trade
|
||||
@ -177,7 +240,7 @@ yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade)
|
||||
-- revert the trade
|
||||
player_inv:add_item("main", payment)
|
||||
npc_inv:add_item("npc_main", sold)
|
||||
return "Sorry. "..npc_name.." accepts only undammaged items."
|
||||
return {msg = "Sorry. "..npc_name.." accepts only undammaged items.", stock = stock}
|
||||
end
|
||||
player_inv:add_item("main", sold)
|
||||
npc_inv:add_item("npc_main", payment)
|
||||
@ -194,7 +257,7 @@ yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade)
|
||||
yl_speak_up.log_change(pname, n_id,
|
||||
"bought "..tostring(pay_stack:to_string())..
|
||||
" for "..tostring(buy_stack:to_string()))
|
||||
return "OK"
|
||||
return {msg = "OK", stock = stock}
|
||||
end
|
||||
|
||||
|
||||
@ -261,12 +324,37 @@ yl_speak_up.get_fs_trade_via_buy_button = function(player, trade_id)
|
||||
buy_name,
|
||||
"]",
|
||||
"image[3.5,2.0;1,1;gui_furnace_arrow_bg.png^[transformR270]",
|
||||
-- go back to the trade list
|
||||
"button[0.2,0.0;8.0,1.0;back_to_trade_list;Back to list]"..
|
||||
"tooltip[back_to_trade_list;Click here once you've traded enough with this "..
|
||||
"NPC and want to get back to the trade list.]"
|
||||
}
|
||||
|
||||
if(not(dialog.trades[ trade_id ].d_id)) then
|
||||
-- go back to the trade list
|
||||
table.insert(formspec, "button[0.2,0.0;8.0,1.0;back_to_trade_list;Back to trade list]")
|
||||
table.insert(formspec, "tooltip[back_to_trade_list;"..
|
||||
"Click here once you've traded enough with this "..
|
||||
"NPC and want to get back to the trade list.]")
|
||||
elseif(true) then
|
||||
-- go back to the trade list
|
||||
table.insert(formspec, "button[0.2,0.0;3.8,1.0;back_to_trade_list_dialog_trade;Back to trade list]")
|
||||
table.insert(formspec, "tooltip[back_to_trade_list_dialog_trade;"..
|
||||
"Click here once you've traded enough with this "..
|
||||
"NPC and want to get back to the trade list.]")
|
||||
-- go back to dialog
|
||||
table.insert(formspec, "button[4.2,0.0;3.8,1.0;back_to_dialog;Back to dialog ")
|
||||
table.insert(formspec, minetest.formspec_escape(dialog.trades[ trade_id ].d_id))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "tooltip[back_to_dialog;"..
|
||||
"Click here once you've traded enough with this "..
|
||||
"NPC and want to get back to talking with the NPC.]")
|
||||
else
|
||||
-- go back to dialog
|
||||
table.insert(formspec, "button[0.2,0.0;8.0,1.0;back_to_dialog;Back to dialog ")
|
||||
table.insert(formspec, minetest.formspec_escape(dialog.trades[ trade_id ].d_id))
|
||||
table.insert(formspec, "]")
|
||||
table.insert(formspec, "tooltip[back_to_dialog;"..
|
||||
"Click here once you've traded enough with this "..
|
||||
"NPC and want to get back to talking with the NPC.]")
|
||||
end
|
||||
|
||||
-- show edit button for the owner if in edit_mode
|
||||
if(yl_speak_up.may_edit_npc(player, n_id)) then
|
||||
-- for trades in trade list: allow delete (new trades can easily be added)
|
||||
@ -280,8 +368,8 @@ yl_speak_up.get_fs_trade_via_buy_button = function(player, trade_id)
|
||||
end
|
||||
|
||||
-- dry-run: test if the trade can be done
|
||||
local trade_possible = yl_speak_up.check_trade_via_buy_button(player, trade_id, false)
|
||||
if(trade_possible == "OK") then
|
||||
local res = yl_speak_up.check_trade_via_buy_button(player, trade_id, false)
|
||||
if(res.msg == "OK") then
|
||||
local buy_str = "Buy"
|
||||
local trade_done = yl_speak_up.speak_to[pname].trade_done
|
||||
if(trade_done and trade_done > 0) then
|
||||
@ -297,12 +385,18 @@ yl_speak_up.get_fs_trade_via_buy_button = function(player, trade_id)
|
||||
table.insert(formspec, "style_type[button;bgcolor=#FF4444]"..
|
||||
"button[0.2,3.5;8.0,1.0;back_from_error_msg;")
|
||||
-- table.insert(formspec, "label[0.5,3.5;")
|
||||
table.insert(formspec, trade_possible)
|
||||
table.insert(formspec, res.msg)
|
||||
table.insert(formspec, ']')
|
||||
-- set the background color for the next buttons back to our normal one
|
||||
table.insert(formspec, 'style_type[button;bgcolor=#a37e45]')
|
||||
-- table.insert(formspec, "label[6.5,2.0;Trade not\npossible.]")
|
||||
end
|
||||
-- how often can this trade be repeated?
|
||||
if(res.stock and res.stock > 0) then
|
||||
table.insert(formspec, "label[6.5,2.0;Trade ")
|
||||
table.insert(formspec, tostring(res.stock))
|
||||
table.insert(formspec, " x\navailable]")
|
||||
end
|
||||
|
||||
table.insert(formspec, "container_end[]"..
|
||||
"real_coordinates[true]"..
|
||||
|
@ -109,7 +109,7 @@ yl_speak_up.get_fs_trade_list = function(player, show_dialog_option_trades)
|
||||
-- the order in which the trades appear shall not change each time;
|
||||
-- but lua cannot sort the keys of a table by itself...
|
||||
-- this function can be found in fs_trade_via_button.lua
|
||||
local sorted_trades = yl_speak_up.get_sorted_trade_id_list(dialog)
|
||||
local sorted_trades = yl_speak_up.get_sorted_trade_id_list(dialog, show_dialog_option_trades)
|
||||
yl_speak_up.speak_to[pname].trade_id_list = sorted_trades
|
||||
|
||||
for i, k in ipairs(sorted_trades) do
|
||||
|
Loading…
Reference in New Issue
Block a user