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) {