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