mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-03-01 06:55:59 +00:00
fix(Core/Spells): Implement TrinityCore spell_group and spell_group_stack_rules (#23346)
Co-authored-by: treeston <treeston.mmoc@gmail.com> Co-authored-by: Trisjdc <trisjdc@gmail.com> Co-authored-by: QAston <none@none> Co-authored-by: ariel- <ariel-@users.noreply.github.com> Co-authored-by: Shauren <shauren.trinity@gmail.com> Co-authored-by: Jelle Meeus <sogladev@gmail.com>
This commit is contained in:
@@ -19,7 +19,6 @@
|
||||
#include "ArenaSpectator.h"
|
||||
#include "BattlefieldMgr.h"
|
||||
#include "Battleground.h"
|
||||
#include "BattlegroundIC.h"
|
||||
#include "CharmInfo.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Common.h"
|
||||
@@ -33,7 +32,6 @@
|
||||
#include "InstanceScript.h"
|
||||
#include "Log.h"
|
||||
#include "LootMgr.h"
|
||||
#include "MapMgr.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Opcodes.h"
|
||||
@@ -41,6 +39,7 @@
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SpellAuraDefines.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
@@ -1240,11 +1239,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
|
||||
// Other special target selection goes here
|
||||
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
|
||||
{
|
||||
Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
|
||||
for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
|
||||
if ((*j)->IsAffectedOnSpell(m_spellInfo))
|
||||
maxTargets += (*j)->GetAmount();
|
||||
|
||||
maxTargets += m_caster->GetTotalAuraModifierByAffectMask(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS, m_spellInfo);
|
||||
Acore::Containers::RandomResize(targets, maxTargets);
|
||||
}
|
||||
|
||||
@@ -1327,11 +1322,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
|
||||
// Other special target selection goes here
|
||||
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
|
||||
{
|
||||
Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
|
||||
for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
|
||||
if ((*j)->IsAffectedOnSpell(m_spellInfo))
|
||||
maxTargets += (*j)->GetAmount();
|
||||
|
||||
maxTargets += m_caster->GetTotalAuraModifierByAffectMask(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS, m_spellInfo);
|
||||
Acore::Containers::RandomResize(targets, maxTargets);
|
||||
}
|
||||
|
||||
@@ -6076,6 +6067,8 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
}
|
||||
}
|
||||
|
||||
uint8 approximateAuraEffectMask = 0;
|
||||
uint8 nonAuraEffectMask = 0;
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
// for effects of spells that have only one target
|
||||
@@ -6561,6 +6554,11 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_spellInfo->Effects[i].IsAura())
|
||||
approximateAuraEffectMask |= 1 << i;
|
||||
else if (m_spellInfo->Effects[i].IsEffect())
|
||||
nonAuraEffectMask |= 1 << i;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
@@ -6723,6 +6721,13 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// check if target already has the same type, but more powerful aura
|
||||
if (!nonAuraEffectMask && (approximateAuraEffectMask & (1 << i)) && !m_spellInfo->IsTargetingArea())
|
||||
if (Unit* target = m_targets.GetUnitTarget())
|
||||
if (!target->IsHighestExclusiveAuraEffect(m_spellInfo, AuraType(m_spellInfo->Effects[i].ApplyAuraName),
|
||||
m_spellInfo->Effects[i].CalcValue(m_caster, &m_spellValue->EffectBasePoints[i]), approximateAuraEffectMask, false))
|
||||
return SPELL_FAILED_AURA_BOUNCED;
|
||||
}
|
||||
|
||||
// check trade slot case (last, for allow catch any another cast problems)
|
||||
@@ -6973,26 +6978,35 @@ bool Spell::CanAutoCast(Unit* target)
|
||||
{
|
||||
ObjectGuid targetguid = target->GetGUID();
|
||||
|
||||
for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
|
||||
for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects())
|
||||
{
|
||||
if (m_spellInfo->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA)
|
||||
if (!spellEffectInfo.IsAura())
|
||||
continue;
|
||||
|
||||
AuraType const& auraType = spellEffectInfo.ApplyAuraName;
|
||||
Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(auraType);
|
||||
for (Unit::AuraEffectList::const_iterator auraIt = auras.begin(); auraIt != auras.end(); ++auraIt)
|
||||
{
|
||||
if (m_spellInfo->StackAmount <= 1)
|
||||
{
|
||||
if (target->HasAuraEffect(m_spellInfo->Id, j))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AuraEffect* aureff = target->GetAuraEffect(m_spellInfo->Id, j))
|
||||
if (aureff->GetBase()->GetStackAmount() >= m_spellInfo->StackAmount)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (m_spellInfo->Effects[j].IsAreaAuraEffect())
|
||||
{
|
||||
if (target->HasAuraEffect(m_spellInfo->Id, j))
|
||||
if (GetSpellInfo()->Id == (*auraIt)->GetSpellInfo()->Id)
|
||||
return false;
|
||||
|
||||
switch (sSpellMgr->CheckSpellGroupStackRules(GetSpellInfo(), (*auraIt)->GetSpellInfo()))
|
||||
{
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE:
|
||||
return false;
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER:
|
||||
if (GetCaster() == (*auraIt)->GetCaster())
|
||||
return false;
|
||||
break;
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT: // this one has further checks, but i don't think they're necessary for autocast logic
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST:
|
||||
if (abs(spellEffectInfo.BasePoints) <= abs((*auraIt)->GetAmount()))
|
||||
return false;
|
||||
break;
|
||||
case SPELL_GROUP_STACK_RULE_DEFAULT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user