diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index f2650829c..9586c2ec0 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -754,8 +754,8 @@ function mob_class:go_to_pos(b) if not self then return end 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) + if vector.distance(b,s) < .5 then return true end + self:turn_in_direction(b.x - s.x, b.z - s.z, 2) self:set_velocity(self.follow_velocity) self:set_animation("walk") end @@ -863,8 +863,8 @@ function mob_class:do_states_walk() or not self.fly and (self:is_node_dangerous(self.standing_on) or self:is_node_waterhazard(self.standing_on)) then -- Better way to find shore - copied from upstream local lp = minetest.find_nodes_in_area_under_air( - {x = s.x - 5, y = s.y - 0.5, z = s.z - 5}, - {x = s.x + 5, y = s.y + 1, z = s.z + 5}, + vector.new(s.x - 5, s.y - 0.5, s.z - 5), + vector.new(s.x + 5, s.y + 1, s.z + 5), {"group:solid"}) -- TODO: use node with smallest change in yaw? @@ -882,7 +882,8 @@ function mob_class:do_states_walk() end end -- stop at fences or randomly - if self.facing_fence == true or random() <= 0.3 then + -- fences break villager pathfinding! if self.facing_fence == true or random() <= 0.3 then + if random() <= 0.3 then self:stand() return end @@ -907,7 +908,12 @@ function mob_class:do_states_walk() self:turn_by(TWOPI * (random() - 0.5), 6) -- otherwise randomly turn elseif random() <= 0.3 then - self:turn_by(PIHALF * (random() - 0.5), 10) + local home = self._home or self._bed + if home and random() < 0.3 then + self:turn_in_direction(home.x - s.x, home.z - s.z, 8) + else + self:turn_by(PIHALF * (random() - 0.5), 10) + end end self:set_velocity(self.walk_velocity) self:animate_walk_or_fly() @@ -915,9 +921,9 @@ end function mob_class:do_states_stand(player_in_active_range) if random() < 0.25 then + local s = self.object:get_pos() local lp if player_in_active_range and self.look_at_players then - local s = self.object:get_pos() local objs = minetest.get_objects_inside_radius(s, 3) for n = 1, #objs do if objs[n]:is_player() then @@ -930,7 +936,12 @@ function mob_class:do_states_stand(player_in_active_range) if lp then self:turn_in_direction(lp.x - s.x, lp.z - s.z, 10) else - self:turn_by(PIHALF * (random() - 0.5), 10) + local home = self._home or self._bed + if home and random() < 0.3 then + self:turn_in_direction(home.x - s.x, home.z - s.z, 8) + else + self:turn_by(PIHALF * (random() - 0.5), 10) + end end end if self.order == "sit" then diff --git a/mods/ENTITIES/mcl_mobs/pathfinding.lua b/mods/ENTITIES/mcl_mobs/pathfinding.lua index df490c423..c95d4a375 100644 --- a/mods/ENTITIES/mcl_mobs/pathfinding.lua +++ b/mods/ENTITIES/mcl_mobs/pathfinding.lua @@ -373,6 +373,16 @@ function mob_class:check_gowp(dtime) 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 + -- also check next target, maybe we were too fast + local next_target = #self.waypoints > 0 and self.waypoints[1] + if next_target and next_target["pos"] and distance_to_current_target < 2 then + local dx, dy, dz = next_target["pos"].x-p.x, next_target["pos"].y-p.y, next_target["pos"].z-p.z + local distance_to_next_target = (dx*dx+dy*dy*0.25+dz*dz)^0.5 -- reduced weight on y + if distance_to_next_target < distance_to_current_target then + self.current_target = table.remove(self.waypoints, 1) -- pop waypoint already + distance_to_current_target = distance_to_next_target + end + 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 @@ -411,6 +421,7 @@ function mob_class:check_gowp(dtime) --mcl_log("Not at pos with failed attempts ".. failed_attempts ..": ".. minetest.pos_to_string(p) .. "self.current_target: ".. minetest.pos_to_string(self.current_target["pos"]) .. ". Distance: ".. distance_to_current_target) self:go_to_pos(self.current_target["pos"]) + self:turn_by(2 * (math.random() - 0.5), 2) -- but try turning left or right -- Do i just delete current_target, and return so we can find final path. else -- Not at target, no current waypoints or current_target. Through the door and should be able to path to target. diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 2b74d2a44..0da66eb2d 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -271,6 +271,7 @@ function mob_class:turn_by(angle, delay, dtime) end -- Turn into a direction (e.g., to the player, or away) function mob_class:turn_in_direction(dx, dz, delay, dtime) + if math.abs(dx) == 0 and math.abs(dz) == 0 then return self.object:get_yaw() + self.rotate end return self:set_yaw(-atan2(dx, dz) - self.rotate, delay, dtime) end -- set and return valid yaw