Add bomb and cracked stones

This commit is contained in:
Wuzzy 2024-08-28 23:52:21 +02:00
parent 8fe199d84d
commit 4780df0f42
22 changed files with 254 additions and 4 deletions

View File

@ -104,6 +104,7 @@ This is a reference of all groups used for nodes.
* `2`: Node catches fire first, then is destroyed.
`_lzr_active` must contain the name of the burning variant.
The burning variant in turn must have `_lzr_inactive`
* `3`: Same as `2`, but gets ignited from the top only
* `laser_incompatible=1`: The node is "incompatible" with lasers.
(see above)
* `flammable=1`: Node catches fire from neighboring burning blocks

View File

@ -23,7 +23,7 @@ All levels by Wuzzy.
## Textures
- `farming_cotton_wild.png` by Extex101 (CC BY-SA 3.0)
- Water, wood (normal), tree (normal), stone (normal), sandstone brick, sandstone block, tools, hand, gold block, wooden chest, locked wooden chest, ship lightbox, player textures, crates, seaweed, purple coral, crab grass, fire, candle (standing, wall, wield), wool (cloth) come from “PixelBOX” texture pack by jp (CC0)
- Water, wood (normal), tree (normal), stone (normal), sandstone brick, sandstone block, tools, hand, gold block, wooden chest, locked wooden chest, ship lightbox, player textures, crates, seaweed, purple coral, crab grass, fire, candle (standing, wall, wield), wool (cloth), bomb come from “PixelBOX” texture pack by jp (CC0)
- Sandstone by Wuzzy (CC0)
- Derivative work of PixelBox sandstone
- Hanging candle by Wuzzy (CC0)
@ -176,6 +176,18 @@ All levels by Wuzzy.
- original file name: laugh.WAV
- sound was shortened a bit
- License CC BY 4.0
- `lzr_laser_bomb_fuse.ogg`:
- by maximumplay3r <https://freesound.org/people/maximumplay3r/sounds/713344/>
- License: CC0
- `lzr_laser_bomb_explode.ogg`:
- by MultiMax2121 <https://freesound.org/people/MultiMax2121/sounds/156896/>
- edited by Wuzzy
- License: CC0
- `lzr_laser_bomb_explode.2.ogg`:
- by WaveAdventurer <https://freesound.org/people/WaveAdventurer/sounds/732252/>
- original name: explosion1(crunchier)
- sound was shortened
- License: CC BY 4.0
- All other sounds come from Minetest Game (see license of Minetest Game 5.4.1 for details)

View File

