forked from MineClone5/MineClone5
Merge pull request 'Release 1.9' (#252) from compatibility into production-compatible
Reviewed-on: MineClone5/MineClone5#252
This commit is contained in:
commit
cd4cd3f7c7
|
@ -27,19 +27,35 @@ Any Pull Request that isn't a bug fix can be closed within a week unless it rece
|
||||||
|
|
||||||
Start coding!
|
Start coding!
|
||||||
|
|
||||||
Refer to Minetest Lua API, Developer Wiki and other documentation.
|
Refer to [Minetest Lua API](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt), [Developer Wiki](https://dev.minetest.net/), [MineClone 5 Wiki](https://git.minetest.land/MineClone5/MineClone5/wiki/) and other documentation.
|
||||||
|
|
||||||
Follow Lua code style guidelines. Use tabs, not spaces for indentation (tab size = 8). Never use `minetest.env`.
|
Follow [Lua code style guidelines](https://dev.minetest.net/Lua_code_style_guidelines). Use tabs, not spaces for indentation (tab size = 8). Never use `minetest.env`.
|
||||||
|
|
||||||
Check your code works as expected.
|
Check your code works as expected.
|
||||||
|
|
||||||
Commit & push your changes to a new branch (not master, one change per branch)
|
Commit & push your changes to a new branch (not master, one change per a branch).
|
||||||
|
|
||||||
Commit messages should use the present tense and be descriptive.
|
Commit messages should use the present tense and be descriptive.
|
||||||
|
|
||||||
Once you are happy with your changes, submit a pull request.
|
Once you are happy with your changes, submit a pull request.
|
||||||
|
|
||||||
A pull-request is considered merge-able when:
|
A pull-request is considered merge-able when it looks good to one person from the community.
|
||||||
|
|
||||||
|
Please invite other developers to review your contribution when you know they are online. If there is no any reaction during 24 hours after posting the invitation and pinging developers - you are welcome to do a self-review and merge the request.
|
||||||
|
|
||||||
|
If someone else's contribution looks good to you - you are free to merge it ASAP.
|
||||||
|
|
||||||
|
Different git branches are welcomed! Releases by different people are welcomed! Releases from different branches are welcomed! Frequent releases are welcomed!
|
||||||
|
|
||||||
|
It is nice not to block other developers by your work and don't dictate them what to do, unsless they really want that. Git branches and forks are recommended to avoid conflicts at development stage.
|
||||||
|
|
||||||
|
It is nice to try splitting big features into small steps.
|
||||||
|
|
||||||
|
It is nice to create an issue for any work and mention the issue in the commit text, like `#123 Fix blast resistance of cactus`, where `#123` is the issue number.
|
||||||
|
|
||||||
|
Actually, it looks like we all love what we do, so any stupid situations should be carefully discussed before merging into upstreams. But nothing prevents us from releasing controversial stuff through dedicated branches. Release your contribution when you need more feedback.
|
||||||
|
|
||||||
|
Feel free to break the rules if you're sure you have to.
|
||||||
|
|
||||||
#### Contributors
|
#### Contributors
|
||||||
|
|
||||||
|
|
|
@ -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,35 +118,30 @@ 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",
|
||||||
{
|
"Swampland",
|
||||||
"FlowerForest",
|
"Taiga",
|
||||||
"Swampland",
|
"ExtremeHills",
|
||||||
"Taiga",
|
"BirchForest",
|
||||||
"ExtremeHills",
|
"MegaSpruceTaiga",
|
||||||
"BirchForest",
|
"MegaTaiga",
|
||||||
"MegaSpruceTaiga",
|
"ExtremeHills+",
|
||||||
"MegaTaiga",
|
"Forest",
|
||||||
"ExtremeHills+",
|
"Plains",
|
||||||
"Forest",
|
"ColdTaiga",
|
||||||
"Plains",
|
"SunflowerPlains",
|
||||||
"ColdTaiga",
|
"RoofedForest",
|
||||||
"SunflowerPlains",
|
"MesaPlateauFM_grasstop",
|
||||||
"RoofedForest",
|
"ExtremeHillsM",
|
||||||
"MesaPlateauFM_grasstop",
|
"BirchForestM",
|
||||||
"ExtremeHillsM",
|
},
|
||||||
"BirchForestM",
|
interval = 30,
|
||||||
},
|
chance = 6000,
|
||||||
0,
|
min_height = mobs_mc.spawn_height.water,
|
||||||
minetest.LIGHT_MAX+1,
|
})
|
||||||
30,
|
|
||||||
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",
|
||||||
"Nether"
|
biomes = {
|
||||||
},
|
"Nether"
|
||||||
0,
|
},
|
||||||
minetest.LIGHT_MAX+1,
|
min_height = mcl_mapgen.nether.min,
|
||||||
30,
|
max_height = mcl_mapgen.nether.max,
|
||||||
6000,
|
chance = 2000,
|
||||||
3,
|
check_position = function(pos)
|
||||||
mobs_mc.spawn_height.nether_min,
|
return minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z}).name:find("lava")
|
||||||
mobs_mc.spawn_height.nether_max)
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -488,6 +488,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)
|
||||||
return mobs.mob_staticdata(self)
|
if self and mobs then
|
||||||
|
return mobs.mob_staticdata(self)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--harmed_by_heal = def.harmed_by_heal,
|
--harmed_by_heal = def.harmed_by_heal,
|
||||||
|
|
|
@ -801,20 +801,6 @@ function mobs.mob_step(self, dtime)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--DEBUG TIME!
|
|
||||||
--REMEMBER TO MOVE THIS AFTER DEATH CHECK
|
|
||||||
|
|
||||||
--if self.has_head then
|
|
||||||
-- mobs.do_head_logic(self,dtime)
|
|
||||||
--end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--if true then--DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
|
|
||||||
-- return
|
|
||||||
--end
|
|
||||||
|
|
||||||
--despawn mechanism
|
--despawn mechanism
|
||||||
--don't despawned tamed or bred mobs
|
--don't despawned tamed or bred mobs
|
||||||
if not self.tamed and not self.bred then
|
if not self.tamed and not self.bred then
|
||||||
|
@ -833,7 +819,7 @@ function mobs.mob_step(self, dtime)
|
||||||
self.object:set_texture_mod("^[colorize:red:120")
|
self.object:set_texture_mod("^[colorize:red:120")
|
||||||
--fix double death sound
|
--fix double death sound
|
||||||
if self.health > 0 then
|
if self.health > 0 then
|
||||||
mobs.play_sound(self,"damage")
|
mobs.play_sound(self, "damage")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.old_health = self.health
|
self.old_health = self.health
|
||||||
|
@ -863,7 +849,7 @@ function mobs.mob_step(self, dtime)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
mobs.random_sound_handling(self,dtime)
|
mobs.random_sound_handling(self, dtime)
|
||||||
|
|
||||||
--mobs drowning mechanic
|
--mobs drowning mechanic
|
||||||
if not self.breathes_in_water then
|
if not self.breathes_in_water then
|
||||||
|
@ -893,14 +879,40 @@ function mobs.mob_step(self, dtime)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
local node = minetest_get_node(pos).name
|
||||||
|
|
||||||
--water damage
|
--water damage
|
||||||
if self.water_damage and self.water_damage ~= 0 then
|
if self.water_damage and self.water_damage ~= 0 and minetest_get_item_group(node, "water") ~= 0 then
|
||||||
local pos = self.object:get_pos()
|
self.water_counter = (self.water_counter or 0) + dtime
|
||||||
local node = minetest_get_node(pos).name
|
if self.water_counter >= 1 then
|
||||||
if minetest_get_item_group(node, "water") ~= 0 then
|
|
||||||
mobs.smoke_effect(self)
|
mobs.smoke_effect(self)
|
||||||
self.health = self.health - self.water_damage
|
self.health = self.health - self.water_damage
|
||||||
self:teleport()
|
self:teleport()
|
||||||
|
self.water_counter = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--lava damage
|
||||||
|
local lava_damage = self.lava_damage
|
||||||
|
if lava_damage and lava_damage ~= 0 and minetest_get_item_group(node, "lava") ~= 0 then
|
||||||
|
self.lava_counter = (self.lava_counter or 0) + dtime
|
||||||
|
if self.lava_counter >= 1 then
|
||||||
|
minetest.sound_play("default_punch", {
|
||||||
|
object = self.object,
|
||||||
|
max_hear_distance = 5
|
||||||
|
}, true)
|
||||||
|
--[[ 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,
|
||||||
|
damage_groups = {fleshy = self.lava_damage}
|
||||||
|
}, nil)
|
||||||
|
-- end
|
||||||
|
self.lava_counter = 0
|
||||||
|
self.health = self.health - lava_damage
|
||||||
|
self:teleport()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -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,151 +25,171 @@ 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,
|
||||||
|
}
|
||||||
|
|
||||||
underground:
|
-- THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
|
||||||
"FlowerForest_underground",
|
-- Also used for missing parameter
|
||||||
"JungleEdge_underground",local spawning_position = spawning_position_list[math.random(1,#spawning_position_list)]
|
-- Please update the list when adding new biomes!
|
||||||
"ColdTaiga_underground",
|
|
||||||
"IcePlains_underground",
|
|
||||||
"IcePlainsSpikes_underground",
|
|
||||||
"MegaTaiga_underground",
|
|
||||||
"Taiga_underground",
|
|
||||||
"ExtremeHills+_underground",
|
|
||||||
"JungleM_underground",
|
|
||||||
"ExtremeHillsM_underground",
|
|
||||||
"JungleEdgeM_underground",
|
|
||||||
|
|
||||||
ocean:
|
local list_of_all_biomes = {
|
||||||
"RoofedForest_ocean",
|
|
||||||
"JungleEdgeM_ocean",
|
|
||||||
"BirchForestM_ocean",
|
|
||||||
"BirchForest_ocean",
|
|
||||||
"IcePlains_deep_ocean",
|
|
||||||
"Jungle_deep_ocean",
|
|
||||||
"Savanna_ocean",
|
|
||||||
"MesaPlateauF_ocean",
|
|
||||||
"ExtremeHillsM_deep_ocean",
|
|
||||||
"Savanna_deep_ocean",
|
|
||||||
"SunflowerPlains_ocean",
|
|
||||||
"Swampland_deep_ocean",
|
|
||||||
"Swampland_ocean",
|
|
||||||
"MegaSpruceTaiga_deep_ocean",
|
|
||||||
"ExtremeHillsM_ocean",
|
|
||||||
"JungleEdgeM_deep_ocean",
|
|
||||||
"SunflowerPlains_deep_ocean",
|
|
||||||
"BirchForest_deep_ocean",
|
|
||||||
"IcePlainsSpikes_ocean",
|
|
||||||
"Mesa_ocean",
|
|
||||||
"StoneBeach_ocean",
|
|
||||||
"Plains_deep_ocean",
|
|
||||||
"JungleEdge_deep_ocean",
|
|
||||||
"SavannaM_deep_ocean",
|
|
||||||
"Desert_deep_ocean",
|
|
||||||
"Mesa_deep_ocean",
|
|
||||||
"ColdTaiga_deep_ocean",
|
|
||||||
"Plains_ocean",
|
|
||||||
"MesaPlateauFM_ocean",
|
|
||||||
"Forest_deep_ocean",
|
|
||||||
"JungleM_deep_ocean",
|
|
||||||
"FlowerForest_deep_ocean",
|
|
||||||
"MushroomIsland_ocean",
|
|
||||||
"MegaTaiga_ocean",
|
|
||||||
"StoneBeach_deep_ocean",
|
|
||||||
"IcePlainsSpikes_deep_ocean",
|
|
||||||
"ColdTaiga_ocean",
|
|
||||||
"SavannaM_ocean",
|
|
||||||
"MesaPlateauF_deep_ocean",
|
|
||||||
"MesaBryce_deep_ocean",
|
|
||||||
"ExtremeHills+_deep_ocean",
|
|
||||||
"ExtremeHills_ocean",
|
|
||||||
"MushroomIsland_deep_ocean",
|
|
||||||
"Forest_ocean",
|
|
||||||
"MegaTaiga_deep_ocean",
|
|
||||||
"JungleEdge_ocean",
|
|
||||||
"MesaBryce_ocean",
|
|
||||||
"MegaSpruceTaiga_ocean",
|
|
||||||
"ExtremeHills+_ocean",
|
|
||||||
"Jungle_ocean",
|
|
||||||
"RoofedForest_deep_ocean",
|
|
||||||
"IcePlains_ocean",
|
|
||||||
"FlowerForest_ocean",
|
|
||||||
"ExtremeHills_deep_ocean",
|
|
||||||
"MesaPlateauFM_deep_ocean",
|
|
||||||
"Desert_ocean",
|
|
||||||
"Taiga_ocean",
|
|
||||||
"BirchForestM_deep_ocean",
|
|
||||||
"Taiga_deep_ocean",
|
|
||||||
"JungleM_ocean",
|
|
||||||
|
|
||||||
water or beach?
|
-- underground:
|
||||||
"MesaPlateauFM_sandlevel",
|
|
||||||
"MesaPlateauF_sandlevel",
|
|
||||||
"MesaBryce_sandlevel",
|
|
||||||
"Mesa_sandlevel",
|
|
||||||
|
|
||||||
beach:
|
"FlowerForest_underground",
|
||||||
"FlowerForest_beach",
|
"JungleEdge_underground",
|
||||||
"Forest_beach",
|
"ColdTaiga_underground",
|
||||||
"StoneBeach",
|
"IcePlains_underground",
|
||||||
"ColdTaiga_beach_water",
|
"IcePlainsSpikes_underground",
|
||||||
"Taiga_beach",
|
"MegaTaiga_underground",
|
||||||
"Savanna_beach",
|
"Taiga_underground",
|
||||||
"Plains_beach",
|
"ExtremeHills+_underground",
|
||||||
"ExtremeHills_beach",
|
"JungleM_underground",
|
||||||
"ColdTaiga_beach",
|
"ExtremeHillsM_underground",
|
||||||
"Swampland_shore",
|
"JungleEdgeM_underground",
|
||||||
"MushroomIslandShore",
|
|
||||||
"JungleM_shore",
|
|
||||||
"Jungle_shore",
|
|
||||||
|
|
||||||
dimension biome:
|
-- ocean:
|
||||||
"Nether",
|
|
||||||
"End",
|
|
||||||
|
|
||||||
Overworld regular:
|
"RoofedForest_ocean",
|
||||||
"Mesa",
|
"JungleEdgeM_ocean",
|
||||||
"FlowerForest",
|
"BirchForestM_ocean",
|
||||||
"Swampland",
|
"BirchForest_ocean",
|
||||||
"Taiga",
|
"IcePlains_deep_ocean",
|
||||||
"ExtremeHills",
|
"Jungle_deep_ocean",
|
||||||
"Jungle",
|
"Savanna_ocean",
|
||||||
"Savanna",
|
"MesaPlateauF_ocean",
|
||||||
"BirchForest",
|
"ExtremeHillsM_deep_ocean",
|
||||||
"MegaSpruceTaiga",
|
"Savanna_deep_ocean",
|
||||||
"MegaTaiga",
|
"SunflowerPlains_ocean",
|
||||||
"ExtremeHills+",
|
"Swampland_deep_ocean",
|
||||||
"Forest",
|
"Swampland_ocean",
|
||||||
"Plains",
|
"MegaSpruceTaiga_deep_ocean",
|
||||||
"Desert",
|
"ExtremeHillsM_ocean",
|
||||||
"ColdTaiga",
|
"JungleEdgeM_deep_ocean",
|
||||||
"MushroomIsland",
|
"SunflowerPlains_deep_ocean",
|
||||||
"IcePlainsSpikes",
|
"BirchForest_deep_ocean",
|
||||||
"SunflowerPlains",
|
"IcePlainsSpikes_ocean",
|
||||||
"IcePlains",
|
"Mesa_ocean",
|
||||||
"RoofedForest",
|
"StoneBeach_ocean",
|
||||||
"ExtremeHills+_snowtop",
|
"Plains_deep_ocean",
|
||||||
"MesaPlateauFM_grasstop",
|
"JungleEdge_deep_ocean",
|
||||||
"JungleEdgeM",
|
"SavannaM_deep_ocean",
|
||||||
"ExtremeHillsM",
|
"Desert_deep_ocean",
|
||||||
"JungleM",
|
"Mesa_deep_ocean",
|
||||||
"BirchForestM",
|
"ColdTaiga_deep_ocean",
|
||||||
"MesaPlateauF",
|
"Plains_ocean",
|
||||||
"MesaPlateauFM",
|
"MesaPlateauFM_ocean",
|
||||||
"MesaPlateauF_grasstop",
|
"Forest_deep_ocean",
|
||||||
"MesaBryce",
|
"JungleM_deep_ocean",
|
||||||
"JungleEdge",
|
"FlowerForest_deep_ocean",
|
||||||
"SavannaM",
|
"MushroomIsland_ocean",
|
||||||
]]--
|
"MegaTaiga_ocean",
|
||||||
|
"StoneBeach_deep_ocean",
|
||||||
|
"IcePlainsSpikes_deep_ocean",
|
||||||
|
"ColdTaiga_ocean",
|
||||||
|
"SavannaM_ocean",
|
||||||
|
"MesaPlateauF_deep_ocean",
|
||||||
|
"MesaBryce_deep_ocean",
|
||||||
|
"ExtremeHills+_deep_ocean",
|
||||||
|
"ExtremeHills_ocean",
|
||||||
|
"MushroomIsland_deep_ocean",
|
||||||
|
"Forest_ocean",
|
||||||
|
"MegaTaiga_deep_ocean",
|
||||||
|
"JungleEdge_ocean",
|
||||||
|
"MesaBryce_ocean",
|
||||||
|
"MegaSpruceTaiga_ocean",
|
||||||
|
"ExtremeHills+_ocean",
|
||||||
|
"Jungle_ocean",
|
||||||
|
"RoofedForest_deep_ocean",
|
||||||
|
"IcePlains_ocean",
|
||||||
|
"FlowerForest_ocean",
|
||||||
|
"ExtremeHills_deep_ocean",
|
||||||
|
"MesaPlateauFM_deep_ocean",
|
||||||
|
"Desert_ocean",
|
||||||
|
"Taiga_ocean",
|
||||||
|
"BirchForestM_deep_ocean",
|
||||||
|
"Taiga_deep_ocean",
|
||||||
|
"JungleM_ocean",
|
||||||
|
|
||||||
|
-- water or beach?
|
||||||
|
|
||||||
|
"MesaPlateauFM_sandlevel",
|
||||||
|
"MesaPlateauF_sandlevel",
|
||||||
|
"MesaBryce_sandlevel",
|
||||||
|
"Mesa_sandlevel",
|
||||||
|
|
||||||
|
-- beach:
|
||||||
|
|
||||||
|
"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",
|
||||||
|
|
||||||
|
-- dimension biome:
|
||||||
|
|
||||||
|
"Nether",
|
||||||
|
"End",
|
||||||
|
|
||||||
|
-- Overworld regular:
|
||||||
|
|
||||||
|
"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",
|
||||||
|
}
|
||||||
|
|
||||||
-- 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,
|
||||||
|
z = math_round(pos.z + distance * math_sin(angle))
|
||||||
|
}
|
||||||
end
|
end
|
||||||
]]--
|
|
||||||
|
|
||||||
|
|
||||||
--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}
|
|
||||||
}
|
|
||||||
]]--
|
|
||||||
|
|
||||||
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,176 +373,102 @@ local function biome_check(biome_list, biome_goal)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--todo mob limiting
|
|
||||||
--MAIN LOOP
|
|
||||||
|
|
||||||
if mobs_spawn then
|
if mobs_spawn then
|
||||||
|
|
||||||
|
local perlin_noise
|
||||||
|
|
||||||
|
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)]
|
||||||
|
|
||||||
|
--hard code mob limit in area to 5 for now
|
||||||
|
if count_mobs(spawning_position) >= 5 then return end
|
||||||
|
|
||||||
|
local gotten_node = get_node(spawning_position).name
|
||||||
|
local gotten_biome = minetest.get_biome_data(spawning_position)
|
||||||
|
if not gotten_node or not gotten_biome then return end
|
||||||
|
gotten_biome = get_biome_name(gotten_biome.biome) --makes it easier to work with
|
||||||
|
|
||||||
|
--add this so mobs don't spawn inside nodes
|
||||||
|
spawning_position.y = spawning_position.y + 1
|
||||||
|
|
||||||
|
--only need to poll for node light if everything else worked
|
||||||
|
local gotten_light = get_node_light(spawning_position)
|
||||||
|
|
||||||
|
local is_water = get_item_group(gotten_node, "water") ~= 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
|
||||||
|
|
||||||
|
--create a disconnected clone of the spawn dictionary
|
||||||
|
--prevents memory leak
|
||||||
|
local mob_library_worker_table = table_copy(spawn_dictionary)
|
||||||
|
|
||||||
|
--grab mob that fits into the spawning location
|
||||||
|
--randomly grab a mob, don't exclude any possibilities
|
||||||
|
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
||||||
|
local noise = perlin_noise:get_3d(spawning_position)
|
||||||
|
local current_summary_chance = summary_chance
|
||||||
|
while #mob_library_worker_table > 0 do
|
||||||
|
local mob_chance_offset = (math_round(noise * current_summary_chance + 12345) % current_summary_chance) + 1
|
||||||
|
local mob_index = 1
|
||||||
|
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
|
||||||
|
local mob_def = mob_library_worker_table[mob_index]
|
||||||
|
if mob_def
|
||||||
|
and spawning_position.y >= mob_def.min_height
|
||||||
|
and spawning_position.y <= mob_def.max_height
|
||||||
|
and mob_def.dimension == dimension
|
||||||
|
and biome_check(mob_def.biomes, gotten_biome)
|
||||||
|
and gotten_light >= mob_def.min_light
|
||||||
|
and gotten_light <= mob_def.max_light
|
||||||
|
and (is_ground or mob_def.type_of_spawning ~= "ground")
|
||||||
|
and (mob_def.check_position and mob_def.check_position(spawning_position) or true)
|
||||||
|
then
|
||||||
|
--everything is correct, spawn mob
|
||||||
|
local object = minetest.add_entity(spawning_position, mob_def.name)
|
||||||
|
if object then
|
||||||
|
return mob_def.on_spawn and mob_def.on_spawn(object, pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
current_summary_chance = current_summary_chance - mob_chance
|
||||||
|
table_remove(mob_library_worker_table, mob_index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--MAIN LOOP
|
||||||
|
|
||||||
local timer = 0
|
local timer = 0
|
||||||
minetest.register_globalstep(function(dtime)
|
minetest.register_globalstep(function(dtime)
|
||||||
timer = timer + dtime
|
timer = timer + dtime
|
||||||
if timer >= 10 then
|
if timer < 10 then return end
|
||||||
timer = 0
|
timer = 0
|
||||||
for _,player in pairs(get_connected_players()) do
|
for _, player in pairs(get_connected_players()) do
|
||||||
-- after this line each "break" means "continue"
|
local pos = player:get_pos()
|
||||||
local do_mob_spawning = true
|
local dimension = mcl_worlds.pos_to_dimension(pos)
|
||||||
repeat
|
-- ignore void and unloaded area
|
||||||
--don't need to get these variables more than once
|
if dimension ~= "void" and dimension ~= "default" then
|
||||||
--they happen in a single server step
|
local y_min, y_max = decypher_limits(pos.y)
|
||||||
|
for i = 1, math_random(1, 4) do
|
||||||
local player_pos = player:get_pos()
|
spawn_a_mob(pos, dimension, y_min, y_max)
|
||||||
local dimension = mcl_worlds.pos_to_dimension(player_pos)
|
end
|
||||||
|
|
||||||
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 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
|
|
||||||
if count_mobs(spawning_position) >= 5 then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
--add this so mobs don't spawn inside nodes
|
|
||||||
spawning_position.y = spawning_position.y + 1
|
|
||||||
|
|
||||||
--only need to poll for node light if everything else worked
|
|
||||||
local gotten_light = get_node_light(spawning_position)
|
|
||||||
|
|
||||||
local is_water = get_item_group(gotten_node, "water") ~= 0
|
|
||||||
local is_lava = get_item_group(gotten_node, "lava") ~= 0
|
|
||||||
|
|
||||||
local mob_def = nil
|
|
||||||
|
|
||||||
--create a disconnected clone of the spawn dictionary
|
|
||||||
--prevents memory leak
|
|
||||||
local mob_library_worker_table = table_copy(spawn_dictionary)
|
|
||||||
|
|
||||||
--grab mob that fits into the spawning location
|
|
||||||
--randomly grab a mob, don't exclude any possibilities
|
|
||||||
local repeat_mob_search = true
|
|
||||||
repeat
|
|
||||||
|
|
||||||
--do not infinite loop
|
|
||||||
if #mob_library_worker_table <= 0 then
|
|
||||||
--print("breaking infinite loop")
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
local skip = false
|
|
||||||
|
|
||||||
--use this for removing table elements of mobs that do not match
|
|
||||||
local temp_index = math_random(1,#mob_library_worker_table)
|
|
||||||
|
|
||||||
local temp_def = mob_library_worker_table[temp_index]
|
|
||||||
|
|
||||||
--skip if something ridiculous happens (nil mob def)
|
|
||||||
--something truly horrible has happened if skip gets
|
|
||||||
--activated at this point
|
|
||||||
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
|
|
||||||
minetest.add_entity(spawning_position, mob_def.name)
|
|
||||||
|
|
||||||
break
|
|
||||||
until do_mob_algorithm == false --this is a safety catch
|
|
||||||
end
|
|
||||||
|
|
||||||
break
|
|
||||||
until do_mob_spawning == false --this is a performance catch
|
|
||||||
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,11 +38,14 @@ 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
|
||||||
obj:punch(self.object, 1.0, {
|
local entity = obj:get_luaentity()
|
||||||
full_punch_interval=1.0,
|
if entity and entity._cmi_is_mob then
|
||||||
damage_groups={fleshy=damagemulitplier - vector.distance(self.object:get_pos(), obj:get_pos())},
|
obj:punch(self.object, 1.0, {
|
||||||
}, self.object:get_velocity())
|
full_punch_interval=1.0,
|
||||||
|
damage_groups={fleshy=damagemulitplier - vector.distance(self.object:get_pos(), obj:get_pos())},
|
||||||
|
}, self.object:get_velocity())
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -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,6 +746,13 @@ minetest.register_abm({
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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")
|
||||||
|
if pigman_obj then
|
||||||
|
teleport_cooloff(pigman_obj)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local o = node.param2 -- orientation
|
local o = node.param2 -- orientation
|
||||||
|
|
||||||
local closer_node_name = get_node({x = pos.x - 1 + o, y = pos.y, z = pos.z - o}).name
|
local closer_node_name = get_node({x = pos.x - 1 + o, y = pos.y, z = pos.z - o}).name
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -291,9 +291,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)
|
||||||
|
|
|
@ -63,7 +63,7 @@ local function update_player(player_object)
|
||||||
|
|
||||||
local noclip = #find_nodes_in_area({x = x, y = head_y, z = z}, {x = x + 1, y = head_y + 1, z = z + 1}, "group:opaque") == 8
|
local noclip = #find_nodes_in_area({x = x, y = head_y, z = z}, {x = x + 1, y = head_y + 1, z = z + 1}, "group:opaque") == 8
|
||||||
|
|
||||||
local velocity = player_object:get_velocity()
|
local velocity = player_object:get_velocity() or player_object:get_player_velocity()
|
||||||
if vector_length(velocity) < 0.00000001 then
|
if vector_length(velocity) < 0.00000001 then
|
||||||
player_doesnt_move[name] = (player_doesnt_move[name] or 0) + 1
|
player_doesnt_move[name] = (player_doesnt_move[name] or 0) + 1
|
||||||
else
|
else
|
||||||
|
@ -71,7 +71,7 @@ local function update_player(player_object)
|
||||||
end
|
end
|
||||||
local player_data = {
|
local player_data = {
|
||||||
pos = pos,
|
pos = pos,
|
||||||
velocity = player_object:get_velocity() or player_object:get_player_velocity(),
|
velocity = velocity,
|
||||||
air = air,
|
air = air,
|
||||||
noclip = noclip,
|
noclip = noclip,
|
||||||
}
|
}
|
||||||
|
@ -199,11 +199,10 @@ local function step()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif #players < 26 then
|
elseif #players < 26 then
|
||||||
if should_be_banned then
|
for _, player_name in pairs(players) do
|
||||||
minetest.chat_send_all("Player " .. first .. " has been banned for having more than 9 connections at once")
|
if should_be_banned then
|
||||||
minetest.ban_player(first)
|
minetest.ban_player(player_name)
|
||||||
else
|
else
|
||||||
for _, player_name in pairs(players) do
|
|
||||||
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
|
for _, player_name in pairs(players) do
|
||||||
minetest.ban_player(first)
|
if should_be_banned then
|
||||||
minetest.chat_send_all("Player " .. first .. " has been banned for having more than 25 connections at once")
|
minetest.ban_player(player_name)
|
||||||
else
|
else
|
||||||
for _, player_name in pairs(players) do
|
|
||||||
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)
|
||||||
|
ban_next_time[ip] = 1
|
||||||
end
|
end
|
||||||
ban_next_time[ip] = 1
|
|
||||||
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
|
||||||
|
@ -341,9 +340,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))
|
||||||
|
@ -466,13 +462,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
|
||||||
if not player_pos_for_bubble_columns[name] then
|
local bubble_column_head = node_head == "mcl_core:bubble_column_source"
|
||||||
player_pos_for_bubble_columns[name] = fly_pos
|
if bubble_column_head then
|
||||||
|
if not player_pos_for_bubble_columns[name] then
|
||||||
|
player_pos_for_bubble_columns[name] = fly_pos
|
||||||
|
else
|
||||||
|
local head_alt_1 = fly_pos.y + 1.5
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
else
|
||||||
|
player_pos_for_bubble_columns[name] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
local bubble_column_head = node_head == "mcl_core:bubble_column_source"
|
player_pos_for_bubble_columns[name] = nil
|
||||||
fly_pos.y = player_pos_for_bubble_columns[name].y + (bubble_column_head and time or time/10)
|
|
||||||
player:set_pos(fly_pos)
|
|
||||||
player_pos_for_bubble_columns[name] = fly_pos
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local whirlpool_feet = node_feet == "mcl_core:whirlpool_source"
|
local whirlpool_feet = node_feet == "mcl_core:whirlpool_source"
|
||||||
|
@ -485,20 +524,43 @@ 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)
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
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
|
||||||
fly_pos.y = player_pos_for_bubble_columns[name].y - (whirlpool_head and time/2 or time/5)
|
player_pos_for_bubble_columns[name] = nil
|
||||||
local will_stand_on = minetest.get_node({x = fly_pos.x, y = fly_pos.y - 0.0001, z = fly_pos.z}).name
|
|
||||||
if will_stand_on == "mcl_nether:magma" then
|
|
||||||
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
|
|
||||||
elseif will_stand_on == "mcl_core:whirlpool_source" then
|
|
||||||
player:set_pos(fly_pos)
|
|
||||||
player_pos_for_bubble_columns[name] = fly_pos
|
|
||||||
else
|
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue