diff options
-rw-r--r-- | src/bindings/scripts/include/sc_creature.cpp | 46 | ||||
-rw-r--r-- | src/game/GridNotifiersImpl.h | 2 | ||||
-rw-r--r-- | src/game/Pet.cpp | 4 | ||||
-rw-r--r-- | src/game/PetHandler.cpp | 2 | ||||
-rw-r--r-- | src/game/SharedDefines.h | 77 | ||||
-rw-r--r-- | src/game/Spell.cpp | 924 | ||||
-rw-r--r-- | src/game/Spell.h | 44 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 8 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 142 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 8 | ||||
-rw-r--r-- | src/game/Unit.cpp | 2 |
11 files changed, 652 insertions, 607 deletions
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index a7cc388bbbb..62a6255828f 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -572,49 +572,49 @@ void FillSpellSummary() for (int j=0; j<3; j++) { //Spell targets self - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF ) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1); //Spell targets a single enemy - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || - TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES ) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY || + TempSpell->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1); //Spell targets AoE at enemy - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER || + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_SRC || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_DST || + TempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_DYNOBJ_ENEMY ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1); //Spell targets an enemy - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || - TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER || + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ENEMY || + TempSpell->EffectImplicitTargetA[j] == TARGET_DST_TARGET_ENEMY || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_SRC || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_AREA_ENEMY_DST || + TempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_DYNOBJ_ENEMY ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1); //Spell targets a single friend(or self) - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF || - TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND || - TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY ) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ALLY || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_PARTY ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1); //Spell targets aoe friends - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || - TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_TARGET || + TempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1); //Spell targets any friend(or self) - if ( TempSpell->EffectImplicitTargetA[j] == TARGET_SELF || - TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND || - TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || - TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER) + if ( TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_ALLY || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_TARGET_PARTY || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_UNIT_PARTY_TARGET || + TempSpell->EffectImplicitTargetA[j] == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1); //Make sure that this spell includes a damage effect diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 78d3d9aba5a..3b9a7b79204 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -181,7 +181,7 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target) SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId()); uint32 eff_index = i_dynobject.GetEffIndex(); if(spellInfo->EffectImplicitTargetB[eff_index] == TARGET_DEST_DYNOBJ_ALLY - || spellInfo->EffectImplicitTargetB[eff_index] == TARGET_UNIT_AREA_ALLY_GROUND) + || spellInfo->EffectImplicitTargetB[eff_index] == TARGET_UNIT_AREA_ALLY_DST) { if(!i_check->IsFriendlyTo(target)) return; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 6b5ff6c1543..75664032ce3 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1721,8 +1721,8 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) return; //if(const SpellEntry *tempSpell = GetSpellStore()->LookupEntry(spellid)) - // if(tempSpell->EffectImplicitTargetA[0] != TARGET_ALL_AROUND_CASTER - // && tempSpell->EffectImplicitTargetA[0] != TARGET_CHAIN_DAMAGE) + // if(tempSpell->EffectImplicitTargetA[0] != TARGET_SRC_CASTER + // && tempSpell->EffectImplicitTargetA[0] != TARGET_UNIT_TARGET_ENEMY) // return; PetSpellMap::const_iterator itr = m_spells.find((uint16)spellid); diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index de9079750ff..a3644371f47 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -194,7 +194,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) for(uint32 i = 0; i < 3;i++) { - if(spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) + if(spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_SRC || spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_DST || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) return; } diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 3266b5aa62d..c62551e0932 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -788,64 +788,42 @@ enum SpellImmunity enum Targets { - TARGET_SELF = 1, TARGET_UNIT_CASTER = 1, - TARGET_RANDOM_ENEMY_CHAIN_IN_AREA = 2, // only one spell has that, but regardless, it's a target type after all - //TARGET_UNIT_NEARBY_ENEMY - TARGET_UNIT_SINGLE_UNKNOWN = 3, - TARGET_UNIT_NEARBY_ALLY = 4, - TARGET_PET = 5, + TARGET_UNIT_NEARBY_ENEMY = 2, // only one spell has that, but regardless, it's a target type after all + TARGET_UNIT_NEARBY_ALLY = 3, + TARGET_UNIT_NEARBY_ALLY_UNK = 4, TARGET_UNIT_PET = 5, - TARGET_CHAIN_DAMAGE = 6, TARGET_UNIT_TARGET_ENEMY = 6, - TARGET_UNIT_AREA_ENTRY = 7, - TARGET_AREAEFFECT_CUSTOM = 8, - TARGET_UNIT_AREA_ENTRY_GROUND = 8, - TARGET_INNKEEPER_COORDINATES = 9, // uses in teleport to innkeeper spells - //TARGET_DEST_HOME + TARGET_UNIT_AREA_ENTRY_SRC = 7, + TARGET_UNIT_AREA_ENTRY_DST = 8, + TARGET_DST_HOME = 9, // uses in teleport to innkeeper spells TARGET_UNIT_TARGET_DEST_CASTER = 11, // teleport target to caster - TARGET_ALL_ENEMY_IN_AREA = 15, - TARGET_UNIT_AREA_ENEMY = 15, - TARGET_ALL_ENEMY_IN_AREA_INSTANT = 16, - TARGET_UNIT_AREA_ENEMY_GROUND = 16, - TARGET_TABLE_X_Y_Z_COORDINATES = 17, // uses in teleport spells and some other - //TARGET_DEST_TABLE - TARGET_EFFECT_SELECT = 18, // highly depends on the spell effect - TARGET_DEST_CASTER_GROUND = 18, - TARGET_ALL_PARTY_AROUND_CASTER = 20, + TARGET_UNIT_AREA_ENEMY_SRC = 15, + TARGET_UNIT_AREA_ENEMY_DST = 16, + TARGET_DST_DB = 17, // uses in teleport spells and some other + TARGET_DST_CASTER = 18, TARGET_UNIT_PARTY_CASTER = 20, - TARGET_SINGLE_FRIEND = 21, TARGET_UNIT_TARGET_ALLY = 21, - TARGET_ALL_AROUND_CASTER = 22, // used only in TargetA, target selection dependent from TargetB - TARGET_DEST_CASTER = 22, + TARGET_SRC_CASTER = 22, TARGET_GAMEOBJECT = 23, //TARGET_OBJECT_OPEN - TARGET_IN_FRONT_OF_CASTER = 24, TARGET_UNIT_CONE_ENEMY = 24, - TARGET_DUELVSPLAYER = 25, TARGET_UNIT_TARGET_ANY = 25, TARGET_GAMEOBJECT_ITEM = 26, //TARGET_OBJECT_ITEM_PICKLOCK TARGET_UNIT_MASTER = 27, TARGET_DEST_DYNOBJ_ENEMY = 28, TARGET_DEST_DYNOBJ_ALLY = 29, // only for effect 27 - TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER = 30, // in TargetB used only with TARGET_ALL_AROUND_CASTER and in self casting range in TargetA - TARGET_UNIT_AREA_ALLY = 30, - TARGET_ALL_FRIENDLY_UNITS_IN_AREA = 31, - TARGET_UNIT_AREA_ALLY_GROUND = 31, + TARGET_UNIT_AREA_ALLY_SRC = 30, // in TargetB used only with TARGET_SRC_CASTER and in self casting range in TargetA + TARGET_UNIT_AREA_ALLY_DST = 31, TARGET_MINION = 32, //TARGET_DEST_SUMMON - TARGET_ALL_PARTY = 33, - TARGET_UNIT_AREA_PARTY = 33, - TARGET_ALL_PARTY_AROUND_CASTER_2 = 34, // used in Tranquility - TARGET_UNIT_AREA_PARTY_GROUND = 34, - TARGET_SINGLE_PARTY = 35, + TARGET_UNIT_AREA_PARTY_SRC = 33, + TARGET_UNIT_AREA_PARTY_DST = 34, // used in Tranquility TARGET_UNIT_TARGET_PARTY = 35, TARGET_DEST_CASTER_RANDOM_UNKNOWN = 36, //unknown - TARGET_AREAEFFECT_PARTY = 37, TARGET_UNIT_PARTY_TARGET = 37, - TARGET_SCRIPT = 38, - //TARGET_UNIT_NEARBY_ENTRY + TARGET_UNIT_NEARBY_ENTRY = 38, TARGET_UNIT_CASTER_FISHING = 39, TARGET_OBJECT_USE = 40, TARGET_DEST_CASTER_FRONT_LEFT = 41, //earth totem @@ -853,28 +831,23 @@ enum Targets TARGET_DEST_CASTER_BACK_RIGHT = 43, //air totem TARGET_DEST_CASTER_FRONT_RIGHT = 44, //fire totem TARGET_UNIT_CHAINHEAL = 45, - TARGET_SCRIPT_COORDINATES = 46, - //TARGET_DEST_NEARBY_ENTRY + TARGET_DST_NEARBY_ENTRY = 46, TARGET_DEST_CASTER_FRONT = 47, TARGET_DEST_CASTER_BACK = 48, TARGET_DEST_CASTER_RIGHT = 49, TARGET_DEST_CASTER_LEFT = 50, - TARGET_OBJECT_AREA = 51, - TARGET_AREAEFFECT_CUSTOM_2 = 52, - //TARGET_DUMMY - TARGET_CURRENT_ENEMY_COORDINATES = 53, // set unit coordinates as dest, only 16 target B imlemented - TARGET_DEST_TARGET_ENEMY = 53, - TARGET_UNIT_CONE_ENEMY_UNKNOWN = 54, + TARGET_OBJECT_AREA_SRC = 51, + TARGET_OBJECT_AREA_DST = 52, + TARGET_DST_TARGET_ENEMY = 53, // set unit coordinates as dest, only 16 target B imlemented + TARGET_UNIT_CONE_ENEMY_UNKNOWN = 54, // 180 degree, or different angle TARGET_DEST_CASTER_FRONT_LEAP = 55, // for a leap spell - TARGET_UNIT_RAID = 56, - TARGET_SINGLE_FRIEND_2 = 57, + TARGET_UNIT_RAID_CASTER = 56, TARGET_UNIT_TARGET_RAID = 57, + TARGET_UNIT_NEARBY_RAID = 58, TARGET_UNIT_CONE_ALLY = 59, - TARGET_UNIT_AREA_SCRIPT = 60, - TARGET_AREAEFFECT_PARTY_AND_CLASS = 61, + TARGET_UNIT_CONE_ENTRY = 60, TARGET_UNIT_CLASS_TARGET = 61, TARGET_TEST = 62, // for a test spell - TARGET_DUELVSPLAYER_COORDINATES = 63, TARGET_DEST_TARGET_ANY = 63, TARGET_DEST_TARGET_FRONT = 64, TARGET_DEST_TARGET_BACK = 65, // uses in teleport behind spells @@ -900,7 +873,7 @@ enum Targets TARGET_DEST_DEST_FRONT_RIGHT = 85, TARGET_DEST_DEST_RANDOM = 86, TARGET_DEST_DEST = 87, - TARGET_UNIT_AREA_ALL_CHANNEL = 88, + TARGET_DEST_DYNOBJ_NONE = 88, TARGET_DEST_TRAJ = 89, TARGET_UNIT_MINIPET = 90, TARGET_CORPSE_AREA_ENEMY_PLAYER = 93, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 81f73e6ad65..622ca263adf 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -76,7 +76,6 @@ SpellCastTargets::SpellCastTargets() m_itemTargetEntry = 0; m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0; - m_hasDest = false; m_strTarget = ""; m_targetMask = 0; } @@ -95,29 +94,40 @@ void SpellCastTargets::setUnitTarget(Unit *target) m_targetMask |= TARGET_FLAG_UNIT; } -void SpellCastTargets::setDestination(float x, float y, float z, bool send, int32 mapId) +void SpellCastTargets::setSrc(float x, float y, float z) +{ + m_srcX = x; + m_srcY = y; + m_srcZ = z; + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; +} + +void SpellCastTargets::setSrc(WorldObject *target) +{ + if(!target) + return; + + target->GetPosition(m_srcX, m_srcY, m_srcZ); + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; +} + +void SpellCastTargets::setDestination(float x, float y, float z, int32 mapId) { m_destX = x; m_destY = y; m_destZ = z; - m_hasDest = true; - if(send) - m_targetMask |= TARGET_FLAG_DEST_LOCATION; + m_targetMask |= TARGET_FLAG_DEST_LOCATION; if(mapId >= 0) m_mapId = mapId; } -void SpellCastTargets::setDestination(Unit *target, bool send) +void SpellCastTargets::setDestination(WorldObject *target) { if(!target) return; - m_destX = target->GetPositionX(); - m_destY = target->GetPositionY(); - m_destZ = target->GetPositionZ(); - m_hasDest = true; - if(send) - m_targetMask |= TARGET_FLAG_DEST_LOCATION; + target->GetPosition(m_destX, m_destY, m_destZ); + m_targetMask |= TARGET_FLAG_DEST_LOCATION; } void SpellCastTargets::setGOTarget(GameObject *target) @@ -190,7 +200,7 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) if(!readGUID(*data, m_itemTargetGUID)) return false; - /*if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) + if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) { if(data->rpos()+4+4+4 > data->size()) return false; @@ -198,15 +208,14 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) *data >> m_srcX >> m_srcY >> m_srcZ; if(!Trinity::IsValidMapCoord(m_srcX, m_srcY, m_srcZ)) return false; - }*/ + } - if( m_targetMask & (TARGET_FLAG_SOURCE_LOCATION | TARGET_FLAG_DEST_LOCATION) ) + if( m_targetMask & TARGET_FLAG_DEST_LOCATION ) { if(data->rpos()+4+4+4 > data->size()) return false; *data >> m_destX >> m_destY >> m_destZ; - m_hasDest = true; if(!Trinity::IsValidMapCoord(m_destX, m_destY, m_destZ)) return false; } @@ -411,28 +420,18 @@ void Spell::FillTargetMap() if(effectTargetType == SPELL_REQUIRE_NONE) continue; - std::list<Unit*> tmpUnitMap; uint32 targetA = m_spellInfo->EffectImplicitTargetA[i]; uint32 targetB = m_spellInfo->EffectImplicitTargetB[i]; if(targetA) - SetTargetMap(i, targetA, tmpUnitMap); + SetTargetMap(i, targetA); if(targetB) // In very rare case !A && B - SetTargetMap(i, targetB, tmpUnitMap); + SetTargetMap(i, targetB); if(effectTargetType != SPELL_REQUIRE_UNIT) { if(effectTargetType == SPELL_REQUIRE_CASTER) AddUnitTarget(m_caster, i); - /*else if(effectTargetType == SPELL_REQUIRE_DEST) - { - if(m_targets.HasDest() && m_spellInfo->speed > 0.0f) - { - float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); - if (dist < 5.0f) dist = 5.0f; - m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f); - } - }*/ else if(effectTargetType == SPELL_REQUIRE_ITEM) { if(m_targets.getItemTarget()) @@ -471,12 +470,12 @@ void Spell::FillTargetMap() { case TYPEID_UNIT: case TYPEID_PLAYER: - tmpUnitMap.push_back((Unit*)result); + AddUnitTarget((Unit*)result, i); break; case TYPEID_CORPSE: m_targets.setCorpseTarget((Corpse*)result); if(Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID())) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); break; } } @@ -500,7 +499,7 @@ void Spell::FillTargetMap() } default: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); break; } break; @@ -513,21 +512,21 @@ void Spell::FillTargetMap() case SPELL_EFFECT_REPUTATION: case SPELL_EFFECT_LEARN_SPELL: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); else - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case SPELL_EFFECT_SUMMON_PLAYER: if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetSelection()) { Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection()); if(target) - tmpUnitMap.push_back(target); + AddUnitTarget(target, i); } break; case SPELL_EFFECT_RESURRECT_NEW: if(m_targets.getUnitTarget()) - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); if(m_targets.getCorpseTargetGUID()) { Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID()); @@ -535,7 +534,7 @@ void Spell::FillTargetMap() { Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); if(owner) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); } } break; @@ -543,11 +542,11 @@ void Spell::FillTargetMap() case SPELL_EFFECT_ADD_FARSIGHT: case SPELL_EFFECT_STUCK: case SPELL_EFFECT_DESTROY_ALL_TOTEMS: - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case SPELL_EFFECT_LEARN_PET_SPELL: if(Pet* pet = m_caster->GetPet()) - tmpUnitMap.push_back(pet); + AddUnitTarget(pet, i); break; /*case SPELL_EFFECT_ENCHANT_ITEM: case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY: @@ -560,9 +559,9 @@ void Spell::FillTargetMap() case SPELL_EFFECT_APPLY_AURA: switch(m_spellInfo->EffectApplyAuraName[i]) { - case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_SELF(1) (and present for other ranks for same spell for example) + case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_UNIT_CASTER(1) (and present for other ranks for same spell for example) case SPELL_AURA_ADD_PCT_MODIFIER: - tmpUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; default: // apply to target in other case break; @@ -571,12 +570,12 @@ void Spell::FillTargetMap() case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: // AreaAura if(m_spellInfo->Attributes == 0x9050000 || m_spellInfo->Attributes == 0x10000) - SetTargetMap(i,TARGET_AREAEFFECT_PARTY,tmpUnitMap); + SetTargetMap(i, TARGET_UNIT_PARTY_TARGET); break; case SPELL_EFFECT_SKIN_PLAYER_CORPSE: if(m_targets.getUnitTarget()) { - tmpUnitMap.push_back(m_targets.getUnitTarget()); + AddUnitTarget(m_targets.getUnitTarget(), i); } else if (m_targets.getCorpseTargetGUID()) { @@ -585,7 +584,7 @@ void Spell::FillTargetMap() { Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); if(owner) - tmpUnitMap.push_back(owner); + AddUnitTarget(owner, i); } } break; @@ -594,28 +593,23 @@ void Spell::FillTargetMap() } } - - if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty()) - m_needAliveTargetMask |= (1<<i); - - for (std::list<Unit*>::iterator itr = tmpUnitMap.begin() ; itr != tmpUnitMap.end();) + if(IsChanneledSpell(m_spellInfo)) { - if(!CheckTarget(*itr, i, false )) + uint8 mask = (1<<i); + for(std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { - itr = tmpUnitMap.erase(itr); - continue; + if(ihit->effectMask & mask) + { + m_needAliveTargetMask |= mask; + break; + } } - else - ++itr; } - - for(std::list<Unit*>::iterator iunit= tmpUnitMap.begin();iunit != tmpUnitMap.end();++iunit) - AddUnitTarget((*iunit), i); } if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) { - if(m_spellInfo->speed > 0.0f && m_targets.HasDest()) + if(m_spellInfo->speed > 0.0f && m_targets.HasDst()) { float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); if (dist < 5.0f) dist = 5.0f; @@ -713,6 +707,9 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) if( m_spellInfo->Effect[effIndex]==0 ) return; + if(!CheckTarget(pVictim, effIndex)) + return; + uint64 targetGUID = pVictim->GetGUID(); // Lookup target in already in list @@ -1378,13 +1375,13 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin std::list<Unit*> tempUnitMap; if(TargetType == SPELL_TARGETS_CHAINHEAL) { - SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, SPELL_TARGETS_ALLY); + SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, SPELL_TARGETS_ALLY); tempUnitMap.sort(ChainHealingOrder(m_caster)); //if(cur->GetHealth() == cur->GetMaxHealth() && tempUnitMap.size()) // cur = tempUnitMap.front(); } else - SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, TargetType); + SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, TargetType); tempUnitMap.remove(cur); while(num) @@ -1431,12 +1428,12 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin } } -void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const uint32 &type, SpellTargets TargetType, uint32 entry) +void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const uint32 type, SpellTargets TargetType, uint32 entry) { float x, y, z; - if(type == PUSH_DEST_CENTER) + if(type == PUSH_DST_CENTER) { - if(!m_targets.HasDest()) + if(!m_targets.HasDst()) { sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id ); return; @@ -1445,7 +1442,7 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u y = m_targets.m_destY; z = m_targets.m_destZ; } - else if(type == PUSH_TARGET_CENTER) + else if(type == PUSH_CHAIN) { Unit *target = m_targets.getUnitTarget(); if(!target) @@ -1472,71 +1469,112 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u m_caster->GetMap()->VisitAll(x, y, radius, notifier); } -Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry) +WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType) { - Unit* target = NULL; switch(TargetType) { case SPELL_TARGETS_ENTRY: { - if(entry) + SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); + SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); + if(lower == upper) { - Creature* target = NULL; - Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, entry, true, radius); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - return target; + sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); + if(IsPositiveSpell(m_spellInfo->Id)) + return SearchNearbyTarget(range, SPELL_TARGETS_ALLY); + else + return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY); } - else + + Creature* creatureScriptTarget = NULL; + GameObject* goScriptTarget = NULL; + + for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) { - //TODO: nearest player - return NULL; + switch(i_spellST->second.type) + { + case SPELL_TARGET_TYPE_GAMEOBJECT: + { + GameObject* p_GameObject = NULL; + + if(i_spellST->second.targetEntry) + { + Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); + Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check); + m_caster->VisitNearbyGridObject(range, checker); + + if(p_GameObject) + { + // remember found target and range, next attempt will find more near target with another entry + creatureScriptTarget = NULL; + goScriptTarget = p_GameObject; + range = go_check.GetLastRange(); + } + } + else if( focusObject ) //Focus Object + { + float frange = m_caster->GetDistance(focusObject); + if(range >= frange) + { + creatureScriptTarget = NULL; + goScriptTarget = focusObject; + range = frange; + } + } + break; + } + case SPELL_TARGET_TYPE_CREATURE: + case SPELL_TARGET_TYPE_DEAD: + default: + { + Creature *p_Creature = NULL; + + Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check); + m_caster->VisitNearbyObject(range, searcher); + + if(p_Creature ) + { + creatureScriptTarget = p_Creature; + goScriptTarget = NULL; + range = u_check.GetLastRange(); + } + break; + } + } } + + if(creatureScriptTarget) + return creatureScriptTarget; + else + return goScriptTarget; } default: case SPELL_TARGETS_ENEMY: { - Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); + Unit *target = NULL; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range); Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - }break; + m_caster->VisitNearbyObject(range, searcher); + return target; + } case SPELL_TARGETS_ALLY: { - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); + Unit *target = NULL; + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, range); Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(target, u_check); - m_caster->VisitNearbyObject(radius, searcher); - }break; + m_caster->VisitNearbyObject(range, searcher); + return target; + } } - return target; } -void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) +void Spell::SetTargetMap(uint32 i, uint32 cur) { - float radius; - if (m_spellInfo->EffectRadiusIndex[i]) - radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); - else - radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); - - //Chain: 2, 6, 22, 25, 45, 77 - uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[i]; - uint32 unMaxTargets = m_spellValue->MaxAffectedTargets; - + SpellNotifyPushType pushType = PUSH_NONE; + Player *modOwner = NULL; if(m_originalCaster) - { - if(Player* modOwner = m_originalCaster->GetSpellModOwner()) - { - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius,this); - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); - } - } - - if(EffectChainTarget > 1) - { - //otherwise, this multiplier is used for something else - m_damageMultipliers[i] = 1.0f; - m_applyMultiplierMask |= 1 << i; - } + modOwner = m_originalCaster->GetSpellModOwner(); switch(spellmgr.SpellTargetType[cur]) { @@ -1546,357 +1584,122 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) { case TARGET_UNIT_CASTER: case TARGET_UNIT_CASTER_FISHING: - TagUnitMap.push_back(m_caster); + AddUnitTarget(m_caster, i); break; case TARGET_UNIT_MASTER: if(Unit* owner = m_caster->GetCharmerOrOwner()) - TagUnitMap.push_back(owner); + AddUnitTarget(owner, i); break; case TARGET_UNIT_PET: if(Pet* pet = m_caster->GetPet()) - TagUnitMap.push_back(pet); + AddUnitTarget(pet, i); break; case TARGET_UNIT_PARTY_CASTER: - m_caster->GetPartyMember(TagUnitMap, radius); - break; - case TARGET_UNIT_RAID: - if(Unit *target = m_targets.getUnitTarget()) - TagUnitMap.push_back(target); - else - m_caster->GetRaidMember(TagUnitMap, radius); + case TARGET_UNIT_RAID_CASTER: + pushType = PUSH_CASTER_CENTER; break; } - }break; + break; + } case TARGET_TYPE_UNIT_TARGET: { Unit *target = m_targets.getUnitTarget(); if(!target) { - sLog.outError("SPELL: no unit target for spell ID %u\n", m_spellInfo->Id); + sLog.outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id); break; } switch(cur) { - case TARGET_UNIT_MINIPET: - if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET) - TagUnitMap.push_back(target); + case TARGET_UNIT_TARGET_ENEMY: + SelectMagnetTarget(); + case TARGET_UNIT_CHAINHEAL: + pushType = PUSH_CHAIN; break; case TARGET_UNIT_TARGET_ALLY: case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_ANY: // SelectMagnetTarget()? case TARGET_UNIT_TARGET_PARTY: - case TARGET_UNIT_SINGLE_UNKNOWN: - TagUnitMap.push_back(target); + case TARGET_UNIT_MINIPET: + AddUnitTarget(target, i); break; case TARGET_UNIT_PARTY_TARGET: - target->GetPartyMember(TagUnitMap, radius); - break; - case TARGET_UNIT_TARGET_ENEMY: - if(EffectChainTarget <= 1) - TagUnitMap.push_back(SelectMagnetTarget()); - else if(SelectMagnetTarget()) //TODO: chain target should also use magnet target - SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY); - break; - case TARGET_UNIT_CHAINHEAL: - if(EffectChainTarget <= 1) - TagUnitMap.push_back(target); - else - SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_CHAINHEAL); - break; - } - }break; - - case TARGET_TYPE_CHANNEL: - { - if(!m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) - { - sLog.outError( "SPELL: no current channeled spell for spell ID %u\n", m_spellInfo->Id ); - break; - } - - switch(cur) - { - case TARGET_UNIT_CHANNEL: - if(Unit* target = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.getUnitTarget()) - TagUnitMap.push_back(target); - else - sLog.outError( "SPELL: cannot find channel spell target for spell ID %u\n", m_spellInfo->Id ); - break; - case TARGET_DEST_CHANNEL: - if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.HasDest()) - m_targets = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets; - else - sLog.outError( "SPELL: cannot find channel spell destination for spell ID %u\n", m_spellInfo->Id ); + case TARGET_UNIT_CLASS_TARGET: + pushType = PUSH_CASTER_CENTER; // not real break; } - }break; + break; + } - case TARGET_TYPE_AREA_DEST: + case TARGET_TYPE_UNIT_NEARBY: { - if(!m_targets.HasDest()) - { - sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id ); - return; - } + float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); - // Dummy for client - if(spellmgr.EffectTargetType[m_spellInfo->Effect[i]] == SPELL_REQUIRE_DEST) - break; + WorldObject *target = NULL; switch(cur) { - case TARGET_UNIT_AREA_ENEMY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ENEMY: - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); + case TARGET_UNIT_NEARBY_ENEMY: + target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY); break; - case TARGET_UNIT_AREA_ALLY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ALLY: - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ALLY); + case TARGET_UNIT_NEARBY_ALLY: + case TARGET_UNIT_NEARBY_ALLY_UNK: + case TARGET_UNIT_NEARBY_RAID: + target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY); break; - case TARGET_UNIT_AREA_PARTY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_PARTY: - m_caster->GetPartyMember(TagUnitMap, radius); + case TARGET_UNIT_NEARBY_ENTRY: + target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY); break; - case TARGET_UNIT_AREA_ENTRY_GROUND: - m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; - case TARGET_UNIT_AREA_ENTRY: - { - SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); - SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); - if(lower==upper) - { - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); - sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); - break; - } - // let it be done in one check? - for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) - { - if(i_spellST->second.type != SPELL_TARGET_TYPE_CREATURE) - { - sLog.outError( "SPELL: spell ID %u requires non-creature target\n", m_spellInfo->Id ); - continue; - } - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry); - } - } - break; } - }break; - case TARGET_TYPE_DEFAULT: - { - switch(cur) + if(!target) + return; + else if(target->GetTypeId() == TYPEID_UNIT) { + pushType = PUSH_CHAIN; - case TARGET_GAMEOBJECT: - { - if(m_targets.getGOTarget()) - AddGOTarget(m_targets.getGOTarget(), i); - }break; - case TARGET_GAMEOBJECT_ITEM: - { - if(m_targets.getGOTargetGUID()) - AddGOTarget(m_targets.getGOTarget(), i); - else if(m_targets.getItemTarget()) - AddItemTarget(m_targets.getItemTarget(), i); - }break; - - case TARGET_TABLE_X_Y_Z_COORDINATES: - if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id)) - { - //TODO: fix this check - if(m_spellInfo->Effect[0] == SPELL_EFFECT_TELEPORT_UNITS - || m_spellInfo->Effect[1] == SPELL_EFFECT_TELEPORT_UNITS - || m_spellInfo->Effect[2] == SPELL_EFFECT_TELEPORT_UNITS) - m_targets.setDestination(st->target_X, st->target_Y, st->target_Z, true, (int32)st->target_mapId); - else if(st->target_mapId == m_caster->GetMapId()) - m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); + if(!m_targets.getUnitTarget()) + m_targets.setUnitTarget((Unit*)target); } - else - sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); - break; - case TARGET_INNKEEPER_COORDINATES: - if(m_caster->GetTypeId() == TYPEID_PLAYER) - m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, true, ((Player*)m_caster)->m_homebindMapId); - break; - + else if(target->GetTypeId() == TYPEID_GAMEOBJECT) + AddGOTarget((GameObject*)target, i); - case TARGET_IN_FRONT_OF_CASTER: - case TARGET_UNIT_CONE_ENEMY_UNKNOWN: - if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_BACK, SPELL_TARGETS_ENEMY); - else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE) - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_ENEMY); - else - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_ENEMY); - break; - case TARGET_UNIT_CONE_ALLY: - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_ALLY); break; + } - // nearby target - case TARGET_UNIT_NEARBY_ALLY: - if(!m_targets.getUnitTarget()) - m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ALLY)); - if(m_targets.getUnitTarget()) - { - if(EffectChainTarget <= 1) - TagUnitMap.push_back(m_targets.getUnitTarget()); - else - SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ALLY); - } - break; - case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: - if(!m_targets.getUnitTarget()) - m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ENEMY)); - if(m_targets.getUnitTarget()) - { - if(EffectChainTarget <= 1) - TagUnitMap.push_back(m_targets.getUnitTarget()); - else - SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY); - } + case TARGET_TYPE_AREA_SRC: + CheckSrc(); + pushType = PUSH_SRC_CENTER; break; - case TARGET_SCRIPT: - case TARGET_SCRIPT_COORDINATES: - case TARGET_UNIT_AREA_SCRIPT: - { - SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); - SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); - if(lower==upper) - { - sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); - TagUnitMap.push_back(m_caster); - break; - } - - SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); - float range = GetSpellMaxRange(srange); - - Creature* creatureScriptTarget = NULL; - GameObject* goScriptTarget = NULL; - for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) - { - switch(i_spellST->second.type) - { - case SPELL_TARGET_TYPE_GAMEOBJECT: - { - GameObject* p_GameObject = NULL; - - if(i_spellST->second.targetEntry) - { - Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); - Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check); - m_caster->VisitNearbyGridObject(range, checker); - - if(p_GameObject) - { - // remember found target and range, next attempt will find more near target with another entry - creatureScriptTarget = NULL; - goScriptTarget = p_GameObject; - range = go_check.GetLastRange(); - } - } - else if( focusObject ) //Focus Object - { - float frange = m_caster->GetDistance(focusObject); - if(range >= frange) - { - creatureScriptTarget = NULL; - goScriptTarget = focusObject; - range = frange; - } - } - break; - } - case SPELL_TARGET_TYPE_CREATURE: - case SPELL_TARGET_TYPE_DEAD: - default: - { - Creature *p_Creature = NULL; - - Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check); - m_caster->VisitNearbyObject(range, searcher); - - if(p_Creature ) - { - creatureScriptTarget = p_Creature; - goScriptTarget = NULL; - range = u_check.GetLastRange(); - } - break; - } - } - } - - if(cur == TARGET_SCRIPT_COORDINATES) - { - if(creatureScriptTarget) - m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); - else if(goScriptTarget) - m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); - } - else - { - if(creatureScriptTarget) - TagUnitMap.push_back(creatureScriptTarget); - else if(goScriptTarget) - AddGOTarget(goScriptTarget, i); - } - }break; - - // dummy - case TARGET_AREAEFFECT_CUSTOM_2: - { - TagUnitMap.push_back(m_caster); + case TARGET_TYPE_AREA_DST: + CheckDst(); + pushType = PUSH_DST_CENTER; break; - } - case TARGET_AREAEFFECT_PARTY_AND_CLASS: - { - Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER - ? (Player*)m_targets.getUnitTarget() : NULL; - Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL; - if(pGroup) - { - for(GroupReference *itr = pGroup->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) ) - { - TagUnitMap.push_back(Target); - } - } - } - else if(m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + case TARGET_TYPE_AREA_CONE: + if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) + pushType = PUSH_IN_BACK; + else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE) + pushType = PUSH_IN_LINE; + else + pushType = PUSH_IN_FRONT; break; - } - } - }break; - - case TARGET_TYPE_DEST_CASTER: + + case TARGET_TYPE_DEST_CASTER: //4+8+2 { - if(cur == TARGET_DEST_CASTER_GROUND) + if(cur == TARGET_SRC_CASTER) { - m_targets.setDestination(m_caster, true); + m_targets.setSrc(m_caster); break; } - else if(cur == TARGET_DEST_CASTER) + else if(cur == TARGET_DST_CASTER) { - m_targets.setDestination(m_caster, false); + m_targets.setDestination(m_caster); break; } @@ -1925,10 +1728,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) } m_caster->GetGroundPointAroundUnit(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } - case TARGET_TYPE_DEST_TARGET: + case TARGET_TYPE_DEST_TARGET: //2+8+2 { Unit *target = m_targets.getUnitTarget(); if(!target) @@ -1937,9 +1741,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) break; } - if(cur == TARGET_DEST_TARGET_ENEMY || cur == TARGET_DEST_TARGET_ANY) + if(cur == TARGET_DST_TARGET_ENEMY || cur == TARGET_DEST_TARGET_ANY) { - m_targets.setDestination(target, true); + m_targets.setDestination(target); break; } @@ -1966,12 +1770,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) } target->GetGroundPointAroundUnit(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } - case TARGET_TYPE_DEST_DEST: + case TARGET_TYPE_DEST_DEST: //5+8+1 { - if(!m_targets.HasDest()) + if(!m_targets.HasDst()) { sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id); break; @@ -1982,7 +1787,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) { case TARGET_DEST_DYNOBJ_ENEMY: case TARGET_DEST_DYNOBJ_ALLY: + case TARGET_DEST_DYNOBJ_NONE: case TARGET_DEST_DEST: + case TARGET_DEST_TRAJ: return; case TARGET_DEST_DEST_FRONT: angle = 0.0f; break; case TARGET_DEST_DEST_BACK: angle = M_PI; break; @@ -2004,20 +1811,251 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) y = m_targets.m_destY; z = m_targets.m_destZ; m_caster->GetGroundPoint(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); // do not know if has ground visual - }break; + m_targets.setDestination(x, y, z); + break; + } + + case TARGET_TYPE_DEST_SPECIAL: + { + switch(cur) + { + case TARGET_DST_DB: + if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id)) + { + //TODO: fix this check + if(m_spellInfo->Effect[0] == SPELL_EFFECT_TELEPORT_UNITS + || m_spellInfo->Effect[1] == SPELL_EFFECT_TELEPORT_UNITS + || m_spellInfo->Effect[2] == SPELL_EFFECT_TELEPORT_UNITS) + m_targets.setDestination(st->target_X, st->target_Y, st->target_Z, (int32)st->target_mapId); + else if(st->target_mapId == m_caster->GetMapId()) + m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); + } + else + sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); + break; + case TARGET_DST_HOME: + if(m_caster->GetTypeId() == TYPEID_PLAYER) + m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, ((Player*)m_caster)->m_homebindMapId); + break; + case TARGET_DST_NEARBY_ENTRY: + { + float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + + WorldObject *target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY); + if(target) + m_targets.setDestination(target); + break; + } + } + break; + } + + case TARGET_TYPE_CHANNEL: + { + if(!m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) + { + sLog.outError( "SPELL: no current channeled spell for spell ID %u", m_spellInfo->Id ); + break; + } + + switch(cur) + { + case TARGET_UNIT_CHANNEL: + if(Unit* target = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.getUnitTarget()) + AddUnitTarget(target, i); + else + sLog.outError( "SPELL: cannot find channel spell target for spell ID %u", m_spellInfo->Id ); + break; + case TARGET_DEST_CHANNEL: + if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.HasDst()) + m_targets = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets; + else + sLog.outError( "SPELL: cannot find channel spell destination for spell ID %u", m_spellInfo->Id ); + break; + } + break; + } default: + { + switch(cur) + { + case TARGET_GAMEOBJECT: + case TARGET_OBJECT_USE: + if(m_targets.getGOTarget()) + AddGOTarget(m_targets.getGOTarget(), i); + break; + case TARGET_GAMEOBJECT_ITEM: + if(m_targets.getGOTargetGUID()) + AddGOTarget(m_targets.getGOTarget(), i); + else if(m_targets.getItemTarget()) + AddItemTarget(m_targets.getItemTarget(), i); + break; + default: + sLog.outError("Unhandled spell target %u", cur); + break; + } break; + } } - if(unMaxTargets && !EffectChainTarget && TagUnitMap.size() > 1) + if(pushType == PUSH_CHAIN) // Chain { - if(m_spellInfo->Id == 5246) //Intimidating Shout - TagUnitMap.remove(m_targets.getUnitTarget()); + Unit *target = m_targets.getUnitTarget(); + if(!target) + { + sLog.outError("SPELL: no chain unit target for spell ID %u", m_spellInfo->Id); + return; + } - Trinity::RandomResizeList(TagUnitMap, unMaxTargets); + //Chain: 2, 6, 22, 25, 45, 77 + uint32 maxTargets = m_spellInfo->EffectChainTarget[i]; + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); + + if(maxTargets > 1) + { + //otherwise, this multiplier is used for something else + m_damageMultipliers[i] = 1.0f; + m_applyMultiplierMask |= 1 << i; + + float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); + + std::list<Unit*> unitList; + + switch(cur) + { + case TARGET_UNIT_NEARBY_ENEMY: + case TARGET_UNIT_TARGET_ENEMY: + case TARGET_UNIT_NEARBY_ENTRY: // fix me + SearchChainTarget(unitList, radius, maxTargets, SPELL_TARGETS_ENEMY); + break; + case TARGET_UNIT_CHAINHEAL: + case TARGET_UNIT_NEARBY_ALLY: // fix me + case TARGET_UNIT_NEARBY_ALLY_UNK: + case TARGET_UNIT_NEARBY_RAID: + SearchChainTarget(unitList, radius, maxTargets, SPELL_TARGETS_CHAINHEAL); + break; + } + + for(std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) + AddUnitTarget(*itr, i); + } + else + AddUnitTarget(target, i); } + else if(pushType) + { + // Dummy, just for client + if(spellmgr.EffectTargetType[m_spellInfo->Effect[i]] == SPELL_REQUIRE_DEST) + return; + + float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + if(modOwner) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); + + std::list<Unit*> unitList; + + switch(cur) + { + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_CONE_ENEMY: + case TARGET_UNIT_CONE_ENEMY_UNKNOWN: + SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENEMY); + break; + case TARGET_UNIT_AREA_ALLY_SRC: + case TARGET_UNIT_AREA_ALLY_DST: + case TARGET_UNIT_CONE_ALLY: + SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ALLY); + break; + case TARGET_UNIT_AREA_PARTY_SRC: + case TARGET_UNIT_AREA_PARTY_DST: + m_caster->GetPartyMember(unitList, radius); //fix me + break; + case TARGET_OBJECT_AREA_SRC: // fix me + case TARGET_OBJECT_AREA_DST: + break; + case TARGET_UNIT_AREA_ENTRY_SRC: + case TARGET_UNIT_AREA_ENTRY_DST: + case TARGET_UNIT_CONE_ENTRY: // fix me + { + SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); + SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); + if(lower == upper) + { + sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); + + if(IsPositiveEffect(m_spellInfo->Id, i)) + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ALLY); + else + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ENEMY); + } + // let it be done in one check? + else + { + for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST) + { + if(i_spellST->second.type == SPELL_TARGET_TYPE_CREATURE) + SearchAreaTarget(unitList, radius, PUSH_DST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry); + } + } + break; + } + case TARGET_UNIT_PARTY_TARGET: + m_targets.getUnitTarget()->GetPartyMember(unitList, radius); + break; + case TARGET_UNIT_PARTY_CASTER: + m_caster->GetPartyMember(unitList, radius); + break; + case TARGET_UNIT_RAID_CASTER: + m_caster->GetRaidMember(unitList, radius); + break; + case TARGET_UNIT_CLASS_TARGET: + { + Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER + ? (Player*)m_targets.getUnitTarget() : NULL; + + Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL; + if(pGroup) + { + for(GroupReference *itr = pGroup->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, i); + } + } + } + else if(m_targets.getUnitTarget()) + AddUnitTarget(m_targets.getUnitTarget(), i); + break; + } + } + + if(!unitList.empty()) + { + if(m_spellValue->MaxAffectedTargets) + { + if(m_spellInfo->Id == 5246) //Intimidating Shout + unitList.remove(m_targets.getUnitTarget()); + + Trinity::RandomResizeList(unitList, m_spellValue->MaxAffectedTargets); + } + + for(std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) + AddUnitTarget(*itr, i); + } + } // Chain or Area } void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura) @@ -2425,8 +2463,8 @@ void Spell::_handle_immediate_phase() { if(spellmgr.EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_DEST) { - if(!m_targets.HasDest()) - m_targets.setDestination(m_caster, false); + if(!m_targets.HasDst()) + m_targets.setDestination(m_caster); HandleEffects(m_originalCaster, NULL, NULL, j); } else if(spellmgr.EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_NONE) @@ -3409,7 +3447,7 @@ uint8 Spell::CanCast(bool strict) // check pet presents for(int j=0;j<3;j++) { - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_PET) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_PET) { target = m_caster->GetPet(); if(!target) @@ -3519,15 +3557,15 @@ uint8 Spell::CanCast(bool strict) { for(uint8 j = 0; j < 3; j++) { - if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF || - m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + if( m_spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_UNIT_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetA[j] != TARGET_UNIT_CASTER || + m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id); SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); if(lower==upper) - sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id); + sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_UNIT_NEARBY_ENTRY or TARGET_DST_NEARBY_ENTRY, but does not have record in `spell_script_target`",m_spellInfo->Id); SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); float range = GetSpellMaxRange(srange); @@ -3608,31 +3646,31 @@ uint8 Spell::CanCast(bool strict) if(creatureScriptTarget) { - // store coordinates for TARGET_SCRIPT_COORDINATES - if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + // store coordinates for TARGET_DST_NEARBY_ENTRY + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) AddUnitTarget(creatureScriptTarget, j); } - // store explicit target for TARGET_SCRIPT + // store explicit target for TARGET_UNIT_NEARBY_ENTRY else AddUnitTarget(creatureScriptTarget, j); } else if(goScriptTarget) { - // store coordinates for TARGET_SCRIPT_COORDINATES - if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + // store coordinates for TARGET_DST_NEARBY_ENTRY + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) AddGOTarget(goScriptTarget, j); } - // store explicit target for TARGET_SCRIPT + // store explicit target for TARGET_UNIT_NEARBY_ENTRY else AddGOTarget(goScriptTarget, j); } @@ -3708,7 +3746,7 @@ uint8 Spell::CanCast(bool strict) } case SPELL_EFFECT_LEARN_SPELL: { - if(m_spellInfo->EffectImplicitTargetA[i] != TARGET_PET) + if(m_spellInfo->EffectImplicitTargetA[i] != TARGET_UNIT_PET) break; Pet* pet = m_caster->GetPet(); @@ -4224,7 +4262,7 @@ int16 Spell::PetCanCast(Unit* target) bool need = false; for(uint32 i = 0;i<3;i++) { - if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES) + if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ENEMY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ALLY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ANY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DST_TARGET_ENEMY) { need = true; if(!target) @@ -4584,8 +4622,8 @@ uint8 Spell::CheckItems() uint8 failReason = 0; for (int i = 0; i < 3; i++) { - // skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster - if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_PET) + // skip check, pet not required like checks, and for TARGET_UNIT_PET m_targets.getUnitTarget() is not the real target but the caster + if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_PET) continue; if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL) @@ -5063,10 +5101,10 @@ CurrentSpellTypes Spell::GetCurrentContainer() return(CURRENT_GENERIC_SPELL); } -bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase ) +bool Spell::CheckTarget(Unit* target, uint32 eff) { // Check targets for creature type mask and remove not appropriate (skip explicit self target case, maybe need other explicit targets) - if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_SELF) + if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_UNIT_CASTER) { if (!CheckTargetCreatureType(target)) return false; @@ -5080,11 +5118,11 @@ bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase ) if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return false; - // unselectable targets skipped in all cases except TARGET_SCRIPT targeting - // in case TARGET_SCRIPT target selected by server always and can't be cheated + // unselectable targets skipped in all cases except TARGET_UNIT_NEARBY_ENTRY targeting + // in case TARGET_UNIT_NEARBY_ENTRY target selected by server always and can't be cheated /*if( target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) && - m_spellInfo->EffectImplicitTargetA[eff] != TARGET_SCRIPT && - m_spellInfo->EffectImplicitTargetB[eff] != TARGET_SCRIPT ) + m_spellInfo->EffectImplicitTargetA[eff] != TARGET_UNIT_NEARBY_ENTRY && + m_spellInfo->EffectImplicitTargetB[eff] != TARGET_UNIT_NEARBY_ENTRY ) return false;*/ } diff --git a/src/game/Spell.h b/src/game/Spell.h index 824450061d3..346dc421e2d 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -75,11 +75,14 @@ enum SpellRangeFlag enum SpellNotifyPushType { + PUSH_NONE = 0, PUSH_IN_FRONT, PUSH_IN_BACK, PUSH_IN_LINE, - PUSH_DEST_CENTER, - PUSH_TARGET_CENTER, + PUSH_SRC_CENTER, + PUSH_DST_CENTER, + PUSH_CASTER_CENTER, + PUSH_CHAIN, }; bool IsQuestTameSpell(uint32 spellId); @@ -111,28 +114,30 @@ class SpellCastTargets m_itemTargetEntry = target.m_itemTargetEntry; - //m_srcX = target.m_srcX; - //m_srcY = target.m_srcY; - //m_srcZ = target.m_srcZ; + m_srcX = target.m_srcX; + m_srcY = target.m_srcY; + m_srcZ = target.m_srcZ; - m_mapId = -1; m_destX = target.m_destX; m_destY = target.m_destY; m_destZ = target.m_destZ; - m_hasDest = target.m_hasDest; m_strTarget = target.m_strTarget; m_targetMask = target.m_targetMask; + m_mapId = -1; + return *this; } uint64 getUnitTargetGUID() const { return m_unitTargetGUID; } Unit *getUnitTarget() const { return m_unitTarget; } void setUnitTarget(Unit *target); - void setDestination(float x, float y, float z, bool send = true, int32 mapId = -1); - void setDestination(Unit *target, bool send = true); + void setSrc(float x, float y, float z); + void setSrc(WorldObject *target); + void setDestination(float x, float y, float z, int32 mapId = -1); + void setDestination(WorldObject *target); uint64 getGOTargetGUID() const { return m_GOTargetGUID; } GameObject *getGOTarget() const { return m_GOTarget; } @@ -154,14 +159,14 @@ class SpellCastTargets } bool IsEmpty() const { return m_GOTargetGUID==0 && m_unitTargetGUID==0 && m_itemTarget==0 && m_CorpseTargetGUID==0; } - bool HasDest() const { return m_hasDest; } + bool HasSrc() const { return m_targetMask & TARGET_FLAG_SOURCE_LOCATION; } + bool HasDst() const { return m_targetMask & TARGET_FLAG_DEST_LOCATION; } void Update(Unit* caster); float m_srcX, m_srcY, m_srcZ; - int32 m_mapId; float m_destX, m_destY, m_destZ; - bool m_hasDest; + int32 m_mapId; std::string m_strTarget; uint32 m_targetMask; @@ -368,10 +373,13 @@ class Spell void WriteAmmoToPacket( WorldPacket * data ); void FillTargetMap(); - void SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap); + void SetTargetMap(uint32 i, uint32 cur); Unit* SelectMagnetTarget(); - bool CheckTarget( Unit* target, uint32 eff, bool hitPhase ); + bool CheckTarget(Unit* target, uint32 eff); + + void CheckSrc() { if(!m_targets.HasSrc()) m_targets.setSrc(m_caster); } + void CheckDst() { if(!m_targets.HasDst()) m_targets.setDestination(m_caster); } void SendCastResult(uint8 result); void SendSpellStart(); @@ -547,11 +555,9 @@ class Spell void DoAllEffectOnTarget(GOTargetInfo *target); void DoAllEffectOnTarget(ItemTargetInfo *target); bool IsAliveUnitPresentInTargetList(); - void SearchAreaTarget(std::list<Unit*> &data, float radius, const uint32 &type, - SpellTargets TargetType, uint32 entry = 0); - void SearchChainTarget(std::list<Unit*> &data, float radius, uint32 unMaxTargets, - SpellTargets TargetType); - Unit* SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry = 0); + void SearchAreaTarget(std::list<Unit*> &unitList, float radius, const uint32 type, SpellTargets TargetType, uint32 entry = 0); + void SearchChainTarget(std::list<Unit*> &unitList, float radius, uint32 unMaxTargets, SpellTargets TargetType); + WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType); bool IsValidSingleTargetEffect(Unit const* target, Targets type) const; bool IsValidSingleTargetSpell(Unit const* target) const; void CalculateDamageDoneForAllTargets(); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index e0589918dad..dd6169c3b3c 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1960,7 +1960,7 @@ void Spell::EffectTriggerSpell(uint32 i) bool instant = false; for(uint32 j = i+1; j < 3; ++j) { - if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF) + if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_UNIT_CASTER) { instant = true; break; @@ -2007,7 +2007,7 @@ void Spell::EffectTeleportUnits(uint32 i) return; // If not exist data for dest location - return - if(!m_targets.HasDest()) + if(!m_targets.HasDst()) { sLog.outError( "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id ); return; @@ -2031,7 +2031,7 @@ void Spell::EffectTeleportUnits(uint32 i) unitTarget->SendMessageToSet(&data, false); } - // post effects for TARGET_TABLE_X_Y_Z_COORDINATES + // post effects for TARGET_DST_DB switch ( m_spellInfo->Id ) { // Dimensional Ripper - Everlook @@ -5463,7 +5463,7 @@ void Spell::EffectMomentMove(uint32 i) if(unitTarget->isInFlight()) return; - if(!m_targets.HasDest()) + if(!m_targets.HasDst()) return; uint32 mapid = m_caster->GetMapId(); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 25c68da03d6..4682faf1ab8 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -98,35 +98,64 @@ SpellMgr::SpellMgr() case TARGET_UNIT_MASTER: case TARGET_UNIT_PET: case TARGET_UNIT_PARTY_CASTER: - case TARGET_UNIT_RAID: + case TARGET_UNIT_RAID_CASTER: SpellTargetType[i] = TARGET_TYPE_UNIT_CASTER; break; case TARGET_UNIT_MINIPET: case TARGET_UNIT_TARGET_ALLY: case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_ANY: - case TARGET_UNIT_SINGLE_UNKNOWN: case TARGET_UNIT_TARGET_ENEMY: case TARGET_UNIT_TARGET_PARTY: case TARGET_UNIT_PARTY_TARGET: + case TARGET_UNIT_CLASS_TARGET: case TARGET_UNIT_CHAINHEAL: SpellTargetType[i] = TARGET_TYPE_UNIT_TARGET; break; - case TARGET_UNIT_CHANNEL: - case TARGET_DEST_CHANNEL: - SpellTargetType[i] = TARGET_TYPE_CHANNEL; + case TARGET_UNIT_NEARBY_ENEMY: + case TARGET_UNIT_NEARBY_ALLY: + case TARGET_UNIT_NEARBY_ALLY_UNK: + case TARGET_UNIT_NEARBY_ENTRY: + case TARGET_UNIT_NEARBY_RAID: + SpellTargetType[i] = TARGET_TYPE_UNIT_NEARBY; break; - case TARGET_UNIT_AREA_ENEMY_GROUND: - case TARGET_UNIT_AREA_ENEMY: - case TARGET_UNIT_AREA_ALLY_GROUND: - case TARGET_UNIT_AREA_ALLY: - case TARGET_UNIT_AREA_ENTRY_GROUND: - case TARGET_UNIT_AREA_ENTRY: - case TARGET_UNIT_AREA_PARTY_GROUND: - case TARGET_UNIT_AREA_PARTY: - SpellTargetType[i] = TARGET_TYPE_AREA_DEST; + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ALLY_SRC: + case TARGET_UNIT_AREA_ENTRY_SRC: + case TARGET_UNIT_AREA_PARTY_SRC: + case TARGET_OBJECT_AREA_SRC: + SpellTargetType[i] = TARGET_TYPE_AREA_SRC; break; - case TARGET_DEST_TARGET_ENEMY: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_AREA_ALLY_DST: + case TARGET_UNIT_AREA_ENTRY_DST: + case TARGET_UNIT_AREA_PARTY_DST: + case TARGET_OBJECT_AREA_DST: + SpellTargetType[i] = TARGET_TYPE_AREA_DST; + break; + case TARGET_UNIT_CONE_ENEMY: + case TARGET_UNIT_CONE_ALLY: + case TARGET_UNIT_CONE_ENTRY: + case TARGET_UNIT_CONE_ENEMY_UNKNOWN: + SpellTargetType[i] = TARGET_TYPE_AREA_CONE; + break; + case TARGET_DST_CASTER: + case TARGET_SRC_CASTER: + case TARGET_MINION: + case TARGET_DEST_CASTER_FRONT_LEAP: + case TARGET_DEST_CASTER_FRONT: + case TARGET_DEST_CASTER_BACK: + case TARGET_DEST_CASTER_RIGHT: + case TARGET_DEST_CASTER_LEFT: + case TARGET_DEST_CASTER_FRONT_LEFT: + case TARGET_DEST_CASTER_BACK_LEFT: + case TARGET_DEST_CASTER_BACK_RIGHT: + case TARGET_DEST_CASTER_FRONT_RIGHT: + case TARGET_DEST_CASTER_RANDOM: + case TARGET_DEST_CASTER_RADIUS: + SpellTargetType[i] = TARGET_TYPE_DEST_CASTER; + break; + case TARGET_DST_TARGET_ENEMY: case TARGET_DEST_TARGET_ANY: case TARGET_DEST_TARGET_FRONT: case TARGET_DEST_TARGET_BACK: @@ -140,25 +169,11 @@ SpellMgr::SpellMgr() case TARGET_DEST_TARGET_RADIUS: SpellTargetType[i] = TARGET_TYPE_DEST_TARGET; break; - case TARGET_DEST_CASTER_GROUND: - case TARGET_DEST_CASTER: - case TARGET_DEST_CASTER_FRONT_LEFT: - case TARGET_DEST_CASTER_BACK_LEFT: - case TARGET_DEST_CASTER_BACK_RIGHT: - case TARGET_DEST_CASTER_FRONT_RIGHT: - case TARGET_DEST_CASTER_FRONT: - case TARGET_MINION: - case TARGET_DEST_CASTER_FRONT_LEAP: - case TARGET_DEST_CASTER_BACK: - case TARGET_DEST_CASTER_RIGHT: - case TARGET_DEST_CASTER_LEFT: - case TARGET_DEST_CASTER_RANDOM: - case TARGET_DEST_CASTER_RADIUS: - SpellTargetType[i] = TARGET_TYPE_DEST_CASTER; - break; case TARGET_DEST_DYNOBJ_ENEMY: case TARGET_DEST_DYNOBJ_ALLY: + case TARGET_DEST_DYNOBJ_NONE: case TARGET_DEST_DEST: + case TARGET_DEST_TRAJ: case TARGET_DEST_DEST_FRONT_LEFT: case TARGET_DEST_DEST_BACK_LEFT: case TARGET_DEST_DEST_BACK_RIGHT: @@ -170,6 +185,15 @@ SpellMgr::SpellMgr() case TARGET_DEST_DEST_RANDOM: SpellTargetType[i] = TARGET_TYPE_DEST_DEST; break; + case TARGET_DST_DB: + case TARGET_DST_HOME: + case TARGET_DST_NEARBY_ENTRY: + SpellTargetType[i] = TARGET_TYPE_DEST_SPECIAL; + break; + case TARGET_UNIT_CHANNEL: + case TARGET_DEST_CHANNEL: + SpellTargetType[i] = TARGET_TYPE_CHANNEL; + break; default: SpellTargetType[i] = TARGET_TYPE_DEFAULT; } @@ -179,20 +203,20 @@ SpellMgr::SpellMgr() { switch(i) { - case TARGET_UNIT_AREA_ENEMY_GROUND: - case TARGET_UNIT_AREA_ENEMY: - case TARGET_UNIT_AREA_ALLY_GROUND: - case TARGET_UNIT_AREA_ALLY: - case TARGET_UNIT_AREA_ENTRY_GROUND: - case TARGET_UNIT_AREA_ENTRY: - case TARGET_UNIT_AREA_PARTY_GROUND: - case TARGET_UNIT_AREA_PARTY: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ALLY_DST: + case TARGET_UNIT_AREA_ALLY_SRC: + case TARGET_UNIT_AREA_ENTRY_DST: + case TARGET_UNIT_AREA_ENTRY_SRC: + case TARGET_UNIT_AREA_PARTY_DST: + case TARGET_UNIT_AREA_PARTY_SRC: case TARGET_UNIT_PARTY_TARGET: case TARGET_UNIT_PARTY_CASTER: case TARGET_UNIT_CONE_ENEMY: case TARGET_UNIT_CONE_ALLY: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: - case TARGET_UNIT_RAID: + case TARGET_UNIT_RAID_CASTER: IsAreaEffectTarget[i] = true; break; default: @@ -486,16 +510,16 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB) // non-positive targets switch(targetA) { - case TARGET_CHAIN_DAMAGE: - case TARGET_ALL_ENEMY_IN_AREA: - case TARGET_ALL_ENEMY_IN_AREA_INSTANT: - case TARGET_IN_FRONT_OF_CASTER: + case TARGET_UNIT_TARGET_ENEMY: + case TARGET_UNIT_AREA_ENEMY_SRC: + case TARGET_UNIT_AREA_ENEMY_DST: + case TARGET_UNIT_CONE_ENEMY: case TARGET_DEST_DYNOBJ_ENEMY: - case TARGET_CURRENT_ENEMY_COORDINATES: + case TARGET_DST_TARGET_ENEMY: case TARGET_UNIT_CHANNEL: return false; - case TARGET_ALL_AROUND_CASTER: - return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER); + case TARGET_SRC_CASTER: + return (targetB == TARGET_UNIT_AREA_PARTY_SRC || targetB == TARGET_UNIT_AREA_ALLY_SRC); default: break; } @@ -608,12 +632,12 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex) return false; case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. // part of negative spell if casted at self (prevent cancel) - if(spellproto->EffectImplicitTargetA[effIndex] == TARGET_SELF) + if(spellproto->EffectImplicitTargetA[effIndex] == TARGET_UNIT_CASTER) return false; break; case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also // part of positive spell if casted at self - if(spellproto->EffectImplicitTargetA[effIndex] != TARGET_SELF) + if(spellproto->EffectImplicitTargetA[effIndex] != TARGET_UNIT_CASTER) return false; // but not this if this first effect (don't found batter check) if(spellproto->Attributes & 0x4000000 && effIndex==0) @@ -864,7 +888,7 @@ void SpellMgr::LoadSpellTargetPositions() bool found = false; for(int i = 0; i < 3; ++i) { - if( spellInfo->EffectImplicitTargetA[i]==TARGET_TABLE_X_Y_Z_COORDINATES || spellInfo->EffectImplicitTargetB[i]==TARGET_TABLE_X_Y_Z_COORDINATES ) + if( spellInfo->EffectImplicitTargetA[i]==TARGET_DST_DB || spellInfo->EffectImplicitTargetB[i]==TARGET_DST_DB ) { found = true; break; @@ -872,7 +896,7 @@ void SpellMgr::LoadSpellTargetPositions() } if(!found) { - sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID); + sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_DST_DB (17).",Spell_ID); continue; } @@ -1931,10 +1955,10 @@ void SpellMgr::LoadSpellScriptTarget() /*bool targetfound = false; for(int i = 0; i <3; ++i) { - if( spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT || - spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT || - spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT_COORDINATES || - spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT_COORDINATES ) + if( spellProto->EffectImplicitTargetA[i]==TARGET_UNIT_NEARBY_ENTRY || + spellProto->EffectImplicitTargetB[i]==TARGET_UNIT_NEARBY_ENTRY || + spellProto->EffectImplicitTargetA[i]==TARGET_DST_NEARBY_ENTRY || + spellProto->EffectImplicitTargetB[i]==TARGET_DST_NEARBY_ENTRY ) { targetfound = true; break; @@ -1942,7 +1966,7 @@ void SpellMgr::LoadSpellScriptTarget() } if(!targetfound) { - sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_SCRIPT(38) or TARGET_SCRIPT_COORDINATES (46).",spellId,targetEntry); + sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DST_NEARBY_ENTRY (46).",spellId,targetEntry); continue; }*/ @@ -2008,13 +2032,13 @@ void SpellMgr::LoadSpellScriptTarget() bool found = false; for(int j=0; j<3; ++j) { - if( spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || spellInfo->EffectImplicitTargetA[j] != TARGET_SELF && spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT ) + if( spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_NEARBY_ENTRY || spellInfo->EffectImplicitTargetA[j] != TARGET_UNIT_CASTER && spellInfo->EffectImplicitTargetB[j] == TARGET_UNIT_NEARBY_ENTRY ) { SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(spellInfo->Id); SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(spellInfo->Id); if(lower==upper) { - sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = %u (TARGET_SCRIPT), but does not have record in `spell_script_target`",spellInfo->Id,TARGET_SCRIPT); + sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = %u (TARGET_UNIT_NEARBY_ENTRY), but does not have record in `spell_script_target`",spellInfo->Id,TARGET_UNIT_NEARBY_ENTRY); break; // effects of spell } } @@ -2091,7 +2115,7 @@ void SpellMgr::LoadSpellPetAuras() continue; } - PetAura pa(pet, aura, spellInfo->EffectImplicitTargetA[i] == TARGET_PET, spellInfo->EffectBasePoints[i] + spellInfo->EffectBaseDice[i]); + PetAura pa(pet, aura, spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_PET, spellInfo->EffectBasePoints[i] + spellInfo->EffectBaseDice[i]); mSpellPetAuraMap[spell] = pa; } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index f9d5cdd09f4..70b81403a52 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -248,11 +248,15 @@ enum SpellSelectTargetTypes TARGET_TYPE_DEFAULT, TARGET_TYPE_UNIT_CASTER, TARGET_TYPE_UNIT_TARGET, - TARGET_TYPE_CHANNEL, - TARGET_TYPE_AREA_DEST, + TARGET_TYPE_UNIT_NEARBY, + TARGET_TYPE_AREA_SRC, + TARGET_TYPE_AREA_DST, + TARGET_TYPE_AREA_CONE, TARGET_TYPE_DEST_CASTER, TARGET_TYPE_DEST_TARGET, TARGET_TYPE_DEST_DEST, + TARGET_TYPE_DEST_SPECIAL, + TARGET_TYPE_CHANNEL, }; //Some SpellFamilyFlags diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b87ba3c19fc..c9769cf89f2 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -11064,7 +11064,7 @@ void CharmInfo::InitCharmCreateSpells() if(!spellInfo) onlyselfcast = false; for(uint32 i = 0;i<3 && onlyselfcast;++i) //non existent spell will not make any problems as onlyselfcast would be false -> break right away { - if(spellInfo->EffectImplicitTargetA[i] != TARGET_SELF && spellInfo->EffectImplicitTargetA[i] != 0) + if(spellInfo->EffectImplicitTargetA[i] != TARGET_UNIT_CASTER && spellInfo->EffectImplicitTargetA[i] != 0) onlyselfcast = false; } |