aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h1
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp8
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Spells/Spell.cpp92
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp2
5 files changed, 64 insertions, 40 deletions
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h
index d69f1c88845..76c129d325a 100644
--- a/src/server/game/Entities/Item/ItemTemplate.h
+++ b/src/server/game/Entities/Item/ItemTemplate.h
@@ -680,6 +680,7 @@ struct TC_GAME_API ItemTemplate
uint32 GetScalingStatDistribution() const { return ExtendedData->ScalingStatDistribution; }
uint32 GetDamageType() const { return ExtendedData->DamageType; }
uint32 GetDelay() const { return ExtendedData->Delay; }
+ float GetRangedModRange() const { return ExtendedData->RangedModRange; }
ItemBondingType GetBonding() const { return ItemBondingType(ExtendedData->Bonding); }
char const* GetName(LocaleConstant locale) const;
uint32 GetPageText() const { return ExtendedData->PageText; }
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index f65449dbf74..c408d4390cd 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -484,12 +484,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))
@@ -516,7 +510,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;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 2ee0ea8873a..962d9549f2c 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1365,7 +1365,6 @@ class TC_GAME_API 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;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index a09d97b8e68..2b59926fa33 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5924,43 +5924,73 @@ 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->RangeEntry->ID == 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);
- range_type = m_spellInfo->RangeEntry->Flags;
+ 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;
+ }
+ }
+
+ 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;
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))
@@ -5969,10 +5999,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;
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp
index b87c836c2a4..84ee5cd97db 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp
@@ -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))
{