Guidebook!

This commit is contained in:
Evert Prants 2019-11-08 20:39:07 +02:00
parent 80b8364527
commit d8350bd491
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
16 changed files with 292 additions and 30 deletions

View File

@ -79,6 +79,10 @@ function magicalities.available_to_player(player_name, unlocked, researchable)
return all return all
end end
local function no_newline(str)
return str:gsub("\n(.*)", "")
end
-- Learn a recipe or an ability -- Learn a recipe or an ability
function magicalities.player_learn(player_name, item, recipe, silent) function magicalities.player_learn(player_name, item, recipe, silent)
if not magicalities.data[player_name] then if not magicalities.data[player_name] then
@ -91,7 +95,7 @@ function magicalities.player_learn(player_name, item, recipe, silent)
if recipe and not magicalities.player_has_recipe(player_name, item) then if recipe and not magicalities.player_has_recipe(player_name, item) then
local recipe_n = recipes[item] local recipe_n = recipes[item]
if recipe_n then if recipe_n then
recipe_n = recipe_n.description recipe_n = no_newline(recipe_n.description)
table.insert(magicalities.data[player_name].recipes, item) table.insert(magicalities.data[player_name].recipes, item)
success = true success = true
msgname = msgname .. recipe_n msgname = msgname .. recipe_n
@ -99,7 +103,7 @@ function magicalities.player_learn(player_name, item, recipe, silent)
elseif not recipe and not magicalities.player_has_ability(player_name, item) then elseif not recipe and not magicalities.player_has_ability(player_name, item) then
local ability_n = abilities[item] local ability_n = abilities[item]
if ability_n then if ability_n then
ability_n = ability_n.description ability_n = no_newline(ability_n.description)
table.insert(magicalities.data[player_name].abilities, item) table.insert(magicalities.data[player_name].abilities, item)
success = true success = true
msgname = "to " .. ability_n msgname = "to " .. ability_n

141
book.lua
View File

