forked from VoxeLibre/VoxeLibre
156 lines
5.6 KiB
Lua
156 lines
5.6 KiB
Lua
local function spawn_tnt(pos, entname)
|
|
minetest.sound_play("tnt_ignite", {pos = pos,gain = 1.0,max_hear_distance = 15,})
|
|
local tnt = minetest.add_entity(pos, entname)
|
|
tnt:set_armor_groups({immortal=1})
|
|
return tnt
|
|
end
|
|
|
|
local function activate_if_tnt(nname, np, tnt_np, tntr)
|
|
if nname == "mcl_tnt:tnt" then
|
|
local e = spawn_tnt(np, nname)
|
|
e:setvelocity({x=(np.x - tnt_np.x)*5+(tntr / 4), y=(np.y - tnt_np.y)*5+(tntr / 3), z=(np.z - tnt_np.z)*5+(tntr / 4)})
|
|
end
|
|
end
|
|
|
|
local function do_tnt_physics(tnt_np,tntr)
|
|
local objs = minetest.get_objects_inside_radius(tnt_np, tntr)
|
|
for k, obj in pairs(objs) do
|
|
local oname = obj:get_entity_name()
|
|
local v = obj:getvelocity()
|
|
local p = obj:getpos()
|
|
if oname == "mcl_tnt:tnt" then
|
|
obj:setvelocity({x=(p.x - tnt_np.x) + (tntr / 2) + v.x, y=(p.y - tnt_np.y) + tntr + v.y, z=(p.z - tnt_np.z) + (tntr / 2) + v.z})
|
|
else
|
|
if v ~= nil then
|
|
obj:setvelocity({x=(p.x - tnt_np.x) + (tntr / 4) + v.x, y=(p.y - tnt_np.y) + (tntr / 2) + v.y, z=(p.z - tnt_np.z) + (tntr / 4) + v.z})
|
|
else
|
|
if obj:get_player_name() ~= nil then
|
|
obj:set_hp(obj:get_hp() - 1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
tnt = {}
|
|
tnt.ignite = function(pos)
|
|
minetest.remove_node(pos)
|
|
spawn_tnt(pos, "mcl_tnt:tnt")
|
|
core.check_for_falling(pos)
|
|
end
|
|
|
|
local TNT_RANGE = 3
|
|
|
|
minetest.register_node("mcl_tnt:tnt", {
|
|
tiles = {"default_tnt_top.png", "default_tnt_bottom.png",
|
|
"default_tnt_side.png", "default_tnt_side.png",
|
|
"default_tnt_side.png", "default_tnt_side.png"},
|
|
is_ground_content = false,
|
|
stack_max = 64,
|
|
description = "TNT",
|
|
_doc_items_longdesc = string.format("An explosive device. When it explodes, it will hurt living beings, destroy blocks around it, throw blocks affected by gravity all over the place and light fires. A single TNT has an explosion radius of %d. With a small chance, blocks may drop as an item (as if being mined) rather than being destroyed. TNT can be ignited by tools, explosions, igniter blocks and redstone signals.", TNT_RANGE),
|
|
_doc_items_usagehelp = "Place the TNT on the ground and ignite it with one of the methods above. Quickly get in safe distance quickly. The TNT will start to be affected by gravity and explodes in 4 seconds.",
|
|
groups = { dig_immediate = 3, tnt = 1, },
|
|
mesecons = {effector = {
|
|
action_on = tnt.ignite
|
|
}},
|
|
sounds = mcl_sounds.node_sound_wood_defaults(),
|
|
})
|
|
|
|
local TNT = {
|
|
-- Static definition
|
|
physical = true, -- Collides with things
|
|
--weight = -100,
|
|
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
|
visual = "cube",
|
|
textures = {"default_tnt_top.png", "default_tnt_bottom.png",
|
|
"default_tnt_side.png", "default_tnt_side.png",
|
|
"default_tnt_side.png", "default_tnt_side.png"},
|
|
-- Initial value for our timer
|
|
timer = 0,
|
|
-- Number of punches required to defuse
|
|
health = 1,
|
|
blinktimer = 0,
|
|
blinkstatus = true,}
|
|
|
|
function TNT:on_activate(staticdata)
|
|
self.object:setvelocity({x=0, y=4, z=0})
|
|
self.object:setacceleration({x=0, y=-10, z=0})
|
|
self.object:settexturemod("^mcl_tnt_blink.png")
|
|
end
|
|
|
|
function TNT:on_step(dtime)
|
|
local pos = self.object:getpos()
|
|
minetest.add_particle({
|
|
pos = {x=pos.x,y=pos.y+0.5,z=pos.z},
|
|
velocity = {x=math.random(-.1,.1),y=math.random(1,2),z=math.random(-.1,.1)},
|
|
acceleration = {x=0,y=-0.1,z=0},
|
|
expirationtime = math.random(.5,1),
|
|
size = math.random(1,2),
|
|
collisiondetection = false,
|
|
texture = "tnt_smoke.png"
|
|
})
|
|
self.timer = self.timer + dtime
|
|
self.blinktimer = self.blinktimer + dtime
|
|
if self.blinktimer > 0.25 then
|
|
self.blinktimer = self.blinktimer - 0.25
|
|
if self.blinkstatus then
|
|
self.object:settexturemod("")
|
|
else
|
|
self.object:settexturemod("^mcl_tnt_blink.png")
|
|
end
|
|
self.blinkstatus = not self.blinkstatus
|
|
end
|
|
if self.timer > 4 then
|
|
local pos = self.object:getpos()
|
|
pos.x = math.floor(pos.x+0.5)
|
|
pos.y = math.floor(pos.y+0.5)
|
|
pos.z = math.floor(pos.z+0.5)
|
|
do_tnt_physics(pos, TNT_RANGE)
|
|
local meta = minetest.get_meta(pos)
|
|
minetest.sound_play("tnt_explode", {pos = pos,gain = 1.0,max_hear_distance = 16,})
|
|
if minetest.get_node(pos).name == "mcl_core:water_source" or minetest.get_node(pos).name == "mcl_core:water_flowing" or minetest.get_node(pos).name == "mcl_core:bedrock" or minetest.get_node(pos).name == "protector:display" or minetest.is_protected(pos, "tnt") then
|
|
-- Cancel the Explosion
|
|
self.object:remove()
|
|
return
|
|
end
|
|
for x=-TNT_RANGE,TNT_RANGE do
|
|
for y=-TNT_RANGE,TNT_RANGE do
|
|
for z=-TNT_RANGE,TNT_RANGE do
|
|
if x*x+y*y+z*z <= TNT_RANGE * TNT_RANGE + TNT_RANGE then
|
|
local np={x=pos.x+x,y=pos.y+y,z=pos.z+z}
|
|
local n = minetest.get_node(np)
|
|
if n.name ~= "air" and n.name ~= "mcl_core:obsidian" and n.name ~= "mcl_core:bedrock" and n.name ~= "protector:protect" then
|
|
activate_if_tnt(n.name, np, pos, 3)
|
|
minetest.remove_node(np)
|
|
core.check_for_falling(np)
|
|
if n.name ~= "mcl_tnt:tnt" and math.random() > 0.9 then
|
|
local drop = minetest.get_node_drops(n.name, "")
|
|
for _,item in ipairs(drop) do
|
|
if type(item) == "string" then
|
|
if math.random(1,100) > 40 then
|
|
local obj = minetest.add_item(np, item)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
self.object:remove()
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_entity("mcl_tnt:tnt", TNT)
|
|
|
|
minetest.register_craft({
|
|
output = "mcl_tnt:tnt",
|
|
recipe = {
|
|
{'mcl_mobitems:gunpowder','group:sand','mcl_mobitems:gunpowder'},
|
|
{'group:sand','mcl_mobitems:gunpowder','group:sand'},
|
|
{'mcl_mobitems:gunpowder','group:sand','mcl_mobitems:gunpowder'}
|
|
}
|
|
})
|