From c9eb3b0ef46491444bf297b2e699998cfbe8da96 Mon Sep 17 00:00:00 2001 From: Hector Franqui Date: Thu, 31 Aug 2017 09:11:43 -0400 Subject: [PATCH] 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. --- occupations/occupations.lua | 73 ++++++++++++++++++++++++++----------- spawner.lua | 56 ++++++++++++++++++++++++---- 2 files changed, 100 insertions(+), 29 deletions(-) diff --git a/occupations/occupations.lua b/occupations/occupations.lua index 6065387..21bfc73 100644 --- a/occupations/occupations.lua +++ b/occupations/occupations.lua @@ -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 diff --git a/spawner.lua b/spawner.lua index 4e6345f..5f67be9 100644 --- a/spawner.lua +++ b/spawner.lua @@ -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)