Mob pushing improvements

This commit is contained in:
kno10 2024-07-14 19:03:26 +02:00
parent b91f48b419
commit 77c6c34d0e
2 changed files with 57 additions and 63 deletions

@ -361,7 +361,7 @@ function mob_class:env_danger_movement_checks(player_in_active_range)
return return
end end
end end
if self:is_at_cliff_or_danger() and not self._can_jump_cliff then if not self._can_jump_cliff and self:is_at_cliff_or_danger() then
if logging then if logging then
minetest.log("action", "[mcl_mobs] "..self.name.." at cliff danger, rotate") minetest.log("action", "[mcl_mobs] "..self.name.." at cliff danger, rotate")
end end
@ -858,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()
self:turn_by(PIHALF * (random() - 0.5), 6) self:turn_by(PI * (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))
@ -910,7 +910,7 @@ 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
self:turn_by(PI * (random() - 0.5), 6) self:turn_by(TWOPI * (random() - 0.5), 6)
-- otherwise randomly turn -- otherwise randomly turn
elseif random() <= 0.3 then elseif random() <= 0.3 then
self:turn_by(PIHALF * (random() - 0.5), 10) self:turn_by(PIHALF * (random() - 0.5), 10)
@ -920,8 +920,6 @@ function mob_class:do_states_walk()
end end
function mob_class:do_states_stand(player_in_active_range) function mob_class:do_states_stand(player_in_active_range)
local yaw = self.object:get_yaw() or 0
if random() < 0.25 then if random() < 0.25 then
local lp local lp
if player_in_active_range and self.look_at_players then if player_in_active_range and self.look_at_players then
@ -942,10 +940,10 @@ function mob_class:do_states_stand(player_in_active_range)
end end
end end
if self.order == "sit" then if self.order == "sit" then
self:set_animation( "sit") self:set_animation("sit")
self:set_velocity(0) self:set_velocity(0)
else else
self:set_animation( "stand") self:set_animation("stand")
self:set_velocity(0) self:set_velocity(0)
end end
@ -970,10 +968,7 @@ function mob_class:do_states_stand(player_in_active_range)
end end
function mob_class:do_states_runaway() function mob_class:do_states_runaway()
local yaw = self.object:get_yaw() or 0
self.runaway_timer = self.runaway_timer + 1 self.runaway_timer = self.runaway_timer + 1
-- stop after 5 seconds or when at cliff -- stop after 5 seconds or when at cliff
if self.runaway_timer > 5 if self.runaway_timer > 5
or self:is_at_cliff_or_danger() then or self:is_at_cliff_or_danger() then

