diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index a9e681f97..f2650829c 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -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 diff --git a/mods/ENTITIES/mcl_mobs/pathfinding.lua b/mods/ENTITIES/mcl_mobs/pathfinding.lua index ce706b190..df490c423 100644 --- a/mods/ENTITIES/mcl_mobs/pathfinding.lua +++ b/mods/ENTITIES/mcl_mobs/pathfinding.lua @@ -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 diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 1644da0b8..2b74d2a44 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -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)