[Implémentation] Stacking rules
concerne les totems,buff etc dans un groupe de raid
[code=diff]
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 9799731..0052a17 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -2836,7 +2836,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS,0);
for (int i = 0; i < MAX_SPELL_SCHOOL; ++i)
{
- SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i, 0);
+ SetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i, 0);
SetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, 0);
SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i, 1.00f);
}
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index 71c1203..ebd969e 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -1079,7 +1079,11 @@ enum WeaponAttackType
{
BASE_ATTACK = 0,
OFF_ATTACK = 1,
- RANGED_ATTACK = 2
+ RANGED_ATTACK = 2,
+
+ // leave these greater than or equal to MAX_ATTACK
+ NONSTACKING_MOD_MELEE = 3,
+ NONSTACKING_MOD_ALL = 4
};

#define MAX_ATTACK 3
diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h
index f4e7305..24fa4d1 100644
--- a/src/game/SpellAuraDefines.h
+++ b/src/game/SpellAuraDefines.h
@@ -265,7 +265,7 @@ enum AuraType
SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE = 227,
SPELL_AURA_DETECT_STEALTH = 228,
SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE = 229,
- SPELL_AURA_230 = 230,
+ SPELL_AURA_MOD_PARTY_MAX_HEALTH = 230,
SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE = 231,
SPELL_AURA_MECHANIC_DURATION_MOD = 232,
SPELL_AURA_233 = 233,
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index d7580dd..da97a2c 100755
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -452,6 +452,8 @@ m_isPersistent(false), m_in_use(0), m_spellAuraHolder(holder)
// Start periodic on next tick or at aura apply
if (!(spellproto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY))
m_periodicTimer += m_modifier.periodictime;
+
+ m_stacking = IsEffectStacking();
}

Aura::~Aura()
@@ -5785,18 +5787,9 @@ void Aura::HandleAuraModResistanceExclusive(bool apply, bool /*Real*/)
int32 oldMaxValue = 0;
if(m_modifier.m_miscvalue & int32(1<<x))
{
- // no same resistance auras stack together
- Unit::AuraList const& REAuras = GetTarget()->GetAurasByType(SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE);
- for (Unit::AuraList::const_iterator i = REAuras.begin(); i != REAuras.end(); ++i)
- if (((*i)->GetMiscValue() & int32(1<<x)) && (*i)->GetSpellProto()->Id != GetSpellProto()->Id)
- if (oldMaxValue < (*i)->GetModifier()->m_amount)
- oldMaxValue = (*i)->GetModifier()->m_amount;
-
- float value = (m_modifier.m_amount > oldMaxValue) ? m_modifier.m_amount - oldMaxValue : 0.0f;
-
- GetTarget()->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, value, apply);
- if(GetTarget()->GetTypeId() == TYPEID_PLAYER)
- GetTarget()->ApplyResistanceBuffModsMod(SpellSchools(x), m_positive, value, apply);
+ float change = GetTarget()->CheckAuraStackingAndApply(this, UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply, int32(1<<x));
+ if(GetTarget()->GetTypeId() == TYPEID_PLAYER && change != 0)
+ GetTarget()->ApplyResistanceBuffModsMod(SpellSchools(x), change, true);
}
}
}
@@ -5809,7 +5802,7 @@ void Aura::HandleAuraModResistance(bool apply, bool /*Real*/)
{
GetTarget()->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
if(GetTarget()->GetTypeId() == TYPEID_PLAYER || ((Creature*)GetTarget())->IsPet())
- GetTarget()->ApplyResistanceBuffModsMod(SpellSchools(x), m_positive, float(m_modifier.m_amount), apply);
+ GetTarget()->ApplyResistanceBuffModsMod(SpellSchools(x), m_modifier.m_amount, apply);
}
}
}
@@ -5835,11 +5828,10 @@ void Aura::HandleModResistancePercent(bool apply, bool /*Real*/)
{
if(m_modifier.m_miscvalue & int32(1<<i))
{
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
- if(target->GetTypeId() == TYPEID_PLAYER || ((Creature*)target)->IsPet())
+ float change = target->CheckAuraStackingAndApply(this, UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply, int32(1<<i));
+ if((target->GetTypeId() == TYPEID_PLAYER || ((Creature*)target)->IsPet()) && change != 0)
{
- target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, float(m_modifier.m_amount), apply);
- target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, float(m_modifier.m_amount), apply);
+ target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), change, apply);
}
}
}
@@ -5874,9 +5866,9 @@ void Aura::HandleAuraModStat(bool apply, bool /*Real*/)
if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
{
//m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
- GetTarget()->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
- if(GetTarget()->GetTypeId() == TYPEID_PLAYER || ((Creature*)GetTarget())->IsPet())
- GetTarget()->ApplyStatBuffMod(Stats(i), float(m_modifier.m_amount), apply);
+ float change = GetTarget()->CheckAuraStackingAndApply(this, UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply, 0, i+1);
+ if((GetTarget()->GetTypeId() == TYPEID_PLAYER || ((Creature*)GetTarget())->IsPet()) && change != 0)
+ GetTarget()->ApplyStatBuffMod(Stats(i), (change < 0 && !IsStacking() ? -change : change), apply);
}
}
}
@@ -6159,7 +6151,7 @@ void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool /*Real*/)
uint32 oldhealth = target->GetHealth();
double healthPercentage = (double)oldhealth / (double)target->GetMaxHealth();

- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ target->CheckAuraStackingAndApply(this, UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);

// refresh percentage
if(oldhealth > 0)
@@ -6279,11 +6271,43 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real)
// with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
// m_modifier.m_miscvalue comparison with item generated damage types

+ float amount = float(m_modifier.m_amount);
+
if (GetSpellProto()->EquippedItemClass == -1)
{
- ((Player*)target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
- ((Player*)target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
- ((Player*)target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
+ if(IsStacking())
+ {
+ ((Player*)target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, amount, apply);
+ ((Player*)target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, amount, apply);
+ ((Player*)target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, amount, apply);
+ }
+ else
+ {
+ float current = ((Player*)target)->GetBaseModValue(NONSTACKING_CRIT_PERCENTAGE, FLAT_MOD);
+
+ if(amount < current)
+ return;
+
+ // unapply old aura
+ if(current)
+ {
+ ((Player*)target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, current, false);
+ ((Player*)target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, current, false);
+ ((Player*)target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, current, false);
+ }
+
+ if(!apply)
+ amount = target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_CRIT_PERCENT, true);
+
+ if(amount)
+ {
+ ((Player*)target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, amount, true);
+ ((Player*)target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, amount, true);
+ ((Player*)target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, amount, true);
+ }
+
+ ((Player*)target)->SetBaseModValue(NONSTACKING_CRIT_PERCENTAGE, FLAT_MOD, amount);
+ }
}
else
{
@@ -6369,10 +6393,40 @@ void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool /*Real*/)
void Aura::HandleModCombatSpeedPct(bool apply, bool /*Real*/)
{
Unit *target = GetTarget();
- target->ApplyCastTimePercentMod(float(m_modifier.m_amount), apply);
- target->ApplyAttackTimePercentMod(BASE_ATTACK, float(m_modifier.m_amount), apply);
- target->ApplyAttackTimePercentMod(OFF_ATTACK, float(m_modifier.m_amount), apply);
- target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(m_modifier.m_amount), apply);
+ if(IsStacking())
+ {
+ target->ApplyCastTimePercentMod(m_modifier.m_amount, apply);
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount, apply);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount, apply);
+ target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
+ }
+ else
+ {
+ // Only positive effects are nonstacking in this handler
+ float amount = float(m_modifier.m_amount);
+
+ if(amount < target->m_modAttackSpeedPct[NONSTACKING_MOD_ALL])
+ return;
+
+ // unapply old aura
+ if(target->m_modAttackSpeedPct[NONSTACKING_MOD_ALL])
+ {
+ target->ApplyCastTimePercentMod(target->m_modAttackSpeedPct[NONSTACKING_MOD_ALL], false);
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, target->m_modAttackSpeedPct[NONSTACKING_MOD_ALL], false);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, target->m_modAttackSpeedPct[NONSTACKING_MOD_ALL], false);
+ target->ApplyAttackTimePercentMod(RANGED_ATTACK, target->m_modAttackSpeedPct[NONSTACKING_MOD_ALL], false);
+ }
+
+ if(!apply)
+ amount = target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MELEE_HASTE, true);
+
+ target->ApplyCastTimePercentMod(amount, true);
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, amount, true);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, amount, true);
+ target->ApplyAttackTimePercentMod(RANGED_ATTACK, amount, true);
+
+ target->m_modAttackSpeedPct[NONSTACKING_MOD_ALL] = amount;
+ }
}

void Aura::HandleModAttackSpeed(bool apply, bool /*Real*/)
@@ -6383,8 +6437,33 @@ void Aura::HandleModAttackSpeed(bool apply, bool /*Real*/)
void Aura::HandleModMeleeSpeedPct(bool apply, bool /*Real*/)
{
Unit *target = GetTarget();
- target->ApplyAttackTimePercentMod(BASE_ATTACK, float(m_modifier.m_amount), apply);
- target->ApplyAttackTimePercentMod(OFF_ATTACK, float(m_modifier.m_amount), apply);
+ if (IsStacking())
+ {
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount, apply);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount, apply);
+ }
+ else
+ {
+ if(m_modifier.m_amount < target->m_modAttackSpeedPct[NONSTACKING_MOD_MELEE])
+ return;
+
+ float amount = float(m_modifier.m_amount);
+
+ // unapply old aura
+ if(target->m_modAttackSpeedPct[NONSTACKING_MOD_MELEE])
+ {
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, target->m_modAttackSpeedPct[NONSTACKING_MOD_MELEE], false);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, target->m_modAttackSpeedPct[NONSTACKING_MOD_MELEE], false);
+ }
+
+ if(!apply)
+ amount = target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MELEE_HASTE, true);
+
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, amount, true);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, amount, true);
+
+ target->m_modAttackSpeedPct[NONSTACKING_MOD_MELEE] = amount;
+ }
}

