Compare commits

...
Sign in to create a new pull request.

3 commits

View file

@ -300,6 +300,11 @@ end
-- Returns true is node can deal damage to self -- Returns true is node can deal damage to self
local is_node_dangerous = function(self, nodename) local is_node_dangerous = function(self, nodename)
local nn = nodename local nn = nodename
if self.fly then
if not minetest.get_item_group(nn, self.fly_in) then
return true
end
end
if self.water_damage > 0 then if self.water_damage > 0 then
if minetest.get_item_group(nn, "water") ~= 0 then if minetest.get_item_group(nn, "water") ~= 0 then
return true return true
@ -317,7 +322,10 @@ local is_node_dangerous = function(self, nodename)
end end
if minetest.registered_nodes[nn].drowning > 0 then if minetest.registered_nodes[nn].drowning > 0 then
if self.breath_max ~= -1 then if self.breath_max ~= -1 then
return true -- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case
if not self.breathes_in_water and minetest.get_item_group(nn, "water") ~= 0 then
return true
end
end end
end end
if minetest.registered_nodes[nn].damage_per_second > 0 then if minetest.registered_nodes[nn].damage_per_second > 0 then
@ -2013,8 +2021,12 @@ local do_states = function(self, dtime)
if (self.water_damage > 0 if (self.water_damage > 0
and self.lava_damage > 0) and self.lava_damage > 0)
or self.breath_max ~= -1 then or self.breath_max ~= -1 then
-- water-breathing mobs don't have to avoid water, but air
lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"}) if self.breathes_in_water then
lp = minetest.find_node_near(s, 1, {"air", "group:lava"})
else
lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"})
end
elseif self.water_damage > 0 then elseif self.water_damage > 0 then
@ -2032,34 +2044,60 @@ local do_states = function(self, dtime)
local is_in_danger = false local is_in_danger = false
if lp then if lp then
-- If mob in or on dangerous block, look for land -- minetest.log(self.name .. ": " .. minetest.get_node(lp).name)
if (is_node_dangerous(self, self.standing_in) or -- if mob is flying, only check the block it is inside
if self.fly then
if is_node_dangerous(self, self.standing_in) then
is_in_danger = true
end
elseif not self.fly and (is_node_dangerous(self, self.standing_in) or
is_node_dangerous(self, self.standing_on)) then is_node_dangerous(self, self.standing_on)) then
is_in_danger = true is_in_danger = true
end
-- If mob in or on dangerous block, look for land
if is_in_danger then
-- minetest.log(self.name .. " is in/on dangerous node " .. self.standing_on .. " or " .. self.standing_in)
lp = minetest.find_node_near(s, 5, {"group:solid"}) lp = minetest.find_node_near(s, 5, {"group:solid"})
-- did we find land? -- did we find land?
if lp then if lp then
local nn = minetest.get_node(lp).name local nn = minetest.get_node(lp).name
if is_node_dangerous(self, nn) then -- minetest.log(self.name .. " found land: " .. nn)
-- is the chosen destination safe? Retry if not (max 10 iterations)
local i = 0 -- is the chosen destination safe and walkable? Retry if not (max 10 iterations)
while i < 10 do local i = 0
if lp then local max_i = 10
nn = minetest.get_node(lp).name while i < max_i do
minetest.log("Found solid block: " .. nn) local node_above_ok = false
if not is_node_dangerous(self, nn) then break if lp then
nn = minetest.get_node(lp).name
local pos = {x = lp.x, y = lp.y + 2, z = lp.z}
local node_above = minetest.get_node(pos)
local nn_above = node_above.name
minetest.log("Node: " .. nn .. " Node above: " .. nn_above)
if self.breath_max ~= -1 then
-- water-breathing mobs don't have to avoid water, but air
if self.breathes_in_water and minetest.get_item_group(nn_above, "water") then
node_above_ok = true
elseif not self.breathes_in_water and nn_above == "air" then
node_above_ok = true
end
else
node_above_ok = true
end end
-- look for solid node 5 blocks around the mob's position if not is_node_dangerous(self, nn) and minetest.registered_nodes[nn].walkable and node_above_ok then
elseif i < 5 then minetest.log(self.name .. ": Found solid block: " .. nn .. " Above: " .. nn_above)
lp = minetest.find_node_near(s, 5, {"group:solid"}) break
-- after 5 iterations double search radius
elseif i < 10 then
lp = minetest.find_node_near(s, 10, {"group:solid"})
end
i = i + 1
end end
-- look for solid node 5 blocks around the mob's position
elseif i < (max_i / 2) then
lp = minetest.find_node_near(s, 5, {"group:solid"})
-- after 5 iterations double search radius
elseif i < max_i then
lp = minetest.find_node_near(s, 10, {"group:solid"})
end
i = i + 1
end end
local vec = { local vec = {