aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/Spell.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
-rw-r--r--src/server/game/Spells/Spell.cpp98
1 files changed, 77 insertions, 21 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 2a677dc50d1..867753ecfb6 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -420,6 +420,16 @@ void SpellCastTargets::RemoveDst()
m_targetMask &= ~(TARGET_FLAG_DEST_LOCATION);
}
+bool SpellCastTargets::HasSrc() const
+{
+ return (GetTargetMask() & TARGET_FLAG_SOURCE_LOCATION) != 0;
+}
+
+bool SpellCastTargets::HasDst() const
+{
+ return (GetTargetMask() & TARGET_FLAG_DEST_LOCATION) != 0;
+}
+
void SpellCastTargets::Update(Unit* caster)
{
m_objectTarget = !m_objectTargetGUID.IsEmpty() ? ((m_objectTargetGUID == caster->GetGUID()) ? caster : ObjectAccessor::GetWorldObject(*caster, m_objectTargetGUID)) : NULL;
@@ -498,9 +508,22 @@ SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto)
AuraStackAmount = 1;
}
+class TC_GAME_API SpellEvent : public BasicEvent
+{
+public:
+ SpellEvent(Spell* spell);
+ virtual ~SpellEvent();
+
+ virtual bool Execute(uint64 e_time, uint32 p_time) override;
+ virtual void Abort(uint64 e_time) override;
+ virtual bool IsDeletable() const override;
+protected:
+ Spell* m_Spell;
+};
+
Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) :
m_spellInfo(info), m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster),
-m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster))
+m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo))
{
_effects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID());
@@ -3927,10 +3950,10 @@ void Spell::SendSpellStart()
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet()))
- && std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellInfo::CostData const& cost) { return cost.Power != POWER_HEALTH; }) != m_powerCost.end())
+ && std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellPowerCost const& cost) { return cost.Power != POWER_HEALTH; }) != m_powerCost.end())
castFlags |= CAST_FLAG_POWER_LEFT_SELF;
- if (std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellInfo::CostData const& cost) { return cost.Power == POWER_RUNES; }) != m_powerCost.end())
+ if (std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellPowerCost const& cost) { return cost.Power == POWER_RUNES; }) != m_powerCost.end())
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
WorldPackets::Spells::SpellStart packet;
@@ -3954,7 +3977,7 @@ void Spell::SendSpellStart()
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
{
- for (SpellInfo::CostData const& cost : m_powerCost)
+ for (SpellPowerCost const& cost : m_powerCost)
{
WorldPackets::Spells::SpellPowerData powerData;
powerData.Type = cost.Power;
@@ -4028,12 +4051,12 @@ void Spell::SendSpellGo()
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsPet()))
- && std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellInfo::CostData const& cost) { return cost.Power != POWER_HEALTH; }) != m_powerCost.end())
+ && std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellPowerCost const& cost) { return cost.Power != POWER_HEALTH; }) != m_powerCost.end())
castFlags |= CAST_FLAG_POWER_LEFT_SELF; // should only be sent to self, but the current messaging doesn't make that possible
if ((m_caster->GetTypeId() == TYPEID_PLAYER)
&& (m_caster->getClass() == CLASS_DEATH_KNIGHT)
- && std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellInfo::CostData const& cost) { return cost.Power == POWER_RUNES; }) != m_powerCost.end()
+ && std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellPowerCost const& cost) { return cost.Power == POWER_RUNES; }) != m_powerCost.end()
&& !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST))
{
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
@@ -4072,7 +4095,7 @@ void Spell::SendSpellGo()
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
{
- for (SpellInfo::CostData const& cost : m_powerCost)
+ for (SpellPowerCost const& cost : m_powerCost)
{
WorldPackets::Spells::SpellPowerData powerData;
powerData.Type = cost.Power;
@@ -4503,7 +4526,7 @@ void Spell::TakePower()
return;
}
- for (SpellInfo::CostData& cost : m_powerCost)
+ for (SpellPowerCost& cost : m_powerCost)
{
Powers powerType = Powers(cost.Power);
bool hit = true;
@@ -4563,7 +4586,7 @@ void Spell::TakePower()
SpellCastResult Spell::CheckRuneCost()
{
- auto runeCost = std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellInfo::CostData const& cost) { return cost.Power == POWER_RUNES; });
+ auto runeCost = std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellPowerCost const& cost) { return cost.Power == POWER_RUNES; });
if (runeCost == m_powerCost.end())
return SPELL_CAST_OK;
@@ -4593,7 +4616,7 @@ void Spell::TakeRunePower(bool didHit)
Player* player = m_caster->ToPlayer();
m_runesState = player->GetRunesState(); // store previous state
- int32 runeCost = std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellInfo::CostData const& cost)
+ int32 runeCost = std::find_if(m_powerCost.begin(), m_powerCost.end(), [](SpellPowerCost const& cost)
{
return cost.Power == POWER_RUNES;
})->Amount;
@@ -5242,26 +5265,27 @@ SpellCastResult Spell::CheckCast(bool strict)
float objSize = target->GetObjectSize();
float range = m_spellInfo->GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict
- m_preGeneratedPath.SetPathLengthLimit(range);
+ m_preGeneratedPath = Trinity::make_unique<PathGenerator>(m_caster);
+ m_preGeneratedPath->SetPathLengthLimit(range);
// first try with raycast, if it fails fall back to normal path
float targetObjectSize = std::min(target->GetObjectSize(), 4.0f);
- bool result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, true);
- if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT)
+ bool result = m_preGeneratedPath->CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, true);
+ if (m_preGeneratedPath->GetPathType() & PATHFIND_SHORT)
return SPELL_FAILED_OUT_OF_RANGE;
- else if (!result || m_preGeneratedPath.GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE))
+ else if (!result || m_preGeneratedPath->GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE))
{
- result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, false);
- if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT)
+ result = m_preGeneratedPath->CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, false);
+ if (m_preGeneratedPath->GetPathType() & PATHFIND_SHORT)
return SPELL_FAILED_OUT_OF_RANGE;
- else if (!result || m_preGeneratedPath.GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE))
+ else if (!result || m_preGeneratedPath->GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE))
return SPELL_FAILED_NOPATH;
- else if (m_preGeneratedPath.IsInvalidDestinationZ(target)) // Check position z, if not in a straight line
+ else if (m_preGeneratedPath->IsInvalidDestinationZ(target)) // Check position z, if not in a straight line
return SPELL_FAILED_NOPATH;
}
- else if (m_preGeneratedPath.IsInvalidDestinationZ(target)) // Check position z, if in a straight line
+ else if (m_preGeneratedPath->IsInvalidDestinationZ(target)) // Check position z, if in a straight line
return SPELL_FAILED_NOPATH;
- m_preGeneratedPath.ReducePathLenghtByDist(objSize); // move back
+ m_preGeneratedPath->ReducePathLenghtByDist(objSize); // move back
}
break;
}
@@ -5902,6 +5926,11 @@ SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules()
return SPELL_CAST_OK;
}
+int32 Spell::CalculateDamage(uint8 i, Unit const* target, float* var /*= nullptr*/) const
+{
+ return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_spellValue->EffectBasePoints[i], var, m_castItemLevel);
+}
+
bool Spell::CanAutoCast(Unit* target)
{
if (!target)
@@ -5961,6 +5990,18 @@ bool Spell::CanAutoCast(Unit* target)
return false;
}
+void Spell::CheckSrc()
+{
+ if (!m_targets.HasSrc())
+ m_targets.SetSrc(*m_caster);
+}
+
+void Spell::CheckDst()
+{
+ if (!m_targets.HasDst())
+ m_targets.SetDst(*m_caster);
+}
+
SpellCastResult Spell::CheckRange(bool strict)
{
// Don't check for instant cast spells
@@ -6059,7 +6100,7 @@ SpellCastResult Spell::CheckPower()
if (m_CastItem)
return SPELL_CAST_OK;
- for (SpellInfo::CostData const& cost : m_powerCost)
+ for (SpellPowerCost const& cost : m_powerCost)
{
// health as power used - need check health amount
if (cost.Power == POWER_HEALTH)
@@ -6801,6 +6842,21 @@ bool Spell::IsNextMeleeSwingSpell() const
return m_spellInfo->HasAttribute(SPELL_ATTR0_ON_NEXT_SWING);
}
+bool Spell::IsTriggered() const
+{
+ return (_triggeredCastFlags & TRIGGERED_FULL_MASK) != 0;
+}
+
+bool Spell::IsIgnoringCooldowns() const
+{
+ return (_triggeredCastFlags & TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD) != 0;
+}
+
+bool Spell::IsChannelActive() const
+{
+ return m_caster->GetUInt32Value(UNIT_CHANNEL_SPELL) != 0;
+}
+
bool Spell::IsAutoActionResetSpell() const
{
/// @todo changed SPELL_INTERRUPT_FLAG_AUTOATTACK -> SPELL_INTERRUPT_FLAG_INTERRUPT to fix compile - is this check correct at all?