void Aura::HandleAuraModRangedHaste(bool apply, bool /*Real*/)
@@ -6405,7 +6484,7 @@ void Aura::HandleRangedAmmoHaste(bool apply, bool /*Real*/)

void Aura::HandleAuraModAttackPower(bool apply, bool /*Real*/)
{
- GetTarget()->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ GetTarget()->CheckAuraStackingAndApply(this, UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}

void Aura::HandleAuraModRangedAttackPower(bool apply, bool /*Real*/)
@@ -6413,13 +6492,13 @@ void Aura::HandleAuraModRangedAttackPower(bool apply, bool /*Real*/)
if((GetTarget()->getClassMask() & CLASSMASK_WAND_USERS)!=0)
return;

- GetTarget()->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ GetTarget()->CheckAuraStackingAndApply(this, UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
}

void Aura::HandleAuraModAttackPowerPercent(bool apply, bool /*Real*/)
{
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
- GetTarget()->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
+ GetTarget()->CheckAuraStackingAndApply(this, UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
}

void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool /*Real*/)
@@ -6428,7 +6507,7 @@ void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool /*Real*/)
return;

//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
- GetTarget()->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
+ GetTarget()->CheckAuraStackingAndApply(this, UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
}

void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool /*apply*/, bool Real)
@@ -10336,6 +10415,80 @@ void SpellAuraHolder::UnregisterSingleCastHolder()
}
}

