Skip to content

Commit

Permalink
Core/Creature: Reworked creature aggro radius calculation (#20615)
Browse files Browse the repository at this point in the history
* Core/Creatures: rewrote creature aggro radius calculation
* Formulas are taken from WoW Wiki
  • Loading branch information
Ovahlord authored and Shauren committed Nov 15, 2017
1 parent 434380c commit ea99801
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 48 deletions.
52 changes: 28 additions & 24 deletions src/server/game/Entities/Creature/Creature.cpp
Expand Up @@ -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();

This comment has been minimized.

Copy link
@funjoker

funjoker Nov 16, 2017

Member

What about Scaling Creatures?
Would be GetLevelForTarget(player) a better way than getLevel() ?


uint32 playerlevel = player->GetLevelForTarget(this);
uint32 creaturelevel = GetLevelForTarget(player);
if (aggroRate == 0.0f)
return 0.0;

This comment has been minimized.

Copy link
@Ovahlord

Ovahlord Nov 16, 2017

Author Contributor

whoopsie. this will probably cause a warning.


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());

// Make sure that we wont go over the total range limits
if (aggroRadius > maxRadius)
aggroRadius = maxRadius;
else if (aggroRadius < minRadius)
aggroRadius = minRadius;

return (RetDistance*aggroRate);
return (aggroRadius * aggroRate);
}

void Creature::setDeathState(DeathState s)
Expand Down
24 changes: 0 additions & 24 deletions src/server/game/Handlers/ReferAFriendHandler.cpp
Expand Up @@ -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);
Expand Down
24 changes: 24 additions & 0 deletions src/server/game/Miscellaneous/SharedDefines.h
Expand Up @@ -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,
Expand Down

0 comments on commit ea99801

Please sign in to comment.