[12682] Add ACTION_T_THROW_AI_EVENT and EVENT_T_RECEIVE_AI_EVENT to …

original author @Schmoozerd, commit is based on
64fa443957
This commit is contained in:
sanctum32 2013-10-11 19:23:29 +03:00 committed by Antz
parent 2629260ba2
commit f41967cfa3
4 changed files with 105 additions and 30 deletions

View file

@ -158,7 +158,7 @@ inline bool IsTimerBasedEvent(EventAI_Type type)
}
}
bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker)
bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker, Creature* pAIEventSender)
{
if (!pHolder.Enabled || pHolder.Time)
return false;
@ -412,6 +412,8 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
pHolder.UpdateRepeatTimer(m_creature, event.buffed.repeatMin, event.buffed.repeatMax);
break;
}
case EVENT_T_RECEIVE_AI_EVENT:
break;
default:
sLog.outErrorEventAI("Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
break;
@ -432,7 +434,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
if (!(pHolder.Event.event_flags & EFLAG_RANDOM_ACTION))
{
for (uint32 j = 0; j < MAX_ACTIONS; ++j)
ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker);
ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker, pAIEventSender);
}
// Process actions, random case
else
@ -460,13 +462,13 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
}
}
ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker);
ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker, pAIEventSender);
}
}
return true;
}
void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker)
void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker, Creature* pAIEventSender)
{
if (action.type == ACTION_T_NONE)
return;
@ -588,7 +590,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
selectFlags = SELECT_FLAG_IN_LOS;
}
Unit* target = GetTargetByType(action.cast.target, pActionInvoker, spellId, selectFlags);
Unit* target = GetTargetByType(action.cast.target, pActionInvoker, pAIEventSender, spellId, selectFlags);
if (!target)
{
sLog.outDebug("CreatureEventAI: NULL target for ACTION_T_CAST creature entry %u casting spell id %u", m_creature->GetEntry(), action.cast.spellId);
@ -629,7 +631,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
}
case ACTION_T_SUMMON:
{
Unit* target = GetTargetByType(action.summon.target, pActionInvoker);
Unit* target = GetTargetByType(action.summon.target, pActionInvoker, pAIEventSender);
Creature* pCreature = NULL;
@ -645,7 +647,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
break;
}
case ACTION_T_THREAT_SINGLE_PCT:
if (Unit* target = GetTargetByType(action.threat_single_pct.target, pActionInvoker))
if (Unit* target = GetTargetByType(action.threat_single_pct.target, pActionInvoker, pAIEventSender))
m_creature->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent);
break;
case ACTION_T_THREAT_ALL_PCT:
@ -657,18 +659,18 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
break;
}
case ACTION_T_QUEST_EVENT:
if (Unit* target = GetTargetByType(action.quest_event.target, pActionInvoker))
if (Unit* target = GetTargetByType(action.quest_event.target, pActionInvoker, pAIEventSender))
if (target->GetTypeId() == TYPEID_PLAYER)
((Player*)target)->AreaExploredOrEventHappens(action.quest_event.questId);
break;
case ACTION_T_CAST_EVENT:
if (Unit* target = GetTargetByType(action.cast_event.target, pActionInvoker, 0, SELECT_FLAG_PLAYER))
if (Unit* target = GetTargetByType(action.cast_event.target, pActionInvoker, pAIEventSender, 0, SELECT_FLAG_PLAYER))
if (target->GetTypeId() == TYPEID_PLAYER)
((Player*)target)->CastedCreatureOrGO(action.cast_event.creatureId, m_creature->GetObjectGuid(), action.cast_event.spellId);
break;
case ACTION_T_SET_UNIT_FIELD:
{
Unit* target = GetTargetByType(action.set_unit_field.target, pActionInvoker);
Unit* target = GetTargetByType(action.set_unit_field.target, pActionInvoker, pAIEventSender);
// not allow modify important for integrity object fields
if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
@ -680,11 +682,11 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
break;
}
case ACTION_T_SET_UNIT_FLAG:
if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker))
if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker, pAIEventSender))
target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
break;
case ACTION_T_REMOVE_UNIT_FLAG:
if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker))
if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker, pAIEventSender))
target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
break;
case ACTION_T_AUTO_ATTACK:
@ -744,7 +746,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
break;
}
case ACTION_T_REMOVEAURASFROMSPELL:
if (Unit* target = GetTargetByType(action.remove_aura.target, pActionInvoker))
if (Unit* target = GetTargetByType(action.remove_aura.target, pActionInvoker, pAIEventSender))
target->RemoveAurasDueToSpell(action.remove_aura.spellId);
break;
case ACTION_T_RANGED_MOVEMENT:
@ -773,7 +775,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
break;
case ACTION_T_SUMMON_ID:
{
Unit* target = GetTargetByType(action.summon_id.target, pActionInvoker);
Unit* target = GetTargetByType(action.summon_id.target, pActionInvoker, pAIEventSender);
CreatureEventAI_Summon_Map::const_iterator i = sEventAIMgr.GetCreatureEventAISummonMap().find(action.summon_id.spawnId);
if (i == sEventAIMgr.GetCreatureEventAISummonMap().end())
@ -821,7 +823,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
}
case ACTION_T_SET_INST_DATA64:
{
Unit* target = GetTargetByType(action.set_inst_data64.target, pActionInvoker);
Unit* target = GetTargetByType(action.set_inst_data64.target, pActionInvoker, pAIEventSender);
if (!target)
{
sLog.outErrorEventAI("Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature->GetEntry());
@ -907,6 +909,11 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
break;
}
case ACTION_T_THROW_AI_EVENT:
{
SendAIEvent(AIEventType(action.throwEvent.eventType), pActionInvoker, 0, action.throwEvent.radius);
break;
}
}
}
@ -1070,6 +1077,19 @@ void CreatureEventAI::SummonedCreatureDespawn(Creature* pUnit)
}
}
void CreatureEventAI::ReceiveAIEvent(AIEventType eventType, Creature* pSender, Unit* pInvoker)
{
if (m_bEmptyList || !pSender)
return;
for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr)
{
if (itr->Event.event_type == EVENT_T_RECEIVE_AI_EVENT &&
itr->Event.receiveAIEvent.eventType == eventType && (!itr->Event.receiveAIEvent.senderEntry || itr->Event.receiveAIEvent.senderEntry == pSender->GetEntry()))
ProcessEvent(*itr, pInvoker, pSender);
}
}
void CreatureEventAI::EnterCombat(Unit* enemy)
{
// Check for on combat start events
@ -1288,7 +1308,7 @@ inline int32 CreatureEventAI::GetRandActionParam(uint32 rnd, int32 param1, int32
return 0;
}
inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoker, uint32 forSpellId, uint32 selectFlags)
inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoker, Creature* pAIEventSender, uint32 forSpellId, uint32 selectFlags)
{
switch (Target)
{
@ -1312,6 +1332,8 @@ inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoke
return pActionInvoker;
case TARGET_T_ACTION_INVOKER_OWNER:
return pActionInvoker ? pActionInvoker->GetCharmerOrOwnerOrSelf() : NULL;
case TARGET_T_EVENT_SENDER:
return pAIEventSender;
default:
return NULL;
};

View file

@ -63,6 +63,7 @@ enum EventAI_Type
EVENT_T_MISSING_AURA = 27, // Param1 = SpellID, Param2 = Number of time stacked expected, Param3/4 Repeat Min/Max
EVENT_T_TARGET_MISSING_AURA = 28, // Param1 = SpellID, Param2 = Number of time stacked expected, Param3/4 Repeat Min/Max
EVENT_T_TIMER_GENERIC = 29, // InitialMin, InitialMax, RepeatMin, RepeatMax
EVENT_T_RECEIVE_AI_EVENT = 30, // AIEventType, Sender-Entry, unused, unused
EVENT_T_END,
};
@ -114,6 +115,7 @@ enum EventAI_ActionType
ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue, format(0-flat,1-percent from max health)
ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to unmount)
ACTION_T_CHANCED_TEXT = 44, // Chance to display the text, TextId1, optionally TextId2. If more than just -TextId1 is defined, randomize. Negative values.
ACTION_T_THROW_AI_EVENT = 45, // EventType, Radius, unused
ACTION_T_END,
};
@ -123,19 +125,20 @@ enum Target
TARGET_T_SELF = 0, // Self cast
// Hostile targets (if pet then returns pet owner)
TARGET_T_HOSTILE, // Our current target (ie: highest aggro)
TARGET_T_HOSTILE_SECOND_AGGRO, // Second highest aggro (generaly used for cleaves and some special attacks)
TARGET_T_HOSTILE_LAST_AGGRO, // Dead last on aggro (no idea what this could be used for)
TARGET_T_HOSTILE_RANDOM, // Just any random target on our threat list
TARGET_T_HOSTILE_RANDOM_NOT_TOP, // Any random target except top threat
TARGET_T_HOSTILE = 1, // Our current target (ie: highest aggro)
TARGET_T_HOSTILE_SECOND_AGGRO = 2, // Second highest aggro (generaly used for cleaves and some special attacks)
TARGET_T_HOSTILE_LAST_AGGRO = 3, // Dead last on aggro (no idea what this could be used for)
TARGET_T_HOSTILE_RANDOM = 4, // Just any random target on our threat list
TARGET_T_HOSTILE_RANDOM_NOT_TOP = 5, // Any random target except top threat
// Invoker targets (if pet then returns pet owner)
TARGET_T_ACTION_INVOKER, // Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
TARGET_T_ACTION_INVOKER_OWNER, // Unit who is responsible for Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
TARGET_T_ACTION_INVOKER = 6, // Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
TARGET_T_ACTION_INVOKER_OWNER = 7, // Unit who is responsible for Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
TARGET_T_EVENT_SENDER = 10, // Unit who sent an AIEvent that was received with EVENT_T_RECEIVE_AI_EVENT
// Hostile targets (including pets)
TARGET_T_HOSTILE_RANDOM_PLAYER, // Just any random player on our threat list
TARGET_T_HOSTILE_RANDOM_NOT_TOP_PLAYER, // Any random player from threat list except top threat
TARGET_T_HOSTILE_RANDOM_PLAYER = 8, // Just any random player on our threat list
TARGET_T_HOSTILE_RANDOM_NOT_TOP_PLAYER = 9, // Any random player from threat list except top threat
TARGET_T_END
};
@ -392,6 +395,13 @@ struct CreatureEventAI_Action
uint32 chance;
int32 TextId[2];
} chanced_text;
// ACTION_T_THROW_AI_EVENT = 45
struct
{
uint32 eventType;
uint32 radius;
uint32 unused;
} throwEvent;
// RAW
struct
{
@ -537,6 +547,14 @@ struct CreatureEventAI_Event
uint32 repeatMin;
uint32 repeatMax;
} buffed;
// EVENT_T_RECEIVE_AI_EVENT = 30
struct
{
uint32 eventType; // See CreatureAI.h enum AIEventType - Receive only events of this type
uint32 senderEntry; // Optional npc from only whom this event can be received
uint32 unused1;
uint32 unused2;
} receiveAIEvent;
// RAW
struct
{
@ -607,14 +625,15 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI
void ReceiveEmote(Player* pPlayer, uint32 text_emote) override;
void SummonedCreatureJustDied(Creature* unit) override;
void SummonedCreatureDespawn(Creature* unit) override;
void ReceiveAIEvent(AIEventType eventType, Creature* pSender, Unit* pInvoker) override;
static int Permissible(const Creature*);
bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL);
void ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker);
bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL, Creature* pAIEventSender = NULL);
void ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker, Creature* pAIEventSender);
inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3);
inline int32 GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3);
inline Unit* GetTargetByType(uint32 Target, Unit* pActionInvoker, uint32 forSpellId = 0, uint32 selectFlags = 0);
inline Unit* GetTargetByType(uint32 Target, Unit* pActionInvoker, Creature* pAIEventSender, uint32 forSpellId = 0, uint32 selectFlags = 0);
void DoScriptText(int32 textEntry, WorldObject* pSource, Unit* target);

