From d923f71c92ca5d293e6dc75d2b1c76a5b0e1e783 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Thu, 30 Jan 2020 18:04:50 +0100 Subject: [PATCH] Teach mobs how to not walk into danger ... kinda --- mods/ENTITIES/mcl_mobs/api.lua | 87 +++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 27 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 03adf9ad7..b736bf6fb 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -265,6 +265,35 @@ function mobs:set_animation(self, anim) set_animation(self, anim) end +-- Returns true is node can deal damage to self +local is_node_dangerous = function(self, nodename) + local nn = nodename + if self.water_damage > 0 then + if minetest.get_item_group(nn, "water") ~= 0 then + return true + end + end + if self.lava_damage > 0 then + if minetest.get_item_group(nn, "lava") ~= 0 then + return true + end + end + if self.fire_damage > 0 then + if minetest.get_item_group(nn, "fire") ~= 0 then + return true + end + end + if minetest.registered_nodes[nn].drowning > 0 then + if self.breath_max ~= -1 then + return true + end + end + if minetest.registered_nodes[nn].damage_per_second > 0 then + return true + end + return false +end + -- check line of sight (BrunoMine) local line_of_sight = function(self, pos1, pos2, stepsize) @@ -618,8 +647,8 @@ local within_limits = function(pos, radius) end --- is mob facing a cliff -local is_at_cliff = function(self) +-- is mob facing a cliff or danger +local is_at_cliff_or_danger = function(self) if self.fear_height == 0 then -- 0 for no falling protection! return false @@ -631,12 +660,20 @@ local is_at_cliff = function(self) local pos = self.object:get_pos() local ypos = pos.y + self.collisionbox[2] -- just above floor - if minetest.line_of_sight( + local free_fall, blocker = minetest.line_of_sight( {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, - {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z} - , 1) then - + {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}) + if free_fall then return true + else + local bnode = minetest.get_node(blocker) + local danger = is_node_dangerous(self, bnode.name) + if danger then + return true + else + local def = minetest.registered_nodes[bnode.name] + return (not def and def.walkable) + end end return false @@ -728,7 +765,7 @@ local do_env_damage = function(self) local nodef = minetest.registered_nodes[self.standing_in] -- rain - if self.rain_damage and mod_weather then + if self.rain_damage > 0 and mod_weather then if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then self.health = self.health - self.rain_damage @@ -741,7 +778,7 @@ local do_env_damage = function(self) pos.y = pos.y + 1 -- for particle effect position -- water damage - if self.water_damage + if self.water_damage > 0 and nodef.groups.water then if self.water_damage ~= 0 then @@ -755,7 +792,7 @@ local do_env_damage = function(self) end -- lava damage - elseif self.lava_damage + elseif self.lava_damage > 0 and (nodef.groups.lava) then if self.lava_damage ~= 0 then @@ -769,7 +806,7 @@ local do_env_damage = function(self) end -- fire damage - elseif self.fire_damage + elseif self.fire_damage > 0 and (nodef.groups.fire) then if self.fire_damage ~= 0 then @@ -1900,7 +1937,7 @@ local do_states = function(self, dtime) if self.walk_chance ~= 0 and self.facing_fence ~= true and random(1, 100) <= self.walk_chance - and is_at_cliff(self) == false then + and is_at_cliff_or_danger(self) == false then set_velocity(self, self.walk_velocity) self.state = "walk" @@ -1934,18 +1971,12 @@ local do_states = function(self, dtime) end + local is_in_danger = false if lp then - local def = minetest.registered_nodes[self.standing_in] - local def2 = minetest.registered_nodes[self.standing_on] -- If mob in or on dangerous block, look for land - if (self.breath_max ~= -1 - and (def.drowning > 0 or def2.drowning > 0)) - or (self.lava_damage - and (def.groups.lava or def2.groups.lava)) - or (self.water_damage - and (def.groups.water or def2.groups.water)) - or (self.fire_damage - and (def.groups.fire or def2.groups.fire)) then + if (is_node_dangerous(self, self.standing_in) or + is_node_dangerous(self, self.standing_on)) then + is_in_danger = true lp = minetest.find_node_near(s, 5, {"group:solid"}) @@ -1988,11 +2019,13 @@ local do_states = function(self, dtime) yaw = set_yaw(self, yaw, 8) end - -- stand for great fall in front - local temp_is_cliff = is_at_cliff(self) - + -- stand for great fall or danger or fence in front + local cliff_or_danger = false + if is_in_danger then + cliff_or_danger = is_at_cliff_or_danger(self) + end if self.facing_fence == true - or temp_is_cliff + or cliff_or_danger or random(1, 100) <= 30 then set_velocity(self, 0) @@ -2019,7 +2052,7 @@ local do_states = function(self, dtime) -- stop after 5 seconds or when at cliff if self.runaway_timer > 5 - or is_at_cliff(self) then + or is_at_cliff_or_danger(self) then self.runaway_timer = 0 set_velocity(self, 0) self.state = "stand" @@ -2264,7 +2297,7 @@ local do_states = function(self, dtime) smart_mobs(self, s, p, dist, dtime) end - if is_at_cliff(self) then + if is_at_cliff_or_danger(self) then set_velocity(self, 0) set_animation(self, "stand")