mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-30 14:31:07 +01:00
112 lines
No EOL
3.1 KiB
Lua
112 lines
No EOL
3.1 KiB
Lua
local minetest_line_of_sight = minetest.line_of_sight
|
|
local minetest_dir_to_yaw = minetest.dir_to_yaw
|
|
local minetest_yaw_to_dir = minetest.yaw_to_dir
|
|
local minetest_get_node = minetest.get_node
|
|
local minetest_get_item_group = minetest.get_item_group
|
|
|
|
local vector_new = vector.new
|
|
local vector_multiply = vector.multiply
|
|
|
|
-- default function when mobs are blown up with TNT
|
|
local do_tnt = function(obj, damage)
|
|
|
|
obj.object:punch(obj.object, 1.0, {
|
|
full_punch_interval = 1.0,
|
|
damage_groups = {fleshy = damage},
|
|
}, nil)
|
|
|
|
return false, true, {}
|
|
end
|
|
|
|
--a fast function to be able to detect only players without using objects_in_radius
|
|
mobs.detect_closest_player_within_radius = function(self, line_of_sight, radius, object_height_adder)
|
|
|
|
line_of_sight = line_of_sight or true --fallback line_of_sight
|
|
radius = radius or 10 -- fallback radius
|
|
object_height_adder = object_height_adder or 0 --fallback entity (y height) addition for line of sight
|
|
|
|
local pos1 = self.object:get_pos()
|
|
local players_in_area = {}
|
|
local winner_player = nil
|
|
local players_detected = 0
|
|
|
|
--get players in radius
|
|
for _,player in pairs(minetest.get_connected_players()) do
|
|
if player and player:get_hp() > 0 then
|
|
|
|
local pos2 = player:get_pos()
|
|
|
|
local distance = vector.distance(pos1,pos2)
|
|
|
|
if distance <= radius then
|
|
if line_of_sight then
|
|
--must add eye height or stuff breaks randomly because of
|
|
--seethrough nodes being a blocker (like grass)
|
|
if minetest_line_of_sight(
|
|
vector_new(pos1.x, pos1.y + object_height_adder, pos1.z),
|
|
vector_new(pos2.x, pos2.y + player:get_properties().eye_height, pos2.z)
|
|
) then
|
|
players_detected = players_detected + 1
|
|
players_in_area[player] = distance
|
|
end
|
|
else
|
|
players_detected = players_detected + 1
|
|
players_in_area[player] = distance
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
--return if there's no one near by
|
|
if players_detected <= 0 then --handle negative numbers for some crazy error that could possibly happen
|
|
return nil
|
|
end
|
|
|
|
--do a default radius max
|
|
local shortest_disance = radius + 1
|
|
|
|
--sort through players and find the closest player
|
|
for player,distance in pairs(players_in_area) do
|
|
if distance < shortest_disance then
|
|
shortest_disance = distance
|
|
winner_player = player
|
|
end
|
|
end
|
|
|
|
return(winner_player)
|
|
end
|
|
|
|
|
|
--check if a mob needs to jump
|
|
mobs.jump_check = function(self,dtime)
|
|
|
|
local pos = self.object:get_pos()
|
|
pos.y = pos.y + 0.1
|
|
local dir = minetest_yaw_to_dir(self.yaw)
|
|
|
|
local collisionbox = self.object:get_properties().collisionbox
|
|
local radius = collisionbox[4] + 0.5
|
|
|
|
vector_multiply(dir, radius)
|
|
|
|
--only jump if there's a node and a non-solid node above it
|
|
local test_dir = vector.add(pos,dir)
|
|
|
|
local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0
|
|
|
|
test_dir.y = test_dir.y + 1
|
|
|
|
local green_flag_2 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") == 0
|
|
|
|
if green_flag_1 and green_flag_2 then
|
|
--can jump over node
|
|
return(1)
|
|
elseif green_flag_1 and not green_flag_2 then
|
|
--wall in front of mob
|
|
return(2)
|
|
end
|
|
|
|
--nothing to jump over
|
|
return(0)
|
|
end |