Prepare for learnable recipes and abilities

This commit is contained in:
Evert Prants 2019-11-05 23:36:44 +02:00
parent 3e48788251
commit 37aaf600dd
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
9 changed files with 231 additions and 30 deletions

View File

@ -31,3 +31,23 @@ minetest.register_craftitem("magicalities:transterra", {
groups = {shard = 1, transterra = 1} 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
})

View File

@ -29,10 +29,15 @@ minetest.register_craftitem("magicalities:focus_teleport", {
local targ = ray:next() local targ = ray:next()
local can_go = targ == nil local can_go = targ == nil
-- Go above node
if targ and targ.type == "node" then if targ and targ.type == "node" then
local abv = minetest.get_node(targ.above) local abv = minetest.get_node(targ.above)
if not abv or abv.name == "air" then 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 can_go = true
end end
end end

View File

@ -16,6 +16,9 @@ magicalities.elements = {
-- Inherited Elements -- Inherited Elements
} }
-- Storage
dofile(modpath.."/storage.lua")
-- Crystals -- Crystals
dofile(modpath.."/crystals.lua") dofile(modpath.."/crystals.lua")

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 optional_depends = craftguide,fluid_lib,creative

View File

@ -8,6 +8,24 @@ for name, data in pairs(magicalities.elements) do
end end
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 -- -- Arcane crafting recipes --
----------------------------- -----------------------------
@ -154,24 +172,6 @@ for _, recipe in pairs(recipes) do
magicalities.arcane.register_recipe(recipe) magicalities.arcane.register_recipe(recipe)
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,
})
-------------------- --------------------
-- Basic Crafting -- -- Basic Crafting --
-------------------- --------------------
@ -283,3 +283,10 @@ if minetest.get_modpath("craftguide") ~= nil then
register_craftguide_recipe("cauldron", v.output, v.items) register_craftguide_recipe("cauldron", v.output, v.items)
end end
end end
-- Other
magicalities.register_ability_learnable({
name = "magicalities:pickup_jarred",
description = "pick up nodes using jars"
})

View File

@ -11,10 +11,14 @@
-- Modstorage -- Modstorage
local storage = minetest.get_mod_storage() local storage = minetest.get_mod_storage()
local abilities = {}
local recipes = {}
-- Memory cache -- Memory cache
magicalities.data = {} magicalities.data = {}
-- Storage actions
function magicalities.load_player_data(player_name) function magicalities.load_player_data(player_name)
local stdata = minetest.deserialize(storage:get_string(player_name)) local stdata = minetest.deserialize(storage:get_string(player_name))
@ -49,4 +53,120 @@ function magicalities.save_all_data()
end end
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_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)

View File

@ -68,6 +68,20 @@ local function arcane_table_formspec(requirements, present)
end end
function magicalities.arcane.register_recipe(data) 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) table.insert(magicalities.arcane.recipes, data)
end end
@ -142,12 +156,18 @@ function magicalities.arcane.get_recipe(items)
local recipe = compare_find(split) local recipe = compare_find(split)
if not recipe then return nil end 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 for _,stack in pairs(items) do
stack:take_item(1) stack:take_item(1)
result.new_input[#result.new_input + 1] = stack result.new_input[#result.new_input + 1] = stack
end end
print(dump(recipe))
if recipe.learnable then
result.learn = recipe.output
end
return result return result
end end
@ -191,23 +211,23 @@ local function set_output(pos)
-- Check for wand -- Check for wand
local wand = inv:get_stack("wand", 1) local wand = inv:get_stack("wand", 1)
if not wand or wand:is_empty() then if not wand or wand:is_empty() then
return nil, result.requirements return nil, result
end end
-- Check requirements -- Check requirements
local requirements = result.requirements local requirements = result.requirements
if not magicalities.wands.wand_has_contents(wand, requirements) then if not magicalities.wands.wand_has_contents(wand, requirements) then
return nil, result.requirements return nil, result
end end
-- Output fits -- Output fits
local output = ItemStack(result.output) local output = ItemStack(result.output)
if not inv:room_for_item("craftres", output) then 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 end
-- Set output -- Set output
return output, result.requirements return output, result
end end
local function requirements_present(requirements, wand) local function requirements_present(requirements, wand)
@ -222,12 +242,22 @@ end
local function update_craft(pos) local function update_craft(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() 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 local present = requirements_present(recipe.requirements, wand)
meta:set_string("formspec", arcane_table_formspec(reqs, present))
if recipe.requirements then
meta:set_string("formspec", arcane_table_formspec(recipe.requirements, present))
else else
meta:set_string("formspec", arcane_table_formspec({})) meta:set_string("formspec", arcane_table_formspec({}))
end end

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 B

View File

@ -45,7 +45,7 @@ end
magicalities.wands.transform_recipes = { magicalities.wands.transform_recipes = {
["group:enchanted_table"] = {result = "magicalities:arcane_table", requirements = nil}, ["group:enchanted_table"] = {result = "magicalities:arcane_table", requirements = nil},
["default:bookshelf"] = {result = "magicalities:book", requirements = nil, drop = true}, ["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}, ["group:tree"] = {result = "magicalities:tree_enchanted", requirements = nil},
} }
@ -77,6 +77,11 @@ function magicalities.wands.get_wand_focus(stack)
return focus, itemdef return focus, itemdef
end 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) local function focus_requirements(stack, fdef)
if fdef["_wand_requirements"] then if fdef["_wand_requirements"] then
return magicalities.wands.wand_has_contents(stack, fdef["_wand_requirements"]) 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 node = minetest.get_node(pointed_thing.under)
local imeta = itemstack:get_meta() local imeta = itemstack:get_meta()
-- Set last wand user
imeta:set_string("player", placer:get_player_name())
-- Initialize wand metadata -- Initialize wand metadata
if imeta:get_string("contents") == nil or imeta:get_string("contents") == "" then if imeta:get_string("contents") == nil or imeta:get_string("contents") == "" then
initialize_wand(itemstack) initialize_wand(itemstack)
@ -278,6 +286,9 @@ end
local function use_wand(itemstack, user, pointed_thing) local function use_wand(itemstack, user, pointed_thing)
local imeta = itemstack:get_meta() local imeta = itemstack:get_meta()
-- Set last wand user
imeta:set_string("player", user:get_player_name())
-- Initialize wand metadata -- Initialize wand metadata
if imeta:get_string("contents") == "" then if imeta:get_string("contents") == "" then
initialize_wand(itemstack) initialize_wand(itemstack)
@ -320,6 +331,11 @@ local function use_wand(itemstack, user, pointed_thing)
end end
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 if to_replace then
local take_req = true local take_req = true