mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/AI: logs, codestyle & cosmetics standarization
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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*/)
|
||||
{
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
*/
|
||||
|
||||
#include "ScriptedGossip.h"
|
||||
#include "Player.h"
|
||||
#include "Creature.h"
|
||||
#include "Player.h"
|
||||
|
||||
uint32 GetGossipActionFor(Player* player, uint32 gossipListId)
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user