Core/Spells: Fixed spell range check

Closes #17060
This commit is contained in:
Shauren authored and Aokromes committed 2016-07-20 18:26:18 +02:00
1 parent 4305129672
commit fa7026cee3
4 files changed
+63 -40

No files matched your search

+1 -7
View File
@@ -462,12 +462,6 @@ void Unit::resetAttackTimer(WeaponAttackType type)
m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]);
}
float Unit::GetMeleeReach() const
{
float reach = m_floatValues[UNIT_FIELD_COMBATREACH];
return reach > MIN_MELEE_REACH ? reach : MIN_MELEE_REACH;
}
bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const
{
if (!obj || !IsInMap(obj) || !IsInPhase(obj))
@@ -494,7 +488,7 @@ bool Unit::IsWithinMeleeRange(const Unit* obj, float dist) const
float dz = GetPositionZMinusOffset() - obj->GetPositionZMinusOffset();
float distsq = dx*dx + dy*dy + dz*dz;
float sizefactor = GetMeleeReach() + obj->GetMeleeReach();
float sizefactor = GetCombatReach() + obj->GetCombatReach() + 4.0f / 3.0f;
float maxdist = dist + sizefactor;
return distsq < maxdist * maxdist;
-1
View File
@@ -1307,7 +1307,6 @@ class Unit : public WorldObject
bool CanDualWield() const { return m_canDualWield; }
virtual void SetCanDualWield(bool value) { m_canDualWield = value; }
float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; }
float GetMeleeReach() const;
bool IsWithinCombatRange(const Unit* obj, float dist2compare) const;
bool IsWithinMeleeRange(const Unit* obj, float dist = MELEE_RANGE) const;
void GetRandomContactPoint(const Unit* target, float &x, float &y, float &z, float distance2dMin, float distance2dMax) const;
+61 -31
View File
@@ -5928,43 +5928,73 @@ SpellCastResult Spell::CheckRange(bool strict)
if (!strict && m_casttime == 0)
return SPELL_CAST_OK;
uint32 range_type = 0;
if (m_spellInfo->RangeEntry)
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)
{
// 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->RangeEntry->ID == 1)
return SPELL_CAST_OK;
if (m_spellInfo->RangeEntry->type & SPELL_RANGE_MELEE)
{
rangeMod = m_caster->GetCombatReach() + 4.0f / 3.0f;
if (target)
rangeMod += target->GetCombatReach();
else
rangeMod += m_caster->GetCombatReach();
range_type = m_spellInfo->RangeEntry->type;
rangeMod = std::max(rangeMod, NOMINAL_MELEE_RANGE);
}
else
{
float meleeRange = 0.0f;
if (m_spellInfo->RangeEntry->type & 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->type & SPELL_RANGE_RANGED))
minRange += rangeMod;
}
}
if (target && m_caster->isMoving() && target->isMoving() && !m_caster->IsWalking() && !target->IsWalking() &&
(m_spellInfo->RangeEntry->type & 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()->RangedModRange * 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;
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->IsInDist(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->IsInDist(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))
@@ -5973,10 +6003,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->IsInDist(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->IsInDist(m_targets.GetDstPos(), minRange))
return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT;
}
return SPELL_CAST_OK;
@@ -298,7 +298,7 @@ public:
if (Blind_Timer <= diff)
{
std::list<Unit*> targets;
SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetMeleeReach()*5, true);
SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetCombatReach()*5, true);
for (std::list<Unit*>::const_iterator i = targets.begin(); i != targets.end(); ++i)
if (!me->IsWithinMeleeRange(*i))
{