2009-02-04 12:04:12 +01:00
/* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
2008-10-14 11:57:03 -05:00
*
* Thanks to the original authors: ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
2008-10-11 14:16:25 -05:00
* This program is free software licensed under GPL version 2
* Please see the included DOCS/LICENSE.TXT for more information */
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "precompiled.h"
#include "Item.h"
#include "Spell.h"
2009-02-05 15:38:24 -06:00
#include "ObjectMgr.h"
2009-05-11 11:46:48 -05:00
#include "TemporarySummon.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Spell summary for ScriptedAI::SelectSpell
2009-08-14 19:45:06 +02:00
struct TSpellSummary
{
2008-10-25 11:40:10 -05:00
uint8 Targets ; // set of enum SelectTarget
uint8 Effects ; // set of enum SelectEffect
2008-10-11 14:16:25 -05:00
} * SpellSummary ;
2009-10-17 15:51:44 -07:00
2009-05-13 10:54:11 -05:00
void SummonList :: DoZoneInCombat ( uint32 entry )
{
2009-10-17 16:20:24 -07:00
for ( iterator i = begin (); i != end (); )
2009-05-13 10:54:11 -05:00
{
Creature * summon = Unit :: GetCreature ( * m_creature , * i );
++ i ;
if ( summon && summon -> IsAIEnabled
&& ( ! entry || summon -> GetEntry () == entry ))
summon -> AI () -> DoZoneInCombat ();
}
}
2009-10-17 15:51:44 -07:00
2009-04-22 23:03:49 -05:00
void SummonList :: DoAction ( uint32 entry , uint32 info )
2008-11-03 10:16:06 -06:00
{
2009-10-17 16:20:24 -07:00
for ( iterator i = begin (); i != end (); )
2008-11-03 10:16:06 -06:00
{
2009-04-22 23:03:49 -05:00
Creature * summon = Unit :: GetCreature ( * m_creature , * i );
++ i ;
2009-05-13 10:54:11 -05:00
if ( summon && summon -> IsAIEnabled
&& ( ! entry || summon -> GetEntry () == entry ))
2009-04-22 23:03:49 -05:00
summon -> AI () -> DoAction ( info );
2008-11-03 10:16:06 -06:00
}
}
2009-10-17 15:51:44 -07:00
2008-11-03 10:16:06 -06:00
void SummonList :: DespawnEntry ( uint32 entry )
{
2009-10-17 16:20:24 -07:00
for ( iterator i = begin (); i != end (); )
2008-11-03 10:16:06 -06:00
{
2009-04-22 23:03:49 -05:00
Creature * summon = Unit :: GetCreature ( * m_creature , * i );
if ( ! summon )
erase ( i ++ );
else if ( summon -> GetEntry () == entry )
2008-11-03 10:16:06 -06:00
{
2009-04-22 23:03:49 -05:00
erase ( i ++ );
summon -> setDeathState ( JUST_DIED );
summon -> RemoveCorpse ();
2008-11-03 10:16:06 -06:00
}
else
2009-04-22 23:03:49 -05:00
++ i ;
2008-11-03 10:16:06 -06:00
}
}
2009-10-17 15:51:44 -07:00
2008-11-03 10:16:06 -06:00
void SummonList :: DespawnAll ()
{
2009-04-22 23:03:49 -05:00
while ( ! empty ())
2008-11-03 10:16:06 -06:00
{
2009-04-22 23:03:49 -05:00
Creature * summon = Unit :: GetCreature ( * m_creature , * begin ());
if ( ! summon )
erase ( begin ());
else
2008-11-03 10:16:06 -06:00
{
2009-04-22 23:03:49 -05:00
erase ( begin ());
2009-08-28 11:26:20 -05:00
if ( summon -> isSummon ())
{
summon -> DestroyForNearbyPlayers ();
2009-06-16 11:45:33 -05:00
CAST_SUM ( summon ) -> UnSummon ();
2009-08-28 11:26:20 -05:00
}
2009-05-11 11:46:48 -05:00
else
2009-08-28 11:26:20 -05:00
summon -> DisappearAndDie ();
2008-11-03 10:16:06 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2009-08-16 21:46:31 +02:00
ScriptedAI :: ScriptedAI ( Creature * pCreature ) : CreatureAI ( pCreature ),
m_creature ( pCreature ),
IsFleeing ( false ),
m_bCombatMovement ( true ),
m_uiEvadeCheckCooldown ( 2500 )
2009-04-29 00:15:18 -05:00
{
HeroicMode = m_creature -> GetMap () -> IsHeroic ();
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: AttackStartNoMove ( Unit * pWho )
2008-10-25 11:40:10 -05:00
{
2009-08-14 19:45:06 +02:00
if ( ! pWho )
2008-10-25 11:40:10 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
if ( m_creature -> Attack ( pWho , false ))
DoStartNoMovement ( pWho );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: UpdateAI ( const uint32 uiDiff )
2008-10-11 14:16:25 -05:00
{
//Check if we have a current target
2009-08-14 19:45:06 +02:00
if ( ! UpdateVictim ())
return ;
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
if ( m_creature -> isAttackReady ())
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
//If we are within range melee the target
if ( m_creature -> IsWithinMeleeRange ( m_creature -> getVictim ()))
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
m_creature -> AttackerStateUpdate ( m_creature -> getVictim ());
m_creature -> resetAttackTimer ();
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: DoStartMovement ( Unit * pVictim , float fDistance , float fAngle )
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
if ( pVictim )
m_creature -> GetMotionMaster () -> MoveChase ( pVictim , fDistance , fAngle );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: DoStartNoMovement ( Unit * pVictim )
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
if ( ! pVictim )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-25 11:40:10 -05:00
m_creature -> GetMotionMaster () -> MoveIdle ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ScriptedAI :: DoStopAttack ()
{
2009-08-14 19:45:06 +02:00
if ( m_creature -> getVictim ())
2008-10-11 14:16:25 -05:00
m_creature -> AttackStop ();
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: DoCastSpell ( Unit * pTarget , SpellEntry const * pSpellInfo , bool bTriggered )
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
if ( ! pTarget || m_creature -> IsNonMeleeSpellCasted ( false ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_creature -> StopMoving ();
2009-08-14 19:45:06 +02:00
m_creature -> CastSpell ( pTarget , pSpellInfo , bTriggered );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-06 17:36:32 +02:00
void ScriptedAI :: DoPlaySoundToSet ( WorldObject * pSource , uint32 uiSoundId )
2008-10-11 14:16:25 -05:00
{
2009-04-09 23:07:32 +02:00
if ( ! pSource )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-09 23:07:32 +02:00
if ( ! GetSoundEntriesStore () -> LookupEntry ( uiSoundId ))
2008-10-11 14:16:25 -05:00
{
2009-08-06 17:36:32 +02:00
error_log ( "TSCR: Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)" , uiSoundId , pSource -> GetTypeId (), pSource -> GetGUIDLow ());
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-04-09 23:07:32 +02:00
pSource -> PlayDirectSound ( uiSoundId );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
Creature * ScriptedAI :: DoSpawnCreature ( uint32 uiId , float fX , float fY , float fZ , float fAngle , uint32 uiType , uint32 uiDespawntime )
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
return m_creature -> SummonCreature ( uiId , m_creature -> GetPositionX () + fX , m_creature -> GetPositionY () + fY , m_creature -> GetPositionZ () + fZ , fAngle , ( TempSummonType ) uiType , uiDespawntime );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-10-27 21:28:20 -07:00
Unit * ScriptedAI :: SelectUnit ( SelectAggroTarget pTarget , uint32 uiPosition )
2008-10-11 14:16:25 -05:00
{
//ThreatList m_threatlist;
2009-08-14 19:45:06 +02:00
std :: list < HostilReference *>& threatlist = m_creature -> getThreatManager (). getThreatList ();
std :: list < HostilReference *>:: iterator itr = threatlist . begin ();
std :: list < HostilReference *>:: reverse_iterator ritr = threatlist . rbegin ();
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
if ( uiPosition >= threatlist . size () || ! threatlist . size ())
2008-10-11 14:16:25 -05:00
return NULL ;
2009-10-17 15:51:44 -07:00
2009-10-27 21:28:20 -07:00
switch ( pTarget )
2008-10-11 14:16:25 -05:00
{
case SELECT_TARGET_RANDOM :
2009-08-14 19:45:06 +02:00
advance ( itr , uiPosition + ( rand () % ( threatlist . size () - uiPosition ) ));
return Unit :: GetUnit (( * m_creature ),( * itr ) -> getUnitGuid ());
2008-10-11 14:16:25 -05:00
break ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case SELECT_TARGET_TOPAGGRO :
2009-08-14 19:45:06 +02:00
advance ( itr , uiPosition );
return Unit :: GetUnit (( * m_creature ),( * itr ) -> getUnitGuid ());
2008-10-11 14:16:25 -05:00
break ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case SELECT_TARGET_BOTTOMAGGRO :
2009-08-14 19:45:06 +02:00
advance ( ritr , uiPosition );
return Unit :: GetUnit (( * m_creature ),( * ritr ) -> getUnitGuid ());
2008-10-11 14:16:25 -05:00
break ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
SpellEntry const * ScriptedAI :: SelectSpell ( Unit * pTarget , int32 uiSchool , int32 uiMechanic , SelectTargetType selectTargets , uint32 uiPowerCostMin , uint32 uiPowerCostMax , float fRangeMin , float fRangeMax , SelectEffect selectEffects )
2008-10-11 14:16:25 -05:00
{
2009-10-27 21:39:53 -07:00
//No target so we can't cast
2009-08-14 19:45:06 +02:00
if ( ! pTarget )
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Silenced so we can't cast
if ( m_creature -> HasFlag ( UNIT_FIELD_FLAGS , UNIT_FLAG_SILENCED ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Using the extended script system we first create a list of viable spells
2009-08-14 19:45:06 +02:00
SpellEntry const * apSpell [ CREATURE_MAX_SPELLS ];
2009-08-14 20:12:58 +02:00
memset ( apSpell , 0 , sizeof ( SpellEntry * ) * CREATURE_MAX_SPELLS );
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
uint32 uiSpellCount = 0 ;
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
SpellEntry const * pTempSpell ;
SpellRangeEntry const * pTempRange ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Check if each spell is viable(set it to null if not)
2009-02-11 22:59:02 +01:00
for ( uint32 i = 0 ; i < CREATURE_MAX_SPELLS ; i ++ )
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
pTempSpell = GetSpellStore () -> LookupEntry ( m_creature -> m_spells [ i ]);
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//This spell doesn't exist
2009-08-14 19:45:06 +02:00
if ( ! pTempSpell )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Targets and Effects checked first as most used restrictions
//Check the spell targets if specified
2009-08-14 19:45:06 +02:00
if ( selectTargets && ! ( SpellSummary [ m_creature -> m_spells [ i ]]. Targets & ( 1 << ( selectTargets - 1 ))))
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Check the type of spell if we are looking for a specific spell type
2009-08-14 19:45:06 +02:00
if ( selectEffects && ! ( SpellSummary [ m_creature -> m_spells [ i ]]. Effects & ( 1 << ( selectEffects - 1 ))))
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Check for school if specified
2009-08-14 19:45:06 +02:00
if ( uiSchool >= 0 && pTempSpell -> SchoolMask & uiSchool )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Check for spell mechanic if specified
2009-08-14 19:45:06 +02:00
if ( uiMechanic >= 0 && pTempSpell -> Mechanic != uiMechanic )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Make sure that the spell uses the requested amount of power
2009-08-14 19:45:06 +02:00
if ( uiPowerCostMin && pTempSpell -> manaCost < uiPowerCostMin )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
if ( uiPowerCostMax && pTempSpell -> manaCost > uiPowerCostMax )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Continue if we don't have the mana to actually cast this spell
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> manaCost > m_creature -> GetPower (( Powers ) pTempSpell -> powerType ))
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Get the Range
2009-08-14 19:45:06 +02:00
pTempRange = GetSpellRangeStore () -> LookupEntry ( pTempSpell -> rangeIndex );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Spell has invalid range store so we can't use it
2009-08-14 19:45:06 +02:00
if ( ! pTempRange )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Check if the spell meets our range requirements
2009-08-14 19:45:06 +02:00
if ( fRangeMin && m_creature -> GetSpellMinRangeForTarget ( pTarget , pTempRange ) < fRangeMin )
2008-10-11 14:16:25 -05:00
continue ;
2009-08-14 19:45:06 +02:00
if ( fRangeMax && m_creature -> GetSpellMaxRangeForTarget ( pTarget , pTempRange ) > fRangeMax )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-10-27 21:39:53 -07:00
//Check if our target is in range
2009-08-14 19:45:06 +02:00
if ( m_creature -> IsWithinDistInMap ( pTarget , m_creature -> GetSpellMinRangeForTarget ( pTarget , pTempRange )) || ! m_creature -> IsWithinDistInMap ( pTarget , m_creature -> GetSpellMaxRangeForTarget ( pTarget , pTempRange )))
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//All good so lets add it to the spell list
2009-08-14 19:45:06 +02:00
apSpell [ uiSpellCount ] = pTempSpell ;
++ uiSpellCount ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//We got our usable spells so now lets randomly pick one
2009-08-14 19:45:06 +02:00
if ( ! uiSpellCount )
2008-10-11 14:16:25 -05:00
return NULL ;
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
return apSpell [ rand () % uiSpellCount ];
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
bool ScriptedAI :: CanCast ( Unit * pTarget , SpellEntry const * pSpell , bool bTriggered )
2008-10-11 14:16:25 -05:00
{
2009-10-27 21:39:53 -07:00
//No target so we can't cast
2009-08-14 19:45:06 +02:00
if ( ! pTarget || ! pSpell )
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Silenced so we can't cast
2009-08-14 19:45:06 +02:00
if ( ! bTriggered && me -> HasFlag ( UNIT_FIELD_FLAGS , UNIT_FLAG_SILENCED ))
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Check for power
2009-08-14 19:45:06 +02:00
if ( ! bTriggered && me -> GetPower (( Powers ) pSpell -> powerType ) < pSpell -> manaCost )
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
SpellRangeEntry const * pTempRange = GetSpellRangeStore () -> LookupEntry ( pSpell -> rangeIndex );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Spell has invalid range store so we can't use it
2009-08-14 19:45:06 +02:00
if ( ! pTempRange )
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Unit is out of range of this spell
2009-08-14 19:45:06 +02:00
if ( me -> IsInRange ( pTarget , m_creature -> GetSpellMinRangeForTarget ( pTarget , pTempRange ), m_creature -> GetSpellMaxRangeForTarget ( pTarget , pTempRange )))
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void FillSpellSummary ()
{
SpellSummary = new TSpellSummary [ GetSpellStore () -> GetNumRows ()];
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
SpellEntry const * pTempSpell ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < GetSpellStore () -> GetNumRows (); ++ i )
2008-10-11 14:16:25 -05:00
{
SpellSummary [ i ]. Effects = 0 ;
SpellSummary [ i ]. Targets = 0 ;
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
pTempSpell = GetSpellStore () -> LookupEntry ( i );
2008-10-11 14:16:25 -05:00
//This spell doesn't exist
2009-08-14 19:45:06 +02:00
if ( ! pTempSpell )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 j = 0 ; j < 3 ; ++ j )
2008-10-11 14:16:25 -05:00
{
//Spell targets self
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_CASTER )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Targets |= 1 << ( SELECT_TARGET_SELF - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Spell targets a single enemy
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_TARGET_ENEMY ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_DST_TARGET_ENEMY )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Targets |= 1 << ( SELECT_TARGET_SINGLE_ENEMY - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Spell targets AoE at enemy
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_AREA_ENEMY_SRC ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_AREA_ENEMY_DST ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_SRC_CASTER ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_DEST_DYNOBJ_ENEMY )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Targets |= 1 << ( SELECT_TARGET_AOE_ENEMY - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Spell targets an enemy
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_TARGET_ENEMY ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_DST_TARGET_ENEMY ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_AREA_ENEMY_SRC ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_AREA_ENEMY_DST ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_SRC_CASTER ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_DEST_DYNOBJ_ENEMY )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Targets |= 1 << ( SELECT_TARGET_ANY_ENEMY - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Spell targets a single friend(or self)
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_CASTER ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_TARGET_ALLY ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_TARGET_PARTY )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Targets |= 1 << ( SELECT_TARGET_SINGLE_FRIEND - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Spell targets aoe friends
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_PARTY_CASTER ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_PARTY_TARGET ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_SRC_CASTER )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Targets |= 1 << ( SELECT_TARGET_AOE_FRIEND - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Spell targets any friend(or self)
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_CASTER ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_TARGET_ALLY ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_TARGET_PARTY ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_PARTY_CASTER ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_UNIT_PARTY_TARGET ||
pTempSpell -> EffectImplicitTargetA [ j ] == TARGET_SRC_CASTER )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Targets |= 1 << ( SELECT_TARGET_ANY_FRIEND - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Make sure that this spell includes a damage effect
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> Effect [ j ] == SPELL_EFFECT_SCHOOL_DAMAGE ||
pTempSpell -> Effect [ j ] == SPELL_EFFECT_INSTAKILL ||
pTempSpell -> Effect [ j ] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
pTempSpell -> Effect [ j ] == SPELL_EFFECT_HEALTH_LEECH )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Effects |= 1 << ( SELECT_EFFECT_DAMAGE - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Make sure that this spell includes a healing effect (or an apply aura with a periodic heal)
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> Effect [ j ] == SPELL_EFFECT_HEAL ||
pTempSpell -> Effect [ j ] == SPELL_EFFECT_HEAL_MAX_HEALTH ||
pTempSpell -> Effect [ j ] == SPELL_EFFECT_HEAL_MECHANICAL ||
( pTempSpell -> Effect [ j ] == SPELL_EFFECT_APPLY_AURA && pTempSpell -> EffectApplyAuraName [ j ] == 8 ))
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Effects |= 1 << ( SELECT_EFFECT_HEALING - 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//Make sure that this spell applies an aura
2009-08-14 19:45:06 +02:00
if ( pTempSpell -> Effect [ j ] == SPELL_EFFECT_APPLY_AURA )
2008-10-11 14:16:25 -05:00
SpellSummary [ i ]. Effects |= 1 << ( SELECT_EFFECT_AURA - 1 );
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ScriptedAI :: DoResetThreat ()
{
if ( ! m_creature -> CanHaveThreatList () || m_creature -> getThreatManager (). isThreatListEmpty ())
{
2009-04-24 00:51:09 -04:00
error_log ( "TSCR: DoResetThreat called for creature that either cannot have threat list or has empty threat list (m_creature entry = %d)" , m_creature -> GetEntry ());
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
std :: list < HostilReference *>& threatlist = m_creature -> getThreatManager (). getThreatList ();
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( std :: list < HostilReference *>:: iterator itr = threatlist . begin (); itr != threatlist . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
Unit * pUnit = Unit :: GetUnit (( * m_creature ), ( * itr ) -> getUnitGuid ());
2009-10-17 15:51:44 -07:00
2009-01-09 12:06:08 -06:00
if ( pUnit && DoGetThreat ( pUnit ))
DoModifyThreatPercent ( pUnit , - 100 );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-01-09 12:06:08 -06:00
float ScriptedAI :: DoGetThreat ( Unit * pUnit )
{
if ( ! pUnit ) return 0.0f ;
return m_creature -> getThreatManager (). getThreat ( pUnit );
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: DoModifyThreatPercent ( Unit * pUnit , int32 pct )
2009-01-09 12:06:08 -06:00
{
if ( ! pUnit ) return ;
m_creature -> getThreatManager (). modifyThreatPercent ( pUnit , pct );
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: DoTeleportTo ( float fX , float fY , float fZ , uint32 uiTime )
2009-02-23 13:14:04 -06:00
{
2009-08-14 19:45:06 +02:00
m_creature -> Relocate ( fX , fY , fZ );
m_creature -> SendMonsterMove ( fX , fY , fZ , uiTime );
2009-02-23 13:14:04 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: DoTeleportTo ( const float fPos [ 4 ])
2009-05-13 10:54:11 -05:00
{
2009-08-14 19:45:06 +02:00
me -> NearTeleportTo ( fPos [ 0 ], fPos [ 1 ], fPos [ 2 ], fPos [ 3 ]);
2009-05-13 10:54:11 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: DoTeleportPlayer ( Unit * pUnit , float fX , float fY , float fZ , float fO )
2008-10-11 14:16:25 -05:00
{
if ( ! pUnit || pUnit -> GetTypeId () != TYPEID_PLAYER )
{
if ( pUnit )
2009-08-14 19:45:06 +02:00
error_log ( "TSCR: Creature %u (Entry: %u) Tried to teleport non-player unit (Type: %u GUID: %u) to x: %f y:%f z: %f o: %f. Aborted." , m_creature -> GetGUID (), m_creature -> GetEntry (), pUnit -> GetTypeId (), pUnit -> GetGUID (), fX , fY , fZ , fO );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
CAST_PLR ( pUnit ) -> TeleportTo ( pUnit -> GetMapId (), fX , fY , fZ , fO , TELE_TO_NOT_LEAVE_COMBAT );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void ScriptedAI :: DoTeleportAll ( float fX , float fY , float fZ , float fO )
2008-11-18 19:40:06 -06:00
{
Map * map = m_creature -> GetMap ();
if ( ! map -> IsDungeon ())
return ;
2009-10-17 15:51:44 -07:00
2008-11-21 10:07:11 -06:00
Map :: PlayerList const & PlayerList = map -> GetPlayers ();
2009-10-17 16:20:24 -07:00
for ( Map :: PlayerList :: const_iterator i = PlayerList . begin (); i != PlayerList . end (); ++ i )
2008-11-21 10:07:11 -06:00
if ( Player * i_pl = i -> getSource ())
2009-01-03 12:42:23 +01:00
if ( i_pl -> isAlive ())
2009-08-14 19:45:06 +02:00
i_pl -> TeleportTo ( m_creature -> GetMapId (), fX , fY , fZ , fO , TELE_TO_NOT_LEAVE_COMBAT );
2008-11-18 19:40:06 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
Unit * ScriptedAI :: DoSelectLowestHpFriendly ( float fRange , uint32 uiMinHPDiff )
2008-10-11 14:16:25 -05:00
{
Unit * pUnit = NULL ;
2009-08-14 19:45:06 +02:00
Trinity :: MostHPMissingInRange u_check ( m_creature , fRange , uiMinHPDiff );
2009-01-31 16:38:50 -06:00
Trinity :: UnitLastSearcher < Trinity :: MostHPMissingInRange > searcher ( m_creature , pUnit , u_check );
2009-08-14 19:45:06 +02:00
m_creature -> VisitNearbyObject ( fRange , searcher );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return pUnit ;
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
std :: list < Creature *> ScriptedAI :: DoFindFriendlyCC ( float fRange )
2008-10-11 14:16:25 -05:00
{
std :: list < Creature *> pList ;
2009-08-14 19:45:06 +02:00
Trinity :: FriendlyCCedInRange u_check ( m_creature , fRange );
2009-01-31 16:38:50 -06:00
Trinity :: CreatureListSearcher < Trinity :: FriendlyCCedInRange > searcher ( m_creature , pList , u_check );
2009-08-14 19:45:06 +02:00
m_creature -> VisitNearbyObject ( fRange , searcher );
2008-10-11 14:16:25 -05:00
return pList ;
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
std :: list < Creature *> ScriptedAI :: DoFindFriendlyMissingBuff ( float fRange , uint32 uiSpellid )
2008-10-11 14:16:25 -05:00
{
std :: list < Creature *> pList ;
2009-08-14 19:45:06 +02:00
Trinity :: FriendlyMissingBuffInRange u_check ( m_creature , fRange , uiSpellid );
2009-01-31 16:38:50 -06:00
Trinity :: CreatureListSearcher < Trinity :: FriendlyMissingBuffInRange > searcher ( m_creature , pList , u_check );
2009-08-14 19:45:06 +02:00
m_creature -> VisitNearbyObject ( fRange , searcher );
2008-10-11 14:16:25 -05:00
return pList ;
}
2009-10-17 15:51:44 -07:00
2009-07-24 05:27:49 +02:00
Player * ScriptedAI :: GetPlayerAtMinimumRange ( float fMinimumRange )
{
Player * pPlayer = NULL ;
2009-10-17 15:51:44 -07:00
2009-07-24 05:27:49 +02:00
CellPair pair ( Trinity :: ComputeCellPair ( m_creature -> GetPositionX (), m_creature -> GetPositionY ()));
Cell cell ( pair );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2009-07-24 05:27:49 +02:00
Trinity :: PlayerAtMinimumRangeAway check ( m_creature , fMinimumRange );
Trinity :: PlayerSearcher < Trinity :: PlayerAtMinimumRangeAway > searcher ( m_creature , pPlayer , check );
TypeContainerVisitor < Trinity :: PlayerSearcher < Trinity :: PlayerAtMinimumRangeAway > , GridTypeMapContainer > visitor ( searcher );
2009-10-17 15:51:44 -07:00
2009-07-24 05:27:49 +02:00
CellLock < GridReadGuard > cell_lock ( cell , pair );
cell_lock -> Visit ( cell_lock , visitor , * ( m_creature -> GetMap ()));
2009-10-17 15:51:44 -07:00
2009-07-24 05:27:49 +02:00
return pPlayer ;
}
2009-10-17 15:51:44 -07:00
2009-04-19 21:16:11 +02:00
void ScriptedAI :: SetEquipmentSlots ( bool bLoadDefault , int32 uiMainHand , int32 uiOffHand , int32 uiRanged )
{
if ( bLoadDefault )
{
if ( CreatureInfo const * pInfo = GetCreatureTemplateStore ( m_creature -> GetEntry ()))
m_creature -> LoadEquipment ( pInfo -> equipmentId , true );
2009-10-17 15:51:44 -07:00
2009-04-19 21:16:11 +02:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-04-19 21:16:11 +02:00
if ( uiMainHand >= 0 )
m_creature -> SetUInt32Value ( UNIT_VIRTUAL_ITEM_SLOT_ID + 0 , uint32 ( uiMainHand ));
2009-10-17 15:51:44 -07:00
2009-04-19 21:16:11 +02:00
if ( uiOffHand >= 0 )
m_creature -> SetUInt32Value ( UNIT_VIRTUAL_ITEM_SLOT_ID + 1 , uint32 ( uiOffHand ));
2009-10-17 15:51:44 -07:00
2009-04-19 21:16:11 +02:00
if ( uiRanged >= 0 )
m_creature -> SetUInt32Value ( UNIT_VIRTUAL_ITEM_SLOT_ID + 2 , uint32 ( uiRanged ));
}
2009-10-17 15:51:44 -07:00
2009-08-13 02:48:34 +02:00
void ScriptedAI :: SetCombatMovement ( bool bCombatMove )
2009-05-19 21:03:43 +02:00
{
2009-08-13 02:48:34 +02:00
m_bCombatMovement = bCombatMove ;
2009-05-19 21:03:43 +02:00
}
2009-10-17 15:51:44 -07:00
2009-10-17 07:42:48 -07:00
enum eNPCs
2009-08-14 19:45:06 +02:00
{
NPC_BROODLORD = 12017 ,
NPC_VOID_REAVER = 19516 ,
NPC_JAN_ALAI = 23578 ,
NPC_SARTHARION = 28860
};
2009-10-17 15:51:44 -07:00
2009-08-08 21:29:12 +02:00
// Hacklike storage used for misc creatures that are expected to evade of outside of a certain area.
// It is assumed the information is found elswehere and can be handled by mangos. So far no luck finding such information/way to extract it.
bool ScriptedAI :: EnterEvadeIfOutOfCombatArea ( const uint32 uiDiff )
{
2009-10-27 17:07:40 -07:00
if ( m_uiEvadeCheckCooldown <= uiDiff )
2009-08-08 21:29:12 +02:00
m_uiEvadeCheckCooldown = 2500 ;
else
{
m_uiEvadeCheckCooldown -= uiDiff ;
return false ;
}
2009-10-17 15:51:44 -07:00
2009-08-08 21:29:12 +02:00
if ( m_creature -> IsInEvadeMode () || ! m_creature -> getVictim ())
return false ;
2009-10-17 15:51:44 -07:00
2009-08-08 21:29:12 +02:00
float fX = m_creature -> GetPositionX ();
float fY = m_creature -> GetPositionY ();
float fZ = m_creature -> GetPositionZ ();
2009-10-17 15:51:44 -07:00
2009-08-08 21:29:12 +02:00
switch ( m_creature -> GetEntry ())
{
2009-08-14 19:45:06 +02:00
case NPC_BROODLORD : // broodlord (not move down stairs)
2009-08-08 21:29:12 +02:00
if ( fZ > 448.60f )
return false ;
break ;
2009-08-14 19:45:06 +02:00
case NPC_VOID_REAVER : // void reaver (calculate from center of room)
2009-08-08 21:29:12 +02:00
if ( m_creature -> GetDistance2d ( 432.59f , 371.93f ) < 105.0f )
return false ;
break ;
2009-08-14 19:45:06 +02:00
case NPC_JAN_ALAI : // jan'alai (calculate by Z)
2009-08-08 21:29:12 +02:00
if ( fZ > 12.0f )
return false ;
break ;
2009-08-14 19:45:06 +02:00
case NPC_SARTHARION : // sartharion (calculate box)
2009-08-12 23:34:19 +02:00
if ( fX > 3218.86f && fX < 3275.69f && fY < 572.40f && fY > 484.68f )
2009-08-08 21:29:12 +02:00
return false ;
break ;
default :
error_log ( "TSCR: EnterEvadeIfOutOfCombatArea used for creature entry %u, but does not have any definition." , m_creature -> GetEntry ());
return false ;
}
2009-10-17 15:51:44 -07:00
2009-08-08 21:29:12 +02:00
EnterEvadeMode ();
return true ;
}
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
void Scripted_NoMovementAI :: AttackStart ( Unit * pWho )
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
if ( ! pWho )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-08-14 19:45:06 +02:00
if ( m_creature -> Attack ( pWho , true ))
2008-10-11 14:16:25 -05:00
{
2009-08-14 19:45:06 +02:00
DoStartNoMovement ( pWho );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-05-17 16:37:03 -05:00
BossAI :: BossAI ( Creature * c , uint32 id ) : ScriptedAI ( c )
, bossId ( id ), summons ( me ), instance ( c -> GetInstanceData ())
, boundary ( instance ? instance -> GetBossBoundary ( id ) : NULL )
{
}
2009-10-17 15:51:44 -07:00
2009-05-10 22:48:22 -05:00
void BossAI :: _Reset ()
{
2009-06-13 11:23:50 -05:00
if ( ! me -> isAlive ())
return ;
2009-10-17 15:51:44 -07:00
2009-05-10 22:48:22 -05:00
events . Reset ();
summons . DespawnAll ();
2009-05-16 22:45:13 -05:00
if ( instance )
instance -> SetBossState ( bossId , NOT_STARTED );
2009-05-10 22:48:22 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-10 22:48:22 -05:00
void BossAI :: _JustDied ()
{
events . Reset ();
summons . DespawnAll ();
2009-05-16 22:45:13 -05:00
if ( instance )
instance -> SetBossState ( bossId , DONE );
2009-05-10 22:48:22 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-10 22:48:22 -05:00
void BossAI :: _EnterCombat ()
{
2009-05-20 11:44:38 -05:00
me -> setActive ( true );
2009-05-10 22:48:22 -05:00
DoZoneInCombat ();
2009-05-16 22:45:13 -05:00
if ( instance )
instance -> SetBossState ( bossId , IN_PROGRESS );
2009-05-10 22:48:22 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-26 19:55:41 -05:00
void BossAI :: TeleportCheaters ()
{
float x , y , z ;
me -> GetPosition ( x , y , z );
std :: list < HostilReference *> & m_threatlist = me -> getThreatManager (). getThreatList ();
2009-10-17 16:20:24 -07:00
for ( std :: list < HostilReference *>:: iterator itr = m_threatlist . begin (); itr != m_threatlist . end (); ++ itr )
2009-05-26 19:55:41 -05:00
if (( * itr ) -> getTarget () -> GetTypeId () == TYPEID_PLAYER && ! CheckBoundary (( * itr ) -> getTarget ()))
( * itr ) -> getTarget () -> NearTeleportTo ( x , y , z , 0 );
}
2009-10-17 15:51:44 -07:00
2009-05-17 16:37:03 -05:00
bool BossAI :: CheckBoundary ( Unit * who )
{
if ( ! boundary || ! who )
return true ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( BossBoundaryMap :: const_iterator itr = boundary -> begin (); itr != boundary -> end (); ++ itr )
2009-05-17 16:37:03 -05:00
{
switch ( itr -> first )
{
case BOUNDARY_N :
if ( me -> GetPositionX () > itr -> second )
return false ;
break ;
case BOUNDARY_S :
if ( me -> GetPositionX () < itr -> second )
return false ;
break ;
case BOUNDARY_E :
if ( me -> GetPositionY () < itr -> second )
return false ;
break ;
case BOUNDARY_W :
if ( me -> GetPositionY () > itr -> second )
return false ;
break ;
case BOUNDARY_NW :
if ( me -> GetPositionX () + me -> GetPositionY () > itr -> second )
return false ;
break ;
case BOUNDARY_SE :
if ( me -> GetPositionX () + me -> GetPositionY () < itr -> second )
return false ;
break ;
case BOUNDARY_NE :
if ( me -> GetPositionX () - me -> GetPositionY () > itr -> second )
return false ;
break ;
case BOUNDARY_SW :
if ( me -> GetPositionX () - me -> GetPositionY () < itr -> second )
return false ;
break ;
}
}
2009-10-17 15:51:44 -07:00
2009-05-17 16:37:03 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2009-05-10 22:48:22 -05:00
void BossAI :: JustSummoned ( Creature * summon )
{
summons . Summon ( summon );
2009-05-13 10:54:11 -05:00
if ( me -> isInCombat ())
DoZoneInCombat ( summon );
2009-05-10 22:48:22 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-10 22:48:22 -05:00
void BossAI :: SummonedCreatureDespawn ( Creature * summon )
{
summons . Despawn ( summon );
}
2009-10-17 15:51:44 -07:00
2009-05-10 01:22:51 -05:00
#define GOBJECT(x) (const_cast<GameObjectInfo*>(GetGameObjectInfo(x)))
2009-10-17 15:51:44 -07:00
2009-02-05 15:38:24 -06:00
void LoadOverridenSQLData ()
{
GameObjectInfo * goInfo ;
2009-10-17 15:51:44 -07:00
2009-02-05 15:38:24 -06:00
// Sunwell Plateau : Kalecgos : Spectral Rift
2009-05-10 01:22:51 -05:00
if ( goInfo = GOBJECT ( 187055 ))
if ( goInfo -> type == GAMEOBJECT_TYPE_GOOBER )
goInfo -> goober . lockId = 57 ; // need LOCKTYPE_QUICK_OPEN
2009-10-17 15:51:44 -07:00
2009-05-10 01:22:51 -05:00
// Naxxramas : Sapphiron Birth
if ( goInfo = GOBJECT ( 181356 ))
if ( goInfo -> type == GAMEOBJECT_TYPE_TRAP )
goInfo -> trap . radius = 50 ;
2009-02-05 15:38:24 -06:00
}
2009-10-17 15:51:44 -07:00
2009-02-05 15:38:24 -06:00
void LoadOverridenDBCData ()
{
SpellEntry * spellInfo ;
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < GetSpellStore () -> GetNumRows (); ++ i )
2009-05-09 10:50:41 -05:00
{
2009-06-04 17:42:48 -05:00
spellInfo = GET_SPELL ( i );
2009-05-13 10:54:11 -05:00
if ( ! spellInfo )
continue ;
2009-10-17 15:51:44 -07:00
2009-05-13 10:54:11 -05:00
switch ( i )
{
// Black Temple : Illidan : Parasitic Shadowfiend Passive
case 41013 :
spellInfo -> EffectApplyAuraName [ 0 ] = 4 ; // proc debuff, and summon infinite fiends
break ;
2009-08-09 15:09:44 -05:00
// Naxxramas : Gothik : Inform Inf range
2009-05-13 10:54:11 -05:00
case 27892 :
case 27928 :
case 27935 :
case 27915 :
case 27931 :
case 27937 :
spellInfo -> rangeIndex = 13 ;
break ;
2009-08-09 15:09:44 -05:00
// Ulduar : Flame Leviathan : Pursued
case 62374 :
spellInfo -> MaxAffectedTargets = 1 ;
spellInfo -> EffectImplicitTargetB [ 0 ] = TARGET_UNIT_AREA_ENTRY_SRC ;
spellInfo -> EffectImplicitTargetB [ 1 ] = TARGET_UNIT_AREA_ENTRY_SRC ;
break ;
2009-05-13 10:54:11 -05:00
}
2009-05-09 10:50:41 -05:00
}
}
2009-07-12 01:17:04 +02:00
Creature * GetClosestCreatureWithEntry ( WorldObject * pSource , uint32 Entry , float MaxSearchRange )
{
Creature * pCreature = NULL ;
2009-10-17 15:51:44 -07:00
2009-07-12 01:17:04 +02:00
CellPair pair ( Trinity :: ComputeCellPair ( pSource -> GetPositionX (), pSource -> GetPositionY ()));
Cell cell ( pair );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2009-07-12 01:17:04 +02:00
Trinity :: NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check ( * pSource , Entry , true , MaxSearchRange );
Trinity :: CreatureLastSearcher < Trinity :: NearestCreatureEntryWithLiveStateInObjectRangeCheck > searcher ( pSource , pCreature , creature_check );
2009-10-17 15:51:44 -07:00
2009-07-12 01:17:04 +02:00
TypeContainerVisitor < Trinity :: CreatureLastSearcher < Trinity :: NearestCreatureEntryWithLiveStateInObjectRangeCheck > , GridTypeMapContainer > creature_searcher ( searcher );
2009-10-17 15:51:44 -07:00
2009-07-12 01:17:04 +02:00
CellLock < GridReadGuard > cell_lock ( cell , pair );
cell_lock -> Visit ( cell_lock , creature_searcher , * ( pSource -> GetMap ()));
2009-10-17 15:51:44 -07:00
2009-07-12 01:17:04 +02:00
return pCreature ;
}