mirror of
https://gitcode.com/GitHub_Trending/az/azerothcore-wotlk.git
synced 2026-10-10 07:06:38 +08:00
fix(Core/Unit): restore UNIT_STATE_CASTING for all channels and gate actions on ALLOW_ACTION_DURING_CHANNEL (#26914)
Co-authored-by: sogladev <[email protected]> Co-authored-by: Gultask <[email protected]>
This commit is contained in:
co-authored by
sogladev
Gultask
parent
af97edcbd4
commit
58f0fca353
@@ -91,7 +91,7 @@ void CombatAI::UpdateAI(uint32 diff)
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me->IsActionPreventedByCasting())
|
||||
return;
|
||||
|
||||
if (uint32 spellId = events.ExecuteEvent())
|
||||
@@ -161,7 +161,7 @@ void CasterAI::UpdateAI(uint32 diff)
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me->IsActionPreventedByCasting())
|
||||
return;
|
||||
|
||||
if (uint32 spellId = events.ExecuteEvent())
|
||||
|
||||
@@ -40,7 +40,7 @@ void UnitAI::AttackStartCaster(Unit* victim, float dist)
|
||||
|
||||
void UnitAI::DoMeleeAttackIfReady()
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me->IsActionPreventedByCasting())
|
||||
return;
|
||||
|
||||
Unit* victim = me->GetVictim();
|
||||
@@ -75,7 +75,7 @@ void UnitAI::DoMeleeAttackIfReady()
|
||||
|
||||
bool UnitAI::DoSpellAttackIfReady(uint32 spell)
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) || !me->isAttackReady())
|
||||
if (me->IsActionPreventedByCasting() || !me->isAttackReady())
|
||||
return true;
|
||||
|
||||
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell))
|
||||
@@ -93,7 +93,7 @@ bool UnitAI::DoSpellAttackIfReady(uint32 spell)
|
||||
|
||||
void UnitAI::DoSpellAttackToRandomTargetIfReady(uint32 spell, uint32 threatTablePosition /*= 0*/, float dist /*= 0.f*/, bool playerOnly /*= true*/)
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) || !me->isAttackReady())
|
||||
if (me->IsActionPreventedByCasting() || !me->isAttackReady())
|
||||
return;
|
||||
|
||||
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell))
|
||||
@@ -269,7 +269,7 @@ SpellCastResult UnitAI::DoCast(Unit* victim, uint32 spellId, bool triggered)
|
||||
if (!victim)
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) && !triggered)
|
||||
if (me->IsActionPreventedByCasting() && !triggered)
|
||||
return SPELL_FAILED_SPELL_IN_PROGRESS;
|
||||
|
||||
return me->CastSpell(victim, spellId, triggered);
|
||||
@@ -285,7 +285,7 @@ SpellCastResult UnitAI::DoCastVictim(uint32 spellId, bool triggered)
|
||||
|
||||
SpellCastResult UnitAI::DoCastAOE(uint32 spellId, bool triggered)
|
||||
{
|
||||
if (!triggered && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (!triggered && me->IsActionPreventedByCasting())
|
||||
return SPELL_FAILED_SPELL_IN_PROGRESS;
|
||||
|
||||
return me->CastSpell((Unit*)nullptr, spellId, triggered);
|
||||
|
||||
@@ -624,7 +624,7 @@ BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature),
|
||||
// Clear it in the script if you need it to update while the creature is casting.
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
return !me->IsActionPreventedByCasting();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -749,7 +749,7 @@ void BossAI::UpdateAI(uint32 diff)
|
||||
events.Update(diff);
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me->IsActionPreventedByCasting())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -757,7 +757,7 @@ void BossAI::UpdateAI(uint32 diff)
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
ExecuteEvent(eventId);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me->IsActionPreventedByCasting())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -794,7 +794,7 @@ void BossAI::_CheckHealthAfterCast()
|
||||
// This must be delayed because creature might still have unit state casting at this point, which might break scripts.
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me->IsActionPreventedByCasting())
|
||||
context.Repeat();
|
||||
else
|
||||
ProcessHealthCheck();
|
||||
@@ -810,7 +810,7 @@ void BossAI::DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damage
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(_nextHealthCheck._healthPct, damage))
|
||||
{
|
||||
if (!_nextHealthCheck._allowedWhileCasting && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (!_nextHealthCheck._allowedWhileCasting && me->IsActionPreventedByCasting())
|
||||
{
|
||||
_nextHealthCheck.UpdateStatus(HEALTH_CHECK_PENDING);
|
||||
return;
|
||||
@@ -920,7 +920,7 @@ void WorldBossAI::UpdateAI(uint32 diff)
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me->IsActionPreventedByCasting())
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
|
||||
@@ -5100,7 +5100,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
{
|
||||
if (!(e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS))
|
||||
{
|
||||
if (me && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (me && me->IsActionPreventedByCasting())
|
||||
{
|
||||
RaisePriority(e);
|
||||
return;
|
||||
@@ -5109,7 +5109,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
}
|
||||
|
||||
// Delay flee for assist event if casting
|
||||
if (e.GetActionType() == SMART_ACTION_FLEE_FOR_ASSIST && me && me->HasUnitState(UNIT_STATE_CASTING))
|
||||
if (e.GetActionType() == SMART_ACTION_FLEE_FOR_ASSIST && me && me->IsActionPreventedByCasting())
|
||||
{
|
||||
e.timer = 1200;
|
||||
return;
|
||||
|
||||
@@ -2739,7 +2739,9 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BASE_A
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) && !extra && !ignoreCasting)
|
||||
// UNIT_STATE_CASTING is checked through IsActionPreventedByCasting() so that channels
|
||||
// flagged as "allow actions during channel" do not block the auto attack
|
||||
if ((HasUnitState(UNIT_STATE_LOST_CONTROL) || IsActionPreventedByCasting()) && !extra && !ignoreCasting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -4193,8 +4195,7 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell)
|
||||
m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != 75)
|
||||
InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
|
||||
|
||||
if (!pSpell->GetSpellInfo()->IsActionAllowedChannel())
|
||||
AddUnitState(UNIT_STATE_CASTING);
|
||||
AddUnitState(UNIT_STATE_CASTING);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -4371,6 +4372,26 @@ bool Unit::IsMovementPreventedByCasting() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Unit::IsActionPreventedByCasting() const
|
||||
{
|
||||
// can always act when not casting
|
||||
if (!HasUnitState(UNIT_STATE_CASTING))
|
||||
return false;
|
||||
|
||||
// a regular cast in progress always prevents other actions, even alongside a permissive channel
|
||||
if (Spell* spell = m_currentSpells[CURRENT_GENERIC_SPELL])
|
||||
if (spell->getState() != SPELL_STATE_FINISHED)
|
||||
return true;
|
||||
|
||||
// channeled spells during channel stage (after the initial cast timer) allow actions with a specific spell attribute
|
||||
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
|
||||
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive() && spell->GetSpellInfo()->IsActionAllowedChannel())
|
||||
return false;
|
||||
|
||||
// prohibit actions for all other spell casts
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
|
||||
{
|
||||
return IsWithinDistInMap(target, distance) && HasInArc(arc, target);
|
||||
|
||||
@@ -1721,6 +1721,7 @@ public:
|
||||
[[nodiscard]] float GetHoverHeight() const { return IsHovering() ? GetFloatValue(UNIT_FIELD_HOVERHEIGHT) : 0.0f; }
|
||||
|
||||
[[nodiscard]] virtual bool IsMovementPreventedByCasting() const;
|
||||
[[nodiscard]] bool IsActionPreventedByCasting() const;
|
||||
|
||||
[[nodiscard]] virtual bool CanEnterWater() const = 0;
|
||||
[[nodiscard]] virtual bool CanSwim() const;
|
||||
|
||||
@@ -3672,7 +3672,8 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const
|
||||
caster->AI()->OnSpellStart(GetSpellInfo());
|
||||
|
||||
// set target for proper facing
|
||||
if ((m_casttime || m_spellInfo->IsChanneled()) && !HasTriggeredCastFlag(TRIGGERED_IGNORE_SET_FACING))
|
||||
// channels that allow actions must not lock target and facing, the creature keeps fighting while channeling
|
||||
if ((m_casttime || m_spellInfo->IsChanneled()) && !m_spellInfo->IsActionAllowedChannel() && !HasTriggeredCastFlag(TRIGGERED_IGNORE_SET_FACING))
|
||||
{
|
||||
if (m_caster->IsCreature() && !m_caster->ToCreature()->IsInEvadeMode() &&
|
||||
((m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget()) || m_spellInfo->IsPositive()))
|
||||
|
||||
Reference in New Issue
Block a user