Spawner: Assign sits, furnaces and storage nodes to spawned NPCs.
Small basic schedule change: NPCs now sit from 12-1 on whatever sit they 'own'. Fixed /restore_plotmarkers not clearing all metadata. NPC: Attempted to add a fix for the children growing on their own (due to mobs_redo).
This commit is contained in:
parent
c19ea70242
commit
3df43ab580
@ -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)
|
||||||
|
13
npc.lua
13
npc.lua
@ -44,7 +44,7 @@ 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
|
||||||
}
|
}
|
||||||
@ -884,6 +884,11 @@ 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 = {
|
||||||
@ -938,7 +943,7 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
--self.textures = {"mobs_npc_child_male1.png"}
|
--self.textures = {"mobs_npc_child_male1.png"}
|
||||||
--self.base_texture = "mobs_npc_child_male1.png"
|
--self.base_texture = "mobs_npc_child_male1.png"
|
||||||
--self.object:set_properties(self)
|
--self.object:set_properties(self)
|
||||||
|
npc.log("INFO", "NPC places: "..dump(self.places_map))
|
||||||
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
|
||||||
@ -980,10 +985,14 @@ 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}
|
||||||
|
130
spawner.lua
130
spawner.lua
@ -88,9 +88,38 @@ 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 = {
|
||||||
|
[1] = {task = npc.actions.cmd.USE_SITTABLE, args = {
|
||||||
|
pos = npc.places.PLACE_TYPE.SITTABLE.PRIMARY,
|
||||||
|
action = npc.actions.const.sittable.GET_UP
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- Allow mobs_redo wandering
|
||||||
|
[2] = {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 = {
|
||||||
-- Get inside home
|
-- Get inside home
|
||||||
[1] = {task = npc.actions.cmd.WALK_TO_POS, args = {
|
[1] = {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,
|
||||||
@ -164,6 +193,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 +220,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 +311,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)
|
||||||
@ -620,8 +684,8 @@ if minetest.get_modpath("mg_villages") ~= nil then
|
|||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
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 = npc.spawner.replacement_interval,
|
interval = 10,--npc.spawner.replacement_interval,
|
||||||
chance = 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
|
||||||
|
Loading…
Reference in New Issue
Block a user