diff options
Diffstat (limited to 'src/game/ThreatManager.cpp')
| -rw-r--r-- | src/game/ThreatManager.cpp | 78 | 
1 files changed, 49 insertions, 29 deletions
diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index ac124da6951..336f02c4470 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -1,7 +1,7 @@  /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>   * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -23,7 +23,6 @@  #include "Creature.h"  #include "CreatureAI.h"  #include "Map.h" -#include "MapManager.h"  #include "Player.h"  #include "ObjectAccessor.h"  #include "UnitEvents.h" @@ -84,7 +83,7 @@ void HostilReference::sourceObjectDestroyLink()  //============================================================  // Inform the source, that the status of the reference changed -void HostilReference::fireStatusChanged(const ThreatRefStatusChangeEvent& pThreatRefStatusChangeEvent) +void HostilReference::fireStatusChanged(ThreatRefStatusChangeEvent& pThreatRefStatusChangeEvent)  {      if(getSource())          getSource()->processThreatEvent(&pThreatRefStatusChangeEvent); @@ -100,7 +99,11 @@ void HostilReference::addThreat(float pMod)      if(!isOnline())          updateOnlineStatus();      if(pMod != 0.0f) -        fireStatusChanged(ThreatRefStatusChangeEvent(UEV_THREAT_REF_THREAT_CHANGE, this, pMod)); +    { +        ThreatRefStatusChangeEvent event(UEV_THREAT_REF_THREAT_CHANGE, this, pMod); +        fireStatusChanged(event); +    } +      if(isValid() && pMod >= 0)      {          Unit* victim_owner = getTarget()->GetCharmerOrOwner(); @@ -155,8 +158,10 @@ void HostilReference::setOnlineOfflineState(bool pIsOnline)      {          iOnline = pIsOnline;          if(!iOnline) -            setAccessibleState(false);                      // if not online that not accessible as well -        fireStatusChanged(ThreatRefStatusChangeEvent(UEV_THREAT_REF_ONLINE_STATUS, this)); +            setAccessibleState(false);                      // if not online that not accessable as well + +        ThreatRefStatusChangeEvent event(UEV_THREAT_REF_ONLINE_STATUS, this); +        fireStatusChanged(event);      }  } @@ -167,7 +172,9 @@ void HostilReference::setAccessibleState(bool pIsAccessible)      if(iAccessible != pIsAccessible)      {          iAccessible = pIsAccessible; -        fireStatusChanged(ThreatRefStatusChangeEvent(UEV_THREAT_REF_ASSECCIBLE_STATUS, this)); + +        ThreatRefStatusChangeEvent event(UEV_THREAT_REF_ASSECCIBLE_STATUS, this); +        fireStatusChanged(event);      }  } @@ -178,7 +185,9 @@ void HostilReference::setAccessibleState(bool pIsAccessible)  void HostilReference::removeReference()  {      invalidate(); -    fireStatusChanged(ThreatRefStatusChangeEvent(UEV_THREAT_REF_REMOVE_FROM_LIST, this)); + +    ThreatRefStatusChangeEvent event(UEV_THREAT_REF_REMOVE_FROM_LIST, this); +    fireStatusChanged(event);  }  //============================================================ @@ -267,26 +276,36 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe  {      HostilReference* currentRef = NULL;      bool found = false; +    bool noPriorityTargetFound = false;      std::list<HostilReference*>::iterator lastRef = iThreatList.end();      lastRef--; -    for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found; ++iter) +    for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;)      {          currentRef = (*iter);          Unit* target = currentRef->getTarget();          assert(target);                                     // if the ref has status online the target must be there ! -        // some units are preferred in comparison to others -        if(iter != lastRef && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask(), false) || -                target->hasUnitState(UNIT_STAT_CONFUSED) -                ) ) +        // some units are prefered in comparison to others +        if(!noPriorityTargetFound && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask()) || target->hasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_DAMAGE)) )          { -            // current victim is a second choice target, so don't compare threat with it below -            if(currentRef == pCurrentVictim) -                pCurrentVictim = NULL; -            continue; +            if(iter != lastRef) +            { +                // current victim is a second choice target, so don't compare threat with it below +                if(currentRef == pCurrentVictim) +                    pCurrentVictim = NULL; +                ++iter; +                continue; +            } +            else +            { +                // if we reached to this point, everyone in the threatlist is a second choice target. In such a situation the target with the highest threat should be attacked. +                noPriorityTargetFound = true; +                iter = iThreatList.begin(); +                continue; +            }          }          if(!pAttacker->IsOutOfThreatArea(target))           // skip non attackable currently targets @@ -314,6 +333,7 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe                  break;              }          } +        ++iter;      }      if(!found)          currentRef = NULL; @@ -347,12 +367,18 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask scho      //players and pets have only InHateListOf      //HateOfflineList is used co contain unattackable victims (in-flight, in-water, GM etc.) -    if (pVictim == getOwner())                              // only for same creatures :) +    // not to self +    if (pVictim == getOwner())          return; +    // not to GM      if(!pVictim || (pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster()) )          return; +    // not to dead and not for dead +    if(!pVictim->isAlive() || !getOwner()->isAlive() ) +        return; +      assert(getOwner()->GetTypeId()== TYPEID_UNIT);      float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, schoolMask, pThreatSpell); @@ -450,18 +476,13 @@ void ThreatManager::setCurrentVictim(HostilReference* pHostilReference)  // The hated unit is gone, dead or deleted  // return true, if the event is consumed -bool ThreatManager::processThreatEvent(const UnitBaseEvent* pUnitBaseEvent) +void ThreatManager::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusChangeEvent)  { -    bool consumed = false; - -    ThreatRefStatusChangeEvent* threatRefStatusChangeEvent; -    HostilReference* hostilReference; - -    threatRefStatusChangeEvent = (ThreatRefStatusChangeEvent*) pUnitBaseEvent;      threatRefStatusChangeEvent->setThreatManager(this);     // now we can set the threat manager -    hostilReference = threatRefStatusChangeEvent->getReference(); -    switch(pUnitBaseEvent->getType()) +    HostilReference* hostilReference = threatRefStatusChangeEvent->getReference(); + +    switch(threatRefStatusChangeEvent->getType())      {          case UEV_THREAT_REF_THREAT_CHANGE:              if((getCurrentVictim() == hostilReference && threatRefStatusChangeEvent->getFValue()<0.0f) || @@ -499,6 +520,5 @@ bool ThreatManager::processThreatEvent(const UnitBaseEvent* pUnitBaseEvent)                  iThreatOfflineContainer.remove(hostilReference);              break;      } -    return consumed;  }  | 
