aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/116_world.sql8
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp35
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/illidari_council.cpp3
-rw-r--r--src/game/SharedDefines.h4
-rw-r--r--src/game/Spell.cpp1048
-rw-r--r--src/game/Spell.h103
-rw-r--r--src/game/SpellMgr.cpp4
7 files changed, 490 insertions, 715 deletions
diff --git a/sql/updates/116_world.sql b/sql/updates/116_world.sql
new file mode 100644
index 00000000000..7d9fce4c319
--- /dev/null
+++ b/sql/updates/116_world.sql
@@ -0,0 +1,8 @@
+INSERT INTO `spell_script_target` VALUES ('30531', '1', '17256');
+INSERT INTO `spell_script_target` VALUES ('41455', '1', '22949');
+INSERT INTO `spell_script_target` VALUES ('41455', '1', '22950');
+INSERT INTO `spell_script_target` VALUES ('41455', '1', '22951');
+INSERT INTO `spell_script_target` VALUES ('41455', '1', '22952');
+INSERT INTO `spell_script_target` VALUES ('42471', '1', '23817');
+INSERT INTO `spell_script_target` VALUES ('43734', '1', '23817');
+INSERT INTO `spell_script_target` VALUES ('42631', '1', '23920'); \ No newline at end of file
diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
index 87152a249f2..505f73e7f21 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
@@ -96,6 +96,7 @@ EndScriptData */
#define SPELL_DUAL_WIELD 42459
//Phase Normal spells
#define SPELL_FLAME_CRASH_EFFECT 40836 // Firey blue ring of circle that the other flame crash summons
+#define SPELL_SUMMON_SHADOWDEMON 41117 // Summon four shadowfiends
#define SPELL_SHADOWFIEND_PASSIVE 41913 // Passive aura for shadowfiends
#define SPELL_SHADOW_DEMON_PASSIVE 41079 // Adds the "shadowform" aura to Shadow Demons.
#define SPELL_CONSUME_SOUL 41080 // Once the Shadow Demons reach their target, they use this to kill them
@@ -385,13 +386,18 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
void Reset();
- void JustSummoned(Creature* summon)//, TempSummonType type)
+ void JustSummoned(Creature* summon)
{
- if(summon->GetCreatureInfo()->Entry == FLAME_CRASH)
+ if(summon->GetCreatureInfo()->Entry == SHADOW_DEMON)
{
- // type = TEMPSUMMON_TIMED_DESPAWN;
+ Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0);
+ if(target && target->GetTypeId() == TYPEID_PLAYER) // only on players.
+ {
+ summon->AddThreat(target, 5000000.0f);
+ summon->AI()->AttackStart(target);
+ }
+ DoZoneInCombat(summon);
}
- //error_log("justsummoned %d %d", summon->GetCreatureInfo()->Entry, summon->GetGUID());
}
void SummonedCreatureDespawn(Creature* summon)
@@ -558,25 +564,6 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
void CastEyeBlast();
void SummonFlamesOfAzzinoth();
void SummonMaiev();
- void SummonShadowDemon()
- {
- Creature* ShadowDemon = NULL;
- Unit* target = NULL;
- for(uint8 i = 0; i < 4; i++)
- {
- ShadowDemon = DoSpawnCreature(SHADOW_DEMON, 0,0,0,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,25000);
- if(ShadowDemon)
- {
- target = SelectUnit(SELECT_TARGET_RANDOM, 0);
- if(target && target->GetTypeId() == TYPEID_PLAYER) // only on players.
- {
- ShadowDemon->AddThreat(target, 5000000.0f);
- ShadowDemon->AI()->AttackStart(target);
- }
- DoZoneInCombat(ShadowDemon);
- }
- }
- }
void HandleTalkSequence();
void HandleFlightSequence()
{
@@ -943,7 +930,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
Timer[EVENT_SHADOW_BLAST] = 4000;
break;
case EVENT_SHADOWDEMON:
- SummonShadowDemon();
+ DoCast(m_creature, SPELL_SUMMON_SHADOWDEMON);
Timer[EVENT_SHADOWDEMON] = 0;
Timer[EVENT_FLAME_BURST] += 10000;
break;
diff --git a/src/bindings/scripts/scripts/zone/black_temple/illidari_council.cpp b/src/bindings/scripts/scripts/zone/black_temple/illidari_council.cpp
index 13f30cf37da..6e5cabc034c 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/illidari_council.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/illidari_council.cpp
@@ -695,8 +695,7 @@ struct TRINITY_DLL_DECL boss_lady_malandeAI : public boss_illidari_councilAI
if(CircleOfHealingTimer < diff)
{
- //Currently bugged and puts Malande on the threatlist of the other council members. It also heals players.
- //DoCast(m_creature, SPELL_CIRCLE_OF_HEALING);
+ DoCast(m_creature, SPELL_CIRCLE_OF_HEALING);
CircleOfHealingTimer = 60000;
}else CircleOfHealingTimer -= diff;
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index 988c43a826b..f950a9ceb6c 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -807,7 +807,7 @@ enum Targets
TARGET_IN_FRONT_OF_CASTER = 24,
//TARGET_UNIT_CONE_ENEMY
TARGET_DUELVSPLAYER = 25,
- //TARGET_UNIT_SINGLE
+ //TARGET_UNIT_TARGET
TARGET_GAMEOBJECT_ITEM = 26,
//TARGET_OBJECT_ITEM_PICKLOCK
TARGET_MASTER = 27,
@@ -842,7 +842,7 @@ enum Targets
TARGET_CHAIN_HEAL = 45,
//TARGET_UNIT_CHAINHEAL
TARGET_SCRIPT_COORDINATES = 46,
- //TARGET_DEST_TABLE_UNKNOWN
+ //TARGET_DEST_NEARBY_ENTRY
TARGET_DEST_CASTER_FRONT = 47,
TARGET_DEST_CASTER_BACK = 48,
TARGET_DEST_CASTER_RIGHT = 49,
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 7684d31eee9..716cc7a518e 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -392,12 +392,6 @@ void Spell::FillTargetMap()
if(m_spellInfo->Effect[i]==0)
continue;
- // targets for TARGET_SCRIPT_COORDINATES (A) and TARGET_SCRIPT filled in Spell::canCast call
- if( m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT_COORDINATES ||
- m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT ||
- m_spellInfo->EffectImplicitTargetB[i] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[i] != TARGET_SELF )
- continue;
-
// TODO: find a way so this is not needed?
// for area auras always add caster as target (needed for totems for example)
if(IsAreaAuraEffect(m_spellInfo->Effect[i]))
@@ -405,52 +399,31 @@ void Spell::FillTargetMap()
std::list<Unit*> tmpUnitMap;
- // TargetA/TargetB dependent from each other, we not switch to full support this dependences
- // but need it support in some know cases
- switch(m_spellInfo->EffectImplicitTargetA[i])
+ // Note: this hack with search required until GO casting not implemented
+ // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
+ // currently each enemy selected explicitly and self cast damage
+ if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_AROUND_CASTER
+ && m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA
+ && m_spellInfo->Effect[i]==SPELL_EFFECT_ENVIRONMENTAL_DAMAGE)
{
- case TARGET_ALL_AROUND_CASTER:
- if( m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_PARTY ||
- m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER ||
- m_spellInfo->EffectImplicitTargetB[i]==TARGET_RANDOM_RAID_MEMBER )
- {
- SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap);
- }
- // Note: this hack with search required until GO casting not implemented
- // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
- // currently each enemy selected explicitly and self cast damage
- else if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA && m_spellInfo->Effect[i]==SPELL_EFFECT_ENVIRONMENTAL_DAMAGE)
- {
- if(m_targets.getUnitTarget())
- tmpUnitMap.push_back(m_targets.getUnitTarget());
- }
- else
- {
- SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap);
- SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap);
- }
- break;
- case TARGET_TABLE_X_Y_Z_COORDINATES:
- // Only if target A, for target B (used in teleports) dest select in effect
- SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap);
- break;
- default:
- switch(m_spellInfo->EffectImplicitTargetB[i])
- {
- case TARGET_SCRIPT_COORDINATES: // B case filled in canCast but we need fill unit list base at A case
- SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap);
- break;
- default:
- SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap);
- SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap);
- break;
- }
- break;
+ tmpUnitMap.push_back(m_targets.getUnitTarget());
+ }
+ else
+ {
+ SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap);
+ SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap);
}
- if( (m_spellInfo->EffectImplicitTargetA[i]==0 || m_spellInfo->EffectImplicitTargetA[i]==TARGET_EFFECT_SELECT) &&
- (m_spellInfo->EffectImplicitTargetB[i]==0 || m_spellInfo->EffectImplicitTargetB[i]==TARGET_EFFECT_SELECT) )
+ if(tmpUnitMap.empty())
{
+ if( m_spellInfo->EffectImplicitTargetA[i]==TARGET_SCRIPT ||
+ m_spellInfo->EffectImplicitTargetB[i]==TARGET_SCRIPT ||
+ m_spellInfo->EffectImplicitTargetA[i]==TARGET_SCRIPT_COORDINATES ||
+ m_spellInfo->EffectImplicitTargetB[i]==TARGET_SCRIPT_COORDINATES )
+ {
+ if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
+ continue;
+ }
// add here custom effects that need default target.
// FOR EVERY TARGET TYPE THERE IS A DIFFERENT FILL!!
switch(m_spellInfo->Effect[i])
@@ -1166,6 +1139,140 @@ struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit,
}
};
+void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, Unit* pUnitTarget, float max_range, uint32 unMaxTargets)
+{
+ if(!pUnitTarget)
+ return;
+
+ //FIXME: This very like horrible hack and wrong for most spells
+ if(m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE)
+ max_range += unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
+
+ CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ std::list<Unit *> tempUnitMap;
+
+ {
+ Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, m_caster, max_range);
+ Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check);
+
+ TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
+ TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
+
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ }
+
+ tempUnitMap.sort(TargetDistanceOrder(pUnitTarget));
+
+ if(tempUnitMap.empty())
+ return;
+
+ uint32 t = unMaxTargets;
+ if(pUnitTarget != m_caster)
+ {
+ if(*tempUnitMap.begin() == pUnitTarget)
+ tempUnitMap.erase(tempUnitMap.begin());
+ TagUnitMap.push_back(pUnitTarget);
+ --t;
+ }
+ Unit *prev = pUnitTarget;
+
+ std::list<Unit*>::iterator next = tempUnitMap.begin();
+
+ while(t && next != tempUnitMap.end())
+ {
+ if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
+ break;
+
+ if(!prev->IsWithinLOSInMap(*next)
+ || m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE && !m_caster->isInFront(*next, max_range))
+ {
+ ++next;
+ continue;
+ }
+
+ prev = *next;
+ TagUnitMap.push_back(prev);
+ tempUnitMap.erase(next);
+ tempUnitMap.sort(TargetDistanceOrder(prev));
+ next = tempUnitMap.begin();
+ --t;
+ }
+}
+
+void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const uint32 &type, SpellTargets TargetType, uint32 entry)
+{
+ if(type == PUSH_DEST_CENTER && !m_targets.m_destX && !m_targets.m_destY && !m_targets.m_destZ)
+ {
+ sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id );
+ return;
+ }
+
+ CellPair p(Trinity::ComputeCellPair(m_targets.m_destX, m_targets.m_destY));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+ CellLock<GridReadGuard> cell_lock(cell, p);
+
+ Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry);
+
+ if(TargetType != SPELL_TARGETS_ENTRY)
+ {
+ TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
+ cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ }
+ TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
+ cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+}
+
+Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry)
+{
+ CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+ CellLock<GridReadGuard> cell_lock(cell, p);
+
+ Unit* target = NULL;
+ switch(TargetType)
+ {
+ case SPELL_TARGETS_ENTRY:
+ {
+ Creature* target = NULL;
+ Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, entry, true, radius);
+ Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(target, u_check);
+ TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
+ cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ return target;
+ }break;
+ default:
+ case SPELL_TARGETS_AOE_DAMAGE:
+ {
+ Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius);
+ Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, u_check);
+ TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
+ TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
+ cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ }break;
+ case SPELL_TARGETS_FRIENDLY:
+ {
+ Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius);
+ Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(target, u_check);
+ TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
+ TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
+ cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ }break;
+ }
+ return target;
+}
+
void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
{
float radius;
@@ -1186,311 +1293,249 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets;
switch(cur)
{
- // destination around caster
- case TARGET_DEST_CASTER_FRONT_LEFT:
- case TARGET_DEST_CASTER_BACK_LEFT:
- case TARGET_DEST_CASTER_BACK_RIGHT:
- case TARGET_DEST_CASTER_FRONT_RIGHT:
- case TARGET_DEST_CASTER_FRONT:
- case TARGET_DEST_CASTER_BACK:
- case TARGET_DEST_CASTER_RIGHT:
- case TARGET_DEST_CASTER_LEFT:
- case TARGET_DEST_CASTER_RANDOM:
- case TARGET_DEST_CASTER_RADIUS:
+ // specific unit
+ case TARGET_SELF:
+ case TARGET_SELF_FISHING:
{
- float x, y, z, angle, dist;
-
- if (m_spellInfo->EffectRadiusIndex[i])
- dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
- else
- dist = 3.0f;//do we need this?
- if (cur == TARGET_DEST_CASTER_RANDOM)
- dist *= rand_norm(); // This case we need to consider caster size
- else
- dist -= m_caster->GetObjectSize(); // Size is calculated in GetNearPoint(), but we do not need it
- //need a new function to remove this repeated work
-
- switch(cur)
+ TagUnitMap.push_back(m_caster);
+ }break;
+ case TARGET_MASTER:
+ {
+ if(Unit* owner = m_caster->GetCharmerOrOwner())
+ TagUnitMap.push_back(owner);
+ }break;
+ case TARGET_PET:
+ {
+ if(Pet* tmpUnit = m_caster->GetPet())
+ TagUnitMap.push_back(tmpUnit);
+ }break;
+ case TARGET_NONCOMBAT_PET:
+ {
+ if(Unit* target = m_targets.getUnitTarget())
+ if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET)
+ TagUnitMap.push_back(target);
+ }break;
+ case TARGET_SINGLE_FRIEND: // ally
+ case TARGET_SINGLE_FRIEND_2: // raid member
+ case TARGET_DUELVSPLAYER: // all (SelectMagnetTarget()?)
+ case TARGET_UNIT_SINGLE_UNKNOWN:
+ {
+ if(m_targets.getUnitTarget())
+ TagUnitMap.push_back(m_targets.getUnitTarget());
+ }break;
+ case TARGET_CHAIN_DAMAGE:
+ {
+ if(Unit* pUnitTarget = SelectMagnetTarget())
{
- case TARGET_DEST_CASTER_FRONT_LEFT: angle = -M_PI/4; break;
- case TARGET_DEST_CASTER_BACK_LEFT: angle = -3*M_PI/4; break;
- case TARGET_DEST_CASTER_BACK_RIGHT: angle = 3*M_PI/4; break;
- case TARGET_DEST_CASTER_FRONT_RIGHT:angle = M_PI/4; break;
- case TARGET_DEST_CASTER_FRONT: angle = 0.0f; break;
- case TARGET_DEST_CASTER_BACK: angle = M_PI; break;
- case TARGET_DEST_CASTER_RIGHT: angle = M_PI/2; break;
- case TARGET_DEST_CASTER_LEFT: angle = -M_PI/2; break;
- default: angle = rand_norm()*2*M_PI; break;
+ if(EffectChainTarget <= 1)
+ TagUnitMap.push_back(pUnitTarget);
+ else //TODO: chain target should also use magnet target
+ SearchChainTarget(TagUnitMap, pUnitTarget, radius, EffectChainTarget);
}
-
- m_caster->GetClosePoint(x, y, z, 0, dist, angle);
- m_targets.setDestination(x, y, z); // do not know if has ground visual
- TagUnitMap.push_back(m_caster); // may remove this in the future, if unitmap is empty, push m_caster
+ }break;
+ case TARGET_GAMEOBJECT:
+ {
+ if(m_targets.getGOTarget())
+ AddGOTarget(m_targets.getGOTarget(), i);
+ }break;
+ case TARGET_GAMEOBJECT_ITEM:
+ {
+ if(m_targets.getGOTargetGUID())
+ AddGOTarget(m_targets.getGOTarget(), i);
+ else if(m_targets.getItemTarget())
+ AddItemTarget(m_targets.getItemTarget(), i);
}break;
- // destination around target
- case TARGET_DEST_TARGET_FRONT:
- case TARGET_DEST_TARGET_BACK:
- case TARGET_DEST_TARGET_RIGHT:
- case TARGET_DEST_TARGET_LEFT:
- case TARGET_DEST_TARGET_RANDOM:
- case TARGET_DEST_TARGET_RADIUS:
+ // reference dest
+ case TARGET_EFFECT_SELECT:
+ m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
+ case TARGET_ALL_AROUND_CASTER:
{
- Unit *target = m_targets.getUnitTarget();
- if(!target)
+ m_caster->GetPosition(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ);
+ }break;
+ case TARGET_CURRENT_ENEMY_COORDINATES:
+ m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
+ case TARGET_DUELVSPLAYER_COORDINATES: // no ground?
+ {
+ if(Unit* currentTarget = m_targets.getUnitTarget())
+ currentTarget->GetPosition(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ);
+ }break;
+ case TARGET_DEST_TABLE_UNKNOWN2:
+ case TARGET_TABLE_X_Y_Z_COORDINATES:
+ {
+ SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
+ if(st)
{
- sLog.outError("SPELL: no unit target for spell ID %u\n", m_spellInfo->Id);
- break;
+ if (st->target_mapId == m_caster->GetMapId())
+ m_targets.setDestination(st->target_X, st->target_Y, st->target_Z);
}
-
- float x, y, z, angle, dist;
-
- if (m_spellInfo->EffectRadiusIndex[i])
- dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
- else
- dist = 3.0f;//do we need this?
- if (cur == TARGET_DEST_TARGET_RANDOM)
- dist *= rand_norm(); // This case we need to consider caster size
else
- dist -= target->GetObjectSize(); // Size is calculated in GetNearPoint(), but we do not need it
- //need a new function to remove this repeated work
-
- switch(cur)
- {
- case TARGET_DEST_TARGET_FRONT: angle = 0.0f; break;
- case TARGET_DEST_TARGET_BACK: angle = M_PI; break;
- case TARGET_DEST_TARGET_RIGHT: angle = M_PI/2; break;
- case TARGET_DEST_TARGET_LEFT: angle = -M_PI/2; break;
- default: angle = rand_norm()*2*M_PI; break;
- }
-
- target->GetClosePoint(x, y, z, 0, dist, angle);
- m_targets.setDestination(x, y, z); // do not know if has ground visual
- TagUnitMap.push_back(m_caster); // may remove this in the future, if unitmap is empty, push m_caster
+ sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id );
}break;
- // destination around destination
- case TARGET_DEST_DEST_RANDOM:
+ // area targets
+ case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
{
- if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
- {
- sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id);
+ if(m_spellInfo->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA)
break;
- }
- float x, y, z, dist, px, py, pz;
- dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
- x = m_targets.m_destX;
- y = m_targets.m_destY;
- z = m_targets.m_destZ;
- m_caster->GetRandomPoint(x, y, z, dist, px, py, pz);
- m_targets.setDestination(px, py, pz);
- TagUnitMap.push_back(m_caster);
+ m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
+ }
+ case TARGET_ALL_ENEMY_IN_AREA:
+ {
+ SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE);
}break;
- case TARGET_SELF2:
+ case TARGET_ALL_FRIENDLY_UNITS_IN_AREA:
+ m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
+ case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER:
{
- TagUnitMap.push_back(m_caster);
+ SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_FRIENDLY);
}break;
-
- case TARGET_SELF:
case TARGET_AREAEFFECT_CUSTOM:
- case TARGET_AREAEFFECT_CUSTOM_2:
- {
- TagUnitMap.push_back(m_caster);
- break;
- }
- case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA:
+ m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
+ case TARGET_UNIT_AREA_ENTRY:
{
- m_targets.m_targetMask = 0;
- unMaxTargets = EffectChainTarget;
- float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
-
- CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
-
- std::list<Unit *> tempUnitMap;
-
+ SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id);
+ SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id);
+ if(lower==upper)
{
- Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range);
- Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check);
-
- TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
- TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
-
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- }
-
- if(tempUnitMap.empty())
+ sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT, but does not have record in `spell_script_target`",m_spellInfo->Id);
break;
-
- tempUnitMap.sort(TargetDistanceOrder(m_caster));
-
- //Now to get us a random target that's in the initial range of the spell
- uint32 t = 0;
- std::list<Unit *>::iterator itr = tempUnitMap.begin();
- while(itr!= tempUnitMap.end() && (*itr)->GetDistance(m_caster) < radius)
- ++t, ++itr;
-
- if(!t)
- break;
-
- itr = tempUnitMap.begin();
- std::advance(itr, rand()%t);
- Unit *pUnitTarget = *itr;
- TagUnitMap.push_back(pUnitTarget);
-
- tempUnitMap.erase(itr);
-
- tempUnitMap.sort(TargetDistanceOrder(pUnitTarget));
-
- t = unMaxTargets - 1;
- Unit *prev = pUnitTarget;
- std::list<Unit*>::iterator next = tempUnitMap.begin();
-
- while(t && next != tempUnitMap.end() )
+ }
+ // let it be done in one check?
+ for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST)
{
- if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
- break;
-
- if(!prev->IsWithinLOSInMap(*next))
+ if(i_spellST->second.type != SPELL_TARGET_TYPE_CREATURE)
{
- ++next;
+ sLog.outError( "SPELL: spell ID %u requires non-creature target\n", m_spellInfo->Id );
continue;
}
-
- prev = *next;
- TagUnitMap.push_back(prev);
- tempUnitMap.erase(next);
- tempUnitMap.sort(TargetDistanceOrder(prev));
- next = tempUnitMap.begin();
-
- --t;
+ SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry);
}
}break;
- case TARGET_PET:
+ case TARGET_IN_FRONT_OF_CASTER:
{
- Pet* tmpUnit = m_caster->GetPet();
- if (!tmpUnit) break;
- TagUnitMap.push_back(tmpUnit);
- break;
- }
- case TARGET_CHAIN_DAMAGE:
+ bool inFront = m_spellInfo->SpellVisual != 3879;
+ SearchAreaTarget(TagUnitMap, radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE);
+ }break;
+
+ // nearby target
+ case TARGET_UNIT_NEARBY_ALLY:
{
- if (EffectChainTarget <= 1)
+ if(Unit* pUnitTarget = SearchNearbyTarget(radius, SPELL_TARGETS_FRIENDLY))
+ TagUnitMap.push_back(pUnitTarget);
+ }break;
+ case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA:
+ {
+ if(EffectChainTarget <= 1)
{
- Unit* pUnitTarget = SelectMagnetTarget();
- if(pUnitTarget)
+ if(Unit* pUnitTarget = SearchNearbyTarget(radius, SPELL_TARGETS_AOE_DAMAGE))
TagUnitMap.push_back(pUnitTarget);
}
else
- {
- Unit* pUnitTarget = m_targets.getUnitTarget();
- if(!pUnitTarget)
- break;
+ SearchChainTarget(TagUnitMap, m_caster, radius, EffectChainTarget);
+ }break;
+ case TARGET_SCRIPT:
+ case TARGET_SCRIPT_COORDINATES:
+ {
+ SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id);
+ SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id);
+ if(lower==upper)
+ sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id);
- unMaxTargets = EffectChainTarget;
+ SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
+ float range = GetSpellMaxRange(srange);
- float max_range;
- if(m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE)
- max_range = radius; //
- else
- //FIXME: This very like horrible hack and wrong for most spells
- max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
+ Creature* creatureScriptTarget = NULL;
+ GameObject* goScriptTarget = NULL;
- CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
-
- Unit* originalCaster = GetOriginalCaster();
- if(originalCaster)
+ for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST)
+ {
+ switch(i_spellST->second.type)
{
- std::list<Unit *> tempUnitMap;
-
+ case SPELL_TARGET_TYPE_GAMEOBJECT:
{
- Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, originalCaster, max_range);
- Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check);
+ GameObject* p_GameObject = NULL;
- TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
- TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
+ if(i_spellST->second.targetEntry)
+ {
+ CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- }
+ Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range);
+ Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check);
- tempUnitMap.sort(TargetDistanceOrder(pUnitTarget));
+ TypeContainerVisitor<Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- if(tempUnitMap.empty())
+ if(p_GameObject)
+ {
+ // remember found target and range, next attempt will find more near target with another entry
+ creatureScriptTarget = NULL;
+ goScriptTarget = p_GameObject;
+ range = go_check.GetLastRange();
+ }
+ }
+ else if( focusObject ) //Focus Object
+ {
+ float frange = m_caster->GetDistance(focusObject);
+ if(range >= frange)
+ {
+ creatureScriptTarget = NULL;
+ goScriptTarget = focusObject;
+ range = frange;
+ }
+ }
break;
+ }
+ case SPELL_TARGET_TYPE_CREATURE:
+ case SPELL_TARGET_TYPE_DEAD:
+ default:
+ {
+ Creature *p_Creature = NULL;
- if(*tempUnitMap.begin() == pUnitTarget)
- tempUnitMap.erase(tempUnitMap.begin());
+ CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate(); // Really don't know what is that???
- TagUnitMap.push_back(pUnitTarget);
- uint32 t = unMaxTargets - 1;
- Unit *prev = pUnitTarget;
- std::list<Unit*>::iterator next = tempUnitMap.begin();
+ Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range);
+ Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check);
- while(t && next != tempUnitMap.end() )
- {
- if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
- break;
+ TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
+
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, grid_creature_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- if(!prev->IsWithinLOSInMap(*next))
+ if(p_Creature )
{
- ++next;
- continue;
+ creatureScriptTarget = p_Creature;
+ goScriptTarget = NULL;
+ range = u_check.GetLastRange();
}
-
- prev = *next;
- TagUnitMap.push_back(prev);
- tempUnitMap.erase(next);
- tempUnitMap.sort(TargetDistanceOrder(prev));
- next = tempUnitMap.begin();
-
- --t;
+ break;
}
}
}
- }break;
- case TARGET_ALL_ENEMY_IN_AREA:
- {
- }break;
- case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
- {
- // targets the ground, not the units in the area
- if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA)
- {
- CellPair p(Trinity::ComputeCellPair(m_targets.m_destX, m_targets.m_destY));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
-
- Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE);
-
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
-
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- // exclude caster (this can be important if this not original caster)
- TagUnitMap.remove(m_caster);
- }
- }break;
- case TARGET_DUELVSPLAYER_COORDINATES:
- {
- if(Unit* currentTarget = m_targets.getUnitTarget())
+ if(cur == TARGET_SCRIPT_COORDINATES)
{
- m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ());
- TagUnitMap.push_back(currentTarget);
+ if(creatureScriptTarget)
+ m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ());
+ else if(goScriptTarget)
+ m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ());
}
}break;
+
+
+ // dummy
+ case TARGET_AREAEFFECT_CUSTOM_2:
+ {
+ TagUnitMap.push_back(m_caster);
+ break;
+ }
+
case TARGET_ALL_PARTY_AROUND_CASTER:
case TARGET_ALL_PARTY_AROUND_CASTER_2:
case TARGET_ALL_PARTY:
@@ -1534,66 +1579,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
if(Player* target = ((Player*)m_caster)->GetNextRandomRaidMember(radius))
TagUnitMap.push_back(target);
}break;
- case TARGET_SINGLE_FRIEND:
- case TARGET_SINGLE_FRIEND_2:
- {
- if(m_targets.getUnitTarget())
- TagUnitMap.push_back(m_targets.getUnitTarget());
- }break;
- case TARGET_NONCOMBAT_PET:
- {
- if(Unit* target = m_targets.getUnitTarget())
- if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET)
- TagUnitMap.push_back(target);
- }break;
- case TARGET_ALL_AROUND_CASTER:
- {
- CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
-
- Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_SELF_CENTER,SPELL_TARGETS_AOE_DAMAGE);
-
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
-
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- }break;
- case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER:
- {
- CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
-
- Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY);
-
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
-
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- }break;
- case TARGET_ALL_FRIENDLY_UNITS_IN_AREA:
- {
- CellPair p(Trinity::ComputeCellPair(m_targets.m_destX, m_targets.m_destY));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
-
- Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_FRIENDLY);
-
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
-
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- }break;
// TARGET_SINGLE_PARTY means that the spells can only be casted on a party member and not on the caster (some sceals, fire shield from imp, etc..)
case TARGET_SINGLE_PARTY:
{
@@ -1649,59 +1634,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}
}
}break;
- case TARGET_GAMEOBJECT:
- {
- if(m_targets.getGOTarget())
- AddGOTarget(m_targets.getGOTarget(), i);
- }break;
- case TARGET_IN_FRONT_OF_CASTER:
- {
- CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
-
- bool inFront = m_spellInfo->SpellVisual != 3879;
- Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE);
-
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
-
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- }break;
- case TARGET_DUELVSPLAYER:
- {
- Unit *target = m_targets.getUnitTarget();
- if(target)
- {
- if(m_caster->IsFriendlyTo(target))
- {
- TagUnitMap.push_back(target);
- }
- else
- {
- Unit* pUnitTarget = SelectMagnetTarget();
- if(pUnitTarget)
- TagUnitMap.push_back(pUnitTarget);
- }
- }
- }break;
- case TARGET_GAMEOBJECT_ITEM:
- {
- if(m_targets.getGOTargetGUID())
- AddGOTarget(m_targets.getGOTarget(), i);
- else if(m_targets.getItemTarget())
- AddItemTarget(m_targets.getItemTarget(), i);
- break;
- }
- case TARGET_MASTER:
- {
- if(Unit* owner = m_caster->GetCharmerOrOwner())
- TagUnitMap.push_back(owner);
- break;
- }
case TARGET_ALL_ENEMY_IN_AREA_CHANNELED:
{
// targets the ground, not the units in the area
@@ -1799,17 +1731,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}
}break;
- case TARGET_SCRIPT:
- {
- if(m_targets.getUnitTarget())
- TagUnitMap.push_back(m_targets.getUnitTarget());
- if(m_targets.getItemTarget())
- AddItemTarget(m_targets.getItemTarget(), i);
- }break;
- case TARGET_SELF_FISHING:
- {
- TagUnitMap.push_back(m_caster);
- }break;
case TARGET_CHAIN_HEAL:
{
Unit* pUnitTarget = m_targets.getUnitTarget();
@@ -1885,28 +1806,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}
}
}break;
- case TARGET_CURRENT_ENEMY_COORDINATES:
- {
- Unit* currentTarget = m_targets.getUnitTarget();
- if(currentTarget)
- {
- TagUnitMap.push_back(currentTarget);
- m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ());
- if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA_INSTANT)
- {
- CellPair p(Trinity::ComputeCellPair(currentTarget->GetPositionX(), currentTarget->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
- Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius,PUSH_TARGET_CENTER, SPELL_TARGETS_AOE_DAMAGE);
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_notifier(notifier);
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_notifier(notifier);
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- }
- }
- }break;
case TARGET_AREAEFFECT_PARTY_AND_CLASS:
{
Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER
@@ -1932,40 +1831,106 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
TagUnitMap.push_back(m_targets.getUnitTarget());
break;
}
- case TARGET_TABLE_X_Y_Z_COORDINATES:
+
+ // destination around caster
+ case TARGET_DEST_CASTER_FRONT_LEFT:
+ case TARGET_DEST_CASTER_BACK_LEFT:
+ case TARGET_DEST_CASTER_BACK_RIGHT:
+ case TARGET_DEST_CASTER_FRONT_RIGHT:
+ case TARGET_DEST_CASTER_FRONT:
+ case TARGET_DEST_CASTER_BACK:
+ case TARGET_DEST_CASTER_RIGHT:
+ case TARGET_DEST_CASTER_LEFT:
+ case TARGET_DEST_CASTER_RANDOM:
+ case TARGET_DEST_CASTER_RADIUS:
{
- SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
- if(st)
+ float x, y, z, angle, dist;
+
+ if (m_spellInfo->EffectRadiusIndex[i])
+ dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
+ else
+ dist = 3.0f;//do we need this?
+ if (cur == TARGET_DEST_CASTER_RANDOM)
+ dist *= rand_norm(); // This case we need to consider caster size
+ else
+ dist -= m_caster->GetObjectSize(); // Size is calculated in GetNearPoint(), but we do not need it
+ //need a new function to remove this repeated work
+
+ switch(cur)
{
- if (st->target_mapId == m_caster->GetMapId())
- m_targets.setDestination(st->target_X, st->target_Y, st->target_Z);
+ case TARGET_DEST_CASTER_FRONT_LEFT: angle = -M_PI/4; break;
+ case TARGET_DEST_CASTER_BACK_LEFT: angle = -3*M_PI/4; break;
+ case TARGET_DEST_CASTER_BACK_RIGHT: angle = 3*M_PI/4; break;
+ case TARGET_DEST_CASTER_FRONT_RIGHT:angle = M_PI/4; break;
+ case TARGET_DEST_CASTER_FRONT: angle = 0.0f; break;
+ case TARGET_DEST_CASTER_BACK: angle = M_PI; break;
+ case TARGET_DEST_CASTER_RIGHT: angle = M_PI/2; break;
+ case TARGET_DEST_CASTER_LEFT: angle = -M_PI/2; break;
+ default: angle = rand_norm()*2*M_PI; break;
+ }
- // if B==TARGET_TABLE_X_Y_Z_COORDINATES then A already fill all required targets
- if (m_spellInfo->EffectImplicitTargetB[i] && m_spellInfo->EffectImplicitTargetB[i]!=TARGET_TABLE_X_Y_Z_COORDINATES)
- {
- CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate();
+ m_caster->GetClosePoint(x, y, z, 0, dist, angle);
+ m_targets.setDestination(x, y, z); // do not know if has ground visual
+ }break;
- SpellTargets targetB = SPELL_TARGETS_AOE_DAMAGE;
- // Select friendly targets for positive effect
- if (IsPositiveEffect(m_spellInfo->Id, i))
- targetB = SPELL_TARGETS_FRIENDLY;
+ // destination around target
+ case TARGET_DEST_TARGET_FRONT:
+ case TARGET_DEST_TARGET_BACK:
+ case TARGET_DEST_TARGET_RIGHT:
+ case TARGET_DEST_TARGET_LEFT:
+ case TARGET_DEST_TARGET_RANDOM:
+ case TARGET_DEST_TARGET_RADIUS:
+ {
+ Unit *target = m_targets.getUnitTarget();
+ if(!target)
+ {
+ sLog.outError("SPELL: no unit target for spell ID %u\n", m_spellInfo->Id);
+ break;
+ }
- Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius,PUSH_DEST_CENTER, targetB);
+ float x, y, z, angle, dist;
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_notifier(notifier);
- TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_notifier(notifier);
+ if (m_spellInfo->EffectRadiusIndex[i])
+ dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
+ else
+ dist = 3.0f;//do we need this?
+ if (cur == TARGET_DEST_TARGET_RANDOM)
+ dist *= rand_norm(); // This case we need to consider caster size
+ else
+ dist -= target->GetObjectSize(); // Size is calculated in GetNearPoint(), but we do not need it
+ //need a new function to remove this repeated work
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, world_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- cell_lock->Visit(cell_lock, grid_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
- }
+ switch(cur)
+ {
+ case TARGET_DEST_TARGET_FRONT: angle = 0.0f; break;
+ case TARGET_DEST_TARGET_BACK: angle = M_PI; break;
+ case TARGET_DEST_TARGET_RIGHT: angle = M_PI/2; break;
+ case TARGET_DEST_TARGET_LEFT: angle = -M_PI/2; break;
+ default: angle = rand_norm()*2*M_PI; break;
}
- else
- sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id );
+
+ target->GetClosePoint(x, y, z, 0, dist, angle);
+ m_targets.setDestination(x, y, z); // do not know if has ground visual
+ }break;
+
+ // destination around destination
+ case TARGET_DEST_DEST_RANDOM:
+ {
+ if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
+ {
+ sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id);
+ break;
+ }
+ float x, y, z, dist, px, py, pz;
+ dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
+ x = m_targets.m_destX;
+ y = m_targets.m_destY;
+ z = m_targets.m_destZ;
+ m_caster->GetRandomPoint(x, y, z, dist, px, py, pz);
+ m_targets.setDestination(px, py, pz);
}break;
+ case TARGET_SELF2:
+ break;
default:
break;
}
@@ -2012,9 +1977,7 @@ void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura)
m_spellState = SPELL_STATE_PREPARING;
- m_castPositionX = m_caster->GetPositionX();
- m_castPositionY = m_caster->GetPositionY();
- m_castPositionZ = m_caster->GetPositionZ();
+ m_caster->GetPosition(m_castPositionX, m_castPositionY, m_castPositionZ);
m_castOrientation = m_caster->GetOrientation();
if(triggeredByAura)
@@ -2170,6 +2133,9 @@ void Spell::cast(bool skipCheck)
}
}
+ FillTargetMap();
+
+ // who did this hack?
// Conflagrate - consumes immolate
if ((m_spellInfo->TargetAuraState == AURA_STATE_IMMOLATE) && m_targets.getUnitTarget())
{
@@ -2195,7 +2161,6 @@ void Spell::cast(bool skipCheck)
TakePower();
TakeReagents(); // we must remove reagents before HandleEffects to allow place crafted item in same slot
- FillTargetMap();
if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in Take*/FillTargetMap
return;
@@ -3438,143 +3403,6 @@ uint8 Spell::CanCast(bool strict)
if(uint8 castResult = CheckItems())
return castResult;
- //ImpliciteTargetA-B = 38, If fact there is 0 Spell with ImpliciteTargetB=38
- if(m_UniqueTargetInfo.empty()) // skip second canCast apply (for delayed spells for example)
- {
- for(uint8 j = 0; j < 3; j++)
- {
- if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT ||
- m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF ||
- m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES ||
- m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES )
- {
- bool okDoo = false;
-
- SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id);
- SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id);
- if(lower==upper)
- sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id);
-
- SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
- float range = GetSpellMaxRange(srange);
-
- Creature* creatureScriptTarget = NULL;
- GameObject* goScriptTarget = NULL;
-
- for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST)
- {
- switch(i_spellST->second.type)
- {
- case SPELL_TARGET_TYPE_GAMEOBJECT:
- {
- GameObject* p_GameObject = NULL;
-
- if(i_spellST->second.targetEntry)
- {
- CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
-
- Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range);
- Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check);
-
- TypeContainerVisitor<Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
-
- if(p_GameObject)
- {
- // remember found target and range, next attempt will find more near target with another entry
- creatureScriptTarget = NULL;
- goScriptTarget = p_GameObject;
- range = go_check.GetLastRange();
- }
- }
- else if( focusObject ) //Focus Object
- {
- float frange = m_caster->GetDistance(focusObject);
- if(range >= frange)
- {
- creatureScriptTarget = NULL;
- goScriptTarget = focusObject;
- range = frange;
- }
- }
- break;
- }
- case SPELL_TARGET_TYPE_CREATURE:
- case SPELL_TARGET_TYPE_DEAD:
- default:
- {
- Creature *p_Creature = NULL;
-
- CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
- cell.SetNoCreate(); // Really don't know what is that???
-
- Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range);
- Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check);
-
- TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
-
- CellLock<GridReadGuard> cell_lock(cell, p);
- cell_lock->Visit(cell_lock, grid_creature_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
-
- if(p_Creature )
- {
- creatureScriptTarget = p_Creature;
- goScriptTarget = NULL;
- range = u_check.GetLastRange();
- }
- break;
- }
- }
- }
-
- if(creatureScriptTarget)
- {
- // store coordinates for TARGET_SCRIPT_COORDINATES
- if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES ||
- m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES )
- {
- m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ());
-
- if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA)
- AddUnitTarget(creatureScriptTarget, j);
- }
- // store explicit target for TARGET_SCRIPT
- else
- AddUnitTarget(creatureScriptTarget, j);
- }
- else if(goScriptTarget)
- {
- // store coordinates for TARGET_SCRIPT_COORDINATES
- if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES ||
- m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES )
- {
- m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ());
-
- if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA)
- AddGOTarget(goScriptTarget, j);
- }
- // store explicit target for TARGET_SCRIPT
- else
- AddGOTarget(goScriptTarget, j);
- }
- //Missing DB Entry or targets for this spellEffect.
- else
- {
- // not report target not existence for triggered spells
- if(m_triggeredByAuraSpell || m_IsTriggeredSpell)
- return SPELL_FAILED_DONT_REPORT;
- else
- return SPELL_FAILED_BAD_TARGETS;
- }
- }
- }
- }
-
if(uint8 castResult = CheckRange(strict))
return castResult;
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 5f7ec033381..e66a5af0876 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -75,14 +75,12 @@ enum SpellNotifyPushType
PUSH_IN_BACK,
PUSH_SELF_CENTER,
PUSH_DEST_CENTER,
- PUSH_TARGET_CENTER
};
bool IsQuestTameSpell(uint32 spellId);
namespace Trinity
{
- struct SpellNotifierPlayer;
struct SpellNotifierCreatureAndPlayer;
}
@@ -180,13 +178,27 @@ enum SpellState
SPELL_STATE_DELAYED = 5
};
+enum ReplenishType
+{
+ REPLENISH_UNDEFINED = 0,
+ REPLENISH_HEALTH = 20,
+ REPLENISH_MANA = 21,
+ REPLENISH_RAGE = 22
+};
+
+enum SpellTargets
+{
+ SPELL_TARGETS_FRIENDLY,
+ SPELL_TARGETS_AOE_DAMAGE,
+ SPELL_TARGETS_ENTRY
+};
+
#define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL 1000
typedef std::multimap<uint64, uint64> SpellTargetTimeMap;
class Spell
{
- friend struct Trinity::SpellNotifierPlayer;
friend struct Trinity::SpellNotifierCreatureAndPlayer;
public:
@@ -497,6 +509,10 @@ class Spell
void DoAllEffectOnTarget(GOTargetInfo *target);
void DoAllEffectOnTarget(ItemTargetInfo *target);
bool IsAliveUnitPresentInTargetList();
+ void SearchAreaTarget(std::list<Unit*> &data, float radius, const uint32 &type,
+ SpellTargets TargetType, uint32 entry = 0);
+ Unit* SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry = 0);
+ void SearchChainTarget(std::list<Unit*> &data, Unit* pUnitTarget, float max_range, uint32 unMaxTargets);
// -------------------------------------------
//List For Triggered Spells
@@ -518,60 +534,8 @@ class Spell
SpellEntry const* m_triggeredByAuraSpell;
};
-enum ReplenishType
-{
- REPLENISH_UNDEFINED = 0,
- REPLENISH_HEALTH = 20,
- REPLENISH_MANA = 21,
- REPLENISH_RAGE = 22
-};
-
-enum SpellTargets
-{
- SPELL_TARGETS_HOSTILE,
- SPELL_TARGETS_NOT_FRIENDLY,
- SPELL_TARGETS_NOT_HOSTILE,
- SPELL_TARGETS_FRIENDLY,
- SPELL_TARGETS_AOE_DAMAGE
-};
-
namespace Trinity
{
- struct TRINITY_DLL_DECL SpellNotifierPlayer
- {
- std::list<Unit*> &i_data;
- Spell &i_spell;
- const uint32& i_index;
- float i_radius;
- Unit* i_originalCaster;
-
- SpellNotifierPlayer(Spell &spell, std::list<Unit*> &data, const uint32 &i, float radius)
- : i_data(data), i_spell(spell), i_index(i), i_radius(radius)
- {
- i_originalCaster = i_spell.GetOriginalCaster();
- }
-
- void Visit(PlayerMapType &m)
- {
- if(!i_originalCaster)
- return;
-
- for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
- {
- Player * pPlayer = itr->getSource();
- if( !pPlayer->isAlive() || pPlayer->isInFlight())
- continue;
-
- if( i_originalCaster->IsFriendlyTo(pPlayer) )
- continue;
-
- if( pPlayer->GetDistance(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ) < i_radius )
- i_data.push_back(pPlayer);
- }
- }
- template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
- };
-
struct TRINITY_DLL_DECL SpellNotifierCreatureAndPlayer
{
std::list<Unit*> *i_data;
@@ -580,10 +544,11 @@ namespace Trinity
float i_radius;
SpellTargets i_TargetType;
Unit* i_originalCaster;
+ uint32 i_entry;
SpellNotifierCreatureAndPlayer(Spell &spell, std::list<Unit*> &data, float radius, const uint32 &type,
- SpellTargets TargetType = SPELL_TARGETS_NOT_FRIENDLY)
- : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType)
+ SpellTargets TargetType = SPELL_TARGETS_AOE_DAMAGE, uint32 entry = 0)
+ : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType), i_entry(entry)
{
i_originalCaster = spell.GetOriginalCaster();
}
@@ -602,18 +567,6 @@ namespace Trinity
switch (i_TargetType)
{
- case SPELL_TARGETS_HOSTILE:
- if (!itr->getSource()->isTargetableForAttack() || !i_originalCaster->IsHostileTo( itr->getSource() ))
- continue;
- break;
- case SPELL_TARGETS_NOT_FRIENDLY:
- if (!itr->getSource()->isTargetableForAttack() || i_originalCaster->IsFriendlyTo( itr->getSource() ))
- continue;
- break;
- case SPELL_TARGETS_NOT_HOSTILE:
- if (!itr->getSource()->isTargetableForAttack() || i_originalCaster->IsHostileTo( itr->getSource() ))
- continue;
- break;
case SPELL_TARGETS_FRIENDLY:
if (!itr->getSource()->isTargetableForAttack() || !i_originalCaster->IsFriendlyTo( itr->getSource() ))
continue;
@@ -637,8 +590,12 @@ namespace Trinity
if (!check->IsHostileTo( itr->getSource() ))
continue;
}
- }
- break;
+ }break;
+ case SPELL_TARGETS_ENTRY:
+ {
+ if(itr->getSource()->GetTypeId()!=TYPEID_UNIT || itr->getSource()->GetEntry()!= i_entry)
+ continue;
+ }break;
default: continue;
}
@@ -660,10 +617,6 @@ namespace Trinity
if((itr->getSource()->GetDistance(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ) < i_radius ))
i_data->push_back(itr->getSource());
break;
- case PUSH_TARGET_CENTER:
- if(i_spell.m_targets.getUnitTarget()->IsWithinDistInMap((Unit*)(itr->getSource()), i_radius))
- i_data->push_back(itr->getSource());
- break;
}
}
}
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index bafc54ba2f0..efb83aa0fe2 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -1793,7 +1793,7 @@ void SpellMgr::LoadSpellScriptTarget()
continue;
}
- bool targetfound = false;
+ /*bool targetfound = false;
for(int i = 0; i <3; ++i)
{
if( spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT ||
@@ -1809,7 +1809,7 @@ void SpellMgr::LoadSpellScriptTarget()
{
sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_SCRIPT(38) or TARGET_SCRIPT_COORDINATES (46).",spellId,targetEntry);
continue;
- }
+ }*/
if( type >= MAX_SPELL_TARGET_TYPE )
{