fix(Core/Leash): Improve leashing behavior and timer handling (#22525)
This commit is contained in:
committed by
GitHub
parent
40c58123b1
commit
67aa022dbf
@@ -801,7 +801,7 @@ void Creature::Update(uint32 diff)
|
|||||||
// Periodically check if able to move, if not, extend leash timer
|
// Periodically check if able to move, if not, extend leash timer
|
||||||
if (diff >= m_extendLeashTime)
|
if (diff >= m_extendLeashTime)
|
||||||
{
|
{
|
||||||
if (!CanFreeMove())
|
if (HasUnitState(UNIT_STATE_LOST_CONTROL))
|
||||||
UpdateLeashExtensionTime();
|
UpdateLeashExtensionTime();
|
||||||
m_extendLeashTime = EXTEND_LEASH_CHECK_INTERVAL;
|
m_extendLeashTime = EXTEND_LEASH_CHECK_INTERVAL;
|
||||||
}
|
}
|
||||||
@@ -2685,10 +2685,11 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool skipDistCheck) const
|
|||||||
|
|
||||||
float dist = sWorld->getFloatConfig(CONFIG_CREATURE_LEASH_RADIUS);
|
float dist = sWorld->getFloatConfig(CONFIG_CREATURE_LEASH_RADIUS);
|
||||||
|
|
||||||
if (GetCharmerOrOwner())
|
if (Unit* unit = GetCharmerOrOwner())
|
||||||
{
|
{
|
||||||
dist = std::min<float>(GetMap()->GetVisibilityRange() + GetObjectSize() * 2, 150.0f);
|
float visibilityDist = std::min<float>(GetMap()->GetVisibilityRange() + GetObjectSize() * 2, 150.0f);
|
||||||
return IsWithinDist(victim, dist);
|
if (!victim->IsWithinDist(unit, visibilityDist))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dist)
|
if (!dist)
|
||||||
|
|||||||
@@ -4185,6 +4185,15 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id, bool withI
|
|||||||
InterruptSpell(CURRENT_CHANNELED_SPELL, true, true, bySelf);
|
InterruptSpell(CURRENT_CHANNELED_SPELL, true, true, bySelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spell* Unit::GetFirstCurrentCastingSpell() const
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
|
||||||
|
if (m_currentSpells[i] && m_currentSpells[i]->GetCastTimeRemaining() > 0)
|
||||||
|
return m_currentSpells[i];
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const
|
Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
|
for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
|
||||||
@@ -10412,8 +10421,29 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
|||||||
if (meleeAttack)
|
if (meleeAttack)
|
||||||
AddUnitState(UNIT_STATE_MELEE_ATTACKING);
|
AddUnitState(UNIT_STATE_MELEE_ATTACKING);
|
||||||
|
|
||||||
|
Unit* owner = GetCharmerOrOwner();
|
||||||
|
Creature* ownerCreature = owner ? owner->ToCreature() : nullptr;
|
||||||
|
Creature* controlledCreatureWithSameVictim = nullptr;
|
||||||
|
if (creature && !m_Controlled.empty())
|
||||||
|
{
|
||||||
|
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->ToCreature() && (*itr)->GetVictim() == victim)
|
||||||
|
{
|
||||||
|
controlledCreatureWithSameVictim = (*itr)->ToCreature();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Share leash timer with controlled unit
|
||||||
|
if (controlledCreatureWithSameVictim)
|
||||||
|
creature->SetLastLeashExtensionTimePtr(controlledCreatureWithSameVictim->GetLastLeashExtensionTimePtr());
|
||||||
|
// Share leash timer with owner
|
||||||
|
else if (creature && ownerCreature && ownerCreature->GetVictim() == victim)
|
||||||
|
creature->SetLastLeashExtensionTimePtr(ownerCreature->GetLastLeashExtensionTimePtr());
|
||||||
// Update leash timer when attacking creatures
|
// Update leash timer when attacking creatures
|
||||||
if (victim->IsCreature())
|
else if (victim->IsCreature())
|
||||||
victim->ToCreature()->UpdateLeashExtensionTime();
|
victim->ToCreature()->UpdateLeashExtensionTime();
|
||||||
|
|
||||||
// set position before any AI calls/assistance
|
// set position before any AI calls/assistance
|
||||||
|
|||||||
@@ -1494,6 +1494,7 @@ public:
|
|||||||
[[nodiscard]] Player* GetSpellModOwner() const;
|
[[nodiscard]] Player* GetSpellModOwner() const;
|
||||||
[[nodiscard]] Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; }
|
[[nodiscard]] Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; }
|
||||||
[[nodiscard]] Spell* GetCurrentSpell(uint32 spellType) const { return m_currentSpells[spellType]; }
|
[[nodiscard]] Spell* GetCurrentSpell(uint32 spellType) const { return m_currentSpells[spellType]; }
|
||||||
|
[[nodiscard]] Spell* GetFirstCurrentCastingSpell() const;
|
||||||
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
||||||
[[nodiscard]] int32 GetCurrentSpellCastTime(uint32 spell_id) const;
|
[[nodiscard]] int32 GetCurrentSpellCastTime(uint32 spell_id) const;
|
||||||
|
|
||||||
|
|||||||
@@ -72,15 +72,27 @@ bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
Creature* cOwner = owner->ToCreature();
|
Creature* cOwner = owner->ToCreature();
|
||||||
|
bool isStoppedBecauseOfCasting = cOwner && cOwner->IsMovementPreventedByCasting();
|
||||||
|
|
||||||
// the owner might be unable to move (rooted or casting), or we have lost the target, pause movement
|
// the owner might be unable to move (rooted or casting), or we have lost the target, pause movement
|
||||||
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || HasLostTarget(owner) || (cOwner && cOwner->IsMovementPreventedByCasting()))
|
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || HasLostTarget(owner) || isStoppedBecauseOfCasting)
|
||||||
{
|
{
|
||||||
owner->StopMoving();
|
owner->StopMoving();
|
||||||
_lastTargetPosition.reset();
|
_lastTargetPosition.reset();
|
||||||
if (cOwner)
|
if (cOwner)
|
||||||
{
|
{
|
||||||
cOwner->UpdateLeashExtensionTime();
|
if (isStoppedBecauseOfCasting)
|
||||||
|
{
|
||||||
|
// Don't reset leash timer if it's a spell like Shoot with a short cast time.
|
||||||
|
/// @todo: Research how it should actually work.
|
||||||
|
Spell *spell = cOwner->GetFirstCurrentCastingSpell();
|
||||||
|
bool spellHasLongCast = spell && spell->GetCastTime() > 1 * SECOND * IN_MILLISECONDS;
|
||||||
|
if (spellHasLongCast)
|
||||||
|
cOwner->UpdateLeashExtensionTime();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cOwner->UpdateLeashExtensionTime();
|
||||||
|
|
||||||
cOwner->SetCannotReachTarget();
|
cOwner->SetCannotReachTarget();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user