mirror of
https://github.com/mangosfour/server.git
synced 2025-12-23 16:37:03 +00:00
[11846] Changes to default target selection
* Add a new function: Unit::IsSecondChoiceTarget to evaluate if a target will be selected * Cleanup a bit related code * SelectHostileTarget - Only call AI()->AttackStart for new targets - Remove exception for top-most taunter * Fix a few minor bugs related to selectNextVictim Signed-off-by: Schmoozerd <schmoozerd@scriptdev2.com>
This commit is contained in:
parent
b35dea1703
commit
f4d862ac0a
4 changed files with 86 additions and 52 deletions
|
|
@ -281,58 +281,82 @@ void ThreatContainer::update()
|
|||
|
||||
HostileReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostileReference* pCurrentVictim)
|
||||
{
|
||||
HostileReference* currentRef = NULL;
|
||||
HostileReference* pCurrentRef = NULL;
|
||||
bool found = false;
|
||||
bool noPriorityTargetFound = false;
|
||||
bool onlySecondChoiceTargetsFound = false;
|
||||
bool checkedCurrentVictim = false;
|
||||
|
||||
ThreatList::const_iterator lastRef = iThreatList.end();
|
||||
lastRef--;
|
||||
|
||||
for(ThreatList::const_iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;)
|
||||
for (ThreatList::const_iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;)
|
||||
{
|
||||
currentRef = (*iter);
|
||||
pCurrentRef = (*iter);
|
||||
|
||||
Unit* target = currentRef->getTarget();
|
||||
MANGOS_ASSERT(target); // if the ref has status online the target must be there !
|
||||
Unit* pTarget = pCurrentRef->getTarget();
|
||||
MANGOS_ASSERT(pTarget); // if the ref has status online the target must be there!
|
||||
|
||||
// some units are prefered in comparison to others
|
||||
if(!noPriorityTargetFound && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask()) || target->hasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_DAMAGE)) )
|
||||
// if (checkThreatArea) consider IsOutOfThreatArea - expected to be only set for pCurrentVictim
|
||||
// This prevents dropping valid targets due to 1.1 or 1.3 threat rule vs invalid current target
|
||||
if (!onlySecondChoiceTargetsFound && pAttacker->IsSecondChoiceTarget(pTarget, pCurrentRef == pCurrentVictim))
|
||||
{
|
||||
if(iter != lastRef)
|
||||
{
|
||||
// current victim is a second choice target, so don't compare threat with it below
|
||||
if(currentRef == pCurrentVictim)
|
||||
pCurrentVictim = NULL;
|
||||
if (iter != lastRef)
|
||||
++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;
|
||||
onlySecondChoiceTargetsFound = true;
|
||||
iter = iThreatList.begin();
|
||||
continue;
|
||||
}
|
||||
|
||||
// current victim is a second choice target, so don't compare threat with it below
|
||||
if (pCurrentRef == pCurrentVictim)
|
||||
pCurrentVictim = NULL;
|
||||
|
||||
// second choice targets are only handled threat dependend if we have only have second choice targets
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pAttacker->IsOutOfThreatArea(target)) // skip non attackable currently targets
|
||||
if (!pAttacker->IsOutOfThreatArea(pTarget)) // skip non attackable currently targets
|
||||
{
|
||||
if (pCurrentVictim) // select 1.3/1.1 better target in comparison current target
|
||||
{
|
||||
// list sorted and and we check current target, then this is best case
|
||||
if(pCurrentVictim == currentRef || currentRef->getThreat() <= 1.1f * pCurrentVictim->getThreat() )
|
||||
// normal case: pCurrentRef is still valid and most hated
|
||||
if (pCurrentVictim == pCurrentRef)
|
||||
{
|
||||
currentRef = pCurrentVictim; // for second case
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentRef->getThreat() > 1.3f * pCurrentVictim->getThreat() ||
|
||||
(currentRef->getThreat() > 1.1f * pCurrentVictim->getThreat() &&
|
||||
pAttacker->CanReachWithMeleeAttack(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
|
||||
// we found a valid target, but only compare its threat if the currect victim is also a valid target
|
||||
// Additional check to prevent unneeded comparision in case of valid current victim
|
||||
if (!checkedCurrentVictim)
|
||||
{
|
||||
Unit* pCurrentTarget = pCurrentVictim->getTarget();
|
||||
MANGOS_ASSERT(pCurrentTarget);
|
||||
if (pAttacker->IsSecondChoiceTarget(pCurrentTarget, true))
|
||||
{
|
||||
// CurrentVictim is invalid, so return CurrentRef
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
checkedCurrentVictim = true;
|
||||
}
|
||||
|
||||
// list sorted and and we check current target, then this is best case
|
||||
if (pCurrentRef->getThreat() <= 1.1f * pCurrentVictim->getThreat())
|
||||
{
|
||||
pCurrentRef = pCurrentVictim;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pCurrentRef->getThreat() > 1.3f * pCurrentVictim->getThreat() ||
|
||||
(pCurrentRef->getThreat() > 1.1f * pCurrentVictim->getThreat() && pAttacker->CanReachWithMeleeAttack(pTarget)))
|
||||
{ // implement 110% threat rule for targets in melee range
|
||||
found = true; // and 130% rule for targets in ranged distances
|
||||
break; // for selecting alive targets
|
||||
}
|
||||
}
|
||||
else // select any
|
||||
|
|
@ -343,10 +367,10 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* pAttacker, Hostile
|
|||
}
|
||||
++iter;
|
||||
}
|
||||
if(!found)
|
||||
currentRef = NULL;
|
||||
if (!found)
|
||||
pCurrentRef = NULL;
|
||||
|
||||
return currentRef;
|
||||
return pCurrentRef;
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue