Core/AI: logs, codestyle & cosmetics standarization

This commit is contained in:
ccrs
2019-05-15 19:23:28 +02:00
parent 0eb5d240fa
commit fdb71ce19e
27 changed files with 301 additions and 316 deletions

View File

@@ -118,9 +118,11 @@ void CasterAI::InitializeAI()
CombatAI::InitializeAI();
_attackDistance = 30.0f;
for (SpellVector::iterator itr = Spells.begin(); itr != Spells.end(); ++itr)
if (AISpellInfo[*itr].condition == AICOND_COMBAT && _attackDistance > GetAISpellInfo(*itr)->maxRange)
_attackDistance = GetAISpellInfo(*itr)->maxRange;
if (_attackDistance == 30.0f)
_attackDistance = MELEE_RANGE;
}
@@ -177,18 +179,18 @@ void CasterAI::UpdateAI(uint32 diff)
// ArcherAI
//////////////
ArcherAI::ArcherAI(Creature* c) : CreatureAI(c)
ArcherAI::ArcherAI(Creature* creature) : CreatureAI(creature)
{
if (!me->m_spells[0])
TC_LOG_ERROR("misc", "ArcherAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry());
if (!creature->m_spells[0])
TC_LOG_ERROR("scripts.ai", "ArcherAI set for creature with spell1 = 0. AI will do nothing (%s)", creature->GetGUID().ToString().c_str());
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->m_spells[0]);
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(creature->m_spells[0]);
_minimumRange = spellInfo ? spellInfo->GetMinRange(false) : 0;
if (!_minimumRange)
_minimumRange = MELEE_RANGE;
me->m_CombatDistance = spellInfo ? spellInfo->GetMaxRange(false) : 0;
me->m_SightDistance = me->m_CombatDistance;
creature->m_CombatDistance = spellInfo ? spellInfo->GetMaxRange(false) : 0;
creature->m_SightDistance = creature->m_CombatDistance;
}
void ArcherAI::AttackStart(Unit* who)
@@ -226,22 +228,21 @@ void ArcherAI::UpdateAI(uint32 /*diff*/)
// TurretAI
//////////////
TurretAI::TurretAI(Creature* c) : CreatureAI(c)
TurretAI::TurretAI(Creature* creature) : CreatureAI(creature)
{
if (!me->m_spells[0])
TC_LOG_ERROR("misc", "TurretAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry());
if (!creature->m_spells[0])
TC_LOG_ERROR("scripts.ai", "TurretAI set for creature with spell1 = 0. AI will do nothing (%s)", creature->GetGUID().ToString().c_str());
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->m_spells[0]);
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(creature->m_spells[0]);
_minimumRange = spellInfo ? spellInfo->GetMinRange(false) : 0;
me->m_CombatDistance = spellInfo ? spellInfo->GetMaxRange(false) : 0;
me->m_SightDistance = me->m_CombatDistance;
creature->m_CombatDistance = spellInfo ? spellInfo->GetMaxRange(false) : 0;
creature->m_SightDistance = creature->m_CombatDistance;
}
bool TurretAI::CanAIAttack(Unit const* who) const
{
/// @todo use one function to replace it
if (!me->IsWithinCombatRange(who, me->m_CombatDistance)
|| (_minimumRange && me->IsWithinCombatRange(who, _minimumRange)))
if (!me->IsWithinCombatRange(who, me->m_CombatDistance) || (_minimumRange && me->IsWithinCombatRange(who, _minimumRange)))
return false;
return true;
}

View File

