forked from Sokomine/yl_speak_up
		
	show stock in trade_via_buy_button
This commit is contained in:
		
							parent
							
								
									d5fe15a7c7
								
							
						
					
					
						commit
						7adabf312d
					
				| @ -12,25 +12,57 @@ yl_speak_up.get_trade_item_desc = function(item) | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| -- helper function; returns how often a trade can be done | ||||
| -- 	stock_buy	how much of the buy stack does the NPC have in storage? | ||||
| -- 	stock_pay	how much of the price stack does the NPC have in storage? | ||||
| -- 	buy_stack	stack containing the item the NPC sells | ||||
| -- 	pay_stack	stack containing the price for said item | ||||
| -- 	min_storage	how many items of the buy stack items shall the NPC keep? | ||||
| -- 	max_storage	how many items of the pay stack items can the NPC accept? | ||||
| yl_speak_up.get_trade_amount_available = function(stock_buy, stock_pay, buy_stack, pay_stack, min_storage, max_storage) | ||||
| 	local stock = 0 | ||||
| 	-- the NPC shall not sell more than this | ||||
| 	if(min_storage and min_storage > 0) then | ||||
| 		stock_buy = math.max(0, stock_buy - min_storage) | ||||
| 	end | ||||
| 	stock = math.floor(stock_buy / buy_stack:get_count()) | ||||
| 	-- the NPC shall not buy more than this | ||||
| 	if(max_storage and max_storage < 10000) then | ||||
| 		stock_pay = math.min(max_storage - stock_pay, 10000) | ||||
| 		stock = math.min(stock, math.floor(stock_pay / pay_stack:get_count())) | ||||
| 	end | ||||
| 	return stock | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| -- helper function; also used by trade_list.lua | ||||
| yl_speak_up.get_sorted_trade_id_list = function(dialog) | ||||
| yl_speak_up.get_sorted_trade_id_list = function(dialog, show_dialog_option_trades) | ||||
| 	-- make sure all fields exist | ||||
| 	yl_speak_up.setup_trade_limits(dialog) | ||||
| 	local keys = {} | ||||
| 	for k, v in pairs(dialog.trades) do | ||||
| 		if(k ~= "limits" and k ~= "") then | ||||
| 			-- structure of the indices: sell name amount for name amount | ||||
| 			local parts = string.split(k, " ") | ||||
| 			if(parts and #parts == 6 and parts[4] == "for" | ||||
| 			  and v.pay and v.pay[1] ~= "" and v.pay[1] == parts[5].." "..parts[6] | ||||
| 			  and v.buy and v.buy[1] ~= "" and v.buy[1] == parts[2].." "..parts[3] | ||||
| 			  and minetest.registered_items[parts[5]] | ||||
| 			  and minetest.registered_items[parts[2]] | ||||
| 			  and tonumber(parts[6]) > 0 | ||||
| 			  and tonumber(parts[3]) > 0) then | ||||
| 	if(show_dialog_option_trades) then | ||||
| 		for k, v in pairs(dialog.trades) do | ||||
| 			if(k ~= "limits" and k ~= "" and v.d_id) then | ||||
| 				table.insert(keys, k) | ||||
| 			end | ||||
| 		end | ||||
| 	else | ||||
| 		for k, v in pairs(dialog.trades) do | ||||
| 			if(k ~= "limits" and k ~= "") then | ||||
| 				-- structure of the indices: sell name amount for name amount | ||||
| 				local parts = string.split(k, " ") | ||||
| 				if(parts and #parts == 6 and parts[4] == "for" | ||||
| 				  and v.pay and v.pay[1] ~= "" and v.pay[1] == parts[5].." "..parts[6] | ||||
| 				  and v.buy and v.buy[1] ~= "" and v.buy[1] == parts[2].." "..parts[3] | ||||
| 				  and minetest.registered_items[parts[5]] | ||||
| 				  and minetest.registered_items[parts[2]] | ||||
| 				  and tonumber(parts[6]) > 0 | ||||
| 				  and tonumber(parts[3]) > 0) then | ||||
| 					table.insert(keys, k) | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| 	table.sort(keys) | ||||
| 	return keys | ||||
| @ -42,13 +74,13 @@ yl_speak_up.input_trade_via_buy_button = function(player, formname, fields) | ||||
| 
 | ||||
