diff options
3 files changed, 34 insertions, 27 deletions
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp index f26522b8ed6..a103b34ff56 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.cpp +++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp @@ -769,18 +769,30 @@ Unit* PlayerAI::SelectAttackTarget() const return me->GetCharmer() ? me->GetCharmer()->GetVictim() : nullptr; } -struct UncontrolledTargetSelectPredicate +struct ValidTargetSelectPredicate { + ValidTargetSelectPredicate(UnitAI const* ai) : _ai(ai) { } + UnitAI const* const _ai; bool operator()(Unit const* target) const { - return !target->HasBreakableByDamageCrowdControlAura(); + return _ai->CanAIAttack(target); } }; +bool SimpleCharmedPlayerAI::CanAIAttack(Unit const* who) const +{ + if (!me->IsValidAttackTarget(who) || who->HasBreakableByDamageCrowdControlAura()) + return false; + if (Unit* charmer = me->GetCharmer()) + if (!charmer->IsValidAttackTarget(who)) + return false; + return UnitAI::CanAIAttack(who); +} + Unit* SimpleCharmedPlayerAI::SelectAttackTarget() const { if (Unit* charmer = me->GetCharmer()) - return charmer->IsAIEnabled ? charmer->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, UncontrolledTargetSelectPredicate()) : charmer->GetVictim(); + return charmer->IsAIEnabled ? charmer->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, ValidTargetSelectPredicate(this)) : charmer->GetVictim(); return nullptr; } @@ -1316,11 +1328,23 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff) if (charmer->IsEngaged()) { Unit* target = me->GetVictim(); - if (!target || !charmer->IsValidAttackTarget(target) || !me->IsValidAttackTarget(target) || target->HasBreakableByDamageCrowdControlAura()) + if (!target || !CanAIAttack(target)) { target = SelectAttackTarget(); - if (!target) + if (!target || !CanAIAttack(target)) + { + if (!_isFollowing) + { + _isFollowing = true; + me->AttackStop(); + me->CastStop(); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + } return; + } + _isFollowing = false; if (IsRangedAttacker()) { @@ -1373,8 +1397,9 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff) DoAutoAttackIfReady(); } - else + else if (!_isFollowing) { + _isFollowing = true; me->AttackStop(); me->CastStop(); me->StopMoving(); diff --git a/src/server/game/AI/PlayerAI/PlayerAI.h b/src/server/game/AI/PlayerAI/PlayerAI.h index 8afc5ab3ce9..faff09b6b6e 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.h +++ b/src/server/game/AI/PlayerAI/PlayerAI.h @@ -97,11 +97,12 @@ class TC_GAME_API PlayerAI : public UnitAI class TC_GAME_API SimpleCharmedPlayerAI : public PlayerAI { public: - SimpleCharmedPlayerAI(Player* player) : PlayerAI(player), _castCheckTimer(500), _chaseCloser(false), _forceFacing(true) { } + SimpleCharmedPlayerAI(Player* player) : PlayerAI(player), _castCheckTimer(2500), _chaseCloser(false), _forceFacing(true), _isFollowing(false) { } void UpdateAI(uint32 diff) override; void OnCharmed(bool apply) override; protected: + bool CanAIAttack(Unit const* who) const override; Unit* SelectAttackTarget() const override; private: @@ -109,6 +110,7 @@ class TC_GAME_API SimpleCharmedPlayerAI : public PlayerAI uint32 _castCheckTimer; bool _chaseCloser; bool _forceFacing; + bool _isFollowing; }; #endif diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp index 7f9111cfffb..62a81af385c 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp @@ -57,26 +57,6 @@ enum Events class BlackheartCharmedPlayerAI : public SimpleCharmedPlayerAI { using SimpleCharmedPlayerAI::SimpleCharmedPlayerAI; - Unit* SelectAttackTarget() const override - { - if (Unit* charmer = me->GetCharmer()) - { - std::list<Player*> targets; - for (ThreatReference const* ref : charmer->GetThreatManager().GetUnsortedThreatList()) - { - if (Player* victim = ref->GetVictim()->ToPlayer()) - if (me->IsValidAttackTarget(victim)) - targets.push_back(victim); - } - if (targets.empty()) - return nullptr; - - auto it = targets.begin(); - std::advance(it, urand(0, targets.size() - 1)); - return *it; - } - return nullptr; - } void OnCharmed(bool apply) override { SimpleCharmedPlayerAI::OnCharmed(apply); |