From e89cd1e18d3df5285833ae0211f8b6dc64508ce3 Mon Sep 17 00:00:00 2001 From: zorman2000 Date: Fri, 2 Dec 2016 18:39:06 -0500 Subject: [PATCH] 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. --- dialogue.lua | 99 ++++++++++++++++++++++++++++------------------------ npc.lua | 83 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 121 insertions(+), 61 deletions(-) diff --git a/dialogue.lua b/dialogue.lua index 82eb929..fe71d0a 100644 --- a/dialogue.lua +++ b/dialogue.lua @@ -10,6 +10,7 @@ npc.dialogue.MAX_DIALOGUES = 4 -- This table contains the answers of dialogue boxes npc.dialogue.dialogue_results = { + options_dialogue = {}, yes_no_dialogue = {} } @@ -17,20 +18,28 @@ npc.dialogue.dialogue_results = { -- The dialogue boxes are used for the player to interact with the -- NPC in dialogues. -------------------------------------------------------------------- --- Multi-option dialogue -local function create_formspec(options, close_option) - local options_length = table.getn(options) + 1 - local formspec_height = (options_length * 0.7) + 1 +-- Creates and shows a multi-option dialogue based on the number of responses +-- that the dialogue object contains +function npc.dialogue.show_options_dialogue(responses, dismiss_option_label, player_name) + local options_length = table.getn(responses) + 1 + local formspec_height = (options_length * 0.7) + 0.7 local formspec = "size[7,"..tostring(formspec_height).."]" - for i, opt in ipairs(options) do + + for i = 1, #responses do local y = 0.7; if i > 1 then y = (y * i) 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 - formspec = formspec.."button_exit[0.5,"..(formspec_height - 1)..";6,0.5;exit;"..close_option.."]" - return formspec + formspec = formspec.."button_exit[0.5,"..(formspec_height - 0.7)..";6,0.5;exit;"..dismiss_option_label.."]" + + -- 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 -- 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.."]" -- Create entry into responses table - npc.dialogue.dialogue_results.yes_no_dialogue[1] = { - name = player_name, - response = "", + npc.dialogue.dialogue_results.yes_no_dialogue[player_name] = { yes_callback = positive_callback, no_callback = negative_callback } @@ -93,6 +100,15 @@ function npc.dialogue.process_dialogue(dialogue, player_name) if dialogue.text then minetest.chat_send_player(player_name, dialogue.text) 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 -- and their actions end @@ -137,52 +153,45 @@ local function rotate_npc_to_player(self) self.object:setyaw(yaw) 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 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:yes_no" then local player_name = player:get_player_name() 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 - player_response.response = true player_response.yes_callback() elseif fields.no_option then - player_response.response = false player_response.no_callback() end - minetest.log(player_name.." chose response: " - ..dump(get_yes_no_dialogue_response_by_player_name(player_name).response)) + end + 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 diff --git a/npc.lua b/npc.lua index 3d4be99..ff89a07 100755 --- a/npc.lua +++ b/npc.lua @@ -233,7 +233,8 @@ local function select_random_favorite_items(sex, phase) end -- 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 result = {} 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 relationship_decrease_interval = npc.RELATIONSHIP_DECREASE_TIMER_INTERVAL, -- 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 @@ -327,6 +330,17 @@ local function check_npc_can_receive_gift(self, clicker_name) return nil 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 local function reset_gift_timer(self, clicker_name) for i = 1, #self.relationships do @@ -338,6 +352,16 @@ local function reset_gift_timer(self, clicker_name) 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 local function reset_relationship_decrease_timer(self, clicker_name) for i = 1, #self.relationships do @@ -529,7 +553,22 @@ end -- Relationships are slowly increased by talking, increases by +0.2. -- 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 if self.is_married_to ~= nil and clicker_name == self.is_married_to then modifier = 1 @@ -537,23 +576,31 @@ local function dialogue_relationship_update(self, clicker_name) -- Update relationship update_relationship(self, clicker_name, modifier) + -- Resert timers + reset_talk_timer(self, clicker_name) reset_relationship_decrease_timer(self, clicker_name) end -- Chat functions -local function start_chat(self, clicker) - local name = npc.get_entity_name(clicker) +local function start_dialogue(self, 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 -- TODO: Improve this. There should be a dialogue box for this - if self.owner and self.owner == name then - if self.order == "follow" then - self.order = "stand" - minetest.chat_send_player(name, S("Ok dear, I will wait here for you.")) - else - self.order = "follow" - minetest.chat_send_player(name, S("Let's go honey!")) - end - end + -- if self.owner and self.owner == name then + -- if self.order == "follow" then + -- self.order = "stand" + -- minetest.chat_send_player(name, S("Ok dear, I will wait here for you.")) + -- else + -- self.order = "follow" + -- minetest.chat_send_player(name, S("Let's go honey!")) + -- end + -- end end @@ -639,12 +686,12 @@ mobs:register_mob("advanced_npc:npc", { end, npc.dialogue.NEGATIVE_ANSWER_LABEL, function() - npc.dialogue.start_dialogue(self, clicker) + start_dialogue(self, clicker) end, name ) else - npc.dialogue.start_dialogue(self, clicker) + start_dialogue(self, clicker) end end, @@ -655,6 +702,10 @@ mobs:register_mob("advanced_npc:npc", { -- Gift timer check if relationship.gift_timer_value < relationship.gift_interval then 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 -- Relationship decrease timer if relationship.relationship_decrease_timer_value