diff options
-rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.cpp | 68 | ||||
-rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.h | 26 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 23 |
3 files changed, 116 insertions, 1 deletions
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index 51534f1b9f7..0d303268569 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -319,6 +319,74 @@ void MessageDistDeliverer::Visit(DynamicObjectMapType &m) } } +void MessageDistDelivererToHostile::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Player* target = iter->GetSource(); + if (!target->IsInPhase(i_source)) + continue; + + if (target->GetExactDist2dSq(i_source) > i_distSq) + continue; + + // Send packet to all who are sharing the player's vision + if (target->HasSharedVision()) + { + SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); + for (; i != target->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == target) + SendPacket(*i); + } + + if (target->m_seer == target || target->GetVehicle()) + SendPacket(target); + } +} + +void MessageDistDelivererToHostile::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Creature* target = iter->GetSource(); + if (!target->IsInPhase(i_source)) + continue; + + if (target->GetExactDist2dSq(i_source) > i_distSq) + continue; + + // Send packet to all who are sharing the creature's vision + if (target->HasSharedVision()) + { + SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); + for (; i != target->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == target) + SendPacket(*i); + } + } +} + +void MessageDistDelivererToHostile::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + DynamicObject* target = iter->GetSource(); + if (!target->IsInPhase(i_source)) + continue; + + if (target->GetExactDist2dSq(i_source) > i_distSq) + continue; + + if (Unit* caster = target->GetCaster()) + { + // Send packet back to the caster if the caster has vision of dynamic object + Player* player = caster->ToPlayer(); + if (player && player->m_seer == target) + SendPacket(player); + } + } +} + /* void MessageDistDeliverer::VisitObject(Player* player) diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index da6318c8455..3a918a3fe18 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -153,6 +153,32 @@ namespace Trinity } }; + struct TC_GAME_API MessageDistDelivererToHostile + { + Unit* i_source; + WorldPacket const* i_message; + float i_distSq; + + MessageDistDelivererToHostile(Unit* src, WorldPacket const* msg, float dist) + : i_source(src), i_message(msg), i_distSq(dist * dist) + { + } + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(DynamicObjectMapType &m); + template<class SKIP> void Visit(GridRefManager<SKIP> &) { } + + void SendPacket(Player* player) + { + // never send packet to self + if (player == i_source || !player->HaveAtClient(i_source) || player->IsFriendlyTo(i_source)) + return; + + player->SendDirectMessage(i_message); + } + }; + struct ObjectUpdater { uint32 i_timeDiff; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 9a93e2358a5..2abc32d1619 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -22,6 +22,7 @@ #include "Battleground.h" #include "BattlegroundMgr.h" #include "BattlePetMgr.h" +#include "CellImpl.h" #include "CombatLogPackets.h" #include "CombatPackets.h" #include "Common.h" @@ -36,6 +37,7 @@ #include "GameObjectAI.h" #include "Garrison.h" #include "GossipDef.h" +#include "GridNotifiers.h" #include "Group.h" #include "Guild.h" #include "InstanceScript.h" @@ -4089,9 +4091,28 @@ void Spell::EffectForceDeselect(SpellEffIndex /*effIndex*/) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; + float dist = m_caster->GetVisibilityRange(); + + // clear focus + WorldPackets::Combat::BreakTarget breakTarget; + breakTarget.UnitGUID = m_caster->GetGUID(); + Trinity::MessageDistDelivererToHostile notifierBreak(m_caster, breakTarget.Write(), dist); + Cell::VisitWorldObjects(m_caster, notifierBreak, dist); + + // and selection WorldPackets::Spells::ClearTarget clearTarget; clearTarget.Guid = m_caster->GetGUID(); - m_caster->SendMessageToSet(clearTarget.Write(), true); + Trinity::MessageDistDelivererToHostile notifierClear(m_caster, clearTarget.Write(), dist); + Cell::VisitWorldObjects(m_caster, notifierClear, dist); + + // we should also force pets to remove us from current target + Unit::AttackerSet attackerSet; + for (Unit::AttackerSet::const_iterator itr = m_caster->getAttackers().begin(); itr != m_caster->getAttackers().end(); ++itr) + if ((*itr)->GetTypeId() == TYPEID_UNIT && !(*itr)->CanHaveThreatList()) + attackerSet.insert(*itr); + + for (Unit::AttackerSet::const_iterator itr = attackerSet.begin(); itr != attackerSet.end(); ++itr) + (*itr)->AttackStop(); } void Spell::EffectSelfResurrect(SpellEffIndex /*effIndex*/) |