feat(Core/Spell): implement SPELL_ATTR2_CHAIN_FROM_CASTER (#22515)
Co-authored-by: Shauren <shauren.trinity@gmail.com>
This commit is contained in:
@@ -2238,21 +2238,15 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
|||||||
if (isBouncingFar)
|
if (isBouncingFar)
|
||||||
searchRadius *= chainTargets;
|
searchRadius *= chainTargets;
|
||||||
|
|
||||||
|
WorldObject* chainSource = m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER) ? m_caster : target;
|
||||||
std::list<WorldObject*> tempTargets;
|
std::list<WorldObject*> tempTargets;
|
||||||
SearchAreaTargets(tempTargets, searchRadius, target, m_caster, objectType, selectType, condList);
|
SearchAreaTargets(tempTargets, searchRadius, chainSource, m_caster, objectType, selectType, condList);
|
||||||
tempTargets.remove(target);
|
tempTargets.remove(target);
|
||||||
|
|
||||||
// remove targets which are always invalid for chain spells
|
// remove targets which are always invalid for chain spells
|
||||||
// for some spells allow only chain targets in front of caster (swipe for example)
|
// for some spells allow only chain targets in front of caster (swipe for example)
|
||||||
if (!isBouncingFar)
|
if (!isBouncingFar)
|
||||||
{
|
tempTargets.remove_if([this](WorldObject* target) { return !m_caster->HasInArc(static_cast<float>(M_PI), target); });
|
||||||
for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();)
|
|
||||||
{
|
|
||||||
std::list<WorldObject*>::iterator checkItr = itr++;
|
|
||||||
if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr))
|
|
||||||
tempTargets.erase(checkItr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (chainTargets)
|
while (chainTargets)
|
||||||
{
|
{
|
||||||
@@ -2267,7 +2261,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
|||||||
if (Unit* unit = (*itr)->ToUnit())
|
if (Unit* unit = (*itr)->ToUnit())
|
||||||
{
|
{
|
||||||
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
|
uint32 deficit = unit->GetMaxHealth() - unit->GetHealth();
|
||||||
if (deficit > maxHPDeficit && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2))
|
if (deficit > maxHPDeficit && chainSource->IsWithinDist(unit, jumpRadius) && chainSource->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2))
|
||||||
{
|
{
|
||||||
foundItr = itr;
|
foundItr = itr;
|
||||||
maxHPDeficit = deficit;
|
maxHPDeficit = deficit;
|
||||||
@@ -2282,19 +2276,22 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
|
|||||||
{
|
{
|
||||||
if (foundItr == tempTargets.end())
|
if (foundItr == tempTargets.end())
|
||||||
{
|
{
|
||||||
if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
if ((!isBouncingFar || chainSource->IsWithinDist(*itr, jumpRadius)) && chainSource->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
||||||
foundItr = itr;
|
foundItr = itr;
|
||||||
}
|
}
|
||||||
else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
else if (chainSource->GetDistanceOrder(*itr, *foundItr) && chainSource->IsWithinLOSInMap(*itr, VMAP::ModelIgnoreFlags::M2))
|
||||||
foundItr = itr;
|
foundItr = itr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// not found any valid target - chain ends
|
// not found any valid target - chain ends
|
||||||
if (foundItr == tempTargets.end())
|
if (foundItr == tempTargets.end())
|
||||||
break;
|
break;
|
||||||
target = *foundItr;
|
|
||||||
|
if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER))
|
||||||
|
chainSource = *foundItr;
|
||||||
|
|
||||||
|
targets.push_back(*foundItr);
|
||||||
tempTargets.erase(foundItr);
|
tempTargets.erase(foundItr);
|
||||||
targets.push_back(target);
|
|
||||||
--chainTargets;
|
--chainTargets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -465,7 +465,7 @@ enum SpellAttr2 : uint32
|
|||||||
SPELL_ATTR2_ALWAYS_CAST_AS_UNIT = 0x00000200, // TITLE Unknown attribute 9@Attr2
|
SPELL_ATTR2_ALWAYS_CAST_AS_UNIT = 0x00000200, // TITLE Unknown attribute 9@Attr2
|
||||||
SPELL_ATTR2_SPECIAL_TAMING_FLAG = 0x00000400, // TITLE Unknown attribute 10@Attr2 DESCRIPTION Related to taming?
|
SPELL_ATTR2_SPECIAL_TAMING_FLAG = 0x00000400, // TITLE Unknown attribute 10@Attr2 DESCRIPTION Related to taming?
|
||||||
SPELL_ATTR2_NO_TARGET_PER_SECOND_COST = 0x00000800, // TITLE Health Funnel
|
SPELL_ATTR2_NO_TARGET_PER_SECOND_COST = 0x00000800, // TITLE Health Funnel
|
||||||
SPELL_ATTR2_CHAIN_FROM_CASTER = 0x00001000, // TITLE Unknown attribute 12@Attr2 DESCRIPTION Cleave, Heart Strike, Maul, Sunder Armor, Swipe
|
SPELL_ATTR2_CHAIN_FROM_CASTER = 0x00001000, // TITLE Chain from caster DESCRIPTION Cleave, Heart Strike, Maul, Sunder Armor, Swipe
|
||||||
SPELL_ATTR2_ENCHANT_OWN_ITEM_ONLY = 0x00002000, // TITLE Enchant persists when entering arena
|
SPELL_ATTR2_ENCHANT_OWN_ITEM_ONLY = 0x00002000, // TITLE Enchant persists when entering arena
|
||||||
SPELL_ATTR2_ALLOW_WHILE_INVISIBLE = 0x00004000, // TITLE Unknown attribute 14@Attr2
|
SPELL_ATTR2_ALLOW_WHILE_INVISIBLE = 0x00004000, // TITLE Unknown attribute 14@Attr2
|
||||||
SPELL_ATTR2_DO_NOT_CONSUME_IF_GAINED_DURING_CAST = 0x00008000, // TITLE Unused attribute 15@Attr2 DESCRIPTION not set in 3.3.5a
|
SPELL_ATTR2_DO_NOT_CONSUME_IF_GAINED_DURING_CAST = 0x00008000, // TITLE Unused attribute 15@Attr2 DESCRIPTION not set in 3.3.5a
|
||||||
|
|||||||
Reference in New Issue
Block a user