[7852] Use union of per-event type structures, more checks at creature event ai loading. Author: VladimirMangos

Including:
    * Fixed check for EVENT_T_SPELLHIT school field. Add check at loading. Note: this event expect before and now schol _mask_ in param2.
    * In EVENT_T_RECEIVE_EMOTE use original player condition check code instead copy of related code.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-05-19 15:38:36 -05:00
parent ca4c3eb847
commit 74206e4b6a
4 changed files with 268 additions and 402 deletions

View File

@@ -32,6 +32,22 @@
#include "WorldPacket.h"
#include "InstanceData.h"
bool CreatureEventAIHolder::UpdateRepeatTimer( Creature* creature, uint32 repeatMin, uint32 repeatMax )
{
if (repeatMin == repeatMax)
Time = repeatMin;
else if (repeatMax > repeatMin)
Time = urand(repeatMin, repeatMax);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", creature->GetEntry(), Event.event_id, Event.event_type);
Enabled = false;
return false;
}
return true;
}
int CreatureEventAI::Permissible(const Creature *creature)
{
if( creature->GetAIName() == "EventAI" )
@@ -109,53 +125,25 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
if (pHolder.Event.event_chance <= rnd % 100)
return false;
uint32 param1 = pHolder.Event.event_param1;
uint32 param2 = pHolder.Event.event_param2;
uint32 param3 = pHolder.Event.event_param3;
uint32 param4 = pHolder.Event.event_param4;
CreatureEventAI_Event const& event = pHolder.Event;
//Check event conditions based on the event type, also reset events
switch (pHolder.Event.event_type)
switch (event.event_type)
{
case EVENT_T_TIMER:
{
if (!m_creature->isInCombat())
return false;
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
pHolder.UpdateRepeatTimer(m_creature,event.timer.repeatMin,event.timer.repeatMax);
break;
case EVENT_T_TIMER_OOC:
{
if (m_creature->isInCombat())
return false;
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
pHolder.UpdateRepeatTimer(m_creature,event.timer.repeatMin,event.timer.repeatMax);
break;
case EVENT_T_HP:
{
if (!m_creature->isInCombat() || !m_creature->GetMaxHealth())
@@ -163,24 +151,13 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
uint32 perc = (m_creature->GetHealth()*100) / m_creature->GetMaxHealth();
if (perc > param1 || perc < param2)
if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
return false;
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
pHolder.UpdateRepeatTimer(m_creature,event.percent_range.repeatMin,event.percent_range.repeatMax);
break;
}
break;
case EVENT_T_MANA:
{
if (!m_creature->isInCombat() || !m_creature->GetMaxPower(POWER_MANA))
@@ -188,109 +165,38 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
uint32 perc = (m_creature->GetPower(POWER_MANA)*100) / m_creature->GetMaxPower(POWER_MANA);
if (perc > param1 || perc < param2)
if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
return false;
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
pHolder.UpdateRepeatTimer(m_creature,event.percent_range.repeatMin,event.percent_range.repeatMax);
break;
}
break;
case EVENT_T_AGGRO:
{
}
break;
break;
case EVENT_T_KILL:
{
//Repeat Timers
if (param1 == param2)
{
pHolder.Time = param1;
}else if (param2 > param1)
pHolder.Time = urand(param1, param2);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
pHolder.UpdateRepeatTimer(m_creature,event.kill.repeatMin,event.kill.repeatMax);
break;
case EVENT_T_DEATH:
{
}
break;
case EVENT_T_EVADE:
{
}
break;
break;
case EVENT_T_SPELLHIT:
{
//Spell hit is special case, param1 and param2 handled within CreatureEventAI::SpellHit
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
pHolder.UpdateRepeatTimer(m_creature,event.spell_hit.repeatMin,event.spell_hit.repeatMax);
break;
case EVENT_T_RANGE:
{
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
pHolder.UpdateRepeatTimer(m_creature,event.range.repeatMin,event.range.repeatMax);
break;
case EVENT_T_OOC_LOS:
{
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
pHolder.UpdateRepeatTimer(m_creature,event.ooc_los.repeatMin,event.ooc_los.repeatMax);
break;
case EVENT_T_SPAWNED:
{
}
break;
break;
case EVENT_T_TARGET_HP:
{
if (!m_creature->isInCombat() || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxHealth())
@@ -298,78 +204,42 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
uint32 perc = (m_creature->getVictim()->GetHealth()*100) / m_creature->getVictim()->GetMaxHealth();
if (perc > param1 || perc < param2)
if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
return false;
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
pHolder.UpdateRepeatTimer(m_creature,event.percent_range.repeatMin,event.percent_range.repeatMax);
break;
}
break;
case EVENT_T_TARGET_CASTING:
{
if (!m_creature->isInCombat() || !m_creature->getVictim() || !m_creature->getVictim()->IsNonMeleeSpellCasted(false, false, true))
return false;
//Repeat Timers
if (param1 == param2)
{
pHolder.Time = param1;
}else if (param2 > param1)
pHolder.Time = urand(param1, param2);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
pHolder.UpdateRepeatTimer(m_creature,event.target_casting.repeatMin,event.target_casting.repeatMax);
break;
case EVENT_T_FRIENDLY_HP:
{
if (!m_creature->isInCombat())
return false;
Unit* pUnit = DoSelectLowestHpFriendly(param2, param1);
Unit* pUnit = DoSelectLowestHpFriendly(event.friendly_hp.radius, event.friendly_hp.hpDeficit);
if (!pUnit)
return false;
pActionInvoker = pUnit;
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
pHolder.UpdateRepeatTimer(m_creature,event.friendly_hp.repeatMin,event.friendly_hp.repeatMax);
break;
}
break;
case EVENT_T_FRIENDLY_IS_CC:
{
if (!m_creature->isInCombat())
return false;
std::list<Creature*> pList;
DoFindFriendlyCC(pList, param2);
DoFindFriendlyCC(pList, event.friendly_is_cc.radius);
//List is empty
if (pList.empty())
@@ -379,23 +249,13 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
pActionInvoker = *(pList.begin());
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
pHolder.UpdateRepeatTimer(m_creature,event.friendly_is_cc.repeatMin,event.friendly_is_cc.repeatMax);
break;
}
break;
case EVENT_T_FRIENDLY_MISSING_BUFF:
{
std::list<Creature*> pList;
DoFindFriendlyMissingBuff(pList, param2, param1);
DoFindFriendlyMissingBuff(pList, event.friendly_buff.radius, event.friendly_buff.spellId);
//List is empty
if (pList.empty())
@@ -405,20 +265,9 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
pActionInvoker = *(pList.begin());
//Repeat Timers
if (param3 == param4)
{
pHolder.Time = param3;
}else if (param4 > param3)
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
pHolder.UpdateRepeatTimer(m_creature,event.friendly_buff.repeatMin,event.friendly_buff.repeatMax);
break;
}
break;
case EVENT_T_SUMMONED_UNIT:
{
//Prevent event from occuring on no unit or non creatures
@@ -426,34 +275,31 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
return false;
//Creature id doesn't match up
if (param1 && ((Creature*)pActionInvoker)->GetEntry() != param1)
if (((Creature*)pActionInvoker)->GetEntry() != event.summon_unit.creatureId)
return false;
//Repeat Timers
if (param2 == param3)
{
pHolder.Time = param2;
}else if (param3 > param2)
pHolder.Time = urand(param2, param3);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
pHolder.UpdateRepeatTimer(m_creature,event.summon_unit.repeatMin,event.summon_unit.repeatMax);
}
break;
case EVENT_T_TARGET_MANA:
{
if (!m_creature->isInCombat() || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxPower(POWER_MANA))
return false;
uint32 perc = (m_creature->getVictim()->GetPower(POWER_MANA)*100) / m_creature->getVictim()->GetMaxPower(POWER_MANA);
if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
return false;
//Repeat Timers
pHolder.UpdateRepeatTimer(m_creature,event.percent_range.repeatMin,event.percent_range.repeatMax);
break;
}
case EVENT_T_REACHED_HOME:
{
}
break;
case EVENT_T_RECEIVE_EMOTE:
{
}
break;
break;
default:
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
break;
}
@@ -946,25 +792,16 @@ void CreatureEventAI::Reset()
//Reset all events to enabled
for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
{
switch ((*i).Event.event_type)
CreatureEventAI_Event const& event = (*i).Event;
switch (event.event_type)
{
//Reset all out of combat timers
case EVENT_T_TIMER_OOC:
{
if ((*i).Event.event_param2 == (*i).Event.event_param1)
{
(*i).Time = (*i).Event.event_param1;
if ((*i).UpdateRepeatTimer(m_creature,event.timer.initialMin,event.timer.initialMax))
(*i).Enabled = true;
}
else if ((*i).Event.event_param2 > (*i).Event.event_param1)
{
(*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2);
(*i).Enabled = true;
}
else
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
break;
}
break;
//default:
//TODO: enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void EnterCombat()
//(*i).Enabled = true;
@@ -1052,7 +889,8 @@ void CreatureEventAI::EnterCombat(Unit *enemy)
{
for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
{
switch ((*i).Event.event_type)
CreatureEventAI_Event const& event = (*i).Event;
switch (event.event_type)
{
case EVENT_T_AGGRO:
(*i).Enabled = true;
@@ -1060,18 +898,8 @@ void CreatureEventAI::EnterCombat(Unit *enemy)
break;
//Reset all in combat timers
case EVENT_T_TIMER:
if ((*i).Event.event_param2 == (*i).Event.event_param1)
{
(*i).Time = (*i).Event.event_param1;
if ((*i).UpdateRepeatTimer(m_creature,event.timer.initialMin,event.timer.initialMax))
(*i).Enabled = true;
}
else if ((*i).Event.event_param2 > (*i).Event.event_param1)
{
(*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2);
(*i).Enabled = true;
}
else
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
break;
//All normal events need to be re-enabled and their time set to 0
default:
@@ -1117,14 +945,14 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who)
if ((*itr).Event.event_type == EVENT_T_OOC_LOS)
{
//can trigger if closer than fMaxAllowedRange
float fMaxAllowedRange = (*itr).Event.event_param2;
float fMaxAllowedRange = (*itr).Event.ooc_los.maxRange;
//if range is ok and we are actually in LOS
if (m_creature->IsWithinDistInMap(who, fMaxAllowedRange) && m_creature->IsWithinLOSInMap(who))
{
//if friendly event&&who is not hostile OR hostile event&&who is hostile
if (((*itr).Event.event_param1 && !m_creature->IsHostileTo(who)) ||
((!(*itr).Event.event_param1) && m_creature->IsHostileTo(who)))
if (((*itr).Event.ooc_los.noHostile && !m_creature->IsHostileTo(who)) ||
((!(*itr).Event.ooc_los.noHostile) && m_creature->IsHostileTo(who)))
ProcessEvent(*itr, who);
}
}
@@ -1145,17 +973,11 @@ void CreatureEventAI::SpellHit(Unit* pUnit, const SpellEntry* pSpell)
return;
for (std::list<CreatureEventAIHolder>::iterator i = CreatureEventAIList.begin(); i != CreatureEventAIList.end(); ++i)
{
if ((*i).Event.event_type == EVENT_T_SPELLHIT)
{
//If spell id matches (or no spell id) & if spell school matches (or no spell school)
if (!(*i).Event.event_param1 || pSpell->Id == (*i).Event.event_param1)
{
if ((*i).Event.event_param2_s == -1 || pSpell->SchoolMask == (*i).Event.event_param2)
if (!(*i).Event.spell_hit.spellId || pSpell->Id == (*i).Event.spell_hit.spellId)
if (pSpell->SchoolMask & (*i).Event.spell_hit.schoolMask)
ProcessEvent(*i, pUnit);
}
}
}
}
void CreatureEventAI::UpdateAI(const uint32 diff)
@@ -1227,8 +1049,7 @@ void CreatureEventAI::UpdateAI(const uint32 diff)
case EVENT_T_RANGE:
if (me->getVictim())
if (m_creature->IsInMap(m_creature->getVictim()))
if (m_creature->IsInRange(m_creature->getVictim(),
(float)(*i).Event.event_param1,(float)(*i).Event.event_param2))
if (m_creature->IsInRange(m_creature->getVictim(),(float)(*i).Event.range.minDist,(float)(*i).Event.range.maxDist))
ProcessEvent(*i);
break;
}
@@ -1495,60 +1316,11 @@ void CreatureEventAI::ReceiveEmote(Player* pPlayer, uint32 text_emote)
{
if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE)
{
if ((*itr).Event.event_param1 != text_emote)
if ((*itr).Event.receive_emote.emoteId != text_emote)
return;
bool bProcess = false;
switch((*itr).Event.event_param2)
{
//enum ConditionType
case CONDITION_NONE: // 0 0
bProcess = true;
break;
case CONDITION_AURA: // spell_id effindex
if (pPlayer->HasAuraEffect((*itr).Event.event_param3,(*itr).Event.event_param4))
bProcess = true;
break;
case CONDITION_ITEM: // item_id count
if (pPlayer->HasItemCount((*itr).Event.event_param3,(*itr).Event.event_param4))
bProcess = true;
break;
case CONDITION_ITEM_EQUIPPED: // item_id count
if (pPlayer->HasItemOrGemWithIdEquipped((*itr).Event.event_param3,(*itr).Event.event_param4))
bProcess = true;
break;
case CONDITION_ZONEID: // zone_id 0
if (pPlayer->GetZoneId() == (*itr).Event.event_param3)
bProcess = true;
break;
case CONDITION_REPUTATION_RANK: // faction_id min_rank
if (pPlayer->GetReputationRank((*itr).Event.event_param3) >= (*itr).Event.event_param4)
bProcess = true;
break;
case CONDITION_TEAM: // player_team 0, (469 - Alliance 67 - Horde)
if (pPlayer->GetTeam() == (*itr).Event.event_param3)
bProcess = true;
break;
case CONDITION_SKILL: // skill_id min skill_value
if (pPlayer->HasSkill((*itr).Event.event_param3) && pPlayer->GetSkillValue((*itr).Event.event_param3) >= (*itr).Event.event_param4)
bProcess = true;
break;
case CONDITION_QUESTREWARDED: // quest_id 0
if (pPlayer->GetQuestRewardStatus((*itr).Event.event_param3))
bProcess = true;
break;
case CONDITION_QUESTTAKEN: // quest_id 0, for condition true while quest active.
if (pPlayer->GetQuestStatus((*itr).Event.event_param3) == QUEST_STATUS_INCOMPLETE)
bProcess = true;
break;
case CONDITION_ACTIVE_EVENT: // event_id 0
if (IsHolidayActive(HolidayIds((*itr).Event.event_param3)))
bProcess = true;
break;
}
if (bProcess)
PlayerCondition pcon((*itr).Event.receive_emote.condition,(*itr).Event.receive_emote.conditionValue1,(*itr).Event.receive_emote.conditionValue2);
if (pcon.Meets(pPlayer))
{
sLog.outDebug("CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing");
ProcessEvent(*itr, pPlayer);