diff options
| author | Shauren <shauren.trinity@gmail.com> | 2016-07-06 00:05:13 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2016-07-06 00:05:13 +0200 |
| commit | 70137b8f3aae7c875f1fc0b1643d80aece933104 (patch) | |
| tree | 2ffc5d94bca4988dd5ba5af1a4bd3f077de5e238 /src/server/game/Spells/Spell.cpp | |
| parent | f7883bd5251a759da1ca8be3ba6f6cead36723ec (diff) | |
| parent | a7fcae93280d5d8010c4fe8139ce1925a92c8744 (diff) | |
Merge branch '6.x' of https://github.com/TrinityCore/TrinityCore into legion
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 130 |
1 files changed, 86 insertions, 44 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index c69c2ebea5f..de5d96f9894 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -591,7 +591,7 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)), focusObject = NULL; m_castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, m_caster->GetMapId(), m_spellInfo->Id, m_caster->GetMap()->GenerateLowGuid<HighGuid::Cast>()); memset(m_misc.Raw.Data, 0, sizeof(m_misc.Raw.Data)); - m_SpellVisual = m_spellInfo->GetSpellXSpellVisualId(caster->GetMap()->GetDifficultyID()); + m_SpellVisual = caster->GetCastSpellXSpellVisualId(m_spellInfo); m_preCastSpell = 0; m_triggeredByAuraSpell = NULL; m_spellAura = NULL; @@ -4366,7 +4366,7 @@ void Spell::SendChannelStart(uint32 duration) m_caster->SetChannelObjectGuid(channelTarget); m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, m_spellInfo->Id); - m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL_X_SPELL_VISUAL, m_spellInfo->GetSpellXSpellVisualId(m_caster->GetMap()->GetDifficultyID())); + m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL_X_SPELL_VISUAL, m_SpellVisual); } void Spell::SendResurrectRequest(Player* target) @@ -5657,7 +5657,7 @@ SpellCastResult Spell::CheckCasterAuras() const Unit::AuraEffectList const& stunAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_STUN); for (Unit::AuraEffectList::const_iterator i = stunAuras.begin(); i != stunAuras.end(); ++i) { - if ((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() && !((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() & (1<<MECHANIC_STUN))) + if ((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() && !((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() & (1 << MECHANIC_STUN))) { foundNotStun = true; break; @@ -5673,10 +5673,12 @@ SpellCastResult Spell::CheckCasterAuras() const prevented_reason = SPELL_FAILED_CONFUSED; else if (unitflag & UNIT_FLAG_FLEEING && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED)) prevented_reason = SPELL_FAILED_FLEEING; - else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) prevented_reason = SPELL_FAILED_SILENCED; - else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY) + else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY) prevented_reason = SPELL_FAILED_PACIFIED; + else if (m_caster->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_NO_ACTIONS) && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_NO_ACTIONS) + prevented_reason = SPELL_FAILED_NO_ACTIONS; // Attr must make flag drop spell totally immune from all effects if (prevented_reason != SPELL_CAST_OK) @@ -5722,9 +5724,9 @@ SpellCastResult Spell::CheckCasterAuras() const case SPELL_AURA_MOD_SILENCE: case SPELL_AURA_MOD_PACIFY: case SPELL_AURA_MOD_PACIFY_SILENCE: - if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY) + if (m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY) return SPELL_FAILED_PACIFIED; - else if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + else if (m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) return SPELL_FAILED_SILENCED; break; default: break; @@ -5830,43 +5832,76 @@ SpellCastResult Spell::CheckRange(bool strict) if (!strict && m_casttime == 0) return SPELL_CAST_OK; - uint32 range_type = 0; + Unit* target = m_targets.GetUnitTarget(); + float minRange = 0.0f; + float maxRange = 0.0f; + float rangeMod = 0.0f; + if (strict && IsNextMeleeSwingSpell()) + maxRange = 100.0f; + else if (m_spellInfo->RangeEntry) + { + if (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_MELEE) + { + rangeMod = m_caster->GetCombatReach() + 4.0f / 3.0f; + if (target) + rangeMod += target->GetCombatReach(); + else + rangeMod += m_caster->GetCombatReach(); - if (m_spellInfo->RangeEntry) - { - // check needed by 68766 51693 - both spells are cast on enemies and have 0 max range - // these are triggered by other spells - possibly we should omit range check in that case? - if (m_spellInfo->RangeIndex == 1) - return SPELL_CAST_OK; + rangeMod = std::max(rangeMod, NOMINAL_MELEE_RANGE); + } + else + { + float meleeRange = 0.0f; + if (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_RANGED) + { + meleeRange = m_caster->GetCombatReach() + 4.0f / 3.0f; + if (target) + meleeRange += target->GetCombatReach(); + else + meleeRange += m_caster->GetCombatReach(); + + meleeRange = std::max(meleeRange, NOMINAL_MELEE_RANGE); + } + + minRange = m_caster->GetSpellMinRangeForTarget(target, m_spellInfo) + meleeRange; + maxRange = m_caster->GetSpellMaxRangeForTarget(target, m_spellInfo); + + if (target || m_targets.GetCorpseTarget()) + { + rangeMod = m_caster->GetCombatReach(); + if (target) + rangeMod += target->GetCombatReach(); + + if (minRange > 0.0f && !(m_spellInfo->RangeEntry->Flags & SPELL_RANGE_RANGED)) + minRange += rangeMod; + } + } - range_type = m_spellInfo->RangeEntry->Flags; + if (target && m_caster->isMoving() && target->isMoving() && !m_caster->IsWalking() && !target->IsWalking() && + (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_MELEE || target->GetTypeId() == TYPEID_PLAYER)) + rangeMod += 5.0f / 3.0f; } - Unit* target = m_targets.GetUnitTarget(); - float max_range = m_caster->GetSpellMaxRangeForTarget(target, m_spellInfo); - float min_range = m_caster->GetSpellMinRangeForTarget(target, m_spellInfo); + if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) && m_caster->GetTypeId() == TYPEID_PLAYER) + if (Item* ranged = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK, true)) + maxRange *= ranged->GetTemplate()->GetRangedModRange() * 0.01f; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, maxRange, this); + + maxRange += rangeMod; + + minRange *= minRange; + maxRange *= maxRange; if (target && target != m_caster) { - if (range_type == SPELL_RANGE_MELEE) - { - // Because of lag, we can not check too strictly here. - if (!m_caster->IsWithinMeleeRange(target, max_range)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - } - else if (!m_caster->IsWithinCombatRange(target, max_range)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; //0x5A; + if (m_caster->GetExactDistSq(target) > maxRange) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - if (range_type == SPELL_RANGE_RANGED) - { - if (m_caster->IsWithinMeleeRange(target)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_TOO_CLOSE : SPELL_FAILED_DONT_REPORT; - } - else if (min_range && m_caster->IsWithinCombatRange(target, min_range)) // skip this check if min_range = 0 - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_TOO_CLOSE : SPELL_FAILED_DONT_REPORT; + if (minRange > 0.0f && m_caster->GetExactDistSq(target) < minRange) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; if (m_caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc(static_cast<float>(M_PI), target)) @@ -5875,10 +5910,10 @@ SpellCastResult Spell::CheckRange(bool strict) if (m_targets.HasDst() && !m_targets.HasTraj()) { - if (!m_caster->IsWithinDist3d(m_targets.GetDstPos(), max_range)) - return SPELL_FAILED_OUT_OF_RANGE; - if (min_range && m_caster->IsWithinDist3d(m_targets.GetDstPos(), min_range)) - return SPELL_FAILED_TOO_CLOSE; + if (m_caster->GetExactDistSq(m_targets.GetDstPos()) > maxRange) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; + if (minRange > 0.0f && m_caster->GetExactDistSq(m_targets.GetDstPos()) < minRange) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; } return SPELL_CAST_OK; @@ -6669,7 +6704,7 @@ bool Spell::IsAutoActionResetSpell() const bool Spell::IsNeedSendToClient() const { - return m_spellInfo->GetSpellXSpellVisualId(m_caster->GetMap()->GetDifficultyID()) || m_spellInfo->IsChanneled() || + return m_SpellVisual || m_spellInfo->IsChanneled() || (m_spellInfo->HasAttribute(SPELL_ATTR8_AURA_SEND_AMOUNT)) || m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered()); } @@ -6730,8 +6765,8 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) return true; // spell is deletable, finish event } // event will be re-added automatically at the end of routine) - } break; - + break; + } case SPELL_STATE_DELAYED: { // first, check, if we have just started @@ -6781,17 +6816,24 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) { // delaying had just started, record the moment m_Spell->SetDelayStart(e_time); + // handle effects on caster if the spell has travel time but also affects the caster in some way + if (!m_Spell->m_targets.HasDst()) + { + uint64 n_offset = m_Spell->handle_delayed(0); + ASSERT(n_offset == m_Spell->GetDelayMoment()); + } // re-plan the event for the delay moment m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + m_Spell->GetDelayMoment(), false); return false; // event not complete } - } break; - + break; + } default: { // all other states // event will be re-added automatically at the end of routine) - } break; + break; + } } // spell processing not complete, plan event on the next update interval |
