mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2024-12-11 20:23:15 +01:00
Movement and path finding improvements.
This commit is contained in:
parent
77c6c34d0e
commit
e4deb9c7b5
@ -392,6 +392,7 @@ function mob_class:do_jump()
|
||||
end
|
||||
|
||||
local pos = self.object:get_pos()
|
||||
local v = self.object:get_velocity()
|
||||
local cbox = self.collisionbox
|
||||
|
||||
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()
|
||||
|
||||
-- where is front
|
||||
local dir_x = -sin(yaw) * (cbox[4] + 0.5)
|
||||
local dir_z = cos(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) + v.z * 0.25
|
||||
|
||||
-- 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.
|
||||
-- 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?
|
||||
|
||||
-- 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
|
||||
|
||||
local ndef = minetest.registered_nodes[nod.name]
|
||||
if self.walk_chance == 0 or ndef and ndef.walkable or self._can_jump_cliff then
|
||||
|
||||
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
|
||||
if self.walk_chance ~= 0 and not (ndef and ndef.walkable) and not self._can_jump_cliff then
|
||||
return false
|
||||
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
|
||||
|
||||
-- should mob follow what I'm holding ?
|
||||
@ -753,15 +752,10 @@ end
|
||||
|
||||
function mob_class:go_to_pos(b)
|
||||
if not self then return end
|
||||
local s=self.object:get_pos()
|
||||
if not b then
|
||||
--self.state = "stand"
|
||||
return end
|
||||
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)
|
||||
if not b then return end
|
||||
local s = self.object:get_pos()
|
||||
if vector.distance(b,s) < 1 then return true end
|
||||
self:turn_in_direction(b.x - s.x, b.z - s.z, 4)
|
||||
self:set_velocity(self.follow_velocity)
|
||||
self:set_animation("walk")
|
||||
end
|
||||
|
@ -358,8 +358,8 @@ function mob_class:check_gowp(dtime)
|
||||
self.current_target = nil
|
||||
self.state = "stand"
|
||||
self.order = "stand"
|
||||
self.object:set_velocity({x = 0, y = 0, z = 0})
|
||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||
self.object:set_velocity(vector.zero())
|
||||
self.object:set_acceleration(vector.zero())
|
||||
if self.callback_arrived then return self.callback_arrived(self) end
|
||||
return true
|
||||
elseif not self.current_target then
|
||||
@ -369,13 +369,15 @@ function mob_class:check_gowp(dtime)
|
||||
-- More pathing to be done
|
||||
local distance_to_current_target = 50
|
||||
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
|
||||
|
||||
-- 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.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.
|
||||
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)
|
||||
|
||||
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"])
|
||||
return
|
||||
elseif self.current_target and self.current_target["pos"] then
|
||||
@ -397,8 +404,8 @@ function mob_class:check_gowp(dtime)
|
||||
self.waypoints = nil
|
||||
self._target = nil
|
||||
self._pf_last_failed = os.time()
|
||||
self.object:set_velocity({x = 0, y = 0, z = 0})
|
||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||
self.object:set_velocity(vector.zero())
|
||||
self.object:set_acceleration(vector.zero())
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -303,11 +303,11 @@ function mob_class:check_smooth_rotation(dtime)
|
||||
if self.shaking then
|
||||
yaw = yaw + (random() * 2 - 1) / 72 * dtime
|
||||
end
|
||||
if self.acc then
|
||||
--[[ needed? if self.acc then
|
||||
local change = yaw - initial_yaw
|
||||
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
|
||||
end
|
||||
end ]]--
|
||||
self.object:set_yaw(yaw)
|
||||
self:update_roll()
|
||||
end
|
||||
@ -869,7 +869,6 @@ function mob_class:falling(pos, moveresult)
|
||||
local v = self.object:get_velocity()
|
||||
if v then
|
||||
local new_acceleration
|
||||
|
||||
if v.y > 0 then
|
||||
-- apply gravity when moving up
|
||||
new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0)
|
||||
|
Loading…
Reference in New Issue
Block a user