add and use turn_by/turn_in_direction methods

This commit is contained in:
kno10 2024-07-13 16:46:50 +02:00
parent 5eda59dc13
commit b91f48b419
3 changed files with 46 additions and 57 deletions

@ -11,8 +11,8 @@ local stuck_path_timeout = 10 -- how long will mob follow path before giving up
local enable_pathfinding = true local enable_pathfinding = true
local TIME_TO_FORGET_TARGET = 15 local TIME_TO_FORGET_TARGET = 15
local PI = math.pi
local atan2 = math.atan2 local random = math.random
-- check if daytime and also if mob is docile during daylight hours -- check if daytime and also if mob is docile during daylight hours
function mob_class:day_docile() 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 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 if hitter and is_player and hitter:get_pos() and not die and self.runaway == true and self.state ~= "flop" then
local hp, sp = hitter:get_pos(), self.object:get_pos()
local yaw = self:set_yaw( minetest.dir_to_yaw(vector.direction(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() 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 if self and self.object and hitter and is_player then
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:set_velocity( self.run_velocity) 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
end) end)
self.state = "runaway" self.state = "runaway"
@ -917,8 +920,7 @@ function mob_class:do_states_attack (dtime)
if self.attack_type == "explode" then if self.attack_type == "explode" then
if target_line_of_sight then if target_line_of_sight then
yaw = -atan2(p.x - s.x, p.z - s.z) - self.rotate self:turn_in_direction(p.x - s.x, p.z - s.z, 1, dtime)
yaw = self:set_yaw(yaw, 1, dtime)
end end
local node_break_radius = self.explosion_radius or 1 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} p = {x = p1.x, y = p1.y, z = p1.z}
end end
yaw = -atan2(p.x - s.x, p.z - s.z) - self.rotate self:turn_in_direction(p.x - s.x, p.z - s.z, 1, dtime)
yaw = self:set_yaw(yaw, 1, dtime)
-- move towards enemy if beyond mob reach -- move towards enemy if beyond mob reach
if dist > self.reach then if dist > self.reach then
@ -1082,10 +1083,9 @@ function mob_class:do_states_attack (dtime)
end end
if self:is_at_cliff_or_danger() then if self:is_at_cliff_or_danger() then
self:set_velocity( 0) self:set_velocity(0)
self:set_animation( "stand") self:set_animation("stand")
local yaw = self.object:get_yaw() or 0 self:turn_by(PI * (random() - 0.5), 10)
yaw = self:set_yaw( yaw + 0.78, 8)
else else
if self.path.stuck then if self.path.stuck then
self:set_velocity(self.walk_velocity) self:set_velocity(self.walk_velocity)
@ -1159,8 +1159,7 @@ function mob_class:do_states_attack (dtime)
z = p.z - s.z z = p.z - s.z
} }
local dist = (vec.x^2 + vec.y^2 + vec.z^2)^0.5 local dist = (vec.x^2 + vec.y^2 + vec.z^2)^0.5
yaw = -atan2(vec.x, vec.z) - self.rotate self:turn_in_direction(vec.x, vec.z, 1, dtime)
yaw = self:set_yaw(yaw, 1, dtime)
local stay_away_from_player = vector.zero() local stay_away_from_player = vector.zero()

