Spawner: Avoid multiple spawning by not replacing the mg_villages:plotmarker, but just override its definition.

NPC: (WIP) Support change properties on schedules.
This commit is contained in:
Hector Franqui 2017-06-21 07:16:11 -04:00
parent fd4cec0d63
commit 7110c49b42
2 changed files with 91 additions and 47 deletions

46
npc.lua
View File

@ -455,6 +455,24 @@ function npc.initialize(entity, pos, is_lua_entity, npc_stats)
ent.object:set_properties(ent)
end
---------------------------------------------------------------------------------------
-- Trading functions
---------------------------------------------------------------------------------------
function npc.generate_trade_list_from_inventory(self)
local list = {}
for i = 1, #self.inventory do
list[npc.get_item_name(self.inventory[i])] = {}
end
self.trader_data.trade_list.both = list
end
function npc.set_trading_status(self, status)
-- Set status
self.trader_data.trader_status = status
-- Re-generate trade offers
npc.trade.generate_trade_offers_by_status(self)
end
---------------------------------------------------------------------------------------
-- Inventory functions
---------------------------------------------------------------------------------------
@ -743,6 +761,12 @@ npc.schedule_types = {
["date_based"] = "date_based"
}
npc.schedule_properties = {
put_item = "put_item",
take_item = "take_item",
trader_status = "trader_status"
}
local function get_time_in_hours()
return minetest.get_timeofday() * 24
end
@ -861,6 +885,19 @@ function npc.delete_schedule_entry(self, schedule_type, date, time)
end
end
function npc.schedule_change_property(self, property, args)
if property == npc.schedule_properties.trader_status then
-- Get status from args
local status = args.status
-- Set status to NPC
npc.set_trading_status(self, status)
elseif property == npc.schedule_properties.put_item then
elseif property == npc.schedule_properties.take_item then
end
end
---------------------------------------------------------------------------------------
-- NPC Definition
---------------------------------------------------------------------------------------
@ -996,6 +1033,7 @@ mobs:register_mob("advanced_npc:npc", {
-- Set correct textures
self.texture = {self.selected_texture}
self.base_texture = {self.selected_texture}
self.object:set_properties(self)
-- Set interval to large interval so this code isn't called frequently
npc.texture_check.interval = 60
end
@ -1095,12 +1133,16 @@ mobs:register_mob("advanced_npc:npc", {
npc.log("DEBUG", "Adding actions to action queue")
-- Add to action queue all actions on schedule
for i = 1, #schedule[time] do
if schedule[time][i].action == nil then
--minetest.log("schedule[time]: "..dump(schedule[time]))
if schedule[time][i].task ~= nil then
-- Add task
npc.add_task(self, schedule[time][i].task, schedule[time][i].args)
else
elseif schedule[time][i].action ~= nil then
-- Add action
npc.add_action(self, schedule[time][i].action, schedule[time][i].args)
elseif schedule[time][i].property ~= nil then
-- Change NPC property
npc.schedule_change_property(self, schedule[time][i].property, schedule[time][i].args)
end
end
npc.log("DEBUG", "New action queue: "..dump(self.actions))

View File

@ -114,19 +114,29 @@ local function get_basic_schedule()
action = npc.actions.const.sittable.GET_UP
}
},
-- Change trader status to "trader"
[2] = {property = npc.schedule_properties.trader_status, args = {
status = npc.trade.TRADER
}
},
-- Allow mobs_redo wandering
[2] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
[3] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
},
-- Afternoon actions: go inside the house
-- This will be executed around 6 PM MTG time
late_afternoon_actions = {
-- Change trader status to "none"
[1] = {property = npc.schedule_properties.trader_status, args = {
status = npc.trade.NONE
}
},
-- Get inside home
[1] = {task = npc.actions.cmd.WALK_TO_POS, args = {
[2] = {task = npc.actions.cmd.WALK_TO_POS, args = {
end_pos = npc.places.PLACE_TYPE.OTHER.HOME_INSIDE,
walkable = {}}
},
-- Allow mobs_redo wandering
[2] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
[3] = {action = npc.actions.cmd.FREEZE, args = {freeze = false}}
},
-- Evening actions: walk to bed and use it.
-- This will be executed around 10 PM MTG time
@ -412,17 +422,15 @@ end
-- This function takes care of calculating how many NPCs will be spawn
function spawner.calculate_npc_spawning(pos)
-- Check node
local node = minetest.get_node(pos)
if node.name ~= "advanced_npc:plotmarker_auto_spawner" then
return
end
-- Check node metadata
local meta = minetest.get_meta(pos)
if meta:get_string("replaced") ~= "true" then
return
end
-- Get nodes for this building
local node_data = minetest.deserialize(meta:get_string("node_data"))
if node_data == nil then
npc.log("ERROR", "Mis-configured advanced_npc:plotmarker_auto_spawner at position: "..minetest.pos_to_string(pos))
npc.log("ERROR", "Mis-configured mg_villages:plotmarker at position: "..minetest.pos_to_string(pos))
return
end
-- Check number of beds
@ -527,10 +535,6 @@ end
-- 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)
-- Check if it is already replaced
-- if minetest.get_node(pos).name == "advanced_npc:plotmarker_auto_spawner" then
-- return
-- end
-- Get the meta at the current position
local meta = minetest.get_meta(pos)
local village_id = meta:get_string("village_id")
@ -547,7 +551,7 @@ function spawner.replace_mg_villages_plotmarker(pos)
npc.log("INFO", "Replacing mg_villages:plotmarker at "..minetest.pos_to_string(pos))
-- Replace the plotmarker for auto-spawner
minetest.set_node(pos, {name="advanced_npc:plotmarker_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)
@ -595,9 +599,10 @@ function spawner.replace_mg_villages_plotmarker(pos)
meta:set_string("npc_stats", minetest.serialize(npc_stats))
-- Set replaced
meta:set_string("replaced", "true")
-- Calculate how many NPCs will spawn
spawner.calculate_npc_spawning(pos)
-- Stop searching for building type
break
end
end
end
@ -609,19 +614,19 @@ if minetest.get_modpath("mg_villages") ~= nil then
-- Node registration
-- This node is currently a slightly modified mg_villages:plotmarker
-- TODO: Change formspec to a more detailed one.
minetest.register_node("advanced_npc:plotmarker_auto_spawner", {
description = "Automatic NPC Spawner",
drawtype = "nodebox",
tiles = {"default_stone.png"},
paramtype = "light",
paramtype2 = "facedir",
node_box = {
type = "fixed",
fixed = {
{-0.5+2/16, -0.5, -0.5+2/16, 0.5-2/16, -0.5+2/16, 0.5-2/16},
--{-0.5+0/16, -0.5, -0.5+0/16, 0.5-0/16, -0.5+0/16, 0.5-0/16},
}
},
minetest.override_item("mg_villages:plotmarker", {
-- description = "Automatic NPC Spawner",
-- drawtype = "nodebox",
-- tiles = {"default_stone.png"},
-- paramtype = "light",
-- paramtype2 = "facedir",
-- node_box = {
-- type = "fixed",
-- fixed = {
-- {-0.5+2/16, -0.5, -0.5+2/16, 0.5-2/16, -0.5+2/16, 0.5-2/16},
-- --{-0.5+0/16, -0.5, -0.5+0/16, 0.5-0/16, -0.5+0/16, 0.5-0/16},
-- }
-- },
walkable = false,
groups = {cracky=3,stone=2},
@ -633,7 +638,7 @@ if minetest.get_modpath("mg_villages") ~= nil then
--minetest.log("First-floor beds: "..dump(spawner.filter_first_floor_nodes(nodedata.bed_type, pos)))
--local entrance = npc.places.find_entrance_from_openable_nodes(nodedata.openable_type, pos)
--minetest.log("Found entrance: "..dump(entrance))
minetest.log("Replaced: "..dump(minetest.get_meta(pos):get_string("replaced")))
-- for i = 1, #nodedata.bed_type do
-- nodedata.bed_type[i].owner = ""
-- end
@ -644,22 +649,22 @@ if minetest.get_modpath("mg_villages") ~= nil then
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 );
end,
-- on_receive_fields = function(pos, formname, fields, sender)
-- return mg_villages.plotmarker_formspec( pos, formname, fields, sender );
-- end,
on_timer = function(pos, elapsed)
npc.spawner.spawn_npc(pos)
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
-- 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
})
-- LBM Registration
@ -696,14 +701,14 @@ if minetest.get_modpath("mg_villages") ~= nil then
if npc.spawner.replace_activated then
-- Replace mg_villages:plotmarker
spawner.replace_mg_villages_plotmarker(pos)
-- Set NPCs to spawn
spawner.calculate_npc_spawning(pos)
end
end
})
end
--minetest.register_alias_force("mg_villages:plotmarker", )
-- Chat commands to manage spawners
minetest.register_chatcommand("restore_plotmarkers", {
description = "Replaces all advanced_npc:plotmarker_auto_spawner with mg_villages:plotmarker in the specified radius.",
@ -726,7 +731,7 @@ minetest.register_chatcommand("restore_plotmarkers", {
local start_pos = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius}
local end_pos = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
local nodes = minetest.find_nodes_in_area_under_air(start_pos, end_pos,
{"advanced_npc:plotmarker_auto_spawner"})
{"mg_villages:plotmarker"})
-- Check if we have nodes to replace
minetest.chat_send_player(name, "Found "..dump(#nodes).." nodes to replace...")
if #nodes == 0 then
@ -734,13 +739,10 @@ minetest.register_chatcommand("restore_plotmarkers", {
end
-- Replace all nodes
for i = 1, #nodes do
--minetest.log(dump(nodes[i]))
local meta = minetest.get_meta(nodes[i])
local village_id = meta:get_string("village_id")
local plot_nr = meta:get_int("plot_nr")
local infotext = meta:get_string("infotext")
-- Replace node
minetest.set_node(nodes[i], {name="mg_villages:plotmarker"})
-- Set metadata
meta = minetest.get_meta(nodes[i])
meta:set_string("village_id", village_id)