diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 382328dfa..e9adaa1f7 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -523,8 +523,8 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 break; case ACTION_T_THREAT_ALL_PCT: { - std::list& threatList = m_creature->getThreatManager().getThreatList(); - for (std::list::iterator i = threatList.begin(); i != threatList.end(); ++i) + ThreatList& threatList = m_creature->getThreatManager().getThreatList(); + for (ThreatList::iterator i = threatList.begin(); i != threatList.end(); ++i) if(Unit* Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid())) m_creature->getThreatManager().modifyThreatPercent(Temp, action.threat_all_pct.percent); break; @@ -634,8 +634,8 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 break; case ACTION_T_CAST_EVENT_ALL: { - std::list& threatList = m_creature->getThreatManager().getThreatList(); - for (std::list::iterator i = threatList.begin(); i != threatList.end(); ++i) + ThreatList& threatList = m_creature->getThreatManager().getThreatList(); + for (ThreatList::iterator i = threatList.begin(); i != threatList.end(); ++i) if (Unit* Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid())) if (Temp->GetTypeId() == TYPEID_PLAYER) ((Player*)Temp)->CastedCreatureOrGO(action.cast_event_all.creatureId, m_creature->GetGUID(), action.cast_event_all.spellId); @@ -1114,9 +1114,9 @@ bool CreatureEventAI::IsVisible(Unit *pl) const inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position) { //ThreatList m_threatlist; - std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); - std::list::iterator i = m_threatlist.begin(); - std::list::reverse_iterator r = m_threatlist.rbegin(); + ThreatList& m_threatlist = m_creature->getThreatManager().getThreatList(); + ThreatList::iterator i = m_threatlist.begin(); + ThreatList::reverse_iterator r = m_threatlist.rbegin(); if (position >= m_threatlist.size() || !m_threatlist.size()) return NULL; diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index 11b560482..dbbf48a16 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -208,7 +208,7 @@ Unit* HostileReference::getSourceUnit() void ThreatContainer::clearReferences() { - for(std::list::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) + for(ThreatList::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) { (*i)->unlink(); delete (*i); @@ -222,7 +222,7 @@ HostileReference* ThreatContainer::getReferenceByTarget(Unit* pVictim) { HostileReference* result = NULL; uint64 guid = pVictim->GetGUID(); - for(std::list::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) + for(ThreatList::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) { if((*i)->getUnitGuid() == guid) { @@ -283,10 +283,10 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* pAttacker, Hostile bool found = false; bool noPriorityTargetFound = false; - std::list::const_iterator lastRef = iThreatList.end(); + ThreatList::const_iterator lastRef = iThreatList.end(); lastRef--; - for(std::list::const_iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;) + for(ThreatList::const_iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;) { currentRef = (*iter); @@ -351,7 +351,7 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* pAttacker, Hostile //=================== ThreatManager ========================== //============================================================ -ThreatManager::ThreatManager(Unit* owner) : iCurrentVictim(NULL), iOwner(owner) +ThreatManager::ThreatManager(Unit* owner) : iCurrentVictim(NULL), iOwner(owner), iUpdateTimer(THREAT_UPDATE_INTERVAL) { } @@ -362,6 +362,7 @@ void ThreatManager::clearReferences() iThreatContainer.clearReferences(); iThreatOfflineContainer.clearReferences(); iCurrentVictim = NULL; + iUpdateTimer.Reset(THREAT_UPDATE_INTERVAL); } //============================================================ @@ -461,6 +462,9 @@ void ThreatManager::tauntFadeOut(Unit *pTaunter) void ThreatManager::setCurrentVictim(HostileReference* pHostileReference) { + if (pHostileReference && pHostileReference != iCurrentVictim) + iOwner->SendHighestThreatUpdate(pHostileReference); + iCurrentVictim = pHostileReference; } @@ -506,6 +510,7 @@ void ThreatManager::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStat setCurrentVictim(NULL); setDirty(true); } + iOwner->SendThreatRemove(hostileReference); if(hostileReference->isOnline()) iThreatContainer.remove(hostileReference); else @@ -513,3 +518,16 @@ void ThreatManager::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStat break; } } + +void ThreatManager::UpdateForClient(uint32 diff) +{ + if (isThreatListEmpty()) + return; + + iUpdateTimer.Update(diff); + if (iUpdateTimer.Passed()) + { + iOwner->SendThreatUpdate(); + iUpdateTimer.Reset(THREAT_UPDATE_INTERVAL); + } +} diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h index 7c8cf23fb..9f2a14edf 100644 --- a/src/game/ThreatManager.h +++ b/src/game/ThreatManager.h @@ -23,7 +23,7 @@ #include "SharedDefines.h" #include "Utilities/LinkedReference/Reference.h" #include "UnitEvents.h" - +#include "Timer.h" #include //============================================================== @@ -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 @@ -127,10 +129,13 @@ class MANGOS_DLL_SPEC HostileReference : public Reference //============================================================== class ThreatManager; +typedef std::list ThreatList; + + class MANGOS_DLL_SPEC ThreatContainer { private: - std::list iThreatList; + ThreatList iThreatList; bool iDirty; protected: friend class ThreatManager; @@ -160,7 +165,8 @@ class MANGOS_DLL_SPEC ThreatContainer HostileReference* getReferenceByTarget(Unit* pVictim); - std::list& getThreatList() { return iThreatList; } + ThreatList& getThreatList() { return iThreatList; } + ThreatList const& getThreatList() const { return iThreatList; } }; //================================================= @@ -186,6 +192,8 @@ class MANGOS_DLL_SPEC ThreatManager void processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusChangeEvent); + void UpdateForClient(uint32 time); + HostileReference* getCurrentVictim() { return iCurrentVictim; } Unit* getOwner() { return iOwner; } @@ -201,13 +209,18 @@ class MANGOS_DLL_SPEC ThreatManager // methods to access the lists from the outside to do sume dirty manipulation (scriping and such) // I hope they are used as little as possible. - std::list& getThreatList() { return iThreatContainer.getThreatList(); } - std::list& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); } + ThreatList& getThreatList() { return iThreatContainer.getThreatList(); } + ThreatList const& getThreatList() const { return iThreatContainer.getThreatList(); } + ThreatList& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); } + ThreatList const& getOfflieThreatList() const { return iThreatOfflineContainer.getThreatList(); } ThreatContainer& getOnlineContainer() { return iThreatContainer; } + ThreatContainer const& getOnlineContainer() const { return iThreatContainer; } ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; } + ThreatContainer const& getOfflineContainer() const { return iThreatOfflineContainer; } private: HostileReference* iCurrentVictim; Unit* iOwner; + TimeTrackerSmall iUpdateTimer; ThreatContainer iThreatContainer; ThreatContainer iThreatOfflineContainer; }; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 89edca06b..e6f1e32b8 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -209,6 +209,9 @@ void Unit::Update( uint32 p_time ) delete *itr; m_deletedAuras.clear(); + if (CanHaveThreatList()) + getThreatManager().UpdateForClient(p_time); + // update combat timer only for players and pets if (isInCombat() && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet() || ((Creature*)this)->isCharmed())) { @@ -10402,6 +10405,8 @@ void Unit::AddThreat(Unit* pVictim, float threat /*= 0.0f*/, bool crit /*= false void Unit::DeleteThreatList() { + if(CanHaveThreatList() && !m_ThreatManager.isThreatListEmpty()) + SendThreatClear(); m_ThreatManager.clearReferences(); } @@ -12763,3 +12768,57 @@ uint32 Unit::GetCombatRatingDamageReduction(CombatRating cr, float rate, float c percent = cap; return uint32 (percent * damage / 100.0f); } + +void Unit::SendThreatUpdate() +{ + 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); + ThreatList& tlist = getThreatManager().getThreatList(); + for (ThreatList::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr) + { + data.appendPackGUID((*itr)->getUnitGuid()); + data << uint32((*itr)->getThreat()); + } + SendMessageToSet(&data, false); + } +} + +void Unit::SendHighestThreatUpdate(HostileReference* pHostilReference) +{ + 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(pHostilReference->getUnitGuid()); + data << uint32(count); + ThreatList const& tlist = getThreatManager().getThreatList(); + for (ThreatList::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr) + { + data.appendPackGUID((*itr)->getUnitGuid()); + data << uint32((*itr)->getThreat()); + } + SendMessageToSet(&data, false); + } +} + +void Unit::SendThreatClear() +{ + sLog.outDebug( "WORLD: Send SMSG_THREAT_CLEAR Message" ); + WorldPacket data(SMSG_THREAT_CLEAR, 8); + data.append(GetPackGUID()); + SendMessageToSet(&data, false); +} + +void Unit::SendThreatRemove(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 aa1d5fce2..1a0ac3861 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1161,6 +1161,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 SendHighestThreatUpdate(HostileReference* pHostileReference); + void SendThreatClear(); + void SendThreatRemove(HostileReference* pHostileReference); + void SendThreatUpdate(); + void BuildHeartBeatMsg( WorldPacket *data ) const; virtual void MoveOutOfRange(Player &) { }; @@ -1373,6 +1378,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void TauntApply(Unit* pVictim); void TauntFadeOut(Unit *taunter); ThreatManager& getThreatManager() { return m_ThreatManager; } + ThreatManager const& getThreatManager() const { return m_ThreatManager; } void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); }; void removeHatedBy(HostileReference* /*pHostileReference*/ ) { /* nothing to do yet */ } HostileRefManager& getHostileRefManager() { return m_HostileRefManager; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 79031d12f..ab01a3877 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8857" + #define REVISION_NR "8858" #endif // __REVISION_NR_H__