@ -16,7 +16,6 @@ local logging = minetest.settings:get_bool("mcl_logging_mobs_movement", true)
local random = math.random local random = math.random
local sin = math.sin local sin = math.sin
local cos = math.cos local cos = math.cos
local atan2 = math.atan2
local abs = math.abs local abs = math.abs
local floor = math.floor local floor = math.floor
local PI = math.pi local PI = math.pi
@ -356,12 +355,9 @@ function mob_class:env_danger_movement_checks(player_in_active_range)
if logging then if logging then
minetest.log("action", "[mcl_mobs] "..self.name.." at water danger, stop and rotate?") minetest.log("action", "[mcl_mobs] "..self.name.." at water danger, stop and rotate?")
end end
if random() <= 0.8 then if random() <= 0.9 then
if self.state ~= "stand" then if self.state ~= "stand" then self:stand() end
self:stand() self:turn_by(PI * (random() - 0.5), 10)
end
local yaw = self.object:get_yaw() or 0
self:set_yaw(yaw + PIHALF * (random() - 0.5), 10)
return return
end end
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") minetest.log("action", "[mcl_mobs] "..self.name.." at cliff danger, rotate")
end end
if random() <= 0.99 then if random() <= 0.99 then
if self.state ~= "stand" then if self.state ~= "stand" then self:stand() end
self:stand() self:turn_by(PI * (random() - 0.5), 10)
end
local yaw = self.object:get_yaw() or 0
yaw = self:set_yaw(yaw + PI * (random() - 0.5), 10)
end end
end 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 if self.object:get_velocity().x ~= 0 and self.object:get_velocity().z ~= 0 then
self.jump_count = (self.jump_count or 0) + 1 self.jump_count = (self.jump_count or 0) + 1
if self.jump_count == 4 then if self.jump_count == 4 then
local yaw = self.object:get_yaw() or 0 self:turn_by(PI * (random() - 0.5), 8)
yaw = self:set_yaw(yaw + PI * (random() - 0.5), 8)
self.jump_count = 0 self.jump_count = 0
end end
end end
return true return true
end end
return false return false
end end
@ -654,8 +644,7 @@ function mob_class:check_runaway_from()
if min_player then if min_player then
local lp = player:get_pos() local lp = player:get_pos()
local yaw = -atan2(s.x - lp.x, s.z - lp.z) - self.rotate -- away from player self:turn_in_direction(s.x - lp.x, s.z - lp.z, 4) -- away from player
self:set_yaw(yaw, 4)
self.state = "runaway" self.state = "runaway"
self.runaway_timer = 3 self.runaway_timer = 3
self.following = nil self.following = nil
@ -710,7 +699,7 @@ function mob_class:check_follow()
if (not self:object_in_range(self.following)) then if (not self:object_in_range(self.following)) then
self.following = nil self.following = nil
else 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 -- anyone but standing npc's can move along
local dist = vector.distance(p, s) local dist = vector.distance(p, s)
@ -772,7 +761,7 @@ function mob_class:go_to_pos(b)
--self:set_velocity(0) --self:set_velocity(0)
return true return true
end 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_velocity(self.follow_velocity)
self:set_animation("walk") self:set_animation("walk")
end end
@ -789,17 +778,11 @@ function mob_class:check_herd(dtime)
check_herd_timer = 0 check_herd_timer = 0
for _,o in pairs(minetest.get_objects_inside_radius(pos,self.view_range)) do for _,o in pairs(minetest.get_objects_inside_radius(pos,self.view_range)) do
local l = o:get_luaentity() local l = o:get_luaentity()
local p,y
if l and l.is_mob and l.name == self.name then if l and l.is_mob and l.name == self.name then
if self.horny and l.horny then if self.horny and l.horny then
p = l.object:get_pos() self:go_to_pos(l.object:get_pos())
else else
y = o:get_yaw() self:set_yaw(o:get_yaw(), 8)
end
if p then
self:go_to_pos(p)
elseif y then
self:set_yaw(y)
end end
end end
end end
@ -875,7 +858,7 @@ function mob_class:do_states_walk()
self:set_yaw(yaw, 8) self:set_yaw(yaw, 8)
end end
self:stand() self:stand()
yaw = self:set_yaw(yaw + PIHALF * (random() - 0.5), 6) self:turn_by(PIHALF * (random() - 0.5), 6)
return return
elseif logging then elseif logging then
minetest.log("action", "[mcl_mobs] "..self.name.." ignores the danger "..tostring(danger)) 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)) minetest.log("action", "[mcl_mobs] "..self.name.." heading to land ".. tostring(minetest.get_node(lp).name or nil))
end end
-- look towards land and move in that direction -- 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:set_velocity(self.walk_velocity)
self:animate_walk_or_fly() self:animate_walk_or_fly()
return return
@ -927,10 +910,10 @@ function mob_class:do_states_walk()
if logging then if logging then
minetest.log("action", "[mcl_mobs] "..self.name.." facing a wall, turning.") minetest.log("action", "[mcl_mobs] "..self.name.." facing a wall, turning.")
end end
yaw = self:set_yaw(yaw + PI * (random() - 0.5), 6) self:turn_by(PI * (random() - 0.5), 6)
-- otherwise randomly turn -- otherwise randomly turn
elseif random() <= 0.3 then elseif random() <= 0.3 then
yaw = self:set_yaw(yaw + PIHALF * (random() - 0.5), 10) self:turn_by(PIHALF * (random() - 0.5), 10)
end end
self:set_velocity(self.walk_velocity) self:set_velocity(self.walk_velocity)
self:animate_walk_or_fly() self:animate_walk_or_fly()
@ -953,11 +936,10 @@ function mob_class:do_states_stand(player_in_active_range)
end end
-- look at any players nearby, otherwise turn randomly -- look at any players nearby, otherwise turn randomly
if lp then 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 else
yaw = yaw + PIHALF * (random() - 0.5) self:turn_by(PIHALF * (random() - 0.5), 10)
end end
yaw = self:set_yaw(yaw, 10)
end end
if self.order == "sit" then if self.order == "sit" then
self:set_animation( "sit") self:set_animation( "sit")
@ -976,8 +958,7 @@ function mob_class:do_states_stand(player_in_active_range)
and self.facing_fence ~= true and self.facing_fence ~= true
and random(1, 100) <= self.walk_chance then and random(1, 100) <= self.walk_chance then
if self:is_at_cliff_or_danger() then if self:is_at_cliff_or_danger() then
yaw = yaw + PI * (random() - 0.5) self:turn_by(PI * (random() - 0.5), 10)
yaw = self:set_yaw(yaw, 10)
else else
self:set_velocity(self.walk_velocity) self:set_velocity(self.walk_velocity)
self.state = "walk" self.state = "walk"
@ -998,7 +979,7 @@ function mob_class:do_states_runaway()
or self:is_at_cliff_or_danger() then or self:is_at_cliff_or_danger() then
self.runaway_timer = 0 self.runaway_timer = 0
self:stand() self:stand()
yaw = self:set_yaw(yaw + PI * (random() + 0.5), 8) self:turn_by(PI * (random() + 0.5), 8)
else else
self:set_velocity( self.run_velocity) self:set_velocity( self.run_velocity)
self:set_animation( "run") self:set_animation( "run")