| 	if(fields.buy_directly) then | ||||
| 		local trade_id = yl_speak_up.speak_to[pname].trade_id | ||||
| 		local error_msg = yl_speak_up.check_trade_via_buy_button(player, trade_id, true) | ||||
| 		local res = yl_speak_up.check_trade_via_buy_button(player, trade_id, true) | ||||
| 
 | ||||
| 		if(error_msg ~= "OK") then | ||||
| 		if(res.msg ~= "OK") then | ||||
| 			yl_speak_up.show_fs(player, "msg", { | ||||
| 				input_to = "yl_speak_up:trade_via_buy_button", | ||||
| 				formspec = "size[6,2.5]".. | ||||
| 					"label[0.2,-0.2;"..error_msg.."\nTrade aborted.]".. | ||||
| 					"label[0.2,-0.2;"..res.msg.."\nTrade aborted.]".. | ||||
| 					"button[2,1.5;1,0.9;back_from_error_msg;Back]"}) | ||||
| 			return | ||||
| 		end | ||||
| @ -80,8 +112,23 @@ yl_speak_up.input_trade_via_buy_button = function(player, formname, fields) | ||||
| 	end | ||||
| 	-- TODO: delete button  if(fields.delete_trade_via_buy_button) then | ||||
| 
 | ||||
| 	-- the owner wants to go back to the trade list from a dialog trade (action) view | ||||
| 	if(fields.back_to_trade_list_dialog_trade) then | ||||
| 		yl_speak_up.show_fs(player, "trade_list", true) | ||||
| 		return | ||||
| 	-- a dialog trade (action) was displayed; go back to the corresponding dialog | ||||
| 	elseif(fields.back_to_dialog) then | ||||
| 		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 | ||||
| 		local trade_id = yl_speak_up.speak_to[pname].trade_id | ||||
| 		local new_d_id = dialog.trades[ trade_id ].d_id | ||||
| 		yl_speak_up.speak_to[pname].d_id = new_d_id | ||||
| 		yl_speak_up.speak_to[pname].trade_list = {} | ||||
| 		yl_speak_up.show_fs(player, "talk") -- TODO parameters | ||||
| 		return | ||||
| 	-- show the trade list | ||||
| 	if(fields.back_to_trade_list or fields.quit | ||||
| 	elseif(fields.back_to_trade_list or fields.quit | ||||
| 	  or not(yl_speak_up.speak_to[pname].trade_id)) then | ||||
| 		yl_speak_up.show_fs(player, "trade_list") | ||||
| 		return | ||||
| @ -96,6 +143,7 @@ end | ||||
| -- if do_trade is false: check only if the trade would be possible and return | ||||
| -- 	error message if not; return "OK" when trade is possible | ||||
| -- if do_trade is true: if possible, execute the trade; return the same as above | ||||
| -- also returns how many times the trade could be done (stock= ..) | ||||
| yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade) | ||||
| 	local pname = player:get_player_name() | ||||
| 	local n_id = yl_speak_up.speak_to[pname].n_id | ||||
| @ -108,11 +156,11 @@ yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade) | ||||
| 	-- the NPCs' inventory | ||||
| 	local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(n_id)}) | ||||
| 	if(not(this_trade)) then | ||||
| 		return "Trade not found." | ||||
| 		return {msg = "Trade not found.", stock=0} | ||||
| 	elseif(not(player_inv)) then | ||||
| 		return "Couldn't find player's inventory." | ||||
| 		return {msg = "Couldn't find player's inventory.", stock=0} | ||||
| 	elseif(not(npc_inv)) then | ||||
| 		return "Couldn't find the NPC's inventory." | ||||
| 		return {msg = "Couldn't find the NPC's inventory.", stock=0} | ||||
| 	end | ||||
| 	-- store which trade we're doing | ||||
| 	yl_speak_up.speak_to[pname].trade_id = trade_id | ||||
| @ -125,47 +173,62 @@ yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade) | ||||
| 
 | ||||
