From b7ba16f4cdf9a50cd59ba6215ff113e1ff6dc231 Mon Sep 17 00:00:00 2001 From: Alexander Minges Date: Fri, 1 May 2020 14:56:29 +0200 Subject: [PATCH 1/3] fix detection of dangerous location for flying mobs --- mods/ENTITIES/mcl_mobs/api.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 4a4a56bb..c027ce16 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -2032,11 +2032,21 @@ local do_states = function(self, dtime) local is_in_danger = false if lp then - -- If mob in or on dangerous block, look for land - if (is_node_dangerous(self, self.standing_in) or + -- if mob is flying, check if it is in its preferred medium + if self.fly then + if minetest.get_item_group(self.standing_in, self.fly_in) then + is_in_danger = false + elseif is_node_dangerous(self, self.standing_in) then + is_in_danger = true + end + elseif (is_node_dangerous(self, self.standing_in) or is_node_dangerous(self, self.standing_on)) then 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) + minetest.log(self.water_damage) lp = minetest.find_node_near(s, 5, {"group:solid"}) -- did we find land? From faea58469f1b01ec9d786491e2ca87405142862f Mon Sep 17 00:00:00 2001 From: Alexander Minges Date: Fri, 1 May 2020 18:18:35 +0200 Subject: [PATCH 2/3] refactor code; adjust checks for dangerous blocks --- mods/ENTITIES/mcl_mobs/api.lua | 66 +++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index c027ce16..cb936510 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -300,6 +300,11 @@ end -- Returns true is node can deal damage to self local is_node_dangerous = function(self, 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 minetest.get_item_group(nn, "water") ~= 0 then return true @@ -317,7 +322,10 @@ local is_node_dangerous = function(self, nodename) end if minetest.registered_nodes[nn].drowning > 0 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 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 and self.lava_damage > 0) or self.breath_max ~= -1 then - - lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"}) + -- water-breathing mobs don't have to avoid water, but air + 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 @@ -2032,44 +2044,42 @@ local do_states = function(self, dtime) local is_in_danger = false if lp then - -- if mob is flying, check if it is in its preferred medium - if self.fly then - if minetest.get_item_group(self.standing_in, self.fly_in) then - is_in_danger = false - elseif is_node_dangerous(self, self.standing_in) then + minetest.log(self.name .. ": " .. minetest.get_node(lp).name) + -- 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 (is_node_dangerous(self, self.standing_in) or + elseif not self.fly and (is_node_dangerous(self, self.standing_in) or is_node_dangerous(self, self.standing_on)) then 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) - minetest.log(self.water_damage) + -- 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"}) -- did we find land? if lp then local nn = minetest.get_node(lp).name - if is_node_dangerous(self, nn) then - -- is the chosen destination safe? Retry if not (max 10 iterations) - local i = 0 - while i < 10 do - if lp then - nn = minetest.get_node(lp).name - minetest.log("Found solid block: " .. nn) - if not is_node_dangerous(self, nn) then break - end - -- look for solid node 5 blocks around the mob's position - elseif i < 5 then - lp = minetest.find_node_near(s, 5, {"group:solid"}) - -- after 5 iterations double search radius - elseif i < 10 then - lp = minetest.find_node_near(s, 10, {"group:solid"}) - end - i = i + 1 + -- minetest.log(self.name .. " found land: " .. nn) + + -- is the chosen destination safe and walkable? Retry if not (max 10 iterations) + local i = 0 + while i < 10 do + if lp then + nn = minetest.get_node(lp).name + -- minetest.log("Found solid block: " .. nn) + if not is_node_dangerous(self, nn) and minetest.registered_nodes[nn].walkable then break end + -- look for solid node 5 blocks around the mob's position + elseif i < 5 then + lp = minetest.find_node_near(s, 5, {"group:solid"}) + -- after 5 iterations double search radius + elseif i < 10 then + lp = minetest.find_node_near(s, 10, {"group:solid"}) + end + i = i + 1 end local vec = { From 8180f79d6cd06a6189ebb74a570899771ce63711 Mon Sep 17 00:00:00 2001 From: Alexander Minges Date: Fri, 1 May 2020 22:39:11 +0200 Subject: [PATCH 3/3] try to fix mobs stuck forever in water --- mods/ENTITIES/mcl_mobs/api.lua | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index cb936510..0cf10941 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -2044,7 +2044,7 @@ local do_states = function(self, dtime) local is_in_danger = false if lp then - minetest.log(self.name .. ": " .. minetest.get_node(lp).name) + -- minetest.log(self.name .. ": " .. minetest.get_node(lp).name) -- if mob is flying, only check the block it is inside if self.fly then if is_node_dangerous(self, self.standing_in) then @@ -2066,17 +2066,35 @@ local do_states = function(self, dtime) -- is the chosen destination safe and walkable? Retry if not (max 10 iterations) local i = 0 - while i < 10 do + local max_i = 10 + while i < max_i do + local node_above_ok = false if lp then nn = minetest.get_node(lp).name - -- minetest.log("Found solid block: " .. nn) - if not is_node_dangerous(self, nn) and minetest.registered_nodes[nn].walkable then break + 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 + if not is_node_dangerous(self, nn) and minetest.registered_nodes[nn].walkable and node_above_ok then + minetest.log(self.name .. ": Found solid block: " .. nn .. " Above: " .. nn_above) + break end -- look for solid node 5 blocks around the mob's position - elseif i < 5 then + elseif i < (max_i / 2) then lp = minetest.find_node_near(s, 5, {"group:solid"}) -- after 5 iterations double search radius - elseif i < 10 then + elseif i < max_i then lp = minetest.find_node_near(s, 10, {"group:solid"}) end i = i + 1