fix(Scripts/ZulGurub): Hakkar's Blood Siphon (#12196)
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
--
|
||||||
|
DELETE FROM `spell_script_names` WHERE `spell_id`=24324;
|
||||||
|
INSERT INTO `spell_script_names` VALUES
|
||||||
|
(24324,'spell_blood_siphon');
|
||||||
@@ -3439,7 +3439,7 @@ bool Creature::IsMovementPreventedByCasting() const
|
|||||||
{
|
{
|
||||||
Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL];
|
Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL];
|
||||||
// first check if currently a movement allowed channel is active and we're not casting
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3622,8 +3622,12 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell)
|
|||||||
{
|
{
|
||||||
// generic spells always break channeled not delayed spells
|
// generic spells always break channeled not delayed spells
|
||||||
if (Spell* s = GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
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);
|
InterruptSpell(CURRENT_CHANNELED_SPELL, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// autorepeat breaking
|
// autorepeat breaking
|
||||||
if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
|
if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
|
||||||
@@ -3658,7 +3662,14 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell)
|
|||||||
if (pSpell->m_spellInfo->Id != 75)
|
if (pSpell->m_spellInfo->Id != 75)
|
||||||
{
|
{
|
||||||
// generic autorepeats break generic non-delayed and channeled non-delayed spells
|
// 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);
|
InterruptSpell(CURRENT_CHANNELED_SPELL, false);
|
||||||
}
|
}
|
||||||
// special action: set first cast flag
|
// special action: set first cast flag
|
||||||
@@ -3793,7 +3804,7 @@ bool Unit::IsMovementPreventedByCasting() const
|
|||||||
{
|
{
|
||||||
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
|
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
|
||||||
{
|
{
|
||||||
if (spell->GetSpellInfo()->IsMoveAllowedChannel())
|
if (spell->GetSpellInfo()->IsActionAllowedChannel())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3804,15 +3815,6 @@ bool Unit::IsMovementPreventedByCasting() const
|
|||||||
return true;
|
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
|
bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
|
||||||
{
|
{
|
||||||
return IsWithinDistInMap(target, distance) && HasInArc(arc, target);
|
return IsWithinDistInMap(target, distance) && HasInArc(arc, target);
|
||||||
|
|||||||
@@ -2029,9 +2029,6 @@ public:
|
|||||||
// delayed+channeled spells are always interrupted
|
// delayed+channeled spells are always interrupted
|
||||||
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0, bool withInstant = true, bool bySelf = false);
|
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(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* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket)
|
|||||||
if (!spellInfo)
|
if (!spellInfo)
|
||||||
return;
|
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))
|
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_AURA_CANCEL))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -569,12 +569,33 @@ void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& /*recvPacket*/
|
|||||||
|
|
||||||
void WorldSession::HandleCancelChanneling(WorldPacket& recvData)
|
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)
|
// ignore for remote control state (for player case)
|
||||||
Unit* mover = _player->m_mover;
|
Unit* mover = _player->m_mover;
|
||||||
if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER)
|
if (!mover)
|
||||||
|
{
|
||||||
return;
|
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);
|
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)
|
// (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())
|
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);
|
// 1. Has casttime, 2. Or doesn't have flag to allow action during channel
|
||||||
finish(false);
|
if (m_casttime || !m_spellInfo->IsActionAllowedChannel())
|
||||||
return SPELL_FAILED_MOVING;
|
{
|
||||||
|
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
|
// 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));
|
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);
|
return IsChanneled() && HasAttribute(SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ public:
|
|||||||
bool IsPositive() const;
|
bool IsPositive() const;
|
||||||
bool IsPositiveEffect(uint8 effIndex) const;
|
bool IsPositiveEffect(uint8 effIndex) const;
|
||||||
bool IsChanneled() const;
|
bool IsChanneled() const;
|
||||||
[[nodiscard]] bool IsMoveAllowedChannel() const;
|
[[nodiscard]] bool IsActionAllowedChannel() const;
|
||||||
bool NeedsComboPoints() const;
|
bool NeedsComboPoints() const;
|
||||||
bool IsBreakingStealth() const;
|
bool IsBreakingStealth() const;
|
||||||
bool IsRangedWeaponSpell() const;
|
bool IsRangedWeaponSpell() const;
|
||||||
|
|||||||
@@ -4301,6 +4301,16 @@ void SpellMgr::LoadSpellInfoCorrections()
|
|||||||
spellInfo->Effects[EFFECT_0].MiscValueB = 64;
|
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
|
// Place Fake Fur
|
||||||
ApplySpellFix({ 46085 }, [](SpellInfo* spellInfo)
|
ApplySpellFix({ 46085 }, [](SpellInfo* spellInfo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,10 +39,9 @@ enum Says
|
|||||||
|
|
||||||
enum Spells
|
enum Spells
|
||||||
{
|
{
|
||||||
SPELL_POISONOUS_BLOOD = 24321,
|
|
||||||
SPELL_BLOOD_SIPHON_HEAL = 24322,
|
|
||||||
SPELL_BLOOD_SIPHON_DMG = 24323,
|
|
||||||
SPELL_BLOOD_SIPHON = 24324,
|
SPELL_BLOOD_SIPHON = 24324,
|
||||||
|
SPELL_BLOOD_SIPHON_HEAL = 24322,
|
||||||
|
SPELL_BLOOD_SIPHON_DAMAGE = 24323,
|
||||||
SPELL_CORRUPTED_BLOOD = 24328,
|
SPELL_CORRUPTED_BLOOD = 24328,
|
||||||
SPELL_CAUSE_INSANITY = 24327,
|
SPELL_CAUSE_INSANITY = 24327,
|
||||||
SPELL_ENRAGE = 24318,
|
SPELL_ENRAGE = 24318,
|
||||||
@@ -51,7 +50,8 @@ enum Spells
|
|||||||
SPELL_ASPECT_OF_VENOXIS = 24688,
|
SPELL_ASPECT_OF_VENOXIS = 24688,
|
||||||
SPELL_ASPECT_OF_MARLI = 24686,
|
SPELL_ASPECT_OF_MARLI = 24686,
|
||||||
SPELL_ASPECT_OF_THEKAL = 24689,
|
SPELL_ASPECT_OF_THEKAL = 24689,
|
||||||
SPELL_ASPECT_OF_ARLOKK = 24690
|
SPELL_ASPECT_OF_ARLOKK = 24690,
|
||||||
|
SPELL_POISONOUS_BLOOD = 24321
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Events
|
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
|
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();
|
// Max. 20 targets
|
||||||
Unit* target = GetHitUnit();
|
if (!targets.empty())
|
||||||
if (!caster || !target)
|
{
|
||||||
return;
|
Acore::Containers::RandomResize(targets, 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (target->HasAura(SPELL_POISONOUS_BLOOD))
|
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||||
target->CastSpell(caster, SPELL_BLOOD_SIPHON_DMG, true);
|
{
|
||||||
else
|
if (Unit* caster = GetCaster())
|
||||||
target->CastSpell(caster, SPELL_BLOOD_SIPHON_HEAL, true);
|
{
|
||||||
|
if (Player* player = GetHitPlayer())
|
||||||
|
{
|
||||||
|
player->CastSpell(caster, player->HasAura(SPELL_POISONOUS_BLOOD) ? SPELL_BLOOD_SIPHON_DAMAGE : SPELL_BLOOD_SIPHON_HEAL, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Register() override
|
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_entrance_speech();
|
||||||
new at_zulgurub_bridge_speech();
|
new at_zulgurub_bridge_speech();
|
||||||
new at_zulgurub_temple_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
|
// EnumUtils: DESCRIBE THIS
|
||||||
enum SpellAttr5 : uint32
|
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_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_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
|
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)
|
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_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_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", "" };
|
case SPELL_ATTR5_ALLOW_WHILE_STUNNED: return { "SPELL_ATTR5_ALLOW_WHILE_STUNNED", "Usable while stunned", "" };
|
||||||
|
|||||||
Reference in New Issue
Block a user