Fix indents in mcl_explosions
parent
679e2b1b70
commit
026d406d4b
|
@ -1,19 +1,13 @@
|
|||
--[[ .__ .__
|
||||
____ ___ _________ | | ____ _____|__| ____ ____ ______
|
||||
_/ __ \\ \/ /\____ \| | / _ \/ ___/ |/ _ \ / \ / ___/
|
||||
\ ___/ > < | |_> > |_( <_> )___ \| ( <_> ) | \\___ \
|
||||
\___ >__/\_ \| __/|____/\____/____ >__|\____/|___| /____ >
|
||||
\/ \/|__| \/ \/ \/
|
||||
--[[
|
||||
Explosion API mod for Minetest (adapted to MineClone 2)
|
||||
|
||||
Explosion API mod for Minetest (adapted to MineClone 2)
|
||||
This mod is based on the Minetest explosion API mod, but has been changed
|
||||
to have the same explosion mechanics as Minecraft and work with MineClone.
|
||||
The computation-intensive parts of the mod has been optimized to allow for
|
||||
larger explosions and faster world updating.
|
||||
|
||||
This mod is based on the Minetest explosion API mod, but has been changed
|
||||
to have the same explosion mechanics as Minecraft and work with MineClone.
|
||||
The computation-intensive parts of the mod has been optimized to allow for
|
||||
larger explosions and faster world updating.
|
||||
|
||||
This mod was created by Elias Astrom <ryvnf@riseup.net> and is released
|
||||
under the LGPLv2.1 license.
|
||||
This mod was created by Elias Astrom <ryvnf@riseup.net> and is released
|
||||
under the LGPLv2.1 license.
|
||||
--]]
|
||||
|
||||
|
||||
|
@ -36,348 +30,348 @@ local STEP_LENGTH = 0.3
|
|||
local N_EXPOSURE_RAYS = 16
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
-- Store blast resistance values by content ids to improve performance.
|
||||
for name, def in pairs(minetest.registered_nodes) do
|
||||
node_blastres[minetest.get_content_id(name)] = def._mcl_blast_resistance or 0
|
||||
node_on_blast[minetest.get_content_id(name)] = def.on_blast
|
||||
node_walkable[minetest.get_content_id(name)] = def.walkable
|
||||
end
|
||||
-- Store blast resistance values by content ids to improve performance.
|
||||
for name, def in pairs(minetest.registered_nodes) do
|
||||
node_blastres[minetest.get_content_id(name)] = def._mcl_blast_resistance or 0
|
||||
node_on_blast[minetest.get_content_id(name)] = def.on_blast
|
||||
node_walkable[minetest.get_content_id(name)] = def.walkable
|
||||
end
|
||||
end)
|
||||
|
||||
-- Compute the rays which make up a sphere with radius. Returns a list of rays
|
||||
-- which can be used to trace explosions. This function is not efficient
|
||||
-- Compute the rays which make up a sphere with radius. Returns a list of rays
|
||||
-- which can be used to trace explosions. This function is not efficient
|
||||
-- (especially for larger radiuses), so the generated rays for various radiuses
|
||||
-- should be cached and reused.
|
||||
--
|
||||
-- Should be possible to improve by using a midpoint circle algorithm multiple
|
||||
-- times to create the sphere, currently uses more of a brute-force approach.
|
||||
local function compute_sphere_rays(radius)
|
||||
local rays = {}
|
||||
local sphere = {}
|
||||
local rays = {}
|
||||
local sphere = {}
|
||||
|
||||
for i=1, 2 do
|
||||
for y = -radius, radius do
|
||||
for z = -radius, radius do
|
||||
for x = -radius, 0, 1 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
local pos = { x = x, y = y, z = z }
|
||||
sphere[minetest.hash_node_position(pos)] = pos
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1, 2 do
|
||||
for y = -radius, radius do
|
||||
for z = -radius, radius do
|
||||
for x = -radius, 0, 1 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
local pos = { x = x, y = y, z = z }
|
||||
sphere[minetest.hash_node_position(pos)] = pos
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,2 do
|
||||
for x = -radius, radius do
|
||||
for z = -radius, radius do
|
||||
for y = -radius, 0, 1 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
local pos = { x = x, y = y, z = z }
|
||||
sphere[minetest.hash_node_position(pos)] = pos
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1,2 do
|
||||
for x = -radius, radius do
|
||||
for z = -radius, radius do
|
||||
for y = -radius, 0, 1 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
local pos = { x = x, y = y, z = z }
|
||||
sphere[minetest.hash_node_position(pos)] = pos
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,2 do
|
||||
for x = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
for z = -radius, 0, 1 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
local pos = { x = x, y = y, z = z }
|
||||
sphere[minetest.hash_node_position(pos)] = pos
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1,2 do
|
||||
for x = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
for z = -radius, 0, 1 do
|
||||
local d = x * x + y * y + z * z
|
||||
if d <= radius * radius then
|
||||
local pos = { x = x, y = y, z = z }
|
||||
sphere[minetest.hash_node_position(pos)] = pos
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, pos in pairs(sphere) do
|
||||
rays[#rays + 1] = vector.normalize(pos)
|
||||
end
|
||||
for _, pos in pairs(sphere) do
|
||||
rays[#rays + 1] = vector.normalize(pos)
|
||||
end
|
||||
|
||||
return rays
|
||||
return rays
|
||||
end
|
||||
|
||||
-- Add particles from explosion
|
||||
--
|
||||
-- Parameters:
|
||||
-- pos - The position of the explosion
|
||||
-- radius - The radius of the explosion
|
||||
-- pos - The position of the explosion
|
||||
-- radius - The radius of the explosion
|
||||
local function add_particles(pos, radius)
|
||||
minetest.add_particlespawner({
|
||||
amount = 64,
|
||||
time = 0.125,
|
||||
minpos = pos,
|
||||
maxpos = pos,
|
||||
minvel = {x = -radius, y = -radius, z = -radius},
|
||||
maxvel = {x = radius, y = radius, z = radius},
|
||||
minacc = vector.new(),
|
||||
maxacc = vector.new(),
|
||||
minexptime = 0.5,
|
||||
maxexptime = 1.0,
|
||||
minsize = radius * 0.5,
|
||||
maxsize = radius * 1.0,
|
||||
texture = "tnt_smoke.png",
|
||||
})
|
||||
minetest.add_particlespawner({
|
||||
amount = 64,
|
||||
time = 0.125,
|
||||
minpos = pos,
|
||||
maxpos = pos,
|
||||
minvel = {x = -radius, y = -radius, z = -radius},
|
||||
maxvel = {x = radius, y = radius, z = radius},
|
||||
minacc = vector.new(),
|
||||
maxacc = vector.new(),
|
||||
minexptime = 0.5,
|
||||
maxexptime = 1.0,
|
||||
minsize = radius * 0.5,
|
||||
maxsize = radius * 1.0,
|
||||
texture = "tnt_smoke.png",
|
||||
})
|
||||
end
|
||||
|
||||
-- Get position from hash. This should be identical to
|
||||
-- Get position from hash. This should be identical to
|
||||
-- 'minetest.get_position_from_hash' but is used in case the hashing function
|
||||
-- would change.
|
||||
local function get_position_from_hash(hash)
|
||||
local pos = {}
|
||||
pos.x = (hash % 65536) - 32768
|
||||
hash = math.floor(hash / 65536)
|
||||
pos.y = (hash % 65536) - 32768
|
||||
hash = math.floor(hash / 65536)
|
||||
pos.z = (hash % 65536) - 32768
|
||||
return pos
|
||||
local pos = {}
|
||||
pos.x = (hash % 65536) - 32768
|
||||
hash = math.floor(hash / 65536)
|
||||
pos.y = (hash % 65536) - 32768
|
||||
hash = math.floor(hash / 65536)
|
||||
pos.z = (hash % 65536) - 32768
|
||||
return pos
|
||||
end
|
||||
|
||||
-- Traces the rays of an explosion, and updates the environment.
|
||||
--
|
||||
-- Parameters:
|
||||
-- pos - Where the rays in the explosion should start from
|
||||
-- strength - The strength of each ray
|
||||
-- raydirs - The directions for each ray
|
||||
-- radius - The maximum distance each ray will go
|
||||
-- drop_chance - The chance that destroyed nodes will drop their items
|
||||
-- pos - Where the rays in the explosion should start from
|
||||
-- strength - The strength of each ray
|
||||
-- raydirs - The directions for each ray
|
||||
-- radius - The maximum distance each ray will go
|
||||
-- drop_chance - The chance that destroyed nodes will drop their items
|
||||
--
|
||||
-- Note that this function has been optimized, it contains code which has been
|
||||
-- inlined to avoid function calls and unnecessary table creation. This was
|
||||
-- inlined to avoid function calls and unnecessary table creation. This was
|
||||
-- measured to give a significant performance increase.
|
||||
local function trace_explode(pos, strength, raydirs, radius, drop_chance)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local vm = minetest.get_voxel_manip()
|
||||
|
||||
local emin, emax = vm:read_from_map(vector.subtract(pos, radius),
|
||||
vector.add(pos, radius))
|
||||
local emin_x = emin.x
|
||||
local emin_y = emin.y
|
||||
local emin_z = emin.z
|
||||
local emin, emax = vm:read_from_map(vector.subtract(pos, radius),
|
||||
vector.add(pos, radius))
|
||||
local emin_x = emin.x
|
||||
local emin_y = emin.y
|
||||
local emin_z = emin.z
|
||||
|
||||
local ystride = (emax.x - emin_x + 1)
|
||||
local zstride = ystride * (emax.y - emin_y + 1)
|
||||
local pos_x = pos.x
|
||||
local pos_y = pos.y
|
||||
local pos_z = pos.z
|
||||
local ystride = (emax.x - emin_x + 1)
|
||||
local zstride = ystride * (emax.y - emin_y + 1)
|
||||
local pos_x = pos.x
|
||||
local pos_y = pos.y
|
||||
local pos_z = pos.z
|
||||
|
||||
local area = VoxelArea:new {
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax
|
||||
}
|
||||
local data = vm:get_data()
|
||||
local destroy = {}
|
||||
local area = VoxelArea:new {
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax
|
||||
}
|
||||
local data = vm:get_data()
|
||||
local destroy = {}
|
||||
|
||||
-- Trace rays for environment destruction
|
||||
for i = 1, #raydirs do
|
||||
local rpos_x = pos.x
|
||||
local rpos_y = pos.y
|
||||
local rpos_z = pos.z
|
||||
local rdir_x = raydirs[i].x
|
||||
local rdir_y = raydirs[i].y
|
||||
local rdir_z = raydirs[i].z
|
||||
local rstr = (0.7 + math.random() * 0.6) * strength
|
||||
-- Trace rays for environment destruction
|
||||
for i = 1, #raydirs do
|
||||
local rpos_x = pos.x
|
||||
local rpos_y = pos.y
|
||||
local rpos_z = pos.z
|
||||
local rdir_x = raydirs[i].x
|
||||
local rdir_y = raydirs[i].y
|
||||
local rdir_z = raydirs[i].z
|
||||
local rstr = (0.7 + math.random() * 0.6) * strength
|
||||
|
||||
for r = 0, math.ceil(radius * (1.0 / STEP_LENGTH)) do
|
||||
local npos_x = math.floor(rpos_x + 0.5)
|
||||
local npos_y = math.floor(rpos_y + 0.5)
|
||||
local npos_z = math.floor(rpos_z + 0.5)
|
||||
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
|
||||
npos_x - emin_x + 1
|
||||
for r = 0, math.ceil(radius * (1.0 / STEP_LENGTH)) do
|
||||
local npos_x = math.floor(rpos_x + 0.5)
|
||||
local npos_y = math.floor(rpos_y + 0.5)
|
||||
local npos_z = math.floor(rpos_z + 0.5)
|
||||
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
|
||||
npos_x - emin_x + 1
|
||||
|
||||
local cid = data[idx]
|
||||
local br = node_blastres[cid]
|
||||
local hash = (npos_z + 32768) * 65536 * 65536 +
|
||||
(npos_y + 32768) * 65536 +
|
||||
npos_x + 32768
|
||||
local cid = data[idx]
|
||||
local br = node_blastres[cid]
|
||||
local hash = (npos_z + 32768) * 65536 * 65536 +
|
||||
(npos_y + 32768) * 65536 +
|
||||
npos_x + 32768
|
||||
|
||||
rpos_x = rpos_x + STEP_LENGTH * rdir_x
|
||||
rpos_y = rpos_y + STEP_LENGTH * rdir_y
|
||||
rpos_z = rpos_z + STEP_LENGTH * rdir_z
|
||||
rpos_x = rpos_x + STEP_LENGTH * rdir_x
|
||||
rpos_y = rpos_y + STEP_LENGTH * rdir_y
|
||||
rpos_z = rpos_z + STEP_LENGTH * rdir_z
|
||||
|
||||
rstr = rstr - 0.75 * STEP_LENGTH - (br + 0.3) * STEP_LENGTH
|
||||
rstr = rstr - 0.75 * STEP_LENGTH - (br + 0.3) * STEP_LENGTH
|
||||
|
||||
if rstr <= 0 then
|
||||
break
|
||||
end
|
||||
if rstr <= 0 then
|
||||
break
|
||||
end
|
||||
|
||||
if cid ~= minetest.CONTENT_AIR then
|
||||
destroy[hash] = idx
|
||||
end
|
||||
end
|
||||
end
|
||||
if cid ~= minetest.CONTENT_AIR then
|
||||
destroy[hash] = idx
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Entities in radius of explosion
|
||||
local punch_radius = 2 * strength
|
||||
local objs = minetest.get_objects_inside_radius(pos, punch_radius)
|
||||
-- Entities in radius of explosion
|
||||
local punch_radius = 2 * strength
|
||||
local objs = minetest.get_objects_inside_radius(pos, punch_radius)
|
||||
|
||||
-- Trace rays for entity damage
|
||||
for _, obj in pairs(objs) do
|
||||
local ent = obj:get_luaentity()
|
||||
-- Trace rays for entity damage
|
||||
for _, obj in pairs(objs) do
|
||||
local ent = obj:get_luaentity()
|
||||
|
||||
-- Ignore items to lower lag
|
||||
if obj:is_player() or (ent and ent.name ~= '__builtin.item') then
|
||||
local opos = obj:get_pos()
|
||||
local collisionbox = nil
|
||||
-- Ignore items to lower lag
|
||||
if obj:is_player() or (ent and ent.name ~= '__builtin.item') then
|
||||
local opos = obj:get_pos()
|
||||
local collisionbox = nil
|
||||
|
||||
if obj:is_player() then
|
||||
collisionbox = { -0.3, 0.0, -0.3, 0.3, 1.77, 0.3 }
|
||||
elseif ent.name then
|
||||
local def = minetest.registered_entities[ent.name]
|
||||
collisionbox = def.collisionbox
|
||||
end
|
||||
if obj:is_player() then
|
||||
collisionbox = { -0.3, 0.0, -0.3, 0.3, 1.77, 0.3 }
|
||||
elseif ent.name then
|
||||
local def = minetest.registered_entities[ent.name]
|
||||
collisionbox = def.collisionbox
|
||||
end
|
||||
|
||||
if collisionbox then
|
||||
-- Create rays from random points in the collision box
|
||||
local x1 = collisionbox[1] * 2
|
||||
local y1 = collisionbox[2] * 2
|
||||
local z1 = collisionbox[3] * 2
|
||||
local x2 = collisionbox[4] * 2
|
||||
local y2 = collisionbox[5] * 2
|
||||
local z2 = collisionbox[6] * 2
|
||||
local x_len = math.abs(x2 - x1)
|
||||
local y_len = math.abs(y2 - y1)
|
||||
local z_len = math.abs(z2 - z1)
|
||||
if collisionbox then
|
||||
-- Create rays from random points in the collision box
|
||||
local x1 = collisionbox[1] * 2
|
||||
local y1 = collisionbox[2] * 2
|
||||
local z1 = collisionbox[3] * 2
|
||||
local x2 = collisionbox[4] * 2
|
||||
local y2 = collisionbox[5] * 2
|
||||
local z2 = collisionbox[6] * 2
|
||||
local x_len = math.abs(x2 - x1)
|
||||
local y_len = math.abs(y2 - y1)
|
||||
local z_len = math.abs(z2 - z1)
|
||||
|
||||
-- Move object position to the center of its bounding box
|
||||
opos.x = opos.x + x1 + x2
|
||||
opos.y = opos.y + y1 + y2
|
||||
opos.z = opos.z + z1 + z2
|
||||
-- Move object position to the center of its bounding box
|
||||
opos.x = opos.x + x1 + x2
|
||||
opos.y = opos.y + y1 + y2
|
||||
opos.z = opos.z + z1 + z2
|
||||
|
||||
-- Count number of rays from collision box which are unobstructed
|
||||
local count = N_EXPOSURE_RAYS
|
||||
-- Count number of rays from collision box which are unobstructed
|
||||
local count = N_EXPOSURE_RAYS
|
||||
|
||||
for i = 1, N_EXPOSURE_RAYS do
|
||||
local rpos_x = opos.x + math.random() * x_len - x_len / 2
|
||||
local rpos_y = opos.y + math.random() * y_len - y_len / 2
|
||||
local rpos_z = opos.z + math.random() * z_len - z_len / 2
|
||||
local rdir_x = pos.x - rpos_x
|
||||
local rdir_y = pos.y - rpos_y
|
||||
local rdir_z = pos.z - rpos_z
|
||||
local rdir_len = math.hypot(rdir_x, math.hypot(rdir_y, rdir_z))
|
||||
rdir_x = rdir_x / rdir_len
|
||||
rdir_y = rdir_y / rdir_len
|
||||
rdir_z = rdir_z / rdir_len
|
||||
for i = 1, N_EXPOSURE_RAYS do
|
||||
local rpos_x = opos.x + math.random() * x_len - x_len / 2
|
||||
local rpos_y = opos.y + math.random() * y_len - y_len / 2
|
||||
local rpos_z = opos.z + math.random() * z_len - z_len / 2
|
||||
local rdir_x = pos.x - rpos_x
|
||||
local rdir_y = pos.y - rpos_y
|
||||
local rdir_z = pos.z - rpos_z
|
||||
local rdir_len = math.hypot(rdir_x, math.hypot(rdir_y, rdir_z))
|
||||
rdir_x = rdir_x / rdir_len
|
||||
rdir_y = rdir_y / rdir_len
|
||||
rdir_z = rdir_z / rdir_len
|
||||
|
||||
for i=0, rdir_len / STEP_LENGTH do
|
||||
rpos_x = rpos_x + rdir_x * STEP_LENGTH
|
||||
rpos_y = rpos_y + rdir_y * STEP_LENGTH
|
||||
rpos_z = rpos_z + rdir_z * STEP_LENGTH
|
||||
local npos_x = math.floor(rpos_x + 0.5)
|
||||
local npos_y = math.floor(rpos_y + 0.5)
|
||||
local npos_z = math.floor(rpos_z + 0.5)
|
||||
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
|
||||
npos_x - emin_x + 1
|
||||
for i=0, rdir_len / STEP_LENGTH do
|
||||
rpos_x = rpos_x + rdir_x * STEP_LENGTH
|
||||
rpos_y = rpos_y + rdir_y * STEP_LENGTH
|
||||
rpos_z = rpos_z + rdir_z * STEP_LENGTH
|
||||
local npos_x = math.floor(rpos_x + 0.5)
|
||||
local npos_y = math.floor(rpos_y + 0.5)
|
||||
local npos_z = math.floor(rpos_z + 0.5)
|
||||
local idx = (npos_z - emin_z) * zstride + (npos_y - emin_y) * ystride +
|
||||
npos_x - emin_x + 1
|
||||
|
||||
|
||||
local cid = data[idx]
|
||||
local walkable = node_walkable[cid]
|
||||
local cid = data[idx]
|
||||
local walkable = node_walkable[cid]
|
||||
|
||||
if walkable then
|
||||
count = count - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if walkable then
|
||||
count = count - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Punch entity with damage depending on explosion exposure and
|
||||
-- distance to explosion
|
||||
local exposure = count / N_EXPOSURE_RAYS
|
||||
local punch_vec = vector.subtract(opos, pos)
|
||||
local punch_dir = vector.normalize(punch_vec)
|
||||
local impact = (1 - vector.length(punch_vec) / punch_radius) * exposure
|
||||
if impact < 0 then
|
||||
impact = 0
|
||||
end
|
||||
local damage = math.floor((impact * impact + impact) * 7 * strength + 1)
|
||||
obj:punch(obj, 10, { damage_groups = { full_punch_interval = 1,
|
||||
fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
|
||||
-- Punch entity with damage depending on explosion exposure and
|
||||
-- distance to explosion
|
||||
local exposure = count / N_EXPOSURE_RAYS
|
||||
local punch_vec = vector.subtract(opos, pos)
|
||||
local punch_dir = vector.normalize(punch_vec)
|
||||
local impact = (1 - vector.length(punch_vec) / punch_radius) * exposure
|
||||
if impact < 0 then
|
||||
impact = 0
|
||||
end
|
||||
local damage = math.floor((impact * impact + impact) * 7 * strength + 1)
|
||||
obj:punch(obj, 10, { damage_groups = { full_punch_interval = 1,
|
||||
fleshy = damage, knockback = impact * 20.0 } }, punch_dir)
|
||||
|
||||
if obj:is_player() then
|
||||
obj:add_player_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
elseif ent.tnt_knockback then
|
||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if obj:is_player() then
|
||||
obj:add_player_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
elseif ent.tnt_knockback then
|
||||
obj:add_velocity(vector.multiply(punch_dir, impact * 20))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove destroyed blocks and drop items
|
||||
for hash, idx in pairs(destroy) do
|
||||
local do_drop = not creative_mode and math.random() <= drop_chance
|
||||
local on_blast = node_on_blast[data[idx]]
|
||||
local remove = true
|
||||
-- Remove destroyed blocks and drop items
|
||||
for hash, idx in pairs(destroy) do
|
||||
local do_drop = not creative_mode and math.random() <= drop_chance
|
||||
local on_blast = node_on_blast[data[idx]]
|
||||
local remove = true
|
||||
|
||||
if do_drop or on_blast ~= nil then
|
||||
local npos = get_position_from_hash(hash)
|
||||
if on_blast ~= nil then
|
||||
remove = on_blast(npos, 1.0)
|
||||
else
|
||||
local name = minetest.get_name_from_content_id(data[idx])
|
||||
local drop = minetest.get_node_drops(name, "")
|
||||
if do_drop or on_blast ~= nil then
|
||||
local npos = get_position_from_hash(hash)
|
||||
if on_blast ~= nil then
|
||||
remove = on_blast(npos, 1.0)
|
||||
else
|
||||
local name = minetest.get_name_from_content_id(data[idx])
|
||||
local drop = minetest.get_node_drops(name, "")
|
||||
|
||||
for _, item in ipairs(drop) do
|
||||
if item ~= "string" then
|
||||
item = item:get_name() .. item:get_count()
|
||||
end
|
||||
minetest.add_item(npos, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
if remove then
|
||||
data[idx] = minetest.CONTENT_AIR
|
||||
end
|
||||
end
|
||||
for _, item in ipairs(drop) do
|
||||
if item ~= "string" then
|
||||
item = item:get_name() .. item:get_count()
|
||||
end
|
||||
minetest.add_item(npos, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
if remove then
|
||||
data[idx] = minetest.CONTENT_AIR
|
||||
end
|
||||
end
|
||||
|
||||
-- Log explosion
|
||||
minetest.log('action', 'Explosion at ' .. minetest.pos_to_string(pos) ..
|
||||
' with strength ' .. strength .. ' and radius ' .. radius)
|
||||
-- Log explosion
|
||||
minetest.log('action', 'Explosion at ' .. minetest.pos_to_string(pos) ..
|
||||
' with strength ' .. strength .. ' and radius ' .. radius)
|
||||
|
||||
-- Update environment
|
||||
vm:set_data(data)
|
||||
vm:write_to_map(data)
|
||||
vm:update_liquids()
|
||||
-- Update environment
|
||||
vm:set_data(data)
|
||||
vm:write_to_map(data)
|
||||
vm:update_liquids()
|
||||
end
|
||||
|
||||
-- Create an explosion with strength at pos.
|
||||
--
|
||||
-- Parameters:
|
||||
-- pos - The position where the explosion originates from
|
||||
-- strength - The blast strength of the explosion (a TNT explosion uses 4)
|
||||
-- info - Table containing information about explosion.
|
||||
-- pos - The position where the explosion originates from
|
||||
-- strength - The blast strength of the explosion (a TNT explosion uses 4)
|
||||
-- info - Table containing information about explosion.
|
||||
--
|
||||
-- Values in info:
|
||||
-- drop_chance - If specified becomes the drop chance of all nodes in the
|
||||
-- explosion (defaults to 1.0 / strength)
|
||||
-- no_sound - If true then the explosion will not play a sound
|
||||
-- no_particle - If true then the explosion will not create particles
|
||||
-- drop_chance - If specified becomes the drop chance of all nodes in the
|
||||
-- explosion (defaults to 1.0 / strength)
|
||||
-- no_sound - If true then the explosion will not play a sound
|
||||
-- no_particle - If true then the explosion will not create particles
|
||||
function mcl_explosions.explode(pos, strength, info)
|
||||
-- The maximum blast radius (in the air)
|
||||
local radius = math.ceil(1.3 * strength / (0.3 * 0.75) * 0.3)
|
||||
-- The maximum blast radius (in the air)
|
||||
local radius = math.ceil(1.3 * strength / (0.3 * 0.75) * 0.3)
|
||||
|
||||
if not sphere_shapes[radius] then
|
||||
sphere_shapes[radius] = compute_sphere_rays(radius)
|
||||
end
|
||||
shape = sphere_shapes[radius]
|
||||
if not sphere_shapes[radius] then
|
||||
sphere_shapes[radius] = compute_sphere_rays(radius)
|
||||
end
|
||||
shape = sphere_shapes[radius]
|
||||
|
||||
trace_explode(pos, strength, shape, radius, (info and info.drop_chance) or 1 / strength)
|
||||
trace_explode(pos, strength, shape, radius, (info and info.drop_chance) or 1 / strength)
|
||||
|
||||
if not (info and info.no_sound) then
|
||||
add_particles(pos, radius)
|
||||
end
|
||||
if not (info and info.no_particle) then
|
||||
minetest.sound_play("tnt_explode", {
|
||||
pos = pos, gain = 1.0,
|
||||
max_hear_distance = strength * 16
|
||||
}, true)
|
||||
end
|
||||
if not (info and info.no_sound) then
|
||||
add_particles(pos, radius)
|
||||
end
|
||||
if not (info and info.no_particle) then
|
||||
minetest.sound_play("tnt_explode", {
|
||||
pos = pos, gain = 1.0,
|
||||
max_hear_distance = strength * 16
|
||||
}, true)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue