Dialogues: Re-write dialogues to allow Minetest's like registration system instead of the actual table lookup system. In general, dialogues now are registered in similar fashion as nodes, entities and others are registered in Minetest.

Relationships: Re-write to the way favorite/disliked items are defined, now allow Minetest's like registration as well.
Random data: Random data now includes registrations for gift items and dialogues.
This commit is contained in:
Hector Franqui 2017-07-13 19:01:28 -04:00
parent bf935fd091
commit e79fb91ff3
7 changed files with 1274 additions and 675 deletions

View File

@ -1,20 +1,6 @@
-------------------------------------------------------------------------------------
-- NPC dialogue code by Zorman2000
-- Dialogue definitions:
-- TODO: Complete
-- {
-- text: "",
-- ^ The "spoken" dialogue line
-- flag:
-- ^ If the flag with the specified name has the specified value
-- then this dialogue is valid
-- {
-- name: ""
-- ^ Name of the flag
-- value:
-- ^ Expected value of the flag. A flag can be a function. In such a case, it is
-- expected the function will return this value.
-- }
-- }
-------------------------------------------------------------------------------------
npc.dialogue = {}
@ -37,11 +23,144 @@ npc.dialogue.dialogue_results = {
yes_no_dialogue = {}
}
---------------------------------------------------------------------------------------
npc.dialogue.tags = {
UNISEX = "unisex",
MALE = "male",
FEMALE = "female",
-- Relationship based tags - these are one-to-one with the
-- phase names.
PHASE_1 = "phase1",
PHASE_2 = "phase2",
PHASE_3 = "phase3",
PHASE_4 = "phase4",
PHASE_5 = "phase5",
GIFT_ITEM_HINT = "gift_item_hint",
GIFT_ITEM_RESPONSE = "gift_item_response",
GIFT_ITEM_LIKED = "gift_item_liked",
GIFT_ITEM_UNLIKED = "gift_item_unliked",
-- Occupation-based tags - these are one-to-one with the
-- default occupation names
BASIC = "basic", -- Dialogues related to the basic occupation should
-- use this. As basic occupation is generic, any occupation
-- should be able to use these dialogues.
DEFAULT_FARMER = "default_farmer",
DEFAULT_COOKER = "default_cooker"
}
-- This table will contain all the registered dialogues for NPCs
npc.dialogue.registered_dialogues = {}
--------------------------------------------------------------------------------------
-- Dialogue registration functions
-- All dialogues will be registered by providing a definition.
-- A unique key will be assigned to them. The dialogue definition is the following:
-- {
-- text: "",
-- ^ The "spoken" dialogue line
-- flag:
-- ^ If the flag with the specified name has the specified value
-- then this dialogue is valid
-- {
-- name: ""
-- ^ Name of the flag
-- value:
-- ^ Expected value of the flag. A flag can be a function. In such a case, it is
-- expected the function will return this value.
-- },
-- tags = {
-- -- Tags are an array of string that allow to classify dialogues
-- -- A dialogue can have as many tags as desired and can take any form.
-- -- However, for consistency, some predefined tags can be found at
-- -- npc.dialogue.tags.
-- -- Example:
-- "phase1",
-- "any"
-- }
-- responses = {
-- -- Array of responses the player can choose. A response can be of
-- -- two types: as [1] or as [2] (see example below)
-- [1] = {
-- text = "Yes",
-- -- Text displayed to the player
-- action_type = "dialogue",
-- -- Type of action that happens when the player chooses this response.
-- -- can be "dialogue" or "function". This example shows "dialogue"
-- action = {
-- text = "It's so beautiful, and big, and large, and infinite, and..."
-- },
-- },
-- -- A table containing a dialogue. This means you can include not only
-- -- text but also flag and responses as well. Dialogues are recursive.
-- [2] = {
-- text = "No",
-- action_type = "function",
-- action = function(self, player)
-- -- A function will have access to self, which is the NPC
-- -- and the player, which is the player ObjectRef. You can
-- -- pretty much do anything here. The example here is very simple,
-- -- just sending a chat message. But you can add items to players
-- -- or to NPCs and so on.
-- minetest.chat_send_player(player:get_player_name(), "Oh, ok...")
-- end,
-- },
-- }
-- }
--------------------------------------------------------------------------------------
-- The register dialogue function will just receive the definition as
-- explained above. The unique key will be the index it gets into the
-- array when inserted.
function npc.dialogue.register_dialogue(def)
-- If def has not tags then apply the default ones
if not def.tags then
def.tags = {npc.dialogue.tags.UNISEX, npc.dialogue.tags.PHASE_1}
end
-- Insert dialogue into table
table.insert(npc.dialogue.registered_dialogues, def)
--minetest.log("Dialogues: "..dump(npc.dialogue.registered_dialogues))
end
-- This function returns a table of dialogues that meet the given
-- tags array. The keys in the table are the keys in
-- npc.dialogue.registered_dialogues, therefore you can use them to
--retrieve specific dialogues. However, it should be stored by the NPC.
function npc.dialogue.search_dialogue_by_tags(tags, find_all)
--minetest.log("Tags being searched: "..dump(tags))
local result = {}
for key, def in pairs(npc.dialogue.registered_dialogues) do
-- Check if def.tags have any of the provided tags
local tags_found = 0
--minetest.log("Tags on dialogue def: "..dump(def.tags))
for i = 1, #tags do
if npc.utils.array_contains(def.tags, tags[i]) then
tags_found = tags_found + 1
end
end
--minetest.log("Tags found: "..dump(tags_found))
-- Check if we found all tags
if find_all then
if tags_found == #tags then
-- Add result
result[key] = def
end
elseif not find_all then
if tags_found == #tags or tags_found == #def.tags then
-- Add result
result[key] = def
end
end
-- if (find_all == true and tags_found == #tags)
-- or (not find_all and tags_found == #def.tags) then
-- end
end
return result
end
--------------------------------------------------------------------------------------
-- Dialogue box definitions
-- The dialogue boxes are used for the player to interact with the
-- NPC in dialogues.
---------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
-- Creates and shows a multi-option dialogue based on the number of responses
-- that the dialogue object contains
function npc.dialogue.show_options_dialogue(self,
@ -67,10 +186,14 @@ function npc.dialogue.show_options_dialogue(self,
-- Create entry on options_dialogue table
npc.dialogue.dialogue_results.options_dialogue[player_name] = {
npc = self,
is_married_dialogue = (dialogue.dialogue_type == npc.dialogue.dialogue_type.married),
is_casual_trade_dialogue = (dialogue.dialogue_type == npc.dialogue.dialogue_type.casual_trade),
is_dedicated_trade_dialogue = (dialogue.dialogue_type == npc.dialogue.dialogue_type.dedicated_trade),
is_custom_trade_dialogue = (dialogue.dialogue_type == npc.dialogue.dialogue_type.custom_trade),
is_married_dialogue =
(dialogue.dialogue_type == npc.dialogue.dialogue_type.married),
is_casual_trade_dialogue =
(dialogue.dialogue_type == npc.dialogue.dialogue_type.casual_trade),
is_dedicated_trade_dialogue =
(dialogue.dialogue_type == npc.dialogue.dialogue_type.dedicated_trade),
is_custom_trade_dialogue =
(dialogue.dialogue_type == npc.dialogue.dialogue_type.custom_trade),
casual_trade_type = dialogue.casual_trade_type,
options = responses
}
@ -104,9 +227,9 @@ function npc.dialogue.show_yes_no_dialogue(self,
minetest.show_formspec(player_name, "advanced_npc:yes_no", formspec)
end
---------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
-- Dialogue methods
---------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
-- This function sets a unique response ID (made of <depth>:<response index>) to
-- each response that features a function. This is to be able to locate the
-- function easily later
@ -135,43 +258,79 @@ end
-- Select random dialogue objects for an NPC based on sex
-- and the relationship phase with player
function npc.dialogue.select_random_dialogues_for_npc(sex, phase, favorite_items, disliked_items)
function npc.dialogue.select_random_dialogues_for_npc(self, phase)
local result = {
normal = {},
hints = {}
}
local dialogues = npc.data.DIALOGUES.female
if sex == npc.MALE then
dialogues = npc.data.DIALOGUES.male
local phase_tag = "phase1"
if phase then
phase_tag = phase
end
dialogues = dialogues[phase]
local search_tags = {
"unisex",
self.sex,
phase_tag,
self.occupation
}
local dialogues = npc.dialogue.search_dialogue_by_tags(search_tags)
minetest.log("dialogues found by tag search: "..dump(dialogues))
-- Determine how many dialogue lines the NPC will have
local number_of_dialogues = math.random(npc.dialogue.MIN_DIALOGUES, npc.dialogue.MAX_DIALOGUES)
for i = 1,number_of_dialogues do
local dialogue_id = math.random(1, #dialogues)
result.normal[i] = dialogues[dialogue_id]
result.normal[i] = dialogue_id
set_response_ids_recursively(result.normal[i], 0, dialogue_id)
--set_response_ids_recursively(result.normal[i], 0, dialogue_id)
end
-- Add item hints.
-- Favorite items
for i = 1, 2 do
result.hints[i] = {}
result.hints[i].text =
npc.relationships.get_hint_for_favorite_item(favorite_items["fav"..tostring(i)], sex, phase)
local hints = npc.relationships.get_dialogues_for_gift_item(
self.gift_data.favorite_items["fav"..tostring(i)],
npc.dialogue.tags.GIFT_ITEM_HINT,
npc.dialogue.tags.GIFT_ITEM_LIKED,
self.sex,
phase_tag)
for key, value in pairs(hints) do
result.hints[i] = key
end
end
-- Disliked items
for i = 3, 4 do
result.hints[i] = {}
result.hints[i].text =
npc.relationships.get_hint_for_disliked_item(disliked_items["dis"..tostring(i-2)], sex)
local hints = npc.relationships.get_dialogues_for_gift_item(
self.gift_data.disliked_items["dis"..tostring(i-2)],
npc.dialogue.tags.GIFT_ITEM_HINT,
npc.dialogue.tags.GIFT_ITEM_UNLIKED,
self.sex)
for key, value in pairs(hints) do
result.hints[i] = key
end
end
-- Favorite items
-- for i = 1, 2 do
-- result.hints[i] = {}
-- result.hints[i].text =
-- npc.relationships.get_hint_for_favorite_item(
-- self.gift_data.favorite_items["fav"..tostring(i)], self.sex, phase_tag)
-- end
-- -- Disliked items
-- for i = 3, 4 do
-- result.hints[i] = {}
-- result.hints[i].text =
-- npc.relationships.get_hint_for_disliked_item(
-- self.gift_data.disliked_items["dis"..tostring(i-2)], self.sex, phase_tag)
-- end
minetest.log("Dialogue results:"..dump(result))
return result
end
@ -181,7 +340,10 @@ function npc.dialogue.create_custom_trade_options(self, player)
-- Create the action for each option
local actions = {}
for i = 1, #self.trader_data.custom_trades do
table.insert(actions, function() npc.trade.show_custom_trade_offer(self, player, self.trader_data.custom_trades[i]) end)
table.insert(actions,
function()
npc.trade.show_custom_trade_offer(self, player, self.trader_data.custom_trades[i])
end)
end
-- Default text to be shown for dialogue prompt
local text = npc.trade.CUSTOM_TRADES_PROMPT_TEXT
@ -211,60 +373,61 @@ function npc.dialogue.start_dialogue(self, player, show_married_dialogue)
-- Construct dialogue for marriage
if npc.relationships.get_relationship_phase(self, player:get_player_name()) == "phase6"
and show_married_dialogue == true then
dialogue = npc.relationships.MARRIED_NPC_DIALOGUE
npc.dialogue.process_dialogue(self, dialogue, player:get_player_name())
dialogue = npc.relationships.MARRIED_NPC_DIALOGUE
npc.dialogue.process_dialogue(self, dialogue, player:get_player_name())
return
end
-- Show options dialogue for dedicated trader
if self.trader_data.trader_status == npc.trade.TRADER then
dialogue = npc.trade.DEDICATED_TRADER_PROMPT
npc.dialogue.process_dialogue(self, dialogue, player:get_player_name())
return
end
-- Show options dialogue for dedicated trader
if self.trader_data.trader_status == npc.trade.TRADER then
dialogue = npc.trade.DEDICATED_TRADER_PROMPT
npc.dialogue.process_dialogue(self, dialogue, player:get_player_name())
return
end
local chance = math.random(1, 100)
minetest.log("Chance: "..dump(chance))
if chance < 30 then
-- If NPC is a casual trader, show a sell or buy dialogue 30% of the time, depending
-- on the state of the casual trader.
if self.trader_data.trader_status == npc.trade.NONE then
-- Show custom trade options if available
if table.getn(self.trader_data.custom_trades) > 0 then
-- Show custom trade options
dialogue = npc.dialogue.create_custom_trade_options(self, player)
end
elseif self.trader_data.trader_status == npc.trade.CASUAL then
local max_trade_chance = 2
if table.getn(self.trader_data.custom_trades) > 0 then
max_trade_chance = 3
end
-- Show buy/sell with 50% chance each
local trade_chance = math.random(1, max_trade_chance)
if trade_chance == 1 then
-- Show casual buy dialogue
dialogue = npc.trade.CASUAL_TRADE_BUY_DIALOGUE
elseif trade_chance == 2 then
-- Show casual sell dialogue
dialogue = npc.trade.CASUAL_TRADE_SELL_DIALOGUE
elseif trade_chance == 3 then
-- Show custom trade options
dialogue = npc.dialogue.create_custom_trade_options(self, player)
end
end
-- Show trading options for casual traders
-- If NPC has custom trading options, these will be
-- shown as well with equal chance as the casual
-- buy/sell options
if self.trader_data.trader_status == npc.trade.NONE then
-- Show custom trade options if available
if table.getn(self.trader_data.custom_trades) > 0 then
-- Show custom trade options
dialogue = npc.dialogue.create_custom_trade_options(self, player)
end
elseif self.trader_data.trader_status == npc.trade.CASUAL then
local max_trade_chance = 2
if table.getn(self.trader_data.custom_trades) > 0 then
max_trade_chance = 3
end
-- Show buy/sell with 50% chance each
local trade_chance = math.random(1, max_trade_chance)
if trade_chance == 1 then
-- Show casual buy dialogue
dialogue = npc.trade.CASUAL_TRADE_BUY_DIALOGUE
elseif trade_chance == 2 then
-- Show casual sell dialogue
dialogue = npc.trade.CASUAL_TRADE_SELL_DIALOGUE
elseif trade_chance == 3 then
-- Show custom trade options
dialogue = npc.dialogue.create_custom_trade_options(self, player)
end
end
elseif chance >= 30 and chance < 90 then
-- Choose a random dialogue from the common ones
-- Choose a random dialogue from the common ones
dialogue = self.dialogues.normal[math.random(1, #self.dialogues.normal)]
elseif chance >= 90 then
-- Choose a random dialogue line from the favorite/disliked item hints
-- Choose a random dialogue line from the favorite/disliked item hints
dialogue = self.dialogues.hints[math.random(1, 4)]
end
local dialogue_result = npc.dialogue.process_dialogue(self, dialogue, player:get_player_name())
if dialogue_result == false then
-- Try to find another dialogue line
npc.dialogue.start_dialogue(self, player, show_married_dialogue)
end
if dialogue_result == false then
-- Try to find another dialogue line
npc.dialogue.start_dialogue(self, player, show_married_dialogue)
end
end
-- This function processes a dialogue object and performs
@ -274,6 +437,11 @@ function npc.dialogue.process_dialogue(self, dialogue, player_name)
-- Freeze NPC actions
npc.lock_actions(self)
if type(dialogue) ~= "table" then
dialogue = npc.dialogue.registered_dialogues[dialogue]
minetest.log("Found dialogue: "..dump(dialogue))
end
-- Check if this dialogue has a flag definition
if dialogue.flag then
-- Check if the NPC has this flag

View File

@ -24,6 +24,7 @@ end
mobs.intllib = S
dofile(path .. "/npc.lua")
dofile(path .. "/utils.lua")
dofile(path .. "/spawner.lua")
dofile(path .. "/relationships.lua")
dofile(path .. "/dialogue.lua")
@ -33,6 +34,10 @@ dofile(path .. "/actions/actions.lua")
dofile(path .. "/actions/places.lua")
dofile(path .. "/actions/pathfinder.lua")
dofile(path .. "/actions/node_registry.lua")
-- Load random data definitions
dofile(path .. "/random_data.lua")
dofile(path .. "/random_data/dialogues_data.lua")
dofile(path .. "/random_data/gift_items_data.lua")
dofile(path .. "/random_data/names_data.lua")
print (S("[Mod] Advanced NPC loaded"))

1186
npc.lua

File diff suppressed because it is too large Load Diff

View File

View File

@ -0,0 +1,237 @@
------------------------------------------------------------------------------
-- Gift Items data definitions
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- PHASE 1
------------------------------------------------------------------------------
npc.relationships.register_favorite_item("default:apple", "phase1", "female", {
responses = {"Hey, I really wanted an apple, thank you!"},
hints = {"I could really do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase1", "female", {
responses = {"Thanks, you didn't have to, but thanks..."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("farming:seed_cotton", "phase1", "female", {
responses = {"Thank you, I will plant this really soon"},
hints = {"I would like to have some cotton plants around"}
})
npc.relationships.register_favorite_item("farming:seed_wheat", "phase1", "female", {
responses = {"Thank you! These seeds will make a good wheat plant!"},
hints = {"I've been thinking I should get wheat seeds"}
})
npc.relationships.register_favorite_item("flowers:rose", "phase1", "female", {
responses = {"Thanks..."},
hints = {"Red roses make a nice gift!"}
})
npc.relationships.register_favorite_item("flowers:geranium", "phase1", "female", {
responses = {"Oh, for me? Thank you!"},
hints = {"Blue geraniums are so beautiful"}
})
npc.relationships.register_favorite_item("default:clay_lump", "phase1", "female", {
responses = {"Thanks! Now, what can I do with this..."},
hints = {"If I had some clay lump, I may do some pottery"}
})
npc.relationships.register_favorite_item("mobs:meat_raw", "phase1", "female", {
responses = {"This will be great for tonight! Thanks"},
hints = {"A good dinner always have meat"}
})
npc.relationships.register_favorite_item("mobs:leather", "phase1", "female", {
responses = {"Thank you! I needed this!"},
hints = {"If only I could get some leather"}
})
npc.relationships.register_favorite_item("default:sapling", "phase1", "female", {
responses = {"Now I can plant that tree..."},
hints = {"I really would like an apple tree close by."}
})
npc.relationships.register_favorite_item("farming:cotton", "phase2", "female", {
responses = {"This is going to be very helpful, thank you!"},
hints = {"If I just had some cotton lying around..."}
})
npc.relationships.register_favorite_item("wool:white", "phase2", "female", {
responses = {"Thanks, you didn't have to, but thanks..."},
hints = {"Have you seen a sheep? I wish I had some white wool..."}
})
npc.relationships.register_favorite_item("default:apple", "phase3", "female", {
responses = {"Hey, I really wanted an apple, thank you!"},
hints = {"I could really do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase3", "female", {
responses = {"Thanks, you didn't have to, but thanks..."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("default:apple", "phase4", "female", {
responses = {"Hey, I really wanted an apple, thank you!"},
hints = {"I could really do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase4", "female", {
responses = {"Thanks, you didn't have to, but thanks..."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("default:apple", "phase5", "female", {
responses = {"Hey, I really wanted an apple, thank you!"},
hints = {"I could really do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase5", "female", {
responses = {"Thanks, you didn't have to, but thanks..."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("default:apple", "phase6", "female", {
responses = {"Hey, I really wanted an apple, thank you!"},
hints = {"I could really do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase6", "female", {
responses = {"Thanks, you didn't have to, but thanks..."},
hints = {"Some fresh bread would be good!"}
})
-- Male
npc.relationships.register_favorite_item("default:apple", "phase1", "male", {
responses = {"Good apple, thank you!"},
hints = {"I could do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase1", "male", {
responses = {"Thank you! I was hungry."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("farming:seed_cotton", "phase1", "male", {
responses = {"Thank you, I will plant this soon"},
hints = {"I would like to have some cotton plants around."}
})
npc.relationships.register_favorite_item("farming:seed_wheat", "phase1", "male", {
responses = {"Thank you! These seeds will make a good wheat plant!"},
hints = {"I've been thinking I should get wheat seeds."}
})
npc.relationships.register_favorite_item("default:wood", "phase1", "male", {
responses = {"Thanks, I needed this."},
hints = {"Some wood without having to cut a tree would be good.}"}
})
npc.relationships.register_favorite_item("default:tree", "phase1", "male", {
responses = {"Excellent to get that furnace going!"},
hints = {"I'm looking for some logs"}
})
npc.relationships.register_favorite_item("default:clay_lump", "phase1", "male", {
responses = {"Thanks! Now, what can I do with this..."},
hints = {"Now, some clay would be good."}
})
npc.relationships.register_favorite_item("mobs:meat_raw", "phase1", "male", {
responses = {"This makes a great meal. Thank you"},
hints = {"Meat is always great"},
})
npc.relationships.register_favorite_item("mobs:leather", "phase1", "male", {
responses = {"Time to tan some leathers!"},
hints = {"I have been needing leather these days."}
})
npc.relationships.register_favorite_item("default:sapling", "phase1", "male", {
responses = {"Thanks, I will plant this right now"},
hints = {"I really would like an apple tree close by."}
})
npc.relationships.register_favorite_item("default:apple", "phase2", "male", {
responses = {"Good apple, thank you!"},
hints = {"I could do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase2", "male", {
responses = {"Thank you! I was hungry."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("default:apple", "phase3", "male", {
responses = {"Good apple, thank you!"},
hints = {"I could do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase3", "male", {
responses = {"Thank you! I was hungry."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("default:apple", "phase4", "male", {
responses = {"Good apple, thank you!"},
hints = {"I could do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase4", "male", {
responses = {"Thank you! I was hungry."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("default:apple", "phase5", "male", {
responses = {"Good apple, thank you!"},
hints = {"I could do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase5", "male", {
responses = {"Thank you! I was hungry."},
hints = {"Some fresh bread would be good!"}
})
npc.relationships.register_favorite_item("default:apple", "phase6", "male", {
responses = {"Good apple, thank you!"},
hints = {"I could do with an apple..."}
})
npc.relationships.register_favorite_item("farming:bread", "phase6", "male", {
responses = {"Thank you! I was hungry."},
hints = {"Some fresh bread would be good!"}
})
-- Disliked items
-- Female
npc.relationships.register_disliked_item("default:stone", "female", {
responses = {"A stone, oh... why do you give this to me?"},
hints = {"Why would someone want a stone?"}
})
npc.relationships.register_disliked_item("default:cobble", "female", {
responses = {"Cobblestone? No, no, why?"},
hints = {"Anything worst than stone is cobblestone."}
})
-- Male
npc.relationships.register_disliked_item("default:stone", "male", {
responses = {"Good apple, thank you!"},
hints = {"I could do with an apple..."}
})
npc.relationships.register_disliked_item("default:cobble", "male", {
responses = {"Cobblestone!? Wow, you sure think a lot before giving a gift..."},
hints = {"If I really hate something, that's cobblestone!"}
})
npc.log("INFO", "Registered gift items: "..dump(npc.relationships.gift_items))
npc.log("INFO", "Registered dialogues: "..dump(npc.dialogue.registered_dialogues))

View File

View File

@ -37,6 +37,40 @@ 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}
npc.relationships.GIFT_ITEM_LIKED = "liked"
npc.relationships.GIFT_ITEM_DISLIKED = "disliked"
npc.relationships.GIFT_ITEM_HINT = "hint"
npc.relationships.GIFT_ITEM_RESPONSE = "response"
-- Favorite and disliked items tables
npc.relationships.gift_items = {
liked = {
female = {
["phase1"] = {},
["phase2"] = {},
["phase3"] = {},
["phase4"] = {},
["phase5"] = {},
["phase6"] = {}
},
male = {
["phase1"] = {},
["phase2"] = {},
["phase3"] = {},
["phase4"] = {},
["phase5"] = {},
["phase6"] = {}
}
},
disliked = {
female = {},
male = {}
}
}
npc.relationships.DEFAULT_RESPONSE_NO_GIFT_RECEIVE =
"Thank you, but I don't need anything for now."
-- Married NPC dialogue definition
npc.relationships.MARRIED_NPC_DIALOGUE = {
@ -90,6 +124,96 @@ function npc.relationships.get_relationship_phase_by_points(points)
end
end
-- Registration functions
-----------------------------------------------------------------------------
-- Items can be registered to be part of the gift system using the
-- below function. The def is the following:
-- {
-- dialogues = {
-- liked = {
-- -- ^ This is an array of the following table:
-- [1] = {dialogue_type="", sex="", text=""}
-- -- ^ dialogue_type: defines is this is a hint or a response.
-- -- valid values are: "hint", "response"
-- -- sex: valid values are: "male", female"
-- -- text: the dialogue text
-- },
-- disliked = {
-- -- ^ This is an array with the same type of tables as above
-- }
-- }
-- }
function npc.relationships.register_favorite_item(item_name, phase, sex, def)
local dialogues = {}
-- Register dialogues based on the hints and responses
-- Liked
for i = 1, #def.hints do
table.insert(dialogues, {
text = def.hints[i],
tags = {phase, item_name, sex,
npc.dialogue.tags.GIFT_ITEM_HINT, npc.dialogue.tags.GIFT_ITEM_LIKED}
})
end
for i = 1, #def.responses do
table.insert(dialogues, {
text = def.responses[i],
tags = {phase, item_name, sex,
npc.dialogue.tags.GIFT_ITEM_RESPONSE, npc.dialogue.tags.GIFT_ITEM_LIKED}
})
end
-- Register all dialogues
for i = 1, #dialogues do
npc.dialogue.register_dialogue(dialogues[i])
end
-- Insert item into table
table.insert(npc.relationships.gift_items.liked[sex][phase], item_name)
end
function npc.relationships.register_disliked_item(item_name, sex, def)
local dialogues = {}
-- Register dialogues based on the hints and responses
-- Liked
for i = 1, #def.hints do
table.insert(dialogues, {
text = def.hints[i],
tags = {item_name, sex,
npc.dialogue.tags.GIFT_ITEM_HINT, npc.dialogue.tags.GIFT_ITEM_UNLIKED}
})
end
for i = 1, #def.responses do
table.insert(dialogues, {
text = def.responses[i],
tags = {item_name, sex,
npc.dialogue.tags.GIFT_ITEM_RESPONSE, npc.dialogue.tags.GIFT_ITEM_UNLIKED}
})
end
-- Register all dialogues
for i = 1, #dialogues do
npc.dialogue.register_dialogue(dialogues[i])
end
-- Insert item into table
table.insert(npc.relationships.gift_items.disliked[sex], item_name)
end
function npc.relationships.get_dialogues_for_gift_item(item_name, dialogue_type, item_type, sex, phase)
local tags = {
[1] = item_name,
[2] = dialogue_type,
[3] = item_type,
[4] = sex
}
if phase ~= nil then
tags[5] = phase
end
minetest.log("Searching with tags: "..dump(tags))
return npc.dialogue.search_dialogue_by_tags(tags, true)
end
-- Returns the response message for a given item
function npc.relationships.get_response_for_favorite_item(item_name, sex, phase)
local items = npc.FAVORITE_ITEMS.female
@ -144,7 +268,7 @@ end
-- Relationship functions
---------------------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- This function selects two random items from the npc.favorite_items table
-- It checks for sex and phase for choosing the items
@ -152,18 +276,19 @@ function npc.relationships.select_random_favorite_items(sex, phase)
local result = {}
local items = {}
-- Filter sex
if sex == npc.FEMALE then
items = npc.FAVORITE_ITEMS.female
else
items = npc.FAVORITE_ITEMS.male
end
-- -- Filter sex
-- if sex == npc.FEMALE then
-- items = npc.FAVORITE_ITEMS.female
-- else
-- items = npc.FAVORITE_ITEMS.male
-- end
-- Select the phase
items = items[phase]
-- items = items[phase]
items = npc.relationships.gift_items.liked[sex][phase]
result.fav1 = items[math.random(1, #items)].item
result.fav2 = items[math.random(1, #items)].item
result.fav1 = items[math.random(1, #items)]
result.fav2 = items[math.random(1, #items)]
return result
end
@ -174,15 +299,16 @@ function npc.relationships.select_random_disliked_items(sex)
local result = {}
local items = {}
-- Filter sex
if sex == npc.FEMALE then
items = npc.DISLIKED_ITEMS.female
else
items = npc.DISLIKED_ITEMS.male
end
-- -- Filter sex
-- if sex == npc.FEMALE then
-- items = npc.DISLIKED_ITEMS.female
-- else
-- items = npc.DISLIKED_ITEMS.male
-- end
items = npc.relationships.gift_items.disliked[sex]
result.dis1 = items[math.random(1, #items)].item
result.dis2 = items[math.random(1, #items)].item
result.dis1 = items[math.random(1, #items)]
result.dis2 = items[math.random(1, #items)]
return result
end
@ -233,10 +359,8 @@ local function update_relationship(self, clicker_name, modifier)
npc.relationships.select_random_favorite_items(self.sex, self.relationships[i].phase)
-- Re-select dialogues per new
self.dialogues =
npc.dialogue.select_random_dialogues_for_npc(self.sex,
self.relationships[i].phase,
self.gift_data.favorite_items,
self.gift_data.disliked_items)
npc.dialogue.select_random_dialogues_for_npc(self,
self.relationships[i].phase)
return true
end
return false
@ -352,14 +476,22 @@ local function show_receive_gift_reaction(self, item_name, modifier, clicker_nam
-- Send message
-- TODO: There might be an error with getting the message...
--minetest.log("Item_name: "..dump(item_name)..", sex: "..dump(self.sex)..", phase: "..dump(phase))
local message_to_send =
npc.relationships.get_response_for_favorite_item(item_name, self.sex, phase)
local message_to_send = npc.relationships.get_dialogues_for_gift_item(
item_name,
npc.relationships.GIFT_ITEM_RESPONSE,
npc.relationships.GIFT_ITEM_LIKED,
self.sex,
phase)
npc.chat(self.npc_name, clicker_name, message_to_send)
-- Disliked items reactions
elseif modifier < 0 then
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "default_item_smoke.png")
--minetest.log("Item name: "..item_name..", sex: "..self.sex)
local message_to_send = npc.relationships.get_response_for_disliked_item(item_name, self.sex)
local message_to_send = npc.relationships.get_dialogues_for_gift_item(
item_name,
npc.relationships.GIFT_ITEM_RESPONSE,
npc.relationships.GIFT_ITEM_DISLIKED,
self.sex)
npc.chat(self.npc_name, clicker_name, message_to_send)
end
@ -390,7 +522,7 @@ function npc.relationships.receive_gift(self, clicker)
-- and that with only a certain chance. The self.owner is to whom is married
-- this NPC... he he.
if get_relationship_points(self, clicker_name) >=
npc.relationships.RELATIONSHIP_PHASE["phase5"].limit
npc.relationships.RELATIONSHIP_PHASE["phase5"].limit
and self.owner ~= clicker_name
and item:get_name() ~= "advanced_npc:marriage_ring" then
npc.chat(self.npc_name, clicker_name,
@ -401,7 +533,7 @@ function npc.relationships.receive_gift(self, clicker)
reset_gift_timer(self, clicker_name)
return true
elseif get_relationship_points(self, clicker_name) >=
npc.relationships.RELATIONSHIP_PHASE["phase5"].limit
npc.relationships.RELATIONSHIP_PHASE["phase5"].limit
and item:get_name() == "advanced_npc:marriage_ring" then
-- If the player/entity is offering a marriage ring, then NPC will accept with a 50%
-- chance to marry the clicker
@ -425,21 +557,20 @@ function npc.relationships.receive_gift(self, clicker)
else
npc.chat(self.npc_name, clicker_name,
"Dear, I feel the same as you. But maybe not yet...")
end
-- Reset gift timer
reset_gift_timer(self, clicker_name)
return true
end
-- Marriage gifts: except for disliked items, all product a 0.5 * npc.ITEM_GIFT_EFFECT
-- Disliked items cause only a -1 point effect
-- Disliked items cause only a -0.5 point effect
if get_relationship_points(self, clicker_name) >=
npc.relationships.RELATIONSHIP_PHASE["phase5"].limit then
local modifier = 0.5 * npc.ITEM_GIFT_EFFECT
-- Check for disliked items
if item:get_name() == self.gift_data.disliked_items.dis1
or item:get_name() == self.gift_data.disliked_items.dis2 then
modifier = -1
modifier = -0.5
show_receive_gift_reaction(self, item:get_name(), modifier, clicker_name, false)
elseif item:get_name() == self.gift_data.favorite_items.fav1
or item:get_name() == self.gift_data.favorite_items.fav2 then