diff options
Diffstat (limited to 'src/game/ThreatManager.cpp')
-rw-r--r-- | src/game/ThreatManager.cpp | 89 |
1 files changed, 55 insertions, 34 deletions
diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index ac124da6951..a0459aa81dc 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); } //============================================================ @@ -194,7 +203,7 @@ Unit* HostilReference::getSourceUnit() void ThreatContainer::clearReferences() { - for(std::list<HostilReference*>::iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) + for(std::list<HostilReference*>::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) { (*i)->unlink(); delete (*i); @@ -208,7 +217,7 @@ HostilReference* ThreatContainer::getReferenceByTarget(Unit* pVictim) { HostilReference* result = NULL; uint64 guid = pVictim->GetGUID(); - for(std::list<HostilReference*>::iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) + for(std::list<HostilReference*>::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) { if((*i)->getUnitGuid() == guid) { @@ -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(); + std::list<HostilReference*>::const_iterator lastRef = iThreatList.end(); lastRef--; - for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found; ++iter) + for(std::list<HostilReference*>::const_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_TAKE_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 @@ -301,8 +320,9 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe break; } - if( currentRef->getThreat() > 1.3f * pCurrentVictim->getThreat() || - currentRef->getThreat() > 1.1f * pCurrentVictim->getThreat() && pAttacker->IsWithinMeleeRange(target) ) + if (currentRef->getThreat() > 1.3f * pCurrentVictim->getThreat() || + currentRef->getThreat() > 1.1f * pCurrentVictim->getThreat() && + pAttacker->IsWithinMeleeRange(target)) { //implement 110% threat rule for targets in melee range found = true; //and 130% rule for targets in ranged distances break; //for selecting alive targets @@ -314,6 +334,7 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe break; } } + ++iter; } if(!found) currentRef = NULL; @@ -347,12 +368,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 +477,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 +521,5 @@ bool ThreatManager::processThreatEvent(const UnitBaseEvent* pUnitBaseEvent) iThreatOfflineContainer.remove(hostilReference); break; } - return consumed; } |