diff options
-rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 92 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp | 2 |
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)) { |