2 * Copyright (C) 2005-2013 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "CreatureAI.h"
21 #include "DBCStores.h"
24 CreatureAI::~CreatureAI()
28 void CreatureAI::AttackedBy(Unit
* attacker
)
30 if (!m_creature
->getVictim())
31 AttackStart(attacker
);
34 CanCastResult
CreatureAI::CanCastSpell(Unit
* pTarget
, const SpellEntry
* pSpell
, bool isTriggered
)
36 // If not triggered, we check
39 // State does not allow
40 if (m_creature
->hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL
))
41 return CAST_FAIL_STATE
;
43 if (pSpell
->GetPreventionType() == SPELL_PREVENTION_TYPE_SILENCE
&& m_creature
->HasFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_SILENCED
))
44 return CAST_FAIL_STATE
;
46 if (pSpell
->GetPreventionType() == SPELL_PREVENTION_TYPE_PACIFY
&& m_creature
->HasFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_PACIFIED
))
47 return CAST_FAIL_STATE
;
49 // Check for power (also done by Spell::CheckCast())
50 if (m_creature
->GetPower((Powers
)pSpell
->powerType
) < Spell::CalculatePowerCost(pSpell
, m_creature
))
51 return CAST_FAIL_POWER
;
54 if (const SpellRangeEntry
* pSpellRange
= sSpellRangeStore
.LookupEntry(pSpell
->rangeIndex
))
56 if (pTarget
!= m_creature
)
58 // pTarget is out of range of this spell (also done by Spell::CheckCast())
59 float fDistance
= m_creature
->GetCombatDistance(pTarget
);
61 if (fDistance
> (m_creature
->IsHostileTo(pTarget
) ? pSpellRange
->maxRange
: pSpellRange
->maxRangeFriendly
))
62 return CAST_FAIL_TOO_FAR
;
64 float fMinRange
= m_creature
->IsHostileTo(pTarget
) ? pSpellRange
->minRange
: pSpellRange
->minRangeFriendly
;
66 if (fMinRange
&& fDistance
< fMinRange
)
67 return CAST_FAIL_TOO_CLOSE
;
73 return CAST_FAIL_OTHER
;
76 CanCastResult
CreatureAI::DoCastSpellIfCan(Unit
* pTarget
, uint32 uiSpell
, uint32 uiCastFlags
, ObjectGuid uiOriginalCasterGUID
)
78 Unit
* pCaster
= m_creature
;
80 if (uiCastFlags
& CAST_FORCE_TARGET_SELF
)
83 // Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
84 if (!pCaster
->IsNonMeleeSpellCasted(false) || (uiCastFlags
& (CAST_TRIGGERED
| CAST_INTERRUPT_PREVIOUS
)))
86 if (const SpellEntry
* pSpell
= sSpellStore
.LookupEntry(uiSpell
))
88 // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
89 if (uiCastFlags
& CAST_AURA_NOT_PRESENT
)
91 if (pTarget
->HasAura(uiSpell
))
92 return CAST_FAIL_TARGET_AURA
;
95 // Check if cannot cast spell
96 if (!(uiCastFlags
& (CAST_FORCE_TARGET_SELF
| CAST_FORCE_CAST
)))
98 CanCastResult castResult
= CanCastSpell(pTarget
, pSpell
, uiCastFlags
& CAST_TRIGGERED
);
100 if (castResult
!= CAST_OK
)
104 // Interrupt any previous spell
105 if (uiCastFlags
& CAST_INTERRUPT_PREVIOUS
&& pCaster
->IsNonMeleeSpellCasted(false))
106 pCaster
->InterruptNonMeleeSpells(false);
108 pCaster
->CastSpell(pTarget
, pSpell
, uiCastFlags
& CAST_TRIGGERED
, NULL
, NULL
, uiOriginalCasterGUID
);
113 sLog
.outErrorDb("DoCastSpellIfCan by creature entry %u attempt to cast spell %u but spell does not exist.", m_creature
->GetEntry(), uiSpell
);
114 return CAST_FAIL_OTHER
;
118 return CAST_FAIL_IS_CASTING
;
121 bool CreatureAI::DoMeleeAttackIfReady()
123 return m_creature
->UpdateMeleeAttackingState();