\[BROKEN ATM!\]more stuff towards research system
135
ability.lua
Normal file
@ -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
|
20
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
|
||||
})
|
50
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
|
||||
|
@ -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"
|
||||
})
|
||||
|
4
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")
|
||||
|
109
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 },
|
||||
})
|
||||
|
68
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
|
||||
})
|
||||
|
125
research_table.lua
Normal file
@ -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,
|
||||
})
|
105
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)
|
||||
|
31
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
|
||||
|
BIN
textures/magicalities_gui_book_slot.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
textures/magicalities_gui_paper_slot.png
Normal file
After Width: | Height: | Size: 256 B |
BIN
textures/magicalities_gui_quill_slot.png
Normal file
After Width: | Height: | Size: 232 B |
BIN
textures/magicalities_quill.png
Normal file
After Width: | Height: | Size: 349 B |
BIN
textures/magicalities_quill_front.png
Normal file
After Width: | Height: | Size: 219 B |
BIN
textures/magicalities_quill_right.png
Normal file
After Width: | Height: | Size: 304 B |
BIN
textures/magicalities_quill_top.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
textures/magicalities_quill_top_research.png
Normal file
After Width: | Height: | Size: 570 B |
BIN
textures/magicalities_research.png
Normal file
After Width: | Height: | Size: 811 B |
BIN
textures/magicalities_research_complete.png
Normal file
After Width: | Height: | Size: 813 B |
55
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)
|
||||
|