Merge branch 'master' into player-globalstep

This commit is contained in:
AFCMS 2021-04-10 21:20:55 +02:00
commit 753cdb09d7
6 changed files with 180 additions and 139 deletions

View File

@ -1,14 +1,15 @@
--lua locals --lua locals
local get_node = minetest.get_node local get_node = minetest.get_node
local get_item_group = minetest.get_item_group local get_item_group = minetest.get_item_group
local get_node_light = minetest.get_node_light local get_node_light = minetest.get_node_light
local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air
local new_vector = vector.new local get_biome_data = minetest.get_biome_data
local math_random = math.random local new_vector = vector.new
local get_biome_name = minetest.get_biome_name local math_random = math.random
local max = math.max local get_biome_name = minetest.get_biome_name
local max = math.max
local get_objects_inside_radius = minetest.get_objects_inside_radius local get_objects_inside_radius = minetest.get_objects_inside_radius
local vector_distance = vector.distance local vector_distance = vector.distance
-- range for mob count -- range for mob count
local aoc_range = 32 local aoc_range = 32
@ -536,113 +537,87 @@ end
--todo mob limiting --todo mob limiting
--MAIN LOOP --MAIN LOOP
if mobs_spawn then if mobs_spawn then
local timer = 0 local timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
timer = timer + dtime timer = timer + dtime
if timer >= 8 then if timer >= 8 then
timer = 0 timer = 0
for _,player in ipairs(minetest.get_connected_players()) do for _,player in pairs(minetest.get_connected_players()) do
for i = 1,math.random(3,8) do for i = 1,math_random(3,8) do
local player_pos = player:get_pos() local player_pos = player:get_pos()
local _,dimension = mcl_worlds.y_to_layer(player_pos.y) local _,dimension = mcl_worlds.y_to_layer(player_pos.y)
if dimension == "void" or dimension == "default" then if dimension ~= "void" and dimension ~= "default" then
goto continue -- ignore void and unloaded area
end
local min,max = decypher_limits(player_pos.y)
local goal_pos = position_calculation(player_pos) local min,max = decypher_limits(player_pos.y)
local spawning_position_list = find_nodes_in_area_under_air(new_vector(goal_pos.x,min,goal_pos.z), vector.new(goal_pos.x,max,goal_pos.z), {"group:solid", "group:water", "group:lava"})
--couldn't find node local goal_pos = position_calculation(player_pos)
if #spawning_position_list <= 0 then
goto continue local spawning_position_list = find_nodes_in_area_under_air(new_vector(goal_pos.x,min,goal_pos.z), vector.new(goal_pos.x,max,goal_pos.z), {"group:solid", "group:water", "group:lava"})
if #spawning_position_list > 0 then --couldn't find node
local spawning_position = spawning_position_list[math_random(1,#spawning_position_list)]
--Prevent strange behavior/too close to player
if spawning_position and vector_distance(player_pos, spawning_position) > 15 then
local gotten_node = get_node(spawning_position).name
if gotten_node and gotten_node ~= "air" then --skip air nodes
local gotten_biome = get_biome_data(spawning_position)
if gotten_biome then --skip if in unloaded area
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
--grab random mob
local mob_def = spawn_dictionary[math.random(1,#spawn_dictionary)]
if mob_def --skip if something ridiculous happens (nil mob def)
and mob_def.dimension == dimension --skip if not correct dimension
and biome_check(mob_def.biomes, gotten_biome) then --skip if not in correct biome
--add this so mobs don't spawn inside nodes
spawning_position.y = spawning_position.y + 1
if spawning_position.y >= mob_def.min_height and spawning_position.y <= mob_def.max_height then
--only need to poll for node light if everything else worked
local gotten_light = get_node_light(spawning_position)
--don't spawn if not in light limits
if gotten_light >= mob_def.min_light and gotten_light <= mob_def.max_light then
local is_water = get_item_group(gotten_node, "water") ~= 0
local is_lava = get_item_group(gotten_node, "lava") ~= 0
if mob_def.type_of_spawning ~= "ground" or not (is_water or is_lava) then
--finally do the heavy check (for now) of mobs in area
if count_mobs(spawning_position, mob_def.spawn_class) < mob_def.aoc then
--adjust the position for water and lava mobs
if mob_def.type_of_spawning == "water" or mob_def.type_of_spawning == "lava" then
spawning_position.y = spawning_position.y - 1
end
--everything is correct, spawn mob
minetest.add_entity(spawning_position, mob_def.name)
end
end
end
end
end
end
end
end
end
end end
end
local spawning_position = spawning_position_list[math_random(1,#spawning_position_list)] end
end
--Prevent strange behavior/too close to player end)
if not spawning_position or vector_distance(player_pos, spawning_position) < 15 then
goto continue
end
local gotten_node = get_node(spawning_position).name
if not gotten_node or gotten_node == "air" then --skip air nodes
goto continue
end
local gotten_biome = minetest.get_biome_data(spawning_position)
if not gotten_biome then
goto continue --skip if in unloaded area
end
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
--grab random mob
local mob_def = spawn_dictionary[math.random(1,#spawn_dictionary)]
if not mob_def then
goto continue --skip if something ridiculous happens (nil mob def)
end
--skip if not correct dimension
if mob_def.dimension ~= dimension then
goto continue
end
--skip if not in correct biome
if not biome_check(mob_def.biomes, gotten_biome) then
goto continue
end
--add this so mobs don't spawn inside nodes
spawning_position.y = spawning_position.y + 1
if spawning_position.y < mob_def.min_height or spawning_position.y > mob_def.max_height then
goto continue
end
--only need to poll for node light if everything else worked
local gotten_light = get_node_light(spawning_position)
--don't spawn if not in light limits
if gotten_light < mob_def.min_light or gotten_light > mob_def.max_light then
goto continue
end
local is_water = get_item_group(gotten_node, "water") ~= 0
local is_lava = get_item_group(gotten_node, "lava") ~= 0
if mob_def.type_of_spawning == "ground" and is_water then
goto continue
end
if mob_def.type_of_spawning == "ground" and is_lava then
goto continue
end
--finally do the heavy check (for now) of mobs in area
if count_mobs(spawning_position, mob_def.spawn_class) >= mob_def.aoc then
goto continue
end
--adjust the position for water and lava mobs
if mob_def.type_of_spawning == "water" or mob_def.type_of_spawning == "lava" then
spawning_position.y = spawning_position.y - 1
end
--everything is correct, spawn mob
minetest.add_entity(spawning_position, mob_def.name)
::continue:: --this is a safety catch
end
end
end
end)
end end

View File

@ -61,6 +61,22 @@ mobs:register_mob("mobs_mc:enderdragon", {
ignores_nametag = true, ignores_nametag = true,
do_custom = function(self) do_custom = function(self)
mcl_bossbars.update_boss(self, "Ender Dragon", "light_purple") mcl_bossbars.update_boss(self, "Ender Dragon", "light_purple")
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 80)) do
local luaentity = obj:get_luaentity()
if luaentity and luaentity.name == "mcl_end:crystal" then
if luaentity.beam then
if luaentity.beam == self.beam then
break
end
else
if self.beam then
self.beam:remove()
end
minetest.add_entity(self.object:get_pos(), "mcl_end:crystal_beam"):get_luaentity():init(self.object, obj)
break
end
end
end
if self._portal_pos then if self._portal_pos then
-- migrate old format -- migrate old format
if type(self._portal_pos) == "string" then if type(self._portal_pos) == "string" then

View File

@ -346,29 +346,28 @@ mobs:register_mob("mobs_mc:enderman", {
--skip player if they have no data - log it --skip player if they have no data - log it
if not player_eye_height then if not player_eye_height then
minetest.log("error", "Enderman at location: ".. dump(enderpos).." has indexed a null player!") minetest.log("error", "Enderman at location: ".. dump(enderpos).." has indexed a null player!")
goto continue else
end
--calculate very quickly the exact location the player is looking --calculate very quickly the exact location the player is looking
--within the distance between the two "heads" (player and enderman) --within the distance between the two "heads" (player and enderman)
local look_pos = vector.new(player_pos.x, player_pos.y + player_eye_height, player_pos.z) local look_pos = vector.new(player_pos.x, player_pos.y + player_eye_height, player_pos.z)
local look_pos_base = look_pos local look_pos_base = look_pos
local ender_eye_pos = vector.new(enderpos.x, enderpos.y + 2.75, enderpos.z) local ender_eye_pos = vector.new(enderpos.x, enderpos.y + 2.75, enderpos.z)
local eye_distance_from_player = vector.distance(ender_eye_pos, look_pos) local eye_distance_from_player = vector.distance(ender_eye_pos, look_pos)
look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player)) look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player))
--if looking in general head position, turn hostile --if looking in general head position, turn hostile
if minetest.line_of_sight(ender_eye_pos, look_pos_base) and vector.distance(look_pos, ender_eye_pos) <= 0.4 then if minetest.line_of_sight(ender_eye_pos, look_pos_base) and vector.distance(look_pos, ender_eye_pos) <= 0.4 then
self.provoked = "staring" self.provoked = "staring"
self.attack = minetest.get_player_by_name(obj:get_player_name()) self.attack = minetest.get_player_by_name(obj:get_player_name())
break break
else -- I'm not sure what this part does, but I don't want to break anything - jordan4ibanez else -- I'm not sure what this part does, but I don't want to break anything - jordan4ibanez
if self.provoked == "staring" then if self.provoked == "staring" then
self.provoked = "broke_contact" self.provoked = "broke_contact"
end end
end
end end
::continue:: -- this is a sweep over statement, this can be used to continue even when errors occurred
end end
end end
end end

View File

@ -36,12 +36,12 @@ end
local last_id = 0 local last_id = 0
function mcl_bossbars.add_bar(player, def) function mcl_bossbars.add_bar(player, def, dynamic, priority)
local name = player:get_player_name() local name = player:get_player_name()
local bars = mcl_bossbars.bars[name] local bars = mcl_bossbars.bars[name]
local bar = {text = def.text} local bar = {text = def.text, priority = priority or 0}
bar.color, bar.image = get_color_info(def.color, def.percentage) bar.color, bar.image = get_color_info(def.color, def.percentage)
if def.dynamic then if dynamic then
for _, other in pairs(bars) do for _, other in pairs(bars) do
if not other.id and other.color == bar.color and (other.original_text or other.text) == bar.text and other.image == bar.image then if not other.id and other.color == bar.color and (other.original_text or other.text) == bar.text and other.image == bar.image then
if not other.count then if not other.count then
@ -55,7 +55,7 @@ function mcl_bossbars.add_bar(player, def)
end end
end end
table.insert(bars, bar) table.insert(bars, bar)
if not def.dynamic then if not dynamic then
bar.raw_color = def.color bar.raw_color = def.color
bar.id = last_id + 1 bar.id = last_id + 1
last_id = bar.id last_id = bar.id
@ -69,10 +69,11 @@ function mcl_bossbars.remove_bar(id)
mcl_bossbars.static[id] = nil mcl_bossbars.static[id] = nil
end end
function mcl_bossbars.update_bar(id, def) function mcl_bossbars.update_bar(id, def, priority)
local old = mcl_bossbars.static[id] local old = mcl_bossbars.static[id]
old.color = get_color_info(def.color or old.raw_color, def.percentage or old.percentage) old.color = get_color_info(def.color or old.raw_color, def.percentage or old.percentage)
old.text = def.text or old.text old.text = def.text or old.text
old.priority = priority or old.priority
end end
function mcl_bossbars.update_boss(luaentity, name, color) function mcl_bossbars.update_boss(luaentity, name, color)
@ -81,14 +82,15 @@ function mcl_bossbars.update_boss(luaentity, name, color)
text = luaentity.nametag, text = luaentity.nametag,
percentage = math.floor(luaentity.health / luaentity.hp_max * 100), percentage = math.floor(luaentity.health / luaentity.hp_max * 100),
color = color, color = color,
dynamic = true,
} }
if not bardef.text or bardef.text == "" then if not bardef.text or bardef.text == "" then
bardef.text = name bardef.text = name
end end
for _, obj in pairs(minetest.get_objects_inside_radius(object:get_pos(), 128)) do local pos = object:get_pos()
if obj:is_player() then for _, player in pairs(minetest.get_connected_players()) do
mcl_bossbars.add_bar(obj, bardef) local d = vector.distance(pos, player:get_pos())
if d <= 80 then
mcl_bossbars.add_bar(player, bardef, true, d)
end end
end end
end end
@ -115,6 +117,7 @@ minetest.register_globalstep(function()
local name = player:get_player_name() local name = player:get_player_name()
local bars = mcl_bossbars.bars[name] local bars = mcl_bossbars.bars[name]
local huds = mcl_bossbars.huds[name] local huds = mcl_bossbars.huds[name]
table.sort(bars, function(a, b) return a.priority < b.priority end)
local huds_new = {} local huds_new = {}
local bars_new = {} local bars_new = {}
local i = 0 local i = 0

View File

@ -79,6 +79,54 @@ minetest.register_entity("mcl_end:crystal", {
_hittable_by_projectile = true _hittable_by_projectile = true
}) })
minetest.register_entity("mcl_end:crystal_beam", {
initial_properties = {
physical = false,
visual = "cube",
visual_size = {x = 1, y = 1, z = 1},
textures = {
"mcl_end_crystal_beam.png^[transformR90",
"mcl_end_crystal_beam.png^[transformR90",
"mcl_end_crystal_beam.png",
"mcl_end_crystal_beam.png",
"blank.png",
"blank.png",
},
static_save = false,
},
spin = 0,
init = function(self, dragon, crystal)
self.dragon, self.crystal = dragon, crystal
crystal:get_luaentity().beam = self.object
dragon:get_luaentity().beam = self.object
end,
on_deactivate = function(self)
if self.crystal and self.crystal:get_luaentity() then
self.crystal:get_luaentity().beam = nil
end
if self.dragon and self.dragon:get_luaentity() then
self.dragon:get_luaentity().beam = nil
end
end,
on_step = function(self, dtime)
if self.dragon and self.dragon:get_luaentity() and self.crystal and self.crystal:get_luaentity() then
self.spin = self.spin + dtime * math.pi * 2 / 4
local dragon_pos, crystal_pos = self.dragon:get_pos(), self.crystal:get_pos()
dragon_pos.y = dragon_pos.y + 4
crystal_pos.y = crystal_pos.y + 2
self.object:set_pos(vector.divide(vector.add(dragon_pos, crystal_pos), 2))
local rot = vector.dir_to_rotation(vector.direction(dragon_pos, crystal_pos))
rot.z = self.spin
self.object:set_rotation(rot)
self.object:set_properties({visual_size = {x = 0.5, y = 0.5, z = vector.distance(dragon_pos, crystal_pos)}})
else
self.object:remove()
end
end,
})
minetest.register_craftitem("mcl_end:crystal", { minetest.register_craftitem("mcl_end:crystal", {
inventory_image = "mcl_end_crystal_item.png", inventory_image = "mcl_end_crystal_item.png",
description = S("End Crystal"), description = S("End Crystal"),

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB