Movement and path finding improvements.

This commit is contained in:
kno10 2024-07-15 02:31:21 +02:00
parent 77c6c34d0e
commit e4deb9c7b5
3 changed files with 72 additions and 72 deletions

@ -392,6 +392,7 @@ function mob_class:do_jump()
end end
local pos = self.object:get_pos() local pos = self.object:get_pos()
local v = self.object:get_velocity()
local cbox = self.collisionbox local cbox = self.collisionbox
local in_water = minetest.get_item_group(node_ok(pos).name, "water") > 0 local in_water = minetest.get_item_group(node_ok(pos).name, "water") > 0
@ -406,15 +407,15 @@ function mob_class:do_jump()
local yaw = self.object:get_yaw() local yaw = self.object:get_yaw()
-- where is front -- where is front
local dir_x = -sin(yaw) * (cbox[4] + 0.5) local dir_x = -sin(yaw) * (cbox[4] + 0.5) + v.x * 0.25
local dir_z = cos(yaw) * (cbox[4] + 0.5) local dir_z = cos(yaw) * (cbox[4] + 0.5) + v.z * 0.25
-- what is in front of mob? -- what is in front of mob?
local nod = node_ok({ x = pos.x + dir_x, y = pos.y + 0.5, z = pos.z + dir_z }) local nod = node_ok(vector.new(pos.x + dir_x, pos.y + 0.5, pos.z + dir_z))
-- this is used to detect if there's a block on top of the block in front of the mob. -- this is used to detect if there's a block on top of the block in front of the mob.
-- If there is, there is no point in jumping as we won't manage. -- If there is, there is no point in jumping as we won't manage.
local nodTop = node_ok({ x = pos.x + dir_x, y = pos.y + 1.5, z = pos.z + dir_z }, "air") local nodTop = node_ok(vector.new(pos.x + dir_x, pos.y + 1.5, pos.z + dir_z), "air")
-- TODO: also check above the mob itself? -- TODO: also check above the mob itself?
-- we don't attempt to jump if there's a stack of blocks blocking, unless attacking -- we don't attempt to jump if there's a stack of blocks blocking, unless attacking
@ -428,57 +429,55 @@ function mob_class:do_jump()
end end
local ndef = minetest.registered_nodes[nod.name] local ndef = minetest.registered_nodes[nod.name]
if self.walk_chance == 0 or ndef and ndef.walkable or self._can_jump_cliff then if self.walk_chance ~= 0 and not (ndef and ndef.walkable) and not self._can_jump_cliff then
return false
if minetest.get_item_group(nod.name, "fence") == 0
and minetest.get_item_group(nod.name, "fence_gate") == 0
and minetest.get_item_group(nod.name, "wall") == 0 then
local v = self.object:get_velocity()
v.y = self.jump_height + 0.1 * 3
if in_water then
v=vector.multiply(v, vector.new(1.2,1.5,1.2))
elseif self._can_jump_cliff then
v=vector.multiply(v, vector.new(2.5,1.1,2.5))
end
self:set_animation( "jump") -- only when defined
self.object:set_velocity(v)
-- when in air move forward
minetest.after(0.3, function(self, v)
if (not self.object) or (not self.object:get_luaentity()) or (self.state == "die") then
return
end
self.object:set_acceleration({
x = v.x * 2,
y = DEFAULT_FALL_SPEED,
z = v.z * 2,
})
end, self, v)
if self.jump_sound_cooloff <= 0 then
self:mob_sound("jump")
self.jump_sound_cooloff = 0.5
end
else
self.facing_fence = true
end
-- if we jumped against a block/wall 4 times then turn
if self.object:get_velocity().x ~= 0 and self.object:get_velocity().z ~= 0 then
self.jump_count = (self.jump_count or 0) + 1
if self.jump_count == 4 then
self:turn_by(PI * (random() - 0.5), 8)
self.jump_count = 0
end
end
return true
end end
return false if minetest.get_item_group(nod.name, "fence") ~= 0
or minetest.get_item_group(nod.name, "fence_gate") ~= 0
or minetest.get_item_group(nod.name, "wall") ~= 0 then
self.facing_fence = true
return false
end
v.y = self.jump_height + 0.3
if in_water then
v=vector.multiply(v, vector.new(1.2,1.5,1.2))
elseif self._can_jump_cliff then
v=vector.multiply(v, vector.new(2.5,1.1,2.5))
end
self:set_animation("jump") -- only when defined
self.object:set_velocity(v)
-- when in air move forward
local forward = function(self, v)
if not self.object or not self.object:get_luaentity() or self.state == "die" then
return
end
self.object:set_acceleration(vector.new(v.x * 2, DEFAULT_FALL_SPEED, v.z * 2))
end
-- trying multiple time helps mobs jump
minetest.after(0.1, forward, self, v)
minetest.after(0.2, forward, self, v)
minetest.after(0.3, forward, self, v)
if self.jump_sound_cooloff <= 0 then
self:mob_sound("jump")
self.jump_sound_cooloff = 0.5
end
-- if we jumped against a block/wall 4 times then turn
if (v.x * v.x + v.z * v.z) < 0.1 then
self._jump_count = (self._jump_count or 0) + 1
if self._jump_count == 4 then
self:turn_by(TWOPI * (random() - 0.5), 8)
self._jump_count = 0
return false
end
else
self._jump_count = 0
end
return true
end end
-- should mob follow what I'm holding ? -- should mob follow what I'm holding ?
@ -753,15 +752,10 @@ end
function mob_class:go_to_pos(b) function mob_class:go_to_pos(b)
if not self then return end if not self then return end
local s=self.object:get_pos() if not b then return end
if not b then local s = self.object:get_pos()
--self.state = "stand" if vector.distance(b,s) < 1 then return true end
return end self:turn_in_direction(b.x - s.x, b.z - s.z, 4)
if vector.distance(b,s) < 1 then
--self:set_velocity(0)
return true
end
self:turn_in_direction(b.x - s.x, b.z - s.z, 6)
self:set_velocity(self.follow_velocity) self:set_velocity(self.follow_velocity)
self:set_animation("walk") self:set_animation("walk")
end end

