[12676] AI-Event throwing and receiving implementation

Add new AI hooks to
* SendAIEvent (either around the npc, or to a specified npc)
* ReceiveAIEvent (hook to receive sent events)
This commit is contained in:
Schmoozerd 2013-08-19 16:32:06 +03:00 committed by Antz
parent 60a7bec73f
commit c7a07a7dc6
5 changed files with 141 additions and 63 deletions

View file

@ -20,6 +20,9 @@
#include "Creature.h"
#include "DBCStores.h"
#include "Spell.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
CreatureAI::~CreatureAI()
{
@ -152,3 +155,79 @@ void CreatureAI::HandleMovementOnAttackStart(Unit* victim)
m_creature->StopMoving();
}
}
// ////////////////////////////////////////////////////////////////////////////////////////////////
// Event system
// ////////////////////////////////////////////////////////////////////////////////////////////////
class AiDelayEventAround : public BasicEvent
{
public:
AiDelayEventAround(AIEventType eventType, ObjectGuid invokerGuid, Creature& owner, std::list<Creature*> const& receivers) :
BasicEvent(),
m_eventType(eventType),
m_invokerGuid(invokerGuid),
m_owner(owner)
{
// Pushing guids because in delay can happen some creature gets despawned => invalid pointer
m_receiverGuids.reserve(receivers.size());
for (std::list<Creature*>::const_iterator itr = receivers.begin(); itr != receivers.end(); ++itr)
m_receiverGuids.push_back((*itr)->GetObjectGuid());
}
bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
{
Unit* pInvoker = m_owner.GetMap()->GetUnit(m_invokerGuid);
for (GuidVector::const_reverse_iterator itr = m_receiverGuids.rbegin(); itr != m_receiverGuids.rend(); ++itr)
{
if (Creature* pReceiver = m_owner.GetMap()->GetAnyTypeCreature(*itr))
{
pReceiver->AI()->ReceiveAIEvent(m_eventType, &m_owner, pInvoker);
// Special case for type 0 (call-assistance)
if (m_eventType == AI_EVENT_CALL_ASSISTANCE && pInvoker && pReceiver->CanAssistTo(&m_owner, pInvoker))
{
pReceiver->SetNoCallAssistance(true);
pReceiver->AI()->AttackStart(pInvoker);
}
}
}
m_receiverGuids.clear();
return true;
}
private:
AiDelayEventAround();
ObjectGuid m_invokerGuid;
GuidVector m_receiverGuids;
Creature& m_owner;
AIEventType m_eventType;
};
void CreatureAI::SendAIEvent(AIEventType eventType, Unit* pInvoker, uint32 uiDelay, float fRadius) const
{
if (fRadius > 0)
{
std::list<Creature*> receiverList;
// Use this check here to collect only assitable creatures in case of CALL_ASSISTANCE, else be less strict
MaNGOS::AnyAssistCreatureInRangeCheck u_check(m_creature, eventType == AI_EVENT_CALL_ASSISTANCE ? pInvoker : NULL, fRadius);
MaNGOS::CreatureListSearcher<MaNGOS::AnyAssistCreatureInRangeCheck> searcher(receiverList, u_check);
Cell::VisitGridObjects(m_creature, searcher, fRadius);
if (!receiverList.empty())
{
AiDelayEventAround* e = new AiDelayEventAround(eventType, pInvoker ? pInvoker->GetObjectGuid() : ObjectGuid(), *m_creature, receiverList);
m_creature->m_Events.AddEvent(e, m_creature->m_Events.CalculateTime(uiDelay));
}
}
}
void CreatureAI::SendAIEvent(AIEventType eventType, Unit* pInvoker, Creature* pReceiver) const
{
MANGOS_ASSERT(pReceiver);
pReceiver->AI()->ReceiveAIEvent(eventType, m_creature, pInvoker);
}