| 	-- can the NPC provide his part? | ||||
| 	if(not(npc_inv:contains_item("npc_main", buy_stack))) then | ||||
| 		return "Out of stock" --"Sorry. "..npc_name.." ran out of stock.\nPlease come back later." | ||||
| 		return {msg = "Out of stock", stock = 0} | ||||
| 		-- return {msg = "Sorry. "..npc_name.." ran out of stock.\nPlease come back later.", stock=0} | ||||
| 	-- has the NPC room for the payment? | ||||
| 	elseif(not(npc_inv:room_for_item("npc_main", pay_stack))) then | ||||
| 		return npc_name.." has no room left!" | ||||
| 		return {npc_name.." has no room left!", stock = 0} | ||||
| --		return "Sorry. "..npc_name.." ran out of inventory space.\n".. | ||||
| --			"There is no room to store your payment!" | ||||
| 	end | ||||
| 
 | ||||
| 	local counted_npc_inv = yl_speak_up.count_npc_inv(n_id) | ||||
| 	local stock_pay = counted_npc_inv[ pay_stack:get_name() ] or 0 | ||||
| 	local stock_buy = counted_npc_inv[ buy_stack:get_name() ] or 0 | ||||
| 	-- are there any limits which we have to take into account? | ||||
| 	local min_storage = dialog.trades.limits.sell_if_more[ buy_stack:get_name() ] | ||||
| 	local max_storage = dialog.trades.limits.buy_if_less[  pay_stack:get_name() ] | ||||
| 	if((min_storage and min_storage > 0) | ||||
| 	  or (max_storage and max_storage < 10000)) then | ||||
| 		local counted_npc_inv = yl_speak_up.count_npc_inv(n_id) | ||||
| 		local stock_pay = counted_npc_inv[ pay_stack:get_name() ] or 0 | ||||
| 		local stock_buy = counted_npc_inv[ buy_stack:get_name() ] or 0 | ||||
| 		-- trade limit: is enough left after the player buys the item? | ||||
| 		if(    min_storage and min_storage > stock_buy - buy_stack:get_count()) then | ||||
| 			return "Sorry. "..npc_name.." currently does not want to\nsell that much.".. | ||||
| --			return "Stock too low. Only "..tostring(stock_buy).. | ||||
| --				" left, want to keep "..tostring(min_storage).."." | ||||
| 			return {msg = "Sorry. "..npc_name.." currently does not want to\nsell that much.".. | ||||
| 				" Current stock: "..tostring(stock_buy).. | ||||
| 				" (min: "..tostring(min_storage).."). Perhaps later?" | ||||
| 				" (min: "..tostring(min_storage).."). Perhaps later?", | ||||
| 				stock = 0} | ||||
| 		-- trade limit: make sure the bought amount does not exceed the desired maximum | ||||
| 		elseif(max_storage and max_storage < stock_pay + pay_stack:get_count()) then | ||||
| 			return "Sorry. "..npc_name.." currently does not want to\n".. | ||||
| 			return {msg = "Sorry. "..npc_name.." currently does not want to\n".. | ||||
| 				"buy that much.".. | ||||
| 				" Current stock: "..tostring(stock_pay).. | ||||
| 				" (max: "..tostring(max_storage).."). Perhaps later?" | ||||
| 				" (max: "..tostring(max_storage).."). Perhaps later?", | ||||
| 				stock = 0} | ||||
| 		end | ||||
| 		-- the NPC shall not sell more than this | ||||
| 		if(min_storage and min_storage > 0) then | ||||
| 			stock_buy = math.max(0, stock_buy - min_storage) | ||||
| 		end | ||||
| 	end | ||||
| 	-- how often can this trade be done? | ||||
| 	local stock = yl_speak_up.get_trade_amount_available( | ||||
| 				stock_buy, stock_pay, | ||||
| 				buy_stack, pay_stack, | ||||
| 				min_storage, max_storage) | ||||
| 	-- can the player pay? | ||||
| 	if(not(player_inv:contains_item("main", pay_stack))) then | ||||
| 		-- both slots will remain empty | ||||
| 		return "You can't pay the price." | ||||
| 		return {msg = "You can't pay the price.", stock = stock} | ||||
| 	elseif(not(player_inv:room_for_item("main", buy_stack))) then | ||||
| 		-- the player has no room for the sold item; give a warning | ||||
| 		return "You don't have enough free inventory\nspace to store your purchase." | ||||
| 		return {msg = "You don't have enough free inventory\nspace to store your purchase.", | ||||
| 			stock = stock} | ||||
| 	end | ||||
| 
 | ||||
