From c7a07a7dc660d912a4c99afd78d3b4225f92bea6 Mon Sep 17 00:00:00 2001 From: Schmoozerd Date: Mon, 19 Aug 2013 16:32:06 +0300 Subject: [PATCH] [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) --- src/game/Creature.cpp | 51 ++------------------------ src/game/Creature.h | 14 ------- src/game/CreatureAI.cpp | 79 ++++++++++++++++++++++++++++++++++++++++ src/game/CreatureAI.h | 58 +++++++++++++++++++++++++++++ src/shared/revision_nr.h | 2 +- 5 files changed, 141 insertions(+), 63 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index d3a72127b..3aa2fdf68 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -97,34 +97,6 @@ VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint8 type, u return NULL; } -bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) -{ - if (Unit* victim = m_owner.GetMap()->GetUnit(m_victimGuid)) - { - while (!m_assistantGuids.empty()) - { - Creature* assistant = m_owner.GetMap()->GetAnyTypeCreature(*m_assistantGuids.rbegin()); - m_assistantGuids.pop_back(); - - if (assistant && assistant->CanAssistTo(&m_owner, victim)) - { - assistant->SetNoCallAssistance(true); - if (assistant->AI()) - assistant->AI()->AttackStart(victim); - } - } - } - return true; -} - -AssistDelayEvent::AssistDelayEvent(ObjectGuid victim, Unit& owner, std::list const& assistants) : BasicEvent(), m_victimGuid(victim), m_owner(owner) -{ - // Pushing guids because in delay can happen some creature gets despawned => invalid pointer - m_assistantGuids.reserve(assistants.size()); - for (std::list::const_iterator itr = assistants.begin(); itr != assistants.end(); ++itr) - m_assistantGuids.push_back((*itr)->GetObjectGuid()); -} - bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { m_owner.ForcedDespawn(); @@ -1800,24 +1772,7 @@ void Creature::CallAssistance() if (!m_AlreadyCallAssistance && getVictim() && !isCharmed()) { SetNoCallAssistance(true); - - float radius = sWorld.getConfig(CONFIG_FLOAT_CREATURE_FAMILY_ASSISTANCE_RADIUS); - if (radius > 0) - { - std::list assistList; - - { - MaNGOS::AnyAssistCreatureInRangeCheck u_check(this, getVictim(), radius); - MaNGOS::CreatureListSearcher searcher(assistList, u_check); - Cell::VisitGridObjects(this, searcher, radius); - } - - if (!assistList.empty()) - { - AssistDelayEvent* e = new AssistDelayEvent(getVictim()->GetObjectGuid(), *this, assistList); - m_Events.AddEvent(e, m_Events.CalculateTime(sWorld.getConfig(CONFIG_UINT32_CREATURE_FAMILY_ASSISTANCE_DELAY))); - } - } + AI()->SendAIEvent(AI_EVENT_CALL_ASSISTANCE, getVictim(), sWorld.getConfig(CONFIG_UINT32_CREATURE_FAMILY_ASSISTANCE_DELAY), sWorld.getConfig(CONFIG_FLOAT_CREATURE_FAMILY_ASSISTANCE_RADIUS)); } } @@ -1846,7 +1801,7 @@ bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction / return false; // skip fighting creature - if (isInCombat()) + if (enemy && isInCombat()) return false; // only free creature @@ -1866,7 +1821,7 @@ bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction / } // skip non hostile to caster enemy creatures - if (!IsHostileTo(enemy)) + if (enemy && !IsHostileTo(enemy)) return false; return true; diff --git a/src/game/Creature.h b/src/game/Creature.h index 5b2fcff01..a8e3133e0 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -780,20 +780,6 @@ class MANGOS_DLL_SPEC Creature : public Unit CreatureInfo const* m_creatureInfo; // in difficulty mode > 0 can different from ObjMgr::GetCreatureTemplate(GetEntry()) }; -class AssistDelayEvent : public BasicEvent -{ - public: - AssistDelayEvent(ObjectGuid victim, Unit& owner, std::list const& assistants); - - bool Execute(uint64 e_time, uint32 p_time) override; - private: - AssistDelayEvent(); - - ObjectGuid m_victimGuid; - GuidVector m_assistantGuids; - Unit& m_owner; -}; - class ForcedDespawnDelayEvent : public BasicEvent { public: diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index 830f3d2e5..2595455bc 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -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 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::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 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 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); +} diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index e430bd288..6881a45bc 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -59,6 +59,37 @@ enum CastFlags CAST_AURA_NOT_PRESENT = 0x20, // Only casts the spell if the target does not have an aura from the spell }; +enum AIEventType +{ + // Usable with Event AI + AI_EVENT_JUST_DIED = 0, // Sender = Killed Npc, Invoker = Killer + AI_EVENT_CRITICAL_HEALTH = 1, // Sender = Hurt Npc, Invoker = DamageDealer + AI_EVENT_LOST_HEALTH = 2, // Sender = Hurt Npc, Invoker = DamageDealer + AI_EVENT_GOT_CCED = 3, // Sender = CCed Npc, Invoker = Caster that CCed + AI_EVENT_GOT_FULL_HEALTH = 4, // Sender = Healed Npc, Invoker = Healer + AI_EVENT_CUSTOM_EVENTAI_A = 5, // Sender = Npc that throws custom event, Invoker = TARGET_T_ACTION_INVOKER (if exists) + AI_EVENT_CUSTOM_EVENTAI_B = 6, // Sender = Npc that throws custom event, Invoker = TARGET_T_ACTION_INVOKER (if exists) + MAXIMAL_AI_EVENT_EVENTAI = 7, + + // Internal Use + AI_EVENT_CALL_ASSISTANCE = 10, // Sender = Attacked Npc, Invoker = Enemy + + // Predefined for SD2 + AI_EVENT_START_ESCORT = 100, // Invoker = Escorting Player + AI_EVENT_START_ESCORT_B = 101, // Invoker = Escorting Player + AI_EVENT_START_EVENT = 102, // Invoker = EventStarter + AI_EVENT_START_EVENT_A = 103, // Invoker = EventStarter + AI_EVENT_START_EVENT_B = 104, // Invoker = EventStarter + + // Some IDs for special cases in SD2 + AI_EVENT_CUSTOM_A = 1000, + AI_EVENT_CUSTOM_B = 1001, + AI_EVENT_CUSTOM_C = 1002, + AI_EVENT_CUSTOM_D = 1003, + AI_EVENT_CUSTOM_E = 1004, + AI_EVENT_CUSTOM_F = 1005, +}; + class MANGOS_DLL_SPEC CreatureAI { public: @@ -277,6 +308,33 @@ class MANGOS_DLL_SPEC CreatureAI void SetCombatMovement(bool enable, bool stopOrStartMovement = false); bool IsCombatMovement() const { return m_isCombatMovement; } + ///== Event Handling =============================== + + /** + * Send an AI Event to nearby Creatures around + * @param uiType number to specify the event, default cases listed in enum AIEventType + * @param pInvoker Unit that triggered this event (like an attacker) + * @param uiDelay delay time until the Event will be triggered + * @param fRadius range in which for receiver is searched + */ + void SendAIEvent(AIEventType eventType, Unit* pInvoker, uint32 uiDelay, float fRadius) const; + + /** + * Send an AI Event to a Creature + * @param eventType to specify the event, default cases listed in enum AIEventType + * @param pInvoker Unit that triggered this event (like an attacker) + * @param pReceiver Creature to receive this event + */ + void SendAIEvent(AIEventType eventType, Unit* pInvoker, Creature* pReceiver) const; + + /** + * Called when an AI Event is received + * @param eventType to specify the event, default cases listed in enum AIEventType + * @param pSender Creature that sent this event + * @param pInvoker Unit that triggered this event (like an attacker) + */ + virtual void ReceiveAIEvent(AIEventType /*eventType*/, Creature* /*pSender*/, Unit* /*pInvoker*/) {} + protected: void HandleMovementOnAttackStart(Unit* victim); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 19b03f363..b81d620b0 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "12675" + #define REVISION_NR "12676" #endif // __REVISION_NR_H__