diff --git a/collectible_lore/README.md b/collectible_lore/README.md new file mode 100644 index 0000000..0a43332 --- /dev/null +++ b/collectible_lore/README.md @@ -0,0 +1,34 @@ +This mod provides a framework for adding "lore" collectibles, entries that are either a block of text or an image. Players unlock these collectibles by finding stone cairns, and view them by using a "satchel" object. Note that players are not literally carrying these collectibles, whether they've been unlocked is recorded globally and any satchel will allow them to view their collection. + +This is intended as a somewhat similar concept to achievements, but to reward exploration in general and to provide information about the world the player finds themself in. + +An example: + + collectible_lore.register_lorebook({ + id = "banks tunnels", + title = S("Twisting Tunnels"), + text = S([[Today's exploration took us deep into the caverns beneath the surface world. As we progressed, I was reminded of the intricate network of passages that make up the bedrock of this world. + + It is fascinating to see how these passages have been carved by a combination of ancient streams and other mysterious processes that have yet to be fully understood. They twist and turn, making navigation a challenging task. Although it is possible to reach almost any location by following these existing passages, they can be so convoluted that it sometimes makes more sense to simply mine a direct route to your destination. + + The significance of these passages cannot be overstated. They provide a glimpse into the geological history of the world and the forces that shaped it. The passages also hold the promise of valuable mineral deposits and other resources, making them a crucial area of exploration for anyone seeking to unlock the secrets of the earth. + + Signed, + Dr. Theodore Banks]]), + sort = 101, + }) + +The id should be a unique string, this is the key that will be recorded when a player unlocks a collectible. The title is shown in the list of collectibles when it is unlocked. The sort value is used to sort items in the collectible list in increasing order; it doesn't have to be unique, items with the same sort number will fall back to sorting by id. + +Instead of text, an image can be shown: + + collectible_lore.register_lorebook({ + id = "rose watercolor chasm wall", + title = S("Chasm Wall, By Amelia Rose"), + image = "df_lorebooks_chasm_wall.jpg", + sort = 201, + }) + +Note that currently images and text are mutually exclusive, and images should have a square aspect ratio. + +This mod by itself currently only provides a framework and defines the cairn and satchel nodes, you'll need to provide a mapgen to insert them into your world. The ``collectible_lore.place_cairn`` method checks to see if there are nearby cairns before it goes ahead and places a cairn, preventing them from being bunched too closely together, and should prove useful. \ No newline at end of file diff --git a/collectible_lore/init.lua b/collectible_lore/init.lua index 0e481a7..3167588 100644 --- a/collectible_lore/init.lua +++ b/collectible_lore/init.lua @@ -5,6 +5,14 @@ local modmeta = minetest.get_mod_storage() collectible_lore = {} collectible_lore.lorebooks = {} +local ids = {} + +on_collected_callbacks = {} + +collectible_lore.register_on_collected = function(callback) + table.insert(on_collected_callbacks, callback) +end + collectible_lore.get_player_collected = function(player_name) local collected_string = modmeta:get("player_" .. player_name) if collected_string == nil then @@ -27,9 +35,18 @@ collectible_lore.get_player_uncollected_list = function(player_name) end local set_collected = function(player_name, id, state) + if not ids[id] then + minetest.log("error", "[collectible_lore] Setting state for unknown collectible id " .. id .. " for player " .. player_name) + state = nil + end local collected = collectible_lore.get_player_collected(player_name) - collected[id] = state - modmeta:set_string("player_" .. player_name, minetest.serialize(collected)) + if collected[id] ~= state then + collected[id] = state + modmeta:set_string("player_" .. player_name, minetest.serialize(collected)) + for _, callback in ipairs(on_collected_callbacks) do + callback(player_name, id, state, collected) + end + end end collectible_lore.collect = function(player_name, id) @@ -50,8 +67,6 @@ local collectible_lore_sort = function(first, second) return false end -local ids = {} - collectible_lore.register_lorebook = function(def) if def.id == nil then minetest.log("error", "[collectible_lore] nil id for def " .. dump(def)) diff --git a/collectible_lore/items.lua b/collectible_lore/items.lua index 63e854e..4a0c11b 100644 --- a/collectible_lore/items.lua +++ b/collectible_lore/items.lua @@ -90,7 +90,7 @@ minetest.register_node("collectible_lore:cairn", { _doc_items_longdesc = S("A cairn of rocks constructed by a previous explorer to protect documents and supplies."), _doc_items_usagehelp = S("The first time you discover a cairn like this, it may reveal to you some new record or piece of lore. Afterward it can be used as a public storage location."), drawtype = "nodebox", - tiles = {df_dependencies.texture_cobble, df_dependencies.texture_cobble, df_dependencies.texture_cobble .. "^(collectible_lore_cairn_marker.png^[opacity:100)"}, + tiles = {df_dependencies.texture_cobble, df_dependencies.texture_cobble, df_dependencies.texture_cobble .. "^(collectible_lore_cairn_marker.png^[multiply:#100000^[opacity:128)"}, is_ground_content = true, groups = {cracky = 3, container=2}, _mcl_hardness = 1.5, @@ -245,6 +245,15 @@ minetest.register_craftitem("collectible_lore:satchel", { end }) +minetest.register_craft({ + output = "collectible_lore:satchel", + recipe = { + {"", df_dependencies.node_name_string, ""}, + {df_dependencies.node_name_string, "", df_dependencies.node_name_string}, + {df_dependencies.node_name_wool_white, df_dependencies.node_name_wool_white, df_dependencies.node_name_wool_white}, + }, +}) + minetest.register_on_player_receive_fields(function(player, formname, fields) if formname == "collectible_lore:formspec" then if fields.list then diff --git a/df_achievements/locale/template.txt b/df_achievements/locale/template.txt index 82b4f81..c000995 100644 --- a/df_achievements/locale/template.txt +++ b/df_achievements/locale/template.txt @@ -107,6 +107,7 @@ Slightly less prestigious than the Primordial Fruit, but still rare and exotic c Activating a puzzle seal has produced a breach in the slade foundations of the world.= Capture an Ice Sprite= +Collect All Lore= Decipher the code of the ancients. Do you dare turn the key?= Detonate Mine Gas= Get Attacked by an Underworld Guardian= @@ -125,6 +126,8 @@ You've captured an ice sprite and placed it in a bottle. It dances and sparkles You've discovered something important about those mysterious slade statues in the Underworld.= +You've searched the world top to bottom for cairns containing lore and your collection is now complete.= + ### travel.lua ### diff --git a/df_achievements/misc.lua b/df_achievements/misc.lua index e8cd84c..3b25c31 100644 --- a/df_achievements/misc.lua +++ b/df_achievements/misc.lua @@ -82,6 +82,23 @@ if minetest.get_modpath("df_underworld_items") then end +if minetest.get_modpath("df_lorebooks") then + collectible_lore.register_on_collected(function(player_name, id, state, collected) + local count = 0 + for id, val in pairs(collected) do + if val then count = count + 1 end + end + if count >= #(collectible_lore.lorebooks) then + awards.unlock(player_name, "dfcaverns_all_lorebooks_found") + end + end) + awards.register_achievement("dfcaverns_all_lorebooks_found", { + title = S("Collect All Lore"), + difficulty = 4, + description = S("You've searched the world top to bottom for cairns containing lore and your collection is now complete."), + icon = "dfcaverns_awards_backgroundx32.png^dfcaverns_awards_lore_cairnsx32.png^dfcaverns_awards_foregroundx32.png", + }) +end -- can't think of an easy way to detect these --awards.register_achievement("dfcaverns_torch_detonated_mine_gas", { diff --git a/df_achievements/mod.conf b/df_achievements/mod.conf index b7b77ac..5b73f09 100644 --- a/df_achievements/mod.conf +++ b/df_achievements/mod.conf @@ -1,4 +1,4 @@ name=df_achievements description=Achievements for DFCaverns depends=df_caverns, df_trees, df_farming, df_mapitems, df_dependencies, pit_caves -optional_depends=df_underworld_items, hunter_statue, awards, big_webs, bubblesponge \ No newline at end of file +optional_depends=df_underworld_items, hunter_statue, awards, big_webs, bubblesponge, df_lorebooks \ No newline at end of file diff --git a/df_achievements/textures/dfcaverns_awards_lore_cairnsx32.png b/df_achievements/textures/dfcaverns_awards_lore_cairnsx32.png new file mode 100644 index 0000000..2349ce5 Binary files /dev/null and b/df_achievements/textures/dfcaverns_awards_lore_cairnsx32.png differ diff --git a/df_caverns/lorebooks.lua b/df_caverns/lorebooks.lua index 93454d8..b2cf3ee 100644 --- a/df_caverns/lorebooks.lua +++ b/df_caverns/lorebooks.lua @@ -1,6 +1,6 @@ if not minetest.get_modpath("df_lorebooks") then return end -local foundations = {"group:stone", "group:dirt", "group:soil"} +local foundations = {"group:stone", "group:dirt", "group:soil", "group:sand"} minetest.register_on_generated(function(minp, maxp, blockseed) if maxp.y > 0 or maxp.y < df_caverns.config.primordial_min then return end diff --git a/df_lorebooks/ecology_flora.lua b/df_lorebooks/ecology_flora.lua index 5f3e250..9b15801 100644 --- a/df_lorebooks/ecology_flora.lua +++ b/df_lorebooks/ecology_flora.lua @@ -157,7 +157,7 @@ Professor Amelia Rose]]), collectible_lore.register_lorebook({ id = "rose sand scum", title = S("Sand scum"), - text = S([[Today, I encountered something new down here in the caverns, something I never expected to find: Sand Scum. It's a crust of algae that grows on wet sand and, apparently, it's able to survive by utilizing the light from other organisms. + text = S([[Today, I encountered something new down here in the caverns: Sand Scum. It's a crust of algae that grows on wet sand and, apparently, it's able to survive by utilizing the bioluminescent light from other organisms. To be honest, I have to admit that I'm at a loss for words when it comes to Sand Scum. I have tried my best to find something interesting to say about it, but unfortunately, I have failed. It's just not that exciting of a discovery. I suppose it's a good indicator of the diversity of life that can be found in even the harshest environments, but that's about the extent of my thoughts on the matter. diff --git a/df_lorebooks/geology_the_great_caverns.lua b/df_lorebooks/geology_the_great_caverns.lua index 515a21a..afa8e15 100644 --- a/df_lorebooks/geology_the_great_caverns.lua +++ b/df_lorebooks/geology_the_great_caverns.lua @@ -19,8 +19,6 @@ Dr. Theodore Banks]]), sort = base + 0, }) - - collectible_lore.register_lorebook({ id = "banks tunnels", title = S("Twisting Tunnels"), diff --git a/df_lorebooks/locale/template.txt b/df_lorebooks/locale/template.txt index 5e0f5bc..9fea174 100644 --- a/df_lorebooks/locale/template.txt +++ b/df_lorebooks/locale/template.txt @@ -65,7 +65,7 @@ Today, I discovered a new species of mushroom deep in the caverns - the Dimple C Today, I encountered a new species of fungus, known as Stillworm, while exploring the caverns. At first glance, its appearance is that of pale, motionless earthworms intertwined with the soil. Despite being aware that it is a form of fungus, I can't help but feel disturbed by its uncanny resemblance to actual worms. Walking on soil where Stillworm grows is an eerie experience, and I find myself tiptoeing cautiously to avoid stepping on them. Its survival in harsh underground environments is remarkable, but its eerie appearance leaves a lasting impression.@n@nSincerely,@nProfessor Amelia Rose= -Today, I encountered something new down here in the caverns, something I never expected to find: Sand Scum. It's a crust of algae that grows on wet sand and, apparently, it's able to survive by utilizing the light from other organisms.@n@nTo be honest, I have to admit that I'm at a loss for words when it comes to Sand Scum. I have tried my best to find something interesting to say about it, but unfortunately, I have failed. It's just not that exciting of a discovery. I suppose it's a good indicator of the diversity of life that can be found in even the harshest environments, but that's about the extent of my thoughts on the matter.@n@nSincerely,@nProfessor Amelia Rose= +Today, I encountered something new down here in the caverns: Sand Scum. It's a crust of algae that grows on wet sand and, apparently, it's able to survive by utilizing the bioluminescent light from other organisms.@n@nTo be honest, I have to admit that I'm at a loss for words when it comes to Sand Scum. I have tried my best to find something interesting to say about it, but unfortunately, I have failed. It's just not that exciting of a discovery. I suppose it's a good indicator of the diversity of life that can be found in even the harshest environments, but that's about the extent of my thoughts on the matter.@n@nSincerely,@nProfessor Amelia Rose= Today, I had the pleasure of discovering a new species of subterranean fungi - the sweet pods. These mushrooms grow in rich soil, and once they reach maturity, they draw the nutrients from the soil up their pale stalks to concentrate it in their round fruiting bodies. The fruiting bodies turn bright red when ripe and can be processed in a variety of ways to extract the sugars they contain.@n@nWhen dried and milled, the sweet pods produce a granular pink-tinted sugary substance that can be used as a sweetener in a variety of dishes. Additionally, when crushed in a bucket, a flavorful syrup can be squeezed out that can be used as a topping or an ingredient in cooking.@n@nThe sweet pods are a delightful discovery and open up new possibilities for gourmet cooking in the subterranean regions. I can't wait to experiment with different recipes and see what other culinary delights can be created using these delicious mushrooms.@n@nSincerely,@nProfessor Amelia Rose=