aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/Spell.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
-rw-r--r--src/server/game/Spells/Spell.cpp41
1 files changed, 27 insertions, 14 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 60554e0717c..883f051b700 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1564,7 +1564,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
if (Creature* creatureTarget = unit->ToCreature())
{
- if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PROJECTILE_COLLISION))
+ if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_COLLIDE_WITH_MISSILES))
continue;
}
}
@@ -2320,8 +2320,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
}
}
+ bool enablePvP = false; // need to check PvP state before spell effects, but act on it afterwards
+
if (spellHitTarget)
{
+ // if target is flagged for pvp also flag caster if a player
+ if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER)
+ enablePvP = true; // Decide on PvP flagging now, but act on it later.
SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura);
if (missInfo2 != SPELL_MISS_NONE)
{
@@ -2474,8 +2479,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
// Needs to be called after dealing damage/healing to not remove breaking on damage auras
DoTriggersOnSpellHit(spellHitTarget, mask);
- // if target is fallged for pvp also flag caster if a player
- if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER)
+ if (enablePvP)
m_caster->ToPlayer()->UpdatePvP(true);
CallScriptAfterHitHandlers();
@@ -2986,12 +2990,17 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
}
// don't allow channeled spells / spells with cast time to be cast while moving
+ // exception are only channeled spells that have no casttime and SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING
// (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)
{
- SendCastResult(SPELL_FAILED_MOVING);
- finish(false);
- return;
+ // 1. Is a channel spell, 2. Has no casttime, 3. And has flag to allow movement during channel
+ if (!(m_spellInfo->IsChanneled() && !m_casttime && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING)))
+ {
+ SendCastResult(SPELL_FAILED_MOVING);
+ finish(false);
+ return;
+ }
}
// set timer base at cast time
@@ -3219,6 +3228,10 @@ void Spell::cast(bool skipCheck)
return;
}
+ if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET))
+ if (Creature* pet = ObjectAccessor::GetCreature(*m_caster, m_caster->GetPetGUID()))
+ pet->DespawnOrUnsummon();
+
PrepareTriggersExecutedOnHit();
CallScriptOnCastHandlers();
@@ -3528,11 +3541,11 @@ void Spell::update(uint32 difftime)
// check if the player caster has moved before the spell finished
if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
- m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) &&
- (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)))
+ m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT &&
+ (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))))
{
// don't cancel for melee, autorepeat, triggered and instant spells
- if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered())
+ if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING)))
cancel();
}
@@ -5286,7 +5299,7 @@ SpellCastResult Spell::CheckCast(bool strict)
switch (SummonProperties->Category)
{
case SUMMON_CATEGORY_PET:
- if (m_caster->GetPetGUID())
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_caster->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
// intentional missing break, check both GetPetGUID() and GetCharmGUID for SUMMON_CATEGORY_PET
case SUMMON_CATEGORY_PUPPET:
@@ -5302,7 +5315,7 @@ SpellCastResult Spell::CheckCast(bool strict)
{
if (m_targets.GetUnitTarget()->GetTypeId() != TYPEID_PLAYER)
return SPELL_FAILED_BAD_TARGETS;
- if (m_targets.GetUnitTarget()->GetPetGUID())
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_targets.GetUnitTarget()->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
}
break;
@@ -5311,13 +5324,13 @@ SpellCastResult Spell::CheckCast(bool strict)
{
if (m_caster->GetPetGUID()) //let warlock do a replacement summon
{
- if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARLOCK)
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
if (strict) //starting cast, trigger pet stun (cast by pet so it doesn't attack player)
if (Pet* pet = m_caster->ToPlayer()->GetPet())
pet->CastSpell(pet, 32752, true, NULL, NULL, pet->GetGUID());
}
- else
+ else if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET))
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
}
@@ -5444,7 +5457,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_CHARM
|| m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_POSSESS)
{
- if (m_caster->GetPetGUID())
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_caster->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
if (m_caster->GetCharmGUID())