Mineclone compatibility (#36)

* latest versions of mapgen_helper and subterrane

* initial work

* call it "minetest_game" compatibility instead of "default" compatibility

* Getting started on moving all default dependencies to a single root mod

* distilling out more dependencies

* fix some typos

* more default dependencies

* beds

* start getting some MCL equivalents set up

* mine gas dependencies

* reorganize

* add some mapgen stuff

* getting close to actually being able to run mineclone with this

* it actually runs! Crashes with out-of-memory error when you try to go below -64, but it's a start.

* hide flowing pit plasma from creative inventory

* mineclone 5 settings

* Update subterrane

* get rid of meselamp dependency, bring in ancient lanterns from deep roads

* stair dependencies

* add mcl fences

* add mcl blast resistance and hardness to everything. Also an alternate name for Nethercap in MCL, since "nether" has another meaning there.

* buckets of oil and syrup should work in mineclone now

* 'splosions!

* make hunters avoid repaired ancient lanterns

* mapgen torchspine wasn't having its timer set

* split mapgen compatibility code into its own file

* bypass dependency indirection for df_farming.

* apply threshold alpha to food items, they look better that way

* bypass dependency indirection for df_mapitems

* bypass dependency indirection for df_primordial_items

* bypass dependency indirection for df_trees

* bypass dependency indirection for df_underworld_items

* bypass dependency indirection for df_caverns

* fixing up the puzzle seal to work in both

* fix puzzle seal formspec for mcl

* create built-in substitutes for fireflies and bones mods for when those aren't available

* set up mcl dungeon loot for underworld warriors, port over some translations from default

* overlooked a debug

* add itemslot backgrounds for mcl

* added mineclone groups to all registered nodes. TODO: craftitems.

This was extremely tedious. Completely untested, aside from simply running the game.

* minor fixes to the built-in bones node

* eatable group for edibles

* clean up some TODOs

* adjust pit plasma abm conditions

* add df_ambience

* fixing up explosions. Also make slade sand diggable in mcl, and fix a bug in web generators

* make tower cap caves less chirpy, fix bigger goblin hut schematic, allow glowing spindlestem extract bottles

* avoid an undeclared global check

* alas, cave pearls aren't set up right for attached_node_facedir.

* bunch of work on mineclone ores, moved main config into df_dependencies

* add a few more ores

* update depends in mod.conf

* add opaque group to light-sensitive dirt types

Mineclone adds the "opaque" group only to non-light nodes, and torches check for the opaque group to decide whether they can be placed there. light-sensitive nodes need the "light" paramtype to work, though. So adding the opaque group manually to these.

* add a touch of reverb to one of the whisper tracks, it didn't fit with the others without it

* bloodthorn also needs to be set opaque

* add sound to torchspines

* isolate Nethercap translation name to make it easier to swap out in Mineclone contexts

* ambience tweak

* fix dirt spreads

https://github.com/FaceDeer/dfcaverns/issues/35

* adding achievements! Almost all untested yet.

* fix a few achievements glitches

* tweak some more achievements, add delay when achievements unlock other achievements

* fix farming achievements, fix spindlestem callbacks on place

* icons for farming achievements

* more achievement icons, fix ancient lantern achievement

* two more icons, update text

* add icons for upper cavern layers

* all achievements have icons now. Also add another sound to the magma sea ambience

* hook into awards' trigger system to get "x/y" progress displayed for the multi-achievement achievements

* ironically, Mineclone has an old version of awards that is incompatible with my trigger work.

* every award should now have a description and a difficulty.

* removing leftovers

* missing callbacks for farmables

* put growth restrictions on farmables so the achievement doesn't trigger inappropriately.

* enable ores in MCL2, fix some undeclared globals, fix icecap growth in MCL (achievements are a good debugging tool)

* get *all* the copper and iron containing nodes

* fix old awards mod's handling of grouped dig items

* Add a little bonus for players who activate a slade breacher - a handheld 'splosion tool

* used the wrong drop method

* beef up explosions in MCL, make slade brick craftable from slade sand and lava

* better creative mode checks, fix crash when digging walls in MCL

* Update subterrane

* various bugfixes and tweaks

* whipping up a simple puzzle chest to give a clue about ancient numbering

The coding is done, but UI and a node mesh need to be done

* prepare for some art tomorrow

* chest node and sounds

* images for the combination dials

* add puzzle chests to the underworld buildings

* update translations

* oops, can't initialize the contents of puzzle chests every time or players get endless stuff

* add backgrounds to item slots in MCL

* wrap the existing function rather than copy and pasting it

* fix bucket dependency in cooking recipes

* add _mcl_saturation to edibles
This commit is contained in:
FaceDeer
2022-08-28 23:48:44 -06:00
committed by GitHub
parent b2ee829c1a
commit 0a0c97b74e
435 changed files with 6100 additions and 1367 deletions

View File

@ -0,0 +1,149 @@
local S = minetest.get_translator(minetest.get_current_modname())
local lantern_nodebox = {
{-0.5, -0.5, -0.5, -0.3125, 0.5, -0.3125},
{-0.5, -0.5, 0.3125, -0.3125, 0.5, 0.5},
{0.3125, -0.5, 0.3125, 0.5, 0.5, 0.5},
{0.3125, -0.5, -0.5, 0.5, 0.5, -0.3125},
{-0.3125, 0.3125, -0.5, 0.3125, 0.5, -0.3125},
{-0.3125, 0.3125, 0.3125, 0.3125, 0.5, 0.5},
{0.3125, 0.3125, -0.3125, 0.5, 0.5, 0.3125},
{-0.5, 0.3125, -0.3125, -0.3125, 0.5, 0.3125},
{-0.5, -0.5, -0.3125, -0.3125, -0.3125, 0.3125},
{0.3125, -0.5, -0.3125, 0.5, -0.3125, 0.3125},
{-0.3125, -0.5, 0.3125, 0.3125, -0.3125, 0.5},
{-0.3125, -0.5, -0.5, 0.3125, -0.3125, -0.3125},
{-0.375, -0.375, -0.375, 0.375, 0.375, 0.375},
}
local mese_crystal_node = df_dependencies.node_name_mese_crystal
local brick_texture = "dfcaverns_slade_brick.png"
local lantern_texture = df_dependencies.texture_meselamp
local ancient_lantern_sound = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } })
local invulnerable = df_underworld_items.config.invulnerable_slade and not minetest.settings:get_bool("creative_mode")
local can_dig
if invulnerable then
can_dig = function(pos, player)
return minetest.check_player_privs(player, "server")
end
end
local slade_mcl_blast_resistance = 1200
local slade_mcl_hardness = 50
local slade_groups = {stone=1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1, cracky = 3, creative_breakable=1, building_block=1, material_stone=1}
if invulnerable then
slade_groups.immortal = 1
slade_mcl_blast_resistance = 3600000
slade_mcl_hardness = -1
end
-- override this to allow achievements to be recorded without requiring a dependency
df_underworld_items.ancient_lantern_fixed = function(pos, player) end
local punch_fix = function(pos, node, puncher, pointed_thing)
local wielded = puncher:get_wielded_item()
if wielded:get_name() == mese_crystal_node then
minetest.set_node(pos, {name="df_underworld_items:ancient_lantern_slade"})
minetest.get_node_timer(pos):stop()
if not minetest.is_creative_enabled(puncher:get_player_name()) then
wielded:take_item()
puncher:set_wielded_item(wielded)
end
df_underworld_items.ancient_lantern_fixed(pos, puncher)
return
end
minetest.node_punch(pos, node, puncher, pointed_thing)
end
minetest.register_node("df_underworld_items:ancient_lantern_slade", {
description = S("Ancient Lantern"),
paramtype2 = "facedir",
place_param2 = 0,
tiles = {brick_texture .. "^(" .. lantern_texture .. "^[mask:dfcaverns_lantern_mask.png)"},
is_ground_content = false,
groups = slade_groups,
sounds = ancient_lantern_sound,
drawtype= "nodebox",
light_source = minetest.LIGHT_MAX,
node_box = {
type = "fixed",
fixed = lantern_nodebox,
},
can_dig = can_dig,
_mcl_blast_resistance = slade_mcl_blast_resistance,
_mcl_hardness = slade_mcl_hardness,
})
minetest.register_node("df_underworld_items:ancient_lantern_slade_worn", {
description = S("Ancient Lantern"),
paramtype2 = "facedir",
place_param2 = 0,
tiles = {brick_texture .. "^(" .. lantern_texture .. "^[multiply:#FF8888^[mask:dfcaverns_lantern_mask.png)"},
is_ground_content = false,
groups = slade_groups,
sounds = ancient_lantern_sound,
drawtype= "nodebox",
light_source = 6,
node_box = {
type = "fixed",
fixed = lantern_nodebox,
},
_mcl_blast_resistance = slade_mcl_blast_resistance,
_mcl_hardness = slade_mcl_hardness,
on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(100, 200))
end,
on_timer = function(pos, elapsed)
minetest.swap_node(pos, {name="df_underworld_items:ancient_lantern_slade_burnt_out"})
if math.random() < 0.1 then
minetest.get_node_timer(pos):start(math.random(30, 60))
else
minetest.get_node_timer(pos):start(0.25)
end
end,
on_punch = punch_fix,
can_dig = can_dig,
})
minetest.register_node("df_underworld_items:ancient_lantern_slade_burnt_out", {
description = S("Ancient Lantern"),
paramtype2 = "facedir",
place_param2 = 0,
tiles = {brick_texture .. "^(" .. lantern_texture .. "^[multiply:#884444^[mask:dfcaverns_lantern_mask.png)"},
is_ground_content = false,
groups = slade_groups,
sounds = ancient_lantern_sound,
drawtype= "nodebox",
light_source = 0,
node_box = {
type = "fixed",
fixed = lantern_nodebox,
},
drops = "df_underworld_items:ancient_lantern_slade_worn",
_mcl_blast_resistance = slade_mcl_blast_resistance,
_mcl_hardness = slade_mcl_hardness,
on_construct = function(pos)
minetest.get_node_timer(pos):start(math.random(100, 200))
end,
on_timer = function(pos, elapsed)
minetest.swap_node(pos, {name="df_underworld_items:ancient_lantern_slade_worn"})
if math.random() < 0.1 then
minetest.get_node_timer(pos):start(math.random(300, 600))
else
minetest.get_node_timer(pos):start(0.25)
end
end,
on_punch = punch_fix,
can_dig = can_dig,
})
--minetest.register_craft({
-- output = "df_underworld_items:ancient_lantern_slade",
-- type = "shapeless",
-- recipe = {
-- "group:df_underworld_items_ancient_lantern",
-- mese_crystal_node,
-- }
--})

