yl_speak_up/api/api_trade.lua

138 lines
4.4 KiB
Lua

-----------------------------------------------------------------------------
-- limits for trading: maximum and minimum stock to keep
-----------------------------------------------------------------------------
-- sometimes players may not want the NPC to sell *all* of their stock,
-- or not let the NPC buy endless amounts of something when only a limited
-- amount is needed
-----------------------------------------------------------------------------
-- helper function: make sure all necessary entries in the trades table exist
yl_speak_up.setup_trade_limits = function(dialog)
if(not(dialog)) then
dialog = {}
end
if(not(dialog.trades)) then
dialog.trades = {}
end
if(not(dialog.trades.limits)) then
dialog.trades.limits = {}
end
if(not(dialog.trades.limits.sell_if_more)) then
dialog.trades.limits.sell_if_more = {}
end
if(not(dialog.trades.limits.buy_if_less)) then
dialog.trades.limits.buy_if_less = {}
end
return dialog
end
-- helper function: count how many items the NPC has in his inventory
-- empty stacks are counted under the key "";
-- for other items, the amount of items of each type is counted
yl_speak_up.count_npc_inv = function(n_id)
if(not(n_id)) then
return {}
end
-- the NPC's inventory
local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(n_id)})
if(not(npc_inv)) then
return {}
end
local anz = npc_inv:get_size('npc_main')
local stored = {}
for i=1, anz do
local stack = npc_inv:get_stack('npc_main', i )
local name = stack:get_name()
local count = stack:get_count()
-- count empty stacks
if(name=="") then
count = 1
end
-- count how much of each item is there
if(not(stored[ name ])) then
stored[ name ] = count
else
stored[ name ] = stored[ name ] + count
end
end
return stored
end
-- helper function: update the items table so that it reflects a limitation
-- items is a table (list) with these entries:
-- [1] 0 in stock;
-- [2] sell if more than 0;
-- [3] buy if less than 10000;
-- [4] item is part of a trade offer
yl_speak_up.insert_trade_item_limitation = function( items, k, i, v )
if( i<1 or i>4) then
return;
end
if( not( items[ k ] )) then
-- 0 in stock; sell if more than 0; buy if less than 10000; item is part of a trade offer
items[ k ] = { 0, 0, 10000, false, #items }
end
items[ k ][ i ] = v
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?
-- used in fs_trade_via_buy_button.lua and fs_trade_list.lua
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 fs_trade_list.lua
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 = {}
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
end