@ -358,8 +358,8 @@ function mob_class:check_gowp(dtime)
self.current_target = nil self.current_target = nil
self.state = "stand" self.state = "stand"
self.order = "stand" self.order = "stand"
self.object:set_velocity({x = 0, y = 0, z = 0}) self.object:set_velocity(vector.zero())
self.object:set_acceleration({x = 0, y = 0, z = 0}) self.object:set_acceleration(vector.zero())
if self.callback_arrived then return self.callback_arrived(self) end if self.callback_arrived then return self.callback_arrived(self) end
return true return true
elseif not self.current_target then elseif not self.current_target then
@ -369,13 +369,15 @@ function mob_class:check_gowp(dtime)
-- More pathing to be done -- More pathing to be done
local distance_to_current_target = 50 local distance_to_current_target = 50
if self.current_target and self.current_target["pos"] then if self.current_target and self.current_target["pos"] then
distance_to_current_target = vector.distance(p,self.current_target["pos"]) local dx, dy, dz = self.current_target["pos"].x-p.x, self.current_target["pos"].y-p.y, self.current_target["pos"].z-p.z
distance_to_current_target = (dx*dx+dy*dy*0.25+dz*dz)^0.5 -- reduced weight on y
--distance_to_current_target = vector.distance(p,self.current_target["pos"])
end end
-- 0.6 is working but too sensitive. sends villager back too frequently. 0.7 is quite good, but not with heights -- 0.6 is working but too sensitive. sends villager back too frequently. 0.7 is quite good, but not with heights
-- 0.8 is optimal for 0.025 frequency checks and also 1... Actually. 0.8 is winning -- 0.8 is optimal for 0.025 frequency checks and also 1... Actually. 0.8 is winning
-- 0.9 and 1.0 is also good. Stick with unless door open or closing issues -- 0.9 and 1.0 is also good. Stick with unless door open or closing issues
if self.waypoints and #self.waypoints > 0 and ( not self.current_target or not self.current_target["pos"] or distance_to_current_target < 0.9 ) then if self.waypoints and #self.waypoints > 0 and ( not self.current_target or not self.current_target["pos"] or distance_to_current_target < 0.8 ) then
-- We have waypoints, and are at current_target or have no current target. We need a new current_target. -- We have waypoints, and are at current_target or have no current target. We need a new current_target.
self:do_pathfind_action (self.current_target["action"]) self:do_pathfind_action (self.current_target["action"])
@ -383,6 +385,11 @@ function mob_class:check_gowp(dtime)
mcl_log("There after " .. failed_attempts .. " failed attempts. current target:".. minetest.pos_to_string(self.current_target["pos"]) .. ". Distance: " .. distance_to_current_target) mcl_log("There after " .. failed_attempts .. " failed attempts. current target:".. minetest.pos_to_string(self.current_target["pos"]) .. ". Distance: " .. distance_to_current_target)
self.current_target = table.remove(self.waypoints, 1) self.current_target = table.remove(self.waypoints, 1)
-- use smoothing
if #self.waypoints > 0 then
local curwp, nextwp = self.current_target["pos"], self.waypoints[1]["pos"]
self:go_to_pos(vector.new(curwp.x*0.5+nextwp.x*0.5,curwp.y*0.5+nextwp.y*0.5,curwp.z*0.5+nextwp.z*0.5))
end
self:go_to_pos(self.current_target["pos"]) self:go_to_pos(self.current_target["pos"])
return return
elseif self.current_target and self.current_target["pos"] then elseif self.current_target and self.current_target["pos"] then
@ -397,8 +404,8 @@ function mob_class:check_gowp(dtime)
self.waypoints = nil self.waypoints = nil
self._target = nil self._target = nil
self._pf_last_failed = os.time() self._pf_last_failed = os.time()
self.object:set_velocity({x = 0, y = 0, z = 0}) self.object:set_velocity(vector.zero())
self.object:set_acceleration({x = 0, y = 0, z = 0}) self.object:set_acceleration(vector.zero())
return return
end end

@ -303,11 +303,11 @@ function mob_class:check_smooth_rotation(dtime)
if self.shaking then if self.shaking then
yaw = yaw + (random() * 2 - 1) / 72 * dtime yaw = yaw + (random() * 2 - 1) / 72 * dtime
end end
if self.acc then --[[ needed? if self.acc then
local change = yaw - initial_yaw local change = yaw - initial_yaw
local si, co = math.sin(change), math.cos(change) local si, co = math.sin(change), math.cos(change)
self.acc.x, self.acc.y = co * self.acc.x - si * self.acc.y, si * self.acc.x + co * self.acc.y self.acc.x, self.acc.y = co * self.acc.x - si * self.acc.y, si * self.acc.x + co * self.acc.y
end end ]]--
self.object:set_yaw(yaw) self.object:set_yaw(yaw)
self:update_roll() self:update_roll()
end end
@ -869,7 +869,6 @@ function mob_class:falling(pos, moveresult)
local v = self.object:get_velocity() local v = self.object:get_velocity()
if v then if v then
local new_acceleration local new_acceleration
if v.y > 0 then if v.y > 0 then
-- apply gravity when moving up -- apply gravity when moving up
new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0) new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0)