diff options
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 98 |
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? |