NPC: Rewrote external inventory methods.
Trade: Added change casual offers timer functionality.
This commit is contained in:
parent
42619ad035
commit
a2e38ab85f
339
npc.lua
339
npc.lua
@ -143,45 +143,68 @@ function npc.take_item_from_inventory(self, item_name, count)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Same take method but with itemstring for convenience
|
||||||
|
function npc.take_item_from_inventory_itemstring(self, item_string)
|
||||||
|
local item_name = npc.get_item_name(item_string)
|
||||||
|
local item_count = npc.get_item_count(item_string)
|
||||||
|
npc.take_item_from_inventory(self, item_name, item_count)
|
||||||
|
end
|
||||||
|
|
||||||
-- Inventory functions for players and for nodes
|
-- Inventory functions for players and for nodes
|
||||||
-- TODO: Need to rewrite this functions
|
-- This function is a convenience function to make it easy to put
|
||||||
function npc.give_item_to_player(player, item_name, count)
|
-- and get items from another inventory (be it a player inv or
|
||||||
local player_name = npc.get_entity_name(player)
|
-- a node inv)
|
||||||
local player_inv = minetest.get_inventory({type="player", name=player_name})
|
function npc.put_item_on_external_inventory(player, pos, inv_list, item_name, count)
|
||||||
|
local inv
|
||||||
|
if player_name ~= nil then
|
||||||
|
inv = minetest.get_inventory({type="player", name=player:get_player_name()})
|
||||||
|
else
|
||||||
|
inv = minetest.get_inventory({type="node", pos})
|
||||||
|
end
|
||||||
|
-- Create ItemSTack to put on external inventory
|
||||||
local item = ItemStack(item_name.." "..count)
|
local item = ItemStack(item_name.." "..count)
|
||||||
player_inv:add_item("main", item)
|
-- Check if there is enough room to add the item on external invenotry
|
||||||
|
if inv:room_for_item(inv_list, price_stack) then
|
||||||
|
-- Take item from NPC's inventory
|
||||||
|
if npc.take_item_from_inventory_itemstring(self, item) then
|
||||||
|
-- NPC doesn't have item and/or specified quantity
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
-- Add items to external inventory
|
||||||
|
inv:add_item(inv_list, item)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
-- Not able to put on external inventory
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function npc.check_item_to_player(player, item_name)
|
function npc.take_item_from_external_inventory(player, pos, item_name, count)
|
||||||
local player_name = npc.get_entity_name(player)
|
local inv
|
||||||
local player_inv = minetest.get_inventory({type="player", name=player_name})
|
if player_name ~= nil then
|
||||||
local main_list = player_inv:get_list("main")
|
inv = minetest.get_inventory({type="player", name=player:get_player_name()})
|
||||||
for i = 1, #main_list do
|
else
|
||||||
if main_list[i]:get_name() == item_name then
|
inv = minetest.get_inventory({type="node", pos})
|
||||||
return main_list[i]
|
|
||||||
end
|
end
|
||||||
|
-- Create ItemSTack to take from external inventory
|
||||||
|
local item = ItemStack(item_name.." "..count)
|
||||||
|
-- Check if there is enough of the item to take
|
||||||
|
if inv:contains_item(inv_list, item) then
|
||||||
|
-- Add item to NPC's inventory
|
||||||
|
npc.add_item_to_inventory_itemstring(self, item)
|
||||||
|
-- Add items to external inventory
|
||||||
|
inv:remove_item(inv_list, item)
|
||||||
|
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
-- Not found
|
-- Not able to put on external inventory
|
||||||
return nil
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function npc.take_item_from_player(player, item_name, count)
|
-- Dialogue functions
|
||||||
local player_name = npc.get_entity_name(player)
|
|
||||||
local player_inv = minetest.get_inventory({type="player", name=player_name})
|
|
||||||
local main_list = player_inv:get_list("main")
|
|
||||||
for i = 1, #main_list do
|
|
||||||
if main_list[i]:get_name() == item_name then
|
|
||||||
main_list[i].take_item(count)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Not found
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Chat functions
|
|
||||||
function npc.start_dialogue(self, clicker, show_married_dialogue)
|
function npc.start_dialogue(self, clicker, show_married_dialogue)
|
||||||
|
|
||||||
-- Call chat function as normal
|
-- Call dialogue function as normal
|
||||||
npc.dialogue.start_dialogue(self, clicker, show_married_dialogue)
|
npc.dialogue.start_dialogue(self, clicker, show_married_dialogue)
|
||||||
|
|
||||||
-- Check and update relationship if needed
|
-- Check and update relationship if needed
|
||||||
@ -189,8 +212,133 @@ function npc.start_dialogue(self, clicker, show_married_dialogue)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------
|
||||||
-- Definitions
|
-- Spawning functions
|
||||||
|
---------------------------------------------------------------------------------------
|
||||||
|
-- These functions are used at spawn time to determine several
|
||||||
|
-- random attributes for the NPC in case they are not already
|
||||||
|
-- defined. On a later phase, pre-defining many of the NPC values
|
||||||
|
-- will be allowed.
|
||||||
|
|
||||||
|
-- This function checks for "female" text on the texture name
|
||||||
|
local function is_female_texture(textures)
|
||||||
|
for i = 1, #textures do
|
||||||
|
if string.find(textures[i], "female") ~= nil then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Choose whether NPC can have relationships. Only 30% of NPCs cannot have relationships
|
||||||
|
local function can_have_relationships()
|
||||||
|
local chance = math.random(1,10)
|
||||||
|
return chance > 3
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Choose a maximum of two items that the NPC will have at spawn time
|
||||||
|
-- These items are chosen from the favorite items list.
|
||||||
|
local function choose_spawn_items(self)
|
||||||
|
local number_of_items_to_add = math.random(1, 2)
|
||||||
|
local number_of_items = #npc.FAVORITE_ITEMS[self.sex].phase1
|
||||||
|
|
||||||
|
for i = 1, number_of_items_to_add do
|
||||||
|
npc.add_item_to_inventory(
|
||||||
|
self,
|
||||||
|
npc.FAVORITE_ITEMS[self.sex].phase1[math.random(1, number_of_items)].item,
|
||||||
|
math.random(1,5)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
-- Add currency to the items spawned with. Will add 5-10 tier 3
|
||||||
|
-- currency items
|
||||||
|
local currency_item_count = math.random(5, 10)
|
||||||
|
npc.add_item_to_inventory(self, npc.trade.prices.currency.tier3, currency_item_count)
|
||||||
|
|
||||||
|
minetest.log("Initial inventory: "..dump(self.inventory))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Creates new single buy and sell offers for NPCs that
|
||||||
|
-- trade casually.
|
||||||
|
local function select_casual_trade_offers(self)
|
||||||
|
self.trader_data.buy_offers = {
|
||||||
|
[1] = npc.trade.get_casual_trade_offer(self, npc.trade.OFFER_BUY)
|
||||||
|
}
|
||||||
|
self.trader_data.sell_offers = {
|
||||||
|
[1] = npc.trade.get_casual_trade_offer(self, npc.trade.OFFER_SELL)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Spawn function. Initializes all variables that the
|
||||||
|
-- NPC will have and choose random, starting values
|
||||||
|
local function npc_spawn(self, pos)
|
||||||
|
minetest.log("Spawning new NPC:")
|
||||||
|
local ent = self:get_luaentity()
|
||||||
|
ent.nametag = "Kio"
|
||||||
|
|
||||||
|
-- Determine sex based on textures
|
||||||
|
if (is_female_texture(ent.base_texture)) then
|
||||||
|
ent.sex = npc.FEMALE
|
||||||
|
else
|
||||||
|
ent.sex = npc.MALE
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialize all gift data
|
||||||
|
ent.gift_data = {
|
||||||
|
-- Choose favorite items. Choose phase1 per default
|
||||||
|
favorite_items = npc.relationships.select_random_favorite_items(ent.sex, "phase1"),
|
||||||
|
-- Choose disliked items. Choose phase1 per default
|
||||||
|
disliked_items = npc.relationships.select_random_disliked_items(ent.sex),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Flag that determines if NPC can have a relationship
|
||||||
|
ent.can_have_relationship = can_have_relationships()
|
||||||
|
|
||||||
|
-- Initialize relationships object
|
||||||
|
ent.relationships = {}
|
||||||
|
|
||||||
|
-- Determines if NPC is married or not
|
||||||
|
ent.is_married_to = nil
|
||||||
|
|
||||||
|
-- Initialize dialogues
|
||||||
|
ent.dialogues = npc.dialogue.select_random_dialogues_for_npc(ent.sex,
|
||||||
|
"phase1",
|
||||||
|
ent.gift_data.favorite_items,
|
||||||
|
ent.gift_data.disliked_items)
|
||||||
|
-- Declare trade data
|
||||||
|
ent.trader_data = {
|
||||||
|
-- Type of trader
|
||||||
|
trader_status = npc.trade.get_random_trade_status(),
|
||||||
|
-- Current buy offers
|
||||||
|
buy_offers = {},
|
||||||
|
-- Current sell offers
|
||||||
|
sell_offers = {},
|
||||||
|
-- Items to buy change timer
|
||||||
|
change_offers_timer = 0,
|
||||||
|
-- Items to buy change timer interval
|
||||||
|
change_offers_timer_interval = 60
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Declare NPC inventory
|
||||||
|
ent.inventory = initialize_inventory()
|
||||||
|
|
||||||
|
-- Choose items to spawn with
|
||||||
|
choose_spawn_items(ent)
|
||||||
|
|
||||||
|
-- Initialize trading offers if NPC is casual trader
|
||||||
|
if ent.trader_data.trader_status == npc.trade.CASUAL then
|
||||||
|
select_casual_trade_offers(ent)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.log(dump(ent))
|
||||||
|
|
||||||
|
-- Refreshes entity
|
||||||
|
ent.object:set_properties(ent)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------
|
||||||
|
-- NPC Definition
|
||||||
---------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------
|
||||||
mobs:register_mob("advanced_npc:npc", {
|
mobs:register_mob("advanced_npc:npc", {
|
||||||
type = "npc",
|
type = "npc",
|
||||||
@ -284,6 +432,17 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
|
|
||||||
end,
|
end,
|
||||||
do_custom = function(self, dtime)
|
do_custom = function(self, dtime)
|
||||||
|
-- Timer function for casual traders to reset their trade offers
|
||||||
|
self.trader_data.change_offers_timer = self.trader_data.change_offers_timer + dtime
|
||||||
|
-- Check if time has come to change offers
|
||||||
|
if self.trader_data.trader_status == npc.trade.CASUAL and
|
||||||
|
self.trader_data.change_offers_timer >= self.trader_data.change_offers_timer_interval then
|
||||||
|
-- Reset timer
|
||||||
|
self.trader_data.change_offers_timer = 0
|
||||||
|
-- Re-select casual trade offers
|
||||||
|
select_casual_trade_offers(self)
|
||||||
|
end
|
||||||
|
|
||||||
-- Timer function for gifts
|
-- Timer function for gifts
|
||||||
for i = 1, #self.relationships do
|
for i = 1, #self.relationships do
|
||||||
local relationship = self.relationships[i]
|
local relationship = self.relationships[i]
|
||||||
@ -319,122 +478,6 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------
|
|
||||||
-- Spawning functions
|
|
||||||
---------------------------------------------------------------------------------------
|
|
||||||
-- These functions are used at spawn time to determine several
|
|
||||||
-- random attributes for the NPC in case they are not already
|
|
||||||
-- defined. On a later phase, pre-defining many of the NPC values
|
|
||||||
-- will be allowed.
|
|
||||||
|
|
||||||
-- This function checks for "female" text on the texture name
|
|
||||||
local function is_female_texture(textures)
|
|
||||||
for i = 1, #textures do
|
|
||||||
if string.find(textures[i], "female") ~= nil then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Choose whether NPC can have relationships. Only 30% of NPCs cannot have relationships
|
|
||||||
local function can_have_relationships()
|
|
||||||
local chance = math.random(1,10)
|
|
||||||
return chance > 3
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Choose a maximum of two items that the NPC will have at spawn time
|
|
||||||
-- These items are chosen from the favorite items list.
|
|
||||||
local function choose_spawn_items(self)
|
|
||||||
local number_of_items_to_add = math.random(1, 2)
|
|
||||||
local number_of_items = #npc.FAVORITE_ITEMS[self.sex].phase1
|
|
||||||
|
|
||||||
for i = 1, number_of_items_to_add do
|
|
||||||
npc.add_item_to_inventory(
|
|
||||||
self,
|
|
||||||
npc.FAVORITE_ITEMS[self.sex].phase1[math.random(1, number_of_items)].item,
|
|
||||||
math.random(1,5)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
-- Add currency to the items spawned with. Will add 5-10 tier 3
|
|
||||||
-- currency items
|
|
||||||
local currency_item_count = math.random(5, 10)
|
|
||||||
npc.add_item_to_inventory(self, npc.trade.prices.currency.tier3, currency_item_count)
|
|
||||||
|
|
||||||
minetest.log("Initial inventory: "..dump(self.inventory))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function npc_spawn(self, pos)
|
|
||||||
minetest.log("Spawning new NPC:")
|
|
||||||
local ent = self:get_luaentity()
|
|
||||||
ent.nametag = "Kio"
|
|
||||||
|
|
||||||
-- Determine sex based on textures
|
|
||||||
if (is_female_texture(ent.base_texture)) then
|
|
||||||
ent.sex = npc.FEMALE
|
|
||||||
else
|
|
||||||
ent.sex = npc.MALE
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Initialize all gift data
|
|
||||||
ent.gift_data = {
|
|
||||||
-- Choose favorite items. Choose phase1 per default
|
|
||||||
favorite_items = npc.relationships.select_random_favorite_items(ent.sex, "phase1"),
|
|
||||||
-- Choose disliked items. Choose phase1 per default
|
|
||||||
disliked_items = npc.relationships.select_random_disliked_items(ent.sex),
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Flag that determines if NPC can have a relationship
|
|
||||||
ent.can_have_relationship = can_have_relationships()
|
|
||||||
|
|
||||||
-- Initialize relationships object
|
|
||||||
ent.relationships = {}
|
|
||||||
|
|
||||||
-- Determines if NPC is married or not
|
|
||||||
ent.is_married_to = nil
|
|
||||||
|
|
||||||
-- Initialize dialogues
|
|
||||||
ent.dialogues = npc.dialogue.select_random_dialogues_for_npc(ent.sex,
|
|
||||||
"phase1",
|
|
||||||
ent.gift_data.favorite_items,
|
|
||||||
ent.gift_data.disliked_items)
|
|
||||||
|
|
||||||
-- Declare NPC inventory
|
|
||||||
ent.inventory = initialize_inventory()
|
|
||||||
|
|
||||||
-- Choose items to spawn with
|
|
||||||
choose_spawn_items(ent)
|
|
||||||
|
|
||||||
ent.trader_data = {
|
|
||||||
-- Type of trader
|
|
||||||
trader_status = npc.trade.get_random_trade_status(),
|
|
||||||
-- Current buy offers
|
|
||||||
buy_offers = {},
|
|
||||||
-- Current sell offers
|
|
||||||
sell_offers = {},
|
|
||||||
-- Items to buy change timer
|
|
||||||
change_offers_timer = 0,
|
|
||||||
-- Items to buy change timer interval
|
|
||||||
change_offers_timer_interval = 20
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Initialize trading offers if NPC is casual trader
|
|
||||||
if ent.trader_data.trader_status == npc.trade.CASUAL then
|
|
||||||
ent.trader_data.buy_offers = {
|
|
||||||
[1] = npc.trade.get_casual_trade_offer(ent, npc.trade.OFFER_BUY)
|
|
||||||
}
|
|
||||||
|
|
||||||
ent.trader_data.sell_offers = {
|
|
||||||
[1] = npc.trade.get_casual_trade_offer(ent, npc.trade.OFFER_SELL)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.log(dump(ent))
|
|
||||||
|
|
||||||
-- Refreshes entity
|
|
||||||
ent.object:set_properties(ent)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Spawn
|
-- Spawn
|
||||||
mobs:spawn({
|
mobs:spawn({
|
||||||
name = "advanced_npc:npc",
|
name = "advanced_npc:npc",
|
||||||
@ -447,6 +490,10 @@ mobs:spawn({
|
|||||||
on_spawn = npc_spawn,
|
on_spawn = npc_spawn,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Item definitions
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
mobs:register_egg("advanced_npc:npc", S("Npc"), "default_brick.png", 1)
|
mobs:register_egg("advanced_npc:npc", S("Npc"), "default_brick.png", 1)
|
||||||
|
|
||||||
-- compatibility
|
-- compatibility
|
||||||
|
@ -165,7 +165,7 @@ function npc.trade.get_casual_trade_offer(self, offer_type)
|
|||||||
price = price_string
|
price = price_string
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
-- Make sell offer, NPC will sell items to NPC at regular price
|
-- Make sell offer, NPC will sell items to player at regular price
|
||||||
-- NPC will also offer items from their inventory
|
-- NPC will also offer items from their inventory
|
||||||
local sellable_items = {}
|
local sellable_items = {}
|
||||||
for i = 1, #self.inventory do
|
for i = 1, #self.inventory do
|
||||||
@ -182,6 +182,10 @@ function npc.trade.get_casual_trade_offer(self, offer_type)
|
|||||||
-- Get and calculate price for this object
|
-- Get and calculate price for this object
|
||||||
minetest.log("Item: "..dump(item)..", name: "..dump(npc.get_item_name(item)))
|
minetest.log("Item: "..dump(item)..", name: "..dump(npc.get_item_name(item)))
|
||||||
local price_object = npc.trade.prices.table[npc.get_item_name(item)]
|
local price_object = npc.trade.prices.table[npc.get_item_name(item)]
|
||||||
|
-- Check price object, if price < 1 then offer to sell for 1
|
||||||
|
if price_object.count < 1 then
|
||||||
|
price_object.count = 1
|
||||||
|
end
|
||||||
local price_string = price_object.tier.." "..tostring(price_object.count * count)
|
local price_string = price_object.tier.." "..tostring(price_object.count * count)
|
||||||
-- Build return object
|
-- Build return object
|
||||||
result = {
|
result = {
|
||||||
|
Loading…
Reference in New Issue
Block a user