aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/Formulas.h13
-rw-r--r--src/game/ItemPrototype.h6
-rw-r--r--src/game/Level1.cpp2
-rw-r--r--src/game/Player.cpp69
-rw-r--r--src/game/Player.h10
-rw-r--r--src/game/Spell.cpp36
-rw-r--r--src/game/SpellAuras.cpp86
-rw-r--r--src/game/SpellEffects.cpp8
-rw-r--r--src/game/SpellMgr.cpp5
-rw-r--r--src/game/SpellMgr.h3
-rw-r--r--src/game/StatSystem.cpp35
-rw-r--r--src/game/Unit.cpp246
-rw-r--r--src/game/Unit.h3
-rw-r--r--src/shared/Database/DBCStores.cpp2
-rw-r--r--src/shared/revision_nr.h2
15 files changed, 423 insertions, 103 deletions
diff --git a/src/game/Formulas.h b/src/game/Formulas.h
index a3af5adedbe..cdfe971eba6 100644
--- a/src/game/Formulas.h
+++ b/src/game/Formulas.h
@@ -80,8 +80,17 @@ namespace Trinity
inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ContentLevels content)
{
- //TODO: need modifier for CONTENT_71_80 different from CONTENT_61_70?
- const uint32 nBaseExp = content == CONTENT_1_60 ? 45 : 235;
+ uint32 nBaseExp;
+ switch(content)
+ {
+ case CONTENT_1_60: nBaseExp = 45; break;
+ case CONTENT_61_70: nBaseExp = 235; break;
+ case CONTENT_71_80: nBaseExp = 580; break;
+ default:
+ sLog.outError("BaseGain: Unsupported content level %u",content);
+ nBaseExp = 45; break;
+ }
+
if( mob_level >= pl_level )
{
uint32 nLevelDiff = mob_level - pl_level;
diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h
index e4eb17c840f..b31cc819629 100644
--- a/src/game/ItemPrototype.h
+++ b/src/game/ItemPrototype.h
@@ -76,6 +76,12 @@ enum ItemSpelltriggerType
ITEM_SPELLTRIGGER_ON_EQUIP = 1,
ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2,
ITEM_SPELLTRIGGER_SOULSTONE = 4,
+ /*
+ * ItemSpelltriggerType 5 might have changed on 2.4.3/3.0.3: Such auras
+ * will be applied on item pickup and removed on item loss - maybe on the
+ * other hand the item is destroyed if the aura is removed ("removed on
+ * death" of spell 57348 makes me think so)
+ */
ITEM_SPELLTRIGGER_ON_NO_DELAY_USE = 5, // no equip cooldown
ITEM_SPELLTRIGGER_LEARN_SPELL_ID = 6 // used in item_template.spell_2 with spell_id with SPELL_GENERIC_LEARN in spell_1
};
diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp
index 06032053490..e31d6fe6170 100644
--- a/src/game/Level1.cpp
+++ b/src/game/Level1.cpp
@@ -2085,7 +2085,7 @@ bool ChatHandler::HandleModifyBitCommand(const char* args)
if( !*args )
return false;
- Unit *unit = this->getSelectedUnit();
+ Unit *unit = getSelectedUnit();
if (!unit)
{
SendSysMessage(LANG_NO_CHAR_SELECTED);
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 0f03e0791f4..758574de90b 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -426,6 +426,11 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this)
for (int i = 0; i < MAX_COMBAT_RATING; i++)
m_baseRatingValue[i] = 0;
+
+ m_baseSpellDamage = 0;
+ m_baseSpellHealing = 0;
+ m_baseFeralAP = 0;
+ m_baseManaRegen = 0;
// Honor System
m_lastHonorUpdateTime = time(NULL);
@@ -2963,12 +2968,15 @@ void Player::learnSpell(uint32 spell_id)
bool learning = addSpell(spell_id,active,true,false);
// learn all disabled higher ranks (recursive)
- SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id);
- if (node)
+ if(disabled)
{
- PlayerSpellMap::iterator iter = m_spells.find(node->next);
- if (disabled && iter != m_spells.end() && iter->second->disabled )
- learnSpell(node->next);
+ SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id);
+ if(node)
+ {
+ PlayerSpellMap::iterator iter = m_spells.find(node->next);
+ if (iter != m_spells.end() && iter->second->disabled )
+ learnSpell(node->next);
+ }
}
// prevent duplicated entires in spell book, also not send if not in world (loading)
@@ -6792,9 +6800,31 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
case ITEM_MOD_EXPERTISE_RATING:
ApplyRatingMod(CR_EXPERTISE, int32(val), apply);
break;
+ case ITEM_MOD_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_RANGED_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_FERAL_ATTACK_POWER:
+ ApplyFeralAPBonus(int32(val), apply);
+ break;
+ case ITEM_MOD_SPELL_HEALING_DONE:
+ ApplySpellHealingBonus(int32(val), apply);
+ break;
+ case ITEM_MOD_SPELL_DAMAGE_DONE:
+ ApplySpellDamageBonus(int32(val), apply);
+ break;
+ case ITEM_MOD_MANA_REGENERATION:
+ ApplyManaRegenBonus(int32(val), apply);
+ break;
case ITEM_MOD_ARMOR_PENETRATION_RATING:
ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply);
break;
+ case ITEM_MOD_SPELL_POWER:
+ ApplySpellHealingBonus(int32(val), apply);
+ ApplySpellDamageBonus(int32(val), apply);
+ break;
}
}
@@ -12267,10 +12297,39 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a
((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply);
sLog.outDebug("+ %u EXPERTISE", enchant_amount);
break;
+ case ITEM_MOD_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply);
+ sLog.outDebug("+ %u ATTACK_POWER", enchant_amount);
+ break;
+ case ITEM_MOD_RANGED_ATTACK_POWER:
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
+ sLog.outDebug("+ %u RANGED_ATTACK_POWER", enchant_amount);
+ break;
+ case ITEM_MOD_FERAL_ATTACK_POWER:
+ ((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount);
+ break;
+ case ITEM_MOD_SPELL_HEALING_DONE:
+ ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u SPELL_HEALING_DONE", enchant_amount);
+ break;
+ case ITEM_MOD_SPELL_DAMAGE_DONE:
+ ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u SPELL_DAMAGE_DONE", enchant_amount);
+ break;
+ case ITEM_MOD_MANA_REGENERATION:
+ ((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u MANA_REGENERATION", enchant_amount);
+ break;
case ITEM_MOD_ARMOR_PENETRATION_RATING:
((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply);
sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount);
break;
+ case ITEM_MOD_SPELL_POWER:
+ ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply);
+ ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u SPELL_POWER", enchant_amount);
+ break;
default:
break;
}
diff --git a/src/game/Player.h b/src/game/Player.h
index 0917f0acf27..fb5bb036e4a 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1644,9 +1644,12 @@ class TRINITY_DLL_SPEC Player : public Unit
void UpdateArmor();
void UpdateMaxHealth();
void UpdateMaxPower(Powers power);
+ void ApplyFeralAPBonus(int32 amount, bool apply);
void UpdateAttackPowerAndDamage(bool ranged = false);
void UpdateShieldBlockValue();
void UpdateDamagePhysical(WeaponAttackType attType);
+ void ApplySpellDamageBonus(int32 amount, bool apply);
+ void ApplySpellHealingBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus();
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage);
@@ -1664,6 +1667,8 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 GetRangedCritDamageReduction(uint32 damage) const;
uint32 GetSpellCritDamageReduction(uint32 damage) const;
uint32 GetDotDamageReduction(uint32 damage) const;
+ uint32 GetBaseSpellDamageBonus() { return m_baseSpellDamage;}
+ uint32 GetBaseSpellHealingBonus() { return m_baseSpellHealing;}
float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
void UpdateBlockPercentage();
@@ -1678,6 +1683,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void UpdateAllSpellCritChances();
void UpdateSpellCritChance(uint32 school);
void UpdateExpertise(WeaponAttackType attType);
+ void ApplyManaRegenBonus(int32 amount, bool apply);
void UpdateManaRegen();
const uint64& GetLootGUID() const { return m_lootGuid; }
@@ -2344,6 +2350,10 @@ class TRINITY_DLL_SPEC Player : public Unit
float m_auraBaseMod[BASEMOD_END][MOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING];
+ uint16 m_baseSpellDamage;
+ uint16 m_baseSpellHealing;
+ uint16 m_baseFeralAP;
+ uint16 m_baseManaRegen;
SpellModList m_spellMods[MAX_SPELLMOD];
int32 m_SpellModRemoveCount;
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 858b6038ba8..b57b2f3ff5f 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -624,15 +624,19 @@ void Spell::prepareDataForTriggerSystem()
// Ņan spell trigger another or not ( m_canTrigger )
// Create base triggers flags for Attacker and Victim ( m_procAttacker and m_procVictim)
//==========================================================================================
-
// Fill flag can spell trigger or not
- if (!m_IsTriggeredSpell)
+ // TODO: possible exist spell attribute for this
+ m_canTrigger = false;
+
+ if (m_CastItem)
+ m_canTrigger = false; // Do not trigger from item cast spell
+ else if (!m_IsTriggeredSpell)
m_canTrigger = true; // Normal cast - can trigger
else if (!m_triggeredByAuraSpell)
m_canTrigger = true; // Triggered from SPELL_EFFECT_TRIGGER_SPELL - can trigger
- else // Exceptions (some periodic triggers)
+
+ if (!m_canTrigger) // Exceptions (some periodic triggers)
{
- m_canTrigger = false; // Triggered spells can`t trigger another
switch (m_spellInfo->SpellFamilyName)
{
case SPELLFAMILY_MAGE: // Arcane Missles / Blizzard triggers need do it
@@ -644,17 +648,17 @@ void Spell::prepareDataForTriggerSystem()
case SPELLFAMILY_PRIEST: // For Penance heal/damage triggers need do it
if (m_spellInfo->SpellFamilyFlags & 0x0001800000000000LL) m_canTrigger = true;
break;
- case SPELLFAMILY_HUNTER: // Hunter Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect
- if (m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL) m_canTrigger = true;
+ case SPELLFAMILY_ROGUE: // For poisons need do it
+ if (m_spellInfo->SpellFamilyFlags & 0x000000101001E000LL) m_canTrigger = true;
+ break;
+ case SPELLFAMILY_HUNTER: // Hunter Rapid Killing/Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect
+ if (m_spellInfo->SpellFamilyFlags & 0x0100200000000014LL) m_canTrigger = true;
break;
case SPELLFAMILY_PALADIN: // For Holy Shock triggers need do it
if (m_spellInfo->SpellFamilyFlags & 0x0001000000200000LL) m_canTrigger = true;
break;
}
}
- // Do not trigger from item cast spell
- if (m_CastItem)
- m_canTrigger = false;
// Get data for type of attack and fill base info for trigger
switch (m_spellInfo->DmgClass)
@@ -3626,6 +3630,20 @@ uint8 Spell::CanCast(bool strict)
}
}
}
+ else if (m_caster->GetTypeId()==TYPEID_PLAYER) // Target - is player caster
+ {
+ // Additional check for some spells
+ // If 0 spell effect empty - client not send target data (need use selection)
+ // TODO: check it on next client version
+ if (m_targets.m_targetMask == TARGET_FLAG_SELF &&
+ m_spellInfo->Effect[0] == 0 && m_spellInfo->EffectImplicitTargetA[1] != TARGET_SELF)
+ {
+ if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection()))
+ m_targets.setUnitTarget(target);
+ else
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+ }
// check pet presents
for(int j=0;j<3;j++)
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index 182bacf8ee8..a7758846316 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -855,7 +855,7 @@ void Aura::_AddAura()
if (!secondaura)
{
// Update Seals information
- if( IsSealSpell(GetSpellProto()) )
+ if (IsSealSpell(m_spellProto))
m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
// Conflagrate aura state on Immolate
@@ -863,15 +863,15 @@ void Aura::_AddAura()
m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
// Faerie Fire (druid versions)
- if( m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true);
// Victorious
- if( m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true);
// Swiftmend state on Regrowth & Rejuvenation
- if(m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x50 )
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x50 )
m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
// Deadly poison aura state
@@ -945,59 +945,55 @@ void Aura::_RemoveAura()
//*****************************************************
// Update target aura state flag (at last aura remove)
- // TODO: Make it easer
//*****************************************************
- // Update Seals information
- if( IsSealSpell(GetSpellProto()) )
- m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false);
-
- // Conflagrate aura state
- if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
- m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false);
-
- // Faerie Fire (druid versions)
- if( m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
- m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, false);
-
- // Victorious
- if( m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
- m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
-
- // Swiftmend aura state
- if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags & 0x50)
+ uint32 removeState = 0;
+ switch(m_spellProto->SpellFamilyName)
{
- bool found = false;
- Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
- for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
- {
- if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && (*i)->GetSpellProto()->SpellFamilyFlags & 0x50 )
- {
- found = true;
- break;
- }
- }
- if(!found)
- m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false);
- }
+ case SPELLFAMILY_PALADIN:
+ if (IsSealSpell(m_spellProto))
+ removeState = AURA_STATE_JUDGEMENT; // Update Seals information
+ break;
+ case SPELLFAMILY_WARLOCK:
+ if(m_spellProto->SpellFamilyFlags & 4)
+ removeState = AURA_STATE_IMMOLATE; // Conflagrate aura state
+ break;
+ case SPELLFAMILY_DRUID:
+ if(m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
+ removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
+ else if(m_spellProto->SpellFamilyFlags & 0x50)
+ removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
+ break;
+ case SPELLFAMILY_WARRIOR:
+ if(m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
+ removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
+ break;
+ case SPELLFAMILY_ROGUE:
+ if(m_spellProto->SpellFamilyFlags & 0x10000)
+ removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
+ break;
+ case SPELLFAMILY_HUNTER:
+ if(m_spellProto->SpellFamilyFlags & 0x1000000000000000LL)
+ removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
- // Deadly poison aura state
- if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags & 0x10000)
+ }
+ // Remove state (but need check other auras for it)
+ if (removeState)
{
- // current aura already removed, search present of another
bool found = false;
- Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
- for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
+ Unit::AuraMap& Auras = m_target->GetAuras();
+ for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
- SpellEntry const* itr_spell = (*itr)->GetSpellProto();
- if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && itr_spell->SpellFamilyFlags & 0x10000)
+ SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
+ if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
+ auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags )
{
found = true;
break;
}
}
- // this has been last deadly poison aura
+ // this has been last aura
if(!found)
- m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
+ m_target->ModifyAuraState(AuraState(removeState), false);
}
// reset cooldown state for spells
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 2c249afdd24..abf20cd9dc2 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -1673,6 +1673,14 @@ void Spell::EffectDummy(uint32 i)
switch(m_spellInfo->Id)
{
+ // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus
+ case 20187:
+ {
+ if (!unitTarget)
+ return;
+ m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
+ return;
+ }
case 31789: // Righteous Defense (step 1)
{
// 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 79942a2d38e..2b5787bad90 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -1273,6 +1273,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool
if(spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
return false;
+ // TODO: Is this needed?
+ // Allow stack passive and not passive spells
+ if ((spellInfo_1->Attributes & SPELL_ATTR_PASSIVE)!=(spellInfo_2->Attributes & SPELL_ATTR_PASSIVE))
+ return false;
+
// generic spells
if(!spellInfo_1->SpellFamilyName)
{
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index 76bffbce1dd..8dc2d1af35c 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -285,6 +285,7 @@ enum SpellSelectTargetTypes
#define SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR 0x000004000LL
#define SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK 0x080000000LL
+#define SPELLFAMILYFLAG_PALADIN_SEALS 0x26000C000A000000LL
// Spell clasification
enum SpellSpecific
{
@@ -338,7 +339,7 @@ inline bool IsSealSpell(SpellEntry const *spellInfo)
{
//Collection of all the seal family flags. No other paladin spell has any of those.
return spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN &&
- ( spellInfo->SpellFamilyFlags & 0x26000C000A000000LL );
+ ( spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_PALADIN_SEALS );
}
inline bool IsElementalShield(SpellEntry const *spellInfo)
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp
index 50f0ed66bd7..5473206e8bd 100644
--- a/src/game/StatSystem.cpp
+++ b/src/game/StatSystem.cpp
@@ -93,6 +93,21 @@ bool Player::UpdateStats(Stats stat)
return true;
}
+void Player::ApplySpellDamageBonus(int32 amount, bool apply)
+{
+ m_baseSpellDamage+=apply?amount:-amount;
+ // For speed just update for client
+ ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply);
+}
+
+void Player::ApplySpellHealingBonus(int32 amount, bool apply)
+{
+ m_baseSpellHealing+=apply?amount:-amount;
+ // For speed just update for client
+ for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
+ ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, amount, apply);;
+}
+
void Player::UpdateSpellDamageAndHealingBonus()
{
// Magic damage modifiers implemented in Unit::SpellDamageBonus
@@ -223,6 +238,12 @@ void Player::UpdateMaxPower(Powers power)
SetMaxPower(power, uint32(value));
}
+void Player::ApplyFeralAPBonus(int32 amount, bool apply)
+{
+ m_baseFeralAP+= apply ? amount:-amount;
+ UpdateAttackPowerAndDamage();
+}
+
void Player::UpdateAttackPowerAndDamage(bool ranged )
{
float val2 = 0.0f;
@@ -297,12 +318,12 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
switch(m_form)
{
case FORM_CAT:
- val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f; break;
+ val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f + m_baseFeralAP; break;
case FORM_BEAR:
case FORM_DIREBEAR:
- val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break;
case FORM_MOONKIN:
- val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break;
default:
val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
}
@@ -629,6 +650,12 @@ void Player::UpdateExpertise(WeaponAttackType attack)
}
}
+void Player::ApplyManaRegenBonus(int32 amount, bool apply)
+{
+ m_baseManaRegen+= apply ? amount : -amount;
+ UpdateManaRegen();
+}
+
void Player::UpdateManaRegen()
{
float Intellect = GetStat(STAT_INTELLECT);
@@ -638,7 +665,7 @@ void Player::UpdateManaRegen()
power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA);
// Mana regen from SPELL_AURA_MOD_POWER_REGEN aura
- float power_regen_mp5 = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f;
+ float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f;
// Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura
AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index f50187efc64..d4c7b1de61f 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -905,7 +905,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(spell->getState() == SPELL_STATE_PREPARING)
{
uint32 interruptFlags = spell->m_spellInfo->InterruptFlags;
- if(interruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE)
+ if(interruptFlags & SPELL_INTERRUPT_FLAG_ABORT_ON_DMG)
pVictim->InterruptNonMeleeSpells(false);
else if(interruptFlags & SPELL_INTERRUPT_FLAG_PUSH_BACK)
spell->Delayed();
@@ -5004,7 +5004,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 22858;
break;
}
- else if (dummySpell->SpellIconID == 1697) // Second Wind
+ // Second Wind
+ if (dummySpell->SpellIconID == 1697)
{
// only for spells and hit/crit (trigger start always) and not start from self casted spells (5530 Mace Stun Effect for example)
if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
@@ -5017,6 +5018,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
{
case 29838: triggered_spell_id=29842; break;
case 29834: triggered_spell_id=29841; break;
+ case 42770: triggered_spell_id=42771; break;
default:
sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (SW)",dummySpell->Id);
return false;
@@ -5025,6 +5027,13 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
target = this;
break;
}
+ // Damage Shield
+ if (dummySpell->SpellIconID == 3214)
+ {
+ triggered_spell_id = 59653;
+ basepoints0 = GetShieldBlockValue() * triggeredByAura->GetModifier()->m_amount / 100;
+ break;
+ }
break;
}
case SPELLFAMILY_WARLOCK:
@@ -5074,6 +5083,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
mod->m_amount-=damage;
return true;
}
+ // Fel Synergy
+ if (dummySpell->SpellIconID == 3222)
+ {
+ target = GetPet();
+ if (!target)
+ return false;
+ triggered_spell_id = 54181;
+ basepoints0 = damage * triggeredByAura->GetModifier()->m_amount / 100;
+ break;
+ }
switch(dummySpell->Id)
{
// Nightfall
@@ -5194,7 +5213,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
// heal amount
- basepoints0 = int32(damage * 2 / 100);
+ basepoints0 = damage * triggeredByAura->GetModifier()->m_amount/100;
target = this;
triggered_spell_id = 39373;
break;
@@ -5326,6 +5345,31 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
break;
}
}
+ // Cut to the Chase
+ if( dummySpell->SpellIconID == 2909 )
+ {
+ // "refresh your Slice and Dice duration to its 5 combo point maximum"
+ // lookup Slice and Dice
+ AuraList const& sd = GetAurasByType(SPELL_AURA_MOD_HASTE);
+ for(AuraList::const_iterator itr = sd.begin(); itr != sd.end(); ++itr)
+ {
+ SpellEntry const *spellProto = (*itr)->GetSpellProto();
+ if( spellProto->SpellFamilyName == SPELLFAMILY_ROGUE &&
+ spellProto->SpellFamilyFlags & 0x0000000000040000LL)
+ {
+ (*itr)->SetAuraMaxDuration(GetSpellMaxDuration(spellProto));
+ (*itr)->RefreshAura();
+ return true;
+ }
+ }
+ return false;
+ }
+ // Deadly Brew
+ if( dummySpell->SpellIconID == 2963 )
+ {
+ triggered_spell_id = 25809;
+ break;
+ }
// Quick Recovery
if( dummySpell->SpellIconID == 2116 )
{
@@ -5360,6 +5404,33 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 34720;
break;
}
+ // Hunting Party
+ if ( dummySpell->SpellIconID == 3406 )
+ {
+ triggered_spell_id = 57669;
+ target = this;
+ return true;
+ }
+ // Lock and Load
+ if ( dummySpell->SpellIconID == 3579 )
+ {
+ // Proc only from periodic (from trap activation proc another aura of this spell)
+ if (!(procFlag & PROC_FLAG_ON_DO_PERIODIC))
+ return false;
+ if (!roll_chance_i(triggeredByAura->GetModifier()->m_amount))
+ return false;
+ triggered_spell_id = 56453;
+ target = this;
+ break;
+ }
+ // Rapid Recuperation
+ if ( dummySpell->SpellIconID == 3560 )
+ {
+ // mane regen from Rapid Killing
+ triggered_spell_id = 56654;
+ target = this;
+ break;
+ }
break;
}
case SPELLFAMILY_PALADIN:
@@ -5702,8 +5773,27 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 55533;
break;
}
+ // Spirit Hunt
+ case 58877:
+ {
+ // Cast on owner
+ target = GetOwner();
+ if(!target)
+ return false;
+ basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
+ triggered_spell_id = 58879;
+ break;
+ }
+ }
+ // Ancestral Awakening
+ if (dummySpell->SpellIconID == 2018)
+ {
+ // TODO: frite dummy fot triggered spell
+ triggered_spell_id = 52759;
+ basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
+ target = this;
+ break;
}
-
// Earth Shield
if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL)
{
@@ -5712,6 +5802,26 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 379;
break;
}
+ // Improved Water Shield
+ if (dummySpell->SpellIconID == 2287)
+ {
+ // lookup water shield
+ AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
+ for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr)
+ {
+ if( (*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN &&
+ (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000002000000000LL)
+ {
+ uint32 spell = (*itr)->GetSpellProto()->EffectTriggerSpell[(*itr)->GetEffIndex()];
+ CastSpell(this, spell, true, castItem, triggeredByAura);
+ if ((*itr)->DropAuraCharge())
+ RemoveAurasDueToSpell((*itr)->GetId());
+ return true;
+ }
+ }
+ return false;
+ break;
+ }
// Lightning Overload
if (dummySpell->SpellIconID == 2018) // only this spell have SpellFamily Shaman SpellIconID == 2018 and dummy aura
{
@@ -5755,6 +5865,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return false;
}
// No thread generated mod
+ // TODO: exist special flag in spell attributes for this, need found and use!
SpellModifier *mod = new SpellModifier;
mod->op = SPELLMOD_THREAT;
mod->value = -100;
@@ -5777,10 +5888,78 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return true;
}
+ // Static Shock
+ if(dummySpell->SpellIconID == 3059)
+ {
+ // lookup Lightning Shield
+ AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
+ for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr)
+ {
+ if( (*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN &&
+ (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL)
+ {
+ uint32 spell = 0;
+ switch ((*itr)->GetId())
+ {
+ case 324: spell = 26364; break;
+ case 325: spell = 26365; break;
+ case 905: spell = 26366; break;
+ case 945: spell = 26367; break;
+ case 8134: spell = 26369; break;
+ case 10431: spell = 26370; break;
+ case 10432: spell = 26363; break;
+ case 25469: spell = 26371; break;
+ case 25472: spell = 26372; break;
+ default:
+ return false;
+ }
+ CastSpell(this, spell, true, castItem, triggeredByAura);
+ if ((*itr)->DropAuraCharge())
+ RemoveAurasDueToSpell((*itr)->GetId());
+ return true;
+ }
+ }
+ return false;
+ break;
+ }
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
+ // Blood Aura
+ if (dummySpell->SpellIconID == 2636)
+ {
+ if (GetTypeId() != TYPEID_PLAYER || !((Player*)this)->isHonorOrXPTarget(pVictim))
+ return false;
+ basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
+ triggered_spell_id = 53168;
+ break;
+ }
+ // Butchery
+ if (dummySpell->SpellIconID == 2664)
+ {
+ basepoints0 = triggeredByAura->GetModifier()->m_amount;
+ triggered_spell_id = 50163;
+ target = this;
+ break;
+ }
+ // Dancing Rune Weapon
+ if (dummySpell->Id == 49028)
+ {
+ // 1 dummy aura for dismiss rune blade
+ if (triggeredByAura->GetEffIndex()!=2)
+ return false;
+ // TODO: wite script for this "fights on its own, doing the same attacks"
+ // NOTE: Trigger here on every attack and spell cast
+ return false;
+ }
+ // Mark of Blood
+ if (dummySpell->Id == 49005)
+ {
+ // TODO: need more info (cooldowns/PPM)
+ triggered_spell_id = 50424;
+ break;
+ }
// Vendetta
if (dummySpell->SpellFamilyFlags & 0x0000000000010000LL)
{
@@ -5790,20 +5969,34 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
break;
}
// Necrosis
- else if (dummySpell->SpellIconID == 2709)
+ if (dummySpell->SpellIconID == 2709)
{
basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
triggered_spell_id = 51460;
break;
}
- // Butchery
- else if (dummySpell->SpellIconID == 2664)
+ // Runic Power Back on Snare/Root
+ if (dummySpell->Id == 61257)
{
- basepoints0 = triggeredByAura->GetModifier()->m_amount;
- triggered_spell_id = 50163;
+ // only for spells and hit/crit (trigger start always) and not start from self casted spells
+ if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
+ return false;
+ // Need snare or root mechanic
+ if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_SNARE))))
+ return false;
+ triggered_spell_id = 61258;
target = this;
break;
}
+ // Wandering Plague
+ if (dummySpell->SpellIconID == 1614)
+ {
+ if (!roll_chance_f(GetUnitCriticalChance(BASE_ATTACK, pVictim)))
+ return false;
+ basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
+ triggered_spell_id = 50526;
+ break;
+ }
break;
}
default:
@@ -6272,10 +6465,6 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
trigger_spell_id = 26371; break;
case 25472: // Rank 9
trigger_spell_id = 26372; break;
- case 49280: // Rank 10
- trigger_spell_id = 49278; break;
- case 49281: // Rank 11
- trigger_spell_id = 49279; break;
default:
sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield", auraSpellInfo->Id);
return false;
@@ -6494,8 +6683,9 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
// Astral Shift
case 52179:
{
- if(!procSpell)
+ if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
return false;
+
// Need stun, fear or silence mechanic
if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_SILENCE)|(1<<MECHANIC_STUN)|(1<<MECHANIC_FEAR))))
return false;
@@ -7587,21 +7777,10 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
DotFactor = 0.95f;
CastingTime = 3500;
}
- // Seal of Righteousness - 10.2%/9.8% ( based on weapon type ) of Holy Damage, multiplied by weapon speed
- else if((spellProto->SpellFamilyFlags & 0x8000000LL) && spellProto->SpellIconID == 25)
+ // Judgement of Righteousness - 32%
+ else if (spellProto->SpellFamilyFlags & 0x0000000000000400LL)
{
- Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
- float wspeed = GetAttackTime(BASE_ATTACK)/1000.0f;
-
- if( item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON)
- CastingTime = uint32(wspeed*3500*0.102f);
- else
- CastingTime = uint32(wspeed*3500*0.098f);
- }
- // Judgement of Righteousness - 73%
- else if ((spellProto->SpellFamilyFlags & 1024) && spellProto->SpellIconID == 25)
- {
- CastingTime = 2555;
+ CastingTime = 1120;
}
// Seal of Vengeance - 17% per Fully Stacked Tick - 5 Applications
else if ((spellProto->SpellFamilyFlags & 0x80000000000LL) && spellProto->SpellIconID == 2292)
@@ -7619,11 +7798,6 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
{
CastingTime = 0;
}
- // Seal of Righteousness trigger - already computed for parent spell
- else if ( spellProto->SpellFamilyName==SPELLFAMILY_PALADIN && spellProto->SpellIconID==25 && spellProto->AttributesEx4 & 0x00800000LL )
- {
- return pdamage;
- }
break;
case SPELLFAMILY_SHAMAN:
// totem attack
@@ -7749,6 +7923,9 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
if (GetTypeId() == TYPEID_PLAYER)
{
+ // Base value
+ DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellDamageBonus();
+
// Damage bonus from stats
AuraList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
for(AuraList::const_iterator i = mDamageDoneOfStatPercent.begin();i != mDamageDoneOfStatPercent.end(); ++i)
@@ -8126,6 +8303,9 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask)
// Healing bonus of spirit, intellect and strength
if (GetTypeId() == TYPEID_PLAYER)
{
+ // Base value
+ AdvertisedBenefit +=((Player*)this)->GetBaseSpellHealingBonus();
+
// Healing bonus from stats
AuraList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT);
for(AuraList::const_iterator i = mHealingDoneOfStatPercent.begin();i != mHealingDoneOfStatPercent.end(); ++i)
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 5791c060289..4c3d6e48eee 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -45,7 +45,8 @@ enum SpellInterruptFlags
SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back
SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, // interrupt
SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, // no
- SPELL_INTERRUPT_FLAG_DAMAGE = 0x10 // _complete_ interrupt on direct damage?
+ SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10, // _complete_ interrupt on direct damage
+ //SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph"
};
enum SpellChannelInterruptFlags
diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp
index cd02ed42252..cd4a2e5faf0 100644
--- a/src/shared/Database/DBCStores.cpp
+++ b/src/shared/Database/DBCStores.cpp
@@ -568,7 +568,7 @@ uint32 GetAreaFlagByMapId(uint32 mapid)
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
{
- if(mapid != 530 || mapid != 571) // speed for most cases
+ if(mapid != 530 && mapid != 571) // speed for most cases
return mapid;
if(WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId))
diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h
index d159296e986..60f75e4853c 100644
--- a/src/shared/revision_nr.h
+++ b/src/shared/revision_nr.h
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
- #define REVISION_NR "7092"
+ #define REVISION_NR "7100"
#endif // __REVISION_NR_H__