@ -159,32 +159,29 @@ end
-- collision function borrowed amended from jordan4ibanez open_ai mod -- collision function borrowed amended from jordan4ibanez open_ai mod
function mob_class:collision() function mob_class:collision()
local pos = self.object:get_pos() local pos = self.object:get_pos()
if not pos then return {0,0} end if not pos then return 0,0 end
local vel = self.object:get_velocity() local vel = self.object:get_velocity()
local x = 0 local x, z = 0, 0
local z = 0
local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5 local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5
for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do
local ent = object:get_luaentity() local ent = object:get_luaentity()
if object:is_player() or (ent and ent.is_mob and object ~= self.object) then if object:is_player() or (ent and ent.is_mob and object ~= self.object) then
if object:is_player() and mcl_burning.is_burning(self.object) then if object:is_player() and mcl_burning.is_burning(self.object) then
mcl_burning.set_on_fire(object, 4) mcl_burning.set_on_fire(object, 4)
end end
local pos2 = object:get_pos() local pos2 = object:get_pos()
local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} local vx, vz = pos.x - pos2.x, pos.z - pos2.z
local force = (width + 0.5) - vector.distance( local force = width - (vx*vx+vz*vz)^0.5
{x = pos.x, y = 0, z = pos.z}, if force > 0 then
{x = pos2.x, y = 0, z = pos2.z}) force = force * force * (object:is_player() and 2 or 1) -- players push more
-- minetest.log("mob push force "..force.." "..tostring(self.name).." by "..tostring(ent and ent.name or "player"))
x = x + (vec.x * force) x = x + vx * force
z = z + (vec.z * force) z = z + vz * force
end end
end end
end
return({x,z}) return x, z
end end
function mob_class:check_death_and_slow_mob() function mob_class:check_death_and_slow_mob()
@ -195,44 +192,45 @@ function mob_class:check_death_and_slow_mob()
local v = self.object:get_velocity() local v = self.object:get_velocity()
if v then if v then
--diffuse object velocity --diffuse object velocity
self.object:set_velocity({x = v.x*d, y = v.y, z = v.z*d}) self.object:set_velocity(vector.new(v.x*d, v.y, v.z*d))
end end
return dying return dying
end end
-- move mob in facing direction -- move mob in facing direction
function mob_class:set_velocity(v) function mob_class:set_velocity(v)
if not v then return end local c_x, c_z = 0, 0
local c_x, c_y = 0, 0
-- can mob be pushed, if so calculate direction -- can mob be pushed, if so calculate direction
if self.pushable then if self.pushable then
c_x, c_y = unpack(self:collision()) c_x, c_z = self:collision()
end end
if v > 0 then
-- halt mob if it has been ordered to stay
if self.order == "stand" or self.order == "sit" then
self.acc = vector.zero()
return
end
local yaw = (self.object:get_yaw() or 0) + self.rotate local yaw = (self.object:get_yaw() or 0) + self.rotate
local vv = self.object:get_velocity() local x = ((-math.sin(yaw) * v) + c_x) * .4
local z = (( math.cos(yaw) * v) + c_z) * .4
if vv and yaw then if not self.acc then
self.acc = vector.new(((math.sin(yaw) * -v) + c_x) * .4, 0, ((math.cos(yaw) * v) + c_y) * .4) self.acc = vector.new(x, 0, z)
else
self.acc.x = x
self.acc.y = 0
self.acc.z = z
end
else -- allow standing mobs to be pushed
if not self.acc then
self.acc = vector.new(c_x * .2, 0, c_z * .2)
else
self.acc.x = c_x * .2
self.acc.y = 0
self.acc.z = c_z * .2
end
end end
end end
-- calculate mob velocity -- calculate mob velocity (2d)
function mob_class:get_velocity() function mob_class:get_velocity()
local v = self.object:get_velocity() local v = self.object:get_velocity()
if v then if not v then return 0 end
return (v.x * v.x + v.z * v.z) ^ 0.5 return (v.x*v.x + v.z*v.z)^0.5
end
return 0
end end
function mob_class:update_roll() function mob_class:update_roll()
@ -292,25 +290,26 @@ function mob_class:check_smooth_rotation(dtime)
end end
local delay = self.delay local delay = self.delay
local yaw = self.object:get_yaw() or 0 local initial_yaw = self.object:get_yaw() or 0
local target_yaw = self.target_yaw local yaw -- resulting yaw for this tick
if delay and delay > 1 then if delay and delay > 1 then
local dif = (target_yaw - yaw + PI) % TWOPI - PI local dif = (self.target_yaw - initial_yaw + PI) % TWOPI - PI
yaw = (yaw + dif / delay) % TWOPI yaw = (initial_yaw + dif / delay) % TWOPI
self.delay = delay - 1 self.delay = delay - 1
else else
yaw = target_yaw yaw = self.target_yaw
end end
if self.shaking then if self.shaking then
yaw = yaw + (random() * 2 - 1) / 72 * dtime yaw = yaw + (random() * 2 - 1) / 72 * dtime
end end
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
self.object:set_yaw(yaw) self.object:set_yaw(yaw)
-- TODO: needed? self:update_roll()
--if validate_vector(self.acc) then
-- self.acc=vector.rotate_around_axis(self.acc,vector.new(0,1,0), target_shortest_path*(3.6*ddtime))
--end
--self:update_roll()
end end
-- global function to set mob yaw -- global function to set mob yaw
@ -596,7 +595,7 @@ function mob_class:do_env_damage()
-- what is mob standing in? -- what is mob standing in?
pos.y = pos.y + y_level + 0.25 -- foot level pos.y = pos.y + y_level + 0.25 -- foot level
local pos2 = {x=pos.x, y=pos.y-1, z=pos.z} local pos2 = vector.new(pos.x, pos.y-1, pos.z)
self.standing_in = node_ok(pos, "air").name self.standing_in = node_ok(pos, "air").name
self.standing_on = node_ok(pos2, "air").name self.standing_on = node_ok(pos2, "air").name
@ -605,7 +604,7 @@ function mob_class:do_env_damage()
-- don't fall when on ignore, just stand still -- don't fall when on ignore, just stand still
if self.standing_in == "ignore" then if self.standing_in == "ignore" then
self.object:set_velocity({x = 0, y = 0, z = 0}) self.object:set_velocity(vector.zero())
-- wither rose effect -- wither rose effect
elseif self.standing_in == "mcl_flowers:wither_rose" then elseif self.standing_in == "mcl_flowers:wither_rose" then
mcl_potions.give_effect_by_level("withering", self.object, 2, 2) mcl_potions.give_effect_by_level("withering", self.object, 2, 2)
@ -885,7 +884,7 @@ function mob_class:falling(pos, moveresult)
end end
else else
-- stop accelerating once max fall speed hit -- stop accelerating once max fall speed hit
new_acceleration =vector.zero() new_acceleration = vector.zero()
end end
self.object:set_acceleration(new_acceleration) self.object:set_acceleration(new_acceleration)
@ -949,8 +948,8 @@ function mob_class:check_water_flow()
local f = 1.39 local f = 1.39
-- Set new item moving speed into the direciton of the liquid -- Set new item moving speed into the direciton of the liquid
local newv = vector.multiply(vec, f) local newv = vector.multiply(vec, f)
self.object:set_acceleration({x = 0, y = 0, z = 0}) self.object:set_acceleration(vector.zero())
self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z}) self.object:set_velocity(vector.new(newv.x, -0.22, newv.z))
self.physical_state = true self.physical_state = true
self._flowing = true self._flowing = true