mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-29 08:33:47 +00:00
fix(Scripts/ZulGurub): Hakkar's Blood Siphon (#12196)
This commit is contained in:
@@ -3439,7 +3439,7 @@ bool Creature::IsMovementPreventedByCasting() const
|
||||
{
|
||||
Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL];
|
||||
// first check if currently a movement allowed channel is active and we're not casting
|
||||
if (spell && spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive() && spell->GetSpellInfo()->IsMoveAllowedChannel())
|
||||
if (spell && spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive() && spell->GetSpellInfo()->IsActionAllowedChannel())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3622,8 +3622,12 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell)
|
||||
{
|
||||
// generic spells always break channeled not delayed spells
|
||||
if (Spell* s = GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
if (s->GetSpellInfo()->Id != 69051) // pussywizard: FoS, boss Devourer of Souls, Mirrored Soul, does not have any special attribute
|
||||
{
|
||||
if (!s->GetSpellInfo()->IsActionAllowedChannel())
|
||||
{
|
||||
InterruptSpell(CURRENT_CHANNELED_SPELL, false);
|
||||
}
|
||||
}
|
||||
|
||||
// autorepeat breaking
|
||||
if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
|
||||
@@ -3658,7 +3662,14 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell)
|
||||
if (pSpell->m_spellInfo->Id != 75)
|
||||
{
|
||||
// generic autorepeats break generic non-delayed and channeled non-delayed spells
|
||||
InterruptSpell(CURRENT_GENERIC_SPELL, false);
|
||||
if (Spell* s = GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
{
|
||||
if (!s->GetSpellInfo()->IsActionAllowedChannel())
|
||||
{
|
||||
InterruptSpell(CURRENT_CHANNELED_SPELL, false);
|
||||
}
|
||||
}
|
||||
|
||||
InterruptSpell(CURRENT_CHANNELED_SPELL, false);
|
||||
}
|
||||
// special action: set first cast flag
|
||||
@@ -3793,7 +3804,7 @@ bool Unit::IsMovementPreventedByCasting() const
|
||||
{
|
||||
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
|
||||
{
|
||||
if (spell->GetSpellInfo()->IsMoveAllowedChannel())
|
||||
if (spell->GetSpellInfo()->IsActionAllowedChannel())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -3804,15 +3815,6 @@ bool Unit::IsMovementPreventedByCasting() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Unit::CanMoveDuringChannel() const
|
||||
{
|
||||
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
|
||||
if (spell->getState() != SPELL_STATE_FINISHED)
|
||||
return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL) && spell->IsChannelActive();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
|
||||
{
|
||||
return IsWithinDistInMap(target, distance) && HasInArc(arc, target);
|
||||
|
||||
@@ -2029,9 +2029,6 @@ public:
|
||||
// delayed+channeled spells are always interrupted
|
||||
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0, bool withInstant = true, bool bySelf = false);
|
||||
|
||||
// Check if our current channel spell has attribute SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL
|
||||
[[nodiscard]] bool CanMoveDuringChannel() const;
|
||||
|
||||
[[nodiscard]] Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; }
|
||||
[[nodiscard]] Spell* GetCurrentSpell(uint32 spellType) const { return m_currentSpells[spellType]; }
|
||||
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
||||
|
||||
@@ -491,7 +491,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket)
|
||||
if (!spellInfo)
|
||||
return;
|
||||
|
||||
// not allow remove spells with attr SPELL_ATTR0_CANT_CANCEL
|
||||
// not allow remove spells with attr SPELL_ATTR0_NO_AURA_CANCEL
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_AURA_CANCEL))
|
||||
{
|
||||
return;
|
||||
@@ -569,12 +569,33 @@ void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& /*recvPacket*/
|
||||
|
||||
void WorldSession::HandleCancelChanneling(WorldPacket& recvData)
|
||||
{
|
||||
recvData.read_skip<uint32>(); // spellid, not used
|
||||
uint32 spellID = 0;
|
||||
recvData >> spellID;
|
||||
|
||||
// ignore for remote control state (for player case)
|
||||
Unit* mover = _player->m_mover;
|
||||
if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER)
|
||||
if (!mover)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
|
||||
if (!spellInfo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// not allow remove spells with attr SPELL_ATTR0_NO_AURA_CANCEL
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_AURA_CANCEL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Spell* spell = mover->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
|
||||
if (!spell || spell->GetSpellInfo()->Id != spellInfo->Id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mover->InterruptSpell(CURRENT_CHANNELED_SPELL);
|
||||
}
|
||||
|
||||
@@ -3555,9 +3555,13 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const
|
||||
// (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 && !IsTriggered())
|
||||
{
|
||||
SendCastResult(SPELL_FAILED_MOVING);
|
||||
finish(false);
|
||||
return SPELL_FAILED_MOVING;
|
||||
// 1. Has casttime, 2. Or doesn't have flag to allow action during channel
|
||||
if (m_casttime || !m_spellInfo->IsActionAllowedChannel())
|
||||
{
|
||||
SendCastResult(SPELL_FAILED_MOVING);
|
||||
finish(false);
|
||||
return SPELL_FAILED_MOVING;
|
||||
}
|
||||
}
|
||||
|
||||
// xinef: if spell have nearby target entry only, do not allow to cast if no targets are found
|
||||
|
||||
@@ -1241,7 +1241,7 @@ bool SpellInfo::IsChanneled() const
|
||||
return (AttributesEx & (SPELL_ATTR1_IS_CHANNELED | SPELL_ATTR1_IS_SELF_CHANNELED));
|
||||
}
|
||||
|
||||
bool SpellInfo::IsMoveAllowedChannel() const
|
||||
bool SpellInfo::IsActionAllowedChannel() const
|
||||
{
|
||||
return IsChanneled() && HasAttribute(SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL);
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ public:
|
||||
bool IsPositive() const;
|
||||
bool IsPositiveEffect(uint8 effIndex) const;
|
||||
bool IsChanneled() const;
|
||||
[[nodiscard]] bool IsMoveAllowedChannel() const;
|
||||
[[nodiscard]] bool IsActionAllowedChannel() const;
|
||||
bool NeedsComboPoints() const;
|
||||
bool IsBreakingStealth() const;
|
||||
bool IsRangedWeaponSpell() const;
|
||||
|
||||
@@ -4301,6 +4301,16 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->Effects[EFFECT_0].MiscValueB = 64;
|
||||
});
|
||||
|
||||
// Blood Siphon
|
||||
ApplySpellFix({ 24322, 24323 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_MOD_STUN;
|
||||
spellInfo->Effects[EFFECT_2].Effect = 0;
|
||||
spellInfo->Attributes |= SPELL_ATTR0_NO_AURA_CANCEL;
|
||||
spellInfo->AttributesEx5 |= SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL;
|
||||
spellInfo->ChannelInterruptFlags &= ~AURA_INTERRUPT_FLAG_MOVE;
|
||||
});
|
||||
|
||||
// Place Fake Fur
|
||||
ApplySpellFix({ 46085 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
|
||||
@@ -39,10 +39,9 @@ enum Says
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_POISONOUS_BLOOD = 24321,
|
||||
SPELL_BLOOD_SIPHON_HEAL = 24322,
|
||||
SPELL_BLOOD_SIPHON_DMG = 24323,
|
||||
SPELL_BLOOD_SIPHON = 24324,
|
||||
SPELL_BLOOD_SIPHON_HEAL = 24322,
|
||||
SPELL_BLOOD_SIPHON_DAMAGE = 24323,
|
||||
SPELL_CORRUPTED_BLOOD = 24328,
|
||||
SPELL_CAUSE_INSANITY = 24327,
|
||||
SPELL_ENRAGE = 24318,
|
||||
@@ -51,7 +50,8 @@ enum Spells
|
||||
SPELL_ASPECT_OF_VENOXIS = 24688,
|
||||
SPELL_ASPECT_OF_MARLI = 24686,
|
||||
SPELL_ASPECT_OF_THEKAL = 24689,
|
||||
SPELL_ASPECT_OF_ARLOKK = 24690
|
||||
SPELL_ASPECT_OF_ARLOKK = 24690,
|
||||
SPELL_POISONOUS_BLOOD = 24321
|
||||
};
|
||||
|
||||
enum Events
|
||||
@@ -265,31 +265,39 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_hakkar_blood_siphon : public SpellScript
|
||||
class spell_blood_siphon : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_hakkar_blood_siphon);
|
||||
PrepareSpellScript(spell_blood_siphon);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_BLOOD_SIPHON_HEAL, SPELL_BLOOD_SIPHON_DMG });
|
||||
return ValidateSpellInfo({ SPELL_BLOOD_SIPHON_DAMAGE, SPELL_BLOOD_SIPHON_HEAL });
|
||||
}
|
||||
|
||||
void OnSpellHit()
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
Unit* target = GetHitUnit();
|
||||
if (!caster || !target)
|
||||
return;
|
||||
// Max. 20 targets
|
||||
if (!targets.empty())
|
||||
{
|
||||
Acore::Containers::RandomResize(targets, 20);
|
||||
}
|
||||
}
|
||||
|
||||
if (target->HasAura(SPELL_POISONOUS_BLOOD))
|
||||
target->CastSpell(caster, SPELL_BLOOD_SIPHON_DMG, true);
|
||||
else
|
||||
target->CastSpell(caster, SPELL_BLOOD_SIPHON_HEAL, true);
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Player* player = GetHitPlayer())
|
||||
{
|
||||
player->CastSpell(caster, player->HasAura(SPELL_POISONOUS_BLOOD) ? SPELL_BLOOD_SIPHON_DAMAGE : SPELL_BLOOD_SIPHON_HEAL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_hakkar_blood_siphon::OnSpellHit);
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blood_siphon::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_blood_siphon::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -299,5 +307,5 @@ void AddSC_boss_hakkar()
|
||||
new at_zulgurub_entrance_speech();
|
||||
new at_zulgurub_bridge_speech();
|
||||
new at_zulgurub_temple_speech();
|
||||
RegisterSpellScript(spell_hakkar_blood_siphon);
|
||||
RegisterSpellScript(spell_blood_siphon);
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ enum SpellAttr4 : uint32
|
||||
// EnumUtils: DESCRIBE THIS
|
||||
enum SpellAttr5 : uint32
|
||||
{
|
||||
SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL = 0x00000001, // TITLE Can be channeled while moving
|
||||
SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL = 0x00000001, // TITLE Can be channeled while moving/casting
|
||||
SPELL_ATTR5_NO_REAGENT_COST_WITH_AURA = 0x00000002, // TITLE No reagents during arena preparation
|
||||
SPELL_ATTR5_REMOVE_ENTERING_ARENA = 0x00000004, // TITLE Remove when entering arena DESCRIPTION Force this aura to be removed on entering arena, regardless of other properties
|
||||
SPELL_ATTR5_ALLOW_WHILE_STUNNED = 0x00000008, // TITLE Usable while stunned
|
||||
|
||||
@@ -802,7 +802,7 @@ AC_API_EXPORT EnumText EnumUtils<SpellAttr5>::ToString(SpellAttr5 value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL: return { "SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL", "Can be channeled while moving", "" };
|
||||
case SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL: return { "SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL", "Can be channeled while moving/casting", "" };
|
||||
case SPELL_ATTR5_NO_REAGENT_COST_WITH_AURA: return { "SPELL_ATTR5_NO_REAGENT_COST_WITH_AURA", "No reagents during arena preparation", "" };
|
||||
case SPELL_ATTR5_REMOVE_ENTERING_ARENA: return { "SPELL_ATTR5_REMOVE_ENTERING_ARENA", "Remove when entering arena", "Force this aura to be removed on entering arena, regardless of other properties" };
|
||||
case SPELL_ATTR5_ALLOW_WHILE_STUNNED: return { "SPELL_ATTR5_ALLOW_WHILE_STUNNED", "Usable while stunned", "" };
|
||||
|
||||
Reference in New Issue
Block a user