@ -1,18 +1,135 @@
local function book_formspec(user) local page_cache = {}
local function book_formspec(user, page, scrollindex)
if page then
return "size[8,8]"..
"button[0,0;2,1;back;Back to index]"..
"hypertext[0.1,0.5;7.9,7.5;text;"..page_cache[page].."]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots
end
local avail_list = magicalities.available_to_player(user, true) local avail_list = magicalities.available_to_player(user, true)
return "size[5,6]".. return "size[6,5.7]"..
default.gui_bg.. default.gui_bg..
default.gui_bg_img.. default.gui_bg_img..
default.gui_slots default.gui_slots..
magicalities.researching.generate_formspec_list(avail_list, 0, 0, 5, 5.25, scrollindex, false, true)
end end
local function book_read(itemstack, user, pointed_thing) local function first_key(list)
local uname = user:get_player_name() local ekey
minetest.show_formspec(uname, "magicalities:book", book_formspec(uname)) for key,_ in pairs(list) do
return itemstack ekey = key
break
end
return ekey
end end
local function book_read_page(book, user, page, ptype)
local uname = user:get_player_name()
local check = magicalities.player_has_ability
if ptype == 2 then
check = magicalities.player_has_recipe
end
if not check(uname, page) then return book end
local chapter = "#"..ptype..""..page
if not page_cache[chapter] then
return
end
minetest.show_formspec(uname, "magicalities:book", book_formspec(uname, chapter, 0))
end
local function book_read(book, user, pointed_thing)
local uname = user:get_player_name()
local meta = book:get_meta()
minetest.show_formspec(uname, "magicalities:book", book_formspec(uname, nil, meta:get_int("scrolli")))
return book
end
local function cache_book_pages()
local file = io.open(minetest.get_modpath("magicalities").."/book.txt")
local all = {}
local previous = ""
local since = 0
for line in file:lines() do
if line:sub(0,1) == "#" then
all[line] = ""
previous = line
since = 0
elseif previous ~= "" then
if since > 0 then
line = '\n'..line
end
all[previous] = all[previous] .. line
since = since + 1
end
end
page_cache = all
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "magicalities:book" then return false end
local book = player:get_wielded_item()
if book:get_name() ~= "magicalities:book" then return true end
local bmeta = book:get_meta()
local scrolled = false
local findex = bmeta:get_int("scrolli")
local page
local page_type
local fkey = first_key(fields)
if fields["text"] and fields["text"]:sub(0,6) == "action" then
local pact = fields["text"]:sub(8):gsub("\"", "")
if pact then
fkey = pact
end
end
if fields["dn"] then
scrolled = true
findex = findex + 1
elseif fields["up"] then
scrolled = true
findex = findex - 1
if findex < 0 then
findex = 0
end
elseif fkey and fkey:sub(0,1) == "#" then
page_type = tonumber(fkey:sub(2,2))
page = fkey:sub(3)
elseif fields["back"] then
book_read(book, player)
return true
end
if scrolled then
bmeta:set_int("scrolli", findex)
player:set_wielded_item(book)
book_read(book, player)
return true
end
if not page or not page_type then return true end
-- Handle page
--print("Open page on topic " .. page .. ", which is of type " .. page_type)
book_read_page(book, player, page, page_type)
return true
end)
minetest.register_craftitem("magicalities:book", { minetest.register_craftitem("magicalities:book", {
description = "Magicalities' Guide for Witches and Wizards", description = "Magicalities' Guide for Witches and Wizards",
inventory_image = "magicalities_book.png", inventory_image = "magicalities_book.png",
@ -24,3 +141,13 @@ minetest.register_craftitem("magicalities:book", {
end, end,
stack_max = 1 stack_max = 1
}) })
minetest.register_chatcommand("mgcbookcache", {
privs = {basic_privs = 1},
func = function ()
cache_book_pages()
return true, "Reloaded book cache successfully."
end
})
cache_book_pages()

46
book.txt Normal file
View File

@ -0,0 +1,46 @@
#1magicalities:crystal
<b>Crystals</b> are nodes that you can find in underground - they grow on the ceilings and the floors of caves.
<b>Crystal Tapping</b> is an action in which by <b>right-clicking</b> a crystal with your wand, you can extract elements from it.
#1magicalities:crystal_preserve
The <b>Crystal Preservation</b> ability helps you collect elements from crystals without completely draining them. You learned that when you drain a crystal of it's elements completely, it will not regenerate anything.
#1magicalities:crystal_draining
The <b>Efficient Crystal Draining</b> ability helps you collect elements from crystals 5x faster than normal.
#1magicalities:pickup_jarred
The <b>Crystal Jarring</b> procedure will enable you to collect crystals without removing all of their contents.
When using this method, the crystal will not break into shards, instead it will drop itself.
<big><b>Procedure</b></big>
Surround a crystal in a 3x3 thing of glass, except for the top layer, which has to be wood slabs.
When the structure is complete, hit any node of glass with the <action name="#2magicalities:wand_steel">wand</action>.
<center><item name="stairs:slab_wood" width=64 height=64><item name="stairs:slab_wood" width=64 height=64><item name="stairs:slab_wood" width=64 height=64></center>
<center><item name="default:glass" width=64 height=64><item name="magicalities:crystal_cluster_air" width=64 height=64><item name="default:glass" width=64 height=64></center>
<center><item name="default:glass" width=64 height=64><item name="default:glass" width=64 height=64><item name="default:glass" width=64 height=64></center>
#2magicalities:table
The <b>Research Table</b> is used to do research about various topics in the world of magic.
In order to do research, you need to find knowledge around the world. You can find bookshelves in various structures that will give you the knowledge you need to do your research. If you find a bookshelf that is generated in the world, you can extract knowledge from it by right-clicking.
The Research Table will need three items to operate: Your <b>Guide Book</b> (you're reading it right now!), an <b>Ink and Quill</b> and a piece of paper.
Provided you have acquired sufficient knowledge from exploring the world, you can then dwell deeper into topics you have heard about but don't know all the details of.
#2magicalities:arcane_table
<b>Arcane Table</b> is used for magical crafting. You can create an Arcane Table by <i>using</i> your wand on a Table. Make sure that the table is empty first, though!
<center><item name="magicalities:table" width=64 height=64><img name=magicalities_book_plus.png width=64 height=64><item name="magicalities:wand_steel" width=64 height=64></center>
The Arcane Table will also tell you what elements you need inside of your wand to finish crafting your item.
#2magicalities:cauldron
<b>Cauldron</b> is used for magical crafting. It requires a <b>fire source</b> under it and <b>water</b> to accept items.
Right-Click on the Cauldron with a <b>Bucket of Water</b> in order to fill it with water.
#2magicalities:wand_steel
<b>Wands</b> are used to cast spells. The first wand you know of is called the <b>Steel-Capped Wand</b>, which can contain up to 25 of any element.
#2magicalities:wand_gold
The <b>Gold-Capped Wand</b> is an improved version of the Steel-Capped Wand. It can contain up to 50 of each element instead of the Steel Wand's 25.
#2magicalities:transterra
The <b>Transterra</b> is a stone that can be used to <b>create or remove nodes from the world</b>. It is made in the Cauldron.
<center><item name="default:stone" width=64 height=64><img name=magicalities_book_plus.png width=64 height=64><item name="default:dirt" width=64 height=64><img name=magicalities_book_plus.png width=64 height=64><item name="magicalities:crystal_fire" width=64 height=64></center>
<center><img name=gui_furnace_arrow_bg.png^\[transformFY width=64 height=64></center>
<center><item name="magicalities:cauldron_with_water" width=64 height=64><img name=magicalities_book_plus.png width=64 height=64><item name="magicalities:wand_steel" width=64 height=64></center>
#2magicalities:tellium
<b>Tellium</b> is a metal that can be used to <b>create magical tools</b>. It is made in the Cauldron.
<center><item name="default:steel_ingot" width=64 height=64><img name=magicalities_book_plus.png width=64 height=64><item name="default:obsidian" width=64 height=64></center>
<center><img name=gui_furnace_arrow_bg.png^\[transformFY width=64 height=64></center>
<center><item name="magicalities:cauldron_with_water" width=64 height=64><img name=magicalities_book_plus.png width=64 height=64><item name="magicalities:wand_steel" width=64 height=64></center>
#2magicalities:element_ring
The <b>Elemental Ring</b> can show you what elements a crystal contains and their quantities.
#2magicalities:focus_blank
The <b>Blank Wand Focus</b> is your gateway to the world of <b>Wand Focuses</b>.

View File

@ -86,7 +86,8 @@ local function update_contents(pos, contents)
end end
local function crystal_rightclick(pos, node, clicker, itemstack, pointed_thing) local function crystal_rightclick(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos) local player = clicker:get_player_name()
local meta = minetest.get_meta(pos)
-- Add contents to the crystal -- Add contents to the crystal
local contents = minetest.deserialize(meta:get_string("contents")) local contents = minetest.deserialize(meta:get_string("contents"))
@ -100,13 +101,19 @@ local function crystal_rightclick(pos, node, clicker, itemstack, pointed_thing)
return itemstack return itemstack
end end
-- Check if the player knows anything about the Element Ring, if not, surprise them!
local element_ring = magicalities.player_has_recipe(player, "magicalities:element_ring")
if not element_ring then
magicalities.player_learn(player, "magicalities:element_ring", true)
end
-- Check if player can preserve this crystal -- Check if player can preserve this crystal
local preserve = magicalities.player_has_ability(clicker:get_player_name(), "magicalities:crystal_preserve") local preserve = magicalities.player_has_ability(player, "magicalities:crystal_preserve")
local mincheck = 0 local mincheck = 0
if preserve then mincheck = 1 end if preserve then mincheck = 1 end
-- Check if we can take more than one -- Check if we can take more than one
local draining = magicalities.player_has_ability(clicker:get_player_name(), "magicalities:crystal_draining") local draining = magicalities.player_has_ability(player, "magicalities:crystal_draining")
local maxtake = 1 local maxtake = 1
if draining then maxtake = 5 end if draining then maxtake = 5 end
@ -124,13 +131,17 @@ local function crystal_rightclick(pos, node, clicker, itemstack, pointed_thing)
end end
end end
local done_did = 0
local can_put = magicalities.wands.wand_insertable_contents(itemstack, one_of_each) local can_put = magicalities.wands.wand_insertable_contents(itemstack, one_of_each)
for name, count in pairs(can_put) do for name, count in pairs(can_put) do
if count > 0 then if count > 0 then
done_did = done_did + count
contents[name][1] = contents[name][1] - count contents[name][1] = contents[name][1] - count
end end
end end
if done_did == 0 then return itemstack end
-- Take - Particles -- Take - Particles
local cpls = clicker:get_pos() local cpls = clicker:get_pos()
cpls.y = cpls.y + 1 cpls.y = cpls.y + 1

View File

@ -1,5 +1,7 @@
-- Wand Focuses -- Wand Focuses
local particles = minetest.settings:get_bool("mgc_particles", true)
-- Constants -- Constants
-- TODO: make settings -- TODO: make settings
magicalities.magic_spray_count = 16 magicalities.magic_spray_count = 16
@ -299,6 +301,7 @@ local special_fn = {}
-- Particles -- Particles
local randparticles = PcgRandom(os.clock()) local randparticles = PcgRandom(os.clock())
local function shoot_particles (user, velocity, color) local function shoot_particles (user, velocity, color)
if not particles then return end
if not color then if not color then
color = "" color = ""
else else

View File

@ -50,5 +50,8 @@ dofile(modpath.."/cauldron.lua")
-- Book -- Book
dofile(modpath.."/book.lua") dofile(modpath.."/book.lua")
-- Map generation
dofile(modpath.."/mapgen.lua")
-- Register -- Register
dofile(modpath.."/register.lua") dofile(modpath.."/register.lua")

16
mapgen.lua Normal file
View File

@ -0,0 +1,16 @@
local nostructures = minetest.settings:get_bool("mgc_skip_structures", false)
if not nostructures then
minetest.register_decoration({
deco_type = "schematic",
place_on = "default:dirt_with_grass",
y_min = 0,
y_max = 31000,
flags = "force_placement, all_floors",
schematic = "schems/magicalities_booktower.mts",
rotation = "random",
place_offset_y = 0,
-- what noise_params should i use instead of this?
fill_ratio = 0.00000001,
})
end

View File

@ -1,4 +1,4 @@
name = magicalities name = magicalities
description = Magic mod. description = Magic mod.
depends = default depends = default
optional_depends = craftguide,fluid_lib,creative,mobs,mobs_animal,dye optional_depends = craftguide,fluid_lib,creative,mobs,mobs_animal,dye,treasurer

View File

@ -11,6 +11,11 @@ minetest.register_node("magicalities:tree_enchanted", {
on_place = minetest.rotate_node on_place = minetest.rotate_node
}) })
-- circumvent a weird issue
local function add_fix(inv, item)
inv:add_item("main", item)
end
-- Researchable bookshelf -- Researchable bookshelf
-- Supposed to be a generated node that gives Research Notes -- Supposed to be a generated node that gives Research Notes
minetest.register_node("magicalities:bookshelf", { minetest.register_node("magicalities:bookshelf", {
@ -48,8 +53,7 @@ minetest.register_node("magicalities:bookshelf", {
local inv = clicker:get_inventory() local inv = clicker:get_inventory()
if inv:room_for_item("main", item) then if inv:room_for_item("main", item) then
-- idk minetest.after(0.1, add_fix, inv, item)
inv:add_item("main", item)
else else
minetest.item_drop(item, clicker, clicker:get_pos()) minetest.item_drop(item, clicker, clicker:get_pos())
end end

View File

@ -45,7 +45,8 @@ local recipes = {
["fire"] = 15, ["fire"] = 15,
["dark"] = 15, ["dark"] = 15,
["air"] = 15, ["air"] = 15,
} },
learnable = true
}, },
{ {
input = { input = {
@ -358,7 +359,47 @@ if minetest.get_modpath("craftguide") ~= nil then
end end
end end
-- Abilities -- Treasurer mod, add Research Notes as a form of treasure.
if minetest.get_modpath("treasurer") then
treasurer.register_treasure("magicalities:note", 0.35, 5, {1,3}, nil, "tool")
end
---------------
-- Abilities --
---------------
-- Default abilities
magicalities.register_recipe_learnable({
name = "magicalities:wand_steel",
description = "Wands",
default = true,
})
magicalities.register_ability_learnable({
name = "magicalities:crystal",
description = "Crystal Tapping\nExtract elements from crystals",
icon = "magicalities_crystal_gui.png",
default = true,
})
magicalities.register_recipe_learnable({
name = "magicalities:table",
description = "Research Table\nDo research about the magic world",
default = true,
})
magicalities.register_recipe_learnable({
name = "magicalities:arcane_table",
description = "Arcane Table\nCraft magical items",
default = true,
})
magicalities.register_recipe_learnable({
name = "magicalities:cauldron",
description = "Cauldron",
default = true
})
magicalities.register_ability_learnable({ magicalities.register_ability_learnable({
name = "magicalities:crystal_preserve", name = "magicalities:crystal_preserve",
@ -379,9 +420,3 @@ magicalities.register_ability_learnable({
depends = {"magicalities:crystal_preserve"}, depends = {"magicalities:crystal_preserve"},
icon = "magicalities_jarred.png" icon = "magicalities_jarred.png"
}) })
magicalities.register_recipe_learnable({
name = "magicalities:cauldron",
description = "Cauldron",
default = true
})

View File

@ -1,7 +1,7 @@
magicalities.researching = {} magicalities.researching = {}
local function genlist(list, x, y, w, h, index, canlearn) function magicalities.researching.generate_formspec_list(list, x, y, w, h, index, canlearn, canopen)
local i = "" local i = ""
if #list == 0 then return "" end if #list == 0 then return "" end
local ty = 0 local ty = 0
@ -9,7 +9,7 @@ local function genlist(list, x, y, w, h, index, canlearn)
local visualtotal = math.ceil(y + h) local visualtotal = math.ceil(y + h)
local reallist = {} local reallist = {}
for i = index * visualtotal, visualtotal do for i = index * visualtotal, (index * visualtotal) + visualtotal do
if list[i + 1] then if list[i + 1] then
table.insert(reallist, list[i + 1]) table.insert(reallist, list[i + 1])
end end
@ -18,6 +18,12 @@ local function genlist(list, x, y, w, h, index, canlearn)
for _,v in pairs(reallist) do for _,v in pairs(reallist) do
if ty + 1 > visualtotal then break end if ty + 1 > visualtotal then break end
local icon = "" local icon = ""
local t = 1
if v.type == "recipe" then t = 2 end
if canopen then
i = i .. "button["..x..","..(y+ty)..";"..w..",1;#"..t..""..v.name..";]"
end
if v.icon ~= nil then if v.icon ~= nil then
icon = "image["..x..","..(y+ty)..";1,1;"..v.icon.."]" icon = "image["..x..","..(y+ty)..";1,1;"..v.icon.."]"
@ -27,8 +33,6 @@ local function genlist(list, x, y, w, h, index, canlearn)
i = i .. icon .. "label["..(x + 1)..","..(y+ty)..";"..v.description.."]" i = i .. icon .. "label["..(x + 1)..","..(y+ty)..";"..v.description.."]"
if canlearn then if canlearn then
local t = 1
if v.type == "recipe" then t = 2 end
i = i .. "button["..(x+w-1)..","..(y+ty)..";1,1;@"..t..""..v.name..";Learn]" i = i .. "button["..(x+w-1)..","..(y+ty)..";1,1;@"..t..""..v.name..";Learn]"
end end
ty = ty + 1 ty = ty + 1
@ -37,7 +41,7 @@ local function genlist(list, x, y, w, h, index, canlearn)
if index > 0 then if index > 0 then
i = i .. "button["..(x+w)..","..y..";1,1;up;Up]" i = i .. "button["..(x+w)..","..y..";1,1;up;Up]"
elseif total > visualtotal then elseif total > visualtotal then
i = i .. "button["..(x+w)..","..(y+h)..";1,1;dn;Down]" i = i .. "button["..(x+w)..","..(y+h-0.25)..";1,1;dn;Down]"
end end
return i return i
@ -60,7 +64,7 @@ local function table_formspec(player, research, index, canlearn)
"list[context;tools;0.5,1.5;1,1;]".. "list[context;tools;0.5,1.5;1,1;]"..
"image[0.5,2.5;1,1;magicalities_gui_paper_slot.png]".. "image[0.5,2.5;1,1;magicalities_gui_paper_slot.png]"..
"list[context;paper;0.5,2.5;3,3;]".. "list[context;paper;0.5,2.5;3,3;]"..
genlist(list, 1.5, 0.5, 5.5, 2, index, canlearn).. magicalities.researching.generate_formspec_list(list, 1.5, 0.5, 5.5, 2, index, canlearn)..
"list[current_player;main;0,4.25;8,1;]".. "list[current_player;main;0,4.25;8,1;]"..
"list[current_player;main;0,5.5;8,3;8]".. "list[current_player;main;0,5.5;8,3;8]"..
"listring[current_player;main]".. "listring[current_player;main]"..
@ -254,6 +258,7 @@ end
-- Base Table Override -- Base Table Override
minetest.override_item("magicalities:table", { minetest.override_item("magicalities:table", {
description = "Research Table",
on_construct = function (pos) on_construct = function (pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()

Binary file not shown.

6
settingtypes.txt Normal file
View File

@ -0,0 +1,6 @@
# Setting this to true will prevent Magicalities' structures from being placed in the world
mgc_skip_structures (Skip generating Magicalities structures) bool false
# Enable Magicalities' particle effects
mgc_particles (Magicalities particle effects) bool true

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -236,8 +236,10 @@ function magicalities.wands.wand_insertable_contents(stack, to_put)
for name, count in pairs(to_put) do for name, count in pairs(to_put) do
if data_table[name] then if data_table[name] then
if data_table[name] + count < cap + 1 then if data_table[name] + count <= cap then
insertable[name] = count insertable[name] = count
elseif cap - data_table[name] > 0 then
insertable[name] = cap - data_table[name]
end end
end end
end end