diff --git a/actions/places.lua b/actions/places.lua index 251d662..89ce5e9 100644 --- a/actions/places.lua +++ b/actions/places.lua @@ -8,34 +8,57 @@ -- to know where the farm they work is located, or where the bed they sleep is. -- Other mods have to be supported for this to work correctly, as there are -- many sitting nodes, many beds, many tables, chests, etc. For now, by default, --- support for default and cottages is going to be provided. +-- support for default MTG games and cottages mod is going to be provided. npc.places = {} npc.places.nodes = { - BEDS = { + BED_TYPE = { "beds:bed_bottom", - "beds:fancy_bed_bottom" - }, - SITTABLE = { + "beds:fancy_bed_bottom", + "cottages:bed_foot", + "cottages:straw_mat", + "cottages:sleeping_mat" + }, + SITTABLE_TYPE = { "cottages:bench", - -- TODO: Register all stairs node that are supported for sitting - -- Hint: wood + -- TODO: Register other stair types "stairs:stair_wood" }, - CHESTS = { + STORAGE_TYPE = { "default:chest", - "default:chest_locked" + "default:chest_locked", + "cottages:shelf" + }, + FURNACE_TYPE = { + "default:furnace", + "default:furnace_active" + }, + OPENABLE_TYPE = { + -- TODO: Register fences + "doors:door_glass_a", + "doors:door_glass_b", + "doors:door_obsidian_a", + "doors:door_obsidian_b", + "doors:door_steel_a", + "doors:door_steel_b", + "doors:door_wood_a", + "doors:door_wood_b", + "cottages:gate_open", + "cottages:gate_closed", + "cottages:half_door" } } npc.places.PLACE_TYPE = { - "OWN_BED", - "OWN_CHEST", - "HOUSE_CHAIR", - "HOUSE_TABLE", - "HOUSE_FURNACE", - "HOUSE_ENTRANCE" + NPC_HOUSE = { + "OWN_BED", + "OWN_ROOM_DOOR", + "OWN_STORAGE", + "SHARED_FURNACE", + "SHARED_SITTABLE", + "ENTRANCE_DOOR" + } } diff --git a/spawner.lua b/spawner.lua index 2e8ee32..33e1d9f 100644 --- a/spawner.lua +++ b/spawner.lua @@ -37,9 +37,14 @@ -- such as scanning upper floors, spawning families of NPCs and creating relationships -- among them, etc. will be for other versions. +-- Public API +npc.spawner = {} +-- Private API +local spawner = {} + -- This is the official list of support building types -- from the mg_villages mod -local mg_villages_supported_building_types = { +npc.spawner.mg_villages_supported_building_types = { "house", "farm_full", "farm_tiny", @@ -47,13 +52,112 @@ local mg_villages_supported_building_types = { "lumberjack" } -local replace_activated = true -local max_replace_count = 1 -local replace_count = 0 +npc.spawner.replace_activated = true +-- npc.spawner.max_replace_count = 1 +-- spawner.replace_count = 0 --- Node registration --- This node is currently a slightly modified mg_villages:plotmarker -minetest.register_node("advanced_npc:auto_spawner", { +--------------------------------------------------------------------------------------- +-- Scanning functions +--------------------------------------------------------------------------------------- + +-- Scans an area for the supported nodes: beds, benches, +-- furnaces, storage (e.g. chests) and openable (e.g. doors). +-- Returns a table with these classifications +function spawner.scan_area(start_pos, end_pos) + minetest.log("Scanning area for nodes...") + minetest.log("Start pos: "..dump(start_pos)) + minetest.log("End pos: "..dump(end_pos)) + local result = { + bed_type = {}, + sittable_type = {}, + furnace_type = {}, + storage_type = {}, + openable_type = {} + } + + result.bed_type = npc.places.find_node_in_area(start_pos, end_pos, npc.places.nodes.BED_TYPE) + result.sittable_type = npc.places.find_node_in_area(start_pos, end_pos, npc.places.nodes.SITTABLE_TYPE) + result.furnace_type = npc.places.find_node_in_area(start_pos, end_pos, npc.places.nodes.FURNACE_TYPE) + result.storage_type = npc.places.find_node_in_area(start_pos, end_pos, npc.places.nodes.STORAGE_TYPE) + result.openable_type = npc.places.find_node_in_area(start_pos, end_pos, npc.places.nodes.OPENABLE_TYPE) + + minetest.log("Found nodes inside area: "..dump(result)) + return result +end + + + +-- This function takes care of calculating how many NPCs will be spawn +function spawner.calculate_npc_spawning(pos) + +end + +--------------------------------------------------------------------------------------- +-- Support code for mg_villages mods +--------------------------------------------------------------------------------------- + +-- This function creates a table of the scannable nodes inside +-- a mg_villages building. It needs the plotmarker position for a start +-- point and the building_data to get the x, y and z-coordinate size +-- of the building schematic +function spawner.scan_mg_villages_building(pos, building_data) + -- Get area of the building + local x_size = building_data.sizex + local y_size = building_data.ysize + local z_size = building_data.sizez + local start_pos = {x=pos.x, y=pos.y, z=pos.z} + local end_pos = {x=pos.x + x_size, y=pos.y + y_size, z=pos.z + z_size} + + return spawner.scan_area(start_pos, end_pos) +end + +-- This function replaces an existent mg_villages:plotmarker with +-- and advanced_npc:auto_spawner. The existing metadata will be kept, +-- to allow compatibility. A new formspec will appear on right-click, +-- however it will as well allow to buy or manage the plot. +-- Also, the building is scanned for NPC-usable nodes and the amount +-- of NPCs to spawn and the interval is calculated. +function spawner.replace_mg_villages_plotmarker(pos) + -- Get the meta at the current position + local meta = minetest.get_meta(pos) + local village_id = meta:get_string("village_id") + local plot_nr = meta:get_int("plot_nr") + local infotext = meta:get_string("infotext") + -- Following line from mg_villages mod, protection.lua + local btype = mg_villages.all_villages[village_id].to_add_data.bpos[plot_nr].btype + local building_data = mg_villages.BUILDINGS[btype] + local building_type = building_data.typ + -- Check if the building is of the support types + for _,value in pairs(npc.spawner.mg_villages_supported_building_types) do + + if building_type == value then + + minetest.log("Replacing mg_villages:plotmarker at "..dump(pos)) + -- Replace the plotmarker for auto-spawner + minetest.set_node(pos, {name="advanced_npc:plotmarker_auto_spawner"}) + -- Store old plotmarker metadata again + meta:set_string("village_id", village_id) + meta:set_int("plot_nr", plot_nr) + meta:set_string("infotext", infotext) + -- Store building type in metadata + meta:set_string("building_type", building_type) + -- Scan building for nodes + local nodedata = spawner.scan_mg_villages_building(pos, building_data) + -- Store nodedata into the spawner's metadata + meta:set_string("nodedata", minetest.serialize(nodedata)) + -- Stop searching for building type + break + + end + end +end + +-- Only register the node, the ABM and the LBM if mg_villages mod +-- is present +if minetest.get_modpath("mg_villages") ~= nil then + -- Node registration + -- This node is currently a slightly modified mg_villages:plotmarker + minetest.register_node("advanced_npc:plotmarker_auto_spawner", { description = "Automatic NPC Spawner", drawtype = "nodebox", tiles = {"default_stone.png"}, @@ -68,97 +172,53 @@ minetest.register_node("advanced_npc:auto_spawner", { groups = {cracky=3,stone=2}, on_rightclick = function( pos, node, clicker, itemstack, pointed_thing) - return mg_villages.plotmarker_formspec( pos, nil, {}, clicker ) + return mg_villages.plotmarker_formspec( pos, nil, {}, clicker ) end, 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, -- protect against digging can_dig = function(pos, player) - 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 - return false; - end - return true; - end -}) + 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 + return false; + end + return true; + end + }) --- Scans an area for the supported nodes: beds, benches, --- furnaces, storage (e.g. chests) and openable (e.g. doors). --- Returns a table with these classifications -local function scan_area(start_pos, end_pos) - local result = { - bed_type = {}, - sittable_type = {}, - furnace_type = {}, - storage_type = {}, - openable_type = {} - } + -- LBM Registration + -- Used to modify plotmarkers and replace them with advanced_npc:plotmarker_auto_spawner + minetest.register_lbm({ + label = "Replace mg_villages:plotmarker with Advanced NPC auto spawners", + name = "advanced_npc:mg_villages_plotmarker_replacer", + nodenames = {"mg_villages:plotmarker"}, + run_at_every_load = true, + action = function(pos, node) + -- Check if replacement is activated + if npc.spawner.replace_activated then + -- Replace mg_villages:plotmarker + spawner.replace_mg_villages_plotmarker(pos) + end + end + }) - + -- ABM Registration... for when LBM fails. + minetest.register_abm({ + label = "Replace mg_villages:plotmarker with Advanced NPC auto spawners", + nodenames = {"mg_villages:plotmarker"}, + interval = 1.0, + chance = 1, + catch_up = true, + action = function(pos, node, active_object_count, active_object_count_wider) + -- Check if replacement is activated + if npc.spawner.replace_activated then + -- Replace mg_villages:plotmarker + spawner.replace_mg_villages_plotmarker(pos) + end + end + }) - -end - --- This function creates a table of the scannable nodes inside --- a mg_villages building. It needs the plotmarker position for a start --- point and the building_data to get the x, y and z-coordinate size --- of the building schematic -local function scan_mg_villages_building(pos, building_data) - -- Get area of the building - local x_size = building_data.sizex - local y_size = building_data.ysize - local z_size = building_data.sizez - local start_pos = {x=pos.x, y=pos.y, z=pos.z} - local end_pos = {x=pos.x + x_size, y=pos.y + y_size, z=pos.z + z_size} - - return scan_area(start_pos, end_pos) -end - - -if minetest.get_modpath("mg_villages") ~= nil then - -- LBM Registration - -- Used to modify plotmarkers and replace them with advanced_npc:auto_spawner - minetest.register_lbm({ - label = "Replace mg_villages:plotmarker with Advanced NPC auto spawners", - name = "advanced_npc:mg_villages_plotmarker_replacer", - nodenames = {"mg_villages:plotmarker"}, - run_at_every_load = true, - action = function(pos, node) - -- Check if replacement is activated - if replace_activated then - -- Check if limit has been reached - if replace_count < max_replace_count then - -- Get the meta at the current position - local meta = minetest.get_meta(pos) - local village_id = meta:get_string("village_id") - local plot_nr = meta:get_int("plot_nr") - local infotext = meta:get_string("infotext") - -- Following line from mg_villages mod, protection.lua - local btype = mg_villages.all_villages[village_id].to_add_data.bpos[plot_nr].btype - minetest.log("All info: "..dump(mg_villages.BUILDINGS[btype])) - local building_data = mg_villages.BUILDINGS[btype] - local building_type = building_data.typ - -- Check if the building is of the support types - for _,value in pairs(mg_villages_supported_building_types) do - minetest.log("Current value: "..dump(value)) - if building_type == value then - -- Replace the plotmarker for auto-spawner - minetest.set_node(pos, {name="advanced_npc:auto_spawner"}) - -- Set the old plotmarker meta again - meta:set_string("village_id", village_id) - meta:set_int("plot_nr", plot_nr) - meta:set_string("infotext", infotext) - - - -- Increase count of modified nodes - replace_count = replace_count + 1 - end - end - end - end - end - }) end \ No newline at end of file