mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-04 22:07:52 +00:00
fix(Core/Unit): improve leeway bonus range and speed calculations (#25958)
Co-authored-by: GuybrushGit <turinpt3@gmail.com> Co-authored-by: lightshope <lh@lightshope.org> Co-authored-by: sidsukana <pgsilent@gmail.com> Co-authored-by: ratkosrb <ratkomladic2@abv.bg>
This commit is contained in:
@@ -1753,6 +1753,56 @@ float WorldObject::GetSightRange(WorldObject const* target) const
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float WorldObject::GetLeewayBonusRangeForTargets(Player const* player, Unit const* target)
|
||||
{
|
||||
if (!player || !target)
|
||||
return 0.0f;
|
||||
|
||||
constexpr uint32 leewayMoveFlags = MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_FALLING;
|
||||
if (player->HasUnitMovementFlag(leewayMoveFlags) && !player->IsWalking() && target->HasUnitMovementFlag(leewayMoveFlags) && !target->IsWalking())
|
||||
return LEEWAY_BONUS_RANGE;
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float WorldObject::GetLeewayBonusRange(Unit const* target) const
|
||||
{
|
||||
if (!target)
|
||||
return 0.0f;
|
||||
|
||||
if (Player const* player = ToPlayer())
|
||||
return GetLeewayBonusRangeForTargets(player, target);
|
||||
|
||||
if (Player const* playerTarget = target->ToPlayer())
|
||||
return GetLeewayBonusRangeForTargets(playerTarget, ToUnit());
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float WorldObject::GetLeewayBonusRadius() const
|
||||
{
|
||||
if (Player const* player = ToPlayer())
|
||||
{
|
||||
bool hasLeewayMovement = false;
|
||||
|
||||
if (player->HasUnitState(UNIT_STATE_JUMPING) || player->HasUnitMovementFlag(MOVEMENTFLAG_FALLING))
|
||||
hasLeewayMovement = true;
|
||||
else
|
||||
{
|
||||
float speedXY = (player->m_movementInfo.jump.xyspeed > 0.0f)
|
||||
? player->m_movementInfo.jump.xyspeed
|
||||
: player->GetSpeed(player->IsWalking() ? MOVE_WALK : MOVE_RUN);
|
||||
|
||||
hasLeewayMovement = speedXY > LEEWAY_MIN_MOVE_SPEED;
|
||||
}
|
||||
|
||||
if (hasLeewayMovement)
|
||||
return LEEWAY_BONUS_RANGE;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, bool distanceCheck, bool checkAlert) const
|
||||
{
|
||||
if (this == obj)
|
||||
|
||||
@@ -605,6 +605,11 @@ public:
|
||||
[[nodiscard]] float GetGridActivationRange() const;
|
||||
[[nodiscard]] float GetVisibilityRange() const;
|
||||
virtual float GetSightRange(WorldObject const* target = nullptr) const;
|
||||
|
||||
[[nodiscard]] static float GetLeewayBonusRangeForTargets(Player const* player, Unit const* target);
|
||||
[[nodiscard]] float GetLeewayBonusRange(Unit const* target) const;
|
||||
[[nodiscard]] float GetLeewayBonusRadius() const;
|
||||
|
||||
//bool CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth = false, bool distanceCheck = false) const;
|
||||
bool CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth = false, bool distanceCheck = false, bool checkAlert = false) const;
|
||||
|
||||
|
||||
@@ -792,8 +792,7 @@ bool Unit::IsWithinMeleeRange(Unit const* obj, float dist) const
|
||||
|
||||
float maxdist = dist + GetMeleeRange(obj);
|
||||
|
||||
if ((IsPlayer() || obj->IsPlayer()) && HasLeewayMovement() && obj->HasLeewayMovement())
|
||||
maxdist += LEEWAY_BONUS_RANGE;
|
||||
maxdist += GetLeewayBonusRange(obj);
|
||||
|
||||
return distsq < maxdist * maxdist;
|
||||
}
|
||||
|
||||
@@ -1729,12 +1729,6 @@ public:
|
||||
UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED) && !GetOwnerGUID();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool HasLeewayMovement() const
|
||||
{
|
||||
return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_FALLING)
|
||||
&& !IsWalking();
|
||||
}
|
||||
|
||||
void KnockbackFrom(float x, float y, float speedXY, float speedZ);
|
||||
void JumpTo(float speedXY, float speedZ, bool forward = true);
|
||||
void JumpTo(WorldObject* obj, float speedZ);
|
||||
|
||||
@@ -1248,6 +1248,9 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
|
||||
}
|
||||
|
||||
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
|
||||
|
||||
radius += m_caster->GetLeewayBonusRadius();
|
||||
|
||||
if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList))
|
||||
{
|
||||
Acore::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList);
|
||||
@@ -1335,6 +1338,17 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
|
||||
// Xinef: the distance should be increased by caster size, it is neglected in latter calculations
|
||||
std::list<WorldObject*> targets;
|
||||
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
|
||||
switch (targetType.GetTarget())
|
||||
{
|
||||
case TARGET_UNIT_SRC_AREA_ENEMY:
|
||||
case TARGET_UNIT_CASTER_AREA_PARTY:
|
||||
case TARGET_UNIT_CASTER_AREA_RAID:
|
||||
radius += m_caster->GetLeewayBonusRadius();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions, Acore::WorldObjectSpellAreaTargetSearchReason::Area);
|
||||
|
||||
CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
|
||||
@@ -7088,8 +7102,9 @@ SpellCastResult Spell::CheckRange(bool strict)
|
||||
if (range_type == SPELL_RANGE_MELEE)
|
||||
{
|
||||
float real_max_range = max_range;
|
||||
if (!m_caster->IsCreature() && m_caster->HasLeewayMovement() && target->HasLeewayMovement())
|
||||
real_max_range -= MIN_MELEE_REACH; // Because of lag, we can not check too strictly here (is only used if both caster and target are moving)
|
||||
|
||||
if (m_caster->GetLeewayBonusRange(target) > 0.0f)
|
||||
real_max_range -= MIN_MELEE_REACH; // less strict when leeway applies
|
||||
else
|
||||
real_max_range -= 2 * MIN_MELEE_REACH;
|
||||
|
||||
@@ -7124,7 +7139,7 @@ SpellCastResult Spell::CheckRange(bool strict)
|
||||
|
||||
if (m_targets.HasDst() && !m_targets.HasTraj())
|
||||
{
|
||||
if (!m_caster->IsWithinDist3d(m_targets.GetDstPos(), max_range))
|
||||
if (!m_caster->IsWithinDist3d(m_targets.GetDstPos(), max_range + m_caster->GetLeewayBonusRadius()))
|
||||
return SPELL_FAILED_OUT_OF_RANGE;
|
||||
if (min_range && m_caster->IsWithinDist3d(m_targets.GetDstPos(), min_range))
|
||||
return SPELL_FAILED_TOO_CLOSE;
|
||||
|
||||
Reference in New Issue
Block a user