Remplissage du dépôt.

This commit is contained in:
sys4-fr 2018-09-01 12:48:12 +02:00
parent b6d4b7fa32
commit 5edca3189c
45 changed files with 1134 additions and 2 deletions

12
README.md Normal file → Executable file
View File

@ -1,3 +1,11 @@
# runes
Rune mod by Mg
##############
Dépôt du mod runes. Extrait du dépôt MFF Classic.
# Purpose
This mod proposes 3 runes used in the balance of solarmana.
# Authors
- Mg (@LeMagnesium)
# Medias
<none atm>

94
amulets.lua Executable file
View File

@ -0,0 +1,94 @@
-- Amulets
runes.functions.register_amulet("silver_cross", "Silver Cross", 1, 25 )
runes.functions.register_amulet("minotaur_eye", "Minotaur Eye", 1, 50 )
runes.functions.register_amulet("hellfire", "Hellfire Amulet", 1, 75 )
runes.functions.register_amulet("grim_reaper", "Grim Reaper's Amulet", 1, 100)
-- Recipes
minetest.register_craft({
output = "runes:silver_cross_amulet",
recipe = {
{"", "farming:cotton", ""},
{"default:silver_ingot", "default:silver_ingot", "default:silver_ingot"},
{"", "default:silver_ingot", ""},
}
})
minetest.register_craft({
output = "runes:minotaur_eye_amulet",
recipe = {
{"", "darkage:chain", ""},
{"technic:brass_ingot", "mobs:minotaur_eye", "technic:brass_ingot"},
{"", "mesecons_materials:glue", ""},
}
})
minetest.register_craft({
output = "runes:hellfire_amulet",
recipe = {
{"", "darkage:chain", ""},
{"mobs:lava_orb", "default:diamondblock", "mobs:lava_orb"},
{"default:obsidian", "bucket:bucket_lava", "default:obsidian"},
}
})
minetest.register_craft({
output = "runes:grim_reaper_amulet",
recipe = {
{"", "runes:hellfire_amulet", ""},
{"nether:white", "runes:black_magic_block", "nether:white"},
{"", "default:mithrilblock", ""},
}
})
minetest.register_craft({
output = "runes:black_magic_block",
recipe = {
{"nether:white", "runes:hellfire_amulet", "default:obsidian"},
{"default:nyancat", "nether:tree", "default:mese"},
{"default:obsidian", "default:mithrilblock", "nether:white"},
}
})
-- Nodes
minetest.register_node("runes:black_magic_block", {
description = "Black Magic Block",
tiles = {"runes_black_magic_block.png"},
is_ground_content = true,
paramtype2 = "facedir",
groups = {crumbly=3},
sounds = default.node_sound_sand_defaults(),
})
-- Globalstep checking for the amulets
tmpdata = {}
loop = function()
for _, player in pairs(minetest.get_connected_players()) do
local inv = player:get_inventory()
local pname = player:get_player_name()
local basemana = mana.getmax(pname) - (tmpdata[pname] or 0) -- Baseline mana, without any amulets
local addons = 0
for index, item in pairs(inv:get_list("main")) do
local itemname = item:get_name()
local itemcount = item:get_count()
for name, manadiff in pairs(runes.datas.amulets) do
if itemname == "runes:" .. name .. "_amulet" then
addons = addons + (manadiff * itemcount)
--print("Detected " .. name)
end
end
end
mana.setmax(pname, basemana + addons)
tmpdata[pname] = addons
end
minetest.after(1, loop)
end
minetest.after(0, loop)
minetest.register_on_leaveplayer(function(player)
local pname = player:get_player_name()
mana.setmax(pname, mana.getmax(pname) - tmpdata[pname]) -- Reset
tmpdata[pname] = nil
mana.save_to_file(pname) -- Double class since we aren't sure mana hasn't already saved (it probably did)
end)

301
api.lua Executable file
View File