| 	-- was it a dry run to check if the trade is possible? | ||||
| 	if(not(do_trade)) then | ||||
| 		return "OK" | ||||
| 		return {msg = "OK", stock = stock} | ||||
| 	end | ||||
| 
 | ||||
| 	-- actually do the trade | ||||
| @ -177,7 +240,7 @@ yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade) | ||||
| 		-- revert the trade | ||||
| 		player_inv:add_item("main", payment) | ||||
| 		npc_inv:add_item("npc_main", sold) | ||||
| 		return "Sorry. "..npc_name.." accepts only undammaged items." | ||||
| 		return {msg  = "Sorry. "..npc_name.." accepts only undammaged items.", stock = stock} | ||||
| 	end | ||||
| 	player_inv:add_item("main", sold) | ||||
| 	npc_inv:add_item("npc_main", payment) | ||||
| @ -194,7 +257,7 @@ yl_speak_up.check_trade_via_buy_button = function(player, trade_id, do_trade) | ||||
| 	yl_speak_up.log_change(pname, n_id, | ||||
| 		"bought "..tostring(pay_stack:to_string()).. | ||||
| 		" for "..tostring(buy_stack:to_string())) | ||||
| 	return "OK" | ||||
| 	return {msg = "OK", stock = stock} | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| @ -261,12 +324,37 @@ yl_speak_up.get_fs_trade_via_buy_button = function(player, trade_id) | ||||
| 			buy_name, | ||||
| 			"]", | ||||
| 		"image[3.5,2.0;1,1;gui_furnace_arrow_bg.png^[transformR270]", | ||||
| 		-- go back to the trade list | ||||
| 		"button[0.2,0.0;8.0,1.0;back_to_trade_list;Back to list]".. | ||||
| 			"tooltip[back_to_trade_list;Click here once you've traded enough with this ".. | ||||
| 				"NPC and want to get back to the trade list.]" | ||||
| 	} | ||||
| 
 | ||||
| 	if(not(dialog.trades[ trade_id ].d_id)) then | ||||
| 		-- go back to the trade list | ||||
| 		table.insert(formspec, "button[0.2,0.0;8.0,1.0;back_to_trade_list;Back to trade list]") | ||||
| 		table.insert(formspec, "tooltip[back_to_trade_list;".. | ||||
| 						"Click here once you've traded enough with this ".. | ||||
| 						"NPC and want to get back to the trade list.]") | ||||
| 	elseif(true) then | ||||
| 		-- go back to the trade list | ||||
| 		table.insert(formspec, "button[0.2,0.0;3.8,1.0;back_to_trade_list_dialog_trade;Back to trade list]") | ||||
| 		table.insert(formspec, "tooltip[back_to_trade_list_dialog_trade;".. | ||||
| 						"Click here once you've traded enough with this ".. | ||||
| 						"NPC and want to get back to the trade list.]") | ||||
| 		-- go back to dialog | ||||
| 		table.insert(formspec, "button[4.2,0.0;3.8,1.0;back_to_dialog;Back to dialog ") | ||||
| 		table.insert(formspec, minetest.formspec_escape(dialog.trades[ trade_id ].d_id)) | ||||
| 		table.insert(formspec, "]") | ||||
| 		table.insert(formspec, "tooltip[back_to_dialog;".. | ||||
| 						"Click here once you've traded enough with this ".. | ||||
| 						"NPC and want to get back to talking with the NPC.]") | ||||
| 	else | ||||
| 		-- go back to dialog | ||||
| 		table.insert(formspec, "button[0.2,0.0;8.0,1.0;back_to_dialog;Back to dialog ") | ||||
| 		table.insert(formspec, minetest.formspec_escape(dialog.trades[ trade_id ].d_id)) | ||||
| 		table.insert(formspec, "]") | ||||
| 		table.insert(formspec, "tooltip[back_to_dialog;".. | ||||
| 						"Click here once you've traded enough with this ".. | ||||
| 						"NPC and want to get back to talking with the NPC.]") | ||||
| 	end | ||||
| 
 | ||||
