2015-07-29 20:42:45 +01:00

200 lines
7.0 KiB
Lua

local function show_formspec(self, player_name, selected_id)
local inv = minetest.get_inventory({type="detached", name="npcf_"..self.npc_id})
if not inv then
return
end
local trades = {}
for i,v in ipairs(self.metadata.trades) do
local avail = self.metadata.inventory[v.item_sell] or 0
local item_buy = minetest.registered_items[v.item_buy].description or v.item_buy
local item_sell = minetest.registered_items[v.item_sell].description or v.item_sell
if item_buy and item_sell then
local str = item_buy.." ("..v.qty_buy..") - "..item_sell.." ("..v.qty_sell..") ["..avail.."]"
trades[i] = minetest.formspec_escape(str)
end
end
local tradelist = table.concat(trades, ",") or ""
local select = ""
local input = inv:get_stack("input", 1)
local output = inv:get_stack("output", 1)
output:clear()
if selected_id == nil and input:get_count() > 0 then
for i,v in ipairs(self.metadata.trades) do
if v.item_buy == input:get_name() then
selected_id = i
break
end
end
end
if selected_id then
local trade = self.metadata.trades[selected_id]
if trade then
if self.owner == player_name then
local qty_sell = self.metadata.inventory[trade.item_sell] or 0
local qty_buy = self.metadata.inventory[trade.item_buy] or 0
output = ItemStack(trade.item_sell.." "..qty_sell)
input = ItemStack(trade.item_buy.." "..qty_buy)
inv:set_stack("input", 1, input)
elseif input:get_name() == trade.item_buy then
local avail = self.metadata.inventory[trade.item_sell] or 0
local req = math.floor(input:get_count() / trade.qty_buy) * trade.qty_sell
if req > avail then
req = avail
end
output = ItemStack(trade.item_sell.." "..req)
end
select = selected_id
end
end
inv:set_stack("output", 1, output)
local formspec = "size[8,10]"
.."list[detached:npcf_"..self.npc_id..";input;0.0,3.7;1,1;]"
.."list[detached:npcf_"..self.npc_id..";output;7.0,3.7;1,1;]"
.."list[current_player;main;0.0,5.0;8.0,4.0;]"
if self.owner == player_name then
formspec = formspec
.."textlist[0.0,0.0;5.7,3.5;inv_select;"..tradelist..";"..select..";]"
.."field[0.3,9.7;2.0,0.5;item_buy;Item Buy;]"
.."field[2.3,9.7;1.0,0.5;qty_buy;Qty;]"
.."field[3.3,9.7;2.0,0.5;item_sell;Item Sell;]"
.."field[5.3,9.7;1.0,0.5;qty_sell;Qty;]"
.."button[6.0,9.4;2.0,0.5;trade_add;Add Trade]"
.."list[detached:npcf_"..self.npc_id..";stock;3.5,3.7;1,1;]"
if select ~= "" then
formspec = formspec.."button[6.0,0.0;2.0,0.5;trade_delete_"..select..";Del Trade]"
end
else
formspec = formspec
.."textlist[0.0,0.0;7.5,3.5;inv_select;"..tradelist..";"..select..";]"
.."button_exit[3.0,4.0;2.0,0.5;trade_accept;Accept]"
end
npcf:show_formspec(player_name, self.npc_id, formspec)
end
local function get_field_qty(str)
if str then
local qty = math.floor(tonumber(str) or 1)
if qty > 0 then
return qty
end
end
return 1
end
local function is_valid_item(item)
if item then
if item ~= "" then
return minetest.registered_items[item]
end
end
end
npcf:register_npc("npcf_trader:npc" ,{
description = "Trader NPC",
textures = {"npcf_trader_skin.png"},
metadata = {
trades = {},
inventory = {},
},
inventory_image = "npcf_trader_inv.png",
on_activate = function(self)
local inv = minetest.create_detached_inventory("npcf_"..self.npc_id, {
on_put = function(inv, listname, index, stack, player)
local player_name = player:get_player_name()
if listname == "stock" and self.owner == player_name then
local item = stack:get_name()
if self.metadata.inventory[item] then
self.metadata.inventory[item] = self.metadata.inventory[item] + stack:get_count()
inv:remove_item("stock", stack)
end
end
show_formspec(self, player_name, nil)
end,
on_take = function(inv, listname, index, stack, player)
if self.owner == player:get_player_name() and (listname == "input" or listname == "output") then
local item = stack:get_name()
if self.metadata.inventory[item] then
self.metadata.inventory[item] = self.metadata.inventory[item] - stack:get_count()
end
end
show_formspec(self, player:get_player_name(), nil)
end,
allow_put = function(inv, listname, index, stack, player)
if listname == "stock" or (listname == "input" and self.owner ~= player:get_player_name()) then
return stack:get_count()
end
return 0
end,
allow_take = function(inv, listname, index, stack, player)
if listname == "input" or self.owner == player:get_player_name() then
return stack:get_count()
end
return 0
end,
})
inv:set_size("input", 1)
inv:set_size("output", 1)
inv:set_size("stock", 1)
end,
on_rightclick = function(self, clicker)
show_formspec(self, clicker:get_player_name(), nil)
end,
on_receive_fields = function(self, fields, sender)
local player_name = sender:get_player_name()
if fields.trade_add and self.owner == player_name then
if is_valid_item(fields.item_buy) and is_valid_item(fields.item_sell) then
local trade = {}
trade["item_buy"] = fields.item_buy
trade["qty_buy"] = get_field_qty(fields.qty_buy)
trade["item_sell"] = fields.item_sell
trade["qty_sell"] = get_field_qty(fields.qty_sell)
table.insert(self.metadata.trades, trade)
self.metadata.inventory[fields.item_buy] = self.metadata.inventory[fields.item_buy] or 0
self.metadata.inventory[fields.item_sell] = self.metadata.inventory[fields.item_sell] or 0
show_formspec(self, player_name, nil)
else
minetest.chat_send_player(player_name, "Error: Invalid Item Name!")
end
elseif fields.inv_select then
local id = tonumber(string.match(fields.inv_select, "%d+"))
if id then
show_formspec(self, player_name, id)
end
elseif fields.trade_accept then
local inv = minetest.get_inventory({type="detached", name="npcf_"..self.npc_id})
local input = inv:get_stack("input", 1)
local output = inv:get_stack("output", 1)
local item_buy = input:get_name()
local item_sell = output:get_name()
local qty_buy = input:get_count()
local qty_sell = output:get_count()
local max = output:get_stack_max()
if qty_buy > 0 and qty_sell > 0 and max > 0 then
self.metadata.inventory[item_buy] = self.metadata.inventory[item_buy] + qty_buy
self.metadata.inventory[item_sell] = self.metadata.inventory[item_sell] - qty_sell
while qty_sell > max do
sender:get_inventory():add_item("main", item_sell.." "..max)
qty_sell = qty_sell - max
end
if qty_sell > 0 then
sender:get_inventory():add_item("main", item_sell.." "..qty_sell)
end
input:clear()
inv:set_stack("input", 1, input)
end
elseif self.owner == player_name then
for k,_ in pairs(fields) do
selected_id = k:gsub("trade_delete_", "")
if selected_id ~= k and self.metadata.trades[tonumber(selected_id)] then
local inv = minetest.get_inventory({type="detached", name="npcf_"..self.npc_id})
inv:set_stack("input", 1, ItemStack(""))
table.remove(self.metadata.trades, selected_id)
show_formspec(self, player_name, nil)
break
end
end
end
end,
})