Actions: Add mine animation to dig/place actions.

Fix bug enabling wandering after dig action.
Improved "random" dir functionality for walk_step to avoid getting NPC stuck.
General formatting fixes.
This commit is contained in:
Hector Franqui 2017-09-12 09:08:44 -04:00
parent ce47958144
commit 70c7a3c96f
1 changed files with 164 additions and 75 deletions

View File

@ -15,6 +15,49 @@ npc.actions = {}
npc.actions.default_interval = 1
npc.actions.dir_data = {
-- North
[0] = {
yaw = 0,
vel = {x=0, y=0, z=1}
},
-- East
[1] = {
yaw = (3 * math.pi) / 2,
vel = {x=1, y=0, z=0}
},
-- South
[2] = {
yaw = math.pi,
vel = {x=0, y=0, z=-1}
},
-- West
[3] = {
yaw = math.pi / 2,
vel = {x=-1, y=0, z=0}
},
-- North east
[4] = {
yaw = (7 * math.pi) / 4,
vel = {x=1, y=0, z=1}
},
-- North west
[5] = {
yaw = math.pi / 4,
vel = {x=-1, y=0, z=1}
},
-- South east
[6] = {
yaw = (5 * math.pi) / 4,
vel = {x=1, y=0, z=-1}
},
-- South west
[7] = {
yaw = (3 * math.pi) / 4,
vel = {x=-1, y=0, z=-1}
}
}
-- Describes actions with doors or openable nodes
npc.actions.const = {
doors = {
@ -170,6 +213,12 @@ function npc.actions.dig(self, args)
local bypass_protection = args.bypass_protection
local node = minetest.get_node_or_nil(pos)
if node then
-- Set mine animation
self.object:set_animation({
x = npc.ANIMATION_MINE_START,
y = npc.ANIMATION_MINE_END},
self.animation.speed_normal, 0)
-- Check if protection not enforced
if not force_dig then
-- Try to dig node
@ -180,7 +229,7 @@ function npc.actions.dig(self, args)
local drop = minetest.registered_nodes[node.name].drop
local drop_itemname = node.name
if drop and drop.items then
local random_item = drop.items[math.random(1, #drop)]
local random_item = drop.items[math.random(1, #drop.items)]
if random_item then
drop_itemname = random_item.items[1]
end
@ -188,7 +237,8 @@ function npc.actions.dig(self, args)
-- Add to NPC inventory
npc.add_item_to_inventory(self, drop_itemname, 1)
end
return true
--return true
return
end
else
-- Add to inventory
@ -202,7 +252,7 @@ function npc.actions.dig(self, args)
minetest.set_node(pos, {name="air"})
end
end
return false
--return false
end
@ -240,16 +290,55 @@ function npc.actions.place(self, args)
end
-- Place node
if place_item == true then
-- Set mine animation
self.object:set_animation({
x = npc.ANIMATION_MINE_START,
y = npc.ANIMATION_MINE_END},
self.animation.speed_normal, 0)
-- Place node
minetest.set_node(pos, {name=node})
end
end
end
end
-- This function allows to move into directions that are walkable. It
-- avoids fences and allows to move on plants.
-- This will make for nice wanderings, making the NPC move smartly instead
-- of just getting stuck at places
local function random_dir_helper(start_pos, speed, dir_start, dir_end)
-- Limit the number of tries - otherwise it could become an infinite loop
for i = 1, 8 do
local dir = math.random(dir_start, dir_end)
local vel = vector.multiply(npc.actions.dir_data[dir].vel, speed)
local pos = vector.add(start_pos, vel)
local node = minetest.get_node(pos)
if node then
if node.name == "air"
-- Any walkable node except fences
or (minetest.registered_nodes[node.name].walkable == true
and minetest.registered_nodes[node.name].groups.fence ~= 1)
-- Farming plants
or minetest.registered_nodes[node.name].groups.plant == 1 then
return dir
end
end
end
-- Return -1 signaling that no good direction could be found
return -1
end
-- This action is to rotate to mob to a specifc direction. Currently, the code
-- contains also for diagonals, but remaining in the orthogonal domain is preferrable.
function npc.actions.rotate(self, args)
local dir = args.dir
local start_pos = args.start_pos
local end_pos = args.end_pos
-- Calculate dir if positions are given
if start_pos and end_pos and not dir then
dir = npc.actions.get_direction(start_pos, end_pos)
end
local yaw = 0
self.rotate = 0
if dir == npc.direction.north then
@ -277,6 +366,7 @@ end
-- true if it can move on that direction, and false if there is an obstacle
function npc.actions.walk_step(self, args)
local dir = args.dir
local step_into_air_only = args.step_into_air_only
local speed = args.speed
local target_pos = args.target_pos
local start_pos = args.start_pos
@ -287,12 +377,12 @@ function npc.actions.walk_step(self, args)
speed = npc.actions.one_nps_speed
end
-- Set is_walking = true
self.actions.walking.is_walking = true
-- Check if dir should be random
if dir == "random" then
dir = math.random(0, 7)
if dir == "random_all" or dir == "random" then
dir = random_dir_helper(start_pos, speed, 0, 7)
end
if dir == "random_orthogonal" then
dir = random_dir_helper(start_pos, speed, 0, 3)
end
if dir == npc.direction.north then
@ -311,17 +401,16 @@ function npc.actions.walk_step(self, args)
vel = {x=-speed, y=0, z=0}
elseif dir == npc.direction.north_west then
vel = {x=-speed, y=0, z=speed }
else
-- No direction provided or NPC is trapped, don't move NPC
vel = {x=0, y=0, z=0}
end
-- Automatically calculate target pos for dir = "random"
if args.dir == "random" and not target_pos and start_pos then
--minetest.log("Vel: "..dump(vel.x/speed)..", "..dump(vel.y/speed)..", "..dump(vel.z/speed))
target_pos = {x=start_pos.x + (vel.x/speed), y=start_pos.y + (vel.y/speed), z=start_pos.z + (vel.z/speed)}
end
-- If there is a target position to reach, set it
-- If there is a target position to reach, set it and set walking to true
if target_pos ~= nil then
self.actions.walking.target_pos = target_pos
-- Set is_walking = true
self.actions.walking.is_walking = true
end
-- Rotate NPC
@ -339,7 +428,7 @@ end
function npc.actions.stand(self, args)
local pos = args.pos
local dir = args.dir
-- Set is_walking = true
-- Set is_walking = false
self.actions.walking.is_walking = false
-- Stop NPC
self.object:setvelocity({x=0, y=0, z=0})
@ -860,7 +949,7 @@ end
-- path.
function npc.actions.walk_to_pos(self, args)
-- Get arguments for this task
local end_pos = get_pos_argument(self, args.end_pos, args.use_access_node)
local end_pos = get_pos_argument(self, args.end_pos, args.use_access_node or true)
if end_pos == nil then
npc.log("WARNING", "Got nil position in 'walk_to_pos' using args.pos: "..dump(args.end_pos))
return