Villagers offer more trades at once

This commit is contained in:
Wuzzy 2022-05-31 19:40:28 +02:00
parent aa2b766b40
commit a33c5ab445
2 changed files with 101 additions and 10 deletions

View File

@ -3,6 +3,9 @@
-- Modded by KaadmY
local S = minetest.get_translator("mobs")
-- How many different trades an NPC offers
local NPC_TRADES_COUNT = 4
local get_item_fuel_burntime = function(itemstring)
local input = {
method = "fuel",
@ -160,6 +163,8 @@ for _, npc_type_table in pairs(npc_types) do
return
end
local npc_type = self.npc_type
local iname = item:get_name()
if npc_type ~= "blacksmith" and (minetest.get_item_group(iname, "sword") > 0 or minetest.get_item_group(iname, "spear") > 0) then
say(S("Get this thing out of my face!"), name)
@ -176,12 +181,25 @@ for _, npc_type_table in pairs(npc_types) do
return
end
if not self.npc_trade then
self.npc_trade = util.choice_element(
gold.trades[self.npc_type], gold.pr)
if not self.npc_trades or not self.npc_trade or not self.npc_trade_index then
self.npc_trades = {}
local possible_trades = table.copy(gold.trades[npc_type])
for t=1, NPC_TRADES_COUNT do
if #possible_trades == 0 then
break
end
local trade, index = util.choice_element(possible_trades, gold.pr)
table.insert(self.npc_trades, trade)
possible_trades[index] = nil
end
self.npc_trade_index = 1
if not self.npc_trade then
self.npc_trade = self.npc_trades[self.npc_trade_index]
end
minetest.log("action", "[mobs] NPC trades of NPC at "..minetest.pos_to_string(self.object:get_pos(), 1).." initialized")
end
if not gold.trade(self.npc_trade, self.npc_type, clicker) then
if not gold.trade(self.npc_trade, npc_type, clicker, self.npc_trade_index, self.npc_trades) then
-- Good mood: Give hint or funny text
if hp >= self.hp_max-7 then

View File

@ -11,6 +11,9 @@ gold.pr = PseudoRandom(mapseed+8732)
gold.trades = {}
gold.trade_names = {}
local TRADE_FORMSPEC_OFFSET = 2
local GOLD_COLOR = "#FFFF00FF"
if minetest.get_modpath("mobs") ~= nil then
gold.trades["farmer"] = {
-- seeds/plants
@ -177,14 +180,14 @@ local form_trading = ""
form_trading = form_trading .. rp_formspec.get_page("rp_default:notabs_2part")
form_trading = form_trading .. "list[current_player;gold_trade_out;4.75,2.25;1,1;]"
form_trading = form_trading .. rp_formspec.get_hotbar_itemslot_bg(4.75, 2.25, 1, 1)
form_trading = form_trading .. "list[current_player;main;0.25,4.75;8,4;]"
form_trading = form_trading .. rp_formspec.get_hotbar_itemslot_bg(0.25, 4.75, 8, 1)
form_trading = form_trading .. rp_formspec.get_itemslot_bg(0.25, 5.75, 8, 3)
form_trading = form_trading .. "container["..TRADE_FORMSPEC_OFFSET..",0]"
form_trading = form_trading .. "list[current_player;gold_trade_out;4.75,2.25;1,1;]"
form_trading = form_trading .. rp_formspec.get_hotbar_itemslot_bg(4.75, 2.25, 1, 1)
form_trading = form_trading .. "list[current_player;gold_trade_in;1.25,2.25;2,1;]"
form_trading = form_trading .. rp_formspec.get_itemslot_bg(1.25, 2.25, 2, 1)
@ -197,11 +200,21 @@ form_trading = form_trading .. "image[3.5,1.25;1,1;ui_arrow_bg.png^[transformR27
form_trading = form_trading .. "image[3.5,2.25;1,1;ui_arrow.png^[transformR270]"
form_trading = form_trading .. rp_formspec.button(1.25, 3.25, 2, 1, "trade", S("Trade"))
form_trading = form_trading .. rp_formspec.button_exit(5.25, 3.25, 2, 1, "cancel", S("Cancel"))
form_trading = form_trading .. rp_formspec.button_exit(4.25, 3.25, 2, 1, "cancel", S("Cancel"))
form_trading = form_trading .. "container_end[]"
rp_formspec.register_page("rp_gold_trading_book", form_trading)
function gold.trade(trade, trade_type, player)
-- Remember with which traders the players trade
local active_tradings = {}
-- Open the trading formspec that allows players to trade with NPCs.
-- * trade: Single trade table from gold.trades table
-- * trade_type: Trader type name
-- * player: Player object of player who trades
-- * trade_index: Index of current active trade in all of the available trades for this trader
-- * all_trades: List of all trades available by this trader
function gold.trade(trade, trade_type, player, trade_index, all_trades)
local name = player:get_player_name()
local item = player:get_wielded_item()
@ -209,6 +222,8 @@ function gold.trade(trade, trade_type, player)
local item_alias = minetest.registered_aliases[itemname]
if itemname ~= "rp_gold:trading_book" and item_alias ~= "rp_gold:trading_book" then return end
active_tradings[name] = { all_trades = all_trades, trade_index = trade_index, trade_type = trade_type }
local inv = player:get_inventory()
if inv:get_size("gold_trade_wanted") ~= 2 then
@ -239,9 +254,46 @@ function gold.trade(trade, trade_type, player)
local form = rp_formspec.get_page("rp_gold_trading_book")
form = form .. "label[0.25,0.25;"..minetest.formspec_escape(trade_name).."]"
local trades_listed = {}
local print_item = function(itemstring)
local stack = ItemStack(itemstring)
local name = stack:get_short_description()
if stack:get_name() == "rp_gold:ingot_gold" then
-- Short for "Gold Ingot"
name = S("G")
name = minetest.colorize("#FF0000", name)
end
local count = stack:get_count()
local out
if stack:get_name() == "rp_gold:ingot_gold" then
out = S("@1 @2", count, name)
elseif count > 1 then
out = S("@1×@2", count, name)
else
out = name
end
return out
end
for t=1, #all_trades do
local take, give
if all_trades[t][2] == "" then
take = print_item(all_trades[t][1])
else
take = S("@1 + @2", print_item(all_trades[t][1]), print_item(all_trades[t][2]))
end
give = print_item(all_trades[t][3])
local entry = S("@1 → @2", take, give)
table.insert(trades_listed, minetest.formspec_escape(entry))
end
local trades_listed_str = table.concat(trades_listed, ",")
form = form .. "tablecolumns[text]"
form = form .. "table[0.15,1.25;3,2.5;tradelist;"..trades_listed_str..";"..trade_index.."]"
form = form .. "container["..TRADE_FORMSPEC_OFFSET..",0]"
form = form .. rp_formspec.fake_itemstack(1.25, 1.25, trade_wanted1)
form = form .. rp_formspec.fake_itemstack(2.25, 1.25, trade_wanted2)
form = form .. rp_formspec.fake_itemstack(4.75, 1.25, ItemStack(trade[3]))
form = form .. "container_end[]"
minetest.show_formspec(name, "rp_gold:trading_book", form)
@ -298,16 +350,32 @@ end
minetest.register_on_player_receive_fields(
function(player, form_name, fields)
local name = player:get_player_name()
if form_name ~= "rp_gold:trading_book" then
active_tradings[name] = nil
return
end
local inv = player:get_inventory()
if fields.cancel or fields.quit then
clear_trading_slots(inv, player:get_pos())
active_tradings[name] = nil
return
end
if fields.tradelist then
local tdata = minetest.explode_table_event(fields.tradelist)
if tdata.type == "CHG" or tdata.type == "DCL" then
if active_tradings[name] ~= nil then
local trade_index = tdata.row
local all_trades = active_tradings[name].all_trades
local trade_type = active_tradings[name].trade_type
local trade = all_trades[trade_index]
gold.trade(trade, trade_type, player, trade_index, all_trades)
end
end
return
end
if fields.trade then
local item = player:get_wielded_item()
@ -503,6 +571,11 @@ achievements.register_achievement(
dignode = "rp_gold:stone_with_gold",
})
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
active_tradings[name] = nil
end)
if minetest.settings:get_bool("rp_testing_enable", false) == true then
-- Check if all specified items are valid
minetest.register_on_mods_loaded(function()