From ff57174b313940728b70dbc6dd76e50b5d9f78e8 Mon Sep 17 00:00:00 2001 From: Pedro Cruz Date: Wed, 30 Oct 2024 23:19:58 -0300 Subject: [PATCH] feat: new augments and update item description (amber items) (#2900) This updates the augments to be able to handle the substitution of the Increase Damage, Strong Impact and Powerful Impact into Base Damage and Base Healing. It also adds the new item description to handle the new Amber Items with elemental attack greater than 0 and physical attack value equal 0. --- data/items/items.xml | 118 ++++++++++++++----- src/creatures/combat/spells.cpp | 4 +- src/items/item.cpp | 63 +++++++--- src/items/items.cpp | 7 +- src/items/items_definitions.hpp | 1 + src/server/network/protocol/protocolgame.cpp | 21 ++-- 6 files changed, 158 insertions(+), 56 deletions(-) diff --git a/data/items/items.xml b/data/items/items.xml index d4e2e6bf5cf..eb00ac6bdf3 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -75139,7 +75139,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75165,9 +75167,11 @@ Granted by TibiaGoals.com"/> - + + + - + @@ -75194,7 +75198,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75220,7 +75226,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75246,7 +75254,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75272,7 +75282,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75300,7 +75312,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75327,7 +75341,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75354,7 +75370,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75381,7 +75399,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75408,7 +75428,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75435,7 +75457,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75488,7 +75512,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75518,7 +75544,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75548,7 +75576,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75578,7 +75608,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -75627,8 +75659,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -75660,8 +75696,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -75722,8 +75762,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -75755,8 +75799,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + @@ -75953,7 +76001,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -76116,7 +76166,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -76160,7 +76212,9 @@ Granted by TibiaGoals.com"/> - + + + @@ -76175,8 +76229,12 @@ Granted by TibiaGoals.com"/> - - + + + + + + diff --git a/src/creatures/combat/spells.cpp b/src/creatures/combat/spells.cpp index b6ae30bee87..0d66602ddca 100644 --- a/src/creatures/combat/spells.cpp +++ b/src/creatures/combat/spells.cpp @@ -682,7 +682,9 @@ void Spell::getCombatDataAugment(const std::shared_ptr &player, CombatDa if (augment->value == 0) { continue; } - if (augment->type == Augment_t::IncreasedDamage || augment->type == Augment_t::PowerfulImpact || augment->type == Augment_t::StrongImpact) { + if ( + augment->type == Augment_t::IncreasedDamage || augment->type == Augment_t::PowerfulImpact || augment->type == Augment_t::StrongImpact || augment->type == Augment_t::Base + ) { const float augmentPercent = augment->value / 100.0; damage.primary.value += static_cast(damage.primary.value * augmentPercent); damage.secondary.value += static_cast(damage.secondary.value * augmentPercent); diff --git a/src/items/item.cpp b/src/items/item.cpp index 2fbec7c84f1..14af2cfb47f 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -1280,13 +1280,20 @@ Item::getDescriptions(const ItemType &it, const std::shared_ptr &item /*= ss << static_cast(shootRange) << " fields"; } descriptions.emplace_back("Attack", ss.str()); - } else if (!it.isRanged() && attack != 0) { + } else { + std::string attackDescription; if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - ss.str(""); - ss << attack << " physical +" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - descriptions.emplace_back("Attack", ss.str()); - } else { - descriptions.emplace_back("Attack", std::to_string(attack)); + attackDescription = fmt::format("{} {}", it.abilities->elementDamage, getCombatName(it.abilities->elementType)); + } + + if (attack != 0 && !attackDescription.empty()) { + attackDescription = fmt::format("{} physical + {}", attack, attackDescription); + } else if (attack != 0 && attackDescription.empty()) { + attackDescription = std::to_string(attack); + } + + if (!attackDescription.empty()) { + descriptions.emplace_back("Attack", attackDescription); } } @@ -1352,6 +1359,10 @@ Item::getDescriptions(const ItemType &it, const std::shared_ptr &item /*= skillBoost = true; } + if (it.abilities->regeneration) { + ss << ", faster regeneration"; + } + if (it.abilities->stats[STAT_MAGICPOINTS]) { if (skillBoost) { ss << ", "; @@ -1693,13 +1704,20 @@ Item::getDescriptions(const ItemType &it, const std::shared_ptr &item /*= ss << static_cast(shootRange) << " fields"; } descriptions.emplace_back("Attack", ss.str()); - } else if (!it.isRanged() && attack != 0) { + } else { + std::string attackDescription; if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - ss.str(""); - ss << attack << " physical +" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - descriptions.emplace_back("Attack", ss.str()); - } else { - descriptions.emplace_back("Attack", std::to_string(attack)); + attackDescription = fmt::format("{} {}", it.abilities->elementDamage, getCombatName(it.abilities->elementType)); + } + + if (attack != 0 && !attackDescription.empty()) { + attackDescription = fmt::format("{} physical + {}", attack, attackDescription); + } else if (attack != 0 && attackDescription.empty()) { + attackDescription = std::to_string(attack); + } + + if (!attackDescription.empty()) { + descriptions.emplace_back("Attack", attackDescription); } } @@ -2741,13 +2759,17 @@ std::string Item::getDescription(const ItemType &it, int32_t lookDistance, const s << "Vol:" << volume; } } + if (attack != 0) { begin = false; s << " (Atk:" << attack; + } - if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - s << " physical + " << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - } + if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0 && !begin) { + s << " physical + " << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); + } else if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0 && begin) { + begin = false; + s << " (" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); } if (defense != 0 || extraDefense != 0 || it.isMissile()) { @@ -2780,6 +2802,17 @@ std::string Item::getDescription(const ItemType &it, int32_t lookDistance, const s << getSkillName(i) << ' ' << std::showpos << it.abilities->skills[i] << std::noshowpos; } + if (it.abilities->regeneration) { + if (begin) { + begin = false; + s << " ("; + } else { + s << ", "; + } + + s << "faster regeneration"; + } + for (uint8_t i = SKILL_CRITICAL_HIT_CHANCE; i <= SKILL_LAST; i++) { auto skill = item ? item->getSkill(static_cast(i)) : it.getSkill(static_cast(i)); if (!skill) { diff --git a/src/items/items.cpp b/src/items/items.cpp index 69ce46ced92..5aaf2129b29 100644 --- a/src/items/items.cpp +++ b/src/items/items.cpp @@ -15,6 +15,7 @@ #include "items/weapons/weapons.hpp" #include "lua/creature/movement.hpp" #include "utils/pugicast.hpp" +#include "creatures/combat/spells.hpp" #include "utils/tools.hpp" #include @@ -95,7 +96,7 @@ std::string ItemType::parseAugmentDescription(bool inspect /*= false*/) const { } std::string ItemType::getFormattedAugmentDescription(const std::shared_ptr &augmentInfo) const { - const std::string augmentName = Items::getAugmentNameByType(augmentInfo->type); + const auto augmentName = Items::getAugmentNameByType(augmentInfo->type); std::string augmentSpellNameCapitalized = augmentInfo->spellName; capitalizeWordsIgnoringString(augmentSpellNameCapitalized, " of "); @@ -105,7 +106,11 @@ std::string ItemType::getFormattedAugmentDescription(const std::shared_ptr {}", augmentSpellNameCapitalized, augmentName); } else if (augmentInfo->type == Augment_t::Cooldown) { return fmt::format("{} -> {}{}s {}", augmentSpellNameCapitalized, signal, augmentInfo->value / 1000, augmentName); + } else if (augmentInfo->type == Augment_t::Base) { + const auto &spell = g_spells().getSpellByName(augmentInfo->spellName); + return fmt::format("{} -> {:+}% {} {}", augmentSpellNameCapitalized, augmentInfo->value, augmentName, spell->getGroup() == SPELLGROUP_HEALING ? "healing" : "damage"); } + return fmt::format("{} -> {:+}% {}", augmentSpellNameCapitalized, augmentInfo->value, augmentName); } diff --git a/src/items/items_definitions.hpp b/src/items/items_definitions.hpp index 403200e231a..19d7f30b942 100644 --- a/src/items/items_definitions.hpp +++ b/src/items/items_definitions.hpp @@ -272,6 +272,7 @@ enum ImbuementTypes_t : int64_t { enum class Augment_t : uint8_t { None, + Base, PowerfulImpact, StrongImpact, IncreasedDamage, diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index aa99cb57d26..c59f0d89c25 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -5761,16 +5761,19 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { ss << static_cast(it.shootRange) << " fields"; } msg.addString(ss.str()); - } else if (!it.isRanged() && it.attack != 0) { + } else { + std::string attackDescription; if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - std::ostringstream ss; - ss << it.attack << " physical +" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - msg.addString(ss.str()); - } else { - msg.addString(std::to_string(it.attack)); + attackDescription = fmt::format("{} {}", it.abilities->elementDamage, getCombatName(it.abilities->elementType)); } - } else { - msg.add(0x00); + + if (it.attack != 0 && !attackDescription.empty()) { + attackDescription = fmt::format("{} physical + {}", it.attack, attackDescription); + } else if (it.attack != 0 && attackDescription.empty()) { + attackDescription = std::to_string(it.attack); + } + + msg.addString(attackDescription); } if (it.isContainer()) { @@ -5878,7 +5881,7 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId, uint8_t tier) { separator = true; } - ss << fmt::format("{} {:+.2f}%", getSkillName(i), skills / 100.0); + ss << fmt::format("{} {:+}%", getSkillName(i), skills / 100.0); } if (it.abilities->stats[STAT_MAGICPOINTS] != 0) {