diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 93e34636e6..64f0d4391e 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1623,40 +1623,47 @@ bool Creature::CheckNoGrayAggroConfig(uint32 playerLevel, uint32 creatureLevel) float Creature::GetAttackDistance(Unit const* player) const { + // WoW Wiki: the minimum radius seems to be 5 yards, while the maximum range is 45 yards + float maxRadius = (45.0f * sWorld->getRate(RATE_CREATURE_AGGRO)); + float minRadius = (5.0f * sWorld->getRate(RATE_CREATURE_AGGRO)); float aggroRate = sWorld->getRate(RATE_CREATURE_AGGRO); - if (aggroRate == 0) + uint8 expansionMaxLevel = uint8(GetMaxLevelForExpansion(GetCreatureTemplate()->expansion)); + + uint32 playerLevel = player->getLevel(); + uint32 creatureLevel = getLevel(); + + if (aggroRate == 0.0f) return 0.0f; - uint32 playerlevel = player->getLevelForTarget(this); - uint32 creaturelevel = getLevelForTarget(player); + // The aggro radius for creatures with equal level as the player is 20 yards. + // The combatreach should not get taken into account for the distance so we drop it from the range (see Supremus as expample) + float baseAggroDistance = 20.0f - GetCombatReach(); + float aggroRadius = baseAggroDistance; - int32 leveldif = int32(playerlevel) - int32(creaturelevel); - - // "The maximum Aggro Radius has a cap of 25 levels under. Example: A level 30 char has the same Aggro Radius of a level 5 char on a level 60 mob." - if (leveldif < - 25) - leveldif = -25; - - // "The aggro radius of a mob having the same level as the player is roughly 20 yards" - float RetDistance = 20; - - // "Aggro Radius varies with level difference at a rate of roughly 1 yard/level" - // radius grow if playlevel < creaturelevel - RetDistance -= (float)leveldif; - - if (creaturelevel+5 <= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) + // detect range auras + if ((creatureLevel + 5) <= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { - // detect range auras - RetDistance += GetTotalAuraModifier(SPELL_AURA_MOD_DETECT_RANGE); + aggroRadius += GetTotalAuraModifier(SPELL_AURA_MOD_DETECT_RANGE); - // detected range auras - RetDistance += player->GetTotalAuraModifier(SPELL_AURA_MOD_DETECTED_RANGE); + aggroRadius += player->GetTotalAuraModifier(SPELL_AURA_MOD_DETECTED_RANGE); } - // "Minimum Aggro Radius for a mob seems to be combat range (5 yards)" - if (RetDistance < 5) - RetDistance = 5; + // The aggro range of creatures with higher levels than the total player level for the expansion should get the maxlevel treatment + // This makes sure that creatures such as bosses wont have a bigger aggro range than the rest of the npc's + // The following code is used for blizzlike behavior such as skipable bosses (e.g. Commander Springvale at level 85) + if (creatureLevel > expansionMaxLevel) + aggroRadius += float(expansionMaxLevel) - float(playerLevel); + // + - 1 yard for each level difference between player and creature + else + aggroRadius += float(creatureLevel) - float(playerLevel); - return (RetDistance*aggroRate); + // Make sure that we wont go over the total range limits + if (aggroRadius > maxRadius) + aggroRadius = maxRadius; + else if (aggroRadius < minRadius) + aggroRadius = minRadius; + + return (aggroRadius * aggroRate); } void Creature::setDeathState(DeathState s)