aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormegamage <none@none>2009-05-18 15:14:27 -0500
committermegamage <none@none>2009-05-18 15:14:27 -0500
commitc3499f39da83887e79a2fe219ddc75961c81c756 (patch)
tree16c523cf0a9692dbd14c7df1bc4b0449bbf8999b /src
parent40dad11d74c2af732956ee699deeb8986c874afd (diff)
[7847] Replace paramter unions by uniton of event ai action type structures. Add/fix some loading checks. Author: VladimirMangos
* Also send to process function reference to strucutre instead large amount fields. * Specially note that fixed check for first arg of action type 27 that before wrongly test as quest id, when by using code expected creature id. Possible some used data wrongly can be quest ids.... --HG-- branch : trunk
Diffstat (limited to 'src')
-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: