Compare commits
11 Commits
1.0.0-alph
...
1.0.0-alph
Author | SHA1 | Date | |
---|---|---|---|
4c0e2b574a | |||
bf935fd091 | |||
6141af11aa | |||
e70888c3e5 | |||
cc56446206 | |||
7110c49b42 | |||
fd4cec0d63 | |||
3df43ab580 | |||
c19ea70242 | |||
a3b428fe14 | |||
4814c16ba0 |
@ -27,7 +27,7 @@ License
|
|||||||
|
|
||||||
__advanced_npc__ is Copyright (C) 2016-2017 Hector Franqui (zorman2000), licensed under the GPLv3 license. See `license.txt` for details.
|
__advanced_npc__ is Copyright (C) 2016-2017 Hector Franqui (zorman2000), licensed under the GPLv3 license. See `license.txt` for details.
|
||||||
|
|
||||||
The `pathfinder.lua` file contains code slighlty modified from the [pathfinder mod](https://github.com/Yonaba/Jumper) by MarkBu, which is licensed as WTFPL. See `actions/pathfinder.lua` for details.
|
The `pathfinder.lua` file contains code slighlty modified from the [pathfinder mod](https://github.com/MarkuBu/pathfinder) by MarkBu, which is licensed as WTFPL. See `actions/pathfinder.lua` for details.
|
||||||
|
|
||||||
Current NPC textures are from mobs_redo mod.
|
Current NPC textures are from mobs_redo mod.
|
||||||
The following textures are by Zorman2000:
|
The following textures are by Zorman2000:
|
||||||
|
@ -604,6 +604,10 @@ function npc.actions.use_bed(self, args)
|
|||||||
|
|
||||||
if action == npc.actions.const.beds.LAY then
|
if action == npc.actions.const.beds.LAY then
|
||||||
-- Get position
|
-- Get position
|
||||||
|
-- Error here due to ignore. Need to come up with better solution
|
||||||
|
if node.name == "ignore" then
|
||||||
|
return
|
||||||
|
end
|
||||||
local bed_pos = npc.actions.nodes.beds[node.name].get_lay_pos(pos, dir)
|
local bed_pos = npc.actions.nodes.beds[node.name].get_lay_pos(pos, dir)
|
||||||
-- Sit down on bed, rotate to correct direction
|
-- Sit down on bed, rotate to correct direction
|
||||||
npc.add_action(self, npc.actions.cmd.SIT, {pos=bed_pos, dir=(node.param2 + 2) % 4})
|
npc.add_action(self, npc.actions.cmd.SIT, {pos=bed_pos, dir=(node.param2 + 2) % 4})
|
||||||
@ -611,6 +615,10 @@ function npc.actions.use_bed(self, args)
|
|||||||
npc.add_action(self, npc.actions.cmd.LAY, {})
|
npc.add_action(self, npc.actions.cmd.LAY, {})
|
||||||
else
|
else
|
||||||
-- Calculate position to get up
|
-- Calculate position to get up
|
||||||
|
-- Error here due to ignore. Need to come up with better solution
|
||||||
|
if node.name == "ignore" then
|
||||||
|
return
|
||||||
|
end
|
||||||
local bed_pos_y = npc.actions.nodes.beds[node.name].get_lay_pos(pos, dir).y
|
local bed_pos_y = npc.actions.nodes.beds[node.name].get_lay_pos(pos, dir).y
|
||||||
local bed_pos = {x = pos.x, y = bed_pos_y, z = pos.z}
|
local bed_pos = {x = pos.x, y = bed_pos_y, z = pos.z}
|
||||||
-- Sit up
|
-- Sit up
|
||||||
@ -662,6 +670,10 @@ function npc.actions.use_sittable(self, args)
|
|||||||
|
|
||||||
if action == npc.actions.const.sittable.SIT then
|
if action == npc.actions.const.sittable.SIT then
|
||||||
-- Calculate position depending on bench
|
-- Calculate position depending on bench
|
||||||
|
-- Error here due to ignore. Need to come up with better solution
|
||||||
|
if node.name == "ignore" then
|
||||||
|
return
|
||||||
|
end
|
||||||
local sit_pos = npc.actions.nodes.sittable[node.name].get_sit_pos(pos, node.param2)
|
local sit_pos = npc.actions.nodes.sittable[node.name].get_sit_pos(pos, node.param2)
|
||||||
-- Sit down on bench/chair/stairs
|
-- Sit down on bench/chair/stairs
|
||||||
npc.add_action(self, npc.actions.cmd.SIT, {pos=sit_pos, dir=(node.param2 + 2) % 4})
|
npc.add_action(self, npc.actions.cmd.SIT, {pos=sit_pos, dir=(node.param2 + 2) % 4})
|
||||||
|
@ -153,7 +153,11 @@ local function walkable(node, exceptions)
|
|||||||
if node.name == "cottages:wood_flat" then
|
if node.name == "cottages:wood_flat" then
|
||||||
is_mg_villages_ceiling = true
|
is_mg_villages_ceiling = true
|
||||||
end
|
end
|
||||||
if node ~= nil and node.name ~= nil and not minetest.registered_nodes[node.name].walkable then
|
if node ~= nil
|
||||||
|
and node.name ~= nil
|
||||||
|
and node.name ~= "ignore"
|
||||||
|
and minetest.registered_nodes[node.name]
|
||||||
|
and not minetest.registered_nodes[node.name].walkable then
|
||||||
return false
|
return false
|
||||||
elseif is_openable then
|
elseif is_openable then
|
||||||
return false
|
return false
|
||||||
|
@ -22,8 +22,10 @@ npc.places.nodes = {
|
|||||||
},
|
},
|
||||||
SITTABLE_TYPE = {
|
SITTABLE_TYPE = {
|
||||||
"cottages:bench",
|
"cottages:bench",
|
||||||
|
-- Currently commented out since some NPCs
|
||||||
|
-- were sitting at stairs that are actually staircases
|
||||||
-- TODO: Register other stair types
|
-- TODO: Register other stair types
|
||||||
"stairs:stair_wood"
|
--"stairs:stair_wood"
|
||||||
},
|
},
|
||||||
STORAGE_TYPE = {
|
STORAGE_TYPE = {
|
||||||
"default:chest",
|
"default:chest",
|
||||||
@ -56,7 +58,16 @@ npc.places.PLACE_TYPE = {
|
|||||||
PRIMARY = "bed_primary"
|
PRIMARY = "bed_primary"
|
||||||
},
|
},
|
||||||
SITTABLE = {
|
SITTABLE = {
|
||||||
PRIMARY = "sit_primary"
|
PRIMARY = "sit_primary",
|
||||||
|
SHARED = "sit_shared"
|
||||||
|
},
|
||||||
|
FURNACE = {
|
||||||
|
PRIMARY = "furnace_primary",
|
||||||
|
SHARED = "furnace_shared"
|
||||||
|
},
|
||||||
|
STORAGE = {
|
||||||
|
PRIMARY = "storage_primary",
|
||||||
|
SHARED = "storage_shared"
|
||||||
},
|
},
|
||||||
OPENABLE = {
|
OPENABLE = {
|
||||||
HOME_ENTRANCE_DOOR = "home_entrance_door"
|
HOME_ENTRANCE_DOOR = "home_entrance_door"
|
||||||
@ -68,27 +79,51 @@ npc.places.PLACE_TYPE = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function npc.places.add_public(self, place_name, place_type, pos, access_node)
|
function npc.places.add_shared(self, place_name, place_type, pos, access_node)
|
||||||
--minetest.log("Place name: "..dump(place_name)..", type: "..dump(place_type))
|
|
||||||
self.places_map[place_name] = {type=place_type, pos=pos, access_node=access_node or pos, status="shared"}
|
self.places_map[place_name] = {type=place_type, pos=pos, access_node=access_node or pos, status="shared"}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Adds a specific node to the NPC places, and modifies the
|
|
||||||
-- node metadata to identify the NPC as the owner. This allows
|
|
||||||
-- other NPCs to avoid to take this as their own.
|
|
||||||
function npc.places.add_owned(self, place_name, place_type, pos, access_node)
|
function npc.places.add_owned(self, place_name, place_type, pos, access_node)
|
||||||
-- Get node metadata
|
|
||||||
--local meta = minetest.get_meta(pos)
|
|
||||||
-- Check if it is owned by an NPC?
|
|
||||||
--if meta:get_string("npc_owner") == "" then
|
|
||||||
-- Set owned by NPC
|
|
||||||
--meta:set_string("npc_owner", self.npc_id)
|
|
||||||
-- Add place to list
|
|
||||||
self.places_map[place_name] = {type=place_type, pos=pos, access_node=access_node or pos, status="owned"}
|
self.places_map[place_name] = {type=place_type, pos=pos, access_node=access_node or pos, status="owned"}
|
||||||
--npc.places.add_public(self, place_name, place_type, pos)
|
end
|
||||||
return true
|
|
||||||
--end
|
function npc.places.add_unowned_accessible_place(self, nodes, place_type)
|
||||||
--return false
|
for i = 1, #nodes do
|
||||||
|
-- Check if node has owner
|
||||||
|
if nodes[i].owner == "" then
|
||||||
|
-- If node has no owner, check if it is accessible
|
||||||
|
local empty_nodes = npc.places.find_node_orthogonally(
|
||||||
|
nodes[i].node_pos, {"air"}, 0)
|
||||||
|
-- Check if node is accessible
|
||||||
|
if #empty_nodes > 0 then
|
||||||
|
-- Set owner to this NPC
|
||||||
|
nodes[i].owner = self.npc_id
|
||||||
|
-- Assign node to NPC
|
||||||
|
npc.places.add_owned(self, place_type, place_type,
|
||||||
|
nodes[i].node_pos, empty_nodes[1].pos)
|
||||||
|
npc.log("DEBUG", "Added node at "..minetest.pos_to_string(nodes[i].node_pos)
|
||||||
|
.." to NPC "..dump(self.npc_name))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function npc.places.add_shared_accessible_place(self, nodes, place_type)
|
||||||
|
for i = 1, #nodes do
|
||||||
|
-- Check of not adding same owned sit
|
||||||
|
if nodes[i].owner ~= self.npc_id then
|
||||||
|
-- Check if it is accessible
|
||||||
|
local empty_nodes = npc.places.find_node_orthogonally(
|
||||||
|
nodes[i].node_pos, {"air"}, 0)
|
||||||
|
-- Check if bed is accessible
|
||||||
|
if #empty_nodes > 0 then
|
||||||
|
-- Assign node to NPC
|
||||||
|
npc.places.add_shared(self, place_type..dump(i),
|
||||||
|
place_type, nodes[i].node_pos, empty_nodes[1].pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function npc.places.get_by_type(self, place_type)
|
function npc.places.get_by_type(self, place_type)
|
||||||
|
94
dialogue.lua
94
dialogue.lua
@ -45,10 +45,10 @@ npc.dialogue.dialogue_results = {
|
|||||||
-- Creates and shows a multi-option dialogue based on the number of responses
|
-- Creates and shows a multi-option dialogue based on the number of responses
|
||||||
-- that the dialogue object contains
|
-- that the dialogue object contains
|
||||||
function npc.dialogue.show_options_dialogue(self,
|
function npc.dialogue.show_options_dialogue(self,
|
||||||
dialogue,
|
dialogue,
|
||||||
dismiss_option_label,
|
dismiss_option_label,
|
||||||
player_name)
|
player_name)
|
||||||
local responses = dialogue.responses
|
local responses = dialogue.responses
|
||||||
local options_length = table.getn(responses) + 1
|
local options_length = table.getn(responses) + 1
|
||||||
local formspec_height = (options_length * 0.7) + 0.4
|
local formspec_height = (options_length * 0.7) + 0.4
|
||||||
local formspec = "size[7,"..tostring(formspec_height).."]"
|
local formspec = "size[7,"..tostring(formspec_height).."]"
|
||||||
@ -81,22 +81,22 @@ end
|
|||||||
-- This function is used for showing a yes/no dialogue formspec
|
-- This function is used for showing a yes/no dialogue formspec
|
||||||
function npc.dialogue.show_yes_no_dialogue(self,
|
function npc.dialogue.show_yes_no_dialogue(self,
|
||||||
prompt,
|
prompt,
|
||||||
positive_answer_label,
|
positive_answer_label,
|
||||||
positive_callback,
|
positive_callback,
|
||||||
negative_answer_label,
|
negative_answer_label,
|
||||||
negative_callback,
|
negative_callback,
|
||||||
player_name)
|
player_name)
|
||||||
|
|
||||||
npc.lock_actions(self)
|
npc.lock_actions(self)
|
||||||
|
|
||||||
local formspec = "size[7,3]"..
|
local formspec = "size[7,3]"..
|
||||||
"label[0.5,0.1;"..prompt.."]"..
|
"label[0.5,0.1;"..prompt.."]"..
|
||||||
"button_exit[0.5,1.15;6,0.5;yes_option;"..positive_answer_label.."]"..
|
"button_exit[0.5,1.15;6,0.5;yes_option;"..positive_answer_label.."]"..
|
||||||
"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[player_name] = {
|
npc.dialogue.dialogue_results.yes_no_dialogue[player_name] = {
|
||||||
npc = self,
|
npc = self,
|
||||||
yes_callback = positive_callback,
|
yes_callback = positive_callback,
|
||||||
no_callback = negative_callback
|
no_callback = negative_callback
|
||||||
}
|
}
|
||||||
@ -418,8 +418,8 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
|
|||||||
if fields then
|
if fields then
|
||||||
local player_response = npc.dialogue.dialogue_results.yes_no_dialogue[player_name]
|
local player_response = npc.dialogue.dialogue_results.yes_no_dialogue[player_name]
|
||||||
|
|
||||||
-- Unlock queue, reset action timer and unfreeze NPC.
|
-- Unlock queue, reset action timer and unfreeze NPC.
|
||||||
npc.unlock_actions(player_response.npc)
|
npc.unlock_actions(player_response.npc)
|
||||||
|
|
||||||
if fields.yes_option then
|
if fields.yes_option then
|
||||||
player_response.yes_callback()
|
player_response.yes_callback()
|
||||||
@ -437,11 +437,11 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
|
|||||||
-- Get player response
|
-- Get player response
|
||||||
local player_response = npc.dialogue.dialogue_results.options_dialogue[player_name]
|
local player_response = npc.dialogue.dialogue_results.options_dialogue[player_name]
|
||||||
|
|
||||||
-- Check if the player hit the negative option
|
-- Check if the player hit the negative option or esc button
|
||||||
if fields["exit"] then
|
if fields["exit"] or fields["quit"] == "true" then
|
||||||
-- Unlock queue, reset action timer and unfreeze NPC.
|
-- Unlock queue, reset action timer and unfreeze NPC.
|
||||||
npc.unlock_actions(player_response.npc)
|
npc.unlock_actions(player_response.npc)
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, #player_response.options do
|
for i = 1, #player_response.options do
|
||||||
local button_label = "opt"..tostring(i)
|
local button_label = "opt"..tostring(i)
|
||||||
@ -476,36 +476,36 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
|
|||||||
.responses[player_response.options[i].response_id]
|
.responses[player_response.options[i].response_id]
|
||||||
.action(player_response.npc, player)
|
.action(player_response.npc, player)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
elseif player_response.is_dedicated_trade_dialogue == true then
|
elseif player_response.is_dedicated_trade_dialogue == true then
|
||||||
-- Get the functions for a dedicated trader prompt
|
-- Get the functions for a dedicated trader prompt
|
||||||
npc.trade.DEDICATED_TRADER_PROMPT
|
npc.trade.DEDICATED_TRADER_PROMPT
|
||||||
.responses[player_response.options[i].response_id]
|
.responses[player_response.options[i].response_id]
|
||||||
.action(player_response.npc, player)
|
.action(player_response.npc, player)
|
||||||
return
|
return
|
||||||
elseif player_response.is_custom_trade_dialogue == true then
|
elseif player_response.is_custom_trade_dialogue == true then
|
||||||
-- Functions for a custom trade should be available from the same dialogue
|
-- Functions for a custom trade should be available from the same dialogue
|
||||||
-- object as it is created in memory
|
-- object as it is created in memory
|
||||||
minetest.log("Player response: "..dump(player_response.options[i]))
|
minetest.log("Player response: "..dump(player_response.options[i]))
|
||||||
player_response.options[i].action(player_response.npc, player)
|
player_response.options[i].action(player_response.npc, player)
|
||||||
else
|
else
|
||||||
-- Get dialogues for sex and phase
|
-- Get dialogues for sex and phase
|
||||||
local dialogues = npc.data.DIALOGUES[player_response.npc.sex][phase]
|
local dialogues = npc.data.DIALOGUES[player_response.npc.sex][phase]
|
||||||
|
|
||||||
minetest.log("Object: "..dump(dialogues[player_response.options[i].dialogue_id]))
|
minetest.log("Object: "..dump(dialogues[player_response.options[i].dialogue_id]))
|
||||||
local response = get_response_object_by_id_recursive(dialogues[player_response.options[i].dialogue_id], 0, player_response.options[i].response_id)
|
local response = get_response_object_by_id_recursive(dialogues[player_response.options[i].dialogue_id], 0, player_response.options[i].response_id)
|
||||||
minetest.log("Found: "..dump(response))
|
minetest.log("Found: "..dump(response))
|
||||||
|
|
||||||
-- Execute function
|
-- Execute function
|
||||||
response.action(player_response.npc, player)
|
response.action(player_response.npc, player)
|
||||||
|
|
||||||
-- Execute function
|
-- Execute function
|
||||||
-- dialogues[player_response.options[i].dialogue_id]
|
-- dialogues[player_response.options[i].dialogue_id]
|
||||||
-- .responses[player_response.options[i].response_id]
|
-- .responses[player_response.options[i].response_id]
|
||||||
-- .action(player_response.npc, player)
|
-- .action(player_response.npc, player)
|
||||||
|
|
||||||
-- Unlock queue, reset action timer and unfreeze NPC.
|
-- Unlock queue, reset action timer and unfreeze NPC.
|
||||||
npc.unlock_actions(player_response.npc)
|
npc.unlock_actions(player_response.npc)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
111
npc.lua
111
npc.lua
@ -44,14 +44,14 @@ npc.action_state = {
|
|||||||
|
|
||||||
npc.log_level = {
|
npc.log_level = {
|
||||||
INFO = true,
|
INFO = true,
|
||||||
WARNING = false,
|
WARNING = true,
|
||||||
ERROR = true,
|
ERROR = true,
|
||||||
DEBUG = false
|
DEBUG = false
|
||||||
}
|
}
|
||||||
|
|
||||||
npc.texture_check = {
|
npc.texture_check = {
|
||||||
timer = 0,
|
timer = 0,
|
||||||
interval = 0
|
interval = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------
|
||||||
@ -149,9 +149,9 @@ local function get_random_texture(sex, age)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Choose whether NPC can have relationships. Only 30% of NPCs cannot have relationships
|
-- Choose whether NPC can have relationships. Only 30% of NPCs cannot have relationships
|
||||||
local function can_have_relationships(age)
|
local function can_have_relationships(is_child)
|
||||||
-- Children can't have relationships
|
-- Children can't have relationships
|
||||||
if not age then
|
if is_child then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local chance = math.random(1,10)
|
local chance = math.random(1,10)
|
||||||
@ -264,8 +264,8 @@ function npc.initialize(entity, pos, is_lua_entity, npc_stats)
|
|||||||
elseif child_s <= age_chance and age_chance <= child_e then
|
elseif child_s <= age_chance and age_chance <= child_e then
|
||||||
selected_age = npc.age.child
|
selected_age = npc.age.child
|
||||||
ent.visual_size = {
|
ent.visual_size = {
|
||||||
x = 0.5,
|
x = 0.75,
|
||||||
y = 0.5
|
y = 0.75
|
||||||
}
|
}
|
||||||
ent.collisionbox = {-0.10,-0.50,-0.10, 0.10,0.40,0.10}
|
ent.collisionbox = {-0.10,-0.50,-0.10, 0.10,0.40,0.10}
|
||||||
ent.is_child = true
|
ent.is_child = true
|
||||||
@ -310,6 +310,11 @@ function npc.initialize(entity, pos, is_lua_entity, npc_stats)
|
|||||||
-- Flag that determines if NPC can have a relationship
|
-- Flag that determines if NPC can have a relationship
|
||||||
ent.can_have_relationship = can_have_relationships(ent.is_child)
|
ent.can_have_relationship = can_have_relationships(ent.is_child)
|
||||||
|
|
||||||
|
ent.infotext = "Interested in relationships: "..dump(ent.can_have_relationship)
|
||||||
|
|
||||||
|
-- Flag to determine if NPC can receive gifts
|
||||||
|
ent.can_receive_gifts = ent.can_have_relationship
|
||||||
|
|
||||||
-- Initialize relationships object
|
-- Initialize relationships object
|
||||||
ent.relationships = {}
|
ent.relationships = {}
|
||||||
|
|
||||||
@ -455,6 +460,24 @@ function npc.initialize(entity, pos, is_lua_entity, npc_stats)
|
|||||||
ent.object:set_properties(ent)
|
ent.object:set_properties(ent)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------
|
||||||
|
-- Trading functions
|
||||||
|
---------------------------------------------------------------------------------------
|
||||||
|
function npc.generate_trade_list_from_inventory(self)
|
||||||
|
local list = {}
|
||||||
|
for i = 1, #self.inventory do
|
||||||
|
list[npc.get_item_name(self.inventory[i])] = {}
|
||||||
|
end
|
||||||
|
self.trader_data.trade_list.both = list
|
||||||
|
end
|
||||||
|
|
||||||
|
function npc.set_trading_status(self, status)
|
||||||
|
-- Set status
|
||||||
|
self.trader_data.trader_status = status
|
||||||
|
-- Re-generate trade offers
|
||||||
|
npc.trade.generate_trade_offers_by_status(self)
|
||||||
|
end
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------
|
||||||
-- Inventory functions
|
-- Inventory functions
|
||||||
---------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------
|
||||||
@ -743,6 +766,14 @@ npc.schedule_types = {
|
|||||||
["date_based"] = "date_based"
|
["date_based"] = "date_based"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
npc.schedule_properties = {
|
||||||
|
put_item = "put_item",
|
||||||
|
put_multiple_items = "put_multiple_items",
|
||||||
|
take_item = "take_item",
|
||||||
|
trader_status = "trader_status",
|
||||||
|
can_receive_gifts = "can_receive_gifts"
|
||||||
|
}
|
||||||
|
|
||||||
local function get_time_in_hours()
|
local function get_time_in_hours()
|
||||||
return minetest.get_timeofday() * 24
|
return minetest.get_timeofday() * 24
|
||||||
end
|
end
|
||||||
@ -861,6 +892,41 @@ function npc.delete_schedule_entry(self, schedule_type, date, time)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function npc.schedule_change_property(self, property, args)
|
||||||
|
if property == npc.schedule_properties.trader_status then
|
||||||
|
-- Get status from args
|
||||||
|
local status = args.status
|
||||||
|
-- Set status to NPC
|
||||||
|
npc.set_trading_status(self, status)
|
||||||
|
elseif property == npc.schedule_properties.put_item then
|
||||||
|
local itemstring = args.itemstring
|
||||||
|
-- Add item
|
||||||
|
npc.add_item_to_inventory_itemstring(self, itemstring)
|
||||||
|
elseif property == npc.schedule_properties.put_multiple_items then
|
||||||
|
local itemlist = args.itemlist
|
||||||
|
for i = 1, #itemlist do
|
||||||
|
local itemlist_entry = itemlist[i]
|
||||||
|
local current_itemstring = itemlist[i].name
|
||||||
|
if itemlist_entry.random == true then
|
||||||
|
current_itemstring = current_itemstring
|
||||||
|
.." "..dump(math.random(itemlist_entry.min, itemlist_entry.max))
|
||||||
|
else
|
||||||
|
current_itemstring = current_itemstring.." "..tostring(itemlist_entry.count)
|
||||||
|
end
|
||||||
|
-- Add item to inventory
|
||||||
|
npc.add_item_to_inventory_itemstring(self, current_itemstring)
|
||||||
|
end
|
||||||
|
elseif property == npc.schedule_properties.take_item then
|
||||||
|
local itemstring = args.itemstring
|
||||||
|
-- Add item
|
||||||
|
npc.take_item_from_inventory_itemstring(self, itemstring)
|
||||||
|
elseif property == npc.schedule_properties.can_receive_gifts then
|
||||||
|
local value = args.can_receive_gifts
|
||||||
|
-- Set status
|
||||||
|
self.can_receive_gifts = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------
|
||||||
-- NPC Definition
|
-- NPC Definition
|
||||||
---------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------
|
||||||
@ -884,12 +950,17 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
drawtype = "front",
|
drawtype = "front",
|
||||||
textures = {
|
textures = {
|
||||||
{"npc_male1.png"},
|
{"npc_male1.png"},
|
||||||
|
--{"npc_male2.png"},
|
||||||
|
--{"npc_male3.png"},
|
||||||
|
--{"npc_male4.png"},
|
||||||
|
--{"npc_male5.png"},
|
||||||
|
--{"npc_male6.png"},
|
||||||
{"npc_female1.png"}, -- female by nuttmeg20
|
{"npc_female1.png"}, -- female by nuttmeg20
|
||||||
},
|
},
|
||||||
child_texture = {
|
child_texture = {
|
||||||
{"npc_baby_male1.png"},
|
{"npc_baby_male1.png"},
|
||||||
{"npc_baby_female1.png"},
|
{"npc_baby_female1.png"},
|
||||||
},
|
},
|
||||||
makes_footstep_sound = true,
|
makes_footstep_sound = true,
|
||||||
sounds = {},
|
sounds = {},
|
||||||
-- Added walk chance
|
-- Added walk chance
|
||||||
@ -934,16 +1005,14 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
local item = clicker:get_wielded_item()
|
local item = clicker:get_wielded_item()
|
||||||
local name = clicker:get_player_name()
|
local name = clicker:get_player_name()
|
||||||
|
|
||||||
--self.child = true
|
|
||||||
--self.textures = {"mobs_npc_child_male1.png"}
|
|
||||||
--self.base_texture = "mobs_npc_child_male1.png"
|
|
||||||
--self.object:set_properties(self)
|
|
||||||
|
|
||||||
npc.log("DEBUG", "Right-clicked NPC: "..dump(self))
|
npc.log("DEBUG", "Right-clicked NPC: "..dump(self))
|
||||||
|
|
||||||
-- Receive gift or start chat. If player has no item in hand
|
-- Receive gift or start chat. If player has no item in hand
|
||||||
-- then it is going to start chat directly
|
-- then it is going to start chat directly
|
||||||
if self.can_have_relationship and item:to_table() ~= nil then
|
minetest.log("self.can_have_relationship: "..dump(self.can_have_relationship)..", self.can_receive_gifts: "..dump(self.can_receive_gifts)..", table: "..dump(item:to_table()))
|
||||||
|
if self.can_have_relationship
|
||||||
|
and self.can_receive_gifts
|
||||||
|
and item:to_table() ~= nil then
|
||||||
-- Get item name
|
-- Get item name
|
||||||
local item = minetest.registered_items[item:get_name()]
|
local item = minetest.registered_items[item:get_name()]
|
||||||
local item_name = item.description
|
local item_name = item.description
|
||||||
@ -980,13 +1049,19 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
-- NPC is initialized, check other variables
|
-- NPC is initialized, check other variables
|
||||||
-- Check child texture issues
|
-- Check child texture issues
|
||||||
if self.is_child then
|
if self.is_child then
|
||||||
|
-- Check texture
|
||||||
npc.texture_check.timer = npc.texture_check.timer + dtime
|
npc.texture_check.timer = npc.texture_check.timer + dtime
|
||||||
if npc.texture_check.timer > npc.texture_check.interval then
|
if npc.texture_check.timer > npc.texture_check.interval then
|
||||||
-- Reset timer
|
-- Reset timer
|
||||||
npc.texture_check.timer = 0
|
npc.texture_check.timer = 0
|
||||||
|
-- Set hornytimer to zero every 60 seconds so that children
|
||||||
|
-- don't grow automatically
|
||||||
|
self.hornytimer = 0
|
||||||
-- Set correct textures
|
-- Set correct textures
|
||||||
self.texture = {self.selected_texture}
|
self.texture = {self.selected_texture}
|
||||||
self.base_texture = {self.selected_texture}
|
self.base_texture = {self.selected_texture}
|
||||||
|
self.object:set_properties(self)
|
||||||
|
npc.log("WARNING", "Corrected textures on NPC child "..dump(self.npc_name))
|
||||||
-- Set interval to large interval so this code isn't called frequently
|
-- Set interval to large interval so this code isn't called frequently
|
||||||
npc.texture_check.interval = 60
|
npc.texture_check.interval = 60
|
||||||
end
|
end
|
||||||
@ -1086,12 +1161,16 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
npc.log("DEBUG", "Adding actions to action queue")
|
npc.log("DEBUG", "Adding actions to action queue")
|
||||||
-- Add to action queue all actions on schedule
|
-- Add to action queue all actions on schedule
|
||||||
for i = 1, #schedule[time] do
|
for i = 1, #schedule[time] do
|
||||||
if schedule[time][i].action == nil then
|
--minetest.log("schedule[time]: "..dump(schedule[time]))
|
||||||
|
if schedule[time][i].task ~= nil then
|
||||||
-- Add task
|
-- Add task
|
||||||
npc.add_task(self, schedule[time][i].task, schedule[time][i].args)
|
npc.add_task(self, schedule[time][i].task, schedule[time][i].args)
|
||||||
else
|
elseif schedule[time][i].action ~= nil then
|
||||||
-- Add action
|
-- Add action
|
||||||
npc.add_action(self, schedule[time][i].action, schedule[time][i].args)
|
npc.add_action(self, schedule[time][i].action, schedule[time][i].args)
|
||||||
|
elseif schedule[time][i].property ~= nil then
|
||||||
|
-- Change NPC property
|
||||||
|
npc.schedule_change_property(self, schedule[time][i].property, schedule[time][i].args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
npc.log("DEBUG", "New action queue: "..dump(self.actions))
|
npc.log("DEBUG", "New action queue: "..dump(self.actions))
|
||||||
|
@ -27,8 +27,8 @@ npc.relationships = {}
|
|||||||
npc.relationships.ITEM_GIFT_EFFECT = 2.5
|
npc.relationships.ITEM_GIFT_EFFECT = 2.5
|
||||||
|
|
||||||
-- Expected values for these are 720 each respectively
|
-- Expected values for these are 720 each respectively
|
||||||
npc.relationships.GIFT_TIMER_INTERVAL = 2
|
npc.relationships.GIFT_TIMER_INTERVAL = 360
|
||||||
npc.relationships.RELATIONSHIP_DECREASE_TIMER_INTERVAL = 60
|
npc.relationships.RELATIONSHIP_DECREASE_TIMER_INTERVAL = 720
|
||||||
|
|
||||||
npc.relationships.RELATIONSHIP_PHASE = {}
|
npc.relationships.RELATIONSHIP_PHASE = {}
|
||||||
-- Define phases
|
-- Define phases
|
||||||
@ -360,7 +360,7 @@ local function show_receive_gift_reaction(self, item_name, modifier, clicker_nam
|
|||||||
effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "default_item_smoke.png")
|
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)
|
--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_response_for_disliked_item(item_name, self.sex)
|
||||||
npc.name(self.npc_name, clicker_name, message_to_send)
|
npc.chat(self.npc_name, clicker_name, message_to_send)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
241
spawner.lua
241
spawner.lua
@ -88,16 +88,72 @@ local function get_basic_schedule()
|
|||||||
-- Allow mobs_redo wandering
|
-- Allow mobs_redo wandering
|
||||||
[3] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
|
[3] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
|
||||||
},
|
},
|
||||||
|
-- Noon actions: go inside the house
|
||||||
|
-- This will be executed around 12 PM MTG time
|
||||||
|
noon_actions = {
|
||||||
|
-- Walk to a sittable node
|
||||||
|
[1] = {task = npc.actions.cmd.WALK_TO_POS, args = {
|
||||||
|
end_pos = {place_type=npc.places.PLACE_TYPE.SITTABLE.PRIMARY, use_access_node=true},
|
||||||
|
walkable = {"cottages:bench"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- Sit on the node
|
||||||
|
[2] = {task = npc.actions.cmd.USE_SITTABLE, args = {
|
||||||
|
pos = npc.places.PLACE_TYPE.SITTABLE.PRIMARY,
|
||||||
|
action = npc.actions.const.sittable.SIT
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- Stay put into place
|
||||||
|
[3] = {action = npc.actions.cmd.FREEZE, args = {freeze = true}}
|
||||||
|
},
|
||||||
|
-- Afternoon actions: go inside the house
|
||||||
|
-- This will be executed around 1 PM MTG time
|
||||||
|
afternoon_actions = {
|
||||||
|
-- Get up of the sit
|
||||||
|
[1] = {task = npc.actions.cmd.USE_SITTABLE, args = {
|
||||||
|
pos = npc.places.PLACE_TYPE.SITTABLE.PRIMARY,
|
||||||
|
action = npc.actions.const.sittable.GET_UP
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- Give NPC money to buy from player
|
||||||
|
[2] = {property = npc.schedule_properties.put_multiple_items, args = {
|
||||||
|
itemlist = {
|
||||||
|
{name="default:iron_lump", random=true, min=2, max=4}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- Change trader status to "trader"
|
||||||
|
[3] = {property = npc.schedule_properties.trader_status, args = {
|
||||||
|
status = npc.trade.TRADER
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[4] = {property = npc.schedule_properties.can_receive_gifts, args = {
|
||||||
|
value = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- Allow mobs_redo wandering
|
||||||
|
[5] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
|
||||||
|
},
|
||||||
-- Afternoon actions: go inside the house
|
-- Afternoon actions: go inside the house
|
||||||
-- This will be executed around 6 PM MTG time
|
-- This will be executed around 6 PM MTG time
|
||||||
afternoon_actions = {
|
late_afternoon_actions = {
|
||||||
|
-- Change trader status to "none"
|
||||||
|
[1] = {property = npc.schedule_properties.trader_status, args = {
|
||||||
|
status = npc.trade.NONE
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- Enable gift receiving again
|
||||||
|
[2] = {property = npc.schedule_properties.can_receive_gifts, args = {
|
||||||
|
can_receive_gifts = true
|
||||||
|
}
|
||||||
|
},
|
||||||
-- Get inside home
|
-- Get inside home
|
||||||
[1] = {task = npc.actions.cmd.WALK_TO_POS, args = {
|
[3] = {task = npc.actions.cmd.WALK_TO_POS, args = {
|
||||||
end_pos = npc.places.PLACE_TYPE.OTHER.HOME_INSIDE,
|
end_pos = npc.places.PLACE_TYPE.OTHER.HOME_INSIDE,
|
||||||
walkable = {}}
|
walkable = {}}
|
||||||
},
|
},
|
||||||
-- Allow mobs_redo wandering
|
-- Allow mobs_redo wandering
|
||||||
[2] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
|
[4] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
|
||||||
},
|
},
|
||||||
-- Evening actions: walk to bed and use it.
|
-- Evening actions: walk to bed and use it.
|
||||||
-- This will be executed around 10 PM MTG time
|
-- This will be executed around 10 PM MTG time
|
||||||
@ -164,6 +220,7 @@ function spawner.scan_area(pos1, pos2)
|
|||||||
|
|
||||||
result.bed_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.BED_TYPE)
|
result.bed_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.BED_TYPE)
|
||||||
result.sittable_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.SITTABLE_TYPE)
|
result.sittable_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.SITTABLE_TYPE)
|
||||||
|
-- Filter out
|
||||||
result.furnace_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.FURNACE_TYPE)
|
result.furnace_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.FURNACE_TYPE)
|
||||||
result.storage_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.STORAGE_TYPE)
|
result.storage_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.STORAGE_TYPE)
|
||||||
result.openable_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.OPENABLE_TYPE)
|
result.openable_type = spawner.get_nodes_by_type(start_pos, end_pos, npc.places.nodes.OPENABLE_TYPE)
|
||||||
@ -190,49 +247,77 @@ function spawner.assign_places(self, pos)
|
|||||||
local node_data = minetest.deserialize(meta:get_string("node_data"))
|
local node_data = minetest.deserialize(meta:get_string("node_data"))
|
||||||
|
|
||||||
-- Assign plotmarker
|
-- Assign plotmarker
|
||||||
npc.places.add_public(self, npc.places.PLACE_TYPE.OTHER.HOME_PLOTMARKER,
|
npc.places.add_shared(self, npc.places.PLACE_TYPE.OTHER.HOME_PLOTMARKER,
|
||||||
npc.places.PLACE_TYPE.OTHER.HOME_PLOTMARKER, pos)
|
npc.places.PLACE_TYPE.OTHER.HOME_PLOTMARKER, pos)
|
||||||
|
|
||||||
-- Assign entrance door and related locations
|
-- Assign entrance door and related locations
|
||||||
if entrance ~= nil and entrance.node_pos ~= nil then
|
if entrance ~= nil and entrance.node_pos ~= nil then
|
||||||
npc.places.add_public(self, npc.places.PLACE_TYPE.OPENABLE.HOME_ENTRANCE_DOOR, npc.places.PLACE_TYPE.OPENABLE.HOME_ENTRANCE_DOOR, entrance.node_pos)
|
npc.places.add_shared(self, npc.places.PLACE_TYPE.OPENABLE.HOME_ENTRANCE_DOOR, npc.places.PLACE_TYPE.OPENABLE.HOME_ENTRANCE_DOOR, entrance.node_pos)
|
||||||
-- Find the position inside and outside the door
|
-- Find the position inside and outside the door
|
||||||
local entrance_inside = npc.places.find_node_behind_door(entrance.node_pos)
|
local entrance_inside = npc.places.find_node_behind_door(entrance.node_pos)
|
||||||
local entrance_outside = npc.places.find_node_in_front_of_door(entrance.node_pos)
|
local entrance_outside = npc.places.find_node_in_front_of_door(entrance.node_pos)
|
||||||
-- Assign these places to NPC
|
-- Assign these places to NPC
|
||||||
npc.places.add_public(self, npc.places.PLACE_TYPE.OTHER.HOME_INSIDE, npc.places.PLACE_TYPE.OTHER.HOME_INSIDE, entrance_inside)
|
npc.places.add_shared(self, npc.places.PLACE_TYPE.OTHER.HOME_INSIDE, npc.places.PLACE_TYPE.OTHER.HOME_INSIDE, entrance_inside)
|
||||||
npc.places.add_public(self, npc.places.PLACE_TYPE.OTHER.HOME_OUTSIDE, npc.places.PLACE_TYPE.OTHER.HOME_OUTSIDE, entrance_outside)
|
npc.places.add_shared(self, npc.places.PLACE_TYPE.OTHER.HOME_OUTSIDE, npc.places.PLACE_TYPE.OTHER.HOME_OUTSIDE, entrance_outside)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Assign beds
|
-- Assign beds
|
||||||
if #node_data.bed_type > 0 then
|
if #node_data.bed_type > 0 then
|
||||||
-- Find unowned bed
|
-- Assign a specific sittable node to a NPC.
|
||||||
for i = 1, #node_data.bed_type do
|
npc.places.add_unowned_accessible_place(self, node_data.bed_type,
|
||||||
-- Check if bed has owner
|
npc.places.PLACE_TYPE.BED.PRIMARY)
|
||||||
--minetest.log("Node: "..dump(node_data.bed_type[i]))
|
-- Store changes to node_data
|
||||||
if node_data.bed_type[i].owner == "" then
|
meta:set_string("node_data", minetest.serialize(node_data))
|
||||||
-- If bed has no owner, check if it is accessible
|
end
|
||||||
local empty_nodes = npc.places.find_node_orthogonally(
|
|
||||||
node_data.bed_type[i].node_pos, {"air"}, 0)
|
-- Assign sits
|
||||||
-- Check if bed is accessible
|
if #node_data.sittable_type > 0 then
|
||||||
if #empty_nodes > 0 then
|
-- Check if there are same or more amount of sits as beds
|
||||||
-- Set owner to this NPC
|
if #node_data.sittable_type >= #node_data.bed_type then
|
||||||
node_data.bed_type[i].owner = self.npc_id
|
-- Assign a specific sittable node to a NPC.
|
||||||
-- Assign node to NPC
|
npc.places.add_unowned_accessible_place(self, node_data.sittable_type,
|
||||||
npc.places.add_owned(self, npc.places.PLACE_TYPE.BED.PRIMARY,
|
npc.places.PLACE_TYPE.SITTABLE.PRIMARY)
|
||||||
npc.places.PLACE_TYPE.BED.PRIMARY, node_data.bed_type[i].node_pos, empty_nodes[1].pos)
|
-- Store changes to node_data
|
||||||
-- Store changes to node_data
|
meta:set_string("node_data", minetest.serialize(node_data))
|
||||||
meta:set_string("node_data", minetest.serialize(node_data))
|
end
|
||||||
npc.log("DEBUG", "Added bed at "..minetest.pos_to_string(node_data.bed_type[i].node_pos)
|
-- Add all sits to places as shared since NPC should be able to sit
|
||||||
.." to NPC "..dump(self.npc_name))
|
-- at any accessible sit
|
||||||
break
|
npc.places.add_shared_accessible_place(self, node_data.sittable_type,
|
||||||
end
|
npc.places.PLACE_TYPE.SITTABLE.SHARED)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
-- Assign furnaces
|
||||||
|
if #node_data.furnace_type > 0 then
|
||||||
|
-- Check if there are same or more amount of furnace as beds
|
||||||
|
if #node_data.furnace_type >= #node_data.bed_type then
|
||||||
|
-- Assign a specific furnace node to a NPC.
|
||||||
|
npc.places.add_unowned_accessible_place(self, node_data.furnace_type,
|
||||||
|
npc.places.PLACE_TYPE.FURNACE.PRIMARY)
|
||||||
|
-- Store changes to node_data
|
||||||
|
meta:set_string("node_data", minetest.serialize(node_data))
|
||||||
|
end
|
||||||
|
-- Add all furnaces to places as shared since NPC should be able to use
|
||||||
|
-- any accessible furnace
|
||||||
|
npc.places.add_shared_accessible_place(self, node_data.furnace_type,
|
||||||
|
npc.places.PLACE_TYPE.FURNACE.SHARED)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Assign storage nodes
|
||||||
|
if #node_data.storage_type > 0 then
|
||||||
|
-- Check if there are same or more amount of storage as beds
|
||||||
|
if #node_data.storage_type >= #node_data.bed_type then
|
||||||
|
-- Assign a specific storage node to a NPC.
|
||||||
|
npc.places.add_unowned_accessible_place(self, node_data.storage_type,
|
||||||
|
npc.places.PLACE_TYPE.STORAGE.PRIMARY)
|
||||||
|
-- Store changes to node_data
|
||||||
|
meta:set_string("node_data", minetest.serialize(node_data))
|
||||||
|
end
|
||||||
|
-- Add all storage-types to places as shared since NPC should be able
|
||||||
|
-- to use other storage nodes as well.
|
||||||
|
npc.places.add_shared_accessible_place(self, node_data.storage_type,
|
||||||
|
npc.places.PLACE_TYPE.STORAGE.SHARED)
|
||||||
end
|
end
|
||||||
|
|
||||||
--local plot_info = minetest.deserialize(meta:get_string("plot_info"))
|
|
||||||
--minetest.log("Plot info:"..dump(plot_info))
|
|
||||||
npc.log("DEBUG", "Places for NPC "..self.npc_name..": "..dump(self.places_map))
|
npc.log("DEBUG", "Places for NPC "..self.npc_name..": "..dump(self.places_map))
|
||||||
|
|
||||||
-- Make NPC go into their house
|
-- Make NPC go into their house
|
||||||
@ -253,8 +338,14 @@ function spawner.assign_schedules(self, pos)
|
|||||||
-- Add schedule entry for morning actions
|
-- Add schedule entry for morning actions
|
||||||
npc.add_schedule_entry(self, npc.schedule_types.generic, 0, 8, nil, basic_schedule.morning_actions)
|
npc.add_schedule_entry(self, npc.schedule_types.generic, 0, 8, nil, basic_schedule.morning_actions)
|
||||||
|
|
||||||
|
-- Add schedule entry for noon actions
|
||||||
|
npc.add_schedule_entry(self, npc.schedule_types.generic, 0, 12, nil, basic_schedule.noon_actions)
|
||||||
|
|
||||||
-- Add schedule entry for afternoon actions
|
-- Add schedule entry for afternoon actions
|
||||||
npc.add_schedule_entry(self, npc.schedule_types.generic, 0, 18, nil, basic_schedule.afternoon_actions)
|
npc.add_schedule_entry(self, npc.schedule_types.generic, 0, 13, nil, basic_schedule.afternoon_actions)
|
||||||
|
|
||||||
|
-- Add schedule entry for late afternoon actions
|
||||||
|
npc.add_schedule_entry(self, npc.schedule_types.generic, 0, 18, nil, basic_schedule.late_afternoon_actions)
|
||||||
|
|
||||||
-- Add schedule entry for evening actions
|
-- Add schedule entry for evening actions
|
||||||
npc.add_schedule_entry(self, npc.schedule_types.generic, 0, 22, nil, basic_schedule.evening_actions)
|
npc.add_schedule_entry(self, npc.schedule_types.generic, 0, 22, nil, basic_schedule.evening_actions)
|
||||||
@ -348,17 +439,15 @@ end
|
|||||||
|
|
||||||
-- This function takes care of calculating how many NPCs will be spawn
|
-- This function takes care of calculating how many NPCs will be spawn
|
||||||
function spawner.calculate_npc_spawning(pos)
|
function spawner.calculate_npc_spawning(pos)
|
||||||
-- Check node
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
if node.name ~= "advanced_npc:plotmarker_auto_spawner" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
-- Check node metadata
|
-- Check node metadata
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
|
if meta:get_string("replaced") ~= "true" then
|
||||||
|
return
|
||||||
|
end
|
||||||
-- Get nodes for this building
|
-- Get nodes for this building
|
||||||
local node_data = minetest.deserialize(meta:get_string("node_data"))
|
local node_data = minetest.deserialize(meta:get_string("node_data"))
|
||||||
if node_data == nil then
|
if node_data == nil then
|
||||||
npc.log("ERROR", "Mis-configured advanced_npc:plotmarker_auto_spawner at position: "..minetest.pos_to_string(pos))
|
npc.log("ERROR", "Mis-configured mg_villages:plotmarker at position: "..minetest.pos_to_string(pos))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Check number of beds
|
-- Check number of beds
|
||||||
@ -463,15 +552,16 @@ end
|
|||||||
-- Also, the building is scanned for NPC-usable nodes and the amount
|
-- Also, the building is scanned for NPC-usable nodes and the amount
|
||||||
-- of NPCs to spawn and the interval is calculated.
|
-- of NPCs to spawn and the interval is calculated.
|
||||||
function spawner.replace_mg_villages_plotmarker(pos)
|
function spawner.replace_mg_villages_plotmarker(pos)
|
||||||
-- Check if it is already replaced
|
|
||||||
-- if minetest.get_node(pos).name == "advanced_npc:plotmarker_auto_spawner" then
|
|
||||||
-- return
|
|
||||||
-- end
|
|
||||||
-- Get the meta at the current position
|
-- Get the meta at the current position
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local village_id = meta:get_string("village_id")
|
local village_id = meta:get_string("village_id")
|
||||||
local plot_nr = meta:get_int("plot_nr")
|
local plot_nr = meta:get_int("plot_nr")
|
||||||
local infotext = meta:get_string("infotext")
|
local infotext = meta:get_string("infotext")
|
||||||
|
-- Check for nil values above
|
||||||
|
if (not village_id or (village and village == ""))
|
||||||
|
or (not plot_nr or (plot_nr and plot_nr == 0)) then
|
||||||
|
return
|
||||||
|
end
|
||||||
-- Following line from mg_villages mod, protection.lua
|
-- Following line from mg_villages mod, protection.lua
|
||||||
local btype = mg_villages.all_villages[village_id].to_add_data.bpos[plot_nr].btype
|
local btype = mg_villages.all_villages[village_id].to_add_data.bpos[plot_nr].btype
|
||||||
local building_data = mg_villages.BUILDINGS[btype]
|
local building_data = mg_villages.BUILDINGS[btype]
|
||||||
@ -483,7 +573,7 @@ function spawner.replace_mg_villages_plotmarker(pos)
|
|||||||
|
|
||||||
npc.log("INFO", "Replacing mg_villages:plotmarker at "..minetest.pos_to_string(pos))
|
npc.log("INFO", "Replacing mg_villages:plotmarker at "..minetest.pos_to_string(pos))
|
||||||
-- Replace the plotmarker for auto-spawner
|
-- Replace the plotmarker for auto-spawner
|
||||||
minetest.set_node(pos, {name="advanced_npc:plotmarker_auto_spawner"})
|
--minetest.set_node(pos, {name="advanced_npc:plotmarker_auto_spawner"})
|
||||||
-- Store old plotmarker metadata again
|
-- Store old plotmarker metadata again
|
||||||
meta:set_string("village_id", village_id)
|
meta:set_string("village_id", village_id)
|
||||||
meta:set_int("plot_nr", plot_nr)
|
meta:set_int("plot_nr", plot_nr)
|
||||||
@ -531,9 +621,10 @@ function spawner.replace_mg_villages_plotmarker(pos)
|
|||||||
meta:set_string("npc_stats", minetest.serialize(npc_stats))
|
meta:set_string("npc_stats", minetest.serialize(npc_stats))
|
||||||
-- Set replaced
|
-- Set replaced
|
||||||
meta:set_string("replaced", "true")
|
meta:set_string("replaced", "true")
|
||||||
|
-- Calculate how many NPCs will spawn
|
||||||
|
spawner.calculate_npc_spawning(pos)
|
||||||
-- Stop searching for building type
|
-- Stop searching for building type
|
||||||
break
|
break
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -545,19 +636,19 @@ if minetest.get_modpath("mg_villages") ~= nil then
|
|||||||
-- Node registration
|
-- Node registration
|
||||||
-- This node is currently a slightly modified mg_villages:plotmarker
|
-- This node is currently a slightly modified mg_villages:plotmarker
|
||||||
-- TODO: Change formspec to a more detailed one.
|
-- TODO: Change formspec to a more detailed one.
|
||||||
minetest.register_node("advanced_npc:plotmarker_auto_spawner", {
|
minetest.override_item("mg_villages:plotmarker", {
|
||||||
description = "Automatic NPC Spawner",
|
-- description = "Automatic NPC Spawner",
|
||||||
drawtype = "nodebox",
|
-- drawtype = "nodebox",
|
||||||
tiles = {"default_stone.png"},
|
-- tiles = {"default_stone.png"},
|
||||||
paramtype = "light",
|
-- paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
-- paramtype2 = "facedir",
|
||||||
node_box = {
|
-- node_box = {
|
||||||
type = "fixed",
|
-- type = "fixed",
|
||||||
fixed = {
|
-- fixed = {
|
||||||
{-0.5+2/16, -0.5, -0.5+2/16, 0.5-2/16, -0.5+2/16, 0.5-2/16},
|
-- {-0.5+2/16, -0.5, -0.5+2/16, 0.5-2/16, -0.5+2/16, 0.5-2/16},
|
||||||
--{-0.5+0/16, -0.5, -0.5+0/16, 0.5-0/16, -0.5+0/16, 0.5-0/16},
|
-- --{-0.5+0/16, -0.5, -0.5+0/16, 0.5-0/16, -0.5+0/16, 0.5-0/16},
|
||||||
}
|
-- }
|
||||||
},
|
-- },
|
||||||
walkable = false,
|
walkable = false,
|
||||||
groups = {cracky=3,stone=2},
|
groups = {cracky=3,stone=2},
|
||||||
|
|
||||||
@ -569,7 +660,7 @@ if minetest.get_modpath("mg_villages") ~= nil then
|
|||||||
--minetest.log("First-floor beds: "..dump(spawner.filter_first_floor_nodes(nodedata.bed_type, pos)))
|
--minetest.log("First-floor beds: "..dump(spawner.filter_first_floor_nodes(nodedata.bed_type, pos)))
|
||||||
--local entrance = npc.places.find_entrance_from_openable_nodes(nodedata.openable_type, pos)
|
--local entrance = npc.places.find_entrance_from_openable_nodes(nodedata.openable_type, pos)
|
||||||
--minetest.log("Found entrance: "..dump(entrance))
|
--minetest.log("Found entrance: "..dump(entrance))
|
||||||
|
minetest.log("Replaced: "..dump(minetest.get_meta(pos):get_string("replaced")))
|
||||||
-- for i = 1, #nodedata.bed_type do
|
-- for i = 1, #nodedata.bed_type do
|
||||||
-- nodedata.bed_type[i].owner = ""
|
-- nodedata.bed_type[i].owner = ""
|
||||||
-- end
|
-- end
|
||||||
@ -580,22 +671,22 @@ if minetest.get_modpath("mg_villages") ~= nil then
|
|||||||
return mg_villages.plotmarker_formspec( pos, nil, {}, clicker )
|
return mg_villages.plotmarker_formspec( pos, nil, {}, clicker )
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_receive_fields = function(pos, formname, fields, sender)
|
-- on_receive_fields = function(pos, formname, fields, sender)
|
||||||
return mg_villages.plotmarker_formspec( pos, formname, fields, sender );
|
-- return mg_villages.plotmarker_formspec( pos, formname, fields, sender );
|
||||||
end,
|
-- end,
|
||||||
|
|
||||||
on_timer = function(pos, elapsed)
|
on_timer = function(pos, elapsed)
|
||||||
npc.spawner.spawn_npc(pos)
|
npc.spawner.spawn_npc(pos)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- protect against digging
|
-- protect against digging
|
||||||
can_dig = function(pos, player)
|
-- can_dig = function(pos, player)
|
||||||
local meta = minetest.get_meta(pos);
|
-- local meta = minetest.get_meta(pos);
|
||||||
if (meta and meta:get_string("village_id") ~= "" and meta:get_int("plot_nr") and meta:get_int("plot_nr") > 0 ) then
|
-- if (meta and meta:get_string("village_id") ~= "" and meta:get_int("plot_nr") and meta:get_int("plot_nr") > 0 ) then
|
||||||
return false;
|
-- return false;
|
||||||
end
|
-- end
|
||||||
return true;
|
-- return true;
|
||||||
end
|
-- end
|
||||||
})
|
})
|
||||||
|
|
||||||
-- LBM Registration
|
-- LBM Registration
|
||||||
@ -621,7 +712,7 @@ if minetest.get_modpath("mg_villages") ~= nil then
|
|||||||
label = "Replace mg_villages:plotmarker with Advanced NPC auto spawners",
|
label = "Replace mg_villages:plotmarker with Advanced NPC auto spawners",
|
||||||
nodenames = {"mg_villages:plotmarker"},
|
nodenames = {"mg_villages:plotmarker"},
|
||||||
interval = 10,--npc.spawner.replacement_interval,
|
interval = 10,--npc.spawner.replacement_interval,
|
||||||
chance = 1, --5,
|
chance = 1,--5,
|
||||||
catch_up = true,
|
catch_up = true,
|
||||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||||
-- Check if replacement is needed
|
-- Check if replacement is needed
|
||||||
@ -632,14 +723,14 @@ if minetest.get_modpath("mg_villages") ~= nil then
|
|||||||
if npc.spawner.replace_activated then
|
if npc.spawner.replace_activated then
|
||||||
-- Replace mg_villages:plotmarker
|
-- Replace mg_villages:plotmarker
|
||||||
spawner.replace_mg_villages_plotmarker(pos)
|
spawner.replace_mg_villages_plotmarker(pos)
|
||||||
-- Set NPCs to spawn
|
|
||||||
spawner.calculate_npc_spawning(pos)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--minetest.register_alias_force("mg_villages:plotmarker", )
|
||||||
|
|
||||||
-- Chat commands to manage spawners
|
-- Chat commands to manage spawners
|
||||||
minetest.register_chatcommand("restore_plotmarkers", {
|
minetest.register_chatcommand("restore_plotmarkers", {
|
||||||
description = "Replaces all advanced_npc:plotmarker_auto_spawner with mg_villages:plotmarker in the specified radius.",
|
description = "Replaces all advanced_npc:plotmarker_auto_spawner with mg_villages:plotmarker in the specified radius.",
|
||||||
@ -662,7 +753,7 @@ minetest.register_chatcommand("restore_plotmarkers", {
|
|||||||
local start_pos = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius}
|
local start_pos = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius}
|
||||||
local end_pos = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
|
local end_pos = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
|
||||||
local nodes = minetest.find_nodes_in_area_under_air(start_pos, end_pos,
|
local nodes = minetest.find_nodes_in_area_under_air(start_pos, end_pos,
|
||||||
{"advanced_npc:plotmarker_auto_spawner"})
|
{"mg_villages:plotmarker"})
|
||||||
-- Check if we have nodes to replace
|
-- Check if we have nodes to replace
|
||||||
minetest.chat_send_player(name, "Found "..dump(#nodes).." nodes to replace...")
|
minetest.chat_send_player(name, "Found "..dump(#nodes).." nodes to replace...")
|
||||||
if #nodes == 0 then
|
if #nodes == 0 then
|
||||||
@ -670,13 +761,10 @@ minetest.register_chatcommand("restore_plotmarkers", {
|
|||||||
end
|
end
|
||||||
-- Replace all nodes
|
-- Replace all nodes
|
||||||
for i = 1, #nodes do
|
for i = 1, #nodes do
|
||||||
--minetest.log(dump(nodes[i]))
|
|
||||||
local meta = minetest.get_meta(nodes[i])
|
local meta = minetest.get_meta(nodes[i])
|
||||||
local village_id = meta:get_string("village_id")
|
local village_id = meta:get_string("village_id")
|
||||||
local plot_nr = meta:get_int("plot_nr")
|
local plot_nr = meta:get_int("plot_nr")
|
||||||
local infotext = meta:get_string("infotext")
|
local infotext = meta:get_string("infotext")
|
||||||
-- Replace node
|
|
||||||
minetest.set_node(nodes[i], {name="mg_villages:plotmarker"})
|
|
||||||
-- Set metadata
|
-- Set metadata
|
||||||
meta = minetest.get_meta(nodes[i])
|
meta = minetest.get_meta(nodes[i])
|
||||||
meta:set_string("village_id", village_id)
|
meta:set_string("village_id", village_id)
|
||||||
@ -686,6 +774,7 @@ minetest.register_chatcommand("restore_plotmarkers", {
|
|||||||
meta:set_string("node_data", nil)
|
meta:set_string("node_data", nil)
|
||||||
meta:set_string("npcs", nil)
|
meta:set_string("npcs", nil)
|
||||||
meta:set_string("npc_stats", nil)
|
meta:set_string("npc_stats", nil)
|
||||||
|
meta:set_string("replaced", "false")
|
||||||
end
|
end
|
||||||
minetest.chat_send_player(name, "Finished replacement of "..dump(#nodes).." auto-spawners successfully")
|
minetest.chat_send_player(name, "Finished replacement of "..dump(#nodes).." auto-spawners successfully")
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user