diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 2011e70e8..2bcf706ce 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -11,8 +11,8 @@ local stuck_path_timeout = 10 -- how long will mob follow path before giving up local enable_pathfinding = true local TIME_TO_FORGET_TARGET = 15 - -local atan2 = math.atan2 +local PI = math.pi +local random = math.random -- check if daytime and also if mob is docile during daylight hours function mob_class:day_docile() @@ -764,12 +764,15 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir) -- if skittish then run away if hitter and is_player and hitter:get_pos() and not die and self.runaway == true and self.state ~= "flop" then - - local yaw = self:set_yaw( minetest.dir_to_yaw(vector.direction(hitter:get_pos(), self.object:get_pos()))) + local hp, sp = hitter:get_pos(), self.object:get_pos() + self:turn_in_direction(sp.x - hp.x, sp.z - hp.z, 1) minetest.after(0.2,function() - if self and self.object and self.object:get_pos() and hitter and is_player and hitter:get_pos() then - yaw = self:set_yaw( minetest.dir_to_yaw(vector.direction(hitter:get_pos(), self.object:get_pos()))) - self:set_velocity( self.run_velocity) + if self and self.object and hitter and is_player then + local hp, sp = hitter:get_pos(), self.object:get_pos() + if hp and sp then + self:turn_in_direction(sp.x - hp.x, sp.z - hp.z, 1) + self:set_velocity(self.run_velocity) + end end end) self.state = "runaway" @@ -917,8 +920,7 @@ function mob_class:do_states_attack (dtime) if self.attack_type == "explode" then if target_line_of_sight then - yaw = -atan2(p.x - s.x, p.z - s.z) - self.rotate - yaw = self:set_yaw(yaw, 1, dtime) + self:turn_in_direction(p.x - s.x, p.z - s.z, 1, dtime) end local node_break_radius = self.explosion_radius or 1 @@ -1071,8 +1073,7 @@ function mob_class:do_states_attack (dtime) p = {x = p1.x, y = p1.y, z = p1.z} end - yaw = -atan2(p.x - s.x, p.z - s.z) - self.rotate - yaw = self:set_yaw(yaw, 1, dtime) + self:turn_in_direction(p.x - s.x, p.z - s.z, 1, dtime) -- move towards enemy if beyond mob reach if dist > self.reach then @@ -1082,10 +1083,9 @@ function mob_class:do_states_attack (dtime) end if self:is_at_cliff_or_danger() then - self:set_velocity( 0) - self:set_animation( "stand") - local yaw = self.object:get_yaw() or 0 - yaw = self:set_yaw( yaw + 0.78, 8) + self:set_velocity(0) + self:set_animation("stand") + self:turn_by(PI * (random() - 0.5), 10) else if self.path.stuck then self:set_velocity(self.walk_velocity) @@ -1159,8 +1159,7 @@ function mob_class:do_states_attack (dtime) z = p.z - s.z } local dist = (vec.x^2 + vec.y^2 + vec.z^2)^0.5 - yaw = -atan2(vec.x, vec.z) - self.rotate - yaw = self:set_yaw(yaw, 1, dtime) + self:turn_in_direction(vec.x, vec.z, 1, dtime) local stay_away_from_player = vector.zero() diff --git a/mods/ENTITIES/mcl_mobs/movement.lua b/mods/ENTITIES/mcl_mobs/movement.lua index 65c70a2a3..9fa30bb6c 100644 --- a/mods/ENTITIES/mcl_mobs/movement.lua +++ b/mods/ENTITIES/mcl_mobs/movement.lua @@ -16,7 +16,6 @@ local logging = minetest.settings:get_bool("mcl_logging_mobs_movement", true) local random = math.random local sin = math.sin local cos = math.cos -local atan2 = math.atan2 local abs = math.abs local floor = math.floor local PI = math.pi @@ -356,12 +355,9 @@ function mob_class:env_danger_movement_checks(player_in_active_range) if logging then minetest.log("action", "[mcl_mobs] "..self.name.." at water danger, stop and rotate?") end - if random() <= 0.8 then - if self.state ~= "stand" then - self:stand() - end - local yaw = self.object:get_yaw() or 0 - self:set_yaw(yaw + PIHALF * (random() - 0.5), 10) + if random() <= 0.9 then + if self.state ~= "stand" then self:stand() end + self:turn_by(PI * (random() - 0.5), 10) return end end @@ -370,11 +366,8 @@ function mob_class:env_danger_movement_checks(player_in_active_range) minetest.log("action", "[mcl_mobs] "..self.name.." at cliff danger, rotate") end if random() <= 0.99 then - if self.state ~= "stand" then - self:stand() - end - local yaw = self.object:get_yaw() or 0 - yaw = self:set_yaw(yaw + PI * (random() - 0.5), 10) + if self.state ~= "stand" then self:stand() end + self:turn_by(PI * (random() - 0.5), 10) end end end @@ -479,15 +472,12 @@ function mob_class:do_jump() 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 - local yaw = self.object:get_yaw() or 0 - yaw = self:set_yaw(yaw + PI * (random() - 0.5), 8) + self:turn_by(PI * (random() - 0.5), 8) self.jump_count = 0 end end - return true end - return false end @@ -654,8 +644,7 @@ function mob_class:check_runaway_from() if min_player then local lp = player:get_pos() - local yaw = -atan2(s.x - lp.x, s.z - lp.z) - self.rotate -- away from player - self:set_yaw(yaw, 4) + self:turn_in_direction(s.x - lp.x, s.z - lp.z, 4) -- away from player self.state = "runaway" self.runaway_timer = 3 self.following = nil @@ -710,7 +699,7 @@ function mob_class:check_follow() if (not self:object_in_range(self.following)) then self.following = nil else - self:set_yaw(-atan2(p.x - s.x, p.z - s.z) - self.rotate, 2.35) + self:turn_in_direction(p.x - s.x, p.z - s.z, 2.35) -- anyone but standing npc's can move along local dist = vector.distance(p, s) @@ -772,7 +761,7 @@ function mob_class:go_to_pos(b) --self:set_velocity(0) return true end - self.object:set_yaw(-atan2(b.x - s.x, b.z - s.z) - self.rotate) + self:turn_in_direction(b.x - s.x, b.z - s.z, 6) self:set_velocity(self.follow_velocity) self:set_animation("walk") end @@ -789,17 +778,11 @@ function mob_class:check_herd(dtime) check_herd_timer = 0 for _,o in pairs(minetest.get_objects_inside_radius(pos,self.view_range)) do local l = o:get_luaentity() - local p,y if l and l.is_mob and l.name == self.name then if self.horny and l.horny then - p = l.object:get_pos() + self:go_to_pos(l.object:get_pos()) else - y = o:get_yaw() - end - if p then - self:go_to_pos(p) - elseif y then - self:set_yaw(y) + self:set_yaw(o:get_yaw(), 8) end end end @@ -875,7 +858,7 @@ function mob_class:do_states_walk() self:set_yaw(yaw, 8) end self:stand() - yaw = self:set_yaw(yaw + PIHALF * (random() - 0.5), 6) + self:turn_by(PIHALF * (random() - 0.5), 6) return elseif logging then minetest.log("action", "[mcl_mobs] "..self.name.." ignores the danger "..tostring(danger)) @@ -898,7 +881,7 @@ function mob_class:do_states_walk() minetest.log("action", "[mcl_mobs] "..self.name.." heading to land ".. tostring(minetest.get_node(lp).name or nil)) end -- look towards land and move in that direction - self:set_yaw(-atan2(lp.x - s.x, lp.z - s.z) - self.rotate, 8) + self:turn_in_direction(lp.x - s.x, lp.z - s.z, 8) self:set_velocity(self.walk_velocity) self:animate_walk_or_fly() return @@ -927,10 +910,10 @@ function mob_class:do_states_walk() if logging then minetest.log("action", "[mcl_mobs] "..self.name.." facing a wall, turning.") end - yaw = self:set_yaw(yaw + PI * (random() - 0.5), 6) + self:turn_by(PI * (random() - 0.5), 6) -- otherwise randomly turn elseif random() <= 0.3 then - yaw = self:set_yaw(yaw + PIHALF * (random() - 0.5), 10) + self:turn_by(PIHALF * (random() - 0.5), 10) end self:set_velocity(self.walk_velocity) self:animate_walk_or_fly() @@ -953,11 +936,10 @@ function mob_class:do_states_stand(player_in_active_range) end -- look at any players nearby, otherwise turn randomly if lp then - yaw = -atan2(lp.x - s.x, lp.z - s.z) - self.rotate + self:turn_in_direction(lp.x - s.x, lp.z - s.z, 10) else - yaw = yaw + PIHALF * (random() - 0.5) + self:turn_by(PIHALF * (random() - 0.5), 10) end - yaw = self:set_yaw(yaw, 10) end if self.order == "sit" then self:set_animation( "sit") @@ -976,8 +958,7 @@ function mob_class:do_states_stand(player_in_active_range) and self.facing_fence ~= true and random(1, 100) <= self.walk_chance then if self:is_at_cliff_or_danger() then - yaw = yaw + PI * (random() - 0.5) - yaw = self:set_yaw(yaw, 10) + self:turn_by(PI * (random() - 0.5), 10) else self:set_velocity(self.walk_velocity) self.state = "walk" @@ -998,7 +979,7 @@ function mob_class:do_states_runaway() or self:is_at_cliff_or_danger() then self.runaway_timer = 0 self:stand() - yaw = self:set_yaw(yaw + PI * (random() + 0.5), 8) + self:turn_by(PI * (random() + 0.5), 8) else self:set_velocity( self.run_velocity) self:set_animation( "run") diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 361eb5ec4..00bd1bd86 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -8,6 +8,7 @@ local DEATH_DELAY = 0.5 local DEFAULT_FALL_SPEED = -9.81*1.5 local PI = math.pi local TWOPI = 2 * PI +local atan2 = math.atan2 local PATHFINDING = "gowp" local mobs_debug = minetest.settings:get_bool("mobs_debug", false) @@ -266,8 +267,16 @@ function mob_class:update_roll() end +-- Relative turn, primarily for random turning +function mob_class:turn_by(angle, delay, dtime) + return self:set_yaw((self.object:get_yaw() or 0) + 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) + return self:set_yaw(-atan2(dx, dz) - self.rotate, delay, dtime) +end -- set and return valid yaw -function mob_class:set_yaw(yaw, delay, dtime) +function mob_class:set_yaw(yaw, delay, dtime) -- FIXME: dtime unused if self.noyaw then return end if not self.object:get_yaw() or not self.object:get_pos() then return end self.delay = delay or 0 @@ -275,8 +284,8 @@ function mob_class:set_yaw(yaw, delay, dtime) return self.target_yaw end +-- improved smooth rotation function mob_class:check_smooth_rotation(dtime) - -- improved smooth rotation if self._turn_to then self:set_yaw(self._turn_to, .1) self._turn_to = nil