mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-21 09:44:45 +01:00
Core/AI: streamline FollowerAI::AssistPlayerInCombatAgainst with SmartAI and EscortAI
plus couple method reorganizations
(cherry picked from commit 0e22d61d4a)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user