Initial Commit
|
@ -0,0 +1,55 @@
|
|||
# Titanite Upgrades Mod
|
||||
by Kevin "mrunderhill89" Cameron
|
||||
|
||||
SUMMARY:
|
||||
This mod adds the Titanite material from the Dark Souls series to Minetest.
|
||||
Unlike most materials, titanite isn't used to forge weapons directly, but to
|
||||
upgrade existing weapons. Also included in the mod is a procedural upgrade system
|
||||
similar to one in Dark Souls, where tools can be gradually improved from +1 to +10.
|
||||
|
||||
TITANITE:
|
||||
Titanite comes in four interchangeable quantities, just like in Dark Souls:
|
||||
small shards, large shards, chunks, and blocks (based on slabs).
|
||||
Each quantity is worth four times the one below it, and you can freely craft between them.
|
||||
|
||||
Titanite has the same spawn pattern as Mese crystals, with shard appearing at medium depth,
|
||||
and whole blocks at very far depths.
|
||||
|
||||
UPGRADES:
|
||||
Upgrading a weapon is as simple as crafting the desired tool with the required quantity of titanite.
|
||||
Each level requires an increasing amount of titanite, starting with just 1 shard and progressing to
|
||||
chunks and finally blocks by the time you get to +10. Any tool that uses minetest's default
|
||||
tool capabilities can be upgraded, including those added by other mods. Armor from the 3D Armor mod
|
||||
can also be upgraded, but any special-purpose tools like the screwdriver are left alone. As a happy
|
||||
side-effect, upgrading a tool restores its wear value.
|
||||
|
||||
TECHNIC IMPROVEMENTS:
|
||||
If you have the Technic mod and don't want to bother with manual crafting, you can throw your weapons
|
||||
along with some titanite shards into any alloy furnace. The furnace will automatically take the required
|
||||
number of shards to upgrade your weapon. Note that this is only a convenience feature, and you aren't
|
||||
getting or losing anything by using it.
|
||||
|
||||
You can also downgrade your weapons with an Extractor. You'll get back half of the material used to
|
||||
make the upgrade so you can use them on other tools.
|
||||
|
||||
WHAT WORKS:
|
||||
Titanite craftitems and blocks
|
||||
Weapon upgrades
|
||||
Armor upgrades
|
||||
Manual upgrading
|
||||
Alloy-furnace upgrading
|
||||
Graphical overlays on upgraded weapons
|
||||
|
||||
WHAT STILL NEEDS WORK:
|
||||
Graphical overlays show up on the wielded weapon (should just be in inventory)
|
||||
Upgrades for special tools like the screwdriver
|
||||
Weapon Ascension (Dark Souls' version of enchanting)
|
||||
|
||||
LICENSE:
|
||||
Code: WTFPL
|
||||
Textures: Creative Commons Non-Commercial (CC BY-NC 4.0)
|
||||
https://creativecommons.org/licenses/by-nc/4.0/
|
||||
|
||||
I do not claim to own anything regarding the idea for titanite, or anything else
|
||||
related to Dark Souls, which is the property of FROM Software. The textures in this
|
||||
mod were drawn by me but based on the icons from Dark Souls 3.
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
default
|
||||
3d_armor?
|
||||
technic?
|
|
@ -0,0 +1,6 @@
|
|||
titanite = {}
|
||||
local modpath = minetest and minetest.get_modpath("titanite") or "."
|
||||
dofile(modpath.."/test.lua")
|
||||
dofile(modpath.."/ores.lua")
|
||||
dofile(modpath.."/upgrades.lua")
|
||||
dofile(modpath.."/ascension.lua")
|
|
@ -0,0 +1,110 @@
|
|||
titanite.small_shard = "titanite:small_shard"
|
||||
titanite.large_shard = "titanite:large_shard"
|
||||
titanite.chunk = "titanite:chunk"
|
||||
titanite.block = "titanite:block"
|
||||
titanite.ore = "titanite:stone_with_titanite"
|
||||
|
||||
local function four_to_one(input, output)
|
||||
return {
|
||||
output = output,
|
||||
recipe = {
|
||||
{input,input},
|
||||
{input,input}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
local function nine_to_one(input, output)
|
||||
return {
|
||||
output = output,
|
||||
recipe = {
|
||||
{input,input,input},
|
||||
{input,input,input},
|
||||
{input,input,input}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
local function one_to_quantity(input, output, quantity)
|
||||
return {
|
||||
output = output.." "..quantity,
|
||||
recipe = {
|
||||
{input}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
if minetest then
|
||||
minetest.register_craftitem(titanite.small_shard, {
|
||||
description = "Titanite Shard",
|
||||
inventory_image = "titanite_shard.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem(titanite.large_shard, {
|
||||
description = "Large Titanite Shard",
|
||||
inventory_image = "titanite_large_shard.png",
|
||||
})
|
||||
|
||||
minetest.register_craft(four_to_one(titanite.small_shard,titanite.large_shard))
|
||||
minetest.register_craft(one_to_quantity(titanite.large_shard,titanite.small_shard,4))
|
||||
|
||||
minetest.register_craftitem(titanite.chunk, {
|
||||
description = "Titanite Chunk",
|
||||
inventory_image = "titanite_chunk.png",
|
||||
})
|
||||
|
||||
minetest.register_craft(four_to_one(titanite.large_shard,titanite.chunk))
|
||||
minetest.register_craft(one_to_quantity(titanite.chunk,titanite.large_shard,4))
|
||||
|
||||
minetest.register_node(titanite.block, {
|
||||
description = "Titanite Block",
|
||||
tiles = {"titanite_block_top.png","titanite_block_top.png","titanite_block.png"},
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 1, level = 3},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft(four_to_one(titanite.chunk,titanite.block))
|
||||
minetest.register_craft(one_to_quantity(titanite.block,titanite.chunk,4))
|
||||
|
||||
minetest.register_node(titanite.ore, {
|
||||
description = "Titanite Ore",
|
||||
tiles = {"default_stone.png^mineral_titanite.png"},
|
||||
groups = {cracky = 1},
|
||||
drop = "titanite:small_shard",
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = titanite.ore,
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 18 * 18 * 18,
|
||||
clust_num_ores = 3,
|
||||
clust_size = 2,
|
||||
y_min = -255,
|
||||
y_max = -64,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = titanite.ore,
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 14 * 14 * 14,
|
||||
clust_num_ores = 5,
|
||||
clust_size = 3,
|
||||
y_min = -31000,
|
||||
y_max = -256,
|
||||
})
|
||||
|
||||
minetest.register_ore({
|
||||
ore_type = "scatter",
|
||||
ore = titanite.block,
|
||||
wherein = "default:stone",
|
||||
clust_scarcity = 36 * 36 * 36,
|
||||
clust_num_ores = 3,
|
||||
clust_size = 2,
|
||||
y_min = -31000,
|
||||
y_max = -1024,
|
||||
})
|
||||
end
|
|
@ -0,0 +1,55 @@
|
|||
minetest = minetest or {
|
||||
get_modpath = function(modname)
|
||||
assert(type(modname) == "string")
|
||||
print("minetest.get_modpath called:("..modname..")")
|
||||
if (fail_test[modname]) then
|
||||
print("assuming "..modname.." isn't loaded due to test parameters.")
|
||||
return false
|
||||
end
|
||||
return modname end,
|
||||
register_tool = function(name, stats)
|
||||
print("Tool Register:"..name)
|
||||
if stats then
|
||||
local tool_stats = stats.tool_capabilities
|
||||
if tool_stats then
|
||||
print ("Punch Interval:"..tool_stats.full_punch_interval)
|
||||
local groupcaps = tool_stats.groupcaps
|
||||
if groupcaps then
|
||||
for group_name, group in pairs(groupcaps) do
|
||||
print("Group Cap:"..group_name)
|
||||
end
|
||||
else
|
||||
print("WARNING: No groupcaps received.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
register_craftitem = function(name, stats)
|
||||
print("Craft Item Register:"..name)
|
||||
end,
|
||||
register_craft = function()
|
||||
print("Craft Register")
|
||||
end,
|
||||
register_ore = function()
|
||||
print("Ore Register")
|
||||
end,
|
||||
register_node = function()
|
||||
print("Node Register")
|
||||
end,
|
||||
registered_tools = {["default:pick_steel"] = {
|
||||
description = "Steel Pickaxe",
|
||||
inventory_image = "default_tool_steelpick.png",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 1.0,
|
||||
max_drop_level=1,
|
||||
groupcaps={
|
||||
cracky = {times={[1]=4.00, [2]=1.60, [3]=0.80}, uses=20, maxlevel=2},
|
||||
},
|
||||
damage_groups = {fleshy=4},
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
default = default or {
|
||||
node_sound_stone_defaults = function()end
|
||||
}
|
After Width: | Height: | Size: 493 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 946 B |
After Width: | Height: | Size: 672 B |
After Width: | Height: | Size: 408 B |
After Width: | Height: | Size: 362 B |
After Width: | Height: | Size: 207 B |
After Width: | Height: | Size: 220 B |
After Width: | Height: | Size: 207 B |
After Width: | Height: | Size: 208 B |
After Width: | Height: | Size: 210 B |
After Width: | Height: | Size: 207 B |
After Width: | Height: | Size: 213 B |
After Width: | Height: | Size: 211 B |
After Width: | Height: | Size: 215 B |
After Width: | Height: | Size: 212 B |
|
@ -0,0 +1,202 @@
|
|||
local recipes = {
|
||||
[1] = function(item, material)
|
||||
return {
|
||||
{material},
|
||||
{item}
|
||||
}
|
||||
end,
|
||||
[2] = function(item, material)
|
||||
return {
|
||||
{material, material},
|
||||
{item, ""}
|
||||
}
|
||||
end,
|
||||
[0] = function(item, material)
|
||||
return {
|
||||
{material, material, material},
|
||||
{"",item,""}
|
||||
}
|
||||
end
|
||||
}
|
||||
|
||||
titanite.max_levels = 10
|
||||
titanite.shard_count = {}
|
||||
titanite.shard_total = {}
|
||||
for level=1,titanite.max_levels do
|
||||
local material = math.floor((level-1)/3)
|
||||
local quantity = 1+((level-1)%3)
|
||||
titanite.shard_count[level] = math.pow(4, material)*quantity
|
||||
titanite.shard_total[level] = titanite.shard_count[level] + (titanite.shard_total[level-1] or 0)
|
||||
end
|
||||
|
||||
local armor_multipliers = {
|
||||
armor_head = 1,
|
||||
armor_torso = 1,
|
||||
armor_legs = 1,
|
||||
armor_feet = 1,
|
||||
armor_shield = 1,
|
||||
armor_uses = 0.1,
|
||||
}
|
||||
|
||||
titanite.get_upgrade_name = function(item, level)
|
||||
return item.."_"..level
|
||||
end
|
||||
|
||||
titanite.get_upgrade_description = function(desc, level)
|
||||
return desc.." +"..level
|
||||
end
|
||||
|
||||
titanite.get_upgrade_overlay = function(level)
|
||||
return "upgrade_"..level..".png"
|
||||
end
|
||||
|
||||
local function upgrade_recipe(item, level)
|
||||
local upgrade_name = titanite.get_upgrade_name(item, level)
|
||||
local prev = level <= 1 and item or titanite.get_upgrade_name(item, level-1)
|
||||
local quantity = (level % 3)
|
||||
local material =
|
||||
level > 9 and titanite.block
|
||||
or level > 6 and titanite.chunk
|
||||
or level > 3 and titanite.large_shard
|
||||
or titanite.small_shard
|
||||
-- Direct crafting recipe
|
||||
minetest.register_craft({
|
||||
output = upgrade_name,
|
||||
recipe = recipes[quantity](prev,material)
|
||||
})
|
||||
-- Technic Alloying Recipes
|
||||
if technic then
|
||||
local shards = titanite.shard_count[level]
|
||||
technic.register_alloy_recipe({input = {prev, titanite.small_shard.." "..shards}, output = upgrade_name})
|
||||
technic.register_extractor_recipe({
|
||||
input = {upgrade_name},
|
||||
output = {prev,titanite.small_shard.." "..math.floor(shards/2)}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
titanite.power = function(level)
|
||||
return math.sqrt(titanite.shard_total[level] / titanite.shard_total[titanite.max_levels])
|
||||
end
|
||||
|
||||
local function ratio(value, mul)
|
||||
mul = mul or 1.0
|
||||
return 1.0 + (value*mul)
|
||||
end
|
||||
|
||||
local function copy_table (this, that)
|
||||
that = that or {}
|
||||
for key,value in pairs(this) do
|
||||
that[key] = type(value) == "table" and copy_table(value)
|
||||
or value
|
||||
end
|
||||
return that
|
||||
end
|
||||
|
||||
local function floor(value, pow_ten)
|
||||
local mult = math.pow(10, pow_ten or 0)
|
||||
return math.floor(value*mult)/mult
|
||||
end
|
||||
|
||||
local function ceil(value, pow_ten)
|
||||
local mult = math.pow(10, pow_ten or 0)
|
||||
return math.ceil(value*mult)/mult
|
||||
end
|
||||
|
||||
local native_register_tool = minetest.register_tool
|
||||
function titanite.register_upgrade(item, level)
|
||||
if type(item) == "string" and item ~= ":" and item ~= "" then
|
||||
local tool = minetest.registered_tools[item]
|
||||
if tool then
|
||||
local upgrade_name = titanite.get_upgrade_name(item, level)
|
||||
local upgrade = copy_table(tool)
|
||||
local power = titanite.power(level)
|
||||
local diff = false
|
||||
upgrade.description = titanite.get_upgrade_description(tool.description, level)
|
||||
upgrade.inventory_image = tool.inventory_image.."^"..titanite.get_upgrade_overlay(level)
|
||||
upgrade.wield_image = tool.wield_image or tool.inventory_image
|
||||
local caps = tool.tool_capabilities
|
||||
if caps then
|
||||
local upgrade_caps = upgrade.tool_capabilities
|
||||
if caps.full_punch_interval and caps.full_punch_interval > 0 then
|
||||
diff = true
|
||||
upgrade_caps.full_punch_interval = caps.full_punch_interval / ratio(power, 2)
|
||||
end
|
||||
if caps.groupcaps then
|
||||
for groupname, group in pairs(caps.groupcaps) do
|
||||
local upgrade_group = upgrade_caps.groupcaps[groupname]
|
||||
if group.uses and group.uses > 0 then
|
||||
upgrade_group.uses = math.floor(group.uses * ratio(power, 0.1))
|
||||
end
|
||||
if group.maxlevel and group.maxlevel > 0 then
|
||||
diff = true
|
||||
upgrade_group.maxlevel = math.floor(group.maxlevel + level/5)
|
||||
if group.times and #group.times > 0 then
|
||||
local old_level = 1
|
||||
for new_level = 1, upgrade_group.maxlevel do
|
||||
if new_level <= #group.times then
|
||||
old_level = new_level
|
||||
end
|
||||
upgrade_group.times[new_level] =
|
||||
group.times[old_level] / ratio(power, 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if caps.damage_groups then
|
||||
local upgrade_damage = upgrade_caps.damage_groups
|
||||
for group, damage in pairs(caps.damage_groups) do
|
||||
diff = diff or damage > 0
|
||||
upgrade_damage[group] = damage * ratio(power)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
upgrade.groups = upgrade.groups or {}
|
||||
upgrade.groups.not_in_creative_inventory = 1
|
||||
local is_armor = false
|
||||
for group, div in pairs(armor_multipliers) do
|
||||
if upgrade.groups[group] and upgrade.groups[group] > 0 then
|
||||
local value = upgrade.groups[group]
|
||||
diff = true
|
||||
is_armor = true
|
||||
upgrade.groups[group] = floor(value * ratio(power,div),2)
|
||||
end
|
||||
end
|
||||
--Fix armor textures
|
||||
if is_armor and not upgrade.texture then
|
||||
upgrade.texture = item:gsub("%:", "_")
|
||||
end
|
||||
-- Only register if we actually changed something.
|
||||
if diff then
|
||||
native_register_tool(":"..upgrade_name, upgrade)
|
||||
upgrade_recipe(item, level)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function titanite.split_item_name(item)
|
||||
local level = tonumber(string.match(item, "%d+$")) or 0
|
||||
local base = string.gsub(item, "_%d*$", "")
|
||||
return base, level
|
||||
end
|
||||
|
||||
minetest.register_tool = function(item, ...)
|
||||
local item = string.gsub(item, "^:+", "")
|
||||
local result = {native_register_tool(":"..item, ...)}
|
||||
for level = 1,10 do
|
||||
titanite.register_upgrade(item, level)
|
||||
end
|
||||
return unpack(result)
|
||||
end
|
||||
|
||||
local upgradeable_tools = {}
|
||||
for item, _ in pairs(minetest.registered_tools) do
|
||||
table.insert(upgradeable_tools, item)
|
||||
end
|
||||
for _, item in ipairs(upgradeable_tools) do
|
||||
for level = 1,10 do
|
||||
titanite.register_upgrade(item, level)
|
||||
end
|
||||
end
|