+bool Aura::IsEffectStacking()
+{
+ // Flametongue Totem / Totem of Wrath / Strength of Earth Totem / Fel Intelligence / Leader of the Pack
+ // Moonkin Aura / Mana Spring Totem / Tree of Life Aura / Improved Devotion Aura / Improved Icy Talons / Trueshot Aura
+ // Improved Moonkin Form / Sanctified Retribution Aura / Blood Pact
+ if (GetSpellProto()->Effect[m_effIndex] == SPELL_EFFECT_APPLY_AREA_AURA_RAID)
+ return false;
+
+ if (GetSpellSpecific(GetSpellProto()->Id) == SPELL_SCROLL)
+ return false;
+
+ switch(GetModifier()->m_auraname)
+ {
+ case SPELL_AURA_MOD_HEALING_DONE: // Demonic Pact
+ case SPELL_AURA_MOD_DAMAGE_DONE: // Demonic Pact
+ case SPELL_AURA_HASTE_ALL: // Imp. Moonkin Aur / Swift Retribution
+ case SPELL_AURA_MOD_MELEE_HASTE: // (Improved) Icy Talons / Windfury Totem
+ case SPELL_AURA_MOD_MELEE_RANGED_HASTE:
+ case SPELL_AURA_MOD_ATTACK_POWER_PCT: // Abomination's Might / Unleashed Rage
+ case SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT:
+ case SPELL_AURA_MOD_ATTACK_POWER: // (Greater) Blessing of Might / Battle Shout
+ case SPELL_AURA_MOD_RANGED_ATTACK_POWER:
+ case SPELL_AURA_MOD_POWER_REGEN: // (Greater) Blessing of Wisdom
+ case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: // Glyph of Salvation / Pain Suppression / Safeguard ?
+ if (GetSpellProto()->AttributesEx6 & SPELL_ATTR_EX6_UNK26)
+ return false;
+ // (Improved) Icy Talons check
+ else if (GetSpellProto()->SpellIconID == 3785)
+ return false;
+ break;
+ case SPELL_AURA_MOD_STAT:
+ // Horn of Winter / Arcane Intellect / Divine Spirit
+ if (GetSpellProto()->AttributesEx6 & SPELL_ATTR_EX6_UNK26 &&
+ (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT ||
+ GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE ||
+ GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST) )
+ return false;
+ break;
+ case SPELL_AURA_MOD_CRIT_PERCENT:
+ // Rampage
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARRIOR && GetSpellProto()->SpellIconID == 2006)
+ return false;
+ break;
+ case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
+ // Elemental Oath
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && GetSpellProto()->AttributesEx6 & SPELL_ATTR_EX6_UNK26)
+ return false;
+ break;
+ case SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE: // Winter's Chill / Improved Scorch
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE)
+ return false;
+ break;
+ case SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE:
+ return false;
+ case SPELL_AURA_MOD_PARTY_MAX_HEALTH:
+ // Commanding Shout
+ return false;
+ case SPELL_AURA_MOD_HEALING_PCT: // Mortal Strike / Wound Poison / Aimed Shot / Furious Attacks
+ // Healing taken debuffs
+ if (GetSpellProto()->EffectBasePoints[m_effIndex] < 0)
+ return false;
+ case SPELL_AURA_MOD_RESISTANCE_PCT:
+ // Ancestral Healing / Inspiration
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN ||
+ GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST)
+ return false;
+ break;
+
+ default:
+ return true;
+ }
+ return true;
+}
+
void Aura::HandleAuraMirrorImage(bool Apply, bool Real)
{
if (!Real)
diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
index d13d685..ee2f5be 100644
--- a/src/game/SpellAuras.h
+++ b/src/game/SpellAuras.h
@@ -414,6 +414,7 @@ class MANGOS_DLL_SPEC Aura
bool IsAreaAura() const { return m_isAreaAura; }
bool IsPeriodic() const { return m_isPeriodic; }
bool IsInUse() const { return m_in_use; }
+ bool IsStacking() const { return m_stacking;}

void SetInUse(bool state)
{
@@ -442,6 +443,7 @@ class MANGOS_DLL_SPEC Aura
uint32 const *getAuraSpellClassMask() const { return m_spellAuraHolder->GetSpellProto()->GetEffectSpellClassMask(m_effIndex); }
bool isAffectedOnSpell(SpellEntry const *spell) const;
bool CanProcFrom(SpellEntry const *spell, uint32 EventProcEx, uint32 procEx, bool active, bool useClassMask) const;
+ bool IsEffectStacking();

//SpellAuraHolder const* GetHolder() const { return m_spellHolder; }
SpellAuraHolder* GetHolder() { return m_spellAuraHolder; }
@@ -483,6 +485,7 @@ class MANGOS_DLL_SPEC Aura
bool m_isPeriodic:1;
bool m_isAreaAura:1;
bool m_isPersistent:1;
+ bool m_stacking:1; // Aura is not overwritten, but effects are not cumulative with similar effects

uint32 m_in_use; // > 0 while in Aura::ApplyModifier call/Aura::Update/etc

diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index f413326..1fb3eae 100755
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -382,6 +382,10 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
// SpellIcon 2560 is Spell 46687, does not have this flag
if ((spellInfo->AttributesEx2 & SPELL_ATTR_EX2_FOOD_BUFF) || spellInfo->SpellIconID == 2560)
return SPELL_WELL_FED;
+
+ else if (spellInfo->EffectApplyAuraName[EFFECT_INDEX_0] == SPELL_AURA_MOD_STAT && spellInfo->Attributes & SPELL_ATTR_NOT_SHAPESHIFT &&
+ spellInfo->SchoolMask & SPELL_SCHOOL_MASK_NATURE && spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
+ return SPELL_SCROLL;
}
break;
}
@@ -1998,6 +2002,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
// Dragonmaw Illusion (multi-family check)
if (spellId_1 == 40216 && spellId_2 == 42016)
return false;
+
+ // Drums of the Wild and Gift of the Wild
+ if( spellInfo_1->Id == 72588 && spellInfo_2->SpellFamilyFlags & UI64LIT(0x40000))
+ return true;

break;
}
@@ -2032,6 +2040,19 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
// *Band of Eternal Champion and Seal of Command(multi-family check)
if (spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual[0]==7992)
return false;
+ // Drums of Forgotten Kings and Blessing of Kings
+ if( spellInfo_1->Id == 72586 && spellInfo_2->SpellFamilyFlags & UI64LIT(0x10000000))
+ return true;
+ }
+ case SPELLFAMILY_PRIEST:
+ {
+ // Frenzy (Grand Widow Faerlina) and Mind Trauma
+ if( spellInfo_1->SpellIconID == 95 && spellInfo_2->SpellFamilyFlags & UI64LIT(0x84000000))
+ return false;
+
+ // Runescroll of Fortitude and Power Word: Fortitude
+ if( spellInfo_1->Id == 72590 && spellInfo_2->SpellFamilyFlags & UI64LIT(0x8))
+ return true;
}
}
// Dragonmaw Illusion, Blood Elf Illusion, Human Illusion, Illidari Agent Illusion, Scarlet Crusade Disguise
@@ -2186,6 +2207,9 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
(spellInfo_2->SpellIconID == 321 && spellInfo_1->SpellIconID == 329))
return false;
}
+ // Power Word: Fortitude and Runescroll of Fortitude
+ if( spellInfo_1->SpellFamilyFlags & UI64LIT(0x8) && spellInfo_2->Id == 72590 )
+ return true;
break;
case SPELLFAMILY_DRUID:
if (spellInfo_2->SpellFamilyName == SPELLFAMILY_DRUID)
@@ -2251,6 +2275,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
// Dragonmaw Illusion (multi-family check)
if (spellId_1 == 42016 && spellId_2 == 40216 )
return false;
+
+ // Gift of the Wild and Drums of the Wild
+ if( spellInfo_1->SpellFamilyFlags & UI64LIT(0x40000) && spellInfo_2->Id == 72588)
+ return true;

