*Implement aura rank selection for aoe auras casted by player
*More correct level requirement checks for unit target *Fix some visual issues with spells which are interrupted after SendSpellStart but before SendSpellGo *Prevent adding spellmods permamently to already finished spells. --HG-- branch : trunk
This commit is contained in:
@@ -17316,6 +17316,9 @@ void Player::SetSpellModTakingSpell(Spell * spell, bool apply)
|
|||||||
if (!spell || (m_spellModTakingSpell && m_spellModTakingSpell != spell))
|
if (!spell || (m_spellModTakingSpell && m_spellModTakingSpell != spell))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (apply && spell->m_spellState == SPELL_STATE_FINISHED)
|
||||||
|
return;
|
||||||
|
|
||||||
if (apply)
|
if (apply)
|
||||||
m_spellModTakingSpell = spell;
|
m_spellModTakingSpell = spell;
|
||||||
else
|
else
|
||||||
|
|||||||
+101
-19
@@ -371,6 +371,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
|
|||||||
|
|
||||||
m_applyMultiplierMask = 0;
|
m_applyMultiplierMask = 0;
|
||||||
m_effectMask = 0;
|
m_effectMask = 0;
|
||||||
|
m_auraScaleMask = 0;
|
||||||
|
|
||||||
// Get data for type of attack
|
// Get data for type of attack
|
||||||
switch (m_spellInfo->DmgClass)
|
switch (m_spellInfo->DmgClass)
|
||||||
@@ -701,7 +702,6 @@ void Spell::FillTargetMap()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsChanneledSpell(m_spellInfo))
|
if(IsChanneledSpell(m_spellInfo))
|
||||||
{
|
{
|
||||||
uint8 mask = (1<<i);
|
uint8 mask = (1<<i);
|
||||||
@@ -714,6 +714,29 @@ void Spell::FillTargetMap()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (m_auraScaleMask)
|
||||||
|
{
|
||||||
|
bool checkLvl = !m_UniqueTargetInfo.empty();
|
||||||
|
for(std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();)
|
||||||
|
{
|
||||||
|
// remove targets which did not pass min level check
|
||||||
|
if(m_auraScaleMask && ihit->effectMask == m_auraScaleMask)
|
||||||
|
{
|
||||||
|
// Do not check for selfcast
|
||||||
|
if (!ihit->scaleAura && ihit->targetGUID != m_caster->GetGUID())
|
||||||
|
{
|
||||||
|
m_UniqueTargetInfo.erase(ihit++);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++ihit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (checkLvl && m_UniqueTargetInfo.empty())
|
||||||
|
{
|
||||||
|
SendCastResult(SPELL_FAILED_LOWLEVEL);
|
||||||
|
finish(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
|
if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
|
||||||
@@ -859,6 +882,13 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
|
|||||||
{
|
{
|
||||||
if (!immuned)
|
if (!immuned)
|
||||||
ihit->effectMask |= 1 << effIndex; // Add only effect mask if not immuned
|
ihit->effectMask |= 1 << effIndex; // Add only effect mask if not immuned
|
||||||
|
ihit->scaleAura = false;
|
||||||
|
if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask && m_caster != pVictim)
|
||||||
|
{
|
||||||
|
SpellEntry const * auraSpell = sSpellStore.LookupEntry(spellmgr.GetFirstSpellInChain(m_spellInfo->Id));
|
||||||
|
if ((pVictim->getLevel() + 10) >= auraSpell->spellLevel)
|
||||||
|
ihit->scaleAura = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -873,6 +903,13 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
|
|||||||
target.alive = pVictim->isAlive();
|
target.alive = pVictim->isAlive();
|
||||||
target.damage = 0;
|
target.damage = 0;
|
||||||
target.crit = false;
|
target.crit = false;
|
||||||
|
target.scaleAura = false;
|
||||||
|
if (m_auraScaleMask && target.effectMask == m_auraScaleMask && m_caster != pVictim)
|
||||||
|
{
|
||||||
|
SpellEntry const * auraSpell = sSpellStore.LookupEntry(spellmgr.GetFirstSpellInChain(m_spellInfo->Id));
|
||||||
|
if ((pVictim->getLevel() + 10) >= auraSpell->spellLevel)
|
||||||
|
target.scaleAura = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate hit result
|
// Calculate hit result
|
||||||
if(m_originalCaster)
|
if(m_originalCaster)
|
||||||
@@ -1053,7 +1090,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
|||||||
|
|
||||||
if(spellHitTarget)
|
if(spellHitTarget)
|
||||||
{
|
{
|
||||||
SpellMissInfo missInfo = DoSpellHitOnUnit(spellHitTarget, mask);
|
SpellMissInfo missInfo = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura);
|
||||||
if(missInfo != SPELL_MISS_NONE)
|
if(missInfo != SPELL_MISS_NONE)
|
||||||
{
|
{
|
||||||
if(missInfo != SPELL_MISS_MISS)
|
if(missInfo != SPELL_MISS_MISS)
|
||||||
@@ -1179,7 +1216,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask, bool scaleAura)
|
||||||
{
|
{
|
||||||
if(!unit || !effectMask)
|
if(!unit || !effectMask)
|
||||||
return SPELL_MISS_EVADE;
|
return SPELL_MISS_EVADE;
|
||||||
@@ -1270,22 +1307,43 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
|||||||
|
|
||||||
if (aura_effmask)
|
if (aura_effmask)
|
||||||
{
|
{
|
||||||
|
// Select rank for aura with level requirements only in specific cases
|
||||||
|
// Unit has to be target only of aura effect, both caster and target have to be players, target has to be other than unit target
|
||||||
|
SpellEntry const * aurSpellInfo = m_spellInfo;
|
||||||
|
int32 basePoints[3];
|
||||||
|
if (scaleAura)
|
||||||
|
{
|
||||||
|
aurSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(m_spellInfo,unitTarget->getLevel());
|
||||||
|
assert (aurSpellInfo);
|
||||||
|
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||||
|
{
|
||||||
|
basePoints[i] = aurSpellInfo->EffectBasePoints[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||||
|
{
|
||||||
|
basePoints[i] = m_currentBasePoints[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Unit * caster = m_originalCaster ? m_originalCaster : m_caster;
|
Unit * caster = m_originalCaster ? m_originalCaster : m_caster;
|
||||||
Aura * Aur = new Aura(m_spellInfo, aura_effmask, m_currentBasePoints, unit, m_caster, caster, m_CastItem);
|
Aura * Aur = new Aura(aurSpellInfo, aura_effmask, basePoints, unit, m_caster, caster, m_CastItem);
|
||||||
|
|
||||||
if (!Aur->IsAreaAura())
|
if (!Aur->IsAreaAura())
|
||||||
{
|
{
|
||||||
// Now Reduce spell duration using data received at spell hit
|
// Now Reduce spell duration using data received at spell hit
|
||||||
int32 duration = Aur->GetAuraMaxDuration();
|
int32 duration = Aur->GetAuraMaxDuration();
|
||||||
int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,m_spellInfo);
|
int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,aurSpellInfo);
|
||||||
unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
|
unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
|
||||||
Aur->setDiminishGroup(m_diminishGroup);
|
Aur->setDiminishGroup(m_diminishGroup);
|
||||||
|
|
||||||
duration = caster->ModSpellDuration(m_spellInfo, unit, duration, Aur->IsPositive());
|
duration = caster->ModSpellDuration(aurSpellInfo, unit, duration, Aur->IsPositive());
|
||||||
|
|
||||||
//mod duration of channeled aura by spell haste
|
//mod duration of channeled aura by spell haste
|
||||||
if (IsChanneledSpell(m_spellInfo))
|
if (IsChanneledSpell(m_spellInfo))
|
||||||
caster->ModSpellCastTime(m_spellInfo, duration, this);
|
caster->ModSpellCastTime(aurSpellInfo, duration, this);
|
||||||
|
|
||||||
if(duration != Aur->GetAuraMaxDuration())
|
if(duration != Aur->GetAuraMaxDuration())
|
||||||
{
|
{
|
||||||
@@ -1294,9 +1352,9 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prayer of Mending (jump animation), we need formal caster instead original for correct animation
|
// Prayer of Mending (jump animation), we need formal caster instead original for correct animation
|
||||||
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST)
|
if( aurSpellInfo->SpellFamilyName == SPELLFAMILY_PRIEST)
|
||||||
{
|
{
|
||||||
if(m_spellInfo->SpellFamilyFlags[1] & 0x000020)
|
if(aurSpellInfo->SpellFamilyFlags[1] & 0x000020)
|
||||||
m_caster->CastSpell(unit, 41637, true, NULL, NULL, m_originalCasterGUID);
|
m_caster->CastSpell(unit, 41637, true, NULL, NULL, m_originalCasterGUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2486,6 +2544,27 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill aura scaling information
|
||||||
|
if (m_caster->IsControlledByPlayer() && !IsPassiveSpell(m_spellInfo->Id) && m_spellInfo->spellLevel && !IsChanneledSpell(m_spellInfo) && !m_IsTriggeredSpell)
|
||||||
|
{
|
||||||
|
for (uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i)
|
||||||
|
{
|
||||||
|
if (m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
|
||||||
|
{
|
||||||
|
// Change aura with ranks only if basepoints are taken from spellInfo and aura is positive
|
||||||
|
if (IsPositiveEffect(m_spellInfo->Id, i))
|
||||||
|
{
|
||||||
|
m_auraScaleMask |= (1<<i);
|
||||||
|
if (m_currentBasePoints[i] != m_spellInfo->EffectBasePoints[i])
|
||||||
|
{
|
||||||
|
m_auraScaleMask = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_spellState = SPELL_STATE_PREPARING;
|
m_spellState = SPELL_STATE_PREPARING;
|
||||||
|
|
||||||
if(triggeredByAura)
|
if(triggeredByAura)
|
||||||
@@ -2665,6 +2744,7 @@ void Spell::cast(bool skipCheck)
|
|||||||
&& !target->IsFriendlyTo(m_caster) && !m_caster->canSeeOrDetect(target, true))
|
&& !target->IsFriendlyTo(m_caster) && !m_caster->canSeeOrDetect(target, true))
|
||||||
{
|
{
|
||||||
SendCastResult(SPELL_FAILED_BAD_TARGETS);
|
SendCastResult(SPELL_FAILED_BAD_TARGETS);
|
||||||
|
SendInterrupted(0);
|
||||||
finish(false);
|
finish(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2698,6 +2778,7 @@ void Spell::cast(bool skipCheck)
|
|||||||
if(castResult != SPELL_CAST_OK)
|
if(castResult != SPELL_CAST_OK)
|
||||||
{
|
{
|
||||||
SendCastResult(castResult);
|
SendCastResult(castResult);
|
||||||
|
SendInterrupted(0);
|
||||||
finish(false);
|
finish(false);
|
||||||
SetExecutedCurrently(false);
|
SetExecutedCurrently(false);
|
||||||
return;
|
return;
|
||||||
@@ -2706,6 +2787,14 @@ void Spell::cast(bool skipCheck)
|
|||||||
|
|
||||||
FillTargetMap();
|
FillTargetMap();
|
||||||
|
|
||||||
|
// Spell may be finished after target map check
|
||||||
|
if(m_spellState == SPELL_STATE_FINISHED)
|
||||||
|
{
|
||||||
|
SendInterrupted(0);
|
||||||
|
SetExecutedCurrently(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(m_spellInfo->SpellFamilyName)
|
if(m_spellInfo->SpellFamilyName)
|
||||||
{
|
{
|
||||||
if (m_spellInfo->excludeCasterAuraSpell && !IsPositiveSpell(m_spellInfo->excludeCasterAuraSpell))
|
if (m_spellInfo->excludeCasterAuraSpell && !IsPositiveSpell(m_spellInfo->excludeCasterAuraSpell))
|
||||||
@@ -3337,11 +3426,11 @@ void Spell::SendSpellGo()
|
|||||||
//sLog.outDebug("Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
|
//sLog.outDebug("Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
|
||||||
|
|
||||||
uint32 castFlags = CAST_FLAG_UNKNOWN3;
|
uint32 castFlags = CAST_FLAG_UNKNOWN3;
|
||||||
|
|
||||||
// triggered spells with spell visual != 0
|
// triggered spells with spell visual != 0
|
||||||
if(m_IsTriggeredSpell || m_triggeredByAuraSpell)
|
if(m_IsTriggeredSpell || m_triggeredByAuraSpell)
|
||||||
castFlags |= CAST_FLAG_UNKNOWN0;
|
castFlags |= CAST_FLAG_UNKNOWN0;
|
||||||
|
|
||||||
if(m_spellInfo->Attributes & SPELL_ATTR_REQ_AMMO)
|
if(m_spellInfo->Attributes & SPELL_ATTR_REQ_AMMO)
|
||||||
castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
|
castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
|
||||||
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
|
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
|
||||||
@@ -4217,13 +4306,6 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
if(!m_IsTriggeredSpell && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target))
|
if(!m_IsTriggeredSpell && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target))
|
||||||
return SPELL_FAILED_LINE_OF_SIGHT;
|
return SPELL_FAILED_LINE_OF_SIGHT;
|
||||||
|
|
||||||
// auto selection spell rank implemented in WorldSession::HandleCastSpellOpcode
|
|
||||||
// this case can be triggered if rank not found (too low-level target for first rank)
|
|
||||||
if(m_caster->GetTypeId() == TYPEID_PLAYER && !IsPassiveSpell(m_spellInfo->Id) && !m_CastItem)
|
|
||||||
for(int i=0;i<3;i++)
|
|
||||||
if(IsPositiveEffect(m_spellInfo->Id, i) && m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
|
|
||||||
if(target->getLevel() + 10 < m_spellInfo->spellLevel)
|
|
||||||
return SPELL_FAILED_LOWLEVEL;
|
|
||||||
}
|
}
|
||||||
else if (m_caster->GetTypeId() == TYPEID_PLAYER) // Target - is player caster
|
else if (m_caster->GetTypeId() == TYPEID_PLAYER) // Target - is player caster
|
||||||
{
|
{
|
||||||
@@ -5922,7 +6004,7 @@ bool Spell::CheckTarget(Unit* target, uint32 eff)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Do not check LOS for triggered spells
|
//Do not do further checks for triggered spells
|
||||||
if(m_IsTriggeredSpell)
|
if(m_IsTriggeredSpell)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -568,9 +568,10 @@ class Spell
|
|||||||
SpellMissInfo reflectResult:8;
|
SpellMissInfo reflectResult:8;
|
||||||
uint8 effectMask:8;
|
uint8 effectMask:8;
|
||||||
bool processed:1;
|
bool processed:1;
|
||||||
bool alive:1;
|
bool alive:1;
|
||||||
|
bool crit:1;
|
||||||
|
bool scaleAura:1;
|
||||||
int32 damage;
|
int32 damage;
|
||||||
bool crit;
|
|
||||||
};
|
};
|
||||||
std::list<TargetInfo> m_UniqueTargetInfo;
|
std::list<TargetInfo> m_UniqueTargetInfo;
|
||||||
uint8 m_needAliveTargetMask; // Mask req. alive targets
|
uint8 m_needAliveTargetMask; // Mask req. alive targets
|
||||||
@@ -597,7 +598,7 @@ class Spell
|
|||||||
void AddGOTarget(uint64 goGUID, uint32 effIndex);
|
void AddGOTarget(uint64 goGUID, uint32 effIndex);
|
||||||
void AddItemTarget(Item* target, uint32 effIndex);
|
void AddItemTarget(Item* target, uint32 effIndex);
|
||||||
void DoAllEffectOnTarget(TargetInfo *target);
|
void DoAllEffectOnTarget(TargetInfo *target);
|
||||||
SpellMissInfo DoSpellHitOnUnit(Unit *unit, uint32 effectMask);
|
SpellMissInfo DoSpellHitOnUnit(Unit *unit, uint32 effectMask, bool scaleAura);
|
||||||
void DoTriggersOnSpellHit(Unit *unit);
|
void DoTriggersOnSpellHit(Unit *unit);
|
||||||
void DoAllEffectOnTarget(GOTargetInfo *target);
|
void DoAllEffectOnTarget(GOTargetInfo *target);
|
||||||
void DoAllEffectOnTarget(ItemTargetInfo *target);
|
void DoAllEffectOnTarget(ItemTargetInfo *target);
|
||||||
@@ -638,6 +639,7 @@ class Spell
|
|||||||
uint32 m_customAttr;
|
uint32 m_customAttr;
|
||||||
bool m_skipCheck;
|
bool m_skipCheck;
|
||||||
uint32 m_effectMask;
|
uint32 m_effectMask;
|
||||||
|
uint8 m_auraScaleMask;
|
||||||
|
|
||||||
#ifdef MAP_BASED_RAND_GEN
|
#ifdef MAP_BASED_RAND_GEN
|
||||||
int32 irand(int32 min, int32 max) { return int32 (m_caster->GetMap()->mtRand.randInt(max - min)) + min; }
|
int32 irand(int32 min, int32 max) { return int32 (m_caster->GetMap()->mtRand.randInt(max - min)) + min; }
|
||||||
|
|||||||
Reference in New Issue
Block a user