diff --git a/game_api.txt b/game_api.txt index d3330e5..b575b40 100644 --- a/game_api.txt +++ b/game_api.txt @@ -209,6 +209,42 @@ Fire API * Called when fire attempts to remove a burning node. * `pos` Position of the burning node. + +#TNT API +---------- + +tnt.register_tnt(definition) + +^ Register a new type of tnt. + + * `name` The name of the node. If no prefix is given `tnt` is used. + * `description` A description for your TNT. + * `radius` The radius within which the TNT can destroy nodes. The default is 3. + * `damage_radius` The radius within which the TNT can damage players and mobs. By default it is twice the `radius`. + * `disable_drops` Disable drops. By default it is set to false. + * `ignore_protection` Don't check `minetest.is_protected` before removing a node. + * `ignore_on_blast` Don't call `on_blast` even if a node has one. + * `tiles` Textures for node + * `side` Side tiles. By default the name of the tnt with a suffix of `_side.png`. + * `top` Top tile. By default the name of the tnt with a suffix of `_top.png`. + * `bottom` Bottom tile. By default the name of the tnt with a suffix of `_bottom.png`. + * `burning` Top tile when lit. By default the name of the tnt with a suffix of `_top_burning_animated.png". + +`tnt.boom(position, radius, damage_radius, disable_drops) ` + +^ Create an explosion. + +* `position` The center of explosion. +* `radius` The radius within which nodes can be destroyed. +* `damage_radius` The distance from the center that players and mobs can get damaged in. +* `disable_drops` Disable drops. +* `ignore_protection` Don't check `minetest.is_protected` before removing a node. +* `ignore_on_blast` Don't call `on_blast` even if a node has one. + +`tnt.burn(pos)` + +^ Ignite TNT at position + Screwdriver API --------------- diff --git a/mods/tnt/init.lua b/mods/tnt/init.lua index 528aee0..9295ed7 100644 --- a/mods/tnt/init.lua +++ b/mods/tnt/init.lua @@ -1,4 +1,4 @@ - +tnt = {} -- Default to enabled in singleplayer and disabled in multiplayer local singleplayer = minetest.is_singleplayer() local setting = minetest.setting_getbool("enable_tnt") @@ -84,12 +84,12 @@ end local fire_node = {name="fire:basic_flame"} -local function destroy(drops, pos, cid) - if minetest.is_protected(pos, "") then +local function destroy(drops, pos, cid, ignore_protection, ignore_on_blast) + if not ignore_protection and minetest.is_protected(pos, "") then return end local def = cid_data[cid] - if def and def.on_blast then + if not ignore_on_blast and def and def.on_blast then local node_drops = def.on_blast(vector.new(pos), 1) if node_drops then for _, item in ipairs(node_drops) do @@ -128,8 +128,6 @@ local function calc_velocity(pos1, pos2, old_vel, power) end local function entity_physics(pos, radius) - -- Make the damage radius larger than the destruction radius - radius = radius * 2 local objs = minetest.get_objects_inside_radius(pos, radius) for _, obj in pairs(objs) do local obj_pos = obj:getpos() @@ -195,11 +193,12 @@ local function add_effects(pos, radius) }) end -local function burn(pos) +function tnt.burn(pos) local name = minetest.get_node(pos).name - if name == "tnt:tnt" then + local group = minetest.get_item_group(name, "tnt") + if group > 0 then minetest.sound_play("tnt_ignite", {pos=pos}) - minetest.set_node(pos, {name="tnt:tnt_burning"}) + minetest.set_node(pos, {name=name.."_burning"}) minetest.get_node_timer(pos):start(1) elseif name == "tnt:gunpowder" then minetest.sound_play("tnt_gunpowder_burning", {pos=pos, gain=2}) @@ -208,7 +207,7 @@ local function burn(pos) end end -local function explode(pos, radius) +local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) local pos = vector.round(pos) local vm = VoxelManip() local pr = PseudoRandom(os.time()) @@ -234,7 +233,7 @@ local function explode(pos, radius) p.y = pos.y + y p.z = pos.z + z if cid ~= c_air then - destroy(drops, p, cid) + destroy(drops, p, cid, ignore_protection, ignore_on_blast) end end vi = vi + 1 @@ -245,59 +244,19 @@ local function explode(pos, radius) return drops end - -local function boom(pos) +function tnt.boom(pos, def) minetest.sound_play("tnt_explode", {pos=pos, gain=1.5, max_hear_distance=2*64}) minetest.set_node(pos, {name="tnt:boom"}) minetest.get_node_timer(pos):start(0.5) - - local drops = explode(pos, radius) - entity_physics(pos, radius) - eject_drops(drops, pos, radius) - add_effects(pos, radius) + local drops = tnt_explode(pos, def.radius, def.ignore_protection, + def.ignore_on_blast) + entity_physics(pos, def.damage_radius) + if not def.disable_drops then + eject_drops(drops, pos, def.radius) + end + add_effects(pos, def.radius) end -minetest.register_node("tnt:tnt", { - description = "TNT", - tiles = {"tnt_top.png", "tnt_bottom.png", "tnt_side.png"}, - is_ground_content = false, - groups = {dig_immediate=2, mesecon=2}, - sounds = default.node_sound_wood_defaults(), - on_punch = function(pos, node, puncher) - if puncher:get_wielded_item():get_name() == "default:torch" then - minetest.sound_play("tnt_ignite", {pos=pos}) - minetest.set_node(pos, {name="tnt:tnt_burning"}) - end - end, - on_blast = function(pos, intensity) - burn(pos) - end, - mesecons = {effector = {action_on = boom}}, -}) - -minetest.register_node("tnt:tnt_burning", { - tiles = { - { - name = "tnt_top_burning_animated.png", - animation = { - type = "vertical_frames", - aspect_w = 16, - aspect_h = 16, - length = 1, - } - }, - "tnt_bottom.png", "tnt_side.png"}, - light_source = 5, - drop = "", - sounds = default.node_sound_wood_defaults(), - on_construct = function(pos) - minetest.get_node_timer(pos):start(4) - end, - on_timer = boom, - -- unaffected by explosions - on_blast = function() end, -}) - minetest.register_node("tnt:boom", { drawtype = "plantlike", tiles = {"tnt_boom.png"}, @@ -331,11 +290,11 @@ minetest.register_node("tnt:gunpowder", { on_punch = function(pos, node, puncher) if puncher:get_wielded_item():get_name() == "default:torch" then - burn(pos) + tnt.burn(pos) end end, on_blast = function(pos, intensity) - burn(pos) + tnt.burn(pos) end, }) @@ -393,7 +352,7 @@ minetest.register_node("tnt:gunpowder_burning", { for dz = -1, 1 do for dy = -1, 1 do if not (dx == 0 and dz == 0) then - burn({ + tnt.burn({ x = pos.x + dx, y = pos.y + dy, z = pos.z + dz, @@ -409,11 +368,11 @@ minetest.register_node("tnt:gunpowder_burning", { }) minetest.register_abm({ - nodenames = {"tnt:tnt", "tnt:gunpowder"}, + nodenames = {"group:tnt", "tnt:gunpowder"}, neighbors = {"fire:basic_flame", "default:lava_source", "default:lava_flowing"}, interval = 4, chance = 1, - action = burn, + action = tnt.burn, }) minetest.register_craft({ @@ -430,3 +389,74 @@ minetest.register_craft({ {"", "group:wood", ""} } }) + +function tnt.register_tnt(def) + local name = "" + if not def.name:find(':') then + name = "tnt:"..def.name + else + name = def.name + def.name = def.name:match(":([%w_]+)") + end + if not def.tiles then def.tiles = {} end + local tnt_top = def.tiles.top or def.name.."_top.png" + local tnt_bottom = def.tiles.bottom or def.name.."_bottom.png" + local tnt_side = def.tiles.side or def.name.."_side.png" + local tnt_burning = def.tiles.burning or def.name.."_top_burning_animated.png" + if not def.damage_radius then def.damage_radius = def.radius * 2 end + + minetest.register_node(":"..name, { + description = def.description, + tiles = {tnt_top, tnt_bottom, tnt_side}, + is_ground_content = false, + groups = {dig_immediate=2, mesecon=2, tnt=1}, + sounds = default.node_sound_wood_defaults(), + on_punch = function(pos, node, puncher) + if puncher:get_wielded_item():get_name() == "default:torch" then + minetest.sound_play("tnt_ignite", {pos=pos}) + minetest.set_node(pos, {name=name.."_burning"}) + minetest.get_node_timer(pos):start(4) + end + end, + on_blast = function(pos, intensity) + tnt.burn(pos) + end, + mesecons = {effector = + {action_on = + function(pos) + tnt.boom(pos, def) + end + } + }, + }) + + minetest.register_node(":"..name.."_burning", { + tiles = { + { + name = tnt_burning, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1, + } + }, + tnt_bottom, tnt_side + }, + light_source = 5, + drop = "", + sounds = default.node_sound_wood_defaults(), + on_timer = function(pos, elapsed) + tnt.boom(pos, def) + end, + -- unaffected by explosions + on_blast = function() end, + }) +end + +tnt.register_tnt({ + name = "tnt:tnt", + description = "TNT", + radius = radius, +}) +