VoxelDungeon/mods/voxeldungeon/tools.lua

404 lines
15 KiB
Lua

--[[
Voxel Dungeon
Copyright (C) 2019 Noodlemire
Pixel Dungeon
Copyright (C) 2012-2015 Oleg Dolya
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
--]]
voxeldungeon.tools = {}
if not minetest.settings:get_bool("creative_mode") then
minetest.override_item("", {
tool_capabilities = {
full_punch_interval = 0.667,
max_drop_level = 0,
groupcaps = {
crumbly = {times={[2]=3.00, [3]=0.70}, uses=0, maxlevel=1},
snappy = {times={[3]=0.40}, uses=0, maxlevel=1},
oddly_breakable_by_hand = {times={[1]=3.50,[2]=2.00,[3]=0.70}, uses=0}
},
damage_groups = {fleshy = 1},
}
})
end
minetest.override_item("default:pick_wood", {
max_drop_level=1
})
minetest.override_item("default:pick_stone", {
max_drop_level=1
})
minetest.override_item("default:pick_steel", {
max_drop_level=2
})
minetest.override_item("default:pick_diamond", {
tool_capabilities = {
max_drop_level=4,
groupcaps={
cracky = {times={[1]=2.0, [2]=1.0, [3]=0.50}, uses=30, maxlevel=4},
},
}
})
minetest.register_tool("voxeldungeon:pick_demonite", {
description = "Demonite Pickaxe",
inventory_image = "voxeldungeon_tool_pickaxe_demonite.png",
tool_capabilities = {
full_punch_interval = 0.8,
max_drop_level=5,
groupcaps={
cracky = {times={[1]=1.6, [2]=0.8, [3]=0.4}, uses=40, maxlevel=5},
},
damage_groups = {fleshy=6},
},
sound = {breaks = "default_tool_breaks"},
groups = {pickaxe = 1}
})
--any tiered items
local function getStrengthRequirementOf(tierItem)
local level = tierItem:get_meta():get_int("voxeldungeon:level")
local tier = tierItem:get_definition()._tier
--strength requirement decreases at +1, +3, +6, +10, etc.
return 8 + 2 * tier - math.floor(math.floor(math.sqrt(8 * level + 1) - 1) / 2)
end
function voxeldungeon.tools.setLevelOf(tierItem, level)
tierItem:get_meta():set_int("voxeldungeon:level", level)
if minetest.get_item_group(tierItem:get_name(), "weapon") > 0 then
voxeldungeon.tools.updateDescriptionWeapon(tierItem)
else
voxeldungeon.tools.updateDescriptionArmor(tierItem)
end
end
function voxeldungeon.tools.getShortDescriptionOf(tierItem)
local desc = tierItem:get_definition().description
local level = tierItem:get_meta():get_int("voxeldungeon:level")
local levelString = ""
if level > 0 then levelString = " +"..level end
return desc..levelString
end
function voxeldungeon.tools.upgrade(tierItem)
local level = tierItem:get_meta():get_int("voxeldungeon:level")
voxeldungeon.tools.setLevelOf(tierItem, level + 1)
tierItem:set_wear(0)
end
--armor
local function getDefenseOf(armor)
local level = armor:get_meta():get_int("voxeldungeon:level")
local def = armor:get_definition()
local tier = def._tier
return tier + tier * level
end
function voxeldungeon.tools.updateDescriptionArmor(armor)
local meta = armor:get_meta()
local level = meta:get_int("voxeldungeon:level")
local def = armor:get_definition()
local tier = def._tier
local desc = def.description
local info = def._info
local defense = getDefenseOf(armor)
local strreq = getStrengthRequirementOf(armor)
local strTip = "\n \nBe careful about equipping armor without enough strength, your movement speed will decrease."
meta:set_string("description", voxeldungeon.utils.itemDescription(voxeldungeon.tools.getShortDescriptionOf(armor).."\n \n"..info..
"\n \nThis tier-"..tier.." armor blocks "..defense.." damage and requires "..strreq..
" points of strength to wear properly."..strTip))
end
function voxeldungeon.tools.updateStrdiffArmor(player)
local playername = player:get_player_name()
local armor_inv = minetest.get_inventory({type="detached", name=playername.."_armor"})
local armor = armor_inv:get_stack("armor", 1)
player_monoids.speed:del_change(player, "voxeldungeon:armor_strreq_penalty")
if not armor:is_empty() then
local strdiff = voxeldungeon.playerhandler.playerdata[playername].STR - getStrengthRequirementOf(armor)
if strdiff < 0 then
player_monoids.speed:add_change(player, 1 / (-strdiff + 1), "voxeldungeon:armor_strreq_penalty")
end
end
end
function voxeldungeon.tools.register_armor(name, desc, tier, info)
info = info or "!!!NO TEXT FOUND!!!"
armor:register_armor("voxeldungeon:armor_"..name, {
description = desc,
inventory_image = "voxeldungeon_tool_armor_"..name..".png",
armor_groups = {fleshy = 0},
groups = {armor_torso=1, upgradable = 1},
_info = info,
_tier = tier,
_durabilityPerUse = (6 - tier),
on_equip = function(player, index, itemstack)
local strdiff = voxeldungeon.playerhandler.playerdata[player:get_player_name()].STR - getStrengthRequirementOf(itemstack)
if strdiff < 0 then
player_monoids.speed:add_change(player, 1 / (-strdiff + 1), "voxeldungeon:armor_strreq_penalty")
end
end,
on_unequip = function(player, index, itemstack)
player_monoids.speed:del_change(player, "voxeldungeon:armor_strreq_penalty")
end,
})
end
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
local playername = player:get_player_name()
if playername then
local armor_inv = minetest.get_inventory({type="detached", name=playername.."_armor"})
local armor = armor_inv:get_stack("armor", 1)
if not armor:is_empty() then
local defense = getDefenseOf(armor)
damage = math.max(0, damage - defense)
player:set_hp(player:get_hp() - damage)
local wear = math.floor(65535 / (1000 / armor:get_definition()._durabilityPerUse))
armor:add_wear(wear)
armor_inv:set_stack("armor", 1, armor)
return true
end
end
end)
voxeldungeon.tools.register_armor("cloth", "Cloth Armor", 1, "This lightweight armor offers basic protection.")
voxeldungeon.tools.register_armor("cactus", "Cactus Armor", 1, "A rather unconventional type of armor, which offers more discomfort than it does defense.")
voxeldungeon.tools.register_armor("wood", "Wood Armor", 1, "Constructed from wooden planks, this boxy clothing will offer a small level of protection against monster attacks.")
voxeldungeon.tools.register_armor("leather", "Leather Armor", 2, "Armor made from tanned monster hide. Not as light as cloth armor but provides better protection.")
voxeldungeon.tools.register_armor("steel", "Steel Armor", 2, "A set of solid steel armor, albiet a thin one with no padding. While it won't compare to professionally made plate armor, it does offer decent protection.")
voxeldungeon.tools.register_armor("mail", "Mail Armor", 3, "Interlocking metal links make for a tough but flexible suit of armor.")
voxeldungeon.tools.register_armor("mese", "Mese Armor", 3, "A bright golden suit of sturdy armor, the material strong enough to take a beating so that you won't have to.")
voxeldungeon.tools.register_armor("scale", "Scale Armor", 4, "Metal scales are sewn onto a leather vest create a flexible, yet protective armor.")
voxeldungeon.tools.register_armor("diamond", "Diamond Armor", 4, "Finely cut diamond armor ready to take on even the toughest of foes, as long as they're the kind that won't think to strike at just the right angle to cut the suit in half.")
voxeldungeon.tools.register_armor("plate", "Plate Armor", 5, "Enormous plates of metal are joined together into a suit that provides unmatched "..
"protection to any adventurer strong enough to bear its staggering weight.")
voxeldungeon.tools.register_armor("demonite", "Demonite Armor", 5, "A set of armor created out of pure demonite, one of the world's strongest and heaviest materials.")
--weapons
local function getDamageOf(weapon)
local level = weapon:get_meta():get_int("voxeldungeon:level")
local def = weapon:get_definition()
local tier = def._tier
local mult = def._damageMultiplier
return voxeldungeon.utils.round(mult * (3 + 2 * tier + tier * level))
end
local function durabilityPerHitWith(weapon)
local level = weapon:get_meta():get_int("voxeldungeon:level")
return 1 - level / (level + 2)
end
function voxeldungeon.tools.updateDescriptionWeapon(weapon)
local meta = weapon:get_meta()
local level = meta:get_int("voxeldungeon:level")
local def = weapon:get_definition()
local tier = def._tier
local desc = def.description
local info = def._info
local dly = def.tool_capabilities.full_punch_interval
local dur = def._durabilityMultiplier or 1
local damage = getDamageOf(weapon)
local strreq = getStrengthRequirementOf(weapon)
local dlyString = ""
if dly > 1 then dlyString = "\n \nThis is a rather slow weapon."
elseif dly < 1 then dlyString = "\n \nThis is a rather fast weapon."
end
local durString = ""
if dur > 1 then durString = "\n \nThis is a rather durable weapon."
elseif dur < 1 then durString = "\n \nThis is a rather fragile weapon."
end
local strTip = "\n \nHaving excess strength with this weapon will let you deal bonus damage with it, "..
"while lacking strength will greatly reduce your attack speed."
meta:set_string("description", voxeldungeon.utils.itemDescription(voxeldungeon.tools.getShortDescriptionOf(weapon).."\n \n"..info..
"\n \nThis tier-"..tier.." weapon deals "..damage.." damage and requires "..strreq..
" points of strength to wield properly."..dlyString..durString..strTip))
end
local function weapon_on_use(itemstack, user, pointed_thing)
if pointed_thing.type == "object" then
local target = pointed_thing.ref
local toolcap = itemstack:get_tool_capabilities()
local strdiff = voxeldungeon.playerhandler.playerdata[user:get_player_name()].STR - getStrengthRequirementOf(itemstack)
toolcap.damage_groups = {fleshy = getDamageOf(itemstack) + math.max(0, strdiff)}
toolcap.full_punch_interval = toolcap.full_punch_interval * math.max(1, -strdiff + 1)
target:punch(user, voxeldungeon.playerhandler.getTimeFromLastPunch(user), toolcap)
local def = itemstack:get_definition()
local wear = math.floor(65535 / (1000 / def._durabilityPerUse * def._durabilityMultiplier))
itemstack:add_wear(wear)
return itemstack
end
end
function voxeldungeon.tools.register_weapon(name, desc, tier, info, damage, delay, durability)
damage = damage or 1
delay = delay or 1
durability = durability or 1
info = info or "!!!NO TEXT FOUND!!!"
minetest.register_tool("voxeldungeon:weapon_"..name, {
description = desc,
inventory_image = "voxeldungeon_tool_weapon_"..name..".png",
tool_capabilities =
{
full_punch_interval = delay
},
sound = {breaks = "default_tool_breaks"},
groups = {weapon = 1, upgradable = 1},
_info = info,
_tier = tier,
_damageMultiplier = damage,
_durabilityPerUse = (6 - tier),
_durabilityMultiplier = durability,
on_use = weapon_on_use,
})
end
function voxeldungeon.tools.weaponify(name, tier, info, groups)
groups.upgradable = groups.upgradable or 1
groups.weapon = 1
minetest.override_item(name, {
groups = groups,
tool_capabilities =
{
full_punch_interval = 1
},
_info = info,
_tier = tier,
_damageMultiplier = 1,
_durabilityPerUse = (6 - tier),
_durabilityMultiplier = 1,
on_use = weapon_on_use,
})
end
voxeldungeon.tools.weaponify("default:sword_wood", 0, "Little more than a stick carved into the shape of a sword, it's more often used for training "..
"rather than combat.\n \nUnlike most other weapons, it is too weak to hold upgrades or magic.",
{sword = 1, upgradable = 0})
voxeldungeon.tools.register_weapon("shortsword", "Short Sword", 1, "It is indeed quite short, being just a few inches longer than a dagger.")
voxeldungeon.tools.register_weapon("knuckleduster", "Knuckleduster", 1, "A piece of iron shaped to fit around the knuckles.", 0.667, 0.5)
voxeldungeon.tools.register_weapon("dagger", "Dagger", 1, "A simple iron dagger with a well worn wooden handle.", 0.8, 1, 1.5)
voxeldungeon.tools.weaponify("default:sword_stone", 1, "A sturdy but somewhat dull blade of stone.", {sword = 1})
voxeldungeon.tools.register_weapon("quarterstaff", "Quarterstaff", 2, "A staff of hardwood, its ends are shod with iron.")
voxeldungeon.tools.register_weapon("spear", "Spear", 2, "A slender wooden rod tipped with sharpened iron.", 1.333, 1.5)
voxeldungeon.tools.register_weapon("handaxe", "Hand Axe", 2, "A light axe, most commonly used for felling trees. The wide blade works well against "..
"foes as well.", 0.8, 1, 1.5)
voxeldungeon.tools.weaponify("default:sword_steel", 2, "A hand-crafted blade of solid steel. It isn't the best sword ever made, but it's yours.",
{sword = 1})
voxeldungeon.tools.register_weapon("sword", "Sword", 3, "A nicely balanced sword. Not too large, but still notably longer than a shortsword.")
voxeldungeon.tools.register_weapon("scimitar", "Scimitar", 3, " A thick curved blade. Its shape allows for faster, yet less powerful attacks.", 0.8, 0.75)
voxeldungeon.tools.register_weapon("mace", "Mace", 3, "The iron head of this weapon inflicts substantial damage.", 0.8, 1, 1.5)
voxeldungeon.tools.weaponify("default:sword_mese", 3, "A crystalline sword forged from mese, complete with a fine (if uneven) cutting edge.", {sword = 1})
voxeldungeon.tools.register_weapon("longsword", "Long Sword", 4, "This sword's long razor-sharp steel blade shines reassuringly, though its size does make it quite heavy.")
voxeldungeon.tools.register_weapon("stonegauntlet", "Stone Gauntlet", 4, "This massive gauntlet is made of golden fabric with heavy magical stone "..
"layered on top. The fabric tightens around you, making the thick stone plates "..
"almost like a second skin. Swinging such a heavy weapon requires strength, "..
"but adds tremendous force to your blows.", 0.667, 0.5)
voxeldungeon.tools.register_weapon("battleaxe", "Battle Axe", 4, "The enormous steel head of this battle axe puts considerable heft behind each stroke.", 0.8, 1, 1.5)
voxeldungeon.tools.weaponify("default:sword_diamond", 4, "A medium-sized weapon made from pure diamond, ready-made to deal heavy damage to your foes.",
{sword = 1})
voxeldungeon.tools.register_weapon("greatsword", "Great Sword", 5, "This towering blade inflicts heavy damage by investing its heft into every swing.")
voxeldungeon.tools.register_weapon("glaive", "Glaive", 5, "A polearm consisting of a sword blade on the end of a pole.", 1.333, 1.5)
voxeldungeon.tools.register_weapon("warhammer", "Warhammer", 5, "Few creatures can withstand the crushing blow of this towering mass of lead and steel, "..
"but it takes great strength to use effectively.", 0.8, 1, 1.5)
voxeldungeon.tools.register_weapon("sword_demonite", "Demonite Sword", 5, "A deceptively heavy blade carved from shadowy demonite. Despite its size, "..
"it has the potential to become one of the finest blades ever crafted.")
minetest.register_on_craft(function(itemstack)
if minetest.get_item_group(itemstack:get_name(), "weapon") > 0 then
voxeldungeon.tools.updateDescriptionWeapon(itemstack)
return itemstack
elseif minetest.get_item_group(itemstack:get_name(), "armor_torso") > 0 then
voxeldungeon.tools.updateDescriptionArmor(itemstack)
return itemstack
end
end)