break;
case SPELLFAMILY_ROGUE:
@@ -2395,6 +2423,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
// *Seal of Command and Band of Eternal Champion (multi-family check)
if (spellInfo_1->SpellIconID==561 && spellInfo_1->SpellVisual[0]==7992 && spellId_2 == 35081)
return false;
+
+ // Blessing of Kings and Drums of Forgotten Kings
+ if( spellInfo_1->SpellFamilyFlags & UI64LIT(0x10000000) && spellInfo_2->Id == 72586)
+ return true;
break;

case SPELLFAMILY_SHAMAN:
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index 5af4878..575bf02 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -86,6 +86,7 @@ enum SpellSpecific
SPELL_UA_IMMOLATE = 23, // Unstable Affliction and Immolate
SPELL_BLEED_DEBUFF = 24, // Mangle and Trauma
SPELL_MAGE_INTELLECT = 25,
+ SPELL_SCROLL = 30,
};

SpellSpecific GetSpellSpecific(uint32 spellId);
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp
index bf422e6..ef3d31c 100644
--- a/src/game/StatSystem.cpp
+++ b/src/game/StatSystem.cpp
@@ -112,7 +112,7 @@ void Player::UpdateSpellDamageAndHealingBonus()
SetStatInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, SpellBaseHealingBonusDone(SPELL_SCHOOL_MASK_ALL));
// Get damage bonus for all schools
for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)));
+ SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)) - GetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i));

CallForAllControlledUnits(ApplyScalingBonusWithHelper(SCALIN​G_TARGET_ATTACKPOWER, 0, false),CONTROLLED_PET|CONTROLLED_GUARDIANS);
CallForAllControlledUnits(ApplyScalingBonusWithHelper(SCALIN​G_TARGET_SPELLDAMAGE, 0, false),CONTROLLED_PET|CONTROLLED_GUARDIANS);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index b0f1028..e6ee4b2 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -196,6 +196,8 @@ Unit::Unit()
m_modAttackSpeedPct[BASE_ATTACK] = 1.0f;
m_modAttackSpeedPct[OFF_ATTACK] = 1.0f;
m_modAttackSpeedPct[RANGED_ATTACK] = 1.0f;
+ m_modAttackSpeedPct[NONSTACKING_MOD_MELEE] = 0.0f;
+ m_modAttackSpeedPct[NONSTACKING_MOD_ALL] = 0.0f;

m_extraAttacks = 0;

@@ -235,6 +237,8 @@ Unit::Unit()
m_auraModifiersGroup[i][BASE_PCT] = 1.0f;
m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f;
m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
+ m_auraModifiersGroup[i][NONSTACKING_VALUE] = 0.0f;
+ m_auraModifiersGroup[i][NONSTACKING_PCT] = 0.0f;
}
// implement 50% base damage from offhand
m_auraModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f;
@@ -4115,44 +4119,68 @@ void Unit::DeMorph()
int32 Unit::GetTotalAuraModifier(AuraType auratype) const
{
int32 modifier = 0;
+ int32 nonStackingPos = 0;
+ int32 nonStackingNeg = 0;

AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
- modifier += (*i)->GetModifier()->m_amount;
+ {
+ if((*i)->IsStacking())
+ modifier += (*i)->GetModifier()->m_amount;
+ else
+ {
+ if((*i)->GetModifier()->m_amount > nonStackingPos)
+ nonStackingPos = (*i)->GetModifier()->m_amount;
+ else if((*i)->GetModifier()->m_amount < nonStackingNeg)
+ nonStackingNeg = (*i)->GetModifier()->m_amount;
+ }
+ }

- return modifier;
+ return modifier + nonStackingPos + nonStackingNeg;
}

float Unit::GetTotalAuraMultiplier(AuraType auratype) const
{
float multiplier = 1.0f;
+ int32 nonStackingPos = 0;
+ int32 nonStackingNeg = 0;

AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
- multiplier *= (100.0f + (*i)->GetModifier()->m_amount)/100.0f;
+ {
+ if((*i)->IsStacking())
+ multiplier *= (100.0f + (*i)->GetModifier()->m_amount)/100.0f;
+ else
+ {
+ if((*i)->GetModifier()->m_amount > nonStackingPos)
+ nonStackingPos = (*i)->GetModifier()->m_amount;
+ else if((*i)->GetModifier()->m_amount < nonStackingNeg)
+ nonStackingNeg = (*i)->GetModifier()->m_amount;
+ }
+ }

- return multiplier;
+ return multiplier * (100.0f + nonStackingPos)/100.0f * (100.0f + nonStackingNeg)/100.0f;
}