@@ -26,7 +26,7 @@ class Creature;
class TC_GAME_API AggressorAI : public CreatureAI
{
public:
explicit AggressorAI(Creature* c) : CreatureAI(c) { }
explicit AggressorAI(Creature* creature) : CreatureAI(creature) { }
void UpdateAI(uint32) override;
static int32 Permissible(Creature const* creature);
@@ -37,7 +37,7 @@ typedef std::vector<uint32> SpellVector;
class TC_GAME_API CombatAI : public CreatureAI
{
public:
explicit CombatAI(Creature* c) : CreatureAI(c) { }
explicit CombatAI(Creature* creature) : CreatureAI(creature) { }
void InitializeAI() override;
void Reset() override;
@@ -56,7 +56,7 @@ class TC_GAME_API CombatAI : public CreatureAI
class TC_GAME_API CasterAI : public CombatAI
{
public:
explicit CasterAI(Creature* c) : CombatAI(c) { _attackDistance = MELEE_RANGE; }
explicit CasterAI(Creature* creature) : CombatAI(creature) { _attackDistance = MELEE_RANGE; }
void InitializeAI() override;
void AttackStart(Unit* victim) override { AttackStartCaster(victim, _attackDistance); }
void UpdateAI(uint32 diff) override;
@@ -68,7 +68,7 @@ class TC_GAME_API CasterAI : public CombatAI
struct TC_GAME_API ArcherAI : public CreatureAI
{
public:
explicit ArcherAI(Creature* c);
explicit ArcherAI(Creature* creature);
void AttackStart(Unit* who) override;
void UpdateAI(uint32 diff) override;
@@ -81,7 +81,7 @@ struct TC_GAME_API ArcherAI : public CreatureAI
struct TC_GAME_API TurretAI : public CreatureAI
{
public:
explicit TurretAI(Creature* c);
explicit TurretAI(Creature* creature);
bool CanAIAttack(Unit const* who) const override;
void AttackStart(Unit* who) override;
void UpdateAI(uint32 diff) override;

View File

@@ -24,7 +24,7 @@ int32 GameObjectAI::Permissible(GameObject const* /*go*/)
return PERMIT_BASE_NO;
}
NullGameObjectAI::NullGameObjectAI(GameObject* g) : GameObjectAI(g) { }
NullGameObjectAI::NullGameObjectAI(GameObject* go) : GameObjectAI(go) { }
int32 NullGameObjectAI::Permissible(GameObject const* /*go*/)
{

View File

@@ -33,8 +33,9 @@ class TC_GAME_API GameObjectAI
{
protected:
GameObject* const me;
public:
explicit GameObjectAI(GameObject* g) : me(g) { }
explicit GameObjectAI(GameObject* go) : me(go) { }
virtual ~GameObjectAI() { }
virtual void UpdateAI(uint32 /*diff*/) { }
@@ -97,7 +98,7 @@ class TC_GAME_API GameObjectAI
class TC_GAME_API NullGameObjectAI : public GameObjectAI
{
public:
explicit NullGameObjectAI(GameObject* g);
explicit NullGameObjectAI(GameObject* go);
void UpdateAI(uint32 /*diff*/) override { }

View File

@@ -61,7 +61,7 @@ void GuardAI::EnterEvadeMode(EvadeReason /*why*/)
return;
}
TC_LOG_DEBUG("entities.unit", "Guard entry: %u enters evade mode.", me->GetEntry());
TC_LOG_TRACE("scritps.ai", "GuardAI::EnterEvadeMode: %s enters evade mode.", me->GetGUID().ToString().c_str());
me->RemoveAllAuras();
me->GetThreatManager().ClearAllThreat();

View File

@@ -19,9 +19,20 @@
#include "PassiveAI.h"
#include "Creature.h"
PassiveAI::PassiveAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
PossessedAI::PossessedAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
PassiveAI::PassiveAI(Creature* creature) : CreatureAI(creature)
{
creature->SetReactState(REACT_PASSIVE);
}
PossessedAI::PossessedAI(Creature* creature) : CreatureAI(creature)
{
creature->SetReactState(REACT_PASSIVE);
}
NullCreatureAI::NullCreatureAI(Creature* creature) : CreatureAI(creature)
{
creature->SetReactState(REACT_PASSIVE);
}
int32 NullCreatureAI::Permissible(Creature const* creature)
{

View File

@@ -24,7 +24,7 @@
class TC_GAME_API PassiveAI : public CreatureAI
{
public:
explicit PassiveAI(Creature* c);
explicit PassiveAI(Creature* creature);
void MoveInLineOfSight(Unit*) override { }
void AttackStart(Unit*) override { }
@@ -36,7 +36,7 @@ class TC_GAME_API PassiveAI : public CreatureAI
class TC_GAME_API PossessedAI : public CreatureAI
{
public:
explicit PossessedAI(Creature* c);
explicit PossessedAI(Creature* creature);
void MoveInLineOfSight(Unit*) override { }
void AttackStart(Unit* target) override;
@@ -52,7 +52,7 @@ class TC_GAME_API PossessedAI : public CreatureAI
class TC_GAME_API NullCreatureAI : public CreatureAI
{
public:
explicit NullCreatureAI(Creature* c);
explicit NullCreatureAI(Creature* creature);
void MoveInLineOfSight(Unit*) override { }
void AttackStart(Unit*) override { }
@@ -66,7 +66,7 @@ class TC_GAME_API NullCreatureAI : public CreatureAI
class TC_GAME_API CritterAI : public PassiveAI
{
public:
explicit CritterAI(Creature* c) : PassiveAI(c) { }
explicit CritterAI(Creature* creature) : PassiveAI(creature) { }
void DamageTaken(Unit* done_by, uint32& /*damage*/) override;
void EnterEvadeMode(EvadeReason why) override;
@@ -77,7 +77,7 @@ class TC_GAME_API CritterAI : public PassiveAI
class TC_GAME_API TriggerAI : public NullCreatureAI
{
public:
explicit TriggerAI(Creature* c) : NullCreatureAI(c) { }
explicit TriggerAI(Creature* creature) : NullCreatureAI(creature) { }
void IsSummonedBy(Unit* summoner) override;
static int32 Permissible(Creature const* creature);

View File

@@ -44,7 +44,7 @@ int32 PetAI::Permissible(Creature const* creature)
return PERMIT_BASE_NO;
}
PetAI::PetAI(Creature* c) : CreatureAI(c), _tracker(TIME_INTERVAL_LOOK)
PetAI::PetAI(Creature* creature) : CreatureAI(creature), _tracker(TIME_INTERVAL_LOOK)
{
if (!me->GetCharmInfo())
throw InvalidAIException("Creature doesn't have a valid charm info");
@@ -107,7 +107,7 @@ void PetAI::UpdateAI(uint32 diff)
if (NeedToStop())
{
TC_LOG_DEBUG("misc", "Pet AI stopped attacking [guid=%u]", me->GetGUID().GetCounter());
TC_LOG_TRACE("scripts.ai.petai", "PetAI::UpdateAI: AI stopped attacking %s", me->GetGUID().ToString().c_str());
StopAttack();
return;
}
@@ -262,7 +262,7 @@ void PetAI::UpdateAI(uint32 diff)
void PetAI::UpdateAllies()
{
_updateAlliesTimer = 10 * IN_MILLISECONDS; // update friendly targets every 10 seconds, lesser checks increase performance
_updateAlliesTimer = 10 * IN_MILLISECONDS; // update friendly targets every 10 seconds, lesser checks increase performance
Unit* owner = me->GetCharmerOrOwner();
if (!owner)
@@ -272,17 +272,17 @@ void PetAI::UpdateAllies()
if (Player* player = owner->ToPlayer())
group = player->GetGroup();
//only pet and owner/not in group->ok
// only pet and owner/not in group->ok
if (_allySet.size() == 2 && !group)
return;
//owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
// owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
if (group && !group->isRaidGroup() && _allySet.size() == (group->GetMembersCount() + 2))
return;
_allySet.clear();
_allySet.insert(me->GetGUID());
if (group) //add group
if (group) // add group
{
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
@@ -296,7 +296,7 @@ void PetAI::UpdateAllies()
_allySet.insert(Target->GetGUID());
}
}
else //remove group
else // remove group
_allySet.insert(owner->GetGUID());
}
@@ -588,34 +588,33 @@ bool PetAI::CanAttack(Unit* target)
void PetAI::ReceiveEmote(Player* player, uint32 emote)
{
if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
switch (emote)
{
case TEXT_EMOTE_COWER:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
break;
case TEXT_EMOTE_ANGRY:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
break;
case TEXT_EMOTE_GLARE:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(EMOTE_STATE_STUN);
break;
case TEXT_EMOTE_SOOTHE:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(EMOTE_ONESHOT_OMNICAST_GHOUL);
break;
}
if (me->GetOwnerGUID() != player->GetGUID())
return;
switch (emote)
{
case TEXT_EMOTE_COWER:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
break;
case TEXT_EMOTE_ANGRY:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
break;
case TEXT_EMOTE_GLARE:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(EMOTE_STATE_STUN);
break;
case TEXT_EMOTE_SOOTHE:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(EMOTE_ONESHOT_OMNICAST_GHOUL);
break;
}
}
void PetAI::ClearCharmInfoFlags()
{
// Quick access to set all flags to FALSE
CharmInfo* ci = me->GetCharmInfo();
if (ci)
{
ci->SetIsAtStay(false);

View File

@@ -30,15 +30,16 @@ typedef std::vector<std::pair<Unit*, Spell*>> TargetSpellList;
class TC_GAME_API PetAI : public CreatureAI
{
public:
explicit PetAI(Creature* c);
explicit PetAI(Creature* creature);
void UpdateAI(uint32) override;
static int32 Permissible(Creature const* creature);
void KilledUnit(Unit* /*victim*/) override;
void AttackStart(Unit* target) override; // only start attacking if not attacking something else already
void _AttackStart(Unit* target); // always start attacking if possible
// only start attacking if not attacking something else already
void AttackStart(Unit* target) override;
// always start attacking if possible
void _AttackStart(Unit* target);
void MovementInform(uint32 moveType, uint32 data) override;
void OwnerAttackedBy(Unit* attacker) override;
void OwnerAttacked(Unit* target) override;
@@ -46,8 +47,8 @@ class TC_GAME_API PetAI : public CreatureAI
void ReceiveEmote(Player* player, uint32 textEmote) override;
// The following aren't used by the PetAI but need to be defined to override
// default CreatureAI functions which interfere with the PetAI
//
// default CreatureAI functions which interfere with the PetAI
void MoveInLineOfSight(Unit* /*who*/) override { } // CreatureAI interferes with returning pets
void MoveInLineOfSight_Safe(Unit* /*who*/) { } // CreatureAI interferes with returning pets
void EnterEvadeMode(EvadeReason /*why*/) override { } // For fleeing, pets don't use this type of Evade mechanic
@@ -60,6 +61,7 @@ class TC_GAME_API PetAI : public CreatureAI
void HandleReturnMovement();
void DoAttack(Unit* target, bool chase);
bool CanAttack(Unit* target);
// Quick access to set all flags to FALSE
void ClearCharmInfoFlags();
TimeTracker _tracker;

View File

@@ -24,8 +24,7 @@
class TC_GAME_API ReactorAI : public CreatureAI
{
public:
explicit ReactorAI(Creature* c) : CreatureAI(c) { }
explicit ReactorAI(Creature* creature) : CreatureAI(creature) { }
void MoveInLineOfSight(Unit*) override { }
void UpdateAI(uint32 diff) override;

View File

@@ -17,13 +17,14 @@
*/
#include "TotemAI.h"
#include "Totem.h"
#include "CellImpl.h"
#include "Creature.h"
#include "ObjectAccessor.h"
#include "SpellMgr.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "ObjectAccessor.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "Totem.h"
int32 TotemAI::Permissible(Creature const* creature)
{
@@ -33,9 +34,9 @@ int32 TotemAI::Permissible(Creature const* creature)
return PERMIT_BASE_NO;
}
TotemAI::TotemAI(Creature* c) : CreatureAI(c), _victimGUID()
TotemAI::TotemAI(Creature* creature) : CreatureAI(creature), _victimGUID()
{
ASSERT(c->IsTotem());
ASSERT(creature->IsTotem(), "TotemAI: AI assigned to a no-totem creature (%s)!", creature->GetGUID().ToString().c_str());
}
void TotemAI::MoveInLineOfSight(Unit* /*who*/) { }
@@ -67,9 +68,7 @@ void TotemAI::UpdateAI(uint32 /*diff*/)
Unit* victim = _victimGUID ? ObjectAccessor::GetUnit(*me, _victimGUID) : nullptr;
// Search victim if no, not attackable, or out of range, or friendly (possible in case duel end)
if (!victim ||
!victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) ||
me->IsFriendlyTo(victim) || !me->CanSeeOrDetect(victim))
if (!victim || !victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) || me->IsFriendlyTo(victim) || !me->CanSeeOrDetect(victim))
{
victim = nullptr;
Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me->GetCharmerOrOwnerOrSelf(), max_range);
@@ -94,13 +93,15 @@ void TotemAI::AttackStart(Unit* /*victim*/)
{
// Sentry totem sends ping on attack
if (me->GetEntry() == SENTRY_TOTEM_ENTRY)
{
if (Unit* owner = me->GetOwner())
if (Player* player = owner->ToPlayer())
{
WorldPacket data(MSG_MINIMAP_PING, (8+4+4));
WorldPacket data(MSG_MINIMAP_PING, (8 + 4 + 4));
data << me->GetGUID();
data << me->GetPositionX();
data << me->GetPositionY();
player->SendDirectMessage(&data);
}
}
}

View File

@@ -28,8 +28,7 @@ class Totem;
class TC_GAME_API TotemAI : public CreatureAI
{
public:
explicit TotemAI(Creature* c);
explicit TotemAI(Creature* creature);
void MoveInLineOfSight(Unit* who) override;
void AttackStart(Unit* victim) override;

View File

@@ -111,12 +111,6 @@ void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAg
SelectTargetList(targetList, num, targetType, offset, DefaultTargetSelector(me, dist, playerOnly, withTank, aura));
}
float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
return spellInfo ? spellInfo->GetMaxRange(positive) : 0;
}
SpellCastResult UnitAI::DoCast(uint32 spellId)
{
Unit* target = nullptr;
@@ -185,6 +179,12 @@ SpellCastResult UnitAI::DoCastVictim(uint32 spellId, CastSpellExtraArgs const& a
return SPELL_FAILED_BAD_TARGETS;
}
float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
return spellInfo ? spellInfo->GetMaxRange(positive) : 0;
}
#define UPDATE_TARGET(a) {if (AIInfo->target<a) AIInfo->target=a;}
void UnitAI::FillAISpellInfo()

View File

@@ -33,19 +33,6 @@
#include "Vehicle.h"
#include "World.h"
//Disable CreatureAI when charmed
void CreatureAI::OnCharmed(bool isNew)
{
if (isNew && !me->IsCharmed() && me->LastCharmerGUID)
{
if (!me->HasReactState(REACT_PASSIVE))
if (Unit* lastCharmer = ObjectAccessor::GetUnit(*me, me->LastCharmerGUID))
me->EngageWithTarget(lastCharmer);
me->LastCharmerGUID.Clear();
}
UnitAI::OnCharmed(isNew);
}
AISpellInfoType* UnitAI::AISpellInfo;
AISpellInfoType* GetAISpellInfo(uint32 i) { return &UnitAI::AISpellInfo[i]; }
@@ -62,15 +49,32 @@ void CreatureAI::Talk(uint8 id, WorldObject const* whisperTarget /*= nullptr*/)
sCreatureTextMgr->SendChat(me, id, whisperTarget);
}
// Disable CreatureAI when charmed
void CreatureAI::OnCharmed(bool isNew)
{
if (isNew && !me->IsCharmed() && me->LastCharmerGUID)
{
if (!me->HasReactState(REACT_PASSIVE))
{
if (Unit* lastCharmer = ObjectAccessor::GetUnit(*me, me->LastCharmerGUID))
me->EngageWithTarget(lastCharmer);
}
me->LastCharmerGUID.Clear();
}
UnitAI::OnCharmed(isNew);
}
void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/)
{
if (!creature)
creature = me;
Map* map = creature->GetMap();
if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
if (!map->IsDungeon()) // use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
{
TC_LOG_ERROR("misc", "DoZoneInCombat call for map that isn't an instance (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? creature->ToCreature()->GetEntry() : 0);
TC_LOG_ERROR("scripts.ai", "CreatureAI::DoZoneInCombat: call for map that isn't an instance (%s)", creature->GetGUID().ToString().c_str());
return;
}
@@ -79,17 +83,21 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/)
return;
for (auto const& ref : playerList)
{
if (Player* player = ref.GetSource())
{
if (!player->IsAlive() || !CombatManager::CanBeginCombat(creature, player))
continue;
creature->EngageWithTarget(player);
for (Unit* pet : player->m_Controlled)
creature->EngageWithTarget(pet);
if (Unit* vehicle = player->GetVehicleBase())
creature->EngageWithTarget(vehicle);
}
}
}
// scripts does not take care about MoveInLineOfSight loops
@@ -148,7 +156,7 @@ void CreatureAI::EnterEvadeMode(EvadeReason why)
if (!_EnterEvadeMode(why))
return;
TC_LOG_DEBUG("entities.unit", "Creature %u enters evade mode.", me->GetEntry());
TC_LOG_DEBUG("scripts.ai", "CreatureAI::EnterEvadeMode: entering evade mode (why: %u) (%s)", why, me->GetGUID().ToString().c_str());
if (!me->GetVehicle()) // otherwise me will be in evade mode forever
{
@@ -236,11 +244,11 @@ int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) con
std::unordered_set<coordinate> outOfBounds;
Position startPosition = owner->GetPosition();
if (!IsInBoundary(&startPosition))
{ // fall back to creature position
if (!IsInBoundary(&startPosition)) // fall back to creature position
{
startPosition = me->GetPosition();
if (!IsInBoundary(&startPosition))
{ // fall back to creature home position
if (!IsInBoundary(&startPosition)) // fall back to creature home position
{
startPosition = me->GetHomePosition();
if (!IsInBoundary(&startPosition))
return LANG_CREATURE_NO_INTERIOR_POINT_FOUND;
@@ -254,7 +262,7 @@ int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) con
{
coordinate front = Q.front();
bool hasOutOfBoundsNeighbor = false;
for (coordinate off : std::initializer_list<coordinate>{{1,0}, {0,1}, {-1,0}, {0,-1}})
for (coordinate const& off : std::list<coordinate>{ {1, 0}, {0, 1}, {-1, 0}, {0, -1} })
{
coordinate next(front.first + off.first, front.second + off.second);
if (next.first > BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.first < -BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.second > BOUNDARY_VISUALIZE_FAILSAFE_LIMIT || next.second < -BOUNDARY_VISUALIZE_FAILSAFE_LIMIT)
@@ -274,12 +282,12 @@ int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) con
}
alreadyChecked.insert(next);
}
else
if (outOfBounds.find(next) != outOfBounds.end())
hasOutOfBoundsNeighbor = true;
else if (outOfBounds.find(next) != outOfBounds.end())
hasOutOfBoundsNeighbor = true;
}
if (fill || hasOutOfBoundsNeighbor)
if (TempSummon* point = owner->SummonCreature(BOUNDARY_VISUALIZE_CREATURE, Position(startPosition.GetPositionX() + front.first*BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + front.second*BOUNDARY_VISUALIZE_STEP_SIZE, spawnZ), TEMPSUMMON_TIMED_DESPAWN, duration * IN_MILLISECONDS))
{
if (TempSummon* point = owner->SummonCreature(BOUNDARY_VISUALIZE_CREATURE, Position(startPosition.GetPositionX() + front.first * BOUNDARY_VISUALIZE_STEP_SIZE, startPosition.GetPositionY() + front.second * BOUNDARY_VISUALIZE_STEP_SIZE, spawnZ), TEMPSUMMON_TIMED_DESPAWN, duration * IN_MILLISECONDS))
{
point->SetObjectScale(BOUNDARY_VISUALIZE_CREATURE_SCALE);
point->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
@@ -287,6 +295,8 @@ int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) con
if (!hasOutOfBoundsNeighbor)
point->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
}
Q.pop();
}
return boundsWarning ? LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED : 0;
@@ -300,7 +310,7 @@ bool CreatureAI::IsInBoundary(Position const* who) const
if (!who)
who = me;
return (CreatureAI::IsInBounds(*_boundary, who) != _negateBoundary);
return CreatureAI::IsInBounds(*_boundary, who) != _negateBoundary;
}
bool CreatureAI::IsInBounds(CreatureBoundary const& boundary, Position const* pos)

View File

@@ -19,11 +19,11 @@
#ifndef TRINITY_CREATUREAI_H
#define TRINITY_CREATUREAI_H
#include "UnitAI.h"
#include "Common.h"
#include "ObjectDefines.h"
#include "Optional.h"
#include "QuestDef.h"
#include "UnitAI.h"
class AreaBoundary;
class Creature;
@@ -38,29 +38,36 @@ typedef std::vector<AreaBoundary const*> CreatureBoundary;
#define TIME_INTERVAL_LOOK 5000
#define VISIBILITY_RANGE 10000
//Spell targets used by SelectSpell
enum SelectTargetType
enum Permitions : int32
{
SELECT_TARGET_DONTCARE = 0, //All target types allowed
SELECT_TARGET_SELF, //Only Self casting
SELECT_TARGET_SINGLE_ENEMY, //Only Single Enemy
SELECT_TARGET_AOE_ENEMY, //Only AoE Enemy
SELECT_TARGET_ANY_ENEMY, //AoE or Single Enemy
SELECT_TARGET_SINGLE_FRIEND, //Only Single Friend
SELECT_TARGET_AOE_FRIEND, //Only AoE Friend
SELECT_TARGET_ANY_FRIEND //AoE or Single Friend
PERMIT_BASE_NO = -1,
PERMIT_BASE_IDLE = 1,
PERMIT_BASE_REACTIVE = 100,
PERMIT_BASE_PROACTIVE = 200,
PERMIT_BASE_FACTION_SPECIFIC = 400,
PERMIT_BASE_SPECIAL = 800
};
//Spell Effects used by SelectSpell
// Spell targets used by SelectSpell
enum SelectTargetType
{
SELECT_TARGET_DONTCARE = 0, // All target types allowed
SELECT_TARGET_SELF, // Only Self casting
SELECT_TARGET_SINGLE_ENEMY, // Only Single Enemy
SELECT_TARGET_AOE_ENEMY, // Only AoE Enemy
SELECT_TARGET_ANY_ENEMY, // AoE or Single Enemy
SELECT_TARGET_SINGLE_FRIEND, // Only Single Friend
SELECT_TARGET_AOE_FRIEND, // Only AoE Friend
SELECT_TARGET_ANY_FRIEND // AoE or Single Friend
};
// Spell Effects used by SelectSpell
enum SelectEffect
{
SELECT_EFFECT_DONTCARE = 0, //All spell effects allowed
SELECT_EFFECT_DAMAGE, //Spell does damage
SELECT_EFFECT_HEALING, //Spell does healing
SELECT_EFFECT_AURA //Spell applies an aura
SELECT_EFFECT_DONTCARE = 0, // All spell effects allowed
SELECT_EFFECT_DAMAGE, // Spell does damage
SELECT_EFFECT_HEALING, // Spell does healing
SELECT_EFFECT_AURA // Spell applies an aura
};
enum SCEquip
@@ -240,14 +247,4 @@ class TC_GAME_API CreatureAI : public UnitAI
bool _moveInLOSLocked;
};
enum Permitions : int32
{
PERMIT_BASE_NO = -1,
PERMIT_BASE_IDLE = 1,
PERMIT_BASE_REACTIVE = 100,
PERMIT_BASE_PROACTIVE = 200,
PERMIT_BASE_FACTION_SPECIFIC = 400,
PERMIT_BASE_SPECIAL = 800
};
#endif

View File

@@ -1152,13 +1152,13 @@ PlayerAI::TargetedSpell SimpleCharmedPlayerAI::SelectAppropriateCastForSpec()
}
static const float CASTER_CHASE_DISTANCE = 28.0f;
void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
void SimpleCharmedPlayerAI::UpdateAI(uint32 diff)
{
Creature* charmer = GetCharmer();
if (!charmer)
return;
//kill self if charm aura has infinite duration
// kill self if charm aura has infinite duration
if (charmer->IsInEvadeMode())
{
Player::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM);
@@ -1222,8 +1222,8 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
_castCheckTimer = 0;
else
{
if (IsRangedAttacker())
{ // chase to zero if the target isn't in line of sight
if (IsRangedAttacker()) // chase to zero if the target isn't in line of sight
{
bool inLOS = me->IsWithinLOSInMap(target);
if (_chaseCloser != !inLOS)
{

View File

@@ -125,9 +125,7 @@ void SummonList::DoActionImpl(int32 action, StorageType const& summons)
}
}
ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature),
IsFleeing(false),
_isCombatMovementAllowed(true)
ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature), IsFleeing(false), _isCombatMovementAllowed(true)
{
_isHeroic = me->GetMap()->IsHeroic();
_difficulty = Difficulty(me->GetMap()->GetSpawnMode());
@@ -152,7 +150,7 @@ void ScriptedAI::AttackStart(Unit* who)
void ScriptedAI::UpdateAI(uint32 /*diff*/)
{
//Check if we have a current target
// Check if we have a current target
if (!UpdateVictim())
return;
@@ -195,7 +193,7 @@ void ScriptedAI::DoPlaySoundToSet(WorldObject* source, uint32 soundId)
if (!sSoundEntriesStore.LookupEntry(soundId))
{
TC_LOG_ERROR("scripts", "Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)", soundId, source->GetTypeId(), source->GetGUID().GetCounter());
TC_LOG_ERROR("scripts.ai", "ScriptedAI::DoPlaySoundToSet: Invalid soundId %u used in DoPlaySoundToSet (Source: %s)", soundId, source->GetGUID().ToString().c_str());
return;
}
@@ -262,15 +260,15 @@ bool ScriptedAI::HealthAbovePct(uint32 pct) const
SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mechanic, SelectTargetType targets, uint32 powerCostMin, uint32 powerCostMax, float rangeMin, float rangeMax, SelectEffect effects)
{
//No target so we can't cast
// No target so we can't cast
if (!target)
return nullptr;
//Silenced so we can't cast
// Silenced so we can't cast
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
return nullptr;
//Using the extended script system we first create a list of viable spells
// Using the extended script system we first create a list of viable spells
SpellInfo const* apSpell[MAX_CREATURE_SPELLS];
memset(apSpell, 0, MAX_CREATURE_SPELLS * sizeof(SpellInfo*));
@@ -278,59 +276,59 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec
SpellInfo const* tempSpell = nullptr;
//Check if each spell is viable(set it to null if not)
// Check if each spell is viable(set it to null if not)
for (uint32 i = 0; i < MAX_CREATURE_SPELLS; i++)
{
tempSpell = sSpellMgr->GetSpellInfo(me->m_spells[i]);
//This spell doesn't exist
// This spell doesn't exist
if (!tempSpell)
continue;
// Targets and Effects checked first as most used restrictions
//Check the spell targets if specified
// Check the spell targets if specified
if (targets && !(SpellSummary[me->m_spells[i]].Targets & (1 << (targets-1))))
continue;
//Check the type of spell if we are looking for a specific spell type
// Check the type of spell if we are looking for a specific spell type
if (effects && !(SpellSummary[me->m_spells[i]].Effects & (1 << (effects-1))))
continue;
//Check for school if specified
// Check for school if specified
if (school && (tempSpell->SchoolMask & school) == 0)
continue;
//Check for spell mechanic if specified
// Check for spell mechanic if specified
if (mechanic && tempSpell->Mechanic != mechanic)
continue;
//Make sure that the spell uses the requested amount of power
// Make sure that the spell uses the requested amount of power
if (powerCostMin && tempSpell->ManaCost < powerCostMin)
continue;
if (powerCostMax && tempSpell->ManaCost > powerCostMax)
continue;
//Continue if we don't have the mana to actually cast this spell
// Continue if we don't have the mana to actually cast this spell
if (tempSpell->ManaCost > me->GetPower(tempSpell->PowerType))
continue;
//Check if the spell meets our range requirements
// Check if the spell meets our range requirements
if (rangeMin && me->GetSpellMinRangeForTarget(target, tempSpell) < rangeMin)
continue;
if (rangeMax && me->GetSpellMaxRangeForTarget(target, tempSpell) > rangeMax)
continue;
//Check if our target is in range
// Check if our target is in range
if (me->IsWithinDistInMap(target, float(me->GetSpellMinRangeForTarget(target, tempSpell))) || !me->IsWithinDistInMap(target, float(me->GetSpellMaxRangeForTarget(target, tempSpell))))
continue;
//All good so lets add it to the spell list
// All good so lets add it to the spell list
apSpell[spellCount] = tempSpell;
++spellCount;
}
//We got our usable spells so now lets randomly pick one
// We got our usable spells so now lets randomly pick one
if (!spellCount)
return nullptr;
@@ -357,7 +355,7 @@ void ScriptedAI::DoTeleportPlayer(Unit* unit, float x, float y, float z, float o
if (Player* player = unit->ToPlayer())
player->TeleportTo(unit->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
else
TC_LOG_ERROR("scripts", "Creature %s Tried to teleport non-player unit (%s) to x: %f y:%f z: %f o: %f. Aborted.",
TC_LOG_ERROR("scripts.ai", "ScriptedAI::DoTeleportPlayer: Creature %s Tried to teleport non-player unit (%s) to x: %f y:%f z: %f o: %f. Aborted.",
me->GetGUID().ToString().c_str(), unit->GetGUID().ToString().c_str(), x, y, z, o);
}
@@ -448,19 +446,8 @@ void ScriptedAI::SetCombatMovement(bool allowMovement)
_isCombatMovementAllowed = allowMovement;
}
enum NPCs
{
NPC_BROODLORD = 12017,
NPC_VOID_REAVER = 19516,
NPC_JAN_ALAI = 23578,
NPC_SARTHARION = 28860
};
// BossAI - for instanced bosses
BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature),
instance(creature->GetInstanceScript()),
summons(creature),
_bossId(bossId)
BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature), instance(creature->GetInstanceScript()), summons(creature), _bossId(bossId)
{
if (instance)
SetBoundary(instance->GetBossBoundary(bossId));
@@ -571,7 +558,7 @@ void BossAI::_DespawnAtEvade(Seconds delayToRespawn, Creature* who)
{
if (delayToRespawn < Seconds(2))
{
TC_LOG_ERROR("scripts", "_DespawnAtEvade called with delay of %ld seconds, defaulting to 2.", delayToRespawn.count());
TC_LOG_ERROR("scripts.ai", "BossAI::_DespawnAtEvade: called with delay of %ld seconds, defaulting to 2 (me: %s)", delayToRespawn.count(), me->GetGUID().ToString().c_str());
delayToRespawn = Seconds(2);
}
@@ -580,7 +567,7 @@ void BossAI::_DespawnAtEvade(Seconds delayToRespawn, Creature* who)
if (TempSummon* whoSummon = who->ToTempSummon())
{
TC_LOG_WARN("scripts", "_DespawnAtEvade called on a temporary summon.");
TC_LOG_WARN("scripts.ai", "BossAI::_DespawnAtEvade: called on a temporary summon (who: %s)", who->GetGUID().ToString().c_str());
whoSummon->UnSummon();
return;
}
@@ -592,10 +579,7 @@ void BossAI::_DespawnAtEvade(Seconds delayToRespawn, Creature* who)
}
// WorldBossAI - for non-instanced bosses
WorldBossAI::WorldBossAI(Creature* creature) :
ScriptedAI(creature),
summons(creature) { }
WorldBossAI::WorldBossAI(Creature* creature) : ScriptedAI(creature), summons(creature) { }
void WorldBossAI::_Reset()
{

View File

@@ -16,8 +16,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCRIPTEDCREATURE_H_
#define SCRIPTEDCREATURE_H_
#ifndef TRINITY_SCRIPTEDCREATURE_H
#define TRINITY_SCRIPTEDCREATURE_H
#include "CreatureAI.h"
#include "Creature.h" // convenience include for scripts, all uses of ScriptedCreature also need Creature (except ScriptedCreature itself doesn't need Creature)
@@ -134,45 +134,45 @@ struct TC_GAME_API ScriptedAI : public CreatureAI
virtual ~ScriptedAI() { }
// *************
//CreatureAI Functions
// CreatureAI Functions
// *************
void AttackStartNoMove(Unit* target);
//Called at World update tick
// Called at World update tick
virtual void UpdateAI(uint32 diff) override;
// *************
// Variables
// *************
//For fleeing
// For fleeing
bool IsFleeing;
// *************
//Pure virtual functions
// Pure virtual functions
// *************
// Called before JustEngagedWith even before the creature is in combat.
void AttackStart(Unit* /*target*/) override;
// *************
//AI Helper Functions
// AI Helper Functions
// *************
//Start movement toward victim
// Start movement toward victim
void DoStartMovement(Unit* target, float distance = 0.0f, float angle = 0.0f);
//Start no movement on victim
// Start no movement on victim
void DoStartNoMovement(Unit* target);
//Stop attack of current victim
// Stop attack of current victim
void DoStopAttack();
//Cast spell by spell info
// Cast spell by spell info
void DoCastSpell(Unit* target, SpellInfo const* spellInfo, bool triggered = false);
//Plays a sound to all nearby players
// Plays a sound to all nearby players
void DoPlaySoundToSet(WorldObject* source, uint32 soundId);
// Add specified amount of threat directly to victim (ignores redirection effects) - also puts victim in combat and engages them if necessary
@@ -189,32 +189,32 @@ struct TC_GAME_API ScriptedAI : public CreatureAI
void DoTeleportTo(float x, float y, float z, uint32 time = 0);
void DoTeleportTo(float const pos[4]);
//Teleports a player without dropping threat (only teleports to same map)
// Teleports a player without dropping threat (only teleports to same map)
void DoTeleportPlayer(Unit* unit, float x, float y, float z, float o);
void DoTeleportAll(float x, float y, float z, float o);
//Returns friendly unit with the most amount of hp missing from max hp
// Returns friendly unit with the most amount of hp missing from max hp
Unit* DoSelectLowestHpFriendly(float range, uint32 minHPDiff = 1);
//Returns friendly unit with hp pct below specified and with specified entry
// Returns friendly unit with hp pct below specified and with specified entry
Unit* DoSelectBelowHpPctFriendlyWithEntry(uint32 entry, float range, uint8 hpPct = 1, bool excludeSelf = true);
//Returns a list of friendly CC'd units within range
// Returns a list of friendly CC'd units within range
std::list<Creature*> DoFindFriendlyCC(float range);
//Returns a list of all friendly units missing a specific buff within range
// Returns a list of all friendly units missing a specific buff within range
std::list<Creature*> DoFindFriendlyMissingBuff(float range, uint32 spellId);
//Return a player with at least minimumRange from me
// Return a player with at least minimumRange from me
Player* GetPlayerAtMinimumRange(float minRange);
//Spawns a creature relative to me
// Spawns a creature relative to me
Creature* DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, uint32 despawntime);
bool HealthBelowPct(uint32 pct) const;
bool HealthAbovePct(uint32 pct) const;
//Returns spells that meet the specified criteria from the creatures spell list
// Returns spells that meet the specified criteria from the creatures spell list
SpellInfo const* SelectSpell(Unit* target, uint32 school, uint32 mechanic, SelectTargetType targets, uint32 powerCostMin, uint32 powerCostMax, float rangeMin, float rangeMax, SelectEffect effect);
void SetEquipmentSlots(bool loadDefault, int32 mainHand = EQUIP_NO_CHANGE, int32 offHand = EQUIP_NO_CHANGE, int32 ranged = EQUIP_NO_CHANGE);
@@ -403,4 +403,4 @@ inline void GetPlayerListInGrid(Container& container, WorldObject* source, float
source->GetPlayerListInGrid(container, maxSearchRange);
}
#endif // SCRIPTEDCREATURE_H_
#endif // TRINITY_SCRIPTEDCREATURE_H

View File

@@ -104,7 +104,7 @@ void EscortAI::EnterEvadeMode(EvadeReason /*why*/)
{
AddEscortState(STATE_ESCORT_RETURNING);
ReturnToLastPoint();
TC_LOG_DEBUG("scripts", "EscortAI::EnterEvadeMode: left combat and is now returning to last point");
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::EnterEvadeMode: left combat and is now returning to last point (%s)", me->GetGUID().ToString().c_str());
}
else
{
@@ -129,22 +129,22 @@ void EscortAI::MovementInform(uint32 type, uint32 id)
// continue waypoint movement
if (id == POINT_LAST_POINT)
{
TC_LOG_DEBUG("scripts", "EscortAI::MovementInform: returned to before combat position");
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::MovementInform: returned to before combat position (%s)", me->GetGUID().ToString().c_str());
me->SetWalk(!_running);
RemoveEscortState(STATE_ESCORT_RETURNING);
}
else if (id == POINT_HOME)
{
TC_LOG_DEBUG("scripts", "EscortAI::MovementInform: returned to home location and restarting waypoint path");
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::MovementInform: returned to home location and restarting waypoint path (%s)", me->GetGUID().ToString().c_str());
_started = false;
}
}
else if (type == WAYPOINT_MOTION_TYPE)
{
ASSERT(id < _path.nodes.size(), "EscortAI::MovementInform: referenced movement id (%u) points to non-existing node in loaded path", id);
ASSERT(id < _path.nodes.size(), "EscortAI::MovementInform: referenced movement id (%u) points to non-existing node in loaded path (%s)", id, me->GetGUID().ToString().c_str());
WaypointNode waypoint = _path.nodes[id];
TC_LOG_DEBUG("scripts", "EscortAI::MovementInform: waypoint node %u reached", waypoint.id);
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::MovementInform: waypoint node %u reached (%s)", waypoint.id, me->GetGUID().ToString().c_str());
// last point
if (id == _path.nodes.size() - 1)
@@ -174,7 +174,7 @@ void EscortAI::UpdateAI(uint32 diff)
if (_despawnAtEnd)
{
TC_LOG_DEBUG("scripts", "EscortAI::UpdateAI: reached end of waypoints, despawning at end");
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::UpdateAI: reached end of waypoints, despawning at end (%s)", me->GetGUID().ToString().c_str());
if (_returnToStart)
{
Position respawnPosition;
@@ -182,14 +182,14 @@ void EscortAI::UpdateAI(uint32 diff)
me->GetRespawnPosition(respawnPosition.m_positionX, respawnPosition.m_positionY, respawnPosition.m_positionZ, &orientation);
respawnPosition.SetOrientation(orientation);
me->GetMotionMaster()->MovePoint(POINT_HOME, respawnPosition);
TC_LOG_DEBUG("scripts", "EscortAI::UpdateAI: returning to spawn location: %s", respawnPosition.ToString().c_str());
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::UpdateAI: returning to spawn location: %s (%s)", respawnPosition.ToString().c_str(), me->GetGUID().ToString().c_str());
}
else if (_instantRespawn)
me->Respawn(true);
else
me->DespawnOrUnsummon();
}
TC_LOG_DEBUG("scripts", "EscortAI::UpdateAI: reached end of waypoints");
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::UpdateAI: reached end of waypoints (%s)", me->GetGUID().ToString().c_str());
RemoveEscortState(STATE_ESCORT_ESCORTING);
return;
}
@@ -218,7 +218,7 @@ void EscortAI::UpdateAI(uint32 diff)
{
if (!IsPlayerOrGroupInRange())
{
TC_LOG_DEBUG("scripts", "EscortAI::UpdateAI: failed because player/group was to far away or not found");
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::UpdateAI: failed because player/group was to far away or not found (%s)", me->GetGUID().ToString().c_str());
bool isEscort = false;
if (CreatureData const* creatureData = me->GetCreatureData())
@@ -293,15 +293,15 @@ void EscortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */,
}
}
if (me->GetVictim())
if (me->IsEngaged())
{
TC_LOG_ERROR("scripts", "EscortAI::Start: (script: %s, creature entry: %u) attempts to Start while in combat", me->GetScriptName().c_str(), me->GetEntry());
TC_LOG_ERROR("scripts.ai.escortai", "EscortAI::Start: (script: %s) attempts to Start while in combat (%s)", me->GetScriptName().c_str(), me->GetGUID().ToString().c_str());
return;
}
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
TC_LOG_ERROR("scripts", "EscortAI::Start: (script: %s, creature entry: %u) attempts to Start while already escorting", me->GetScriptName().c_str(), me->GetEntry());
TC_LOG_ERROR("scripts.ai.escortai", "EscortAI::Start: (script: %s) attempts to Start while already escorting (%s)", me->GetScriptName().c_str(), me->GetGUID().ToString().c_str());
return;
}
@@ -312,7 +312,7 @@ void EscortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */,
if (_path.nodes.empty())
{
TC_LOG_ERROR("scripts", "EscortAI::Start: (script: %s, creature entry: %u) starts with 0 waypoints (possible missing entry in script_waypoint. Quest: %u).", me->GetScriptName().c_str(), me->GetEntry(), quest ? quest->GetQuestId() : 0);
TC_LOG_ERROR("scripts.ai.escortai", "EscortAI::Start: (script: %s) is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn (%s)", me->GetScriptName().c_str(), me->GetGUID().ToString().c_str());
return;
}
@@ -324,7 +324,7 @@ void EscortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */,
_returnToStart = canLoopPath;
if (_returnToStart && _instantRespawn)
TC_LOG_DEBUG("scripts", "EscortAI::Start: (script: %s, creature entry: %u) is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.", me->GetScriptName().c_str(), me->GetEntry());
TC_LOG_ERROR("scripts.ai.escortai", "EscortAI::Start: (script: %s) is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn (%s)", me->GetScriptName().c_str(), me->GetGUID().ToString().c_str());
me->GetMotionMaster()->MoveIdle();
me->GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL);
@@ -337,7 +337,8 @@ void EscortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */,
me->SetImmuneToNPC(false);
}
TC_LOG_DEBUG("scripts", "EscortAI::Start: (script: %s, creature entry: %u) started with %u waypoints. ActiveAttacker = %d, Run = %d, Player = %s", me->GetScriptName().c_str(), me->GetEntry(), uint32(_path.nodes.size()), _activeAttacker, _running, _playerGUID.ToString().c_str());
TC_LOG_DEBUG("scripts.ai.escortai", "EscortAI::Start: (script: %s) started with %u waypoints. ActiveAttacker = %d, Run = %d, Player = %s (%s)",
me->GetScriptName().c_str(), uint32(_path.nodes.size()), _activeAttacker, _running, _playerGUID.ToString().c_str(), me->GetGUID().ToString().c_str());
// set initial speed
me->SetWalk(!_running);

View File

@@ -16,8 +16,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SC_ESCORTAI_H
#define SC_ESCORTAI_H
#ifndef TRINITY_SCRIPTEDESCORTAI_H
#define TRINITY_SCRIPTEDESCORTAI_H
#include "ScriptedCreature.h"
#include "WaypointDefines.h"
@@ -99,4 +99,5 @@ struct TC_GAME_API EscortAI : public ScriptedAI
bool _ended;
bool _resume;
};
#endif

View File

@@ -16,13 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: FollowerAI
SD%Complete: 50
SDComment: This AI is under development
SDCategory: Npc
EndScriptData */
#include "ScriptedFollowerAI.h"
#include "Creature.h"
#include "Group.h"
@@ -32,18 +25,14 @@ EndScriptData */
#include "ObjectAccessor.h"
#include "Player.h"
const float MAX_PLAYER_DISTANCE = 100.0f;
float constexpr MAX_PLAYER_DISTANCE = 100.0f;
enum Points
{
POINT_COMBAT_START = 0xFFFFFF
POINT_COMBAT_START = 0xFFFFFF
};
FollowerAI::FollowerAI(Creature* creature) : ScriptedAI(creature),
_updateFollowTimer(2500),
_followState(STATE_FOLLOW_NONE),
_questForFollow(nullptr)
{ }
FollowerAI::FollowerAI(Creature* creature) : ScriptedAI(creature), _updateFollowTimer(2500), _followState(STATE_FOLLOW_NONE), _questForFollow(nullptr) { }
void FollowerAI::AttackStart(Unit* who)
{
@@ -62,27 +51,27 @@ 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.
// 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
// experimental (unknown) flag not present
if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))
return false;
//not a player
// not a player
if (!who->EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
return false;
//never attack friendly
// never attack friendly
if (me->IsFriendlyTo(who))
return false;
//too far away and no free sight?
// too far away and no free sight?
if (me->IsWithinDistInMap(who, MAX_PLAYER_DISTANCE) && me->IsWithinLOSInMap(who))
{
me->EngageWithTarget(who);
@@ -167,14 +156,10 @@ void FollowerAI::EnterEvadeMode(EvadeReason /*why*/)
if (HasFollowState(STATE_FOLLOW_INPROGRESS))
{
TC_LOG_DEBUG("scripts", "FollowerAI left combat, returning to CombatStartPosition.");
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::EnterEvadeMode: left combat, returning to CombatStartPosition. (%s)", me->GetGUID().ToString().c_str());
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
{
float fPosX, fPosY, fPosZ;
me->GetPosition(fPosX, fPosY, fPosZ);
me->GetMotionMaster()->MovePoint(POINT_COMBAT_START, fPosX, fPosY, fPosZ);
}
me->GetMotionMaster()->MovePoint(POINT_COMBAT_START, me->GetPosition());
}
else
{
@@ -187,24 +172,24 @@ void FollowerAI::EnterEvadeMode(EvadeReason /*why*/)
void FollowerAI::UpdateAI(uint32 uiDiff)
{
if (HasFollowState(STATE_FOLLOW_INPROGRESS) && !me->GetVictim())
if (HasFollowState(STATE_FOLLOW_INPROGRESS) && !me->IsEngaged())
{
if (_updateFollowTimer <= uiDiff)
{
if (HasFollowState(STATE_FOLLOW_COMPLETE) && !HasFollowState(STATE_FOLLOW_POSTEVENT))
{
TC_LOG_DEBUG("scripts", "FollowerAI is set completed, despawns.");
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::UpdateAI: is set completed, despawns. (%s)", me->GetGUID().ToString().c_str());
me->DespawnOrUnsummon();
return;
}
bool bIsMaxRangeExceeded = true;
bool maxRangeExceeded = true;
if (Player* player = GetLeaderForFollower())
{
if (HasFollowState(STATE_FOLLOW_RETURNING))
{
TC_LOG_DEBUG("scripts", "FollowerAI is returning to leader.");
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::UpdateAI: is returning to leader. (%s)", me->GetGUID().ToString().c_str());
RemoveFollowState(STATE_FOLLOW_RETURNING);
me->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
@@ -218,7 +203,7 @@ void FollowerAI::UpdateAI(uint32 uiDiff)
Player* member = groupRef->GetSource();
if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE))
{
bIsMaxRangeExceeded = false;
maxRangeExceeded = false;
break;
}
}
@@ -226,13 +211,13 @@ void FollowerAI::UpdateAI(uint32 uiDiff)
else
{
if (me->IsWithinDistInMap(player, MAX_PLAYER_DISTANCE))
bIsMaxRangeExceeded = false;
maxRangeExceeded = false;
}
}
if (bIsMaxRangeExceeded)
if (maxRangeExceeded)
{
TC_LOG_DEBUG("scripts", "FollowerAI failed because player/group was to far away or not found");
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::UpdateAI: failed because player/group was to far away or not found (%s)", me->GetGUID().ToString().c_str());
me->DespawnOrUnsummon();
return;
}
@@ -254,12 +239,12 @@ void FollowerAI::UpdateFollowerAI(uint32 /*uiDiff*/)
DoMeleeAttackIfReady();
}
void FollowerAI::MovementInform(uint32 motionType, uint32 pointId)
void FollowerAI::MovementInform(uint32 type, uint32 id)
{
if (motionType != POINT_MOTION_TYPE || !HasFollowState(STATE_FOLLOW_INPROGRESS))
if (type != POINT_MOTION_TYPE || !HasFollowState(STATE_FOLLOW_INPROGRESS))
return;
if (pointId == POINT_COMBAT_START)
if (id == POINT_COMBAT_START)
{
if (GetLeaderForFollower())
{
@@ -273,19 +258,19 @@ void FollowerAI::MovementInform(uint32 motionType, uint32 pointId)
void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, Quest const* quest)
{
if (me->GetVictim())
if (me->IsEngaged())
{
TC_LOG_DEBUG("scripts", "FollowerAI attempt to StartFollow while in combat.");
TC_LOG_DEBUG("scripts.ai.followerai", "FollowerAI::StartFollow: attempt to StartFollow while in combat. (%s)", me->GetGUID().ToString().c_str());
return;
}
if (HasFollowState(STATE_FOLLOW_INPROGRESS))
{
TC_LOG_ERROR("scripts", "FollowerAI attempt to StartFollow while already following.");
TC_LOG_ERROR("scripts.ai.followerai", "FollowerAI::StartFollow: attempt to StartFollow while already following. (%s)", me->GetGUID().ToString().c_str());
return;
}
//set variables
// set variables
_leaderGUID = player->GetGUID();
if (factionForFollower)
@@ -297,7 +282,6 @@ void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, Quest co
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
TC_LOG_DEBUG("scripts", "FollowerAI start with WAYPOINT_MOTION_TYPE, set to MoveIdle.");
}
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
@@ -306,7 +290,7 @@ void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, Quest co
me->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
TC_LOG_DEBUG("scripts", "FollowerAI start follow %s (%s)", player->GetName().c_str(), _leaderGUID.ToString().c_str());
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()
@@ -324,7 +308,7 @@ Player* FollowerAI::GetLeaderForFollower()
Player* member = groupRef->GetSource();
if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE) && member->IsAlive())
{
TC_LOG_DEBUG("scripts", "FollowerAI GetLeader changed and returned new leader.");
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;
}
@@ -333,11 +317,11 @@ Player* FollowerAI::GetLeaderForFollower()
}
}
TC_LOG_DEBUG("scripts", "FollowerAI GetLeader can not find suitable leader.");
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 bWithEndEvent)
void FollowerAI::SetFollowComplete(bool withEndEvent)
{
if (me->HasUnitState(UNIT_STATE_FOLLOW))
{
@@ -348,7 +332,7 @@ void FollowerAI::SetFollowComplete(bool bWithEndEvent)
me->GetMotionMaster()->MoveIdle();
}
if (bWithEndEvent)
if (withEndEvent)
AddFollowState(STATE_FOLLOW_POSTEVENT);
else
{

View File

@@ -16,23 +16,22 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SC_FOLLOWERAI_H
#define SC_FOLLOWERAI_H
#ifndef TRINITY_SCRIPTEDFOLLOWERAI_H
#define TRINITY_SCRIPTEDFOLLOWERAI_H
#include "ScriptedCreature.h"
#include "ScriptSystem.h"
class Quest;
enum eFollowState
enum FollowerState : uint32
{
STATE_FOLLOW_NONE = 0x000,
STATE_FOLLOW_INPROGRESS = 0x001, //must always have this state for any follow
STATE_FOLLOW_RETURNING = 0x002, //when returning to combat start after being in combat
STATE_FOLLOW_PAUSED = 0x004, //disables following
STATE_FOLLOW_COMPLETE = 0x008, //follow is completed and may end
STATE_FOLLOW_PREEVENT = 0x010, //not implemented (allow pre event to run, before follow is initiated)
STATE_FOLLOW_POSTEVENT = 0x020 //can be set at complete and allow post event to run
STATE_FOLLOW_INPROGRESS = 0x001, // must always have this state for any follow
STATE_FOLLOW_RETURNING = 0x002, // when returning to combat start after being in combat
STATE_FOLLOW_PAUSED = 0x004, // disables following
STATE_FOLLOW_COMPLETE = 0x008, // follow is completed and may end
STATE_FOLLOW_PREEVENT = 0x010, // not implemented (allow pre event to run, before follow is initiated)
STATE_FOLLOW_POSTEVENT = 0x020 // can be set at complete and allow post event to run
};
class TC_GAME_API FollowerAI : public ScriptedAI
@@ -41,25 +40,22 @@ class TC_GAME_API FollowerAI : public ScriptedAI
explicit FollowerAI(Creature* creature);
~FollowerAI() { }
void MovementInform(uint32 motionType, uint32 pointId) override;
void MovementInform(uint32 type, uint32 id) override;
void AttackStart(Unit*) override;
void MoveInLineOfSight(Unit*) override;
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override;
void JustDied(Unit*) override;
void JustAppeared() override;
// the "internal" update, calls UpdateFollowerAI()
void UpdateAI(uint32) override;
void UpdateAI(uint32) override; //the "internal" update, calls UpdateFollowerAI()
virtual void UpdateFollowerAI(uint32); //used when it's needed to add code in update (abilities, scripted events, etc)
// used when it's needed to add code in update (abilities, scripted events, etc)
virtual void UpdateFollowerAI(uint32);
void StartFollow(Player* player, uint32 factionForFollower = 0, Quest const* quest = nullptr);
void SetFollowPaused(bool bPaused); //if special event require follow mode to hold/resume during the follow
void SetFollowComplete(bool bWithEndEvent = false);
// if special event require follow mode to hold/resume during the follow
void SetFollowPaused(bool paused);
void SetFollowComplete(bool withEndEvent = false);
bool HasFollowState(uint32 uiFollowState) { return (_followState & uiFollowState) != 0; }
@@ -67,9 +63,8 @@ class TC_GAME_API FollowerAI : public ScriptedAI
Player* GetLeaderForFollower();
private:
void AddFollowState(uint32 uiFollowState) { _followState |= uiFollowState; }
void RemoveFollowState(uint32 uiFollowState) { _followState &= ~uiFollowState; }
void AddFollowState(uint32 followState) { _followState |= followState; }
void RemoveFollowState(uint32 followState) { _followState &= ~followState; }
bool AssistPlayerInCombatAgainst(Unit* who);
ObjectGuid _leaderGUID;

View File

@@ -16,8 +16,8 @@
*/
#include "ScriptedGossip.h"
#include "Player.h"
#include "Creature.h"
#include "Player.h"
uint32 GetGossipActionFor(Player* player, uint32 gossipListId)
{

View File

@@ -16,8 +16,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SC_GOSSIP_H
#define SC_GOSSIP_H
#ifndef TRINITY_SCRIPTEDGOSSIP_H
#define TRINITY_SCRIPTEDGOSSIP_H
#include "GossipDef.h"
#include "QuestDef.h"

View File

@@ -44,9 +44,9 @@ bool SmartAI::IsAIControlled() const
void SmartAI::StartPath(bool run/* = false*/, uint32 pathId/* = 0*/, bool repeat/* = false*/, Unit* invoker/* = nullptr*/, uint32 nodeId/* = 1*/)
{
if (me->IsInCombat()) // no wp movement in combat
if (me->IsEngaged()) // no wp movement in combat
{
TC_LOG_ERROR("scripts.ai.sai", "SmartAI::StartPath: Creature entry %u wanted to start waypoint movement (%u) while in combat, ignoring.", me->GetEntry(), pathId);
TC_LOG_ERROR("scripts.ai.sai", "SmartAI::StartPath: Creature wanted to start waypoint movement (pathId: %u) while in combat, ignoring. (%s)", pathId, me->GetGUID().ToString().c_str());
return;
}
@@ -123,7 +123,7 @@ void SmartAI::PausePath(uint32 delay, bool forced)
if (HasEscortState(SMART_ESCORT_PAUSED))
{
TC_LOG_ERROR("scripts.ai.sai", "SmartAI::PausePath: Creature entry %u wanted to pause waypoint (current waypoint: %u) movement while already paused, ignoring.", me->GetEntry(), _currentWaypointNode);
TC_LOG_ERROR("scripts.ai.sai", "SmartAI::PausePath: Creature wanted to pause waypoint (current waypoint: %u) movement while already paused, ignoring. (%s)", _currentWaypointNode, me->GetGUID().ToString().c_str());
return;
}

View File

@@ -25,25 +25,22 @@
#include "SmartScript.h"
#include "WaypointDefines.h"
enum SmartEscortState
enum SmartEscortState : uint8
{
SMART_ESCORT_NONE = 0x000, //nothing in progress
SMART_ESCORT_ESCORTING = 0x001, //escort is in progress
SMART_ESCORT_RETURNING = 0x002, //escort is returning after being in combat
SMART_ESCORT_PAUSED = 0x004 //will not proceed with waypoints before state is removed
SMART_ESCORT_NONE = 0x00, // nothing in progress
SMART_ESCORT_ESCORTING = 0x01, // escort is in progress
SMART_ESCORT_RETURNING = 0x02, // escort is returning after being in combat
SMART_ESCORT_PAUSED = 0x04 // will not proceed with waypoints before state is removed
};
enum SmartEscortVars
{
SMART_ESCORT_MAX_PLAYER_DIST = 60,
SMART_MAX_AID_DIST = SMART_ESCORT_MAX_PLAYER_DIST / 2
};
static float constexpr SMART_ESCORT_MAX_PLAYER_DIST = 60.f;
static float constexpr SMART_MAX_AID_DIST = SMART_ESCORT_MAX_PLAYER_DIST / 2.f;
class TC_GAME_API SmartAI : public CreatureAI
{
public:
~SmartAI() { }
explicit SmartAI(Creature* c);
explicit SmartAI(Creature* creature);
// core related
static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
@@ -58,9 +55,9 @@ class TC_GAME_API SmartAI : public CreatureAI
void StopPath(uint32 DespawnTime = 0, uint32 quest = 0, bool fail = false);
void EndPath(bool fail = false);
void ResumePath();
bool HasEscortState(uint32 uiEscortState) const { return (_escortState & uiEscortState) != 0; }
void AddEscortState(uint32 uiEscortState) { _escortState |= uiEscortState; }
void RemoveEscortState(uint32 uiEscortState) { _escortState &= ~uiEscortState; }
bool HasEscortState(uint32 escortState) const { return (_escortState & escortState) != 0; }
void AddEscortState(uint32 escortState) { _escortState |= escortState; }
void RemoveEscortState(uint32 escortState) { _escortState &= ~escortState; }
void SetAutoAttack(bool on) { _canAutoAttack = on; }
void SetCombatMove(bool on);
bool CanCombatMove() { return _canCombatMove; }
@@ -245,7 +242,7 @@ class TC_GAME_API SmartAI : public CreatureAI
class TC_GAME_API SmartGameObjectAI : public GameObjectAI
{
public:
SmartGameObjectAI(GameObject* g) : GameObjectAI(g), _gossipReturn(false) { }
SmartGameObjectAI(GameObject* go) : GameObjectAI(go), _gossipReturn(false) { }
~SmartGameObjectAI() { }
void UpdateAI(uint32 diff) override;

View File

@@ -3921,6 +3921,9 @@ Logger.mmaps=3,Server
#Logger.rbac=3,Console Server
#Logger.scripts=3,Console Server
#Logger.scripts.ai=3,Console Server
#Logger.scripts.ai.escortai=3,Console Server
#Logger.scripts.ai.followerai=3,Console Server
#Logger.scripts.ai.petai=3,Console Server
#Logger.scripts.ai.sai=3,Console Server
#Logger.server.authserver=3,Console Server
#Logger.spells=3,Console Server