diff --git a/api.lua b/api.lua index 2336cfa..7d96090 100644 --- a/api.lua +++ b/api.lua @@ -1,5 +1,5 @@ --- Mobs Api (7th January 2017) +-- Mobs Api (17th January 2017) mobs = {} mobs.mod = "redo" @@ -208,6 +208,96 @@ set_animation = function(self, type) end end +-- Get distance +local get_distance = function(a, b) + + local x, y, z = a.x - b.x, a.y - b.y, a.z - b.z + + return square(x * x + y * y + z * z) +end + + +-- check line of sight (BrunoMine) +function line_of_sight(self, pos1, pos2, stepsize) + + stepsize = stepsize or 1 + + local s, pos = minetest.line_of_sight(pos1, pos2, stepsize) + + -- normal walking and flying mobs can see you through air + if s == true then + return true + end + + -- New pos1 to be analyzed + local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} + + local r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + + -- Checks the return + if r == true then return true end + + -- Nodename found + local nn = minetest.get_node(pos).name + + -- Target Distance (td) to travel + local td = get_distance(pos1, pos2) + + -- Actual Distance (ad) traveled + local ad = 0 + + -- It continues to advance in the line of sight in search of a real obstruction. + while minetest.registered_nodes[nn] + and minetest.registered_nodes[nn].walkable == false do + + -- Check if you can still move forward + if td < ad + stepsize then + return true -- Reached the target + end + + -- Moves the analyzed pos + local d = get_distance(pos1, pos2) + npos1.x = ((pos2.x - pos1.x) / d * stepsize) + pos1.x + npos1.y = ((pos2.y - pos1.y) / d * stepsize) + pos1.y + npos1.z = ((pos2.z - pos1.z) / d * stepsize) + pos1.z + + ad = ad + stepsize + + -- scan again + r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + + if r == true then return true end + + -- New Nodename found + nn = minetest.get_node(pos).name + + end + + return false +end + + +-- are we flying in what we are suppose to? (taikedz) +local function flight_check(self, pos_w) + + local nod = minetest.get_node(pos_w).name + + if type(self.fly_in) == "string" + and ( nod == self.fly_in or nod == self.fly_in:gsub("_source", "_flowing") ) then + + return true + + elseif type(self.fly_in) == "table" then + + for _,fly_in in pairs(self.fly_in) do + + if nod == fly_in or nod == fly_in:gsub("_source", "_flowing") then + return true + end + end + end +end + -- check line of sight for walkers and swimmers alike function line_of_sight_water(self, pos1, pos2, stepsize) @@ -235,13 +325,8 @@ function line_of_sight_water(self, pos1, pos2, stepsize) -- just incase we have a special node for flying/swimming mobs elseif s == false and self.fly - and self.fly_in then - - local nod = minetest.get_node(pos_w).name - - if nod == self.fly_in then - return true - end + and flight_check(self, pos_w) then + return true end return false @@ -1063,7 +1148,8 @@ local monster_attack = function(self) -- field of view check goes here -- choose closest player to attack - if line_of_sight_water(self, sp, p, 2) == true +-- if line_of_sight_water(self, sp, p, 2) == true + if line_of_sight(self, sp, p, 2) == true and dist < min_dist then min_dist = dist min_player = player @@ -1222,17 +1308,20 @@ local follow_flop = function(self) end end - -- water swimmers flop when on land - if self.fly - and self.fly_in == "default:water_source" - and self.standing_in ~= self.fly_in then + -- swimmers flop when out of their element, and swim again when back in + if self.fly then + local s = self.object:getpos() + if not flight_check(self, s) then - self.state = "flop" - self.object:setvelocity({x = 0, y = -5, z = 0}) + self.state = "flop" + self.object:setvelocity({x = 0, y = -5, z = 0}) - set_animation(self, "stand") + set_animation(self, "stand") - return + return + elseif self.state == "flop" then + self.state = "stand" + end end end @@ -1554,7 +1643,8 @@ local do_states = function(self, dtime) local p_y = floor(p2.y + 1) local v = self.object:getvelocity() - if nod.name == self.fly_in then +-- if nod.name == self.fly_in then + if flight_check(self, s) then if me_y < p_y then @@ -1692,7 +1782,8 @@ local do_states = function(self, dtime) p2.y = p2.y + .5--1.5 s2.y = s2.y + .5--1.5 - if line_of_sight_water(self, p2, s2) == true then +-- if line_of_sight_water(self, p2, s2) == true then + if line_of_sight(self, p2, s2) == true then -- play attack sound mob_sound(self, self.sounds.attack)