-int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype) const
+int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype, bool nonStackingOnly) const
{
int32 modifier = 0;

AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
- if ((*i)->GetModifier()->m_amount > modifier)
+ if (!(nonStackingOnly && (*i)->IsStacking()) && (*i)->GetModifier()->m_amount > modifier)
modifier = (*i)->GetModifier()->m_amount;

return modifier;
}

-int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const
+int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype, bool nonStackingOnly) const
{
int32 modifier = 0;

AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
- if ((*i)->GetModifier()->m_amount < modifier)
+ if (!(nonStackingOnly && (*i)->IsStacking()) && (*i)->GetModifier()->m_amount < modifier)
modifier = (*i)->GetModifier()->m_amount;

return modifier;
@@ -4164,15 +4192,27 @@ int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask)
return 0;

int32 modifier = 0;
+ int32 nonStackingPos = 0;
+ int32 nonStackingNeg = 0;

AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
if (mod->m_miscvalue & misc_mask)
- modifier += mod->m_amount;
+ {
+ if((*i)->IsStacking())
+ modifier += mod->m_amount;
+ else
+ {
+ if(mod->m_amount > nonStackingPos)
+ nonStackingPos = mod->m_amount;
+ else if(mod->m_amount < nonStackingNeg)
+ nonStackingNeg = mod->m_amount;
+ }
+ }
}
- return modifier;
+ return modifier + nonStackingPos + nonStackingNeg;
}

float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
@@ -4181,18 +4221,31 @@ float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask
return 1.0f;

float multiplier = 1.0f;
+ int32 nonStackingPos = 0;
+ int32 nonStackingNeg = 0;

AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
if (mod->m_miscvalue & misc_mask)
- multiplier *= (100.0f + mod->m_amount)/100.0f;
+ {
+ if((*i)->IsStacking())
+ multiplier *= (100.0f + mod->m_amount)/100.0f;
+ else
+ {
+ if(mod->m_amount > nonStackingPos)
+ nonStackingPos = mod->m_amount;
+ else if(mod->m_amount < nonStackingNeg)
+ nonStackingNeg = mod->m_amount;
+ }
+ }
}
- return multiplier;
+
+ return multiplier * (100.0f + nonStackingPos)/100.0f * (100.0f + nonStackingNeg)/100.0f;
}

-int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
+int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, bool nonStackingOnly) const
{
if(!misc_mask)
return 0;
@@ -4203,14 +4256,14 @@ int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- if (mod->m_miscvalue & misc_mask && mod->m_amount > modifier)
+ if (!(nonStackingOnly && (*i)->IsStacking()) && mod->m_miscvalue & misc_mask && mod->m_amount > modifier)
modifier = mod->m_amount;
}

return modifier;
}

-int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
+int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, bool nonStackingOnly) const
{
if(!misc_mask)
return 0;
@@ -4221,7 +4274,7 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- if (mod->m_miscvalue & misc_mask && mod->m_amount < modifier)
+ if (!(nonStackingOnly && (*i)->IsStacking()) && mod->m_miscvalue & misc_mask && mod->m_amount < modifier)
modifier = mod->m_amount;
}

@@ -4231,32 +4284,54 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_
int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
{
int32 modifier = 0;
+ int32 nonStackingPos = 0;

AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
if (mod->m_miscvalue == misc_value)
- modifier += mod->m_amount;
+ {
+
+ if((*i)->IsStacking())
+ modifier += mod->m_amount;
+ else
+ {
+ if(mod->m_amount > nonStackingPos)
+ nonStackingPos = mod->m_amount;
+ }
+ }
}
- return modifier;
+
+ return modifier + nonStackingPos;
}

float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const
{
float multiplier = 1.0f;
+ float nonStackingPos = 0.0f;

AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
if (mod->m_miscvalue == misc_value)
- multiplier *= (100.0f + mod->m_amount)/100.0f;
+ {
+
+ if((*i)->IsStacking())
+ multiplier *= (100.0f + mod->m_amount)/100.0f;
+ else
+ {
+ if(mod->m_amount > nonStackingPos)
+ nonStackingPos = mod->m_amount;
+ }
+ }
}
- return multiplier;
+
+ return multiplier * (100.0f + nonStackingPos)/100.0f;
}

-int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
+int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value, bool nonStackingOnly) const
{
int32 modifier = 0;

@@ -4264,14 +4339,14 @@ int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- if (mod->m_miscvalue == misc_value && mod->m_amount > modifier)
+ if (!(nonStackingOnly && (*i)->IsStacking()) && mod->m_miscvalue == misc_value && mod->m_amount > modifier)
modifier = mod->m_amount;
}

