Add trade locking for villagers

This commit is contained in:
Wuzzy 2018-06-06 17:33:14 +02:00
parent 8b95871682
commit 3823a6ba11

View file

@ -4,7 +4,8 @@
--License for code WTFPL and otherwise stated in readmes --License for code WTFPL and otherwise stated in readmes
-- TODO: Per-player trading inventories -- TODO: Per-player trading inventories
-- TODO: Trade locking -- TODO: Particles
-- TODO: 4s Regeneration I after trade unlock
-- intllib -- intllib
local MP = minetest.get_modpath(minetest.get_current_modname()) local MP = minetest.get_modpath(minetest.get_current_modname())
@ -89,18 +90,19 @@ local professions = {
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:white", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:white", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:grey", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:grey", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:silver", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:silver", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:black", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:yellow", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:yellow", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:orange", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:red", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:red", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:magenta", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:purple", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:purple", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:blue", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:blue", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:light_blue", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:cyan", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:brown", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:lime", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:lime", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:green", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:green", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:magenta", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:black", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:cyan", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:pink", 1, 1 } }, { { "mcl_core:emerald", 1, 2 }, { "mcl_wool:pink", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:light_blue", 1, 1 } },
{ { "mcl_core:emerald", 1, 2 }, { "mcl_wool:brown", 1, 1 } },
}, },
}, },
}, },
@ -393,18 +395,26 @@ local set_trade = function(trader, player, inv, concrete_tradenum)
end end
local function show_trade_formspec(playername, trader, is_disabled) local function show_trade_formspec(playername, trader, tradenum)
if not trader._trades then
return
end
if not tradenum then
tradenum = 1
end
local trades = minetest.deserialize(trader._trades)
local trade = trades[tradenum]
local profession = professions[trader._profession].name local profession = professions[trader._profession].name
local disabled = "" local disabled_img = ""
if is_disabled then if trade.locked then
disabled = "image[4.3,2.52;1,1;mobs_mc_trading_formspec_disabled.png]" disabled_img = "image[4.3,2.52;1,1;mobs_mc_trading_formspec_disabled.png]"
end end
local formspec = local formspec =
"size[9,8.75]".. "size[9,8.75]"
"background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]".. .."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]"
disabled.. ..disabled_img
mcl_vars.inventory_header.. ..mcl_vars.inventory_header
"label[4,0;"..minetest.formspec_escape(profession).."]" .."label[4,0;"..minetest.formspec_escape(profession).."]"
.."list[current_player;main;0,4.5;9,3;9]" .."list[current_player;main;0,4.5;9,3;9]"
.."list[current_player;main;0,7.74;9,1;]" .."list[current_player;main;0,7.74;9,1;]"
.."button[1,1;0.5,1;prev_trade;<]" .."button[1,1;0.5,1;prev_trade;<]"
@ -422,17 +432,32 @@ local function show_trade_formspec(playername, trader, is_disabled)
end end
local update_offer = function(inv, player, sound) local update_offer = function(inv, player, sound)
local name = player:get_player_name()
local trader = player_trading_with[name]
local tradenum = player_tradenum[name]
if not trader or not tradenum then
return false
end
local trades = minetest.deserialize(trader._trades)
if not trades then
return false
end
local trade = trades[tradenum]
if not trade then
return false
end
if inv:contains_item("input", inv:get_stack("wanted", 1)) and if inv:contains_item("input", inv:get_stack("wanted", 1)) and
(inv:get_stack("wanted", 2):is_empty() or inv:contains_item("input", inv:get_stack("wanted", 2))) then (inv:get_stack("wanted", 2):is_empty() or inv:contains_item("input", inv:get_stack("wanted", 2))) and
(trade.locked == false) then
inv:set_stack("output", 1, inv:get_stack("offered", 1)) inv:set_stack("output", 1, inv:get_stack("offered", 1))
if sound then if sound then
minetest.sound_play("mobs_mc_villager_accept", {to_player = player:get_player_name()}) minetest.sound_play("mobs_mc_villager_accept", {to_player = name})
end end
return true return true
else else
inv:set_stack("output", 1, ItemStack("")) inv:set_stack("output", 1, ItemStack(""))
if sound then if sound then
minetest.sound_play("mobs_mc_villager_deny", {to_player = player:get_player_name()}) minetest.sound_play("mobs_mc_villager_deny", {to_player = name})
end end
return false return false
end end
@ -602,10 +627,12 @@ mobs:register_mob("mobs_mc:villager", {
local trade = trades[tradenum] local trade = trades[tradenum]
local unlock_stuff = false local unlock_stuff = false
if not trade.traded_once then if not trade.traded_once then
-- Unlock all the things if something was traded
-- for the first time ever
unlock_stuff = true unlock_stuff = true
trade.traded_once = true trade.traded_once = true
elseif math.random(1,5) then elseif trade.trade_counter == 0 and math.random(1,5) == 1 then
-- Otherwise, 20% chance to unlock all trades -- Otherwise, 20% chance to unlock if used freshly reset trade
unlock_stuff = true unlock_stuff = true
end end
if unlock_stuff then if unlock_stuff then
@ -622,12 +649,21 @@ mobs:register_mob("mobs_mc:villager", {
if trade.trade_counter >= 12 then if trade.trade_counter >= 12 then
trade.locked = true trade.locked = true
elseif trade.trade_counter >= 2 then elseif trade.trade_counter >= 2 then
math.random(1, math.random(1, 20)) local r = math.random(1, math.random(1, 9))
trade.locked = true if r == 1 then
trade.locked = true
end
end
trader._trades = minetest.serialize(trades)
if trade.locked then
inv:set_stack("output", 1, "")
show_trade_formspec(name, trader, tradenum)
end end
else else
minetest.log("error", "[mobs_mc] Player took item from trader output but player_trading_with or player_tradenum is nil!") minetest.log("error", "[mobs_mc] Player took item from trader output but player_trading_with or player_tradenum is nil!")
end end
accept = true accept = true
elseif listname == "input" then elseif listname == "input" then
update_offer(inv, player, false) update_offer(inv, player, false)
@ -646,7 +682,7 @@ mobs:register_mob("mobs_mc:villager", {
inv:set_size("offered", 1) inv:set_size("offered", 1)
player_tradenum[name] = 1 player_tradenum[name] = 1
set_trade(self, clicker, inv, player_tradenum[name]) set_trade(self, clicker, inv, player_tradenum[name], player_tradenum[name])
show_trade_formspec(name, self) show_trade_formspec(name, self)
end, end,
@ -715,7 +751,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade"}) local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade"})
set_trade(trader, player, inv, player_tradenum[name]) set_trade(trader, player, inv, player_tradenum[name])
update_offer(inv, player, false) update_offer(inv, player, false)
show_trade_formspec(name, trader) show_trade_formspec(name, trader, player_tradenum[name])
elseif fields.prev_trade then elseif fields.prev_trade then
local trader = player_trading_with[name] local trader = player_trading_with[name]
if not trader or not trader.object:get_luaentity() then if not trader or not trader.object:get_luaentity() then
@ -729,7 +765,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade"}) local inv = minetest.get_inventory({type="detached", name="mobs_mc:trade"})
set_trade(trader, player, inv, player_tradenum[name]) set_trade(trader, player, inv, player_tradenum[name])
update_offer(inv, player, false) update_offer(inv, player, false)
show_trade_formspec(name, trader) show_trade_formspec(name, trader, player_tradenum[name])
end end
end end
end) end)