From f717c3f1e52f3c1fe9e187a706ea38a234e799e8 Mon Sep 17 00:00:00 2001 From: zorman2000 Date: Thu, 15 Dec 2016 20:51:06 -0500 Subject: [PATCH] Trade: Working buy/sell trade mechanism. Various cleanups and modularizations for supporting dedicated traders. Data: Added more favorite items for phase 1. --- dialogue.lua | 2 +- npc.lua | 13 +++++-- random_data.lua | 54 ++++++++++++++++++++++++++-- relationships.lua | 2 +- trade/trade.lua | 89 ++++++++++++++++++++++++++++++++++------------- 5 files changed, 128 insertions(+), 32 deletions(-) diff --git a/dialogue.lua b/dialogue.lua index 654b74b..e1aed43 100644 --- a/dialogue.lua +++ b/dialogue.lua @@ -34,7 +34,7 @@ function npc.dialogue.show_options_dialogue(self, for i = 1, #responses do local y = 0.8; if i > 1 then - y = (0.7 * i) + y = (0.75 * i) end formspec = formspec.."button_exit[0.5," ..(y - 0.5)..";6,0.5;opt"..tostring(i)..";"..responses[i].text.."]" diff --git a/npc.lua b/npc.lua index 15490ef..849d837 100755 --- a/npc.lua +++ b/npc.lua @@ -39,12 +39,14 @@ end -- Utility function to get item name from a string local function get_item_name(item_string) - return item_string.sub(item_string, 1, string.find(item_string, " ")) + local i,j = string.find(item_string, " ") + return item_string.sub(item_string, 1, i-1) end -- Utility function to get item count from a string local function get_item_count(item_string) - return tonumber(item_string.sub(item_string, string.find(item_string, " "))) + local i,j = string.find(item_string, " ") + return tonumber(item_string.sub(item_string, i+1)) end local function initialize_inventory() @@ -98,6 +100,13 @@ function npc.add_item_to_inventory(self, item_name, count) end end +-- Same add method but with itemstring for convenience +function npc.add_item_to_inventory_itemstring(self, item_string) + local item_name = get_item_name(item_string) + local item_count = get_item_count(item_string) + npc.add_item_to_inventory(self, item_name, item_count) +end + -- Checks if an item is contained in the inventory. Returns -- the item string or nil if not found function npc.inventory_contains(self, item_name) diff --git a/random_data.lua b/random_data.lua index 74724e9..7ec3600 100644 --- a/random_data.lua +++ b/random_data.lua @@ -276,7 +276,31 @@ npc.FAVORITE_ITEMS.female["phase1"] = { hint = "I could really do with an apple..."}, {item = "farming:bread", response = "Thanks, you didn't have to, but thanks...", - hint = "Some fresh bread would be good!"} + hint = "Some fresh bread would be good!"}, + {item = "farming:seed_cotton", + response = "Thank you, I will plant this really soon", + hint = "I would like to have some cotton plants around"}, + {item = "farming:seed_wheat", + response = "Thank you! These seeds will make a good wheat plant!", + hint = "I've been thinking I should get wheat seeds"}, + {item = "flowers:rose", + response = "Thanks...", + hint = "Red roses make a nice gift!"}, + {item = "flowers:geranium", + response = "Oh, for me? Thank you!", + hint = "Blue geraniums are so beautiful"}, + {item = "default:clay_lump", + response = "Thanks! Now, what can I do with this...", + hint = "If I had some clay lump, I may do some pottery"}, + {item = "mobs:meat_raw", + response = "This will be great for tonight! Thanks", + hint = "A good dinner always have meat"}, + {item = "mobs:leather", + response = "Thank you! I needed this leather!", + hint = "If only I could get some leather"}, + {item = "default:sapling", + response = "Now I can plant that tree...", + hint = "I really would like an apple tree close by."} } npc.FAVORITE_ITEMS.female["phase2"] = { {item = "farming:cotton", @@ -320,12 +344,36 @@ npc.FAVORITE_ITEMS.female["phase6"] = { } -- Male npc.FAVORITE_ITEMS.male["phase1"] = { - {item = "default:apple", + {item = "default:apple", response = "Hey, I really wanted an apple, thank you!", hint = "I could really do with an apple..."}, {item = "farming:bread", response = "Thanks, you didn't have to, but thanks...", - hint = "Some fresh bread would be good!"} + hint = "Some fresh bread would be good!"}, + {item = "farming:seed_cotton", + response = "Thank you, I will plant this really soon", + hint = "I would like to have some cotton plants around"}, + {item = "farming:seed_wheat", + response = "Thank you! These seeds will make a good wheat plant!", + hint = "I've been thinking I should get wheat seeds"}, + {item = "default:wood", + response = "Thanks, I needed this.", + hint = "Some wood without having to cut a tree would be good."}, + {item = "default:tree", + response = "Excellent to get that furnace going!", + hint = "I need logs, do you have some?"}, + {item = "default:clay_lump", + response = "Thanks! Now, what can I do with this...", + hint = "I wish I had some clay"}, + {item = "mobs:meat_raw", + response = "This makes a great meal. Thank you", + hint = "Meat is always great"}, + {item = "mobs:leather", + response = "Time to tan some leathers!", + hint = "I have been needing leather these days"}, + {item = "default:sapling", + response = "Thanks, I will plant this right now", + hint = "I really would like an apple tree close by."} } npc.FAVORITE_ITEMS.male["phase2"] = { {item = "farming:cotton", diff --git a/relationships.lua b/relationships.lua index 842f8e9..0b3f767 100644 --- a/relationships.lua +++ b/relationships.lua @@ -36,7 +36,7 @@ npc.relationships.RELATIONSHIP_PHASE["phase2"] = {limit = 25} npc.relationships.RELATIONSHIP_PHASE["phase3"] = {limit = 45} npc.relationships.RELATIONSHIP_PHASE["phase4"] = {limit = 70} npc.relationships.RELATIONSHIP_PHASE["phase5"] = {limit = 100} - + -- Married NPC dialogue definition npc.relationships.MARRIED_NPC_DIALOGUE = { text = "Hi darling!", diff --git a/trade/trade.lua b/trade/trade.lua index d51b950..a5ffbcc 100644 --- a/trade/trade.lua +++ b/trade/trade.lua @@ -11,8 +11,8 @@ npc.trade.OFFER_SELL = "sell" -- This table holds all responses for trades npc.trade.results = { - casual = {}, - formal = {} + single_trade_offer = {}, + trade_offers = {} } -- Casual trader NPC dialogues definition @@ -26,7 +26,7 @@ npc.trade.CASUAL_TRADE_BUY_DIALOGUE = { action_type = "function", response_id = 1, action = function(self, player) - npc.trade.show_casual_trade_formspec(self, player, npc.trade.OFFER_BUY) + npc.trade.show_trade_offer_formspec(self, player, npc.trade.OFFER_BUY) end } } @@ -42,13 +42,13 @@ npc.trade.CASUAL_TRADE_SELL_DIALOGUE = { action_type = "function", response_id = 1, action = function(self, player) - npc.trade.show_casual_trade_formspec(self, player, npc.trade.OFFER_SELL) + npc.trade.show_trade_offer_formspec(self, player, npc.trade.OFFER_SELL) end } } } -function npc.trade.show_casual_trade_formspec(self, player, offer_type) +function npc.trade.show_trade_offer_formspec(self, player, offer_type) -- Strings for formspec, to include international support later local prompt_string = " offers to buy from you" @@ -76,11 +76,12 @@ function npc.trade.show_casual_trade_formspec(self, player, offer_type) "button_exit[4.1,3.3;2.9,0.5;no_option;"..npc.dialogue.NEGATIVE_ANSWER_LABEL.."]" -- Create entry into results table - npc.trade.results.casual[player:get_player_name()] = { - trade_offer = trade_offer + npc.trade.results.single_trade_offer[player:get_player_name()] = { + trade_offer = trade_offer, + npc = self } -- Show formspec to player - minetest.show_formspec(player:get_player_name(), "advanced_npc:casual_trade", formspec) + minetest.show_formspec(player:get_player_name(), "advanced_npc:trade_offer", formspec) end function npc.trade.get_random_trade_status() @@ -114,32 +115,70 @@ function npc.trade.get_casual_trade_offer(self, offer_type) } end +function npc.trade.perform_trade(self, player_name, offer) + + local item_stack = ItemStack(offer.item) + local price_stack = ItemStack(offer.price) + local inv = minetest.get_inventory({type = "player", name = player_name}) + + -- Check if offer is a buy or sell + if offer.offer_type == npc.trade.OFFER_BUY then + -- If NPC is buying from player, then player loses item, gets price + -- Check player has the item being buyed + if inv:contains_item("main", item_stack) then + -- Check if there is enough room to add the price item to player + if inv:room_for_item("main", price_stack) then + -- Remove item from player + inv:remove_item("main", item_stack) + -- Add item to NPC's inventory + npc.add_item_to_inventory_itemstring(self, offer.item) + -- Add price items to player + inv:add_item("main", price_stack) + -- Send message to player + minetest.chat_send_player(player_name, "Thank you!") + else + minetest.chat_send_player(player_name, + "Looks like you can't what I'm giving you for payment!") + end + else + minetest.chat_send_player(player_name, "Looks like you don't have what I want to buy...") + end + else + -- If NPC is selling to the player, then player gives price and gets + -- item, NPC loses item and gets price + -- Check NPC has the required item to pay + if inv:contains_item("main", price_stack) then + -- Check if there is enough room to add the item to player + if inv:room_for_item("main", item_stack) then + -- Remove item from player + inv:remove_item("main", price_stack) + -- Add item to NPC's inventory + npc.add_item_to_inventory_itemstring(self, offer.price) + -- Add price items to player + inv:add_item("main", item_stack) + -- Send message to player + minetest.chat_send_player(player_name, "Thank you!") + else + minetest.chat_send_player(player_name, "Looks like you can't carry anything else...") + end + else + minetest.chat_send_player(player_name, "Looks like you don't have what I'm asking for!") + end + end +end + -- Handler for chat formspec minetest.register_on_player_receive_fields(function (player, formname, fields) -- Additional checks for other forms should be handled here -- Handle yes/no dialogue - if formname == "advanced_npc:casual_trade" then + if formname == "advanced_npc:trade_offer" then local player_name = player:get_player_name() if fields then - local player_response = npc.trade.results.casual[player_name] + local player_response = npc.trade.results.single_trade_offer[player_name] if fields.yes_option then - -- Check if offer is a buy or sell - if player_response.trade_offer.offer_type == npc.trade.OFFER_BUY then - -- If NPC is buying from player, then player loses item, gets price - local inv = minetest.get_inventory({type = "player", name = player_name}) - -- Check NPC has the item being buyed - if inv:contains_item("main", ItemStack(player_response.trade_offer.item)) then - -- Remove item from player - inv:remove_item("main", ItemStack(player_response.trade_offer.item)) - -- TODO: Add to NPC - -- Add price items to player - inv:add_item("main", ItemStack(player_response.trade_offer.price)) - end - else - - end + npc.trade.perform_trade(player_response.npc, player_name, player_response.trade_offer) elseif fields.no_option then minetest.chat_send_player(player_name, "Talk to me if you change your mind!") end