Spawner: Workplaces are properly assigned to NPC.

If a workplace is assigned to a NPC, it is not used by any other NPC.
"/restore_plotmarkers" command also restores the workplace so it can
be used by other NPCs.
Occupations: Dialogues are registered on occupation registration.
This commit is contained in:
Hector Franqui 2017-08-31 09:11:43 -04:00
parent 706a5cf188
commit c9eb3b0ef4
2 changed files with 100 additions and 29 deletions

View File

@ -246,7 +246,44 @@ npc.occupations.basic_def = {
-- This function registers an occupation
function npc.occupations.register_occupation(name, def)
-- Register all dialogues per definition
local dialogue_keys = {}
if def.dialogues then
-- Check which type of dialogues we have
if def.dialogues.type == "given" then
-- We have been given the dialogues, so def.dialogues.data contains
-- an array of dialogues
for _, dialogue in pairs(def.dialogues.data) do
-- Add to the dialogue tags the "occupation name"
table.insert(dialogue.tags, name)
-- Register dialogue
npc.log("INFO", "Registering dialogue for occupation "..dump(name)..": "..dump(dialogue))
local key = npc.dialogue.register_dialogue(dialogue)
-- Add key to set of dialogue keys
table.insert(dialogue_keys, key)
end
elseif def.dialogues.type == "mix" then
-- We have been given the dialogues, so def.dialogues.data contains
-- an array of dialogues and def.dialogues.tags contains an array of
-- tags. Currently only registering will be performed.
-- Register dialogues
for _, dialogue in pairs(def.dialogues.data) do
-- Add to the dialogue tags the "occupation name"
table.insert(dialogue.tags, name)
-- Register dialogue
local key = npc.dialogue.register_dialogue(dialogue)
-- Add key to set of dialogue keys
table.insert(dialogue_keys, key)
end
end
end
-- Save into the definition the dialogue keys
def.dialogues["keys"] = dialogue_keys
-- Save the definition
npc.occupations.registered_occupations[name] = def
npc.log("INFO", "Successfully registered occupation with name: "..dump(name))
end
@ -339,30 +376,22 @@ function npc.occupations.initialize_occupation_values(self, occupation_name)
if def.dialogues then
local dialogue_keys = {}
-- Check which type of dialogues we have
if def.dialogues.type == "given" then
if def.dialogues.type == "given" and def.dialogues.keys then
-- We have been given the dialogues, so def.dialogues.data contains
-- an array of dialogues
for _, dialogue in pairs(def.dialogues.data) do
-- Add to the dialogue tags the "occupation name"
table.insert(dialogue.tags, occupation_name)
-- Register dialogue
npc.log("INFO", "Registering dialogue for occupation "..dump(occupation_name)..": "..dump(dialogue))
local key = npc.dialogue.register_dialogue(dialogue)
-- Add key to set of dialogue keys
table.insert(dialogue_keys, key)
-- an array of dialogues. These dialogues were registered, therefore we need
-- just the keys
for i = 1, #def.dialogues.keys do
table.insert(dialogue_keys, def.dialogues.keys[i])
end
elseif def.dialogues.type == "mix" then
-- We have been given the dialogues, so def.dialogues.data contains
-- an array of dialogues and def.dialogues.tags contains an array of
-- tags that we will use to search
-- Register dialogues
for _, dialogue in pairs(def.dialogues.data) do
-- Add to the dialogue tags the "occupation name"
table.insert(dialogue.tags, occupation_name)
-- Register dialogue
local key = npc.dialogue.register_dialogue(dialogue)
-- Add key to set of dialogue keys
table.insert(dialogue_keys, key)
if def.dialogues.keys then
-- Add the registered dialogues
for i = 1, #def.dialogues.keys do
table.insert(dialogue_keys, def.dialogues.keys[i])
end
end
-- Find dialogues using tags
local dialogues = npc.search_dialogue_by_tags(def.dialogues.tags, true)
@ -384,10 +413,10 @@ function npc.occupations.initialize_occupation_values(self, occupation_name)
max_dialogue_count = def.dialogues.max_count
end
-- Add dialogues to the normal dialogues for NPC
self.dialogues.normal = dialogue_keys
-- for i = 1, max_dialogue_count do
-- self.dialogues.normal[i] = dialogue_keys[i]
-- end
self.dialogues.normal = {}
for i = 1, math.min(max_dialogue_count, #dialogue_keys) do
self.dialogues.normal[i] = dialogue_keys[i]
end
end
-- Initialize trader status

View File

@ -238,7 +238,7 @@ function npc.spawner.determine_npc_occupation(building_type, workplace_nodes, np
npc.utils.array_contains(surrounding_building_types, workplace_nodes[j].building_type) then
minetest.log("Found corresponding node: "..dump(workplace_nodes[j]))
local meta = minetest.get_meta(workplace_nodes[j].node_pos)
local worker_data = minetest.deserialize(meta:get_string("worker_data") or "")
local worker_data = minetest.deserialize(meta:get_string("work_data") or "")
-- If no worker data is found, then create it
if not worker_data then
return {name=occupation_names[i], node=workplace_nodes[j]}
@ -249,7 +249,7 @@ function npc.spawner.determine_npc_occupation(building_type, workplace_nodes, np
end
end
end
return nil
return {name=npc.occupations.basic_name, node={}}
end
-- This function is called when the node timer for spawning NPC
@ -279,12 +279,25 @@ function npc.spawner.spawn_npc_on_plotmarker(pos)
-- Determine occupation
area_info["building_type"] = meta:get_string("building_type")
local nearby_plotmarkers = minetest.deserialize(meta:get_string("nearby_plotmarkers"))
--minetest.log("BEFORE Workplace nodes: "..dump(area_info.node_data.workplace_type))
local occupation_data = npc.spawner.determine_npc_occupation(
area_info.building_type,
area_info.node_data.workplace_type,
area_info.npcs)
local metadata = npc.spawner.spawn_npc(pos, area_info, occupation_data.name)
--minetest.log("AFTER Workplace nodes: "..dump(area_info.node_data.workplace_type))
-- Assign workplace node
if occupation_data then
for i = 1, #area_info.node_data.workplace_type do
if area_info.node_data.workplace_type[i].node_pos == occupation_data.node.node_pos then
-- Found node, mark it as being used by NPC
area_info.node_data.workplace_type[i]["occupation"] = occupation_data.name
end
end
end
-- Spawn NPC
local metadata = npc.spawner.spawn_npc(pos, area_info, occupation_data.name, occupation_data.node.node_pos)
-- Set all metadata back into the node
-- Increase NPC spawned count
@ -311,7 +324,7 @@ end
-- This function spawns a NPC into the given pos.
-- If area_info is given, updated area_info is returned at end
function npc.spawner.spawn_npc(pos, area_info, occupation_name)
function npc.spawner.spawn_npc(pos, area_info, occupation_name, occupation_workplace_pos)
-- Get current NPC info
local npc_table = area_info.npcs
-- Get NPC stats
@ -367,6 +380,7 @@ function npc.spawner.spawn_npc(pos, area_info, occupation_name)
sex = ent:get_luaentity().sex,
age = age,
occupation = occupation,
workplace = occupation_workplace_pos,
born_day = minetest.get_day_count()
}
minetest.log("Area info: "..dump(area_info))
@ -486,9 +500,28 @@ function npc.spawner.assign_places(self, entrance, node_data, pos)
-- Assign workplace nodes
if #node_data.workplace_type > 0 then
local occupation = npc.occupations.registered_occupations[self.occupation_name]
-- First, find the workplace_node that was marked
for i = 1, #node_data.workplace_type do
minetest.log("In assign places: workplace nodes: "..dump(node_data.workplace_type))
if node_data.workplace_type[i].occupation
and node_data.workplace_type[i].occupation == self.occupation_name then
-- Found the node. Assign only this node to the NPC.
npc.places.add_shared_accessible_place(self, node_data.workplace_type[i],
npc.places.PLACE_TYPE.WORKPLACE.PRIMARY)
-- Edit metadata of this workplace node to not allow it for other NPCs
local meta = minetest.get_meta(node_data.workplace_type[i].node_pos)
local work_data = {
npc_name = self.npc_name,
occupation = self.occupation_name,
multiple_npcs =
npc.occupations.registered_occupations[self.occupation_name].allow_multiple_npcs_at_workplace
}
meta:set_string("work_data", minetest.serialize(work_data))
--
-- meta = minetest.get_meta(node_data.workplace_type[i].node_pos)
-- minetest.log("Work data: "..dump(minetest.deserialize(meta:get_string("work_data"))))
end
end
end
npc.log("DEBUG", "Places for NPC "..self.npc_name..": "..dump(self.places_map))
@ -865,6 +898,15 @@ minetest.register_chatcommand("restore_plotmarkers", {
local village_id = meta:get_string("village_id")
local plot_nr = meta:get_int("plot_nr")
local infotext = meta:get_string("infotext")
local npcs = minetest.deserialize(meta:get_string("npcs"))
-- Restore workplaces to original status
for i = 1, #npcs do
if npcs[i].workplace then
-- Remove work data
local workplace_meta = minetest.get_meta(npcs[i].workplace)
workplace_meta:set_string("work_data", nil)
end
end
-- Set metadata
meta = minetest.get_meta(nodes[i])
meta:set_string("village_id", village_id)