Core/AI: streamline FollowerAI::AssistPlayerInCombatAgainst with SmartAI and EscortAI

plus couple method reorganizations

(cherry picked from commit 0e22d61d4a)
This commit is contained in:
ccrs
2019-05-15 21:59:10 +02:00
committed by Shauren
parent 844f969ed7
commit edbf45404b

View File

@@ -33,6 +33,23 @@ enum Points
FollowerAI::FollowerAI(Creature* creature) : ScriptedAI(creature), _updateFollowTimer(2500), _followState(STATE_FOLLOW_NONE), _questForFollow(nullptr) { }
void FollowerAI::MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE || !HasFollowState(STATE_FOLLOW_INPROGRESS))
return;
if (id == POINT_COMBAT_START)
{
if (GetLeaderForFollower())
{
if (!HasFollowState(STATE_FOLLOW_PAUSED))
AddFollowState(STATE_FOLLOW_RETURNING);
}
else
me->DespawnOrUnsummon();
}
}
void FollowerAI::AttackStart(Unit* who)
{
if (!who)
@@ -50,36 +67,6 @@ void FollowerAI::AttackStart(Unit* who)
}
}
// This part provides assistance to a player that are attacked by who, even if out of normal aggro range
// It will cause me to attack who that are attacking _any_ player (which has been confirmed may happen also on offi)
// The flag (type_flag) is unconfirmed, but used here for further research and is a good candidate.
bool FollowerAI::AssistPlayerInCombatAgainst(Unit* who)
{
if (!who || !who->GetVictim())
return false;
// experimental (unknown) flag not present
if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))
return false;
// not a player
if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
return false;
// never attack friendly
if (me->IsFriendlyTo(who))
return false;
// too far away and no free sight?
if (me->IsWithinDistInMap(who, MAX_PLAYER_DISTANCE) && me->IsWithinLOSInMap(who))
{
me->EngageWithTarget(who);
return true;
}
return false;
}
void FollowerAI::MoveInLineOfSight(Unit* who)
{
if (me->HasReactState(REACT_AGGRESSIVE) && !me->HasUnitState(UNIT_STATE_STUNNED) && who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me))
@@ -238,23 +225,6 @@ void FollowerAI::UpdateFollowerAI(uint32 /*uiDiff*/)
DoMeleeAttackIfReady();
}
void FollowerAI::MovementInform(uint32 type, uint32 id)
{
if (type != POINT_MOTION_TYPE || !HasFollowState(STATE_FOLLOW_INPROGRESS))
return;
if (id == POINT_COMBAT_START)
{
if (GetLeaderForFollower())
{
if (!HasFollowState(STATE_FOLLOW_PAUSED))
AddFollowState(STATE_FOLLOW_RETURNING);
}
else
me->DespawnOrUnsummon();
}
}
void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, Quest const* quest)
{
if (me->IsEngaged())
@@ -293,34 +263,6 @@ void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, Quest co
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::StartFollow: start follow %s - %s (%s)", player->GetName().c_str(), _leaderGUID.ToString().c_str(), me->GetGUID().ToString().c_str());
}
Player* FollowerAI::GetLeaderForFollower()
{
if (Player* player = ObjectAccessor::GetPlayer(*me, _leaderGUID))
{
if (player->IsAlive())
return player;
else
{
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
{
Player* member = groupRef->GetSource();
if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE) && member->IsAlive())
{
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::GetLeaderForFollower: GetLeader changed and returned new leader. (%s)", me->GetGUID().ToString().c_str());
_leaderGUID = member->GetGUID();
return member;
}
}
}
}
}
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::GetLeaderForFollower: GetLeader can not find suitable leader. (%s)", me->GetGUID().ToString().c_str());
return nullptr;
}
void FollowerAI::SetFollowComplete(bool withEndEvent)
{
if (me->HasUnitState(UNIT_STATE_FOLLOW))
@@ -369,3 +311,78 @@ void FollowerAI::SetFollowPaused(bool paused)
me->GetMotionMaster()->MoveFollow(leader, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
}
Player* FollowerAI::GetLeaderForFollower()
{
if (Player* player = ObjectAccessor::GetPlayer(*me, _leaderGUID))
{
if (player->IsAlive())
return player;
else
{
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
{
Player* member = groupRef->GetSource();
if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE) && member->IsAlive())
{
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::GetLeaderForFollower: GetLeader changed and returned new leader. (%s)", me->GetGUID().ToString().c_str());
_leaderGUID = member->GetGUID();
return member;
}
}
}
}
}
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::GetLeaderForFollower: GetLeader can not find suitable leader. (%s)", me->GetGUID().ToString().c_str());
return nullptr;
}
// This part provides assistance to a player that are attacked by who, even if out of normal aggro range
// It will cause me to attack who that are attacking _any_ player (which has been confirmed may happen also on offi)
// The flag (type_flag) is unconfirmed, but used here for further research and is a good candidate.
bool FollowerAI::AssistPlayerInCombatAgainst(Unit* who)
{
if (!who || !who->GetVictim())
return false;
if (me->HasReactState(REACT_PASSIVE))
return false;
// experimental (unknown) flag not present
if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))
return false;
// not a player
if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
return false;
if (!who->isInAccessiblePlaceFor(me))
return false;
if (!CanAIAttack(who))
return false;
// we cannot attack in evade mode
if (me->IsInEvadeMode())
return false;
// or if enemy is in evade mode
if (who->GetTypeId() == TYPEID_UNIT && who->ToCreature()->IsInEvadeMode())
return false;
// never attack friendly
if (me->IsFriendlyTo(who))
return false;
// too far away and no free sight
if (me->IsWithinDistInMap(who, MAX_PLAYER_DISTANCE) && me->IsWithinLOSInMap(who))
{
me->EngageWithTarget(who);
return true;
}
return false;
}