/*
* Copyright (C) 2005-2009 MaNGOS
*
* Copyright (C) 2008-2009 Trinity
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "AggressorAI.h"
#include "SpellMgr.h"
int AggressorAI::Permissible(const Creature *creature)
{
// have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight
if( !creature->isCivilian() && !creature->IsNeutralToAll() )
return PERMIT_BASE_PROACTIVE;
return PERMIT_BASE_NO;
}
void AggressorAI::UpdateAI(const uint32 /*diff*/)
{
if(!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
int SpellAI::Permissible(const Creature *creature)
{
return PERMIT_BASE_NO;
}
void SpellAI::InitializeAI()
{
for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
if(me->m_spells[i] && GetSpellStore()->LookupEntry(me->m_spells[i]))
spells.push_back(me->m_spells[i]);
CreatureAI::InitializeAI();
}
void SpellAI::Reset()
{
events.Reset();
}
void SpellAI::JustDied(Unit *killer)
{
for(SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
if(AISpellInfo[*i].condition == AICOND_DIE)
me->CastSpell(killer, *i, true);
}
void SpellAI::EnterCombat(Unit *who)
{
for(SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
{
if(AISpellInfo[*i].condition == AICOND_AGGRO)
me->CastSpell(who, *i, false);
else if(AISpellInfo[*i].condition == AICOND_COMBAT)
events.ScheduleEvent(*i, AISpellInfo[*i].cooldown + rand()%AISpellInfo[*i].cooldown);
}
}
void SpellAI::UpdateAI(const uint32 diff)
{
if(!UpdateVictim())
return;
events.Update(diff);
if(me->hasUnitState(UNIT_STAT_CASTING))
return;
if(uint32 spellId = events.ExecuteEvent())
{
DoCast(spellId);
events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + rand()%AISpellInfo[spellId].cooldown);
}
else
DoMeleeAttackIfReady();
}
void SpellCasterAI::InitializeAI()
{
SpellAI::InitializeAI();
float m_attackDist = 30.0f;
for(SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr)
{
if (AISpellInfo[*itr].condition == AICOND_COMBAT && m_attackDist > GetAISpellInfo(*itr)->maxRange)
m_attackDist = GetAISpellInfo(*itr)->maxRange;
}
if (m_attackDist == 30.0f)
m_attackDist = MELEE_RANGE;
}
void SpellCasterAI::EnterCombat(Unit *who)
{
if (spells.empty())
return;
uint32 spell = rand() % spells.size();
uint32 count = 0;
for(SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr, ++count)
{
if(AISpellInfo[*itr].condition == AICOND_AGGRO)
me->CastSpell(who, *itr, false);
else if (AISpellInfo[*itr].condition == AICOND_COMBAT)
{
uint32 cooldown = GetAISpellInfo(*itr)->realCooldown;
if (count == spell)
{
DoCast(spells[spell]);
cooldown += me->GetCurrentSpellCastTime(*itr);
}
events.ScheduleEvent(*itr, cooldown);
}
}
}
void SpellCasterAI::UpdateAI(const uint32 diff)
{
if(!UpdateVictim())
return;
events.Update(diff);
if(me->hasUnitState(UNIT_STAT_CASTING))
return;
if(uint32 spellId = events.ExecuteEvent())
{
DoCast(spellId);
uint32 casttime = me->GetCurrentSpellCastTime(spellId);
events.ScheduleEvent(spellId, (casttime ? casttime : 500) + GetAISpellInfo(spellId)->realCooldown);
}
}