aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp14
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp10
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp6
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp14
-rwxr-xr-xsrc/server/game/Battlegrounds/ArenaTeam.cpp4
-rwxr-xr-xsrc/server/game/Battlegrounds/Zones/BattlegroundAV.cpp15
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.cpp447
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.h30
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.cpp20
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.h4
-rwxr-xr-xsrc/server/game/Entities/Creature/CreatureGroups.cpp2
-rwxr-xr-xsrc/server/game/Entities/Object/Object.cpp12
-rwxr-xr-xsrc/server/game/Entities/Object/Object.h6
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp44
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp79
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h3
-rw-r--r--src/server/game/Grids/GridDefines.h10
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.cpp13
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.h117
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiersImpl.h111
-rwxr-xr-xsrc/server/game/Handlers/AuctionHouseHandler.cpp22
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp4
-rwxr-xr-xsrc/server/game/Handlers/NPCHandler.cpp16
-rwxr-xr-xsrc/server/game/Maps/Map.cpp2
-rwxr-xr-xsrc/server/game/Movement/MotionMaster.cpp5
-rwxr-xr-xsrc/server/game/Movement/MotionMaster.h7
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Quests/QuestDef.h2
-rwxr-xr-xsrc/server/game/Scripting/MapScripts.cpp12
-rwxr-xr-xsrc/server/game/Scripting/ScriptLoader.cpp2
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp10
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp2514
-rwxr-xr-xsrc/server/game/Spells/Spell.h192
-rw-r--r--src/server/game/Spells/SpellInfo.cpp414
-rw-r--r--src/server/game/Spells/SpellInfo.h31
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp11
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.h12
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp5
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h1
-rw-r--r--src/server/game/Warden/WardenCheckMgr.cpp6
40 files changed, 2302 insertions, 1929 deletions
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index 048cc8b3d68..01e13b29f19 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -307,11 +307,7 @@ void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
{
sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI has returned to original position before combat");
- if (m_bIsRunning && me->HasUnitMovementFlag(MOVEMENTFLAG_WALKING))
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
- else if (!m_bIsRunning && !me->HasUnitMovementFlag(MOVEMENTFLAG_WALKING))
- me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
-
+ me->SetWalk(!m_bIsRunning);
RemoveEscortState(STATE_ESCORT_RETURNING);
if (!m_uiWPWaitTimer)
@@ -400,14 +396,14 @@ void npc_escortAI::SetRun(bool on)
if (on)
{
if (!m_bIsRunning)
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ me->SetWalk(false);
else
sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI attempt to set run mode, but is already running.");
}
else
{
if (m_bIsRunning)
- me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ me->SetWalk(true);
else
sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI attempt to set walk mode, but is already walking.");
}
@@ -473,9 +469,9 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
//Set initial speed
if (m_bIsRunning)
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ me->SetWalk(false);
else
- me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ me->SetWalk(true);
AddEscortState(STATE_ESCORT_ESCORTING);
}
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 7838e6891fe..8776090c86f 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -45,7 +45,7 @@ SmartAI::SmartAI(Creature* c) : CreatureAI(c)
mCanRepeatPath = false;
// spawn in run mode
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ me->SetWalk(false);
mRun = false;
me->GetPosition(&mLastOOCPos);
@@ -720,9 +720,9 @@ uint64 SmartAI::GetGUID(int32 /*id*/)
void SmartAI::SetRun(bool run)
{
if (run)
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ me->SetWalk(false);
else
- me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ me->SetWalk(true);
mRun = run;
}
@@ -731,12 +731,12 @@ void SmartAI::SetFly(bool fly)
{
if (fly)
{
- me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SetLevitate(true);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x01);
}
else
{
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SetLevitate(false);
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, 0x01);
}
me->SetFlying(fly);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 95574e6d21d..67d26ea06dd 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -482,7 +482,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell))
me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false);
else
- sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: %u Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId()));
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId()));
sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_CAST:: Creature %u casts spell %u on target %u with castflags %u",
me->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags);
}
@@ -511,7 +511,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell))
tempLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false);
else
- sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: %u Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId()));
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId()));
sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker %u casts spell %u on target %u with castflags %u",
tempLastInvoker->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags);
@@ -1576,7 +1576,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*it)->ToUnit()->HasAura(e.action.cast.spell))
(*itr)->ToUnit()->CastSpell((*it)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED) ? true : false);
else
- sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: %u Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*it)->GetGUID(), (*it)->GetEntry(), uint32((*it)->GetTypeId()));
+ sLog->outDebug(LOG_FILTER_DATABASE_AI, "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*it)->GetGUID(), (*it)->GetEntry(), uint32((*it)->GetTypeId()));
}
}
}
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index f99e317454c..4105012ac86 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -62,27 +62,19 @@ void SmartWaypointMgr::LoadFromDB()
y = fields[3].GetFloat();
z = fields[4].GetFloat();
- WayPoint* wp = new WayPoint(id, x, y, z);
-
if (last_entry != entry)
{
- path = new WPPath;
+ waypoint_map[entry] = new WPPath();
last_id = 1;
+ count++;
}
if (last_id != id)
- {
sLog->outErrorDb("SmartWaypointMgr::LoadFromDB: Path entry %u, unexpected point id %u, expected %u.", entry, id, last_id);
- }
last_id++;
- (*path)[id] = wp;
+ (*waypoint_map[entry])[id] = new WayPoint(id, x, y, z);
- if (last_entry != entry)
- {
- count++;
- waypoint_map[entry] = path;
- }
last_entry = entry;
total++;
}
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index 02707261d13..a5c34e4b7ee 100755
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -295,8 +295,10 @@ void ArenaTeam::SetCaptain(uint64 guid)
if (newCaptain)
{
newCaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 0);
+ char const* oldCaptainName = oldCaptain ? oldCaptain->GetName() : "";
+ uint32 oldCaptainLowGuid = oldCaptain ? oldCaptain->GetGUIDLow() : 0;
sLog->outArena("Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u].",
- oldCaptain->GetName(), oldCaptain->GetGUIDLow(), newCaptain->GetName(), newCaptain->GetGUIDLow(), GetId(), GetType());
+ oldCaptainName, oldCaptainLowGuid, newCaptain->GetName(), newCaptain->GetGUIDLow(), GetId(), GetType());
}
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index 801b522feab..5ea9fc67fed 100755
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -1032,17 +1032,18 @@ void BattlegroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object)
std::vector<uint64> ghost_list = m_ReviveQueue[BgCreatures[node]];
if (!ghost_list.empty())
{
- Player* player;
- WorldSafeLocsEntry const* ClosestGrave = NULL;
+ Player* waitingPlayer; // player waiting at graveyard for resurrection
+ WorldSafeLocsEntry const* closestGrave = NULL;
for (std::vector<uint64>::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr)
{
- player = ObjectAccessor::FindPlayer(*ghost_list.begin());
- if (!player)
+ waitingPlayer = ObjectAccessor::FindPlayer(*ghost_list.begin());
+ if (!waitingPlayer)
continue;
- if (!ClosestGrave)
- ClosestGrave = GetClosestGraveYard(player);
+
+ if (!closestGrave)
+ closestGrave = GetClosestGraveYard(waitingPlayer);
else
- player->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, player->GetOrientation());
+ waitingPlayer->TeleportTo(GetMapId(), closestGrave->x, closestGrave->y, closestGrave->z, player->GetOrientation());
}
m_ReviveQueue[BgCreatures[node]].clear();
}
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 550814ccf3f..7d21f94f372 100755
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -26,6 +26,7 @@
#include "ConditionMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
// Checks if object meets the condition
// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI)
@@ -94,14 +95,14 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
}
case CONDITION_CLASS:
{
- if (Player* player = object->ToPlayer())
- condMeets = player->getClassMask() & ConditionValue1;
+ if (Unit* unit = object->ToUnit())
+ condMeets = unit->getClassMask() & ConditionValue1;
break;
}
case CONDITION_RACE:
{
- if (Player* player = object->ToPlayer())
- condMeets = player->getRaceMask() & ConditionValue1;
+ if (Unit* unit = object->ToUnit())
+ condMeets = unit->getRaceMask() & ConditionValue1;
break;
}
case CONDITION_SKILL:
@@ -153,9 +154,6 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
condMeets = ((InstanceMap*)map)->GetInstanceScript()->GetData(ConditionValue1) == ConditionValue2;
break;
}
- case CONDITION_SPELL_SCRIPT_TARGET:
- condMeets = true;//spell target condition is handled in spellsystem, here it is always true
- break;
case CONDITION_MAPID:
condMeets = object->GetMapId() == ConditionValue1;
break;
@@ -291,12 +289,153 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
return condMeets && script;
}
+uint32 Condition::GetSearcherTypeMaskForCondition()
+{
+ // build mask of types for which condition can return true
+ // this is used for speeding up gridsearches
+ if (NegativeCondition)
+ return (GRID_MAP_TYPE_MASK_ALL);
+ uint32 mask = 0;
+ switch (ConditionType)
+ {
+ case CONDITION_NONE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_AURA:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ITEM:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ITEM_EQUIPPED:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ZONEID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_REPUTATION_RANK:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ACHIEVEMENT:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_TEAM:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_CLASS:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_RACE:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_SKILL:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUESTREWARDED:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUESTTAKEN:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUEST_COMPLETE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUEST_NONE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ACTIVE_EVENT:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_INSTANCE_DATA:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_MAPID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_AREAID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_SPELL:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_LEVEL:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_DRUNKENSTATE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_NEAR_CREATURE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_NEAR_GAMEOBJECT:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_OBJECT_ENTRY:
+ switch (ConditionValue1)
+ {
+ case TYPEID_UNIT:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE;
+ break;
+ case TYPEID_PLAYER:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case TYPEID_GAMEOBJECT:
+ mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT;
+ break;
+ case TYPEID_CORPSE:
+ mask |= GRID_MAP_TYPE_MASK_CORPSE;
+ break;
+ default:
+ break;
+ }
+ case CONDITION_TYPE_MASK:
+ if (ConditionValue1 & TYPEMASK_UNIT)
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ if (ConditionValue1 & TYPEMASK_PLAYER)
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ if (ConditionValue1 & TYPEMASK_GAMEOBJECT)
+ mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT;
+ if (ConditionValue1 & TYPEMASK_CORPSE)
+ mask |= GRID_MAP_TYPE_MASK_CORPSE;
+ break;
+ case CONDITION_RELATION_TO:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_REACTION_TO:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_DISTANCE_TO:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_ALIVE:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_HP_VAL:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_HP_PCT:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_WORLD_STATE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_PHASEMASK:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ default:
+ ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
+ break;
+ }
+ return mask;
+}
+
uint32 Condition::GetMaxAvailableConditionTargets()
{
// returns number of targets which are available for given source type
switch(SourceType)
{
case CONDITION_SOURCE_TYPE_SPELL:
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
@@ -327,8 +466,49 @@ ConditionList ConditionMgr::GetConditionReferences(uint32 refId)
return conditions;
}
+uint32 ConditionMgr::GetSearcherTypeMaskForConditionList(ConditionList const& conditions)
+{
+ if (conditions.empty())
+ return GRID_MAP_TYPE_MASK_ALL;
+ // groupId, typeMask
+ std::map<uint32, uint32> ElseGroupStore;
+ for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
+ {
+ // no point of having not loaded conditions in list
+ ASSERT((*i)->isLoaded() && "ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list");
+ std::map<uint32, uint32>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup);
+ // group not filled yet, fill with widest mask possible
+ if (itr == ElseGroupStore.end())
+ ElseGroupStore[(*i)->ElseGroup] = GRID_MAP_TYPE_MASK_ALL;
+ // no point of checking anymore, empty mask
+ else if (!(*itr).second)
+ continue;
+
+ if ((*i)->ReferenceId) // handle reference
+ {
+ ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
+ ASSERT(ref != ConditionReferenceStore.end() && "ConditionMgr::GetSearcherTypeMaskForConditionList - incorrect reference");
+ ElseGroupStore[(*i)->ElseGroup] &= GetSearcherTypeMaskForConditionList((*ref).second);
+ }
+ else // handle normal condition
+ {
+ // object will match conditions in one ElseGroupStore only when it matches all of them
+ // so, let's find a smallest possible mask which satisfies all conditions
+ ElseGroupStore[(*i)->ElseGroup] &= (*i)->GetSearcherTypeMaskForCondition();
+ }
+ }
+ // object will match condition when one of the checks in ElseGroupStore is matching
+ // so, let's include all possible masks
+ uint32 mask = 0;
+ for (std::map<uint32, uint32>::const_iterator i = ElseGroupStore.begin(); i != ElseGroupStore.end(); ++i)
+ mask |= i->second;
+
+ return mask;
+}
+
bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions)
{
+ // groupId, groupCheckPassed
std::map<uint32, bool> ElseGroupStore;
for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
{
@@ -391,6 +571,33 @@ bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, Con
return IsObjectMeetToConditionList(sourceInfo, conditions);
}
+bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const
+{
+ return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
+ sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION ||
+ sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
+ sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET ||
+ sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
+ sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
+}
+
+bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) const
+{
+ return (sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
+}
+
ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry)
{
ConditionList spellCond;
@@ -487,6 +694,7 @@ void ConditionMgr::LoadConditions(bool isReload)
sLog->outString("Re-Loading `gossip_menu_option` Table for Conditions!");
sObjectMgr->LoadGossipMenuItems();
+ sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists();
}
QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, "
@@ -583,16 +791,23 @@ void ConditionMgr::LoadConditions(bool isReload)
}
//Grouping is only allowed for some types (loot templates, gossip menus, gossip items)
- if (cond->SourceGroup && !isGroupable(cond->SourceType))
+ if (cond->SourceGroup && !CanHaveSourceGroupSet(cond->SourceType))
+ {
+ sLog->outErrorDb("Condition type %u has not allowed value of SourceGroup = %u!", uint32(cond->SourceType), cond->SourceGroup);
+ delete cond;
+ continue;
+ }
+ if (cond->SourceId && !CanHaveSourceIdSet(cond->SourceType))
{
- sLog->outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->SourceType), cond->SourceGroup);
+ sLog->outErrorDb("Condition type %u has not allowed value of SourceId = %u!", uint32(cond->SourceType), cond->SourceId);
delete cond;
continue;
}
- else if (cond->SourceGroup)
+
+ if (cond->SourceGroup)
{
bool valid = false;
- //handle grouped conditions
+ // handle grouped conditions
switch (cond->SourceType)
{
case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE:
@@ -637,6 +852,29 @@ void ConditionMgr::LoadConditions(bool isReload)
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
valid = addToGossipMenuItems(cond);
break;
+ case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
+ {
+ //if no list for npc create one
+ if (SpellClickEventConditionStore.find(cond->SourceGroup) == SpellClickEventConditionStore.end())
+ {
+ ConditionTypeContainer cmap;
+ SpellClickEventConditionStore[cond->SourceGroup] = cmap;
+ }
+ //if no list for spellclick spell create one
+ if (SpellClickEventConditionStore[cond->SourceGroup].find(cond->SourceEntry) == SpellClickEventConditionStore[cond->SourceGroup].end())
+ {
+ ConditionList clist;
+ SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry] = clist;
+ }
+ SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
+ valid = true;
+ ++count;
+ continue; // do not add to m_AllocatedMemory to avoid double deleting
+ break;
+ }
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
+ valid = addToSpellImplicitTargetConditions(cond);
+ break;
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
{
//if no list for vehicle create one
@@ -771,6 +1009,78 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond)
return false;
}
+bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
+{
+ uint32 conditionEffMask = cond->SourceGroup;
+ SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->GetSpellInfo(cond->SourceEntry));
+ ASSERT(spellInfo);
+ std::list<uint32> sharedMasks;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ // check if effect is already a part of some shared mask
+ bool found = false;
+ for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
+ {
+ if ((1<<i) & *itr)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ // build new shared mask with found effect
+ uint32 sharedMask = (1<<i);
+ ConditionList* cmp = spellInfo->Effects[i].ImplicitTargetConditions;
+ for (uint8 effIndex = i+1; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ {
+ if (spellInfo->Effects[effIndex].ImplicitTargetConditions == cmp)
+ sharedMask |= 1<<effIndex;
+ }
+ sharedMasks.push_back(sharedMask);
+ }
+
+ for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
+ {
+ // some effect indexes should have same data
+ if (uint32 commonMask = *itr & conditionEffMask)
+ {
+ uint8 firstEffIndex = 0;
+ for (; firstEffIndex < MAX_SPELL_EFFECTS; ++firstEffIndex)
+ if ((1<<firstEffIndex) & *itr)
+ break;
+
+ // get shared data
+ ConditionList* sharedList = spellInfo->Effects[firstEffIndex].ImplicitTargetConditions;
+
+ // there's already data entry for that sharedMask
+ if (sharedList)
+ {
+ // we have overlapping masks in db
+ if (conditionEffMask != *itr)
+ {
+ sLog->outErrorDb("SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - "
+ "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->SourceEntry, cond->SourceGroup);
+ return false;
+ }
+ }
+ // no data for shared mask, we can create new submask
+ else
+ {
+ // add new list, create new shared mask
+ sharedList = new ConditionList();
+ for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i)
+ if ((1<<i) & commonMask)
+ spellInfo->Effects[i].ImplicitTargetConditions = sharedList;
+ }
+ sharedList->push_back(cond);
+ break;
+ }
+ }
+ return true;
+}
+
bool ConditionMgr::isSourceTypeValid(Condition* cond)
{
if (cond->SourceType == CONDITION_SOURCE_TYPE_NONE || cond->SourceType >= CONDITION_SOURCE_TYPE_MAX)
@@ -985,64 +1295,54 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
}
break;
}
- case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET:
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
{
- if (cond->ConditionType != CONDITION_SPELL_SCRIPT_TARGET)
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry);
+ if (!spellInfo)
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_SPELL_SCRIPT_TARGET(18) is valid for CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET(14), ignoring.", cond->SourceEntry, uint32(cond->ConditionType));
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
return false;
}
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry);
- if (!spellProto)
+ if ((cond->SourceGroup > MAX_EFFECT_MASK) || !cond->SourceGroup)
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set , ignoring.", cond->SourceEntry, cond->SourceGroup);
return false;
}
- bool targetfound = false;
+ uint32 origGroup = cond->SourceGroup;
+
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- if (spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_SRC_AREA_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_SRC_AREA ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_SRC_AREA ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_DEST_AREA ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_DEST_AREA ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_DEST_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_DEST_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CONE_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_CONE_ENTRY)
+ if (!((1<<i) & cond->SourceGroup))
+ continue;
+
+ switch (spellInfo->Effects[i].TargetA.GetSelectionCategory())
{
- targetfound = true;
- //break;
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ case TARGET_SELECT_CATEGORY_CONE:
+ case TARGET_SELECT_CATEGORY_AREA:
+ continue;
+ default:
+ break;
}
- else if (cond->ConditionValue3 & (1 << i))
+
+ switch (spellInfo->Effects[i].TargetB.GetSelectionCategory())
{
- cond->ConditionValue3 &= ~(1 << i);
- sLog->outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DEST_NEARBY_ENTRY (46)"
- ", TARGET_UNIT_SRC_AREA_ENTRY(7), TARGET_UNIT_DEST_AREA_ENTRY(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)"
- "TARGET_GAMEOBJECT_SRC_AREA(51), TARGET_GAMEOBJECT_DEST_AREA(52) in effect %u", cond->SourceEntry, uint32(i));
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ case TARGET_SELECT_CATEGORY_CONE:
+ case TARGET_SELECT_CATEGORY_AREA:
+ continue;
+ default:
+ break;
}
+
+ sLog->outErrorDb("SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i));
+ cond->SourceGroup &= ~(1<<i);
}
- if (!targetfound && !cond->ConditionValue3) // cond->mConditionValue3 already errored up there
- {
- sLog->outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DEST_NEARBY_ENTRY (46)"
- ", TARGET_UNIT_SRC_AREA_ENTRY(7), TARGET_UNIT_DEST_AREA_ENTRY(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)"
- "TARGET_GAMEOBJECT_SRC_AREA(51), TARGET_GAMEOBJECT_DEST_AREA(52)", cond->SourceEntry);
+ // all effects were removed, no need to add the condition at all
+ if (!cond->SourceGroup)
return false;
- }
- if ((cond->ConditionValue1 == SPELL_TARGET_TYPE_DEAD) && !spellProto->IsAllowingDeadTarget())
- {
- sLog->outErrorDb("SourceEntry %u in `condition` table does have SPELL_TARGET_TYPE_DEAD specified but spell does not have SPELL_ATTR2_CAN_TARGET_DEAD", cond->SourceEntry);
- return false;
- }
break;
}
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
@@ -1318,46 +1618,6 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
sLog->outErrorDb("Race condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_SPELL_SCRIPT_TARGET:
- {
- if (cond->ConditionValue1 >= MAX_SPELL_TARGET_TYPE)
- {
- sLog->outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->ConditionValue1);
- return false;
- }
-
- switch (cond->ConditionValue1)
- {
- case SPELL_TARGET_TYPE_GAMEOBJECT:
- {
- if (cond->ConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->ConditionValue2))
- {
- sLog->outErrorDb("SpellTarget condition has non existing gameobject (%u) as target, skipped", cond->ConditionValue2);
- return false;
- }
- break;
- }
- case SPELL_TARGET_TYPE_CONTROLLED:
- case SPELL_TARGET_TYPE_CREATURE:
- case SPELL_TARGET_TYPE_DEAD:
- {
- if (cond->ConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->ConditionValue2))
- {
- sLog->outErrorDb("SpellTarget condition has non existing creature template entry (%u) as target, skipped", cond->ConditionValue2);
- return false;
- }
-
- const CreatureTemplate* cInfo = sObjectMgr->GetCreatureTemplate(cond->ConditionValue2);
- if (cond->SourceEntry == 30427 && !cInfo->SkinLootId)
- {
- sLog->outErrorDb("SpellTarget condition has creature entry %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!, skipped", cond->ConditionValue2);
- return false;
- }
- break;
- }
- }
- break;
- }
case CONDITION_MAPID:
{
MapEntry const* me = sMapStore.LookupEntry(cond->ConditionValue1);
@@ -1598,6 +1858,9 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
sLog->outErrorDb("Phasemask condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
+ case CONDITION_UNUSED_18:
+ sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_18 in `conditions` table - ignoring");
+ return false;
case CONDITION_UNUSED_19:
sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
return false;
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 9911aa2a98a..5a5e2dd1c2e 100755
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -48,7 +48,7 @@ enum ConditionTypes
CONDITION_CLASS = 15, // class 0 0 true if player's class is equal to class
CONDITION_RACE = 16, // race 0 0 true if player's race is equal to race
CONDITION_ACHIEVEMENT = 17, // achievement_id 0 0 true if achievement is complete
- CONDITION_SPELL_SCRIPT_TARGET = 18, // SpellScriptTargetType, TargetEntry, 0
+ CONDITION_UNUSED_18 = 18, //
CONDITION_UNUSED_19 = 19, //
CONDITION_UNUSED_20 = 20, //
CONDITION_UNUSED_21 = 21, //
@@ -87,7 +87,7 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10,
CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11,
CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12,
- CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET = 13,
+ CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET = 13,
CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14,
CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15,
CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16,
@@ -173,6 +173,7 @@ struct Condition
}
bool Meets(ConditionSourceInfo& sourceInfo);
+ uint32 GetSearcherTypeMaskForCondition();
bool isLoaded() const { return ConditionType > CONDITION_NONE || ReferenceId; }
uint32 GetMaxAvailableConditionTargets();
};
@@ -198,9 +199,12 @@ class ConditionMgr
bool isConditionTypeValid(Condition* cond);
ConditionList GetConditionReferences(uint32 refId);
+ uint32 GetSearcherTypeMaskForConditionList(ConditionList const& conditions);
bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions);
bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions);
bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
+ bool CanHaveSourceGroupSet(ConditionSourceType sourceType) const;
+ bool CanHaveSourceIdSet(ConditionSourceType sourceType) const;
ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry);
ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType);
@@ -211,29 +215,9 @@ class ConditionMgr
bool addToLootTemplate(Condition* cond, LootTemplate* loot);
bool addToGossipMenus(Condition* cond);
bool addToGossipMenuItems(Condition* cond);
+ bool addToSpellImplicitTargetConditions(Condition* cond);
bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
- bool isGroupable(ConditionSourceType sourceType) const
- {
- return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE ||
- sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
- sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION ||
- sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
- sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
- sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
- }
-
void Clean(); // free up resources
std::list<Condition*> AllocatedMemoryStore; // some garbage collection :)
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 3dfa1cece61..20bcfc8f41c 100755
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -2408,24 +2408,24 @@ bool Creature::IsDungeonBoss() const
return cinfo && (cinfo->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS);
}
-void Creature::SetWalk(bool enable)
+bool Creature::SetWalk(bool enable)
{
- if (enable)
- AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
- else
- RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ if (!Unit::SetWalk(enable))
+ return false;
+
WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9);
data.append(GetPackGUID());
SendMessageToSet(&data, true);
+ return true;
}
-void Creature::SetLevitate(bool enable)
+bool Creature::SetLevitate(bool enable)
{
- if (enable)
- AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
- else
- RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ if (!Unit::SetLevitate(enable))
+ return false;
+
WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
data.append(GetPackGUID());
SendMessageToSet(&data, true);
+ return true;
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index bfe186329e1..40477de7c75 100755
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -520,8 +520,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type);
CreatureAI* AI() const { return (CreatureAI*)i_AI; }
- void SetWalk(bool enable);
- void SetLevitate(bool enable);
+ bool SetWalk(bool enable);
+ bool SetLevitate(bool enable);
uint32 GetShieldBlockValue() const //dunno mob block value
{
diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp
index f440fd497fc..c95d77db358 100755
--- a/src/server/game/Entities/Creature/CreatureGroups.cpp
+++ b/src/server/game/Entities/Creature/CreatureGroups.cpp
@@ -240,7 +240,7 @@ void CreatureGroup::LeaderMoveTo(float x, float y, float z)
if (member->IsWithinDist(m_leader, dist + MAX_DESYNC))
member->SetUnitMovementFlags(m_leader->GetUnitMovementFlags());
else
- member->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ member->SetWalk(false);
member->GetMotionMaster()->MovePoint(0, dx, dy, dz);
member->SetHomePosition(dx, dy, dz, pathangle);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index aadf9f44b0b..c98364ecb2d 100755
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1085,9 +1085,9 @@ bool Object::PrintIndexError(uint32 index, bool set) const
return false;
}
-bool Position::HasInLine(Unit const* target, float distance, float width) const
+bool Position::HasInLine(WorldObject const* target, float width) const
{
- if (!HasInArc(M_PI, target) || !target->IsWithinDist3d(m_positionX, m_positionY, m_positionZ, distance))
+ if (!HasInArc(M_PI, target))
return false;
width += target->GetObjectSize();
float angle = GetRelativeAngle(target);
@@ -1502,14 +1502,14 @@ bool WorldObject::IsInBetween(const WorldObject* obj1, const WorldObject* obj2,
return (size * size) >= GetExactDist2dSq(obj1->GetPositionX() + cos(angle) * dist, obj1->GetPositionY() + sin(angle) * dist);
}
-bool WorldObject::isInFront(WorldObject const* target, float distance, float arc) const
+bool WorldObject::isInFront(WorldObject const* target, float arc) const
{
- return IsWithinDist(target, distance) && HasInArc(arc, target);
+ return HasInArc(arc, target);
}
-bool WorldObject::isInBack(WorldObject const* target, float distance, float arc) const
+bool WorldObject::isInBack(WorldObject const* target, float arc) const
{
- return IsWithinDist(target, distance) && !HasInArc(2 * M_PI - arc, target);
+ return !HasInArc(2 * M_PI - arc, target);
}
void WorldObject::GetRandomPoint(const Position &pos, float distance, float &rand_x, float &rand_y, float &rand_z) const
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index c14b7599d5f..7b3fcc4a337 100755
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -451,7 +451,7 @@ struct Position
bool IsInDist(const Position* pos, float dist) const
{ return GetExactDistSq(pos) < dist * dist; }
bool HasInArc(float arcangle, const Position* pos) const;
- bool HasInLine(Unit const* target, float distance, float width) const;
+ bool HasInLine(WorldObject const* target, float width) const;
std::string ToString() const;
};
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
@@ -707,8 +707,8 @@ class WorldObject : public Object, public WorldLocation
bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const;
bool IsInRange2d(float x, float y, float minRange, float maxRange) const;
bool IsInRange3d(float x, float y, float z, float minRange, float maxRange) const;
- bool isInFront(WorldObject const* target, float distance, float arc = M_PI) const;
- bool isInBack(WorldObject const* target, float distance, float arc = M_PI) const;
+ bool isInFront(WorldObject const* target, float arc = M_PI) const;
+ bool isInBack(WorldObject const* target, float arc = M_PI) const;
bool IsInBetween(const WorldObject* obj1, const WorldObject* obj2, float size = 0) const;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index fde4f4c6959..632453a230f 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7944,14 +7944,12 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
_ApplyWeaponDamage(slot, proto, ssv, apply);
// Apply feral bonus from ScalingStatValue if set
- if (ssv)
- if (int32 feral_bonus = ssv->getFeralBonus(proto->ScalingStatValue))
- ApplyFeralAPBonus(feral_bonus, apply);
-
- // Druids get feral AP bonus from weapon dps (lso use DPS from ScalingStatValue)
- if (getClass() == CLASS_DRUID)
- if (int32 feral_bonus = proto->getFeralBonus(ssv->getDPSMod(proto->ScalingStatValue)))
+ if (ssv && getClass() == CLASS_DRUID)
+ {
+ int32 feral_bonus = ssv->getFeralBonus(proto->ScalingStatValue) + proto->getFeralBonus(ssv->getDPSMod(proto->ScalingStatValue));
+ if (feral_bonus)
ApplyFeralAPBonus(feral_bonus, apply);
+ }
}
void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply)
@@ -14071,12 +14069,10 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
menuItemBounds = sObjectMgr->GetGossipMenuItemsMapBounds(0);
uint32 npcflags = 0;
- Creature* creature = NULL;
if (source->GetTypeId() == TYPEID_UNIT)
{
- creature = source->ToCreature();
- npcflags = creature->GetUInt32Value(UNIT_NPC_FLAGS);
+ npcflags = source->GetUInt32Value(UNIT_NPC_FLAGS);
if (npcflags & UNIT_NPC_FLAG_QUESTGIVER && showQuests)
PrepareQuestMenu(source->GetGUID());
}
@@ -14091,7 +14087,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
if (!sConditionMgr->IsObjectMeetToConditions(this, source, itr->second.Conditions))
continue;
- if (source->GetTypeId() == TYPEID_UNIT)
+ if (Creature* creature = source->ToCreature())
{
if (!(itr->second.OptionNpcflag & npcflags))
continue;
@@ -14164,10 +14160,8 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
break;
}
}
- else if (source->GetTypeId() == TYPEID_GAMEOBJECT)
+ else if (GameObject* go = source->ToGameObject())
{
- GameObject* go = source->ToGameObject();
-
switch (itr->second.OptionType)
{
case GOSSIP_OPTION_GOSSIP:
@@ -16002,9 +15996,9 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id)
if (reqTarget != entry) // if entry doesn't match, check for killcredits referenced in template
{
CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
- for (uint8 j = 0; j < MAX_KILL_CREDIT; ++j)
- if (cinfo->KillCredit[j] == reqTarget)
- entry = cinfo->KillCredit[j];
+ for (uint8 k = 0; k < MAX_KILL_CREDIT; ++k)
+ if (cinfo->KillCredit[k] == reqTarget)
+ entry = cinfo->KillCredit[k];
}
}
}
@@ -17649,7 +17643,7 @@ void Player::_LoadMailedItems(Mail* mail)
{
sLog->outError("Player %u has unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUIDLow(), itemGuid, itemTemplate, mail->messageID);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_MAIL_ITEM);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_MAIL_ITEM);
stmt->setUInt32(0, itemGuid);
CharacterDatabase.Execute(stmt);
@@ -17665,10 +17659,8 @@ void Player::_LoadMailedItems(Mail* mail)
{
sLog->outError("Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: %u, deleted from mail", mail->messageID, itemGuid);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM);
-
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM);
stmt->setUInt32(0, itemGuid);
-
CharacterDatabase.Execute(stmt);
item->FSetState(ITEM_REMOVED);
@@ -19044,20 +19036,22 @@ void Player::_SaveDailyQuestStatus(SQLTransaction& trans)
stmt->setUInt32(0, GetGUIDLow());
trans->Append(stmt);
for (uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx)
+ {
if (GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx))
{
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
stmt->setUInt32(0, GetGUIDLow());
stmt->setUInt32(1, GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx));
stmt->setUInt64(2, uint64(m_lastDailyQuestTime));
trans->Append(stmt);
}
+ }
if (!m_DFQuests.empty())
{
for (DFQuestsDoneList::iterator itr = m_DFQuests.begin(); itr != m_DFQuests.end(); ++itr)
{
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
stmt->setUInt32(0, GetGUIDLow());
stmt->setUInt32(1, (*itr));
stmt->setUInt64(2, uint64(m_lastDailyQuestTime));
@@ -19080,7 +19074,7 @@ void Player::_SaveWeeklyQuestStatus(SQLTransaction& trans)
{
uint32 quest_id = *iter;
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS);
stmt->setUInt32(0, GetGUIDLow());
stmt->setUInt32(1, quest_id);
trans->Append(stmt);
@@ -19106,7 +19100,7 @@ void Player::_SaveSeasonalQuestStatus(SQLTransaction& trans)
{
uint32 quest_id = (*itr);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS);
stmt->setUInt32(0, GetGUIDLow());
stmt->setUInt32(1, quest_id);
stmt->setUInt32(2, event_id);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 47c3c1a9395..f9d287d271a 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -281,7 +281,6 @@ Unit::~Unit()
_DeleteRemovedAuras();
delete m_charmInfo;
- delete m_vehicleKit;
delete movespline;
ASSERT(!m_duringRemoveFromWorld);
@@ -1470,8 +1469,8 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
if (GetTypeId() == TYPEID_PLAYER)
{
float bonusPct = 0;
- AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT);
- for (AuraEffectList::const_iterator itr = ResIgnoreAuras.begin(); itr != ResIgnoreAuras.end(); ++itr)
+ AuraEffectList const& armorPenAuras = GetAuraEffectsByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT);
+ for (AuraEffectList::const_iterator itr = armorPenAuras.begin(); itr != armorPenAuras.end(); ++itr)
{
if ((*itr)->GetSpellInfo()->EquippedItemClass == -1)
{
@@ -9907,7 +9906,7 @@ void Unit::SetCharm(Unit* charm, bool apply)
if (charm->HasUnitMovementFlag(MOVEMENTFLAG_WALKING))
{
- charm->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ charm->SetWalk(false);
charm->SendMovementFlagUpdate();
}
@@ -10004,6 +10003,7 @@ Unit* Unit::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo)
&& _IsValidAttackTarget(magnet, spellInfo)
&& IsWithinLOSInMap(magnet))
{
+ // TODO: handle this charge drop by proc in cast phase on explicit target
(*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
return magnet;
}
@@ -13682,7 +13682,7 @@ void Unit::RemoveFromWorld()
{
m_duringRemoveFromWorld = true;
if (IsVehicle())
- GetVehicleKit()->Uninstall();
+ RemoveVehicleKit();
RemoveCharmAuras();
RemoveBindSightAuras();
@@ -13691,7 +13691,7 @@ void Unit::RemoveFromWorld()
RemoveAllGameObjects();
RemoveAllDynObjects();
- ExitVehicle();
+ ExitVehicle(); // Remove applied auras with SPELL_AURA_CONTROL_VEHICLE
UnsummonAllTotems();
RemoveAllControlled();
@@ -15459,7 +15459,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// Inform pets (if any) when player kills target)
// MUST come after victim->setDeathState(JUST_DIED); or pet next target
// selection will get stuck on same target and break pet react state
- if (Player* player = ToPlayer())
+ if (player)
{
Pet* pet = player->GetPet();
if (pet && pet->isAlive() && pet->isControlled())
@@ -15590,9 +15590,6 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
if (Player* killed = victim->ToPlayer())
sScriptMgr->OnPlayerKilledByCreature(killerCre, killed);
}
-
- if (victim->GetVehicle())
- victim->ExitVehicle();
}
void Unit::SetControlled(bool apply, UnitState state)
@@ -16178,26 +16175,6 @@ bool Unit::IsInRaidWith(Unit const* unit) const
return false;
}
-bool Unit::IsTargetMatchingCheck(Unit const* target, SpellTargetSelectionCheckTypes check) const
-{
- switch (check)
- {
- case TARGET_SELECT_CHECK_ENEMY:
- if (IsControlledByPlayer())
- return !IsFriendlyTo(target);
- else
- return IsHostileTo(target);
- case TARGET_SELECT_CHECK_ALLY:
- return IsFriendlyTo(target);
- case TARGET_SELECT_CHECK_PARTY:
- return IsInPartyWith(target);
- case TARGET_SELECT_CHECK_RAID:
- return IsInRaidWith(target);
- default:
- return true;
- }
-}
-
void Unit::GetRaidMember(std::list<Unit*> &nearMembers, float radius)
{
Player* owner = GetCharmerOrOwnerPlayerOrPlayerItself();
@@ -17021,12 +16998,21 @@ void Unit::ChangeSeat(int8 seatId, bool next)
void Unit::ExitVehicle(Position const* exitPosition)
{
- // This function can be called at upper level code to initialize an exit from the passenger's side.
+ //! This function can be called at upper level code to initialize an exit from the passenger's side.
if (!m_vehicle)
return;
GetVehicleBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, GetGUID());
- _ExitVehicle(exitPosition);
+ //! The following call would not even be executed successfully as the
+ //! SPELL_AURA_CONTROL_VEHICLE unapply handler already calls _ExitVehicle without
+ //! specifying an exitposition. The subsequent call below would return on if (!m_vehicle).
+ /*_ExitVehicle(exitPosition);*/
+ //! To do:
+ //! We need to allow SPELL_AURA_CONTROL_VEHICLE unapply handlers in spellscripts
+ //! to specify exit coordinates and either store those per passenger, or we need to
+ //! init spline movement based on those coordinates in unapply handlers, and
+ //! relocate exiting passengers based on Unit::moveSpline data. Either way,
+ //! Coming Soon™
}
void Unit::_ExitVehicle(Position const* exitPosition)
@@ -17112,6 +17098,9 @@ void Unit::BuildMovementPacket(ByteBuffer *data) const
*data << float (GetTransOffsetO());
*data << uint32(GetTransTime());
*data << uint8 (GetTransSeat());
+
+ if (GetExtraUnitMovementFlags() & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT)
+ *data << uint32(m_movementInfo.t_time2);
}
// 0x02200000
@@ -17466,3 +17455,29 @@ void Unit::SetFacingToObject(WorldObject* pObject)
// TODO: figure out under what conditions creature will move towards object instead of facing it where it currently is.
SetFacingTo(GetAngle(pObject));
}
+
+bool Unit::SetWalk(bool enable)
+{
+ if (enable == IsWalking())
+ return false;
+
+ if (enable)
+ AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
+ else
+ RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
+
+ return true;
+}
+
+bool Unit::SetLevitate(bool enable)
+{
+ if (enable == IsLevitating())
+ return false;
+
+ if (enable)
+ AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ else
+ RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+
+ return true;
+}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 66b0bcbeb54..0fe5f3d8ca3 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1394,7 +1394,6 @@ class Unit : public WorldObject
bool IsNeutralToAll() const;
bool IsInPartyWith(Unit const* unit) const;
bool IsInRaidWith(Unit const* unit) const;
- bool IsTargetMatchingCheck(Unit const* target, SpellTargetSelectionCheckTypes check) const;
void GetPartyMemberInDist(std::list<Unit*> &units, float dist);
void GetPartyMembers(std::list<Unit*> &units);
void GetRaidMember(std::list<Unit*> &units, float dist);
@@ -1628,6 +1627,8 @@ class Unit : public WorldObject
void SendMovementFlagUpdate();
bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_LEVITATING);}
bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);}
+ virtual bool SetWalk(bool enable);
+ virtual bool SetLevitate(bool enable);
void SetInFront(Unit const* target);
void SetFacingTo(float ori);
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
index 8651680cb49..d096bb7ab63 100644
--- a/src/server/game/Grids/GridDefines.h
+++ b/src/server/game/Grids/GridDefines.h
@@ -65,6 +65,16 @@ typedef GridRefManager<DynamicObject> DynamicObjectMapType;
typedef GridRefManager<GameObject> GameObjectMapType;
typedef GridRefManager<Player> PlayerMapType;
+enum GridMapTypeMask
+{
+ GRID_MAP_TYPE_MASK_CORPSE = 0x01,
+ GRID_MAP_TYPE_MASK_CREATURE = 0x02,
+ GRID_MAP_TYPE_MASK_DYNAMICOBJECT = 0x04,
+ GRID_MAP_TYPE_MASK_GAMEOBJECT = 0x08,
+ GRID_MAP_TYPE_MASK_PLAYER = 0x10,
+ GRID_MAP_TYPE_MASK_ALL = 0x1F
+};
+
typedef Grid<Player, AllWorldObjectTypes, AllGridObjectTypes> GridType;
typedef NGrid<MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index 2446e9d4276..17d3066e64d 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -343,24 +343,17 @@ bool AnyDeadUnitObjectInRangeCheck::operator()(Creature* u)
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Player* u)
{
- return AnyDeadUnitObjectInRangeCheck::operator()(u)
- && (i_spellInfo->CheckTarget(i_searchObj, u, true) == SPELL_CAST_OK)
- && i_searchObj->IsTargetMatchingCheck(u, i_check);
+ return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u);
}
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Corpse* u)
{
- Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID());
- return owner && AnyDeadUnitObjectInRangeCheck::operator()(u)
- && (i_spellInfo->CheckTarget(i_searchObj, owner, true) == SPELL_CAST_OK)
- && i_searchObj->IsTargetMatchingCheck(owner, i_check);
+ return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u);
}
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Creature* u)
{
- return AnyDeadUnitObjectInRangeCheck::operator()(u)
- && (i_spellInfo->CheckTarget(i_searchObj, u, true) == SPELL_CAST_OK)
- && i_searchObj->IsTargetMatchingCheck(u, i_check);
+ return AnyDeadUnitObjectInRangeCheck::operator()(u) && i_check(u);
}
template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &);
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 12e3fda0484..7ffdf687561 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -30,6 +30,7 @@
#include "Player.h"
#include "Unit.h"
#include "CreatureAI.h"
+#include "Spell.h"
class Player;
//class Map;
@@ -168,12 +169,33 @@ namespace Trinity
template<class Check>
struct WorldObjectSearcher
{
+ uint32 i_mapTypeMask;
uint32 i_phaseMask;
WorldObject* &i_object;
Check &i_check;
- WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check)
- : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
+ WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
+ : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
+
+ void Visit(GameObjectMapType &m);
+ void Visit(PlayerMapType &m);
+ void Visit(CreatureMapType &m);
+ void Visit(CorpseMapType &m);
+ void Visit(DynamicObjectMapType &m);
+
+ template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
+ };
+
+ template<class Check>
+ struct WorldObjectLastSearcher
+ {
+ uint32 i_mapTypeMask;
+ uint32 i_phaseMask;
+ WorldObject* &i_object;
+ Check &i_check;
+
+ WorldObjectLastSearcher(WorldObject const* searcher, WorldObject* & result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
+ : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(GameObjectMapType &m);
void Visit(PlayerMapType &m);
@@ -187,12 +209,13 @@ namespace Trinity
template<class Check>
struct WorldObjectListSearcher
{
+ uint32 i_mapTypeMask;
uint32 i_phaseMask;
std::list<WorldObject*> &i_objects;
Check& i_check;
- WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check)
- : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {}
+ WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
+ : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {}
void Visit(PlayerMapType &m);
void Visit(CreatureMapType &m);
@@ -206,14 +229,17 @@ namespace Trinity
template<class Do>
struct WorldObjectWorker
{
+ uint32 i_mapTypeMask;
uint32 i_phaseMask;
Do const& i_do;
- WorldObjectWorker(WorldObject const* searcher, Do const& _do)
- : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
+ WorldObjectWorker(WorldObject const* searcher, Do const& _do, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
+ : i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
void Visit(GameObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
+ return;
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
@@ -221,12 +247,16 @@ namespace Trinity
void Visit(PlayerMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
+ return;
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
}
void Visit(CreatureMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
+ return;
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
@@ -234,6 +264,8 @@ namespace Trinity
void Visit(CorpseMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
+ return;
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
@@ -241,6 +273,8 @@ namespace Trinity
void Visit(DynamicObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
+ return;
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
i_do(itr->getSource());
@@ -527,73 +561,11 @@ namespace Trinity
// CHECKS && DO classes
// WorldObject check classes
- class RaiseDeadObjectCheck
- {
- public:
- RaiseDeadObjectCheck(Unit* source, float range) : _source(source), _range(range) {}
- bool operator()(Creature* u)
- {
- if (_source->GetTypeId() != TYPEID_PLAYER || !((Player*)_source)->isHonorOrXPTarget(u) ||
- u->getDeathState() != CORPSE ||
- (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 ||
- (u->GetDisplayId() != u->GetNativeDisplayId()))
- return false;
-
- return _source->IsWithinDistInMap(u, _range);
- }
- bool operator()(Player* u)
- {
- if (_source == u || _source->GetTypeId() != TYPEID_PLAYER || !((Player*)_source)->isHonorOrXPTarget(u) ||
- u->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) || u->isInFlight() || !u->isDead() ||
- (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0)
- return false;
- return _source->IsWithinDistInMap(u, _range);
- }
-
- bool operator()(Corpse* u)
- {
- if (_source->GetTypeId() != TYPEID_PLAYER || u->GetType() == CORPSE_BONES)
- return false;
-
- return _source->IsWithinDistInMap(u, _range);
- }
- template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
- private:
- Unit* const _source;
- float _range;
- };
-
- class ExplodeCorpseObjectCheck
- {
- public:
- ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {}
- bool operator()(Player* u)
- {
- if (u->getDeathState() != CORPSE || u->isInFlight() ||
- u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId()))
- return false;
-
- return i_funit->IsWithinDistInMap(u, i_range);
- }
- bool operator()(Creature* u)
- {
- if (u->getDeathState() != CORPSE || u->isInFlight() ||
- (u->GetDisplayId() != u->GetNativeDisplayId()) ||
- (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0)
- return false;
-
- return i_funit->IsWithinDistInMap(u, i_range);
- }
- template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
- private:
- Unit* const i_funit;
- float i_range;
- };
class AnyDeadUnitObjectInRangeCheck
{
public:
- AnyDeadUnitObjectInRangeCheck(Unit const* searchObj, float range) : i_searchObj(searchObj), i_range(range) {}
+ AnyDeadUnitObjectInRangeCheck(Unit* searchObj, float range) : i_searchObj(searchObj), i_range(range) {}
bool operator()(Player* u);
bool operator()(Corpse* u);
bool operator()(Creature* u);
@@ -606,15 +578,16 @@ namespace Trinity
class AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck
{
public:
- AnyDeadUnitSpellTargetInRangeCheck(Unit const* searchObj, float range, SpellInfo const* spellInfo, SpellTargetSelectionCheckTypes check)
- : AnyDeadUnitObjectInRangeCheck(searchObj, range), i_spellInfo(spellInfo), i_check(check) {}
+ AnyDeadUnitSpellTargetInRangeCheck(Unit* searchObj, float range, SpellInfo const* spellInfo, SpellTargetCheckTypes check)
+ : AnyDeadUnitObjectInRangeCheck(searchObj, range), i_spellInfo(spellInfo), i_check(searchObj, searchObj, spellInfo, check, NULL)
+ {}
bool operator()(Player* u);
bool operator()(Corpse* u);
bool operator()(Creature* u);
template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
protected:
SpellInfo const* i_spellInfo;
- SpellTargetSelectionCheckTypes i_check;
+ WorldObjectSpellTargetCheck i_check;
};
// WorldObject do classes
diff --git a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
index 34fe7757c5f..40b3863679b 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
@@ -51,6 +51,9 @@ inline void Trinity::ObjectUpdater::Visit(CreatureMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
+ return;
+
// already found
if (i_object)
return;
@@ -71,6 +74,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
+ return;
+
// already found
if (i_object)
return;
@@ -91,6 +97,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
+ return;
+
// already found
if (i_object)
return;
@@ -111,6 +120,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
+ return;
+
// already found
if (i_object)
return;
@@ -131,6 +143,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m)
template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
+ return;
+
// already found
if (i_object)
return;
@@ -148,9 +163,93 @@ void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
}
}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
+ return;
+
+ for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(PlayerMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
+ return;
+
+ for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(CreatureMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
+ return;
+
+ for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(CorpseMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
+ return;
+
+ for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
+template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(DynamicObjectMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
+ return;
+
+ for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->getSource()->InSamePhase(i_phaseMask))
+ continue;
+
+ if (i_check(itr->getSource()))
+ i_object = itr->getSource();
+ }
+}
+
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
+ return;
+
for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
@@ -160,6 +259,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
+ return;
+
for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
@@ -169,6 +271,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m)
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
+ return;
+
for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
@@ -178,6 +283,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m)
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
+ return;
+
for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
@@ -187,6 +295,9 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m)
template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m)
{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
+ return;
+
for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_phaseMask))
if (i_check(itr->getSource()))
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index f99bfe52df3..45c0f7bed42 100755
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -309,28 +309,28 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data)
sAuctionMgr->AddAItem(newItem);
auctionHouse->AddAuction(AH);
- for (uint32 i = 0; i < itemsCount; ++i)
+ for (uint32 j = 0; j < itemsCount; ++j)
{
- Item* item = items[i];
+ Item* item2 = items[j];
- if (item->GetCount() == count[i])
+ if (item2->GetCount() == count[j])
{
- _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);
+ _player->MoveItemFromInventory(item2->GetBagSlot(), item2->GetSlot(), true);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- item->DeleteFromInventoryDB(trans);
- item->SaveToDB(trans);
+ item2->DeleteFromInventoryDB(trans);
+ item2->SaveToDB(trans);
CharacterDatabase.CommitTransaction(trans);
}
else
{
- item->SetCount(item->GetCount() - count[i]);
- item->SetState(ITEM_CHANGED, _player);
- _player->ItemRemovedQuestCheck(item->GetEntry(), count[i]);
- item->SendUpdateToPlayer(_player);
+ item2->SetCount(item2->GetCount() - count[j]);
+ item2->SetState(ITEM_CHANGED, _player);
+ _player->ItemRemovedQuestCheck(item2->GetEntry(), count[j]);
+ item2->SendUpdateToPlayer(_player);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- item->SaveToDB(trans);
+ item2->SaveToDB(trans);
CharacterDatabase.CommitTransaction(trans);
}
}
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index a48cf70bd54..30119c79d96 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1811,8 +1811,8 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
{
// Reset guild
- if (QueryResult result = CharacterDatabase.PQuery("SELECT guildid FROM `guild_member` WHERE guid ='%u'", lowGuid))
- if (Guild* guild = sGuildMgr->GetGuildById((result->Fetch()[0]).GetUInt32()))
+ if (QueryResult result2 = CharacterDatabase.PQuery("SELECT guildid FROM `guild_member` WHERE guid ='%u'", lowGuid))
+ if (Guild* guild = sGuildMgr->GetGuildById((result2->Fetch()[0]).GetUInt32()))
guild->DeleteMember(MAKE_NEW_GUID(lowGuid, 0, HIGHGUID_PLAYER));
}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 1f286a0af05..6a44c7ae5e2 100755
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -615,7 +615,7 @@ void WorldSession::HandleStablePet(WorldPacket & recv_data)
Pet* pet = _player->GetPet();
// can't place in stable dead pet
- if (!pet||!pet->isAlive()||pet->getPetType() != HUNTER_PET)
+ if (!pet || !pet->isAlive() || pet->getPetType() != HUNTER_PET)
{
SendStableResult(STABLE_ERR_STABLE);
return;
@@ -853,16 +853,22 @@ void WorldSession::HandleStableSwapPetCallback(PreparedQueryResult result, uint3
return;
}
- // move alive pet to slot or delete dead pet
Pet* pet = _player->GetPet();
+ // The player's pet could have been removed during the delay of the DB callback
+ if (!pet)
+ {
+ SendStableResult(STABLE_ERR_STABLE);
+ return;
+ }
+ // move alive pet to slot or delete dead pet
_player->RemovePet(pet, pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
// summon unstabled pet
- Pet* newpet = new Pet(_player);
- if (!newpet->LoadPetFromDB(_player, petEntry, petId))
+ Pet* newPet = new Pet(_player);
+ if (!newPet->LoadPetFromDB(_player, petEntry, petId))
{
- delete newpet;
+ delete newPet;
SendStableResult(STABLE_ERR_STABLE);
}
else
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index f6189fa556c..cf517ccfbb4 100755
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1544,7 +1544,7 @@ inline GridMap* Map::GetGrid(float x, float y)
return GridMaps[gx][gy];
}
-float Map::GetWaterOrGroundLevel(float x, float y, float z, float* ground /*= NULL*/, bool swim /*= false*/) const
+float Map::GetWaterOrGroundLevel(float x, float y, float z, float* ground /*= NULL*/, bool /*swim = false*/) const
{
if (const_cast<Map*>(this)->GetGrid(x, y))
{
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 954a193c498..27816753ca7 100755
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -365,10 +365,7 @@ void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float spee
init.SetParabolic(max_height,0);
init.SetVelocity(speedXY);
init.Launch();
- if (_owner->GetTypeId() == TYPEID_PLAYER)
- Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
- else
- Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
+ Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
}
void MotionMaster::MoveFall(uint32 id/*=0*/)
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index 9910f8ad40a..d6144bfcc3a 100755
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -84,7 +84,12 @@ class MotionMaster //: private std::stack<MovementGenerator *>
//typedef std::stack<MovementGenerator *> Impl;
typedef MovementGenerator* _Ty;
- void pop() { Impl[_top] = NULL; --_top; }
+ void pop()
+ {
+ Impl[_top] = NULL;
+ while (!top())
+ --_top;
+ }
void push(_Ty _Val) { ++_top; Impl[_top] = _Val; }
bool needInitTop() const { return _needInit[_top]; }
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index fb2249c508e..a8602153de3 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -79,7 +79,7 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance)
{
sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for "UI64FMTD".", i_path->at(i_currentNode)->event_id, i_currentNode, creature.GetGUID());
- creature.GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, &creature, NULL/*, false*/);
+ creature.GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, &creature, NULL);
}
// Inform script
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 21b98ad2cea..7f22b441afe 100755
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -252,7 +252,7 @@ class Quest
uint32 GetFlags() const { return Flags; }
bool IsDaily() const { return Flags & QUEST_FLAGS_DAILY; }
bool IsWeekly() const { return Flags & QUEST_FLAGS_WEEKLY; }
- bool IsSeasonal() const { return (ZoneOrSort == -QUEST_SORT_SEASONAL || ZoneOrSort == -QUEST_SORT_SPECIAL || ZoneOrSort == -QUEST_SORT_LUNAR_FESTIVAL || ZoneOrSort == -QUEST_SORT_MIDSUMMER || ZoneOrSort == -QUEST_SORT_BREWFEST || ZoneOrSort == -QUEST_SORT_LOVE_IS_IN_THE_AIR || ZoneOrSort == -QUEST_SORT_NOBLEGARDEN); }
+ bool IsSeasonal() const { return (ZoneOrSort == -QUEST_SORT_SEASONAL || ZoneOrSort == -QUEST_SORT_SPECIAL || ZoneOrSort == -QUEST_SORT_LUNAR_FESTIVAL || ZoneOrSort == -QUEST_SORT_MIDSUMMER || ZoneOrSort == -QUEST_SORT_BREWFEST || ZoneOrSort == -QUEST_SORT_LOVE_IS_IN_THE_AIR || ZoneOrSort == -QUEST_SORT_NOBLEGARDEN) && !IsRepeatable(); }
bool IsDailyOrWeekly() const { return Flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); }
bool IsRaidQuest() const { return Type == QUEST_TYPE_RAID || Type == QUEST_TYPE_RAID_10 || Type == QUEST_TYPE_RAID_25; }
bool IsAllowedInRaid() const;
diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp
index 7757e1a1a35..fb2590ebbfe 100755
--- a/src/server/game/Scripting/MapScripts.cpp
+++ b/src/server/game/Scripting/MapScripts.cpp
@@ -39,9 +39,9 @@ void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, O
return;
// prepare static data
- uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source
- uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
- uint64 ownerGUID = (source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
+ uint64 sourceGUID = source ? source->GetGUID() : uint64(0); //some script commands doesn't have source
+ uint64 targetGUID = target ? target->GetGUID() : uint64(0);
+ uint64 ownerGUID = (source && source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : uint64(0);
///- Schedule script execution for all scripts in the script map
ScriptMap const* s2 = &(s->second);
@@ -74,9 +74,9 @@ void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* sou
// NOTE: script record _must_ exist until command executed
// prepare static data
- uint64 sourceGUID = source ? source->GetGUID() : (uint64)0;
- uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
- uint64 ownerGUID = (source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
+ uint64 sourceGUID = source ? source->GetGUID() : uint64(0);
+ uint64 targetGUID = target ? target->GetGUID() : uint64(0);
+ uint64 ownerGUID = (source && source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : uint64(0);
ScriptAction sa;
sa.sourceGUID = sourceGUID;
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index cdec6bb3ffa..1207b654817 100755
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -246,7 +246,6 @@ void AddSC_ironforge();
void AddSC_isle_of_queldanas();
void AddSC_loch_modan();
void AddSC_redridge_mountains();
-void AddSC_searing_gorge();
void AddSC_silvermoon_city();
void AddSC_silverpine_forest();
void AddSC_stormwind_city();
@@ -857,7 +856,6 @@ void AddEasternKingdomsScripts()
AddSC_isle_of_queldanas();
AddSC_loch_modan();
AddSC_redridge_mountains();
- AddSC_searing_gorge();
AddSC_silvermoon_city();
AddSC_silverpine_forest();
AddSC_stormwind_city();
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 99497870a15..cb79bd00776 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4686,11 +4686,11 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
if (owner_aura)
{
owner_aura->SetStackAmount(owner_aura->GetSpellInfo()->StackAmount);
- }
- if (pet_aura)
- {
- pet_aura->SetCharges(0);
- pet_aura->SetStackAmount(owner_aura->GetSpellInfo()->StackAmount);
+ if (pet_aura)
+ {
+ pet_aura->SetCharges(0);
+ pet_aura->SetStackAmount(owner_aura->GetSpellInfo()->StackAmount);
+ }
}
break;
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 53356772ff6..db36eb30191 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -592,19 +592,6 @@ Spell::~Spell()
CheckEffectExecuteData();
}
-template<typename T>
-WorldObject* Spell::FindCorpseUsing()
-{
- // non-standard target selection
- float max_range = m_spellInfo->GetMaxRange(false);
-
- WorldObject* result = NULL;
- T u_check(m_caster, max_range);
- Trinity::WorldObjectSearcher<T> searcher(m_caster, result, u_check);
- m_caster->GetMap()->VisitFirstFound(m_caster->GetPositionX(), m_caster->GetPositionY(), max_range, searcher);
- return result;
-}
-
void Spell::InitExplicitTargets(SpellCastTargets const& targets)
{
m_targets = targets;
@@ -707,7 +694,8 @@ void Spell::SelectSpellTargets()
{
// select targets for cast phase
SelectExplicitTargets();
- uint32 processedTargets = 0;
+
+ uint32 processedAreaEffectsMask = 0;
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
// not call for empty effect.
@@ -715,9 +703,6 @@ void Spell::SelectSpellTargets()
if (!m_spellInfo->Effects[i].IsEffect())
continue;
- if (processedTargets & (1 << i))
- continue;
-
// set expected type of implicit targets to be sent to client
uint32 implicitTargetMask = GetTargetFlagMask(m_spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(m_spellInfo->Effects[i].TargetB.GetObjectType());
if (implicitTargetMask & TARGET_FLAG_UNIT)
@@ -725,13 +710,8 @@ void Spell::SelectSpellTargets()
if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM))
m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT);
- uint32 targetA = m_spellInfo->Effects[i].TargetA.GetTarget();
- uint32 targetB = m_spellInfo->Effects[i].TargetB.GetTarget();
-
- if (targetA)
- processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetA);
- if (targetB)
- processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetB);
+ SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetA, processedAreaEffectsMask);
+ SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetB, processedAreaEffectsMask);
// Select targets of effect based on effect type
// those are used when no valid target could be added for spell effect based on spell target type
@@ -793,6 +773,938 @@ void Spell::SelectSpellTargets()
}
}
+void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask)
+{
+ if (!targetType.GetTarget())
+ return;
+
+ uint32 effectMask = 1 << effIndex;
+ // set the same target list for all effects
+ // some spells appear to need this, however this requires more research
+ switch (targetType.GetSelectionCategory())
+ {
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ case TARGET_SELECT_CATEGORY_CONE:
+ case TARGET_SELECT_CATEGORY_AREA:
+ // targets for effect already selected
+ if (effectMask & processedEffectMask)
+ return;
+ // choose which targets we can select at once
+ for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
+ if (GetSpellInfo()->Effects[effIndex].TargetA.GetTarget() == GetSpellInfo()->Effects[j].TargetA.GetTarget() &&
+ GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == GetSpellInfo()->Effects[j].TargetB.GetTarget() &&
+ GetSpellInfo()->Effects[effIndex].ImplicitTargetConditions == GetSpellInfo()->Effects[j].ImplicitTargetConditions &&
+ GetSpellInfo()->Effects[effIndex].CalcRadius(m_caster) == GetSpellInfo()->Effects[j].CalcRadius(m_caster))
+ effectMask |= 1 << j;
+ processedEffectMask |= effectMask;
+ break;
+ default:
+ break;
+ }
+
+ switch(targetType.GetSelectionCategory())
+ {
+ case TARGET_SELECT_CATEGORY_CHANNEL:
+ SelectImplicitChannelTargets(effIndex, targetType);
+ break;
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ SelectImplicitNearbyTargets(effIndex, targetType, effectMask);
+ break;
+ case TARGET_SELECT_CATEGORY_CONE:
+ SelectImplicitConeTargets(effIndex, targetType, effectMask);
+ break;
+ case TARGET_SELECT_CATEGORY_AREA:
+ SelectImplicitAreaTargets(effIndex, targetType, effectMask);
+ break;
+ case TARGET_SELECT_CATEGORY_DEFAULT:
+ switch (targetType.GetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_SRC:
+ switch(targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_CASTER:
+ m_targets.SetSrc(*m_caster);
+ break;
+ default:
+ ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_SRC");
+ break;
+ }
+ break;
+ case TARGET_OBJECT_TYPE_DEST:
+ switch(targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_CASTER:
+ SelectImplicitCasterDestTargets(effIndex, targetType);
+ break;
+ case TARGET_REFERENCE_TYPE_TARGET:
+ SelectImplicitTargetDestTargets(effIndex, targetType);
+ break;
+ case TARGET_REFERENCE_TYPE_DEST:
+ SelectImplicitDestDestTargets(effIndex, targetType);
+ break;
+ default:
+ ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST");
+ break;
+ }
+ break;
+ default:
+ switch(targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_CASTER:
+ SelectImplicitCasterObjectTargets(effIndex, targetType);
+ break;
+ case TARGET_REFERENCE_TYPE_TARGET:
+ SelectImplicitTargetObjectTargets(effIndex, targetType);
+ break;
+ default:
+ ASSERT("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT");
+ break;
+ }
+ break;
+ }
+ break;
+ case TARGET_SELECT_CATEGORY_NYI:
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, effIndex, targetType.GetTarget());
+ break;
+ default:
+ ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target category");
+ break;
+ }
+}
+
+void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
+ {
+ ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target reference type");
+ return;
+ }
+
+ Spell* channeledSpell = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
+ if (!channeledSpell)
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
+ return;
+ }
+ switch (targetType.GetTarget())
+ {
+ case TARGET_UNIT_CHANNEL_TARGET:
+ // unit target may be no longer avalible - teleported out of map for example
+ if (Unit* target = Unit::GetUnit(*m_caster, channeledSpell->m_targets.GetUnitTargetGUID()))
+ AddUnitTarget(target, 1 << effIndex);
+ else
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
+ break;
+ case TARGET_DEST_CHANNEL_TARGET:
+ if (channeledSpell->m_targets.HasDst())
+ m_targets.SetDst(channeledSpell->m_targets);
+ else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, channeledSpell->m_targets.GetObjectTargetGUID()))
+ m_targets.SetDst(*target);
+ else
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
+ break;
+ case TARGET_DEST_CHANNEL_CASTER:
+ m_targets.SetDst(*channeledSpell->GetCaster());
+ break;
+ default:
+ ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target type");
+ break;
+ }
+}
+
+void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
+{
+ if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
+ {
+ ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target reference type");
+ return;
+ }
+
+ float range = 0.0f;
+ switch (targetType.GetCheckType())
+ {
+ case TARGET_CHECK_ENEMY:
+ range = m_spellInfo->GetMaxRange(false, m_caster, this);
+ break;
+ case TARGET_CHECK_ALLY:
+ case TARGET_CHECK_PARTY:
+ case TARGET_CHECK_RAID:
+ case TARGET_CHECK_RAID_CLASS:
+ range = m_spellInfo->GetMaxRange(true, m_caster, this);
+ break;
+ case TARGET_CHECK_ENTRY:
+ case TARGET_CHECK_DEFAULT:
+ range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive(), m_caster, this);
+ break;
+ default:
+ ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented selection check type");
+ break;
+ }
+
+ ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
+
+ // handle emergency case - try to use other provided targets if no conditions provided
+ if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty()))
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, effIndex);
+ switch (targetType.GetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_GOBJ:
+ if (m_spellInfo->RequiresSpellFocus)
+ {
+ if (focusObject)
+ AddGOTarget(focusObject, effMask);
+ return;
+ }
+ break;
+ case TARGET_OBJECT_TYPE_DEST:
+ if (m_spellInfo->RequiresSpellFocus)
+ {
+ if (focusObject)
+ m_targets.SetDst(*focusObject);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ WorldObject* target = SearchNearbyTarget(range, targetType.GetObjectType(), targetType.GetCheckType(), condList);
+ if (!target)
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
+ return;
+ }
+
+ switch (targetType.GetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_UNIT:
+ if (Unit* unitTarget = target->ToUnit())
+ AddUnitTarget(unitTarget, effMask, false);
+ break;
+ case TARGET_OBJECT_TYPE_GOBJ:
+ if (GameObject* gobjTarget = target->ToGameObject())
+ AddGOTarget(gobjTarget, effMask);
+ break;
+ case TARGET_OBJECT_TYPE_DEST:
+ m_targets.SetDst(*target);
+ break;
+ default:
+ ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target object type");
+ break;
+ }
+
+ SelectImplicitChainTargets(effIndex, targetType, target, effMask);
+}
+
+void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
+{
+ if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
+ {
+ ASSERT(false && "Spell::SelectImplicitConeTargets: received not implemented target reference type");
+ return;
+ }
+ std::list<WorldObject*> targets;
+ SpellTargetObjectTypes objectType = targetType.GetObjectType();
+ SpellTargetCheckTypes selectionType = targetType.GetCheckType();
+ ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
+ float coneAngle = M_PI/2;
+ float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
+
+ if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList))
+ {
+ Trinity::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList);
+ Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> searcher(m_caster, targets, check, containerTypeMask);
+ SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, radius);
+
+ if (!targets.empty())
+ {
+ // Other special target selection goes here
+ if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
+ {
+ Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
+ for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
+ if ((*j)->IsAffectedOnSpell(m_spellInfo))
+ maxTargets += (*j)->GetAmount();
+
+ Trinity::RandomResizeList(targets, maxTargets);
+ }
+
+ // for compability with older code - add only unit and go targets
+ // TODO: remove this
+ std::list<Unit*> unitTargets;
+ std::list<GameObject*> gObjTargets;
+
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ {
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ unitTargets.push_back(unitTarget);
+ else if (GameObject* gObjTarget = (*itr)->ToGameObject())
+ gObjTargets.push_back(gObjTarget);
+ }
+
+ CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex);
+
+ for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
+ AddUnitTarget(*itr, effMask, false);
+
+ for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr)
+ AddGOTarget(*itr, effMask);
+ }
+ }
+}
+
+void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask)
+{
+ Unit* referer = NULL;
+ switch (targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_SRC:
+ case TARGET_REFERENCE_TYPE_DEST:
+ case TARGET_REFERENCE_TYPE_CASTER:
+ referer = m_caster;
+ break;
+ case TARGET_REFERENCE_TYPE_TARGET:
+ referer = m_targets.GetUnitTarget();
+ break;
+ case TARGET_REFERENCE_TYPE_LAST:
+ {
+ // find last added target for this effect
+ for (std::list<TargetInfo>::reverse_iterator ihit = m_UniqueTargetInfo.rbegin(); ihit != m_UniqueTargetInfo.rend(); ++ihit)
+ {
+ if (ihit->effectMask & (1<<effIndex))
+ {
+ referer = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
+ return;
+ }
+ if (!referer)
+ return;
+
+ Position const* center = NULL;
+ switch (targetType.GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_SRC:
+ center = m_targets.GetSrc();
+ break;
+ case TARGET_REFERENCE_TYPE_DEST:
+ center = m_targets.GetDst();
+ break;
+ case TARGET_REFERENCE_TYPE_CASTER:
+ case TARGET_REFERENCE_TYPE_TARGET:
+ case TARGET_REFERENCE_TYPE_LAST:
+ center = referer;
+ break;
+ default:
+ ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
+ return;
+ }
+ std::list<WorldObject*> targets;
+ float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
+ SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
+
+ // Custom entries
+ // TODO: remove those
+ switch (m_spellInfo->Id)
+ {
+ case 46584: // Raise Dead
+ {
+ if (Player* playerCaster = m_caster->ToPlayer())
+ {
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ {
+ switch ((*itr)->GetTypeId())
+ {
+ case TYPEID_UNIT:
+ case TYPEID_PLAYER:
+ {
+ Unit* unitTarget = (*itr)->ToUnit();
+ if (unitTarget->isAlive() || !playerCaster->isHonorOrXPTarget(unitTarget)
+ || ((unitTarget->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0)
+ || (unitTarget->GetDisplayId() != unitTarget->GetNativeDisplayId()))
+ break;
+ AddUnitTarget(unitTarget, effMask, false);
+ // no break;
+ }
+ case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet
+ m_targets.SetDst(*(*itr));
+ return; // nothing more to do here
+ default:
+ break;
+ }
+ }
+ }
+ return; // don't add targets to target map
+ }
+ // Corpse Explosion
+ case 49158:
+ case 51325:
+ case 51326:
+ case 51327:
+ case 51328:
+ // check if our target is not valid (spell can target ghoul or dead unit)
+ if (!(m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId() &&
+ ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID())
+ || m_targets.GetUnitTarget()->isDead())))
+ {
+ // remove existing targets
+ CleanupTargetList();
+
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ {
+ switch ((*itr)->GetTypeId())
+ {
+ case TYPEID_UNIT:
+ case TYPEID_PLAYER:
+ if (!(*itr)->ToUnit()->isDead())
+ break;
+ AddUnitTarget((*itr)->ToUnit(), 1 << effIndex, false);
+ return;
+ default:
+ break;
+ }
+ }
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
+ SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW);
+ finish(false);
+ }
+ return;
+ default:
+ break;
+ }
+ std::list<Unit*> unitTargets;
+ std::list<GameObject*> gObjTargets;
+ // for compability with older code - add only unit and go targets
+ // TODO: remove this
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ {
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ unitTargets.push_back(unitTarget);
+ else if (GameObject* gObjTarget = (*itr)->ToGameObject())
+ gObjTargets.push_back(gObjTarget);
+ }
+
+ if (!unitTargets.empty())
+ {
+ // Special target selection for smart heals and energizes
+ uint32 maxSize = 0;
+ int32 power = -1;
+ switch (m_spellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ switch (m_spellInfo->Id)
+ {
+ case 52759: // Ancestral Awakening
+ case 71610: // Echoes of Light (Althor's Abacus normal version)
+ case 71641: // Echoes of Light (Althor's Abacus heroic version)
+ maxSize = 1;
+ power = POWER_HEALTH;
+ break;
+ case 54968: // Glyph of Holy Light
+ maxSize = m_spellInfo->MaxAffectedTargets;
+ power = POWER_HEALTH;
+ break;
+ case 57669: // Replenishment
+ // In arenas Replenishment may only affect the caster
+ if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->InArena())
+ {
+ unitTargets.clear();
+ unitTargets.push_back(m_caster);
+ break;
+ }
+ maxSize = 10;
+ power = POWER_MANA;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SPELLFAMILY_PRIEST:
+ if (m_spellInfo->SpellFamilyFlags[0] == 0x10000000) // Circle of Healing
+ {
+ maxSize = m_caster->HasAura(55675) ? 6 : 5; // Glyph of Circle of Healing
+ power = POWER_HEALTH;
+ }
+ else if (m_spellInfo->Id == 64844) // Divine Hymn
+ {
+ maxSize = 3;
+ power = POWER_HEALTH;
+ }
+ else if (m_spellInfo->Id == 64904) // Hymn of Hope
+ {
+ maxSize = 3;
+ power = POWER_MANA;
+ }
+ else
+ break;
+
+ // Remove targets outside caster's raid
+ for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();)
+ {
+ if (!(*itr)->IsInRaidWith(m_caster))
+ itr = unitTargets.erase(itr);
+ else
+ ++itr;
+ }
+ break;
+ case SPELLFAMILY_DRUID:
+ if (m_spellInfo->SpellFamilyFlags[1] == 0x04000000) // Wild Growth
+ {
+ maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth
+ power = POWER_HEALTH;
+ }
+ else if (m_spellInfo->SpellFamilyFlags[2] == 0x0100) // Starfall
+ {
+ // Remove targets not in LoS or in stealth
+ for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();)
+ {
+ if ((*itr)->HasStealthAura() || (*itr)->HasInvisibilityAura() || !(*itr)->IsWithinLOSInMap(m_caster))
+ itr = unitTargets.erase(itr);
+ else
+ ++itr;
+ }
+ break;
+ }
+ else
+ break;
+
+ // Remove targets outside caster's raid
+ for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();)
+ if (!(*itr)->IsInRaidWith(m_caster))
+ itr = unitTargets.erase(itr);
+ else
+ ++itr;
+ break;
+ default:
+ break;
+ }
+
+ if (maxSize && power != -1)
+ {
+ if (Powers(power) == POWER_HEALTH)
+ {
+ if (unitTargets.size() > maxSize)
+ {
+ unitTargets.sort(Trinity::HealthPctOrderPred());
+ unitTargets.resize(maxSize);
+ }
+ }
+ else
+ {
+ for (std::list<Unit*>::iterator itr = unitTargets.begin() ; itr != unitTargets.end();)
+ if ((*itr)->getPowerType() != (Powers)power)
+ itr = unitTargets.erase(itr);
+ else
+ ++itr;
+
+ if (unitTargets.size() > maxSize)
+ {
+ unitTargets.sort(Trinity::PowerPctOrderPred((Powers)power));
+ unitTargets.resize(maxSize);
+ }
+ }
+ }
+
+ // Other special target selection goes here
+ if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
+ {
+ Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
+ for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
+ if ((*j)->IsAffectedOnSpell(m_spellInfo))
+ maxTargets += (*j)->GetAmount();
+
+ if (m_spellInfo->Id == 5246) //Intimidating Shout
+ unitTargets.remove(m_targets.GetUnitTarget());
+ Trinity::RandomResizeList(unitTargets, maxTargets);
+ }
+
+ CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex);
+
+ for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
+ AddUnitTarget(*itr, effMask, false);
+ }
+
+ if (!gObjTargets.empty())
+ {
+ if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
+ {
+ Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
+ for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
+ if ((*j)->IsAffectedOnSpell(m_spellInfo))
+ maxTargets += (*j)->GetAmount();
+
+ Trinity::RandomResizeList(gObjTargets, maxTargets);
+ }
+ for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr)
+ AddGOTarget(*itr, effMask);
+ }
+}
+
+void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ switch(targetType.GetTarget())
+ {
+ case TARGET_DEST_CASTER:
+ m_targets.SetDst(*m_caster);
+ return;
+ case TARGET_DEST_HOME:
+ if (Player* playerCaster = m_caster->ToPlayer())
+ m_targets.SetDst(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId);
+ return;
+ case TARGET_DEST_DB:
+ if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id))
+ {
+ // TODO: fix this check
+ if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS))
+ m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId);
+ else if (st->target_mapId == m_caster->GetMapId())
+ m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
+ }
+ else
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id);
+ WorldObject* target = m_targets.GetObjectTarget();
+ m_targets.SetDst(target ? *target : *m_caster);
+ }
+ return;
+ case TARGET_DEST_CASTER_FISHING:
+ {
+ float min_dis = m_spellInfo->GetMinRange(true);
+ float max_dis = m_spellInfo->GetMaxRange(true);
+ float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis;
+ float x, y, z, angle;
+ angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
+ m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle);
+ m_targets.SetDst(x, y, z, m_caster->GetOrientation());
+ return;
+ }
+ default:
+ break;
+ }
+
+ float dist;
+ float angle = targetType.CalcDirectionAngle();
+ float objSize = m_caster->GetObjectSize();
+ if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON)
+ dist = PET_FOLLOW_DIST;
+ else
+ dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
+
+ if (dist < objSize)
+ dist = objSize;
+ else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM)
+ dist = objSize + (dist - objSize) * (float)rand_norm();
+
+ Position pos;
+ if (targetType.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP)
+ m_caster->GetFirstCollisionPosition(pos, dist, angle);
+ else
+ m_caster->GetNearPosition(pos, dist, angle);
+ m_targets.SetDst(*m_caster);
+ m_targets.ModDst(pos);
+}
+
+void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ WorldObject* target = m_targets.GetObjectTarget();
+ switch(targetType.GetTarget())
+ {
+ case TARGET_DEST_TARGET_ENEMY:
+ case TARGET_DEST_TARGET_ANY:
+ m_targets.SetDst(*target);
+ return;
+ default:
+ break;
+ }
+
+ float angle = targetType.CalcDirectionAngle();
+ float objSize = target->GetObjectSize();
+ float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
+ if (dist < objSize)
+ dist = objSize;
+ else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM)
+ dist = objSize + (dist - objSize) * (float)rand_norm();
+
+ Position pos;
+ target->GetNearPosition(pos, dist, angle);
+ m_targets.SetDst(*target);
+ m_targets.ModDst(pos);
+}
+
+void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ // set destination to caster if no dest provided
+ // can only happen if previous destination target could not be set for some reason
+ // (not found nearby target, or channel target for example
+ // maybe we should abort the spell in such case?
+ if (!m_targets.HasDst())
+ m_targets.SetDst(*m_caster);
+
+ switch(targetType.GetTarget())
+ {
+ case TARGET_DEST_DYNOBJ_ENEMY:
+ case TARGET_DEST_DYNOBJ_ALLY:
+ case TARGET_DEST_DYNOBJ_NONE:
+ case TARGET_DEST_DEST:
+ return;
+ case TARGET_DEST_TRAJ:
+ SelectImplicitTrajTargets();
+ return;
+ default:
+ break;
+ }
+
+ float angle = targetType.CalcDirectionAngle();
+ float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
+ if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM)
+ dist *= (float)rand_norm();
+
+ Position pos = *m_targets.GetDst();
+ m_caster->MovePosition(pos, dist, angle);
+ m_targets.ModDst(pos);
+}
+
+void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ switch(targetType.GetTarget())
+ {
+ case TARGET_UNIT_CASTER:
+ AddUnitTarget(m_caster, 1 << effIndex, false);
+ break;
+ case TARGET_UNIT_MASTER:
+ if (Unit* owner = m_caster->GetCharmerOrOwner())
+ AddUnitTarget(owner, 1 << effIndex);
+ break;
+ case TARGET_UNIT_PET:
+ if (Guardian* pet = m_caster->GetGuardianPet())
+ AddUnitTarget(pet, 1 << effIndex);
+ break;
+ case TARGET_UNIT_SUMMONER:
+ if (m_caster->isSummon())
+ if (Unit* unit = m_caster->ToTempSummon()->GetSummoner())
+ AddUnitTarget(unit, 1 << effIndex);
+ break;
+ case TARGET_UNIT_VEHICLE:
+ if (Unit *vehicle = m_caster->GetVehicleBase())
+ AddUnitTarget(vehicle, 1 << effIndex);
+ break;
+ case TARGET_UNIT_PASSENGER_0:
+ case TARGET_UNIT_PASSENGER_1:
+ case TARGET_UNIT_PASSENGER_2:
+ case TARGET_UNIT_PASSENGER_3:
+ case TARGET_UNIT_PASSENGER_4:
+ case TARGET_UNIT_PASSENGER_5:
+ case TARGET_UNIT_PASSENGER_6:
+ case TARGET_UNIT_PASSENGER_7:
+ if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle())
+ if (Unit *unit = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0))
+ AddUnitTarget(unit, 1 << effIndex);
+ break;
+ default:
+ break;
+ }
+}
+
+void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
+{
+ ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!");
+ if (Unit* unit = m_targets.GetUnitTarget())
+ AddUnitTarget(unit, 1 << effIndex);
+ else if (GameObject* gobj = m_targets.GetGOTarget())
+ AddGOTarget(gobj, 1 << effIndex);
+ else
+ AddItemTarget(m_targets.GetItemTarget(), effIndex);
+
+ if (WorldObject* target = m_targets.GetObjectTarget())
+ SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex);
+}
+
+void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask)
+{
+ uint32 maxTargets = m_spellInfo->Effects[effIndex].ChainTarget;
+ if (Player* modOwner = m_caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this);
+
+ if (maxTargets > 1)
+ {
+ // mark damage multipliers as used
+ for (uint32 k = effIndex; k < MAX_SPELL_EFFECTS; ++k)
+ if (effMask & (1 << k))
+ m_damageMultipliers[k] = 1.0f;
+ m_applyMultiplierMask |= effMask;
+
+ std::list<WorldObject*> targets;
+ SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType()
+ , m_spellInfo->Effects[effIndex].ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY);
+
+ // for backward compability
+ std::list<Unit*> unitTargets;
+ for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ unitTargets.push_back(unitTarget);
+
+ CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex);
+
+ for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
+ AddUnitTarget(*itr, effMask, false);
+ }
+}
+
+float tangent(float x)
+{
+ x = tan(x);
+ //if (x < std::numeric_limits<float>::max() && x > -std::numeric_limits<float>::max()) return x;
+ //if (x >= std::numeric_limits<float>::max()) return std::numeric_limits<float>::max();
+ //if (x <= -std::numeric_limits<float>::max()) return -std::numeric_limits<float>::max();
+ if (x < 100000.0f && x > -100000.0f) return x;
+ if (x >= 100000.0f) return 100000.0f;
+ if (x <= 100000.0f) return -100000.0f;
+ return 0.0f;
+}
+
+#define DEBUG_TRAJ(a) //a
+
+void Spell::SelectImplicitTrajTargets()
+{
+ if (!m_targets.HasTraj())
+ return;
+
+ float dist2d = m_targets.GetDist2d();
+ if (!dist2d)
+ return;
+
+ float srcToDestDelta = m_targets.GetDst()->m_positionZ - m_targets.GetSrc()->m_positionZ;
+
+ std::list<WorldObject*> targets;
+ Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, m_targets.GetSrc(), m_caster, m_spellInfo);
+ Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL);
+ SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, m_targets.GetSrc(), dist2d);
+ if (targets.empty())
+ return;
+
+ targets.sort(Trinity::ObjectDistanceOrderPred(m_caster));
+
+ float b = tangent(m_targets.GetElevation());
+ float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d);
+ if (a > -0.0001f)
+ a = 0;
+ DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: a %f b %f", a, b);)
+
+ float bestDist = m_spellInfo->GetMaxRange(false);
+
+ std::list<WorldObject*>::const_iterator itr = targets.begin();
+ for (; itr != targets.end(); ++itr)
+ {
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || (unitTarget)->GetVehicle())//(*itr)->IsOnVehicle(m_caster))
+ continue;
+
+ const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)
+ // TODO: all calculation should be based on src instead of m_caster
+ const float objDist2d = m_targets.GetSrc()->GetExactDist2d(*itr) * cos(m_targets.GetSrc()->GetRelativeAngle(*itr));
+ const float dz = (*itr)->GetPositionZ() - m_targets.GetSrc()->m_positionZ;
+
+ DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);)
+
+ float dist = objDist2d - size;
+ float height = dist * (a * dist + b);
+ DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)
+ if (dist < bestDist && height < dz + size && height > dz - size)
+ {
+ bestDist = dist > 0 ? dist : 0;
+ break;
+ }
+
+#define CHECK_DIST {\
+ DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\
+ if (dist > bestDist)\
+ continue;\
+ if (dist < objDist2d + size && dist > objDist2d - size)\
+ {\
+ bestDist = dist;\
+ break;\
+ }\
+ }
+
+ if (!a)
+ {
+ height = dz - size;
+ dist = height / b;
+ CHECK_DIST;
+
+ height = dz + size;
+ dist = height / b;
+ CHECK_DIST;
+
+ continue;
+ }
+
+ height = dz - size;
+ float sqrt1 = b * b + 4 * a * height;
+ if (sqrt1 > 0)
+ {
+ sqrt1 = sqrt(sqrt1);
+ dist = (sqrt1 - b) / (2 * a);
+ CHECK_DIST;
+ }
+
+ height = dz + size;
+ float sqrt2 = b * b + 4 * a * height;
+ if (sqrt2 > 0)
+ {
+ sqrt2 = sqrt(sqrt2);
+ dist = (sqrt2 - b) / (2 * a);
+ CHECK_DIST;
+
+ dist = (-sqrt2 - b) / (2 * a);
+ CHECK_DIST;
+ }
+
+ if (sqrt1 > 0)
+ {
+ dist = (-sqrt1 - b) / (2 * a);
+ CHECK_DIST;
+ }
+ }
+
+ if (m_targets.GetSrc()->GetExactDist2d(m_targets.GetDst()) > bestDist)
+ {
+ float x = m_targets.GetSrc()->m_positionX + cos(m_caster->GetOrientation()) * bestDist;
+ float y = m_targets.GetSrc()->m_positionY + sin(m_caster->GetOrientation()) * bestDist;
+ float z = m_targets.GetSrc()->m_positionZ + bestDist * (a * bestDist + b);
+
+ if (itr != targets.end())
+ {
+ float distSq = (*itr)->GetExactDistSq(x, y, z);
+ float sizeSq = (*itr)->GetObjectSize();
+ sizeSq *= sizeSq;
+ DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
+ if (distSq > sizeSq)
+ {
+ float factor = 1 - sqrt(sizeSq / distSq);
+ x += factor * ((*itr)->GetPositionX() - x);
+ y += factor * ((*itr)->GetPositionY() - y);
+ z += factor * ((*itr)->GetPositionZ() - z);
+
+ distSq = (*itr)->GetExactDistSq(x, y, z);
+ DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
+ }
+ }
+
+ Position trajDst;
+ trajDst.Relocate(x, y, z, m_caster->GetOrientation());
+ m_targets.ModDst(trajDst);
+ }
+}
+
void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
{
// special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER
@@ -865,6 +1777,192 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
}
}
+uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList)
+{
+ // this function selects which containers need to be searched for spell target
+ uint32 retMask = GRID_MAP_TYPE_MASK_ALL;
+
+ // filter searchers based on searched object type
+ switch (objType)
+ {
+ case TARGET_OBJECT_TYPE_UNIT:
+ case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
+ case TARGET_OBJECT_TYPE_CORPSE:
+ case TARGET_OBJECT_TYPE_CORPSE_ENEMY:
+ case TARGET_OBJECT_TYPE_CORPSE_ALLY:
+ retMask &= GRID_MAP_TYPE_MASK_PLAYER | GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_CREATURE;
+ break;
+ case TARGET_OBJECT_TYPE_GOBJ:
+ case TARGET_OBJECT_TYPE_GOBJ_ITEM:
+ retMask &= GRID_MAP_TYPE_MASK_GAMEOBJECT;
+ break;
+ default:
+ break;
+ }
+ if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_DEAD))
+ retMask &= ~GRID_MAP_TYPE_MASK_CORPSE;
+ if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS)
+ retMask &= GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_PLAYER;
+ if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS)
+ retMask &= GRID_MAP_TYPE_MASK_PLAYER;
+
+ if (condList)
+ retMask &= sConditionMgr->GetSearcherTypeMaskForConditionList(*condList);
+ return retMask;
+}
+
+template<class SEARCHER>
+void Spell::SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius)
+{
+ if (!containerMask)
+ return;
+
+ // search world and grid for possible targets
+ bool searchInGrid = containerMask & (GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_GAMEOBJECT);
+ bool searchInWorld = containerMask & (GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER | GRID_MAP_TYPE_MASK_CORPSE);
+ if (searchInGrid || searchInWorld)
+ {
+ float x,y;
+ x = pos->GetPositionX();
+ y = pos->GetPositionY();
+
+ CellCoord p(Trinity::ComputeCellCoord(x, y));
+ Cell cell(p);
+ cell.SetNoCreate();
+
+ Map& map = *(referer->GetMap());
+
+ if (searchInWorld)
+ {
+ TypeContainerVisitor<SEARCHER, WorldTypeMapContainer> world_object_notifier(searcher);
+ cell.Visit(p, world_object_notifier, map, radius, x, y);
+ }
+ if (searchInGrid)
+ {
+ TypeContainerVisitor<SEARCHER, GridTypeMapContainer > grid_object_notifier(searcher);
+ cell.Visit(p, grid_object_notifier, map, radius, x , y);
+ }
+ }
+}
+
+WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList)
+{
+ WorldObject* target = NULL;
+ uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
+ if (!containerTypeMask)
+ return NULL;
+ Trinity::WorldObjectSpellNearbyTargetCheck check(range, m_caster, m_spellInfo, selectionType, condList);
+ Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> searcher(m_caster, target, check, containerTypeMask);
+ SearchTargets<Trinity::WorldObjectLastSearcher<Trinity::WorldObjectSpellNearbyTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, range);
+ return target;
+}
+
+void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList)
+{
+ uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
+ if (!containerTypeMask)
+ return;
+ Trinity::WorldObjectSpellAreaTargetCheck check(range, position, m_caster, referer, m_spellInfo, selectionType, condList);
+ Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(m_caster, targets, check, containerTypeMask);
+ SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, range);
+}
+
+void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal)
+{
+ // max dist for jump target selection
+ float jumpRadius = 0.0f;
+ switch (m_spellInfo->DmgClass)
+ {
+ case SPELL_DAMAGE_CLASS_RANGED:
+ // 7.5y for multi shot
+ jumpRadius = 7.5f;
+ break;
+ case SPELL_DAMAGE_CLASS_MELEE:
+ // 5y for swipe, cleave and similar
+ jumpRadius = 5.0f;
+ break;
+ case SPELL_DAMAGE_CLASS_NONE:
+ case SPELL_DAMAGE_CLASS_MAGIC:
+ // 12.5y for chain heal spell since 3.2 patch
+ if (isChainHeal)
+ jumpRadius = 12.5f;
+ // 10y as default for magic chain spells
+ else
+ jumpRadius = 10.0f;
+ break;
+ }
+
+ // chain lightning/heal spells and similar - allow to jump at larger distance and go out of los
+ bool isBouncingFar = (m_spellInfo->AttributesEx4 & SPELL_ATTR4_AREA_TARGET_CHAIN
+ || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE
+ || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC);
+
+ // max dist which spell can reach
+ float searchRadius = jumpRadius;
+ if (isBouncingFar)
+ searchRadius *= chainTargets;
+
+ std::list<WorldObject*> tempTargets;
+ SearchAreaTargets(tempTargets, searchRadius, target, m_caster, objectType, selectType, condList);
+ tempTargets.remove(target);
+
+ // remove targets which are always invalid for chain spells
+ // for some spells allow only chain targets in front of caster (swipe for example)
+ if (!isBouncingFar)
+ {
+ for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();)
+ {
+ std::list<WorldObject*>::iterator checkItr = itr++;
+ if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr))
+ tempTargets.erase(checkItr);
+ }
+ }
+
+ while (chainTargets)
+ {
+ // try to get unit for next chain jump
+ std::list<WorldObject*>::iterator foundItr = tempTargets.end();
+ // get unit with highest hp deficit in dist
+ if (isChainHeal)
+ {
+ uint32 maxHPDeficit = 0;
+ for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
+ {
+ if (Unit* unitTarget = (*itr)->ToUnit())
+ {
+ uint32 deficit = unitTarget->GetMaxHealth() - unitTarget->GetHealth();
+ if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unitTarget, jumpRadius) && target->IsWithinLOSInMap(unitTarget))
+ {
+ foundItr = itr;
+ maxHPDeficit = deficit;
+ }
+ }
+ }
+ }
+ // get closest object
+ else
+ {
+ for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
+ {
+ if (foundItr == tempTargets.end())
+ {
+ if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr))
+ foundItr = itr;
+ }
+ else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr))
+ foundItr = itr;
+ }
+ }
+ // not found any valid target - chain ends
+ if (foundItr == tempTargets.end())
+ break;
+ target = *foundItr;
+ tempTargets.erase(foundItr);
+ targets.push_back(target);
+ --chainTargets;
+ }
+}
+
void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
{
//==========================================================================================
@@ -1791,1077 +2889,6 @@ struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*,
}
};
-void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uint32 num, SpellTargets TargetType)
-{
- Unit* cur = m_targets.GetUnitTarget();
- if (!cur)
- return;
-
- //FIXME: This very like horrible hack and wrong for most spells
- if (m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE)
- max_range += num * CHAIN_SPELL_JUMP_RADIUS;
-
- std::list<Unit*> tempUnitMap;
- if (TargetType == SPELL_TARGETS_CHAINHEAL)
- {
- SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, SPELL_TARGETS_ALLY);
- tempUnitMap.sort(ChainHealingOrder(m_caster));
- }
- else
- SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, TargetType);
- tempUnitMap.remove(cur);
-
- while (num)
- {
- TagUnitMap.push_back(cur);
- --num;
-
- if (tempUnitMap.empty())
- break;
-
- std::list<Unit*>::iterator next;
-
- if (TargetType == SPELL_TARGETS_CHAINHEAL)
- {
- next = tempUnitMap.begin();
- while (cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS || !cur->IsWithinLOSInMap(*next))
- {
- ++next;
- if (next == tempUnitMap.end())
- return;
- }
- }
- else
- {
- tempUnitMap.sort(Trinity::ObjectDistanceOrderPred(cur));
- next = tempUnitMap.begin();
-
- if (cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) // Don't search beyond the max jump radius
- break;
-
- // Check if (*next) is a valid chain target. If not, don't add to TagUnitMap, and repeat loop.
- // If you want to add any conditions to exclude a target from TagUnitMap, add condition in this while () loop.
- while ((m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE
- && !m_caster->isInFrontInMap(*next, max_range))
- || !m_caster->canSeeOrDetect(*next)
- || !cur->IsWithinLOSInMap(*next)
- || (*next)->GetCreatureType() == CREATURE_TYPE_CRITTER
- || ((GetSpellInfo()->AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED) && !(*next)->CanFreeMove()))
- {
- ++next;
- if (next == tempUnitMap.end() || cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) // Don't search beyond the max jump radius
- return;
- }
- }
-
- cur = *next;
- tempUnitMap.erase(next);
- }
-}
-
-void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry)
-{
- if (TargetType == SPELL_TARGETS_GO)
- return;
-
- Position const* pos;
- switch (type)
- {
- case PUSH_DST_CENTER:
- CheckDst();
- pos = m_targets.GetDst();
- break;
- case PUSH_SRC_CENTER:
- CheckSrc();
- pos = m_targets.GetSrc();
- break;
- case PUSH_CHAIN:
- {
- Unit* target = m_targets.GetUnitTarget();
- if (!target)
- {
- sLog->outError("SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id);
- return;
- }
- pos = target;
- break;
- }
- default:
- pos = m_caster;
- break;
- }
-
- Trinity::SpellNotifierCreatureAndPlayer notifier(m_caster, TagUnitMap, radius, type, TargetType, pos, entry, m_spellInfo);
- if ((m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS) || (TargetType == SPELL_TARGETS_ENTRY && !entry))
- m_caster->GetMap()->VisitWorld(pos->m_positionX, pos->m_positionY, radius, notifier);
- else
- m_caster->GetMap()->VisitAll(pos->m_positionX, pos->m_positionY, radius, notifier);
-}
-
-void Spell::SearchGOAreaTarget(std::list<GameObject*> &TagGOMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry)
-{
- if (TargetType != SPELL_TARGETS_GO)
- return;
-
- Position const* pos;
- switch (type)
- {
- case PUSH_DST_CENTER:
- CheckDst();
- pos = m_targets.GetDst();
- break;
- case PUSH_SRC_CENTER:
- CheckSrc();
- pos = m_targets.GetSrc();
- break;
- default:
- pos = m_caster;
- break;
- }
-
- Trinity::GameObjectInRangeCheck check(pos->m_positionX, pos->m_positionY, pos->m_positionZ, radius, entry);
- Trinity::GameObjectListSearcher<Trinity::GameObjectInRangeCheck> searcher(m_caster, TagGOMap, check);
- m_caster->GetMap()->VisitGrid(pos->m_positionX, pos->m_positionY, radius, searcher);
-}
-
-WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex)
-{
- switch (TargetType)
- {
- case SPELL_TARGETS_ENTRY:
- {
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
- if (conditions.empty())
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) does not have record in `conditions` for spell script target (ConditionSourceType 13)", m_spellInfo->Id, m_caster->GetEntry());
- if (m_spellInfo->IsPositive())
- return SearchNearbyTarget(range, SPELL_TARGETS_ALLY, effIndex);
- else
- return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY, effIndex);
- }
-
- Creature* creatureScriptTarget = NULL;
- GameObject* goScriptTarget = NULL;
-
- for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
- {
- if ((*i_spellST)->ConditionType != CONDITION_SPELL_SCRIPT_TARGET)
- continue;
- if ((*i_spellST)->ConditionValue3 && !((*i_spellST)->ConditionValue3 & (1 << uint32(effIndex))))
- continue;
- switch ((*i_spellST)->ConditionValue1)
- {
- case SPELL_TARGET_TYPE_CONTROLLED:
- for (Unit::ControlList::iterator itr = m_caster->m_Controlled.begin(); itr != m_caster->m_Controlled.end(); ++itr)
- if ((*itr)->GetEntry() == (*i_spellST)->ConditionValue2 && (*itr)->IsWithinDistInMap(m_caster, range))
- {
- goScriptTarget = NULL;
- creatureScriptTarget = (*itr)->ToCreature();
- range = m_caster->GetDistance(creatureScriptTarget);
- }
- break;
- case SPELL_TARGET_TYPE_GAMEOBJECT:
- if ((*i_spellST)->ConditionValue2)
- {
- if (GameObject* go = m_caster->FindNearestGameObject((*i_spellST)->ConditionValue2, range))
- {
- // remember found target and range, next attempt will find more near target with another entry
- goScriptTarget = go;
- creatureScriptTarget = NULL;
- range = m_caster->GetDistance(goScriptTarget);
- }
- }
- 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:
- if (m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetEntry() == (*i_spellST)->ConditionValue2)
- return m_targets.GetUnitTarget();
- case SPELL_TARGET_TYPE_DEAD:
- default:
- if (Creature* cre = m_caster->FindNearestCreature((*i_spellST)->ConditionValue2, range, (*i_spellST)->ConditionValue1 != SPELL_TARGET_TYPE_DEAD))
- {
- creatureScriptTarget = cre;
- goScriptTarget = NULL;
- range = m_caster->GetDistance(creatureScriptTarget);
- }
- break;
- }
- }
-
- if (creatureScriptTarget)
- return creatureScriptTarget;
- else
- return goScriptTarget;
- }
- default:
- case SPELL_TARGETS_ENEMY:
- {
- Unit* target = NULL;
- Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range);
- Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check);
- m_caster->VisitNearbyObject(range, searcher);
- return target;
- }
- case SPELL_TARGETS_ALLY:
- {
- Unit* target = NULL;
- Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range);
- Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check);
- m_caster->VisitNearbyObject(range, searcher);
- return target;
- }
- }
-}
-
-uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur)
-{
- SpellNotifyPushType pushType = PUSH_NONE;
- Player* modOwner = NULL;
- if (m_originalCaster)
- modOwner = m_originalCaster->GetSpellModOwner();
-
- uint32 effectMask = 1 << i;
- // ENTRY targets may have different selection lists, skip those for now until we can compare lists easily and quickly
- if (GetSpellInfo()->Effects[i].TargetA.GetSelectionCheckType() != TARGET_SELECT_CHECK_ENTRY &&
- GetSpellInfo()->Effects[i].TargetB.GetSelectionCheckType() != TARGET_SELECT_CHECK_ENTRY)
- for (uint32 j = i + 1; j < MAX_SPELL_EFFECTS; ++j)
- if (GetSpellInfo()->Effects[i].TargetA.GetTarget() == GetSpellInfo()->Effects[j].TargetA.GetTarget() &&
- GetSpellInfo()->Effects[i].TargetB.GetTarget() == GetSpellInfo()->Effects[j].TargetB.GetTarget() &&
- GetSpellInfo()->Effects[i].CalcRadius(m_caster) == GetSpellInfo()->Effects[j].CalcRadius(m_caster))
- effectMask |= 1 << j;
-
- switch (cur.GetType())
- {
- case TARGET_TYPE_UNIT_CASTER:
- {
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_CASTER:
- AddUnitTarget(m_caster, effectMask, false);
- break;
- case TARGET_DEST_CASTER_FISHING:
- {
- float min_dis = m_spellInfo->GetMinRange(true);
- float max_dis = m_spellInfo->GetMaxRange(true);
- float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis;
- float x, y, z, angle;
- angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
- m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle);
- m_targets.SetDst(x, y, z, m_caster->GetOrientation());
- break;
- }
- case TARGET_UNIT_MASTER:
- if (Unit* owner = m_caster->GetCharmerOrOwner())
- AddUnitTarget(owner, effectMask);
- break;
- case TARGET_UNIT_PET:
- if (Guardian* pet = m_caster->GetGuardianPet())
- AddUnitTarget(pet, effectMask);
- break;
- case TARGET_UNIT_SUMMONER:
- if (m_caster->isSummon())
- if (Unit* unit = m_caster->ToTempSummon()->GetSummoner())
- AddUnitTarget(unit, effectMask);
- break;
- case TARGET_UNIT_CASTER_AREA_PARTY:
- case TARGET_UNIT_CASTER_AREA_RAID:
- pushType = PUSH_CASTER_CENTER;
- break;
- case TARGET_UNIT_VEHICLE:
- if (Unit* vehicle = m_caster->GetVehicleBase())
- AddUnitTarget(vehicle, effectMask);
- break;
- case TARGET_UNIT_PASSENGER_0:
- case TARGET_UNIT_PASSENGER_1:
- case TARGET_UNIT_PASSENGER_2:
- case TARGET_UNIT_PASSENGER_3:
- case TARGET_UNIT_PASSENGER_4:
- case TARGET_UNIT_PASSENGER_5:
- case TARGET_UNIT_PASSENGER_6:
- case TARGET_UNIT_PASSENGER_7:
- if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle())
- if (Unit* unit = m_caster->GetVehicleKit()->GetPassenger(cur.GetTarget() - TARGET_UNIT_PASSENGER_0))
- AddUnitTarget(unit, effectMask);
- break;
- default:
- break;
- }
- break;
- }
-
- case TARGET_TYPE_UNIT_TARGET:
- {
- Unit* target = m_targets.GetUnitTarget();
- if (!target)
- {
- sLog->outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id);
- break;
- }
-
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_TARGET_ENEMY:
- case TARGET_UNIT_TARGET_ANY:
- pushType = PUSH_CHAIN;
- break;
- case TARGET_UNIT_TARGET_CHAINHEAL_ALLY:
- pushType = PUSH_CHAIN;
- break;
- case TARGET_UNIT_TARGET_ALLY:
- AddUnitTarget(target, effectMask, false);
- break;
- case TARGET_UNIT_TARGET_RAID:
- case TARGET_UNIT_TARGET_PARTY:
- case TARGET_UNIT_TARGET_MINIPET:
- AddUnitTarget(target, effectMask, false);
- break;
- case TARGET_UNIT_TARGET_PASSENGER:
- AddUnitTarget(target, effectMask, false);
- break;
- case TARGET_UNIT_LASTTARGET_AREA_PARTY:
- case TARGET_UNIT_TARGET_AREA_RAID_CLASS:
- pushType = PUSH_CASTER_CENTER; // not real
- break;
- default:
- break;
- }
- break;
- }
-
- case TARGET_TYPE_UNIT_NEARBY:
- {
- WorldObject* target = NULL;
- float range;
-
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_NEARBY_ENEMY:
- range = m_spellInfo->GetMaxRange(false);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY, SpellEffIndex(i));
- break;
- case TARGET_UNIT_NEARBY_ALLY:
- case TARGET_UNIT_NEARBY_PARTY: // TODO: fix party/raid targets
- case TARGET_UNIT_NEARBY_RAID:
- range = m_spellInfo->GetMaxRange(true);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY, SpellEffIndex(i));
- break;
- case TARGET_UNIT_NEARBY_ENTRY:
- case TARGET_GAMEOBJECT_NEARBY_ENTRY:
- range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive());
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY, SpellEffIndex(i));
- break;
- default:
- break;
- }
-
- if (!target)
- return 0;
- else if (target->GetTypeId() == TYPEID_GAMEOBJECT)
- AddGOTarget((GameObject*)target, effectMask);
- else
- {
- pushType = PUSH_CHAIN;
-
- if (m_targets.GetUnitTarget() != target)
- m_targets.SetUnitTarget((Unit*)target);
- }
-
- break;
- }
-
- case TARGET_TYPE_AREA_SRC:
- pushType = PUSH_SRC_CENTER;
- break;
-
- case TARGET_TYPE_AREA_DST:
- pushType = PUSH_DST_CENTER;
- break;
-
- case TARGET_TYPE_AREA_CONE:
- if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_BACK)
- pushType = PUSH_IN_BACK;
- else if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_LINE)
- pushType = PUSH_IN_LINE;
- else
- pushType = PUSH_IN_FRONT;
- break;
-
- case TARGET_TYPE_DEST_CASTER: //4+8+2
- {
- if (cur.GetTarget() == TARGET_SRC_CASTER)
- {
- m_targets.SetSrc(*m_caster);
- break;
- }
- else if (cur.GetTarget() == TARGET_DEST_CASTER)
- {
- m_targets.SetDst(*m_caster);
- break;
- }
-
- float angle, dist;
-
- float objSize = m_caster->GetObjectSize();
- if (cur.GetTarget() == TARGET_DEST_CASTER_SUMMON)
- dist = 0.0f;
- else
- dist = m_spellInfo->Effects[i].CalcRadius(m_caster);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, dist, this);
- if (dist < objSize)
- dist = objSize;
- else if (cur.GetTarget() == TARGET_DEST_CASTER_RANDOM)
- dist = objSize + (dist - objSize) * (float)rand_norm();
-
- switch (cur.GetTarget())
- {
- case TARGET_DEST_CASTER_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break;
- case TARGET_DEST_CASTER_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break;
- case TARGET_DEST_CASTER_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break;
- case TARGET_DEST_CASTER_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break;
- case TARGET_DEST_CASTER_SUMMON:
- case TARGET_DEST_CASTER_FRONT_LEAP:
- case TARGET_DEST_CASTER_FRONT: angle = 0.0f; break;
- case TARGET_DEST_CASTER_BACK: angle = static_cast<float>(M_PI); break;
- case TARGET_DEST_CASTER_RIGHT: angle = static_cast<float>(-M_PI/2); break;
- case TARGET_DEST_CASTER_LEFT: angle = static_cast<float>(M_PI/2); break;
- default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break;
- }
-
- Position pos;
- if (cur.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP)
- m_caster->GetFirstCollisionPosition(pos, dist, angle);
- else
- m_caster->GetNearPosition(pos, dist, angle);
- m_targets.SetDst(*m_caster);
- m_targets.ModDst(pos);
- break;
- }
-
- case TARGET_TYPE_DEST_TARGET: //2+8+2
- {
- Unit* target = m_targets.GetUnitTarget();
- if (!target)
- {
- sLog->outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id);
- break;
- }
-
- if (cur.GetTarget() == TARGET_DEST_TARGET_ENEMY || cur.GetTarget() == TARGET_DEST_TARGET_ANY)
- {
- m_targets.SetDst(*target);
- break;
- }
-
- float angle, dist;
-
- float objSize = target->GetObjectSize();
- dist = m_spellInfo->Effects[i].CalcRadius(m_caster);
- if (dist < objSize)
- dist = objSize;
- else if (cur.GetTarget() == TARGET_DEST_TARGET_RANDOM)
- dist = objSize + (dist - objSize) * (float)rand_norm();
-
- switch (cur.GetTarget())
- {
- case TARGET_DEST_TARGET_FRONT: angle = 0.0f; break;
- case TARGET_DEST_TARGET_BACK: angle = static_cast<float>(M_PI); break;
- case TARGET_DEST_TARGET_RIGHT: angle = static_cast<float>(M_PI/2); break;
- case TARGET_DEST_TARGET_LEFT: angle = static_cast<float>(-M_PI/2); break;
- case TARGET_DEST_TARGET_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break;
- case TARGET_DEST_TARGET_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break;
- case TARGET_DEST_TARGET_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break;
- case TARGET_DEST_TARGET_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break;
- default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break;
- }
-
- Position pos;
- target->GetNearPosition(pos, dist, angle);
- m_targets.SetDst(*target);
- m_targets.ModDst(pos);
- break;
- }
-
- case TARGET_TYPE_DEST_DEST: //5+8+1
- {
- if (!m_targets.HasDst())
- {
- sLog->outError("SPELL: no destination for spell ID %u", m_spellInfo->Id);
- break;
- }
-
- float angle;
- switch (cur.GetTarget())
- {
- case TARGET_DEST_DYNOBJ_ENEMY:
- case TARGET_DEST_DYNOBJ_ALLY:
- case TARGET_DEST_DYNOBJ_NONE:
- case TARGET_DEST_DEST:
- return effectMask;
- case TARGET_DEST_TRAJ:
- SelectTrajTargets();
- return effectMask;
- case TARGET_DEST_DEST_FRONT: angle = 0.0f; break;
- case TARGET_DEST_DEST_BACK: angle = static_cast<float>(M_PI); break;
- case TARGET_DEST_DEST_RIGHT: angle = static_cast<float>(M_PI/2); break;
- case TARGET_DEST_DEST_LEFT: angle = static_cast<float>(-M_PI/2); break;
- case TARGET_DEST_DEST_FRONT_LEFT: angle = static_cast<float>(-M_PI/4); break;
- case TARGET_DEST_DEST_BACK_LEFT: angle = static_cast<float>(-3*M_PI/4); break;
- case TARGET_DEST_DEST_BACK_RIGHT: angle = static_cast<float>(3*M_PI/4); break;
- case TARGET_DEST_DEST_FRONT_RIGHT:angle = static_cast<float>(M_PI/4); break;
- default: angle = (float)rand_norm()*static_cast<float>(2*M_PI); break;
- }
-
- float dist = m_spellInfo->Effects[i].CalcRadius(m_caster);
- if (cur.GetTarget() == TARGET_DEST_DEST_RANDOM || cur.GetTarget() == TARGET_DEST_DEST_RADIUS)
- dist *= (float)rand_norm();
-
- // must has dst, no need to set flag
- Position pos = *m_targets.GetDst();
- m_caster->MovePosition(pos, dist, angle);
- m_targets.ModDst(pos);
- break;
- }
-
- case TARGET_TYPE_DEST_SPECIAL:
- {
- switch (cur.GetTarget())
- {
- case TARGET_DEST_DB:
- if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id))
- {
- //TODO: fix this check
- if (m_spellInfo->Effects[0].Effect == SPELL_EFFECT_TELEPORT_UNITS || m_spellInfo->Effects[1].Effect == SPELL_EFFECT_TELEPORT_UNITS || m_spellInfo->Effects[2].Effect == SPELL_EFFECT_TELEPORT_UNITS)
- m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId);
- else if (st->target_mapId == m_caster->GetMapId())
- m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
- }
- else
- {
- sLog->outError("SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id);
- Unit* target = NULL;
- if (uint64 guid = m_caster->GetUInt64Value(UNIT_FIELD_TARGET))
- target = ObjectAccessor::GetUnit(*m_caster, guid);
- m_targets.SetDst(target ? *target : *m_caster);
- }
- break;
- case TARGET_DEST_HOME:
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_targets.SetDst(m_caster->ToPlayer()->m_homebindX, m_caster->ToPlayer()->m_homebindY, m_caster->ToPlayer()->m_homebindZ, m_caster->ToPlayer()->GetOrientation(), m_caster->ToPlayer()->m_homebindMapId);
- break;
- case TARGET_DEST_NEARBY_ENTRY:
- {
- float range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive());
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
-
- if (WorldObject* target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY, SpellEffIndex(i)))
- m_targets.SetDst(*target);
- break;
- }
- default:
- break;
- }
- break;
- }
-
- case TARGET_TYPE_CHANNEL:
- {
- if (!m_originalCaster || !m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
- {
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: no current channeled spell for spell ID %u - spell triggering this spell was interrupted.", m_spellInfo->Id);
- break;
- }
-
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_CHANNEL_TARGET:
- // unit target may be no longer avalible - teleported out of map for example
- if (Unit* target = Unit::GetUnit(*m_caster, m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.GetUnitTargetGUID()))
- AddUnitTarget(target, effectMask);
- else
- sLog->outError("SPELL: cannot find channel spell target for spell ID %u", m_spellInfo->Id);
- break;
- case TARGET_DEST_CHANNEL_TARGET:
- if (m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.HasDst())
- m_targets.SetDst(m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets);
- else if (Unit* target = Unit::GetUnit(*m_caster, m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.GetUnitTargetGUID()))
- m_targets.SetDst(*target);
- else
- sLog->outError("SPELL: cannot find channel spell destination for spell ID %u", m_spellInfo->Id);
- break;
- case TARGET_DEST_CHANNEL_CASTER:
- m_targets.SetDst(*m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->GetCaster());
- break;
- default:
- break;
- }
- break;
- }
-
- default:
- {
- switch (cur.GetTarget())
- {
- case TARGET_GAMEOBJECT_TARGET:
- if (m_targets.GetGOTarget())
- AddGOTarget(m_targets.GetGOTarget(), effectMask);
- break;
- case TARGET_GAMEOBJECT_ITEM_TARGET:
- if (m_targets.GetGOTargetGUID())
- AddGOTarget(m_targets.GetGOTarget(), effectMask);
- else if (m_targets.GetItemTarget())
- AddItemTarget(m_targets.GetItemTarget(), effectMask);
- break;
- default:
- sLog->outError("SPELL (caster[type: %u; guidlow: %u], spell: %u): unhandled spell target (%u)",
- m_caster->GetTypeId(), m_caster->GetGUIDLow(), m_spellInfo->Id, cur.GetTarget());
- break;
- }
- break;
- }
- }
-
- if (pushType == PUSH_CHAIN) // Chain
- {
- Unit* target = m_targets.GetUnitTarget();
- if (!target)
- {
- sLog->outError("SPELL: no chain unit target for spell ID %u", m_spellInfo->Id);
- return 0;
- }
-
- //Chain: 2, 6, 22, 25, 45, 77
- uint32 maxTargets = m_spellInfo->Effects[i].ChainTarget;
- if (modOwner)
- modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this);
-
- if (maxTargets > 1)
- {
- //otherwise, this multiplier is used for something else
- for (uint32 k = i; k < MAX_SPELL_EFFECTS; ++k)
- if (effectMask & (1 << k))
- m_damageMultipliers[k] = 1.0f;
- m_applyMultiplierMask |= effectMask;
-
- float range;
- std::list<Unit*> unitList;
-
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_NEARBY_ENEMY:
- case TARGET_UNIT_TARGET_ENEMY:
- case TARGET_UNIT_NEARBY_ENTRY: // fix me
- range = m_spellInfo->GetMaxRange(false);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- SearchChainTarget(unitList, range, maxTargets, SPELL_TARGETS_ENEMY);
- break;
- case TARGET_UNIT_TARGET_CHAINHEAL_ALLY:
- case TARGET_UNIT_NEARBY_ALLY: // fix me
- case TARGET_UNIT_NEARBY_PARTY:
- case TARGET_UNIT_NEARBY_RAID:
- range = m_spellInfo->GetMaxRange(true);
- if (modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
- SearchChainTarget(unitList, range, maxTargets, SPELL_TARGETS_CHAINHEAL);
- break;
- default:
- break;
- }
-
- CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i));
-
- for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
- AddUnitTarget(*itr, effectMask, false);
- }
- else
- AddUnitTarget(target, effectMask, false);
- }
- else if (pushType)
- {
- float radius;
- SpellTargets targetType;
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_SRC_AREA_ENEMY:
- case TARGET_UNIT_DEST_AREA_ENEMY:
- case TARGET_UNIT_CONE_ENEMY_24:
- case TARGET_UNIT_CONE_ENEMY_54:
- case TARGET_UNIT_CONE_ENEMY_104:
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_ENEMY;
- break;
- case TARGET_UNIT_SRC_AREA_ALLY:
- case TARGET_UNIT_DEST_AREA_ALLY:
- case TARGET_UNIT_CONE_ALLY:
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_ALLY;
- break;
- case TARGET_UNIT_DEST_AREA_ENTRY:
- case TARGET_UNIT_SRC_AREA_ENTRY:
- case TARGET_UNIT_CONE_ENTRY: // fix me
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_ENTRY;
- break;
- case TARGET_GAMEOBJECT_SRC_AREA:
- case TARGET_GAMEOBJECT_DEST_AREA:
- case TARGET_GAMEOBJECT_CONE:
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_GO;
- break;
- default:
- radius = m_spellInfo->Effects[i].CalcRadius();
- targetType = SPELL_TARGETS_NONE;
- break;
- }
-
- if (modOwner)
- modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this);
- radius *= m_spellValue->RadiusMod;
-
- std::list<Unit*> unitList;
- std::list<GameObject*> gobjectList;
- switch (targetType)
- {
- case SPELL_TARGETS_ENTRY:
- {
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
- if (!conditions.empty())
- {
- for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
- {
- if ((*i_spellST)->ConditionType != CONDITION_SPELL_SCRIPT_TARGET)
- continue;
- if ((*i_spellST)->ConditionValue3 && !((*i_spellST)->ConditionValue3 & effectMask))
- continue;
- if ((*i_spellST)->ConditionValue1 == SPELL_TARGET_TYPE_CREATURE)
- SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, (*i_spellST)->ConditionValue2);
- else if ((*i_spellST)->ConditionValue1 == SPELL_TARGET_TYPE_CONTROLLED)
- {
- for (Unit::ControlList::iterator itr = m_caster->m_Controlled.begin(); itr != m_caster->m_Controlled.end(); ++itr)
- if ((*itr)->GetEntry() == (*i_spellST)->ConditionValue2 &&
- (*itr)->IsInMap(m_caster)) // For 60243 and 52173 need skip radius check or use range (no radius entry for effect)
- unitList.push_back(*itr);
- }
- }
- }
- else
- {
- // Custom entries
- // TODO: move these to sql
- switch (m_spellInfo->Id)
- {
- case 46584: // Raise Dead
- {
- if (WorldObject* result = FindCorpseUsing<Trinity::RaiseDeadObjectCheck>())
- {
- switch (result->GetTypeId())
- {
- case TYPEID_UNIT:
- case TYPEID_PLAYER:
- unitList.push_back(result->ToUnit());
- // no break;
- case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet
- m_targets.SetDst(*result);
- break;
- default:
- break;
- }
- }
- break;
- }
- // Corpse Explosion
- case 49158:
- case 51325:
- case 51326:
- case 51327:
- case 51328:
- // Search for ghoul if our ghoul or dead body not valid unit target
- if (!(m_targets.GetUnitTarget() && ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID())
- || (m_targets.GetUnitTarget()->getDeathState() == CORPSE
- && m_targets.GetUnitTarget()->GetTypeId() == TYPEID_UNIT
- && !(m_targets.GetUnitTarget()->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL)
- && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId()))))
- {
- CleanupTargetList();
-
- WorldObject* result = FindCorpseUsing<Trinity::ExplodeCorpseObjectCheck>();
-
- if (result)
- {
- switch (result->GetTypeId())
- {
- case TYPEID_UNIT:
- case TYPEID_PLAYER:
- m_targets.SetUnitTarget((Unit*)result);
- break;
- default:
- break;
- }
- }
- else
- {
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
- SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW);
- finish(false);
- }
- }
- break;
-
- default:
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) does not have type CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET record in `conditions` table.", m_spellInfo->Id, m_caster->GetEntry());
-
- if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_TELEPORT_UNITS)
- SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, 0);
- else if (m_spellInfo->IsPositiveEffect(i))
- SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ALLY);
- else
- SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENEMY);
- }
- }
- break;
- }
- case SPELL_TARGETS_GO:
- {
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
- if (!conditions.empty())
- {
- for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
- {
- if ((*i_spellST)->ConditionType != CONDITION_SPELL_SCRIPT_TARGET)
- continue;
- if ((*i_spellST)->ConditionValue3 && !((*i_spellST)->ConditionValue3 & effectMask))
- continue;
- if ((*i_spellST)->ConditionValue1 == SPELL_TARGET_TYPE_GAMEOBJECT)
- SearchGOAreaTarget(gobjectList, radius, pushType, SPELL_TARGETS_GO, (*i_spellST)->ConditionValue2);
- }
- }
- else
- {
- if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_ACTIVATE_OBJECT)
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) (caster Entry: %u) with SPELL_EFFECT_ACTIVATE_OBJECT does not have type CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET record in `conditions` table.", m_spellInfo->Id, m_caster->GetEntry());
- SearchGOAreaTarget(gobjectList, radius, pushType, SPELL_TARGETS_GO);
- }
- break;
- }
- case SPELL_TARGETS_ALLY:
- case SPELL_TARGETS_ENEMY:
- case SPELL_TARGETS_CHAINHEAL:
- case SPELL_TARGETS_ANY:
- SearchAreaTarget(unitList, radius, pushType, targetType);
- break;
- default:
- switch (cur.GetTarget())
- {
- case TARGET_UNIT_SRC_AREA_PARTY:
- case TARGET_UNIT_DEST_AREA_PARTY:
- m_caster->GetPartyMemberInDist(unitList, radius); //fix me
- break;
- case TARGET_UNIT_LASTTARGET_AREA_PARTY:
- m_targets.GetUnitTarget()->GetPartyMemberInDist(unitList, radius);
- break;
- case TARGET_UNIT_CASTER_AREA_PARTY:
- m_caster->GetPartyMemberInDist(unitList, radius);
- break;
- case TARGET_UNIT_CASTER_AREA_RAID:
- m_caster->GetRaidMember(unitList, radius);
- break;
- case TARGET_UNIT_TARGET_AREA_RAID_CLASS:
- {
- Player* targetPlayer = m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetTypeId() == TYPEID_PLAYER
- ? (Player*)m_targets.GetUnitTarget() : NULL;
-
- Group* group = targetPlayer ? targetPlayer->GetGroup() : NULL;
- if (group)
- {
- for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
- {
- Player* Target = itr->getSource();
-
- // IsHostileTo check duel and controlled by enemy
- if (Target && targetPlayer->IsWithinDistInMap(Target, radius) && targetPlayer->getClass() == Target->getClass() && !m_caster->IsHostileTo(Target))
- AddUnitTarget(Target, effectMask);
- }
- }
- else if (m_targets.GetUnitTarget())
- AddUnitTarget(m_targets.GetUnitTarget(), effectMask);
- break;
- }
- default:
- break;
- }
- break;
- }
-
- if (!unitList.empty())
- {
- // Special target selection for smart heals and energizes
- uint32 maxSize = 0;
- int32 power = -1;
- switch (m_spellInfo->SpellFamilyName)
- {
- case SPELLFAMILY_GENERIC:
- switch (m_spellInfo->Id)
- {
- case 52759: // Ancestral Awakening
- case 71610: // Echoes of Light (Althor's Abacus normal version)
- case 71641: // Echoes of Light (Althor's Abacus heroic version)
- maxSize = 1;
- power = POWER_HEALTH;
- break;
- case 54968: // Glyph of Holy Light
- maxSize = m_spellInfo->MaxAffectedTargets;
- power = POWER_HEALTH;
- break;
- case 57669: // Replenishment
- // In arenas Replenishment may only affect the caster
- if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->InArena())
- {
- unitList.clear();
- unitList.push_back(m_caster);
- break;
- }
- maxSize = 10;
- power = POWER_MANA;
- break;
- default:
- break;
- }
- break;
- case SPELLFAMILY_PRIEST:
- if (m_spellInfo->SpellFamilyFlags[0] == 0x10000000) // Circle of Healing
- {
- maxSize = m_caster->HasAura(55675) ? 6 : 5; // Glyph of Circle of Healing
- power = POWER_HEALTH;
- }
- else if (m_spellInfo->Id == 64844) // Divine Hymn
- {
- maxSize = 3;
- power = POWER_HEALTH;
- }
- else if (m_spellInfo->Id == 64904) // Hymn of Hope
- {
- maxSize = 3;
- power = POWER_MANA;
- }
- else
- break;
-
- // Remove targets outside caster's raid
- for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();)
- {
- if (!(*itr)->IsInRaidWith(m_caster))
- itr = unitList.erase(itr);
- else
- ++itr;
- }
- break;
- case SPELLFAMILY_DRUID:
- if (m_spellInfo->SpellFamilyFlags[1] == 0x04000000) // Wild Growth
- {
- maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth
- power = POWER_HEALTH;
- }
- else if (m_spellInfo->SpellFamilyFlags[2] == 0x0100) // Starfall
- {
- // Remove targets not in LoS or in stealth
- for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();)
- {
- if ((*itr)->HasStealthAura() || (*itr)->HasInvisibilityAura() || !(*itr)->IsWithinLOSInMap(m_caster))
- itr = unitList.erase(itr);
- else
- ++itr;
- }
- break;
- }
- else
- break;
-
- // Remove targets outside caster's raid
- for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();)
- if (!(*itr)->IsInRaidWith(m_caster))
- itr = unitList.erase(itr);
- else
- ++itr;
- break;
- default:
- break;
- }
-
- if (maxSize && power != -1)
- {
- if (Powers(power) == POWER_HEALTH)
- {
- if (unitList.size() > maxSize)
- {
- unitList.sort(Trinity::HealthPctOrderPred());
- unitList.resize(maxSize);
- }
- }
- else
- {
- for (std::list<Unit*>::iterator itr = unitList.begin() ; itr != unitList.end();)
- if ((*itr)->getPowerType() != (Powers)power)
- itr = unitList.erase(itr);
- else
- ++itr;
-
- if (unitList.size() > maxSize)
- {
- unitList.sort(Trinity::PowerPctOrderPred((Powers)power));
- unitList.resize(maxSize);
- }
- }
- }
-
- // Other special target selection goes here
- if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
- if (m_spellInfo->Id == 5246) //Intimidating Shout
- unitList.remove(m_targets.GetUnitTarget());
- Trinity::RandomResizeList(unitList, maxTargets);
- }
-
- CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i));
-
- for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
- AddUnitTarget(*itr, effectMask, false);
- }
-
- if (!gobjectList.empty())
- {
- if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
- {
- Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
- for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(m_spellInfo))
- maxTargets += (*j)->GetAmount();
-
- Trinity::RandomResizeList(gobjectList, maxTargets);
- }
- for (std::list<GameObject*>::iterator itr = gobjectList.begin(); itr != gobjectList.end(); ++itr)
- AddGOTarget(*itr, effectMask);
- }
- }
-
- return effectMask;
-}
-
void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura)
{
if (m_CastItem)
@@ -4478,9 +4505,7 @@ void Spell::TakeReagents()
if (m_caster->GetTypeId() != TYPEID_PLAYER)
return;
- ItemTemplate const* castItemTemplate = m_CastItem
- ? m_CastItem->GetTemplate()
- : NULL;
+ ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetTemplate() : NULL;
// do not take reagents for these item casts
if (castItemTemplate && castItemTemplate->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST)
@@ -6847,150 +6872,6 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value)
}
}
-float tangent(float x)
-{
- x = tan(x);
- //if (x < std::numeric_limits<float>::max() && x > -std::numeric_limits<float>::max()) return x;
- //if (x >= std::numeric_limits<float>::max()) return std::numeric_limits<float>::max();
- //if (x <= -std::numeric_limits<float>::max()) return -std::numeric_limits<float>::max();
- if (x < 100000.0f && x > -100000.0f) return x;
- if (x >= 100000.0f) return 100000.0f;
- if (x <= 100000.0f) return -100000.0f;
- return 0.0f;
-}
-
-#define DEBUG_TRAJ(a) //a
-
-void Spell::SelectTrajTargets()
-{
- if (!m_targets.HasTraj())
- return;
-
- float dist2d = m_targets.GetDist2d();
- if (!dist2d)
- return;
-
- float srcToDestDelta = m_targets.GetDst()->m_positionZ - m_targets.GetSrc()->m_positionZ;
-
- UnitList unitList;
- SearchAreaTarget(unitList, dist2d, PUSH_IN_THIN_LINE, SPELL_TARGETS_ANY);
- if (unitList.empty())
- return;
-
- unitList.sort(Trinity::ObjectDistanceOrderPred(m_caster));
-
- float b = tangent(m_targets.GetElevation());
- float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d);
- if (a > -0.0001f)
- a = 0;
- DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: a %f b %f", a, b);)
-
- float bestDist = m_spellInfo->GetMaxRange(false);
-
- UnitList::const_iterator itr = unitList.begin();
- for (; itr != unitList.end(); ++itr)
- {
- if (m_caster == *itr || m_caster->IsOnVehicle(*itr) || (*itr)->GetVehicle())//(*itr)->IsOnVehicle(m_caster))
- continue;
-
- const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)
- // TODO: all calculation should be based on src instead of m_caster
- const float objDist2d = m_targets.GetSrc()->GetExactDist2d(*itr) * cos(m_targets.GetSrc()->GetRelativeAngle(*itr));
- const float dz = (*itr)->GetPositionZ() - m_targets.GetSrc()->m_positionZ;
-
- DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);)
-
- float dist = objDist2d - size;
- float height = dist * (a * dist + b);
- DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)
- if (dist < bestDist && height < dz + size && height > dz - size)
- {
- bestDist = dist > 0 ? dist : 0;
- break;
- }
-
-#define CHECK_DIST {\
- DEBUG_TRAJ(sLog->outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\
- if (dist > bestDist)\
- continue;\
- if (dist < objDist2d + size && dist > objDist2d - size)\
- {\
- bestDist = dist;\
- break;\
- }\
- }
-
- if (!a)
- {
- height = dz - size;
- dist = height / b;
- CHECK_DIST;
-
- height = dz + size;
- dist = height / b;
- CHECK_DIST;
-
- continue;
- }
-
- height = dz - size;
- float sqrt1 = b * b + 4 * a * height;
- if (sqrt1 > 0)
- {
- sqrt1 = sqrt(sqrt1);
- dist = (sqrt1 - b) / (2 * a);
- CHECK_DIST;
- }
-
- height = dz + size;
- float sqrt2 = b * b + 4 * a * height;
- if (sqrt2 > 0)
- {
- sqrt2 = sqrt(sqrt2);
- dist = (sqrt2 - b) / (2 * a);
- CHECK_DIST;
-
- dist = (-sqrt2 - b) / (2 * a);
- CHECK_DIST;
- }
-
- if (sqrt1 > 0)
- {
- dist = (-sqrt1 - b) / (2 * a);
- CHECK_DIST;
- }
- }
-
- if (m_targets.GetSrc()->GetExactDist2d(m_targets.GetDst()) > bestDist)
- {
- float x = m_targets.GetSrc()->m_positionX + cos(m_caster->GetOrientation()) * bestDist;
- float y = m_targets.GetSrc()->m_positionY + sin(m_caster->GetOrientation()) * bestDist;
- float z = m_targets.GetSrc()->m_positionZ + bestDist * (a * bestDist + b);
-
- if (itr != unitList.end())
- {
- float distSq = (*itr)->GetExactDistSq(x, y, z);
- float sizeSq = (*itr)->GetObjectSize();
- sizeSq *= sizeSq;
- DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
- if (distSq > sizeSq)
- {
- float factor = 1 - sqrt(sizeSq / distSq);
- x += factor * ((*itr)->GetPositionX() - x);
- y += factor * ((*itr)->GetPositionY() - y);
- z += factor * ((*itr)->GetPositionZ() - z);
-
- distSq = (*itr)->GetExactDistSq(x, y, z);
- DEBUG_TRAJ(sLog->outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
- }
- }
-
- Position trajDst;
- trajDst.Relocate(x, y, z, m_caster->GetOrientation());
- m_targets.ModDst(trajDst);
- }
-}
-
void Spell::PrepareTargetProcessing()
{
CheckEffectExecuteData();
@@ -7342,3 +7223,152 @@ void Spell::CancelGlobalCooldown()
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->ToPlayer()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
}
+
+namespace Trinity
+{
+
+WorldObjectSpellTargetCheck::WorldObjectSpellTargetCheck(Unit* caster, Unit* referer, SpellInfo const* spellInfo,
+ SpellTargetCheckTypes selectionType, ConditionList* condList) : _caster(caster), _referer(referer), _spellInfo(spellInfo),
+ _targetSelectionType(selectionType), _condList(condList)
+{
+ if (condList)
+ _condSrcInfo = new ConditionSourceInfo(NULL, caster);
+ else
+ _condSrcInfo = NULL;
+}
+
+WorldObjectSpellTargetCheck::~WorldObjectSpellTargetCheck()
+{
+ if (_condSrcInfo)
+ delete _condSrcInfo;
+}
+
+bool WorldObjectSpellTargetCheck::operator()(WorldObject* target)
+{
+ if (_spellInfo->CheckTarget(_caster, target, true) != SPELL_CAST_OK)
+ return false;
+ Unit* unitTarget = target->ToUnit();
+ if (Corpse* corpseTarget = target->ToCorpse())
+ {
+ // use ofter for party/assistance checks
+ if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
+ unitTarget = owner;
+ else
+ return false;
+ }
+ if (unitTarget)
+ {
+ switch (_targetSelectionType)
+ {
+ case TARGET_CHECK_ENEMY:
+ if (unitTarget->isTotem())
+ return false;
+ if (!_caster->_IsValidAttackTarget(unitTarget, _spellInfo))
+ return false;
+ break;
+ case TARGET_CHECK_ALLY:
+ if (unitTarget->isTotem())
+ return false;
+ if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
+ return false;
+ break;
+ case TARGET_CHECK_PARTY:
+ if (unitTarget->isTotem())
+ return false;
+ if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
+ return false;
+ if (!_referer->IsInPartyWith(unitTarget))
+ return false;
+ break;
+ case TARGET_CHECK_RAID_CLASS:
+ if (_referer->getClass() != unitTarget->getClass())
+ return false;
+ // nobreak;
+ case TARGET_CHECK_RAID:
+ if (unitTarget->isTotem())
+ return false;
+ if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
+ return false;
+ if (!_referer->IsInRaidWith(unitTarget))
+ return false;
+ break;
+ default:
+ break;
+ }
+ }
+ if (!_condSrcInfo)
+ return true;
+ _condSrcInfo->mConditionTargets[0] = target;
+ return sConditionMgr->IsObjectMeetToConditions(*_condSrcInfo, *_condList);
+}
+
+WorldObjectSpellNearbyTargetCheck::WorldObjectSpellNearbyTargetCheck(float range, Unit* caster, SpellInfo const* spellInfo,
+ SpellTargetCheckTypes selectionType, ConditionList* condList)
+ : WorldObjectSpellTargetCheck(caster, caster, spellInfo, selectionType, condList), _range(range), _position(caster)
+{
+}
+
+bool WorldObjectSpellNearbyTargetCheck::operator()(WorldObject* target)
+{
+ float dist = target->GetDistance(*_position);
+ if (dist < _range && WorldObjectSpellTargetCheck::operator ()(target))
+ {
+ _range = dist;
+ return true;
+ }
+ return false;
+}
+
+WorldObjectSpellAreaTargetCheck::WorldObjectSpellAreaTargetCheck(float range, Position const* position, Unit* caster,
+ Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList)
+ : WorldObjectSpellTargetCheck(caster, referer, spellInfo, selectionType, condList), _range(range), _position(position)
+{
+}
+
+bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target)
+{
+ if (!target->IsWithinDist3d(_position, _range))
+ return false;
+ return WorldObjectSpellTargetCheck::operator ()(target);
+}
+
+WorldObjectSpellConeTargetCheck::WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster,
+ SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList)
+ : WorldObjectSpellAreaTargetCheck(range, caster, caster, caster, spellInfo, selectionType, condList), _coneAngle(coneAngle)
+{
+}
+
+bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
+{
+ if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_BACK)
+ {
+ if (!_caster->isInBack(target, _coneAngle))
+ return false;
+ }
+ else if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_LINE)
+ {
+ if (!_caster->HasInLine(target, _caster->GetObjectSize()))
+ return false;
+ }
+ else
+ {
+ if (!_caster->isInFront(target, _coneAngle))
+ return false;
+ }
+ return WorldObjectSpellAreaTargetCheck::operator ()(target);
+}
+
+WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo)
+ : WorldObjectSpellAreaTargetCheck(range, position, caster, caster, spellInfo, TARGET_CHECK_DEFAULT, NULL)
+{
+}
+
+bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target)
+{
+ // return all targets on missile trajectory (0 - size of a missile)
+ if (!_caster->HasInLine(target, 0))
+ return false;
+ return WorldObjectSpellAreaTargetCheck::operator ()(target);
+}
+
+} //namespace Trinity
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 583123eb261..971bc1989ab 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -79,19 +79,6 @@ enum SpellRangeFlag
SPELL_RANGE_RANGED = 2, //hunter range and ranged weapon
};
-enum SpellNotifyPushType
-{
- PUSH_NONE = 0,
- PUSH_IN_FRONT,
- PUSH_IN_BACK,
- PUSH_IN_LINE,
- PUSH_IN_THIN_LINE,
- PUSH_SRC_CENTER,
- PUSH_DST_CENTER,
- PUSH_CASTER_CENTER, //this is never used in grid search
- PUSH_CHAIN,
-};
-
class SpellCastTargets
{
public:
@@ -210,17 +197,6 @@ enum SpellEffectHandleMode
SPELL_EFFECT_HANDLE_HIT_TARGET,
};
-enum SpellTargets
-{
- SPELL_TARGETS_NONE = 0,
- SPELL_TARGETS_ALLY,
- SPELL_TARGETS_ENEMY,
- SPELL_TARGETS_ENTRY,
- SPELL_TARGETS_CHAINHEAL,
- SPELL_TARGETS_ANY,
- SPELL_TARGETS_GO
-};
-
namespace Trinity
{
struct SpellNotifierCreatureAndPlayer;
@@ -228,7 +204,6 @@ namespace Trinity
class Spell
{
- friend struct Trinity::SpellNotifierCreatureAndPlayer;
friend void Unit::SetCurrentCastedSpell(Spell* pSpell);
friend class SpellScript;
public:
@@ -364,6 +339,32 @@ class Spell
Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, uint64 originalCasterGUID = 0, bool skipCheck = false);
~Spell();
+ void InitExplicitTargets(SpellCastTargets const& targets);
+ void SelectExplicitTargets();
+
+ void SelectSpellTargets();
+ void SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask);
+ void SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask);
+ void SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask);
+ void SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask);
+ void SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask);
+ void SelectImplicitTrajTargets();
+
+ void SelectEffectTypeImplicitTargets(uint8 effIndex);
+
+ uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList);
+ template<class SEARCHER> void SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius);
+
+ WorldObject* SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList = NULL);
+ void SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList);
+ void SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal);
+
void prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura = NULL);
void cancel();
void update(uint32 difftime);
@@ -404,15 +405,6 @@ class Spell
void WriteSpellGoTargets(WorldPacket* data);
void WriteAmmoToPacket(WorldPacket* data);
- void InitExplicitTargets(SpellCastTargets const& targets);
- void SelectExplicitTargets();
- void SelectSpellTargets();
- void SelectEffectTypeImplicitTargets(uint8 effIndex);
- uint32 SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur);
- void SelectTrajTargets();
-
- template<typename T> WorldObject* FindCorpseUsing();
-
bool CheckEffectTarget(Unit const* target, uint32 eff) const;
bool CanAutoCast(Unit* target);
void CheckSrc() { if (!m_targets.HasSrc()) m_targets.SetSrc(*m_caster); }
@@ -607,10 +599,6 @@ class Spell
void DoAllEffectOnTarget(GOTargetInfo* target);
void DoAllEffectOnTarget(ItemTargetInfo* target);
bool UpdateChanneledTargetList();
- void SearchAreaTarget(std::list<Unit*> &unitList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0);
- void SearchGOAreaTarget(std::list<GameObject*> &gobjectList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0);
- void SearchChainTarget(std::list<Unit*> &unitList, float radius, uint32 unMaxTargets, SpellTargets TargetType);
- WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex);
bool IsValidDeadOrAliveTarget(Unit const* target) const;
void HandleLaunchPhase();
void DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier);
@@ -676,98 +664,52 @@ class Spell
namespace Trinity
{
- struct SpellNotifierCreatureAndPlayer
+ struct WorldObjectSpellTargetCheck
{
- std::list<Unit*> *i_data;
- SpellNotifyPushType i_push_type;
- float i_radius;
- SpellTargets i_TargetType;
- const Unit* const i_source;
- uint32 i_entry;
- const Position* const i_pos;
- SpellInfo const* i_spellProto;
-
- SpellNotifierCreatureAndPlayer(Unit* source, std::list<Unit*> &data, float radius, SpellNotifyPushType type,
- SpellTargets TargetType = SPELL_TARGETS_ENEMY, const Position* pos = NULL, uint32 entry = 0, SpellInfo const* spellProto = NULL)
- : i_data(&data), i_push_type(type), i_radius(radius), i_TargetType(TargetType),
- i_source(source), i_entry(entry), i_pos(pos), i_spellProto(spellProto)
- {
- ASSERT(i_source);
- }
+ Unit* _caster;
+ Unit* _referer;
+ SpellInfo const* _spellInfo;
+ SpellTargetCheckTypes _targetSelectionType;
+ ConditionSourceInfo* _condSrcInfo;
+ ConditionList* _condList;
+
+ WorldObjectSpellTargetCheck(Unit* caster, Unit* referer, SpellInfo const* spellInfo,
+ SpellTargetCheckTypes selectionType, ConditionList* condList);
+ ~WorldObjectSpellTargetCheck();
+ bool operator()(WorldObject* target);
+ };
- template<class T> inline void Visit(GridRefManager<T>& m)
- {
- for (typename GridRefManager<T>::iterator itr = m.begin(); itr != m.end(); ++itr)
- {
- Unit* target = (Unit*)itr->getSource();
-
- if (i_spellProto->CheckTarget(i_source, target, true) != SPELL_CAST_OK)
- continue;
-
- switch (i_TargetType)
- {
- case SPELL_TARGETS_ENEMY:
- if (target->isTotem())
- continue;
- if (!i_source->_IsValidAttackTarget(target, i_spellProto))
- continue;
- break;
- case SPELL_TARGETS_ALLY:
- if (target->isTotem())
- continue;
- if (!i_source->_IsValidAssistTarget(target, i_spellProto))
- continue;
- break;
- case SPELL_TARGETS_ENTRY:
- if (target->GetEntry()!= i_entry)
- continue;
- break;
- case SPELL_TARGETS_ANY:
- default:
- break;
- }
-
- switch (i_push_type)
- {
- case PUSH_SRC_CENTER:
- case PUSH_DST_CENTER:
- case PUSH_CHAIN:
- default:
- if (target->IsWithinDist3d(i_pos, i_radius))
- i_data->push_back(target);
- break;
- case PUSH_IN_FRONT:
- if (i_source->isInFront(target, i_radius, static_cast<float>(M_PI/2)))
- i_data->push_back(target);
- break;
- case PUSH_IN_BACK:
- if (i_source->isInBack(target, i_radius, static_cast<float>(M_PI/2)))
- i_data->push_back(target);
- break;
- case PUSH_IN_LINE:
- if (i_source->HasInLine(target, i_radius, i_source->GetObjectSize()))
- i_data->push_back(target);
- break;
- case PUSH_IN_THIN_LINE: // only traj
- if (i_pos->HasInLine(target, i_radius, 0))
- i_data->push_back(target);
- break;
- }
- }
- }
+ struct WorldObjectSpellNearbyTargetCheck : public WorldObjectSpellTargetCheck
+ {
+ float _range;
+ Position const* _position;
+ WorldObjectSpellNearbyTargetCheck(float range, Unit* caster, SpellInfo const* spellInfo,
+ SpellTargetCheckTypes selectionType, ConditionList* condList);
+ bool operator()(WorldObject* target);
+ };
+
+ struct WorldObjectSpellAreaTargetCheck : public WorldObjectSpellTargetCheck
+ {
+ float _range;
+ Position const* _position;
+ WorldObjectSpellAreaTargetCheck(float range, Position const* position, Unit* caster,
+ Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList);
+ bool operator()(WorldObject* target);
+ };
- #ifdef _WIN32
- template<> inline void Visit(CorpseMapType &) {}
- template<> inline void Visit(GameObjectMapType &) {}
- template<> inline void Visit(DynamicObjectMapType &) {}
- #endif
+ struct WorldObjectSpellConeTargetCheck : public WorldObjectSpellAreaTargetCheck
+ {
+ float _coneAngle;
+ WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster,
+ SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList);
+ bool operator()(WorldObject* target);
};
- #ifndef _WIN32
- template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType&) {}
- template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType&) {}
- template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType&) {}
- #endif
+ struct WorldObjectSpellTrajTargetCheck : public WorldObjectSpellAreaTargetCheck
+ {
+ WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo);
+ bool operator()(WorldObject* target);
+ };
}
typedef void(Spell::*pEffect)(SpellEffIndex effIndex);
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index ad465767ab0..3365aad1cd9 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -20,6 +20,7 @@
#include "SpellMgr.h"
#include "Spell.h"
#include "DBCStores.h"
+#include "ConditionMgr.h"
uint32 GetTargetFlagMask(SpellTargetObjectTypes objType)
{
@@ -80,7 +81,7 @@ SpellTargetObjectTypes SpellImplicitTargetInfo::GetObjectType() const
return _data[_target].ObjectType;
}
-SpellTargetSelectionCheckTypes SpellImplicitTargetInfo::GetSelectionCheckType() const
+SpellTargetCheckTypes SpellImplicitTargetInfo::GetCheckType() const
{
return _data[_target].SelectionCheckType;
}
@@ -158,23 +159,25 @@ uint32 SpellImplicitTargetInfo::GetExplicitTargetMask(bool& srcSet, bool& dstSet
case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
case TARGET_OBJECT_TYPE_UNIT:
case TARGET_OBJECT_TYPE_DEST:
- switch (GetSelectionCheckType())
+ switch (GetCheckType())
{
- case TARGET_SELECT_CHECK_ENEMY:
+ case TARGET_CHECK_ENEMY:
targetMask = TARGET_FLAG_UNIT_ENEMY;
break;
- case TARGET_SELECT_CHECK_ALLY:
+ case TARGET_CHECK_ALLY:
targetMask = TARGET_FLAG_UNIT_ALLY;
break;
- case TARGET_SELECT_CHECK_PARTY:
+ case TARGET_CHECK_PARTY:
targetMask = TARGET_FLAG_UNIT_PARTY;
break;
- case TARGET_SELECT_CHECK_RAID:
+ case TARGET_CHECK_RAID:
targetMask = TARGET_FLAG_UNIT_RAID;
break;
- case TARGET_SELECT_CHECK_PASSENGER:
+ case TARGET_CHECK_PASSENGER:
targetMask = TARGET_FLAG_UNIT_PASSENGER;
break;
+ case TARGET_CHECK_RAID_CLASS:
+ // nobreak;
default:
targetMask = TARGET_FLAG_UNIT;
break;
@@ -344,117 +347,117 @@ SpellSelectTargetTypes SpellImplicitTargetInfo::Type[TOTAL_SPELL_TARGETS];
SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_TARGETS] =
{
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, //
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 1 TARGET_UNIT_CASTER
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 2 TARGET_UNIT_NEARBY_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 3 TARGET_UNIT_NEARBY_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 4 TARGET_UNIT_NEARBY_ALLY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 5 TARGET_UNIT_PET
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 6 TARGET_UNIT_TARGET_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 7 TARGET_UNIT_SRC_AREA_ENTRY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 8 TARGET_UNIT_DEST_AREA_ENTRY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 9 TARGET_DEST_HOME
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 10
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 11 TARGET_UNIT_SRC_AREA_UNK_11
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 12
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 13
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 14
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 15 TARGET_UNIT_SRC_AREA_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 16 TARGET_UNIT_DEST_AREA_ENEMY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 17 TARGET_DEST_DB
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 18 TARGET_DEST_CASTER
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 19
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 20 TARGET_UNIT_CASTER_AREA_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 21 TARGET_UNIT_TARGET_ALLY
- {TARGET_OBJECT_TYPE_SRC, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 22 TARGET_SRC_CASTER
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 23 TARGET_GAMEOBJECT_TARGET
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 24 TARGET_UNIT_CONE_ENEMY_24
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 25 TARGET_UNIT_TARGET_ANY
- {TARGET_OBJECT_TYPE_GOBJ_ITEM, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 26 TARGET_GAMEOBJECT_ITEM_TARGET
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 27 TARGET_UNIT_MASTER
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 28 TARGET_DEST_DYNOBJ_ENEMY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 29 TARGET_DEST_DYNOBJ_ALLY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 30 TARGET_UNIT_SRC_AREA_ALLY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 31 TARGET_UNIT_DEST_AREA_ALLY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 32 TARGET_DEST_CASTER_SUMMON
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 33 TARGET_UNIT_SRC_AREA_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 34 TARGET_UNIT_DEST_AREA_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 35 TARGET_UNIT_TARGET_PARTY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 36 TARGET_DEST_CASTER_UNK_36
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_LAST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_PARTY, TARGET_DIR_NONE}, // 37 TARGET_UNIT_LASTTARGET_AREA_PARTY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 38 TARGET_UNIT_NEARBY_ENTRY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 39 TARGET_DEST_CASTER_FISHING
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 40 TARGET_GAMEOBJECT_NEARBY_ENTRY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 41 TARGET_DEST_CASTER_FRONT_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 42 TARGET_DEST_CASTER_BACK_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 43 TARGET_DEST_CASTER_BACK_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 44 TARGET_DEST_CASTER_FRONT_LEFT
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_NONE}, // 45 TARGET_UNIT_TARGET_CHAINHEAL_ALLY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_NONE}, // 46 TARGET_DEST_NEARBY_ENTRY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 47 TARGET_DEST_CASTER_FRONT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 48 TARGET_DEST_CASTER_BACK
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 49 TARGET_DEST_CASTER_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 50 TARGET_DEST_CASTER_LEFT
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 51 TARGET_GAMEOBJECT_SRC_AREA
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 52 TARGET_GAMEOBJECT_DEST_AREA
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 53 TARGET_DEST_TARGET_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 54 TARGET_UNIT_CONE_ENEMY_54
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 55 TARGET_DEST_CASTER_FRONT_LEAP
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 56 TARGET_UNIT_CASTER_AREA_RAID
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 57 TARGET_UNIT_TARGET_RAID
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 58 TARGET_UNIT_NEARBY_RAID
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ALLY, TARGET_DIR_FRONT}, // 59 TARGET_UNIT_CONE_ALLY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENTRY, TARGET_DIR_FRONT}, // 60 TARGET_UNIT_CONE_ENTRY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_AREA, TARGET_SELECT_CHECK_RAID, TARGET_DIR_NONE}, // 61 TARGET_UNIT_TARGET_AREA_RAID_CLASS
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 62 TARGET_UNK_62
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 63 TARGET_DEST_TARGET_ANY
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 64 TARGET_DEST_TARGET_FRONT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 65 TARGET_DEST_TARGET_BACK
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 66 TARGET_DEST_TARGET_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 67 TARGET_DEST_TARGET_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 68 TARGET_DEST_TARGET_FRONT_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 69 TARGET_DEST_TARGET_BACK_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 70 TARGET_DEST_TARGET_BACK_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 71 TARGET_DEST_TARGET_FRONT_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 72 TARGET_DEST_CASTER_RANDOM
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 73 TARGET_DEST_CASTER_RADIUS
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 74 TARGET_DEST_TARGET_RANDOM
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 75 TARGET_DEST_TARGET_RADIUS
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 76 TARGET_DEST_CHANNEL_TARGET
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 77 TARGET_UNIT_CHANNEL_TARGET
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 78 TARGET_DEST_DEST_FRONT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK}, // 79 TARGET_DEST_DEST_BACK
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 80 TARGET_DEST_DEST_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 81 TARGET_DEST_DEST_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 82 TARGET_DEST_DEST_FRONT_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 83 TARGET_DEST_DEST_BACK_RIGHT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 84 TARGET_DEST_DEST_BACK_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 85 TARGET_DEST_DEST_FRONT_LEFT
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 86 TARGET_DEST_DEST_RANDOM
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 87 TARGET_DEST_DEST
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 88 TARGET_DEST_DYNOBJ_NONE
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 89 TARGET_DEST_TRAJ
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 90 TARGET_UNIT_TARGET_MINIPET
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 91 TARGET_DEST_DEST_RADIUS
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 92 TARGET_UNIT_SUMMONER
- {TARGET_OBJECT_TYPE_CORPSE, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_NONE}, // 93 TARGET_CORPSE_SRC_AREA_ENEMY
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 94 TARGET_UNIT_VEHICLE
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_PASSENGER, TARGET_DIR_NONE}, // 95 TARGET_UNIT_TARGET_PASSENGER
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 96 TARGET_UNIT_PASSENGER_0
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 97 TARGET_UNIT_PASSENGER_1
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 98 TARGET_UNIT_PASSENGER_2
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 99 TARGET_UNIT_PASSENGER_3
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 100 TARGET_UNIT_PASSENGER_4
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 101 TARGET_UNIT_PASSENGER_5
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 102 TARGET_UNIT_PASSENGER_6
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 103 TARGET_UNIT_PASSENGER_7
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_ENEMY, TARGET_DIR_FRONT}, // 104 TARGET_UNIT_CONE_ENEMY_104
- {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 105 TARGET_UNIT_UNK_105
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 106 TARGET_DEST_CHANNEL_CASTER
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107
- {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE
- {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109
- {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_SELECT_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, //
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 1 TARGET_UNIT_CASTER
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 2 TARGET_UNIT_NEARBY_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 3 TARGET_UNIT_NEARBY_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 4 TARGET_UNIT_NEARBY_ALLY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 5 TARGET_UNIT_PET
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 6 TARGET_UNIT_TARGET_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 7 TARGET_UNIT_SRC_AREA_ENTRY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 8 TARGET_UNIT_DEST_AREA_ENTRY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 9 TARGET_DEST_HOME
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 10
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 11 TARGET_UNIT_SRC_AREA_UNK_11
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 12
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 13
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 14
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 15 TARGET_UNIT_SRC_AREA_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 16 TARGET_UNIT_DEST_AREA_ENEMY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 17 TARGET_DEST_DB
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 18 TARGET_DEST_CASTER
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 19
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 20 TARGET_UNIT_CASTER_AREA_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 21 TARGET_UNIT_TARGET_ALLY
+ {TARGET_OBJECT_TYPE_SRC, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 22 TARGET_SRC_CASTER
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 23 TARGET_GAMEOBJECT_TARGET
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 24 TARGET_UNIT_CONE_ENEMY_24
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 25 TARGET_UNIT_TARGET_ANY
+ {TARGET_OBJECT_TYPE_GOBJ_ITEM, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 26 TARGET_GAMEOBJECT_ITEM_TARGET
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 27 TARGET_UNIT_MASTER
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 28 TARGET_DEST_DYNOBJ_ENEMY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 29 TARGET_DEST_DYNOBJ_ALLY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 30 TARGET_UNIT_SRC_AREA_ALLY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 31 TARGET_UNIT_DEST_AREA_ALLY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 32 TARGET_DEST_CASTER_SUMMON
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 33 TARGET_UNIT_SRC_AREA_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 34 TARGET_UNIT_DEST_AREA_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 35 TARGET_UNIT_TARGET_PARTY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 36 TARGET_DEST_CASTER_UNK_36
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_LAST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_PARTY, TARGET_DIR_NONE}, // 37 TARGET_UNIT_LASTTARGET_AREA_PARTY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 38 TARGET_UNIT_NEARBY_ENTRY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 39 TARGET_DEST_CASTER_FISHING
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 40 TARGET_GAMEOBJECT_NEARBY_ENTRY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 41 TARGET_DEST_CASTER_FRONT_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 42 TARGET_DEST_CASTER_BACK_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 43 TARGET_DEST_CASTER_BACK_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 44 TARGET_DEST_CASTER_FRONT_LEFT
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ALLY, TARGET_DIR_NONE}, // 45 TARGET_UNIT_TARGET_CHAINHEAL_ALLY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_ENTRY, TARGET_DIR_NONE}, // 46 TARGET_DEST_NEARBY_ENTRY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 47 TARGET_DEST_CASTER_FRONT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 48 TARGET_DEST_CASTER_BACK
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 49 TARGET_DEST_CASTER_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 50 TARGET_DEST_CASTER_LEFT
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 51 TARGET_GAMEOBJECT_SRC_AREA
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 52 TARGET_GAMEOBJECT_DEST_AREA
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 53 TARGET_DEST_TARGET_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 54 TARGET_UNIT_CONE_ENEMY_54
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 55 TARGET_DEST_CASTER_FRONT_LEAP
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 56 TARGET_UNIT_CASTER_AREA_RAID
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 57 TARGET_UNIT_TARGET_RAID
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_NEARBY, TARGET_CHECK_RAID, TARGET_DIR_NONE}, // 58 TARGET_UNIT_NEARBY_RAID
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ALLY, TARGET_DIR_FRONT}, // 59 TARGET_UNIT_CONE_ALLY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENTRY, TARGET_DIR_FRONT}, // 60 TARGET_UNIT_CONE_ENTRY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_RAID_CLASS,TARGET_DIR_NONE}, // 61 TARGET_UNIT_TARGET_AREA_RAID_CLASS
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 62 TARGET_UNK_62
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 63 TARGET_DEST_TARGET_ANY
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 64 TARGET_DEST_TARGET_FRONT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 65 TARGET_DEST_TARGET_BACK
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 66 TARGET_DEST_TARGET_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 67 TARGET_DEST_TARGET_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 68 TARGET_DEST_TARGET_FRONT_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 69 TARGET_DEST_TARGET_BACK_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 70 TARGET_DEST_TARGET_BACK_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 71 TARGET_DEST_TARGET_FRONT_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 72 TARGET_DEST_CASTER_RANDOM
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 73 TARGET_DEST_CASTER_RADIUS
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 74 TARGET_DEST_TARGET_RANDOM
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 75 TARGET_DEST_TARGET_RADIUS
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 76 TARGET_DEST_CHANNEL_TARGET
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 77 TARGET_UNIT_CHANNEL_TARGET
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 78 TARGET_DEST_DEST_FRONT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK}, // 79 TARGET_DEST_DEST_BACK
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RIGHT}, // 80 TARGET_DEST_DEST_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_LEFT}, // 81 TARGET_DEST_DEST_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_RIGHT}, // 82 TARGET_DEST_DEST_FRONT_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_RIGHT}, // 83 TARGET_DEST_DEST_BACK_RIGHT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_BACK_LEFT}, // 84 TARGET_DEST_DEST_BACK_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT_LEFT}, // 85 TARGET_DEST_DEST_FRONT_LEFT
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 86 TARGET_DEST_DEST_RANDOM
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 87 TARGET_DEST_DEST
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 88 TARGET_DEST_DYNOBJ_NONE
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 89 TARGET_DEST_TRAJ
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 90 TARGET_UNIT_TARGET_MINIPET
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 91 TARGET_DEST_DEST_RADIUS
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 92 TARGET_UNIT_SUMMONER
+ {TARGET_OBJECT_TYPE_CORPSE, TARGET_REFERENCE_TYPE_SRC, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 93 TARGET_CORPSE_SRC_AREA_ENEMY
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 94 TARGET_UNIT_VEHICLE
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_TARGET, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_PASSENGER, TARGET_DIR_NONE}, // 95 TARGET_UNIT_TARGET_PASSENGER
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 96 TARGET_UNIT_PASSENGER_0
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 97 TARGET_UNIT_PASSENGER_1
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 98 TARGET_UNIT_PASSENGER_2
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 99 TARGET_UNIT_PASSENGER_3
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 100 TARGET_UNIT_PASSENGER_4
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 101 TARGET_UNIT_PASSENGER_5
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 102 TARGET_UNIT_PASSENGER_6
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 103 TARGET_UNIT_PASSENGER_7
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_ENEMY, TARGET_DIR_FRONT}, // 104 TARGET_UNIT_CONE_ENEMY_104
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 105 TARGET_UNIT_UNK_105
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CHANNEL, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 106 TARGET_DEST_CHANNEL_CASTER
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_DEST, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 107 TARGET_UNK_DEST_AREA_UNK_107
+ {TARGET_OBJECT_TYPE_GOBJ, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_CONE, TARGET_CHECK_DEFAULT, TARGET_DIR_FRONT}, // 108 TARGET_GAMEOBJECT_CONE
+ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 109
+ {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 110 TARGET_DEST_UNK_110
};
SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex)
@@ -481,6 +484,7 @@ SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const*
ItemType = spellEntry->EffectItemType[effIndex];
TriggerSpell = spellEntry->EffectTriggerSpell[effIndex];
SpellClassMask = spellEntry->EffectSpellClassMask[effIndex];
+ ImplicitTargetConditions = NULL;
}
bool SpellEffectInfo::IsEffect() const
@@ -938,6 +942,11 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
ChainEntry = NULL;
}
+SpellInfo::~SpellInfo()
+{
+ _UnloadImplicitTargetConditionLists();
+}
+
bool SpellInfo::HasEffect(SpellEffects effect) const
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -1563,38 +1572,99 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
return SPELL_CAST_OK;
}
-SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, bool implicit) const
+SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* target, bool implicit) const
{
if (AttributesEx & SPELL_ATTR1_CANT_TARGET_SELF && caster == target)
return SPELL_FAILED_BAD_TARGETS;
- if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT && target->isInCombat())
- return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
+ // check visibility - ignore stealth for implicit (area) targets
+ if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->canSeeOrDetect(target, implicit))
+ return SPELL_FAILED_BAD_TARGETS;
+
+ Unit const* unitTarget = target->ToUnit();
+
+ // creature/player specific target checks
+ if (unitTarget)
+ {
+ if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT && unitTarget->isInCombat())
+ return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
+
+ // only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
+ if (((AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS) != 0) != unitTarget->HasAuraType(SPELL_AURA_GHOST))
+ {
+ if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS)
+ return SPELL_FAILED_TARGET_NOT_GHOST;
+ else
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+
+ if (caster != unitTarget)
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
+ if (AttributesEx2 & SPELL_ATTR2_CANT_TARGET_TAPPED)
+ if (Creature const* targetCreature = unitTarget->ToCreature())
+ if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer()))
+ return SPELL_FAILED_CANT_CAST_ON_TAPPED;
+
+ if (AttributesCu & SPELL_ATTR0_CU_PICKPOCKET)
+ {
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER)
+ return SPELL_FAILED_BAD_TARGETS;
+ else if ((unitTarget->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0)
+ return SPELL_FAILED_TARGET_NO_POCKETS;
+ }
+
+ // Not allow disarm unarmed player
+ if (Mechanic == MECHANIC_DISARM)
+ {
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER)
+ {
+ Player const* player = unitTarget->ToPlayer();
+ if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true))
+ return SPELL_FAILED_TARGET_NO_WEAPONS;
+ }
+ else if (!unitTarget->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID))
+ return SPELL_FAILED_TARGET_NO_WEAPONS;
+ }
+ }
+ }
+ }
+ // corpse specific target checks
+ else if (Corpse const* corpseTarget = target->ToCorpse())
+ {
+ // cannot target bare bones
+ if (corpseTarget->GetType() == CORPSE_BONES)
+ return SPELL_FAILED_BAD_TARGETS;
+ // we have to use owner for some checks (aura preventing resurrection for example)
+ if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
+ unitTarget = owner;
+ // we're not interested in corpses without owner
+ else
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+ // other types of objects - always valid
+ else return SPELL_CAST_OK;
- if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS && !target->ToPlayer())
+ // corpseOwner and unit specific target checks
+ if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS && !unitTarget->ToPlayer())
return SPELL_FAILED_TARGET_NOT_PLAYER;
- if (!IsAllowingDeadTarget() && !target->isAlive())
+ if (!IsAllowingDeadTarget() && !unitTarget->isAlive())
return SPELL_FAILED_TARGETS_DEAD;
- if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS && !(!target->isAlive() && target->HasAuraType(SPELL_AURA_GHOST)))
- return SPELL_FAILED_TARGET_NOT_GHOST;
-
// check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness
- if (implicit && AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED && !target->CanFreeMove())
+ if (implicit && AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED && !unitTarget->CanFreeMove())
return SPELL_FAILED_BAD_TARGETS;
- // check visibility - ignore stealth for implicit (area) targets
- if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->canSeeOrDetect(target, implicit))
- return SPELL_FAILED_BAD_TARGETS;
-
// checked in Unit::IsValidAttack/AssistTarget, shouldn't be checked for ENTRY targets
//if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
// return SPELL_FAILED_BAD_TARGETS;
//if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_POSSESSED_FRIENDS)
- if (!CheckTargetCreatureType(target))
+ if (!CheckTargetCreatureType(unitTarget))
{
if (target->GetTypeId() == TYPEID_PLAYER)
return SPELL_FAILED_TARGET_IS_PLAYER;
@@ -1603,65 +1673,32 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, b
}
// check GM mode and GM invisibility - only for player casts (npc casts are controlled by AI) and negative spells
- if (target != caster && (caster->IsControlledByPlayer() || !IsPositive()) && target->GetTypeId() == TYPEID_PLAYER)
+ if (unitTarget != caster && (caster->IsControlledByPlayer() || !IsPositive()) && unitTarget->GetTypeId() == TYPEID_PLAYER)
{
- if (!target->ToPlayer()->IsVisible())
+ if (!unitTarget->ToPlayer()->IsVisible())
return SPELL_FAILED_BM_OR_INVISGOD;
- if (target->ToPlayer()->isGameMaster())
+ if (unitTarget->ToPlayer()->isGameMaster())
return SPELL_FAILED_BM_OR_INVISGOD;
}
// not allow casting on flying player
- if (target->HasUnitState(UNIT_STATE_IN_FLIGHT))
+ if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT))
return SPELL_FAILED_BAD_TARGETS;
- if (TargetAuraState && !target->HasAuraState(AuraStateType(TargetAuraState), this, caster))
+ if (TargetAuraState && !unitTarget->HasAuraState(AuraStateType(TargetAuraState), this, caster))
return SPELL_FAILED_TARGET_AURASTATE;
- if (TargetAuraStateNot && target->HasAuraState(AuraStateType(TargetAuraStateNot), this, caster))
+ if (TargetAuraStateNot && unitTarget->HasAuraState(AuraStateType(TargetAuraStateNot), this, caster))
return SPELL_FAILED_TARGET_AURASTATE;
- if (TargetAuraSpell && !target->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster)))
+ if (TargetAuraSpell && !unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster)))
return SPELL_FAILED_TARGET_AURASTATE;
- if (ExcludeTargetAuraSpell && target->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster)))
+ if (ExcludeTargetAuraSpell && unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster)))
return SPELL_FAILED_TARGET_AURASTATE;
- if (caster != target)
- {
- if (caster->GetTypeId() == TYPEID_PLAYER)
- {
- // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
- if (AttributesEx2 & SPELL_ATTR2_CANT_TARGET_TAPPED)
- if (Creature const* targetCreature = target->ToCreature())
- if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer()))
- return SPELL_FAILED_CANT_CAST_ON_TAPPED;
-
- if (AttributesCu & SPELL_ATTR0_CU_PICKPOCKET)
- {
- if (target->GetTypeId() == TYPEID_PLAYER)
- return SPELL_FAILED_BAD_TARGETS;
- else if ((target->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0)
- return SPELL_FAILED_TARGET_NO_POCKETS;
- }
-
- // Not allow disarm unarmed player
- if (Mechanic == MECHANIC_DISARM)
- {
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- Player const* player = target->ToPlayer();
- if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true))
- return SPELL_FAILED_TARGET_NO_WEAPONS;
- }
- else if (!target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID))
- return SPELL_FAILED_TARGET_NO_WEAPONS;
- }
- }
- }
-
- if (target->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION))
+ if (unitTarget->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION))
if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT_NEW))
return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED;
@@ -2035,13 +2072,19 @@ float SpellInfo::GetMinRange(bool positive) const
return RangeEntry->minRangeHostile;
}
-float SpellInfo::GetMaxRange(bool positive) const
+float SpellInfo::GetMaxRange(bool positive, Unit* caster, Spell* spell) const
{
if (!RangeEntry)
return 0.0f;
+ float range;
if (positive)
- return RangeEntry->maxRangeFriend;
- return RangeEntry->maxRangeHostile;
+ range = RangeEntry->maxRangeFriend;
+ else
+ range = RangeEntry->maxRangeHostile;
+ if (caster)
+ if (Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(Id, SPELLMOD_RANGE, range, spell);
+ return range;
}
int32 SpellInfo::GetDuration() const
@@ -2552,3 +2595,20 @@ bool SpellInfo::_IsPositiveTarget(uint32 targetA, uint32 targetB)
return _IsPositiveTarget(targetB, 0);
return true;
}
+
+void SpellInfo::_UnloadImplicitTargetConditionLists()
+{
+ // find the same instances of ConditionList and delete them.
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ ConditionList* cur = Effects[i].ImplicitTargetConditions;
+ if (!cur)
+ continue;
+ for (uint8 j = i; j < MAX_SPELL_EFFECTS; ++j)
+ {
+ if (Effects[j].ImplicitTargetConditions == cur)
+ Effects[j].ImplicitTargetConditions = NULL;
+ }
+ delete cur;
+ }
+}
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 65be5981c64..69ea07f7563 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -36,6 +36,7 @@ struct SpellRangeEntry;
struct SpellRadiusEntry;
struct SpellEntry;
struct SpellCastTimesEntry;
+struct Condition;
enum SpellCastTargetFlags
{
@@ -105,15 +106,16 @@ enum SpellTargetObjectTypes
TARGET_OBJECT_TYPE_CORPSE_ALLY,
};
-enum SpellTargetSelectionCheckTypes
+enum SpellTargetCheckTypes
{
- TARGET_SELECT_CHECK_DEFAULT,
- TARGET_SELECT_CHECK_ENTRY,
- TARGET_SELECT_CHECK_ENEMY,
- TARGET_SELECT_CHECK_ALLY,
- TARGET_SELECT_CHECK_PARTY,
- TARGET_SELECT_CHECK_RAID,
- TARGET_SELECT_CHECK_PASSENGER,
+ TARGET_CHECK_DEFAULT,
+ TARGET_CHECK_ENTRY,
+ TARGET_CHECK_ENEMY,
+ TARGET_CHECK_ALLY,
+ TARGET_CHECK_PARTY,
+ TARGET_CHECK_RAID,
+ TARGET_CHECK_RAID_CLASS,
+ TARGET_CHECK_PASSENGER,
};
enum SpellTargetDirectionTypes
@@ -220,7 +222,7 @@ public:
SpellTargetSelectionCategories GetSelectionCategory() const;
SpellTargetReferenceTypes GetReferenceType() const;
SpellTargetObjectTypes GetObjectType() const;
- SpellTargetSelectionCheckTypes GetSelectionCheckType() const;
+ SpellTargetCheckTypes GetCheckType() const;
SpellTargetDirectionTypes GetDirectionType() const;
float CalcDirectionAngle() const;
@@ -240,7 +242,7 @@ private:
SpellTargetObjectTypes ObjectType; // type of object returned by target type
SpellTargetReferenceTypes ReferenceType; // defines which object is used as a reference when selecting target
SpellTargetSelectionCategories SelectionCategory;
- SpellTargetSelectionCheckTypes SelectionCheckType; // defines selection criteria
+ SpellTargetCheckTypes SelectionCheckType; // defines selection criteria
SpellTargetDirectionTypes DirectionType; // direction for cone and dest targets
};
static StaticData _data[TOTAL_SPELL_TARGETS];
@@ -271,6 +273,7 @@ public:
uint32 ItemType;
uint32 TriggerSpell;
flag96 SpellClassMask;
+ std::list<Condition*>* ImplicitTargetConditions;
SpellEffectInfo() {}
SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex);
@@ -388,6 +391,7 @@ public:
SpellChainNode const* ChainEntry;
SpellInfo(SpellEntry const* spellEntry);
+ ~SpellInfo();
bool HasEffect(SpellEffects effect) const;
bool HasAura(AuraType aura) const;
@@ -438,7 +442,7 @@ public:
SpellCastResult CheckShapeshift(uint32 form) const;
SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const;
- SpellCastResult CheckTarget(Unit const* caster, Unit const* target, bool implicit = true) const;
+ SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const;
SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const;
bool CheckTargetCreatureType(Unit const* target) const;
@@ -456,7 +460,7 @@ public:
SpellSpecificType GetSpellSpecific() const;
float GetMinRange(bool positive = false) const;
- float GetMaxRange(bool positive = false) const;
+ float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) const;
int32 GetDuration() const;
int32 GetMaxDuration() const;
@@ -482,6 +486,9 @@ public:
bool _IsPositiveEffect(uint8 effIndex, bool deep) const;
bool _IsPositiveSpell() const;
static bool _IsPositiveTarget(uint32 targetA, uint32 targetB);
+
+ // unloading helpers
+ void _UnloadImplicitTargetConditionLists();
};
#endif // _SPELLINFO_H
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index ff4eaae42f2..c1b267d9fac 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2644,11 +2644,20 @@ void SpellMgr::UnloadSpellInfoStore()
for (uint32 i = 0; i < mSpellInfoMap.size(); ++i)
{
if (mSpellInfoMap[i])
- delete mSpellInfoMap[i];
+ delete mSpellInfoMap[i];
}
mSpellInfoMap.clear();
}
+void SpellMgr::UnloadSpellInfoImplicitTargetConditionLists()
+{
+ for (uint32 i = 0; i < mSpellInfoMap.size(); ++i)
+ {
+ if (mSpellInfoMap[i])
+ mSpellInfoMap[i]->_UnloadImplicitTargetConditionLists();
+ }
+}
+
void SpellMgr::LoadSpellCustomAttr()
{
uint32 oldMSTime = getMSTime();
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 14137b6a91b..9fffd474651 100755
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -360,17 +360,6 @@ struct SpellThreatEntry
typedef std::map<uint32, SpellThreatEntry> SpellThreatMap;
-// Spell script target related declarations (accessed using SpellMgr functions)
-enum SpellScriptTargetType
-{
- SPELL_TARGET_TYPE_GAMEOBJECT = 0,
- SPELL_TARGET_TYPE_CREATURE = 1,
- SPELL_TARGET_TYPE_DEAD = 2,
- SPELL_TARGET_TYPE_CONTROLLED = 3,
-};
-
-#define MAX_SPELL_TARGET_TYPE 4
-
// coordinates for spells (accessed using SpellMgr functions)
struct SpellTargetPosition
{
@@ -726,6 +715,7 @@ class SpellMgr
void LoadSpellAreas();
void LoadSpellInfoStore();
void UnloadSpellInfoStore();
+ void UnloadSpellInfoImplicitTargetConditionLists();
void LoadSpellCustomAttr();
void LoadDbcDataCorrections();
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 14dd32a71b6..03fea614c0d 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -473,11 +473,6 @@ void SpellScript::GetSummonPosition(uint32 i, Position &pos, float radius = 0.0f
m_spell->GetSummonPosition(i, pos, radius, count);
}
-void SpellScript::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry)
-{
- m_spell->SearchAreaTarget(TagUnitMap, radius, type, TargetType, entry);
-}
-
void SpellScript::PreventHitEffect(SpellEffIndex effIndex)
{
if (!IsInHitPhase() && !IsInEffectHook())
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 09b9eaebd62..1bf8d25adef 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -336,7 +336,6 @@ class SpellScript : public _SpellScript
void PreventHitHeal() { SetHitHeal(0); }
Spell* GetSpell() { return m_spell; }
void GetSummonPosition(uint32 i, Position &pos, float radius, uint32 count);
- void SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry);
// returns current spell hit target aura
Aura* GetHitAura();
// prevents applying aura on current spell hit target
diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp
index 77332bd30a8..589b666c035 100644
--- a/src/server/game/Warden/WardenCheckMgr.cpp
+++ b/src/server/game/Warden/WardenCheckMgr.cpp
@@ -82,7 +82,7 @@ void WardenCheckMgr::LoadWardenChecks()
uint32 count = 0;
do
{
- Field* fields = result->Fetch();
+ fields = result->Fetch();
uint16 id = fields[0].GetUInt16();
uint8 checkType = fields[1].GetUInt8();
@@ -156,11 +156,11 @@ void WardenCheckMgr::LoadWardenChecks()
uint32 overrideCount = 0;
- if(overrideResult)
+ if (overrideResult)
{
do
{
- Field * fields = overrideResult->Fetch();
+ fields = overrideResult->Fetch();
uint16 checkId = fields[0].GetUInt16();