aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/CreatureEventAI.cpp412
-rw-r--r--src/game/CreatureEventAI.h224
-rw-r--r--src/game/CreatureEventAIMgr.cpp308
3 files changed, 527 insertions, 417 deletions
diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
index 3b8df3419da..1b412c3c314 100644
--- a/src/game/CreatureEventAI.cpp
+++ b/src/game/CreatureEventAI.cpp
@@ -464,37 +464,35 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
//Process actions
for (uint32 j = 0; j < MAX_ACTIONS; j++)
- ProcessAction(pHolder.Event.action[j].type, pHolder.Event.action[j].param1, pHolder.Event.action[j].param2, pHolder.Event.action[j].param3, rnd, pHolder.Event.event_id, pActionInvoker);
+ ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker);
return true;
}
-void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker)
+void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker)
{
- switch (type)
+ switch (action.type)
{
case ACTION_T_TEXT:
{
- if (!param1)
+ if (!action.text.TextId1)
return;
- uint32 temp = 0;
+ int32 temp = 0;
- if (param2 && param3)
+ if (action.text.TextId2 && action.text.TextId3)
{
switch( rand()%3 )
{
- case 0: temp = param1; break;
- case 2: temp = param2; break;
- case 3: temp = param3; break;
+ case 0: temp = action.text.TextId1; break;
+ case 2: temp = action.text.TextId2; break;
+ case 3: temp = action.text.TextId3; break;
}
- }else if ( param2 && urand(0,1) )
- {
- temp = param2;
- }else
- {
- temp = param1;
}
+ else if (action.text.TextId2 && urand(0,1))
+ temp = action.text.TextId2;
+ else
+ temp = action.text.TextId1;
if (temp)
{
@@ -520,12 +518,12 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
DoScriptText(temp, m_creature, target);
}
+ break;
}
- break;
case ACTION_T_SET_FACTION:
{
- if (param1)
- m_creature->setFaction(param1);
+ if (action.set_faction.factionId)
+ m_creature->setFaction(action.set_faction.factionId);
else
{
if (CreatureInfo const* ci = GetCreatureTemplateStore(m_creature->GetEntry()))
@@ -535,16 +533,16 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
m_creature->setFaction(ci->faction_A);
}
}
+ break;
}
- break;
case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
{
- if (param1 || param2)
+ if (action.morph.creatireId || action.morph.modelId)
{
//set model based on entry from creature_template
- if (param1)
+ if (action.morph.creatireId)
{
- if (CreatureInfo const* ci = GetCreatureTemplateStore(param1))
+ if (CreatureInfo const* ci = GetCreatureTemplateStore(action.morph.creatireId))
{
//use default display
if (ci->Modelid_A1)
@@ -553,72 +551,66 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
}
//if no param1, then use value from param2 (modelId)
else
- m_creature->SetDisplayId(param2);
+ m_creature->SetDisplayId(action.morph.modelId);
}
else
m_creature->DeMorph();
+ break;
}
- break;
case ACTION_T_SOUND:
- m_creature->PlayDirectSound(param1);
+ m_creature->PlayDirectSound(action.sound.soundId);
break;
case ACTION_T_EMOTE:
- m_creature->HandleEmoteCommand(param1);
+ m_creature->HandleEmoteCommand(action.emote.emoteId);
break;
case ACTION_T_RANDOM_SOUND:
{
- uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
-
- if (temp != uint32(0xffffffff))
- m_creature->PlayDirectSound( temp );
+ int32 temp = GetRandActionParam(rnd, action.random_sound.soundId1, action.random_sound.soundId2, action.random_sound.soundId3);
+ if (temp >= 0)
+ m_creature->PlayDirectSound(temp);
+ break;
}
- break;
case ACTION_T_RANDOM_EMOTE:
{
- uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
-
- if (temp != uint32(0xffffffff))
+ int32 temp = GetRandActionParam(rnd, action.random_emote.emoteId1, action.random_emote.emoteId2, action.random_emote.emoteId3);
+ if (temp >= 0)
m_creature->HandleEmoteCommand(temp);
+ break;
}
- break;
case ACTION_T_CAST:
{
- Unit* target = GetTargetByType(param2, pActionInvoker);
+ Unit* target = GetTargetByType(action.cast.target, pActionInvoker);
Unit* caster = m_creature;
if (!target)
return;
- //Cast is always triggered if target is forced to cast on self
- if (param3 & CAST_FORCE_TARGET_SELF)
- {
- param3 |= CAST_TRIGGERED;
+ if (action.cast.castFlags & CAST_FORCE_TARGET_SELF)
caster = target;
- }
//Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
- bool canCast = !caster->IsNonMeleeSpellCasted(false) || (param3 & (CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS));
+ bool canCast = !caster->IsNonMeleeSpellCasted(false) || (action.cast.castFlags & (CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS));
// If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
- if(param3 & CAST_AURA_NOT_PRESENT)
+ if(action.cast.castFlags & CAST_AURA_NOT_PRESENT)
{
- if(target->HasAura(param1))
+ if(target->HasAura(action.cast.spellId))
return;
}
if (canCast)
{
- const SpellEntry* tSpell = GetSpellStore()->LookupEntry(param1);
+ const SpellEntry* tSpell = GetSpellStore()->LookupEntry(action.cast.spellId);
//Verify that spell exists
if (tSpell)
{
//Check if cannot cast spell
- if (!(param3 & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
- !CanCast(target, tSpell, (param3 & CAST_TRIGGERED)))
+ if (!(action.cast.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
+ !CanCast(target, tSpell, (action.cast.castFlags & CAST_TRIGGERED)))
{
//Melee current victim if flag not set
- if (!(param3 & CAST_NO_MELEE_IF_OOM))
+ if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM))
{
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
{
@@ -633,111 +625,83 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
else
{
//Interrupt any previous spell
- if (caster->IsNonMeleeSpellCasted(false) && param3 & CAST_INTURRUPT_PREVIOUS)
+ if (caster->IsNonMeleeSpellCasted(false) && action.cast.castFlags & CAST_INTURRUPT_PREVIOUS)
caster->InterruptNonMeleeSpells(false);
- caster->CastSpell(target, param1, (param3 & CAST_TRIGGERED));
+ caster->CastSpell(target, action.cast.spellId, (action.cast.castFlags & CAST_TRIGGERED));
}
- }else
- sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), param1);
+ }
+ else
+ sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), action.cast.spellId);
}
+ break;
}
- break;
case ACTION_T_SUMMON:
{
- Unit* target = GetTargetByType(param2, pActionInvoker);
+ Unit* target = GetTargetByType(action.summon.target, pActionInvoker);
Creature* pCreature = NULL;
- if (param3)
- pCreature = m_creature->SummonCreature(param1, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3);
+ if (action.summon.duration)
+ pCreature = m_creature->SummonCreature(action.summon.creatured, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, action.summon.duration);
else
- pCreature = m_creature->SummonCreature(param1, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
+ pCreature = m_creature->SummonCreature(action.summon.creatured, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
if (!pCreature)
- {
-
- sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature->GetEntry());
- }
- else if (param2 != TARGET_T_SELF && target)
+ sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", action.summon.creatured, EventId, m_creature->GetEntry());
+ else if (action.summon.target != TARGET_T_SELF && target)
pCreature->AI()->AttackStart(target);
+ break;
}
- break;
case ACTION_T_THREAT_SINGLE_PCT:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- if (target)
- m_creature->getThreatManager().modifyThreatPercent(target, param1);
- }
- break;
+ if (Unit* target = GetTargetByType(action.threat_single_pct.target, pActionInvoker))
+ m_creature->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent);
+ break;
case ACTION_T_THREAT_ALL_PCT:
{
- Unit* Temp = NULL;
-
- std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
- for (; i != m_creature->getThreatManager().getThreatList().end(); ++i)
- {
- Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid());
- if (Temp)
- m_creature->getThreatManager().modifyThreatPercent(Temp, param1);
- }
+ std::list<HostilReference*>& threatList = m_creature->getThreatManager().getThreatList();
+ for (std::list<HostilReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i)
+ if(Unit* Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid()))
+ m_creature->getThreatManager().modifyThreatPercent(Temp, action.threat_all_pct.percent);
+ break;
}
- break;
case ACTION_T_QUEST_EVENT:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- if (target && target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)target)->AreaExploredOrEventHappens(param1);
- }
- break;
- case ACTION_T_CASTCREATUREGO:
- {
- Unit* target = GetTargetByType(param3, pActionInvoker);
-
- if (target && target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)target)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2);
- }
- break;
+ if (Unit* target = GetTargetByType(action.quest_event.target, pActionInvoker))
+ 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))
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)target)->CastedCreatureOrGO(action.cast_event.creatureId, m_creature->GetGUID(), action.cast_event.spellId);
+ break;
case ACTION_T_SET_UNIT_FIELD:
{
- Unit* target = GetTargetByType(param3, pActionInvoker);
+ Unit* target = GetTargetByType(action.set_unit_field.target, pActionInvoker);
- if (param1 < OBJECT_END || param1 >= UNIT_END)
+ // not allow modify important for integrity object fields
+ if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
return;
if (target)
- target->SetUInt32Value(param1, param2);
- }
- break;
- case ACTION_T_SET_UNIT_FLAG:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
+ target->SetUInt32Value(action.set_unit_field.field, action.set_unit_field.value);
- if (target)
- target->SetFlag(UNIT_FIELD_FLAGS, param1);
+ break;
}
- break;
+ case ACTION_T_SET_UNIT_FLAG:
+ if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker))
+ target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
+ break;
case ACTION_T_REMOVE_UNIT_FLAG:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- if (target)
- target->RemoveFlag(UNIT_FIELD_FLAGS, param1);
- }
- break;
+ if (Unit* target = GetTargetByType(action.unit_flag.target, pActionInvoker))
+ target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
+ break;
case ACTION_T_AUTO_ATTACK:
- {
- if (param1)
- MeleeEnabled = true;
- else MeleeEnabled = false;
- }
- break;
+ MeleeEnabled = action.auto_attack.state != 0;
+ break;
case ACTION_T_COMBAT_MOVEMENT:
- {
- CombatMovementEnabled = param1;
+ CombatMovementEnabled = action.combat_movement.state != 0;
//Allow movement (create new targeted movement gen only if idle)
if (CombatMovementEnabled)
@@ -748,140 +712,113 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
{
m_creature->GetMotionMaster()->MoveIdle();
}
- }
- break;
+ break;
case ACTION_T_SET_PHASE:
- {
- Phase = param1;
- }
- break;
+ Phase = action.set_phase.phase;
+ break;
case ACTION_T_INC_PHASE:
{
- Phase += param1;
-
- if (Phase > 31)
+ int32 new_phase = int32(Phase)+action.set_inc_phase.step;
+ if (new_phase < 0)
+ {
+ sLog.outErrorDb( "CreatureEventAI: Event %d decrease Phase under 0. CreatureEntry = %d", EventId, m_creature->GetEntry());
+ Phase = 0;
+ }
+ else if (new_phase >= MAX_PHASE)
+ {
+ sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above %u. Phase mask cannot be used with phases past %u. CreatureEntry = %d", EventId, MAX_PHASE-1, MAX_PHASE-1, m_creature->GetEntry());
+ Phase = MAX_PHASE-1;
+ }
+ else
+ Phase = new_phase;
- sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature->GetEntry());
+ break;
}
- break;
case ACTION_T_EVADE:
- {
EnterEvadeMode();
- }
- break;
+ break;
case ACTION_T_FLEE:
- {
- if(m_creature->HasAuraType(SPELL_AURA_PREVENTS_FLEEING))
- break;
- TimetoFleeLeft = 8000;
- m_creature->DoFleeToGetAssistance();
- IsFleeing = true;
- }
+ if(me->HasAuraType(SPELL_AURA_PREVENTS_FLEEING))
+ break;
+ TimetoFleeLeft = 8000;
+ me->DoFleeToGetAssistance();
+ IsFleeing = true;
break;
case ACTION_T_QUEST_EVENT_ALL:
- {
- Unit* Temp = NULL;
- if( pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER )
+ if (pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER)
{
- Temp = Unit::GetUnit(*m_creature,pActionInvoker->GetGUID());
- if( Temp )
- ((Player*)Temp)->GroupEventHappens(param1,m_creature);
+ if (Unit* Temp = Unit::GetUnit(*m_creature,pActionInvoker->GetGUID()))
+ if (Temp->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)Temp)->GroupEventHappens(action.quest_event_all.questId,m_creature);
}
- }
- break;
- case ACTION_T_CASTCREATUREGO_ALL:
+ break;
+ case ACTION_T_CAST_EVENT_ALL:
{
- Unit* Temp = NULL;
-
- std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
- for (; i != m_creature->getThreatManager().getThreatList().end(); ++i)
- {
- Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid());
- if (Temp && Temp->GetTypeId() == TYPEID_PLAYER)
- ((Player*)Temp)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2);
- }
+ std::list<HostilReference*>& threatList = m_creature->getThreatManager().getThreatList();
+ for (std::list<HostilReference*>::iterator i = threatList.begin(); i != threatList.end(); ++i)
+ if (Unit* Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid()))
+ if (Temp->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)Temp)->CastedCreatureOrGO(action.cast_event_all.creatureId, m_creature->GetGUID(), action.cast_event_all.spellId);
+ break;
}
- break;
case ACTION_T_REMOVEAURASFROMSPELL:
- {
- Unit* target = GetTargetByType(param1, pActionInvoker);
-
- if (target)
- target->RemoveAurasDueToSpell(param2);
- }
- break;
+ if (Unit* target = GetTargetByType(action.remove_aura.target, pActionInvoker))
+ target->RemoveAurasDueToSpell(action.remove_aura.spellId);
+ break;
case ACTION_T_RANGED_MOVEMENT:
- {
- AttackDistance = param1;
- AttackAngle = ((float)param2/180)*M_PI;
+ AttackDistance = action.ranged_movement.distance;
+ AttackAngle = ((float)action.ranged_movement.angle/180)*M_PI;
if (CombatMovementEnabled)
{
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle);
}
- }
- break;
+ break;
case ACTION_T_RANDOM_PHASE:
- {
- uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
-
- Phase = temp;
- }
- break;
+ Phase = GetRandActionParam(rnd, action.random_phase.phase1, action.random_phase.phase2, action.random_phase.phase3);
+ break;
case ACTION_T_RANDOM_PHASE_RANGE:
- {
- if (param2 > param1)
- {
- Phase = param1 + (rnd % (param2 - param1));
- }
+ if (action.random_phase_range.phaseMax > action.random_phase_range.phaseMin)
+ Phase = action.random_phase_range.phaseMin + (rnd % (action.random_phase_range.phaseMax - action.random_phase_range.phaseMin));
else
sLog.outErrorDb( "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature->GetEntry());
- }
- break;
+ break;
case ACTION_T_SUMMON_ID:
{
- Unit* target = GetTargetByType(param2, pActionInvoker);
+ Unit* target = GetTargetByType(action.summon_id.target, pActionInvoker);
- //Duration
- Creature* pCreature = NULL;
-
- CreatureEventAI_Summon_Map::const_iterator i = CreatureEAI_Mgr.GetCreatureEventAISummonMap().find(param3);
+ CreatureEventAI_Summon_Map::const_iterator i = CreatureEAI_Mgr.GetCreatureEventAISummonMap().find(action.summon_id.spawnId);
if (i == CreatureEAI_Mgr.GetCreatureEventAISummonMap().end())
{
-
- sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature->GetEntry());
+ sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", action.summon_id.creatureId, action.summon_id.spawnId, EventId, m_creature->GetEntry());
return;
}
+ Creature* pCreature = NULL;
if ((*i).second.SpawnTimeSecs)
- pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
- else pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
+ pCreature = m_creature->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
+ else
+ pCreature = m_creature->SummonCreature(action.summon_id.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
if (!pCreature)
- {
-
- sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature->GetEntry());
- }
- else if (param2 != TARGET_T_SELF && target)
+ sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", action.summon_id.creatureId, EventId, m_creature->GetEntry());
+ else if (action.summon_id.target != TARGET_T_SELF && target)
pCreature->AI()->AttackStart(target);
+
+ break;
}
- break;
case ACTION_T_KILLED_MONSTER:
- {
//first attempt player who tapped creature
if (Player* pPlayer = m_creature->GetLootRecipient())
- pPlayer->RewardPlayerAndGroupAtEvent(param1, m_creature);
+ pPlayer->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, m_creature);
else
{
//if not available, use pActionInvoker
- if (Unit* pTarget = GetTargetByType(param2, pActionInvoker))
- {
+ if (Unit* pTarget = GetTargetByType(action.killed_monster.target, pActionInvoker))
if (Player* pPlayer2 = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself())
- pPlayer2->RewardPlayerAndGroupAtEvent(param1, m_creature);
- }
+ pPlayer2->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, m_creature);
}
- }
- break;
+ break;
case ACTION_T_SET_INST_DATA:
{
InstanceData* pInst = (InstanceData*)m_creature->GetInstanceData();
@@ -891,12 +828,12 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
return;
}
- pInst->SetData(param1, param2);
+ pInst->SetData(action.set_inst_data.field, action.set_inst_data.value);
+ break;
}
- break;
case ACTION_T_SET_INST_DATA64:
{
- Unit* target = GetTargetByType(param2, pActionInvoker);
+ Unit* target = GetTargetByType(action.set_inst_data64.target, pActionInvoker);
if (!target)
{
sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature->GetEntry());
@@ -910,19 +847,19 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
return;
}
- pInst->SetData64(param1, target->GetGUID());
+ pInst->SetData64(action.set_inst_data64.field, target->GetGUID());
+ break;
}
- break;
case ACTION_T_UPDATE_TEMPLATE:
{
- if (m_creature->GetEntry() == param1)
+ if (m_creature->GetEntry() == action.update_template.creatureId)
{
sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature->GetEntry());
return;
}
- m_creature->UpdateEntry(param1, param2 ? HORDE : ALLIANCE);
+ m_creature->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE);
}
break;
case ACTION_T_DIE:
@@ -951,13 +888,13 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
// TRINITY ONLY
case ACTION_T_SET_ACTIVE:
- me->setActive(param1 ? true : false);
+ me->setActive(action.raw.param1 ? true : false);
break;
case ACTION_T_SET_AGGRESSIVE:
- me->SetReactState(ReactStates(param1));
+ me->SetReactState(ReactStates(action.raw.param1));
break;
case ACTION_T_ATTACK_START_PULSE:
- AttackStart(me->SelectNearestTarget((float)param1));
+ AttackStart(me->SelectNearestTarget((float)action.raw.param1));
break;
case ACTION_T_SUMMON_GO:
{
@@ -965,16 +902,16 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
float x,y,z;
m_creature->GetPosition(x,y,z);
- pObject = m_creature->SummonGameObject(param1, x, y, z, 0, 0, 0, 0, 0, param2);
+ pObject = m_creature->SummonGameObject(action.raw.param1, x, y, z, 0, 0, 0, 0, 0, action.raw.param2);
if (!pObject)
{
- sLog.outErrorDb("TSCR: EventAI failed to spawn object %u. Spawn event %d is on creature %d", param1, EventId, m_creature->GetEntry());
+ sLog.outErrorDb("TSCR: EventAI failed to spawn object %u. Spawn event %d is on creature %d", action.raw.param1, EventId, m_creature->GetEntry());
}
break;
}
case ACTION_T_CALL_ASSISTANCE:
m_creature->SetNoCallAssistance(false);
- m_creature->CallAssistance(param1);
+ m_creature->CallAssistance(action.raw.param1);
break;
}
}
@@ -1347,15 +1284,20 @@ inline uint32 CreatureEventAI::GetRandActionParam(uint32 rnd, uint32 param1, uin
{
switch (rnd % 3)
{
- case 0:
- return param1;
- break;
- case 1:
- return param2;
- break;
- case 2:
- return param3;
- break;
+ case 0: return param1;
+ case 1: return param2;
+ case 2: return param3;
+ }
+ return 0;
+}
+
+inline int32 CreatureEventAI::GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3)
+{
+ switch (rnd % 3)
+ {
+ case 0: return param1;
+ case 1: return param2;
+ case 2: return param3;
}
return 0;
}
@@ -1366,28 +1308,20 @@ inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoke
{
case TARGET_T_SELF:
return m_creature;
- break;
case TARGET_T_HOSTILE:
return m_creature->getVictim();
- break;
case TARGET_T_HOSTILE_SECOND_AGGRO:
return SelectUnit(ATTACKING_TARGET_TOPAGGRO,1);
- break;
case TARGET_T_HOSTILE_LAST_AGGRO:
return SelectUnit(ATTACKING_TARGET_BOTTOMAGGRO,0);
- break;
case TARGET_T_HOSTILE_RANDOM:
return SelectUnit(ATTACKING_TARGET_RANDOM,0);
- break;
case TARGET_T_HOSTILE_RANDOM_NOT_TOP:
return SelectUnit(ATTACKING_TARGET_RANDOM,1);
- break;
case TARGET_T_ACTION_INVOKER:
return pActionInvoker;
- break;
default:
return NULL;
- break;
};
}
diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h
index 006cd7df08b..412a3b1919d 100644
--- a/src/game/CreatureEventAI.h
+++ b/src/game/CreatureEventAI.h
@@ -30,6 +30,7 @@ class WorldObject;
#define EVENT_UPDATE_TIME 500
#define SPELL_RUN_AWAY 8225
#define MAX_ACTIONS 3
+#define MAX_PHASE 32
enum EventAI_Type
{
@@ -78,7 +79,7 @@ enum EventAI_ActionType
ACTION_T_THREAT_SINGLE_PCT = 13, //*Threat%, Target
ACTION_T_THREAT_ALL_PCT = 14, //Threat%
ACTION_T_QUEST_EVENT = 15, //*QuestID, Target
- ACTION_T_CASTCREATUREGO = 16, //*QuestID, SpellId, Target
+ ACTION_T_CAST_EVENT = 16, //*QuestID, SpellId, Target - must be removed as hack?
ACTION_T_SET_UNIT_FIELD = 17, //*Field_Number, Value, Target
ACTION_T_SET_UNIT_FLAG = 18, //*Flags (may be more than one field OR'd together), Target
ACTION_T_REMOVE_UNIT_FLAG = 19, //*Flags (may be more than one field OR'd together), Target
@@ -89,7 +90,7 @@ enum EventAI_ActionType
ACTION_T_EVADE = 24, //No Params
ACTION_T_FLEE = 25, //No Params
ACTION_T_QUEST_EVENT_ALL = 26, //*QuestID
- ACTION_T_CASTCREATUREGO_ALL = 27, //*QuestId, SpellId
+ ACTION_T_CAST_EVENT_ALL = 27, //*QuestId, SpellId
ACTION_T_REMOVEAURASFROMSPELL = 28, //*Target, Spellid
ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle
ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3
@@ -171,6 +172,202 @@ struct StringTextData
// Text Maps
typedef UNORDERED_MAP<int32, StringTextData> CreatureEventAI_TextMap;
+struct CreatureEventAI_Action
+{
+ EventAI_ActionType type: 16;
+ union
+ {
+ // ACTION_T_TEXT = 1
+ struct
+ {
+ int32 TextId1;
+ int32 TextId2;
+ int32 TextId3;
+ } text;
+ // ACTION_T_SET_FACTION = 2
+ struct
+ {
+ uint32 factionId; // faction or 0 for default)
+ } set_faction;
+ // ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3
+ struct
+ {
+ uint32 creatireId; // set one from fields (or 0 for both to demorph)
+ uint32 modelId;
+ } morph;
+ // ACTION_T_SOUND = 4
+ struct
+ {
+ uint32 soundId;
+ } sound;
+ // ACTION_T_EMOTE = 5
+ struct
+ {
+ uint32 emoteId;
+ } emote;
+ // ACTION_T_RANDOM_SOUND = 9
+ struct
+ {
+ int32 soundId1; // (-1 in any field means no output if randomed that field)
+ int32 soundId2;
+ int32 soundId3;
+ } random_sound;
+ // ACTION_T_RANDOM_EMOTE = 10
+ struct
+ {
+ int32 emoteId1; // (-1 in any field means no output if randomed that field)
+ int32 emoteId2;
+ int32 emoteId3;
+ } random_emote;
+ // ACTION_T_CAST = 11
+ struct
+ {
+ uint32 spellId;
+ uint32 target;
+ uint32 castFlags;
+ } cast;
+ // ACTION_T_SUMMON = 12
+ struct
+ {
+ uint32 creatured;
+ uint32 target;
+ uint32 duration;
+ } summon;
+ // ACTION_T_THREAT_SINGLE_PCT = 13
+ struct
+ {
+ int32 percent;
+ uint32 target;
+ } threat_single_pct;
+ // ACTION_T_THREAT_ALL_PCT = 14
+ struct
+ {
+ int32 percent;
+ } threat_all_pct;
+ // ACTION_T_QUEST_EVENT = 15
+ struct
+ {
+ uint32 questId;
+ uint32 target;
+ } quest_event;
+ // ACTION_T_CAST_EVENT = 16
+ struct
+ {
+ uint32 creatureId;
+ uint32 spellId;
+ uint32 target;
+ } cast_event;
+ // ACTION_T_SET_UNIT_FIELD = 17
+ struct
+ {
+ uint32 field;
+ uint32 value;
+ uint32 target;
+ } set_unit_field;
+ // ACTION_T_SET_UNIT_FLAG = 18, // value provided mask bits that will be set
+ // ACTION_T_REMOVE_UNIT_FLAG = 19, // value provided mask bits that will be clear
+ struct
+ {
+ uint32 value;
+ uint32 target;
+ } unit_flag;
+ // ACTION_T_AUTO_ATTACK = 20
+ struct
+ {
+ uint32 state; // 0 = stop attack, anything else means continue attacking
+ } auto_attack;
+ // ACTION_T_COMBAT_MOVEMENT = 21
+ struct
+ {
+ uint32 state; // 0 = stop combat based movement, anything else continue attacking
+ } combat_movement;
+ // ACTION_T_SET_PHASE = 22
+ struct
+ {
+ uint32 phase;
+ } set_phase;
+ // ACTION_T_INC_PHASE = 23
+ struct
+ {
+ int32 step;
+ } set_inc_phase;
+ // ACTION_T_QUEST_EVENT_ALL = 26
+ struct
+ {
+ uint32 questId;
+ } quest_event_all;
+ // ACTION_T_CAST_EVENT_ALL = 27
+ struct
+ {
+ uint32 creatureId;
+ uint32 spellId;
+ } cast_event_all;
+ // ACTION_T_REMOVEAURASFROMSPELL = 28
+ struct
+ {
+ uint32 target;
+ uint32 spellId;
+ } remove_aura;
+ // ACTION_T_RANGED_MOVEMENT = 29
+ struct
+ {
+ uint32 distance;
+ int32 angle;
+ } ranged_movement;
+ // ACTION_T_RANDOM_PHASE = 30
+ struct
+ {
+ uint32 phase1;
+ uint32 phase2;
+ uint32 phase3;
+ } random_phase;
+ // ACTION_T_RANDOM_PHASE_RANGE = 31
+ struct
+ {
+ uint32 phaseMin;
+ uint32 phaseMax;
+ } random_phase_range;
+ // ACTION_T_SUMMON_ID = 32
+ struct
+ {
+ uint32 creatureId;
+ uint32 target;
+ uint32 spawnId;
+ } summon_id;
+ // ACTION_T_KILLED_MONSTER = 33
+ struct
+ {
+ uint32 creatureId;
+ uint32 target;
+ } killed_monster;
+ // ACTION_T_SET_INST_DATA = 34
+ struct
+ {
+ uint32 field;
+ uint32 value;
+ } set_inst_data;
+ // ACTION_T_SET_INST_DATA64 = 35
+ struct
+ {
+ uint32 field;
+ uint32 target;
+ } set_inst_data64;
+ // ACTION_T_UPDATE_TEMPLATE = 36, //*Entry, Team
+ struct
+ {
+ uint32 creatureId;
+ uint32 team;
+ } update_template;
+ // RAW
+ struct
+ {
+ uint32 param1;
+ uint32 param2;
+ uint32 param3;
+ } raw;
+ };
+};
+
struct CreatureEventAI_Event
{
uint32 event_id;
@@ -204,25 +401,7 @@ struct CreatureEventAI_Event
int32 event_param4_s;
};
- struct _action
- {
- EventAI_ActionType type: 16;
- union
- {
- uint32 param1;
- int32 param1_s;
- };
- union
- {
- uint32 param2;
- int32 param2_s;
- };
- union
- {
- uint32 param3;
- int32 param3_s;
- };
- }action[MAX_ACTIONS];
+ CreatureEventAI_Action action[MAX_ACTIONS];
};
//Event_Map
typedef UNORDERED_MAP<uint32, std::vector<CreatureEventAI_Event> > CreatureEventAI_Event_Map;
@@ -275,8 +454,9 @@ class TRINITY_DLL_SPEC CreatureEventAI : public CreatureAI
static int Permissible(const Creature *);
bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL);
- void ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker);
+ void ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 EventId, Unit* pActionInvoker);
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);
inline Unit* SelectUnit(AttackingTarget target, uint32 position);
diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp
index 01c92ade6db..a8e3f04db71 100644
--- a/src/game/CreatureEventAIMgr.cpp
+++ b/src/game/CreatureEventAIMgr.cpp
@@ -388,251 +388,252 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
continue;
}
- temp.action[j].type = EventAI_ActionType(action_type);
- temp.action[j].param1 = fields[11+(j*4)].GetUInt32();
- temp.action[j].param2 = fields[12+(j*4)].GetUInt32();
- temp.action[j].param3 = fields[13+(j*4)].GetUInt32();
+ CreatureEventAI_Action& action = temp.action[j];
+
+ action.type = EventAI_ActionType(action_type);
+ action.raw.param1 = fields[11+(j*4)].GetUInt32();
+ action.raw.param2 = fields[12+(j*4)].GetUInt32();
+ action.raw.param3 = fields[13+(j*4)].GetUInt32();
//Report any errors in actions
- switch (temp.action[j].type)
+ switch (action.type)
{
case ACTION_T_NONE:
break;
case ACTION_T_TEXT:
{
- if (temp.action[j].param1_s < 0)
+ if (action.text.TextId1 < 0)
{
- if (m_CreatureEventAI_TextMap.find(temp.action[j].param1_s) == m_CreatureEventAI_TextMap.end())
+ if (m_CreatureEventAI_TextMap.find(action.text.TextId1) == m_CreatureEventAI_TextMap.end())
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1);
}
- if (temp.action[j].param2_s < 0)
+ if (action.text.TextId2 < 0)
{
- if (m_CreatureEventAI_TextMap.find(temp.action[j].param2_s) == m_CreatureEventAI_TextMap.end())
+ if (m_CreatureEventAI_TextMap.find(action.text.TextId2) == m_CreatureEventAI_TextMap.end())
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1);
- if (!temp.action[j].param1_s)
+ if (!action.text.TextId1)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1);
}
- if (temp.action[j].param3_s < 0)
+ if (action.text.TextId3 < 0)
{
- if (m_CreatureEventAI_TextMap.find(temp.action[j].param3_s) == m_CreatureEventAI_TextMap.end())
+ if (m_CreatureEventAI_TextMap.find(action.text.TextId3) == m_CreatureEventAI_TextMap.end())
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1);
- if (!temp.action[j].param1_s || !temp.action[j].param2_s)
+ if (!action.text.TextId1 || !action.text.TextId2)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1);
}
break;
}
case ACTION_T_SET_FACTION:
- if (temp.action[j].param1 !=0 && !sFactionStore.LookupEntry(temp.action[j].param1))
+ if (action.set_faction.factionId !=0 && !sFactionStore.LookupEntry(action.set_faction.factionId))
{
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant FactionId %u.", i, j+1, temp.action[j].param1);
- temp.action[j].param1 = 0;
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent FactionId %u.", i, j+1, action.set_faction.factionId);
+ action.set_faction.factionId = 0;
}
break;
case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
- if (temp.action[j].param1 !=0 || temp.action[j].param2 !=0)
+ if (action.morph.creatireId !=0 || action.morph.modelId !=0)
{
- if (temp.action[j].param1 && !sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
+ if (action.morph.creatireId && !sCreatureStorage.LookupEntry<CreatureInfo>(action.morph.creatireId))
{
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, temp.action[j].param1);
- temp.action[j].param1 = 0;
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, action.morph.creatireId);
+ action.morph.creatireId = 0;
}
- if (temp.action[j].param2 && !sCreatureDisplayInfoStore.LookupEntry(temp.action[j].param2))
+ if (action.morph.modelId)
{
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, temp.action[j].param2);
- temp.action[j].param2 = 0;
+ if (action.morph.creatireId)
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.morph.modelId,action.morph.creatireId);
+ action.morph.modelId = 0;
+ }
+ else if (!sCreatureDisplayInfoStore.LookupEntry(action.morph.modelId))
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, action.morph.modelId);
+ action.morph.modelId = 0;
+ }
}
+
+ break;
}
- break;
case ACTION_T_SOUND:
- if (!sSoundEntriesStore.LookupEntry(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
- break;
- case ACTION_T_RANDOM_SOUND:
- if (!sSoundEntriesStore.LookupEntry(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
- if (temp.action[j].param2_s >= 0 && !sSoundEntriesStore.LookupEntry(temp.action[j].param2))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, temp.action[j].param2);
- if (temp.action[j].param3_s >= 0 && !sSoundEntriesStore.LookupEntry(temp.action[j].param3))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, temp.action[j].param3);
+ if (!sSoundEntriesStore.LookupEntry(action.sound.soundId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId);
break;
case ACTION_T_EMOTE:
- if (!sEmotesStore.LookupEntry(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param1);
+ if (!sEmotesStore.LookupEntry(action.emote.emoteId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.emote.emoteId);
+ break;
+ case ACTION_T_RANDOM_SOUND:
+ if (!sSoundEntriesStore.LookupEntry(action.random_sound.soundId1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId1);
+ if (action.random_sound.soundId2 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId2))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId2);
+ if (action.random_sound.soundId3 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId3))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId3);
break;
case ACTION_T_RANDOM_EMOTE:
- if (!sEmotesStore.LookupEntry(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param1);
- if (temp.action[j].param2_s >= 0 && !sEmotesStore.LookupEntry(temp.action[j].param2))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param2);
- if (temp.action[j].param3_s >= 0 && !sEmotesStore.LookupEntry(temp.action[j].param3))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param3);
+ if (!sEmotesStore.LookupEntry(action.random_emote.emoteId1))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId1);
+ if (action.random_emote.emoteId2 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId2))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId2);
+ if (action.random_emote.emoteId3 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId3))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId3);
break;
case ACTION_T_CAST:
{
- const SpellEntry *spell = sSpellStore.LookupEntry(temp.action[j].param1);
+ const SpellEntry *spell = sSpellStore.LookupEntry(action.cast.spellId);
if (!spell)
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1);
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast.spellId);
else
{
if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE)
{
//output as debug for now, also because there's no general rule all spells have RecoveryTime
if (temp.event_param3 < spell->RecoveryTime)
- sLog.outDebug("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1,temp.action[j].param1, spell->RecoveryTime, temp.event_param3);
+ sLog.outDebug("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1,action.cast.spellId, spell->RecoveryTime, temp.event_param3);
}
}
- if (temp.action[j].param2 >= TARGET_T_END)
+ //Cast is always triggered if target is forced to cast on self
+ if (action.cast.castFlags & CAST_FORCE_TARGET_SELF)
+ action.cast.castFlags |= CAST_TRIGGERED;
+
+ if (action.cast.target >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
}
- case ACTION_T_REMOVEAURASFROMSPELL:
- {
- if (!sSpellStore.LookupEntry(temp.action[j].param2))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
+ case ACTION_T_SUMMON:
+ if (!sCreatureStorage.LookupEntry<CreatureInfo>(action.summon.creatured))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.summon.creatured);
- if (temp.action[j].param1 >= TARGET_T_END)
+ if (action.summon.target >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
- }
+ case ACTION_T_THREAT_SINGLE_PCT:
+ if (std::abs(action.threat_single_pct.percent) > 100)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_single_pct.percent);
+ if (action.threat_single_pct.target >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ break;
+ case ACTION_T_THREAT_ALL_PCT:
+ if (std::abs(action.threat_all_pct.percent) > 100)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_all_pct.percent);
+ break;
case ACTION_T_QUEST_EVENT:
- {
- if (Quest const* qid = objmgr.GetQuestTemplate(temp.action[j].param1))
+ if (Quest const* qid = objmgr.GetQuestTemplate(action.quest_event.questId))
{
if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1);
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event.questId);
}
else
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event.questId);
- if (temp.action[j].param2 >= TARGET_T_END)
+ if (action.quest_event.target >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
- }
+ case ACTION_T_CAST_EVENT:
+ if (!sCreatureStorage.LookupEntry<CreatureInfo>(action.cast_event.creatureId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event.creatureId);
+ if (!sSpellStore.LookupEntry(action.cast_event.spellId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event.spellId);
+ if (action.cast_event.target >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ break;
+ case ACTION_T_SET_UNIT_FIELD:
+ if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1);
+ if (action.set_unit_field.target >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ break;
+ case ACTION_T_SET_UNIT_FLAG:
+ case ACTION_T_REMOVE_UNIT_FLAG:
+ if (action.unit_flag.target >= TARGET_T_END)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ break;
+ case ACTION_T_SET_PHASE:
+ if (action.set_phase.phase >= MAX_PHASE)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
+ break;
+ case ACTION_T_INC_PHASE:
+ if (action.set_inc_phase.step == 0)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1);
+ else if (std::abs(action.set_inc_phase.step) > MAX_PHASE-1)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u is change phase by too large for any use %i.", i, j+1, action.set_inc_phase.step);
+ break;
case ACTION_T_QUEST_EVENT_ALL:
- {
- if (Quest const* qid = objmgr.GetQuestTemplate(temp.action[j].param1))
+ if (Quest const* qid = objmgr.GetQuestTemplate(action.quest_event_all.questId))
{
if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1);
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event_all.questId);
}
else
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event_all.questId);
break;
- }
- case ACTION_T_CASTCREATUREGO:
- {
- if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
-
- if (!sSpellStore.LookupEntry(temp.action[j].param2))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
-
- if (temp.action[j].param3 >= TARGET_T_END)
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- }
- case ACTION_T_CASTCREATUREGO_ALL:
- {
- if (!objmgr.GetQuestTemplate(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
-
- if (!sSpellStore.LookupEntry(temp.action[j].param2))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
+ case ACTION_T_CAST_EVENT_ALL:
+ if (!sCreatureStorage.LookupEntry<CreatureInfo>(action.cast_event_all.creatureId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event_all.creatureId);
+ if (!sSpellStore.LookupEntry(action.cast_event_all.spellId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event_all.spellId);
break;
- }
-
- //2nd param target
- case ACTION_T_SUMMON_ID:
- {
- if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
-
- if (m_CreatureEventAI_Summon_Map.find(temp.action[j].param3) == m_CreatureEventAI_Summon_Map.end())
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u summons missing CreatureEventAI_Summon %u", i, j+1, temp.action[j].param3);
-
- if (temp.action[j].param2 >= TARGET_T_END)
+ case ACTION_T_REMOVEAURASFROMSPELL:
+ if (!sSpellStore.LookupEntry(action.remove_aura.spellId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.remove_aura.spellId);
+ if (action.remove_aura.target >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
- }
- case ACTION_T_KILLED_MONSTER:
- {
- if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
-
- if (temp.action[j].param2 >= TARGET_T_END)
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3
+ if (action.random_phase.phase1 >= MAX_PHASE)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase1 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
+ if (action.random_phase.phase2 >= MAX_PHASE)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase2 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
+ if (action.random_phase.phase3 >= MAX_PHASE)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase3 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
break;
- }
- case ACTION_T_SUMMON:
- {
- if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
-
- if (temp.action[j].param2 >= TARGET_T_END)
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax
+ if (action.random_phase_range.phaseMin >= MAX_PHASE)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMin >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
+ if (action.random_phase_range.phaseMin >= MAX_PHASE)
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMax >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
+ if (action.random_phase_range.phaseMin >= action.random_phase_range.phaseMax)
+ {
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMax <= phaseMin.", i, j+1);
+ std::swap(action.random_phase_range.phaseMin,action.random_phase_range.phaseMax);
+ // equal case processed at call
+ }
break;
- }
- case ACTION_T_THREAT_SINGLE_PCT:
- case ACTION_T_SET_UNIT_FLAG:
- case ACTION_T_REMOVE_UNIT_FLAG:
- if (temp.action[j].param2 >= TARGET_T_END)
+ case ACTION_T_SUMMON_ID:
+ if (!sCreatureStorage.LookupEntry<CreatureInfo>(action.summon_id.creatureId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.summon_id.creatureId);
+ if (action.summon_id.target >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
+ if (m_CreatureEventAI_Summon_Map.find(action.summon_id.spawnId) == m_CreatureEventAI_Summon_Map.end())
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u summons missing CreatureEventAI_Summon %u", i, j+1, action.summon_id.spawnId);
break;
- //3rd param target
- case ACTION_T_SET_UNIT_FIELD:
- if (temp.action[j].param1 < OBJECT_END || temp.action[j].param1 >= UNIT_END)
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1);
- if (temp.action[j].param3 >= TARGET_T_END)
+ case ACTION_T_KILLED_MONSTER:
+ if (!sCreatureStorage.LookupEntry<CreatureInfo>(action.killed_monster.creatureId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.killed_monster.creatureId);
+ if (action.killed_monster.target >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
-
- case ACTION_T_SET_PHASE:
- if (temp.action[j].param1 > 31)
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase > 31. Phase mask cannot be used past phase 31.", i, j+1);
- break;
-
- case ACTION_T_INC_PHASE:
- if (!temp.action[j].param1)
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1);
- break;
-
case ACTION_T_SET_INST_DATA:
- {
if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
-
- if (temp.action[j].param2 > 4/*SPECIAL*/)
+ if (action.set_inst_data.value > 4/*SPECIAL*/)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1);
-
break;
- }
case ACTION_T_SET_INST_DATA64:
- {
if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
-
- if (temp.action[j].param2 >= TARGET_T_END)
+ if (action.set_inst_data64.target >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
-
break;
- }
case ACTION_T_UPDATE_TEMPLATE:
- {
- if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
- break;
- }
-
- case ACTION_T_THREAT_ALL_PCT:
- if (abs(temp.action[j].param1_s) > 100)
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, temp.action[j].param1);
+ if (!sCreatureStorage.LookupEntry<CreatureInfo>(action.update_template.creatureId))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.update_template.creatureId);
break;
-
case ACTION_T_EVADE: //No Params
case ACTION_T_FLEE: //No Params
case ACTION_T_DIE: //No Params
@@ -642,11 +643,6 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
case ACTION_T_RANGED_MOVEMENT: //Distance, Angle
break;
- case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3
- case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax
- // check not implemented
- break;
-
case ACTION_T_RANDOM_SAY:
case ACTION_T_RANDOM_YELL:
case ACTION_T_RANDOM_TEXTEMOTE: