Actions: Rewrite API to use executor function + constants of commands.

Re-write NPC add action/task functions, do_custom() to use new actions API.
Spawner: Find building entrances (WIP)
Places: Fix numerous bugs with add/get places functions.
Actions: Fix bugs with sittable task.
This commit is contained in:
Hector Franqui 2017-05-13 13:17:45 -04:00
parent 9b3d458872
commit 1d1a56592b
5 changed files with 628 additions and 524 deletions

File diff suppressed because it is too large Load Diff

View File

@ -53,22 +53,23 @@ npc.places.nodes = {
npc.places.PLACE_TYPE = { npc.places.PLACE_TYPE = {
BED = { BED = {
"PRIMARY" PRIMARY = "primary"
}, },
SITTABLE = { SITTABLE = {
"PRIMARY" PRIMARY = "primary"
}, },
OPENABLE = { OPENABLE = {
"HOME_ENTRANCE_DOOR" HOME_ENTRANCE_DOOR = "home_entrance_door"
}, },
OTHER = { OTHER = {
"HOME_INSIDE", HOME_INSIDE = "home_inside",
"HOME_OUTSIDE" HOME_OUTSIDE = "home_outside"
} }
} }
function npc.places.add_public(self, place_name, place_type, pos) function npc.places.add_public(self, place_name, place_type, pos)
self.places_map[place_name] = {type=place_type, pos=pos} --minetest.log("Place name: "..dump(place_name)..", type: "..dump(place_type))
self.places_map[place_name] = {type=place_type, pos=pos, status="shared"}
end end
-- Adds a specific node to the NPC places, and modifies the -- Adds a specific node to the NPC places, and modifies the
@ -92,7 +93,7 @@ function npc.places.get_by_type(self, place_type)
local result = {} local result = {}
for place_name, place_entry in pairs(self.places_map) do for place_name, place_entry in pairs(self.places_map) do
if place_entry.type == place_type then if place_entry.type == place_type then
table.insert(result, place_name) table.insert(result, place_entry)
end end
end end
return result return result

22
npc.lua
View File

@ -329,13 +329,13 @@ function npc.initialize(entity, pos, is_lua_entity)
npc.create_schedule(ent, npc.schedule_types.generic, 0) npc.create_schedule(ent, npc.schedule_types.generic, 0)
-- Add schedule entries -- Add schedule entries
local morning_actions = { local morning_actions = {
[1] = {task = npc.actions.walk_to_pos, args = {end_pos=nodes[1], walkable={}} } , [1] = {task = npc.actions.cmd.WALK_TO_POS, args = {end_pos=nodes[1], walkable={}} } ,
[2] = {task = npc.actions.use_sittable, args = {pos=nodes[1], action=npc.actions.const.sittable.SIT} }, [2] = {task = npc.actions.cmd.USE_SITTABLE, args = {pos=nodes[1], action=npc.actions.const.sittable.SIT} },
[3] = {action = npc.actions.freeze, args = {freeze = true}} [3] = {action = npc.actions.cmd.FREEZE, args = {freeze = true}}
} }
npc.add_schedule_entry(ent, npc.schedule_types.generic, 0, 7, nil, morning_actions) npc.add_schedule_entry(ent, npc.schedule_types.generic, 0, 7, nil, morning_actions)
--local afternoon_actions = { [1] = {action = npc.actions.stand, args = {}} } --local afternoon_actions = { [1] = {action = npc.actions.stand, args = {}} }
local afternoon_actions = {[1] = {task = npc.actions.use_sittable, args = {pos=nodes[1], action=npc.actions.const.sittable.GET_UP} } } local afternoon_actions = {[1] = {task = npc.actions.cmd.USE_SITTABLE, args = {pos=nodes[1], action=npc.actions.const.sittable.GET_UP} } }
npc.add_schedule_entry(ent, npc.schedule_types.generic, 0, 9, nil, afternoon_actions) npc.add_schedule_entry(ent, npc.schedule_types.generic, 0, 9, nil, afternoon_actions)
-- local night_actions = {action: npc.action, args: {}} -- local night_actions = {action: npc.action, args: {}}
-- npc.add_schedule_entry(self, npc.schedule_type.generic, 0, 19, check, actions) -- npc.add_schedule_entry(self, npc.schedule_type.generic, 0, 19, check, actions)
@ -530,7 +530,7 @@ end
function npc.execute_action(self) function npc.execute_action(self)
-- Check if an action was interrupted -- Check if an action was interrupted
if self.actions.current_action_state == npc.action_state.interrupted then if self.actions.current_action_state == npc.action_state.interrupted then
minetest.log("Inserting interrupted action: ") minetest.log("[advanced_npc] DEBUG Re-inserting interrupted action for NPC: '"..dump(self.nametag).."': "..dump(self.actions.state_before_lock.interrupted_action))
-- Insert into queue the interrupted action -- Insert into queue the interrupted action
table.insert(self.actions.queue, 1, self.actions.state_before_lock.interrupted_action) table.insert(self.actions.queue, 1, self.actions.state_before_lock.interrupted_action)
-- Clear the action -- Clear the action
@ -552,7 +552,7 @@ function npc.execute_action(self)
-- If the entry is a task, then push all this new operations in -- If the entry is a task, then push all this new operations in
-- stack fashion -- stack fashion
if action_obj.is_task == true then if action_obj.is_task == true then
minetest.log("Executing task: "..dump(action_obj)) minetest.log("[advanced_npc] DEBUG Executing task for NPC '"..dump(self.nametag).."': "..dump(action_obj))
-- Backup current queue -- Backup current queue
local backup_queue = self.actions.queue local backup_queue = self.actions.queue
-- Remove this "task" action from queue -- Remove this "task" action from queue
@ -560,20 +560,22 @@ function npc.execute_action(self)
-- Clear queue -- Clear queue
self.actions.queue = {} self.actions.queue = {}
-- Now, execute the task with its arguments -- Now, execute the task with its arguments
action_obj.action(self, action_obj.args) result = npc.actions.execute(self, action_obj.action, action_obj.args)
--result = action_obj.action(self, action_obj.args)
-- After all new actions has been added by task, add the previously -- After all new actions has been added by task, add the previously
-- queued actions back -- queued actions back
for i = 1, #backup_queue do for i = 1, #backup_queue do
table.insert(self.actions.queue, backup_queue[i]) table.insert(self.actions.queue, backup_queue[i])
end end
else else
minetest.log("Executing action") minetest.log("[advanced_npc] DEBUG Executing action for NPC '"..dump(self.nametag).."': "..dump(action_obj))
-- Store the action that is being executed -- Store the action that is being executed
self.actions.state_before_lock.interrupted_action = action_obj self.actions.state_before_lock.interrupted_action = action_obj
-- Store current position -- Store current position
self.actions.state_before_lock.pos = self.object:getpos() self.actions.state_before_lock.pos = self.object:getpos()
-- Execute action as normal -- Execute action as normal
result = action_obj.action(self, action_obj.args) result = npc.actions.execute(self, action_obj.action, action_obj.args)
--result = action_obj.action(self, action_obj.args)
-- Remove task -- Remove task
table.remove(self.actions.queue, 1) table.remove(self.actions.queue, 1)
-- Set state -- Set state
@ -603,7 +605,7 @@ function npc.lock_actions(self)
pos.y = self.object:getpos().y pos.y = self.object:getpos().y
end end
-- Stop NPC -- Stop NPC
npc.actions.stand(self, {pos=pos}) npc.actions.execute(self, npc.actions.cmd.STAND, {pos=pos})
-- Avoid all timer execution -- Avoid all timer execution
self.actions.action_timer_lock = true self.actions.action_timer_lock = true
-- Reset timer so that it has some time after interaction is done -- Reset timer so that it has some time after interaction is done

View File

@ -75,7 +75,7 @@ npc.data.DIALOGUES.female["phase1"] = {
item_name=npc.trade.prices.currency.tier3.string, item_name=npc.trade.prices.currency.tier3.string,
count=3 count=3
} }
npc.actions.take_item_from_external_inventory(self, { npc.actions.execute(self, npc.actions.cmd.TAKE_ITEM, {
player=player:get_player_name(), player=player:get_player_name(),
pos=nil, pos=nil,
inv_list="main", inv_list="main",

View File

@ -129,6 +129,36 @@ end
-- - Else, just let the NPC know one of the benches, but not own them -- - Else, just let the NPC know one of the benches, but not own them
-- - Let the NPC know all doors to the house. Identify the front one as the entrance -- - Let the NPC know all doors to the house. Identify the front one as the entrance
function spawner.assign_places(self, pos) function spawner.assign_places(self, pos)
local meta = minetest.get_meta(pos)
local doors = minetest.deserialize(meta:get_string("node_data")).openable_type
minetest.log("Found "..dump(#doors).." openable nodes")
local entrance = npc.places.find_entrance_from_openable_nodes(doors, pos)
if entrance then
minetest.log("Found building entrance at: "..minetest.pos_to_string(entrance.node_pos))
else
minetest.log("Unable to find building entrance!")
end
-- Assign entrance door and related locations
if entrance ~= nil and entrance.node_pos ~= nil then
--minetest.log("Self: "..dump(self))
--minetest.log("Places map: "..dump(self.places_map))
npc.places.add_public(self, npc.places.PLACE_TYPE.OPENABLE.HOME_ENTRANCE_DOOR, npc.places.PLACE_TYPE.OPENABLE.HOME_ENTRANCE_DOOR, entrance.node_pos)
-- Find the position inside and outside the door
local entrance_inside = npc.places.find_node_behind_door(entrance.node_pos)
local entrance_outside = npc.places.find_node_in_front_of_door(entrance.node_pos)
-- Assign these places to NPC
npc.places.add_public(self, npc.places.PLACE_TYPE.OTHER.HOME_INSIDE, npc.places.PLACE_TYPE.OTHER.HOME_INSIDE, entrance_inside)
npc.places.add_public(self, npc.places.PLACE_TYPE.OTHER.HOME_OUTSIDE, npc.places.PLACE_TYPE.OTHER.HOME_OUTSIDE, entrance_outside)
-- Make NPC go into their house
--minetest.log("Place: "..dump(npc.places.get_by_type(self, npc.places.PLACE_TYPE.OTHER.HOME_INSIDE)))
npc.add_task(self, npc.actions.cmd.WALK_TO_POS, {end_pos=npc.places.get_by_type(self, npc.places.PLACE_TYPE.OTHER.HOME_INSIDE)[1].pos, walkable={}})
end
local plot_info = minetest.deserialize(meta:get_string("plot_info"))
minetest.log("Plot info:"..dump(plot_info))
end end
@ -151,7 +181,7 @@ function npc.spawner.spawn_npc(pos)
ent:get_luaentity().initialized = false ent:get_luaentity().initialized = false
npc.initialize(ent, pos) npc.initialize(ent, pos)
-- Assign nodes -- Assign nodes
spawner.assign_places(ent, pos) spawner.assign_places(ent:get_luaentity(), pos)
-- Increase NPC spawned count -- Increase NPC spawned count
spawned_npc_count = spawned_npc_count + 1 spawned_npc_count = spawned_npc_count + 1
-- Store count into node -- Store count into node
@ -351,19 +381,6 @@ if minetest.get_modpath("mg_villages") ~= nil then
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
-- Get all openable-type nodes for this building -- Get all openable-type nodes for this building
-- NOTE: This is temporary code for testing... -- NOTE: This is temporary code for testing...
local meta = minetest.get_meta(pos)
local doors = minetest.deserialize(meta:get_string("node_data")).openable_type
minetest.log("Found "..dump(#doors).." openable nodes")
local entrance = npc.places.find_entrance_from_openable_nodes(doors, pos)
if entrance then
minetest.log("Found building entrance at: "..minetest.pos_to_string(entrance.node_pos))
else
minetest.log("Unable to find building entrance!")
end
local plot_info = minetest.deserialize(meta:get_string("plot_info"))
minetest.log("Plot info:"..dump(plot_info))
return mg_villages.plotmarker_formspec( pos, nil, {}, clicker ) return mg_villages.plotmarker_formspec( pos, nil, {}, clicker )
end, end,