Improve danger avoidance code.

This commit is contained in:
kno10 2024-09-28 03:03:47 +02:00
parent 8fce90111b
commit a94b3a8d4a
1 changed files with 13 additions and 67 deletions

View File

@ -48,24 +48,19 @@ end
-- Returns true is node can deal damage to self -- Returns true is node can deal damage to self
function mob_class:is_node_dangerous(nodename) function mob_class:is_node_dangerous(nodename)
local nn = nodename local ndef = minetest.registered_nodes[nodename]
if self.lava_damage > 0 and minetest.get_item_group(nn, "lava") ~= 0 then return true end return ndef and (
if self.fire_damage > 0 and minetest.get_item_group(nn, "fire") ~= 0 then return true end (self.lava_damage > 0 and ndef.groups.lava)
if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].damage_per_second and minetest.registered_nodes[nn].damage_per_second > 0 then return true end or (self.fire_damage > 0 and ndef.groups.fire)
return false or ((ndef.damage_per_second or 0) > 0))
end end
-- Returns true if node is a water hazard -- Returns true if node is a water hazard
function mob_class:is_node_waterhazard(nodename) function mob_class:is_node_waterhazard(nodename)
local nn = nodename local ndef = minetest.registered_nodes[nodename]
if self.water_damage > 0 and minetest.get_item_group(nn, "water") ~= 0 then return true end return ndef and ndef.groups.water and (
if minetest.registered_nodes[nn] and (minetest.registered_nodes[nn].drowning or 0) > 0 (self.water_damage > 0)
and self.breath_max ~= -1 or (not self.breathes_in_water and self.breath_max ~= -1 and (ndef.drowning or 0) > 0))
-- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case
-- this will prevent water-breathing mobs to classify water or e.g. sand below them as dangerous
and not self.breathes_in_water and minetest.get_item_group(nn, "water") ~= 0 then return true end
return false
end end
@ -712,64 +707,15 @@ function mob_class:do_states_walk()
local yaw = self.object:get_yaw() or 0 local yaw = self.object:get_yaw() or 0
local s = self.object:get_pos() local s = self.object:get_pos()
-- is there something I need to avoid?
if (self.water_damage > 0
and self.lava_damage > 0)
or self.breath_max ~= -1 then
lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"})
elseif self.water_damage > 0 then
lp = minetest.find_node_near(s, 1, {"group:water"})
elseif self.lava_damage > 0 then
lp = minetest.find_node_near(s, 1, {"group:lava"})
elseif self.fire_damage > 0 then
lp = minetest.find_node_near(s, 1, {"group:fire"})
end
local is_in_danger = false
if lp then
-- If mob in or on dangerous block, look for land
if self:is_node_dangerous(self.standing_in) or self:is_node_waterhazard(self.standing_in)
or not self.fly and (self:is_node_dangerous(self.standing_on) or self:is_node_waterhazard(self.standing_on)) then
is_in_danger = true
-- If mob in or on dangerous block, look for land
if is_in_danger then
-- Better way to find shore - copied from upstream
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},
{"group:solid"})
lp = #lp > 0 and lp[random(#lp)]
-- did we find land?
if lp then
-- minetest.log(self.name .. " heading to land ".. tostring(minetest.get_node(lp).name or nil))
yaw = atan2(lp.x - s.x, lp.z - s.z) - self.rotate
-- look towards land and move in that direction
self:set_yaw(yaw, 6)
self:set_velocity(self.walk_velocity)
end
end
-- A danger is near but mob is not inside
else
-- Randomly turn
if random(1, 100) <= 30 then
yaw = yaw + random() - 0.5
self:set_yaw(yaw, 8)
end
self:stand()
self:turn_by(PI * (random() - 0.5), 6)
return
end
end
-- If mob in or on dangerous block, look for land -- If mob in or on dangerous block, look for land
if self:is_node_dangerous(self.standing_in) or self:is_node_waterhazard(self.standing_in) if self:is_node_dangerous(self.standing_in) or self:is_node_waterhazard(self.standing_in)
or not self.fly and (self:is_node_dangerous(self.standing_on) or self:is_node_waterhazard(self.standing_on)) then 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 -- Better way to find shore - copied from upstream
local lp = minetest.find_nodes_in_area_under_air(vector_offset(s, -5, -0.5, -5), vector_offset(s, 5, 1, 5), {"group:solid"}) local lp = minetest.find_nodes_in_area_under_air(vector_offset(s, -5, -0.5, -5), vector_offset(s, 5, 1, 5), {"group:solid"})
-- TODO: use node with smallest change in yaw? if #lp == 0 then
local lp = minetest.find_nodes_in_area_under_air(vector_offset(s, -10, -0.5, -10), vector_offset(s, 10, 1, 10), {"group:solid"})
end
-- TODO: use node with smallest change in yaw instead of random?
lp = #lp > 0 and lp[random(#lp)] lp = #lp > 0 and lp[random(#lp)]
-- did we find land? -- did we find land?
if lp then if lp then