Cleanup: moved relationships into own file.
Moved trading and pricing code to another folder, separate files. NPC: Added further inventory functionality. Trading: Added price data structure, which allows for setting prices for items. Also includes some default definitions.
This commit is contained in:
parent
2720be8d48
commit
83c9b2c681
14
dialogue.lua
14
dialogue.lua
@ -116,14 +116,14 @@ function npc.dialogue.select_random_dialogues_for_npc(sex, phase, favorite_items
|
||||
for i = 1, 2 do
|
||||
result.hints[i] = {}
|
||||
result.hints[i].text =
|
||||
npc.get_hint_for_favorite_item(favorite_items["fav"..tostring(i)], sex, phase)
|
||||
npc.relationships.get_hint_for_favorite_item(favorite_items["fav"..tostring(i)], sex, phase)
|
||||
end
|
||||
|
||||
-- Disliked items
|
||||
for i = 3, 4 do
|
||||
result.hints[i] = {}
|
||||
result.hints[i].text =
|
||||
npc.get_hint_for_disliked_item(disliked_items["dis"..tostring(i-2)], sex)
|
||||
npc.relationships.get_hint_for_disliked_item(disliked_items["dis"..tostring(i-2)], sex)
|
||||
end
|
||||
|
||||
return result
|
||||
@ -137,9 +137,9 @@ function npc.dialogue.start_dialogue(self, player, show_married_dialogue)
|
||||
local dialogue = {}
|
||||
|
||||
-- Construct dialogue for marriage
|
||||
if npc.get_relationship_phase(self, player:get_player_name()) == "phase6"
|
||||
if npc.relationships.get_relationship_phase(self, player:get_player_name()) == "phase6"
|
||||
and show_married_dialogue == true then
|
||||
dialogue = npc.MARRIED_NPC_DIALOGUE
|
||||
dialogue = npc.relationships.MARRIED_NPC_DIALOGUE
|
||||
npc.dialogue.process_dialogue(self, dialogue, player:get_player_name())
|
||||
return
|
||||
end
|
||||
@ -251,10 +251,12 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
|
||||
elseif player_response.options[i].action_type == "function" then
|
||||
-- Execute function - get it directly from definition
|
||||
-- Find NPC relationship phase with player
|
||||
local phase = npc.get_relationship_phase(player_response.npc, player_name)
|
||||
local phase =
|
||||
npc.relationships.get_relationship_phase(player_response.npc, player_name)
|
||||
-- Check if NPC is married and the married NPC dialogue should be shown
|
||||
if phase == "phase6" and player_response.is_married_dialogue == true then
|
||||
npc.MARRIED_NPC_DIALOGUE.responses[player_response.options[i].response_id]
|
||||
npc.relationships.MARRIED_NPC_DIALOGUE
|
||||
.responses[player_response.options[i].response_id]
|
||||
.action(player_response.npc, player)
|
||||
else
|
||||
-- Get dialogues for sex and phase
|
||||
|
4
init.lua
4
init.lua
@ -25,8 +25,10 @@ mobs.intllib = S
|
||||
|
||||
-- NPC
|
||||
dofile(path .. "/npc.lua")
|
||||
dofile(path .. "/relationships.lua")
|
||||
dofile(path .. "/dialogue.lua")
|
||||
dofile(path .. "/random_data.lua")
|
||||
dofile(path .. "/trade.lua")
|
||||
dofile(path .. "/trade/trade.lua")
|
||||
dofile(path .. "/trade/prices.lua")
|
||||
|
||||
print (S("[MOD] Advanced NPC loaded"))
|
||||
|
587
npc.lua
587
npc.lua
@ -1,58 +1,13 @@
|
||||
-- Advanced NPC by Zorman2000
|
||||
-- Based on original NPC by Tenplus1
|
||||
|
||||
local S = mobs.intllib
|
||||
|
||||
-- Advanced NPC by Zorman2000
|
||||
-- Based on original NPC by Tenplus1
|
||||
npc = {}
|
||||
|
||||
-- Constants
|
||||
npc.FEMALE = "female"
|
||||
npc.MALE = "male"
|
||||
npc.ITEM_GIFT_EFFECT = 2.5
|
||||
-- Expected values for these are 720 each respectively
|
||||
npc.GIFT_TIMER_INTERVAL = 2
|
||||
npc.RELATIONSHIP_DECREASE_TIMER_INTERVAL = 60
|
||||
npc.RELATIONSHIP_PHASE = {}
|
||||
-- Define phases
|
||||
npc.RELATIONSHIP_PHASE["phase1"] = {limit = 10}
|
||||
npc.RELATIONSHIP_PHASE["phase2"] = {limit = 25}
|
||||
npc.RELATIONSHIP_PHASE["phase3"] = {limit = 45}
|
||||
npc.RELATIONSHIP_PHASE["phase4"] = {limit = 70}
|
||||
npc.RELATIONSHIP_PHASE["phase5"] = {limit = 100}
|
||||
|
||||
-- Married NPC dialogue definition
|
||||
npc.MARRIED_NPC_DIALOGUE = {
|
||||
text = "Hi darling!",
|
||||
is_married_dialogue = true,
|
||||
responses = {
|
||||
[1] = {
|
||||
text = "Let's talk!",
|
||||
action_type = "function",
|
||||
response_id = 1,
|
||||
action = function(self, player)
|
||||
npc.start_dialogue(self, player, false)
|
||||
end
|
||||
},
|
||||
[2] = {
|
||||
text = "Honey, can you wait for me here?",
|
||||
action_type = "function",
|
||||
response_id = 2,
|
||||
action = function(self, player)
|
||||
self.order = "stand"
|
||||
minetest.chat_send_player(player:get_player_name(), S("Ok dear, I will wait here for you."))
|
||||
end
|
||||
},
|
||||
[3] = {
|
||||
text = "Come with me, please!",
|
||||
action_type = "function",
|
||||
response_id = 3,
|
||||
action = function(self, player)
|
||||
self.order = "follow"
|
||||
minetest.chat_send_player(player:get_player_name(), S("Ok, let's go!"))
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
npc.INVENTORY_ITEM_MAX_STACK = 99
|
||||
|
||||
@ -61,8 +16,9 @@ mobs.npc_drops = {
|
||||
"default:shovel_steel", "farming:bread", "bucket:bucket_water"
|
||||
}
|
||||
|
||||
|
||||
---------------------------------------------------------------------------------------
|
||||
-- General functions
|
||||
---------------------------------------------------------------------------------------
|
||||
-- Gets name of player or NPC
|
||||
function npc.get_entity_name(entity)
|
||||
if entity:is_player() then
|
||||
@ -74,13 +30,15 @@ end
|
||||
|
||||
-- Returns the item "wielded" by player or NPC
|
||||
-- TODO: Implement NPC
|
||||
local function get_entity_wielded_item(entity)
|
||||
function npc.get_entity_wielded_item(entity)
|
||||
if entity:is_player() then
|
||||
return entity:get_wielded_item()
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------------------
|
||||
-- Inventory functions
|
||||
---------------------------------------------------------------------------------------
|
||||
-- NPCs inventories are restrained to 16 slots.
|
||||
-- Each slot can hold one item up to 99 count.
|
||||
|
||||
@ -104,6 +62,8 @@ local function initialize_inventory()
|
||||
end
|
||||
|
||||
-- Add an item to inventory. Returns true if add successful
|
||||
-- These function can be used to give items to other NPCs
|
||||
-- given that the "self" variable can be any NPC
|
||||
function npc.add_item_to_inventory(self, item_name, count)
|
||||
-- Check if NPC already has item
|
||||
local existing_item = npc.inventory_contains(self, item_name)
|
||||
@ -165,7 +125,7 @@ function npc.take_item_from_inventory(self, item_name, count)
|
||||
local new_count = existing_count
|
||||
if existing_count - count < 0 then
|
||||
-- Remove item first
|
||||
self.inventory[existin_item.slot] = ""
|
||||
self.inventory[existing_item.slot] = ""
|
||||
-- TODO: Support for retrieving from next stack. Too complicated
|
||||
-- and honestly might be unecessary.
|
||||
return item_name.." "..tostring(new_count)
|
||||
@ -180,485 +140,40 @@ function npc.take_item_from_inventory(self, item_name, count)
|
||||
end
|
||||
end
|
||||
|
||||
-- Function to get relationship phase
|
||||
function npc.get_relationship_phase_by_points(points)
|
||||
if points > npc.RELATIONSHIP_PHASE["phase5"].limit then
|
||||
return "phase6"
|
||||
elseif points > npc.RELATIONSHIP_PHASE["phase4"].limit then
|
||||
return "phase5"
|
||||
elseif points > npc.RELATIONSHIP_PHASE["phase3"].limit then
|
||||
return "phase4"
|
||||
elseif points > npc.RELATIONSHIP_PHASE["phase2"].limit then
|
||||
return "phase3"
|
||||
elseif points > npc.RELATIONSHIP_PHASE["phase1"].limit then
|
||||
return "phase2"
|
||||
else
|
||||
return "phase1"
|
||||
end
|
||||
-- Inventory functions for players
|
||||
function npc.give_item_to_player(player, item_name, count)
|
||||
local player_name = npc.get_entity_name(player)
|
||||
local player_inv = minetest.get_inventory({type="player", name=player_name})
|
||||
local item = ItemStack(item_name.." "..count)
|
||||
player_inv:add_item("main", item)
|
||||
end
|
||||
|
||||
-- Returns the response message for a given item
|
||||
function npc.get_response_for_favorite_item(item_name, sex, phase)
|
||||
local items = npc.FAVORITE_ITEMS.female
|
||||
if sex == npc.MALE then
|
||||
items = npc.FAVORITE_ITEMS.male
|
||||
end
|
||||
|
||||
for i = 1, #items[phase] do
|
||||
if items[phase][i].item == item_name then
|
||||
return items[phase][i].response
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Returns the response message for a disliked item
|
||||
function npc.get_response_for_disliked_item(item_name, sex)
|
||||
local items = npc.DISLIKED_ITEMS.female
|
||||
if sex == npc.MALE then
|
||||
items = npc.DISLIKED_ITEMS.male
|
||||
end
|
||||
|
||||
for i = 1, #items do
|
||||
if items[i].item == item_name then
|
||||
return items[i].response
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Gets the item hint for a favorite item
|
||||
function npc.get_hint_for_favorite_item(item_name, sex, phase)
|
||||
for i = 1, #npc.FAVORITE_ITEMS[sex][phase] do
|
||||
if npc.FAVORITE_ITEMS[sex][phase][i].item == item_name then
|
||||
return npc.FAVORITE_ITEMS[sex][phase][i].hint
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Gets the item hint for a disliked item
|
||||
function npc.get_hint_for_disliked_item(item_name, sex)
|
||||
for i = 1, #npc.DISLIKED_ITEMS[sex] do
|
||||
if npc.DISLIKED_ITEMS[sex][i].item == item_name then
|
||||
return npc.DISLIKED_ITEMS[sex][i].hint
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
-- Functions on right click
|
||||
---------------------------------------------------------------------------------------
|
||||
-- Gift and relationship system
|
||||
---------------------------------------------------------------------------------------
|
||||
-- Each NPCs has 2 favorite and 2 disliked items. These items are chosen at spawn
|
||||
-- time and will be re-chosen when the age changes (from child to adult, for example).
|
||||
-- The items are chosen from the npc.FAVORITE_ITEMS table, and depends on sex and age.
|
||||
-- A player, via right-click, or another NPC, can gift an item to a NPC. In the case
|
||||
-- of the player, the player will give one of the currently wielded item. Gifts can be
|
||||
-- given only once per some time period, the NPC will reject the given item if still
|
||||
-- the period isn't over.
|
||||
-- If the NPC is neutral on the item (meanining it's neither favorite or disliked), it
|
||||
-- is possible it will not accept it, and the relationship the giver has with the NPC
|
||||
-- will be unchanged.
|
||||
-- In the other hand, if the item given its a favorite, the relationship points the NPC
|
||||
-- has with giver will increase by a given amount, depending on favoriteness. Favorite 1
|
||||
-- will increase the relationship by 2 * npc.ITEM_GIFT_EFFECT, and favorite 2 only by
|
||||
-- npc.ITEM_GIFT_EFFECT. Similarly, if the item given is a disliked item, the NPC will
|
||||
-- not take it, and its relationship points with the giver will decrease by 2 or 1 times
|
||||
-- npc.ITEM_GIFT_EFFECT.
|
||||
|
||||
-- Relationship functions
|
||||
---------------------------------------------------------------------------------------
|
||||
|
||||
-- This function selects two random items from the npc.favorite_items table
|
||||
-- It checks for sex and phase for choosing the items
|
||||
local function 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
|
||||
|
||||
-- Select the phase
|
||||
items = items[phase]
|
||||
|
||||
result.fav1 = items[math.random(1, #items)].item
|
||||
result.fav2 = items[math.random(1, #items)].item
|
||||
return result
|
||||
end
|
||||
|
||||
-- This function selects two random items from the npc.disliked_items table
|
||||
-- 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 = {}
|
||||
|
||||
-- Filter sex
|
||||
if sex == npc.FEMALE then
|
||||
items = npc.DISLIKED_ITEMS.female
|
||||
else
|
||||
items = npc.DISLIKED_ITEMS.male
|
||||
end
|
||||
|
||||
result.dis1 = items[math.random(1, #items)].item
|
||||
result.dis2 = items[math.random(1, #items)].item
|
||||
return result
|
||||
end
|
||||
|
||||
-- Creates a relationship with a given player or NPC
|
||||
local function create_relationship(self, clicker_name)
|
||||
local count = #self.relationships
|
||||
self.relationships[count + 1] = {
|
||||
-- Player or NPC name with whom the relationship is with
|
||||
name = clicker_name,
|
||||
-- Relationship points
|
||||
points = 0,
|
||||
-- Relationship phase, used for items and for phrases
|
||||
phase = "phase1",
|
||||
-- How frequent can the NPC receive a gift
|
||||
gift_interval = npc.GIFT_TIMER_INTERVAL,
|
||||
-- Current timer count since last gift
|
||||
gift_timer_value = 0,
|
||||
-- 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,
|
||||
-- Current timer count since last time player talked to NPC
|
||||
talk_timer_value = 0
|
||||
}
|
||||
end
|
||||
|
||||
-- Returns a relationship points
|
||||
local function get_relationship_points(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
return self.relationships[i].points
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Updates relationship with given points
|
||||
local function update_relationship(self, clicker_name, modifier)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
self.relationships[i].points = self.relationships[i].points + modifier
|
||||
local current_phase = self.relationships[i].phase
|
||||
self.relationships[i].phase = npc.get_relationship_phase_by_points(self.relationships[i].points)
|
||||
if current_phase ~= self.relationships[i].phase then
|
||||
-- Re-select favorite items per new phase
|
||||
self.gift_data.favorite_items =
|
||||
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)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- Relationship not found, huge error
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Checks if a relationship with given player or NPC exists
|
||||
local function check_relationship_exists(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Returns the relationship phase given the name of the player
|
||||
function npc.get_relationship_phase(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if clicker_name == self.relationships[i].name then
|
||||
return self.relationships[i].phase
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Checks if NPC can receive gifts
|
||||
local function check_npc_can_receive_gift(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
-- Checks avoid married NPC to receive from others
|
||||
if self.is_married_to == nil
|
||||
or (self.is_married ~= nil and self.is_married_to == clicker_name) then
|
||||
return self.relationships[i].gift_timer_value >= self.relationships[i].gift_interval
|
||||
else
|
||||
return false
|
||||
end
|
||||
function npc.check_item_to_player(player, item_name)
|
||||
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
|
||||
return main_list[i]
|
||||
end
|
||||
end
|
||||
-- Not found
|
||||
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
|
||||
function npc.take_item_from_player(player, item_name, count)
|
||||
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
|
||||
|
||||
-- Resets the gift timer
|
||||
local function reset_gift_timer(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
self.relationships[i].gift_timer_value = 0
|
||||
self.relationships[i].relationship_decrease_timer_value = 0
|
||||
return
|
||||
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
|
||||
local function reset_relationship_decrease_timer(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
self.relationships[i].relationship_decrease_timer_value = 0
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Gifts functions
|
||||
---------------------------------------------------------------------------------------
|
||||
|
||||
-- Displays message and hearts depending on relationship level
|
||||
local function show_receive_gift_reaction(self, item_name, modifier, clicker_name, phase_change)
|
||||
local points = get_relationship_points(self, clicker_name)
|
||||
|
||||
local pos = self.object:getpos()
|
||||
-- Positive modifier (favorite items) reactions
|
||||
if modifier >= 0 then
|
||||
local phase = npc.get_relationship_phase_by_points(points)
|
||||
if phase == "phase3" then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 2, "heart.png")
|
||||
elseif phase == "phase4" then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 4, "heart.png")
|
||||
elseif phase == "phase5" then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 6, "heart.png")
|
||||
elseif phase == "phase6" then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png")
|
||||
end
|
||||
if phase_change then
|
||||
local number_code = phase:byte(phase:len()) - 1
|
||||
phase = "phase"..string.char(number_code)
|
||||
end
|
||||
-- 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.get_response_for_favorite_item(item_name, self.sex, phase)
|
||||
minetest.chat_send_player(clicker_name, message_to_send)
|
||||
-- Disliked items reactions
|
||||
elseif modifier < 0 then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "smoke.png")
|
||||
local message_to_send = npc.get_response_for_disliked_item(item_name, self.sex)
|
||||
minetest.chat_send_player(clicker_name, message_to_send)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Receive gift function; applies relationship points as explained above
|
||||
-- Also, creates a relationship object if not present
|
||||
local function receive_gift(self, clicker)
|
||||
-- Return if clicker is not offering an item
|
||||
local item = get_entity_wielded_item(clicker)
|
||||
if item:get_name() == "" then return false end
|
||||
|
||||
-- Get clicker name
|
||||
local clicker_name = npc.get_entity_name(clicker)
|
||||
|
||||
-- Create relationship if it doesn't exists
|
||||
if check_relationship_exists(self, clicker_name) == false then
|
||||
create_relationship(self, clicker_name)
|
||||
end
|
||||
|
||||
-- If NPC received a gift from this person, then reject any more gifts for now
|
||||
if check_npc_can_receive_gift(self, clicker_name) == false then
|
||||
minetest.chat_send_player(clicker_name, "Thanks, but I don't need anything for now")
|
||||
return false
|
||||
end
|
||||
|
||||
-- If NPC is ready for marriage, do no accept anything else but the ring,
|
||||
-- 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.RELATIONSHIP_PHASE["phase5"].limit
|
||||
and self.owner ~= clicker_name
|
||||
and item:get_name() ~= "advanced_npc:marriage_ring" then
|
||||
minetest.chat_send_player(clicker_name,
|
||||
"Thank you my love, but I think that you have given me")
|
||||
minetest.chat_send_player(clicker_name,
|
||||
"enough gifts for now. Maybe we should go a step further")
|
||||
-- Reset gift timer
|
||||
reset_gift_timer(self, clicker_name)
|
||||
return true
|
||||
elseif get_relationship_points(self, clicker_name) >= npc.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
|
||||
local receive_chance = math.random(1, 10)
|
||||
-- Receive ring and get married
|
||||
if receive_chance < 6 then
|
||||
minetest.chat_send_player(clicker_name,
|
||||
"Oh, oh you make me so happy! Yes! I will marry you!")
|
||||
-- Get ring
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
-- TODO: Implement marriage event
|
||||
-- Show marriage reaction
|
||||
local pos = self.object:getpos()
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 20, "heart.png", 4)
|
||||
-- Give 100 points, so NPC is really happy on marriage
|
||||
update_relationship(self, clicker_name, 100)
|
||||
-- This sets the married state, for now. Hehe
|
||||
self.owner = clicker_name
|
||||
-- Reject ring for now
|
||||
else
|
||||
minetest.chat_send_player(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
|
||||
if get_relationship_points(self, clicker_name) >= npc.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
|
||||
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
|
||||
-- Favorite item reaction
|
||||
show_receive_gift_reaction(self, item:get_name(), modifier, clicker_name, false)
|
||||
else
|
||||
-- Neutral item reaction
|
||||
minetest.chat_send_player(clicker_name, "Thank you honey!")
|
||||
end
|
||||
-- Take item
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
-- Update relationship
|
||||
update_relationship(self, clicker_name, modifier)
|
||||
-- Reset gift timer
|
||||
reset_gift_timer(self, clicker_name)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Modifies relationship depending on given item
|
||||
local modifier = 0
|
||||
local take = true
|
||||
local show_reaction = false
|
||||
|
||||
if item:get_name() == self.gift_data.favorite_items.fav1 then
|
||||
modifier = 2 * npc.ITEM_GIFT_EFFECT
|
||||
show_reaction = true
|
||||
elseif item:get_name() == self.gift_data.favorite_items.fav2 then
|
||||
modifier = npc.ITEM_GIFT_EFFECT
|
||||
show_reaction = true
|
||||
elseif item:get_name() == self.gift_data.disliked_items.dis1 then
|
||||
modifier = (-2) * npc.ITEM_GIFT_EFFECT
|
||||
show_reaction = true
|
||||
elseif item:get_name() == self.gift_data.disliked_items.dis2 then
|
||||
modifier = (-1) * npc.ITEM_GIFT_EFFECT
|
||||
show_reaction = true
|
||||
else
|
||||
-- If item is not a favorite or a dislike, then receive chance
|
||||
-- if 70%
|
||||
local receive_chance = math.random(1,10)
|
||||
if receive_chance < 7 then
|
||||
minetest.chat_send_player(clicker_name, "Thanks. I will find some use for this.")
|
||||
else
|
||||
minetest.chat_send_player(clicker_name, "Thank you, but no, I have no use for this.")
|
||||
take = false
|
||||
end
|
||||
show_reaction = false
|
||||
end
|
||||
|
||||
-- Take item if NPC accepted it
|
||||
if take == true then
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
|
||||
-- Update relationship status
|
||||
local is_phase_changed = update_relationship(self, clicker_name, modifier)
|
||||
|
||||
-- Show NPC reaction to gift
|
||||
if show_reaction == true then
|
||||
show_receive_gift_reaction(self, item:get_name(), modifier, clicker_name, is_phase_changed)
|
||||
end
|
||||
|
||||
minetest.log(dump(self))
|
||||
-- Reset gift timer
|
||||
reset_gift_timer(self, clicker_name)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Relationships are slowly increased by talking, increases by +0.2.
|
||||
-- Talking to married NPC increases relationship by +1
|
||||
-- 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
|
||||
end
|
||||
-- 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
|
||||
function npc.start_dialogue(self, clicker, show_married_dialogue)
|
||||
|
||||
@ -666,11 +181,13 @@ function npc.start_dialogue(self, clicker, show_married_dialogue)
|
||||
npc.dialogue.start_dialogue(self, clicker, show_married_dialogue)
|
||||
|
||||
-- Check and update relationship if needed
|
||||
dialogue_relationship_update(self, clicker)
|
||||
npc.relationships.dialogue_relationship_update(self, clicker)
|
||||
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------------------------------------
|
||||
-- Definitions
|
||||
---------------------------------------------------------------------------------------
|
||||
mobs:register_mob("advanced_npc:npc", {
|
||||
type = "npc",
|
||||
passive = false,
|
||||
@ -749,7 +266,7 @@ mobs:register_mob("advanced_npc:npc", {
|
||||
"Do you want to give "..item_name.." to "..self.nametag.."?",
|
||||
npc.dialogue.POSITIVE_GIFT_ANSWER_PREFIX..item_name,
|
||||
function()
|
||||
receive_gift(self, clicker)
|
||||
npc.relationships.receive_gift(self, clicker)
|
||||
end,
|
||||
npc.dialogue.NEGATIVE_ANSWER_LABEL,
|
||||
function()
|
||||
@ -783,7 +300,8 @@ mobs:register_mob("advanced_npc:npc", {
|
||||
-- Check if married to decrease half
|
||||
if relationship.phase == "phase6" then
|
||||
-- Avoid going below the marriage phase limit
|
||||
if (relationship.points - 0.5) >= npc.RELATIONSHIP_PHASE["phase5"].limit then
|
||||
if (relationship.points - 0.5) >=
|
||||
npc.relationships.RELATIONSHIP_PHASE["phase5"].limit then
|
||||
relationship.points = relationship.points - 0.5
|
||||
end
|
||||
else
|
||||
@ -797,6 +315,14 @@ mobs:register_mob("advanced_npc:npc", {
|
||||
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
|
||||
@ -813,6 +339,20 @@ local function can_have_relationships()
|
||||
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]
|
||||
for i = 1, number_of_items_to_add do
|
||||
npc.add_item_to_inventory(
|
||||
self,
|
||||
npc.FAVORITE_ITEMS[self.sex][math.random(1, number_of_items)],
|
||||
math.random(1,4)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local function npc_spawn(self, pos)
|
||||
minetest.log("Spawning new NPC:")
|
||||
local ent = self:get_luaentity()
|
||||
@ -828,9 +368,9 @@ local function npc_spawn(self, pos)
|
||||
-- Initialize all gift data
|
||||
ent.gift_data = {
|
||||
-- Choose favorite items. Choose phase1 per default
|
||||
favorite_items = select_random_favorite_items(ent.sex, "phase1"),
|
||||
favorite_items = npc.relationships.select_random_favorite_items(ent.sex, "phase1"),
|
||||
-- Choose disliked items. Choose phase1 per default
|
||||
disliked_items = select_random_disliked_items(ent.sex),
|
||||
disliked_items = npc.relationships.select_random_disliked_items(ent.sex),
|
||||
}
|
||||
|
||||
-- Flag that determines if NPC can have a relationship
|
||||
@ -851,9 +391,12 @@ local function npc_spawn(self, pos)
|
||||
-- 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()
|
||||
trader_status = npc.trade.get_random_trade_status(),
|
||||
-- Items to buy
|
||||
items_to_buy = {},
|
||||
-- Items to sell
|
||||
|
538
relationships.lua
Normal file
538
relationships.lua
Normal file
@ -0,0 +1,538 @@
|
||||
---------------------------------------------------------------------------------------
|
||||
-- Gift and relationship system
|
||||
---------------------------------------------------------------------------------------
|
||||
-- Each NPCs has 2 favorite and 2 disliked items. These items are chosen at spawn
|
||||
-- time and will be re-chosen when the age changes (from child to adult, for example).
|
||||
-- The items are chosen from the npc.FAVORITE_ITEMS table, and depends on sex and age.
|
||||
-- A player, via right-click, or another NPC, can gift an item to a NPC. In the case
|
||||
-- of the player, the player will give one of the currently wielded item. Gifts can be
|
||||
-- given only once per some time period, the NPC will reject the given item if still
|
||||
-- the period isn't over.
|
||||
-- If the NPC is neutral on the item (meanining it's neither favorite or disliked), it
|
||||
-- is possible it will not accept it, and the relationship the giver has with the NPC
|
||||
-- will be unchanged.
|
||||
-- In the other hand, if the item given its a favorite, the relationship points the NPC
|
||||
-- has with giver will increase by a given amount, depending on favoriteness. Favorite 1
|
||||
-- will increase the relationship by 2 * npc.ITEM_GIFT_EFFECT, and favorite 2 only by
|
||||
-- npc.ITEM_GIFT_EFFECT. Similarly, if the item given is a disliked item, the NPC will
|
||||
-- not take it, and its relationship points with the giver will decrease by 2 or 1 times
|
||||
-- npc.ITEM_GIFT_EFFECT.
|
||||
|
||||
local S = mobs.intllib
|
||||
|
||||
npc.relationships = {}
|
||||
|
||||
-- Constants
|
||||
npc.relationships.ITEM_GIFT_EFFECT = 2.5
|
||||
|
||||
-- Expected values for these are 720 each respectively
|
||||
npc.relationships.GIFT_TIMER_INTERVAL = 2
|
||||
npc.relationships.RELATIONSHIP_DECREASE_TIMER_INTERVAL = 60
|
||||
|
||||
npc.relationships.RELATIONSHIP_PHASE = {}
|
||||
-- Define phases
|
||||
npc.relationships.RELATIONSHIP_PHASE["phase1"] = {limit = 10}
|
||||
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}
|
||||
|
||||
-- Married NPC dialogue definition
|
||||
npc.relationships.MARRIED_NPC_DIALOGUE = {
|
||||
text = "Hi darling!",
|
||||
is_married_dialogue = true,
|
||||
responses = {
|
||||
[1] = {
|
||||
text = "Let's talk!",
|
||||
action_type = "function",
|
||||
response_id = 1,
|
||||
action = function(self, player)
|
||||
npc.start_dialogue(self, player, false)
|
||||
end
|
||||
},
|
||||
[2] = {
|
||||
text = "Honey, can you wait for me here?",
|
||||
action_type = "function",
|
||||
response_id = 2,
|
||||
action = function(self, player)
|
||||
self.order = "stand"
|
||||
minetest.chat_send_player(player:get_player_name(), S("Ok dear, I will wait here for you."))
|
||||
end
|
||||
},
|
||||
[3] = {
|
||||
text = "Come with me, please!",
|
||||
action_type = "function",
|
||||
response_id = 3,
|
||||
action = function(self, player)
|
||||
self.order = "follow"
|
||||
minetest.chat_send_player(player:get_player_name(), S("Ok, let's go!"))
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- Function to get relationship phase
|
||||
function npc.relationships.get_relationship_phase_by_points(points)
|
||||
if points > npc.relationships.RELATIONSHIP_PHASE["phase5"].limit then
|
||||
return "phase6"
|
||||
elseif points > npc.relationships.RELATIONSHIP_PHASE["phase4"].limit then
|
||||
return "phase5"
|
||||
elseif points > npc.relationships.RELATIONSHIP_PHASE["phase3"].limit then
|
||||
return "phase4"
|
||||
elseif points > npc.relationships.RELATIONSHIP_PHASE["phase2"].limit then
|
||||
return "phase3"
|
||||
elseif points > npc.relationships.RELATIONSHIP_PHASE["phase1"].limit then
|
||||
return "phase2"
|
||||
else
|
||||
return "phase1"
|
||||
end
|
||||
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
|
||||
if sex == npc.MALE then
|
||||
items = npc.FAVORITE_ITEMS.male
|
||||
end
|
||||
|
||||
for i = 1, #items[phase] do
|
||||
if items[phase][i].item == item_name then
|
||||
return items[phase][i].response
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Returns the response message for a disliked item
|
||||
function npc.relationships.get_response_for_disliked_item(item_name, sex)
|
||||
local items = npc.DISLIKED_ITEMS.female
|
||||
if sex == npc.MALE then
|
||||
items = npc.DISLIKED_ITEMS.male
|
||||
end
|
||||
|
||||
for i = 1, #items do
|
||||
minetest.log(dump(items[i]))
|
||||
if items[i].item == item_name then
|
||||
minetest.log("Returning: "..dump(items[i].response))
|
||||
return items[i].response
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Gets the item hint for a favorite item
|
||||
function npc.relationships.get_hint_for_favorite_item(item_name, sex, phase)
|
||||
for i = 1, #npc.FAVORITE_ITEMS[sex][phase] do
|
||||
if npc.FAVORITE_ITEMS[sex][phase][i].item == item_name then
|
||||
return npc.FAVORITE_ITEMS[sex][phase][i].hint
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Gets the item hint for a disliked item
|
||||
function npc.relationships.get_hint_for_disliked_item(item_name, sex)
|
||||
for i = 1, #npc.DISLIKED_ITEMS[sex] do
|
||||
if npc.DISLIKED_ITEMS[sex][i].item == item_name then
|
||||
return npc.DISLIKED_ITEMS[sex][i].hint
|
||||
end
|
||||
end
|
||||
return nil
|
||||
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
|
||||
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
|
||||
|
||||
-- Select the phase
|
||||
items = items[phase]
|
||||
|
||||
result.fav1 = items[math.random(1, #items)].item
|
||||
result.fav2 = items[math.random(1, #items)].item
|
||||
return result
|
||||
end
|
||||
|
||||
-- This function selects two random items from the npc.disliked_items table
|
||||
-- It checks for sex for choosing the items. They stay the same for all
|
||||
-- phases
|
||||
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
|
||||
|
||||
result.dis1 = items[math.random(1, #items)].item
|
||||
result.dis2 = items[math.random(1, #items)].item
|
||||
return result
|
||||
end
|
||||
|
||||
-- Creates a relationship with a given player or NPC
|
||||
local function create_relationship(self, clicker_name)
|
||||
local count = #self.relationships
|
||||
self.relationships[count + 1] = {
|
||||
-- Player or NPC name with whom the relationship is with
|
||||
name = clicker_name,
|
||||
-- Relationship points
|
||||
points = 0,
|
||||
-- Relationship phase, used for items and for phrases
|
||||
phase = "phase1",
|
||||
-- How frequent can the NPC receive a gift
|
||||
gift_interval = npc.relationships.GIFT_TIMER_INTERVAL,
|
||||
-- Current timer count since last gift
|
||||
gift_timer_value = 0,
|
||||
-- The amount of time without providing gift or talking that will decrease relationship points
|
||||
relationship_decrease_interval = npc.relationships.RELATIONSHIP_DECREASE_TIMER_INTERVAL,
|
||||
-- Current timer count for relationship decrease
|
||||
relationship_decrease_timer_value = 0,
|
||||
-- Current timer count since last time player talked to NPC
|
||||
talk_timer_value = 0
|
||||
}
|
||||
end
|
||||
|
||||
-- Returns a relationship points
|
||||
local function get_relationship_points(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
return self.relationships[i].points
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Updates relationship with given points
|
||||
local function update_relationship(self, clicker_name, modifier)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
self.relationships[i].points = self.relationships[i].points + modifier
|
||||
local current_phase = self.relationships[i].phase
|
||||
self.relationships[i].phase =
|
||||
npc.relationships.get_relationship_phase_by_points(self.relationships[i].points)
|
||||
if current_phase ~= self.relationships[i].phase then
|
||||
-- Re-select favorite items per new phase
|
||||
self.gift_data.favorite_items =
|
||||
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)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- Relationship not found, huge error
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Checks if a relationship with given player or NPC exists
|
||||
local function check_relationship_exists(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Returns the relationship phase given the name of the player
|
||||
function npc.relationships.get_relationship_phase(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if clicker_name == self.relationships[i].name then
|
||||
return self.relationships[i].phase
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Checks if NPC can receive gifts
|
||||
local function check_npc_can_receive_gift(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
-- Checks avoid married NPC to receive from others
|
||||
if self.is_married_to == nil
|
||||
or (self.is_married ~= nil and self.is_married_to == clicker_name) then
|
||||
return self.relationships[i].gift_timer_value >= self.relationships[i].gift_interval
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Not found
|
||||
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
|
||||
if self.relationships[i].name == clicker_name then
|
||||
self.relationships[i].gift_timer_value = 0
|
||||
self.relationships[i].relationship_decrease_timer_value = 0
|
||||
return
|
||||
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
|
||||
local function reset_relationship_decrease_timer(self, clicker_name)
|
||||
for i = 1, #self.relationships do
|
||||
if self.relationships[i].name == clicker_name then
|
||||
self.relationships[i].relationship_decrease_timer_value = 0
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Gifts functions
|
||||
---------------------------------------------------------------------------------------
|
||||
|
||||
-- Displays message and hearts depending on relationship level
|
||||
local function show_receive_gift_reaction(self, item_name, modifier, clicker_name, phase_change)
|
||||
local points = get_relationship_points(self, clicker_name)
|
||||
|
||||
local pos = self.object:getpos()
|
||||
-- Positive modifier (favorite items) reactions
|
||||
if modifier >= 0 then
|
||||
local phase = npc.relationships.get_relationship_phase_by_points(points)
|
||||
if phase == "phase3" then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 2, "heart.png")
|
||||
elseif phase == "phase4" then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 4, "heart.png")
|
||||
elseif phase == "phase5" then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 6, "heart.png")
|
||||
elseif phase == "phase6" then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png")
|
||||
end
|
||||
if phase_change then
|
||||
local number_code = phase:byte(phase:len()) - 1
|
||||
phase = "phase"..string.char(number_code)
|
||||
end
|
||||
-- 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)
|
||||
minetest.chat_send_player(clicker_name, message_to_send)
|
||||
-- Disliked items reactions
|
||||
elseif modifier < 0 then
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "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)
|
||||
minetest.chat_send_player(clicker_name, message_to_send)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Receive gift function; applies relationship points as explained above
|
||||
-- Also, creates a relationship object if not present
|
||||
function npc.relationships.receive_gift(self, clicker)
|
||||
-- Return if clicker is not offering an item
|
||||
local item = npc.get_entity_wielded_item(clicker)
|
||||
if item:get_name() == "" then return false end
|
||||
|
||||
-- Get clicker name
|
||||
local clicker_name = npc.get_entity_name(clicker)
|
||||
|
||||
-- Create relationship if it doesn't exists
|
||||
if check_relationship_exists(self, clicker_name) == false then
|
||||
create_relationship(self, clicker_name)
|
||||
end
|
||||
|
||||
-- If NPC received a gift from this person, then reject any more gifts for now
|
||||
if check_npc_can_receive_gift(self, clicker_name) == false then
|
||||
minetest.chat_send_player(clicker_name, "Thanks, but I don't need anything for now")
|
||||
return false
|
||||
end
|
||||
|
||||
-- If NPC is ready for marriage, do no accept anything else but the ring,
|
||||
-- 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
|
||||
and self.owner ~= clicker_name
|
||||
and item:get_name() ~= "advanced_npc:marriage_ring" then
|
||||
minetest.chat_send_player(clicker_name,
|
||||
"Thank you my love, but I think that you have given me")
|
||||
minetest.chat_send_player(clicker_name,
|
||||
"enough gifts for now. Maybe we should go a step further")
|
||||
-- Reset gift timer
|
||||
reset_gift_timer(self, clicker_name)
|
||||
return true
|
||||
elseif get_relationship_points(self, clicker_name) >=
|
||||
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
|
||||
local receive_chance = math.random(1, 10)
|
||||
-- Receive ring and get married
|
||||
if receive_chance < 6 then
|
||||
minetest.chat_send_player(clicker_name,
|
||||
"Oh, oh you make me so happy! Yes! I will marry you!")
|
||||
-- Get ring
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
-- TODO: Implement marriage event
|
||||
-- Show marriage reaction
|
||||
local pos = self.object:getpos()
|
||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 20, "heart.png", 4)
|
||||
-- Give 100 points, so NPC is really happy on marriage
|
||||
update_relationship(self, clicker_name, 100)
|
||||
-- This sets the married state, for now. Hehe
|
||||
self.owner = clicker_name
|
||||
-- Reject ring for now
|
||||
else
|
||||
minetest.chat_send_player(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
|
||||
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
|
||||
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
|
||||
-- Favorite item reaction
|
||||
show_receive_gift_reaction(self, item:get_name(), modifier, clicker_name, false)
|
||||
else
|
||||
-- Neutral item reaction
|
||||
minetest.chat_send_player(clicker_name, "Thank you honey!")
|
||||
end
|
||||
-- Take item
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
-- Update relationship
|
||||
update_relationship(self, clicker_name, modifier)
|
||||
-- Reset gift timer
|
||||
reset_gift_timer(self, clicker_name)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Modifies relationship depending on given item
|
||||
local modifier = 0
|
||||
local take = true
|
||||
local show_reaction = false
|
||||
|
||||
if item:get_name() == self.gift_data.favorite_items.fav1 then
|
||||
modifier = 2 * npc.relationships.ITEM_GIFT_EFFECT
|
||||
show_reaction = true
|
||||
elseif item:get_name() == self.gift_data.favorite_items.fav2 then
|
||||
modifier = npc.relationships.ITEM_GIFT_EFFECT
|
||||
show_reaction = true
|
||||
elseif item:get_name() == self.gift_data.disliked_items.dis1 then
|
||||
modifier = (-2) * npc.relationships.ITEM_GIFT_EFFECT
|
||||
show_reaction = true
|
||||
elseif item:get_name() == self.gift_data.disliked_items.dis2 then
|
||||
modifier = (-1) * npc.relationships.ITEM_GIFT_EFFECT
|
||||
show_reaction = true
|
||||
else
|
||||
-- If item is not a favorite or a dislike, then receive chance
|
||||
-- if 70%
|
||||
local receive_chance = math.random(1,10)
|
||||
if receive_chance < 7 then
|
||||
minetest.chat_send_player(clicker_name, "Thanks. I will find some use for this.")
|
||||
else
|
||||
minetest.chat_send_player(clicker_name, "Thank you, but no, I have no use for this.")
|
||||
take = false
|
||||
end
|
||||
show_reaction = false
|
||||
end
|
||||
|
||||
-- Update relationship status
|
||||
local is_phase_changed = update_relationship(self, clicker_name, modifier)
|
||||
|
||||
-- Show NPC reaction to gift
|
||||
if show_reaction == true then
|
||||
show_receive_gift_reaction(self, item:get_name(), modifier, clicker_name, is_phase_changed)
|
||||
end
|
||||
|
||||
-- Take item if NPC accepted it
|
||||
if take == true then
|
||||
item:take_item()
|
||||
clicker:set_wielded_item(item)
|
||||
end
|
||||
|
||||
minetest.log(dump(self))
|
||||
-- Reset gift timer
|
||||
reset_gift_timer(self, clicker_name)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Relationships are slowly increased by talking, increases by +0.2.
|
||||
-- Talking to married NPC increases relationship by +1
|
||||
-- TODO: This needs a timer as the gift timer. NPC will talk anyways
|
||||
-- but relationship will not increase.
|
||||
function npc.relationships.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
|
||||
end
|
||||
-- Update relationship
|
||||
update_relationship(self, clicker_name, modifier)
|
||||
|
||||
-- Resert timers
|
||||
reset_talk_timer(self, clicker_name)
|
||||
reset_relationship_decrease_timer(self, clicker_name)
|
||||
end
|
53
trade/prices.lua
Normal file
53
trade/prices.lua
Normal file
@ -0,0 +1,53 @@
|
||||
-- Price table for items bought/sold by NPC traders by Zorman2000
|
||||
-- This table should be globally accessible so that other mods can set
|
||||
-- prices as they see fit.
|
||||
|
||||
npc.trade.prices = {}
|
||||
|
||||
-- Table that contains the prices
|
||||
npc.trade.prices.table = {}
|
||||
|
||||
-- Default definitions for in-game items
|
||||
npc.trade.prices.table["default:apple"] = {item = "default:iron_ingot", count = 1}
|
||||
npc.trade.prices.table["default:stone"] = {item = "default:wood_planks", count = 1}
|
||||
npc.trade.prices.table["default:cobble"] = {item = "default:iron_ingot", count = 1}
|
||||
npc.trade.prices.table["farming:cotton"] = {item = "default:iron_ingot", count = 1}
|
||||
npc.trade.prices.table["farming:bread"] = {item = "default:gold_ingot", count = 1}
|
||||
npc.trade.prices.table["default:sword_stone"] = {item = "default:iron_ingot", count = 2}
|
||||
npc.trade.prices.table["default:pick_stone"] = {item = "default:iron_ingot", count = 1}
|
||||
npc.trade.prices.table["default:shovel_stone"] = {item = "default:iron_ingot", count = 2}
|
||||
npc.trade.prices.table["default:axe_stone"] = {item = "default:iron_ingot", count = 1}
|
||||
npc.trade.prices.table["default:hoe_stone"] = {item = "default:iron_ingot", count = 1}
|
||||
|
||||
|
||||
-- Functions
|
||||
function npc.trade.prices.update(item_name, price)
|
||||
for key,value in pairs(npc.trade.prices.table) do
|
||||
if key == item_name then
|
||||
value = price
|
||||
return
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function npc.trade.prices.get(item_name)
|
||||
for key,value in pairs(npc.trade.prices.table) do
|
||||
if key == item_name then
|
||||
return {item_name = key, price = value}
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function npc.trade.prices.add(item_name, price)
|
||||
if npc.trade.prices.get(item_name) == nil then
|
||||
npc.trade.prices.table[item_name] = price
|
||||
else
|
||||
npc.trade.prices.update(item_name, price)
|
||||
end
|
||||
end
|
||||
|
||||
function npc.trade.prices.remove(item_name)
|
||||
npc.trade.prices.table[item_name] = nil
|
||||
end
|
Loading…
Reference in New Issue
Block a user