magicalities/wands.lua

224 lines
5.7 KiB
Lua

-- Magicalities Wands
magicalities.wands = {}
local transform_recipes = {
["mg_table"] = {result = "magicalities:arcane_table", requires = {["earth"] = 5, ["light"] = 5}}
}
local wandcaps = {
full_punch_interval = 1.0,
max_drop_level = 0,
groupcaps = {},
damage_groups = {fleshy = 2},
}
local randparticles = PcgRandom(os.clock())
local function align(len)
local str = ""
for i = 1, len do
str = str.."\t"
end
return str
end
-- Update wand's description
function magicalities.wands.update_wand_desc(stack)
local meta = stack:get_meta()
local data_table = minetest.deserialize(meta:get_string("contents"))
local wanddata = minetest.registered_items[stack:get_name()]
local description = wanddata.description
local capcontents = wanddata["_cap_max"] or 15
local strbld = description.."\n"
local longest_desc = 0
for _,data in pairs(magicalities.elements) do
if not data.inheritance then
local len = #data.description
if len > longest_desc then
longest_desc = len
end
end
end
for elem, amount in pairs(data_table) do
local dataelem = magicalities.elements[elem]
if amount > 0 then
strbld = strbld.."\n"
strbld = strbld..minetest.colorize(dataelem.color, dataelem.description.." ")
strbld = strbld..align(longest_desc * 2 - #dataelem.description)
strbld = strbld..amount.."/"..capcontents
end
end
meta:set_string("description", strbld)
end
-- Ensure wand has contents
function magicalities.wands.wand_has_contents(stack, requirements)
local meta = stack:get_meta()
local data_table = minetest.deserialize(meta:get_string("contents"))
if not data_table then return false end
for name, count in pairs(requirements) do
if not data_table[name] or data_table[name] < count then
return false
end
end
return true
end
-- Take wand contents
function magicalities.wands.wand_take_contents(stack, to_take)
local meta = stack:get_meta()
local data_table = minetest.deserialize(meta:get_string("contents"))
for name, count in pairs(to_take) do
if not data_table[name] or data_table[name] - count < 0 then
return nil
end
data_table[name] = data_table[name] - count
end
local data_res = minetest.serialize(data_table)
meta:set_string("contents", data_res)
return stack
end
-- Initialize wand metadata
local function initialize_wand(stack)
local data_table = {}
for name, data in pairs(magicalities.elements) do
if not data.inheritance then
data_table[name] = 10
end
end
local meta = stack:get_meta()
meta:set_string("contents", minetest.serialize(data_table))
end
local function wand_action(itemstack, placer, pointed_thing)
if not pointed_thing.type == "node" then return itemstack end
local node = minetest.get_node(pointed_thing.under)
local imeta = itemstack:get_meta()
-- Initialize wand metadata
if imeta:get_string("contents") == nil or imeta:get_string("contents") == "" then
initialize_wand(itemstack)
magicalities.wands.update_wand_desc(itemstack)
end
local to_replace = nil
for grp, result in pairs(transform_recipes) do
if minetest.get_item_group(node.name, grp) > 0 then
to_replace = result
break
end
end
if not to_replace then return itemstack end
if to_replace.requires then
if not magicalities.wands.wand_has_contents(itemstack, to_replace.requires) then return itemstack end
itemstack = magicalities.wands.wand_take_contents(itemstack, to_replace.requires)
magicalities.wands.update_wand_desc(itemstack)
end
minetest.swap_node(pointed_thing.under, {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(pointed_thing.under)
end
return itemstack
end
local function use_wand(itemstack, user, pointed_thing)
local imeta = itemstack:get_meta()
-- Initialize wand metadata
if imeta:get_string("contents") == nil or imeta:get_string("contents") == "" then
initialize_wand(itemstack)
magicalities.wands.update_wand_desc(itemstack)
end
if not magicalities.wands.wand_has_contents(itemstack, {water = 5}) then
return itemstack
end
--itemstack = magicalities.wands.wand_take_contents(itemstack, {water = 5})
-- Calculate velocity
local dir = user:get_look_dir()
local vel = {x=0,y=0,z=0}
vel.x = dir.x * 16
vel.y = dir.y * 16
vel.z = dir.z * 16
-- Calculate position
local pos = user:get_pos()
pos.x = pos.x + (dir.x * 2)
pos.y = pos.y + (dir.y * 2) + 1.5
pos.z = pos.z + (dir.z * 2)
for i = 1, 8 do
-- Deviation
local relvel = {x=0,y=0,z=0}
relvel.x = vel.x + (randparticles:next((-i/2.5) * 1000, (i/2.5) * 1000) / 1000)
relvel.y = vel.y + (randparticles:next((-i/2.5) * 1000, (i/2.5) * 1000) / 1000)
relvel.z = vel.z + (randparticles:next((-i/2.5) * 1000, (i/2.5) * 1000) / 1000)
minetest.add_particle({
pos = pos,
velocity = relvel,
acceleration = relvel,
expirationtime = 1,
size = 4,
collisiondetection = true,
collision_removal = true,
texture = "magicalities_spark.png",
-- animation = {Tile Animation definition},
glow = 2
})
end
magicalities.wands.update_wand_desc(itemstack)
return itemstack
end
function magicalities.wands.register_wand(name, data)
local mod = minetest.get_current_modname()
minetest.register_tool(mod..":wand_"..name, {
description = data.description,
inventory_image = data.image,
tool_capabilities = wandcaps,
stack_max = 1,
_cap_max = data.wand_cap,
on_use = use_wand,
on_place = wand_action,
groups = {wand = 1}
})
end
-- 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,
})