@ -7,6 +7,7 @@ minetest.register_node("lzr_core:stone", {
sounds = lzr_sounds.node_sound_stone_defaults(),
})
minetest.register_node("lzr_core:stone_block", {
description = S("Stone Block"),
tiles = {"default_stone_block.png"},
@ -98,6 +99,32 @@ minetest.register_node("lzr_core:dirt", {
sounds = lzr_sounds.node_sound_dirt_defaults(),
})
minetest.register_node("lzr_core:stone_cracked", {
description = S("Cracked Stone"),
tiles = {"lzr_core_stone_cracked.png"},
groups = { breakable = 1, cracked = 1 },
sounds = lzr_sounds.node_sound_stone_defaults(),
})
minetest.register_node("lzr_core:cave_stone_cracked", {
description = S("Cracked Cave Stone"),
tiles = {"lzr_core_cave_stone_cracked.png"},
groups = { breakable = 1, cracked = 1 },
sounds = lzr_sounds.node_sound_stone_defaults(),
})
minetest.register_node("lzr_core:sandstone_cracked", {
description = S("Cracked Sandstone"),
tiles = {"lzr_core_sandstone_cracked.png"},
groups = { breakable = 1, cracked = 1 },
sounds = lzr_sounds.node_sound_stone_defaults(),
})
minetest.register_node("lzr_core:island_stone_cracked", {
description = S("Cracked Island Stone"),
tiles = {"lzr_core_island_stone_cracked.png"},
groups = { breakable = 1, cracked = 1 },
sounds = lzr_sounds.node_sound_stone_defaults(),
})
minetest.register_node("lzr_core:dirt_with_grass", {
description = S("Dirt with Grass"),
tiles = {"default_grass.png", "default_dirt.png",

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

View File

@ -390,6 +390,13 @@ minetest.register_node("lzr_decor:ocean_stone", {
groups = { breakable = 1 },
sounds = lzr_sounds.node_sound_stone_defaults(),
})
minetest.register_node("lzr_decor:ocean_stone_cracked", {
description = S("Cracked Ocean Stone"),
tiles = {"lzr_decor_ocean_stone_cracked.png"},
groups = { breakable = 1, cracked = 1 },
sounds = lzr_sounds.node_sound_stone_defaults(),
})
minetest.register_node("lzr_decor:ocean_stone_block", {
description = S("Ocean Stone Block"),
tiles = {"lzr_decor_ocean_stone_block.png"},

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

View File

@ -17,6 +17,12 @@ local OPACITY_SKULL_GONE = 128
-- How long a barricade burns, in seconds
local BARRICADE_BURN_TIME = 1.0
-- How long the bomb fuse burns, in seconds
local BOMB_BURN_TIME = 2.0
local BOMB_BURN_TIME_QUICK = 0.2
local bomb_fuse_sounds = {}
minetest.register_node("lzr_laser:crate", {
description = S("Heavy Crate"),
tiles = {
@ -1083,6 +1089,170 @@ minetest.register_node("lzr_laser:barricade_on", {
})
local def_bomb_takable = {
description = S("Bomb"),
paramtype2 = "facedir",
_tt_help = S("Explodes when fuse gets ignited by laser").."\n"..
S("Destroys cracked blocks in a 3×3×3 area"),
tiles = {"lzr_laser_bomb_top.png", "lzr_laser_bomb_bottom.png", "lzr_laser_bomb_side.png"},
groups = { bomb = 1, breakable = 1, flammable = 1, laser_destroys = 3, rotatable = 2, takable = 1 },
sounds = lzr_sounds.node_sound_metal_defaults(),
_lzr_active = "lzr_laser:bomb_takable_on",
}
local def_bomb_takable_on = {
description = S("Ignited bomb"),
paramtype2 = "facedir",
_tt_help = S("Will explode soon").."\n"..
S("Destroys cracked blocks in a 3×3×3 area"),
light_source = 3,
tiles = {
{ name="lzr_laser_bomb_top_ignited.png", animation={
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.0,
},},
"lzr_laser_bomb_bottom.png",
"lzr_laser_bomb_side.png",
},
groups = { bomb = 2, breakable = 1, not_in_creative_inventory = 1, rotataobe = 3 },
sounds = lzr_sounds.node_sound_metal_defaults(),
on_construct = function(pos)
local handle = minetest.sound_play({name="lzr_laser_bomb_fuse", gain=0.5}, {pos=pos})
if handle then
local hash = minetest.hash_node_position(pos)
bomb_fuse_sounds[hash] = handle
end
-- TODO: Spawn fuse particles
local timer = minetest.get_node_timer(pos)
timer:start(BOMB_BURN_TIME)
end,
after_destruct = function(pos)
local hash = minetest.hash_node_position(pos)
if bomb_fuse_sounds[hash] then
minetest.sound_stop(bomb_fuse_sounds[hash])
bomb_fuse_sounds[hash] = nil
end
end,
on_timer = function(pos)
-- While lasers are frozen, ignited bomb won't explode
if lzr_laser.get_lasers_frozen() then
local timer = minetest.get_node_timer(pos)
timer:start(BOMB_BURN_TIME)
return
end
minetest.sound_play({name="lzr_laser_bomb_explode", gain=1.0}, {pos=pos}, true)
-- Remove bomb node
local bomb_node = minetest.get_node(pos)
minetest.remove_node(pos)
minetest.add_particlespawner({
amount = 16,
time = 0.001,
minpos = vector.subtract(pos, vector.new(0.5, 0.5, 0.5)),
maxpos = vector.add(pos, vector.new(0.5, 0.5, 0.5)),
minvel = vector.new(-2.5, -1.2, -2.5),
maxvel = vector.new(2.5, 1.2, 2.5),
minacc = vector.new(0, -lzr_globals.GRAVITY, 0),
maxacc = vector.new(0, -lzr_globals.GRAVITY, 0),
minsize = 1.5,
maxsize = 1.5,
node = bomb_node,
})
-- Spawn explosion particles
minetest.add_particle({
pos = pos,
velocity = vector.new(),
acceleration = vector.new(),
expirationtime = 0.4,
size = 10,
collisiondetection = false,
vertical = false,
texture = "lzr_laser_bomb_boom.png",
glow = minetest.LIGHT_MAX,
})
minetest.add_particlespawner({
amount = 64,
time = 0.5,
minpos = vector.subtract(pos, 1 / 2),
maxpos = vector.add(pos, 1 / 2),
minvel = {x = -4, y = -4, z = -4},
maxvel = {x = 4, y = 4, z = 4},
minacc = vector.new(),
maxacc = vector.new(),
minexptime = 0.5,
maxexptime = 1,
minsize = 3,
maxsize = 5,
texture = "lzr_laser_bomb_smoke.png",
})
-- destroy neighboring cracked nodes
local crackeds = minetest.find_nodes_in_area(vector.subtract(pos, vector.new(1,1,1)), vector.add(pos, vector.new(1,1,1)), "group:cracked")
for c=1, #crackeds do
local cpos = crackeds[c]
local node = minetest.get_node(cpos)
minetest.remove_node(cpos)
minetest.add_particlespawner({
amount = 16,
time = 0.001,
minpos = vector.subtract(cpos, vector.new(0.5, 0.5, 0.5)),
maxpos = vector.add(cpos, vector.new(0.5, 0.5, 0.5)),
minvel = vector.new(-0.5, -0.2, -0.5),
maxvel = vector.new(0.5, 0.2, 0.5),
minacc = vector.new(0, -lzr_globals.GRAVITY, 0),
maxacc = vector.new(0, -lzr_globals.GRAVITY, 0),
minsize = 1.5,
maxsize = 1.5,
node = node,
})
end
-- ignite bombs
local bombs = minetest.find_nodes_in_area(vector.subtract(pos, vector.new(1,1,1)), vector.add(pos, vector.new(1,1,1)), "group:bomb")
for b=1, #bombs do
local node = minetest.get_node(bombs[b])
if minetest.get_item_group(node.name, "bomb") == 1 then
local def = minetest.registered_nodes[node.name]
minetest.set_node(bombs[b], {name=def._lzr_active, param2=node.param2})
local timer = minetest.get_node_timer(bombs[b])
timer:start(BOMB_BURN_TIME_QUICK)
end
end
lzr_laser.full_laser_update_and_victory_check()
end,
drop = "",
_lzr_inactive = "lzr_laser:bomb_takable",
}
local def_bomb_fixed = table.copy(def_bomb_takable)
def_bomb_fixed.tiles = {"lzr_laser_bomb_top.png^lzr_laser_fixed.png", "lzr_laser_bomb_bottom.png^lzr_laser_fixed.png", "lzr_laser_bomb_side.png^lzr_laser_fixed.png"}
def_bomb_fixed.description = S("@1 (fixed)", S("Bomb"))
def_bomb_fixed.groups.takable = nil
def_bomb_fixed._lzr_active = "lzr_laser:bomb_on"
local def_bomb_fixed_on = table.copy(def_bomb_takable_on)
def_bomb_fixed_on.description = S("@1 (fixed)", S("Ignited Bomb"))
def_bomb_fixed_on.tiles = {
{ name="lzr_laser_bomb_top_ignited.png^lzr_laser_bomb_top_ignited_fixed.png", animation={
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.0,
},},
"lzr_laser_bomb_bottom.png^lzr_laser_fixed.png",
"lzr_laser_bomb_side.png^lzr_laser_fixed.png",
}
def_bomb_fixed_on._lzr_inactive = "lzr_laser:bomb"
minetest.register_node("lzr_laser:bomb", def_bomb_fixed)
minetest.register_node("lzr_laser:bomb_on", def_bomb_fixed_on)
minetest.register_node("lzr_laser:bomb_takable", def_bomb_takable)
minetest.register_node("lzr_laser:bomb_takable_on", def_bomb_takable_on)
-- Aliases for the pre-laser color era
minetest.register_alias("lzr_laser:mirror_takable_on", "lzr_laser:mirror_takable_on_1")
minetest.register_alias("lzr_laser:mirror_on", "lzr_laser:mirror_on_1")

View File

@ -43,6 +43,28 @@ lzr_laser.get_front_dir = function(param2)
return dir_input
end
lzr_laser.get_top_dir = function(param2)
if not param2 then
return
end
if (param2 >= 0 and param2 <= 3) then
return vector.new(0, 1, 0)
elseif (param2 >= 4 and param2 <= 7) then
return vector.new(0, 0, 1)
elseif (param2 >= 8 and param2 <= 11) then
return vector.new(0, 0, -1)
elseif (param2 >= 12 and param2 <= 15) then
return vector.new(1, 0, 0)
elseif (param2 >= 16 and param2 <= 19) then
return vector.new(-1, 0, 0)
elseif (param2 >= 20 and param2 <= 23) then
return vector.new(0, -1, 0)
else
return vector.new(0, 1, 0)
end
end
lzr_laser.get_barrel_axis = function(param2)
if not param2 then
return

View File

@ -59,17 +59,28 @@ function lzr_laser.add_laser(pos, dir, colorcode, varea, vdata, vdata_p2)
pos = vector.add(pos, dir)
return { "laser", {pos, dir, colorcode}}
-- Burning block
elseif ld == 2 then
elseif ld == 2 or ld == 3 then
local def = minetest.registered_nodes[nodename]
local active = def._lzr_active
if active then
local burn = false
if ld == 2 then
burn = true
-- Gets ignited from top only (bomb)
elseif ld == 3 then
local top_dir = lzr_laser.get_top_dir(param2)
local inverted_dir = vector.multiply(dir, -1)
if vector.equals(inverted_dir, top_dir) then
burn = true
end
end
-- Only burn in-game (for editor convenience)
if lzr_gamestate.get_state() == lzr_gamestate.LEVEL then
if burn and lzr_gamestate.get_state() == lzr_gamestate.LEVEL then
vdata[vi] = minetest.get_content_id(active)
table.insert(burning_cache, pos)
end
else
minetest.log("error", "[lzr_laser] Node definition of "..nodename.." has laser_destroys=2 but no _lzr_active")
minetest.log("error", "[lzr_laser] Node definition of "..nodename.." has laser_destroys="..ld.." but no _lzr_active")
end
-- Laser collides
return false

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B