diff --git a/data/XML/imbuements.xml b/data/XML/imbuements.xml
index 0a2fd90702f..c00a2b8d3e1 100644
--- a/data/XML/imbuements.xml
+++ b/data/XML/imbuements.xml
@@ -22,6 +22,7 @@
+
@@ -427,4 +428,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/items/items.xml b/data/items/items.xml
index 0858df99219..e4e4208cb82 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -8566,7 +8566,7 @@
-
+
diff --git a/data/scripts/runes/paralyze_rune.lua b/data/scripts/runes/paralyze_rune.lua
index b0c602a159b..e055ab12421 100644
--- a/data/scripts/runes/paralyze_rune.lua
+++ b/data/scripts/runes/paralyze_rune.lua
@@ -3,7 +3,7 @@ combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED)
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_UNDEFINEDDAMAGE)
local condition = Condition(CONDITION_PARALYZE)
-condition:setParameter(CONDITION_PARAM_TICKS, 6000)
+condition:setParameter(CONDITION_PARAM_TICKS, 60000)
condition:setFormula(-1, 0, -1, 0)
combat:addCondition(condition)
@@ -29,8 +29,8 @@ rune:charges(1)
rune:setPzLocked(true)
rune:level(54)
rune:magicLevel(18)
-rune:cooldown(6 * 1000)
-rune:groupCooldown(2 * 1000)
+rune:cooldown(1 * 1000)
+rune:groupCooldown(1 * 1000)
rune:mana(1400)
rune:needTarget(true)
rune:isBlocking(true) -- True = Solid / False = Creature
diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp
index 56cca63fe56..823a029ea33 100644
--- a/src/creatures/combat/combat.cpp
+++ b/src/creatures/combat/combat.cpp
@@ -753,23 +753,64 @@ void Combat::CombatConditionFunc(std::shared_ptr caster, std::shared_p
if (condition->getType() == CONDITION_FEARED && !checkFearConditionAffected(player)) {
return;
}
- }
- if (caster == target || target && !target->isImmune(condition->getType())) {
- auto conditionCopy = condition->clone();
- if (caster) {
- conditionCopy->setParam(CONDITION_PARAM_OWNER, caster->getID());
- conditionCopy->setPositionParam(CONDITION_PARAM_CASTER_POSITION, caster->getPosition());
+ if (condition->getType() == CONDITION_PARALYZE && target) {
+ if (player) {
+ if (reflectParalyzeCondition(caster, player, condition)) {
+ return;
+ }
+ }
}
- // TODO: infight condition until all aggressive conditions has ended
- if (target) {
- target->addCombatCondition(conditionCopy, caster && caster->getPlayer() != nullptr);
+ if (caster == target || (target && !target->isImmune(condition->getType()))) {
+ auto conditionCopy = condition->clone();
+ if (caster) {
+ conditionCopy->setParam(CONDITION_PARAM_OWNER, caster->getID());
+ conditionCopy->setPositionParam(CONDITION_PARAM_CASTER_POSITION, caster->getPosition());
+ }
+
+ // TODO: infight condition until all aggressive conditions has ended
+ if (target) {
+ target->addCombatCondition(conditionCopy, caster && caster->getPlayer() != nullptr);
+ }
}
}
}
}
+bool Combat::reflectParalyzeCondition(const std::shared_ptr &caster, const std::shared_ptr &target, const std::shared_ptr &condition) {
+ if (!target->hasCondition(CONDITION_PARALYZE)) {
+ target->addCondition(condition->clone());
+ return true;
+ }
+
+ int32_t reflectionChance = 0;
+ for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) {
+ auto item = target->getInventoryItem(static_cast(slot));
+ if (item) {
+ for (uint8_t slotid = 0; slotid < item->getImbuementSlot(); ++slotid) {
+ ImbuementInfo imbuementInfo;
+ if (item->getImbuementInfo(slotid, &imbuementInfo)) {
+ reflectionChance = std::max(reflectionChance, imbuementInfo.imbuement->paralyzeReduction);
+ }
+ }
+ }
+ }
+
+ if (caster && !caster->isImmune(CONDITION_PARALYZE)) {
+ caster->addCondition(condition->clone());
+ }
+
+ if (uniform_random(1, 100) <= reflectionChance) {
+ if (target->hasCondition(CONDITION_PARALYZE)) {
+ target->removeCondition(CONDITION_PARALYZE);
+ }
+ return true;
+ }
+
+ return false;
+}
+
void Combat::CombatDispelFunc(std::shared_ptr, std::shared_ptr target, const CombatParams ¶ms, CombatDamage*) {
if (target) {
target->removeCombatCondition(params.dispelType);
diff --git a/src/creatures/combat/combat.hpp b/src/creatures/combat/combat.hpp
index 6a79455c7c4..206f90de94b 100644
--- a/src/creatures/combat/combat.hpp
+++ b/src/creatures/combat/combat.hpp
@@ -385,6 +385,8 @@ class Combat {
static void combatTileEffects(const CreatureVector &spectators, std::shared_ptr caster, std::shared_ptr tile, const CombatParams ¶ms);
+ static bool reflectParalyzeCondition(const std::shared_ptr &caster, const std::shared_ptr &target, const std::shared_ptr &condition);
+
/**
* @brief Calculate the level formula for combat.
*
diff --git a/src/creatures/players/imbuements/imbuements.cpp b/src/creatures/players/imbuements/imbuements.cpp
index ed312dbf8e1..6e114c69cd6 100644
--- a/src/creatures/players/imbuements/imbuements.cpp
+++ b/src/creatures/players/imbuements/imbuements.cpp
@@ -12,7 +12,30 @@
#include "lua/creature/events.hpp"
#include "utils/pugicast.hpp"
-Imbuement* Imbuements::getImbuement(uint16_t id) {
+static const std::unordered_map skillMap = {
+ { "sword", SKILL_SWORD },
+ { "axe", SKILL_AXE },
+ { "club", SKILL_CLUB },
+ { "dist", SKILL_DISTANCE },
+ { "distance", SKILL_DISTANCE },
+ { "fish", SKILL_FISHING },
+ { "shield", SKILL_SHIELD },
+ { "fist", SKILL_FIST },
+ { "magicpoints", STAT_MAGICPOINTS },
+ { "critical", SKILL_CRITICAL_HIT_DAMAGE },
+ { "lifeleech", SKILL_LIFE_LEECH_AMOUNT },
+ { "manaleech", SKILL_MANA_LEECH_AMOUNT }
+};
+
+static const std::unordered_map effectTypeToSkillMode = {
+ { "skill", NormalSkill },
+ { "magicpoints", MagicLevel },
+ { "critical", SpecialSkill },
+ { "lifeleech", SpecialSkill },
+ { "manaleech", SpecialSkill }
+};
+
+std::shared_ptr Imbuements::getImbuement(uint16_t id) const {
if (id == 0) {
return nullptr;
}
@@ -22,7 +45,7 @@ Imbuement* Imbuements::getImbuement(uint16_t id) {
g_logger().warn("Imbuement {} not found", id);
return nullptr;
}
- return &it->second;
+ return it->second;
}
bool Imbuements::loadFromXml(bool /* reloading */) {
@@ -35,277 +58,289 @@ bool Imbuements::loadFromXml(bool /* reloading */) {
}
loaded = true;
- for (auto baseNode : doc.child("imbuements").children()) {
- pugi::xml_attribute attr;
- // Base for imbue
- if (strcasecmp(baseNode.name(), "base") == 0) {
- pugi::xml_attribute id = baseNode.attribute("id");
- if (!id) {
- g_logger().warn("Missing id for base entry");
- continue;
- }
- basesImbuement.emplace_back(
- pugi::cast(id.value()),
- baseNode.attribute("name").as_string(),
- pugi::cast(baseNode.attribute("price").value()),
- pugi::cast(baseNode.attribute("protectionPrice").value()),
- pugi::cast(baseNode.attribute("removecost").value()),
- pugi::cast(baseNode.attribute("duration").value()),
- pugi::cast(baseNode.attribute("percent").value())
- );
-
- // Category/Group
- } else if (strcasecmp(baseNode.name(), "category") == 0) {
- pugi::xml_attribute id = baseNode.attribute("id");
- if (!id) {
- g_logger().warn("Missing id for category entry");
- continue;
- }
- categoriesImbuement.emplace_back(
- pugi::cast(id.value()),
- baseNode.attribute("name").as_string(),
- baseNode.attribute("agressive").as_bool(true)
- );
-
- // Imbuements
- } else if (strcasecmp(baseNode.name(), "imbuement") == 0) {
+ if (!std::ranges::all_of(doc.child("imbuements").children(), [&](const auto &baseNode) {
++runningid;
- pugi::xml_attribute base = baseNode.attribute("base");
- if (!base) {
- g_logger().warn("Missing imbuement base id");
- continue;
+ if (strcasecmp(baseNode.name(), "base") == 0) {
+ if (!processBaseNode(baseNode)) {
+ g_logger().error("Falha ao processar o nó base");
+ return false;
+ }
+ } else if (strcasecmp(baseNode.name(), "category") == 0) {
+ if (!processCategoryNode(baseNode)) {
+ g_logger().error("Falha ao processar o nó category");
+ return false;
+ }
+ } else if (strcasecmp(baseNode.name(), "imbuement") == 0) {
+ if (!processImbuementNode(baseNode)) {
+ g_logger().error("Falha ao processar o nó imbuement");
+ return false;
+ }
}
+ return true;
+ })) {
+ return false;
+ }
+ return true;
+}
- uint16_t baseid = pugi::cast(base.value());
- auto groupBase = getBaseByID(baseid);
- if (groupBase == nullptr) {
- g_logger().warn("Group base '{}' not exist", baseid);
- continue;
- }
+bool Imbuements::processBaseNode(const pugi::xml_node &baseNode) {
+ pugi::xml_attribute id = baseNode.attribute("id");
+ if (!id) {
+ g_logger().warn("Missing id for base entry");
+ return false;
+ }
- auto imbuements = imbuementMap.emplace(std::piecewise_construct, std::forward_as_tuple(runningid), std::forward_as_tuple(runningid, baseid));
+ basesImbuement.emplace_back(std::make_shared(
+ pugi::cast(id.value()),
+ baseNode.attribute("name").as_string(),
+ pugi::cast(baseNode.attribute("price").value()),
+ pugi::cast(baseNode.attribute("protectionPrice").value()),
+ pugi::cast(baseNode.attribute("removecost").value()),
+ pugi::cast(baseNode.attribute("duration").value()),
+ pugi::cast(baseNode.attribute("percent").value())
+ ));
- if (!imbuements.second) {
- g_logger().warn("Duplicate imbuement of Base ID: '{}' ignored", baseid);
- continue;
- }
+ return true;
+}
- Imbuement &imbuement = imbuements.first->second;
+bool Imbuements::processCategoryNode(const pugi::xml_node &categoryNode) {
+ pugi::xml_attribute id = categoryNode.attribute("id");
+ if (!id) {
+ g_logger().warn("Missing id for category entry");
+ return false;
+ }
- pugi::xml_attribute iconBase = baseNode.attribute("iconid");
- if (!iconBase) {
- g_logger().warn("Missing 'iconid' for imbuement entry");
- continue;
- }
- imbuement.icon = pugi::cast(iconBase.value());
+ categoriesImbuement.emplace_back(std::make_shared(
+ pugi::cast(id.value()),
+ categoryNode.attribute("name").as_string(),
+ categoryNode.attribute("agressive").as_bool(true)
+ ));
- if (pugi::xml_attribute soundBase = baseNode.attribute("sound")) {
- imbuement.soundEffect = static_cast(pugi::cast(soundBase.value()));
- }
+ return true;
+}
+
+bool Imbuements::processImbuementNode(const pugi::xml_node &imbuementNode) {
+ pugi::xml_attribute base = imbuementNode.attribute("base");
+ if (!base) {
+ g_logger().warn("Missing imbuement base id");
+ return false;
+ }
+
+ uint16_t baseid = pugi::cast(base.value());
+ const auto &groupBase = getBaseByID(baseid);
+ if (groupBase == nullptr) {
+ g_logger().warn("Group base '{}' not exist", baseid);
+ return false;
+ }
+
+ auto imbuements = imbuementMap.emplace(std::piecewise_construct, std::forward_as_tuple(runningid), std::forward_as_tuple(std::make_shared(runningid, baseid)));
+
+ if (!imbuements.second) {
+ g_logger().warn("Duplicate imbuement of Base ID: '{}' ignored", baseid);
+ return false;
+ }
+
+ const auto &imbuement = imbuements.first->second;
+
+ pugi::xml_attribute iconBase = imbuementNode.attribute("iconid");
+ if (!iconBase) {
+ g_logger().warn("Missing 'iconid' for imbuement entry");
+ return false;
+ }
+ imbuement->icon = pugi::cast(iconBase.value());
+
+ if (pugi::xml_attribute soundBase = imbuementNode.attribute("sound")) {
+ imbuement->soundEffect = static_cast(pugi::cast(soundBase.value()));
+ }
+
+ pugi::xml_attribute premiumBase = imbuementNode.attribute("premium");
+ if (premiumBase) {
+ imbuement->premium = premiumBase.as_bool();
+ }
+
+ if (pugi::xml_attribute storageBase = imbuementNode.attribute("storage")) {
+ imbuement->storage = pugi::cast(storageBase.value());
+ }
- pugi::xml_attribute premiumBase = baseNode.attribute("premium");
- if (premiumBase) {
- imbuement.premium = premiumBase.as_bool();
+ pugi::xml_attribute subgroupBase = imbuementNode.attribute("subgroup");
+ if (subgroupBase) {
+ imbuement->subgroup = subgroupBase.as_string();
+ }
+
+ pugi::xml_attribute categorybase = imbuementNode.attribute("category");
+ if (!categorybase) {
+ g_logger().warn("Missing imbuement category");
+ return false;
+ }
+
+ auto category = pugi::cast(categorybase.value());
+ const auto &category_p = getCategoryByID(category);
+ if (category_p == nullptr) {
+ g_logger().warn("Category imbuement {} not exist", category);
+ return false;
+ }
+
+ imbuement->category = category;
+
+ pugi::xml_attribute nameBase = imbuementNode.attribute("name");
+ if (!nameBase) {
+ g_logger().warn("Missing imbuement name");
+ return false;
+ }
+ imbuement->name = nameBase.value();
+
+ return processImbuementChildNodes(imbuementNode, imbuement);
+}
+
+bool Imbuements::processImbuementChildNodes(const pugi::xml_node &imbuementNode, const std::shared_ptr &imbuement) {
+ pugi::xml_attribute attr;
+ for (auto childNode : imbuementNode.children()) {
+ if (!(attr = childNode.attribute("key"))) {
+ g_logger().warn("Missing key attribute in imbuement id: {}", runningid);
+ return false;
+ }
+
+ std::string type = attr.as_string();
+ if (strcasecmp(type.c_str(), "item") == 0) {
+ if (!(attr = childNode.attribute("value"))) {
+ g_logger().warn("Missing item ID for imbuement name '{}'", imbuement->name);
+ return false;
}
+ auto sourceId = pugi::cast(attr.value());
- if (pugi::xml_attribute storageBase = baseNode.attribute("storage")) {
- imbuement.storage = pugi::cast(storageBase.value());
+ uint16_t count = 1;
+ if ((attr = childNode.attribute("count"))) {
+ count = pugi::cast(attr.value());
}
- pugi::xml_attribute subgroupBase = baseNode.attribute("subgroup");
- if (subgroupBase) {
- imbuement.subgroup = subgroupBase.as_string();
+ auto it2 = std::find_if(imbuement->items.begin(), imbuement->items.end(), [sourceId](const std::pair &source) -> bool {
+ return source.first == sourceId;
+ });
+
+ if (it2 != imbuement->items.end()) {
+ g_logger().warn("Duplicate item: {}, imbument name: {} ignored", childNode.attribute("value").value(), imbuement->name);
+ return false;
}
- pugi::xml_attribute categorybase = baseNode.attribute("category");
- if (!categorybase) {
- g_logger().warn("Missing imbuement category");
- continue;
+ imbuement->items.emplace_back(sourceId, count);
+
+ } else if (strcasecmp(type.c_str(), "description") == 0) {
+ std::string description = imbuement->name;
+ if ((attr = childNode.attribute("value"))) {
+ description = attr.as_string();
}
- uint16_t category = pugi::cast(categorybase.value());
- auto category_p = getCategoryByID(category);
- if (category_p == nullptr) {
- g_logger().warn("Category imbuement {} not exist", category);
- continue;
+ imbuement->description = description;
+ } else if (strcasecmp(type.c_str(), "effect") == 0) {
+ // Effects
+ if (!(attr = childNode.attribute("type"))) {
+ g_logger().warn("Missing effect type for imbuement name: {}", imbuement->name);
+ return false;
}
- imbuement.category = category;
+ std::string effecttype = attr.as_string();
- pugi::xml_attribute nameBase = baseNode.attribute("name");
- if (!nameBase) {
- g_logger().warn("Missing imbuement name");
- continue;
- }
- imbuement.name = nameBase.value();
+ if (strcasecmp(effecttype.c_str(), "skill") == 0) {
+ if (!(attr = childNode.attribute("value"))) {
+ g_logger().warn("Missing effect value for imbuement name {}", imbuement->name);
+ return false;
+ }
- for (auto childNode : baseNode.children()) {
- if (!(attr = childNode.attribute("key"))) {
- g_logger().warn("Missing key attribute in imbuement id: {}", runningid);
- continue;
+ std::string skillName = asLowerCaseString(attr.as_string());
+ auto it = skillMap.find(skillName);
+ if (it == skillMap.end()) {
+ g_logger().warn("Unknown skill name {} in imbuement name {}", skillName, imbuement->name);
+ return false;
}
- std::string type = attr.as_string();
- if (strcasecmp(type.c_str(), "item") == 0) {
- if (!(attr = childNode.attribute("value"))) {
- g_logger().warn("Missing item ID for imbuement name '{}'", imbuement.name);
- continue;
- }
- uint16_t sourceId = pugi::cast(attr.value());
+ uint8_t skillId = it->second;
- uint16_t count = 1;
- if ((attr = childNode.attribute("count"))) {
- count = pugi::cast(childNode.attribute("count").value());
+ if (!(attr = childNode.attribute("bonus"))) {
+ g_logger().warn("Missing skill bonus for imbuement name {}", imbuement->name);
+ return false;
+ }
+ auto bonus = pugi::cast(attr.value());
+
+ auto itSkillMode = effectTypeToSkillMode.find(skillName);
+ UseSkillMode useSkillMode = (itSkillMode != effectTypeToSkillMode.end()) ? itSkillMode->second : NormalSkill;
+
+ if (useSkillMode == NormalSkill) {
+ imbuement->skills[skillId] = bonus;
+ } else if (useSkillMode == MagicLevel) {
+ imbuement->stats[skillId] = bonus;
+ } else if (useSkillMode == SpecialSkill) {
+ imbuement->skills[skillId] = bonus;
+ int32_t chance = 100;
+ if ((attr = childNode.attribute("chance"))) {
+ chance = std::min(10000, pugi::cast(attr.value()));
}
+ imbuement->skills[skillId - 1] = chance;
+ }
+ } else if (strcasecmp(effecttype.c_str(), "damage") == 0) {
+ if (!(attr = childNode.attribute("combat"))) {
+ g_logger().warn("Missing combat for imbuement name {}", imbuement->name);
+ return false;
+ }
- auto it2 = std::find_if(imbuement.items.begin(), imbuement.items.end(), [sourceId](const std::pair &source) -> bool {
- return source.first == sourceId;
- });
+ CombatType_t combatType = getCombatTypeByName(attr.as_string());
+ if (combatType == COMBAT_NONE) {
+ g_logger().warn("Unknown combat type for element {}", attr.as_string());
+ return false;
+ }
- if (it2 != imbuement.items.end()) {
- g_logger().warn("Duplicate item: {}, imbument name: {} ignored", childNode.attribute("value").value(), imbuement.name);
- continue;
- }
+ if (!(attr = childNode.attribute("value"))) {
+ g_logger().warn("Missing damage reduction percentage for imbuement name {}", imbuement->name);
+ return false;
+ }
- imbuement.items.emplace_back(sourceId, count);
+ uint32_t percent = std::min(100, pugi::cast(attr.value()));
- } else if (strcasecmp(type.c_str(), "description") == 0) {
- std::string description = imbuement.name;
- if ((attr = childNode.attribute("value"))) {
- description = attr.as_string();
- }
+ imbuement->combatType = combatType;
+ imbuement->elementDamage = std::min(100, static_cast(percent));
+ } else if (strcasecmp(effecttype.c_str(), "reduction") == 0) {
+ if (!(attr = childNode.attribute("combat"))) {
+ g_logger().warn("Missing combat for imbuement name {}", imbuement->name);
+ return false;
+ }
- imbuement.description = description;
- } else if (strcasecmp(type.c_str(), "effect") == 0) {
- // Effects
- if (!(attr = childNode.attribute("type"))) {
- g_logger().warn("Missing effect type for imbuement name: {}", imbuement.name);
- continue;
- }
+ CombatType_t combatType = getCombatTypeByName(attr.as_string());
+ if (combatType == COMBAT_NONE) {
+ g_logger().warn("Unknown combat type for element {}", attr.as_string());
+ return false;
+ }
- std::string effecttype = attr.as_string();
-
- if (strcasecmp(effecttype.c_str(), "skill") == 0) {
- if (!(attr = childNode.attribute("value"))) {
- g_logger().warn("Missing effect value for imbuement name {}", imbuement.name);
- continue;
- }
-
- uint8_t usenormalskill = 1; // 1 = skill normal, 2 = magiclevel, 3 = leechs/crit
-
- uint8_t skillId;
- std::string tmpStrValue = asLowerCaseString(attr.as_string());
- if (tmpStrValue == "sword") {
- skillId = SKILL_SWORD;
- } else if (tmpStrValue == "axe") {
- skillId = SKILL_AXE;
- } else if (tmpStrValue == "club") {
- skillId = SKILL_CLUB;
- } else if ((tmpStrValue == "dist") || (tmpStrValue == "distance")) {
- skillId = SKILL_DISTANCE;
- } else if (tmpStrValue == "fish") {
- skillId = SKILL_FISHING;
- } else if (tmpStrValue == "shield") {
- skillId = SKILL_SHIELD;
- } else if (tmpStrValue == "fist") {
- skillId = SKILL_FIST;
- } else if (tmpStrValue == "magicpoints") {
- skillId = STAT_MAGICPOINTS;
- usenormalskill = 2;
- } else if (tmpStrValue == "critical") {
- usenormalskill = 3;
- skillId = SKILL_CRITICAL_HIT_DAMAGE;
- } else if (tmpStrValue == "lifeleech") {
- usenormalskill = 3;
- skillId = SKILL_LIFE_LEECH_AMOUNT;
- } else if (tmpStrValue == "manaleech") {
- usenormalskill = 3;
- skillId = SKILL_MANA_LEECH_AMOUNT;
- } else {
- g_logger().warn("Unknow skill name {} in imbuement name {}", tmpStrValue, imbuement.name);
- continue;
- }
-
- if (!(attr = childNode.attribute("bonus"))) {
- g_logger().warn("Missing skill bonus for imbuement name {}", imbuement.name);
- continue;
- }
- int32_t bonus = pugi::cast(attr.value());
-
- if (usenormalskill == 1) {
- imbuement.skills[skillId] = bonus;
- } else if (usenormalskill == 2) {
- imbuement.stats[skillId] = bonus;
- } else if (usenormalskill == 3) {
- imbuement.skills[skillId] = bonus;
- int32_t chance = 100;
- if ((attr = childNode.attribute("chance"))) {
- chance = std::min(10000, pugi::cast(attr.value()));
- }
-
- imbuement.skills[skillId - 1] = chance;
- }
- } else if (strcasecmp(effecttype.c_str(), "damage") == 0) {
- if (!(attr = childNode.attribute("combat"))) {
- g_logger().warn("Missing combat for imbuement name {}", imbuement.name);
- continue;
- }
-
- CombatType_t combatType = getCombatTypeByName(attr.as_string());
- if (combatType == COMBAT_NONE) {
- g_logger().warn("Unknown combat type for element {}", attr.as_string());
- continue;
- }
-
- if (!(attr = childNode.attribute("value"))) {
- g_logger().warn("Missing damage reduction percentage for imbuement name {}", imbuement.name);
- continue;
- }
-
- uint32_t percent = std::min(100, pugi::cast(attr.value()));
-
- imbuement.combatType = combatType;
- imbuement.elementDamage = std::min(100, percent);
- } else if (strcasecmp(effecttype.c_str(), "reduction") == 0) {
- if (!(attr = childNode.attribute("combat"))) {
- g_logger().warn("Missing combat for imbuement name {}", imbuement.name);
- continue;
- }
-
- CombatType_t combatType = getCombatTypeByName(attr.as_string());
- if (combatType == COMBAT_NONE) {
- g_logger().warn("Unknown combat type for element {}", attr.as_string());
- continue;
- }
-
- if (!(attr = childNode.attribute("value"))) {
- g_logger().warn("Missing damage reduction percentage for imbuement name {}", imbuement.name);
- continue;
- }
-
- uint32_t percent = std::min(100, pugi::cast(attr.value()));
-
- imbuement.absorbPercent[combatTypeToIndex(combatType)] = percent;
- } else if (strcasecmp(effecttype.c_str(), "speed") == 0) {
- if (!(attr = childNode.attribute("value"))) {
- g_logger().warn("Missing speed value for imbuement name {}", imbuement.name);
- continue;
- }
-
- imbuement.speed = pugi::cast(attr.value());
- } else if (strcasecmp(effecttype.c_str(), "capacity") == 0) {
- if (!(attr = childNode.attribute("value"))) {
- g_logger().warn("Missing cap value for imbuement name {}", imbuement.name);
- continue;
- }
-
- imbuement.capacity = pugi::cast(attr.value());
- }
+ if (!(attr = childNode.attribute("value"))) {
+ g_logger().warn("Missing damage reduction percentage for imbuement name {}", imbuement->name);
+ return false;
+ }
+
+ uint32_t percent = std::min(100, pugi::cast(attr.value()));
+
+ imbuement->absorbPercent[combatTypeToIndex(combatType)] = static_cast(percent);
+ } else if (strcasecmp(effecttype.c_str(), "speed") == 0) {
+ if (!(attr = childNode.attribute("value"))) {
+ g_logger().warn("Missing speed value for imbuement name {}", imbuement->name);
+ return false;
+ }
+
+ imbuement->speed = static_cast(pugi::cast(attr.value()));
+ } else if (strcasecmp(effecttype.c_str(), "capacity") == 0) {
+ if (!(attr = childNode.attribute("value"))) {
+ g_logger().warn("Missing cap value for imbuement name {}", imbuement->name);
+ return false;
+ }
+
+ imbuement->capacity = pugi::cast(attr.value());
+ } else if (strcasecmp(effecttype.c_str(), "vibrancy") == 0) {
+ if (!(attr = childNode.attribute("chance"))) {
+ g_logger().warn("Missing chance value for imbuement name {}", imbuement->name);
+ return false;
}
+
+ imbuement->paralyzeReduction = pugi::cast(attr.value());
}
}
}
-
return true;
}
@@ -320,27 +355,27 @@ bool Imbuements::reload() {
return loadFromXml(true);
}
-BaseImbuement* Imbuements::getBaseByID(uint16_t id) {
- auto baseImbuements = std::find_if(basesImbuement.begin(), basesImbuement.end(), [id](const BaseImbuement &groupImbuement) {
- return groupImbuement.id == id;
+std::shared_ptr Imbuements::getBaseByID(uint16_t id) const {
+ auto baseImbuements = std::find_if(basesImbuement.begin(), basesImbuement.end(), [id](const auto &groupImbuement) {
+ return groupImbuement->id == id;
});
- return baseImbuements != basesImbuement.end() ? &*baseImbuements : nullptr;
+ return baseImbuements != basesImbuement.end() ? *baseImbuements : nullptr;
}
-CategoryImbuement* Imbuements::getCategoryByID(uint16_t id) {
- auto categoryImbuements = std::find_if(categoriesImbuement.begin(), categoriesImbuement.end(), [id](const CategoryImbuement &categoryImbuement) {
- return categoryImbuement.id == id;
+std::shared_ptr Imbuements::getCategoryByID(uint16_t id) const {
+ auto categoryImbuements = std::find_if(categoriesImbuement.begin(), categoriesImbuement.end(), [id](const auto &categoryImbuement) {
+ return categoryImbuement->id == id;
});
- return categoryImbuements != categoriesImbuement.end() ? &*categoryImbuements : nullptr;
+ return categoryImbuements != categoriesImbuement.end() ? *categoryImbuements : nullptr;
}
-std::vector Imbuements::getImbuements(std::shared_ptr player, std::shared_ptr- item) {
- std::vector imbuements;
+std::vector> Imbuements::getImbuements(const std::shared_ptr &player, const std::shared_ptr
- &item) const {
+ std::vector> imbuements;
for (auto &[key, value] : imbuementMap) {
- Imbuement* imbuement = &value;
+ const std::shared_ptr &imbuement = value;
if (!imbuement) {
continue;
}
@@ -354,7 +389,7 @@ std::vector Imbuements::getImbuements(std::shared_ptr player
}
// Send only the imbuements registered on item (in items.xml) to the imbuement window
- const CategoryImbuement* categoryImbuement = getCategoryByID(imbuement->getCategory());
+ const std::shared_ptr &categoryImbuement = getCategoryByID(imbuement->getCategory());
if (!item->hasImbuementType(static_cast(categoryImbuement->id), imbuement->getBaseID())) {
continue;
}
@@ -364,7 +399,7 @@ std::vector Imbuements::getImbuements(std::shared_ptr player
continue;
}
- imbuements.push_back(imbuement);
+ imbuements.emplace_back(imbuement);
}
return imbuements;
diff --git a/src/creatures/players/imbuements/imbuements.hpp b/src/creatures/players/imbuements/imbuements.hpp
index 265e813aa1c..d992b3bd06c 100644
--- a/src/creatures/players/imbuements/imbuements.hpp
+++ b/src/creatures/players/imbuements/imbuements.hpp
@@ -17,7 +17,11 @@
class Player;
class Item;
-class Imbuement;
+enum UseSkillMode : uint8_t {
+ NormalSkill = 1,
+ MagicLevel = 2,
+ SpecialSkill = 3
+};
struct BaseImbuement {
BaseImbuement(uint16_t initId, std::string initName, uint32_t initPrice, uint32_t initProtectionPrice, uint32_t initRemoveCost, uint32_t initDuration, uint8_t initPercent) :
@@ -56,23 +60,27 @@ class Imbuements {
return inject();
}
- Imbuement* getImbuement(uint16_t id);
+ std::shared_ptr getImbuement(uint16_t id) const;
+ std::shared_ptr getBaseByID(uint16_t id) const;
+ std::shared_ptr getCategoryByID(uint16_t id) const;
- BaseImbuement* getBaseByID(uint16_t id);
- CategoryImbuement* getCategoryByID(uint16_t id);
- std::vector getImbuements(std::shared_ptr player, std::shared_ptr
- item);
+ std::vector> getImbuements(const std::shared_ptr &player, const std::shared_ptr
- &item) const;
protected:
friend class Imbuement;
bool loaded = false;
private:
- std::map imbuementMap;
+ uint32_t runningid = 0;
- std::vector basesImbuement;
- std::vector categoriesImbuement;
+ std::map> imbuementMap;
+ std::vector> basesImbuement;
+ std::vector> categoriesImbuement;
- uint32_t runningid = 0;
+ bool processBaseNode(const pugi::xml_node &baseNode);
+ bool processCategoryNode(const pugi::xml_node &categoryNode);
+ bool processImbuementNode(const pugi::xml_node &imbuementNode);
+ bool processImbuementChildNodes(const pugi::xml_node &imbuementNode, const std::shared_ptr &imbuement);
};
constexpr auto g_imbuements = Imbuements::getInstance;
@@ -94,7 +102,7 @@ class Imbuement {
return storage;
}
- bool isPremium() {
+ bool isPremium() const {
return premium;
}
std::string getName() const {
@@ -116,7 +124,7 @@ class Imbuement {
return items;
}
- uint16_t getIconID() {
+ uint16_t getIconID() const {
return icon + (baseid - 1);
}
@@ -124,11 +132,11 @@ class Imbuement {
int32_t stats[STAT_LAST + 1] = {};
int32_t skills[SKILL_LAST + 1] = {};
int32_t speed = 0;
+ int32_t paralyzeReduction = 0;
uint32_t capacity = 0;
int16_t absorbPercent[COMBAT_COUNT] = {};
int16_t elementDamage = 0;
SoundEffect_t soundEffect = SoundEffect_t::SILENCE;
-
CombatType_t combatType = COMBAT_NONE;
protected:
@@ -139,7 +147,7 @@ class Imbuement {
bool premium = false;
uint32_t storage = 0;
uint16_t id, baseid, category = 0;
- std::string name, description, subgroup = "";
+ std::string name, description, subgroup;
std::vector> items;
};
diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp
index 925086f2b53..fdba2a7d931 100644
--- a/src/creatures/players/player.cpp
+++ b/src/creatures/players/player.cpp
@@ -583,7 +583,7 @@ void Player::updateInventoryImbuement() {
// Imbuement from imbuementInfo, this variable reduces code complexity
auto imbuement = imbuementInfo.imbuement;
// Get the category of the imbuement
- const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory());
+ const auto &categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory());
// Parent of the imbued item
auto parent = item->getParent();
bool isInBackpack = parent && parent->getContainer();
@@ -1453,7 +1453,7 @@ void Player::sendHouseWindow(std::shared_ptr house, uint32_t listId) cons
}
}
-void Player::onApplyImbuement(Imbuement* imbuement, std::shared_ptr
- item, uint8_t slot, bool protectionCharm) {
+void Player::onApplyImbuement(std::shared_ptr imbuement, std::shared_ptr
- item, uint8_t slot, bool protectionCharm) {
if (!imbuement || !item) {
return;
}
@@ -1474,7 +1474,7 @@ void Player::onApplyImbuement(Imbuement* imbuement, std::shared_ptr
- item,
}
}
- const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID());
+ const auto &baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID());
if (!baseImbuement) {
return;
}
@@ -1541,7 +1541,7 @@ void Player::onClearImbuement(std::shared_ptr
- item, uint8_t slot) {
return;
}
- const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID());
+ const auto &baseImbuement = g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID());
if (!baseImbuement) {
return;
}
@@ -6383,7 +6383,7 @@ uint16_t Player::getFreeBackpackSlots() const {
return counter;
}
-void Player::addItemImbuementStats(const Imbuement* imbuement) {
+void Player::addItemImbuementStats(const std::shared_ptr imbuement) {
bool requestUpdate = false;
// Check imbuement skills
for (int32_t skill = SKILL_FIRST; skill <= SKILL_LAST; ++skill) {
@@ -6418,7 +6418,7 @@ void Player::addItemImbuementStats(const Imbuement* imbuement) {
}
}
-void Player::removeItemImbuementStats(const Imbuement* imbuement) {
+void Player::removeItemImbuementStats(const std::shared_ptr imbuement) {
if (!imbuement) {
return;
}
diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp
index da4c0cec9e8..56fe064e955 100644
--- a/src/creatures/players/player.hpp
+++ b/src/creatures/players/player.hpp
@@ -1566,7 +1566,7 @@ class Player final : public Creature, public Cylinder, public Bankable {
}
}
// Imbuements
- void onApplyImbuement(Imbuement* imbuement, std::shared_ptr
- item, uint8_t slot, bool protectionCharm);
+ void onApplyImbuement(std::shared_ptr imbuement, std::shared_ptr
- item, uint8_t slot, bool protectionCharm);
void onClearImbuement(std::shared_ptr
- item, uint8_t slot);
void openImbuementWindow(std::shared_ptr
- item);
void sendImbuementResult(const std::string message) {
@@ -1853,8 +1853,8 @@ class Player final : public Creature, public Cylinder, public Bankable {
void setTraining(bool value);
- void addItemImbuementStats(const Imbuement* imbuement);
- void removeItemImbuementStats(const Imbuement* imbuement);
+ void addItemImbuementStats(const std::shared_ptr imbuement);
+ void removeItemImbuementStats(const std::shared_ptr imbuement);
void updateImbuementTrackerStats() const;
bool isUIExhausted(uint32_t exhaustionTime = 250) const;
diff --git a/src/game/game.cpp b/src/game/game.cpp
index d731bd766b6..93db62e9267 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -5805,7 +5805,7 @@ void Game::playerApplyImbuement(uint32_t playerId, uint16_t imbuementid, uint8_t
return;
}
- Imbuement* imbuement = g_imbuements().getImbuement(imbuementid);
+ const auto &imbuement = g_imbuements().getImbuement(imbuementid);
if (!imbuement) {
return;
}
diff --git a/src/items/functions/item/item_parse.cpp b/src/items/functions/item/item_parse.cpp
index 2d1ba9301c5..520be1613c0 100644
--- a/src/items/functions/item/item_parse.cpp
+++ b/src/items/functions/item/item_parse.cpp
@@ -865,7 +865,7 @@ void ItemParse::parseImbuement(const std::string &tmpStrValue, pugi::xml_node at
continue;
}
} else {
- g_logger().warn("[ParseImbuement::initParseImbuement] - Unknown type: {}", valueAttribute.as_string());
+ g_logger().warn("[ParseImbuement::initParseImbuement] - Unknown type: {}, item: {}", valueAttribute.as_string(), itemType.id);
}
}
}
diff --git a/src/items/functions/item/item_parse.hpp b/src/items/functions/item/item_parse.hpp
index 7859a77fe9c..63fd09d2cc7 100644
--- a/src/items/functions/item/item_parse.hpp
+++ b/src/items/functions/item/item_parse.hpp
@@ -244,7 +244,8 @@ const phmap::flat_hash_map ImbuementsTypeMap = {
{ "skillboost shielding", IMBUEMENT_SKILLBOOST_SHIELDING },
{ "skillboost distance", IMBUEMENT_SKILLBOOST_DISTANCE },
{ "skillboost magic level", IMBUEMENT_SKILLBOOST_MAGIC_LEVEL },
- { "increase capacity", IMBUEMENT_INCREASE_CAPACITY }
+ { "increase capacity", IMBUEMENT_INCREASE_CAPACITY },
+ { "vibrancy", IMBUEMENT_VIBRANCY_PARALYZE }
};
class ItemParse : public Items {
diff --git a/src/items/item.cpp b/src/items/item.cpp
index 81d24a790e7..3c39c7fa992 100644
--- a/src/items/item.cpp
+++ b/src/items/item.cpp
@@ -106,13 +106,13 @@ void Item::addImbuement(uint8_t slot, uint16_t imbuementId, uint32_t duration) {
}
// Get imbuement by the id
- const Imbuement* imbuement = g_imbuements().getImbuement(imbuementId);
+ const auto &imbuement = g_imbuements().getImbuement(imbuementId);
if (!imbuement) {
return;
}
// Get category imbuement for acess category id
- const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory());
+ const auto &categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory());
if (!hasImbuementType(static_cast(categoryImbuement->id), imbuement->getBaseID())) {
return;
}
@@ -131,7 +131,7 @@ bool Item::hasImbuementCategoryId(uint16_t categoryId) const {
for (uint8_t slotid = 0; slotid < getImbuementSlot(); slotid++) {
ImbuementInfo imbuementInfo;
if (getImbuementInfo(slotid, &imbuementInfo)) {
- if (const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuementInfo.imbuement->getCategory());
+ if (const auto &categoryImbuement = g_imbuements().getCategoryByID(imbuementInfo.imbuement->getCategory());
categoryImbuement->id == categoryId) {
return true;
}
@@ -1424,7 +1424,7 @@ Item::getDescriptions(const ItemType &it, std::shared_ptr
- item /*= nullptr
continue;
}
- const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID());
+ const auto &baseImbuement = g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID());
if (!baseImbuement) {
continue;
}
@@ -1914,7 +1914,7 @@ std::string Item::parseImbuementDescription(std::shared_ptr
- item) {
continue;
}
- const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID());
+ const auto &baseImbuement = g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID());
if (!baseImbuement) {
continue;
}
diff --git a/src/items/items_definitions.hpp b/src/items/items_definitions.hpp
index f044d4b5248..07b386ad701 100644
--- a/src/items/items_definitions.hpp
+++ b/src/items/items_definitions.hpp
@@ -267,7 +267,8 @@ enum ImbuementTypes_t : int64_t {
IMBUEMENT_SKILLBOOST_SHIELDING = 14,
IMBUEMENT_SKILLBOOST_DISTANCE = 15,
IMBUEMENT_SKILLBOOST_MAGIC_LEVEL = 16,
- IMBUEMENT_INCREASE_CAPACITY = 17
+ IMBUEMENT_INCREASE_CAPACITY = 17,
+ IMBUEMENT_VIBRANCY_PARALYZE = 18
};
enum class ContainerCategory_t : uint8_t {
@@ -609,6 +610,6 @@ enum ItemParseAttributes_t {
};
struct ImbuementInfo {
- Imbuement* imbuement;
+ std::shared_ptr imbuement;
uint32_t duration = 0;
};
diff --git a/src/lua/functions/items/imbuement_functions.cpp b/src/lua/functions/items/imbuement_functions.cpp
index f24a3f564d7..f2e73805677 100644
--- a/src/lua/functions/items/imbuement_functions.cpp
+++ b/src/lua/functions/items/imbuement_functions.cpp
@@ -16,7 +16,7 @@
int ImbuementFunctions::luaCreateImbuement(lua_State* L) {
// Imbuement(id)
uint16_t imbuementId = getNumber(L, 2);
- Imbuement* imbuement = g_imbuements().getImbuement(imbuementId);
+ const auto &imbuement = g_imbuements().getImbuement(imbuementId);
if (imbuement) {
pushUserdata(L, imbuement);
@@ -29,7 +29,7 @@ int ImbuementFunctions::luaCreateImbuement(lua_State* L) {
int ImbuementFunctions::luaImbuementGetName(lua_State* L) {
// imbuement:getName()
- Imbuement* imbuement = getUserdata(L, 1);
+ const auto &imbuement = getUserdata(L, 1);
if (imbuement) {
pushString(L, imbuement->getName());
} else {
@@ -40,7 +40,7 @@ int ImbuementFunctions::luaImbuementGetName(lua_State* L) {
int ImbuementFunctions::luaImbuementGetId(lua_State* L) {
// imbuement:getId()
- Imbuement* imbuement = getUserdata(L, 1);
+ const auto &imbuement = getUserdata(L, 1);
if (imbuement) {
lua_pushnumber(L, imbuement->getID());
} else {
@@ -51,7 +51,7 @@ int ImbuementFunctions::luaImbuementGetId(lua_State* L) {
int ImbuementFunctions::luaImbuementGetItems(lua_State* L) {
// imbuement:getItems()
- Imbuement* imbuement = getUserdata(L, 1);
+ const auto &imbuement = getUserdata(L, 1);
if (!imbuement) {
lua_pushnil(L);
return 1;
@@ -72,13 +72,13 @@ int ImbuementFunctions::luaImbuementGetItems(lua_State* L) {
int ImbuementFunctions::luaImbuementGetBase(lua_State* L) {
// imbuement:getBase()
- Imbuement* imbuement = getUserdata(L, 1);
+ const auto &imbuement = getUserdata(L, 1);
if (!imbuement) {
lua_pushnil(L);
return 1;
}
- const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID());
+ const auto &baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID());
if (!baseImbuement) {
lua_pushnil(L);
return 1;
@@ -97,13 +97,13 @@ int ImbuementFunctions::luaImbuementGetBase(lua_State* L) {
int ImbuementFunctions::luaImbuementGetCategory(lua_State* L) {
// imbuement:getCategory()
- Imbuement* imbuement = getUserdata(L, 1);
+ const auto &imbuement = getUserdata(L, 1);
if (!imbuement) {
lua_pushnil(L);
return 1;
}
uint16_t categoryId = imbuement->getCategory();
- const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(categoryId);
+ const auto &categoryImbuement = g_imbuements().getCategoryByID(categoryId);
if (categoryImbuement) {
lua_createtable(L, 0, 2);
@@ -118,7 +118,7 @@ int ImbuementFunctions::luaImbuementGetCategory(lua_State* L) {
int ImbuementFunctions::luaImbuementIsPremium(lua_State* L) {
// imbuement:isPremium()
- Imbuement* imbuement = getUserdata(L, 1);
+ const auto &imbuement = getUserdata(L, 1);
if (!imbuement) {
lua_pushnil(L);
return 1;
@@ -130,7 +130,7 @@ int ImbuementFunctions::luaImbuementIsPremium(lua_State* L) {
int ImbuementFunctions::luaImbuementGetElementDamage(lua_State* L) {
// imbuement:getElementDamage()
- Imbuement* imbuement = getUserdata(L, 1);
+ const auto &imbuement = getUserdata(L, 1);
if (imbuement) {
lua_pushnumber(L, imbuement->elementDamage);
} else {
@@ -141,7 +141,7 @@ int ImbuementFunctions::luaImbuementGetElementDamage(lua_State* L) {
int ImbuementFunctions::luaImbuementGetCombatType(lua_State* L) {
// imbuement:getCombatType()
- Imbuement* imbuement = getUserdata(L, 1);
+ const auto &imbuement = getUserdata(L, 1);
if (imbuement) {
lua_pushnumber(L, imbuement->combatType);
} else {
diff --git a/src/lua/functions/items/imbuement_functions.hpp b/src/lua/functions/items/imbuement_functions.hpp
index 516fe91a3b1..6e9457b8a4c 100644
--- a/src/lua/functions/items/imbuement_functions.hpp
+++ b/src/lua/functions/items/imbuement_functions.hpp
@@ -14,7 +14,7 @@
class ImbuementFunctions final : LuaScriptInterface {
public:
static void init(lua_State* L) {
- registerClass(L, "Imbuement", "", ImbuementFunctions::luaCreateImbuement);
+ registerSharedClass(L, "Imbuement", "", ImbuementFunctions::luaCreateImbuement);
registerMetaMethod(L, "Imbuement", "__eq", ImbuementFunctions::luaUserdataCompare);
registerMethod(L, "Imbuement", "getName", ImbuementFunctions::luaImbuementGetName);
diff --git a/src/lua/functions/items/item_functions.cpp b/src/lua/functions/items/item_functions.cpp
index 71ab040f47d..a72c1ca6282 100644
--- a/src/lua/functions/items/item_functions.cpp
+++ b/src/lua/functions/items/item_functions.cpp
@@ -776,7 +776,7 @@ int ItemFunctions::luaItemGetImbuement(lua_State* L) {
continue;
}
- Imbuement* imbuement = imbuementInfo.imbuement;
+ const auto &imbuement = imbuementInfo.imbuement;
if (!imbuement) {
continue;
}
diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp
index d924e0bfb0e..e36188519cf 100644
--- a/src/server/network/protocol/protocolgame.cpp
+++ b/src/server/network/protocol/protocolgame.cpp
@@ -7569,9 +7569,9 @@ void ProtocolGame::AddOutfit(NetworkMessage &msg, const Outfit_t &outfit, bool a
}
void ProtocolGame::addImbuementInfo(NetworkMessage &msg, uint16_t imbuementId) const {
- Imbuement* imbuement = g_imbuements().getImbuement(imbuementId);
- const BaseImbuement* baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID());
- const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory());
+ const auto &imbuement = g_imbuements().getImbuement(imbuementId);
+ const auto &baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID());
+ const auto &categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory());
msg.add(imbuementId);
msg.addString(baseImbuement->name + " " + imbuement->getName(), "ProtocolGame::addImbuementInfo - baseImbuement->name + "
@@ -7628,11 +7628,11 @@ void ProtocolGame::openImbuementWindow(std::shared_ptr
- item) {
msg.add(g_imbuements().getBaseByID(imbuementInfo.imbuement->getBaseID())->removeCost);
}
- std::vector imbuements = g_imbuements().getImbuements(player, item);
+ std::vector> imbuements = g_imbuements().getImbuements(player, item);
phmap::flat_hash_map needItems;
msg.add(imbuements.size());
- for (const Imbuement* imbuement : imbuements) {
+ for (const auto &imbuement : imbuements) {
addImbuementInfo(msg, imbuement->getID());
const auto items = imbuement->getItems();
@@ -8116,7 +8116,7 @@ void ProtocolGame::sendInventoryImbuements(const std::mapgetBaseID());
+ const auto &baseImbuement = g_imbuements().getBaseByID(imbuement->getBaseID());
msg.addByte(0x01);
msg.addString(baseImbuement->name + " " + imbuement->getName(), "ProtocolGame::sendInventoryImbuements - baseImbuement->name + "
" + imbuement->getName()");
@@ -8129,7 +8129,7 @@ void ProtocolGame::sendInventoryImbuements(const std::maphasCondition(CONDITION_INFIGHT);
// Get the category of the imbuement
- const CategoryImbuement* categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory());
+ const auto &categoryImbuement = g_imbuements().getCategoryByID(imbuement->getCategory());
// Parent of the imbued item
auto parent = item->getParent();
// If the imbuement is aggressive and the player is not in fight mode or is in a protection zone, or the item is in a container, ignore it.
diff --git a/src/utils/tools.cpp b/src/utils/tools.cpp
index 0d8b39a485d..c81bad7003c 100644
--- a/src/utils/tools.cpp
+++ b/src/utils/tools.cpp
@@ -869,7 +869,8 @@ const ImbuementTypeNames imbuementTypeNames = {
{ "skillboost shielding", IMBUEMENT_SKILLBOOST_SHIELDING },
{ "skillboost distance", IMBUEMENT_SKILLBOOST_DISTANCE },
{ "skillboost magic level", IMBUEMENT_SKILLBOOST_MAGIC_LEVEL },
- { "increase capacity", IMBUEMENT_INCREASE_CAPACITY }
+ { "increase capacity", IMBUEMENT_INCREASE_CAPACITY },
+ { "vibrancy", IMBUEMENT_VIBRANCY_PARALYZE }
};
/**