Core/Combat: Fix Evade Mechanics

- Can now kite mobs beyond ThreatRadius (CONF) if continuing to damage them. World bosses still use ThreatRadius to prevent pulling them to cities
- A mob that is beyond the ThreatRadius, it will return home (evade) after 10 seconds of no damage if there are no valid targets within attack distance of it, otherwise it will still attack
- Mobs now properly report "Evade" if attacked while returning home.

(modified - Nayd)

Closes #830
Closes #7748
This commit is contained in:
MrSmite
2012-09-22 02:11:31 +01:00
committed by Nay
parent 53cd8cf684
commit ce6785d9db
3 changed files with 28 additions and 0 deletions

View File

@@ -153,13 +153,20 @@ void CreatureAI::EnterEvadeMode()
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
}
else
{
// Required to prevent attacking creatures that are evading and cause them to reenter combat
// Does not apply to MoveFollow
me->AddUnitState(UNIT_STATE_EVADE);
me->GetMotionMaster()->MoveTargetedHome();
}
}
Reset();
if (me->IsVehicle()) // use the same sequence of addtoworld, aireset may remove all summons!
me->GetVehicleKit()->Reset(true);
me->SetLastDamagedTime(0);
}
/*void CreatureAI::AttackedBy(Unit* attacker)

View File

@@ -173,6 +173,7 @@ Unit::Unit(bool isWorldObject): WorldObject(isWorldObject)
, m_vehicleKit(NULL)
, m_unitTypeMask(UNIT_MASK_NONE)
, m_HostileRefManager(this)
, _lastDamagedTime(0)
{
#ifdef _MSC_VER
#pragma warning(default:4355)
@@ -12416,6 +12417,10 @@ int32 Unit::ModifyHealth(int32 dVal)
if (dVal == 0)
return 0;
// Part of Evade mechanics. Only track health lost, not gained.
if (dVal < 0 && GetTypeId() != TYPEID_PLAYER && !isPet())
SetLastDamagedTime(time(NULL));
int32 curHealth = (int32)GetHealth();
int32 val = dVal + curHealth;
@@ -13042,6 +13047,14 @@ Unit* Creature::SelectVictim()
return target;
}
// Case where mob is being kited.
// Mob may not be in range to attack or may have dropped target. In any case,
// don't evade if damage received within the last 10 seconds
// Does not apply to world bosses to prevent kiting to cities
if (!isWorldBoss() && !GetInstanceId())
if (time(NULL) - GetLastDamagedTime() <= MAX_AGGRO_RESET_TIME)
return target;
// last case when creature must not go to evade mode:
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
// for example at owner command to pet attack some far away creature

View File

@@ -262,6 +262,8 @@ enum UnitRename
#define MAX_SPELL_POSSESS 8
#define MAX_SPELL_CONTROL_BAR 10
#define MAX_AGGRO_RESET_TIME 10 // in seconds
enum Swing
{
NOSWING = 0,
@@ -2218,6 +2220,10 @@ class Unit : public WorldObject
// Movement info
Movement::MoveSpline * movespline;
// Part of Evade mechanics
time_t GetLastDamagedTime() const { return _lastDamagedTime; }
void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; }
protected:
explicit Unit (bool isWorldObject);
@@ -2339,6 +2345,8 @@ class Unit : public WorldObject
Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing
bool _isWalkingBeforeCharm; // Are we walking before we were charmed?
time_t _lastDamagedTime; // Part of Evade mechanics
};
namespace Trinity