Jump to content

[fix][8858] Threat


Auntie Mangos

Recommended Posts

  • Replies 63
  • Created
  • Last Reply

Top Posters In This Topic

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 &) {  };

Link to comment
Share on other sites

heres the diff against 8757 working for me

-------------------------- src/game/ThreatManager.cpp --------------------------
index 11b5604..650861c 100644
@@ -220,8 +220,11 @@ void ThreatContainer::clearReferences()
// Return the HostileReference of NULL, if not found
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)
    {
        if((*i)->getUnitGuid() == guid)
@@ -350,9 +353,9 @@ 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)
{
}

//============================================================
@@ -361,8 +364,9 @@ void ThreatManager::clearReferences()
{
    iThreatContainer.clearReferences();
    iThreatOfflineContainer.clearReferences();
    iCurrentVictim = NULL;
+    iUpdateTimer = THREAT_UPDATE_INTERVAL;
}

//============================================================

@@ -460,8 +464,12 @@ void ThreatManager::tauntFadeOut(Unit *pTaunter)
//============================================================

void ThreatManager::setCurrentVictim(HostileReference* pHostileReference)
{
+    if (pHostileReference && pHostileReference != iCurrentVictim)
+    {
+        iOwner->SendChangeCurrentVictimOpcode(pHostileReference);
+    }
    iCurrentVictim = pHostileReference;
}

//============================================================
@@ -505,11 +513,25 @@ void ThreatManager::ProcessThreatEvent(ThreatRefStatusChangeEvent* threatRefStat
            {
                setCurrentVictim(NULL);
                setDirty(true);
            }
+            iOwner->SendRemoveFromThreatListOpcode(hostileReference);
            if(hostileReference->isOnline())
                iThreatContainer.remove(hostileReference);
            else
                iThreatOfflineContainer.remove(hostileReference);
            break;
    }
}
+
+bool ThreatManager::isNeedUpdateToClient(uint32 time)
+{
+    if (isThreatListEmpty())
+        return false;
+    if (time >= iUpdateTimer)
+    {
+        iUpdateTimer = THREAT_UPDATE_INTERVAL;
+        return true;
+    }
+    iUpdateTimer -= time;
+    return false;
+}
--------------------------- src/game/ThreatManager.h ---------------------------
index 7c8cf23..dc32898 100644
@@ -32,8 +32,10 @@ class Unit;
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

class ThreatCalcHelper
@@ -185,8 +187,10 @@ class MANGOS_DLL_SPEC ThreatManager
        bool isThreatListEmpty() { return iThreatContainer.empty();}

        void processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusChangeEvent);

+        bool isNeedUpdateToClient(uint32 time);
+
        HostileReference* getCurrentVictim() { return iCurrentVictim; }

        Unit*  getOwner() { return iOwner; }

@@ -207,8 +211,9 @@ class MANGOS_DLL_SPEC ThreatManager
        ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; }
    private:
        HostileReference* iCurrentVictim;
        Unit* iOwner;
+        uint32 iUpdateTimer;
        ThreatContainer iThreatContainer;
        ThreatContainer iThreatOfflineContainer;
};

------------------------------ src/game/Unit.cpp ------------------------------
index ac5f15d..e8d3833 100644
@@ -205,8 +205,11 @@ void Unit::Update( uint32 p_time )
    for(AuraList::const_iterator itr = m_deletedAuras.begin(); itr != m_deletedAuras.begin(); ++itr)
        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()))
    {
        // Check UNIT_STAT_MELEE_ATTACKING or UNIT_STAT_CHASE (without UNIT_STAT_FOLLOW in this case) so pets can reach far away
@@ -10290,8 +10293,10 @@ void Unit::AddThreat(Unit* pVictim, float threat /*= 0.0f*/, bool crit /*= false
//======================================================================

void Unit::DeleteThreatList()
{
+    if(CanHaveThreatList() && !m_ThreatManager.isThreatListEmpty())
+        SendClearThreatListOpcode();
    m_ThreatManager.clearReferences();
}

//======================================================================
@@ -12628,8 +12633,9 @@ void Unit::KnockBackFrom(Unit* target, float horizintalSpeed, float verticalSpee
        NearTeleportTo(fx, fy, fz, GetOrientation(), this == target);
    }
}

+
float Unit::GetCombatRatingReduction(CombatRating cr) const
{
    if (GetTypeId() == TYPEID_PLAYER)
        return ((Player const*)this)->GetRatingBonusValue(cr);
@@ -12650,4 +12656,58 @@ uint32 Unit::GetCombatRatingDamageReduction(CombatRating cr, float rate, float c
    if (percent > cap)
        percent = cap;
    return uint32 (percent * damage / 100.0f);
}
+
+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);
+}
------------------------------- src/game/Unit.h -------------------------------
index b481c37..900a60d 100644
@@ -1154,8 +1154,13 @@ 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 &) {  };

Link to comment
Share on other sites

Yep, patch works great...

I really like mangos, and I don't switch to other fork projects -which I won't name- for the mangos seriousness and professional way of developping, but I only regret that they take just a bit too much time to include patches that have been proven efficient and bug-free long ago :) .

Anyway, I hope this patch will get in master soon..!

Keep up the good work :) .

Link to comment
Share on other sites

don't let it be the last patch you commit. :)

you do great work and it's like you say. those ppl that know how to use a patch file will love it every minute just as much as you do.

Getting it to the master trunk would be awesome, but as every dev has it's own focal points he wants to further some of the smaller features keep getting stuck in the line.

this does not mean that they are useless or badly coded however!!

Thank you for every thing you have doen/will do for the community

cheers

shane99

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use