@ -0,0 +1,301 @@
-- API of the rune mod --
-- Global namespace
runes = {}
runes.datas = {}
runes.datas.handlers = {}
runes.datas.items = {}
runes.datas.amulets = {}
runes.functions = {}
-- Simple rune register function
runes.functions.register_rune = function(parameters)
local runedef = {}
if not parameters.name then
minetest.log("ERROR","[runes] Cannot register rune : no name")
return
end
runedef.name = parameters.name
runedef.desc = parameters.description or ""
runedef.img = parameters.img or "default_stone.png"
if type(runedef.img) ~= "table" then
runedef.img = {
["minor"] = runedef.img .. "_minor.png",
["medium"] = runedef.img .. "_medium.png",
["major"] = runedef.img .. "_major.png",
}
end
runedef.type = parameters.type or "craftitem"
runedef.needed_mana = parameters.needed_mana or {["minor"] = 0, ["medium"] = 5, ["major"] = 10}
runes.datas.handlers[runedef.name] = {}
if runedef.type == "cube" then
for _, level in pairs({"minor", "medium", "major"}) do
minetest.register_node("runes:rune_" .. runedef.name .. "_" .. level, {
description = runedef.desc .. " ("..level..")",
tiles = {runedef.img[level]},
groups = {oddly_breakable_by_hand = 2, rune = 1},
after_place_node = function(pos, placer, itemstack, pointed_thing)
if placer and placer:is_player() then
local meta = minetest.get_meta(pos)
meta:set_string("owner",placer:get_player_name())
end
if runes.datas.handlers[runedef.name].on_place then
if mana.get(placer:get_player_name()) >= runedef.needed_mana[level] then
local answer = runes.datas.handlers[runedef.name].on_place(level, pos, placer, itemstack, pointed_thing)
-- True answer leads to no dicrease (generally because the handler did it itself)
if not answer then
mana.subtract(placer:get_player_name(),runedef.needed_mana[level])
end
else
minetest.chat_send_player(placer:get_player_name(),"Not enough mana (needed : " .. runedef.needed_mana[level] ..")")
end
end
end,
can_dig = function(pos, player)
if runes.datas.handlers[runedef.name].can_dig then
return runes.datas.handlers[runedef.name].can_dig(level, pos, player)
else
return true
end
end,
on_punch = function(pos, node, puncher, pointed_thing)
if runes.datas.handlers[runedef.name].on_punch then
if mana.get(puncher:get_player_name()) >= runedef.needed_mana[level] then
runes.datas.handlers[runedef.name].on_punch(level, pos, node, puncher, pointed_thing)
mana.subtract(puncher:get_player_name(),runedef.needed_mana[level])
else
minetest.chat_send_player(puncher:get_player_name(),"Not enough mana (needed : " .. runedef.needed_mana[level] ..")")
end
end
end,
--[[after_dig_node = function(pos, oldnode, oldmetadata, digger)
--if runes.datas.handlers[runedef.name].can_dig and runes.datas.handlers[runedef.name].can_dig(pos, digger) then
if runes.datas.handlers[runedef.name].on_dig then
if mana.get(digger:get_player_name()) >= runedef.needed_mana[level] then
runes.datas.handlers[runedef.name].on_dig(pos, oldnode, digger)
mana.subtract(digger:get_player_name(),runedef.needed_mana)
else
minetest.chat_send_player(digger:get_player_name(),"Not enough mana (needed : " .. runedef.needed_mana[level] ..")")
end
end
end
end,]]
})
end
elseif runedef.type == "plate" then
for _, level in pairs({"minor", "medium", "major"}) do
minetest.register_node("runes:rune_" .. runedef.name .. "_" .. level, {
description = runedef.desc .. " (" .. level .. ")",
paramtype = "light",
inventory_image = runedef.img[level],
sunlight_propagates = true,
walkable = false,
tiles = {runedef.img[level]},
groups = {rune = 1, oddly_breakable_by_hand = 2},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, -0.499, 0.5},
}
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
if placer and placer:is_player() then
local meta = minetest.get_meta(pos)
meta:set_string("owner",placer:get_player_name())
end
if runes.datas.handlers[runedef.name].on_place then
if mana.get(placer:get_player_name()) >= runedef.needed_mana[level] then
local answer = runes.datas.handlers[runedef.name].on_place(level, pos, placer, itemstack, pointed_thing)
if not answer then
mana.subtract(placer:get_player_name(),runedef.needed_mana[level])
end
else
minetest.chat_send_player(placer:get_player_name(),"Not enough mana (needed : " .. runedef.needed_mana[level] ..")")
end
end
end,
can_dig = function(pos, player)
if runes.datas.handlers[runedef.name].can_dig then
return runes.datas.handlers[runedef.name].can_dig(level, pos, player)
else
return true
end
end,
on_punch = function(pos, node, puncher, pointed_thing)
if runes.datas.handlers[runedef.name].on_punch then
if mana.get(placer:get_player_name()) >= runedef.needed_mana[level] then
local answer = runes.datas.handlers[runedef.name].on_punch(level, pos, node, puncher, pointed_thing)
if not answer then
mana.subtract(placer:get_player_name(),runedef.needed_mana[level])
end
else
minetest.chat_send_player(placer:get_player_name(),"Not enough mana (needed : " .. runedef.needed_mana[level] ..")")
end
end
end,
})
end
elseif runedef.type == "craftitem" then
for _, level in pairs({"minor", "medium", "major"}) do
minetest.register_craftitem("runes:rune_" .. runedef.name .. "_" .. level, {
description = runedef.desc .. " (" .. level ..")",
inventory_image = runedef.img[level],
groups = {rune = 1},
on_use = function(itemstack, user, pointed_thing)
-- Let the handler do its job
if runes.datas.handlers[runedef.name].on_use then
if mana.get(user:get_player_name()) >= runedef.needed_mana[level] then
local answer = runes.datas.handlers[runedef.name].on_use(level, itemstack, user, pointed_thing)
if not answer then
mana.subtract(user:get_player_name(),runedef.needed_mana[level])
user:get_inventory():remove_item("main",{name = runedef.name .. "_" .. level})
end
else
minetest.chat_send_player(user:get_player_name(),"Not enough mana (needed : " .. runedef.needed_mana[level] ..")")
end
end
end
})
end
end
end
-- Handler connector
runes.functions.connect = function(itemname, callback, handler)
--[[ Available callback :
use
place
dig
can_dig
punch
]]
if not runes.datas.items[itemname] then
minetest.log("error","[runes] Cannot connect handler at " .. handler .. " to unknown item " .. itemname)
return
end
if callback == "use" then
runes.datas.handlers[itemname].on_use = handler
elseif callback == "place" then
runes.datas.handlers[itemname].on_place = handler
elseif callback == "dig" then
runes.datas.handlers[itemname].on_dig = handler
elseif callback == "can_dig" then
runes.datas.handlers[itemname].can_dig = handler
elseif callback == "punch" then
runes.datas.handlers[itemname].on_punch = handler
else
minetest.log("error","[runes] Cannot connect handler to item's " .. itemname .. " unknown " .. callback .. " callback")
return
end
end
-- Amulets
runes.functions.register_amulet = function(name, desc, maxcount, manadiff)
minetest.register_craftitem("runes:" .. name .. "_amulet", {
description = desc,
inventory_image = "runes_" .. name .. "_amulet.png",
groups = {amulet = 1, rune = 1},
stack_max = maxcount,
})
runes.datas.amulets[name] = manadiff
end
-- Inventory
unified_inventory.register_button("runes", {
type = "image",
image = "runes_heal_major.png",
tooltip = "Rune inventory",
show_with = false, --Modif MFF (Crabman 30/06/2015)
})
unified_inventory.register_page("runes", {
get_formspec = function(player)
local name = player:get_player_name()
local formspec = "background[0,0.2;8,4;runes_rune_inventory.png]"..
"background[0,4.5;8,4;ui_main_inventory.png]"..
"size[8,10]"..
"list[detached:"..name.."_runes;runes;0,0.2;8,4;]"
return {formspec=formspec}
end,
})
runes.functions.register_detached_inventory = function(player)
local name = player:get_player_name()
local player_inv = player:get_inventory()
local datafile = io.open(minetest.get_worldpath().."/runes/"..name.."_rune.inv", "r")
local rune_inv_data = {}
if datafile then
local line = datafile:read()
if line then
rune_inv_data = minetest.deserialize(line)
end
io.close(datafile)
end
local rune_inv = minetest.create_detached_inventory(name.."_runes",{
on_put = function(inv, listname, index, stack, player)
player:get_inventory():set_stack(listname, index, stack)
armor:set_player_armor(player)
armor:update_inventory(player)
end,
on_take = function(inv, listname, index, stack, player)
player:get_inventory():set_stack(listname, index, nil)
armor:set_player_armor(player)
armor:update_inventory(player)
end,
allow_put = function(inv, listname, index, stack, player)
if minetest.get_item_group(stack:get_name(), "rune") > 0 then
return stack:get_count()
end
return 0
end,
allow_take = function(inv, listname, index, stack, player)
return stack:get_count()
end,
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
return count
end,
})
rune_inv:set_size("runes", 8*4)
rune_inv:set_list("runes",rune_inv_data)
minetest.log("action","[runes] Rune inventory loaded for player " .. name)
end
minetest.register_on_joinplayer(runes.functions.register_detached_inventory)
runes.functions.save_detached_inventory = function(player)
local name = player:get_player_name()
local player_inv = player:get_inventory()
local datafile = io.open(minetest.get_worldpath().."/runes/"..name.."_rune.inv", "w")
local rune_inv_data = minetest.get_inventory({type = "detached", name=name.."_runes"})
if not rune_inv_data then
minetest.log("error", "[runes] Couldn't save rune inventory for player " .. name .. " : data unavailable")
return false
end
local translated_rune_data = {}
for index, data in pairs(rune_inv_data:get_list("runes")) do
translated_rune_data[index] = data:get_name() .. " " .. data:get_count()
end
if datafile then
datafile:write(minetest.serialize(translated_rune_data))
io.close(datafile)
end
minetest.log("action", "[runes] Rune inventory saved for player " .. name)
end
minetest.register_on_leaveplayer(runes.functions.save_detached_inventory)
minetest.register_on_shutdown(function()
for index, player in pairs(minetest.get_connected_players()) do
runes.functions.save_detached_inventory(player)
end
end)