return modifier;
}

-int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
+int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value, bool nonStackingOnly) const
{
int32 modifier = 0;

@@ -4279,7 +4354,7 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
- if (mod->m_miscvalue == misc_value && mod->m_amount < modifier)
+ if (!(nonStackingOnly && (*i)->IsStacking()) && mod->m_miscvalue == misc_value && mod->m_amount < modifier)
modifier = mod->m_amount;
}

@@ -4502,6 +4577,49 @@ void Unit::AddAuraToModList(Aura *aura)
m_modAuras[aura->GetModifier()->m_auraname].push_back(aura);
}

+float Unit::CheckAuraStackingAndApply(Aura *Aur, UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply, int32 miscMask, int32 miscValue)
+{
+ if(!Aur->IsStacking())
+ {
+ if(modifierType == TOTAL_VALUE)
+ modifierType = NONSTACKING_VALUE;
+ else if(modifierType == TOTAL_PCT)
+ modifierType = NONSTACKING_PCT;
+ // need a sanity check here?
+
+ float current = GetModifierValue(unitMod, modifierType);
+
+ if(amount < current) // value does not change as a result of applying/removing this aura
+ return 0.0f;
+
+ if(!apply) // aura removed is the aura that is currently in effect, must find second highest nonstacking aura's m_amount
+ {
+ if(miscMask)
+ amount = (float)GetMaxPositiveAuraModifierByMiscMask(Aur->GetModifier()->m_auraname, miscMask, true);
+ else if(miscValue)
+ amount = (float)GetMaxPositiveAuraModifierByMiscValue(Aur->GetModifier()->m_auraname, miscValue-1, true);
+ else
+ amount = (float)GetMaxPositiveAuraModifier(Aur->GetModifier()->m_auraname, true);
+ }
+
+ HandleStatModifier(unitMod, modifierType, amount, apply);
+
+ if(modifierType == NONSTACKING_VALUE)
+ amount -= current;
+ else
+ {
+ if(apply)
+ amount = ((100.0f + amount) / (100.0f + current) - 1.0f) * 100.0f;
+ else
+ amount = ((100.0f + current) / (100.0f + amount) - 1.0f) * 100.0f;
+ }
+ }
+ else
+ HandleStatModifier(unitMod, modifierType, amount, apply);
+
+ return amount;
+}
+
void Unit::RemoveRankAurasDueToSpell(uint32 spellId)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
@@ -9699,6 +9817,10 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
val = (100.0f + amount) / 100.0f;
m_auraModifiersGroup[unitMod][modifierType] *= apply ? val : (1.0f/val);
break;
+ case NONSTACKING_PCT:
+ case NONSTACKING_VALUE:
+ m_auraModifiersGroup[unitMod][modifierType] = amount;
+ break;

default:
break;
@@ -9755,10 +9877,23 @@ float Unit::GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) co
return 0.0f;
}

- if(modifierType == TOTAL_PCT && m_auraModifiersGroup[unitMod][modifierType] <= 0.0f)
- return 0.0f;
-
- return m_auraModifiersGroup[unitMod][modifierType];
+ if(modifierType == TOTAL_PCT)
+ {
+ if(m_auraModifiersGroup[unitMod][modifierType] <= 0.0f)
+ {
+ return 0.0f;
+ }
+ else
+ {
+ return m_auraModifiersGroup[unitMod][TOTAL_PCT] * (m_auraModifiersGroup[unitMod][NONSTACKING_PCT] + 100.0f) / 100.0f;
+ }
+ }
+ else if(modifierType == TOTAL_VALUE)
+ {
+ return m_auraModifiersGroup[unitMod][TOTAL_VALUE] + m_auraModifiersGroup[unitMod][NONSTACKING_VALUE];
+ }
+ else
+ return m_auraModifiersGroup[unitMod][modifierType];
}

float Unit::GetTotalStatValue(Stats stat) const
@@ -9771,8 +9906,8 @@ float Unit::GetTotalStatValue(Stats stat) const
// value = ((base_value * base_pct) + total_value) * total_pct
float value = m_auraModifiersGroup[unitMod][BASE_VALUE] + GetCreateStat(stat);
value *= m_auraModifiersGroup[unitMod][BASE_PCT];
- value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
- value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
+ value += (m_auraModifiersGroup[unitMod][TOTAL_VALUE] + m_auraModifiersGroup[unitMod][NONSTACKING_VALUE]);
+ value *= (m_auraModifiersGroup[unitMod][TOTAL_PCT] * (m_auraModifiersGroup[unitMod][NONSTACKING_PCT] + 100.0f) / 100.0f);

return value;
}
@@ -9790,8 +9925,8 @@ float Unit::GetTotalAuraModValue(UnitMods unitMod) const