@ -8,6 +8,7 @@ local DEATH_DELAY = 0.5
local DEFAULT_FALL_SPEED = -9.81*1.5 local DEFAULT_FALL_SPEED = -9.81*1.5
local PI = math.pi local PI = math.pi
local TWOPI = 2 * PI local TWOPI = 2 * PI
local atan2 = math.atan2
local PATHFINDING = "gowp" local PATHFINDING = "gowp"
local mobs_debug = minetest.settings:get_bool("mobs_debug", false) local mobs_debug = minetest.settings:get_bool("mobs_debug", false)
@ -266,8 +267,16 @@ function mob_class:update_roll()
end 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 -- 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 self.noyaw then return end
if not self.object:get_yaw() or not self.object:get_pos() then return end if not self.object:get_yaw() or not self.object:get_pos() then return end
self.delay = delay or 0 self.delay = delay or 0
@ -275,8 +284,8 @@ function mob_class:set_yaw(yaw, delay, dtime)
return self.target_yaw return self.target_yaw
end end
-- improved smooth rotation
function mob_class:check_smooth_rotation(dtime) function mob_class:check_smooth_rotation(dtime)
-- improved smooth rotation
if self._turn_to then if self._turn_to then
self:set_yaw(self._turn_to, .1) self:set_yaw(self._turn_to, .1)
self._turn_to = nil self._turn_to = nil