2021-05-29 16:12:33 +02:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
2023-03-09 15:05:25 +01:00
local explosions_griefing = minetest.settings : get_bool ( " mcl_explosions_griefing " , true )
2019-03-08 00:46:35 +01:00
2022-11-11 10:53:40 +01:00
tnt = { }
tnt.BOOMTIMER = 4
tnt.BLINKTIMER = 0.25
---@param pos Vector
---@param entname string
---@return ObjectRef?
2017-01-16 14:59:16 +01:00
local function spawn_tnt ( pos , entname )
2022-11-11 10:53:40 +01:00
minetest.sound_play ( " tnt_ignite " , { pos = pos , gain = 1.0 , max_hear_distance = 15 } , true )
local ent = minetest.add_entity ( pos , entname )
if ent then
ent : set_armor_groups ( { immortal = 1 } )
end
return ent
2015-06-29 19:55:56 +02:00
end
2022-11-11 10:53:40 +01:00
---@param pos Vector
---@return ObjectRef?
2021-05-29 16:12:33 +02:00
function tnt . ignite ( pos )
2017-01-16 14:59:16 +01:00
minetest.remove_node ( pos )
2020-06-07 20:39:19 +02:00
local e = spawn_tnt ( pos , " mcl_tnt:tnt " )
2020-02-05 12:45:29 +01:00
minetest.check_for_falling ( pos )
2020-06-07 20:39:19 +02:00
return e
2017-01-16 14:59:16 +01:00
end
2022-11-11 10:53:40 +01:00
---Add smoke particle of entity at pos.
---
---Intended to be called every step.
---@param pos Vector
2021-05-29 16:12:33 +02:00
function tnt . smoke_step ( pos )
2020-01-30 22:05:18 +01:00
minetest.add_particle ( {
2022-11-11 10:53:40 +01:00
pos = vector.offset ( pos , 0 , 0.5 , 0 ) ,
velocity = vector.new ( math.random ( ) * 0.2 - 0.1 , 1.0 + math.random ( ) , math.random ( ) * 0.2 - 0.1 ) ,
acceleration = vector.new ( 0 , - 0.1 , 0 ) ,
expirationtime = 0.15 + math.random ( ) * 0.25 ,
size = 1.0 + math.random ( ) ,
2020-01-30 22:05:18 +01:00
collisiondetection = false ,
2022-11-11 10:53:40 +01:00
texture = " mcl_particles_smoke.png "
2020-01-30 22:05:18 +01:00
} )
end
2017-03-11 20:54:27 +01:00
local TNT_RANGE = 3
2017-01-16 14:59:16 +01:00
2017-08-09 13:38:47 +02:00
local sounds
if minetest.get_modpath ( " mcl_sounds " ) then
sounds = mcl_sounds.node_sound_wood_defaults ( )
end
2022-11-11 10:53:40 +01:00
2019-03-17 09:33:44 +01:00
local tnt_mesecons
if minetest.get_modpath ( " mesecons " ) then
2022-11-11 10:53:40 +01:00
tnt_mesecons = {
effector = {
action_on = tnt.ignite ,
rules = mesecon.rules . alldirs ,
} ,
}
2019-03-17 09:33:44 +01:00
end
2020-02-05 03:11:32 +01:00
local longdesc
2023-03-09 15:05:25 +01:00
if explosions_griefing then
2022-11-11 10:53:40 +01:00
longdesc = S ( " An explosive device. When it explodes, it will hurt living beings and destroy blocks around it. TNT has an explosion radius of @1. 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, fire, lava and redstone signals. "
, TNT_RANGE )
2020-02-05 03:11:32 +01:00
else
2022-11-11 10:53:40 +01:00
longdesc = S ( " An explosive device. When it explodes, it will hurt living beings. TNT has an explosion radius of @1. TNT can be ignited by tools, explosions, fire, lava and redstone signals. "
, TNT_RANGE )
2020-02-05 03:11:32 +01:00
end
2017-01-26 11:23:09 +01:00
minetest.register_node ( " mcl_tnt:tnt " , {
2022-11-11 10:53:40 +01:00
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 " ,
} ,
2017-01-04 22:36:51 +01:00
is_ground_content = false ,
2015-06-29 19:55:56 +02:00
stack_max = 64 ,
2019-03-08 00:46:35 +01:00
description = S ( " TNT " ) ,
2017-06-13 14:46:21 +02:00
paramtype = " light " ,
sunlight_propagates = true ,
2022-11-11 10:53:40 +01:00
_tt_help = S ( " Ignited by tools, explosions, fire, lava, redstone power " ) ..
" \n " .. S ( " Explosion radius: @1 " , tostring ( TNT_RANGE ) ) ,
2020-02-05 03:11:32 +01:00
_doc_items_longdesc = longdesc ,
2019-03-16 00:07:44 +01:00
_doc_items_usagehelp = S ( " Place the TNT and ignite it with one of the methods above. Quickly get in safe distance. The TNT will start to be affected by gravity and explodes in 4 seconds. " ) ,
2022-11-11 10:53:40 +01:00
groups = { dig_immediate = 3 , tnt = 1 , enderman_takable = 1 , flammable = - 1 } ,
2019-03-17 09:33:44 +01:00
mesecons = tnt_mesecons ,
2022-11-11 10:53:40 +01:00
on_blast = function ( pos , _ )
local e = tnt.ignite ( pos )
if e then
e : get_luaentity ( ) . timer = tnt.BOOMTIMER - ( 0.5 + math.random ( ) )
end
2020-04-16 23:05:50 +02:00
end ,
2017-08-17 04:12:34 +02:00
_on_ignite = function ( player , pointed_thing )
tnt.ignite ( pointed_thing.under )
2017-09-19 15:45:23 +02:00
return true
2017-05-09 17:49:38 +02:00
end ,
2020-05-09 18:52:03 +02:00
_on_burn = function ( pos )
tnt.ignite ( pos )
return true
end ,
2018-02-01 22:45:19 +01:00
_on_dispense = function ( stack , pos , droppos , dropnode , dropdir )
-- Place and ignite TNT
if minetest.registered_nodes [ dropnode.name ] . buildable_to then
2022-11-11 10:53:40 +01:00
minetest.set_node ( droppos , { name = stack : get_name ( ) } )
2018-02-01 22:45:19 +01:00
tnt.ignite ( droppos )
end
end ,
2017-08-09 13:38:47 +02:00
sounds = sounds ,
2015-06-29 19:55:56 +02:00
} )
local TNT = {
-- Static definition
physical = true , -- Collides with things
2022-11-11 10:53:40 +01:00
--weight = -100,
collisionbox = { - 0.5 , - 0.5 , - 0.5 , 0.5 , 0.5 , 0.5 } ,
2015-06-29 19:55:56 +02:00
visual = " cube " ,
2022-11-11 10:53:40 +01:00
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 " ,
} ,
2015-06-29 19:55:56 +02:00
-- Initial value for our timer
timer = 0 ,
blinktimer = 0 ,
2020-04-18 14:18:23 +02:00
tnt_knockback = true ,
2022-11-11 10:53:40 +01:00
blinkstatus = true ,
}
2015-06-29 19:55:56 +02:00
2022-11-11 10:53:40 +01:00
function TNT : on_activate ( _ , _ )
local phi = math.random ( 0 , 65535 ) / 65535 * 2 * math.pi
2018-01-25 16:23:54 +01:00
local hdir_x = math.cos ( phi ) * 0.02
local hdir_z = math.sin ( phi ) * 0.02
2022-11-11 10:53:40 +01:00
self.object : set_velocity ( vector.new ( hdir_x , 2 , hdir_z ) )
self.object : set_acceleration ( vector.new ( 0 , - 10 , 0 ) )
2019-03-06 04:38:57 +01:00
self.object : set_texture_mod ( " ^mcl_tnt_blink.png " )
2015-06-29 19:55:56 +02:00
end
2021-05-22 20:00:59 +02:00
--[[local function add_effects(pos, radius, drops)
2017-05-30 01:27:45 +02:00
minetest.add_particlespawner ( {
amount = 64 ,
time = 0.5 ,
minpos = vector.subtract ( pos , radius / 2 ) ,
maxpos = vector.add ( pos , radius / 2 ) ,
2022-11-11 10:53:40 +01:00
minvel = vector.new ( - 10 , - 10 , - 10 ) ,
maxvel = vector.new ( 10 , 10 , 10 ) ,
2017-05-30 01:27:45 +02:00
minacc = vector.new ( ) ,
maxacc = vector.new ( ) ,
minexptime = 1 ,
maxexptime = 2.5 ,
minsize = radius * 1 ,
maxsize = radius * 3 ,
2020-08-19 18:47:58 +02:00
texture = " mcl_particles_smoke.png " ,
2017-05-30 01:27:45 +02:00
} )
-- we just dropped some items. Look at the items entities and pick
-- one of them to use as texture
2020-08-19 18:47:58 +02:00
local texture = " mcl_particles_smoke.png " --fallback texture
2017-05-30 01:27:45 +02:00
local most = 0
for name , stack in pairs ( drops ) do
local count = stack : get_count ( )
if count > most then
most = count
local def = minetest.registered_nodes [ name ]
if def and def.tiles and def.tiles [ 1 ] then
texture = def.tiles [ 1 ]
end
end
end
minetest.add_particlespawner ( {
amount = 32 ,
time = 0.1 ,
minpos = vector.subtract ( pos , radius / 2 ) ,
maxpos = vector.add ( pos , radius / 2 ) ,
2022-11-11 10:53:40 +01:00
minvel = vector.new ( - 3 , 0 , - 3 ) ,
maxvel = vector.new ( 3 , 5 , 3 ) ,
minacc = vector.new ( 0 , - 10 , 0 ) ,
2017-05-30 01:27:45 +02:00
minexptime = 0.8 ,
maxexptime = 2.0 ,
minsize = radius * 0.66 ,
maxsize = radius * 2 ,
texture = texture ,
collisiondetection = true ,
} )
2021-05-22 20:00:59 +02:00
end ] ]
2017-05-30 01:27:45 +02:00
2022-11-11 10:53:40 +01:00
function TNT : on_step ( dtime , _ )
2019-02-01 06:33:07 +01:00
local pos = self.object : get_pos ( )
2020-01-30 22:05:18 +01:00
tnt.smoke_step ( pos )
2015-06-29 19:55:56 +02:00
self.timer = self.timer + dtime
self.blinktimer = self.blinktimer + dtime
2020-01-30 22:05:18 +01:00
if self.blinktimer > tnt.BLINKTIMER then
self.blinktimer = self.blinktimer - tnt.BLINKTIMER
2015-06-29 19:55:56 +02:00
if self.blinkstatus then
2019-03-06 04:38:57 +01:00
self.object : set_texture_mod ( " " )
2015-06-29 19:55:56 +02:00
else
2019-03-06 04:38:57 +01:00
self.object : set_texture_mod ( " ^mcl_tnt_blink.png " )
2015-06-29 19:55:56 +02:00
end
self.blinkstatus = not self.blinkstatus
end
2020-01-30 22:05:18 +01:00
if self.timer > tnt.BOOMTIMER then
2021-03-01 16:08:52 +01:00
mcl_explosions.explode ( self.object : get_pos ( ) , 4 , { } , self.object )
2017-07-25 04:44:46 +02:00
self.object : remove ( )
end
end
2017-01-26 11:23:09 +01:00
minetest.register_entity ( " mcl_tnt:tnt " , TNT )
2015-06-29 19:55:56 +02:00
2017-08-09 13:38:47 +02:00
if minetest.get_modpath ( " mcl_mobitems " ) then
minetest.register_craft ( {
output = " mcl_tnt:tnt " ,
recipe = {
2022-11-11 10:53:40 +01:00
{ " mcl_mobitems:gunpowder " , " group:sand " , " mcl_mobitems:gunpowder " } ,
{ " group:sand " , " mcl_mobitems:gunpowder " , " group:sand " } ,
{ " mcl_mobitems:gunpowder " , " group:sand " , " mcl_mobitems:gunpowder " }
} ,
2017-08-09 13:38:47 +02:00
} )
end
2017-03-21 04:36:18 +01:00
if minetest.get_modpath ( " doc_identifier " ) then
doc.sub . identifier.register_object ( " mcl_tnt:tnt " , " nodes " , " mcl_tnt:tnt " )
end