forked from MineClone5/MineClone5
Merge testing into master
This commit is contained in:
commit
05e739390e
|
@ -18,12 +18,7 @@ local S = minetest.get_translator("extra_mobs")
|
||||||
--################### fox
|
--################### fox
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
local followitem = ""
|
local followitem = "mcl_farming:sweet_berry"
|
||||||
if minetest.get_modpath("mc_sweet_berry") then
|
|
||||||
followitem = "mc_sweet_berry:sweet_berry"
|
|
||||||
else
|
|
||||||
followitem = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local fox = {
|
local fox = {
|
||||||
type = "monster",
|
type = "monster",
|
||||||
|
@ -123,11 +118,9 @@ local fox = {
|
||||||
mobs:register_mob("extra_mobs:fox", fox)
|
mobs:register_mob("extra_mobs:fox", fox)
|
||||||
|
|
||||||
-- spawning
|
-- spawning
|
||||||
mobs:spawn_specific(
|
mobs:spawn_setup({
|
||||||
"extra_mobs:fox",
|
name = "extra_mobs:fox",
|
||||||
"overworld",
|
biomes = {
|
||||||
"ground",
|
|
||||||
{
|
|
||||||
"FlowerForest",
|
"FlowerForest",
|
||||||
"Swampland",
|
"Swampland",
|
||||||
"Taiga",
|
"Taiga",
|
||||||
|
@ -145,13 +138,10 @@ mobs:spawn_specific(
|
||||||
"ExtremeHillsM",
|
"ExtremeHillsM",
|
||||||
"BirchForestM",
|
"BirchForestM",
|
||||||
},
|
},
|
||||||
0,
|
interval = 30,
|
||||||
minetest.LIGHT_MAX+1,
|
chance = 6000,
|
||||||
30,
|
min_height = mobs_mc.spawn_height.water,
|
||||||
6000,
|
})
|
||||||
3,
|
|
||||||
mobs_mc.spawn_height.water,
|
|
||||||
mobs_mc.spawn_height.overworld_max)
|
|
||||||
|
|
||||||
--mobs:spawn_specific("extra_mobs:fox", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 6000, 3, 0, 500)
|
--mobs:spawn_specific("extra_mobs:fox", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 6000, 3, 0, 500)
|
||||||
--[[
|
--[[
|
||||||
|
|
|
@ -54,10 +54,11 @@ minetest.register_entity("extra_mobs:glow_item_frame_item",{
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
if not self then return end
|
||||||
if self._nodename ~= nil and self._texture ~= nil then
|
if self._nodename ~= nil and self._texture ~= nil then
|
||||||
local ret = self._nodename .. ';' .. self._texture
|
local ret = self._nodename .. ';' .. self._texture
|
||||||
if self._scale ~= nil then
|
if self._scale ~= nil then
|
||||||
ret = ret .. ';' .. self._scale
|
ret = ret .. ';' .. tostring(self._scale)
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
|
@ -213,20 +213,36 @@ baby_strider.child = 1
|
||||||
mobs:register_mob("extra_mobs:baby_strider", baby_strider)
|
mobs:register_mob("extra_mobs:baby_strider", baby_strider)
|
||||||
|
|
||||||
-- Regular spawning in the Nether
|
-- Regular spawning in the Nether
|
||||||
mobs:spawn_specific(
|
|
||||||
"extra_mobs:strider",
|
mobs:spawn_setup({
|
||||||
"nether",
|
name = "extra_mobs:strider",
|
||||||
"lava",
|
type_of_spawning = "lava",
|
||||||
{
|
dimension = "nether",
|
||||||
|
biomes = {
|
||||||
"Nether"
|
"Nether"
|
||||||
},
|
},
|
||||||
0,
|
min_height = mcl_mapgen.nether.min,
|
||||||
minetest.LIGHT_MAX+1,
|
max_height = mcl_mapgen.nether.max,
|
||||||
30,
|
chance = 2000,
|
||||||
6000,
|
check_position = function(pos)
|
||||||
3,
|
return minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z}).name:find("lava")
|
||||||
mobs_mc.spawn_height.nether_min,
|
end
|
||||||
mobs_mc.spawn_height.nether_max)
|
})
|
||||||
|
|
||||||
|
mobs:spawn_setup({
|
||||||
|
name = "extra_mobs:baby_strider",
|
||||||
|
type_of_spawning = "lava",
|
||||||
|
dimension = "nether",
|
||||||
|
biomes = {
|
||||||
|
"Nether"
|
||||||
|
},
|
||||||
|
min_height = mcl_mapgen.nether.min,
|
||||||
|
max_height = mcl_mapgen.nether.max,
|
||||||
|
chance = 100,
|
||||||
|
check_position = function(pos)
|
||||||
|
return minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z}).name:find("lava")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
-- spawn eggs
|
-- spawn eggs
|
||||||
mobs:register_egg("extra_mobs:strider", S("Strider"), "extra_mobs_spawn_icon_strider.png", 0)
|
mobs:register_egg("extra_mobs:strider", S("Strider"), "extra_mobs_spawn_icon_strider.png", 0)
|
||||||
|
|
|
@ -175,10 +175,13 @@ function boat.on_activate(self, staticdata, dtime_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
function boat.get_staticdata(self)
|
function boat.get_staticdata(self)
|
||||||
|
if not self then return end
|
||||||
|
local object = self.object
|
||||||
|
local object_properties = object and object.get_properties and object:get_properties()
|
||||||
return minetest.serialize({
|
return minetest.serialize({
|
||||||
v = self._v,
|
v = self._v,
|
||||||
itemstring = self._itemstring,
|
itemstring = self._itemstring,
|
||||||
textures = self.object:get_properties().textures
|
textures = object_properties and object_properties.textures
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ minetest.register_entity(":__builtin:falling_node", {
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
if not self then return end
|
||||||
local meta = self.meta
|
local meta = self.meta
|
||||||
-- Workaround: Save inventory seperately from metadata.
|
-- Workaround: Save inventory seperately from metadata.
|
||||||
-- Because Minetest crashes when a node with inventory gets deactivated
|
-- Because Minetest crashes when a node with inventory gets deactivated
|
||||||
|
|
|
@ -486,6 +486,7 @@ minetest.register_entity(":__builtin:item", {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
if not self then return end
|
||||||
local data = minetest.serialize({
|
local data = minetest.serialize({
|
||||||
itemstring = self.itemstring,
|
itemstring = self.itemstring,
|
||||||
always_collect = self.always_collect,
|
always_collect = self.always_collect,
|
||||||
|
|
|
@ -503,6 +503,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
||||||
end
|
end
|
||||||
|
|
||||||
function cart:get_staticdata()
|
function cart:get_staticdata()
|
||||||
|
if not self then return end
|
||||||
return minetest.serialize({_railtype = self._railtype})
|
return minetest.serialize({_railtype = self._railtype})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -425,7 +425,9 @@ function mobs:register_mob(name, def)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
if self and mobs then
|
||||||
return mobs.mob_staticdata(self)
|
return mobs.mob_staticdata(self)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--harmed_by_heal = def.harmed_by_heal,
|
--harmed_by_heal = def.harmed_by_heal,
|
||||||
|
|
|
@ -902,10 +902,14 @@ function mobs.mob_step(self, dtime)
|
||||||
object = self.object,
|
object = self.object,
|
||||||
max_hear_distance = 5
|
max_hear_distance = 5
|
||||||
}, true)
|
}, true)
|
||||||
self.object:punch(self.object, 1.0, {
|
--[[ if not mcl_burning.is_burning(self.object) then
|
||||||
|
mcl_burning.set_on_fire(self.object, 1.1)
|
||||||
|
else
|
||||||
|
]] self.object:punch(self.object, 1.0, {
|
||||||
full_punch_interval = 1.0,
|
full_punch_interval = 1.0,
|
||||||
damage_groups = {fleshy = self.lava_damage}
|
damage_groups = {fleshy = self.lava_damage}
|
||||||
}, nil)
|
}, nil)
|
||||||
|
-- end
|
||||||
self.lava_counter = 0
|
self.lava_counter = 0
|
||||||
self.health = self.health - lava_damage
|
self.health = self.health - lava_damage
|
||||||
self:teleport()
|
self:teleport()
|
||||||
|
|
|
@ -211,26 +211,6 @@ mobs.teleport = function(self, target)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--a function used for despawning mobs
|
|
||||||
mobs.check_for_player_within_area = function(self, radius)
|
|
||||||
local pos1 = self.object:get_pos()
|
|
||||||
if not pos1 then return end
|
|
||||||
--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
|
|
||||||
--found a player
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--did not find a player
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--a simple helper function for mobs following
|
--a simple helper function for mobs following
|
||||||
mobs.get_2d_distance = function(pos1,pos2)
|
mobs.get_2d_distance = function(pos1,pos2)
|
||||||
pos1.y = 0
|
pos1.y = 0
|
||||||
|
|
|
@ -5,9 +5,27 @@ local minetest_settings = minetest.settings
|
||||||
-- CMI support check
|
-- CMI support check
|
||||||
local use_cmi = minetest.global_exists("cmi")
|
local use_cmi = minetest.global_exists("cmi")
|
||||||
|
|
||||||
|
local vector_distance = vector.distance
|
||||||
|
local minetest_get_connected_players = minetest.get_connected_players
|
||||||
|
local math_random = math.random
|
||||||
|
|
||||||
mobs.can_despawn = function(self)
|
mobs.can_despawn = function(self)
|
||||||
return (not self.tamed and not self.bred and not self.nametag and
|
if self.tamed or self.bred or self.nametag then return false end
|
||||||
not mobs.check_for_player_within_area(self, 64));
|
local mob_pos = self.object:get_pos()
|
||||||
|
if not mob_pos then return true end
|
||||||
|
local distance = 999
|
||||||
|
for _, player in pairs(minetest_get_connected_players()) do
|
||||||
|
if player and player:get_hp() > 0 then
|
||||||
|
local player_pos = player:get_pos()
|
||||||
|
local new_distance = vector_distance(player_pos, mob_pos)
|
||||||
|
if new_distance < distance then
|
||||||
|
distance = new_distance
|
||||||
|
if distance < 33 then return false end
|
||||||
|
if distance < 128 and math_random(1, 42) ~= 11 then return false end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get entity staticdata
|
-- get entity staticdata
|
||||||
|
@ -24,7 +42,7 @@ mobs.mob_staticdata = function(self)
|
||||||
self.following = nil
|
self.following = nil
|
||||||
|
|
||||||
if use_cmi then
|
if use_cmi then
|
||||||
self.serialized_cmi_components = cmi.serialize_components(self._cmi_components)
|
self.serialized_cmi_components = cmi and cmi.serialize_components(self._cmi_components)
|
||||||
end
|
end
|
||||||
|
|
||||||
local tmp = {}
|
local tmp = {}
|
||||||
|
|
|
@ -6,11 +6,14 @@ local find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air
|
||||||
local get_biome_name = minetest.get_biome_name
|
local get_biome_name = minetest.get_biome_name
|
||||||
local get_objects_inside_radius = minetest.get_objects_inside_radius
|
local get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||||
local get_connected_players = minetest.get_connected_players
|
local get_connected_players = minetest.get_connected_players
|
||||||
|
local minetest_get_perlin = minetest.get_perlin
|
||||||
|
|
||||||
local math_random = math.random
|
local math_random = math.random
|
||||||
local math_floor = math.floor
|
local math_floor = math.floor
|
||||||
--local max = math.max
|
local math_ceil = math.ceil
|
||||||
|
local math_cos = math.cos
|
||||||
|
local math_sin = math.sin
|
||||||
|
local math_round = function(x) return (x > 0) and math_floor(x + 0.5) or math_ceil(x - 0.5) end
|
||||||
|
|
||||||
--local vector_distance = vector.distance
|
--local vector_distance = vector.distance
|
||||||
local vector_new = vector.new
|
local vector_new = vector.new
|
||||||
|
@ -22,18 +25,35 @@ local table_remove = table.remove
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
|
|
||||||
-- range for mob count
|
-- range for mob count
|
||||||
local aoc_range = 48
|
local aoc_range = 32
|
||||||
|
|
||||||
--do mobs spawn?
|
--do mobs spawn?
|
||||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||||
|
|
||||||
--[[
|
|
||||||
|
|
||||||
THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
|
local noise_params = {
|
||||||
|
offset = 0,
|
||||||
|
scale = 3,
|
||||||
|
spread = {
|
||||||
|
x = 301,
|
||||||
|
y = 50,
|
||||||
|
z = 304,
|
||||||
|
},
|
||||||
|
seed = 100,
|
||||||
|
octaves = 3,
|
||||||
|
persistence = 0.5,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
|
||||||
|
-- Also used for missing parameter
|
||||||
|
-- Please update the list when adding new biomes!
|
||||||
|
|
||||||
|
local list_of_all_biomes = {
|
||||||
|
|
||||||
|
-- underground:
|
||||||
|
|
||||||
underground:
|
|
||||||
"FlowerForest_underground",
|
"FlowerForest_underground",
|
||||||
"JungleEdge_underground",local spawning_position = spawning_position_list[math.random(1,#spawning_position_list)]
|
"JungleEdge_underground",
|
||||||
"ColdTaiga_underground",
|
"ColdTaiga_underground",
|
||||||
"IcePlains_underground",
|
"IcePlains_underground",
|
||||||
"IcePlainsSpikes_underground",
|
"IcePlainsSpikes_underground",
|
||||||
|
@ -44,7 +64,8 @@ underground:
|
||||||
"ExtremeHillsM_underground",
|
"ExtremeHillsM_underground",
|
||||||
"JungleEdgeM_underground",
|
"JungleEdgeM_underground",
|
||||||
|
|
||||||
ocean:
|
-- ocean:
|
||||||
|
|
||||||
"RoofedForest_ocean",
|
"RoofedForest_ocean",
|
||||||
"JungleEdgeM_ocean",
|
"JungleEdgeM_ocean",
|
||||||
"BirchForestM_ocean",
|
"BirchForestM_ocean",
|
||||||
|
@ -106,13 +127,15 @@ ocean:
|
||||||
"Taiga_deep_ocean",
|
"Taiga_deep_ocean",
|
||||||
"JungleM_ocean",
|
"JungleM_ocean",
|
||||||
|
|
||||||
water or beach?
|
-- water or beach?
|
||||||
|
|
||||||
"MesaPlateauFM_sandlevel",
|
"MesaPlateauFM_sandlevel",
|
||||||
"MesaPlateauF_sandlevel",
|
"MesaPlateauF_sandlevel",
|
||||||
"MesaBryce_sandlevel",
|
"MesaBryce_sandlevel",
|
||||||
"Mesa_sandlevel",
|
"Mesa_sandlevel",
|
||||||
|
|
||||||
beach:
|
-- beach:
|
||||||
|
|
||||||
"FlowerForest_beach",
|
"FlowerForest_beach",
|
||||||
"Forest_beach",
|
"Forest_beach",
|
||||||
"StoneBeach",
|
"StoneBeach",
|
||||||
|
@ -127,11 +150,13 @@ beach:
|
||||||
"JungleM_shore",
|
"JungleM_shore",
|
||||||
"Jungle_shore",
|
"Jungle_shore",
|
||||||
|
|
||||||
dimension biome:
|
-- dimension biome:
|
||||||
|
|
||||||
"Nether",
|
"Nether",
|
||||||
"End",
|
"End",
|
||||||
|
|
||||||
Overworld regular:
|
-- Overworld regular:
|
||||||
|
|
||||||
"Mesa",
|
"Mesa",
|
||||||
"FlowerForest",
|
"FlowerForest",
|
||||||
"Swampland",
|
"Swampland",
|
||||||
|
@ -164,9 +189,7 @@ Overworld regular:
|
||||||
"MesaBryce",
|
"MesaBryce",
|
||||||
"JungleEdge",
|
"JungleEdge",
|
||||||
"SavannaM",
|
"SavannaM",
|
||||||
]]--
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- count how many mobs are in an area
|
-- count how many mobs are in an area
|
||||||
local function count_mobs(pos)
|
local function count_mobs(pos)
|
||||||
|
@ -216,11 +239,73 @@ WARNING: BIOME INTEGRATION NEEDED -> How to get biome through lua??
|
||||||
|
|
||||||
--this is where all of the spawning information is kept
|
--this is where all of the spawning information is kept
|
||||||
local spawn_dictionary = {}
|
local spawn_dictionary = {}
|
||||||
|
local summary_chance = 0
|
||||||
|
|
||||||
|
function mobs:spawn_setup(def)
|
||||||
|
if not mobs_spawn then return end
|
||||||
|
|
||||||
|
if not def then
|
||||||
|
minetest.log("warning", "Empty mob spawn setup definition")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local name = def.name
|
||||||
|
if not name then
|
||||||
|
minetest.log("warning", "Missing mob name")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local dimension = def.dimension or "overworld"
|
||||||
|
local type_of_spawning = def.type_of_spawning or "ground"
|
||||||
|
local biomes = def.biomes or list_of_all_biomes
|
||||||
|
local min_light = def.min_light or 0
|
||||||
|
local max_light = def.max_light or (minetest.LIGHT_MAX + 1)
|
||||||
|
local chance = def.chance or 1000
|
||||||
|
local aoc = def.aoc or aoc_range
|
||||||
|
local min_height = def.min_height or mcl_mapgen.overworld.min
|
||||||
|
local max_height = def.max_height or mcl_mapgen.overworld.max
|
||||||
|
local day_toggle = def.day_toggle
|
||||||
|
local on_spawn = def.on_spawn
|
||||||
|
local check_position = def.check_position
|
||||||
|
|
||||||
|
-- chance/spawn number override in minetest.conf for registered mob
|
||||||
|
local numbers = minetest.settings:get(name)
|
||||||
|
if numbers then
|
||||||
|
numbers = numbers:split(",")
|
||||||
|
chance = tonumber(numbers[1]) or chance
|
||||||
|
aoc = tonumber(numbers[2]) or aoc
|
||||||
|
if chance == 0 then
|
||||||
|
minetest.log("warning", string.format("[mobs] %s has spawning disabled", name))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.log("action", string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
|
||||||
|
end
|
||||||
|
|
||||||
|
if chance < 1 then
|
||||||
|
chance = 1
|
||||||
|
minetest.log("warning", "Chance shouldn't be less than 1 (mob name: " .. name ..")")
|
||||||
|
end
|
||||||
|
|
||||||
|
spawn_dictionary[#spawn_dictionary + 1] = {
|
||||||
|
name = name,
|
||||||
|
dimension = dimension,
|
||||||
|
type_of_spawning = type_of_spawning,
|
||||||
|
biomes = biomes,
|
||||||
|
min_light = min_light,
|
||||||
|
max_light = max_light,
|
||||||
|
chance = chance,
|
||||||
|
aoc = aoc,
|
||||||
|
min_height = min_height,
|
||||||
|
max_height = max_height,
|
||||||
|
day_toggle = day_toggle,
|
||||||
|
check_position = check_position,
|
||||||
|
on_spawn = on_spawn,
|
||||||
|
}
|
||||||
|
summary_chance = summary_chance + chance
|
||||||
|
end
|
||||||
|
|
||||||
function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_light, max_light, interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
|
function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_light, max_light, interval, chance, aoc, min_height, max_height, day_toggle, on_spawn)
|
||||||
|
|
||||||
--print(dump(biomes))
|
|
||||||
|
|
||||||
-- Do mobs spawn at all?
|
-- Do mobs spawn at all?
|
||||||
if not mobs_spawn then
|
if not mobs_spawn then
|
||||||
return
|
return
|
||||||
|
@ -239,179 +324,7 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.log("action",
|
minetest.log("action", string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
|
||||||
string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc))
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[
|
|
||||||
local function spawn_action(pos, node, active_object_count, active_object_count_wider, name)
|
|
||||||
|
|
||||||
local orig_pos = table.copy(pos)
|
|
||||||
-- is mob actually registered?
|
|
||||||
if not mobs.spawning_mobs[name]
|
|
||||||
or not minetest.registered_entities[name] then
|
|
||||||
minetest.log("warning", "Mob spawn of "..name.." failed, unknown entity or mob is not registered for spawning!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- additional custom checks for spawning mob
|
|
||||||
if mobs:spawn_abm_check(pos, node, name) == true then
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, ABM check rejected!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- count nearby mobs in same spawn class
|
|
||||||
local entdef = minetest.registered_entities[name]
|
|
||||||
local spawn_class = entdef and entdef.spawn_class
|
|
||||||
if not spawn_class then
|
|
||||||
if entdef.type == "monster" then
|
|
||||||
spawn_class = "hostile"
|
|
||||||
else
|
|
||||||
spawn_class = "passive"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local in_class_cap = count_mobs(pos, "!"..spawn_class) < MOB_CAP[spawn_class]
|
|
||||||
-- do not spawn if too many of same mob in area
|
|
||||||
if active_object_count_wider >= max_per_block -- large-range mob cap
|
|
||||||
or (not in_class_cap) -- spawn class mob cap
|
|
||||||
or count_mobs(pos, name) >= aoc then -- per-mob mob cap
|
|
||||||
-- too many entities
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too crowded!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- if toggle set to nil then ignore day/night check
|
|
||||||
if day_toggle then
|
|
||||||
|
|
||||||
local tod = (minetest.get_timeofday() or 0) * 24000
|
|
||||||
|
|
||||||
if tod > 4500 and tod < 19500 then
|
|
||||||
-- daylight, but mob wants night
|
|
||||||
if day_toggle == false then
|
|
||||||
-- mob needs night
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs light!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- night time but mob wants day
|
|
||||||
if day_toggle == true then
|
|
||||||
-- mob needs day
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, mob needs daylight!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- spawn above node
|
|
||||||
pos.y = pos.y + 1
|
|
||||||
|
|
||||||
-- only spawn away from player
|
|
||||||
local objs = minetest.get_objects_inside_radius(pos, 24)
|
|
||||||
|
|
||||||
for n = 1, #objs do
|
|
||||||
|
|
||||||
if objs[n]:is_player() then
|
|
||||||
-- player too close
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, player too close!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- mobs cannot spawn in protected areas when enabled
|
|
||||||
if not spawn_protected
|
|
||||||
and minetest.is_protected(pos, "") then
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, position is protected!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- are we spawning within height limits?
|
|
||||||
if pos.y > max_height
|
|
||||||
or pos.y < min_height then
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, out of height limit!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- are light levels ok?
|
|
||||||
local light = minetest.get_node_light(pos)
|
|
||||||
if not light
|
|
||||||
or light > max_light
|
|
||||||
or light < min_light then
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, bad light!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- do we have enough space to spawn mob?
|
|
||||||
local ent = minetest.registered_entities[name]
|
|
||||||
local width_x = max(1, math.ceil(ent.collisionbox[4] - ent.collisionbox[1]))
|
|
||||||
local min_x, max_x
|
|
||||||
if width_x % 2 == 0 then
|
|
||||||
max_x = math.floor(width_x/2)
|
|
||||||
min_x = -(max_x-1)
|
|
||||||
else
|
|
||||||
max_x = math.floor(width_x/2)
|
|
||||||
min_x = -max_x
|
|
||||||
end
|
|
||||||
|
|
||||||
local width_z = max(1, math.ceil(ent.collisionbox[6] - ent.collisionbox[3]))
|
|
||||||
local min_z, max_z
|
|
||||||
if width_z % 2 == 0 then
|
|
||||||
max_z = math.floor(width_z/2)
|
|
||||||
min_z = -(max_z-1)
|
|
||||||
else
|
|
||||||
max_z = math.floor(width_z/2)
|
|
||||||
min_z = -max_z
|
|
||||||
end
|
|
||||||
|
|
||||||
local max_y = max(0, math.ceil(ent.collisionbox[5] - ent.collisionbox[2]) - 1)
|
|
||||||
|
|
||||||
for y = 0, max_y do
|
|
||||||
for x = min_x, max_x do
|
|
||||||
for z = min_z, max_z do
|
|
||||||
local pos2 = {x = pos.x+x, y = pos.y+y, z = pos.z+z}
|
|
||||||
if minetest.registered_nodes[node_ok(pos2).name].walkable == true then
|
|
||||||
-- inside block
|
|
||||||
minetest.log("info", "Mob spawn of "..name.." at "..minetest.pos_to_string(pos).." failed, too little space!")
|
|
||||||
if ent.spawn_small_alternative and (not minetest.registered_nodes[node_ok(pos).name].walkable) then
|
|
||||||
minetest.log("info", "Trying to spawn smaller alternative mob: "..ent.spawn_small_alternative)
|
|
||||||
spawn_action(orig_pos, node, active_object_count, active_object_count_wider, ent.spawn_small_alternative)
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- tweak X/Y/Z spawn pos
|
|
||||||
if width_x % 2 == 0 then
|
|
||||||
pos.x = pos.x + 0.5
|
|
||||||
end
|
|
||||||
if width_z % 2 == 0 then
|
|
||||||
pos.z = pos.z + 0.5
|
|
||||||
end
|
|
||||||
pos.y = pos.y - 0.5
|
|
||||||
|
|
||||||
local mob = minetest.add_entity(pos, name)
|
|
||||||
minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos))
|
|
||||||
|
|
||||||
if on_spawn then
|
|
||||||
|
|
||||||
local ent = mob:get_luaentity()
|
|
||||||
|
|
||||||
on_spawn(ent, pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function spawn_abm_action(pos, node, active_object_count, active_object_count_wider)
|
|
||||||
spawn_action(pos, node, active_object_count, active_object_count_wider, name)
|
|
||||||
end
|
|
||||||
]]--
|
|
||||||
|
|
||||||
local entdef = minetest.registered_entities[name]
|
|
||||||
local spawn_class
|
|
||||||
if entdef.type == "monster" then
|
|
||||||
spawn_class = "hostile"
|
|
||||||
else
|
|
||||||
spawn_class = "passive"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--load information into the spawn dictionary
|
--load information into the spawn dictionary
|
||||||
|
@ -423,107 +336,34 @@ function mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ligh
|
||||||
spawn_dictionary[key]["biomes"] = biomes
|
spawn_dictionary[key]["biomes"] = biomes
|
||||||
spawn_dictionary[key]["min_light"] = min_light
|
spawn_dictionary[key]["min_light"] = min_light
|
||||||
spawn_dictionary[key]["max_light"] = max_light
|
spawn_dictionary[key]["max_light"] = max_light
|
||||||
spawn_dictionary[key]["interval"] = interval
|
|
||||||
spawn_dictionary[key]["chance"] = chance
|
spawn_dictionary[key]["chance"] = chance
|
||||||
spawn_dictionary[key]["aoc"] = aoc
|
spawn_dictionary[key]["aoc"] = aoc
|
||||||
spawn_dictionary[key]["min_height"] = min_height
|
spawn_dictionary[key]["min_height"] = min_height
|
||||||
spawn_dictionary[key]["max_height"] = max_height
|
spawn_dictionary[key]["max_height"] = max_height
|
||||||
spawn_dictionary[key]["day_toggle"] = day_toggle
|
spawn_dictionary[key]["day_toggle"] = day_toggle
|
||||||
--spawn_dictionary[key]["on_spawn"] = spawn_abm_action
|
|
||||||
spawn_dictionary[key]["spawn_class"] = spawn_class
|
|
||||||
|
|
||||||
--[[
|
summary_chance = summary_chance + chance
|
||||||
minetest.register_abm({
|
|
||||||
label = name .. " spawning",
|
|
||||||
nodenames = nodes,
|
|
||||||
neighbors = neighbors,
|
|
||||||
interval = interval,
|
|
||||||
chance = floor(max(1, chance * mobs_spawn_chance)),
|
|
||||||
catch_up = false,
|
|
||||||
action = spawn_abm_action,
|
|
||||||
})
|
|
||||||
]]--
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- compatibility with older mob registration
|
local two_pi = 2 * math.pi
|
||||||
-- we're going to forget about this for now -j4i
|
local function get_next_mob_spawn_pos(pos)
|
||||||
--[[
|
local distance = math_random(25, 32)
|
||||||
function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, day_toggle)
|
local angle = math_random() * two_pi
|
||||||
|
return {
|
||||||
mobs:spawn_specific(name, nodes, {"air"}, min_light, max_light, 30,
|
x = math_round(pos.x + distance * math_cos(angle)),
|
||||||
chance, active_object_count, -31000, max_height, day_toggle)
|
y = pos.y,
|
||||||
end
|
z = math_round(pos.z + distance * math_sin(angle))
|
||||||
]]--
|
|
||||||
|
|
||||||
|
|
||||||
--Don't disable this yet-j4i
|
|
||||||
-- MarkBu's spawn function
|
|
||||||
|
|
||||||
function mobs:spawn(def)
|
|
||||||
--does nothing for now
|
|
||||||
--[[
|
|
||||||
local name = def.name
|
|
||||||
local nodes = def.nodes or {"group:soil", "group:stone"}
|
|
||||||
local neighbors = def.neighbors or {"air"}
|
|
||||||
local min_light = def.min_light or 0
|
|
||||||
local max_light = def.max_light or 15
|
|
||||||
local interval = def.interval or 30
|
|
||||||
local chance = def.chance or 5000
|
|
||||||
local active_object_count = def.active_object_count or 1
|
|
||||||
local min_height = def.min_height or -31000
|
|
||||||
local max_height = def.max_height or 31000
|
|
||||||
local day_toggle = def.day_toggle
|
|
||||||
local on_spawn = def.on_spawn
|
|
||||||
|
|
||||||
mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval,
|
|
||||||
chance, active_object_count, min_height, max_height, day_toggle, on_spawn)
|
|
||||||
]]--
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local axis
|
|
||||||
--inner and outer part of square donut radius
|
|
||||||
local inner = 15
|
|
||||||
local outer = 64
|
|
||||||
local int = {-1,1}
|
|
||||||
|
|
||||||
local function position_calculation(pos)
|
|
||||||
|
|
||||||
pos = vector_floor(pos)
|
|
||||||
|
|
||||||
--this is used to determine the axis buffer from the player
|
|
||||||
axis = math_random(0,1)
|
|
||||||
|
|
||||||
--cast towards the direction
|
|
||||||
if axis == 0 then --x
|
|
||||||
pos.x = pos.x + math_random(inner,outer)*int[math_random(1,2)]
|
|
||||||
pos.z = pos.z + math_random(-outer,outer)
|
|
||||||
else --z
|
|
||||||
pos.z = pos.z + math_random(inner,outer)*int[math_random(1,2)]
|
|
||||||
pos.x = pos.x + math_random(-outer,outer)
|
|
||||||
end
|
|
||||||
return pos
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[
|
|
||||||
local decypher_limits_dictionary = {
|
|
||||||
["overworld"] = {mcl_vars.mg_overworld_min,mcl_vars.mg_overworld_max},
|
|
||||||
["nether"] = {mcl_vars.mg_nether_min, mcl_vars.mg_nether_max},
|
|
||||||
["end"] = {mcl_vars.mg_end_min, mcl_vars.mg_end_max}
|
|
||||||
}
|
}
|
||||||
]]--
|
end
|
||||||
|
|
||||||
local function decypher_limits(posy)
|
local function decypher_limits(posy)
|
||||||
--local min_max_table = decypher_limits_dictionary[dimension]
|
|
||||||
--return min_max_table[1],min_max_table[2]
|
|
||||||
posy = math_floor(posy)
|
posy = math_floor(posy)
|
||||||
return posy - 32, posy + 32
|
return posy - 32, posy + 32
|
||||||
end
|
end
|
||||||
|
|
||||||
--a simple helper function for mob_spawn
|
--a simple helper function for mob_spawn
|
||||||
local function biome_check(biome_list, biome_goal)
|
local function biome_check(biome_list, biome_goal)
|
||||||
for _,data in ipairs(biome_list) do
|
for _, data in pairs(biome_list) do
|
||||||
if data == biome_goal then
|
if data == biome_goal then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -533,69 +373,27 @@ local function biome_check(biome_list, biome_goal)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--todo mob limiting
|
|
||||||
--MAIN LOOP
|
|
||||||
|
|
||||||
if mobs_spawn then
|
if mobs_spawn then
|
||||||
local timer = 0
|
|
||||||
minetest.register_globalstep(function(dtime)
|
|
||||||
timer = timer + dtime
|
|
||||||
if timer >= 10 then
|
|
||||||
timer = 0
|
|
||||||
for _,player in pairs(get_connected_players()) do
|
|
||||||
-- after this line each "break" means "continue"
|
|
||||||
local do_mob_spawning = true
|
|
||||||
repeat
|
|
||||||
--don't need to get these variables more than once
|
|
||||||
--they happen in a single server step
|
|
||||||
|
|
||||||
local player_pos = player:get_pos()
|
local perlin_noise
|
||||||
local dimension = mcl_worlds.pos_to_dimension(player_pos)
|
|
||||||
|
|
||||||
if dimension == "void" or dimension == "default" then
|
|
||||||
break -- ignore void and unloaded area
|
|
||||||
end
|
|
||||||
|
|
||||||
local min, max = decypher_limits(player_pos.y)
|
|
||||||
|
|
||||||
for i = 1, math_random(1,4) do
|
|
||||||
-- after this line each "break" means "continue"
|
|
||||||
local do_mob_algorithm = true
|
|
||||||
repeat
|
|
||||||
|
|
||||||
local goal_pos = position_calculation(player_pos)
|
|
||||||
|
|
||||||
local spawning_position_list = find_nodes_in_area_under_air(vector_new(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
|
|
||||||
if #spawning_position_list <= 0 then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
|
local function spawn_a_mob(pos, dimension, y_min, y_max)
|
||||||
|
local dimension = dimension or mcl_worlds.pos_to_dimension(pos)
|
||||||
|
local goal_pos = get_next_mob_spawn_pos(pos)
|
||||||
|
local spawning_position_list = find_nodes_in_area_under_air(
|
||||||
|
{x = goal_pos.x, y = y_min, z = goal_pos.z},
|
||||||
|
{x = goal_pos.x, y = y_max, z = goal_pos.z},
|
||||||
|
{"group:solid", "group:water", "group:lava"}
|
||||||
|
)
|
||||||
|
if #spawning_position_list <= 0 then return end
|
||||||
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
|
local spawning_position = spawning_position_list[math_random(1, #spawning_position_list)]
|
||||||
|
|
||||||
--Prevent strange behavior --- this is commented out: /too close to player --fixed with inner circle
|
|
||||||
if not spawning_position then -- or vector_distance(player_pos, spawning_position) < 15
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
--hard code mob limit in area to 5 for now
|
--hard code mob limit in area to 5 for now
|
||||||
if count_mobs(spawning_position) >= 5 then
|
if count_mobs(spawning_position) >= 5 then return end
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
local gotten_node = get_node(spawning_position).name
|
local gotten_node = get_node(spawning_position).name
|
||||||
|
|
||||||
if not gotten_node or gotten_node == "air" then --skip air nodes
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
local gotten_biome = minetest.get_biome_data(spawning_position)
|
local gotten_biome = minetest.get_biome_data(spawning_position)
|
||||||
|
if not gotten_node or not gotten_biome then return end
|
||||||
if not gotten_biome then
|
|
||||||
break --skip if in unloaded area
|
|
||||||
end
|
|
||||||
|
|
||||||
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
|
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
|
||||||
|
|
||||||
--add this so mobs don't spawn inside nodes
|
--add this so mobs don't spawn inside nodes
|
||||||
|
@ -606,8 +404,12 @@ if mobs_spawn then
|
||||||
|
|
||||||
local is_water = get_item_group(gotten_node, "water") ~= 0
|
local is_water = get_item_group(gotten_node, "water") ~= 0
|
||||||
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
||||||
|
local is_ground = not (is_water or is_lava)
|
||||||
|
if not is_ground then
|
||||||
|
spawning_position.y = spawning_position.y - 1
|
||||||
|
end
|
||||||
|
|
||||||
local mob_def = nil
|
local mob_def
|
||||||
|
|
||||||
--create a disconnected clone of the spawn dictionary
|
--create a disconnected clone of the spawn dictionary
|
||||||
--prevents memory leak
|
--prevents memory leak
|
||||||
|
@ -615,94 +417,58 @@ if mobs_spawn then
|
||||||
|
|
||||||
--grab mob that fits into the spawning location
|
--grab mob that fits into the spawning location
|
||||||
--randomly grab a mob, don't exclude any possibilities
|
--randomly grab a mob, don't exclude any possibilities
|
||||||
local repeat_mob_search = true
|
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
||||||
repeat
|
local noise = perlin_noise:get_3d(spawning_position)
|
||||||
|
local current_summary_chance = summary_chance
|
||||||
--do not infinite loop
|
while #mob_library_worker_table > 0 do
|
||||||
if #mob_library_worker_table <= 0 then
|
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
|
||||||
--print("breaking infinite loop")
|
local mob_index = 1
|
||||||
break
|
local mob_chance = mob_library_worker_table[mob_index].chance
|
||||||
|
local step_chance = mob_chance
|
||||||
|
while step_chance < mob_chance_offset do
|
||||||
|
mob_index = mob_index + 1
|
||||||
|
mob_chance = mob_library_worker_table[mob_index].chance
|
||||||
|
step_chance = step_chance + mob_chance
|
||||||
end
|
end
|
||||||
|
local mob_def = mob_library_worker_table[mob_index]
|
||||||
local skip = false
|
if mob_def
|
||||||
|
and spawning_position.y >= mob_def.min_height
|
||||||
--use this for removing table elements of mobs that do not match
|
and spawning_position.y <= mob_def.max_height
|
||||||
local temp_index = math_random(1,#mob_library_worker_table)
|
and mob_def.dimension == dimension
|
||||||
|
and biome_check(mob_def.biomes, gotten_biome)
|
||||||
local temp_def = mob_library_worker_table[temp_index]
|
and gotten_light >= mob_def.min_light
|
||||||
|
and gotten_light <= mob_def.max_light
|
||||||
--skip if something ridiculous happens (nil mob def)
|
and (is_ground or mob_def.type_of_spawning ~= "ground")
|
||||||
--something truly horrible has happened if skip gets
|
and (mob_def.check_position and mob_def.check_position(spawning_position) or true)
|
||||||
--activated at this point
|
then
|
||||||
if not temp_def then
|
|
||||||
skip = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if not skip and (spawning_position.y < temp_def.min_height or spawning_position.y > temp_def.max_height) then
|
|
||||||
skip = true
|
|
||||||
end
|
|
||||||
|
|
||||||
--skip if not correct dimension
|
|
||||||
if not skip and (temp_def.dimension ~= dimension) then
|
|
||||||
skip = true
|
|
||||||
end
|
|
||||||
|
|
||||||
--skip if not in correct biome
|
|
||||||
if not skip and (not biome_check(temp_def.biomes, gotten_biome)) then
|
|
||||||
skip = true
|
|
||||||
end
|
|
||||||
|
|
||||||
--don't spawn if not in light limits
|
|
||||||
if not skip and (gotten_light < temp_def.min_light or gotten_light > temp_def.max_light) then
|
|
||||||
skip = true
|
|
||||||
end
|
|
||||||
|
|
||||||
--skip if not in correct spawning type
|
|
||||||
if not skip and (temp_def.type_of_spawning == "ground" and is_water) then
|
|
||||||
skip = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if not skip and (temp_def.type_of_spawning == "ground" and is_lava) then
|
|
||||||
skip = true
|
|
||||||
end
|
|
||||||
|
|
||||||
--found a mob, exit out of loop
|
|
||||||
if not skip then
|
|
||||||
--minetest.log("warning", "found mob:"..temp_def.name)
|
|
||||||
--print("found mob:"..temp_def.name)
|
|
||||||
mob_def = table_copy(temp_def)
|
|
||||||
break
|
|
||||||
else
|
|
||||||
--minetest.log("warning", "deleting temp index "..temp_index)
|
|
||||||
--print("deleting temp index")
|
|
||||||
table_remove(mob_library_worker_table, temp_index)
|
|
||||||
end
|
|
||||||
|
|
||||||
until repeat_mob_search == false --this is needed to sort through mobs randomly
|
|
||||||
|
|
||||||
|
|
||||||
--catch if went through all mobs and something went horribly wrong
|
|
||||||
--could not find a valid mob to spawn that fits the environment
|
|
||||||
if not mob_def then
|
|
||||||
break
|
|
||||||
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
|
|
||||||
|
|
||||||
--print("spawning: " .. mob_def.name)
|
|
||||||
|
|
||||||
--everything is correct, spawn mob
|
--everything is correct, spawn mob
|
||||||
minetest.add_entity(spawning_position, mob_def.name)
|
local object = minetest.add_entity(spawning_position, mob_def.name)
|
||||||
|
if object then
|
||||||
break
|
return mob_def.on_spawn and mob_def.on_spawn(object, pos)
|
||||||
until do_mob_algorithm == false --this is a safety catch
|
end
|
||||||
|
end
|
||||||
|
current_summary_chance = current_summary_chance - mob_chance
|
||||||
|
table_remove(mob_library_worker_table, mob_index)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
break
|
|
||||||
until do_mob_spawning == false --this is a performance catch
|
--MAIN LOOP
|
||||||
|
|
||||||
|
local timer = 0
|
||||||
|
minetest.register_globalstep(function(dtime)
|
||||||
|
timer = timer + dtime
|
||||||
|
if timer < 10 then return end
|
||||||
|
timer = 0
|
||||||
|
for _, player in pairs(get_connected_players()) do
|
||||||
|
local pos = player:get_pos()
|
||||||
|
local dimension = mcl_worlds.pos_to_dimension(pos)
|
||||||
|
-- ignore void and unloaded area
|
||||||
|
if dimension ~= "void" and dimension ~= "default" then
|
||||||
|
local y_min, y_max = decypher_limits(pos.y)
|
||||||
|
for i = 1, math_random(1, 4) do
|
||||||
|
spawn_a_mob(pos, dimension, y_min, y_max)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -160,6 +160,7 @@ minetest.register_entity("mcl_paintings:painting", {
|
||||||
set_entity(self.object)
|
set_entity(self.object)
|
||||||
end,
|
end,
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
if not self then return end
|
||||||
local data = {
|
local data = {
|
||||||
_facing = self._facing,
|
_facing = self._facing,
|
||||||
_pos = self._pos,
|
_pos = self._pos,
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
--################### SILVERFISH
|
--################### SILVERFISH
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
|
local PLAYER_SCAN_RADIUS = 5
|
||||||
|
|
||||||
local S = minetest.get_translator(minetest.get_current_modname())
|
local S = minetest.get_translator(minetest.get_current_modname())
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:silverfish", {
|
mobs:register_mob("mobs_mc:silverfish", {
|
||||||
|
@ -46,6 +48,20 @@ mobs:register_mob("mobs_mc:silverfish", {
|
||||||
view_range = 16,
|
view_range = 16,
|
||||||
attack_type = "punch",
|
attack_type = "punch",
|
||||||
damage = 1,
|
damage = 1,
|
||||||
|
do_custom = function(self, dtime)
|
||||||
|
self.do_custom_time = (self.do_custom_time or 0) + dtime
|
||||||
|
if self.do_custom_time < 1.5 then return end
|
||||||
|
self.do_custom_time = 0
|
||||||
|
local selfpos = self.object:get_pos()
|
||||||
|
local objects = minetest.get_objects_inside_radius(selfpos, PLAYER_SCAN_RADIUS)
|
||||||
|
for _, obj in pairs(objects) do
|
||||||
|
if obj:is_player() and not minetest.is_creative_enabled(obj:get_player_name()) then
|
||||||
|
self.attacking = obj
|
||||||
|
mobs.group_attack_initialization(self)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
mobs:register_egg("mobs_mc:silverfish", S("Silverfish"), "mobs_mc_spawn_icon_silverfish.png", 0)
|
mobs:register_egg("mobs_mc:silverfish", S("Silverfish"), "mobs_mc_spawn_icon_silverfish.png", 0)
|
||||||
|
|
|
@ -9,6 +9,95 @@ local S = minetest.get_translator(minetest.get_current_modname())
|
||||||
--################### ZOMBIE
|
--################### ZOMBIE
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
|
local husk_biomes = {
|
||||||
|
"Desert",
|
||||||
|
"SavannaM",
|
||||||
|
"Savanna",
|
||||||
|
"Savanna_beach",
|
||||||
|
}
|
||||||
|
|
||||||
|
local zombie_biomes = {
|
||||||
|
"FlowerForest_underground",
|
||||||
|
"JungleEdge_underground",
|
||||||
|
"StoneBeach_underground",
|
||||||
|
"MesaBryce_underground",
|
||||||
|
"Mesa_underground",
|
||||||
|
"RoofedForest_underground",
|
||||||
|
"Jungle_underground",
|
||||||
|
"Swampland_underground",
|
||||||
|
"MushroomIsland_underground",
|
||||||
|
"BirchForest_underground",
|
||||||
|
"Plains_underground",
|
||||||
|
"MesaPlateauF_underground",
|
||||||
|
"ExtremeHills_underground",
|
||||||
|
"MegaSpruceTaiga_underground",
|
||||||
|
"BirchForestM_underground",
|
||||||
|
"SavannaM_underground",
|
||||||
|
"MesaPlateauFM_underground",
|
||||||
|
"Desert_underground",
|
||||||
|
"Savanna_underground",
|
||||||
|
"Forest_underground",
|
||||||
|
"SunflowerPlains_underground",
|
||||||
|
"ColdTaiga_underground",
|
||||||
|
"IcePlains_underground",
|
||||||
|
"IcePlainsSpikes_underground",
|
||||||
|
"MegaTaiga_underground",
|
||||||
|
"Taiga_underground",
|
||||||
|
"ExtremeHills+_underground",
|
||||||
|
"JungleM_underground",
|
||||||
|
"ExtremeHillsM_underground",
|
||||||
|
"JungleEdgeM_underground",
|
||||||
|
"Mesa",
|
||||||
|
"FlowerForest",
|
||||||
|
"Swampland",
|
||||||
|
"Taiga",
|
||||||
|
"ExtremeHills",
|
||||||
|
"Jungle",
|
||||||
|
"Savanna",
|
||||||
|
"BirchForest",
|
||||||
|
"MegaSpruceTaiga",
|
||||||
|
"MegaTaiga",
|
||||||
|
"ExtremeHills+",
|
||||||
|
"Forest",
|
||||||
|
"Plains",
|
||||||
|
"Desert",
|
||||||
|
"ColdTaiga",
|
||||||
|
"MushroomIsland",
|
||||||
|
"IcePlainsSpikes",
|
||||||
|
"SunflowerPlains",
|
||||||
|
"IcePlains",
|
||||||
|
"RoofedForest",
|
||||||
|
"ExtremeHills+_snowtop",
|
||||||
|
"MesaPlateauFM_grasstop",
|
||||||
|
"JungleEdgeM",
|
||||||
|
"ExtremeHillsM",
|
||||||
|
"JungleM",
|
||||||
|
"BirchForestM",
|
||||||
|
"MesaPlateauF",
|
||||||
|
"MesaPlateauFM",
|
||||||
|
"MesaPlateauF_grasstop",
|
||||||
|
"MesaBryce",
|
||||||
|
"JungleEdge",
|
||||||
|
"SavannaM",
|
||||||
|
"FlowerForest_beach",
|
||||||
|
"Forest_beach",
|
||||||
|
"StoneBeach",
|
||||||
|
"ColdTaiga_beach_water",
|
||||||
|
"Taiga_beach",
|
||||||
|
"Savanna_beach",
|
||||||
|
"Plains_beach",
|
||||||
|
"ExtremeHills_beach",
|
||||||
|
"ColdTaiga_beach",
|
||||||
|
"Swampland_shore",
|
||||||
|
"MushroomIslandShore",
|
||||||
|
"JungleM_shore",
|
||||||
|
"Jungle_shore",
|
||||||
|
"MesaPlateauFM_sandlevel",
|
||||||
|
"MesaPlateauF_sandlevel",
|
||||||
|
"MesaBryce_sandlevel",
|
||||||
|
"Mesa_sandlevel",
|
||||||
|
}
|
||||||
|
|
||||||
local drops_common = {
|
local drops_common = {
|
||||||
{name = mobs_mc.items.rotten_flesh,
|
{name = mobs_mc.items.rotten_flesh,
|
||||||
chance = 1,
|
chance = 1,
|
||||||
|
@ -166,230 +255,36 @@ baby_husk.child = 1
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:baby_husk", baby_husk)
|
mobs:register_mob("mobs_mc:baby_husk", baby_husk)
|
||||||
|
|
||||||
|
|
||||||
-- Spawning
|
-- Spawning
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_setup({
|
||||||
"mobs_mc:zombie",
|
name = "mobs_mc:zombie",
|
||||||
"overworld",
|
biomes = zombie_biomes,
|
||||||
"ground",
|
max_light = 7,
|
||||||
{
|
chance = 2000,
|
||||||
"FlowerForest_underground",
|
})
|
||||||
"JungleEdge_underground",
|
|
||||||
"StoneBeach_underground",
|
|
||||||
"MesaBryce_underground",
|
|
||||||
"Mesa_underground",
|
|
||||||
"RoofedForest_underground",
|
|
||||||
"Jungle_underground",
|
|
||||||
"Swampland_underground",
|
|
||||||
"MushroomIsland_underground",
|
|
||||||
"BirchForest_underground",
|
|
||||||
"Plains_underground",
|
|
||||||
"MesaPlateauF_underground",
|
|
||||||
"ExtremeHills_underground",
|
|
||||||
"MegaSpruceTaiga_underground",
|
|
||||||
"BirchForestM_underground",
|
|
||||||
"SavannaM_underground",
|
|
||||||
"MesaPlateauFM_underground",
|
|
||||||
"Desert_underground",
|
|
||||||
"Savanna_underground",
|
|
||||||
"Forest_underground",
|
|
||||||
"SunflowerPlains_underground",
|
|
||||||
"ColdTaiga_underground",
|
|
||||||
"IcePlains_underground",
|
|
||||||
"IcePlainsSpikes_underground",
|
|
||||||
"MegaTaiga_underground",
|
|
||||||
"Taiga_underground",
|
|
||||||
"ExtremeHills+_underground",
|
|
||||||
"JungleM_underground",
|
|
||||||
"ExtremeHillsM_underground",
|
|
||||||
"JungleEdgeM_underground",
|
|
||||||
"Mesa",
|
|
||||||
"FlowerForest",
|
|
||||||
"Swampland",
|
|
||||||
"Taiga",
|
|
||||||
"ExtremeHills",
|
|
||||||
"Jungle",
|
|
||||||
"Savanna",
|
|
||||||
"BirchForest",
|
|
||||||
"MegaSpruceTaiga",
|
|
||||||
"MegaTaiga",
|
|
||||||
"ExtremeHills+",
|
|
||||||
"Forest",
|
|
||||||
"Plains",
|
|
||||||
"Desert",
|
|
||||||
"ColdTaiga",
|
|
||||||
"MushroomIsland",
|
|
||||||
"IcePlainsSpikes",
|
|
||||||
"SunflowerPlains",
|
|
||||||
"IcePlains",
|
|
||||||
"RoofedForest",
|
|
||||||
"ExtremeHills+_snowtop",
|
|
||||||
"MesaPlateauFM_grasstop",
|
|
||||||
"JungleEdgeM",
|
|
||||||
"ExtremeHillsM",
|
|
||||||
"JungleM",
|
|
||||||
"BirchForestM",
|
|
||||||
"MesaPlateauF",
|
|
||||||
"MesaPlateauFM",
|
|
||||||
"MesaPlateauF_grasstop",
|
|
||||||
"MesaBryce",
|
|
||||||
"JungleEdge",
|
|
||||||
"SavannaM",
|
|
||||||
"FlowerForest_beach",
|
|
||||||
"Forest_beach",
|
|
||||||
"StoneBeach",
|
|
||||||
"ColdTaiga_beach_water",
|
|
||||||
"Taiga_beach",
|
|
||||||
"Savanna_beach",
|
|
||||||
"Plains_beach",
|
|
||||||
"ExtremeHills_beach",
|
|
||||||
"ColdTaiga_beach",
|
|
||||||
"Swampland_shore",
|
|
||||||
"MushroomIslandShore",
|
|
||||||
"JungleM_shore",
|
|
||||||
"Jungle_shore",
|
|
||||||
"MesaPlateauFM_sandlevel",
|
|
||||||
"MesaPlateauF_sandlevel",
|
|
||||||
"MesaBryce_sandlevel",
|
|
||||||
"Mesa_sandlevel",
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
7,
|
|
||||||
30,
|
|
||||||
6000,
|
|
||||||
4,
|
|
||||||
mobs_mc.spawn_height.overworld_min,
|
|
||||||
mobs_mc.spawn_height.overworld_max)
|
|
||||||
-- Baby zombie is 20 times less likely than regular zombies
|
-- Baby zombie is 20 times less likely than regular zombies
|
||||||
mobs:spawn_specific(
|
mobs:spawn_setup({
|
||||||
"mobs_mc:baby_zombie",
|
name = "mobs_mc:baby_zombie",
|
||||||
"overworld",
|
biomes = zombie_biomes,
|
||||||
"ground",
|
max_lignt = 7,
|
||||||
{
|
chance = 100,
|
||||||
"FlowerForest_underground",
|
})
|
||||||
"JungleEdge_underground",
|
|
||||||
"StoneBeach_underground",
|
|
||||||
"MesaBryce_underground",
|
|
||||||
"Mesa_underground",
|
|
||||||
"RoofedForest_underground",
|
|
||||||
"Jungle_underground",
|
|
||||||
"Swampland_underground",
|
|
||||||
"MushroomIsland_underground",
|
|
||||||
"BirchForest_underground",
|
|
||||||
"Plains_underground",
|
|
||||||
"MesaPlateauF_underground",
|
|
||||||
"ExtremeHills_underground",
|
|
||||||
"MegaSpruceTaiga_underground",
|
|
||||||
"BirchForestM_underground",
|
|
||||||
"SavannaM_underground",
|
|
||||||
"MesaPlateauFM_underground",
|
|
||||||
"Desert_underground",
|
|
||||||
"Savanna_underground",
|
|
||||||
"Forest_underground",
|
|
||||||
"SunflowerPlains_underground",
|
|
||||||
"ColdTaiga_underground",
|
|
||||||
"IcePlains_underground",
|
|
||||||
"IcePlainsSpikes_underground",
|
|
||||||
"MegaTaiga_underground",
|
|
||||||
"Taiga_underground",
|
|
||||||
"ExtremeHills+_underground",
|
|
||||||
"JungleM_underground",
|
|
||||||
"ExtremeHillsM_underground",
|
|
||||||
"JungleEdgeM_underground",
|
|
||||||
"Mesa",
|
|
||||||
"FlowerForest",
|
|
||||||
"Swampland",
|
|
||||||
"Taiga",
|
|
||||||
"ExtremeHills",
|
|
||||||
"Jungle",
|
|
||||||
"Savanna",
|
|
||||||
"BirchForest",
|
|
||||||
"MegaSpruceTaiga",
|
|
||||||
"MegaTaiga",
|
|
||||||
"ExtremeHills+",
|
|
||||||
"Forest",
|
|
||||||
"Plains",
|
|
||||||
"Desert",
|
|
||||||
"ColdTaiga",
|
|
||||||
"MushroomIsland",
|
|
||||||
"IcePlainsSpikes",
|
|
||||||
"SunflowerPlains",
|
|
||||||
"IcePlains",
|
|
||||||
"RoofedForest",
|
|
||||||
"ExtremeHills+_snowtop",
|
|
||||||
"MesaPlateauFM_grasstop",
|
|
||||||
"JungleEdgeM",
|
|
||||||
"ExtremeHillsM",
|
|
||||||
"JungleM",
|
|
||||||
"BirchForestM",
|
|
||||||
"MesaPlateauF",
|
|
||||||
"MesaPlateauFM",
|
|
||||||
"MesaPlateauF_grasstop",
|
|
||||||
"MesaBryce",
|
|
||||||
"JungleEdge",
|
|
||||||
"SavannaM",
|
|
||||||
"FlowerForest_beach",
|
|
||||||
"Forest_beach",
|
|
||||||
"StoneBeach",
|
|
||||||
"ColdTaiga_beach_water",
|
|
||||||
"Taiga_beach",
|
|
||||||
"Savanna_beach",
|
|
||||||
"Plains_beach",
|
|
||||||
"ExtremeHills_beach",
|
|
||||||
"ColdTaiga_beach",
|
|
||||||
"Swampland_shore",
|
|
||||||
"MushroomIslandShore",
|
|
||||||
"JungleM_shore",
|
|
||||||
"Jungle_shore",
|
|
||||||
"MesaPlateauFM_sandlevel",
|
|
||||||
"MesaPlateauF_sandlevel",
|
|
||||||
"MesaBryce_sandlevel",
|
|
||||||
"Mesa_sandlevel",
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
7,
|
|
||||||
30,
|
|
||||||
60000,
|
|
||||||
4,
|
|
||||||
mobs_mc.spawn_height.overworld_min,
|
|
||||||
mobs_mc.spawn_height.overworld_max)
|
|
||||||
|
|
||||||
|
mobs:spawn_setup({
|
||||||
|
name = "mobs_mc:husk",
|
||||||
|
biomes = husk_biomes,
|
||||||
|
max_light = 7,
|
||||||
|
chance = 2000,
|
||||||
|
})
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_setup({
|
||||||
"mobs_mc:husk",
|
name = "mobs_mc:baby_husk",
|
||||||
"overworld",
|
biomes = husk_biomes,
|
||||||
"ground",
|
max_light = 7,
|
||||||
{
|
chance = 100,
|
||||||
"Desert",
|
})
|
||||||
"SavannaM",
|
|
||||||
"Savanna",
|
|
||||||
"Savanna_beach",
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
7,
|
|
||||||
30,
|
|
||||||
6500,
|
|
||||||
4,
|
|
||||||
mobs_mc.spawn_height.overworld_min,
|
|
||||||
mobs_mc.spawn_height.overworld_max)
|
|
||||||
mobs:spawn_specific(
|
|
||||||
"mobs_mc:baby_husk",
|
|
||||||
"overworld",
|
|
||||||
"ground",
|
|
||||||
{
|
|
||||||
"Desert",
|
|
||||||
"SavannaM",
|
|
||||||
"Savanna",
|
|
||||||
"Savanna_beach",
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
7,
|
|
||||||
30,
|
|
||||||
65000,
|
|
||||||
4,
|
|
||||||
mobs_mc.spawn_height.overworld_min,
|
|
||||||
mobs_mc.spawn_height.overworld_max)
|
|
||||||
|
|
||||||
-- Spawn eggs
|
-- Spawn eggs
|
||||||
mobs:register_egg("mobs_mc:husk", S("Husk"), "mobs_mc_spawn_icon_husk.png", 0)
|
mobs:register_egg("mobs_mc:husk", S("Husk"), "mobs_mc_spawn_icon_husk.png", 0)
|
||||||
|
|
|
@ -346,8 +346,16 @@ function mesecon.vm_abort()
|
||||||
vm_cache = nil
|
vm_cache = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function is_player_close(pos)
|
||||||
|
for k,p in pairs(minetest.get_connected_players()) do
|
||||||
|
local d=vector.distance(pos,p:get_pos())
|
||||||
|
if d < 40 then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Gets the cache entry covering a position, populating it if necessary.
|
-- Gets the cache entry covering a position, populating it if necessary.
|
||||||
local function vm_get_or_create_entry(pos)
|
local function vm_get_or_create_entry(pos)
|
||||||
|
if not is_player_close(pos) then return end
|
||||||
local hash = hash_blockpos(pos)
|
local hash = hash_blockpos(pos)
|
||||||
local tbl = vm_cache[hash]
|
local tbl = vm_cache[hash]
|
||||||
if not tbl then
|
if not tbl then
|
||||||
|
@ -364,6 +372,7 @@ end
|
||||||
-- transaction.
|
-- transaction.
|
||||||
function mesecon.vm_get_node(pos)
|
function mesecon.vm_get_node(pos)
|
||||||
local tbl = vm_get_or_create_entry(pos)
|
local tbl = vm_get_or_create_entry(pos)
|
||||||
|
if not tbl then return end
|
||||||
local index = tbl.va:indexp(pos)
|
local index = tbl.va:indexp(pos)
|
||||||
local node_value = tbl.data[index]
|
local node_value = tbl.data[index]
|
||||||
if node_value == minetest.CONTENT_IGNORE then
|
if node_value == minetest.CONTENT_IGNORE then
|
||||||
|
@ -380,6 +389,7 @@ end
|
||||||
-- Existing param1, param2, and metadata are left alone.
|
-- Existing param1, param2, and metadata are left alone.
|
||||||
function mesecon.vm_swap_node(pos, name)
|
function mesecon.vm_swap_node(pos, name)
|
||||||
local tbl = vm_get_or_create_entry(pos)
|
local tbl = vm_get_or_create_entry(pos)
|
||||||
|
if not tbl then return end
|
||||||
local index = tbl.va:indexp(pos)
|
local index = tbl.va:indexp(pos)
|
||||||
tbl.data[index] = minetest.get_content_id(name)
|
tbl.data[index] = minetest.get_content_id(name)
|
||||||
tbl.dirty = true
|
tbl.dirty = true
|
||||||
|
@ -393,6 +403,7 @@ end
|
||||||
--
|
--
|
||||||
-- Inside a VM transaction, the transaction’s VM cache is used.
|
-- Inside a VM transaction, the transaction’s VM cache is used.
|
||||||
function mesecon.get_node_force(pos)
|
function mesecon.get_node_force(pos)
|
||||||
|
if not is_player_close(pos) then return end
|
||||||
if vm_cache then
|
if vm_cache then
|
||||||
return mesecon.vm_get_node(pos)
|
return mesecon.vm_get_node(pos)
|
||||||
else
|
else
|
||||||
|
@ -424,6 +435,7 @@ function mesecon.swap_node_force(pos, name)
|
||||||
-- This serves to both ensure the mapblock is loaded and also hand us
|
-- This serves to both ensure the mapblock is loaded and also hand us
|
||||||
-- the old node table so we can preserve param2.
|
-- the old node table so we can preserve param2.
|
||||||
local node = mesecon.get_node_force(pos)
|
local node = mesecon.get_node_force(pos)
|
||||||
|
if not node then return end
|
||||||
node.name = name
|
node.name = name
|
||||||
minetest.swap_node(pos, node)
|
minetest.swap_node(pos, node)
|
||||||
end
|
end
|
||||||
|
|
|
@ -618,6 +618,7 @@ local entity_standing = {
|
||||||
-- pattern: name of pattern (see list above)
|
-- pattern: name of pattern (see list above)
|
||||||
|
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
if not self then return end
|
||||||
local out = { _base_color = self._base_color, _layers = self._layers, _name = self._name }
|
local out = { _base_color = self._base_color, _layers = self._layers, _name = self._name }
|
||||||
return minetest.serialize(out)
|
return minetest.serialize(out)
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -441,6 +441,7 @@ function ARROW_ENTITY.on_punch(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ARROW_ENTITY.get_staticdata(self)
|
function ARROW_ENTITY.get_staticdata(self)
|
||||||
|
if not self then return end
|
||||||
local out = {
|
local out = {
|
||||||
lastpos = self._lastpos,
|
lastpos = self._lastpos,
|
||||||
startpos = self._startpos,
|
startpos = self._startpos,
|
||||||
|
|
|
@ -38,7 +38,9 @@ local function damage_explosion(self, damagemulitplier)
|
||||||
for _,obj in pairs(objects) do
|
for _,obj in pairs(objects) do
|
||||||
if obj:is_player() then
|
if obj:is_player() then
|
||||||
mcl_util.deal_damage(obj, damagemulitplier - vector.distance(self.object:get_pos(), obj:get_pos()), {type = "explosion"})
|
mcl_util.deal_damage(obj, damagemulitplier - vector.distance(self.object:get_pos(), obj:get_pos()), {type = "explosion"})
|
||||||
elseif obj:get_luaentity()._cmi_is_mob then
|
else
|
||||||
|
local entity = obj:get_luaentity()
|
||||||
|
if entity and entity._cmi_is_mob then
|
||||||
obj:punch(self.object, 1.0, {
|
obj:punch(self.object, 1.0, {
|
||||||
full_punch_interval=1.0,
|
full_punch_interval=1.0,
|
||||||
damage_groups={fleshy=damagemulitplier - vector.distance(self.object:get_pos(), obj:get_pos())},
|
damage_groups={fleshy=damagemulitplier - vector.distance(self.object:get_pos(), obj:get_pos())},
|
||||||
|
@ -46,6 +48,7 @@ local function damage_explosion(self, damagemulitplier)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function particle_explosion(self)
|
local function particle_explosion(self)
|
||||||
local particle_pattern = math.random(1, 3)
|
local particle_pattern = math.random(1, 3)
|
||||||
|
@ -627,6 +630,7 @@ function ARROW_ENTITY.on_punch(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ARROW_ENTITY.get_staticdata(self)
|
function ARROW_ENTITY.get_staticdata(self)
|
||||||
|
if not self then return end
|
||||||
local out = {
|
local out = {
|
||||||
lastpos = self._lastpos,
|
lastpos = self._lastpos,
|
||||||
startpos = self._startpos,
|
startpos = self._startpos,
|
||||||
|
|
|
@ -248,6 +248,51 @@ local function player_chest_close(player)
|
||||||
open_chests[name] = nil
|
open_chests[name] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function drop_item_stack(pos, stack)
|
||||||
|
if not stack or stack:is_empty() then return end
|
||||||
|
local drop_offset = vector.new(math.random() - 0.5, 0, math.random() - 0.5)
|
||||||
|
minetest.add_item(vector.add(pos, drop_offset), stack)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function drop_items_chest(pos, oldnode, oldmetadata, digger)
|
||||||
|
if oldmetadata and oldmetadata.inventory then
|
||||||
|
-- process after_dig_node callback
|
||||||
|
local main = oldmetadata.inventory.main
|
||||||
|
if not main then return end
|
||||||
|
for _, stack in pairs(main) do
|
||||||
|
drop_item_stack(pos, stack)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
for i = 1, inv:get_size("main") do
|
||||||
|
drop_item_stack(pos, inv:get_stack("main", i))
|
||||||
|
end
|
||||||
|
meta:from_table()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function on_chest_blast(pos, intensity)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
drop_items_chest(pos, node)
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
-- drop node itself with some probability depended on explosion intensity (1 for TNT):
|
||||||
|
if math.random(1, math.floor((intensity or 1) * 2)) ~= 1 then return end
|
||||||
|
local node_def = minetest.registered_nodes[node.name]
|
||||||
|
if not node_def then return end
|
||||||
|
local node_name = node_def.drop or node_def.name
|
||||||
|
drop_item_stack(pos, ItemStack(node_name))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function close_forms(canonical_basename, pos)
|
||||||
|
local players = minetest.get_connected_players()
|
||||||
|
for p=1, #players do
|
||||||
|
if vector.distance(players[p]:get_pos(), pos) <= 30 then
|
||||||
|
minetest.close_formspec(players[p]:get_player_name(), "mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- This is a helper function to register both chests and trapped chests. Trapped chests will make use of the additional parameters
|
-- This is a helper function to register both chests and trapped chests. Trapped chests will make use of the additional parameters
|
||||||
local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tiles_table, hidden, mesecons, on_rightclick_addendum, on_rightclick_addendum_left, on_rightclick_addendum_right, drop, canonical_basename)
|
local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tiles_table, hidden, mesecons, on_rightclick_addendum, on_rightclick_addendum_left, on_rightclick_addendum_right, drop, canonical_basename)
|
||||||
-- START OF register_chest FUNCTION BODY
|
-- START OF register_chest FUNCTION BODY
|
||||||
|
@ -295,42 +340,6 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drop_item_stack(pos, stack)
|
|
||||||
if not stack or stack:is_empty() then return end
|
|
||||||
local drop_offset = vector.new(math.random() - 0.5, 0, math.random() - 0.5)
|
|
||||||
minetest.add_item(vector.add(pos, drop_offset), stack)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drop_items_chest(pos, oldnode, oldmetadata, digger)
|
|
||||||
if oldmetadata and oldmetadata.inventory then
|
|
||||||
-- process after_dig_node callback
|
|
||||||
local main = oldmetadata.inventory.main
|
|
||||||
if not main then return end
|
|
||||||
for _, stack in pairs(main) do
|
|
||||||
drop_item_stack(pos, stack)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
for i = 1, inv:get_size("main") do
|
|
||||||
drop_item_stack(pos, inv:get_stack("main", i))
|
|
||||||
end
|
|
||||||
meta:from_table()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_chest_blast(pos, intensity)
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
drop_items_chest(pos, node)
|
|
||||||
minetest.remove_node(pos)
|
|
||||||
-- drop node itself with some probability depended on explosion intensity (1 for TNT):
|
|
||||||
if math.random(1, math.floor((intensity or 1) * 2)) ~= 1 then return end
|
|
||||||
local node_def = minetest.registered_nodes[node.name]
|
|
||||||
if not node_def then return end
|
|
||||||
local node_name = node_def.drop or node_def.name
|
|
||||||
drop_item_stack(pos, ItemStack(node_name))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function limit_put_list(stack, list)
|
local function limit_put_list(stack, list)
|
||||||
for _, other in ipairs(list) do
|
for _, other in ipairs(list) do
|
||||||
stack = other:add_item(stack)
|
stack = other:add_item(stack)
|
||||||
|
@ -380,15 +389,6 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
local function close_forms(canonical_basename, pos)
|
|
||||||
local players = minetest.get_connected_players()
|
|
||||||
for p=1, #players do
|
|
||||||
if vector.distance(players[p]:get_pos(), pos) <= 30 then
|
|
||||||
minetest.close_formspec(players[p]:get_player_name(), "mcl_chests:"..canonical_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_node(small_name, {
|
minetest.register_node(small_name, {
|
||||||
description = desc,
|
description = desc,
|
||||||
_tt_help = tt_help,
|
_tt_help = tt_help,
|
||||||
|
@ -1476,9 +1476,11 @@ minetest.register_node("mcl_chests:barrel", {
|
||||||
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
||||||
end,
|
end,
|
||||||
after_dig_node = drop_items_chest,
|
after_dig_node = drop_items_chest,
|
||||||
on_blast = on_blast,
|
on_blast = on_chest_blast,
|
||||||
on_rightclick = barrel_open,
|
on_rightclick = barrel_open,
|
||||||
on_destruct = close_forms,
|
on_destruct = function(pos)
|
||||||
|
close_forms("barrel", pos)
|
||||||
|
end,
|
||||||
_mcl_blast_resistance = 2.5,
|
_mcl_blast_resistance = 2.5,
|
||||||
_mcl_hardness = 2.5,
|
_mcl_hardness = 2.5,
|
||||||
})
|
})
|
||||||
|
@ -1497,9 +1499,11 @@ minetest.register_node("mcl_chests:barrel_open", {
|
||||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||||
groups = {handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1, not_in_creative_inventory = 1},
|
groups = {handy = 1, axey = 1, container = 2, material_wood = 1, flammable = -1, deco_block = 1, not_in_creative_inventory = 1},
|
||||||
after_dig_node = drop_items_chest,
|
after_dig_node = drop_items_chest,
|
||||||
on_blast = on_blast,
|
on_blast = on_chest_blast,
|
||||||
on_rightclick = barrel_open,
|
on_rightclick = barrel_open,
|
||||||
on_destruct = close_forms,
|
on_destruct = function(pos)
|
||||||
|
close_forms("barrel_open", pos)
|
||||||
|
end,
|
||||||
_mcl_blast_resistance = 2.5,
|
_mcl_blast_resistance = 2.5,
|
||||||
_mcl_hardness = 2.5,
|
_mcl_hardness = 2.5,
|
||||||
})
|
})
|
||||||
|
|
|
@ -388,6 +388,12 @@ end
|
||||||
["mcl_core:whirlpool_source"] = -BUBBLE_COLUMN_SPEED,
|
["mcl_core:whirlpool_source"] = -BUBBLE_COLUMN_SPEED,
|
||||||
["mcl_core:bubble_column_source"] = BUBBLE_COLUMN_SPEED,
|
["mcl_core:bubble_column_source"] = BUBBLE_COLUMN_SPEED,
|
||||||
}
|
}
|
||||||
|
local bubble_source_fast_switch_from_to = {
|
||||||
|
["mcl_nether:soul_sand"] = "mcl_core:bubble_column_source",
|
||||||
|
["mcl_core:bubble_column_source"] = "mcl_core:bubble_column_source",
|
||||||
|
["mcl_nether:magma"] = "mcl_core:whirlpool_source",
|
||||||
|
["mcl_core:whirlpool_source"] = "mcl_core:whirlpool_source",
|
||||||
|
}
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
label = "Process bubble columns and whirlpools",
|
label = "Process bubble columns and whirlpools",
|
||||||
nodenames = {"mcl_core:whirlpool_source", "mcl_core:bubble_column_source"},
|
nodenames = {"mcl_core:whirlpool_source", "mcl_core:bubble_column_source"},
|
||||||
|
@ -399,7 +405,7 @@ end
|
||||||
local check = nether_node_to_check[name]
|
local check = nether_node_to_check[name]
|
||||||
local below = minetest.get_node({x = x, y = y - 1, z = z}).name
|
local below = minetest.get_node({x = x, y = y - 1, z = z}).name
|
||||||
if below ~= name and below ~= check then
|
if below ~= name and below ~= check then
|
||||||
minetest.swap_node(pos, {name = "mcl_core:water_source"})
|
minetest.swap_node(pos, {name = bubble_source_fast_switch_from_to[below] or "mcl_core:water_source"})
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local upper_pos = {x = x, y = y + 1, z = z}
|
local upper_pos = {x = x, y = y + 1, z = z}
|
||||||
|
|
|
@ -10,7 +10,7 @@ minetest.register_entity("mcl_end:ender_eye", {
|
||||||
|
|
||||||
-- Save and restore age
|
-- Save and restore age
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
return tostring(self._age) or "0"
|
return tostring(self and self._age) or "0"
|
||||||
end,
|
end,
|
||||||
on_activate = function(self, staticdata, dtime_s)
|
on_activate = function(self, staticdata, dtime_s)
|
||||||
local age = tonumber(staticdata)
|
local age = tonumber(staticdata)
|
||||||
|
|
|
@ -33,6 +33,7 @@ minetest.register_entity("mcl_itemframes:item",{
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
if not self then return end
|
||||||
if self._nodename and self._texture then
|
if self._nodename and self._texture then
|
||||||
local ret = self._nodename .. ";" .. self._texture
|
local ret = self._nodename .. ";" .. self._texture
|
||||||
if self._scale then
|
if self._scale then
|
||||||
|
|
|
@ -352,7 +352,7 @@ local doll_def = {
|
||||||
}
|
}
|
||||||
|
|
||||||
doll_def.get_staticdata = function(self)
|
doll_def.get_staticdata = function(self)
|
||||||
return self._mob
|
return self and self._mob
|
||||||
end
|
end
|
||||||
|
|
||||||
doll_def.on_activate = function(self, staticdata, dtime_s)
|
doll_def.on_activate = function(self, staticdata, dtime_s)
|
||||||
|
|
|
@ -470,8 +470,8 @@ minetest.register_abm({
|
||||||
})
|
})
|
||||||
|
|
||||||
function generate_warped_tree(pos)
|
function generate_warped_tree(pos)
|
||||||
breakgrow = false
|
local breakgrow = false
|
||||||
breakgrow2 = false
|
local breakgrow2 = false
|
||||||
-- Baumgenerator
|
-- Baumgenerator
|
||||||
-- erste und zweite Etage
|
-- erste und zweite Etage
|
||||||
for x = pos.x - 2,pos.x + 2 do
|
for x = pos.x - 2,pos.x + 2 do
|
||||||
|
@ -547,8 +547,8 @@ function generate_warped_tree(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function generate_crimson_tree(pos)
|
function generate_crimson_tree(pos)
|
||||||
breakgrow = false
|
local breakgrow = false
|
||||||
breakgrow2 = false
|
local breakgrow2 = false
|
||||||
-- Baumgenerator
|
-- Baumgenerator
|
||||||
-- erste und zweite Etage
|
-- erste und zweite Etage
|
||||||
for x = pos.x - 2,pos.x + 2 do
|
for x = pos.x - 2,pos.x + 2 do
|
||||||
|
|
|
@ -746,7 +746,7 @@ minetest.register_abm({
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if lower_node_name == OBSIDIAN and pos.y >= mcl_mapgen.overworld.min and random(1, 200) == 19 then
|
if lower_node_name == OBSIDIAN and pos.y >= mcl_mapgen.overworld.min and random(1, 750) == 19 then
|
||||||
local pigman_obj = minetest.add_entity(pos, "mobs_mc:pigman")
|
local pigman_obj = minetest.add_entity(pos, "mobs_mc:pigman")
|
||||||
if pigman_obj then
|
if pigman_obj then
|
||||||
teleport_cooloff(pigman_obj)
|
teleport_cooloff(pigman_obj)
|
||||||
|
|
|
@ -391,6 +391,7 @@ function mcl_potions.register_arrow(name, desc, color, def)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ARROW_ENTITY.get_staticdata(self)
|
function ARROW_ENTITY.get_staticdata(self)
|
||||||
|
if not self then return end
|
||||||
local out = {
|
local out = {
|
||||||
lastpos = self._lastpos,
|
lastpos = self._lastpos,
|
||||||
startpos = self._startpos,
|
startpos = self._startpos,
|
||||||
|
|
|
@ -537,6 +537,7 @@ minetest.register_entity("mcl_signs:text", {
|
||||||
self.object:set_armor_groups({ immortal = 1 })
|
self.object:set_armor_groups({ immortal = 1 })
|
||||||
end,
|
end,
|
||||||
get_staticdata = function(self)
|
get_staticdata = function(self)
|
||||||
|
if not self then return end
|
||||||
local out = { _signnodename = self._signnodename }
|
local out = { _signnodename = self._signnodename }
|
||||||
return minetest.serialize(out)
|
return minetest.serialize(out)
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -57,6 +57,7 @@ end
|
||||||
|
|
||||||
-- Staticdata handling because objects may want to be reloaded
|
-- Staticdata handling because objects may want to be reloaded
|
||||||
function mcl_throwing.get_staticdata(self)
|
function mcl_throwing.get_staticdata(self)
|
||||||
|
if not self then return end
|
||||||
local thrower
|
local thrower
|
||||||
-- Only save thrower if it's a player name
|
-- Only save thrower if it's a player name
|
||||||
if type(self._thrower) == "string" then
|
if type(self._thrower) == "string" then
|
||||||
|
|
|
@ -17,16 +17,14 @@ mcl_mapgen.register_mapgen_block(function(minp, maxp)
|
||||||
local nodes = minetest_find_nodes_in_area(minp, maxp, debris_name)
|
local nodes = minetest_find_nodes_in_area(minp, maxp, debris_name)
|
||||||
if nodes then
|
if nodes then
|
||||||
for _, pos in pairs(nodes) do
|
for _, pos in pairs(nodes) do
|
||||||
minetest.log("warning","debris found at "..minetest.pos_to_string(pos))
|
|
||||||
local x, y, z = pos.x, pos.y, pos.z
|
local x, y, z = pos.x, pos.y, pos.z
|
||||||
if minetest_get_node({x = x-1, y = y, z = z}) == air_name
|
if minetest_get_node({x = x-1, y = y, z = z}).name == air_name
|
||||||
or minetest_get_node({x = x+1, y = y, z = z}) == air_name
|
or minetest_get_node({x = x+1, y = y, z = z}).name == air_name
|
||||||
or minetest_get_node({x = x, y = y-1, z = z}) == air_name
|
or minetest_get_node({x = x, y = y-1, z = z}).name == air_name
|
||||||
or minetest_get_node({x = x, y = y+1, z = z}) == air_name
|
or minetest_get_node({x = x, y = y+1, z = z}).name == air_name
|
||||||
or minetest_get_node({x = x, y = y, z = z-1}) == air_name
|
or minetest_get_node({x = x, y = y, z = z-1}).name == air_name
|
||||||
or minetest_get_node({x = x, y = y, z = z+1}) == air_name then
|
or minetest_get_node({x = x, y = y, z = z+1}).name == air_name then
|
||||||
minetest_set_node(pos, netherrack_name)
|
minetest_set_node(pos, {name = netherrack_name})
|
||||||
minetest.log("warning","debris at "..minetest.pos_to_string(pos) .. " replaced to netherrack")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -289,9 +289,9 @@ function mcl_structures.place_schematic(def)
|
||||||
pos = vector.new(pos),
|
pos = vector.new(pos),
|
||||||
schematic = loaded_schematic,
|
schematic = loaded_schematic,
|
||||||
rotation = rotation,
|
rotation = rotation,
|
||||||
replacements = replacements,
|
replacements = def.replacements,
|
||||||
force_placement = force_placement,
|
force_placement = def.force_placement,
|
||||||
flags = flags,
|
flags = def.flags,
|
||||||
size = vector.new(size),
|
size = vector.new(size),
|
||||||
pr = pr,
|
pr = pr,
|
||||||
on_placed = on_placed,
|
on_placed = on_placed,
|
||||||
|
|
|
@ -436,8 +436,7 @@ local function build_a_village(minp, maxp, pr, placer)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Disable natural generation in singlenode.
|
-- Disable natural generation in singlenode.
|
||||||
if mg_name ~= "singlenode" then
|
if not mcl_mapgen.singlenode then
|
||||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
|
||||||
local scan_last_node = mcl_mapgen.LAST_BLOCK * mcl_mapgen.BS - 1
|
local scan_last_node = mcl_mapgen.LAST_BLOCK * mcl_mapgen.BS - 1
|
||||||
local scan_offset = mcl_mapgen.BS
|
local scan_offset = mcl_mapgen.BS
|
||||||
mcl_mapgen.register_mapgen(function(minp, maxp, chunkseed)
|
mcl_mapgen.register_mapgen(function(minp, maxp, chunkseed)
|
||||||
|
|
|
@ -199,11 +199,10 @@ local function step()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif #players < 26 then
|
elseif #players < 26 then
|
||||||
if should_be_banned then
|
|
||||||
minetest.chat_send_all("Player " .. first .. " has been banned for having more than 9 connections at once")
|
|
||||||
minetest.ban_player(first)
|
|
||||||
else
|
|
||||||
for _, player_name in pairs(players) do
|
for _, player_name in pairs(players) do
|
||||||
|
if should_be_banned then
|
||||||
|
minetest.ban_player(player_name)
|
||||||
|
else
|
||||||
if (player_doesnt_move[player_name] or 0) > 90/step_seconds then
|
if (player_doesnt_move[player_name] or 0) > 90/step_seconds then
|
||||||
minetest.kick_player(player_name, "Didn't move during 1.5 minutes being connected multiple times")
|
minetest.kick_player(player_name, "Didn't move during 1.5 minutes being connected multiple times")
|
||||||
ban_next_time[ip] = 1
|
ban_next_time[ip] = 1
|
||||||
|
@ -211,18 +210,18 @@ local function step()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif #players <= 100 then
|
elseif #players <= 100 then
|
||||||
if should_be_banned then
|
|
||||||
minetest.ban_player(first)
|
|
||||||
minetest.chat_send_all("Player " .. first .. " has been banned for having more than 25 connections at once")
|
|
||||||
else
|
|
||||||
for _, player_name in pairs(players) do
|
for _, player_name in pairs(players) do
|
||||||
|
if should_be_banned then
|
||||||
|
minetest.ban_player(player_name)
|
||||||
|
else
|
||||||
minetest.kick_player(player_name, "More than 25 connections from IP address " .. ip)
|
minetest.kick_player(player_name, "More than 25 connections from IP address " .. ip)
|
||||||
end
|
|
||||||
ban_next_time[ip] = 1
|
ban_next_time[ip] = 1
|
||||||
end
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
minetest.ban_player(first)
|
for _, player_name in pairs(players) do
|
||||||
minetest.chat_send_all("Player " .. first .. " has been banned for having more than 100 connections at once")
|
minetest.ban_player(player_name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,6 @@ mcl_playerplus = {
|
||||||
elytra = {},
|
elytra = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
local player_velocity_old = {x=0, y=0, z=0}
|
|
||||||
local get_connected_players = minetest.get_connected_players
|
local get_connected_players = minetest.get_connected_players
|
||||||
local dir_to_yaw = minetest.dir_to_yaw
|
local dir_to_yaw = minetest.dir_to_yaw
|
||||||
local get_item_group = minetest.get_item_group
|
local get_item_group = minetest.get_item_group
|
||||||
|
@ -336,9 +335,6 @@ minetest.register_globalstep(function(dtime)
|
||||||
set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90))
|
set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90))
|
||||||
end
|
end
|
||||||
|
|
||||||
player_velocity_old = player:get_velocity() or player:get_player_velocity()
|
|
||||||
|
|
||||||
|
|
||||||
-- controls right and left arms pitch when shooting a bow or blocking
|
-- controls right and left arms pitch when shooting a bow or blocking
|
||||||
if mcl_shields.is_blocking(player) == 2 then
|
if mcl_shields.is_blocking(player) == 2 then
|
||||||
set_bone_position_conditional(player, "Arm_Right_Pitch_Control", vector.new(-3, 5.785, 0), vector.new(20, -20, 0))
|
set_bone_position_conditional(player, "Arm_Right_Pitch_Control", vector.new(-3, 5.785, 0), vector.new(20, -20, 0))
|
||||||
|
@ -460,13 +456,56 @@ minetest.register_globalstep(function(dtime)
|
||||||
|
|
||||||
local bubble_column_feet = node_feet == "mcl_core:bubble_column_source"
|
local bubble_column_feet = node_feet == "mcl_core:bubble_column_source"
|
||||||
if bubble_column_feet then
|
if bubble_column_feet then
|
||||||
|
local bubble_column_head = node_head == "mcl_core:bubble_column_source"
|
||||||
|
if bubble_column_head then
|
||||||
if not player_pos_for_bubble_columns[name] then
|
if not player_pos_for_bubble_columns[name] then
|
||||||
player_pos_for_bubble_columns[name] = fly_pos
|
player_pos_for_bubble_columns[name] = fly_pos
|
||||||
else
|
else
|
||||||
local bubble_column_head = node_head == "mcl_core:bubble_column_source"
|
local head_alt_1 = fly_pos.y + 1.5
|
||||||
fly_pos.y = player_pos_for_bubble_columns[name].y + (bubble_column_head and time or time/10)
|
local head_alt_2 = head_alt_1 + time
|
||||||
|
while head_alt_1 < head_alt_2 do
|
||||||
|
local next_alt = math.min(head_alt_1 + 1, head_alt_2)
|
||||||
|
local next_node_head = minetest.get_node({x = fly_pos.x, y = next_alt, z = fly_pos.z}).name
|
||||||
|
if next_node_head == "mcl_core:bubble_column_source" then
|
||||||
|
head_alt_1 = next_alt
|
||||||
|
else
|
||||||
|
local ndef = minetest.registered_nodes[next_node_head]
|
||||||
|
if (ndef.walkable == nil or ndef.walkable == true)
|
||||||
|
and (ndef.collision_box == nil or ndef.collision_box.type == "regular")
|
||||||
|
and (ndef.node_box == nil or ndef.node_box.type == "regular")
|
||||||
|
and (ndef.groups.disable_suffocation ~= 1)
|
||||||
|
and (ndef.groups.opaque == 1)
|
||||||
|
then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
-- pull head slightly above water level:
|
||||||
|
head_alt_1 = head_alt_1 + (next_alt - head_alt_1) * 0.5
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local new_alt = head_alt_1 - 1.5
|
||||||
|
local delta_y = new_alt - fly_pos.y
|
||||||
|
if delta_y > 0 then
|
||||||
|
fly_pos.y = new_alt
|
||||||
player:set_pos(fly_pos)
|
player:set_pos(fly_pos)
|
||||||
|
local velocity_y = player_velocity.y
|
||||||
|
local add_velocity_y
|
||||||
|
if velocity_y > 1 then
|
||||||
|
add_velocity_y = -velocity_y/5
|
||||||
|
elseif velocity_y >= -1 then
|
||||||
|
add_velocity_y = -velocity_y/2.5
|
||||||
|
else
|
||||||
|
add_velocity_y = -velocity_y/2
|
||||||
|
end
|
||||||
|
player:add_velocity({x = 0, y = add_velocity_y, z = 0})
|
||||||
player_pos_for_bubble_columns[name] = fly_pos
|
player_pos_for_bubble_columns[name] = fly_pos
|
||||||
|
else
|
||||||
|
player_pos_for_bubble_columns[name] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
player_pos_for_bubble_columns[name] = nil
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local whirlpool_feet = node_feet == "mcl_core:whirlpool_source"
|
local whirlpool_feet = node_feet == "mcl_core:whirlpool_source"
|
||||||
|
@ -479,22 +518,45 @@ minetest.register_globalstep(function(dtime)
|
||||||
if stands_on == "mcl_nether:magma" then
|
if stands_on == "mcl_nether:magma" then
|
||||||
fly_pos.y = math.floor(fly_pos.y) + (control.sneak and 0.51 or 0.5)
|
fly_pos.y = math.floor(fly_pos.y) + (control.sneak and 0.51 or 0.5)
|
||||||
player:set_pos(fly_pos)
|
player:set_pos(fly_pos)
|
||||||
player_pos_for_bubble_columns[name] = fly_pos
|
local add_velocity_y
|
||||||
|
local velocity_y = player_velocity.y
|
||||||
|
if velocity_y < -1 then
|
||||||
|
add_velocity_y = -velocity_y/5
|
||||||
|
elseif velocity_y <= 1 then
|
||||||
|
add_velocity_y = -velocity_y/2.5
|
||||||
else
|
else
|
||||||
fly_pos.y = player_pos_for_bubble_columns[name].y - (whirlpool_head and time/2 or time/5)
|
add_velocity_y = -velocity_y/2
|
||||||
local will_stand_on = minetest.get_node({x = fly_pos.x, y = fly_pos.y - 0.0001, z = fly_pos.z}).name
|
end
|
||||||
if will_stand_on == "mcl_nether:magma" then
|
player:add_velocity({x = 0, y = add_velocity_y, z = 0})
|
||||||
fly_pos.y = math.floor(fly_pos.y) + (control.sneak and 0.51 or 0.5)
|
|
||||||
player:set_pos(fly_pos)
|
|
||||||
player_pos_for_bubble_columns[name] = fly_pos
|
player_pos_for_bubble_columns[name] = fly_pos
|
||||||
elseif will_stand_on == "mcl_core:whirlpool_source" then
|
elseif stands_on == "mcl_core:whirlpool_source" then
|
||||||
|
local estimated_pos_y = player_pos_for_bubble_columns[name].y - (whirlpool_head and time/2 or time/5)
|
||||||
|
local next_pos_y = fly_pos.y
|
||||||
|
while next_pos_y > estimated_pos_y do
|
||||||
|
next_pos_y = next_pos_y - math.min(1, next_pos_y - estimated_pos_y)
|
||||||
|
local will_stand_on = minetest.get_node({x = fly_pos.x, y = next_pos_y - 0.0001, z = fly_pos.z}).name
|
||||||
|
if will_stand_on ~= "mcl_core:whirlpool_source" then
|
||||||
|
next_pos_y = math.floor(next_pos_y - 0.0001) + (control.sneak and 0.51 or 0.5)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
fly_pos.y = next_pos_y
|
||||||
player:set_pos(fly_pos)
|
player:set_pos(fly_pos)
|
||||||
|
local add_velocity_y
|
||||||
|
local velocity_y = player_velocity.y
|
||||||
|
if velocity_y < -1 then
|
||||||
|
add_velocity_y = -velocity_y/5
|
||||||
|
elseif velocity_y <= 1 then
|
||||||
|
add_velocity_y = -velocity_y/2.5
|
||||||
|
else
|
||||||
|
add_velocity_y = -velocity_y/2
|
||||||
|
end
|
||||||
|
player:add_velocity({x = 0, y = add_velocity_y, z = 0})
|
||||||
player_pos_for_bubble_columns[name] = fly_pos
|
player_pos_for_bubble_columns[name] = fly_pos
|
||||||
else
|
else
|
||||||
player_pos_for_bubble_columns[name] = nil
|
player_pos_for_bubble_columns[name] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
elseif player_pos_for_bubble_columns[name] then
|
elseif player_pos_for_bubble_columns[name] then
|
||||||
player_pos_for_bubble_columns[name] = nil
|
player_pos_for_bubble_columns[name] = nil
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue