Relationships: completed support to increase relationship on talk. Implemented timer on this too.

Dialogues: Improved way responses are being stored into table for each player.
Added support for multi option dialogue and the dialogue action as well. WIP in function action type.
Cleaned up code.
This commit is contained in:
zorman2000 2016-12-02 18:39:06 -05:00
parent eeabe601dd
commit e89cd1e18d
2 changed files with 121 additions and 61 deletions

View File

@ -10,6 +10,7 @@ npc.dialogue.MAX_DIALOGUES = 4
-- This table contains the answers of dialogue boxes -- This table contains the answers of dialogue boxes
npc.dialogue.dialogue_results = { npc.dialogue.dialogue_results = {
options_dialogue = {},
yes_no_dialogue = {} yes_no_dialogue = {}
} }
@ -17,20 +18,28 @@ npc.dialogue.dialogue_results = {
-- The dialogue boxes are used for the player to interact with the -- The dialogue boxes are used for the player to interact with the
-- NPC in dialogues. -- NPC in dialogues.
-------------------------------------------------------------------- --------------------------------------------------------------------
-- Multi-option dialogue -- Creates and shows a multi-option dialogue based on the number of responses
local function create_formspec(options, close_option) -- that the dialogue object contains
local options_length = table.getn(options) + 1 function npc.dialogue.show_options_dialogue(responses, dismiss_option_label, player_name)
local formspec_height = (options_length * 0.7) + 1 local options_length = table.getn(responses) + 1
local formspec_height = (options_length * 0.7) + 0.7
local formspec = "size[7,"..tostring(formspec_height).."]" local formspec = "size[7,"..tostring(formspec_height).."]"
for i, opt in ipairs(options) do
for i = 1, #responses do
local y = 0.7; local y = 0.7;
if i > 1 then if i > 1 then
y = (y * i) y = (y * i)
end end
formspec = formspec.."button[0.5,"..y..";6,0.5;opt"..tostring(i)..";"..options[i].opt.."]" formspec = formspec.."button_exit[0.5,"..(y - 0.5)..";6,0.5;opt"..tostring(i)..";"..responses[i].text.."]"
end end
formspec = formspec.."button_exit[0.5,"..(formspec_height - 1)..";6,0.5;exit;"..close_option.."]" formspec = formspec.."button_exit[0.5,"..(formspec_height - 0.7)..";6,0.5;exit;"..dismiss_option_label.."]"
return formspec
-- Create entry on options_dialogue table
npc.dialogue.dialogue_results.options_dialogue[player_name] = {
options = responses
}
minetest.show_formspec(player_name, "advanced_npc:options", formspec)
end end
-- This function is used for showing a yes/no dialogue formspec -- This function is used for showing a yes/no dialogue formspec
@ -47,9 +56,7 @@ function npc.dialogue.show_yes_no_dialogue(prompt,
"button_exit[0.5,1.95;6,0.5;no_option;"..negative_answer_label.."]" "button_exit[0.5,1.95;6,0.5;no_option;"..negative_answer_label.."]"
-- Create entry into responses table -- Create entry into responses table
npc.dialogue.dialogue_results.yes_no_dialogue[1] = { npc.dialogue.dialogue_results.yes_no_dialogue[player_name] = {
name = player_name,
response = "",
yes_callback = positive_callback, yes_callback = positive_callback,
no_callback = negative_callback no_callback = negative_callback
} }
@ -93,6 +100,15 @@ function npc.dialogue.process_dialogue(dialogue, player_name)
if dialogue.text then if dialogue.text then
minetest.chat_send_player(player_name, dialogue.text) minetest.chat_send_player(player_name, dialogue.text)
end end
-- Check if there are responses, then show multi-option dialogue if there are
if dialogue.responses then
npc.dialogue.show_options_dialogue(
dialogue.responses,
npc.dialogue.NEGATIVE_ANSWER_LABEL,
player_name
)
end
-- TODO: Add support for flag, multi-option dialogue -- TODO: Add support for flag, multi-option dialogue
-- and their actions -- and their actions
end end
@ -137,52 +153,45 @@ local function rotate_npc_to_player(self)
self.object:setyaw(yaw) self.object:setyaw(yaw)
end end
---------------------------------------------------------------------
-- Drives conversation
---------------------------------------------------------------------
local function show_chat_option(npc_name, self, player_name, chat_options, close_option)
rotate_npc_to_player(self)
self.order = "stand"
local chatline = get_random_chatline(chat_options)
minetest.chat_send_player(player_name, chatline.text)
if chatline.options ~= nil then
minetest.log("Current options: "..dump(chatline.options))
local formspec = create_formspec(chatline.options, close_option)
minetest.show_formspec(player_name, "rndform", formspec)
end
self.order = "follow"
end
-- Function to get response by player name
local function get_yes_no_dialogue_response_by_player_name(player_name)
for i = 1,#npc.dialogue.dialogue_results.yes_no_dialogue do
local current_result = npc.dialogue.dialogue_results.yes_no_dialogue[i]
if current_result.name == player_name then
return current_result
end
end
return nil
end
-- Handler for chat formspec -- Handler for chat formspec
minetest.register_on_player_receive_fields(function (player, formname, fields) minetest.register_on_player_receive_fields(function (player, formname, fields)
-- Additional checks for other forms should be handled here -- Additional checks for other forms should be handled here
-- Handle yes/no dialogue
if formname == "advanced_npc:yes_no" then if formname == "advanced_npc:yes_no" then
local player_name = player:get_player_name() local player_name = player:get_player_name()
if fields then if fields then
local player_response = get_yes_no_dialogue_response_by_player_name(player_name) local player_response = npc.dialogue.dialogue_results.yes_no_dialogue[player_name]
if fields.yes_option then if fields.yes_option then
player_response.response = true
player_response.yes_callback() player_response.yes_callback()
elseif fields.no_option then elseif fields.no_option then
player_response.response = false
player_response.no_callback() player_response.no_callback()
end end
minetest.log(player_name.." chose response: " end
..dump(get_yes_no_dialogue_response_by_player_name(player_name).response)) end
-- Manage options dialogue
if formname == "advanced_npc:options" then
local player_name = player:get_player_name()
if fields then
-- Get player response
local player_response = npc.dialogue.dialogue_results.options_dialogue[player_name]
for i = 1, #player_response.options do
local button_label = "opt"..tostring(i)
if fields[button_label] then
if player_response.options[i].action_type == "dialogue" then
-- Process dialogue object
npc.dialogue.process_dialogue(player_response.options[i].action, player_name)
elseif player_response.options[i].action_type == "function" then
-- Execute function
-- Bug: for some reason function is null
player_response.options[i].action()
end
return
end
end
end end
end end

83
npc.lua
View File

@ -233,7 +233,8 @@ local function select_random_favorite_items(sex, phase)
end end
-- This function selects two random items from the npc.disliked_items table -- This function selects two random items from the npc.disliked_items table
-- It checks for sex and phase for choosing the items -- It checks for sex for choosing the items. They stay the same for all
-- phases
local function select_random_disliked_items(sex) local function select_random_disliked_items(sex)
local result = {} local result = {}
local items = {} local items = {}
@ -267,7 +268,9 @@ local function create_relationship(self, clicker_name)
-- The amount of time without providing gift or talking that will decrease relationship points -- The amount of time without providing gift or talking that will decrease relationship points
relationship_decrease_interval = npc.RELATIONSHIP_DECREASE_TIMER_INTERVAL, relationship_decrease_interval = npc.RELATIONSHIP_DECREASE_TIMER_INTERVAL,
-- Current timer count for relationship decrease -- Current timer count for relationship decrease
relationship_decrease_timer_value = 0 relationship_decrease_timer_value = 0,
-- Current timer count since last time player talked to NPC
talk_timer_value = 0
} }
end end
@ -327,6 +330,17 @@ local function check_npc_can_receive_gift(self, clicker_name)
return nil return nil
end end
-- Checks if relationship can be updated by talking
local function check_relationship_by_talk_timer_ready(self, clicker_name)
for i = 1, #self.relationships do
if self.relationships[i].name == clicker_name then
return self.relationships[i].talk_timer_value >= self.relationships[i].gift_interval
end
end
-- Not found
return nil
end
-- Resets the gift timer -- Resets the gift timer
local function reset_gift_timer(self, clicker_name) local function reset_gift_timer(self, clicker_name)
for i = 1, #self.relationships do for i = 1, #self.relationships do
@ -338,6 +352,16 @@ local function reset_gift_timer(self, clicker_name)
end end
end end
-- Resets the talk timer
local function reset_talk_timer(self, clicker_name)
for i = 1, #self.relationships do
if self.relationships[i].name == clicker_name then
self.relationships[i].talk_timer_value = 0
return
end
end
end
-- Resets the relationshop decrease timer -- Resets the relationshop decrease timer
local function reset_relationship_decrease_timer(self, clicker_name) local function reset_relationship_decrease_timer(self, clicker_name)
for i = 1, #self.relationships do for i = 1, #self.relationships do
@ -529,7 +553,22 @@ end
-- Relationships are slowly increased by talking, increases by +0.2. -- Relationships are slowly increased by talking, increases by +0.2.
-- Talking to married NPC increases relationship by +1 -- Talking to married NPC increases relationship by +1
local function dialogue_relationship_update(self, clicker_name) -- TODO: This needs a timer as the gift timer. NPC will talk anyways
-- but relationship will not increase.
local function dialogue_relationship_update(self, clicker)
-- Get clicker name
local clicker_name = npc.get_entity_name(clicker)
-- Check if relationship can be updated via talk
if check_relationship_by_talk_timer_ready(self, clicker_name) == false then
return
end
-- Create relationship if it doesn't exists
if check_relationship_exists(self, clicker_name) == false then
create_relationship(self, clicker_name)
end
local modifier = 0.2 local modifier = 0.2
if self.is_married_to ~= nil and clicker_name == self.is_married_to then if self.is_married_to ~= nil and clicker_name == self.is_married_to then
modifier = 1 modifier = 1
@ -537,23 +576,31 @@ local function dialogue_relationship_update(self, clicker_name)
-- Update relationship -- Update relationship
update_relationship(self, clicker_name, modifier) update_relationship(self, clicker_name, modifier)
-- Resert timers
reset_talk_timer(self, clicker_name)
reset_relationship_decrease_timer(self, clicker_name) reset_relationship_decrease_timer(self, clicker_name)
end end
-- Chat functions -- Chat functions
local function start_chat(self, clicker) local function start_dialogue(self, clicker)
local name = npc.get_entity_name(clicker)
-- Call chat function as normal
npc.dialogue.start_dialogue(self, clicker)
-- Check and update relationship if needed
dialogue_relationship_update(self, clicker)
-- Married player can tell NPC to follow or to stay at a given place -- Married player can tell NPC to follow or to stay at a given place
-- TODO: Improve this. There should be a dialogue box for this -- TODO: Improve this. There should be a dialogue box for this
if self.owner and self.owner == name then -- if self.owner and self.owner == name then
if self.order == "follow" then -- if self.order == "follow" then
self.order = "stand" -- self.order = "stand"
minetest.chat_send_player(name, S("Ok dear, I will wait here for you.")) -- minetest.chat_send_player(name, S("Ok dear, I will wait here for you."))
else -- else
self.order = "follow" -- self.order = "follow"
minetest.chat_send_player(name, S("Let's go honey!")) -- minetest.chat_send_player(name, S("Let's go honey!"))
end -- end
end -- end
end end
@ -639,12 +686,12 @@ mobs:register_mob("advanced_npc:npc", {
end, end,
npc.dialogue.NEGATIVE_ANSWER_LABEL, npc.dialogue.NEGATIVE_ANSWER_LABEL,
function() function()
npc.dialogue.start_dialogue(self, clicker) start_dialogue(self, clicker)
end, end,
name name
) )
else else
npc.dialogue.start_dialogue(self, clicker) start_dialogue(self, clicker)
end end
end, end,
@ -655,6 +702,10 @@ mobs:register_mob("advanced_npc:npc", {
-- Gift timer check -- Gift timer check
if relationship.gift_timer_value < relationship.gift_interval then if relationship.gift_timer_value < relationship.gift_interval then
relationship.gift_timer_value = relationship.gift_timer_value + dtime relationship.gift_timer_value = relationship.gift_timer_value + dtime
elseif relationship.talk_timer_value < relationship.gift_interval then
-- Relationship talk timer - only allows players to increase relationship
-- by talking on the same intervals as gifts
relationship.talk_timer_value = relationship.talk_timer_value + dtime
else else
-- Relationship decrease timer -- Relationship decrease timer
if relationship.relationship_decrease_timer_value if relationship.relationship_decrease_timer_value