aboutsummaryrefslogtreecommitdiff
path: root/src/game/ThreatManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/ThreatManager.cpp')
-rw-r--r--src/game/ThreatManager.cpp89
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;
}