| 	-- show edit button for the owner if in edit_mode | ||||
| 	if(yl_speak_up.may_edit_npc(player, n_id)) then | ||||
| 		-- for trades in trade list: allow delete (new trades can easily be added) | ||||
| @ -280,8 +368,8 @@ yl_speak_up.get_fs_trade_via_buy_button = function(player, trade_id) | ||||
| 	end | ||||
| 
 | ||||
| 	-- dry-run: test if the trade can be done | ||||
| 	local trade_possible = yl_speak_up.check_trade_via_buy_button(player, trade_id, false) | ||||
| 	if(trade_possible == "OK") then | ||||
| 	local res = yl_speak_up.check_trade_via_buy_button(player, trade_id, false) | ||||
| 	if(res.msg == "OK") then | ||||
| 		local buy_str = "Buy" | ||||
| 		local trade_done = yl_speak_up.speak_to[pname].trade_done | ||||
| 		if(trade_done and trade_done > 0) then | ||||
| @ -297,12 +385,18 @@ yl_speak_up.get_fs_trade_via_buy_button = function(player, trade_id) | ||||
| 		table.insert(formspec, "style_type[button;bgcolor=#FF4444]".. | ||||
| 					"button[0.2,3.5;8.0,1.0;back_from_error_msg;") | ||||
| --		table.insert(formspec, "label[0.5,3.5;") | ||||
| 		table.insert(formspec, trade_possible) | ||||
| 		table.insert(formspec, res.msg) | ||||
| 		table.insert(formspec, ']') | ||||
| 		-- set the background color for the next buttons back to our normal one | ||||
| 		table.insert(formspec, 'style_type[button;bgcolor=#a37e45]') | ||||
| --		table.insert(formspec, "label[6.5,2.0;Trade not\npossible.]") | ||||
| 	end | ||||
| 	-- how often can this trade be repeated? | ||||
| 	if(res.stock and res.stock > 0) then | ||||
| 		table.insert(formspec, "label[6.5,2.0;Trade ") | ||||
| 		table.insert(formspec, tostring(res.stock)) | ||||
| 		table.insert(formspec, " x\navailable]") | ||||
| 	end | ||||
| 
 | ||||
| 	table.insert(formspec, "container_end[]".. | ||||
| 		"real_coordinates[true]".. | ||||
|  | ||||
| @ -109,7 +109,7 @@ yl_speak_up.get_fs_trade_list = function(player, show_dialog_option_trades) | ||||
| 	-- the order in which the trades appear shall not change each time; | ||||
| 	-- but lua cannot sort the keys of a table by itself... | ||||
| 	-- this function can be found in fs_trade_via_button.lua | ||||
| 	local sorted_trades = yl_speak_up.get_sorted_trade_id_list(dialog) | ||||
| 	local sorted_trades = yl_speak_up.get_sorted_trade_id_list(dialog, show_dialog_option_trades) | ||||
| 	yl_speak_up.speak_to[pname].trade_id_list = sorted_trades | ||||
| 
 | ||||
| 	for i, k in ipairs(sorted_trades) do | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user