aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-04-30 13:14:22 +0200
committerOvahlord <dreadkiller@gmx.de>2025-05-11 11:42:45 +0200
commitfcf08011bbd37c8d9823a07ee9f3e59b8712715a (patch)
treec3d6831ead12a4e9f0dd739a2da3583d22fa8aec
parent2924a5336f40a577edd469283f10c4304437fc32 (diff)
Core/Spells: Start spells triggered by SPELL_EFFECT_FORCE_CAST_2 without any trigger flags
(cherry picked from commit 0fd418eb7472039bb953a7167a48f6495c2b2efb) # Conflicts: # src/server/game/Spells/SpellEffects.cpp
-rw-r--r--src/server/game/Spells/Spell.cpp3
-rw-r--r--src/server/game/Spells/Spell.h1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp44
3 files changed, 45 insertions, 3 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index c52543ec6d9..b697a8e2a04 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3861,6 +3861,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();
@@ -3886,7 +3888,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 48bd69d3cf7..9a742e2d42b 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -310,6 +310,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 0b5edea46a0..2512b64a8cc 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -244,7 +244,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::EffectTalentSpecCount, //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
@@ -808,7 +808,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);
@@ -816,6 +816,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)