From f4c374314a6de85d691022e2f3f7c4cb88917a5e Mon Sep 17 00:00:00 2001 From: Hector Franqui Date: Fri, 5 May 2017 09:13:30 -0400 Subject: [PATCH] Actions: Enhance walking reliability by adding a moveto() at the end of every step and just before the next step. Increase walking speed constants to more normal values. --- actions/actions.lua | 40 +++++++++++++++++++++++++++++++--------- npc.lua | 31 +++++++++++++++++++++++++------ spawner.lua | 2 +- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/actions/actions.lua b/actions/actions.lua index c4a3a59..db03308 100644 --- a/actions/actions.lua +++ b/actions/actions.lua @@ -2,7 +2,7 @@ --------------------------------------------------------------------------------------- -- Action functionality --------------------------------------------------------------------------------------- --- The NPCs will be able to perform five fundamental actions that will allow +-- The NPCs will be able to perform six fundamental actions that will allow -- for them to perform any other kind of interaction in the world. These -- fundamental actions are: place a node, dig a node, put items on an inventory, -- take items from an inventory, find a node closeby (radius 3) and @@ -35,9 +35,12 @@ npc.actions.const = { } } -npc.actions.one_nps_speed = 0.98 -npc.actions.one_half_nps_speed = 1.40 -npc.actions.two_nps_speed = 1.90 +--npc.actions.one_nps_speed = 0.98 +--npc.actions.one_half_nps_speed = 1.40 +--npc.actions.two_nps_speed = 1.90' +npc.actions.one_nps_speed = 1 +npc.actions.one_half_nps_speed = 1.5 +npc.actions.two_nps_speed = 2 --------------------------------------------------------------------------------------- -- Actions @@ -96,11 +99,20 @@ end function npc.actions.walk_step(self, args) local dir = args.dir local speed = args.speed + local target_pos = args.target_pos local vel = {} -- Set default node per seconds if speed == nil then speed = npc.actions.one_nps_speed end + -- If there is a target position to reach, set it + if target_pos ~= nil then + self.actions.walking.target_pos = target_pos + end + + -- Set is_walking = true + self.actions.walking.is_walking = true + if dir == npc.direction.north then vel = {x=0, y=0, z=speed} elseif dir == npc.direction.east then @@ -125,6 +137,8 @@ end function npc.actions.stand(self, args) local pos = args.pos local dir = args.dir + -- Set is_walking = true + self.actions.walking.is_walking = false -- Stop NPC self.object:setvelocity({x=0, y=0, z=0}) -- If position given, set to that position @@ -422,7 +436,7 @@ function npc.actions.use_furnace(self, args) count = npc.get_item_count(item), is_furnace = false } - minetest.log("Taking item back: "..dump(pos)) + minetest.log("Taking item back: "..minetest.pos_to_string(pos)) npc.add_action(self, npc.actions.take_item_from_external_inventory, args) minetest.log("Inventory: "..dump(self.inventory)) @@ -496,8 +510,10 @@ function npc.actions.use_sittable(self, args) local node = minetest.get_node(pos) if action == npc.actions.const.sittable.SIT then + -- minetest.log("On sittable: Node: "..dump(node)) + -- minetest.log("On sittable: Sittable stuff: "..dump(npc.actions.nodes.sittable[node.name])) + -- minetest.log("On sittable: HAHA: "..dump(node)) -- Calculate position depending on bench - minetest.log("Got sit position: "..dump(sit_pos)) local sit_pos = npc.actions.nodes.sittable[node.name].get_sit_pos(pos, node.param2) -- Sit down on bench/chair/stairs npc.add_action(self, npc.actions.sit, {pos=sit_pos, dir=(node.param2 + 2) % 4}) @@ -561,7 +577,9 @@ function npc.actions.walk_to_pos(self, args) local path = pathfinder.find_path(start_pos, end_pos, 20, walkable_nodes) if path ~= nil then - minetest.log("Found path to node: "..dump(end_pos)) + minetest.log("[advanced_npc] Found path to node: "..minetest.pos_to_string(end_pos)) + -- Store path + self.actions.walking.path = path -- Local variables local door_opened = false @@ -571,6 +589,9 @@ function npc.actions.walk_to_pos(self, args) -- the increased speed when walking. npc.add_action(self, npc.actions.set_interval, {interval=0.5, freeze=true}) + -- Set the initial last and target positions + self.actions.walking.target_pos = path[1].pos + -- Add steps to path for i = 1, #path do -- Do not add an extra step if reached the goal node @@ -578,7 +599,7 @@ function npc.actions.walk_to_pos(self, args) -- Add direction to last node local dir = npc.actions.get_direction(path[i].pos, end_pos) -- Add stand animation at end - npc.add_action(self, npc.actions.stand, { dir = dir}) + npc.add_action(self, npc.actions.stand, {dir = dir}) break end -- Get direction to move from path[i] to path[i+1] @@ -597,8 +618,9 @@ function npc.actions.walk_to_pos(self, args) door_opened = true end end + -- Add walk action to action queue - npc.add_action(self, npc.actions.walk_step, {dir = dir, speed = speed}) + npc.add_action(self, npc.actions.walk_step, {dir = dir, speed = speed, target_pos = path[i+1].pos}) if door_opened then -- Stop to close door, this avoids misplaced movements later on diff --git a/npc.lua b/npc.lua index 87e01b9..ff975ae 100755 --- a/npc.lua +++ b/npc.lua @@ -240,7 +240,18 @@ function npc.initialize(entity, pos, is_lua_entity) action_state = npc.action_state.none, -- Action executed while on lock interrupted_action = {} - } + }, + -- Walking variables -- required for implementing accurate movement code + walking = { + -- Defines whether NPC is walking to specific position or not + is_walking = false, + -- Path that the NPC is following + path = {}, + -- Target position the NPC is supposed to walk to in this step. NOTE: + -- This is NOT the end of the path, but the next position in the path + -- relative to the last position + target_pos = {} + } } -- This flag is checked on every step. If it is true, the rest of @@ -270,8 +281,7 @@ function npc.initialize(entity, pos, is_lua_entity) -- Temporary initialization of actions for testing local nodes = npc.places.find_node_nearby(ent.object:getpos(), {"cottages:bench"}, 20) - - minetest.log("Self destination: "..minetest.pos_to_string(nodes[1])) + --minetest.log("Self destination: "..minetest.pos_to_string(nodes[1])) --local path = pathfinder.find_path(ent.object:getpos(), nodes[1], 20, {}) --minetest.log("Path to node: "..dump(path)) @@ -288,7 +298,7 @@ function npc.initialize(entity, pos, is_lua_entity) -- --npc.actions.use_sittable(ent, nodes[1], npc.actions.const.sittable.GET_UP) -- --npc.add_action(ent, npc.actions.set_interval, {self=ent, interval=10, freeze=true}) -- npc.add_action(ent, npc.actions.freeze, {freeze = false}) - -- end + --end -- Dedicated trade test ent.trader_data.trade_list.both = { @@ -324,7 +334,8 @@ function npc.initialize(entity, pos, is_lua_entity) [3] = {action = npc.actions.freeze, args = {freeze = true}} } 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} } } npc.add_schedule_entry(ent, npc.schedule_types.generic, 0, 9, nil, afternoon_actions) -- local night_actions = {action: npc.action, args: {}} -- npc.add_schedule_entry(self, npc.schedule_type.generic, 0, 19, check, actions) @@ -535,10 +546,13 @@ function npc.execute_action(self) return self.freeze end local action_obj = self.actions.queue[1] + if action_obj.action == nil then + return + end -- If the entry is a task, then push all this new operations in -- stack fashion if action_obj.is_task == true then - minetest.log("Executing task") + minetest.log("Executing task: "..dump(action_obj)) -- Backup current queue local backup_queue = self.actions.queue -- Remove this "task" action from queue @@ -918,6 +932,11 @@ mobs:register_mob("advanced_npc:npc", { if self.actions.action_timer >= self.actions.action_interval then -- Reset action timer self.actions.action_timer = 0 + -- Check if NPC is walking + if self.actions.walking.is_walking == true then + local pos = self.actions.walking.target_pos + self.object:moveto({x=pos.x, y=pos.y + 1, z=pos.z}) + end -- Execute action self.freeze = npc.execute_action(self) -- Check if there are still remaining actions in the queue diff --git a/spawner.lua b/spawner.lua index 0010e9a..372ed30 100644 --- a/spawner.lua +++ b/spawner.lua @@ -141,7 +141,7 @@ function npc.spawner.spawn_npc(pos) if spawned_npc_count < npc_count then minetest.log("[advanced_npc] Spawning NPC at "..minetest.pos_to_string(pos)) -- Spawn a NPC - local ent = minetest.add_entity(pos, "advanced_npc:npc") + local ent = minetest.add_entity({x=pos.x, y=pos.y+1, z=pos.z}, "advanced_npc:npc") if ent and ent:get_luaentity() then ent:get_luaentity().initialized = false npc.initialize(ent, pos)