aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/Spell.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-07-06 00:05:13 +0200
committerShauren <shauren.trinity@gmail.com>2016-07-06 00:05:13 +0200
commit70137b8f3aae7c875f1fc0b1643d80aece933104 (patch)
tree2ffc5d94bca4988dd5ba5af1a4bd3f077de5e238 /src/server/game/Spells/Spell.cpp
parentf7883bd5251a759da1ca8be3ba6f6cead36723ec (diff)
parenta7fcae93280d5d8010c4fe8139ce1925a92c8744 (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.cpp130
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