diff --git a/craftitems.lua b/craftitems.lua index 3625dfd..e1ec59a 100644 --- a/craftitems.lua +++ b/craftitems.lua @@ -31,3 +31,23 @@ 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", + inventory_image = "magicalities_note.png", + groups = {note = 1}, + on_place = grant_research, + on_secondary_use = grant_research +}) + diff --git a/focuses.lua b/focuses.lua index ad03a90..1f88c90 100644 --- a/focuses.lua +++ b/focuses.lua @@ -29,10 +29,15 @@ minetest.register_craftitem("magicalities:focus_teleport", { local targ = ray:next() local can_go = targ == nil + -- Go above node if targ and targ.type == "node" then local abv = minetest.get_node(targ.above) if not abv or abv.name == "air" then - dest = targ.above + local add = {x=0,y=0,z=0} + if user:get_pos().y < targ.above.y - 1.5 then + add.y = 1.5 + end + dest = vector.add(targ.above, add) can_go = true end end diff --git a/init.lua b/init.lua index 8af2077..fd8a1ef 100644 --- a/init.lua +++ b/init.lua @@ -16,6 +16,9 @@ magicalities.elements = { -- Inherited Elements } +-- Storage +dofile(modpath.."/storage.lua") + -- Crystals dofile(modpath.."/crystals.lua") diff --git a/mod.conf b/mod.conf index 5d850c7..b1b6b5f 100644 --- a/mod.conf +++ b/mod.conf @@ -1,4 +1,4 @@ name = magicalities description = Magic mod. depends = default -optional_depends = craftguide,fluid_lib +optional_depends = craftguide,fluid_lib,creative diff --git a/register.lua b/register.lua index 6a474d2..3cd6d4e 100644 --- a/register.lua +++ b/register.lua @@ -8,6 +8,24 @@ for name, data in pairs(magicalities.elements) do end end +----------- +-- Wands -- +----------- + +-- Iron +magicalities.wands.register_wand("steel", { + description = "Steel-Capped Wand", + image = "magicalities_wand_iron.png", + wand_cap = 25, +}) + +-- Gold +magicalities.wands.register_wand("gold", { + description = "Gold-Capped Wand", + image = "magicalities_wand_gold.png", + wand_cap = 50, +}) + ----------------------------- -- Arcane crafting recipes -- ----------------------------- @@ -154,24 +172,6 @@ for _, recipe in pairs(recipes) do magicalities.arcane.register_recipe(recipe) end ------------ --- Wands -- ------------ - --- Iron -magicalities.wands.register_wand("steel", { - description = "Steel-Capped Wand", - image = "magicalities_wand_iron.png", - wand_cap = 25, -}) - --- Gold -magicalities.wands.register_wand("gold", { - description = "Gold-Capped Wand", - image = "magicalities_wand_gold.png", - wand_cap = 50, -}) - -------------------- -- Basic Crafting -- -------------------- @@ -283,3 +283,10 @@ if minetest.get_modpath("craftguide") ~= nil then register_craftguide_recipe("cauldron", v.output, v.items) end end + +-- Other + +magicalities.register_ability_learnable({ + name = "magicalities:pickup_jarred", + description = "pick up nodes using jars" +}) diff --git a/storage.lua b/storage.lua index 96ea201..77e7803 100644 --- a/storage.lua +++ b/storage.lua @@ -11,10 +11,14 @@ -- Modstorage local storage = minetest.get_mod_storage() +local abilities = {} +local recipes = {} -- Memory cache magicalities.data = {} +-- Storage actions + function magicalities.load_player_data(player_name) local stdata = minetest.deserialize(storage:get_string(player_name)) @@ -49,4 +53,120 @@ 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) + +minetest.register_on_joinplayer(function (player) + magicalities.load_player_data(player:get_player_name()) +end) + +minetest.register_on_leaveplayer(function (player, timed) + local name = player:get_player_name() + magicalities.save_player_data(name) + if timed then return end + magicalities.data[name] = nil +end) diff --git a/table.lua b/table.lua index 5c20dac..3355aa7 100644 --- a/table.lua +++ b/table.lua @@ -68,6 +68,20 @@ local function arcane_table_formspec(requirements, present) end function magicalities.arcane.register_recipe(data) + if data.learnable then + local recipe_data = { name = data.output } + + 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 + + magicalities.register_recipe_learnable(recipe_data) + end + table.insert(magicalities.arcane.recipes, data) end @@ -142,12 +156,18 @@ 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} + local result = {new_input = {}, output = recipe.output, requirements = recipe.requirements, learn = nil} 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 @@ -191,23 +211,23 @@ local function set_output(pos) -- Check for wand local wand = inv:get_stack("wand", 1) if not wand or wand:is_empty() then - return nil, result.requirements + return nil, result end -- Check requirements local requirements = result.requirements if not magicalities.wands.wand_has_contents(wand, requirements) then - return nil, result.requirements + return nil, result end -- Output fits local output = ItemStack(result.output) if not inv:room_for_item("craftres", output) then - return inv:get_stack("craftres", 1), result.requirements + return inv:get_stack("craftres", 1), result end -- Set output - return output, result.requirements + return output, result end local function requirements_present(requirements, wand) @@ -222,12 +242,22 @@ end local function update_craft(pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() - local out, reqs = set_output(pos) + local out, recipe = set_output(pos) - local present = requirements_present(reqs, inv:get_stack("wand", 1)) + -- Make sure wand is inserted + -- 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 + meta:set_string("formspec", arcane_table_formspec({})) + inv:set_list("craftres", {}) + return + end - if reqs then - meta:set_string("formspec", arcane_table_formspec(reqs, present)) + local present = requirements_present(recipe.requirements, wand) + + if recipe.requirements then + meta:set_string("formspec", arcane_table_formspec(recipe.requirements, present)) else meta:set_string("formspec", arcane_table_formspec({})) end diff --git a/textures/magicalities_note.png b/textures/magicalities_note.png new file mode 100644 index 0000000..02247d0 Binary files /dev/null and b/textures/magicalities_note.png differ diff --git a/wands.lua b/wands.lua index 727b369..b500bfa 100644 --- a/wands.lua +++ b/wands.lua @@ -45,7 +45,7 @@ end magicalities.wands.transform_recipes = { ["group:enchanted_table"] = {result = "magicalities:arcane_table", requirements = nil}, ["default:bookshelf"] = {result = "magicalities:book", requirements = nil, drop = true}, - ["default:glass"] = {result = pickup_jarred, requirements = nil}, + ["default:glass"] = {result = pickup_jarred, requirements = nil, learn = "magicalities:pickup_jarred"}, ["group:tree"] = {result = "magicalities:tree_enchanted", requirements = nil}, } @@ -77,6 +77,11 @@ function magicalities.wands.get_wand_focus(stack) return focus, itemdef end +function magicalities.wands.get_wand_owner(stack) + local meta = stack:get_meta() + return meta:get_string("player") +end + local function focus_requirements(stack, fdef) if fdef["_wand_requirements"] then return magicalities.wands.wand_has_contents(stack, fdef["_wand_requirements"]) @@ -250,6 +255,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) @@ -278,6 +286,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) @@ -320,6 +331,11 @@ local function use_wand(itemstack, user, pointed_thing) end end + -- Make sure player has this replacement ability + if to_replace and to_replace.learn and not magicalities.player_has_ability(magicalities.wands.get_wand_owner(itemstack), to_replace.learn) then + to_replace = nil + end + if to_replace then local take_req = true