View file

@ -27,6 +27,7 @@
#include "ObjectGuid.h"
#include "GridDefines.h"
#include "SpellMgr.h"
#include "World.h"
INSTANTIATE_SINGLETON_1(CreatureEventAIMgr);
@ -486,7 +487,22 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
sLog.outErrorEventAI("Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
break;
}
case EVENT_T_RECEIVE_AI_EVENT:
{
// Sender-Creature does not exist in database
if (temp.receiveAIEvent.senderEntry && !sCreatureStorage.LookupEntry<CreatureInfo>(temp.receiveAIEvent.senderEntry))
{
sLog.outErrorDb("CreatureEventAI: Event %u has nonexisting creature (%u) defined for event RECEIVE_AI_EVENT, skipping.", i, temp.receiveAIEvent.senderEntry);
continue;
}
// Event-Type is not defined
if (temp.receiveAIEvent.eventType >= MAXIMAL_AI_EVENT_EVENTAI)
{
sLog.outErrorDb("CreatureEventAI: Event %u has unfitting event-type (%u) defined for event RECEIVE_AI_EVENT (must be less than %u), skipping.", i, temp.receiveAIEvent.eventType, MAXIMAL_AI_EVENT_EVENTAI);
continue;
}
break;
}
default:
sLog.outErrorEventAI("Creature %u using not checked at load event (%u) in event %u. Need check code update?", temp.creature_id, temp.event_id, i);
break;
@ -831,6 +847,24 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
case ACTION_T_RANDOM_TEXTEMOTE:
sLog.outErrorEventAI("Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j + 1);
break;
case ACTION_T_THROW_AI_EVENT:
if (action.throwEvent.eventType >= MAXIMAL_AI_EVENT_EVENTAI)
{
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses invalid event type %u (must be less than %u), skipping", i, j + 1, action.throwEvent.eventType, MAXIMAL_AI_EVENT_EVENTAI);
continue;
}
if (action.throwEvent.radius > SIZE_OF_GRIDS)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses unexpectedly huge radius %u (expected to be less than %f)", i, j + 1, action.throwEvent.radius, SIZE_OF_GRIDS);
if (action.throwEvent.radius == 0)
{
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses unexpected radius 0 (set to %f of CONFIG_FLOAT_CREATURE_FAMILY_ASSISTANCE_RADIUS)", i, j + 1, sWorld.getConfig(CONFIG_FLOAT_CREATURE_FAMILY_ASSISTANCE_RADIUS));
action.throwEvent.radius = uint32(sWorld.getConfig(CONFIG_FLOAT_CREATURE_FAMILY_ASSISTANCE_RADIUS));
}
break;
default:
sLog.outErrorEventAI("Event %u Action %u have currently not checked at load action type (%u). Need check code update?", i, j + 1, temp.action[j].type);
break;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "12681"
#define REVISION_NR "12682"
#endif // __REVISION_NR_H__