Core/AI: streamline FollowerAI::AssistPlayerInCombatAgainst with SmartAI and EscortAI
Port From (https://github.com/TrinityCore/TrinityCore/commit/edbf45404be2cf003ceec7b4344180616b0e2315)
This commit is contained in:
@@ -48,6 +48,23 @@ namespace Game.AI
|
|||||||
_questForFollow = null;
|
_questForFollow = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void MovementInform(MovementGeneratorType motionType, uint pointId)
|
||||||
|
{
|
||||||
|
if (motionType != MovementGeneratorType.Point || !HasFollowState(FollowState.Inprogress))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pointId == 0xFFFFFF)
|
||||||
|
{
|
||||||
|
if (GetLeaderForFollower())
|
||||||
|
{
|
||||||
|
if (!HasFollowState(FollowState.Paused))
|
||||||
|
AddFollowState(FollowState.Returning);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
me.DespawnOrUnsummon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void AttackStart(Unit who)
|
public override void AttackStart(Unit who)
|
||||||
{
|
{
|
||||||
if (!who)
|
if (!who)
|
||||||
@@ -65,36 +82,6 @@ namespace Game.AI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//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 AssistPlayerInCombatAgainst(Unit who)
|
|
||||||
{
|
|
||||||
if (!who || !who.GetVictim())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//experimental (unknown) flag not present
|
|
||||||
if (!me.GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.CanAssist))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//not a player
|
|
||||||
if (!who.GetVictim().GetCharmerOrOwnerPlayerOrPlayerItself())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//never attack friendly
|
|
||||||
if (me.IsFriendlyTo(who))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//too far away and no free sight?
|
|
||||||
if (me.IsWithinDistInMap(who, 100.0f) && me.IsWithinLOSInMap(who))
|
|
||||||
{
|
|
||||||
me.EngageWithTarget(who);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void MoveInLineOfSight(Unit who)
|
public override void MoveInLineOfSight(Unit who)
|
||||||
{
|
{
|
||||||
if (me.HasReactState(ReactStates.Aggressive) && !me.HasUnitState(UnitState.Stunned) && who.IsTargetableForAttack() && who.IsInAccessiblePlaceFor(me))
|
if (me.HasReactState(ReactStates.Aggressive) && !me.HasUnitState(UnitState.Stunned) && who.IsTargetableForAttack() && who.IsInAccessiblePlaceFor(me))
|
||||||
@@ -264,23 +251,6 @@ namespace Game.AI
|
|||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MovementInform(MovementGeneratorType motionType, uint pointId)
|
|
||||||
{
|
|
||||||
if (motionType != MovementGeneratorType.Point || !HasFollowState(FollowState.Inprogress))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (pointId == 0xFFFFFF)
|
|
||||||
{
|
|
||||||
if (GetLeaderForFollower())
|
|
||||||
{
|
|
||||||
if (!HasFollowState(FollowState.Paused))
|
|
||||||
AddFollowState(FollowState.Returning);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
me.DespawnOrUnsummon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StartFollow(Player player, uint factionForFollower = 0, Quest quest = null)
|
public void StartFollow(Player player, uint factionForFollower = 0, Quest quest = null)
|
||||||
{
|
{
|
||||||
if (me.GetVictim())
|
if (me.GetVictim())
|
||||||
@@ -320,34 +290,26 @@ namespace Game.AI
|
|||||||
Log.outDebug(LogFilter.Scripts, "FollowerAI start follow {0} ({1})", player.GetName(), _leaderGUID.ToString());
|
Log.outDebug(LogFilter.Scripts, "FollowerAI start follow {0} ({1})", player.GetName(), _leaderGUID.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
Player GetLeaderForFollower()
|
void SetFollowPaused(bool paused)
|
||||||
{
|
{
|
||||||
Player player = Global.ObjAccessor.GetPlayer(me, _leaderGUID);
|
if (!HasFollowState(FollowState.Inprogress) || HasFollowState(FollowState.Complete))
|
||||||
if (player)
|
return;
|
||||||
{
|
|
||||||
if (player.IsAlive())
|
|
||||||
return player;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Group group = player.GetGroup();
|
|
||||||
if (group)
|
|
||||||
{
|
|
||||||
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next())
|
|
||||||
{
|
|
||||||
Player member = groupRef.GetSource();
|
|
||||||
if (member && me.IsWithinDistInMap(member, 100.0f) && member.IsAlive())
|
|
||||||
{
|
|
||||||
Log.outDebug(LogFilter.Scripts, "FollowerAI GetLeader changed and returned new leader.");
|
|
||||||
_leaderGUID = member.GetGUID();
|
|
||||||
return member;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.outDebug(LogFilter.Scripts, "FollowerAI GetLeader can not find suitable leader.");
|
if (paused)
|
||||||
return null;
|
{
|
||||||
|
AddFollowState(FollowState.Paused);
|
||||||
|
|
||||||
|
if (me.HasUnitState(UnitState.Follow))
|
||||||
|
me.GetMotionMaster().Remove(MovementGeneratorType.Follow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RemoveFollowState(FollowState.Paused);
|
||||||
|
|
||||||
|
Player leader = GetLeaderForFollower();
|
||||||
|
if (leader != null)
|
||||||
|
me.GetMotionMaster().MoveFollow(leader, SharedConst.PetFollowDist, SharedConst.PetFollowAngle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFollowComplete(bool bWithEndEvent = false)
|
public void SetFollowComplete(bool bWithEndEvent = false)
|
||||||
@@ -372,6 +334,83 @@ namespace Game.AI
|
|||||||
AddFollowState(FollowState.Complete);
|
AddFollowState(FollowState.Complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Player GetLeaderForFollower()
|
||||||
|
{
|
||||||
|
Player player = Global.ObjAccessor.GetPlayer(me, _leaderGUID);
|
||||||
|
if (player)
|
||||||
|
{
|
||||||
|
if (player.IsAlive())
|
||||||
|
return player;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Group group = player.GetGroup();
|
||||||
|
if (group)
|
||||||
|
{
|
||||||
|
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next())
|
||||||
|
{
|
||||||
|
Player member = groupRef.GetSource();
|
||||||
|
if (member && me.IsWithinDistInMap(member, 100.0f) && member.IsAlive())
|
||||||
|
{
|
||||||
|
Log.outDebug(LogFilter.Scripts, "FollowerAI GetLeader changed and returned new leader.");
|
||||||
|
_leaderGUID = member.GetGUID();
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.outDebug(LogFilter.Scripts, "FollowerAI GetLeader can not find suitable leader.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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 AssistPlayerInCombatAgainst(Unit who)
|
||||||
|
{
|
||||||
|
if (!who || !who.GetVictim())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (me.HasReactState(ReactStates.Passive))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//experimental (unknown) flag not present
|
||||||
|
if (!me.GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.CanAssist))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//not a player
|
||||||
|
if (!who.GetVictim().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, 100.0f) && me.IsWithinLOSInMap(who))
|
||||||
|
{
|
||||||
|
me.EngageWithTarget(who);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool HasFollowState(FollowState uiFollowState) { return (_followState & uiFollowState) != 0; }
|
bool HasFollowState(FollowState uiFollowState) { return (_followState & uiFollowState) != 0; }
|
||||||
|
|
||||||
void AddFollowState(FollowState uiFollowState) { _followState |= uiFollowState; }
|
void AddFollowState(FollowState uiFollowState) { _followState |= uiFollowState; }
|
||||||
|
|||||||
Reference in New Issue
Block a user