mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-10 18:21:05 +01:00
Fix volume used for room check during spawn, make mcl_mobs.spawn check for room before adding entity, change iron golems and mob spawners to use mcl_mobs.spawn
This commit is contained in:
parent
8ef08128b1
commit
6c50e0a82b
4 changed files with 66 additions and 47 deletions
|
@ -48,6 +48,18 @@ function table.pairs_by_keys(t, f)
|
||||||
return iter
|
return iter
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function table.pull_random_items(table)
|
||||||
|
local count = #table
|
||||||
|
return function()
|
||||||
|
local idx = math.random(count)
|
||||||
|
local res = table[idx]
|
||||||
|
table[idx] = table[count]
|
||||||
|
table[count] = nil
|
||||||
|
count = count - 1
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default", false)
|
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default", false)
|
||||||
local LOG_MODULE = "[MCL2]"
|
local LOG_MODULE = "[MCL2]"
|
||||||
function mcl_util.mcl_log(message, module, bypass_default_logger)
|
function mcl_util.mcl_log(message, module, bypass_default_logger)
|
||||||
|
|
|
@ -530,7 +530,7 @@ local function get_water_spawn(p)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function has_room(self,pos)
|
local function has_room(self, pos)
|
||||||
local cb = self.spawnbox or self.collisionbox
|
local cb = self.spawnbox or self.collisionbox
|
||||||
local nodes = {}
|
local nodes = {}
|
||||||
if self.fly_in then
|
if self.fly_in then
|
||||||
|
@ -543,16 +543,16 @@ local function has_room(self,pos)
|
||||||
end
|
end
|
||||||
table.insert(nodes,"air")
|
table.insert(nodes,"air")
|
||||||
|
|
||||||
local p1 = vector.offset(pos,cb[1],cb[2] + 1,cb[3])
|
-- Calculate area to check for room
|
||||||
p1.x = math.floor(p1.x)
|
|
||||||
p1.y = math.floor(p1.y)
|
|
||||||
p1.z = math.floor(p1.z)
|
|
||||||
|
|
||||||
local cb_height = cb[5] - cb[2]
|
local cb_height = cb[5] - cb[2]
|
||||||
local p2 = vector.offset(p1,cb[4] - cb[1], cb_height, cb[6] - cb[3])
|
local p1 = vector.new(
|
||||||
p2.x = math.ceil(p2.x) - 1
|
math.round(pos.x + cb[1]),
|
||||||
p2.y = math.ceil(p2.y) - 1
|
pos.y,
|
||||||
p2.z = math.ceil(p2.z) - 1
|
math.round(pos.z + cb[3]))
|
||||||
|
local p2 = vector.new(
|
||||||
|
math.round(pos.x + cb[4]),
|
||||||
|
math.ceil(p1.y + cb_height) - 1,
|
||||||
|
math.round(pos.z + cb[6]))
|
||||||
|
|
||||||
-- Check if the entire spawn volume is free
|
-- Check if the entire spawn volume is free
|
||||||
local dx = p2.x - p1.x + 1
|
local dx = p2.x - p1.x + 1
|
||||||
|
@ -560,7 +560,23 @@ local function has_room(self,pos)
|
||||||
local dz = p2.z - p1.z + 1
|
local dz = p2.z - p1.z + 1
|
||||||
local found_nodes = minetest.find_nodes_in_area(p1,p2,nodes) or 0
|
local found_nodes = minetest.find_nodes_in_area(p1,p2,nodes) or 0
|
||||||
local n = #found_nodes
|
local n = #found_nodes
|
||||||
if n == ( dx * dy * dz ) then return true end
|
--[[
|
||||||
|
minetest.log(dump({
|
||||||
|
cb = cb,
|
||||||
|
pos = pos,
|
||||||
|
n = n,
|
||||||
|
dx = dx,
|
||||||
|
dy = dy,
|
||||||
|
dz = dz,
|
||||||
|
p1 = p1,
|
||||||
|
p2 = p2,
|
||||||
|
found_nodes = found_nodes,
|
||||||
|
nodes = nodes,
|
||||||
|
}))
|
||||||
|
]]
|
||||||
|
if n == ( dx * dy * dz ) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
-- If we don't have an implementation of get_node_boxes, we can't check for sub-node space
|
-- If we don't have an implementation of get_node_boxes, we can't check for sub-node space
|
||||||
if not minetest.get_node_boxes then return false end
|
if not minetest.get_node_boxes then return false end
|
||||||
|
@ -699,10 +715,10 @@ function mcl_mobs.spawn(pos,id)
|
||||||
if not pos or not id then return false end
|
if not pos or not id then return false end
|
||||||
local def = minetest.registered_entities[id] or minetest.registered_entities["mobs_mc:"..id] or minetest.registered_entities["extra_mobs:"..id]
|
local def = minetest.registered_entities[id] or minetest.registered_entities["mobs_mc:"..id] or minetest.registered_entities["extra_mobs:"..id]
|
||||||
if not def or not def.is_mob or (def.can_spawn and not def.can_spawn(pos)) then return false end
|
if not def or not def.is_mob or (def.can_spawn and not def.can_spawn(pos)) then return false end
|
||||||
|
if not has_room(def, pos) then return false end
|
||||||
return minetest.add_entity(pos, def.name)
|
return minetest.add_entity(pos, def.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function spawn_group(p,mob,spawn_on,amount_to_spawn)
|
local function spawn_group(p,mob,spawn_on,amount_to_spawn)
|
||||||
local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on)
|
local nn= minetest.find_nodes_in_area_under_air(vector.offset(p,-5,-3,-5),vector.offset(p,5,3,5),spawn_on)
|
||||||
local o
|
local o
|
||||||
|
|
|
@ -1049,14 +1049,18 @@ local function has_summon_participants(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function summon_golem(self)
|
local function summon_golem(self)
|
||||||
vector.offset(self.object:get_pos(),-10,-10,-10)
|
local pos = self.object:get_pos()
|
||||||
local nn = minetest.find_nodes_in_area_under_air(vector.offset(self.object:get_pos(),-10,-10,-10),vector.offset(self.object:get_pos(),10,10,10),{"group:solid","group:water"})
|
local p1 = vector.offset(pos, -10, -10, -10)
|
||||||
table.shuffle(nn)
|
local p2 = vector.offset(pos, 10, 10, 10)
|
||||||
for _,n in pairs(nn) do
|
local nn = minetest.find_nodes_in_area_under_air(p1, p2,{"group:solid","group:water"})
|
||||||
local up = minetest.find_nodes_in_area(vector.offset(n,0,1,0),vector.offset(n,0,3,0),{"air"})
|
for n in table.pull_random_items(nn) do
|
||||||
if up and #up >= 3 then
|
n.y = n.y + 1
|
||||||
|
minetest.log("trying to summon golem at "..vector.to_string(n))
|
||||||
|
|
||||||
|
local summon = mcl_mobs.spawn(n, "mobs_mc:iron_golem")
|
||||||
|
if summon then
|
||||||
minetest.sound_play("mcl_portals_open_end_portal", {pos=n, gain=0.5, max_hear_distance = 16}, true)
|
minetest.sound_play("mcl_portals_open_end_portal", {pos=n, gain=0.5, max_hear_distance = 16}, true)
|
||||||
return minetest.add_entity(vector.offset(n,0,1,0),"mobs_mc:iron_golem")
|
return summon
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -147,20 +147,14 @@ local function spawn_mobs(pos, elapsed)
|
||||||
-- get meta
|
-- get meta
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
|
|
||||||
-- get settings
|
|
||||||
local mob = meta:get_string("Mob")
|
|
||||||
local mlig = meta:get_int("MinLight")
|
|
||||||
local xlig = meta:get_int("MaxLight")
|
|
||||||
local num = meta:get_int("MaxMobsInArea")
|
|
||||||
local pla = meta:get_int("PlayerDistance")
|
|
||||||
local yof = meta:get_int("YOffset")
|
|
||||||
|
|
||||||
-- if amount is 0 then do nothing
|
-- if amount is 0 then do nothing
|
||||||
|
local num = meta:get_int("MaxMobsInArea")
|
||||||
if num == 0 then
|
if num == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- are we spawning a registered mob?
|
-- are we spawning a registered mob?
|
||||||
|
local mob = meta:get_string("Mob")
|
||||||
if not mcl_mobs.spawning_mobs[mob] then
|
if not mcl_mobs.spawning_mobs[mob] then
|
||||||
minetest.log("error", "[mcl_mobspawners] Mob Spawner: Mob doesn't exist: "..mob)
|
minetest.log("error", "[mcl_mobspawners] Mob Spawner: Mob doesn't exist: "..mob)
|
||||||
return
|
return
|
||||||
|
@ -174,17 +168,14 @@ local function spawn_mobs(pos, elapsed)
|
||||||
local timer = minetest.get_node_timer(pos)
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
|
||||||
-- spawn mob if player detected and in range
|
-- spawn mob if player detected and in range
|
||||||
|
local pla = meta:get_int("PlayerDistance")
|
||||||
if pla > 0 then
|
if pla > 0 then
|
||||||
|
|
||||||
local in_range = 0
|
local in_range = 0
|
||||||
local objs = minetest.get_objects_inside_radius(pos, pla)
|
local objs = minetest.get_objects_inside_radius(pos, pla)
|
||||||
|
|
||||||
for _,oir in pairs(objs) do
|
for _,oir in pairs(objs) do
|
||||||
|
|
||||||
if oir:is_player() then
|
if oir:is_player() then
|
||||||
|
|
||||||
in_range = 1
|
in_range = 1
|
||||||
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -213,7 +204,6 @@ local function spawn_mobs(pos, elapsed)
|
||||||
|
|
||||||
-- count mob objects of same type in area
|
-- count mob objects of same type in area
|
||||||
for k, obj in ipairs(objs) do
|
for k, obj in ipairs(objs) do
|
||||||
|
|
||||||
ent = obj:get_luaentity()
|
ent = obj:get_luaentity()
|
||||||
|
|
||||||
if ent and ent.name and ent.name == mob then
|
if ent and ent.name and ent.name == mob then
|
||||||
|
@ -228,31 +218,28 @@ local function spawn_mobs(pos, elapsed)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- find air blocks within 8×3×8 nodes of spawner
|
-- find air blocks within 8×3×8 nodes of spawner
|
||||||
|
local yof = meta:get_int("YOffset")
|
||||||
local air = minetest.find_nodes_in_area(
|
local air = minetest.find_nodes_in_area(
|
||||||
{x = pos.x - 4, y = pos.y - 1 + yof, z = pos.z - 4},
|
{x = pos.x - 4, y = pos.y - 1 + yof, z = pos.z - 4},
|
||||||
{x = pos.x + 4, y = pos.y + 1 + yof, z = pos.z + 4},
|
{x = pos.x + 4, y = pos.y + 1 + yof, z = pos.z + 4},
|
||||||
{"air"})
|
{"air"})
|
||||||
|
|
||||||
-- spawn up to 4 mobs in random air blocks
|
-- spawn mobs in random air blocks. Default max of 4
|
||||||
if air then
|
if air then
|
||||||
local max = 4
|
local num_to_spawn = spawn_count_overrides[mob] or 4
|
||||||
if spawn_count_overrides[mob] then
|
local mlig = meta:get_int("MinLight")
|
||||||
max = spawn_count_overrides[mob]
|
local xlig = meta:get_int("MaxLight")
|
||||||
end
|
|
||||||
for a=1, max do
|
|
||||||
if #air <= 0 then
|
|
||||||
-- We're out of space! Stop spawning
|
|
||||||
break
|
|
||||||
end
|
|
||||||
local air_index = math.random(#air)
|
|
||||||
local pos2 = air[air_index]
|
|
||||||
local lig = minetest.get_node_light(pos2) or 0
|
|
||||||
|
|
||||||
pos2.y = pos2.y + 0.5
|
for pos2 = table.pull_random_items(air) do
|
||||||
|
local pos2 = air[air_index]
|
||||||
|
|
||||||
-- only if light levels are within range
|
-- only if light levels are within range
|
||||||
|
local lig = minetest.get_node_light(pos2) or 0
|
||||||
if lig >= mlig and lig <= xlig then
|
if lig >= mlig and lig <= xlig then
|
||||||
minetest.add_entity(pos2, mob)
|
if mcl_mobs.spawn(pos2, mob) then
|
||||||
|
num_to_spawn = num_to_spawn - 1
|
||||||
|
if num_to_spawn == 0 then break end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
table.remove(air, air_index)
|
table.remove(air, air_index)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue