aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/Spell.cpp
diff options
context:
space:
mode:
authortreeston <treeston.mmoc@gmail.com>2016-01-13 18:38:54 +0100
committertreeston <treeston.mmoc@gmail.com>2016-01-13 18:38:54 +0100
commit233297c5c8619af96e2aab4fa5ef6d205b5dc18a (patch)
treea1a6f2275592e7639b17b71842cd7aaf90e1455d /src/server/game/Spells/Spell.cpp
parent5b8b8c653039ec2add0b3a66468abb85e6f35054 (diff)
parentf481ae1048aac32ba3a40491f0304d0317234295 (diff)
Merge branch '3.3.5-spellfacing' into 3.3.5-base (PR #15641)
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
-rw-r--r--src/server/game/Spells/Spell.cpp52
1 files changed, 45 insertions, 7 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index aed7c0db043..84bff4a69d6 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -602,6 +602,8 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO
//Auto Shot & Shoot (wand)
m_autoRepeat = m_spellInfo->IsAutoRepeatRangedSpell();
+
+ m_isDelayedInstantCast = false;
m_runesState = 0;
m_powerCost = 0; // setup to correct value in Spell::prepare, must not be used before.
@@ -2936,6 +2938,27 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
else
m_casttime = m_spellInfo->CalcCastTime(this);
+ if (m_caster->GetTypeId() == TYPEID_UNIT && !m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) // _UNIT actually means creature. for some reason.
+ if (!(IsNextMeleeSwingSpell() || IsAutoRepeat() || _triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING))
+ {
+ if (m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
+ {
+ if (m_caster->ToCreature()->FocusTarget(this, m_targets.GetObjectTarget()))
+ {
+ m_isDelayedInstantCast = true;
+ m_timer = 100; // 100ms delay ensures client has updated creature orientation when cast goes off
+ }
+ }
+ else if (m_spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST))
+ {
+ if (m_caster->ToCreature()->FocusTarget(this, nullptr))
+ {
+ m_isDelayedInstantCast = true;
+ m_timer = 100;
+ }
+ }
+ }
+
// don't allow channeled spells / spells with cast time to be cast while 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)
@@ -2971,18 +2994,14 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
}
m_caster->SetCurrentCastSpell(this);
- SendSpellStart();
-
- // set target for proper facing
- if ((m_casttime || m_spellInfo->IsChanneled()) && !(_triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING))
- if (m_caster->GetTypeId() == TYPEID_UNIT && m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
- m_caster->ToCreature()->FocusTarget(this, m_targets.GetObjectTarget());
+ if (!m_isDelayedInstantCast)
+ SendSpellStart();
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_GCD))
TriggerGlobalCooldown();
//item: first cast may destroy item and second cast causes crash
- if (!m_casttime && !m_spellInfo->StartRecoveryTime && !m_castItemGUID && GetCurrentContainer() == CURRENT_GENERIC_SPELL)
+ if (!m_casttime && !m_isDelayedInstantCast && !m_spellInfo->StartRecoveryTime && !m_castItemGUID && GetCurrentContainer() == CURRENT_GENERIC_SPELL)
cast(true);
}
}
@@ -2991,6 +3010,9 @@ void Spell::cancel()
{
if (m_spellState == SPELL_STATE_FINISHED)
return;
+ // delayed instant casts are used for client-side visual orientation; they are treated as instant for all intents and purposes server-side, and thus cannot be interrupted by another cast
+ if (m_isDelayedInstantCast)
+ return;
uint32 oldState = m_spellState;
m_spellState = SPELL_STATE_FINISHED;
@@ -3060,6 +3082,9 @@ void Spell::cast(bool skipCheck)
return;
}
+ if (m_isDelayedInstantCast)
+ SendSpellStart();
+
if (Player* playerCaster = m_caster->ToPlayer())
{
// now that we've done the basic check, now run the scripts
@@ -3139,6 +3164,16 @@ void Spell::cast(bool skipCheck)
}
}
+ // if the spell allows the creature to turn while casting, then adjust server-side orientation to face the target now
+ // client-side orientation is handled by the client itself, as the cast target is targeted due to Creature::FocusTarget
+ if (m_caster->GetTypeId() == TYPEID_UNIT && !m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST))
+ if (WorldObject* objTarget = m_targets.GetObjectTarget())
+ {
+ m_caster->SetInFront(objTarget);
+ m_caster->SetFacingToObject(objTarget);
+ }
+
SelectSpellTargets();
// Spell may be finished after target map check
@@ -3242,6 +3277,9 @@ void Spell::cast(bool skipCheck)
}
SetExecutedCurrently(false);
+
+ if (Creature* creatureCaster = m_caster->ToCreature())
+ creatureCaster->ReleaseFocus(this);
}
void Spell::handle_immediate()