diff --git a/CREDITS.md b/CREDITS.md index f84259ea..ceb74105 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -153,6 +153,10 @@ All levels by Wuzzy. - by MAJ061785 - A shortened version of the original sound is used for this game - License: CC BY 3.0 +- `lzr_treasure_chest_lock_regen.ogg`: + - Heavily distorted derivative work of `lzr_treasure_chest_lock_break.ogg` + - By Wuzzy and MAJ061785 + - License: CC BY 3.0 - `lzr_laser_detector_activate.ogg` - derivative work from sound by Artninja - License: CC BY 4.0 diff --git a/mods/lzr_treasure/init.lua b/mods/lzr_treasure/init.lua index 3343abc7..051ae96f 100644 --- a/mods/lzr_treasure/init.lua +++ b/mods/lzr_treasure/init.lua @@ -18,15 +18,102 @@ local register_chest = function(id, def) local sound_open = def.sound_open or "lzr_treasure_chest_open" local sound_open_fail = def.sound_open_fail or "lzr_treasure_chest_open_fail" local sound_lock_break = def.sound_lock_break or "lzr_treasure_chest_lock_break" + local sound_lock_regen = def.sound_lock_regen or "lzr_treasure_chest_lock_regen" + + local lock_chest = function(pos, node, check_gamestate) + local add_lock = true + if check_gamestate and lzr_gamestate.get_state() ~= lzr_gamestate.LEVEL and not def.regen_lock then + add_lock = false + end + if add_lock then + minetest.swap_node(pos, {name="lzr_treasure:chest_"..id.."_locked", param2=node.param2}) + + minetest.after(0.1, function() + + minetest.sound_play({name=sound_lock_regen, gain=0.8}, {pos=pos}, true) + + local dir = minetest.facedir_to_dir(node.param2) + local w = 3/16 + local k = 9/16 + local l = 8/16 + local minoff, maxoff + if dir.x > 0 then + minoff = vector.new(-k, -w, -w) + maxoff = vector.new(-l, w, w) + elseif dir.x < 0 then + minoff = vector.new(l, -w, -w) + maxoff = vector.new(k, w, w) + elseif dir.z > 0 then + minoff = vector.new(-w, -w, -k) + maxoff = vector.new(w, w, -l) + elseif dir.z < 0 then + minoff = vector.new(-w, -w, l) + maxoff = vector.new(w, w, k) + end + local avgoff = vector.new() + avgoff.x = (minoff.x + maxoff.x) / 2 + avgoff.y = (minoff.y + maxoff.y) / 2 + avgoff.z = (minoff.z + maxoff.z) / 2 + if minoff then + minetest.add_particlespawner({ + amount = 42, + time = 0.001, + minpos = vector.add(pos, minoff), + maxpos = vector.add(pos, maxoff), + minsize = 0.5, + maxsize = 0.5, + minexptime = 1.60, + maxexptime = 1.65, + radius = { + min = 0.4, + max = 0.5, + bias = 0.5, + }, + attract = { + kind = "point", + strength = 4, + origin = vector.add(pos, avgoff), + }, + texture = "lzr_treasure_particle_lock.png", + }) + else + minetest.log("error", "[lzr_treasure] Could not find correct position to spawn treasure chest lock particles") + end + end) + end + end + + local on_toggle_unlocked + local g_unlocked_receiver + local g_unlocked_element + local g_locked_element + local g_unlocked_nici + local tt_help_unlocked = S("Contains a gold block") + local tt_help_locked = S("Contains a gold block") + local element_group = "chest_element" + if def.regen_lock then + on_toggle_unlocked = function(pos, node) + lock_chest(pos, node, true) + end + g_unlocked_receiver = 1 + g_unlocked_element = 2 + g_locked_element = 1 + -- Hide unlocked chest from creative inventory when the lock + -- is able to regenerate to enforce some consistency in the editor. + g_unlocked_nici = 1 + tt_help_unlocked = tt_help_unlocked .. "\n"..S("Gets locked when triggered off") + tt_help_locked = tt_help_locked .. "\n"..S("Lock breaks when triggered on, but it re-appears when triggered off") + else + tt_help_locked = tt_help_locked .. "\n"..S("Lock breaks when triggered on") + end minetest.register_node("lzr_treasure:chest_"..id.."_unlocked", { description = def.description_unlocked, - _tt_help = S("Contains a gold block"), + _tt_help = tt_help_unlocked, paramtype2 = "facedir", tiles = { def.tile_top, def.tile_bottom, def.tile_side, def.tile_side, def.tile_side, def.tile_front }, - groups = { breakable = 1, chest = 1, chest_closed = 1, rotatable = 3 }, + groups = { breakable = 1, chest = 1, chest_closed = 1, rotatable = 3, receiver = g_unlocked_receiver, chest_element = g_unlocked_element, not_in_creative_inventory = g_unlocked_nici }, sounds = def.node_sounds, - on_rotate = screwdriver.rotate_simple, on_punch = function(pos, node, puncher) if lzr_gamestate.get_state() ~= lzr_gamestate.LEVEL then return @@ -49,15 +136,20 @@ local register_chest = function(id, def) victory_job = nil end) end, + after_place_node = lzr_laser.trigger_after_place_node, + after_dig_node = lzr_laser.trigger_after_dig_node, + on_rotate = screwdriver.rotate_simple, + _lzr_on_toggle = on_toggle_unlocked, + _lzr_element_group = element_group, }) local unlock_chest = function(pos, node, check_gamestate) local break_lock = true - if check_gamestate and lzr_gamestate.get_state() ~= lzr_gamestate.LEVEL then + if check_gamestate and lzr_gamestate.get_state() ~= lzr_gamestate.LEVEL and not def.regen_lock then break_lock = false end if break_lock then - minetest.set_node(pos, {name="lzr_treasure:chest_"..id.."_unlocked", param2=node.param2}) + minetest.swap_node(pos, {name="lzr_treasure:chest_"..id.."_unlocked", param2=node.param2}) end minetest.after(0.1, function() @@ -106,13 +198,11 @@ local register_chest = function(id, def) minetest.register_node("lzr_treasure:chest_"..id.."_locked", { description = def.description_locked, - _tt_help = S("Contains a gold block").."\n".. - S("Lock breaks when all detectors in the level are active"), + _tt_help = tt_help_locked, paramtype2 = "facedir", tiles = { def.tile_top, def.tile_bottom, def.tile_side, def.tile_side, def.tile_side, def.tile_front_lock }, - groups = { breakable = 1, chest = 2, chest_closed = 1, rotatable = 3, receiver = 1 }, + groups = { breakable = 1, chest = 2, chest_closed = 1, rotatable = 3, receiver = 1, chest_element = g_locked_element }, sounds = def.node_sounds, - on_rotate = screwdriver.rotate_simple, on_punch = function(pos, node, puncher) if lzr_gamestate.get_state() ~= lzr_gamestate.LEVEL then return @@ -121,6 +211,7 @@ local register_chest = function(id, def) end, after_place_node = lzr_laser.trigger_after_place_node, after_dig_node = lzr_laser.trigger_after_dig_node, + on_rotate = screwdriver.rotate_simple, -- Unlock chest, always _lzr_unlock = function(pos, node) unlock_chest(pos, node) @@ -129,6 +220,7 @@ local register_chest = function(id, def) _lzr_on_toggle = function(pos, node) unlock_chest(pos, node, true) end, + _lzr_element_group = element_group, }) -- Open empty chest (is laser-compatible) @@ -259,6 +351,8 @@ register_chest("dark", { tile_front = "lzr_treasure_dark_chest_front.png", tile_front_lock = "lzr_treasure_dark_chest_lock.png", node_sounds = lzr_sounds.node_sound_stone_defaults(), + -- The dark chest can regenerate its lock when toggled off + regen_lock = true, }) minetest.register_alias("lzr_treasure:chest_wood_open", "lzr_treasure:chest_wood_open_fixed") diff --git a/mods/lzr_treasure/sounds/lzr_treasure_chest_lock_regen.ogg b/mods/lzr_treasure/sounds/lzr_treasure_chest_lock_regen.ogg new file mode 100644 index 00000000..d66f05c7 Binary files /dev/null and b/mods/lzr_treasure/sounds/lzr_treasure_chest_lock_regen.ogg differ