aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/FULL/world_spell_full.sql37
-rw-r--r--sql/updates/4320_world_.sql20
-rw-r--r--src/game/PetHandler.cpp13
-rw-r--r--src/game/Player.cpp3
-rw-r--r--src/game/Spell.cpp120
-rw-r--r--src/game/Spell.h8
-rw-r--r--src/game/SpellAuras.cpp3
-rw-r--r--src/game/SpellMgr.cpp2
-rw-r--r--src/game/Unit.cpp13
9 files changed, 175 insertions, 44 deletions
diff --git a/sql/FULL/world_spell_full.sql b/sql/FULL/world_spell_full.sql
index c8656ee3ecc..42fdce82132 100644
--- a/sql/FULL/world_spell_full.sql
+++ b/sql/FULL/world_spell_full.sql
@@ -1446,15 +1446,34 @@ INSERT INTO `spell_proc_event` (`entry`, `SchoolMask`, `SpellFamilyName`, `Spell
-- --------
TRUNCATE TABLE `spell_enchant_proc_data`;
INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES
-(2, 0, 8.8,0), -- Frostbrand Weapon
-(12, 0, 8.8,0), -- Frostbrand Weapon
-(524, 0, 8.8,0), -- Frostbrand Weapon
-(1667, 0, 8.8,0), -- Frostbrand Weapon
-(1668, 0, 8.8,0), -- Frostbrand Weapon
-(2635, 0, 8.8,0), -- Frostbrand Weapon
-(3782, 0, 8.8,0), -- Frostbrand Weapon
-(3783, 0, 8.8,0), -- Frostbrand Weapon
-(3784, 0, 8.8,0); -- Frostbrand Weapon
+ -- Frostbrand Weapon
+(2, 0, 8.8,0),
+(12, 0, 8.8,0),
+(524, 0, 8.8,0),
+(1667, 0, 8.8,0),
+(1668, 0, 8.8,0),
+(2635, 0, 8.8,0),
+(3782, 0, 8.8,0),
+(3783, 0, 8.8,0),
+(3784, 0, 8.8,0),
+ -- Wound Poison
+(703, 0, 21.43,0),
+(704, 0, 21.43,0),
+(705, 0, 21.43,0),
+(706, 0, 21.43,0),
+(2644, 0, 21.43,0),
+(3772, 0, 21.43,0),
+(3773, 0, 21.43,0),
+ -- Instant Poison
+(323, 0, 8.53,0),
+(324, 0, 8.53,0),
+(325, 0, 8.53,0),
+(623, 0, 8.53,0),
+(624, 0, 8.53,0),
+(625, 0, 8.53,0),
+(2641, 0, 8.53,0),
+(3768, 0, 8.53,0),
+(3769, 0, 8.53,0);
-- --------
-- SPELL AFFECT
diff --git a/sql/updates/4320_world_.sql b/sql/updates/4320_world_.sql
new file mode 100644
index 00000000000..a89e44b88b2
--- /dev/null
+++ b/sql/updates/4320_world_.sql
@@ -0,0 +1,20 @@
+DELETE FROM `spell_enchant_proc_data` WHERE `entry` IN (703, 704, 705, 706, 2644, 3772, 3773, 323, 324, 325, 623, 624, 625, 2641, 3768, 3769);
+INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES
+ -- Wound Poison
+(703, 0, 21.43,0),
+(704, 0, 21.43,0),
+(705, 0, 21.43,0),
+(706, 0, 21.43,0),
+(2644, 0, 21.43,0),
+(3772, 0, 21.43,0),
+(3773, 0, 21.43,0),
+ -- Instant Poison
+(323, 0, 8.53,0),
+(324, 0, 8.53,0),
+(325, 0, 8.53,0),
+(623, 0, 8.53,0),
+(624, 0, 8.53,0),
+(625, 0, 8.53,0),
+(2641, 0, 8.53,0),
+(3768, 0, 8.53,0),
+(3769, 0, 8.53,0);
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index 3dc7c6d4ff1..67e6576c25b 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -615,12 +615,6 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
return;
}
- if (caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->GetGlobalCooldown() > 0)
- {
- caster->SendPetCastFail(spellid, SPELL_FAILED_NOT_READY);
- return;
- }
-
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid);
if(!spellInfo)
{
@@ -628,6 +622,13 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
return;
}
+ if (spellInfo->StartRecoveryCategory > 0) //Check if spell is affected by GCD
+ if (caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->GetGlobalCooldown() > 0)
+ {
+ caster->SendPetCastFail(spellid, SPELL_FAILED_NOT_READY);
+ return;
+ }
+
// do not cast not learned spells
if(!caster->HasSpell(spellid) || IsPassiveSpell(spellid))
return;
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 62f712aabf1..0a90f721899 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -17316,6 +17316,9 @@ void Player::SetSpellModTakingSpell(Spell * spell, bool apply)
if (!spell || (m_spellModTakingSpell && m_spellModTakingSpell != spell))
return;
+ if (apply && spell->getState() == SPELL_STATE_FINISHED)
+ return;
+
if (apply)
m_spellModTakingSpell = spell;
else
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 2dd24dcfc6c..88e815352e1 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -371,6 +371,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
m_applyMultiplierMask = 0;
m_effectMask = 0;
+ m_auraScaleMask = 0;
// Get data for type of attack
switch (m_spellInfo->DmgClass)
@@ -701,7 +702,6 @@ void Spell::FillTargetMap()
break;
}
}
-
if(IsChanneledSpell(m_spellInfo))
{
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)
@@ -859,6 +882,13 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
{
if (!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;
}
}
@@ -873,6 +903,13 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
target.alive = pVictim->isAlive();
target.damage = 0;
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
if(m_originalCaster)
@@ -1053,7 +1090,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
if(spellHitTarget)
{
- SpellMissInfo missInfo = DoSpellHitOnUnit(spellHitTarget, mask);
+ SpellMissInfo missInfo = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura);
if(missInfo != SPELL_MISS_NONE)
{
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)
return SPELL_MISS_EVADE;
@@ -1270,22 +1307,43 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
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;
- 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())
{
// Now Reduce spell duration using data received at spell hit
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);
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
if (IsChanneledSpell(m_spellInfo))
- caster->ModSpellCastTime(m_spellInfo, duration, this);
+ caster->ModSpellCastTime(aurSpellInfo, duration, this);
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
- 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);
}
}
@@ -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;
if(triggeredByAura)
@@ -2665,6 +2744,7 @@ void Spell::cast(bool skipCheck)
&& !target->IsFriendlyTo(m_caster) && !m_caster->canSeeOrDetect(target, true))
{
SendCastResult(SPELL_FAILED_BAD_TARGETS);
+ SendInterrupted(0);
finish(false);
return;
}
@@ -2698,6 +2778,7 @@ void Spell::cast(bool skipCheck)
if(castResult != SPELL_CAST_OK)
{
SendCastResult(castResult);
+ SendInterrupted(0);
finish(false);
SetExecutedCurrently(false);
return;
@@ -2706,6 +2787,14 @@ void Spell::cast(bool skipCheck)
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->excludeCasterAuraSpell && !IsPositiveSpell(m_spellInfo->excludeCasterAuraSpell))
@@ -3337,11 +3426,11 @@ void Spell::SendSpellGo()
//sLog.outDebug("Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
uint32 castFlags = CAST_FLAG_UNKNOWN3;
-
+
// triggered spells with spell visual != 0
if(m_IsTriggeredSpell || m_triggeredByAuraSpell)
castFlags |= CAST_FLAG_UNKNOWN0;
-
+
if(m_spellInfo->Attributes & SPELL_ATTR_REQ_AMMO)
castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
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))
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
{
@@ -5922,7 +6004,7 @@ bool Spell::CheckTarget(Unit* target, uint32 eff)
return false;
}
- //Do not check LOS for triggered spells
+ //Do not do further checks for triggered spells
if(m_IsTriggeredSpell)
return true;
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 59f21fd6bae..21a73b2597a 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -568,9 +568,10 @@ class Spell
SpellMissInfo reflectResult:8;
uint8 effectMask:8;
bool processed:1;
- bool alive:1;
+ bool alive:1;
+ bool crit:1;
+ bool scaleAura:1;
int32 damage;
- bool crit;
};
std::list<TargetInfo> m_UniqueTargetInfo;
uint8 m_needAliveTargetMask; // Mask req. alive targets
@@ -597,7 +598,7 @@ class Spell
void AddGOTarget(uint64 goGUID, uint32 effIndex);
void AddItemTarget(Item* target, uint32 effIndex);
void DoAllEffectOnTarget(TargetInfo *target);
- SpellMissInfo DoSpellHitOnUnit(Unit *unit, uint32 effectMask);
+ SpellMissInfo DoSpellHitOnUnit(Unit *unit, uint32 effectMask, bool scaleAura);
void DoTriggersOnSpellHit(Unit *unit);
void DoAllEffectOnTarget(GOTargetInfo *target);
void DoAllEffectOnTarget(ItemTargetInfo *target);
@@ -638,6 +639,7 @@ class Spell
uint32 m_customAttr;
bool m_skipCheck;
uint32 m_effectMask;
+ uint8 m_auraScaleMask;
#ifdef MAP_BASED_RAND_GEN
int32 irand(int32 min, int32 max) { return int32 (m_caster->GetMap()->mtRand.randInt(max - min)) + min; }
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index aa6db06f4a8..5503dce1b3d 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -4259,6 +4259,9 @@ void AuraEffect::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real, bool chan
m_target->UpdateSpeed(MOVE_RUN, true);
m_target->UpdateSpeed(MOVE_SWIM, true);
m_target->UpdateSpeed(MOVE_FLIGHT, true);
+ m_target->UpdateSpeed(MOVE_RUN_BACK, true);
+ m_target->UpdateSpeed(MOVE_SWIM_BACK, true);
+ m_target->UpdateSpeed(MOVE_FLIGHT_BACK, true);
}
void AuraEffect::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real, bool changeAmount)
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index e479c529d50..c92a75e4661 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -576,6 +576,8 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex, bool deep)
switch(spellId)
{
+ case 46392: // Focused Assault
+ case 46393: // Brutal Assault
case 28441: // not positive dummy spell
case 37675: // Chaos Blast
case 41519: // Mark of Stormrage
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 393137833bb..e1ed8cb44b1 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -60,7 +60,7 @@ float baseMoveSpeed[MAX_MOVE_TYPE] =
{
2.5f, // MOVE_WALK
7.0f, // MOVE_RUN
- 1.25f, // MOVE_RUN_BACK
+ 3.0f, // MOVE_RUN_BACK
4.722222f, // MOVE_SWIM
4.5f, // MOVE_SWIM_BACK
3.141594f, // MOVE_TURN_RATE
@@ -10860,6 +10860,11 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
switch(mtype)
{
+ // Only apply debuffs
+ case MOVE_FLIGHT_BACK:
+ case MOVE_RUN_BACK:
+ case MOVE_SWIM_BACK:
+ break;
case MOVE_WALK:
return;
case MOVE_RUN:
@@ -10878,15 +10883,11 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
}
break;
}
- case MOVE_RUN_BACK:
- return;
case MOVE_SWIM:
{
main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_SWIM_SPEED);
break;
}
- case MOVE_SWIM_BACK:
- return;
case MOVE_FLIGHT:
{
if (GetTypeId()==TYPEID_UNIT && IsControlledByPlayer()) // not sure if good for pet
@@ -10918,8 +10919,6 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
vehicle->UpdateSpeed(MOVE_FLIGHT, true);
break;
}
- case MOVE_FLIGHT_BACK:
- return;
default:
sLog.outError("Unit::UpdateSpeed: Unsupported move type (%d)", mtype);
return;