I took the liberty of updating this patch for the recent commit fixing the typo 'hostil.' So far, it seems to work fine for me.
diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp
index a058a8f..805dbaf 100644
--- a/src/game/ThreatManager.cpp
+++ b/src/game/ThreatManager.cpp
@@ -212,6 +212,9 @@ void ThreatContainer::clearReferences()
HostileReference* ThreatContainer::getReferenceByTarget(Unit* pVictim)
{
HostileReference* result = NULL;
+ if(!pVictim)
+ return NULL;
+
uint64 guid = pVictim->GetGUID();
for(std::list<HostileReference*>::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i)
{
@@ -342,7 +345,7 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostileRe
//=================== ThreatManager ==========================
//============================================================
-ThreatManager::ThreatManager(Unit* owner) : iCurrentVictim(NULL), iOwner(owner)
+ThreatManager::ThreatManager(Unit* owner) : iCurrentVictim(NULL), iOwner(owner), iUpdateTimer(THREAT_UPDATE_INTERVAL)
{
}
@@ -353,6 +356,7 @@ void ThreatManager::clearReferences()
iThreatContainer.clearReferences();
iThreatOfflineContainer.clearReferences();
iCurrentVictim = NULL;
+ iUpdateTimer = THREAT_UPDATE_INTERVAL;
}
//============================================================
@@ -452,6 +456,10 @@ void ThreatManager::tauntFadeOut(Unit *pTaunter)
void ThreatManager::setCurrentVictim(HostileReference* pHostileReference)
{
+ if (pHostileReference && pHostileReference != iCurrentVictim)
+ {
+ iOwner->SendChangeCurrentVictimOpcode(pHostileReference);
+ }
iCurrentVictim = pHostileReference;
}
@@ -497,6 +505,7 @@ void ThreatManager::ProcessThreatEvent(ThreatRefStatusChangeEvent* threatRefStat
setCurrentVictim(NULL);
setDirty(true);
}
+ iOwner->SendRemoveFromThreatListOpcode(hostileReference);
if(hostileReference->isOnline())
iThreatContainer.remove(hostileReference);
else
@@ -504,3 +513,16 @@ void ThreatManager::ProcessThreatEvent(ThreatRefStatusChangeEvent* threatRefStat
break;
}
}
+
+bool ThreatManager::isNeedUpdateToClient(uint32 time)
+{
+ if (isThreatListEmpty())
+ return false;
+ if (time >= iUpdateTimer)
+ {
+ iUpdateTimer = THREAT_UPDATE_INTERVAL;
+ return true;
+ }
+ iUpdateTimer -= time;
+ return false;
+}
diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h
index d569480..efc753b 100644
--- a/src/game/ThreatManager.h
+++ b/src/game/ThreatManager.h
@@ -33,6 +33,8 @@ class Creature;
class ThreatManager;
struct SpellEntry;
+#define THREAT_UPDATE_INTERVAL 1 * IN_MILISECONDS // Server should send threat update to client periodically each second
+
//==============================================================
// Class to calculate the real threat based
@@ -185,6 +187,8 @@ class MANGOS_DLL_SPEC ThreatManager
void processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusChangeEvent);
+ bool isNeedUpdateToClient(uint32 time);
+
HostileReference* getCurrentVictim() { return iCurrentVictim; }
Unit* getOwner() { return iOwner; }
@@ -207,6 +211,7 @@ class MANGOS_DLL_SPEC ThreatManager
private:
HostileReference* iCurrentVictim;
Unit* iOwner;
+ uint32 iUpdateTimer;
ThreatContainer iThreatContainer;
ThreatContainer iThreatOfflineContainer;
};
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 2725018..0e5f1e2 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -205,6 +205,9 @@ void Unit::Update( uint32 p_time )
delete *itr;
m_deletedAuras.clear();
+ if (CanHaveThreatList() && getThreatManager().isNeedUpdateToClient(p_time))
+ SendThreatListUpdate();
+
// update combat timer only for players and pets
if (isInCombat() && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet() || ((Creature*)this)->isCharmed()))
{
@@ -9905,6 +9908,8 @@ void Unit::AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask, Sp
void Unit::DeleteThreatList()
{
+ if(CanHaveThreatList() && !m_ThreatManager.isThreatListEmpty())
+ SendClearThreatListOpcode();
m_ThreatManager.clearReferences();
}
@@ -12147,3 +12152,57 @@ void Unit::KnockBackFrom(Unit* target, float horizintalSpeed, float verticalSpee
NearTeleportTo(fx, fy, fz, GetOrientation(), this == target);
}
}
+
+void Unit::SendThreatListUpdate()
+{
+ if (uint32 count = getThreatManager().getThreatList().size())
+ {
+ sLog.outDebug( "WORLD: Send SMSG_THREAT_UPDATE Message" );
+ WorldPacket data(SMSG_THREAT_UPDATE, 8 + count * 8);
+ data.append(GetPackGUID());
+ data << uint32(count);
+ std::list<HostileReference*>& tlist = getThreatManager().getThreatList();
+ for (std::list<HostileReference*>::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
+ {
+ data.appendPackGUID((*itr)->getUnitGuid());
+ data << uint32((*itr)->getThreat());
+ }
+ SendMessageToSet(&data, false);
+ }
+}
+
+void Unit::SendChangeCurrentVictimOpcode(HostileReference* pHostileReference)
+{
+ if (uint32 count = getThreatManager().getThreatList().size())
+ {
+ sLog.outDebug( "WORLD: Send SMSG_HIGHEST_THREAT_UPDATE Message" );
+ WorldPacket data(SMSG_HIGHEST_THREAT_UPDATE, 8 + 8 + count * 8);
+ data.append(GetPackGUID());
+ data.appendPackGUID(pHostileReference->getUnitGuid());
+ data << uint32(count);
+ std::list<HostileReference*>& tlist = getThreatManager().getThreatList();
+ for (std::list<HostileReference*>::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
+ {
+ data.appendPackGUID((*itr)->getUnitGuid());
+ data << uint32((*itr)->getThreat());
+ }
+ SendMessageToSet(&data, false);
+ }
+}
+
+void Unit::SendClearThreatListOpcode()
+{
+ sLog.outDebug( "WORLD: Send SMSG_THREAT_CLEAR Message" );
+ WorldPacket data(SMSG_THREAT_CLEAR, 8);
+ data.append(GetPackGUID());
+ SendMessageToSet(&data, false);
+}
+
+void Unit::SendRemoveFromThreatListOpcode(HostileReference* pHostileReference)
+{
+ sLog.outDebug( "WORLD: Send SMSG_THREAT_REMOVE Message" );
+ WorldPacket data(SMSG_THREAT_REMOVE, 8 + 8);
+ data.append(GetPackGUID());
+ data.appendPackGUID(pHostileReference->getUnitGuid());
+ SendMessageToSet(&data, false);
+}
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 20c1754..33547b6 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1142,6 +1142,11 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, MonsterMovementFlags flags, uint32 Time, Player* player = NULL);
void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, MonsterMovementFlags flags);
+ void SendChangeCurrentVictimOpcode(HostileReference* pHostileReference);
+ void SendClearThreatListOpcode();
+ void SendRemoveFromThreatListOpcode(HostileReference* pHostileReference);
+ void SendThreatListUpdate();
+
void BuildHeartBeatMsg( WorldPacket *data ) const;
virtual void MoveOutOfRange(Player &) { };