Core/Movement: Fix issues where creatures cancel spell casts chasing target and Implement SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING

This commit is contained in:
Nawuko
2016-04-25 11:46:35 -03:00
committed by Keader
parent 2640f37c66
commit bf2cee8cce
5 changed files with 28 additions and 8 deletions

View File

@@ -3189,6 +3189,15 @@ int32 Unit::GetCurrentSpellCastTime(uint32 spell_id) const
return 0;
}
bool Unit::CanMoveDuringChannel() const
{
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
if (spell->getState() != SPELL_STATE_FINISHED)
return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) && spell->IsChannelActive();
return false;
}
bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
{
return IsWithinDistInMap(target, distance) && HasInArc(arc, target);

View File

@@ -1857,6 +1857,9 @@ class TC_GAME_API Unit : public WorldObject
Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
int32 GetCurrentSpellCastTime(uint32 spell_id) const;
// Check if our current channel spell has attribute SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING
bool CanMoveDuringChannel() const;
SpellHistory* GetSpellHistory() { return m_spellHistory; }
SpellHistory const* GetSpellHistory() const { return m_spellHistory; }

View File

@@ -456,7 +456,7 @@ enum SpellAttr4
enum SpellAttr5
{
SPELL_ATTR5_UNK0 = 0x00000001, // 0
SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING = 0x00000001, // 0 available casting channel spell when moving
SPELL_ATTR5_NO_REAGENT_WHILE_PREP = 0x00000002, // 1 not need reagents if UNIT_FLAG_PREPARATION
SPELL_ATTR5_UNK2 = 0x00000004, // 2
SPELL_ATTR5_USABLE_WHILE_STUNNED = 0x00000008, // 3 usable while stunned

View File

@@ -36,6 +36,9 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE))
return;
if (owner->HasUnitState(UNIT_STATE_CASTING) && !owner->CanMoveDuringChannel())
return;
if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature()))
return;
@@ -139,7 +142,7 @@ bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff)
}
// prevent movement while casting spells with cast time or channel time
if (owner->HasUnitState(UNIT_STATE_CASTING))
if (owner->HasUnitState(UNIT_STATE_CASTING) && !owner->CanMoveDuringChannel())
{
if (!owner->IsStopped())
owner->StopMoving();

View File

@@ -2974,12 +2974,17 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
}
// don't allow channeled spells / spells with cast time to be cast while moving
// exception are only channeled spells that have no casttime and SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING
// (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in)
if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)
{
SendCastResult(SPELL_FAILED_MOVING);
finish(false);
return;
// 1. Is a channel spell, 2. Has no casttime, 3. And has flag to allow movement during channel
if (!(m_spellInfo->IsChanneled() && !m_casttime && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING)))
{
SendCastResult(SPELL_FAILED_MOVING);
finish(false);
return;
}
}
// set timer base at cast time
@@ -3516,11 +3521,11 @@ void Spell::update(uint32 difftime)
// check if the player caster has moved before the spell finished
if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) &&
(m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)))
m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT &&
(m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))))
{
// don't cancel for melee, autorepeat, triggered and instant spells
if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered())
if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING)))
cancel();
}