149 lines
5.0 KiB
Lua
149 lines
5.0 KiB
Lua
|
|
local dbg
|
|
if moddebug then dbg=moddebug.dbg("people") else dbg={v1=function() end,v2=function() end,v3=function() end} end
|
|
|
|
-- Find a shop in range of the given position that's dealing in the
|
|
-- item specified. If 'buy' is true, we want to buy, otherwise we
|
|
-- want to sell. Returns shopinfo. (or nil)
|
|
local function near_shop(pos, item, buy)
|
|
local range = {x=4, y=2, z=4}
|
|
local minp = vector.subtract(pos, range)
|
|
local maxp = vector.add(pos, range)
|
|
local shops = minetest.find_nodes_in_area(minp, maxp, {"barrel:shop_barrel"})
|
|
for _, p in pairs(shops) do
|
|
local shopinfo = barrel.get_shopinfo(p)
|
|
if shopinfo and shopinfo.item == item then
|
|
if buy then
|
|
if shopinfo.saleunit > 0 and
|
|
shopinfo.price > 0 and
|
|
shopinfo.stock >= shopinfo.saleunit then
|
|
return shopinfo
|
|
end
|
|
else
|
|
if shopinfo.saleunit > 0 and
|
|
shopinfo.buyprice > 0 then
|
|
return shopinfo
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return nil
|
|
|
|
end
|
|
|
|
local function move_all(srcinv, srclist, destinv, destlist, item)
|
|
local moved_all = true
|
|
local moved_num = 0
|
|
for i=1,srcinv:get_size(srclist) do
|
|
local stk = srcinv:get_stack(srclist, i)
|
|
if not item or stk:get_name() == item then
|
|
if destinv:room_for_item(destlist, stk) then
|
|
moved_num = moved_num + stk:get_count()
|
|
srcinv:set_stack(srclist, i, nil)
|
|
destinv:add_item(destlist, stk)
|
|
else
|
|
moved_all = false
|
|
end
|
|
end
|
|
end
|
|
return moved_all, moved_num
|
|
end
|
|
|
|
|
|
people.actions.buy = function(state)
|
|
if not (state.action.item or state.action.num) then
|
|
dbg.v1(state.ent.name.." has invalid buy action")
|
|
return true, false
|
|
end
|
|
|
|
local shopinfo = near_shop(state.pos, state.action.item, true)
|
|
if not shopinfo then
|
|
dbg.v1(state.ent.name.." is not near an appropriate shop")
|
|
return true, false
|
|
end
|
|
|
|
local yaw = vector.get_yaw(state.pos, shopinfo.pos)
|
|
-- Need to be fuzzy about comparing this, because of the
|
|
-- lua double/minetest float issue
|
|
if math.abs(yaw - state.yaw) > 0.2 then
|
|
dbg.v3(state.ent.name.." turning to face shop")
|
|
state.action = {"face", yaw=yaw, prevaction=state.action}
|
|
return false
|
|
end
|
|
|
|
local shopinv = shopinfo.meta:get_inventory()
|
|
local repeats = math.ceil(state.action.num / shopinfo.saleunit)
|
|
local cashneeded = repeats * shopinfo.price
|
|
|
|
dbg.v3(state.ent.name.." trying to put $"..cashneeded.." into shop")
|
|
if not currency.remove_from_inv(state.ent.inventory, "main", cashneeded) then
|
|
dbg.v1(state.ent.name.." doesn't have enough money to buy")
|
|
return true, false
|
|
end
|
|
-- TODO - the following just assumes there's room for it - really need
|
|
-- to check and roll back, as we do for getting money
|
|
currency.put_to_inv(shopinv, "exchange", cashneeded)
|
|
|
|
local bought = 0
|
|
while repeats > 0 do
|
|
local success, msg = barrel.do_buy(shopinfo.pos)
|
|
if not success then
|
|
dbg.v3(state.ent.name.." failed during buy loop - shop said: "..msg)
|
|
break
|
|
end
|
|
bought = bought + shopinfo.saleunit
|
|
repeats = repeats - 1
|
|
end
|
|
|
|
if not move_all(shopinv, "exchange", state.ent.inventory, "main", nil) then
|
|
dbg.v1(state.ent.name.." couldn't retrieve everything from shop inventory")
|
|
end
|
|
|
|
dbg.v1(state.ent.name.." finished buy action - bought "..bought.." "..state.action.item)
|
|
return true, true
|
|
end
|
|
|
|
people.actions.sell = function(state)
|
|
if not state.action.item then
|
|
dbg.v1(state.ent.name.." has invalid sell action")
|
|
return true, false
|
|
end
|
|
|
|
local shopinfo = near_shop(state.pos, state.action.item, false)
|
|
if not shopinfo then
|
|
dbg.v1(state.ent.name.." is not near an appropriate shop")
|
|
return true, false
|
|
end
|
|
|
|
local yaw = vector.get_yaw(state.pos, shopinfo.pos)
|
|
-- Need to be fuzzy about comparing this, because of the
|
|
-- lua double/minetest float issue
|
|
if math.abs(yaw - state.yaw) > 0.2 then
|
|
dbg.v3(state.ent.name.." turning to face shop")
|
|
state.action = {"face", yaw=yaw, prevaction=state.action}
|
|
return false
|
|
end
|
|
|
|
local shopinv = shopinfo.meta:get_inventory()
|
|
local moved_all, num = move_all(state.ent.inventory, "main",
|
|
shopinv, "exchange", state.action.item)
|
|
if num == 0 then
|
|
dbg.v1(state.ent.name.." failed to put any "..state.action.item.." for sale into the shop")
|
|
return true, false
|
|
end
|
|
local repeats = math.floor(num / shopinfo.saleunit)
|
|
|
|
while repeats > 0 do
|
|
if not barrel.do_sell(shopinfo.pos) then break end
|
|
repeats = repeats - 1
|
|
end
|
|
|
|
if not move_all(shopinv, "exchange", state.ent.inventory, "main") then
|
|
dbg.v1(state.ent.name.." couldn't retrieve everything from shop inventory")
|
|
end
|
|
|
|
dbg.v1(state.ent.name.." finished sell action")
|
|
return true, true
|
|
end
|
|
|