From 5edca3189ce36bf04d2a3f324fdc6a6d76d4017c Mon Sep 17 00:00:00 2001 From: sys4-fr Date: Sat, 1 Sep 2018 12:48:12 +0200 Subject: [PATCH] =?UTF-8?q?Remplissage=20du=20d=C3=A9p=C3=B4t.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +- amulets.lua | 94 +++++ api.lua | 301 ++++++++++++++++ api.md | 78 +++++ depends.txt | 3 + glyphs.lua | 403 ++++++++++++++++++++++ handlers.lua | 106 ++++++ init.lua | 28 ++ registration.lua | 64 ++++ scrolls.lua | 47 +++ textures/runes_black_magic_block.png | Bin 0 -> 2167 bytes textures/runes_damaging_major.png | Bin 0 -> 2951 bytes textures/runes_damaging_medium.png | Bin 0 -> 3381 bytes textures/runes_damaging_minor.png | Bin 0 -> 3290 bytes textures/runes_earthquake_major.png | Bin 0 -> 2500 bytes textures/runes_earthquake_medium.png | Bin 0 -> 2500 bytes textures/runes_earthquake_minor.png | Bin 0 -> 2500 bytes textures/runes_glyph_deus_ex_machina.png | Bin 0 -> 418 bytes textures/runes_glyph_manasucker.png | Bin 0 -> 145 bytes textures/runes_glyph_prankster.png | Bin 0 -> 176 bytes textures/runes_glyph_spontafire.png | Bin 0 -> 139 bytes textures/runes_glyph_watchdog.png | Bin 0 -> 173 bytes textures/runes_go_to_me_major.png | Bin 0 -> 2255 bytes textures/runes_go_to_me_medium.png | Bin 0 -> 2227 bytes textures/runes_go_to_me_minor.png | Bin 0 -> 2170 bytes textures/runes_grim_reaper_amulet.png | Bin 0 -> 705 bytes textures/runes_heal_major.png | Bin 0 -> 2610 bytes textures/runes_heal_medium.png | Bin 0 -> 2416 bytes textures/runes_heal_minor.png | Bin 0 -> 2353 bytes textures/runes_hellfire_amulet.png | Bin 0 -> 673 bytes textures/runes_info_wand.png | Bin 0 -> 153 bytes textures/runes_megamana_major.png | Bin 0 -> 1668 bytes textures/runes_megamana_medium.png | Bin 0 -> 1740 bytes textures/runes_megamana_minor.png | Bin 0 -> 1868 bytes textures/runes_minotaur_eye_amulet.png | Bin 0 -> 463 bytes textures/runes_recharge_wand.png | Bin 0 -> 240 bytes textures/runes_rune_inventory.png | Bin 0 -> 4639 bytes textures/runes_scroll_deus_ex_machina.png | Bin 0 -> 410 bytes textures/runes_scroll_manasucker.png | Bin 0 -> 215 bytes textures/runes_scroll_prankster.png | Bin 0 -> 227 bytes textures/runes_scroll_spontafire.png | Bin 0 -> 218 bytes textures/runes_scroll_unknown.png | Bin 0 -> 209 bytes textures/runes_scroll_watchdog.png | Bin 0 -> 257 bytes textures/runes_silver_cross_amulet.png | Bin 0 -> 289 bytes textures/runes_stylus.png | Bin 0 -> 247 bytes 45 files changed, 1134 insertions(+), 2 deletions(-) mode change 100644 => 100755 README.md create mode 100755 amulets.lua create mode 100755 api.lua create mode 100755 api.md create mode 100755 depends.txt create mode 100644 glyphs.lua create mode 100755 handlers.lua create mode 100755 init.lua create mode 100755 registration.lua create mode 100644 scrolls.lua create mode 100755 textures/runes_black_magic_block.png create mode 100755 textures/runes_damaging_major.png create mode 100755 textures/runes_damaging_medium.png create mode 100755 textures/runes_damaging_minor.png create mode 100755 textures/runes_earthquake_major.png create mode 100755 textures/runes_earthquake_medium.png create mode 100755 textures/runes_earthquake_minor.png create mode 100644 textures/runes_glyph_deus_ex_machina.png create mode 100644 textures/runes_glyph_manasucker.png create mode 100644 textures/runes_glyph_prankster.png create mode 100644 textures/runes_glyph_spontafire.png create mode 100644 textures/runes_glyph_watchdog.png create mode 100755 textures/runes_go_to_me_major.png create mode 100755 textures/runes_go_to_me_medium.png create mode 100755 textures/runes_go_to_me_minor.png create mode 100755 textures/runes_grim_reaper_amulet.png create mode 100755 textures/runes_heal_major.png create mode 100755 textures/runes_heal_medium.png create mode 100755 textures/runes_heal_minor.png create mode 100755 textures/runes_hellfire_amulet.png create mode 100644 textures/runes_info_wand.png create mode 100755 textures/runes_megamana_major.png create mode 100755 textures/runes_megamana_medium.png create mode 100755 textures/runes_megamana_minor.png create mode 100755 textures/runes_minotaur_eye_amulet.png create mode 100644 textures/runes_recharge_wand.png create mode 100755 textures/runes_rune_inventory.png create mode 100644 textures/runes_scroll_deus_ex_machina.png create mode 100644 textures/runes_scroll_manasucker.png create mode 100644 textures/runes_scroll_prankster.png create mode 100644 textures/runes_scroll_spontafire.png create mode 100644 textures/runes_scroll_unknown.png create mode 100644 textures/runes_scroll_watchdog.png create mode 100755 textures/runes_silver_cross_amulet.png create mode 100644 textures/runes_stylus.png diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 8549f66..fb3678b --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ -# runes +Rune mod by Mg +############## -Dépôt du mod runes. Extrait du dépôt MFF Classic. \ No newline at end of file +# Purpose +This mod proposes 3 runes used in the balance of solarmana. + +# Authors + - Mg (@LeMagnesium) + +# Medias + diff --git a/amulets.lua b/amulets.lua new file mode 100755 index 0000000..7e2f2c9 --- /dev/null +++ b/amulets.lua @@ -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) diff --git a/api.lua b/api.lua new file mode 100755 index 0000000..10de6ff --- /dev/null +++ b/api.lua @@ -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) diff --git a/api.md b/api.md new file mode 100755 index 0000000..b9a24e3 --- /dev/null +++ b/api.md @@ -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 diff --git a/depends.txt b/depends.txt new file mode 100755 index 0000000..66340fe --- /dev/null +++ b/depends.txt @@ -0,0 +1,3 @@ +default +unified_inventory +mana diff --git a/glyphs.lua b/glyphs.lua new file mode 100644 index 0000000..6d8ddfb --- /dev/null +++ b/glyphs.lua @@ -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, +}) diff --git a/handlers.lua b/handlers.lua new file mode 100755 index 0000000..82d26d1 --- /dev/null +++ b/handlers.lua @@ -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) diff --git a/init.lua b/init.lua new file mode 100755 index 0000000..209f939 --- /dev/null +++ b/init.lua @@ -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") diff --git a/registration.lua b/registration.lua new file mode 100755 index 0000000..328c653 --- /dev/null +++ b/registration.lua @@ -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 diff --git a/scrolls.lua b/scrolls.lua new file mode 100644 index 0000000..d05d0e6 --- /dev/null +++ b/scrolls.lua @@ -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", +}) diff --git a/textures/runes_black_magic_block.png b/textures/runes_black_magic_block.png new file mode 100755 index 0000000000000000000000000000000000000000..0717ce46ea53983506bde9e5c87c5b451bf05875 GIT binary patch literal 2167 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 LNkvXXu0mjfLwF4u literal 0 HcmV?d00001 diff --git a/textures/runes_damaging_minor.png b/textures/runes_damaging_minor.png new file mode 100755 index 0000000000000000000000000000000000000000..65fdfc639f01228f609f9cb4275d2120342f872b GIT binary patch literal 3290 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 Y5Aj+zI4@9+IRF3v07*qoM6N<$g0Ec9DgXcg literal 0 HcmV?d00001 diff --git a/textures/runes_earthquake_major.png b/textures/runes_earthquake_major.png new file mode 100755 index 0000000000000000000000000000000000000000..46eca86b49616e1fe2e42473a323468eb04cf0f0 GIT binary patch literal 2500 zcmWmBcQ_S_8wc>OV{bB(%8t0MYj-8WNnF{oA{4hs#7&y^US*Y?L}ZssW=3XKMP_nv z-OS9Ka(=nz_dcKZ`~Ler&o|1{Sf8Cmhy?(ec@LGSN~qt0rg}pqVu_vLxE5 z@?O!|@1?ijn<#W0xItwg><`=oZUMJ}JHTDw9uNQo0zp795CVh(VL&(#0Ym~(Kr|2o z!~$_ZJQabE0Ne*20Es{nkPM^%slY?v5s(I?0~tUj^(7!1$N?S$xxf=34|odX0|me{ zppc3{C<2}X#Xt#A3X}omKm||WLW4-5cDhGkjz%)PtW`J3$CC)kEA7Gx!N$_9b3)LFu0y@`?8bN3K%mD^iEpZ zwB5D#j7+iO%1-k=WBuT4LsXq>>i4nq^c?%*g>Z7v`TVm73d}D_rW7;r=U9bT;A@VL6z7fmFFMdBYaa`%&#?_DGOP_Y9b{doh(r(Tl^Npvd zCUGh8tlG1%vZO0}8r3Yk*1le5SC_k2cE0hfg@tD2D(g)C8a>^K8KyZd=2O4aYN$+` zG}s7kvg!=(o)x*TI~}sbP^-}r5IjE2*sSOBazRart4nkdk2KO=3wiE$WOQtkq9u9EzPaY{oLmErwO5P&e${6Y9Dnx%|XL<&bs?k(XHdhx4vflj?H#KFj6jf z(eO-kiv|WQ3Ds(7WF(Q?QpOvXq(dI)1ucB!0Wf zT_|UQ_X&r#N}OwdrR21reYYstDw+Glofo4#x!x7!k_5JM!+IC)Y#dDR32xr%QwYiM z5Hj8O#Zv7zk%G2H2mT3RCrdVm*TO*?4+`I9-q&T3d!`W<8l9ae{Z{>&rLQybFTSalKx=GN_TQZ|A{3A*CjBjikGMt$F zL)!M)?jeQ)YZSlJ7vCJd8GbF0PbM`sb0N6KbfnTTxhweFL$bqULSDh}CcOc_Zm73R z;0y1nXSA1`b{YKxo7^riFMHMX{aSfMBBe^KXMMFlX0YYn)QyszH^F)bjeHqw8`!GC zv*X7tFL!j!C~ha3cRg&rI`I5;XY4tDPj1(q3qn(W%6Xp{8mX7MS!ZUa{ph*4Y=O8D zuZx43QeC3VPO>!7>(as#(}@jNAK-(;+mPJeTq>KC|U(wI)hc_FD9oNy z)ag7L`l6~=7Jq8Q$vGVJFQ#i7dI?n<&@lC04OdvuLLxx}f4pM2mEsEzg+#_th+mNWR6r zJ2qupX=!yor>+re$(_Dj~nyoI5rz(e-J}MY0et5tf=|6UKiLZU2Q(GzeZ~OBc z#Ja2Bwzve46yxTo8 zY;QJQE>WH0)Blxt#lAM&oNn)^S80PxbyCK)A+eu+m9EBBcST-|YLZ2Z58|HwM&Oii z0+@q`zqVKB*nG$iyq>9*&bON_wnDR(;pHWBBG+=~bSU2lscNxG%+yVI!oX#dcvkRlf}|Y^R^nUq4gCLmAkliId-rL~b!Rfk}DT{O_`Bff{65 zo4$R;I{Nlwat`p0=bRbV&h^#SHrUT4nMOl%`Qua8jQ8!&Q@6Mcs#_E2chrr4qYQj0 zKdfA5eh@kWmb>aKpY@LzFrT*wjIsJfo3vp))8t*V!mLRO=y7?MC0sYX89kWR%1qu- z>^Zh1qa5*P&!?wqlmH*su~$u3H#Mu3cpN#G?3ScL<(AWb=*&#ZRE6C<-=IE! zRN2^>%DEf;AUrPDXS;9HT@;aM+%KO6Pes4~6O(Mk3CbO$`9Ird@=(62wMw)5uiYbXh zQ+MTy&lfc^TUm_iOZL1Z?Ph(3#FhJv$$LR?3e!bzSO?SPE^LIMKg znIX*)F2$aZnzv{5N1>7ynH1w>BzNuSMP%+kyC6L(<=&sU%!#tvQ0x3(ORfyAsEJpPoPWGbbFZbV^=~=*&CS^r7@~ZWrWj#aSKKlPR=JO;Sm8TvrI7 NjsekFuS~}&_&?g7NMis1 literal 0 HcmV?d00001 diff --git a/textures/runes_earthquake_medium.png b/textures/runes_earthquake_medium.png new file mode 100755 index 0000000000000000000000000000000000000000..46eca86b49616e1fe2e42473a323468eb04cf0f0 GIT binary patch literal 2500 zcmWmBcQ_S_8wc>OV{bB(%8t0MYj-8WNnF{oA{4hs#7&y^US*Y?L}ZssW=3XKMP_nv z-OS9Ka(=nz_dcKZ`~Ler&o|1{Sf8Cmhy?(ec@LGSN~qt0rg}pqVu_vLxE5 z@?O!|@1?ijn<#W0xItwg><`=oZUMJ}JHTDw9uNQo0zp795CVh(VL&(#0Ym~(Kr|2o z!~$_ZJQabE0Ne*20Es{nkPM^%slY?v5s(I?0~tUj^(7!1$N?S$xxf=34|odX0|me{ zppc3{C<2}X#Xt#A3X}omKm||WLW4-5cDhGkjz%)PtW`J3$CC)kEA7Gx!N$_9b3)LFu0y@`?8bN3K%mD^iEpZ zwB5D#j7+iO%1-k=WBuT4LsXq>>i4nq^c?%*g>Z7v`TVm73d}D_rW7;r=U9bT;A@VL6z7fmFFMdBYaa`%&#?_DGOP_Y9b{doh(r(Tl^Npvd zCUGh8tlG1%vZO0}8r3Yk*1le5SC_k2cE0hfg@tD2D(g)C8a>^K8KyZd=2O4aYN$+` zG}s7kvg!=(o)x*TI~}sbP^-}r5IjE2*sSOBazRart4nkdk2KO=3wiE$WOQtkq9u9EzPaY{oLmErwO5P&e${6Y9Dnx%|XL<&bs?k(XHdhx4vflj?H#KFj6jf z(eO-kiv|WQ3Ds(7WF(Q?QpOvXq(dI)1ucB!0Wf zT_|UQ_X&r#N}OwdrR21reYYstDw+Glofo4#x!x7!k_5JM!+IC)Y#dDR32xr%QwYiM z5Hj8O#Zv7zk%G2H2mT3RCrdVm*TO*?4+`I9-q&T3d!`W<8l9ae{Z{>&rLQybFTSalKx=GN_TQZ|A{3A*CjBjikGMt$F zL)!M)?jeQ)YZSlJ7vCJd8GbF0PbM`sb0N6KbfnTTxhweFL$bqULSDh}CcOc_Zm73R z;0y1nXSA1`b{YKxo7^riFMHMX{aSfMBBe^KXMMFlX0YYn)QyszH^F)bjeHqw8`!GC zv*X7tFL!j!C~ha3cRg&rI`I5;XY4tDPj1(q3qn(W%6Xp{8mX7MS!ZUa{ph*4Y=O8D zuZx43QeC3VPO>!7>(as#(}@jNAK-(;+mPJeTq>KC|U(wI)hc_FD9oNy z)ag7L`l6~=7Jq8Q$vGVJFQ#i7dI?n<&@lC04OdvuLLxx}f4pM2mEsEzg+#_th+mNWR6r zJ2qupX=!yor>+re$(_Dj~nyoI5rz(e-J}MY0et5tf=|6UKiLZU2Q(GzeZ~OBc z#Ja2Bwzve46yxTo8 zY;QJQE>WH0)Blxt#lAM&oNn)^S80PxbyCK)A+eu+m9EBBcST-|YLZ2Z58|HwM&Oii z0+@q`zqVKB*nG$iyq>9*&bON_wnDR(;pHWBBG+=~bSU2lscNxG%+yVI!oX#dcvkRlf}|Y^R^nUq4gCLmAkliId-rL~b!Rfk}DT{O_`Bff{65 zo4$R;I{Nlwat`p0=bRbV&h^#SHrUT4nMOl%`Qua8jQ8!&Q@6Mcs#_E2chrr4qYQj0 zKdfA5eh@kWmb>aKpY@LzFrT*wjIsJfo3vp))8t*V!mLRO=y7?MC0sYX89kWR%1qu- z>^Zh1qa5*P&!?wqlmH*su~$u3H#Mu3cpN#G?3ScL<(AWb=*&#ZRE6C<-=IE! zRN2^>%DEf;AUrPDXS;9HT@;aM+%KO6Pes4~6O(Mk3CbO$`9Ird@=(62wMw)5uiYbXh zQ+MTy&lfc^TUm_iOZL1Z?Ph(3#FhJv$$LR?3e!bzSO?SPE^LIMKg znIX*)F2$aZnzv{5N1>7ynH1w>BzNuSMP%+kyC6L(<=&sU%!#tvQ0x3(ORfyAsEJpPoPWGbbFZbV^=~=*&CS^r7@~ZWrWj#aSKKlPR=JO;Sm8TvrI7 NjsekFuS~}&_&?g7NMis1 literal 0 HcmV?d00001 diff --git a/textures/runes_earthquake_minor.png b/textures/runes_earthquake_minor.png new file mode 100755 index 0000000000000000000000000000000000000000..46eca86b49616e1fe2e42473a323468eb04cf0f0 GIT binary patch literal 2500 zcmWmBcQ_S_8wc>OV{bB(%8t0MYj-8WNnF{oA{4hs#7&y^US*Y?L}ZssW=3XKMP_nv z-OS9Ka(=nz_dcKZ`~Ler&o|1{Sf8Cmhy?(ec@LGSN~qt0rg}pqVu_vLxE5 z@?O!|@1?ijn<#W0xItwg><`=oZUMJ}JHTDw9uNQo0zp795CVh(VL&(#0Ym~(Kr|2o z!~$_ZJQabE0Ne*20Es{nkPM^%slY?v5s(I?0~tUj^(7!1$N?S$xxf=34|odX0|me{ zppc3{C<2}X#Xt#A3X}omKm||WLW4-5cDhGkjz%)PtW`J3$CC)kEA7Gx!N$_9b3)LFu0y@`?8bN3K%mD^iEpZ zwB5D#j7+iO%1-k=WBuT4LsXq>>i4nq^c?%*g>Z7v`TVm73d}D_rW7;r=U9bT;A@VL6z7fmFFMdBYaa`%&#?_DGOP_Y9b{doh(r(Tl^Npvd zCUGh8tlG1%vZO0}8r3Yk*1le5SC_k2cE0hfg@tD2D(g)C8a>^K8KyZd=2O4aYN$+` zG}s7kvg!=(o)x*TI~}sbP^-}r5IjE2*sSOBazRart4nkdk2KO=3wiE$WOQtkq9u9EzPaY{oLmErwO5P&e${6Y9Dnx%|XL<&bs?k(XHdhx4vflj?H#KFj6jf z(eO-kiv|WQ3Ds(7WF(Q?QpOvXq(dI)1ucB!0Wf zT_|UQ_X&r#N}OwdrR21reYYstDw+Glofo4#x!x7!k_5JM!+IC)Y#dDR32xr%QwYiM z5Hj8O#Zv7zk%G2H2mT3RCrdVm*TO*?4+`I9-q&T3d!`W<8l9ae{Z{>&rLQybFTSalKx=GN_TQZ|A{3A*CjBjikGMt$F zL)!M)?jeQ)YZSlJ7vCJd8GbF0PbM`sb0N6KbfnTTxhweFL$bqULSDh}CcOc_Zm73R z;0y1nXSA1`b{YKxo7^riFMHMX{aSfMBBe^KXMMFlX0YYn)QyszH^F)bjeHqw8`!GC zv*X7tFL!j!C~ha3cRg&rI`I5;XY4tDPj1(q3qn(W%6Xp{8mX7MS!ZUa{ph*4Y=O8D zuZx43QeC3VPO>!7>(as#(}@jNAK-(;+mPJeTq>KC|U(wI)hc_FD9oNy z)ag7L`l6~=7Jq8Q$vGVJFQ#i7dI?n<&@lC04OdvuLLxx}f4pM2mEsEzg+#_th+mNWR6r zJ2qupX=!yor>+re$(_Dj~nyoI5rz(e-J}MY0et5tf=|6UKiLZU2Q(GzeZ~OBc z#Ja2Bwzve46yxTo8 zY;QJQE>WH0)Blxt#lAM&oNn)^S80PxbyCK)A+eu+m9EBBcST-|YLZ2Z58|HwM&Oii z0+@q`zqVKB*nG$iyq>9*&bON_wnDR(;pHWBBG+=~bSU2lscNxG%+yVI!oX#dcvkRlf}|Y^R^nUq4gCLmAkliId-rL~b!Rfk}DT{O_`Bff{65 zo4$R;I{Nlwat`p0=bRbV&h^#SHrUT4nMOl%`Qua8jQ8!&Q@6Mcs#_E2chrr4qYQj0 zKdfA5eh@kWmb>aKpY@LzFrT*wjIsJfo3vp))8t*V!mLRO=y7?MC0sYX89kWR%1qu- z>^Zh1qa5*P&!?wqlmH*su~$u3H#Mu3cpN#G?3ScL<(AWb=*&#ZRE6C<-=IE! zRN2^>%DEf;AUrPDXS;9HT@;aM+%KO6Pes4~6O(Mk3CbO$`9Ird@=(62wMw)5uiYbXh zQ+MTy&lfc^TUm_iOZL1Z?Ph(3#FhJv$$LR?3e!bzSO?SPE^LIMKg znIX*)F2$aZnzv{5N1>7ynH1w>BzNuSMP%+kyC6L(<=&sU%!#tvQ0x3(ORfyAsEJpPoPWGbbFZbV^=~=*&CS^r7@~ZWrWj#aSKKlPR=JO;Sm8TvrI7 NjsekFuS~}&_&?g7NMis1 literal 0 HcmV?d00001 diff --git a/textures/runes_glyph_deus_ex_machina.png b/textures/runes_glyph_deus_ex_machina.png new file mode 100644 index 0000000000000000000000000000000000000000..997da49fd6d3daeb3f057e2d05854e4a84236728 GIT binary patch literal 418 zcmV;T0bTxyP)B zc|0w#`P7;O`%j{DxNzS1bGh}86Ob6(jX(-ms#i=v0;kz^MVh#6*dvbJg(s1C`C z7yzJ~8(8De&5dXu9ZcW{+Hp;ut5XFKdmM^yYpnyCe5H_=kjdK6rXdtrz+tmYLYC+8 zv|Oj#>SgFXiND@oT7($I)sWs(-eVgD@#Q4i3%E1U%}tfcZ_)`JNqJt>j=wH@UP#1+ zNP8ud>Z$+_y_9nArFw4>h=G6Y!-SiA=hG}&2Xf-K)RI>0$asU7T literal 0 HcmV?d00001 diff --git a/textures/runes_glyph_manasucker.png b/textures/runes_glyph_manasucker.png new file mode 100644 index 0000000000000000000000000000000000000000..edcaf6b43ccdfc23c8d28c02c1b1392863336abe GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`5uPrNAr`&K2@AwlOpE_AU&c;& zsn}wPhCFU71r`5E<{6J!ix`x5Ic)v2=>J;&#}X5N?l9SI*OQ#0;wEUvZNRYdWusZ6 t$Mr7`dox_jwth{NQC75DDt4HWVQZ<2#nr7{qCh(sJYD@<);T3K0RR@5Fc$y- literal 0 HcmV?d00001 diff --git a/textures/runes_glyph_prankster.png b/textures/runes_glyph_prankster.png new file mode 100644 index 0000000000000000000000000000000000000000..80476e2cd6edc716003659c72004e65e17cb870a GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`<(@8%Ar`$`gHQ4vFyP=8oop!L zY!DK*SYKQ-P+SEjgEN-NN7Dvyd82V;)gerXt55LyrZ8;~z9k;dWMRxje-`1`1T98y1zV!|3`5n7FjwSh|)IHCiQdEDC Z^Yx~n$QO@yKLI*{!PC{xWt~$(698HRKGFaH literal 0 HcmV?d00001 diff --git a/textures/runes_glyph_spontafire.png b/textures/runes_glyph_spontafire.png new file mode 100644 index 0000000000000000000000000000000000000000..de19275cef2d0cde8c881ac8d698b6833ee01319 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`L7py-Ar`&K2@*vQvUv~Jr`Rbg zvc728%^J+_ceaH`nWMvyVR`Wc)5pbTo{0_D|KBiC{=EO1!5?)?pAOCtwMjllm_GdG m>|Xogp+ks*5YL{4ybOWc)HCc|{fdF6GkCiCxvXTGrESu+-xB^ZFjyGbK9?(e>*-bXe&cE8S#574e+%V*d=-2)fxXAn Vr$NnB$p>gZgQu&X%Q~loCIBx1KeYe= literal 0 HcmV?d00001 diff --git a/textures/runes_go_to_me_major.png b/textures/runes_go_to_me_major.png new file mode 100755 index 0000000000000000000000000000000000000000..c285844f48ea367a43f0d2e8fb55308572cc293a GIT binary patch literal 2255 zcmWlb_dnH-AH`qqaqaDfima=FY(kk)RI)Wbk`W@IkB0j}_ad??m2QKQRlc&bv$x2) z;S-fj61uMJ@$o&6=Q-yOIKP}oi_^!sId*XX0Jo`$k=1tV|KDubcD^hQ{sn+!S)8&l zh9H12b%+6oI}9{{B!CnHcn9!~0GR~HB0x3)atM%1fIJ-X2#`;J_XH@wp@0B|I200~ z2!|p96ys1#fD#-^2vCYc84e$CD951!he{l(aHz(i28UV)!+}LfUq{J2$#(C_ZRa88G{yf23 zD51VSDJdz%PdGh2JvTSEq@={?z>Z4*EZH<%!*>kvjp6B2`2r=C&Q z+z=+N#CvaK8m@m!s@uOA^{AeVxiJgT*Gw@wL+zD-vac?fKL}(gU&^RtK08iIM>JW7 z7}q{VkdF5k^;lN)FD#pe)G8S{Mkrp&DCXq3qXpdI4Att{p}*`o^_Mwbb&dI(%oQoL zYkjSrI-rx}vCCdAFiegr(nz-)DCM{6EA+f@xJUW^hwx86)W((8@kK3m;h6=Y;C%Ua z{Z?a(?TEyq@15uI?i#TO5eu7v85+kk&ofL-xe7$lS-Zm=w3{c^-sEO*u!T4?xOH|( ze4fD@S-kz&58RZZEVWAo~aH$xd^IaE~LVU#8i3-H| z{PS6T)9GKGoYoI<;NNjl_S;hFOD%S7=@AW#s{I0VPkS#FQmgUbM`^0vO$U{y_DIK5vSF_rXl(NCL|#W+QIJcxa8JjjQ;Qt%xB*>i&QFNh zLCuLncu%?|`2C^0X<;e06p5%kN>9Bt;7t|bZ{mrg+(^rC2jl*LrF)6jn8vcYH$=eh-BxTccK8L@o9>wT;qf=D&8!XR^^^Lj3oa5Jp9qdcPRFXW0v1+Wfl8_Ld=FM&=#zj zQpPpoY2_l)R*3el`Jm%>p2JK}znohcIfqBqd5`o4nKJolC1H|mV73z97fGDa~|b|gLetZZm+;eDwO!aob+2Z!Xz54R)-N&KcZR2Ad}MQAv1UBqov z-u;Mk3_BXa!=7?%PN&1;#ROTXZDtFDG&_A2H$AE3RADiz<64vcWbsABa*oyYp}-jxl%pQipexPklcH&JYp<8p33JJqj|wvrKFB)9|l zN;Qm?04MQ?b1K7UYgm^~kz%0au!ET5EbrFyc$K z51N;~?p95CGG0gDOEhK-C@9l=3!fMsNSkN9WMOoP>+QKW2UR|;Tah;4_QcD8!S~bc z`TBu#>m^I&@#Pw~IyW}1A>CbqkEZ&)`*f#O*=LP;Tw_X#GK?^n|oeDTJKBlSMpJJ}ZpYh|>Z^w&;UimC>O z$9ZcQ`k$eeW$YfSWpEr{DJ8NExCSOttog#b^s_Zi2y$EC^;WiKJti_0%QELvr3Quv zXU@+D=?z8S^NG{6yR*b==wLUPA+YcBTtklbYEm)pZ7KV*@`WR%`OD@HPYj2~POg|; z3kax7bl3B&sSncgn)GV9kW(sQz+&)Q&)`bVx-EB-xMZ~oNzF*^?#BFJC`;7q2Zkpv zD26_=Jwp|h=jAPk6@D6SAAJ|=(tB{nmv1jyQc6;CtXE!z(5TMy`GQE%rW>xL&rj;B zvLwcjss8;d{>X<)BrP-IgtCU(ydZN0d-A|dO))=Of+QMZOaH=(bsC(kissQUuKxGcQ zCGnz+MG?P?fwc3>#6 r5T{x}f!DxI$uCr^^=g-h{hOTMf~6nE?cf>QJ}O{peA+16&@tpcVi@ex literal 0 HcmV?d00001 diff --git a/textures/runes_go_to_me_medium.png b/textures/runes_go_to_me_medium.png new file mode 100755 index 0000000000000000000000000000000000000000..81fcbd7f766496b981b0033248f03afd222a0e90 GIT binary patch literal 2227 zcmWkwi8quDAN@VcAkttWLX0RPOO2Aq@FGUmNK{JNNsBhGZK5HxkWv(~B(E4t2t|Xj z6xpVdhU}(7mQl8t&v(yV{(yV#IXBY5ZnwDTT2TNHx3)5OT2AW!C4wz`(yQyE07$OG z9%l;(0$}LFEr9zwAs!$VAl(#R0K6bT4gqorz$8E(0rCk@fI|TR3JLI%07Wf0P_F~0Dl1%0hRy+fXpDsEV5_TLXXUQ3124>t^U_*+&_$Cu~vYi6%1L{#mlz9s09N zEv!N}Rx&c08aYdWvjN_EwTG#0{S}bXQY=m#ao3){yA->kWkDoIyG-bbAG!3i=iNs~ z#90#8ac1nO1Ba4I)NUvjyu-!5ZDc){KXIIaWa-su(w|i68_3XSH4T_aQr@fR#WEZ7 z`(pDPI`r>IhcF!J&&ZqYEb1Of+$tbXpZ4|kt;8s!kM;ecW1VR78p;8+k!MV&6xaTE zEpi}iQ_!vyHzZvrTuF0i=fv$+;$N=HcEccJmwTV7600M}Tgk-hBu|^xk&(zS6^AX_ z4uKtuW`|Dtq1K(Ka*`B@^C0`$lDr-=ZYbY=qqXn6(Ym-oR{vjO6#ffmA5$e2@m5Lg zU17ryQJ3UAFZl1>(=^phgw7VLhr{FQl8TkLD%BaTlNUx^g2;vX(uA=rt;V2)*a3vz zBv?-d=O0@&Z}W~$B+zCq z&{Mgis4nKaxSnNYTNTq9XqbIS^5`iq1vM?+ zg;1LlPgm)y#@O%vy?Kh^R{4)ruUt4;Z2NkaGsj$b<<17dFI}3mw2GX2EVFUd#-GlB zN%QBea=MN_I7QGRpEo@AJ;QYAQme4e{Qd(86JaN8wN6L4A!18sv=^k5a6`iCy!!P^ z9O99#5(4At#2QJEIXEoz3i(Xh^Eq!CUNp?zMk`+Iot> z^Yo3Ks($caFN@s4a_4mgg^<>H3unpBW<%z%MO0{`jlZ5{26~BoRdOzXTO=;MSRY|! zkfHuat))yWDosm=gmXccz@*GXg)}{1$ReXI>?AmmR z@1f|-HnN=OFEu~r?`YwNCQfb7BWZl@?&>C;dNk)5b?e@Gyh^sIfbF=Zz*#8QThZc* z{YS6uZ>!v!+sul4_B9o9X3xx#naC z(sp2e#e_qQ$0Ju+c1%Hg@mU(*W&7EUo6u5(p==7(yChy7tIo^b0%sD-SJKTe*)NvL z9?Dna3EXcG{35&Ey`x;@NK?(9yE*C@Cq`i%F@5fi) z4&%3%y6z07Ews^{j7Q3a2D9Mwk2T(nXSgLJ<-t8+C|dn#z^3e9jmB)|9Wkm+sKon$ zKLuw~N*33(RbF~BrX+qXU2E?-3&;3+`c6BB2GKw{{z+?P$k)r=ejOD*=R(p|hdM}U zZ`3JNQevj3XvQ6p7n>3{SF0I%QWt2B3R|y--}l{ScFmPuo-IFEJt?|-u57gk_jq7R z$XbcRC43V!skVFl*KVz$*y<<$DRd2rmYc#>M!QG%tCrDNrOkeN z@sv7-amKrqP62xw3wzs#f6q$^j|Eibt#Dj@Sk0kC(#v%H(WI0V`wd^FPU~*f)@~}( zkLbLjaB{4adQDcwK7LVmWffgY&-eT2YC&_e!$jWm|Q$L;$i9N R{pB+P))sc=OtT}Q{{sl1*<=6! literal 0 HcmV?d00001 diff --git a/textures/runes_go_to_me_minor.png b/textures/runes_go_to_me_minor.png new file mode 100755 index 0000000000000000000000000000000000000000..6701fecc840baaa8452c1d0366118390e955e580 GIT binary patch literal 2170 zcmWlbi9ghdAI3l5V=_51l`ADz!l0pOD@UVfkjmMnYvt%SGNhtOrAA9ulw(B-ja63U zOc^!EeUw}|O3G~pcREy z4BAj=!{8$dA2Dc0p&f$`6gq!_K^F?2Q22~OHws@+=t1Et3g1xZMWGLcegyha7(ieE zg+T-cQ5ZsC2!&w;hEW&+7(sxCz$gM^2#g~zfxveJCJ~rIU>X5F03U%F1OxyA1ZDwd z5tsv*Ltq|Y9)Sgb1q2oWgaAJPmH?IkegdojhyYnYkVS;WVuhYw9~~VX=Ovq%n3&`% zmztWIc1b=XBO@;_kHg`d%2x6LSQTe&VeWJVVYGzDKBSUr_^YCVXgbd0s&qpwtuZ&- zisuIP!_Nc(3(bE3ky@lTl5&ggy;Phd+X>*?A&uBgO%lx{n>n0srBhnn)_ zD5r)q?NdfV6&Ej)k1&XC*Em++oOv4xDVN_U>A2n*2+nmVFm9au>b!3&7$|7n?#)a+G22K0~ z!Nms0mBb7a$5=aCuZKAf`*(W7_7(Zni0f3;Zi=6h^sfI&#%t&$$kZOA#Xfm&C4T)F zYNE8g_R>(WoWz|lk|9+s+?CHY&Ac6LpzCg?DSVwoacx;wPAaeXHAd1SN<6k(_?>;> zvPJYj{Z77`k&59Nvm|}rGd2g*bVE=7kyd_e_bL@u?-(oFb}zZy<+*w z+r3rGJ1CyP61F}Xmn*J{$#4ZH3!jDqSAta8LKN*tPA&Fs-=sgP^pC~n=BE0P_CDT_ zW$38?@MQdnZGL>L)0o5|eQVj=9VZ zBf#paB7i0S*)s}BYd`*JA3xvXRs><7D+ zx#iebLtV_0mui^BfvXYI-;@RJTipV0%DYgskrX${+E+era>6EDzthE5q{gJzhHj2> zxnIDdc8)lXrS~z`-8%krQA%{fc#6y98CGXVs>LebZ^-OV^@=pmGw6BObbu$5?iVGa zKdTZRXQxIDaE}wrxEsWK^L_n493qkY=?cYimgVlw&H<-%Zm$F&rZxd`YQsDCSR|rK z$7wSrBhR!N3dr~K`9+!Ae3&I(^ZeN=?S|2d!+lqs@fpVQvlunb>7D4U6m8pBPuk|0 zZ^dJ;`QDrK?J_-OG*}4H^lQ(cUvHA}fkf zMect-*eS8fz{B6)MW<}n_xZ52bL&;g*rX>!YL}Q>yajJa4`KhjQ6$CMC$FEkF;wfR zo1CZNu-MzF?lST_zukwl{;J4It~YFPlDdoaajRkX?(qJC=MLu?k`;eeYJ;07Yt`n9t5yf)(w=mbQD=Co#|MM+PSz~+$rB=~ z3#w@wi7|*4l0O)jnBY)vzPwJ)A!cZLYQacYsytm@qiLf+?wh+C?IBDssa&IKHt$XQ z_I{>AI^VN=Bb^6X+!L91YAy~qJo4t}sSc0CkiLel-p8YB z9nv_VOR3_d#++38XY^x$=ayM3bU^xvuc3N(>EZtIjdle|TI=1dvEns8*LYnMwcEod z9w(+9d-(g~-?MhzTk9LI#b%eD%nmkEyz6h0TyOs4=#D`#1-YOi$uu4r9oS=C^}s&i z^RE1Bm{n&aqx<%|2P1-mjKV2lsj6;5pEF+VZIJ#^wL>Tj%nj2}K8}s|yBQXS=^M9= z`kMs=PwVTZaOdSC2nu#vYK)ST`==(Jw|yVe{1M$=wC#C|pGk^s(kI67>&Z>63pXG* z-}M0Jcnhs#)a&227>a*!+}D3spx`-QLFy2r_QFXkIkwE+X$3WL5qfK8{m8lxP3M1o O3b3|3Y>~6i_11rkS+q3( literal 0 HcmV?d00001 diff --git a/textures/runes_grim_reaper_amulet.png b/textures/runes_grim_reaper_amulet.png new file mode 100755 index 0000000000000000000000000000000000000000..9e68a3422d9828ac74814d2f6da4e72a40b5c6d4 GIT binary patch literal 705 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!&IkB}xB_W$aWOqT9b*#{6JsC& zqOGm1tgWqWY=8&|Y;A09ZEb8E#Kl})UEP2P2;3pS!^_Lv-`_tVARsUhhynwHfCvcu zBBOu+L_|jeQ4A2o#>A$8Kq?TV0a0379uVXM0f;C7A|NOP!h+J$(#p!pswyC=uCA(T zXlQ6|u5D>;X>D!o>gwtTf(iYTCr_R_wSU^Q2{UI-nmKdwoHGp zZt&msDq~?{lgNz!f{(-wb%+Yscl9`m`7AeM%@gkPNO|3OyG7Y(<4%rfj|le5SS*2*;#rc6-qH z$HkSC8$WNJ6~Fqrblu}elO74H+HdS$H|uQJ>e9P;+ch_qNpc!(H=n!vT1zhI$19r|7xGl{x8!C?*Su@!PC{xWt~$( F69Am^D);~Z literal 0 HcmV?d00001 diff --git a/textures/runes_heal_major.png b/textures/runes_heal_major.png new file mode 100755 index 0000000000000000000000000000000000000000..aba4993cb538883fc87d4bf79d44d56d3175e540 GIT binary patch literal 2610 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 XbqZ2(=gZVd00000NkvXXu0mjfy+3AM literal 0 HcmV?d00001 diff --git a/textures/runes_hellfire_amulet.png b/textures/runes_hellfire_amulet.png new file mode 100755 index 0000000000000000000000000000000000000000..4e294d58dfc1c6ca91a29c3490c942c51eb7b6bd GIT binary patch literal 673 zcmV;S0$%-zP)b#--sfPjjMij$L*#~1*|Hvq>%0LMxI$5H^)8UWNg z0MthS)K37^R{-D}0N_3V;7b7DQ~=;z0PP(B?Lq+UPXO&$0PSJ`_Z|TEMF96w0QXz~ z`ey+8odEj20Q%kl{~rMVM*#m-03;(#Jpcdz2Xs4jZ(TVhO(RZ*e4&7FteF?6HL@&rNfbKo@Nex z2(#q3%TuratK(NwB`~h6)QzDIfDp5 z_<@<=WRgJysE2Vpcp1d8VkM;70a%3Cfv3|z0LKITlZi|Y$OFezX%19(4*1ic0^*L$ zQ4r>UDLw~m>Gc1zkTM%U+4lhZ`5uUKz?3itj7)wFS(zA+1C-`~$a$H-7}VeY0<`P^ z0&+kE0MF$B$e=C{kxOLIn&l<$+#VU) zNtQi!1^`}4!;@v>@%bEuR0E$(E*GKzL2Ifzd^){e4aLI&1yTPyd^RgfLm`tv4WK44 z@Txi-N+R&6`Rm*JqB@>V$Lgc}{`$1Fh7)u^p^aftRh!NJ7Y}@IunAV{wSn)8!d4*V znCJP*P!z>(M|dxmBye6Z6a=UDT%Hbcg7;NFjx`v#>G3sn00000NkvXX Hu0mjfpMWgy literal 0 HcmV?d00001 diff --git a/textures/runes_info_wand.png b/textures/runes_info_wand.png new file mode 100644 index 0000000000000000000000000000000000000000..d4ffa447738f82f437aeb68b44283d1aa3b2a3c5 GIT binary patch literal 153 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 P=SzW`t0$$xnV$4N(=ul< literal 0 HcmV?d00001 diff --git a/textures/runes_megamana_minor.png b/textures/runes_megamana_minor.png new file mode 100755 index 0000000000000000000000000000000000000000..121cbaec1d43fdf6bc2a3b083d8192c9da82095e GIT binary patch literal 1868 zcmWla`6JW`AAmoMW1KrJwdu5l7#pLeC9mF)!F(Md9TZXxUROFWt>ow}Dy&4_$k1%Z zvX!!3NQnvM8YF2LHpkbJ+zp2LZ0`@x^ZW_V1vgg*4b>H@0HDEkwDb5@>;FTgd~@E@ zgwFtSv2M8`9YQ<8dxQ>z4+xzI9}z?dT?pL>VuT)q zUWC68J|XlW^dk%)3?h&SLkNE(3?qynd`1{W_<}HoFfM~}gb5i;AWR}mAxtC8EWnHm zW)Qy0;46Y;5hOB@Ak4~O7GVxyUIz0BQW;1Q77!K@WJolTL^DYUNuq@$T1ldfB;Juk zJ4w7Ji4KzZKoXrK@sT7%B+*3@-6SCAA4YE1ZKuzehL<508#gID}drfww;Y9SFTIg5?-aN zU31Jgw5^rCN9Qp`LJM}WFPWH^HYx8ZpQ#d*FXoB?eA?>IA}?yS#XpN($s zm2=Q*tR}V5rMg{o>vinI21@Mn!HR5^Galo6OAkb>sr+(_sdepcW*3q$1?ML zkB>=qzs{Iqd@a=?lpSRxfXZ{@!6? z?~eA!?sqOtU0G?heMSz};d^puLYnqDi-tm|0;SwEsH+EhEuCfiM4M_-Kxy@Y(e6qUg0x%i#;O=*-q%<{V*L_ntp>}7Uz5QUimrYtSe#rb|?{>_`fDoH8!2J z8uM1w35cZ5+`fM+^wbva9HT_aAF`{ODq`u?*zQ);O|ZW*`C{#PIX@pwodIRB*~drP zOZIHq{C#1ngyeNA|11vgOVRs%;JlgE;gOj##=`C*+S~6pSc@aOOSkW`*&Jgvcxu%) zQxyp0Zh7ME^~*kOmK>j6Ar;axnGJT_&`$sSz%+-LPiI+2sd`o#1D!qU<66HS>!|q} zH~2rJyuEd(YE;d$Phe1A)&v{74cnH7)_V+PJ6Xl)W@pJHxt-A($Mq^UD7`+(Qx~bE zY@GY;r2*aEWH8X4f2VCttHfw+)%LjpPSC8dfxHu7_@Dh_zY)y1@BIAyukDmDheD>! zX|cERObf#HcbV?rRet?&}%`0T3 zgUJZRvpr=ErRLI{yhZ;>t0f|4>Ltb7bDekEtAi9zcXq9s(~pc*XnANDZ^cfGncrCe zO4cex$%V$dc5m6%lgJ=R2ccD{wtDsGRlP}9`oSXa=Jb5;8}?xgU#b64(#nnIM)i~9 zXW|9Rrz-es9iAvDmfasK-WJcgc<806ihi)8^OT>2C64JyFxJtlSF?cC!CZyO<-Q{- z`gzYey3J}_UAjNFVd#Nn<;48^=n~PW*pb&(Vp@Yja2SG;nAq;{r|H(29F~3arvsW3 zr;R;Mm^y@*{VSwzq1($Bv?FesxCQB0Mr;L&GRcqG%DNkMnQRQ0T1Zr5vK3T}))lIn gP5-VWOfZO(v#Kv>@gMoK?b{`R&2qK7Z+kHDA6S5+cK`qY literal 0 HcmV?d00001 diff --git a/textures/runes_minotaur_eye_amulet.png b/textures/runes_minotaur_eye_amulet.png new file mode 100755 index 0000000000000000000000000000000000000000..930738bf568d48d1488a8e1138bb4533ad3241ae GIT binary patch literal 463 zcmV;=0WkiFP)i|>EhZaS&#Xn%%X zMV*hTka^FG0g0Os-2N$Cxmz-l-YjN7nE$kxA;HsNk#`g?e6#RxkF3wNIfriG5WgIu z%LYP!JP&xNY(i(+T#_d_kT7{;{K$%dEv7xo&+&Tr-%cQeSrW_l|#C_DA^!}^<$As2tS(ERvd>3J|E{^;WUUtP`%|G3X zn~Fq3Z~d1teO{zKL9?MLH9@&FRouX6H^X@w7MC;Y8&>=jG)Ug3eAdH@Z<5RRi@cf3 a{`AgC2~ga5=8j$<$YM`dKbLh*2~7ay(NLNI literal 0 HcmV?d00001 diff --git a/textures/runes_rune_inventory.png b/textures/runes_rune_inventory.png new file mode 100755 index 0000000000000000000000000000000000000000..58a93df38c5b737647538de45c44fb766428d5c0 GIT binary patch literal 4639 zcmchacT`i^+QtKj1q2jC1Su*Y3StBtX=0FSK%^5$`81gTO3I*2e7=@Y5aYY-tI z1UQbMbP$HF5NePpL`Wc%B-YzkP0#XwK{PW^dqN8Vs$6z2><%Jg5mBJRM zqD>AGY(ia7tGms|O4wSYF?*=Zjv1VDq~V5Z7M;N7R0Voe{X4>CW%Vp=$^mg(mzcB(1ncEixfAcIK-~ps{_9f`r+E@j z0V99J0cODOm;`=pi|nAEpk5KB%3#^mG({LPOEp#s5rTukjQBWUM_@2*7%UXh8^^X- zA))Su!S=!a?|+!=R~#=mhcANbztUS=mb9%WgN4hCs!-7OlQy(5qr%9pB}dW7>%bu`^{TsU;S;m8rtLl#!vGrjlM)HD zTqINc93yFbbFceuUBlS)%W%B_IWuehd+F79xq!8Lc)h~VB)kzUn8ka@Sm8os`};o0 z4F|L3t}WIN1b_Irh%hS;&upjRpTs8@9=Wec(yc1IaNneq&>_#rr@O24uFqH>mKOo+ zuAKONPrds-WqwSzOI?O z_?(}*3-;=DltO4Qxvj08A%rx@43e#%yE8NeH5n5E=?Vs0SCCuP43+y1f}crQmtqHp zrj@k%)Lu}!P~{5*B9=j7aFPBv(bbN*rg>Os>x#e^78bK-9`lEH;5Q05QmB7m&lNzN z7_gXs1%7Htb4;eIZ7#WYF$T_$&^*_AH{(njoa?z>VMyqX4LJ9tq-HQcWxTL0)V3I+ z=!hXBZ+Dl<;u!>ApvlvO$n2q=p6~lvc#^Uyuo&|5AZQ{{2@vXP1oLpkBtSFj7HrlRW=A5c8Z z56K3&kM^!F&rl+WYXfgFCTEP85EU5AW%{D&Bhgh6#`-d~mV@K}ml2^5jpShl1+e70 zmi^EQ=*_?Z*!8yjPz6+vz8iUf%`pK$0U37NR#a40oh+ozBWz?Oh^9iAg#Jn#(Ww7% ztQ*0iN8}hzM?cES{6S9t6~g8c`UUbi3)?XoHU>3nkx?##*Id47n32yj*O#eh^PF6w zV4*9$H5?+DA4?wx_DLxYfIVYETzIHWV^Et`H2Wk^rc`L-%AynYf=JwX>%oC1@;nDJ zCH(1Dnp&YvTOv90JhWEnK+_D-BBl!1-$P8!({~HPtUd86mqXp~5mxAVfiS>v4h~xB zHVG~a_Wfc|k#Dm%6jZH}%i!bQkTVqE`v?ghIqxpBaKScaJgMPe?601)ZS6FjJU>or z>sk5uSObLmR%KsIu`t&Z*g8A>92E*$d3TP|cX>daO``hAx;%w}boVHV9A}y}QskFXerPv{iT3I4ZKy2qq_z6K458DO!#+Y~nPa4$H|^{o zcNEkF`2AjfTnU-7|7D~TLw{a-F~8d~;ukcgpIC8K=?H6ev(hiFPD2DUj4fjZQNxp3Ak9w8&ip6pT2P&S zylY9?*t(7)^8u0BBzfw6#h4g=r^Y9RvY2RH$CsAmr5B+ED#VYaQFbG z`{T3ko5rWyDVeIcr#I`Nv;topE3mkAYsv4tFj-*SBb&`mO)&q%Lpr}mxOtBA4{T{q zb-(szyJHNOGogaIf1AUA=<(MsW_PHJD3;TTBxtw|5YPg4_h>37&Q4tfUu?-16M})0 z;f``}uuqyTGMznPb>bv42yeMPS_ pTq~>9~_5XzC?a3Z5+6jsKZoAuKHd`SHI~- zw(aQnZaW?utW_}2Zv$dFH+++58+iMlmBJ_>L*&M!->wL^B`2FFOd;Bn3rn7fnd^tW zsgkB-x=LNnxJ6|0_IYt{&crts_Us*i;NUV(G3w7b*MtacsT)fCPwNrMwi&rMAUaHf z-CvMSx))jPeY#w=+eZx{VfIs8VJqZ5ybN{JJ!kC$j`nMYmB@Q0UoyFI`0TXph1RZ#)i(;?8&yN?%fKeP2$$obAr9mQV3QKQz7Ka z*?d!<(=)v?q8rx=FAQHJmJ;zXBCRh9aLciK>QgOWsd>7bjBCVY!<{KDB%#$zr_J2M$8 zL0TX^D|pt?UXh~F$~2UlIIBcO?+*>^qMdUBJ=`+(L?^8ho*G!>s9{a7MIL8v`C?vp z{$-50L;u_bo^L$-tMi}VVoVR_(Fx6fUT6Euw{&KrH&s-nw7lY;w-OB3NAaBU#edr~GfLA#sJS%L*#6Tmz#?Mg9D1*$^Vpq6mCfrvU|(>^lveN#9^nem{e55jO*`BL>u%floiPb52+P zRL&V>4o$1?>kNDVP6EDUh9bjO=F(Ewdl-Shi0#d8fpQ8Iu>Zcy@)tzmJc9g7e-bMr zN|=TW3j94B^7{XsVk&&eKg1ZOO~SdBH99Vd8vdlzEdH4Ffe^a|z3s3^8S#D25=uVD zE|NrRptw(pe7a$vplx_bDeh8CPg@wCy1+3BuLFcAitj7pnRgIQtof=V?QyxaXGKuQ z-jYj7_3l3okVYBAKR%liRYoIp>?+g%Ov+!QJuz})xthNS&myiv#)X}fUKGX1Iifuz zm+jal#VLgIhZy5ht$^pmEHEj(lJ{||R-xzsAKD=*F_}L!7ts^f_>>V7sC!7`2bRp_ zm2353LOhp7UJ9=pQxIBfS67~C3d*AZ!3F1PYNG9S2y!VTon3SDss*+22Lq1(Ieg5( zCi7v-;_m|8nVT)%ci1@DiC|T_kwh^KuDWy6sozNRa0883hV@sytXCeWZ8+Q|aQSY+ zDQSD5-p%>+X1s2ispOTQ8?_x`jP;6t0Vko0`ES@bvW68qn+4rJy%OiHA6EZV6WzXU z{iMQV+1W|{+%{0wmo@+CT}H(j8GUP35gQe>LJey8TD#@b=Cu7bnL+9$&YiNEqL5G4 z-$F6cosF`{cJH!~$}9LQ@l9KJh2?E&!jhsu?({GPa(1}{noSp^{uMo(&aH?409{w? A6951J literal 0 HcmV?d00001 diff --git a/textures/runes_scroll_deus_ex_machina.png b/textures/runes_scroll_deus_ex_machina.png new file mode 100644 index 0000000000000000000000000000000000000000..edd9c73c7b79435f70e72f46790978d284868895 GIT binary patch literal 410 zcmV;L0cHM)P)sfJ6>q#Ab%du4CfZ zaV%;Ho)qb`3WdsEF_5!q^jHNtHBe$ygmdWy1RMqjrVWw z2@sP9bVQv4>F&N~>*Faf3P{p*Vp6S=F;at(dNQ$9fDM9Nz*mH~0F``f&W2GJ1BYbv zb*}&;wJ{0LT{i%ZZWn?+w_l)HE7z49BG>C7@&;!O=d9t&a=}#_0H;~Y0mz4D?T>ZB zo+UutNQ_l--PYHR37FjpY1X3X@?I#Wz)8SZi4|RL{LUp0oRUx#AvP>G1hhJyy6AE& z%LP!mlLLXva9izUCFtT!W#}Y8pBp=!>0R&($&gomy%p{)@nE(I) literal 0 HcmV?d00001 diff --git a/textures/runes_scroll_manasucker.png b/textures/runes_scroll_manasucker.png new file mode 100644 index 0000000000000000000000000000000000000000..24463dcbc2909548b41786c2fe289736312b1562 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`^E_P~Lo9le6BY;8&!pZj~h zhVPw|1+_gqKv4GTR6#HM`A|WV1NT<+HUh!J3ukxti0p3QoX*0`%zSv3LggA0ql7~O zih>u;F(l3DzuqvRlwZ>6nr+MGiJ6Od6vP5@7`XK~XUuoLW}6ZrtkQq=Cl61C=gh{& z9Y