View File

@ -25,4 +25,5 @@ end
setting("bool", "invulnerable_slade", true, "Slade is invulnerable to players")
setting("bool", "destructive_pit_plasma", true, "Pit plasma destroys adjacent nodes")
setting("bool", "underworld_hunter_statues", true, "Enable hunter statues in the underworld")
setting("bool", "underworld_hunter_statues", true, "Enable hunter statues in the underworld")
setting("bool", "enable_slade_drill", true, "Enable slade drills")

View File

@ -1,4 +1,4 @@
local S = df_underworld_items.S
local S = minetest.get_translator(minetest.get_current_modname())
minetest.register_node("df_underworld_items:glow_amethyst", {
description = S("Glowing Amethyst Block"),
@ -6,13 +6,15 @@ minetest.register_node("df_underworld_items:glow_amethyst", {
_doc_items_usagehelp = df_underworld_items.doc.glow_amethyst_usage,
tiles = {"dfcaverns_glow_amethyst.png"},
is_ground_content = false,
groups = {cracky=3, pit_plasma_resistant=1},
sounds = default.node_sound_glass_defaults(),
groups = {cracky=3, pit_plasma_resistant=1, pickaxey = 4, building_block = 1,}, -- deliberately not in material_stone group to keep pit plasma ABM efficient
sounds = df_dependencies.sound_glass(),
light_source = 6,
paramtype = "light",
use_texture_alpha = "blend",
drawtype = "glasslike",
sunlight_propagates = true,
_mcl_blast_resistance = 6,
_mcl_hardness = 2,
})
if minetest.get_modpath("radiant_damage") and radiant_damage.override_radiant_damage and radiant_damage.config.enable_mese_damage then

View File

@ -1,10 +0,0 @@
df_underworld_items.abm_neighbors = {}
-- common nodes that can be found next to pit plasma, triggering matter degradation
-- don't trigger on air, that's for sparkle generation
df_underworld_items.abm_neighbors.pit_plasma = {"group:stone", "df_underworld_items:glow_amethyst", "group:lava", "group:water"}
-- This stuff should only be used during initialization
minetest.after(0, function()
df_underworld_items.node_name = nil
end)

View File

@ -4,7 +4,7 @@ if not minetest.get_modpath("doc") then
return
end
local S = df_underworld_items.S
local S = minetest.get_translator(minetest.get_current_modname())
df_underworld_items.doc.glowstone_desc = S("Bright glowing stones of unknown origin found lodged in the crevices of the underworld's ceiling.")
df_underworld_items.doc.glowstone_usage = S("These stones are highly volatile and should not be disturbed.")
@ -21,4 +21,7 @@ df_underworld_items.doc.glow_amethyst_desc = S("Glowing purple crystals that gro
df_underworld_items.doc.glow_amethyst_usage = S("These crystals have no known use.")
df_underworld_items.doc.pit_plasma_desc = S("The liquid found in the deepest pits in the underworld is highly dangerous and damaging.")
df_underworld_items.doc.pit_plasma_usage = S("The only use for this material is that it destroys whatever is thrown into it. It cannot otherwise be manipulated.")
df_underworld_items.doc.pit_plasma_usage = S("The only use for this material is that it destroys whatever is thrown into it. It cannot otherwise be manipulated.")
df_underworld_items.doc.slade_drill_desc = S("This shard of a spent slade breacher doesn't appear to have been intended as a portable tool, but it can be used as one.")
df_underworld_items.doc.slade_drill_usage = S("Use this on a target to unleash the energies used to dig through the foundations of the world.")

View File

@ -1,4 +1,4 @@
local S = df_underworld_items.S
local S = minetest.get_translator(minetest.get_current_modname())
local glowstone_def = {
_doc_items_longdesc = df_underworld_items.doc.glowstone_desc,
@ -18,16 +18,21 @@ local glowstone_def = {
},
},
is_ground_content = false,
groups = {cracky=3},
sounds = default.node_sound_glass_defaults(),
groups = {cracky=3, pickaxey = 1, building_block = 1, material_stone =1},
sounds = df_dependencies.sound_glass(),
paramtype = "light",
drawtype = "glasslike",
drop = "",
sunlight_propagates = true,
_mcl_blast_resistance = 0.5,
_mcl_hardness = 0.5,
}
if minetest.get_modpath("tnt") then
local tnt_boom = df_dependencies.tnt_boom
if tnt_boom then
glowstone_def.on_dig = function(pos, node, digger)
tnt.boom(pos, {radius=3})
if minetest.node_dig(pos, node, digger) then
tnt_boom(pos, {radius=3})
end
end
end
minetest.register_node("df_underworld_items:glowstone", glowstone_def)

View File

@ -1,4 +1,6 @@
local S = df_underworld_items.S
local S = minetest.get_translator(minetest.get_current_modname())
local lava_source = df_dependencies.node_name_lava_source
minetest.register_node("df_underworld_items:pit_plasma", {
description = S("Glowing Pit Plasma"),
@ -17,7 +19,7 @@ minetest.register_node("df_underworld_items:pit_plasma", {
},
},
groups={pit_plasma=1, pit_plasma_resistant=1},
groups={pit_plasma=1, pit_plasma_resistant=1,destroys_items=1, set_on_fire=15, fire_damage=1, liquid=1},
walkable = false,
pointable = false,
diggable = false,
@ -36,6 +38,8 @@ minetest.register_node("df_underworld_items:pit_plasma", {
is_ground_content = false,
light_source = minetest.LIGHT_MAX,
paramtype = "light",
_mcl_blast_resistance = 3600000,
_mcl_hardness = -1,
})
minetest.register_node("df_underworld_items:pit_plasma_flowing", {
@ -65,7 +69,7 @@ minetest.register_node("df_underworld_items:pit_plasma_flowing", {
},
},
},
groups={pit_plasma=1, pit_plasma_resistant=1},
groups={pit_plasma=1, pit_plasma_resistant=1, not_in_creative_inventory=1,destroys_items=1, set_on_fire=15, fire_damage=1, liquid=1},
walkable = false,
pointable = false,
diggable = false,
@ -85,6 +89,8 @@ minetest.register_node("df_underworld_items:pit_plasma_flowing", {
is_ground_content = false,
light_source = minetest.LIGHT_MAX,
paramtype = "light",
_mcl_blast_resistance = 3600000,
_mcl_hardness = -1,
})
if minetest.get_modpath("radiant_damage") and radiant_damage.override_radiant_damage then
@ -127,7 +133,7 @@ if df_underworld_items.config.destructive_pit_plasma then
minetest.register_abm({
label = "glowing pit matter degradation",
nodenames = {"group:pit_plasma"},
neighbors = df_underworld_items.abm_neighbors.pit_plasma,
neighbors = df_dependencies.abm_pit_plasma_neighbors,
interval = 2,
chance = 30,
catch_up = false,
@ -144,7 +150,7 @@ if df_underworld_items.config.destructive_pit_plasma then
if math.random() < 0.66 then
minetest.set_node(test_pos, {name="df_underworld_items:glow_amethyst"})
else
minetest.set_node(test_pos, {name="default:lava_source"})
minetest.set_node(test_pos, {name=lava_source})
end
else
minetest.set_node(test_pos, {name="air"})

View File

@ -1,6 +1,6 @@
if minetest.get_modpath("hunter_statue") and df_underworld_items.config.underworld_hunter_statues then
local S = df_underworld_items.S
local S = minetest.get_translator(minetest.get_current_modname())
hunter_statue.register_hunter_statue("df_underworld_items:hunter_statue", {
description = S("Guardian Statue"),
@ -13,6 +13,9 @@ if minetest.get_modpath("hunter_statue") and df_underworld_items.config.underwor
tnt_vulnerable = true,
tnt_debris = "df_underworld_items:slade_sand",
groups = {hunter_statue = 1, falling_node = 1, immortal = 1},
hunters_allowed_here = function(pos)
return not minetest.find_node_near(pos, 6, "df_underworld_items:ancient_lantern_slade", true)
end,
other_overrides = {
can_dig = function(pos, player)
if player then

View File

@ -1,11 +1,9 @@
df_underworld_items = {}
local modname = minetest.get_current_modname()
df_underworld_items.S = minetest.get_translator(modname)
local modpath = minetest.get_modpath(modname)
dofile(modpath.."/config.lua")
dofile(modpath.."/dependencies.lua")
dofile(modpath.."/doc.lua")
dofile(modpath.."/crystals_amethyst.lua")
@ -14,4 +12,9 @@ dofile(modpath.."/slade.lua")
dofile(modpath.."/hunter_statue.lua")
dofile(modpath.."/glowing_pit_plasma.lua")
dofile(modpath.."/puzzle_seal.lua")
dofile(modpath.."/puzzle_seal.lua")
dofile(modpath.."/puzzle_chest.lua")
dofile(modpath.."/ancient_lanterns.lua")
if df_underworld_items.config.enable_slade_drill then
dofile(modpath.."/slade_drill.lua")
end

View File

@ -1,6 +1,10 @@
# textdomain: df_underworld_items
### ancient_lanterns.lua ###
Ancient Lantern=
### crystals_amethyst.lua ###
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
@ -38,6 +42,10 @@ These stones are highly volatile and should not be disturbed.=Diese Steine
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
This block of Slade, carved by an unknown hand, is engraved with mysterious symbols. Most of the engraving's meaning is lost to the mists of time but one frament in the oldest known language can be translated: "This place is not a place of honor."=Dieser von einer unbekannten Hand geschnitzte Slade-Block ist mit mysteriösen Symbolen versehen. Der größte Teil der Bedeutung der Gravur geht den Nebeln der Zeit verloren, aber ein Frament in der ältesten bekannten Sprache kann übersetzt werden: "Dieser Ort ist kein Ehrenplatz."
This shard of a spent slade breacher doesn't appear to have been intended as a portable tool, but it can be used as one.=
Use this on a target to unleash the energies used to dig through the foundations of the world.=
### glow_stone.lua ###
@ -54,6 +62,10 @@ Glowing Pit Plasma=Glühendes Grubenplasma
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Guardian Statue=Wächterstatue
### puzzle_chest.lua ###
Puzzle Chest=
### puzzle_seal.lua ###
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
@ -62,10 +74,6 @@ Active Slade Breacher=Aktiver Slade Breacher
Breach in the Slade=Brich den Slade ein
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Inscribed Slade Block=Beschrifteter Slade-Block
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Slade Block Slab=Slade Block Platte
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Slade Block Stair=Slade Block Treppe
Slade Capstone=
Slade Puzzle Seal=
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
@ -78,7 +86,18 @@ Slade Block=
Slade Brick=
Slade Sand=
Slade Seal=
Slade Wall=
### slade_drill.lua ###
Slade Drill=
##### not used anymore #####
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Slade Block Slab=Slade Block Platte
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Slade Block Stair=Slade Block Treppe
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Slade Slab=Slade-Platte
Slade Stair=
Slade Wall=

View File

@ -1,6 +1,10 @@
# textdomain: df_underworld_items
### ancient_lanterns.lua ###
Ancient Lantern=
### crystals_amethyst.lua ###
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
@ -38,6 +42,10 @@ These stones are highly volatile and should not be disturbed.=Queste pietre sono
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
This block of Slade, carved by an unknown hand, is engraved with mysterious symbols. Most of the engraving's meaning is lost to the mists of time but one frament in the oldest known language can be translated: "This place is not a place of honor."=Questo blocco di Slade, scolpito da una mano sconosciuta, è inciso con simboli misteriosi. La maggior parte del significato dell'incisione si perde nella notte dei tempi, ma un frammento nella più antica lingua conosciuta può essere tradotto: "Questo posto non è un posto d'onore".
This shard of a spent slade breacher doesn't appear to have been intended as a portable tool, but it can be used as one.=
Use this on a target to unleash the energies used to dig through the foundations of the world.=
### glow_stone.lua ###
@ -52,6 +60,10 @@ Glowing Pit Plasma=
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Guardian Statue=Statua del guardiano
### puzzle_chest.lua ###
Puzzle Chest=
### puzzle_seal.lua ###
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
@ -60,8 +72,6 @@ Active Slade Breacher=Attivo Slade Breacher
Breach in the Slade=Violazione nello Slade
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Inscribed Slade Block=Inscritto Slade Block
Slade Block Slab=
Slade Block Stair=
Slade Capstone=
Slade Puzzle Seal=
Turn=
@ -74,6 +84,8 @@ Slade Brick=
Slade Sand=
#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE
Slade Seal=Sigillo Slade
Slade Slab=
Slade Stair=
Slade Wall=
### slade_drill.lua ###
Slade Drill=

View File

@ -1,6 +1,10 @@
# textdomain: df_underworld_items
### ancient_lanterns.lua ###
Ancient Lantern=
### crystals_amethyst.lua ###
Glowing Amethyst Block=
@ -27,6 +31,10 @@ These stones are highly volatile and should not be disturbed.=
This block of Slade, carved by an unknown hand, is engraved with mysterious symbols. Most of the engraving's meaning is lost to the mists of time but one frament in the oldest known language can be translated: "This place is not a place of honor."=
This shard of a spent slade breacher doesn't appear to have been intended as a portable tool, but it can be used as one.=
Use this on a target to unleash the energies used to dig through the foundations of the world.=
### glow_stone.lua ###
@ -40,13 +48,15 @@ Glowing Pit Plasma=
Guardian Statue=
### puzzle_chest.lua ###
Puzzle Chest=
### puzzle_seal.lua ###
Active Slade Breacher=
Breach in the Slade=
Inscribed Slade Block=
Slade Block Slab=
Slade Block Stair=
Slade Capstone=
Slade Puzzle Seal=
Turn=
@ -58,6 +68,8 @@ Slade Block=
Slade Brick=
Slade Sand=
Slade Seal=
Slade Slab=
Slade Stair=
Slade Wall=
### slade_drill.lua ###
Slade Drill=

View File

@ -1,4 +1,4 @@
name = df_underworld_items
description = Various node types used by the dfcaverns mapgen mod for its underworld layer.
depends = default
optional_depends = doc, radiant_damage, mesecons_mvps, tnt, stairs, hunter_statue
depends = df_dependencies
optional_depends = doc, radiant_damage, mesecons_mvps, hunter_statue

View File

@ -0,0 +1,142 @@
dfcaverns_open_chest.obj is copied from minetest_game's default mod, whose media license doesn't specify who in particular created it. The media license for the default mod is as follows:
Licenses of media (textures, models and sounds)
-----------------------------------------------
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
Copyright (C) 2010-2018:
celeron55, Perttu Ahola <celeron55@gmail.com>
Cisoun
G4JC
VanessaE
RealBadAngel
Calinou
MirceaKitsune
Jordach
PilzAdam
jojoa1997
InfinityProject
Splizard
Zeg9
paramat
BlockMen
sofar
Neuromancer
Gambit
asl97
KevDoy
Mito551
GreenXenith
kaeza
kilbith
tobyplowy
CloudyProton
TumeniNodes
Mossmanikin
random-geek
Extex101
An0n3m0us
You are free to:
Share — copy and redistribute the material in any medium or format.
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and
indicate if changes were made. You may do so in any reasonable manner, but not in any way
that suggests the licensor endorses you or your use.
ShareAlike — If you remix, transform, or build upon the material, you must distribute
your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures that
legally restrict others from doing anything the license permits.
Notices:
You do not have to comply with the license for elements of the material in the public
domain or where your use is permitted by an applicable exception or limitation.
No warranties are given. The license may not give you all of the permissions necessary
for your intended use. For example, other rights such as publicity, privacy, or moral
rights may limit how you use the material.
For more details:
http://creativecommons.org/licenses/by-sa/3.0/
-----------------------
Attribution 3.0 Unported (CC BY 3.0)
Copyright (C) 2009 cmusounddesign
Copyright (C) 2010 Tomlija
Copyright (C) 2010 lsprice
Copyright (C) 2014 sonictechtonic
Copyright (C) 2015 yadronoff
Copyright (C) 2007 HerbertBoland
Copyright (C) 2006 AGFX
You are free to:
Share — copy and redistribute the material in any medium or format.
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and
indicate if changes were made. You may do so in any reasonable manner, but not in any way
that suggests the licensor endorses you or your use.
No additional restrictions — You may not apply legal terms or technological measures that
legally restrict others from doing anything the license permits.
Notices:
You do not have to comply with the license for elements of the material in the public
domain or where your use is permitted by an applicable exception or limitation.
No warranties are given. The license may not give you all of the permissions necessary
for your intended use. For example, other rights such as publicity, privacy, or moral
rights may limit how you use the material.
For more details:
http://creativecommons.org/licenses/by/3.0/
-----------------------
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
Iwan Gabovitch
Ottomaani138
Ogrebane
blukotek
Sevin7
Yoyodaman234
Ryding
No Copyright
The person who associated a work with this deed has dedicated the work to the
public domain by waiving all of his or her rights to the work worldwide under
copyright law, including all related and neighboring rights, to the extent
allowed by law.
You can copy, modify, distribute and perform the work, even for commercial
purposes, all without asking permission. See Other Information below.
Other Information:
In no way are the patent or trademark rights of any person affected by CC0, nor
are the rights that other persons may have in the work or in how the work is
used, such as publicity or privacy rights.
Unless expressly stated otherwise, the person who associated a work with this
deed makes no warranties about the work, and disclaims liability for all uses
of the work, to the fullest extent permitted by applicable law.
When using or citing the work, you should not imply endorsement by the author
or the affirmer.
For more details:
https://creativecommons.org/publicdomain/zero/1.0/

View File

@ -0,0 +1,79 @@
# Blender v2.78 (sub 0) OBJ File: 'chest-open.blend'
# www.blender.org
o Top_Cube.002_None_Top_Cube.002_None_bottom
v -0.500000 0.408471 0.720970
v -0.500000 1.115578 0.013863
v -0.500000 0.894607 -0.207108
v -0.500000 0.187501 0.499999
v 0.500000 1.115578 0.013863
v 0.500000 0.408471 0.720970
v 0.500000 0.187501 0.499999
v 0.500000 0.894607 -0.207108
v -0.500000 0.187500 -0.500000
v -0.500000 -0.500000 -0.500000
v -0.500000 -0.500000 0.500000
v 0.500000 0.187500 -0.500000
v 0.500000 -0.500000 0.500000
v 0.500000 -0.500000 -0.500000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vt 1.0000 1.0000
vt 1.0000 0.6875
vt 0.0000 0.6875
vt 1.0000 1.0000
vt 0.0000 0.6875
vt 1.0000 0.6875
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 0.0000 0.0000
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 1.0000 0.6875
vt 1.0000 0.0000
vt 0.0000 1.0000
vt 0.0000 0.6875
vt 0.0000 0.6875
vt 0.0000 0.0000
vt 1.0000 0.5000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.5000
vt 0.0000 0.0000
vt 1.0000 0.0000
vn 0.0000 0.7071 0.7071
vn -0.0000 -1.0000 -0.0000
vn -1.0000 0.0000 0.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 -0.7071 0.7071
vn 0.0000 0.0000 1.0000
vn -0.0000 0.7071 -0.7071
vn -0.0000 0.0000 -1.0000
vn -0.0000 -0.7071 -0.7071
vn -0.0000 1.0000 -0.0000
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Top
s off
f 6/1/1 5/2/1 2/3/1 1/4/1
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Bottom
f 11/5/2 10/6/2 14/7/2 13/8/2
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Right-Left
f 1/9/3 2/10/3 3/11/3 4/12/3
f 5/13/4 6/1/4 7/14/4 8/15/4
f 4/12/3 9/16/3 10/17/3 11/18/3
f 12/19/4 7/14/4 13/8/4 14/20/4
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Back
f 6/21/5 1/9/5 4/12/5 7/22/5
f 7/22/6 4/12/6 11/18/6 13/23/6
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Front
f 2/10/7 5/24/7 8/25/7 3/11/7
f 9/16/8 12/26/8 14/27/8 10/17/8
g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Inside
f 4/28/9 3/29/9 8/30/9 7/31/9
f 7/31/10 12/32/10 9/33/10 4/28/10

View File

@ -0,0 +1,172 @@
local S = minetest.get_translator(minetest.get_current_modname())
local sum_square = function(input)
return {input[1] + input[2], input[3] + input[4], input[1] + input[3], input[2] + input[4]}
end
local initialize = function(pos, meta)
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.y^8 + 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.randomseed(next_seed)
local state = {math.random(0,7), math.random(0,7), math.random(0,7), math.random(0,7)}
local key_sum = sum_square(key)
local state_sum = sum_square(state)
if (key_sum[1] == state_sum[1] and key_sum[2] == state_sum[2] and key_sum[3] == state_sum[3] and key_sum[4] == state_sum[4]) then
-- if we randomly start off solved change one of the states to make it unsolved.
-- lucky player gets an easy one.
state[1] = (state[1] + 1) % 8
end
meta:set_string("key", minetest.serialize(key))
meta:set_string("state", minetest.serialize(state))
meta:mark_as_private("key")
meta:mark_as_private("state") -- not really necessary, but for consistency
end
end
-- 1 2
-- 3 4
local formspec_dial = function(identifier, state)
return "image[0.5,0;2,1;dfcaverns_chest_dial_"..tostring(state)..".png]"
.. "button[0,0.25;0.5,0.5;"..identifier.."+;<]"
.. "button[2.5,0.25;0.5,0.5;"..identifier.."-;>]"
end
local formspec_bar = function(horizontal, state, key)
if horizontal then
return "box[0,0;".. tostring(key/14 * 2 + 0.1) ..",1;#222222ff]box[0.1,0.1;".. tostring(state/14 * 2)..",0.85;#ff00ff44]"
end
return "box[0,0;1,".. tostring(key/14 * 2 + 0.1) ..";#222222ff]box[0.1,0.1;0.85,".. tostring(state/14 * 2)..";#ff00ff44]"
end
local prefix = "df_underworld_items:puzzle_chest"
local prefix_len = string.len("df_underworld_items:puzzle_chest")
local itemslot_bg = df_dependencies.get_itemslot_bg_padded
local show_formspec = function(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
initialize(pos, meta)
local key = minetest.deserialize(meta:get_string("key"))
local state = minetest.deserialize(meta:get_string("state"))
local key_sum = sum_square(key)
local state_sum = sum_square(state)
local solved = key_sum[1] == state_sum[1] and key_sum[2] == state_sum[2] and key_sum[3] == state_sum[3] and key_sum[4] == state_sum[4]
local playername = clicker:get_player_name()
local formname = prefix .. minetest.pos_to_string(pos)
local formspec = "formspec_version[6]"
.. "size[11,12]"
.. "container[1.5,0.5]"
.. "container[0,0]" .. formspec_dial("dial1", state[1]) .. "container_end[]"
.. "container[3,0]" .. formspec_dial("dial2", state[2]) .. "container_end[]"
.. "container[0,1.5]" .. formspec_dial("dial3", state[3]) .. "container_end[]"
.. "container[3,1.5]" .. formspec_dial("dial4", state[4]) .. "container_end[]"
.. "container[6.1,0]" .. formspec_bar(true, state_sum[1], key_sum[1]) .. "container_end[]"
.. "container[6.1,1.5]" .. formspec_bar(true, state_sum[2], key_sum[2]) .. "container_end[]"
.. "container[1,2.75]" .. formspec_bar(false, state_sum[3], key_sum[3]) .. "container_end[]"
.. "container[4,2.75]" .. formspec_bar(false, state_sum[4], key_sum[4]) .. "container_end[]"
.. "container_end[]"
.. itemslot_bg(0.6,6.7,8,4,0.25)
.. "list[current_player;main;0.6,6.7;8,4;]"
if solved then
local nodemeta = "nodemeta:"..pos.x..","..pos.y..","..pos.z
formspec = formspec
.. itemslot_bg(0.6,5.4,8,1,0.25)
.. "list["..nodemeta..";main;0.6,5.4;8,1;]"
.. "listring[]"
if meta:get_string("solved") ~= "true" then
minetest.sound_play("dfcaverns_puzzle_chest_open", {pos = pos})
meta:set_string("solved", "true")
local old_node = minetest.get_node(pos)
minetest.swap_node(pos, {name="df_underworld_items:puzzle_chest_opened", param2=old_node.param2})
end
elseif meta:get_string("solved") == "true" then
minetest.sound_play("dfcaverns_puzzle_chest_close", {pos = pos})
meta:set_string("solved", "")
local old_node = minetest.get_node(pos)
minetest.swap_node(pos, {name="df_underworld_items:puzzle_chest_closed", param2=old_node.param2})
end
minetest.show_formspec(playername, formname, formspec)
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if string.sub(formname, 1, prefix_len) ~= prefix then return end
if fields.quit then return end
local pos = minetest.string_to_pos(string.sub(formname, prefix_len+1, -1))
local meta = minetest.get_meta(pos)
local state = minetest.deserialize(meta:get_string("state"))
for i = 1,4 do
if fields["dial"..tostring(i).."+"] then
state[i] = (state[i] + 1) % 8
break
elseif fields["dial"..tostring(i).."-"] then
state[i] = (state[i] - 1) % 8
break
end
end
meta:set_string("state", minetest.serialize(state))
show_formspec(pos, nil, player)
end)
local puzzle_chest_can_dig = function(pos, player)
local meta = minetest.get_meta(pos)
initialize(pos, meta)
local inv = meta:get_inventory()
return inv:is_empty("main")
end
minetest.register_node("df_underworld_items:puzzle_chest_closed", {
description = S("Puzzle Chest"),
_doc_items_longdesc = df_underworld_items.doc.puzzle_chest_desc,
_doc_items_usagehelp = df_underworld_items.doc.puzzle_chest_usage,
tiles = {
"dfcaverns_slade_block.png^dfcaverns_chest_mask_top.png",
"dfcaverns_slade_block.png^dfcaverns_chest_mask_top.png",
"dfcaverns_slade_block.png^dfcaverns_chest_mask_side.png",
"dfcaverns_slade_block.png^dfcaverns_chest_mask_side.png",
"dfcaverns_slade_block.png^dfcaverns_chest_mask_side.png",
"dfcaverns_slade_block.png^dfcaverns_chest_mask_side.png^dfcaverns_chest_lock_plate.png^dfcaverns_chest_lock_colours.png",
},
paramtype2="facedir",
is_ground_content = false,
groups = {stone=1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1, cracky = 3, building_block=1, material_stone=1},
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
_mcl_blast_resistance = 1200,
_mcl_hardness = 50,
on_rightclick = show_formspec,
can_dig = puzzle_chest_can_dig,
})
minetest.register_node("df_underworld_items:puzzle_chest_opened", {
description = S("Puzzle Chest"),
_doc_items_longdesc = df_underworld_items.doc.puzzle_chest_desc,
_doc_items_usagehelp = df_underworld_items.doc.puzzle_chest_usage,
tiles = {
{name = "dfcaverns_slade_block.png^dfcaverns_chest_mask_top.png", backface_culling = true},
{name = "dfcaverns_slade_block.png^dfcaverns_chest_mask_top.png", backface_culling = true},
{name = "dfcaverns_slade_block.png^dfcaverns_chest_mask_side.png", backface_culling = true},
{name = "dfcaverns_slade_block.png^dfcaverns_chest_mask_side.png", backface_culling = true},
{name = "dfcaverns_slade_block.png^dfcaverns_chest_mask_side.png^dfcaverns_chest_lock_plate.png^dfcaverns_chest_lock_colours.png", backface_culling = true},
{name = "([combine:16x32:0,0=dfcaverns_slade_block.png:0,16=dfcaverns_slade_block.png)^dfcaverns_chest_mask_interior.png", backface_culling = true},
},
is_ground_content = false,
mesh = "dfcaverns_chest_open.obj",
drawtype= "mesh",
visual = "mesh",
paramtype2="facedir",
groups = {stone=1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1, cracky = 3, building_block=1, material_stone=1, not_in_creative_inventory=1},
drop = "df_underworld_items:puzzle_chest_closed",
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
_mcl_blast_resistance = 1200,
_mcl_hardness = 50,
on_rightclick = show_formspec,
can_dig = puzzle_chest_can_dig,
})

View File

@ -1,7 +1,11 @@
local S = df_underworld_items.S
local S = minetest.get_translator(minetest.get_current_modname())
local named_waypoints_path = minetest.get_modpath("named_waypoints")
-- override these to allow achievements to be recorded without requiring a dependency
df_underworld_items.slade_breacher_triggered = function(pos, player) end
df_underworld_items.puzzle_seal_solved = function(pos, player) end -- player can be nil
local invulnerable = df_underworld_items.config.invulnerable_slade and not minetest.settings:get_bool("creative_mode")
local can_dig
@ -11,11 +15,16 @@ if invulnerable then
end
end
local slade_groups = {stone=1, level=3, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1, cracky = 3, not_in_creative_inventory=1}
local slade_mcl_blast_resistance = 1200
local slade_mcl_hardness = 50
local slade_groups = {stone=1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1, cracky = 3, not_in_creative_inventory=1,creative_breakable=1, building_block=1, material_stone=1}
if invulnerable then
slade_groups.immortal = 1
slade_mcl_blast_resistance = 3600000
slade_mcl_hardness = -1
end
local lava_source = df_dependencies.node_name_lava_source
-- Ensures that the node is functioning correctly
local ensure_meta = function(pos)
@ -39,33 +48,78 @@ local ensure_meta = function(pos)
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
{"color_black", "basecolor_black", "excolor_black", "excolor_darkgrey", "color_dark_grey"}, -- 0
{"color_red", "basecolor_red", "excolor_red"}, -- 1
{"color_orange", "basecolor_orange", "excolor_orange"}, -- 2
{"color_yellow", "basecolor_yellow", "excolor_yellow"}, -- 3
{"color_green", "basecolor_green", "excolor_green", "excolor_lime", "color_dark_green"}, -- 4
{"color_blue", "basecolor_blue", "excolor_blue", "excolor_sky_blue"}, -- 5
{"color_violet", "excolor_violet",}, -- 6
{"color_white", "basecolor_white", "excolor_white", "excolor_lightgrey", "color_grey"}, -- 7
}
local test_key = function(pos)
df_underworld_items.colour_items = {}
local cull_colour_groups = function()
local culled_colour_groups = {}
for _, groups in ipairs(colour_groups) do
local new_set = {}
for _, colour_group in pairs(groups) do
for itemname, def in pairs(minetest.registered_items) do
if minetest.get_item_group(itemname, colour_group) ~= 0 then
table.insert(new_set, colour_group)
break
end
end
end
assert(#new_set > 0, "Unsolvable puzzle seals due to lack of any registered items belonging to one of " .. dump(groups))
table.insert(culled_colour_groups, new_set)
end
colour_groups = culled_colour_groups
-- collect a list of all items with useful colour groups
-- to be used for treasure generation
local colour_item_set = {}
for itemname, def in pairs(minetest.registered_items) do
for _, groups in ipairs(colour_groups) do
for _, colour in ipairs(groups) do
if minetest.get_item_group(itemname, colour) ~= 0 then
colour_item_set[itemname] = true
end
end
end
end
for colour_item, _ in pairs(colour_item_set) do
table.insert(df_underworld_items.colour_items, colour_item)
end
end
minetest.after(0, cull_colour_groups)
local item_represents_number = function(itemname, number)
for _, group in pairs(colour_groups[number+1]) do
if minetest.get_item_group(itemname, group) ~= 0 then
return true
end
end
return false
end
local test_key = function(pos, player)
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
if not item_represents_number(item:get_name(), key[keyval]) then
valid = false
break
end
@ -73,6 +127,7 @@ local test_key = function(pos)
if valid then
local unlocked = meta:get_int("unlocked")
if unlocked == 0 then
df_underworld_items.puzzle_seal_solved(pos, player)
meta:set_int("unlocked", 1)
end
return true
@ -93,6 +148,7 @@ end
--This place is best shunned and left uninhabited.
local formspec_prefix = "df_underworld_items_puzzle_seal:"
local itemslot_bg = df_dependencies.get_itemslot_bg
local get_formspec = function(pos, unlocked)
local formspec =
"size[8,8]"
@ -100,13 +156,21 @@ local get_formspec = function(pos, unlocked)
.."image[5.8,0;2.5,4;dfcaverns_puzzle_inscription_background.png^[transformR180^dfcaverns_puzzle_inscription_2.png]"
.."container[2.25,0]"
.."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0.25,0.25;1,1;0]"
..itemslot_bg(0.25,0.25,1,1)
.."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;1.25,0;1,1;1]"
..itemslot_bg(1.25,0,1,1)
.."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;2.25,0.25;1,1;2]"
..itemslot_bg(2.25,0.25,1,1)
.."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;2.5,1.25;1,1;3]"
..itemslot_bg(2.5,1.25,1,1)
.."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;2.25,2.25;1,1;4]"
..itemslot_bg(2.25,2.25,1,1)
.."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;1.25,2.5;1,1;5]"
..itemslot_bg(1.25,2.5,1,1)
.."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0.25,2.25;1,1;6]"
..itemslot_bg(0.25,2.25,1,1)
.."list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,1.25;1,1;7]"
..itemslot_bg(0,1.25,1,1)
if unlocked then
formspec = formspec .. "image_button[1.25,1.25;1,1;dfcaverns_seal.png;open;"..S("Turn").."]"
else
@ -119,12 +183,15 @@ local get_formspec = function(pos, unlocked)
-- .."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
..itemslot_bg(0,0,8,1)
.."list[current_player;main;0,1.25;8,3;8]"
..itemslot_bg(0,1.25,8,3)
.."container_end[]"
return formspec
end
local refresh_formspec = function(pos, player)
local player_name = player:get_player_name()
local unlocked = test_key(pos)
local unlocked = test_key(pos, player)
local formspec = get_formspec(pos, unlocked)
minetest.show_formspec(player_name, formspec_prefix..minetest.pos_to_string(pos), formspec)
end
@ -188,7 +255,7 @@ local puzzle_seal_def = {
paramtype2 = "facedir",
light_source = 8,
groups = slade_groups,
sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }),
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
selection_box = {
type = "fixed",
fixed = {-0.625, -0.625, -0.625, 0.625, 0.625, 0.625},
@ -199,6 +266,8 @@ local puzzle_seal_def = {
},
is_ground_content = false,
can_dig = can_dig,
_mcl_blast_resistance = slade_mcl_blast_resistance,
_mcl_hardness = slade_mcl_hardness,
on_blast = function() end,
on_rotate = function() return false end,
on_construct = function(pos)
@ -238,6 +307,8 @@ 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 tnt_boom = df_dependencies.tnt_boom
local digging_seal_def = {
description = S("Active Slade Breacher"),
_doc_items_longdesc = nil,
@ -247,9 +318,9 @@ local digging_seal_def = {
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 = default.LIGHT_MAX,
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 } }),
light_source = minetest.LIGHT_MAX,
groups = {immortal=1, stone=1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1, not_in_creative_inventory=1,building_block=1, material_stone=1},
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
selection_box = {
type = "fixed",
fixed = {-0.625, -0.625, -0.625, 0.625, 0.625, 0.625},
@ -259,6 +330,8 @@ local digging_seal_def = {
fixed = {-0.625, -0.625, -0.625, 0.625, 0.625, 0.625},
},
is_ground_content = false,
_mcl_blast_resistance = 3600000,
_mcl_hardness = -1,
can_dig = can_dig,
on_blast = function() end,
on_rotate = function() return false end,
@ -301,8 +374,15 @@ local digging_seal_def = {
})
if minetest.get_item_group(below_node.name, "slade") == 0 then
tnt.boom({x=pos.x, y=pos.y-2, z=pos.z}, {radius=3})
minetest.set_node(pos, {name="default:lava_source"})
if df_underworld_items.config.enable_slade_drill then
minetest.set_node(pos, {name="air"})
if tnt_boom then
tnt_boom({x=pos.x, y=pos.y-2, z=pos.z}, {radius=3})
end
minetest.add_item(pos, "df_underworld_items:slade_drill")
else
minetest.set_node(pos, {name=lava_source})
end
return
end
@ -320,8 +400,10 @@ local digging_seal_def = {
minetest.place_schematic({x=pos.x-3, y=pos.y-2, z=pos.z-3}, df_underworld_items.seal_stair_schem, 270, {}, true)
node.param2 = 0
else
tnt.boom(pos, {radius=3})
minetest.set_node(pos, {name="default:lava_source"})
if tnt_boom then
tnt_boom(pos, {radius=3})
end
minetest.set_node(pos, {name=lava_source})
return
end
minetest.set_node(pos, {name="air"})
@ -348,6 +430,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
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)
df_underworld_items.slade_breacher_triggered(pos, player)
end
end)
@ -367,8 +450,10 @@ local inscription_block_def = {
},
paramtype2 = "facedir",
groups = slade_groups,
sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }),
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
is_ground_content = false,
_mcl_blast_resistance = slade_mcl_blast_resistance,
_mcl_hardness = slade_mcl_hardness,
can_dig = can_dig,
on_blast = function() end,
on_rotate = function() return false end,
@ -405,8 +490,10 @@ local capstone_def = {
paramtype2 = "facedir",
groups = slade_groups,
light_source = 8,
sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }),
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
is_ground_content = false,
_mcl_blast_resistance = slade_mcl_blast_resistance,
_mcl_hardness = slade_mcl_hardness,
can_dig = can_dig,
on_blast = function() end,
on_rotate = function() return false end,
@ -418,7 +505,6 @@ minetest.register_node("df_underworld_items:slade_capstone", capstone_def)
-- Schematics
local n1 = { name = "df_underworld_items:slade_block" }
local n5 = { name = "default:meselamp" }
local n6 = { name = "air", prob = 0 } -- ceiling pieces to leave in place
local n8 = { name = "df_underworld_items:puzzle_seal" }
local n3 = { name = "air"}
@ -435,38 +521,33 @@ local n14 = { name = "df_underworld_items:inscription_block", param2 = 2 }
local n15 = { name = "df_underworld_items:inscription_block", param2 = 3 }
local n16 = { name = "df_underworld_items:slade_capstone"}
if minetest.get_modpath("stairs") then
local stair_groups = {level = 3, mese_radiation_shield=1, pit_plasma_resistant=1, slade=1, cracky = 3}
if invulnerable then
stair_groups.immortal = 1
end
df_dependencies.register_stairs("slade_block")
stairs.register_stair_and_slab(
"slade_block",
"df_underworld_items:slade_block",
stair_groups,
{"dfcaverns_slade_block.png"},
S("Slade Block Stair"),
S("Slade Block Slab"),
default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } })
)
if invulnerable then
for name, def in pairs(minetest.registered_nodes) do
if name:sub(1,7) == "stairs:" and name:sub(-11) == "slade_block" then
if invulnerable then
for name, def in pairs(minetest.registered_nodes) do
if (name:sub(1,7) == "stairs:" and name:sub(-11) == "slade_block") or
name:sub(1,11) == "mcl_stairs:" and name:sub(-11) == "slade_block" then
minetest.override_item(name, {can_dig = can_dig})
end
end
end
n2 = { name = "stairs:stair_slade_block", param2 = 3 }
n4 = { name = "stairs:stair_slade_block", param2 = 1 }
n7 = { name = "stairs:stair_slade_block", param2 = 2 }
n9 = { name = "stairs:stair_slade_block" }
n10 = { name = "stairs:slab_slade_block", param2 = 21 }
n11 = { name = "stairs:slab_slade_block", param2 = 1 }
end
if df_dependencies.node_name_stair_slade_block then
n2 = { name = df_dependencies.node_name_stair_slade_block, param2 = 3 }
n4 = { name = df_dependencies.node_name_stair_slade_block, param2 = 1 }
n7 = { name = df_dependencies.node_name_stair_slade_block, param2 = 2 }
n9 = { name = df_dependencies.node_name_stair_slade_block }
n11 = { name = df_dependencies.node_name_slab_slade_block, param2 = 1 }
n10 = { name = df_dependencies.node_name_slab_slade_block, param2 = 21 }
if df_dependencies.node_name_slab_slade_block_top then
-- Mineclone slabs don't support full rotation, this is how to flip them over
n10.name = df_dependencies.node_name_slab_slade_block_top
n10.param2 = 1
end
end
df_underworld_items.seal_temple_schem = {
size = {y = 6, x = 7, z = 7},
data = {

View File

@ -1,3 +1,4 @@
dfcaverns_invulnerable_slade (Slade cannot be damaged) bool true
dfcaverns_destructive_pit_plasma (Pit plasma destroys adjacent nodes) bool true
dfcaverns_underworld_hunter_statues (Enable hunter statues in the underworld) bool true
dfcaverns_underworld_hunter_statues (Enable hunter statues in the underworld) bool true
dfcaverns_enable_slade_drill (Enable slade drills) bool true

View File

@ -1,4 +1,4 @@
local S = df_underworld_items.S
local S = minetest.get_translator(minetest.get_current_modname())
local invulnerable = df_underworld_items.config.invulnerable_slade and not minetest.settings:get_bool("creative_mode")
@ -15,16 +15,20 @@ local add_immortality = function(slade_def)
return slade_def
end
local slade_groups = {cracky=3, stone=1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1,creative_breakable=1, building_block=1, material_stone=1}
local slade_def = {
description = S("Slade"),
_doc_items_longdesc = df_underworld_items.doc.slade_desc,
_doc_items_usagehelp = df_underworld_items.doc.slade_usage,
tiles = {"dfcaverns_slade.png"},
groups = {cracky=3, stone=1, level=3, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1},
sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }),
groups = slade_groups,
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
is_ground_content = false,
_mcl_blast_resistance = 8,
_mcl_hardness = 5,
on_blast = function(pos, intensity)
if intensity > 3.0 then
if intensity >= 1.0 then
minetest.set_node(pos, {name="df_underworld_items:slade_sand"})
minetest.check_for_falling(pos)
end
@ -32,6 +36,8 @@ local slade_def = {
}
if invulnerable then
add_immortality(slade_def)
slade_def._mcl_blast_resistance = 8
slade_def._mcl_hardness = 5
end
minetest.register_node("df_underworld_items:slade", slade_def)
@ -40,15 +46,23 @@ local slade_brick_def = {
_doc_items_longdesc = df_underworld_items.doc.slade_desc,
_doc_items_usagehelp = df_underworld_items.doc.slade_usage,
tiles = {"dfcaverns_slade_brick.png"},
groups = { cracky=3, stone=1, level=3, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1},
sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }),
groups = slade_groups,
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
is_ground_content = false,
_mcl_blast_resistance = 8,
_mcl_hardness = 5,
}
if invulnerable then
add_immortality(slade_brick_def)
end
minetest.register_node("df_underworld_items:slade_brick", slade_brick_def)
-- can't use "wall=1" because MCL has special handling for nodes in that group that explodes if it tries handling this one.
-- fortunately minetest_game walls also connect to group fence, so this should be fine.
local slade_wall_groups = {fence=1}
for key, val in pairs(slade_groups) do
slade_wall_groups[key]=val
end
local slade_wall_def = {
description = S("Slade Wall"),
drawtype = "nodebox",
@ -66,25 +80,26 @@ local slade_wall_def = {
tiles = {"dfcaverns_slade_brick.png"},
walkable = true,
is_ground_content = false,
groups = { cracky=3, stone=1, level=3, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1},
sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }),
groups = slade_wall_groups,
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
_mcl_blast_resistance = 8,
_mcl_hardness = 5,
}
if invulnerable then
add_immortality(slade_wall_def)
end
minetest.register_node("df_underworld_items:slade_wall", slade_wall_def)
minetest.register_node("df_underworld_items:slade_sand", {
description = S("Slade Sand"),
_doc_items_longdesc = df_underworld_items.doc.slade_desc,
_doc_items_usagehelp = df_underworld_items.doc.slade_usage,
tiles = {"dfcaverns_slade_sand.png"},
is_ground_content = false,
groups = {crumbly = 3, level = 2, falling_node = 1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1},
sounds = default.node_sound_gravel_defaults({
footstep = {name = "default_gravel_footstep", gain = 0.45},
}),
groups = {crumbly = 3, falling_node = 1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1,handy=1,shovely=3, sand=1, enderman_takable=1, building_block=1, material_sand=1, crush_after_fall=1, falling_node_damage=1},
sounds = df_dependencies.sound_gravel({footstep = {name = df_dependencies.soundfile_gravel_footstep, gain = 0.45},}),
_mcl_blast_resistance = 8,
_mcl_hardness = 3,
})
local slade_block_def = {
@ -92,9 +107,11 @@ local slade_block_def = {
_doc_items_longdesc = df_underworld_items.doc.slade_desc,
_doc_items_usagehelp = df_underworld_items.doc.slade_usage,
tiles = {"dfcaverns_slade_block.png"},
groups = {cracky=3, stone=1, level=3, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1},
sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }),
groups = slade_groups,
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
is_ground_content = false,
_mcl_blast_resistance = 1200,
_mcl_hardness = 50,
}
if invulnerable then
add_immortality(slade_block_def)
@ -108,9 +125,11 @@ local slade_seal_def = {
_doc_items_longdesc = df_underworld_items.doc.slade_seal_desc,
_doc_items_usagehelp = df_underworld_items.doc.slade_usage,
tiles = {"dfcaverns_slade_block.png^dfcaverns_seal.png", "dfcaverns_slade_block.png"},
groups = {cracky=3, stone=1, level=3, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1},
sounds = default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } }),
groups = slade_groups,
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
is_ground_content = false,
_mcl_blast_resistance = 1200,
_mcl_hardness = 50,
}
if invulnerable then
slade_seal_def.on_blast = function() end
@ -118,7 +137,15 @@ if invulnerable then
end
minetest.register_node("df_underworld_items:slade_seal", slade_seal_def)
minetest.register_craft({
type = "shapeless",
output = "df_underworld_items:slade_brick",
recipe = {
"df_underworld_items:slade_sand",
df_dependencies.node_name_bucket_lava,
},
replacements = {{df_dependencies.node_name_bucket_lava, df_dependencies.node_name_bucket_empty}},
})
minetest.register_abm{
label = "slade seal scratching",
@ -140,33 +167,18 @@ minetest.register_abm{
-- Register stair and slab
if minetest.get_modpath("stairs") then
local stair_groups = {level = 3, mese_radiation_shield=1, pit_plasma_resistant=1, slade=1}
if invulnerable then
stair_groups.immortal = 1
end
stair_groups.cracky = 3
stairs.register_stair_and_slab(
"slade_brick",
"df_underworld_items:slade_brick",
stair_groups,
{"dfcaverns_slade_brick.png"},
S("Slade Stair"),
S("Slade Slab"),
default.node_sound_stone_defaults({ footstep = { name = "bedrock2_step", gain = 1 } })
)
if invulnerable then
for name, def in pairs(minetest.registered_nodes) do
if name:sub(1,7) == "stairs:" and name:sub(-11) == "slade_brick" then
minetest.override_item(name, {can_dig = server_diggable_only})
end
df_dependencies.register_stairs("slade_brick")
if invulnerable then
for name, def in pairs(minetest.registered_nodes) do
if (name:sub(1,7) == "stairs:" and name:sub(-11) == "slade_block") or
name:sub(1,11) == "mcl_stairs:" and name:sub(-11) == "slade_brick" then
minetest.override_item(name, {can_dig = server_diggable_only})
end
end
end
if minetest.get_modpath("mesecons_mvps") and df_underworld_items.config.invulnerable_slade then
mesecon.register_mvps_stopper("df_underworld_items:slade")
end

View File

@ -0,0 +1,84 @@
local S = minetest.get_translator(minetest.get_current_modname())
local use_timeout = {}
local check_timeout = function(user)
if not user:is_player() then return false end
local player_name = user:get_player_name()
local curr_time = minetest.get_gametime() -- minetest.get_us_time() for microsecond precision
local last_used = use_timeout[player_name]
if not last_used or curr_time > last_used then
use_timeout[player_name] = curr_time
return true
end
end
local drill_particles = function(pos)
minetest.add_particlespawner({
amount = 25,
time = 0.5,
minpos = pos,
maxpos = pos,
minvel = {x=-5, y=0, z=-5},
maxvel = {x=5, y=10, z=5},
minacc = {x=0, y=-10, z=0},
maxacc = {x=0, y=-10, z=0},
minexptime = 2.5,
maxexptime = 7.5,
minsize = 1,
maxsize = 5,
texture = "dfcaverns_glowpit_particle.png",
collisiondetection = true,
collision_removal = true,
glow = 15,
})
end
local slade_drill_def = {
_doc_items_longdesc = df_underworld_items.doc.slade_drill_desc,
_doc_items_usagehelp = df_underworld_items.doc.slade_drill_usage,
light_source = minetest.LIGHT_MAX,
description = S("Slade Drill"),
inventory_image = "dfcaverns_slade_drill.png",
groups = {cracky=3, stone=1, slade=1, pit_plasma_resistant=1, mese_radiation_shield=1,creative_breakable=1, material_stone=1},
sounds = df_dependencies.sound_stone({ footstep = { name = "bedrock2_step", gain = 1 } }),
_mcl_blast_resistance = 8,
_mcl_hardness = 5,
on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type == "node" then
local pos = pointed_thing.under
local node = minetest.get_node(pos)
if node.name == "df_underworld_items:slade" and check_timeout(user) then
if not minetest.is_creative_enabled(user:get_player_name()) then
itemstack:set_wear(itemstack:get_wear()+1)
end
minetest.sound_play("dfcaverns_slade_drill", {pos = user:get_pos()})
minetest.set_node(pos, {name="df_underworld_items:slade_sand"})
drill_particles(pointed_thing.above)
return itemstack
end
end
end,
}
local tnt_boom = df_dependencies.tnt_boom
if tnt_boom then
slade_drill_def.on_use = function(itemstack, user, pointed_thing)
if not check_timeout(user) then return end
local pos
if pointed_thing.type == "node" then pos = pointed_thing.under
elseif pointed_thing.type == "object" then pos = pointed_thing.ref:get_pos() end
if pos then
tnt_boom(pos, {radius=1})
minetest.sound_play("dfcaverns_slade_drill", {pos = user:get_pos()})
if not minetest.is_creative_enabled(user:get_player_name()) then
itemstack:set_wear(itemstack:get_wear()+1)
end
drill_particles(pos)
minetest.check_for_falling({x=pos.x, y=pos.y+1, z=pos.z})
return itemstack
end
end
end
minetest.register_tool("df_underworld_items:slade_drill", slade_drill_def)

Binary file not shown.

View File

@ -15,4 +15,9 @@ dfcaverns_seal_unlocked.ogg - from https://freesound.org/people/juskiddink/sound
dfcaverns_seal_key.ogg - From https://freesound.org/people/megashroom/sounds/391488/ by megashroom under the CC0 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
dfcaverns_massive_digging.3.ogg - from https://freesound.org/people/OGsoundFX/sounds/423120/ by OGsoundFX under Creative Commons BY 3.0
dfcaverns_drill - from https://freesound.org/people/Jagadamba/sounds/257021/ by Jagadamba under the CC-BY-A 3.0 license
dfcaverns_puzzle_chest_open - from https://freesound.org/people/Garuda1982/sounds/560304/ by Garuda1982 under CC-BY-A 4.0
dfcaverns_puzzle_chest_close - from https://freesound.org/people/Benboncan/sounds/74441/ by Benboncan under CC-BY-A 4.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.