diff --git a/ability.lua b/ability.lua new file mode 100644 index 0000000..6189a49 --- /dev/null +++ b/ability.lua @@ -0,0 +1,135 @@ + +local abilities = {} +local recipes = {} + +function magicalities.player_has_recipe(player, recipe_name) + if not magicalities.data[player] then return false end + return recipes[recipe_name] and (recipes[recipe_name].default == true or table.indexof(magicalities.data[player].recipes, recipe_name) ~= -1) +end + +function magicalities.player_has_ability(player, ability_name) + if not magicalities.data[player] then return false end + return abilities[ability_name] and (abilities[ability_name].default == true or table.indexof(magicalities.data[player].abilities, ability_name) ~= -1) +end + +function magicalities.player_research(player) + if not magicalities.data[player] then return 0 end + return magicalities.data[player].research +end + +-- Check if a recipe/ability depends on another recipe/ability +function magicalities.learn_meets_prerequisites(player_name, item, recipe) + local a = abilities + local c = magicalities.player_has_ability + + if recipe then + a = recipes + c = magicalities.player_has_recipe + end + + if not a[item] then return false end + if a[item].depends then + local can = true + for v in pairs(a[item].depends) do + if not c(player, v) then + can = false + break + end + end + if not can then return false end + end + + return true +end + +-- List all abilities and crafting recipes available to player, (optionally including ones that can immediately be researched) +function magicalities.available_to_player(player_name, unlocked, researchable) + local all = {} + + -- Abilities + for name,data in pairs(abilities) do + local tc = table.copy(data) + tc.type = 'ability' + if magicalities.player_has_ability(player_name, name) and unlocked then + tc.unlocked = true + table.insert(all, tc) + elseif magicalities.learn_meets_prerequisites(player_name, name) and researchable then + tc.unlocked = false + table.insert(all, tc) + end + end + + -- Recipes + for name,data in pairs(recipes) do + local tc = table.copy(data) + tc.type = 'recipe' + if magicalities.player_has_recipe(player_name, name) and unlocked then + tc.unlocked = true + table.insert(all, tc) + elseif magicalities.learn_meets_prerequisites(player_name, name, true) and researchable then + tc.unlocked = false + table.insert(all, tc) + end + end + + return all +end + +-- Learn a recipe or an ability +function magicalities.player_learn(player_name, item, recipe) + if not magicalities.data[player_name] then + magicalities.load_player_data(player_name) + end + + local success = false + local msgname = "to craft " + + if recipe and not magicalities.player_has_recipe(player_name, item) then + local recipe_n = recipes[item] + if recipe_n then + recipe_n = recipe_n.description + end + table.insert(magicalities.data[player_name].recipes, item) + success = true + msgname = msgname .. recipe_n + elseif not recipe and not magicalities.player_has_ability(player_name, item) then + local ability_n = abilities[item] + if ability_n then + ability_n = ability_n.description + end + table.insert(magicalities.data[player_name].abilities, item) + success = true + msgname = "to " .. ability_n + end + + if success then + magicalities.save_player_data(player_name) + minetest.chat_send_player(player_name, "You have learned " .. msgname .. "!") + end +end + +-- Add/remove research points +function magicalities.deal_research_points(player_name, points) + if not magicalities.data[player_name] then + magicalities.load_player_data(player_name) + end + + magicalities.data[player_name].research = magicalities.data[player_name].research + points + if magicalities.data[player_name].research < 0 then + magicalities.data[player_name].research = 0 + end + + magicalities.save_player_data(player_name) +end + +-- Registration + +function magicalities.register_recipe_learnable(data) + if not data.name or not data.description then return end + recipes[data.name] = data +end + +function magicalities.register_ability_learnable(data) + if not data.name or not data.description then return end + abilities[data.name] = data +end diff --git a/book.lua b/book.lua index 2e038e4..22a1201 100644 --- a/book.lua +++ b/book.lua @@ -1,8 +1,26 @@ +local function book_formspec(user) + local avail_list = magicalities.available_to_player(user, true) + print(dump(avail_list)) + return "size[5,6]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots +end + +local function book_read(itemstack, user, pointed_thing) + local uname = user:get_player_name() + minetest.show_formspec(uname, "magicalities:book", book_formspec(uname)) + return itemstack +end + minetest.register_craftitem("magicalities:book", { description = "Magicalities' Guide for Witches and Wizards", inventory_image = "magicalities_book.png", - on_place = function (itemstack, user, pointed_thing) + on_place = book_read, + on_secondary_use = book_read, + _wand_created = function (itemstack, wand, user, pos) + itemstack:get_meta():set_string("player", user:get_player_name()) return itemstack end -}) \ No newline at end of file +}) diff --git a/cauldron.lua b/cauldron.lua index 2759308..9369aa4 100644 --- a/cauldron.lua +++ b/cauldron.lua @@ -1,26 +1,35 @@ local _fldlib = minetest.get_modpath("fluid_lib") ~= nil -magicalities.cauldron = { - recipes = { - { - items = {"default:steel_ingot", "default:obsidian"}, - requirements = { - earth = 1, - dark = 1, - }, - output = "magicalities:tellium" - }, - { - items = {"default:stone", "default:dirt", "magicalities:crystal_fire"}, - requirements = { - fire = 5, - earth = 5, - }, - output = "magicalities:transterra" - } - } -} +magicalities.cauldron = { recipes = {} } + +function magicalities.cauldron.register_recipe(data) + if data.learnable then + local recipe_data = { name = data.output } + if type(data.learnable) == "string" then + recipe_data.name = data.learnable + end + + if type(data.learnable) == "table" then + recipe_data = table.copy(data.learnable) + if not recipe_data.name then + recipe_data.name = data.output + end + data.learnable = recipe_data.name + end + + if not recipe_data.description then + local itm = minetest.registered_items[data.output] + recipe_data.description = itm.description + else + recipe_data.description = data.description .. "" + end + + magicalities.register_recipe_learnable(recipe_data) + end + + table.insert(magicalities.cauldron.recipes, data) +end local function flatten_stacks(stacks) local temp = {} @@ -147,6 +156,7 @@ local _clddef = { end if not recipe then return itemstack end + if recipe.learnable and not magicalities.player_has_recipe(magicalities.wands.get_wand_owner(itemstack), recipe.learnable) then return itemstack end for j = 1, 16 do if not recipe then break end @@ -204,4 +214,4 @@ minetest.register_abm({ end end end -}) \ No newline at end of file +}) diff --git a/craftitems.lua b/craftitems.lua index e1ec59a..7f54d5d 100644 --- a/craftitems.lua +++ b/craftitems.lua @@ -1,4 +1,35 @@ +local function grant_research(itemstack, placer, pointed_thing) + if not placer or placer:get_player_name() == "" then return itemstack end + local name = placer:get_player_name() + local points = math.random(0, 10) + + if points == 0 then + minetest.chat_send_player(name, "This Research Note did not contain anything interesting.") + else + magicalities.deal_research_points(name, points) + minetest.chat_send_player(name, "This Research Note has granted you some knowledge about magic!") + end + + if not (creative and creative.is_enabled_for and creative.is_enabled_for(name)) then + itemstack:take_item(1) + end + + return itemstack +end + +local function learn_research(paper, player) + local name = player:get_player_name() + local meta = paper:get_meta() + local t = meta:get_int("type") + local l = meta:get_string("learn") + if l ~= "" and t ~= 0 then + magicalities.player_learn(name, l, t == 2) + paper:take_item(1) + end + return paper +end + minetest.register_craftitem("magicalities:wand_core", { description = "Wand Core", inventory_image = "magicalities_wand_core.png" @@ -31,23 +62,31 @@ minetest.register_craftitem("magicalities:transterra", { groups = {shard = 1, transterra = 1} }) -local function grant_research(itemstack, placer, pointed_thing) - if not placer or placer:get_player_name() == "" then return itemstack end - local name = placer:get_player_name() - local points = math.random(1, 10) - magicalities.deal_research_points(name, points) - minetest.chat_send_player(name, "This Research Note granted you " .. points .. " Research Points!") - if not (creative and creative.is_enabled_for and creative.is_enabled_for(name)) then - itemstack:take_item(1) - end - return itemstack -end - minetest.register_craftitem("magicalities:note", { - description = "Research Note", + description = "Research Note\nRight-Click to read and learn!", inventory_image = "magicalities_note.png", groups = {note = 1}, on_place = grant_research, on_secondary_use = grant_research }) +minetest.register_craftitem("magicalities:research", { + description = minetest.colorize("#007bff", "Research Paper") .. "\nIncomplete.", + inventory_image = "magicalities_research.png", + groups = {note = 1, not_in_creative_inventory = 1}, + stack_max = 1 +}) + +minetest.register_craftitem("magicalities:research_complete", { + description = minetest.colorize("#f600ff", "Research Paper (Completed)") .. "\nRight-Click to read and learn!", + inventory_image = "magicalities_research_complete.png", + groups = {note = 1, not_in_creative_inventory = 1}, + stack_max = 1, + on_place = learn_research, + on_secondary_use = learn_research +}) + +minetest.register_tool("magicalities:ink_and_quill", { + description = "Ink and Quill", + inventory_image = "magicalities_quill.png" +}) diff --git a/init.lua b/init.lua index fd8a1ef..1ef4a83 100644 --- a/init.lua +++ b/init.lua @@ -19,6 +19,9 @@ magicalities.elements = { -- Storage dofile(modpath.."/storage.lua") +-- Player abilities +dofile(modpath.."/ability.lua") + -- Crystals dofile(modpath.."/crystals.lua") @@ -30,6 +33,7 @@ dofile(modpath.."/focuses.lua") -- Tables dofile(modpath.."/table.lua") +dofile(modpath.."/research_table.lua") -- Nodes dofile(modpath.."/nodes.lua") diff --git a/nodes.lua b/nodes.lua index 1299e1e..396e137 100644 --- a/nodes.lua +++ b/nodes.lua @@ -10,3 +10,112 @@ minetest.register_node("magicalities:tree_enchanted", { on_place = minetest.rotate_node }) + +-- Researchable bookshelf +-- Supposed to be a generated node that gives Research Notes +minetest.register_node("magicalities:bookshelf", { + description = "Wise Bookshelf", + tiles = {"default_wood.png", "default_wood.png", "default_wood.png", + "default_wood.png", "default_bookshelf.png", "default_bookshelf.png"}, + paramtype2 = "facedir", + is_ground_content = false, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3, not_in_creative_inventory = 1}, + sounds = default.node_sound_wood_defaults(), + drop = "default:bookshelf", + on_rightclick = function (pos, node, clicker, itemstack, pointed_thing) + if not clicker or clicker:get_player_name() == "" then return itemstack end + local name = clicker:get_player_name() + local count = math.random(0, 3) + + -- Swap the node with an ordinary bookshelf after inspecting + node.name = "default:bookshelf" + minetest.swap_node(pos, node) + minetest.registered_nodes[node.name].on_construct(pos) + + -- A chance of not getting anything from this bookshelf + if count == 0 then + minetest.chat_send_player(name, "This bookshelf did not contain anything interesting.") + return itemstack + end + + -- Add some books into the new bookshelf + local bookinv = minetest.get_meta(pos):get_inventory() + bookinv:add_item("books", ItemStack("default:book " .. count)) + + -- Give player Research Notes + local item = ItemStack("magicalities:note") + item:set_count(count) + + local inv = clicker:get_inventory() + if inv:room_for_item("main", item) then + -- idk + inv:add_item("main", item) + else + minetest.item_drop(item, clicker, clicker:get_pos()) + end + + minetest.chat_send_player(name, "You have read some of the books in this bookshelf and wrote up some notes.") + + return itemstack + end +}) + +local nboxcollsel = { + type = "fixed", + fixed = { + {-0.375, -0.5, 0.1875, -0.1875, -0.375, 0.375}, -- pot-base + {-0.3125, -0.375, 0.25, -0.25, -0.3125, 0.3125}, -- pot-head + } +} + +local nbox = { + type = "fixed", + fixed = { + {-0.375, -0.5, 0.1875, -0.1875, -0.375, 0.375}, -- pot-base + {-0.3125, -0.375, 0.25, -0.25, -0.3125, 0.3125}, -- pot-head + {-0.28125, -0.3125, 0.125, -0.28125, 0.1875, 0.4375}, -- feather + {-0.5, -0.5, -0.5, 0.5, -0.5, 0.5}, -- paper-base + } +} + +minetest.register_node("magicalities:quill", { + description = "Quill", + tiles = { + "magicalities_quill_top.png", + "magicalities_quill_top.png^[transformFY", + "magicalities_quill_right.png", + "magicalities_quill_right.png^[transformFX", + "magicalities_quill_front.png^[transformFX", + "magicalities_quill_front.png" + }, + drawtype = "nodebox", + paramtype = "light", + sunlight_propagates = true, + paramtype2 = "facedir", + is_ground_content = false, + node_box = nbox, + selection_box = nboxcollsel, + collision_box = nboxcollsel, + groups = { not_in_creative_inventory = 1 }, +}) + +minetest.register_node("magicalities:quill_research", { + tiles = { + "magicalities_quill_top_research.png", + "magicalities_quill_top.png^[transformFY", + "magicalities_quill_right.png", + "magicalities_quill_right.png^[transformFX", + "magicalities_quill_front.png^[transformFX", + "magicalities_quill_front.png" + }, + drawtype = "nodebox", + paramtype = "light", + sunlight_propagates = true, + paramtype2 = "facedir", + is_ground_content = false, + drop = "magicalities:quill", + node_box = nbox, + selection_box = nboxcollsel, + collision_box = nboxcollsel, + groups = { not_in_creative_inventory = 1 }, +}) diff --git a/register.lua b/register.lua index 3cd6d4e..8ad9a55 100644 --- a/register.lua +++ b/register.lua @@ -61,7 +61,8 @@ local recipes = { ["fire"] = 25, ["dark"] = 25, ["air"] = 25, - } + }, + learnable = true }, { input = { @@ -85,6 +86,9 @@ local recipes = { requirements = { ["light"] = 10, ["dark"] = 10, + }, + learnable = { + depends = {"magicalities:tellium"} } }, { @@ -96,6 +100,9 @@ local recipes = { output = "magicalities:focus_atk_earth", requirements = { ["earth"] = 50, + }, + learnable = { + depends = {"magicalities:focus_blank"} } }, { @@ -107,6 +114,9 @@ local recipes = { output = "magicalities:focus_atk_air", requirements = { ["air"] = 50, + }, + learnable = { + depends = {"magicalities:focus_blank"} } }, { @@ -118,6 +128,9 @@ local recipes = { output = "magicalities:focus_atk_water", requirements = { ["water"] = 50, + }, + learnable = { + depends = {"magicalities:focus_blank"} } }, { @@ -129,6 +142,9 @@ local recipes = { output = "magicalities:focus_atk_fire", requirements = { ["fire"] = 50, + }, + learnable = { + depends = {"magicalities:focus_blank"} } }, { @@ -141,6 +157,9 @@ local recipes = { requirements = { ["earth"] = 25, ["light"] = 25, + }, + learnable = { + depends = {"magicalities:focus_atk_earth"} } }, { @@ -153,6 +172,9 @@ local recipes = { requirements = { ["earth"] = 25, ["dark"] = 25, + }, + learnable = { + depends = {"magicalities:focus_blank", "magicalities:transterra"} } }, { @@ -164,6 +186,9 @@ local recipes = { output = "magicalities:focus_teleport", requirements = { ["air"] = 10, + }, + learnable = { + depends = {"magicalities:focus_blank"} } } } @@ -172,6 +197,35 @@ for _, recipe in pairs(recipes) do magicalities.arcane.register_recipe(recipe) end +-------------- +-- Cauldron -- +-------------- + +local cauldron_recipes = { + { + items = {"default:steel_ingot", "default:obsidian"}, + requirements = { + earth = 1, + dark = 1, + }, + output = "magicalities:tellium", + learnable = true + }, + { + items = {"default:stone", "default:dirt", "magicalities:crystal_fire"}, + requirements = { + fire = 5, + earth = 5, + }, + output = "magicalities:transterra", + learnable = true + } +} + +for _, recipe in pairs(cauldron_recipes) do + magicalities.cauldron.register_recipe(recipe) +end + -------------------- -- Basic Crafting -- -------------------- @@ -279,14 +333,20 @@ if minetest.get_modpath("craftguide") ~= nil then icon = "magicalities_cauldron.png", }) - for g,v in pairs(magicalities.cauldron.recipes) do + for g,v in pairs(cauldron_recipes) do register_craftguide_recipe("cauldron", v.output, v.items) end end --- Other +-- Abilities magicalities.register_ability_learnable({ name = "magicalities:pickup_jarred", - description = "pick up nodes using jars" + description = "pick up crystals using jars" +}) + +magicalities.register_recipe_learnable({ + name = "magicalities:cauldron", + description = "Cauldron", + default = true }) diff --git a/research_table.lua b/research_table.lua new file mode 100644 index 0000000..0afee29 --- /dev/null +++ b/research_table.lua @@ -0,0 +1,125 @@ + +magicalities.researching = {} + +local function table_formspec() + return "size[8,8.5]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "image[0.5,0.5;1,1;magicalities_gui_book_slot.png]".. + "list[context;book;0.5,0.5;1,1;]".. + "image[1.5,0.5;1,1;magicalities_gui_quill_slot.png]".. + "list[context;tools;1.5,0.5;1,1;]".. + "image[2.5,0.5;1,1;magicalities_gui_paper_slot.png]".. + "list[context;paper;2.5,0.5;3,3;]".. + "list[current_player;main;0,4.25;8,1;]".. + "list[current_player;main;0,5.5;8,3;8]".. + "listring[current_player;main]".. + "listring[context;book]".. + "listring[current_player;main]".. + "listring[context;paper]".. + "listring[current_player;main]".. + "listring[context;tools]".. + "listring[current_player;main]".. + default.get_hotbar_bg(0, 4.25) +end + +local function table_use(pos, node, clicker, itemstack, pointed_thing) + return itemstack +end + +local function allow_metadata_inventory_put (pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + + if (listname == "book" and stack:get_name() ~= "magicalities:book") or + (listname == "paper" and stack:get_name() ~= "magicalities:research" and stack:get_name() ~= "default:paper") or + (listname == "tools" and stack:get_name() ~= "magicalities:ink_and_quill") then + return 0 + end + + return 1 +end + +local function allow_metadata_inventory_move (pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local stack = inv:get_stack(from_list, from_index) + + return allow_metadata_inventory_put(pos, to_list, to_index, stack, player) +end + +local function allow_metadata_inventory_take (pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + return stack:get_count() +end + +local function table_inventory_changed (pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + local vec = vector.add(pos,{x=0,y=1,z=0}) + local node = minetest.get_node_or_nil(vec) + if inv:get_stack("tools", 1):is_empty() then + if node and (node.name == "magicalities:quill" or node.name == "magicalities:quill_research") then + minetest.set_node(vec, {name="air"}) + end + elseif node then + local dir = minetest.dir_to_facedir(vector.normalize(vector.subtract(pos, player:get_pos())), false) + local ver = "magicalities:quill" + if not inv:get_stack("paper", 1):is_empty() then + ver = "magicalities:quill_research" + end + minetest.set_node(vec, {name=ver,param2=dir}) + end +end + +-- Base Table Override +minetest.override_item("magicalities:table", { + on_construct = function (pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("book", 1) + inv:set_size("tools", 1) + inv:set_size("paper", 1) + + meta:set_string("formspec", table_formspec()) + end, + on_destruct = function (pos) + local vec = vector.add(pos,{x=0,y=1,z=0}) + local node = minetest.get_node_or_nil(vec) + if node and node.name == "magicalities:quill" then + minetest.set_node(vec, {name="air"}) + end + end, + on_rightclick = table_use, + can_dig = function (pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:get_stack("book", 1):is_empty() and inv:get_stack("paper", 1):is_empty() and inv:get_stack("tools", 1):is_empty() + end, + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_take = allow_metadata_inventory_take, + allow_metadata_inventory_move = allow_metadata_inventory_move, + on_metadata_inventory_take = table_inventory_changed, + on_metadata_inventory_put = table_inventory_changed, + on_metadata_inventory_move = table_inventory_changed, +}) + +-- Remove floating quills +minetest.register_lbm({ + label = "Remove floating quills", + name = "magicalities:quill_cleanup", + nodenames = {"magicalities:quill", "magicalities:quill_research"}, + run_at_every_load = true, + action = function(pos, node) + local vecunder = vector.add(pos,{x=0,y=-1,z=0}) + local nodeunder = minetest.get_node_or_nil(vecunder) + if not nodeunder or nodeunder.name ~= "magicalities:table" then + minetest.set_node(pos, {name="air"}) + end + end, +}) diff --git a/storage.lua b/storage.lua index 77e7803..f7b8ed1 100644 --- a/storage.lua +++ b/storage.lua @@ -11,8 +11,6 @@ -- Modstorage local storage = minetest.get_mod_storage() -local abilities = {} -local recipes = {} -- Memory cache magicalities.data = {} @@ -53,109 +51,6 @@ function magicalities.save_all_data() end end --- Getters - -function magicalities.player_has_recipe(player, recipe_name) - if not magicalities.data[player] then return false end - return table.indexof(magicalities.data[player].recipes, recipe_name) ~= -1 -end - -function magicalities.player_has_ability(player, ability_name) - if not magicalities.data[player] then return false end - return table.indexof(magicalities.data[player].abilities, ability_name) ~= -1 -end - -function magicalities.player_research(player) - if not magicalities.data[player] then return 0 end - return magicalities.data[player].research -end - --- Check if a recipe/ability depends on another recipe/ability -function magicalities.learn_meets_prerequisites(player_name, item, recipe) - local a = abilities - local c = magicalities.player_has_ability - - if recipe then - a = recipes - c = magicalities.player_has_recipe - end - - if not a[item] then return false end - if a[item].depends then - local can = true - for v in pairs(a[item].depends) do - if not c(player, v) then - can = false - break - end - end - if not can then return false end - end - - return true -end - --- Setters - --- Learn a recipe or an ability -function magicalities.player_learn(player_name, item, recipe) - if not magicalities.data[player_name] then - magicalities.load_player_data(player_name) - end - - local success = false - local msgname = "to craft " - - if recipe and not magicalities.player_has_recipe(player_name, item) then - local recipe_n = recipes[item] - if recipe_n then - recipe_n = recipe_n.description - end - table.insert(magicalities.data[player_name].recipes, item) - success = true - msgname = msgname .. recipe_n - elseif not recipe and not magicalities.player_has_ability(player_name, item) then - local ability_n = abilities[item] - if ability_n then - ability_n = ability_n.description - end - table.insert(magicalities.data[player_name].abilities, item) - success = true - msgname = "to " .. ability_n - end - - if success then - magicalities.save_player_data(player_name) - minetest.chat_send_player(player_name, "You have learned " .. msgname .. "!") - end -end - --- Add/remove research points -function magicalities.deal_research_points(player_name, points) - if not magicalities.data[player_name] then - magicalities.load_player_data(player_name) - end - - magicalities.data[player_name].research = magicalities.data[player_name].research + points - if magicalities.data[player_name].research < 0 then - magicalities.data[player_name].research = 0 - end - - magicalities.save_player_data(player_name) -end - --- Registration - -function magicalities.register_recipe_learnable (data) - if not data.name or not data.description then return end - recipes[data.name] = data -end - -function magicalities.register_ability_learnable (data) - if not data.name or not data.description then return end - abilities[data.name] = data -end - -- System Actions minetest.register_on_shutdown(magicalities.save_all_data) diff --git a/table.lua b/table.lua index 3355aa7..65bd7e4 100644 --- a/table.lua +++ b/table.lua @@ -70,13 +70,24 @@ end function magicalities.arcane.register_recipe(data) if data.learnable then local recipe_data = { name = data.output } + if type(data.learnable) == "string" then + recipe_data.name = data.learnable + end - if not data.description then - local itm = minetest.registered_items[data.output] - recipe_data.description = itm.description + if type(data.learnable) == "table" then + recipe_data = table.copy(data.learnable) + if not recipe_data.name then + recipe_data.name = data.output + end + data.learnable = recipe_data.name else - recipe_data.description = data.description .. "" - data.description = nil + if not data.description then + local itm = minetest.registered_items[data.output] + recipe_data.description = itm.description + else + recipe_data.description = data.description .. "" + data.description = nil + end end magicalities.register_recipe_learnable(recipe_data) @@ -156,18 +167,12 @@ function magicalities.arcane.get_recipe(items) local recipe = compare_find(split) if not recipe then return nil end - local result = {new_input = {}, output = recipe.output, requirements = recipe.requirements, learn = nil} + local result = {new_input = {}, output = recipe.output, requirements = recipe.requirements, learnable = recipe.learnable} for _,stack in pairs(items) do stack:take_item(1) result.new_input[#result.new_input + 1] = stack end - print(dump(recipe)) - - if recipe.learnable then - result.learn = recipe.output - end - return result end @@ -248,7 +253,7 @@ local function update_craft(pos) -- Check if the recipe has been learned by the player local wand = inv:get_stack("wand", 1) if not recipe or wand:is_empty() and - (recipe.learn ~= nil and not magicalities.player_has_recipe(magicalities.wands.get_wand_owner(wand), recipe.learn)) then + (recipe.learnable ~= nil and not magicalities.player_has_recipe(magicalities.wands.get_wand_owner(wand), recipe.learnable)) then meta:set_string("formspec", arcane_table_formspec({})) inv:set_list("craftres", {}) return diff --git a/textures/magicalities_gui_book_slot.png b/textures/magicalities_gui_book_slot.png new file mode 100644 index 0000000..9b6654a Binary files /dev/null and b/textures/magicalities_gui_book_slot.png differ diff --git a/textures/magicalities_gui_paper_slot.png b/textures/magicalities_gui_paper_slot.png new file mode 100644 index 0000000..139482a Binary files /dev/null and b/textures/magicalities_gui_paper_slot.png differ diff --git a/textures/magicalities_gui_quill_slot.png b/textures/magicalities_gui_quill_slot.png new file mode 100644 index 0000000..1c5a112 Binary files /dev/null and b/textures/magicalities_gui_quill_slot.png differ diff --git a/textures/magicalities_quill.png b/textures/magicalities_quill.png new file mode 100644 index 0000000..c4c78de Binary files /dev/null and b/textures/magicalities_quill.png differ diff --git a/textures/magicalities_quill_front.png b/textures/magicalities_quill_front.png new file mode 100644 index 0000000..dcd11a4 Binary files /dev/null and b/textures/magicalities_quill_front.png differ diff --git a/textures/magicalities_quill_right.png b/textures/magicalities_quill_right.png new file mode 100644 index 0000000..de7e383 Binary files /dev/null and b/textures/magicalities_quill_right.png differ diff --git a/textures/magicalities_quill_top.png b/textures/magicalities_quill_top.png new file mode 100644 index 0000000..e09878c Binary files /dev/null and b/textures/magicalities_quill_top.png differ diff --git a/textures/magicalities_quill_top_research.png b/textures/magicalities_quill_top_research.png new file mode 100644 index 0000000..80d6208 Binary files /dev/null and b/textures/magicalities_quill_top_research.png differ diff --git a/textures/magicalities_research.png b/textures/magicalities_research.png new file mode 100644 index 0000000..79b5920 Binary files /dev/null and b/textures/magicalities_research.png differ diff --git a/textures/magicalities_research_complete.png b/textures/magicalities_research_complete.png new file mode 100644 index 0000000..cb6cb61 Binary files /dev/null and b/textures/magicalities_research_complete.png differ diff --git a/wands.lua b/wands.lua index b500bfa..811e23d 100644 --- a/wands.lua +++ b/wands.lua @@ -2,6 +2,15 @@ magicalities.wands = {} +-- This is a method of picking up crystals without breaking them into shards and preserving all of their elements. +-- 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 wand. +-- Views from the side: +-- (middle) +-- sss sss sss +-- ggg gxg ggg +-- ggg ggg ggg +-- s: stairs:slab_wood, g: default:glass, x: group:crystal_cluster local function pickup_jarred(itemstack, user, glassp) local node = minetest.get_node_or_nil(glassp) if not node or node.name ~= "default:glass" then return nil end @@ -133,13 +142,14 @@ function magicalities.wands.update_wand_desc(stack) local elems = {} for elem, amount in pairs(data_table) do local dataelem = magicalities.elements[elem] - if amount > 0 then - if amount < 10 then amount = "0"..amount end - local str = "["..amount.."/"..capcontents.."] " - str = str .. minetest.colorize(dataelem.color, dataelem.description) - if focus and fdef and fdef['_wand_requirements'] and fdef['_wand_requirements'][elem] ~= nil then - str = str .. minetest.colorize("#a070e0", " ("..fdef['_wand_requirements'][elem]..") ") - end + local visual = amount + if amount < 10 then visual = "0" .. amount end + if amount == 0 then visual = minetest.colorize("#ff0505", visual) end + local str = "["..visual.."/"..capcontents.."] " + str = str .. minetest.colorize(dataelem.color, dataelem.description) + if focus and fdef and fdef['_wand_requirements'] and fdef['_wand_requirements'][elem] ~= nil then + elems[#elems + 1] = str .. minetest.colorize("#a070e0", " ("..fdef['_wand_requirements'][elem]..") ") + elseif amount ~= 0 then elems[#elems + 1] = str end end @@ -236,7 +246,7 @@ function magicalities.wands.wand_insertable_contents(stack, to_put) end -- Initialize wand metadata -local function initialize_wand(stack) +local function initialize_wand(stack, player) local data_table = {} for name, data in pairs(magicalities.elements) do @@ -246,6 +256,7 @@ local function initialize_wand(stack) end local meta = stack:get_meta() + meta:set_string("player", player) meta:set_string("contents", minetest.serialize(data_table)) end @@ -255,12 +266,9 @@ local function wand_action(itemstack, placer, pointed_thing) local node = minetest.get_node(pointed_thing.under) local imeta = itemstack:get_meta() - -- Set last wand user - imeta:set_string("player", placer:get_player_name()) - -- Initialize wand metadata if imeta:get_string("contents") == nil or imeta:get_string("contents") == "" then - initialize_wand(itemstack) + initialize_wand(itemstack, placer:get_player_name()) magicalities.wands.update_wand_desc(itemstack) end @@ -286,12 +294,9 @@ end local function use_wand(itemstack, user, pointed_thing) local imeta = itemstack:get_meta() - -- Set last wand user - imeta:set_string("player", user:get_player_name()) - -- Initialize wand metadata if imeta:get_string("contents") == "" then - initialize_wand(itemstack) + initialize_wand(itemstack, user:get_player_name()) magicalities.wands.update_wand_desc(itemstack) end @@ -336,6 +341,15 @@ local function use_wand(itemstack, user, pointed_thing) to_replace = nil end + -- Make sure we can "dig" the node before we, potentially, remove it from the world + if to_replace then + local ndef = minetest.registered_items[node.name] + if ndef.can_dig and not ndef.can_dig(pos, user) then + to_replace = nil + end + end + + -- Commit action if to_replace then local take_req = true @@ -347,10 +361,15 @@ local function use_wand(itemstack, user, pointed_thing) itemstack = t end elseif to_replace.drop then - minetest.add_item(pos, ItemStack(to_replace.result)) + local istack = ItemStack(to_replace.result) + local istackdef = minetest.registered_items[to_replace.result] + if istackdef._wand_created then + istack = istackdef._wand_created(istack, itemstack, user, pos) + end + minetest.add_item(pos, istack) minetest.set_node(pos, {name = "air"}) else - minetest.swap_node(pos, {name = to_replace.result, param1 = node.param1, param2 = node.param2}) + minetest.set_node(pos, {name = to_replace.result, param1 = node.param1, param2 = node.param2}) local spec = minetest.registered_nodes[to_replace.result] if spec.on_construct then spec.on_construct(pos)