float value = m_auraModifiersGroup[unitMod][BASE_VALUE];
value *= m_auraModifiersGroup[unitMod][BASE_PCT];
- value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
- value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
+ value += (m_auraModifiersGroup[unitMod][TOTAL_VALUE] + m_auraModifiersGroup[unitMod][NONSTACKING_VALUE]);
+ value *= (m_auraModifiersGroup[unitMod][TOTAL_PCT] * (m_auraModifiersGroup[unitMod][NONSTACKING_PCT] + 100.0f) / 100.0f);

return value;
}
diff --git a/src/game/Unit.h b/src/game/Unit.h
index ef5abb5..c539e21 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -287,7 +287,9 @@ enum UnitModifierType
BASE_PCT = 1,
TOTAL_VALUE = 2,
TOTAL_PCT = 3,
- MODIFIER_TYPE_END = 4
+ NONSTACKING_VALUE = 4,
+ NONSTACKING_PCT = 5,
+ MODIFIER_TYPE_END = 6
};

enum WeaponDamageRange
@@ -359,6 +361,7 @@ enum BaseModGroup
RANGED_CRIT_PERCENTAGE,
OFFHAND_CRIT_PERCENTAGE,
SHIELD_BLOCK_VALUE,
+ NONSTACKING_CRIT_PERCENTAGE,
BASEMOD_END
};

@@ -1600,6 +1603,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject

void _AddAura(uint32 spellID, uint32 duration = 60000);

+ float CheckAuraStackingAndApply(Aura *Aur, UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply, int32 miscMask = 0, int32 miscValue = 0);
+
// removing specific aura stack
void RemoveAura(Aura* aura, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(uint32 spellId, SpellEffectIndex effindex, Aura* except = NULL);
@@ -1637,14 +1642,27 @@ class MANGOS_DLL_SPEC Unit : public WorldObject

float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); }
void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); }
- void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModSignedFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); }
- void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); }
+ void ApplyResistanceBuffModsMod(SpellSchools school, float val, bool apply)
+ {
+ val *= GetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START+school),​ TOTAL_PCT);
+ ApplyModSignedFloatValue((val > 0 ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school), val, apply);
+ }
+ void ApplyResistanceBuffModsPercentMod(SpellSchools school, float val, bool apply)
+ {
+ ApplyPercentModFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSIT​IVE+school, val, apply);
+ ApplyPercentModFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGAT​IVE+school, val, apply);
+ }
+
void InitStatBuffMods()
{
for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_POSSTAT0+i, 0);
for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_NEGSTAT0+i, 0);
}
- void ApplyStatBuffMod(Stats stat, float val, bool apply) { ApplyModSignedFloatValue((val > 0 ? UNIT_FIELD_POSSTAT0+stat : UNIT_FIELD_NEGSTAT0+stat), val, apply); }
+ void ApplyStatBuffMod(Stats stat, float val, bool apply)
+ {
+ val *= GetModifierValue(UnitMods(UNIT_MOD_STAT_STRENGTH+stat), TOTAL_PCT);
+ ApplyModSignedFloatValue((val > 0 ? UNIT_FIELD_POSSTAT0+stat : UNIT_FIELD_NEGSTAT0+stat), val, apply);
+ }
void ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
{
ApplyPercentModFloatValue(UNIT_FIELD_POSSTAT0+stat, val, apply);
@@ -1707,7 +1725,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
int32 m_baseSpellCritChance;

float m_threatModifier[MAX_SPELL_SCHOOL];
- float m_modAttackSpeedPct[3];
+ float m_modAttackSpeedPct[MAX_ATTACK + 2];

// Event handler
EventProcessor m_Events;
@@ -1802,18 +1820,18 @@ class MANGOS_DLL_SPEC Unit : public WorldObject

int32 GetTotalAuraModifier(AuraType auratype) const;
float GetTotalAuraMultiplier(AuraType auratype) const;
- int32 GetMaxPositiveAuraModifier(AuraType auratype) const;
- int32 GetMaxNegativeAuraModifier(AuraType auratype) const;
+ int32 GetMaxPositiveAuraModifier(AuraType auratype, bool nonStackingOnly = false) const;
+ int32 GetMaxNegativeAuraModifier(AuraType auratype, bool nonStackingOnly = false) const;

int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const;
float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const;
- int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const;
- int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const;
+ int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, bool nonStackingOnly = false) const;
+ int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, bool nonStackingOnly = false) const;

int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
float GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const;
- int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
- int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
+ int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value, bool nonStackingOnly = false) const;
+ int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value, bool nonStackingOnly = false) const;

// misc have plain value but we check it fit to provided values mask (mask & (1 << (misc-1)))
float GetTotalAuraMultiplierByMiscValueForMask(AuraType auratype, uint32 mask) const;
[/code]

src: selector et bien d'autre

Retourner en haut Accueil