78
api.md Executable file
View File

@ -0,0 +1,78 @@
RUNES' API
==========
(as accurate as possible)
# 1. How it **does** work
Every rune registered uses the same method to work and access its environment. Runes are first registered using a specific function.
Their datas are stored somewhere in a namespace (see below). You can use multiple values to indicate the needed amount of mana, the type of
the rune, its texture(s), etc. Then, once a rune is registered (as an item, for minetest), the most important thing is to connect its handler(s).
Another specific function is used to this, where you pass as an argument the reference to a function receiving the parameters of the item/node's callback
(eg. on_punch, on_dig, on_use, etc). The handler can choose to return "true" in order to manage the use of mana by itself instead of letting the
item's code in minetest.registered_items[rune].callback do it.
# Functions
#### `runes.register_rune(parameters)`
The most important function. This is the function you use to declare your rune and its specifications to minetest itself.
It takes one argument, a table. This table can have the following articles :
- `name` is mandatory, it's the rune's name (which will be used to craft its itemstring : runes:rune_name_level)
- `desc` is the item's description
- `img` is another table :
- ["minor"] = texture_file
- ["medium"] = texture_file
- ["major"] = texture_file
None of these parameters are mandatory. Runes can have 1 or 2 or 3 levels (ok, not implemented yet, but it's coming).
You can use a single value like `img = texture_file` and the texture will be applied for all levels
- `type` is the type of rune. At the moment, three types are available :
- "craftitem" will register a craftitem
- "cube" will register a node
- "plate" will register a little slab 0.1 node thin
- `needed_mana` is yet another table with different levels :
- ["minor"] = value
- ["medium"] = value
- ["major"] = value
When using this rune at level "major", the ["major"] value of mana will be taken by default if the player has enough mana,
or it will be forbidden for him to use the rune if he doesn't have enough mana.
You don't have to indicate that parameter and just let the handler manage the mana.
#### `runes.functions.connect(itemname, callback, handler)`
This function will connect a registered rune's callback to its handler. It takes three mandatory arguments :
- `itemname` is the rune's identification name (aka. `name` for earlier). The same handler is used for every level
of a rune, so it has to determine what level he will handle (it's actually passed to it)
- `callback` is a code identifying the callback. It can be :
- `use` for `on_use`
- `place` for `after_place_node`
- `dig` for `after_dig_node` (actually commented due to bugs in this section)
- `can_dig` for `can_dig` (true logic)
- `punch` for `on_punch` (rather logic too)
- `handler` is the function handling the callback. See below for details.
Do not hesitate to consult lua_api.txt in order to see which callbacks are handled by what type of runes (craftitems, and nodes).
#### `runes.functions.register_amulet(name, desc, maxcount, manadiff)`
Amulets are special items able to increase the maximum of mana you can stock. Here are the arguments expected to register an amulet :
- `name` is its name, used to create its itemstring : 'runes:name_amulet'
Don't feel forced to use '_amulet' in an amulet name, it's completly useless.
- `desc` is the item description.
- `maxcount` represents the maximum amount of this amulet you can have per stack (aka `stack_max`, see lua_api.txt for this).
- `manadiff` is the amount of space you will get to stock more mana in your inventory. A global_step loop is charged with the task
of regulary looking into everyone's rune inventory to calculate every player's max_mana. If you loose amulets, your mana_max
will dicrease (and mana may be lost with it).
#### `runes.functions.register_detached_inventory(player)`
This function is only important for rune's inners. It registers a detached inventory to contain runes. Do not bother using it, there is no
actual use of it out of runes' core.
#### `runes.functions.save_detached_inventory(player)`
Saves player's rune inventory on hard drive (in minetest.get_worldpath() .. "/runes/" .. player:get_player_name() .. "_rune.inv").
# Namespaces
Here are a few namespaces that could be useful :
- `runes` global namespace, contains everything. Note : When [this](https://github.com/minetest/minetest/pull/2039) is merged, do what we have to do.
- `runes.datas` miscellaneous datas, including tables with parameters transmitted to the registration functions.
- `runes.datas.item`, the item's datas transmitted to registration
- `runes.datas.handlers`, handlers of everynodes (the index of this dictionnary is the rune's name)
- `runes.datas.amulets`, amulet's datas, used for the global_step loop and registration
- `runes.functions`, multiple useful functions

3
depends.txt Executable file
View File

@ -0,0 +1,3 @@
default
unified_inventory
mana

403
glyphs.lua Normal file
View File

@ -0,0 +1,403 @@
-- A stylus to inscribe glyphs
-- Part of a Rune Mod Redo
-- By Mg, 2016
-- License : WTFPL
--
runes.glyphs = {}
minetest.register_tool("runes:stylus", {
description = "Stylus",
inventory_image = "runes_stylus.png",
on_use = function(itemstack, user, pointed_thing)
if not user or pointed_thing.type ~= "node" then return end
local node = minetest.get_node_or_nil(pointed_thing.under)
if not node or not minetest.registered_nodes[node.name].walkable then
return
end
node = minetest.get_node_or_nil(pointed_thing.above)
if not node or node.name ~= "air" then
return
end
local main_inv = user:get_inventory():get_list("main")
local scroll = main_inv[user:get_wield_index()-1]
if not scroll then
minetest.chat_send_player(user:get_player_name(), "There is no scroll before the stylus in your inventory!")
return
elseif minetest.get_item_group(scroll:get_name(), "scroll") == 0 then
minetest.chat_send_player(user:get_player_name(), "The item before your stylus is not a scroll of knowledge!")
return
end
local name = scroll:get_name():gsub("runes:scroll_", "")
if not runes.scrolls[name] then return end
local glyph = runes.scrolls[name].glyph
if not glyph then return end
if mana.get(user:get_player_name()) < runes.glyphs[name].mana_cost then
minetest.chat_send_player(user:get_player_name(), "You need " .. runes.glyphs[name].mana_cost .. " of mana to inscribe that glyph")
return
end
-- Calculate param2 manually since MineTest doesn't even do it
local diff = vector.subtract(pointed_thing.under, pointed_thing.above)
minetest.add_node(pointed_thing.above, {name = glyph, param2 = minetest.dir_to_wallmounted(diff)})
minetest.get_meta(pointed_thing.above):set_string("master", user:get_player_name())
itemstack:add_wear(65535 / 30)
mana.subtract(user:get_player_name(), runes.glyphs[name].mana_cost)
return itemstack
end,
})
minetest.register_craft({
output = "runes:stylus",
recipe = {
{"", "default:obsidian_shard", "default:mithril_ingot"},
{"default:obsidian_shard", "default:nyancat_rainbow", "default:obsidian_shard"},
{"default:obsidian_shard", "default:obsidian_shard", ""},
},
})
minetest.register_craftitem("runes:recharge_wand", {
description = "Recharge wand",
inventory_image = "runes_recharge_wand.png",
on_use = function(itemstack, user, pointed_thing)
if not pointed_thing.type == "node" or not pointed_thing.under then
return
end
local node = minetest.get_node_or_nil(pointed_thing.under)
if not node or not minetest.registered_nodes[node.name]
or minetest.get_item_group(node.name, "glyph") == 0 then
return
end
local meta = minetest.get_meta(pointed_thing.under)
local charge = meta:get_int("charge")
local rname = node.name:sub(13)
local msg = "Rune already charged at maximum capacity"
if charge < runes.glyphs[rname].max_charge then
local pmana = mana.get(user:get_player_name())
-- Lower the index of pmana if it is higher than 20 (to simplify calculations)
if pmana > 20 then
pmana = 20
end
local delta = runes.glyphs[rname].max_charge - charge
if delta < pmana then
meta:set_int("charge", runes.glyphs[rname].max_charge)
mana.subtract(user:get_player_name(), delta)
msg = "Rune recharged at maximum capacity"
else
meta:set_int("charge", charge + pmana)
mana.subtract(user:get_player_name(), 20)
msg = "Rune recharged"
end
end
minetest.chat_send_player(user:get_player_name(), msg)
end,
})
minetest.register_craft({
output = "runes:recharge_wand",
recipe = {
{"", "", "default:diamond"},
{"", "default:mese_crystal_fragment", ""},
{"default:stick", "", ""},
},
})
minetest.register_craftitem("runes:info_wand", {
description = "Information wand",
inventory_image = "runes_info_wand.png",
on_use = function(itemstack, user, pointed_thing)
if not pointed_thing.type == "node" then
return
end
local node = minetest.get_node_or_nil(pointed_thing.under)
if not node or not minetest.registered_nodes[node.name]
or minetest.get_item_group(node.name, "glyph") == 0 then
return
end
local meta = minetest.get_meta(pointed_thing.under)
local metas = meta:to_table().fields
local owner = meta:get_string("master")
if owner == "" then
owner = "nobody"
end
local rname = node.name:sub(13)
local formspec = "size[7,7]" ..
"label[0,0; Rune informations :]" ..
"button_exit[3, 6.6; 1, 0.6; rune_info_exit; Exit]" ..
"textlist[0, 0.5; 6.8, 5.9; runes_info;" ..
"Rune : " .. rname .. "," ..
"Charge : " .. metas["charge"] .. "/" .. runes.glyphs[rname].max_charge .. "," ..
"Owner : " .. owner
local i = 4
for field, value in pairs(metas) do
if field ~= "master" and field ~= "charge" then
formspec = formspec .. "," .. field .. " (meta) : " .. value
i = i + 1
end
end
formspec = formspec .. ";]"
minetest.show_formspec(user:get_player_name(), "runes:glyph_info", formspec)
end,
})
minetest.register_craft({
output = "runes:info_wand",
recipe = {
{"", "", "default:grass"},
{"", "default:mithril_ingot", ""},
{"default:stick", "", ""},
},
})
function register_glyph(name, basics, tab)
--[[ Basics can contain :
- texture = "runes_glyph_unknown.png",
- description = "Mysterious Glyph",
- initial_charge = 0
- mana_cost = 0
--]]
runes.glyphs[name] = {}
runes.glyphs[name].mana_cost = basics.mana_cost or 0
runes.glyphs[name].max_charge = basics.maximum_charge or 100
local def = table.copy(tab)
def.groups.glyph = 1
def.description = basics.description or "Mysterious Glyph"
def.inventory_image = basics.texture or "runes_glyph_unknown.png"
def.tiles = {basics.texture or "default_stone.png"}
def.on_construct = function(pos)
minetest.get_meta(pos):set_int("charge", (basics.initial_charge or 0))
tab.on_construct(pos)
end
def.drawtype = "signlike"
def.paramtype = "light"
def.paramtype2 = "wallmounted"
def.selection_box = {
type = "wallmounted",
wall_top = {-0.5, 0.4, -0.5, 0.5, 0.5, 0.5},
wall_bottom = {-0.5, -0.5, -0.5, 0.5, -0.4, 0.5},
wall_side = {-0.5, -0.5, -0.5, -0.4, 0.5, 0.5},
}
def.walkable = false
minetest.register_node("runes:glyph_" .. name, def)
end
register_glyph("watchdog", {
description = "Watch Dog Glyph",
texture = "runes_glyph_watchdog.png",
initial_charge = 300,
maximum_charge = 300,
mana_cost = 10,
}, {
light_source = 8,
groups = {snappy = 1},
on_construct = function(pos)
minetest.get_node_timer(pos):start(0.2)
end,
on_timer = function(pos, elapsed)
local meta = minetest.get_meta(pos)
for _, ref in pairs(minetest.get_objects_inside_radius(pos, 3)) do
if ref and not ref:get_armor_groups().immortal then
if not ref:is_player() or ref.is_fake_player or not meta:get_string("master") or meta:get_string("master") == "" or ref:get_player_name() ~= meta:get_string("master") then
ref:set_hp(ref:get_hp() - 1)
meta:set_int("charge", (meta:get_int("charge") or 1) - 1)
local collisionbox = ref:get_properties().collisionbox
local refpos = ref:getpos()
refpos.y = refpos.y + (((collisionbox[4] or 0) - (collisionbox[3] or 0)) / 2)
local vel = vector.subtract(refpos, pos)
minetest.add_particlespawner({
amount = 30,
minpos = pos, maxpos = pos,
minvel = vel, maxvel = vector.multiply(vel, 3),
minacc = 0, maxacc = 0,--vector.multiply(vel, 3),
minexptime = 1, maxexptime = 1,
minsize = 2, maxsize = 5,
collisiondetection = false,
vertical = false,
texture = "runes_glyph_watchdog.png",
})
end
end
end
return true
end
}
)
register_glyph("manasucker", {
description = "Mana Sucker Glyph",
texture = "runes_glyph_manasucker.png",
initial_charge = 100,
maximum_charge = 100,
mana_cost = 20,
}, {
groups = {snappy = 1},
on_construct = function(pos)
minetest.get_node_timer(pos):start(3)
minetest.get_meta(pos):set_int("mana", 0)
end,
on_punch = function(pos, _, puncher)
local meta = minetest.get_meta(pos)
if meta:get_string("master") and puncher:is_player() and not puncher.is_fake_player and puncher:get_player_name() == meta:get_string("master") then
local k = meta:get_int("mana")
local name = puncher:get_player_name()
local o = mana.getmax(name) - mana.get(name)
local u = 0
if k > o then
u = k - mana.getmax(name)
mana.set(name, o)
else
mana.add(name, k)
end
meta:set_int("mana", u)
end
end,
on_timer = function(pos, elapsed)
local meta = minetest.get_meta(pos)
if meta:get_int("charge") <= 0 then
return true
end
local more_mana = 0
for _, ref in pairs(minetest.get_objects_inside_radius(pos, 5)) do
if ref and ref:is_player() and not ref.is_fake_player and (not meta:get_string("master") or meta:get_string("master") == "" or meta:get_string("master") ~= ref:get_player_name()) then
local burst = math.random(10, 40)
local manalevel = mana.get(ref:get_player_name())
if manalevel > 0 then
if manalevel < burst then
mana.set(ref:get_player_name(), 0)
more_mana = more_mana + manalevel
else
mana.subtract(ref:get_player_name(), burst)
more_mana = more_mana + burst
end
local collisionbox = ref:get_properties().collisionbox
local refpos = ref:getpos()
refpos.y = refpos.y + (((collisionbox[4] or 0) - (collisionbox[3] or 0)) / 2)
local vel = vector.subtract(pos, refpos)
minetest.add_particlespawner({
amount = 30,
minpos = refpos, maxpos = refpos,
minvel = vel, maxvel = vel,
minacc = 0, maxacc = 0,--vector.multiply(vel, 3),
minexptime = 1, maxexptime = 1,
minsize = 1, maxsize = 1,
collisiondetection = false,
vertical = false,
texture = "runes_glyph_manasucker.png",
})
meta:set_int("charge", meta:get_int("charge") - 1)
end
end
end
meta:set_int("mana", meta:get_int("mana") + more_mana)
return true
end
}
)
register_glyph("spontafire", {
description = "Spontaneous Fire Glyph",
texture = "runes_glyph_spontafire.png",
initial_charge = 0,
maximum_charge = 500,
mana_cost = 20,
}, {
groups = {snappy = 1},
on_construct = function(pos)
minetest.get_node_timer(pos):start(1)
end,
on_timer = function(pos, elapsed)
local meta = minetest.get_meta(pos)
local charge = meta:get_int("charge")
for _, ref in pairs(minetest.get_objects_inside_radius(pos, 10)) do
if ((not ref:is_player()) and ref:get_entity_name() ~= "gauges:hp_bar")
or (ref:get_player_name() ~= "" and ref:get_player_name() ~= meta:get_string("master")) then
local rpos = vector.round(ref:getpos())
rpos.y = rpos.y - 1
local node = minetest.get_node(rpos)
if node.name == "air" and (not minetest.is_protected(rpos, meta:get_string("master")))
and charge >= runes.glyphs["spontafire"].mana_cost then
minetest.add_node(rpos, {name = "fire:basic_flame"})
charge = charge - runes.glyphs["spontafire"].mana_cost
end
end
end
meta:set_int("charge", charge)
return true
end,
})
register_glyph("prankster", {
description = "Prankster Glyph",
texture = "runes_glyph_prankster.png",
initial_charge = 600,
maximum_charge = 1200,
mana_cost = 20,
},{
groups = {snappy = 1},
on_construct = function(pos)
minetest.get_node_timer(pos):start(5)
end,
on_timer = function(pos, elapsed)
local meta = minetest.get_meta(pos)
local charge = meta:get_int("charge")
for _, ref in pairs(minetest.get_objects_inside_radius(pos, 10)) do
if charge >= runes.glyphs["prankster"].mana_cost and ref:is_player() and ref:get_player_name() ~= meta:get_string("master") then
local thieff = math.random(1,32)
local inv = ref:get_inventory()
if inv then
local stolen = inv:get_stack("main", thieff)
inv:set_stack("main", thieff, nil)
if stolen:get_count() > 0 then
local pos = ref:getpos()
local obj = minetest.add_item({x = pos.x, y = pos.y + 2.5, z = pos.z}, stolen)
if obj then
obj:setvelocity({x = math.random(-5,5), y = math.random(3,5), z = math.random(-5,5)})
end
charge = charge - runes.glyphs["prankster"].mana_cost
minetest.chat_send_player(ref:get_player_name(), "The Prankster attacked you and stole " .. stolen:get_count() .. " "
.. (minetest.registered_items[stolen:get_name()].description or " of something")
)
else
minetest.chat_send_player(ref:get_player_name(), "The Prankster attacked you but failed at stealing from you..")
end
else
minetest.log("Inventory retrieval failed")
end
end
end
meta:set_int("charge", charge)
return true
end,
})

106
handlers.lua Executable file
View File

@ -0,0 +1,106 @@
-- Use handlers for runes
-- Every handler must receive as arguments the default callback arguments and
-- as first argument the power level of the rune as a string which can be :
-- `minor` : Low level
-- `medium` : Medium level
-- `major` : High level
-- First, the functions
projection = function(runelevel, itemstack, user, pointed_thing)
if pointed_thing.type == "object" then
local dir = vector.direction(user:getpos(),pointed_thing.ref:getpos())
local v = pointed_thing.ref:getvelocity() or {x=0,y=0,z=0}
local ykb = 10
if v.y ~= 0 then ykb = 0 end
pointed_thing.ref:setvelocity({x=dir.x*50,y=ykb,z=dir.z*50})
end
end
damage_around = function(runelevel, itemstack, user, pointed_thing)
for name,entity in pairs(minetest.get_objects_inside_radius(user:getpos(),10)) do
if true and (entity:is_player() and entity:get_player_name() ~= user:get_player_name()) then
entity:set_hp(1)
end
end
end
earthquake = function(runelevel, itemstack, user, pointed_thing)
for name,entity in pairs(minetest.get_objects_inside_radius(user:getpos(),10)) do
local v = entity:getvelocity() or {x=0,y=0,z=0}
entity:setvelocity({x=v.x, y=v.y+50, z=v.z})
end
end
add_owner = function(runelevel, pos, placer, itemstack, pointed_thing)
if placer and placer:is_player() then
local meta = minetest.get_meta(pos)
meta:set_string("owner",placer:get_player_name())
end
end
is_owner_online = function(runelevel, pos)
local meta = minetest.get_meta(pos)
if meta:get_string("owner") ~= nil then
return minetest.get_player_by_name(meta:get_string("owner")) ~= nil
else
return false
end
end
is_owner = function(runelevel, pos, player)
local meta = minetest.get_meta(pos)
if meta:get_string("owner") ~= nil and player:get_player_name() then
return meta:get_string("owner") == player:get_player_name()
else
return false
end
end
go_to_me = function(runelevel, pos, node, digger)
if digger and is_owner_online(pos) and not (minetest.get_meta(pos):get_string("owner") == digger:get_player_name()) then
digger:setpos(minetest.get_player_by_name(minetest.get_meta(pos):get_string("owner")):getpos())
mana.subtract(minetest.get_meta(pos):get_string("owner"), 5)
else
mana.add(digger:get_player_name(),50)
end
end
set_manamax = function(runelevel, itemstack, user, pointed_thing)
if user and user:is_player() then
mana.set(user:get_player_name(),mana.getmax(user:get_player_name()))
if not minetest.get_player_privs(user:get_player_name()).server then
-- Violent reaction if not admin
user:set_hp(1)
user:set_breath(1)
local userpos = user:getpos()
local useritem = user:get_wielded_item()
user:setpos({x=userpos.x+math.random(-50,50),y = userpos.y + math.random(1,20),z = userpos.z + math.random(-50,50)})
end
end
end
set_manamax = function(level, itemstack, user, pointed_thing)
if user and user:is_player() then
mana.set(user:get_player_name(),mana.getmax(user:get_player_name()))
if not minetest.get_player_privs(user:get_player_name()).server then
-- Violent reaction if not admin
user:set_hp(1)
user:set_breath(1)
local userpos = user:getpos()
local useritem = user:get_wielded_item()
user:setpos({x=userpos.x+math.random(-50,50),y = userpos.y + math.random(1,20),z = userpos.z + math.random(-50,50)})
end
end
end
-- Then, connect
runes.functions.connect("project","use",projection)
runes.functions.connect("damager","use",damage_around)
runes.functions.connect("earthquake","use",earthquake)
runes.functions.connect("gotome","punch",go_to_me)
runes.functions.connect("gotome","can_dig",is_owner)
runes.functions.connect("megamana","use",set_manamax)

28
init.lua Executable file
View File

@ -0,0 +1,28 @@
-- Rune mod by Mg
-- License GPLv3
local modpath = minetest.get_modpath("runes")
runes = {}
-- API first
dofile(modpath.."/api.lua")
-- Then the rune themselves
dofile(modpath.."/registration.lua")
-- The handlers
dofile(modpath.."/handlers.lua")
-- The amulets
dofile(modpath.."/amulets.lua")
---- From this point everything is redo ----
-- Stylus
dofile(modpath .. "/glyphs.lua")
-- Scrolls
dofile(modpath .. "/scrolls.lua")
minetest.log("action","[runes] Mod loaded")

64
registration.lua Executable file
View File

@ -0,0 +1,64 @@
-- Rune definitions : registration.lua
runes.datas.items = {
["project"] = {
description = "Projection rune",
img = "runes_projection",
type = "craftitem",
needed_mana = {
["minor"] = 15,
["medium"] = 30,
["major"] = 45,
},
},
["damager"] = {
description = "Damaging rune",
img = "runes_damaging",
type = "craftitem",
needed_mana = {
["minor"] = 180,
["medium"] = 190,
["major"] = 230
}
},
["earthquake"] = {
description = "Earth Quake rune",
img = "runes_earthquake",
type = "craftitem",
needed_mana = {
["minor"] = 70,
["medium"] = 80,
["major"] = 90
}
},
["heal"] = {
description = "Healing rune",
img = "runes_heal",
type = "cube"
},
["gotome"] = {
description = "Go to me rune",
img = "runes_go_to_me",
type = "cube",
needed_mana = {
["minor"] = 40,
["medium"] = 50,
["major"] = 75
}
},
["megamana"] = {
description = "Mega Mana",
img = {
["minor"] = "default_diamond.png",
["medium"] = "default_diamond.png",
["major"] = "default_diamond.png"
},
type = "craftitem"
},
}
for key, value in pairs(runes.datas.items) do
local runereg = table.copy(value)
runereg.name = key
runes.functions.register_rune(runereg)
end

47
scrolls.lua Normal file
View File

@ -0,0 +1,47 @@
-- Scrolls for Runes Redo
--
runes.scrolls = {}
function register_scroll(name, type, data)
if not data then return end
local def = {
inventory_image = (data.texture or "runes_scroll_unknown.png"),
groups = {scroll = 1},
description = (data.description or "Mysterious Scroll"),
}
minetest.register_craftitem("runes:scroll_" .. name, def)
runes.scrolls[name] = {}
if type == "knowledge" and data.glyph then
runes.scrolls[name].glyph = data.glyph
end
end
register_scroll("watchdog", "knowledge", {
glyph = "runes:glyph_watchdog",
texture = "runes_scroll_watchdog.png",
description = "Watch Dog Knowledge Scroll"
})
register_scroll("manasucker", "knowledge", {
glyph = "runes:glyph_manasucker",
texture = "runes_scroll_manasucker.png",
description = "Mana Sucker Knowledge Scroll",
})
register_scroll("spontafire", "knowledge", {
glyph = "runes:glyph_spontafire",
texture = "runes_scroll_spontafire.png",
description = "Spontaneous Fire Knowledge Scroll",
})
register_scroll("prankster", "knowledge", {
glyph = "runes:glyph_prankster",
texture = "runes_scroll_prankster.png",
description = "Prankster Knowledge Scroll",
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
textures/runes_damaging_major.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
textures/runes_damaging_minor.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

BIN
textures/runes_go_to_me_major.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
textures/runes_go_to_me_minor.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

BIN
textures/runes_heal_major.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
textures/runes_heal_medium.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
textures/runes_heal_minor.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

BIN
textures/runes_megamana_major.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
textures/runes_megamana_minor.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

BIN
textures/runes_rune_inventory.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

BIN
textures/runes_stylus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B