diff options
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 44 |
3 files changed, 45 insertions, 3 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f463e635085..86fd0feeec8 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3858,6 +3858,8 @@ void Spell::_cast(bool skipCheck) if (!m_spellInfo->HasAttribute(SPELL_ATTR12_START_COOLDOWN_ON_CAST_START)) SendSpellCooldown(); + m_spellState = SPELL_STATE_LAUNCHED; + if (!m_spellInfo->LaunchDelay) { HandleLaunchPhase(); @@ -3883,7 +3885,6 @@ void Spell::_cast(bool skipCheck) // Okay, maps created, now prepare flags m_immediateHandled = false; - m_spellState = SPELL_STATE_LAUNCHED; SetDelayStart(0); if (Unit* unitCaster = m_caster->ToUnit()) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 25f7283507d..d7b473eb67d 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -313,6 +313,7 @@ class TC_GAME_API Spell void EffectLearnPetSpell(); void EffectWeaponDmg(); void EffectForceCast(); + void EffectForceCast2(); void EffectTriggerSpell(); void EffectTriggerMissileSpell(); void EffectThreat(); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 8ac287c8ba4..b9cd6b4bdcb 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -248,7 +248,7 @@ NonDefaultConstructible<SpellEffectHandlerFn> SpellEffectHandlers[TOTAL_SPELL_EF &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again - &Spell::EffectForceCast, //160 SPELL_EFFECT_FORCE_CAST_2 + &Spell::EffectForceCast2, //160 SPELL_EFFECT_FORCE_CAST_2 &Spell::EffectNULL, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert) &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec &Spell::EffectNULL, //163 SPELL_EFFECT_OBLITERATE_ITEM @@ -823,7 +823,7 @@ void Spell::EffectForceCast() return; } - CastSpellExtraArgs args(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_REAGENT_COST)); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK & ~(TRIGGERED_IGNORE_POWER_COST | TRIGGERED_CAST_DIRECTLY | TRIGGERED_IGNORE_REAGENT_COST)); if (effectInfo->Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE) for (std::size_t i = 0; i < spellInfo->GetEffects().size(); ++i) args.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), damage); @@ -831,6 +831,46 @@ void Spell::EffectForceCast() unitTarget->CastSpell(m_caster, spellInfo->Id, args); } +void Spell::EffectForceCast2() +{ + if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET) + return; + + if (!unitTarget) + return; + + uint32 triggered_spell_id = effectInfo->TriggerSpell; + if (triggered_spell_id == 0) + { + TC_LOG_WARN("spells.effect.nospell", "Spell::EffectForceCast2: Spell {} [EffectIndex: {}] does not have triggered spell.", m_spellInfo->Id, effectInfo->EffectIndex); + return; + } + + // normal case + if (!sSpellMgr->GetSpellInfo(triggered_spell_id, GetCastDifficulty())) + { + TC_LOG_ERROR("spells.effect.nospell", "Spell::EffectForceCast2 of spell {}: triggering unknown spell id {}.", m_spellInfo->Id, triggered_spell_id); + return; + } + + // Start the cast during next update tick + // This is neccessary to preserve proper SMSG_SPELL_START and SMSG_SPELL_GO packet sequence + // (if packet sequence is not preserved then client cast bar in UI bugs and doesn't stop when the spell is interrupted) + // Triggered spells from effects handled during launch phase (such as SPELL_EFFECT_TRIGGER_SPELL) + // normally have their SMSG_SPELL_GO sent before parent spell SMSG_SPELL_GO + // SPELL_EFFECT_FORCE_CAST_2 requires these packets to be sent after parent spell + // but also needs to be handled during launch phase as well + unitTarget->m_Events.AddEventAtOffset([triggered_spell_id, target = CastSpellTargetArg(m_caster), caster = unitTarget]() mutable + { + if (!target.Targets) + return; + + target.Targets->Update(caster); + + caster->CastSpell(target, triggered_spell_id); + }, 0ms); +} + void Spell::EffectTriggerRitualOfSummoning() { if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) |