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 -- This function registers an occupation
function npc.occupations.register_occupation(name, def) 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.occupations.registered_occupations[name] = def
npc.log("INFO", "Successfully registered occupation with name: "..dump(name)) npc.log("INFO", "Successfully registered occupation with name: "..dump(name))
end end
@ -339,30 +376,22 @@ function npc.occupations.initialize_occupation_values(self, occupation_name)
if def.dialogues then if def.dialogues then
local dialogue_keys = {} local dialogue_keys = {}
-- Check which type of dialogues we have -- 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 -- We have been given the dialogues, so def.dialogues.data contains
-- an array of dialogues -- an array of dialogues. These dialogues were registered, therefore we need
for _, dialogue in pairs(def.dialogues.data) do -- just the keys
-- Add to the dialogue tags the "occupation name" for i = 1, #def.dialogues.keys do
table.insert(dialogue.tags, occupation_name) table.insert(dialogue_keys, def.dialogues.keys[i])
-- 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)
end end
elseif def.dialogues.type == "mix" then elseif def.dialogues.type == "mix" then
-- We have been given the dialogues, so def.dialogues.data contains -- We have been given the dialogues, so def.dialogues.data contains
-- an array of dialogues and def.dialogues.tags contains an array of -- an array of dialogues and def.dialogues.tags contains an array of
-- tags that we will use to search -- tags that we will use to search
-- Register dialogues if def.dialogues.keys then
for _, dialogue in pairs(def.dialogues.data) do -- Add the registered dialogues
-- Add to the dialogue tags the "occupation name" for i = 1, #def.dialogues.keys do
table.insert(dialogue.tags, occupation_name) table.insert(dialogue_keys, def.dialogues.keys[i])
-- Register dialogue end
local key = npc.dialogue.register_dialogue(dialogue)
-- Add key to set of dialogue keys
table.insert(dialogue_keys, key)
end end
-- Find dialogues using tags -- Find dialogues using tags
local dialogues = npc.search_dialogue_by_tags(def.dialogues.tags, true) 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 max_dialogue_count = def.dialogues.max_count
end end
-- Add dialogues to the normal dialogues for NPC -- Add dialogues to the normal dialogues for NPC
self.dialogues.normal = dialogue_keys self.dialogues.normal = {}
-- for i = 1, max_dialogue_count do for i = 1, math.min(max_dialogue_count, #dialogue_keys) do
-- self.dialogues.normal[i] = dialogue_keys[i] self.dialogues.normal[i] = dialogue_keys[i]
-- end end
end end
-- Initialize trader status -- 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 npc.utils.array_contains(surrounding_building_types, workplace_nodes[j].building_type) then
minetest.log("Found corresponding node: "..dump(workplace_nodes[j])) minetest.log("Found corresponding node: "..dump(workplace_nodes[j]))
local meta = minetest.get_meta(workplace_nodes[j].node_pos) 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 no worker data is found, then create it
if not worker_data then if not worker_data then
return {name=occupation_names[i], node=workplace_nodes[j]} 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 end
end end
return nil return {name=npc.occupations.basic_name, node={}}
end end
-- This function is called when the node timer for spawning NPC -- 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 -- Determine occupation
area_info["building_type"] = meta:get_string("building_type") area_info["building_type"] = meta:get_string("building_type")
local nearby_plotmarkers = minetest.deserialize(meta:get_string("nearby_plotmarkers")) 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( local occupation_data = npc.spawner.determine_npc_occupation(
area_info.building_type, area_info.building_type,
area_info.node_data.workplace_type, area_info.node_data.workplace_type,
area_info.npcs) 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 -- Set all metadata back into the node
-- Increase NPC spawned count -- Increase NPC spawned count
@ -311,7 +324,7 @@ end
-- This function spawns a NPC into the given pos. -- This function spawns a NPC into the given pos.
-- If area_info is given, updated area_info is returned at end -- 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 -- Get current NPC info
local npc_table = area_info.npcs local npc_table = area_info.npcs
-- Get NPC stats -- Get NPC stats
@ -367,6 +380,7 @@ function npc.spawner.spawn_npc(pos, area_info, occupation_name)
sex = ent:get_luaentity().sex, sex = ent:get_luaentity().sex,
age = age, age = age,
occupation = occupation, occupation = occupation,
workplace = occupation_workplace_pos,
born_day = minetest.get_day_count() born_day = minetest.get_day_count()
} }
minetest.log("Area info: "..dump(area_info)) minetest.log("Area info: "..dump(area_info))
@ -486,9 +500,28 @@ function npc.spawner.assign_places(self, entrance, node_data, pos)
-- Assign workplace nodes -- Assign workplace nodes
if #node_data.workplace_type > 0 then 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 end
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))
@ -865,6 +898,15 @@ minetest.register_chatcommand("restore_plotmarkers", {
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")
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 -- 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)