[11954] Do not calculate targets for different effects with same targeting multiple times

Some effects or target-combinations might need exception from the generic rule that calculated targets from one effect are used by other effects with same targets.
This will fix bugs that different random targets for different effects are selected, even when they should be the same.

Signed-off-by: Schmoozerd <schmoozerd@scriptdev2.com>
This commit is contained in:
Reamer 2012-04-12 15:49:19 +02:00 committed by Schmoozerd
parent 1ab35e53d9
commit b6f6c670ac
2 changed files with 201 additions and 186 deletions

View file

@ -442,17 +442,19 @@ void Spell::FillTargetMap()
{ {
// TODO: ADD the correct target FILLS!!!!!! // TODO: ADD the correct target FILLS!!!!!!
UnitList tmpUnitLists[MAX_EFFECT_INDEX]; // Stores the temporary Target Lists for each effect
uint8 effToIndex[MAX_EFFECT_INDEX] = {0, 1, 2}; // Helper array, to link to another tmpUnitList, if the targets for both effects match
for(int i = 0; i < MAX_EFFECT_INDEX; ++i) for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
{ {
// not call for empty effect. // not call for empty effect.
// Also some spells use not used effect targets for store targets for dummy effect in triggered spells // Also some spells use not used effect targets for store targets for dummy effect in triggered spells
if(m_spellInfo->Effect[i] == 0) if (m_spellInfo->Effect[i] == 0)
continue; continue;
// targets for TARGET_SCRIPT_COORDINATES (A) and TARGET_SCRIPT // targets for TARGET_SCRIPT_COORDINATES (A) and TARGET_SCRIPT
// for TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT (A) all is checked in Spell::CheckCast and in Spell::CheckItem // for TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT (A) all is checked in Spell::CheckCast and in Spell::CheckItem
// filled in Spell::CheckCast call // filled in Spell::CheckCast call
if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT_COORDINATES || if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT_COORDINATES ||
m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SCRIPT ||
m_spellInfo->EffectImplicitTargetA[i] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT || m_spellInfo->EffectImplicitTargetA[i] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT ||
(m_spellInfo->EffectImplicitTargetB[i] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[i] != TARGET_SELF)) (m_spellInfo->EffectImplicitTargetB[i] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[i] != TARGET_SELF))
@ -460,11 +462,23 @@ void Spell::FillTargetMap()
// TODO: find a way so this is not needed? // TODO: find a way so this is not needed?
// for area auras always add caster as target (needed for totems for example) // for area auras always add caster as target (needed for totems for example)
if(IsAreaAuraEffect(m_spellInfo->Effect[i])) if (IsAreaAuraEffect(m_spellInfo->Effect[i]))
AddUnitTarget(m_caster, SpellEffectIndex(i)); AddUnitTarget(m_caster, SpellEffectIndex(i));
UnitList tmpUnitMap; // no double fill for same targets
for (int j = 0; j < i; ++j)
{
// Check if same target, but handle i.e. AreaAuras different
if (m_spellInfo->EffectImplicitTargetA[i] == m_spellInfo->EffectImplicitTargetA[j] && m_spellInfo->EffectImplicitTargetB[i] == m_spellInfo->EffectImplicitTargetB[j]
&& !IsAreaAuraEffect(m_spellInfo->Effect[i]) && !IsAreaAuraEffect(m_spellInfo->Effect[j]))
// Add further conditions here if required
{
effToIndex[i] = j; // effect i has same targeting list as effect j
}
}
if (effToIndex[i] == i) // New target combination
{
// TargetA/TargetB dependent from each other, we not switch to full support this dependences // TargetA/TargetB dependent from each other, we not switch to full support this dependences
// but need it support in some know cases // but need it support in some know cases
switch(m_spellInfo->EffectImplicitTargetA[i]) switch(m_spellInfo->EffectImplicitTargetA[i])
@ -474,12 +488,12 @@ void Spell::FillTargetMap()
{ {
case TARGET_NONE: case TARGET_NONE:
if (m_caster->GetObjectGuid().IsPet()) if (m_caster->GetObjectGuid().IsPet())
SetTargetMap(SpellEffectIndex(i), TARGET_SELF, tmpUnitMap); SetTargetMap(SpellEffectIndex(i), TARGET_SELF, tmpUnitLists[i /*==effToIndex[i]*/]);
else else
SetTargetMap(SpellEffectIndex(i), TARGET_EFFECT_SELECT, tmpUnitMap); SetTargetMap(SpellEffectIndex(i), TARGET_EFFECT_SELECT, tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
default: default:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
} }
break; break;
@ -488,19 +502,19 @@ void Spell::FillTargetMap()
{ {
case TARGET_NONE: case TARGET_NONE:
case TARGET_EFFECT_SELECT: case TARGET_EFFECT_SELECT:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
case TARGET_AREAEFFECT_INSTANT: // use B case that not dependent from from A in fact case TARGET_AREAEFFECT_INSTANT: // use B case that not dependent from from A in fact
if((m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) == 0) if((m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) == 0)
m_targets.setDestination(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ()); m_targets.setDestination(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ());
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
case TARGET_BEHIND_VICTIM: // use B case that not dependent from from A in fact case TARGET_BEHIND_VICTIM: // use B case that not dependent from from A in fact
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
default: default:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
} }
break; break;
@ -509,7 +523,7 @@ void Spell::FillTargetMap()
{ {
case TARGET_NONE: case TARGET_NONE:
case TARGET_EFFECT_SELECT: case TARGET_EFFECT_SELECT:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
// dest point setup required // dest point setup required
case TARGET_AREAEFFECT_INSTANT: case TARGET_AREAEFFECT_INSTANT:
@ -524,7 +538,7 @@ void Spell::FillTargetMap()
if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) || m_IsTriggeredSpell) if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) || m_IsTriggeredSpell)
if (WorldObject* castObject = GetCastingObject()) if (WorldObject* castObject = GetCastingObject())
m_targets.setDestination(castObject->GetPositionX(), castObject->GetPositionY(), castObject->GetPositionZ()); m_targets.setDestination(castObject->GetPositionX(), castObject->GetPositionY(), castObject->GetPositionZ());
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
// target pre-selection required // target pre-selection required
case TARGET_INNKEEPER_COORDINATES: case TARGET_INNKEEPER_COORDINATES:
@ -543,11 +557,11 @@ void Spell::FillTargetMap()
case TARGET_POINT_AT_SE: case TARGET_POINT_AT_SE:
case TARGET_POINT_AT_SW: case TARGET_POINT_AT_SW:
// need some target for processing // need some target for processing
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
default: default:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
} }
break; break;
@ -561,21 +575,21 @@ void Spell::FillTargetMap()
if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE) if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE)
{ {
if(m_targets.getUnitTarget()) if(m_targets.getUnitTarget())
tmpUnitMap.push_back(m_targets.getUnitTarget()); tmpUnitLists[i /*==effToIndex[i]*/].push_back(m_targets.getUnitTarget());
} }
else else
{ {
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
} }
break; break;
case 0: case 0:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
tmpUnitMap.push_back(m_caster); tmpUnitLists[i /*==effToIndex[i]*/].push_back(m_caster);
break; break;
default: default:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
} }
break; break;
@ -583,17 +597,17 @@ void Spell::FillTargetMap()
switch(m_spellInfo->EffectImplicitTargetB[i]) switch(m_spellInfo->EffectImplicitTargetB[i])
{ {
case 0: case 0:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
// need some target for processing // need some target for processing
SetTargetMap(SpellEffectIndex(i), TARGET_EFFECT_SELECT, tmpUnitMap); SetTargetMap(SpellEffectIndex(i), TARGET_EFFECT_SELECT, tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
case TARGET_AREAEFFECT_INSTANT: // All 17/7 pairs used for dest teleportation, A processed in effect code case TARGET_AREAEFFECT_INSTANT: // All 17/7 pairs used for dest teleportation, A processed in effect code
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
default: default:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
} }
break; break;
@ -602,11 +616,11 @@ void Spell::FillTargetMap()
{ {
case 0: case 0:
case TARGET_EFFECT_SELECT: case TARGET_EFFECT_SELECT:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
// most A/B target pairs is self->negative and not expect adding caster to target list // most A/B target pairs is self->negative and not expect adding caster to target list
default: default:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
} }
break; break;
@ -615,13 +629,13 @@ void Spell::FillTargetMap()
{ {
case 0: case 0:
case TARGET_EFFECT_SELECT: case TARGET_EFFECT_SELECT:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
if (Unit* currentTarget = m_targets.getUnitTarget()) if (Unit* currentTarget = m_targets.getUnitTarget())
tmpUnitMap.push_back(currentTarget); tmpUnitLists[i /*==effToIndex[i]*/].push_back(currentTarget);
break; break;
default: default:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
} }
break; break;
@ -630,23 +644,24 @@ void Spell::FillTargetMap()
{ {
case 0: case 0:
case TARGET_EFFECT_SELECT: case TARGET_EFFECT_SELECT:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
case TARGET_SCRIPT_COORDINATES: // B case filled in CheckCast but we need fill unit list base at A case case TARGET_SCRIPT_COORDINATES: // B case filled in CheckCast but we need fill unit list base at A case
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
default: default:
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetA[i], tmpUnitLists[i /*==effToIndex[i]*/]);
SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); SetTargetMap(SpellEffectIndex(i), m_spellInfo->EffectImplicitTargetB[i], tmpUnitLists[i /*==effToIndex[i]*/]);
break; break;
} }
break; break;
} }
} // End new target combination fill
if (m_caster->GetTypeId() == TYPEID_PLAYER) if (m_caster->GetTypeId() == TYPEID_PLAYER)
{ {
Player *me = (Player*)m_caster; Player* me = (Player*)m_caster;
for (UnitList::const_iterator itr = tmpUnitMap.begin(); itr != tmpUnitMap.end(); ++itr) for (UnitList::const_iterator itr = tmpUnitLists[effToIndex[i]].begin(); itr != tmpUnitLists[effToIndex[i]].end(); ++itr)
{ {
Player *targetOwner = (*itr)->GetCharmerOrOwnerPlayerOrPlayerItself(); Player *targetOwner = (*itr)->GetCharmerOrOwnerPlayerOrPlayerItself();
if (targetOwner && targetOwner != me && targetOwner->IsPvP() && !me->IsInDuelWith(targetOwner)) if (targetOwner && targetOwner != me && targetOwner->IsPvP() && !me->IsInDuelWith(targetOwner))
@ -658,18 +673,18 @@ void Spell::FillTargetMap()
} }
} }
for (UnitList::iterator itr = tmpUnitMap.begin(); itr != tmpUnitMap.end();) for (UnitList::iterator itr = tmpUnitLists[effToIndex[i]].begin(); itr != tmpUnitLists[effToIndex[i]].end();)
{ {
if (!CheckTarget (*itr, SpellEffectIndex(i))) if (!CheckTarget (*itr, SpellEffectIndex(i)))
{ {
itr = tmpUnitMap.erase(itr); itr = tmpUnitLists[effToIndex[i]].erase(itr);
continue; continue;
} }
else else
++itr; ++itr;
} }
for(UnitList::const_iterator iunit = tmpUnitMap.begin(); iunit != tmpUnitMap.end(); ++iunit) for (UnitList::const_iterator iunit = tmpUnitLists[effToIndex[i]].begin(); iunit != tmpUnitLists[effToIndex[i]].end(); ++iunit)
AddUnitTarget((*iunit), SpellEffectIndex(i)); AddUnitTarget((*iunit), SpellEffectIndex(i));
} }
} }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11953" #define REVISION_NR "11954"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__