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