Core/Creature: Reworked creature aggro radius calculation (#20615)

* Core/Creatures: rewrote creature aggro radius calculation
* Formulas are taken from WoW Wiki
This commit is contained in:
Ovah
2017-11-15 21:56:15 +01:00
committed by Shauren
parent 434380c9ac
commit ea99801cd6
3 changed files with 52 additions and 48 deletions

View File

@@ -1646,40 +1646,44 @@ 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)
return 0.0f;
uint8 expansionMaxLevel = uint8(GetMaxLevelForExpansion(GetCreatureTemplate()->RequiredExpansion));
int32 levelDifference = getLevel() - player->getLevel();
uint32 playerlevel = player->GetLevelForTarget(this);
uint32 creaturelevel = GetLevelForTarget(player);
if (aggroRate == 0.0f)
return 0.0;
int32 leveldif = int32(playerlevel) - int32(creaturelevel);
// 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 - GetFloatValue(UNIT_FIELD_COMBATREACH);
// "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;
// + - 1 yard for each level difference between player and creature
float aggroRadius = baseAggroDistance + float(levelDifference);
// "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 (float(getLevel() + 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 += 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 behaivior such as skipable bosses (e.g. Commander Springvale at level 85)
if (getLevel() > expansionMaxLevel)
aggroRadius = baseAggroDistance + float(expansionMaxLevel - player->getLevel());
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)

View File

@@ -22,30 +22,6 @@
#include "ReferAFriendPackets.h"
#include "World.h"
inline uint32 GetMaxLevelForExpansion(uint32 expansion)
{
switch (expansion)
{
case EXPANSION_CLASSIC:
return 60;
case EXPANSION_THE_BURNING_CRUSADE:
return 70;
case EXPANSION_WRATH_OF_THE_LICH_KING:
return 80;
case EXPANSION_CATACLYSM:
return 85;
case EXPANSION_MISTS_OF_PANDARIA:
return 90;
case EXPANSION_WARLORDS_OF_DRAENOR:
return 100;
case EXPANSION_LEGION:
return 110;
default:
break;
}
return 0;
}
void WorldSession::HandleGrantLevel(WorldPackets::RaF::GrantLevel& grantLevel)
{
Player* target = ObjectAccessor::GetPlayer(*_player, grantLevel.Target);

View File

@@ -90,6 +90,30 @@ enum Expansions
#define CURRENT_EXPANSION EXPANSION_LEGION
inline uint32 GetMaxLevelForExpansion(uint32 expansion)
{
switch (expansion)
{
case EXPANSION_CLASSIC:
return 60;
case EXPANSION_THE_BURNING_CRUSADE:
return 70;
case EXPANSION_WRATH_OF_THE_LICH_KING:
return 80;
case EXPANSION_CATACLYSM:
return 85;
case EXPANSION_MISTS_OF_PANDARIA:
return 90;
case EXPANSION_WARLORDS_OF_DRAENOR:
return 100;
case EXPANSION_LEGION:
return 110;
default:
break;
}
return 0;
}
enum Gender
{
GENDER_UNKNOWN = -1,