Add deep water spawner
This commit is contained in:
parent
e058deb494
commit
f98020d6b5
281
mobf/spawn_algorithms/deep_water.lua
Normal file
281
mobf/spawn_algorithms/deep_water.lua
Normal file
@ -0,0 +1,281 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- Mob Framework Mod by Sapier
|
||||
--
|
||||
-- You may copy, use, modify or do nearly anything except removing this
|
||||
-- copyright notice.
|
||||
-- And of course you are NOT allow to pretend you have written it.
|
||||
--
|
||||
--! @file deep_water.lua
|
||||
--! @brief spawn algorithm for deep water spawning
|
||||
--! @copyright Sapier
|
||||
--! @author Sapier
|
||||
--! @date 2013-11-24
|
||||
--
|
||||
--! @addtogroup spawn_algorithms
|
||||
--! @{
|
||||
-- Contact sapier a t gmx net
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local DEEP_WATER_MIN_DEPTH = -20
|
||||
local DEEP_WATER_MAX_DEPTH = -50
|
||||
local DEEP_WATER_SPAWNER_SUFFIX = "_deep_water"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: mobf_spawner_deep_water_spawner_spawnfunc(spawning_data,pos,self)
|
||||
--
|
||||
--! @brief function to spawn a spawner entity
|
||||
--
|
||||
--! @param spawning_data spawning configuration
|
||||
--! @param pos position do spawn
|
||||
-------------------------------------------------------------------------------
|
||||
function mobf_spawner_deep_water_spawner_spawnfunc(spawning_data,pos,self)
|
||||
|
||||
mobf_assert_backtrace(type(spawning_data.minp) == "number")
|
||||
mobf_assert_backtrace(type(spawning_data.maxp) == "number")
|
||||
|
||||
local min_y = spawning_data.minp
|
||||
local max_y = spawning_data.maxp
|
||||
|
||||
dbg_mobf.spawning_lvl3("spawning data: " .. dump(spawning_data))
|
||||
|
||||
--check if we try to spawn in correct area
|
||||
if max_y < DEEP_WATER_MAX_DEPTH then
|
||||
dbg_mobf.spawning_lvl3("MOBF: deep water spawner --> to deep: " ..
|
||||
max_y .. " < " .. DEEP_WATER_MAX_DEPTH)
|
||||
return false
|
||||
end
|
||||
|
||||
if min_y > DEEP_WATER_MIN_DEPTH then
|
||||
dbg_mobf.spawning_lvl3("MOBF: deep water spawner --> to high: " ..
|
||||
max_y .. " < " .. DEEP_WATER_MIN_DEPTH)
|
||||
return false
|
||||
end
|
||||
|
||||
local waternodes = minetest.find_nodes_in_area({x=pos.x,y=min_y,z=pos.z},
|
||||
{x=pos.x,y=max_y,z=pos.z},
|
||||
{ "default:water_flowing",
|
||||
"default:water_source"} )
|
||||
--check for water
|
||||
if #waternodes == 0 then
|
||||
dbg_mobf.spawning_lvl3("MOBF: deep water spawner no water at position "
|
||||
.. printpos(pos) ..
|
||||
" " .. min_y .. "<->" .. max_y .. " found")
|
||||
return false
|
||||
end
|
||||
|
||||
pos = spawning.spawner_get_water_pos( pos,
|
||||
DEEP_WATER_MIN_DEPTH,
|
||||
DEEP_WATER_MIN_DEPTH,
|
||||
min_y,max_y)
|
||||
|
||||
if pos == nil then
|
||||
dbg_mobf.spawning_lvl3(
|
||||
"MOBF: deep water spawnerunable to find a suitable depth at position "
|
||||
.. printpos(pos))
|
||||
return false
|
||||
end
|
||||
|
||||
--only place a spawner if there's enough water around
|
||||
local found_nodes = minetest.find_nodes_in_area({x=pos.x-2,y=pos.y-2,z=pos.z-2},
|
||||
{x=pos.x+2,y=pos.y+2,z=pos.z+2},
|
||||
{ "default:water_flowing",
|
||||
"default:water_source"} )
|
||||
|
||||
--maximum number of water nodes is 64 if less than half is water don't spawn here
|
||||
if #found_nodes < 32 then
|
||||
dbg_mobf.spawning_lvl3("MOBF: deep water spawner " .. printpos(pos) ..
|
||||
" not enough water around: " .. #found_nodes)
|
||||
return false
|
||||
end
|
||||
|
||||
local spawner = spawning.spawn_and_check(
|
||||
spawning_data.name .. "_spawner" ..
|
||||
DEEP_WATER_SPAWNER_SUFFIX,
|
||||
pos,
|
||||
"deep_water")
|
||||
|
||||
if spawner == nil then
|
||||
return false
|
||||
else
|
||||
dbg_mobf.spawning_lvl3("MOBF: deep water spawner spawned at " ..
|
||||
printpos(pos))
|
||||
spawner.spawner_miny = min_y
|
||||
spawner.spawner_maxy = max_y
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: mobf_spawner_deep_water_spawnfunc(spawning_data,pos)
|
||||
--
|
||||
--! @brief function to spawn a mob entity
|
||||
--
|
||||
--! @param spawning_data spawning configuration
|
||||
--! @param pos position do spawn
|
||||
-------------------------------------------------------------------------------
|
||||
function mobf_spawner_deep_water_spawnfunc(spawning_data,pos)
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
|
||||
|
||||
--first find a new water pos
|
||||
pos = spawning.spawner_get_water_pos(pos,
|
||||
DEEP_WATER_MIN_DEPTH,
|
||||
DEEP_WATER_MAX_DEPTH,
|
||||
pos.y+DEEP_WATER_MAX_DEPTH,
|
||||
MIN(0,pos.y-DEEP_WATER_MAX_DEPTH))
|
||||
|
||||
if pos == nil then
|
||||
dbg_mobf.spawning_lvl2("MOBF: didn't find a pos in water")
|
||||
return false
|
||||
end
|
||||
|
||||
--only place a spawner if it's within water
|
||||
local found_nodes = minetest.find_nodes_in_area(
|
||||
{x=pos.x-2,y=pos.y-2,z=pos.z-2},
|
||||
{x=pos.x+2,y=pos.y+2,z=pos.z+2},
|
||||
{ "default:water_flowing","default:water_source"} )
|
||||
|
||||
--maximum number of water nodes is 64 if less than half is water don't spawn here
|
||||
if #found_nodes < 32 then
|
||||
dbg_mobf.spawning_lvl2("MOBF: spawner " .. printpos(pos) .. " not enough water around: " .. #found_nodes)
|
||||
return false
|
||||
end
|
||||
|
||||
--check if there is a mob right there
|
||||
if spawning.position_in_use(pos,spawning_data) then
|
||||
dbg_mobf.spawning_lvl2("MOBF: spawner " .. printpos(pos) .. " is in use")
|
||||
return false
|
||||
end
|
||||
|
||||
--check popualation density limit
|
||||
if spawning.population_density_limit(pos,spawning_data) then
|
||||
dbg_mobf.spawning_lvl2("MOBF: spawner " .. printpos(pos) .. " to many mobs around")
|
||||
return false
|
||||
end
|
||||
|
||||
local pos_above = { x=pos.x,y=pos.y+1,z=pos.z }
|
||||
|
||||
local spawner = spawning.spawn_and_check(spawning_data.name,pos_above,"deep_water")
|
||||
|
||||
if spawner == nil then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: mobf_spawn_initialize_deep_water_abm(spawning_data)
|
||||
--
|
||||
--! @brief find a place in water to spawn mob
|
||||
--
|
||||
--! @param spawning_data spawning configuration
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function mobf_spawn_initialize_deep_water_abm(spawning_data)
|
||||
|
||||
minetest.log(LOGLEVEL_INFO,
|
||||
"MOBF: \tregistering deep water spawn abm callback for mob "..
|
||||
spawning_data.name)
|
||||
|
||||
local media = nil
|
||||
|
||||
if environment ~= nil and
|
||||
environment.media ~= nil then
|
||||
media = environment.media
|
||||
end
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = { "default:water_source" },
|
||||
neighbors = media,
|
||||
interval = 60,
|
||||
chance = math.floor(1/spawning_data.rate),
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local starttime = mobf_get_time_ms()
|
||||
local pos_above = {
|
||||
x = pos.x,
|
||||
y = pos.y + 1,
|
||||
z = pos.z
|
||||
}
|
||||
|
||||
--never try to spawn an mob at pos (0,0,0) it's initial entity spawnpos and
|
||||
--used to find bugs in initial spawnpoint setting code
|
||||
if mobf_pos_is_zero(pos) then
|
||||
mobf_warn_long_fct(starttime,"mobf_spawn_deep_water")
|
||||
return
|
||||
end
|
||||
|
||||
--check if pos is ok
|
||||
if not environment.evaluate_state(
|
||||
spawning.pos_quality(spawning_data,pos_above),
|
||||
LT_SAFE_POS) then
|
||||
mobf_warn_long_fct(starttime,"mobf_spawn_deep_water")
|
||||
return
|
||||
end
|
||||
|
||||
--check population density
|
||||
if mobf_mob_around(spawning_data.name,
|
||||
spawning_data.name_secondary,
|
||||
pos_above,spawning_data.density,true) > 0 then
|
||||
mobf_warn_long_fct(starttime,"mobf_spawn_deep_water")
|
||||
return
|
||||
end
|
||||
|
||||
mobf_spawner_deep_water_spawnfunc(spawning_data,pos)
|
||||
mobf_warn_long_fct(starttime,"mobf_spawn_deep_water")
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: mobf_spawn_initialize_deep_water_mapgen(spawning_data)
|
||||
--
|
||||
--! @brief find a place in deep water
|
||||
--
|
||||
--! @param spawning_data spawning configuration
|
||||
-------------------------------------------------------------------------------
|
||||
function mobf_spawn_initialize_deep_water_mapgen(spawning_data)
|
||||
minetest.log(LOGLEVEL_INFO,
|
||||
"MOBF:\tregistering in deep water mapgen spawn mapgen callback for mob "..
|
||||
spawning_data.name)
|
||||
|
||||
--disable spawner entity y position check
|
||||
spawning_data.relaxed_y_check = true
|
||||
|
||||
spawning.register_spawner_entity(spawning_data,
|
||||
mobf_spawner_deep_water_spawnfunc,
|
||||
nil, --TODO
|
||||
DEEP_WATER_SPAWNER_SUFFIX)
|
||||
|
||||
if minetest.world_setting_get("mobf_delayed_spawning") then
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
local job = {
|
||||
callback = spawning.divide_mapgen_entity_jobfunc,
|
||||
data = {
|
||||
minp = minp,
|
||||
maxp = maxp,
|
||||
spawning_data = spawning_data,
|
||||
spawnfunc = mobf_spawner_deep_water_spawner_spawnfunc,
|
||||
maxtries = 15,
|
||||
func = spawning.divide_mapgen_entity_jobfunc,
|
||||
}
|
||||
}
|
||||
mobf_job_queue.add_job(job)
|
||||
end)
|
||||
else
|
||||
--add mob spawner on map generation
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
local starttime = mobf_get_time_ms()
|
||||
spawning.divide_mapgen_entity(minp,maxp,
|
||||
spawning_data,
|
||||
mobf_spawner_deep_water_spawner_spawnfunc,
|
||||
15)
|
||||
mobf_warn_long_fct(starttime,"on_mapgen " .. spawning_data.name,"mapgen")
|
||||
end) --register mapgen
|
||||
end
|
||||
end --end spawn algo
|
||||
--!@}
|
||||
|
||||
spawning.register_spawn_algorithm("deep_water", mobf_spawn_deep_water)
|
||||
spawning.register_spawn_algorithm("deep_water_spawner",
|
||||
mobf_spawn_initialize_deep_water_mapgen,
|
||||
spawning.register_cleanup_spawner)
|
@ -19,89 +19,6 @@
|
||||
local SHALLOW_WATER_MAX_DEPTH = -10
|
||||
local SHALLOW_WATER_SPAWNER_SUFFIX = "_shallow_water"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: mobf_spawner_get_water_pos(pos,max_depth,min_y,max_y)
|
||||
--
|
||||
--! @brief find a position at x/z within some y limitations
|
||||
--
|
||||
--! @param pos position do spawn
|
||||
--! @param max_depth may depth to spawn
|
||||
--! @param min_y minimum y value of generated chunk
|
||||
--! @param max_y maximum y value of generated chunk
|
||||
-------------------------------------------------------------------------------
|
||||
function mobf_spawner_get_water_pos(pos,max_depth,min_y,max_y)
|
||||
--get information about current position
|
||||
local upper_pos = {x=pos.x,y=max_y,z=pos.z}
|
||||
|
||||
if max_depth == nil then
|
||||
max_depth = SHALLOW_WATER_MAX_DEPTH
|
||||
end
|
||||
|
||||
--TODO add min depth
|
||||
|
||||
local ground_distance = mobf_ground_distance(upper_pos,
|
||||
{ "default:water_flowing",
|
||||
"default:water_source",
|
||||
"air" },max_y - min_y)
|
||||
local ground_level = max_y - ground_distance +1
|
||||
|
||||
local ground_pos = {x=pos.x,y=ground_level,z=pos.z }
|
||||
local water_depth = mobf_air_distance(ground_pos)
|
||||
|
||||
local surfacenode = minetest.get_node(ground_pos)
|
||||
|
||||
if surfacenode == nil then
|
||||
dbg_mobf.spawning_lvl3("MOBF: invalid ground node")
|
||||
return nil
|
||||
end
|
||||
|
||||
if surfacenode.name ~= "default:water_flowing" and
|
||||
surfacenode.name ~= "default:water_source" then
|
||||
--mobf_print("MOBF: WD:" .. water_depth .. " GD: " .. ground_distance)
|
||||
--mobf_print("MOBF: MAXD:" .. max_depth .. " " .. min_y .. "<->" .. max_y)
|
||||
dbg_mobf.spawning_lvl3("MOBF: " .. surfacenode.name .. " isn't open water: " .. printpos(ground_pos))
|
||||
--if ground_pos.y > 0 then
|
||||
-- for i=min_y,max_y,1 do
|
||||
-- local node = minetest.get_node({x=pos.x,y=i,z=pos.z})
|
||||
-- print("i=" .. i .. " : " .. node.name)
|
||||
-- end
|
||||
--end
|
||||
return nil
|
||||
end
|
||||
|
||||
if water_depth <= 0 then
|
||||
dbg_mobf.spawning_lvl3("MOBF: water not found! GP: " .. ground_level .. " WD: " .. water_depth)
|
||||
--TODO spawn in caves?
|
||||
return nil
|
||||
end
|
||||
|
||||
local water_surface_pos = {x=pos.x,y=ground_level + water_depth,z=pos.z}
|
||||
|
||||
--dbg_mobf.spawning_lvl2
|
||||
dbg_mobf.spawning_lvl3("MOBF: mobf_spawner_get_water_pos GL: " ..
|
||||
ground_level ..
|
||||
" WDPT: " .. water_depth ..
|
||||
" WSP: " .. printpos(water_surface_pos))
|
||||
if MAX(ground_level,max_depth) > water_surface_pos.y then
|
||||
mobf_print("MOBF: WD:" .. water_depth .. " GD: " .. ground_distance)
|
||||
mobf_print("MOBF: MAXD:" .. max_depth .. " " .. min_y .. "<->" .. max_y)
|
||||
mobf_print("MOBF: mobf_spawner_get_water_pos GL: " ..
|
||||
ground_level ..
|
||||
" WDPT: " .. water_depth ..
|
||||
" WSP: " .. printpos(water_surface_pos))
|
||||
mobf_assert_backtrace(MAX(ground_level,max_depth) < water_surface_pos.y)
|
||||
return nil
|
||||
end
|
||||
--
|
||||
pos.y = math.floor(
|
||||
math.random(
|
||||
MAX(ground_level,max_depth),
|
||||
water_surface_pos.y
|
||||
)
|
||||
+ 0.5)
|
||||
return pos
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: mobf_spawner_in_shallow_water_spawner_spawnfunc(spawning_data,pos,self)
|
||||
--
|
||||
@ -136,7 +53,7 @@ function mobf_spawner_in_shallow_water_spawner_spawnfunc(spawning_data,pos,self)
|
||||
return false
|
||||
end
|
||||
|
||||
pos = mobf_spawner_get_water_pos(pos,SHALLOW_WATER_MAX_DEPTH,min_y,max_y)
|
||||
pos = spawning.spawner_get_water_pos(pos,0,SHALLOW_WATER_MAX_DEPTH,min_y,max_y)
|
||||
|
||||
if pos == nil then
|
||||
dbg_mobf.spawning_lvl3("MOBF: unable to find a suitable depth at position " .. printpos(pos))
|
||||
@ -183,7 +100,8 @@ function mobf_spawner_in_shallow_water_spawnfunc(spawning_data,pos)
|
||||
|
||||
|
||||
--first find a new water pos
|
||||
pos = mobf_spawner_get_water_pos(pos,
|
||||
pos = spawning.spawner_get_water_pos(pos,
|
||||
0,
|
||||
SHALLOW_WATER_MAX_DEPTH,
|
||||
pos.y+SHALLOW_WATER_MAX_DEPTH,
|
||||
MIN(0,pos.y-SHALLOW_WATER_MAX_DEPTH))
|
||||
|
@ -616,11 +616,11 @@ function spawning.divide_mapgen(minp,maxp,spawning_data,spawnfunc,surfacefunc,ma
|
||||
if not continue and
|
||||
spawning_data.height ~= nil and
|
||||
mobf_air_above(pos,spawning_data.height) ~= true then
|
||||
mobf_print("MOBF: not enough room to spawn: " .. spawning_data.height)
|
||||
dbg_mobf.spawning_lvl3("MOBF: not enough room to spawn: " .. spawning_data.height)
|
||||
local mypos = pos
|
||||
for i=1,spawning_data.height,1 do
|
||||
local nodeatpos = minetest.get_node(mypos)
|
||||
mobf_print("\t" .. printpos(mypos) .. ": " .. nodeatpos.name)
|
||||
dbg_mobf.spawning_lvl3("\t" .. printpos(mypos) .. ": " .. nodeatpos.name)
|
||||
mypos.y = mypos.y +1
|
||||
end
|
||||
continue = true
|
||||
@ -1214,6 +1214,92 @@ function spawning.population_density_limit(pos,spawndata)
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- name: spawner_get_water_pos(pos,max_depth,min_y,max_y)
|
||||
--
|
||||
--! @brief find a position at x/z within some y limitations
|
||||
--
|
||||
--! @param pos position do spawn
|
||||
--! @param min_depth min-y depth to spawn
|
||||
--! @param max_depth max-y depth to spawn
|
||||
--! @param min_y minimum y value of generated chunk
|
||||
--! @param max_y maximum y value of generated chunk
|
||||
-------------------------------------------------------------------------------
|
||||
function spawning.spawner_get_water_pos(pos,min_depth,max_depth,min_y,max_y)
|
||||
--get information about current position
|
||||
local upper_pos = {x=pos.x,y=max_y,z=pos.z}
|
||||
|
||||
mobf_assert_backtrace(type(min_depth) == "number")
|
||||
mobf_assert_backtrace(type(max_depth) == "number")
|
||||
|
||||
local ground_distance = mobf_ground_distance(upper_pos,
|
||||
{ "default:water_flowing",
|
||||
"default:water_source",
|
||||
"air" },max_y - min_y)
|
||||
local ground_level = max_y - ground_distance +1
|
||||
|
||||
local ground_pos = {x=pos.x,y=ground_level,z=pos.z }
|
||||
local water_depth = mobf_air_distance(ground_pos)
|
||||
|
||||
local surfacenode = minetest.get_node(ground_pos)
|
||||
|
||||
if surfacenode == nil then
|
||||
dbg_mobf.spawning_lvl3("MOBF: invalid ground node")
|
||||
return nil
|
||||
end
|
||||
|
||||
if surfacenode.name ~= "default:water_flowing" and
|
||||
surfacenode.name ~= "default:water_source" then
|
||||
--mobf_print("MOBF: WD:" .. water_depth .. " GD: " .. ground_distance)
|
||||
--mobf_print("MOBF: MAXD:" .. max_depth .. " " .. min_y .. "<->" .. max_y)
|
||||
dbg_mobf.spawning_lvl3("MOBF: " .. surfacenode.name .. " isn't open water: " .. printpos(ground_pos))
|
||||
--if ground_pos.y > 0 then
|
||||
-- for i=min_y,max_y,1 do
|
||||
-- local node = minetest.get_node({x=pos.x,y=i,z=pos.z})
|
||||
-- print("i=" .. i .. " : " .. node.name)
|
||||
-- end
|
||||
--end
|
||||
return nil
|
||||
end
|
||||
|
||||
if water_depth <= 0 then
|
||||
dbg_mobf.spawning_lvl3("MOBF: water not found! GP: " .. ground_level .. " WD: " .. water_depth)
|
||||
--TODO spawn in caves?
|
||||
return nil
|
||||
end
|
||||
|
||||
local water_surface_pos = {x=pos.x,y=ground_level + water_depth,z=pos.z}
|
||||
|
||||
--dbg_mobf.spawning_lvl2
|
||||
dbg_mobf.spawning_lvl3("MOBF: mobf_spawner_get_water_pos GL: " ..
|
||||
ground_level ..
|
||||
" WDPT: " .. water_depth ..
|
||||
" WSP: " .. printpos(water_surface_pos))
|
||||
if MAX(ground_level,max_depth) > water_surface_pos.y then
|
||||
mobf_print("MOBF: WD:" .. water_depth .. " GD: " .. ground_distance)
|
||||
mobf_print("MOBF: MAXD:" .. max_depth .. " " .. min_y .. "<->" .. max_y)
|
||||
mobf_print("MOBF: mobf_spawner_get_water_pos GL: " ..
|
||||
ground_level ..
|
||||
" WDPT: " .. water_depth ..
|
||||
" WSP: " .. printpos(water_surface_pos))
|
||||
mobf_assert_backtrace(MAX(ground_level,max_depth) < water_surface_pos.y)
|
||||
return nil
|
||||
end
|
||||
|
||||
--check if there is any chance to find a suitable pos
|
||||
if MAX(ground_level,max_depth) >= MIN(water_surface_pos.y,min_depth) then
|
||||
return nil
|
||||
end
|
||||
|
||||
pos.y = math.floor(
|
||||
math.random(
|
||||
MAX(ground_level,max_depth),
|
||||
MIN(water_surface_pos.y,min_depth)
|
||||
)
|
||||
+ 0.5)
|
||||
return pos
|
||||
end
|
||||
|
||||
--include spawn algorithms
|
||||
dofile (mobf_modpath .. "/spawn_algorithms/at_night.lua")
|
||||
dofile (mobf_modpath .. "/spawn_algorithms/forrest.lua")
|
||||
@ -1224,3 +1310,4 @@ dofile (mobf_modpath .. "/spawn_algorithms/big_willow.lua")
|
||||
dofile (mobf_modpath .. "/spawn_algorithms/in_air1.lua")
|
||||
dofile (mobf_modpath .. "/spawn_algorithms/none.lua")
|
||||
dofile (mobf_modpath .. "/spawn_algorithms/deep_large_caves.lua")
|
||||
dofile (mobf_modpath .. "/spawn_algorithms/deep_water.lua")
|
Loading…
x
Reference in New Issue
Block a user