Core/PlayerAI: Some adjustments:

- Add a 2 second delay before the AI begins using spells. This should provide opportunity for counterplay before that rogue activates cloak and goes on an unstoppable rampage among your healers. (Sorry, guys.)
- Stopped the AI from attacking invalid targets under some conditions. It should now properly leash back and follow the charmer if we try to select an invalid target.
- Stopped the AI from constantly re-creating the follow movement generator (and thus spamming movesplines).
This commit is contained in:
Treeston
2017-07-21 22:59:59 +02:00
parent 1f63554312
commit 331e463de8
3 changed files with 34 additions and 27 deletions

View File

@@ -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();

View File

@@ -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

View File

@@ -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);