diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 8d3612cbf4..60acd2781d 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1925,6 +1925,11 @@ bool Creature::CanStartAttack(Unit const* who, bool force) const if (!_IsTargetAcceptable(who)) return false; + // Totems never pull proximity aggro; they are only attacked in response + // to threat they generate themselves (e.g. Searing Totem) + if (who->IsTotem()) + return false; + if (IsNeutralToAll() || !IsWithinDistInMap(who, GetAggroRange(who) + m_CombatDistance, true, false, false)) return false; } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 8a0eebffce..7ff045e0b6 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2337,8 +2337,9 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert summon->InitSummon(); - // call MoveInLineOfSight for nearby creatures - Acore::AIRelocationNotifier notifier(*summon); + // call MoveInLineOfSight for nearby players and creatures; players are visited + // first (grid typelist order) so aggressive summons prefer them over pets/totems + Acore::AIRelocationNotifier notifier(*summon, true); Cell::VisitObjects(summon, notifier, GetVisibilityRange()); return summon; diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index 28f87f2863..e38c8030c9 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -186,6 +186,19 @@ void AIRelocationNotifier::Visit(CreatureMapType& m) } } +void AIRelocationNotifier::Visit(PlayerMapType& m) +{ + if (!includePlayers) + return; + + Creature* creature = i_unit.ToCreature(); + if (!creature || creature->IsMoveInLineOfSightStrictlyDisabled()) + return; + + for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + CreatureUnitRelocationWorker(creature, iter->GetSource()); +} + // Uses visibility map void MessageDistDeliverer::Visit(VisiblePlayersMap const& m) { diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 8484eb3b57..1f078197f6 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -91,9 +91,11 @@ namespace Acore { Unit& i_unit; bool isCreature; - explicit AIRelocationNotifier(Unit& unit) : i_unit(unit), isCreature(unit.IsCreature()) {} + bool includePlayers; + explicit AIRelocationNotifier(Unit& unit, bool includePlayers = false) : i_unit(unit), isCreature(unit.IsCreature()), includePlayers(includePlayers) {} template void Visit(GridRefMgr&) {} void Visit(CreatureMapType&); + void Visit(PlayerMapType&); }; enum class TeamFilter