Make barricade burn on laser contact
10
CREDITS.md
@ -10,8 +10,9 @@ External mods used:
|
|||||||
---
|
---
|
||||||
|
|
||||||
Textures:
|
Textures:
|
||||||
- Water, wood, tree, stone, tools, hand, gold block, ship lightbox, player textures, crates, seaweed, purple coral, crab grass come from “PixelBOX” texture pack by jp (CC0)
|
- Water, wood, tree, stone, tools, hand, gold block, ship lightbox, player textures, crates, seaweed, purple coral, crab grass, fire come from “PixelBOX” texture pack by jp (CC0)
|
||||||
- Textures in `lzr_decor` mod made by jp (CC0)
|
- Textures in `lzr_decor` mod made by jp (CC0)
|
||||||
|
- Barricade made by jp (CC0)
|
||||||
- Crosshair, wieldhand, `smoke_puff.png`: trivial textures by Wuzzy (CC0)
|
- Crosshair, wieldhand, `smoke_puff.png`: trivial textures by Wuzzy (CC0)
|
||||||
- Emitter, detector textures: Derivate works of xdecor textures by jp (CC0)
|
- Emitter, detector textures: Derivate works of xdecor textures by jp (CC0)
|
||||||
- Mirror textures: by Wuzzy (CC0)
|
- Mirror textures: by Wuzzy (CC0)
|
||||||
@ -84,6 +85,13 @@ Sounds:
|
|||||||
- by Fourier <https://opengameart.org/content/forward-button-press-ui-sound>
|
- by Fourier <https://opengameart.org/content/forward-button-press-ui-sound>
|
||||||
- Edit by Wuzzy (shortened)
|
- Edit by Wuzzy (shortened)
|
||||||
- License: CC BY 3.0
|
- License: CC BY 3.0
|
||||||
|
- `lzr_laser_quickburn.*.ogg`:
|
||||||
|
- Original by florianreichelt <https://freesound.org/people/florianreichelt/sounds/563012/>
|
||||||
|
- Shortened for gameplay reasons
|
||||||
|
- License: CC0
|
||||||
|
- `lzr_laser_barricade_break.ogg`:
|
||||||
|
- By kevinkace <https://freesound.org/people/kevinkace/sounds/66780/>
|
||||||
|
- License: CC0
|
||||||
- `lzr_sounds_footstep_stone.*.ogg`, `default_dirt_footstep.*.ogg`, `lzr_sounds_footstep_leaves.*.ogg`, `lzr_sounds_dug_grass.*.ogg`:
|
- `lzr_sounds_footstep_stone.*.ogg`, `default_dirt_footstep.*.ogg`, `lzr_sounds_footstep_leaves.*.ogg`, `lzr_sounds_dug_grass.*.ogg`:
|
||||||
- by Wuzzy
|
- by Wuzzy
|
||||||
- License: MIT License
|
- License: MIT License
|
||||||
|
@ -45,15 +45,6 @@ register_pane("wood_frame", S("Wood Frame"), {
|
|||||||
groups = {breakable = 1, rotatable = 3, pane = 1},
|
groups = {breakable = 1, rotatable = 3, pane = 1},
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("lzr_decor:barricade", {
|
|
||||||
description = S("Barricade"),
|
|
||||||
drawtype = "plantlike",
|
|
||||||
paramtype = "light",
|
|
||||||
inventory_image = "xdecor_baricade.png",
|
|
||||||
tiles = {"xdecor_baricade.png"},
|
|
||||||
groups = {breakable = 1},
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node("lzr_decor:bonfire", {
|
minetest.register_node("lzr_decor:bonfire", {
|
||||||
description = S("Bonfire"),
|
description = S("Bonfire"),
|
||||||
walkable = false,
|
walkable = false,
|
||||||
|
@ -32,6 +32,8 @@ local mirror_out = {
|
|||||||
[23] = {0,0,1},
|
[23] = {0,0,1},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local movement_gravity = tonumber(minetest.settings:get("movement_gravity")) or 9.81
|
||||||
|
|
||||||
lzr_laser.get_detector_dir = function(param2)
|
lzr_laser.get_detector_dir = function(param2)
|
||||||
local dir_input = minetest.facedir_to_dir(param2)
|
local dir_input = minetest.facedir_to_dir(param2)
|
||||||
if not dir_input then
|
if not dir_input then
|
||||||
@ -132,6 +134,29 @@ local after_rotate = function()
|
|||||||
full_update()
|
full_update()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local element_can_dig = function()
|
||||||
|
return lzr_gamestate.get_state() ~= lzr_gamestate.LEVEL_COMPLETE
|
||||||
|
end
|
||||||
|
local element_on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
if lzr_gamestate.get_state() == lzr_gamestate.LEVEL_COMPLETE then
|
||||||
|
-- Prevent node placement when in 'level complete' state
|
||||||
|
return itemstack
|
||||||
|
else
|
||||||
|
-- node's on_rightclick action takes precedence
|
||||||
|
if pointed_thing.type == "node" and placer then
|
||||||
|
local node = minetest.get_node(pointed_thing.under)
|
||||||
|
local def = minetest.registered_nodes[node.name]
|
||||||
|
local sneak = placer:get_player_control().sneak
|
||||||
|
if def and def.on_rightclick and not sneak then
|
||||||
|
def.on_rightclick(pointed_thing.under, node, placer, itemstack, pointed_thing)
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Default node placement behavior
|
||||||
|
return minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local register_element = function(subname, def, options)
|
local register_element = function(subname, def, options)
|
||||||
local def_core = table.copy(def)
|
local def_core = table.copy(def)
|
||||||
if not options then options = {} end
|
if not options then options = {} end
|
||||||
@ -153,28 +178,8 @@ local register_element = function(subname, def, options)
|
|||||||
end
|
end
|
||||||
def_core.groups.breakable = 1
|
def_core.groups.breakable = 1
|
||||||
def_core.groups[subname] = 1
|
def_core.groups[subname] = 1
|
||||||
def_core.can_dig = function()
|
def_core.can_dig = element_can_dig
|
||||||
return lzr_gamestate.get_state() ~= lzr_gamestate.LEVEL_COMPLETE
|
def_core.on_place = element_on_place
|
||||||
end
|
|
||||||
def_core.on_place = function(itemstack, placer, pointed_thing)
|
|
||||||
if lzr_gamestate.get_state() == lzr_gamestate.LEVEL_COMPLETE then
|
|
||||||
-- Prevent node placement when in 'level complete' state
|
|
||||||
return itemstack
|
|
||||||
else
|
|
||||||
-- node's on_rightclick action takes precedence
|
|
||||||
if pointed_thing.type == "node" and placer then
|
|
||||||
local node = minetest.get_node(pointed_thing.under)
|
|
||||||
local def = minetest.registered_nodes[node.name]
|
|
||||||
local sneak = placer:get_player_control().sneak
|
|
||||||
if def and def.on_rightclick and not sneak then
|
|
||||||
def.on_rightclick(pointed_thing.under, node, placer, itemstack, pointed_thing)
|
|
||||||
return itemstack
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Default node placement behavior
|
|
||||||
return minetest.item_place_node(itemstack, placer, pointed_thing)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_node("lzr_laser:"..subname, def_core)
|
minetest.register_node("lzr_laser:"..subname, def_core)
|
||||||
|
|
||||||
@ -439,3 +444,78 @@ register_element("detector", {
|
|||||||
sounds = lzr_sounds.node_sound_wood_defaults(),
|
sounds = lzr_sounds.node_sound_wood_defaults(),
|
||||||
}, { allow_take = true, is_detector = true })
|
}, { allow_take = true, is_detector = true })
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_node("lzr_laser:barricade", {
|
||||||
|
description = S("Barricade"),
|
||||||
|
drawtype = "mesh",
|
||||||
|
mesh = "lzr_laser_burning.obj",
|
||||||
|
paramtype = "light",
|
||||||
|
inventory_image = "xdecor_baricade.png",
|
||||||
|
wield_image = "xdecor_baricade.png",
|
||||||
|
tiles = {"blank.png","xdecor_baricade.png"},
|
||||||
|
use_texture_alpha = "clip",
|
||||||
|
groups = { breakable = 1, laser_destroys = 2 },
|
||||||
|
sounds = lzr_sounds.node_sound_wood_defaults({
|
||||||
|
dug = {name="lzr_laser_barricade_break", gain=1.0},
|
||||||
|
}),
|
||||||
|
on_place = element_on_place,
|
||||||
|
can_dig = element_can_dig,
|
||||||
|
_lzr_active = "lzr_laser:barricade_on",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("lzr_laser:barricade_on", {
|
||||||
|
description = S("Burning Barricade"),
|
||||||
|
drawtype = "mesh",
|
||||||
|
paramtype = "light",
|
||||||
|
light_source = 12,
|
||||||
|
mesh = "lzr_laser_burning.obj",
|
||||||
|
inventory_image = "lzr_laser_baricade_burning.png",
|
||||||
|
wield_image = "lzr_laser_baricade_burning.png",
|
||||||
|
use_texture_alpha = "clip",
|
||||||
|
tiles = {
|
||||||
|
{ name="fire_basic_flame_animated.png", animation={
|
||||||
|
type = "vertical_frames",
|
||||||
|
aspect_w = 16,
|
||||||
|
aspect_h = 16,
|
||||||
|
length = 1.0,
|
||||||
|
},},
|
||||||
|
{ name="lzr_laser_baricade_burning_animated.png", animation={
|
||||||
|
type = "vertical_frames",
|
||||||
|
aspect_w = 16,
|
||||||
|
aspect_h = 16,
|
||||||
|
length = 1.0,
|
||||||
|
},},
|
||||||
|
},
|
||||||
|
groups = { breakable = 1, not_in_creative_inventory = 1 },
|
||||||
|
sounds = lzr_sounds.node_sound_wood_defaults({
|
||||||
|
dug = {name="lzr_laser_barricade_break", gain=1.0},
|
||||||
|
}),
|
||||||
|
on_timer = function(pos)
|
||||||
|
-- spawn a few particles for the removed node
|
||||||
|
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(-0.5, -0.5, -0.5),
|
||||||
|
maxvel = vector.new(0.5, 0.2, 0.5),
|
||||||
|
minacc = vector.new(0, -movement_gravity, 0),
|
||||||
|
maxacc = vector.new(0, -movement_gravity, 0),
|
||||||
|
minsize = 0.1,
|
||||||
|
maxsize = 0.5,
|
||||||
|
node = {name="lzr_laser:barricade"},
|
||||||
|
})
|
||||||
|
-- Play randomly-pitched break sound
|
||||||
|
local pitch = 1.0+math.random(-100, 100)*0.001 -- 0.9..1.1
|
||||||
|
minetest.sound_play({name="lzr_laser_barricade_break", gain=1.0}, {gain=1.0, pitch=pitch, pos=pos}, true)
|
||||||
|
-- remove node
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
full_update()
|
||||||
|
end,
|
||||||
|
drop = "",
|
||||||
|
on_place = element_on_place,
|
||||||
|
can_dig = element_can_dig,
|
||||||
|
_lzr_inactive = "lzr_laser:barricade",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
BIN
mods/lzr_laser/models/lzr_laser_burning.blend
Normal file
44
mods/lzr_laser/models/lzr_laser_burning.obj
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Blender v3.1.0 Alpha OBJ File: 'lzr_plants_burning.blend'
|
||||||
|
# www.blender.org
|
||||||
|
mtllib lzr_plants_burning.mtl
|
||||||
|
v 0.495000 0.500000 0.495000
|
||||||
|
v 0.495000 -0.500000 0.495000
|
||||||
|
v -0.495000 0.500000 0.495000
|
||||||
|
v -0.495000 -0.500000 0.495000
|
||||||
|
v 0.495000 0.500000 -0.495000
|
||||||
|
v 0.495000 -0.500000 -0.495000
|
||||||
|
v -0.495000 0.500000 -0.495000
|
||||||
|
v -0.495000 -0.500000 -0.495000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vn -1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 -1.0000
|
||||||
|
vn 0.0000 0.0000 1.0000
|
||||||
|
vn 1.0000 0.0000 0.0000
|
||||||
|
vn -0.7071 0.0000 -0.7071
|
||||||
|
vn -0.7071 0.0000 0.7071
|
||||||
|
g Fire_Cube_Fire
|
||||||
|
usemtl Fire
|
||||||
|
s off
|
||||||
|
f 4/1/1 3/2/1 7/3/1 8/4/1
|
||||||
|
f 8/5/2 7/6/2 5/7/2 6/8/2
|
||||||
|
f 2/9/3 1/10/3 3/11/3 4/12/3
|
||||||
|
f 6/13/4 5/14/4 1/15/4 2/16/4
|
||||||
|
g Fire_Cube_Object
|
||||||
|
usemtl Object
|
||||||
|
f 4/1/5 3/2/5 5/7/5 6/8/5
|
||||||
|
f 2/9/6 1/10/6 7/3/6 8/4/6
|
@ -1,6 +1,9 @@
|
|||||||
-- Max. number of steps in the laser travel algorithm
|
-- Max. number of steps in the laser travel algorithm
|
||||||
local MAX_LASER_ITERATIONS = 10000
|
local MAX_LASER_ITERATIONS = 10000
|
||||||
|
|
||||||
|
-- TODO: Don't use this variable, instead transport it between functions
|
||||||
|
local burning_cache = {}
|
||||||
|
|
||||||
-- Add a laser node to pos with the direction `dir`.
|
-- Add a laser node to pos with the direction `dir`.
|
||||||
-- Dir is a direction vector, and only one direction must be set
|
-- Dir is a direction vector, and only one direction must be set
|
||||||
function lzr_laser.add_laser(pos, dir, varea, vdata)
|
function lzr_laser.add_laser(pos, dir, varea, vdata)
|
||||||
@ -13,13 +16,24 @@ function lzr_laser.add_laser(pos, dir, varea, vdata)
|
|||||||
local vi = varea:indexp(pos)
|
local vi = varea:indexp(pos)
|
||||||
local content_id = vdata[vi]
|
local content_id = vdata[vi]
|
||||||
local nodename = minetest.get_name_from_content_id(content_id)
|
local nodename = minetest.get_name_from_content_id(content_id)
|
||||||
|
local ld = minetest.get_item_group(nodename, "laser_destroys")
|
||||||
-- Laser through air or destroyable block
|
-- Laser through air or destroyable block
|
||||||
if content_id == minetest.CONTENT_AIR or minetest.get_item_group(nodename, "laser_destroys") > 0 then
|
if content_id == minetest.CONTENT_AIR or ld == 1 then
|
||||||
local dirs = lzr_laser.vector_to_dirs(dir)
|
local dirs = lzr_laser.vector_to_dirs(dir)
|
||||||
local dirstring = lzr_laser.dirs_to_dirstring(dirs)
|
local dirstring = lzr_laser.dirs_to_dirstring(dirs)
|
||||||
vdata[vi] = minetest.get_content_id("lzr_laser:laser_"..dirstring)
|
vdata[vi] = minetest.get_content_id("lzr_laser:laser_"..dirstring)
|
||||||
pos = vector.add(pos, dir)
|
pos = vector.add(pos, dir)
|
||||||
return {{pos, dir}}
|
return {{pos, dir}}
|
||||||
|
elseif ld == 2 then
|
||||||
|
local def = minetest.registered_nodes[nodename]
|
||||||
|
local active = def._lzr_active
|
||||||
|
if active then
|
||||||
|
vdata[vi] = minetest.get_content_id(active)
|
||||||
|
table.insert(burning_cache, pos)
|
||||||
|
else
|
||||||
|
minetest.log("error", "[lzr_laser] Node definition of "..nodename.." has laser_destroys=2 but no _lzr_active")
|
||||||
|
end
|
||||||
|
return false
|
||||||
-- Laser through laser (laser intersection)
|
-- Laser through laser (laser intersection)
|
||||||
elseif minetest.get_item_group(nodename, "laser") > 0 then
|
elseif minetest.get_item_group(nodename, "laser") > 0 then
|
||||||
local dirnum = minetest.get_item_group(nodename, "laser")
|
local dirnum = minetest.get_item_group(nodename, "laser")
|
||||||
@ -244,6 +258,8 @@ end
|
|||||||
function lzr_laser.full_laser_update(pos1, pos2)
|
function lzr_laser.full_laser_update(pos1, pos2)
|
||||||
local benchmark_time_1 = minetest.get_us_time()
|
local benchmark_time_1 = minetest.get_us_time()
|
||||||
|
|
||||||
|
burning_cache = {}
|
||||||
|
|
||||||
local vmanip = minetest.get_voxel_manip(pos1, pos2)
|
local vmanip = minetest.get_voxel_manip(pos1, pos2)
|
||||||
local vpos1, vpos2 = vmanip:get_emerged_area()
|
local vpos1, vpos2 = vmanip:get_emerged_area()
|
||||||
local varea = VoxelArea:new({MinEdge = vpos1, MaxEdge = vpos2})
|
local varea = VoxelArea:new({MinEdge = vpos1, MaxEdge = vpos2})
|
||||||
@ -257,6 +273,13 @@ function lzr_laser.full_laser_update(pos1, pos2)
|
|||||||
vmanip:set_param2_data(vdata_p2)
|
vmanip:set_param2_data(vdata_p2)
|
||||||
vmanip:write_to_map()
|
vmanip:write_to_map()
|
||||||
|
|
||||||
|
for b=1, #burning_cache do
|
||||||
|
local timer = minetest.get_node_timer(burning_cache[b])
|
||||||
|
minetest.sound_play({name="lzr_laser_quickburn", gain=1.0}, {pos=burning_cache[b]}, true)
|
||||||
|
timer:start(1)
|
||||||
|
end
|
||||||
|
burning_cache = {}
|
||||||
|
|
||||||
-- Print benchmark time
|
-- Print benchmark time
|
||||||
local benchmark_time_2 = minetest.get_us_time()
|
local benchmark_time_2 = minetest.get_us_time()
|
||||||
local diff = benchmark_time_2 - benchmark_time_1
|
local diff = benchmark_time_2 - benchmark_time_1
|
||||||
|
BIN
mods/lzr_laser/sounds/lzr_laser_barricade_break.ogg
Normal file
BIN
mods/lzr_laser/sounds/lzr_laser_quickburn.1.ogg
Normal file
BIN
mods/lzr_laser/sounds/lzr_laser_quickburn.2.ogg
Normal file
BIN
mods/lzr_laser/sounds/lzr_laser_quickburn.3.ogg
Normal file
BIN
mods/lzr_laser/textures/fire_basic_flame.png
Normal file
After Width: | Height: | Size: 256 B |
BIN
mods/lzr_laser/textures/fire_basic_flame_animated.png
Normal file
After Width: | Height: | Size: 913 B |
BIN
mods/lzr_laser/textures/lzr_laser_baricade_burning.png
Normal file
After Width: | Height: | Size: 304 B |
BIN
mods/lzr_laser/textures/lzr_laser_baricade_burning_animated.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 258 B After Width: | Height: | Size: 258 B |
BIN
mods/lzr_plants/textures/xdecor_baricade.png
Normal file
After Width: | Height: | Size: 258 B |