split out animal step fn

improvements to rat
master
Izzy 2019-06-06 22:56:26 -06:00
parent df48ed3aab
commit a7838485dc
3 changed files with 337 additions and 124 deletions

View File

@ -1,12 +1,331 @@
set_velocity2 = function(self, v, up)
local x = 0
local z = 0
if v and v ~= 0 then
local yaw = (self.object:getyaw() + self.rotate) or 0
x = math.sin(yaw) * -v
z = math.cos(yaw) * v
end
local y
if up then
y = up
else
y = self.object:getvelocity().y
end
self.object:setvelocity({
x = x,
y = y,
z = z
})
end
local function animal_step(self, dtime)
local btdata = self.btData
-- print('newstep')
local pos = self.object:getpos()
local yaw = self.object:getyaw() or 0
self.bt_timer = self.bt_timer + dtime
-- run the behavior tree every two seconds
if self.bt_timer > 2 then
btdata.pos = pos
btdata.yaw = yaw
btdata.mob = self
print("\n<<< start >>> ("..math.floor(pos.x)..","..math.floor(pos.z)..")")
-- inventories cannot be serialized and cause the game to crash if
-- placed in the entity's table
local inv = minetest.get_inventory({type="detached", name=self.inv_id})
btdata.inv = inv
bt.tick(self.bt, btdata)
print("<<< end >>>\n")
-- so clear it out after running the behavior trees
btdata.inv = nil
-- the inventory exists on its own
self.bt_timer = 0
end
local rpos = vector.round(pos)
if not vector.equals(self.last_rpos, rpos) then
local below = minetest.get_node({x=rpos.x, y=rpos.y-2, z=rpos.z})
self.node_below = below.name
print("below: ".. self.node_below)
self.last_rpos = rpos
end
-- handle movement
local v = self.object:getvelocity()
-- TODO: floating
if minetest.registered_nodes[self.node_below].climbable then
self.object:setacceleration({
x = 0,
y = 0,
z = 0
})
else
self.object:setacceleration({
x = 0,
y = self.fall_speed,
z = 0
})
end
-- TODO: fall damage
self.jump_timer = self.jump_timer + dtime
if self.destination ~= nil then
self.walk_timer = self.walk_timer + dtime
--print("destination ")
local tdist = distance3(pos, btdata.lastpos)
local dist2 = distance(pos, self.destination)
-- print("walk dist ".. dist)
local s = self.destination
local vec = {
x = pos.x - s.x,
y = pos.y - s.y,
z = pos.z - s.z
}
if tdist < self.walk_velocity * dtime * .9 and self.walk_timer > 1 then
if self.jump_timer > 4 then
local v = self.object:getvelocity()
v.y = self.jump_height + 1
v.x = v.x * 2.2
v.z = v.z * 2.2
self.object:setvelocity(v)
self.jump_timer = 0
end
end
yaw = (math.atan2(vec.z, vec.x) + math.pi / 2) - self.rotate
self.object:setyaw(yaw)
if dist2 < (self.approachDistance or .1) then
-- we have arrived
self.destination = nil
self.walk_timer = 0
-- TODO: make sure this doesn't lead to infinite loops
-- bump bttimer to get new directions
self.bt_timer = 99
set_velocity(self, 0)
set_animation(self, "stand")
else
-- TODO look at dy/dxz and see if we need to try to go up
if dist2 < (self.approachDistance or .1) then
set_velocity(self, 0, self.walk_velocity)
else
set_velocity(self, self.walk_velocity)
set_animation(self, "walk")
end
end
end
btdata.lastpos = pos
end
local function npc_step(self, dtime)
local btdata = self.btData
-- print('newstep')
local pos = self.object:getpos()
local yaw = self.object:getyaw() or 0
self.bt_timer = self.bt_timer + dtime
-- run the behavior tree every two seconds
if self.bt_timer > 2 then
btdata.pos = pos
btdata.yaw = yaw
btdata.mob = self
print("\n<<< start >>> ("..math.floor(pos.x)..","..math.floor(pos.z)..")")
-- inventories cannot be serialized and cause the game to crash if
-- placed in the entity's table
local inv = minetest.get_inventory({type="detached", name=self.inv_id})
btdata.inv = inv
bt.tick(self.bt, btdata)
print("<<< end >>>\n")
-- so clear it out after running the behavior trees
btdata.inv = nil
-- the inventory exists on its own
self.bt_timer = 0
end
local rpos = vector.round(pos)
if not vector.equals(self.last_rpos, rpos) then
local below = minetest.get_node({x=rpos.x, y=rpos.y-2, z=rpos.z})
self.node_below = below.name
print("below: ".. self.node_below)
self.last_rpos = rpos
end
-- handle movement
local v = self.object:getvelocity()
-- TODO: floating
if minetest.registered_nodes[self.node_below].climbable then
self.object:setacceleration({
x = 0,
y = 0,
z = 0
})
else
self.object:setacceleration({
x = 0,
y = self.fall_speed,
z = 0
})
end
-- TODO: fall damage
self.jump_timer = self.jump_timer + dtime
if self.destination ~= nil then
self.walk_timer = self.walk_timer + dtime
--print("destination ")
local tdist = distance3(pos, btdata.lastpos)
local dist2 = distance(pos, self.destination)
local dist3 = distance3(pos, self.destination)
-- print("walk dist ".. dist)
local s = self.destination
local vec = {
x = pos.x - s.x,
y = pos.y - s.y,
z = pos.z - s.z
}
if tdist < self.walk_velocity * dtime * .9 and self.walk_timer > 1 then
-- try to go up first
local n = minetest.get_node(pos)
if minetest.registered_nodes[n.name].climbable then
set_velocity(self, 0, self.walkvelocity)
elseif self.jump_timer > 4 then
local v = self.object:getvelocity()
v.y = self.jump_height + 1
v.x = v.x * 2.2
v.z = v.z * 2.2
self.object:setvelocity(v)
self.jump_timer = 0
end
end
yaw = (math.atan2(vec.z, vec.x) + math.pi / 2) - self.rotate
self.object:setyaw(yaw)
if dist3 < (self.approachDistance or .1) then
-- we have arrived
self.destination = nil
self.walk_timer = 0
-- TODO: make sure this doesn't lead to infinite loops
-- bump bttimer to get new directions
self.bt_timer = 99
set_velocity(self, 0)
set_animation(self, "stand")
else
-- TODO look at dy/dxz and see if we need to try to go up
if dist2 < (self.approachDistance or .1) then
set_velocity(self, 0, self.walk_velocity)
else
set_velocity(self, self.walk_velocity)
set_animation(self, "walk")
end
end
end
btdata.lastpos = pos
end
function mobehavior:register_mob_fast(name, def)
local step
if def.climbs_ladders then
step = npc_step
else
step = animal_step
end
local mdef = {
hp_max = 1,
@ -32,123 +351,14 @@ function mobehavior:register_mob_fast(name, def)
bt_timer = 0,
bt = nil,
btData = nil,
last_rpos = {x=99999999, y=9999999999, z=99999999},
node_below = "air",
jump_timer = 0,
walk_timer = 0,
on_step = function(self, dtime)
local btdata = self.btData
-- print('newstep')
local pos = self.object:getpos()
local yaw = self.object:getyaw() or 0
self.bt_timer = self.bt_timer + dtime
-- run the behavior tree every two seconds
if self.bt_timer > 2 then
btdata.pos = pos
btdata.yaw = yaw
btdata.mob = self
print("\n<<< start >>> ("..math.floor(pos.x)..","..math.floor(pos.z)..")")
-- inventories cannot be serialized and cause the game to crash if
-- placed in the entity's table
local inv = minetest.get_inventory({type="detached", name=self.inv_id})
btdata.inv = inv
bt.tick(self.bt, btdata)
print("<<< end >>>\n")
-- so clear it out after running the behavior trees
btdata.inv = nil
-- the inventory exists on its own
self.bt_timer = 0
end
-- handle movement
local v = self.object:getvelocity()
-- TODO: floating
-- going up then apply gravity
-- if v.y > 0.1 then
self.object:setacceleration({
x = 0,
y = self.fall_speed,
z = 0
})
-- end
-- TODO: fall damage
self.jump_timer = self.jump_timer + dtime
if self.destination ~= nil then
self.walk_timer = self.walk_timer + dtime
--print("destination ")
local tdist = distance(pos, btdata.lastpos)
local dist = distance(pos, self.destination)
-- print("walk dist ".. dist)
local s = self.destination
local vec = {
x = pos.x - s.x,
y = pos.y - s.y,
z = pos.z - s.z
}
if tdist < self.walk_velocity * dtime * .9 and self.walk_timer > 1 then
if self.jump_timer > 4 then
local v = self.object:getvelocity()
v.y = self.jump_height + 1
v.x = v.x * 2.2
v.z = v.z * 2.2
self.object:setvelocity(v)
self.jump_timer = 0
end
end
yaw = (math.atan2(vec.z, vec.x) + math.pi / 2) - self.rotate
self.object:setyaw(yaw)
if dist > (self.approachDistance or .1) then
set_velocity(self, self.walk_velocity)
set_animation(self, "walk")
else
-- we have arrived
self.destination = nil
self.walk_timer = 0
-- TODO: make sure this doesn't lead to infinite loops
-- bump bttimer to get new directions
self.bt_timer = 99
set_velocity(self, 0)
set_animation(self, "stand")
end
end
btdata.lastpos = pos
end,
on_step = step,
on_activate = function(self, staticdata, dtime_s)
self.btData = {
@ -171,6 +381,7 @@ function mobehavior:register_mob_fast(name, def)
--print(btdata.id)
btdata.lastpos = self.object:getpos()
btdata.last_rpos = vector.round(self.object:getpos())
if type(def.pre_activate) == "function" then
def.pre_activate(self, static_data, dtime_s)

View File

@ -251,6 +251,7 @@ function make_rat(name, behavior_fn)
mobehavior:register_mob_fast(mn..":"..name, {
type = "animal",
climbs_ladders = false,
passive = true,
reach = 1,
hp_min = 1,
@ -394,6 +395,7 @@ function make_NPC(name, behavior_fn)
-- mobs:register_simple_mob(mn..":"..name, {
mobehavior:register_mob_fast(mn..":"..name, {
type = "monster",
climbs_ladders = true,
passive = false,
attack_type = "dogfight",
reach = 2,

View File

@ -264,22 +264,22 @@ local rat_root = function()
"group:rice",
}
return bt.Sequence("rat", {
return bt.Selector("rat", {
raid_chest(20, 1),
seek_and_destroy(20, 12, {"doors:door_wood_a","doors:door_wood_b", "doors:trapdoor_a", "doors:trapdoor_b"}),
seek_and_destroy(20, 18, {"doors:door_glass_a","doors:door_glass_b"}),
seek_food(6, food),
bt.Random({
wander_around(2),
wander_around(2),
wander_around(4),
wander_around(6),
-- wander_around(8),
bt.WaitTicks(1),
}),
-- wander_around(8),
-- bt.WaitTicks(1),
bt.WaitTicks(2),
-- bt.WaitTicks(2),
seek_food(6, food),
raid_chest(20, 1),
seek_and_destroy(20, 12, {"doors:door_wood_a","doors:door_wood_b", "doors:trapdoor_a", "doors:trapdoor_b"}),
seek_and_destroy(20, 18, {"doors:door_glass_a","doors:door_glass_b"}),
-- breeding
})
-- bt.WaitTicks(2),
-- breeding
})
end