Generalize TNT item loss probability and apply it to more items

This commit is contained in:
sfan5 2025-02-16 17:13:40 +01:00
parent d38b8e6657
commit 692ac2d062
3 changed files with 30 additions and 11 deletions

View file

@ -599,6 +599,18 @@ Both nodedefs and entitydefs can provide an `on_blast()` callback
* `drops` - a list of drops, e.g. {"wool:red"} * `drops` - a list of drops, e.g. {"wool:red"}
Node drops:
When a node is detonated it is removed according to the following rules.
1. If `on_blast` is defined, that is called.
2. Else if the node has group `flammable` it is replaced with a fire node.
3. Else the dropped items are retrieved and it is replaced with air.
The parameter `_tnt_loss` in any item definition can be set to a number to
effect that "one in X" of these drops will be lost during an explosion.
For example `_tnt_loss = 2` would cause 50% of items to disappear.
The default is to not lose any items, which is equivalent to `_tnt_loss = 0`.
Screwdriver API Screwdriver API
--------------- ---------------

View file

@ -271,6 +271,7 @@ minetest.register_node("default:cobble", {
is_ground_content = false, is_ground_content = false,
groups = {cracky = 3, stone = 2}, groups = {cracky = 3, stone = 2},
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
_tnt_loss = 4,
}) })
minetest.register_node("default:stonebrick", { minetest.register_node("default:stonebrick", {
@ -297,9 +298,9 @@ minetest.register_node("default:mossycobble", {
is_ground_content = false, is_ground_content = false,
groups = {cracky = 3, stone = 1}, groups = {cracky = 3, stone = 1},
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
_tnt_loss = 4,
}) })
minetest.register_node("default:desert_stone", { minetest.register_node("default:desert_stone", {
description = S("Desert Stone"), description = S("Desert Stone"),
tiles = {"default_desert_stone.png"}, tiles = {"default_desert_stone.png"},
@ -315,6 +316,7 @@ minetest.register_node("default:desert_cobble", {
is_ground_content = false, is_ground_content = false,
groups = {cracky = 3, stone = 2}, groups = {cracky = 3, stone = 2},
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
_tnt_loss = 4,
}) })
minetest.register_node("default:desert_stonebrick", { minetest.register_node("default:desert_stonebrick", {
@ -444,6 +446,7 @@ minetest.register_node("default:dirt", {
tiles = {"default_dirt.png"}, tiles = {"default_dirt.png"},
groups = {crumbly = 3, soil = 1}, groups = {crumbly = 3, soil = 1},
sounds = default.node_sound_dirt_defaults(), sounds = default.node_sound_dirt_defaults(),
_tnt_loss = 3,
}) })
minetest.register_node("default:dirt_with_grass", { minetest.register_node("default:dirt_with_grass", {
@ -530,6 +533,7 @@ minetest.register_node("default:dry_dirt", {
tiles = {"default_dry_dirt.png"}, tiles = {"default_dry_dirt.png"},
groups = {crumbly = 3, soil = 1}, groups = {crumbly = 3, soil = 1},
sounds = default.node_sound_dirt_defaults(), sounds = default.node_sound_dirt_defaults(),
_tnt_loss = 3,
}) })
minetest.register_node("default:dry_dirt_with_dry_grass", { minetest.register_node("default:dry_dirt_with_dry_grass", {
@ -576,6 +580,7 @@ minetest.register_node("default:sand", {
tiles = {"default_sand.png"}, tiles = {"default_sand.png"},
groups = {crumbly = 3, falling_node = 1, sand = 1}, groups = {crumbly = 3, falling_node = 1, sand = 1},
sounds = default.node_sound_sand_defaults(), sounds = default.node_sound_sand_defaults(),
_tnt_loss = 2,
}) })
minetest.register_node("default:desert_sand", { minetest.register_node("default:desert_sand", {
@ -583,6 +588,7 @@ minetest.register_node("default:desert_sand", {
tiles = {"default_desert_sand.png"}, tiles = {"default_desert_sand.png"},
groups = {crumbly = 3, falling_node = 1, sand = 1}, groups = {crumbly = 3, falling_node = 1, sand = 1},
sounds = default.node_sound_sand_defaults(), sounds = default.node_sound_sand_defaults(),
_tnt_loss = 2,
}) })
minetest.register_node("default:silver_sand", { minetest.register_node("default:silver_sand", {
@ -590,6 +596,7 @@ minetest.register_node("default:silver_sand", {
tiles = {"default_silver_sand.png"}, tiles = {"default_silver_sand.png"},
groups = {crumbly = 3, falling_node = 1, sand = 1}, groups = {crumbly = 3, falling_node = 1, sand = 1},
sounds = default.node_sound_sand_defaults(), sounds = default.node_sound_sand_defaults(),
_tnt_loss = 2,
}) })
@ -604,7 +611,8 @@ minetest.register_node("default:gravel", {
{items = {"default:flint"}, rarity = 16}, {items = {"default:flint"}, rarity = 16},
{items = {"default:gravel"}} {items = {"default:gravel"}}
} }
} },
_tnt_loss = 3,
}) })
minetest.register_node("default:clay", { minetest.register_node("default:clay", {
@ -639,6 +647,7 @@ minetest.register_node("default:snow", {
}, },
groups = {crumbly = 3, falling_node = 1, snowy = 1}, groups = {crumbly = 3, falling_node = 1, snowy = 1},
sounds = default.node_sound_snow_defaults(), sounds = default.node_sound_snow_defaults(),
_tnt_loss = 1, -- means it will disappear entirely
on_construct = function(pos) on_construct = function(pos)
pos.y = pos.y - 1 pos.y = pos.y - 1
@ -2807,6 +2816,7 @@ minetest.register_node("default:glass", {
is_ground_content = false, is_ground_content = false,
groups = {cracky = 3, oddly_breakable_by_hand = 3}, groups = {cracky = 3, oddly_breakable_by_hand = 3},
sounds = default.node_sound_glass_defaults(), sounds = default.node_sound_glass_defaults(),
_tnt_loss = 2,
}) })
minetest.register_node("default:obsidian_glass", { minetest.register_node("default:obsidian_glass", {

View file

@ -12,12 +12,6 @@ if enable_tnt == nil then
enable_tnt = minetest.is_singleplayer() enable_tnt = minetest.is_singleplayer()
end end
-- loss probabilities array (one in X will be lost)
local loss_prob = {}
loss_prob["default:cobble"] = 3
loss_prob["default:dirt"] = 4
local tnt_radius = tonumber(minetest.settings:get("tnt_radius") or 3) local tnt_radius = tonumber(minetest.settings:get("tnt_radius") or 3)
-- Fill a list with data for content IDs, after all nodes are registered -- Fill a list with data for content IDs, after all nodes are registered
@ -27,7 +21,7 @@ minetest.register_on_mods_loaded(function()
cid_data[minetest.get_content_id(name)] = { cid_data[minetest.get_content_id(name)] = {
name = name, name = name,
drops = def.drops, drops = def.drops,
flammable = def.groups.flammable, flammable = def.groups and (def.groups.flammable or 0) ~= 0,
on_blast = def.on_blast, on_blast = def.on_blast,
} }
end end
@ -76,11 +70,14 @@ end
local function add_drop(drops, item) local function add_drop(drops, item)
item = ItemStack(item) item = ItemStack(item)
local name = item:get_name() -- Note that this needs to be set on the dropped item, not the node.
if loss_prob[name] ~= nil and math.random(1, loss_prob[name]) == 1 then -- Value represents "one in X will be lost"
local lost = item:get_definition()._tnt_loss or 0
if lost > 0 and (lost == 1 or math.random(1, lost) == 1) then
return return
end end
local name = item:get_name()
local drop = drops[name] local drop = drops[name]
if drop == nil then if drop == nil then
drops[name] = item drops[name] = item