diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp index 2224505..e858488 100644 --- a/src/creatures/combat/combat.cpp +++ b/src/creatures/combat/combat.cpp @@ -769,6 +769,18 @@ bool Combat::checkFearConditionAffected(const std::shared_ptr &player) { return true; } +bool Combat::checkRootConditionAffected(const std::shared_ptr &player) { + if (player->isImmuneRoot()) { + return false; + } + + if (player->hasCondition(CONDITION_ROOTED)) { + return false; + } + + return true; +} + void Combat::CombatConditionFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data) { if (params.origin == ORIGIN_MELEE && data && data->primary.value == 0 && data->secondary.value == 0) { return; @@ -805,6 +817,11 @@ void Combat::CombatConditionFunc(const std::shared_ptr &caster, const if (condition->getType() == CONDITION_FEARED && !checkFearConditionAffected(player)) { return; } + + if (condition->getType() == CONDITION_ROOTED && !checkRootConditionAffected(player)) { + return; + } + } if (caster == target || (target && !target->isImmune(condition->getType()))) { diff --git a/src/creatures/combat/combat.hpp b/src/creatures/combat/combat.hpp index 105445d..868ce88 100644 --- a/src/creatures/combat/combat.hpp +++ b/src/creatures/combat/combat.hpp @@ -284,6 +284,7 @@ class Combat { * @return true if the fear condition can be applied, false otherwise. */ static bool checkFearConditionAffected(const std::shared_ptr &player); + static bool checkRootConditionAffected(const std::shared_ptr &player); static void CombatConditionFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data); static void CombatDispelFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data); static void CombatNullFunc(const std::shared_ptr &caster, const std::shared_ptr &target, const CombatParams ¶ms, CombatDamage* data); diff --git a/src/creatures/combat/condition.cpp b/src/creatures/combat/condition.cpp index 7af76fd..cda1234 100644 --- a/src/creatures/combat/condition.cpp +++ b/src/creatures/combat/condition.cpp @@ -260,6 +260,8 @@ std::shared_ptr Condition::createCondition(ConditionId_t id, Conditio return std::make_shared(id, type, ticks, buff, subId); case CONDITION_ROOTED: + return std::make_shared(id, type, ticks, buff, subId); + case CONDITION_INFIGHT: case CONDITION_DRUNK: case CONDITION_EXHAUST: @@ -2230,6 +2232,54 @@ std::shared_ptr ConditionFeared::clone() const { return std::make_shared(*this); } +/** + * Condition Root + */ + +ConditionRooted::ConditionRooted(ConditionId_t intiId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId) : + Condition(intiId, initType, initTicks, initBuff, initSubId) { } + +bool ConditionRooted::startCondition(std::shared_ptr creature) { + g_logger().debug("[ConditionRooted::executeCondition] Condition started for {}", creature->getName()); + return Condition::startCondition(creature); +} + +bool ConditionRooted::executeCondition(const std::shared_ptr &creature, int32_t interval) { + Position currentPos = creature->getPosition(); + + g_logger().debug("[ConditionRooted::executeCondition] Executing condition, current position is {}", currentPos.toString()); + + return Condition::executeCondition(creature, interval); +} + +void ConditionRooted::addCondition(std::shared_ptr, const std::shared_ptr addCondition) { + if (updateCondition(addCondition)) { + setTicks(addCondition->getTicks()); + } +} + +void ConditionRooted::endCondition(std::shared_ptr creature) { + creature->stopEventWalk(); + /* + * After a player is feared there's a 30 seconds before they can can feared again. + */ + const auto &player = creature->getPlayer(); + if (player) { + player->setImmuneRoot(); + } +} + +std::unordered_set ConditionRooted::getIcons() const { + auto icons = Condition::getIcons(); + + icons.insert(PlayerIcon::Rooted); + return icons; +} + +std::shared_ptr ConditionRooted::clone() const { + return std::make_shared(*this); +} + /** * ConditionSpeed */ diff --git a/src/creatures/combat/condition.hpp b/src/creatures/combat/condition.hpp index 7d4a835..939e50c 100644 --- a/src/creatures/combat/condition.hpp +++ b/src/creatures/combat/condition.hpp @@ -326,6 +326,20 @@ class ConditionFeared final : public Condition { uint8_t fleeIndx = 99; }; +class ConditionRooted final : public Condition { +public: + ConditionRooted() = default; + ConditionRooted(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId); + + bool startCondition(std::shared_ptr creature) override; + bool executeCondition(const std::shared_ptr &creature, int32_t interval) override; + void endCondition(std::shared_ptr creature) override; + void addCondition(std::shared_ptr creature, std::shared_ptr condition) override; + std::unordered_set getIcons() const override; + + std::shared_ptr clone() const override; +}; + class ConditionSpeed final : public Condition { public: ConditionSpeed(ConditionId_t initId, ConditionType_t initType, int32_t initTicks, bool initBuff, uint32_t initSubId, int32_t initChangeSpeed); diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index dd54dd9..f3aaaa6 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -1580,6 +1580,16 @@ bool Player::isImmuneFear() const { return (m_fearCondition.first == CONDITION_FEARED) && (timenow <= m_fearCondition.second); } +void Player::setImmuneRoot() { + m_rootCondition.first = CONDITION_ROOTED; + m_rootCondition.second = OTSYS_TIME() + 30000; +} + +bool Player::isImmuneRoot() const { + const uint64_t timenow = OTSYS_TIME(); + return (m_rootCondition.first == CONDITION_ROOTED) && (timenow <= m_rootCondition.second); +} + uint16_t Player::parseRacebyCharm(charmRune_t charmId, bool set, uint16_t newRaceid) { uint16_t raceid = 0; switch (charmId) { diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 7c45903..2b081e0 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -1040,6 +1040,8 @@ class Player final : public Creature, public Cylinder, public Bankable { bool isImmuneCleanse(ConditionType_t conditiontype) const; void setImmuneFear(); bool isImmuneFear() const; + void setImmuneRoot(); + bool isImmuneRoot() const; uint16_t parseRacebyCharm(charmRune_t charmId, bool set, uint16_t newRaceid); uint64_t getItemCustomPrice(uint16_t itemId, bool buyPrice = false) const; @@ -1532,6 +1534,7 @@ class Player final : public Creature, public Cylinder, public Bankable { std::pair cleanseCondition = { CONDITION_NONE, 0 }; std::pair m_fearCondition = { CONDITION_NONE, 0 }; + std::pair m_rootCondition = { CONDITION_NONE, 0 }; uint8_t soul = 0; uint8_t levelPercent = 0;