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:
parent
ce47958144
commit
70c7a3c96f
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user