diff --git a/df_caverns/underworld.lua b/df_caverns/underworld.lua index c0708c4..6f8d3fe 100644 --- a/df_caverns/underworld.lua +++ b/df_caverns/underworld.lua @@ -224,11 +224,8 @@ local get_pit = function(pos) local radius = variance_multiplier * (radius_pit_max - 15) + 15 local variance = radius_pit_variance/2 + radius_pit_variance*variance_multiplier/2 local depth = math.random(plasma_depth_min, plasma_depth_max) - - local shaft_seed = math.random() - local shaft_location = corner_xz math.randomseed(next_seed) - return {location = location, radius = radius, variance = variance, depth = depth}, {seed = shaft_seed, location = shaft_location} + return {location = location, radius = radius, variance = variance, depth = depth} end local perlin_pit = { @@ -248,10 +245,9 @@ minetest.register_chatcommand("find_pit", { decription = "find a nearby glowing pit", func = function(name, param) local player = minetest.get_player_by_name(name) - local pit, shaft = get_pit(player:get_pos()) + local pit = get_pit(player:get_pos()) if pit then minetest.chat_send_player(name, "Pit location: x=" .. math.floor(pit.location.x) .. " z=" .. math.floor(pit.location.z)) - minetest.chat_send_player(name, "Shaft location: x=" .. math.floor(shaft.location.x) .. " z=" .. math.floor(shaft.location.z)) end end, }) @@ -273,7 +269,7 @@ minetest.register_on_generated(function(minp, maxp, seed) local nvals_wave = mapgen_helper.perlin2d("df_caverns:underworld_wave", emin, emax, perlin_wave) --cave noise for structure local nvals_zone = mapgen_helper.perlin2d("df_caverns:underworld_zone", emin, emax, perlin_zone) --building zones - local pit, shaft = get_pit(minp) + local pit = get_pit(minp) --minetest.chat_send_all(minetest.pos_to_string(pit.location)) local buildings = get_buildings(emin, emax, nvals_zone) @@ -300,7 +296,7 @@ minetest.register_on_generated(function(minp, maxp, seed) then -- there's a pit nearby if pit_uninitialized then - nvals_pit, area_pit = mapgen_helper.perlin3d("df_cavern:perlin_cave", minp, maxp, perlin_pit) -- determine which areas are spongey with warrens + nvals_pit, area_pit = mapgen_helper.perlin3d("df_cavern:perlin_cave", minp, maxp, perlin_pit) pit_uninitialized = false end local pit_value = nvals_pit[area_pit:index(x,y,z)] * pit.variance @@ -401,7 +397,7 @@ minetest.register_on_generated(function(minp, maxp, seed) -- puzzle seal local puzzle_seal = nil - if pit_uninitialized and minp.x == shaft.location.x and minp.z == shaft.location.z then + if pit_uninitialized and math.random() < 0.025 then local index2d = mapgen_helper.index2d(emin, emax, minp.x + 3, minp.z + 3) local abs_cave = math.abs(nvals_cave[index2d]) -- range is from 0 to approximately 2, with 0 being connected and 2s being islands local wave = nvals_wave[index2d] * wave_mult @@ -429,7 +425,9 @@ minetest.register_on_generated(function(minp, maxp, seed) if puzzle_seal ~= nil then minetest.place_schematic({x=puzzle_seal.x-3, y=puzzle_seal.y, z=puzzle_seal.z-3}, df_underworld_items.seal_temple_schem, 0, {}, true) - minetest.set_node(puzzle_seal, {name="df_underworld_items:puzzle_seal"}) + local node_name = minetest.get_node(puzzle_seal).name + local node_def = minetest.registered_nodes[node_name] + node_def.on_construct(puzzle_seal) end if bones_loot_path then diff --git a/df_underworld_items/puzzle_seal.lua b/df_underworld_items/puzzle_seal.lua index 62615d5..c14e558 100644 --- a/df_underworld_items/puzzle_seal.lua +++ b/df_underworld_items/puzzle_seal.lua @@ -4,23 +4,148 @@ local S, NS = dofile(MP.."/intllib.lua") local invulnerable = df_underworld_items.config.invulnerable_slade and not minetest.settings:get_bool("creative_mode") -local get_formspec = function(pos, completion) - completion = completion or 0.5 +-- Ensures that the node is functioning correctly +local ensure_meta = function(pos) + local meta = minetest.get_meta(pos) + if not meta:contains("key") then + local inv = meta:get_inventory() + inv:set_size("main", 8) + local next_seed = math.random() * 2^21 + math.randomseed(pos.x + pos.z^16) + -- Key is consistent with location + local key = {math.random(0,7), math.random(0,7), math.random(0,7), math.random(0,7), math.random(0,7), math.random(0,7),math.random(0,7), math.random(0,7)} + math.randomseed(next_seed) + meta:set_string("key", minetest.serialize(key)) + meta:mark_as_private("key") + end + + local timer = minetest.get_node_timer(pos) + if not timer:is_started() then + timer:start(4) + end +end + +local colour_groups = { + "color_black", -- 0 + "color_red", -- 1 + "color_orange", -- 2 + "color_yellow", -- 3 + "color_green", -- 4 + "color_blue", -- 5 + "color_violet", -- 6 + "color_white"} -- 7 + +local test_key = function(pos) + local meta = minetest.get_meta(pos) + if not meta:contains("key") then + return false + end + + local keystring = meta:get_string("key") + local key = minetest.deserialize(keystring) + local inv = meta:get_inventory() + + for offset = 0, 7 do + local valid + for i = 0, 7 do + valid = true + local keyval = (i + offset) % 8 + 1 + local key_group = colour_groups[key[keyval]+1] + local item = inv:get_stack("main", i+1) + if minetest.get_item_group(item:get_name(), key_group) == 0 then + valid = false + break + end + end + if valid then + meta:set_int("unlocked", 1) + return true + end + end + meta:set_int("unlocked", 0) + return false +end + +local formspec_prefix = "df_underworld_items_puzzle_seal:" +local get_formspec = function(pos, unlocked) local formspec = - "size[10,10]" - .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;1,1;3,3;]" - .."container[5,0.5]" - .."box[0,0;1,5;#0A0000]box[0.1,0.1;0.8,4.8;#000000]box[0.1," .. 0.1 + 4.8*completion ..";0.8,".. 4.8*completion ..";#FFCC22]" + "size[8,8]" + .."container[2.25,0]" + .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0.25,0.25;1,1;0]" + .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;1.25,0;1,1;1]" + .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;2.25,0.25;1,1;2]" + .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;2.5,1.25;1,1;3]" + .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;2.25,2.25;1,1;4]" + .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;1.25,2.5;1,1;5]" + .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0.25,2.25;1,1;6]" + .."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,1.25;1,1;7]" + if unlocked then + formspec = formspec .. "image_button[1.25,1.25;1,1;dfcaverns_seal.png;open;"..S("Turn").."]" + else + formspec = formspec .. "image[1.25,1.25;1,1;dfcaverns_seal.png]" + end + + formspec = formspec .."container_end[]" - .."container[1,5.75]list[current_player;main;0,0;8,1;]listring[]" +-- .."container[5,0.5]" +-- .."box[0,0;1,5;#0A0000]box[0.1,0.1;0.8,4.8;#000000]box[0.1," .. 0.1 + 4.8*completion ..";0.8,".. 4.8*completion ..";#FFCC22]" +-- .."container_end[]" + .."container[0,4]list[current_player;main;0,0;8,1;]listring[]" .."list[current_player;main;0,1.25;8,3;8]container_end[]" return formspec end +local refresh_formspec = function(pos, player) + local player_name = player:get_player_name() + local unlocked = test_key(pos) + local formspec = get_formspec(pos, unlocked) + minetest.show_formspec(player_name, formspec_prefix..minetest.pos_to_string(pos), formspec) +end -local ensure_inventory = function(pos) +local show_key = function(pos, index) + minetest.sound_play("dfcaverns_seal_key", { + pos = pos, + gain = 0.125, + max_hear_distance = 16, + }) local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - inv:set_size("main", 3*3) + local keystring = meta:get_string("key") + local key = minetest.deserialize(keystring) + --minetest.chat_send_all(keystring) + local minpos = vector.add(pos, {x=-1, y=1, z=-1}) + local maxpos = vector.add(pos, {x=1, y=3, z=1}) + minetest.add_particlespawner({ + amount = key[index+1], + time = 0.5, + minpos = minpos, + maxpos = maxpos, + minvel = {x=-0.25, y=0, z=-0.25}, + maxvel = {x=0.25, y=0.25, z=0.25}, + minacc = {x=0, y=0, z=0}, + maxacc = {x=0, y=0, z=0}, + minexptime = 3, + maxexptime = 3, + minsize = 1, + maxsize = 1, + texture = "dfcaverns_glow_amethyst.png", + glow = 8, + }) +end + +local show_unlocked = function(pos) + -- Plays globally. This is deliberate. + minetest.sound_play("dfcaverns_seal_unlocked", { + gain = 1.0, + pitch = 1.0, + }) + minetest.add_particle({ + pos = pos, + velocity = {x=0, y=1, z=0}, + expirationtime = 30, + size = 20, + texture = "dfcaverns_seal.png^[invert:rgb^[brighten", + glow = 15, +-- vertical = true, + }) end local puzzle_seal_def = { @@ -32,7 +157,7 @@ local puzzle_seal_def = { tiles = {"dfcaverns_slade_block.png", "dfcaverns_slade_block.png^dfcaverns_seal.png", "dfcaverns_slade_block.png"}, paramtype = "light", paramtype2 = "facedir", - light_source = 12, + light_source = 8, groups = {stone=1, level=3, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1, not_in_creative_inventory=1}, sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }), selection_box = { @@ -47,25 +172,107 @@ local puzzle_seal_def = { on_blast = function() end, on_rotate = function() return false end, on_construct = function(pos) - ensure_inventory(pos) + ensure_meta(pos) end, on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) - minetest.get_node_timer(pos):start(1) - --ensure_inventory(pos) -- needed because mapgen doesn't call on_construct - --local player_name = clicker:get_player_name() - --minetest.show_formspec(player_name, "df_underworld_items_puzzle_seal:"..minetest.pos_to_string(pos)..":"..player_name, get_formspec(pos)) + ensure_meta(pos) + refresh_formspec(pos, clicker) + end, + on_timer = function(pos, elapsed) + local meta = minetest.get_meta(pos) + if meta:get_int("unlocked") > 0 then + show_unlocked(pos) + else + local index = meta:get_int("key_index") + show_key(pos, index) + meta:set_int("key_index", (index+1) % 8) + end + minetest.get_node_timer(pos):start(4) + end, + on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + refresh_formspec(pos, player) + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + refresh_formspec(pos, player) + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + refresh_formspec(pos, player) + end, +} + +if invulnerable then + puzzle_seal_def.groups.immortal = 1 +else + puzzle_seal_def.groups.cracky = 3 +end + +minetest.register_node("df_underworld_items:puzzle_seal", puzzle_seal_def) + +-------------------------------------------------------------------------------- +-- Once the seal is opened, it turns into this and digs its way down through the slade. + +local digging_seal_def = { + description = S("Slade Digging Seal"), + _doc_items_longdesc = nil, + _doc_items_usagehelp = nil, + drawtype = "mesh", + mesh = "underworld_seal.obj", + tiles = {"dfcaverns_pit_plasma_static.png", "dfcaverns_pit_plasma_static.png^dfcaverns_seal.png", "dfcaverns_pit_plasma_static.png"}, + paramtype = "light", + paramtype2 = "facedir", + light_source = 15, + groups = {immortal=1, stone=1, level=3, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1, not_in_creative_inventory=1}, + sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }), + selection_box = { + type = "fixed", + fixed = {-0.625, -0.625, -0.625, 0.625, 0.625, 0.625}, + }, + collision_box = { + type = "fixed", + fixed = {-0.625, -0.625, -0.625, 0.625, 0.625, 0.625}, + }, + is_ground_content = false, + on_blast = function() end, + on_rotate = function() return false end, + on_construct = function(pos) + minetest.get_node_timer(pos):start(0) end, - on_timer = function(pos, elapsed) local node = minetest.get_node(pos) local below_node = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}) if below_node.name == "ignore" then - minetest.get_node_timer(pos):start(1) + minetest.get_node_timer(pos):start(4) return end + + minetest.sound_play("dfcaverns_massive_digging", { + pos = pos, + gain = 1.0, + max_hear_distance = 32, + }) + + local minpos = vector.add(pos, {x=0, y=-1, z=0}) + minetest.add_particlespawner({ + amount = 100, + time = 4, + minpos = minpos, + maxpos = minpos, + minvel = {x=-5, y=0, z=-5}, + maxvel = {x=5, y=20, z=5}, + minacc = {x=0, y=-10, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 5, + maxexptime = 15, + minsize = 1, + maxsize = 5, + texture = "dfcaverns_glowpit_particle.png", + collisiondetection = true, + collision_removal = true, + glow = 15, + }) if minetest.get_item_group(below_node.name, "slade") == 0 then - minetest.set_node(pos, {name="air"}) + minetest.set_node(pos, {name="default:lava_source"}) return end @@ -88,23 +295,28 @@ local puzzle_seal_def = { minetest.set_node(pos, {name="air"}) local newpos = {x=pos.x, y=pos.y-2, z=pos.z} minetest.set_node(newpos, node) - minetest.get_node_timer(newpos):start(1) - end, - on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) - end, - on_metadata_inventory_put = function(pos, listname, index, stack, player) - end, - on_metadata_inventory_take = function(pos, listname, index, stack, player) + minetest.get_node_timer(newpos):start(4) end, } -if invulnerable then - puzzle_seal_def.groups.immortal = 1 -else - puzzle_seal_def.groups.cracky = 3 -end +minetest.register_node("df_underworld_items:digging_seal", digging_seal_def) -minetest.register_node("df_underworld_items:puzzle_seal", puzzle_seal_def) +local prefix_len = string.len(formspec_prefix) +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname:sub(1,prefix_len) ~= formspec_prefix or not fields.open then + return + end + local pos_string = formname:sub(prefix_len+1) + local pos = minetest.string_to_pos(pos_string) + if test_key(pos) then + minetest.set_node(pos, {name="df_underworld_items:digging_seal", param2 = math.random(1,4)-1}) + minetest.get_node_timer(pos):start(4) + minetest.close_formspec(player:get_player_name(), formname) + end +end) + +----------------------------------------------------------------------------------------- +-- Schematics local n1 = { name = "df_underworld_items:slade_block" } local n5 = { name = "default:meselamp" } diff --git a/df_underworld_items/sounds/dfcaverns_massive_digging.1.ogg b/df_underworld_items/sounds/dfcaverns_massive_digging.1.ogg new file mode 100644 index 0000000..0f73c50 Binary files /dev/null and b/df_underworld_items/sounds/dfcaverns_massive_digging.1.ogg differ diff --git a/df_underworld_items/sounds/dfcaverns_massive_digging.2.ogg b/df_underworld_items/sounds/dfcaverns_massive_digging.2.ogg new file mode 100644 index 0000000..7352741 Binary files /dev/null and b/df_underworld_items/sounds/dfcaverns_massive_digging.2.ogg differ diff --git a/df_underworld_items/sounds/dfcaverns_massive_digging.3.ogg b/df_underworld_items/sounds/dfcaverns_massive_digging.3.ogg new file mode 100644 index 0000000..ec7ebe9 Binary files /dev/null and b/df_underworld_items/sounds/dfcaverns_massive_digging.3.ogg differ diff --git a/df_underworld_items/sounds/dfcaverns_seal_key.ogg b/df_underworld_items/sounds/dfcaverns_seal_key.ogg new file mode 100644 index 0000000..ecbcab5 Binary files /dev/null and b/df_underworld_items/sounds/dfcaverns_seal_key.ogg differ diff --git a/df_underworld_items/sounds/dfcaverns_seal_unlocked.ogg b/df_underworld_items/sounds/dfcaverns_seal_unlocked.ogg new file mode 100644 index 0000000..34b82a5 Binary files /dev/null and b/df_underworld_items/sounds/dfcaverns_seal_unlocked.ogg differ diff --git a/df_underworld_items/sounds/license.txt b/df_underworld_items/sounds/license.txt index 195505b..862bd6a 100644 --- a/df_underworld_items/sounds/license.txt +++ b/df_underworld_items/sounds/license.txt @@ -9,4 +9,10 @@ dfcaverns_grinding_stone.3.ogg - from https://freesound.org/people/FreqMan/sound dfcaverns_arcing.1.ogg - from https://freesound.org/people/unfa/sounds/264827/ by unfa under Creative Commons BY 3.0 dfcaverns_arcing.2.ogg - from https://freesound.org/people/unfa/sounds/264827/ by unfa under Creative Commons BY 3.0 dfcaverns_arcing.3.ogg - from https://freesound.org/people/unfa/sounds/264827/ by unfa under Creative Commons BY 3.0 -dfcaverns_arcing.4.ogg - from https://freesound.org/people/unfa/sounds/264827/ by unfa under Creative Commons BY 3.0 \ No newline at end of file +dfcaverns_arcing.4.ogg - from https://freesound.org/people/unfa/sounds/264827/ by unfa under Creative Commons BY 3.0 + +dfcaverns_seal_unlocked.ogg - from https://freesound.org/people/juskiddink/sounds/74920/ by juskiddink under Creative Commons BY 3.0 +dfcaverns_seal_key.ogg - from https://freesound.org/people/Veiler/sounds/209894/ by Veiler under the Creative Commons 0 public domain license +dfcaverns_massive_digging.1.ogg - from https://freesound.org/people/OGsoundFX/sounds/423120/ by OGsoundFX under Creative Commons BY 3.0 +dfcaverns_massive_digging.2.ogg - from https://freesound.org/people/OGsoundFX/sounds/423120/ by OGsoundFX under Creative Commons BY 3.0 +dfcaverns_massive_digging.3.ogg - from https://freesound.org/people/OGsoundFX/sounds/423120/ by OGsoundFX under Creative Commons BY 3.0 \ No newline at end of file