forked from Sokomine/yl_speak_up
added formspecs for simple trade
This commit is contained in:
parent
4c4992f985
commit
53496c7369
@ -24,6 +24,8 @@ yl_speak_up.npc_was_changed = {}
|
||||
-- format: yl_speak_up.npc_owner[ npc_id ] = owner_name
|
||||
yl_speak_up.npc_owner = {}
|
||||
|
||||
-- store the current trade between player and npc
|
||||
yl_speak_up.trade = {}
|
||||
|
||||
function yl_speak_up.init_mob_table()
|
||||
return false
|
||||
@ -2772,7 +2774,7 @@ yl_speak_up.input_talk = function(player, formname, fields)
|
||||
if(edit_mode and fields.show_inventory) then
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
-- the inventory is just an inventory with a back button; come back to this dialog here
|
||||
minetest.show_formspec(pname, "yl_speak_up:inventory", yl_speak_up.get_fs_inventory(player, n_id, dialog.n_npc))
|
||||
minetest.show_formspec(pname, "yl_speak_up:inventory", yl_speak_up.get_fs_inventory(player))
|
||||
return
|
||||
end
|
||||
|
||||
|
5
init.lua
5
init.lua
@ -19,8 +19,13 @@ dofile(modpath .. "config.lua")
|
||||
dofile(modpath .. "privs.lua")
|
||||
-- inventory management, trading and handling of quest items:
|
||||
dofile(modpath .. "inventory.lua")
|
||||
-- trade one item(stack) against one other item(stack)
|
||||
dofile(modpath .. "trade_simple.lua")
|
||||
-- the main functionality of the mod
|
||||
dofile(modpath .. "functions.lua")
|
||||
-- the staffs (requires npc_master priv)
|
||||
dofile(modpath .. "tools.lua")
|
||||
-- the actual mobs, using mobs_redo
|
||||
dofile(modpath .. "mobs.lua")
|
||||
--dofile(modpath .. "debug.lua")
|
||||
|
||||
|
@ -10,14 +10,28 @@ end
|
||||
|
||||
|
||||
-- access the inventory of the NPC (only possible for players with the right priv)
|
||||
yl_speak_up.get_fs_inventory = function(player, n_id, npc_name)
|
||||
yl_speak_up.get_fs_inventory = function(player)
|
||||
if(not(player)) then
|
||||
return ""
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
-- which NPC is the player talking to?
|
||||
local n_id = yl_speak_up.speak_to[pname].n_id
|
||||
local dialog = yl_speak_up.speak_to[pname].dialog
|
||||
-- do we have all the necessary data?
|
||||
if(not(n_id) or not(dialog.n_npc)) then
|
||||
return "size[6,2]"..
|
||||
"label[0.2,0.5;Ups! This NPC lacks ID or name.]"..
|
||||
"button_exit[2,1.5;1,0.9;exit;Exit]"
|
||||
|
||||
end
|
||||
return "size[12,11]" ..
|
||||
"label[2,-0.2;Inventory of "..minetest.formspec_escape(npc_name)..
|
||||
"label[2,-0.2;Inventory of "..minetest.formspec_escape(dialog.n_npc)..
|
||||
" (ID: "..tostring(n_id).."):]"..
|
||||
"list[detached:yl_npc_"..tostring(n_id)..";npc_main;0,0.3;12,6;]" ..
|
||||
"list[detached:yl_speak_up_npc_"..tostring(n_id)..";npc_main;0,0.3;12,6;]" ..
|
||||
"list[current_player;main;2,6.85;8,1;]" ..
|
||||
"list[current_player;main;2,8.08;8,3;8]" ..
|
||||
"listring[detached:yl_npc_"..tostring(n_id)..";npc_main]" ..
|
||||
"listring[detached:yl_speak_up_npc_"..tostring(n_id)..";npc_main]" ..
|
||||
"listring[current_player;main]" ..
|
||||
"button[10.0,10.2;2,0.9;back_from_inventory;Back]"
|
||||
end
|
||||
@ -50,6 +64,7 @@ end
|
||||
|
||||
-- create and load the detached inventory in yl_speak_up.after_activate;
|
||||
-- direct access to this inventory is only possible for players with the right privs
|
||||
-- (this is an inventory for the *NPC*, which is stored to disk sometimes)
|
||||
yl_speak_up.load_npc_inventory = function(n_id)
|
||||
if(not(n_id)) then
|
||||
return
|
||||
@ -59,7 +74,7 @@ yl_speak_up.load_npc_inventory = function(n_id)
|
||||
return
|
||||
end
|
||||
-- create the detached inventory (it is empty for now)
|
||||
local npc_inv = minetest.create_detached_inventory("yl_npc_"..tostring(n_id), {
|
||||
local npc_inv = minetest.create_detached_inventory("yl_speak_up_npc_"..tostring(n_id), {
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
if(not(yl_speak_up.may_edit_npc(player, n_id))) then
|
||||
return 0
|
||||
|
275
trade_simple.lua
Normal file
275
trade_simple.lua
Normal file
@ -0,0 +1,275 @@
|
||||
-- spimple trading: one item(stack) for another item(stack)
|
||||
|
||||
-- fallback message if something went wrong
|
||||
yl_speak_up.trade_fail_fs = "size[6,2]"..
|
||||
"label[0.2,0.5;Ups! The trade is not possible.\nPlease notify an admin.]"..
|
||||
"button_exit[2,1.5;1,0.9;exit;Exit]"
|
||||
|
||||
-- TODO: when closing the formspec: give the items in the pay slot back
|
||||
|
||||
-- can this trade be made? called in allow_take
|
||||
yl_speak_up.can_trade_simple = function(player, count)
|
||||
if(not(player)) then
|
||||
return 0
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
-- which trade are we talking about?
|
||||
local trade = yl_speak_up.trade[pname]
|
||||
-- do we have all the necessary data?
|
||||
if(not(trade) or trade.trade_type ~= "trade_simple") then
|
||||
return 0
|
||||
end
|
||||
|
||||
-- the player tries to take *less* items than what his payment is;
|
||||
-- avoid this confusion!
|
||||
if(ItemStack(trade.npc_gives):get_count() ~= count) then
|
||||
return 0
|
||||
end
|
||||
-- buy, sell and config items need to be placed somewhere
|
||||
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
||||
-- the players' inventory
|
||||
local player_inv = player:get_inventory()
|
||||
-- the NPCs' inventory
|
||||
local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(trade.n_id)})
|
||||
|
||||
-- is the payment in the payment slot?
|
||||
if( not(trade_inv:contains_item("pay", trade.player_gives))
|
||||
-- is the item to be sold in the buy slot?
|
||||
or not(trade_inv:contains_item("buy", trade.npc_gives))
|
||||
-- has the NPC room for the payment?
|
||||
or not(npc_inv:room_for_item("npc_main", trade.player_gives))
|
||||
-- has the player room for the sold item?
|
||||
or not(player_inv:room_for_item("main", trade.npc_gives))) then
|
||||
-- trade not possible
|
||||
return 0
|
||||
end
|
||||
-- all ok; all items that are to be sold can be taken
|
||||
return ItemStack(trade.npc_gives):get_count()
|
||||
end
|
||||
|
||||
|
||||
-- actually execute the trade
|
||||
yl_speak_up.do_trade_simple = function(player, count)
|
||||
-- can the trade be made?
|
||||
if(not(yl_speak_up.can_trade_simple(player, count))) then
|
||||
return
|
||||
end
|
||||
|
||||
local pname = player:get_player_name()
|
||||
-- which trade are we talking about?
|
||||
local trade = yl_speak_up.trade[pname]
|
||||
|
||||
-- buy, sell and config items need to be placed somewhere
|
||||
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
||||
-- the NPCs' inventory
|
||||
local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(trade.n_id)})
|
||||
|
||||
-- the NPC sells these items right now, and the player is moving it to his inventory
|
||||
npc_inv:remove_item("npc_main", trade.npc_gives)
|
||||
|
||||
-- move price items to the NPC
|
||||
local stack = trade_inv:remove_item("pay", trade.player_gives)
|
||||
npc_inv:add_item("npc_main", stack)
|
||||
-- save the inventory of the npc so that the payment does not get lost
|
||||
yl_speak_up.save_npc_inventory( trade.n_id )
|
||||
|
||||
-- store for statistics how many times the player has executed this trade
|
||||
trade.trade_done = trade.trade_done + 1
|
||||
end
|
||||
|
||||
|
||||
-- simple trade: one item(stack) for another
|
||||
-- handles configuration of new trades and showing the formspec for trades;
|
||||
-- checks if payment and buying is possible
|
||||
yl_speak_up.get_fs_trade_simple = function(player, player_gives, npc_gives)
|
||||
if(not(player)) then
|
||||
return yl_speak_up.trade_fail_fs
|
||||
end
|
||||
local pname = player:get_player_name()
|
||||
-- which trade are we talking about?
|
||||
local trade = yl_speak_up.trade[pname]
|
||||
-- do we have all the necessary data?
|
||||
if(not(trade) or trade.trade_type ~= "trade_simple") then
|
||||
return yl_speak_up.trade_fail_fs
|
||||
end
|
||||
-- the common formspec, shared by actual trade and configuration
|
||||
-- no listring here as that would make things more complicated
|
||||
local formspec = "size[8.5,8]"..
|
||||
"label[4.35,0.8;"..minetest.formspec_escape(trade.npc_name).." sells:]"..
|
||||
"list[current_player;main;0.2,3.85;8,1;]"..
|
||||
"list[current_player;main;0.2,5.08;8,3;8]"
|
||||
|
||||
-- configuration of a new trade happens here
|
||||
if(not(trade.player_gives) or not(trade.npc_gives)) then
|
||||
-- is this player allowed to edit the NPC and his trades? If not abort.
|
||||
if(not(yl_speak_up.may_edit_npc(player, trade.n_id))) then
|
||||
return formspec..
|
||||
"label[2.0,1.8;Ups! Something went wrong.]"..
|
||||
"button[6.2,1.6;2.0,0.9;abort_trade_simple;Back]"
|
||||
end
|
||||
return formspec..
|
||||
-- show the second slot of the setup inventory in the detached player's inv
|
||||
"list[detached:yl_speak_up_player_"..pname..";setup;2,1.5;1,1;]"..
|
||||
-- show the second slot of said inventory
|
||||
"list[detached:yl_speak_up_player_"..pname..";setup;5,1.5;1,1;1]"..
|
||||
"label[2.5,0.0;Configure trade with "..minetest.formspec_escape(trade.npc_name)..":]"..
|
||||
"label[1.5,0.8;The customer pays:]"..
|
||||
"label[1.5,2.8;Put items in the two slots and click on \"Store trade\".]"..
|
||||
"label[1.5,3.2;You will get your items back when storing the trade.]"..
|
||||
"button[0.2,1.6;1.0,0.9;abort_trade_simple;Abort]"..
|
||||
"button[6.2,1.6;2.0,0.9;store_trade_simple;Store trade]"..
|
||||
"tooltip[store_trade_simple;Click here to store this as a new trade. Your "..
|
||||
"items will be returned to you and the trade will be shown the way "..
|
||||
"the customer can see it.]"..
|
||||
"tooltip[abort_trade_simple;Abort setting up this new trade.]"
|
||||
end
|
||||
|
||||
-- view for the customer when actually trading
|
||||
|
||||
-- buy, sell and config items need to be placed somewhere
|
||||
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
|
||||
-- the players' inventory
|
||||
local player_inv = player:get_inventory()
|
||||
-- the NPCs' inventory
|
||||
local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(trade.n_id)})
|
||||
|
||||
-- show edit button for the owner
|
||||
if(yl_speak_up.may_edit_npc(player, trade.n_id)) then
|
||||
formspec = formspec..
|
||||
"button[0.2,1.6;0.8,0.9;edit_trade_simple;Edit]"..
|
||||
"tooltip[edit_trade_simple;Edit this trade. You can do so only "..
|
||||
"if you can edit the NPC as such (i.e. own it).]"
|
||||
end
|
||||
|
||||
local trade_possible_msg = "Status of trade: Unknown."
|
||||
-- has the NPC room for the payment?
|
||||
if(not(npc_inv:room_for_item("npc_main", trade.player_gives))) then
|
||||
trade_possible_msg = "Sorry. "..minetest.formspec_escape(trade.npc_name)..
|
||||
" ran out of inventory space.\nThere is no room to store your payment!]"
|
||||
-- can the player pay?
|
||||
elseif(not(player_inv:contains_item("main", trade.player_gives))) then
|
||||
-- both slots will remain empty
|
||||
trade_possible_msg = "You cannot pay the price."
|
||||
-- is the slot for the payment empty?
|
||||
elseif not(trade_inv:is_empty("pay")) then
|
||||
-- both slots will remain empty
|
||||
-- (the slot may already contain the right things; we'll find that out later on)
|
||||
trade_possible_msg = "Please insert the right payment manually."
|
||||
-- all good so far; move the price stack to the pay slot
|
||||
else
|
||||
-- move price item to the price slot
|
||||
local stack = player_inv:remove_item("main", trade.player_gives)
|
||||
trade_inv:add_item("pay", stack)
|
||||
end
|
||||
|
||||
-- make sure the sale slot is empty (we will fill it if the trade is possible)
|
||||
trade_inv:set_stack("buy", 1, "")
|
||||
-- after all this: does the payment slot contain the right things?
|
||||
if(trade_inv:contains_item("pay", trade.player_gives)) then
|
||||
trade_possible_msg = "Take the offered item(s) in order to buy them."
|
||||
|
||||
-- can the NPC provide his part?
|
||||
if(not(npc_inv:contains_item("npc_main", trade.npc_gives))) then
|
||||
trade_possible_msg = "Sorry. "..minetest.formspec_escape(trade.npc_name)..
|
||||
" ran out of stock.\nPlease come back later."
|
||||
else
|
||||
-- put a *copy* of the item(stack) that is to be sold in the sale slot
|
||||
trade_inv:add_item("buy", trade.npc_gives)
|
||||
end
|
||||
end
|
||||
|
||||
if(not(player_inv:room_for_item("main", trade.npc_gives))) then
|
||||
-- the player has no room for the sold item; give a warning
|
||||
trade_possible_msg = "Careful! You do not seem to have enough\n"..
|
||||
"free inventory space to store your purchase.]"
|
||||
end
|
||||
|
||||
return formspec..
|
||||
"label[2.5,0.0;Trading with "..minetest.formspec_escape(trade.npc_name).."]"..
|
||||
"label[1.5,0.8;You pay:]"..
|
||||
-- show images of price and what is sold so that the player knows what
|
||||
-- it costs and what he will get even if the trade is not possible at
|
||||
-- that moment
|
||||
"item_image[1,1.5;1,1;"..tostring(trade.player_gives).."]"..
|
||||
"item_image[4,1.5;1,1;"..tostring(trade.npc_gives).."]"..
|
||||
-- show the pay slot from the detached player's trade inventory
|
||||
"list[detached:yl_speak_up_player_"..pname..";pay;2,1.5;1,1;]" ..
|
||||
-- show the buy slot from the same inventory
|
||||
"list[detached:yl_speak_up_player_"..pname..";buy;5,1.5;1,1;]" ..
|
||||
"label[1.5,2.8;"..trade_possible_msg.."]"..
|
||||
"button[6.2,1.6;2.0,0.9;finished_trading;Finish trading]"..
|
||||
"tooltip[finished_trading;Click here once you've traded enough with this "..
|
||||
"NPC and want to get back to talking.]"
|
||||
end
|
||||
|
||||
|
||||
-- create a detached inventory for the *player* for trading with the npcs
|
||||
minetest.register_on_joinplayer(function(player, last_login)
|
||||
local pname = player:get_player_name()
|
||||
|
||||
-- create the detached inventory;
|
||||
-- the functions for monitoring changes will be important later on
|
||||
-- only the the player owning this detached inventory may access it
|
||||
local trade_inv = minetest.create_detached_inventory("yl_speak_up_player_"..tostring(pname), {
|
||||
-- moving of items between diffrent lists is not allowed
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
if(not(player) or player:get_player_name() ~= pname) then
|
||||
return 0
|
||||
end
|
||||
if(from_list ~= to_list) then
|
||||
return 0
|
||||
end
|
||||
return count
|
||||
end,
|
||||
|
||||
-- these all require calling special functions, depending on context
|
||||
allow_put = function(inv, listname, index, stack, player)
|
||||
if(not(player) or player:get_player_name() ~= pname) then
|
||||
return 0
|
||||
end
|
||||
-- the "buy" slot is managed by the NPC; the player only takes from it
|
||||
if(listname == "buy") then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
if(not(player) or player:get_player_name() ~= pname) then
|
||||
return 0
|
||||
end
|
||||
-- can the trade be made?
|
||||
if(listname == "buy") then
|
||||
return yl_speak_up.can_trade_simple(player, stack:get_count())
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
end,
|
||||
on_put = function(inv, listname, index, stack, player)
|
||||
if(listname == "pay") then
|
||||
local pname = player:get_player_name()
|
||||
-- show formspec with updated information (perhaps sale is now possible)
|
||||
minetest.show_formspec(pname, "yl_speak_up:talk", yl_speak_up.get_fs_trade_simple(player))
|
||||
end
|
||||
end,
|
||||
on_take = function(inv, listname, index, stack, player)
|
||||
-- the player may have put something wrong in the payment slot
|
||||
-- -> show updated formspec
|
||||
if(listname == "pay") then
|
||||
local pname = player:get_player_name()
|
||||
-- show formspec with updated information (perhaps sale is now possible)
|
||||
minetest.show_formspec(pname, "yl_speak_up:talk", yl_speak_up.get_fs_trade_simple(player))
|
||||
elseif(listname == "buy") then
|
||||
yl_speak_up.do_trade_simple(player, stack:get_count())
|
||||
-- information may require an update (NPC might now be out of stock), or
|
||||
-- the player can do the trade a second time
|
||||
minetest.show_formspec(pname, "yl_speak_up:talk", yl_speak_up.get_fs_trade_simple(player))
|
||||
end
|
||||
end,
|
||||
})
|
||||
-- prepare the actual inventories
|
||||
trade_inv:set_size("pay", 1)
|
||||
trade_inv:set_size("buy", 1)
|
||||
-- for setting up new simple trades
|
||||
trade_inv:set_size("setup", 2*1)
|
||||
end)
|
Loading…
Reference in New Issue
Block a user