6%7r5U{9Twhkci-gkAy={P@41bAz_Xs|~MIB^em@tu$2Gv@Y2X=u!qxS3j3^ HP68&!pZj~h zhVPw|1+_gqKv4GTR6#HM`A|WV1NT<+HUh!J3ukxtu*3$u`z?0v-5s5thfHcYe%jw_ zyB7&Y8e1hC(&}O>$V^KB0>x0~i+T><*sOdnG!)(6F0t-_+OY!-)A%GL43e2)A*SE`Z>3^U?w VH%h0}9|gLa!PC{xWt~$(696!7RU!ZY literal 0 HcmV?d00001 diff --git a/textures/runes_scroll_spontafire.png b/textures/runes_scroll_spontafire.png new file mode 100644 index 0000000000000000000000000000000000000000..1cc92860dec4f56b2ec8f6f13e2f2845d174b89d GIT binary patch literal 218 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`3q4&NLo9le6BY;8&!pZj~h zhVPw|1+_gqKv4GTR6#HM`A|WV1NT<+HUh!J3ukxtTq$HUbKbXAJ^AXHP)qTn3}QK5 zK%Q|y=((c_$;>`GaumfTJYk)2@I>4JhX4D|{r$hS?cx9b>x=(CP71!t9l8&!pZj~h zhVPw|1+_gqKv4GTR6#HM`Ot+L)2>yYH~<76zD%--IdgACZzB*qyl{4RPem-lWgcb& z=LxX~T25!4Fgt9rNV+4D!LosMI?JZ{8(Wz#>K#}8&!pZj~h zhVPw|1+_jrKv4GT)c?0vrvASzy>+36PWFz*s|+)$csl>bKmYgtf9bn=SJ$Ke4azbz zU)Gltrr7%InB%6Ca7dl=Gn3wW10dLtAiSr1Y1_gz580fetP zPoF-0|Ni~||NllO!nXnC7)yfuf*Bm1-ADs+wtKobhEy=Vz2?ZpWGLVg=xG)EegDSJ zt$|Sn^@bd?qB;-POPJ5R9U3foW^<2#v3%;}8}E;w*z|Mmw%I!vA;9W30D3 lV9#94qQQM@I_vv~@0RW3pR9Pq!WrlV22WQ%mvv4FO#mq4dyW7A literal 0 HcmV?d00001 diff --git a/textures/runes_stylus.png b/textures/runes_stylus.png new file mode 100644 index 0000000000000000000000000000000000000000..e70b658f1d06b84ebe38e4311d731416cabd1a5e GIT binary patch literal 247 zcmVMbH2M002ovPDHLkV1mFcZ_@w( literal 0 HcmV?d00001