yl_speak_up/fs/fs_trade_limit.lua

174 lines
5.6 KiB
Lua

-- handle input to the formspec
yl_speak_up.input_trade_limit = function(player, formname, fields)
local pname = player:get_player_name()
local n_id = yl_speak_up.speak_to[pname].n_id
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
return
end
-- the player has selected an entry - edit it
if(fields and fields["edit_trade_limit"]) then
local selection = minetest.explode_table_event( fields[ "edit_trade_limit" ])
if( selection and selection['row']
and (selection['type'] == 'DCL' or selection['type'] == 'CHG')) then
-- show edit trade limit formspec
yl_speak_up.show_fs(player, "edit_trade_limit", {selected_row = selection['row']})
return
end
end
if(fields and (fields.back or fields.quit)) then
-- back to the normal trade list
yl_speak_up.show_fs(player, "trade_list")
return
end
-- else show this formspec again
yl_speak_up.show_fs(player, "trade_limit")
end
-- show the formspec
yl_speak_up.get_fs_trade_limit = function(player, selected)
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
-- in items, existing amount and limit are collected for display
local items = {}
if(not(dialog) or not(n_id)) then
return "Error. Missing dialog when accessing trade limits."
end
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
return "Error. You have no right to edit this NPC."
end
-- the player has selected an entry - edit it
-- make sure all necessary entries in the trades table exist
yl_speak_up.setup_trade_limits(dialog)
-- how many items does the NPC have alltogether?
-- there may be more than one stack of the same type; store amount
local counted_inv = yl_speak_up.count_npc_inv(n_id)
for k,v in pairs(counted_inv) do
yl_speak_up.insert_trade_item_limitation(items, k, 1, v)
end
-- items that are part of any of the trades may also be subject to limits; store item names
for trade_id, trade_data in ipairs(dialog.trades) do
if(trade_id ~= "limits") then
-- what the NPC sells may be subject to limits
local stack = ItemStack(trade_data.buy[1])
yl_speak_up.insert_trade_item_limitation(items, stack:get_name(), 4, true )
-- what the customer pays may be subject to limits as well
stack = ItemStack(trade_data.pay[1])
yl_speak_up.insert_trade_item_limitation(items, stack:get_name(), 4, true )
end
end
-- everything for which there's already a sell_if_more limit
for k,v in pairs(dialog.trades.limits.sell_if_more) do
yl_speak_up.insert_trade_item_limitation( items, k, 2, v )
end
-- everything for which there's already a buy_if_less limit
for k,v in pairs(dialog.trades.limits.buy_if_less ) do
yl_speak_up.insert_trade_item_limitation( items, k, 3, v )
end
-- all items for which limitations might possibly be needed have been collected;
-- now display them
local formspec = {'size[18,12]',
'button[0.5,11.1;17,0.8;back;Back]',
'label[7.0,0.5;List of trade limits]',
'label[0.5,1.0;If you do not set any limits, your NPC will buy and sell as many '..
'items as his inventory allows.\n',
'If you set \'Will sell if more than this\', your NPC '..
'will only sell if he will have enough left after the trade,\n',
'and if you set \'Will buy if less than this\', he will '..
'only buy items as long as he will not end up with more than '..
'this.]',
'tablecolumns[',
'text,align=left;',
'color;text,align=right;',
'color;text,align=center;',
'text,align=right;',
'color;text,align=center;',
'text,align=right;',
'color;text,align=left]',
'table[0.1,2.3;17.8,8.5;edit_trade_limit;',
'Description:,',
'#FFFFFF,NPC has:,',
'#FFFFFF,Will sell if more than this:,,',
'#FFFFFF,Will buy if less than this:,,',
'#EEEEEE,Item string:,'
}
-- the table event selection returns a row index - we need to translate that to our table
local item_list = {}
for k,v in pairs( items ) do
table.insert(item_list, k)
end
-- avoid total chaos by sorting this list
table.sort(item_list)
local row = 2
for i, k in ipairs( item_list ) do
local v = items[k]
local c1 = '#FF0000'
if( v[1] > 0 ) then
c1 = '#BBBBBB'
end
local t1 = 'sell always'
local c2 = '#44EE44'
if( v[2] > 0 ) then
c2 = '#00FF00'
t1 = 'sell if more than:'
end
local t2 = 'buy always'
local c3 = '#EEEE44'
if( v[3] ~= 10000 ) then
c3 = '#FFFF00'
t2 = 'buy if less than:'
end
local desc = ''
if( k =="" ) then
desc = '<free inventory slot>'
k = '<nothing>'
elseif( minetest.registered_items[ k ]
and minetest.registered_items[ k ].description ) then
desc = minetest.registered_items[ k ].description
end
table.insert(formspec,
desc..','..
c1..','.. tostring( v[1] )..','..
c2..','..t1..','..tostring( v[2] )..','..
c3..','..t2..','..tostring( v[3] )..',#EEEEEE,'..k..',')
end
-- we need to store the table somewhere so that we know which limit is edited
yl_speak_up.speak_to[pname].trade_limit_items = items
yl_speak_up.speak_to[pname].trade_limit_item_list = item_list
local selected_row = 1
if(selected and selected ~= "") then
selected_row = math.max(1, table.indexof(item_list, selected) + 1)
end
table.insert(formspec, ";"..selected_row.."]")
return table.concat(formspec, '')
end
yl_speak_up.get_fs_trade_limit_wrapper = function(player, param)
if(not(param)) then
param = {}
end
return yl_speak_up.get_fs_trade_limit(player, param.selected)
end
yl_speak_up.register_fs("trade_limit",
yl_speak_up.input_trade_limit,
yl_speak_up.get_fs_trade_limit_wrapper,
-- no special formspec required:
nil
)