Core/Units: Drop hostile world references that are out of our sight (fixes combat bug) (#18591)

(cherry-picked from ba6281bf42)
This commit is contained in:
xinef1
2017-01-21 14:46:32 +01:00
committed by Shauren
parent 46c69df3a7
commit 8573b651c8
5 changed files with 42 additions and 0 deletions

View File

@@ -50,6 +50,11 @@ bool PetAI::_needToStop()
if (me->IsCharmed() && me->GetVictim() == me->GetCharmer())
return true;
// dont allow pets to follow targets far away from owner
if (Unit* owner = me->GetCharmerOrOwner())
if (owner->GetExactDist(me) >= (owner->GetVisibilityRange()-10.0f))
return true;
return !me->IsValidAttackTarget(me->GetVictim());
}

View File

@@ -141,6 +141,26 @@ void HostileRefManager::deleteReferencesForFaction(uint32 faction)
}
}
//=================================================
// delete all references out of specified range
void HostileRefManager::deleteReferencesOutOfRange(float range)
{
HostileReference* ref = getFirst();
range = range*range;
while (ref)
{
HostileReference* nextRef = ref->next();
Unit* owner = ref->GetSource()->GetOwner();
if (!owner->isActiveObject() && owner->GetExactDist2dSq(GetOwner()) > range)
{
ref->removeReference();
delete ref;
}
ref = nextRef;
}
}
//=================================================
// delete one reference, defined by Unit

View File

@@ -53,6 +53,9 @@ class TC_GAME_API HostileRefManager : public RefManager<Unit, ThreatManager>
// Remove specific faction references
void deleteReferencesForFaction(uint32 faction);
// for combat bugs
void deleteReferencesOutOfRange(float range);
HostileReference* getFirst() { return ((HostileReference*) RefManager<Unit, ThreatManager>::getFirst()); }
void updateThreatTables();

View File

@@ -210,6 +210,7 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
m_MirrorTimerFlags = UNDERWATER_NONE;
m_MirrorTimerFlagsLast = UNDERWATER_NONE;
m_isInWater = false;
m_hostileReferenceCheckTimer = 0;
m_drunkTimer = 0;
m_deathTimer = 0;
m_deathExpireTime = 0;
@@ -1348,6 +1349,18 @@ void Player::Update(uint32 p_time)
//if (pet && !pet->IsWithinDistInMap(this, GetMap()->GetVisibilityDistance()) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID())))
RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true);
if (IsAlive())
{
if (m_hostileReferenceCheckTimer <= p_time)
{
m_hostileReferenceCheckTimer = 15 * IN_MILLISECONDS;
if (!GetMap()->IsDungeon())
getHostileRefManager().deleteReferencesOutOfRange(GetVisibilityRange());
}
else
m_hostileReferenceCheckTimer -= p_time;
}
//we should execute delayed teleports only for alive(!) players
//because we don't want player's ghost teleported from graveyard
if (IsHasDelayedTeleport() && IsAlive())

View File

@@ -2593,6 +2593,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool m_SeasonalQuestChanged;
time_t m_lastDailyQuestTime;
uint32 m_hostileReferenceCheckTimer;
uint32 m_drunkTimer;
uint32 m_weaponChangeTimer;