Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pasdVn/273788 to your computer and use it in GitHub Desktop.
Save pasdVn/273788 to your computer and use it in GitHub Desktop.
From d85316e8d2e60481fa6d5e1ebf9525aad1be2bef Mon Sep 17 00:00:00 2001
From: pasdVn <pasdVn3@gmx.de>
Date: Fri, 2 Oct 2009 18:48:00 +0200
Subject: [PATCH 1/6] reworked pet stats and dynamic stat scaling
* added mindmg and maxdmg field to pet_levelstats
* cleanup in Pet::InitStatsForLevel()
* apply bonuses for pets without scaling aura only static - at summon
-> added ap bonus for "shadow fiend" (34433)
-> added bonuses and glyph modification (63271)
for "Feral Spirit" wolves (51533)
-> added spelldamage bonus for "Mirror Image" (55342)
* added support for basepoints calculation of dynamic pet scaling auras
-> corrected scaling values for hunter pets and implemented scaling
modifications ("Wild Hunt" (62758 & ranks), "Hunter vs. Wild" (56339 & ranks))
-> added scaling factors for death knight ghoul and scaling modifications
("Glyph of the Ghoul" (58686)
-> added calculation for expertise and +hit scaling auras
* removed redundant code of old scaling system in pet stat update methods
---
src/game/ObjectMgr.cpp | 6 +-
src/game/ObjectMgr.h | 4 +-
src/game/Pet.cpp | 505 ++++++++++++++++++++++++++++++++++------------
src/game/Pet.h | 6 +-
src/game/Player.cpp | 28 +++-
src/game/Player.h | 3 +
src/game/SharedDefines.h | 2 +-
src/game/SpellAuras.cpp | 16 ++
src/game/SpellAuras.h | 1 +
src/game/StatSystem.cpp | 101 ++--------
src/game/Unit.cpp | 36 +++-
src/game/Unit.h | 1 +
12 files changed, 480 insertions(+), 229 deletions(-)
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index dad5410..6c6bb94 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -2290,8 +2290,8 @@ void ObjectMgr::LoadPetLevelInfo()
{
// Loading levels data
{
- // 0 1 2 3 4 5 6 7 8 9
- QueryResult *result = WorldDatabase.Query("SELECT creature_entry, level, hp, mana, str, agi, sta, inte, spi, armor FROM pet_levelstats");
+ // 0 1 2 3 4 5 6 7 8 9 10 11
+ QueryResult *result = WorldDatabase.Query("SELECT creature_entry, level, hp, mana, str, agi, sta, inte, spi, armor, mindmg, maxdmg FROM pet_levelstats");
uint32 count = 0;
@@ -2348,6 +2348,8 @@ void ObjectMgr::LoadPetLevelInfo()
pLevelInfo->health = fields[2].GetUInt16();
pLevelInfo->mana = fields[3].GetUInt16();
pLevelInfo->armor = fields[9].GetUInt16();
+ pLevelInfo->mindmg = fields[10].GetUInt16();
+ pLevelInfo->maxdmg = fields[11].GetUInt16();
for (int i = 0; i < MAX_STATS; i++)
{
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index 7e51ba9..f3feea9 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -172,12 +172,14 @@ typedef std::pair<ItemRequiredTargetMap::const_iterator, ItemRequiredTargetMap::
struct PetLevelInfo
{
- PetLevelInfo() : health(0), mana(0) { for(int i=0; i < MAX_STATS; ++i ) stats[i] = 0; }
+ PetLevelInfo() : health(0), mana(0), armor(0), mindmg(0), maxdmg(0) { for(int i=0; i < MAX_STATS; ++i ) stats[i] = 0; }
uint16 stats[MAX_STATS];
uint16 health;
uint16 mana;
uint16 armor;
+ uint16 mindmg;
+ uint16 maxdmg;
};
struct MailLevelReward
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index c077d0a..d67d9a9 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -799,10 +799,12 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
CreatureInfo const *cinfo = GetCreatureInfo();
ASSERT(cinfo);
- if(!owner)
+ if (!owner)
{
+ // Do not remove *owner as function argument, GetOwner() won't work on summoning pet if the owner
+ // is no player, because pet is not yet in world; see ObjectAccessor::GetUnit
owner = GetOwner();
- if(!owner)
+ if (!owner)
{
sLog.outError("attempt to summon pet (Entry %u) without owner! Attempt terminated.", cinfo->Entry);
return false;
@@ -813,172 +815,156 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
SetLevel(petlevel);
- SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
+ SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0);
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50));
+ // find stored pet level stats
+ PetLevelInfo const* pInfo = sObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
+ if (pInfo)
+ {
+ SetCreateHealth(pInfo->health);
+ SetCreateMana(pInfo->mana);
- SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME);
- SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME);
- SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME);
+ SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
- SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0);
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(pInfo->mindmg));
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(pInfo->maxdmg));
- CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family);
- if(cFamily && cFamily->minScale > 0.0f && getPetType()==HUNTER_PET)
+ for( int i = STAT_STRENGTH; i < MAX_STATS; ++i)
+ {
+ SetCreateStat(Stats(i), float(pInfo->stats[i]));
+ }
+ }
+ else
{
- float scale;
- if (getLevel() >= cFamily->maxScaleLevel)
- scale = cFamily->maxScale;
- else if (getLevel() <= cFamily->minScaleLevel)
- scale = cFamily->minScale;
- else
- scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale);
+ //maybe different handling for pets summoned by creatures (fixed states from creatureinfo?)
- SetFloatValue(OBJECT_FIELD_SCALE_X, scale);
- }
- m_bonusdamage = 0;
+ // use some fake values
+ SetCreateHealth(28 + 30*petlevel);
+ SetCreateMana(28 + 10*petlevel);
- int32 createResistance[MAX_SPELL_SCHOOL] = {0,0,0,0,0,0,0};
+ SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50));
- if(cinfo && getPetType() != HUNTER_PET)
- {
- createResistance[SPELL_SCHOOL_HOLY] = cinfo->resistance1;
- createResistance[SPELL_SCHOOL_FIRE] = cinfo->resistance2;
- createResistance[SPELL_SCHOOL_NATURE] = cinfo->resistance3;
- createResistance[SPELL_SCHOOL_FROST] = cinfo->resistance4;
- createResistance[SPELL_SCHOOL_SHADOW] = cinfo->resistance5;
- createResistance[SPELL_SCHOOL_ARCANE] = cinfo->resistance6;
+ // 0.5dps/lvl, damagerange = petlevel/2
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
+
+ SetCreateStat(STAT_STRENGTH, 22 + petlevel );
+ SetCreateStat(STAT_AGILITY, 22 + petlevel/2);
+ SetCreateStat(STAT_STAMINA, 25 + petlevel );
+ SetCreateStat(STAT_INTELLECT, 28 + petlevel/2);
+ SetCreateStat(STAT_SPIRIT, 27 + petlevel/2);
}
- switch(getPetType())
+ // custom stat calculation
+ switch (getPetType())
{
case SUMMON_PET:
+ case GUARDIAN_PET:
{
- if(owner->GetTypeId() == TYPEID_PLAYER)
+ // as the creature_template entries for summoned and guardian pets are just used for
+ // pets (not for normal creatures as well), we can use some entries
+ SetAttackTime(BASE_ATTACK, cinfo->baseattacktime);
+ SetAttackTime(OFF_ATTACK, cinfo->baseattacktime);
+ SetAttackTime(RANGED_ATTACK, cinfo->rangeattacktime);
+ SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
+
+ SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cinfo->resistance1));
+ SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cinfo->resistance2));
+ SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cinfo->resistance3));
+ SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cinfo->resistance4));
+ SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cinfo->resistance5));
+ SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cinfo->resistance6));
+
+ float statBonus[MAX_STATS] = {0, 0, 0, 0, 0},
+ armorBonus = 0,
+ apBonus = 0,
+ bonusDamage = 0;
+
+ // some pets scale not dynamically with master's stats (don't have scaling auras),
+ // we just add the bonus here as unit mods
+ switch (cinfo->Entry)
{
- switch(owner->getClass())
+ // mage's Water Elemental
+ case 510:
+ case 37994:
{
- case CLASS_WARLOCK:
- {
-
- //the damage bonus used for pets is either fire or shadow damage, whatever is higher
- uint32 fire = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE);
- uint32 shadow = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW);
- uint32 val = (fire > shadow) ? fire : shadow;
-
- SetBonusDamage(int32 (val * 0.15f));
- //bonusAP += val * 0.57;
- break;
- }
- case CLASS_MAGE:
- {
- //40% damage bonus of mage's frost damage
- float val = owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST) * 0.4f;
- if(val < 0)
- val = 0;
- SetBonusDamage( int32(val));
- break;
- }
- default:
- break;
+ statBonus[STAT_STAMINA] = owner->GetStat(STAT_STAMINA) * 0.3f;
+ statBonus[STAT_INTELLECT] = owner->GetStat(STAT_INTELLECT) * 0.3f;
+ armorBonus = owner->GetArmor() * 0.35f;
+ bonusDamage = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FROST) * 0.4f;
+ break;
}
- }
-
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) );
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)) );
-
- //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
-
- PetLevelInfo const* pInfo = sObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
- if(pInfo) // exist in DB
- {
- SetCreateHealth(pInfo->health);
- SetCreateMana(pInfo->mana);
+ // priest's Shadowfiend
+ case 19668:
+ {
+ apBonus = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW) * 0.565f;
+ break;
+ }
+ // Feral Spirit Wolves
+ case 29264:
+ {
+ // 30% of owners stamina, 35% of owners armor
+ statBonus[STAT_STAMINA] = owner->GetStat(STAT_STAMINA) * 0.3f;
+ armorBonus = owner->GetArmor() * 0.35f;
- if(pInfo->armor > 0)
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
+ // 30% of masters attack power, modified by dummy aura
+ apBonus = 30;
+ if (Aura* pDummy = owner->GetDummyAura(63271))
+ apBonus += pDummy->GetModifier()->m_miscvalue;
+ apBonus = apBonus * owner->GetTotalAttackPowerValue(BASE_ATTACK) / 100;
- for(int stat = 0; stat < MAX_STATS; ++stat)
+ // TODO: hitchance with spell 61783 (cast manually...? not in petspell dbc's :-/)
+ break;
+ }
+ // Mirror Image
+ case 31216:
{
- SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
+ bonusDamage = owner->GetMaxSpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_MAGIC);
+ break;
}
+ default:
+ break;
}
- else // not exist in DB, use some default fake data
- {
- sLog.outErrorDb("Summoned pet (Entry: %u) not have pet stats data in DB",cinfo->Entry);
- // remove elite bonuses included in DB values
- SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
- SetCreateMana( uint32(((float(cinfo->maxmana) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
+ for (uint8 i = 0; i < MAX_STATS; i++)
+ HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, statBonus[i] > 0 ? statBonus[i] : 0, true);
+
+ HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, armorBonus > 0 ? armorBonus : 0, true);
+ HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, apBonus > 0 ? apBonus : 0, true);
+ SetBonusDamage(bonusDamage > 0 ? bonusDamage : 0);
- SetCreateStat(STAT_STRENGTH, 22);
- SetCreateStat(STAT_AGILITY, 22);
- SetCreateStat(STAT_STAMINA, 25);
- SetCreateStat(STAT_INTELLECT, 28);
- SetCreateStat(STAT_SPIRIT, 27);
- }
break;
}
case HUNTER_PET:
{
+ // hunter pets always use base attack time and do physical damage
+ SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME);
+ SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME);
+ SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME);
+ SetMeleeDamageSchool(SPELL_SCHOOL_NORMAL);
+
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr.GetXPForPetLevel(petlevel));
- //these formula may not be correct; however, it is designed to be close to what it should be
- //this makes dps 0.5 of pets level
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) );
- //damage range is then petlevel / 2
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)) );
- //damage is increased afterwards as strength and pet scaling modify attack power
-
- //stored standard pet stats are entry 1 in pet_levelinfo
- PetLevelInfo const* pInfo = sObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
- if(pInfo) // exist in DB
- {
- SetCreateHealth(pInfo->health);
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
- //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
- for( int i = STAT_STRENGTH; i < MAX_STATS; ++i)
- {
- SetCreateStat(Stats(i), float(pInfo->stats[i]));
- }
- }
- else // not exist in DB, use some default fake data
+ // size scaling
+ CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family);
+ if (cFamily && cFamily->minScale > 0.0f && getPetType()==HUNTER_PET)
{
- sLog.outErrorDb("Hunter pet levelstats missing in DB");
-
- // remove elite bonuses included in DB values
- SetCreateHealth( uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
+ float scale;
+ if (getLevel() >= cFamily->maxScaleLevel)
+ scale = cFamily->maxScale;
+ else if (getLevel() <= cFamily->minScaleLevel)
+ scale = cFamily->minScale;
+ else
+ scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale);
- SetCreateStat(STAT_STRENGTH, 22);
- SetCreateStat(STAT_AGILITY, 22);
- SetCreateStat(STAT_STAMINA, 25);
- SetCreateStat(STAT_INTELLECT, 28);
- SetCreateStat(STAT_SPIRIT, 27);
+ SetFloatValue(OBJECT_FIELD_SCALE_X, scale);
}
break;
}
- case GUARDIAN_PET:
- SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
- SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
-
- SetCreateMana(28 + 10*petlevel);
- SetCreateHealth(28 + 30*petlevel);
-
- // FIXME: this is wrong formula, possible each guardian pet have own damage formula
- //these formula may not be correct; however, it is designed to be close to what it should be
- //this makes dps 0.5 of pets level
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
- //damage range is then petlevel / 2
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
- break;
default:
- sLog.outError("Pet have incorrect type (%u) for levelup.", getPetType());
- break;
+ break;
}
- for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]));
-
UpdateAllStats();
SetHealth(GetMaxHealth());
@@ -1904,6 +1890,263 @@ void Pet::CastPetAura(PetAura const* aura)
CastSpell(this, auraId, true);
}
+void Pet::UpdateScalingAuras()
+{
+ // there exists temp. summoned pets with scaling auras
+ // they should not scale dynamically
+ if (isTemporarySummoned())
+ return;
+
+ for (AuraList::const_iterator itr = m_scalingauras.begin(); itr != m_scalingauras.end(); ++itr)
+ {
+ SpellEntry const* spellInfo = (*itr)->GetSpellProto();
+ // check if we need to update aura
+ int32 amount = CalculateSpellDamage(this, spellInfo, (*itr)->GetEffIndex());
+ if ((*itr)->GetModifier()->m_amount == amount)
+ continue;
+
+ // update aura amount
+ (*itr)->UpdateModifierAmount(amount);
+ }
+}
+
+uint32 Pet::CalcScalingAuraBonus(SpellEntry const* spellInfo, uint8 effect_index)
+{
+ Player* owner = GetCharmerOrOwnerPlayerOrPlayerItself();
+ if (!owner || spellInfo->Effect[effect_index] != SPELL_EFFECT_APPLY_AURA)
+ return 0;
+
+ uint32 ownerValue = 0;
+ uint32 bonusValue = 0;
+ float scale = 0;
+
+ switch (spellInfo->EffectApplyAuraName[effect_index])
+ {
+ case SPELL_AURA_MOD_DAMAGE_DONE:
+ {
+ switch (spellInfo->Id)
+ {
+ // hunter pet scaling aura
+ case 34902:
+ {
+ ownerValue = owner->GetTotalAttackPowerValue(RANGED_ATTACK);
+ scale = 0.1287f;
+
+ // search for "Wild Hunt"
+ for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
+ if (itr->second.state != PETSPELL_REMOVED)
+ {
+ SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first);
+ if (!spellInfo || spellInfo->SpellIconID == 3748)
+ continue;
+ scale *= float(spellInfo->EffectBasePoints[1] +101) / 100.0f;
+ break;
+ }
+ break;
+ }
+ // warlock pet scaling aura
+ case 34947:
+ {
+ ownerValue = owner->GetMaxSpellBaseDamageBonusDone(SpellSchoolMask(SPELL_SCHOOL_MASK_FIRE | SPELL_SCHOOL_MASK_SHADOW));
+ scale = 0.15f;
+ break;
+ }
+ // dk pet scaling aura, unknown for now
+ case 54566:
+ break;
+ }
+ break;
+ }
+ case SPELL_AURA_MOD_STAT:
+ {
+ // only single stats in scaling auras (otherwise scaling not possible)
+ if (spellInfo->EffectMiscValue[effect_index] < 0 || spellInfo->EffectMiscValue[effect_index] > 4)
+ return 0;
+
+ ownerValue = uint32(owner->GetTotalStatValue(Stats(spellInfo->EffectMiscValue[effect_index])));
+
+ switch(spellInfo->EffectMiscValue[effect_index])
+ {
+ case STAT_STRENGTH:
+ {
+ // just dk scaling aura here
+ scale = 0.678f;
+
+ // search for "Ravenous Dead" and "Glyph of Ghoul"
+ AuraList const& mDummy = owner->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
+ if ((*itr)->GetSpellProto()->SpellIconID == 3010 || (*itr)->GetId() == 58686)
+ scale *= float((*itr)->GetModifier()->m_amount + 100) / 100.0f;
+
+ break;
+ }
+ case STAT_STAMINA:
+ {
+ scale = 0.3f;
+
+ switch (spellInfo->Id)
+ {
+ // hunter pet scaling aura
+ case 34902:
+ {
+ scale = 0.4493f;
+
+ // search for "Wild Hunt"
+ for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
+ if (itr->second.state != PETSPELL_REMOVED)
+ {
+ SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first);
+ if (!spellInfo || spellInfo->SpellIconID != 3748)
+ continue;
+ scale *= float(spellInfo->EffectBasePoints[0] +101) / 100.0f;
+ break;
+ }
+ break;
+ }
+ // wl scaling aura
+ case 34947:
+ {
+ scale = 0.7f;
+ break;
+ }
+ // dk pet scaling aura
+ case 54566:
+ {
+ scale = 0.3928f;
+
+ // search for "Ravenous Dead" and "Glyph of Ghoul"
+ AuraList const& mDummy = owner->GetAurasByType(SPELL_AURA_DUMMY);
+ for(AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
+ if ((*itr)->GetSpellProto()->SpellIconID == 3010 || (*itr)->GetId() == 58686)
+ scale *= float((*itr)->GetModifier()->m_amount +100) / 100.0f;
+ break;
+ }
+ }
+ break;
+ }
+ case STAT_INTELLECT:
+ {
+ // just warlock pet aura here
+ scale = 0.3f;
+ break;
+ }
+ }
+ break;
+ }
+ case SPELL_AURA_MOD_ATTACK_POWER:
+ {
+ switch (spellInfo->Id)
+ {
+ // hunter pet scaling aura
+ case 34902:
+ {
+ ownerValue = uint32(owner->GetTotalAttackPowerValue(RANGED_ATTACK));
+ scale = 0.22f;
+
+ // search for "Wild Hunt"
+ for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
+ if (itr->second.state != PETSPELL_REMOVED)
+ {
+ SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first);
+ if (!spellInfo || spellInfo->SpellIconID != 3748)
+ continue;
+ scale *= float(spellInfo->EffectBasePoints[1] + 101) / 100.0f;
+ break;
+ }
+
+ // search for "Hunter vs. Wild"
+ AuraList const& mAttackPowerMod = owner->GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT);
+ for(AuraList::const_iterator itr = mAttackPowerMod.begin(); itr != mAttackPowerMod.end(); ++itr)
+ if ((*itr)->GetSpellProto()->SpellIconID == 3647)
+ bonusValue += (*itr)->GetModifier()->m_amount * owner->GetTotalStatValue(Stats((*itr)->GetModifier()->m_miscvalue)) / 100;
+
+ break;
+ }
+ // warlock pet scaling aura
+ case 34947:
+ {
+ ownerValue = owner->GetMaxSpellBaseDamageBonusDone(SpellSchoolMask(SPELL_SCHOOL_MASK_FIRE | SPELL_SCHOOL_MASK_SHADOW));
+ scale = 0.57f;
+ break;
+ }
+ }
+ break;
+ }
+ case SPELL_AURA_MOD_RESISTANCE:
+ {
+ // only single schools in scaling auras (otherwise scaling not possible)
+ SpellSchools school = GetFirstSchoolInMask(SpellSchoolMask(spellInfo->EffectMiscValue[effect_index]));
+ ownerValue = owner->GetResistance(school);
+
+ switch(school)
+ {
+ // armor
+ case SPELL_SCHOOL_NORMAL:
+ {
+ scale = 0.35f;
+
+ // hunter pet scaling aura
+ if (spellInfo->Id == 34904)
+ scale = 0.4497f;
+ break;
+ }
+ // all other resistances
+ default:
+ {
+ scale = 0.4f;
+ break;
+ }
+ }
+ break;
+ }
+ case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE:
+ case SPELL_AURA_MOD_POWER_REGEN:
+ // no information here for now
+ break;
+ case SPELL_AURA_MOD_SPELL_HIT_CHANCE:
+ case SPELL_AURA_MOD_HIT_CHANCE:
+ {
+ // find maximum of owners hit chances (fractions dropped)
+ float hit[3] = {owner->m_modMeleeHitChance, owner->m_modRangedHitChance, owner->m_modSpellHitChance};
+ for (uint8 i = 0; i<3; i++)
+ if (ownerValue < uint32(hit[i]))
+ ownerValue = uint32(hit[i]);
+ // all known auras scale 1:1
+ scale = 1.0f;
+ break;
+ }
+ case SPELL_AURA_HASTE_MELEE:
+ {
+ // find owners maximum haste (== minimum speedPct factor)
+ float cur = 1.0f, factor[3] = {owner->m_modAttackSpeedPct[BASE_ATTACK], m_modAttackSpeedPct[RANGED_ATTACK], owner->GetFloatValue(UNIT_MOD_CAST_SPEED)};
+ for (uint8 i = 0; i<3; i++)
+ if (cur > factor[i])
+ cur = factor[i];
+ // get percent haste out of factor
+ ownerValue = uint32(100.0f/cur -100);
+
+ // just death knight ghoul aura here for now, 1:1
+ scale = 1.0f;
+ }
+ case SPELL_AURA_MOD_EXPERTISE:
+ {
+ // expertise scales proportional to owners hitchance (fractions dropped)
+ // (e.g. 5% hitchance owner -> 5% less chance, that the attack ist dodged/parried)
+ // note: 1 point expertise gives 0.25% less chance to fail
+ float cur = 0, hit[3] = {owner->m_modMeleeHitChance, owner->m_modRangedHitChance, owner->m_modSpellHitChance};
+ for (uint8 i = 0; i<3; i++)
+ if (cur < hit[i])
+ cur = hit[i];
+ bonusValue = uint32(4*cur);
+ break;
+ }
+ default:
+ return 0;
+ }
+
+ return uint32(ownerValue * scale) + bonusValue;
+}
+
struct DoPetLearnSpell
{
DoPetLearnSpell(Pet& _pet) : pet(_pet) {}
diff --git a/src/game/Pet.h b/src/game/Pet.h
index efc9ecd..b58731b 100644
--- a/src/game/Pet.h
+++ b/src/game/Pet.h
@@ -183,12 +183,15 @@ class Pet : public Creature
bool UpdateStats(Stats stat);
bool UpdateAllStats();
- void UpdateResistances(uint32 school);
+ // void UpdateResistances(uint32 school);
void UpdateArmor();
void UpdateMaxHealth();
void UpdateMaxPower(Powers power);
void UpdateAttackPowerAndDamage(bool ranged = false);
void UpdateDamagePhysical(WeaponAttackType attType);
+ void UpdateScalingAuras();
+
+ uint32 CalcScalingAuraBonus(SpellEntry const* spellInfo, uint8 effect_index);
bool CanTakeMoreActiveSpells(uint32 SpellIconID);
void ToggleAutocast(uint32 spellid, bool apply);
@@ -219,6 +222,7 @@ class Pet : public Creature
PetSpellMap m_spells;
AutoSpellList m_autospells;
+ AuraList m_scalingauras;
void InitPetCreateSpells();
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 53706be..fa611ca 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -440,6 +440,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_regenTimer = 0;
m_weaponChangeTimer = 0;
+ m_petScalingUpdateTimer = 0;
m_zoneUpdateId = 0;
m_zoneUpdateTimer = 0;
@@ -1468,10 +1469,20 @@ void Player::Update( uint32 p_time )
// group update
SendUpdateToOutOfRangeGroupMembers();
- Pet* pet = GetPet();
- if(pet && !pet->IsWithinDistInMap(this, GetMap()->GetVisibilityDistance()) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID())))
+ if (Pet* pet = GetPet())
{
- RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true);
+ if (!pet->IsWithinDistInMap(this, GetMap()->GetVisibilityDistance()) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID())))
+ RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true);
+ else if (m_petScalingUpdateTimer)
+ {
+ if (m_petScalingUpdateTimer <= p_time)
+ {
+ pet->UpdateScalingAuras();
+ m_petScalingUpdateTimer = 0;
+ }
+ else
+ m_petScalingUpdateTimer -= p_time;
+ }
}
//we should execute delayed teleports only for alive(!) players
@@ -17865,6 +17876,17 @@ void Player::RemovePetActionBar()
SendDirectMessage(&data);
}
+void Player::UpdatePetScalingAuras()
+{
+ Pet* pet = GetPet();
+ if (!pet)
+ return;
+
+ // pet scaling auras will be updated with delay, to minimize cpu cycles
+ if (!m_petScalingUpdateTimer)
+ m_petScalingUpdateTimer = 1000;
+}
+
bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell)
{
if (!mod || !spellInfo)
diff --git a/src/game/Player.h b/src/game/Player.h
index bdaa399..d697f58 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1608,6 +1608,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void CharmSpellInitialize();
void PossessSpellInitialize();
void RemovePetActionBar();
+ void UpdatePetScalingAuras();
bool HasSpell(uint32 spell) const;
bool HasActiveSpell(uint32 spell) const; // show in spellbook
@@ -2637,6 +2638,8 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 m_temporaryUnsummonedPetNumber;
uint32 m_oldpetspell;
+ uint32 m_petScalingUpdateTimer;
+
AchievementMgr m_achievementMgr;
ReputationMgr m_reputationMgr;
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index e7c3c4f..d03847c 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -377,7 +377,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = {
#define SPELL_ATTR_EX4_UNK22 0x00400000 // 22
#define SPELL_ATTR_EX4_UNK23 0x00800000 // 23
#define SPELL_ATTR_EX4_UNK24 0x01000000 // 24
-#define SPELL_ATTR_EX4_UNK25 0x02000000 // 25 pet scaling auras
+#define SPELL_ATTR_EX4_PET_SCALING_AURA 0x02000000 // 25 pet scaling auras
#define SPELL_ATTR_EX4_CAST_ONLY_IN_OUTLAND 0x04000000 // 26 Can only be used in Outland.
#define SPELL_ATTR_EX4_UNK27 0x08000000 // 27
#define SPELL_ATTR_EX4_UNK28 0x10000000 // 28
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index f6badb4..562f13b 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -598,6 +598,22 @@ void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
m_modifier.periodictime = pt;
}
+void Aura::UpdateModifierAmount(int32 amount)
+{
+ // use this method, to modify modifier.amount when aura is already applied
+ AuraType aura = m_modifier.m_auraname;
+
+ SetInUse(true);
+ if(aura < TOTAL_AURAS)
+ {
+ // maybe we can find a better way here?
+ (*this.*AuraHandler [aura])(false, true);
+ m_modifier.m_amount = amount;
+ (*this.*AuraHandler [aura])(true, true);
+ }
+ SetInUse(false);
+}
+
void Aura::Update(uint32 diff)
{
if (m_duration > 0)
diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
index 89918a8..9de2668 100644
--- a/src/game/SpellAuras.h
+++ b/src/game/SpellAuras.h
@@ -224,6 +224,7 @@ class MANGOS_DLL_SPEC Aura
virtual ~Aura();
void SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue);
+ void UpdateModifierAmount(int32 amount);
Modifier* GetModifier() { return &m_modifier; }
Modifier const* GetModifier() const { return &m_modifier; }
int32 GetMiscValue() const { return m_spellProto->EffectMiscValue[m_effIndex]; }
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp
index f6e30e1..8a829cb 100644
--- a/src/game/StatSystem.cpp
+++ b/src/game/StatSystem.cpp
@@ -39,13 +39,6 @@ bool Player::UpdateStats(Stats stat)
SetStat(stat, int32(value));
- if(stat == STAT_STAMINA || stat == STAT_INTELLECT)
- {
- Pet *pet = GetPet();
- if(pet)
- pet->UpdateStats(stat);
- }
-
switch(stat)
{
case STAT_STRENGTH:
@@ -76,6 +69,8 @@ bool Player::UpdateStats(Stats stat)
UpdateSpellDamageAndHealingBonus();
UpdateManaRegen();
+ UpdatePetScalingAuras();
+
// Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat
uint32 mask = 0;
AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT);
@@ -151,9 +146,7 @@ void Player::UpdateResistances(uint32 school)
float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school));
SetResistance(SpellSchools(school), int32(value));
- Pet *pet = GetPet();
- if(pet)
- pet->UpdateResistances(school);
+ UpdatePetScalingAuras();
}
else
UpdateArmor();
@@ -182,9 +175,7 @@ void Player::UpdateArmor()
SetArmor(int32(value));
- Pet *pet = GetPet();
- if(pet)
- pet->UpdateArmor();
+ UpdatePetScalingAuras();
UpdateAttackPowerAndDamage(); // armor dependent auras update for SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR
}
@@ -380,10 +371,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
if(ranged)
{
UpdateDamagePhysical(RANGED_ATTACK);
-
- Pet *pet = GetPet(); //update pet's AP
- if(pet)
- pet->UpdateAttackPowerAndDamage();
+ UpdatePetScalingAuras();
}
else
{
@@ -612,18 +600,21 @@ void Player::UpdateMeleeHitChances()
{
m_modMeleeHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
m_modMeleeHitChance+= GetRatingBonusValue(CR_HIT_MELEE);
+ UpdatePetScalingAuras();
}
void Player::UpdateRangedHitChances()
{
m_modRangedHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
m_modRangedHitChance+= GetRatingBonusValue(CR_HIT_RANGED);
+ UpdatePetScalingAuras();
}
void Player::UpdateSpellHitChances()
{
m_modSpellHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE);
m_modSpellHitChance+= GetRatingBonusValue(CR_HIT_SPELL);
+ UpdatePetScalingAuras();
}
void Player::UpdateAllSpellCritChances()
@@ -871,20 +862,6 @@ bool Pet::UpdateStats(Stats stat)
// value = ((base_value * base_pct) + total_value) * total_pct
float value = GetTotalStatValue(stat);
-
- Unit *owner = GetOwner();
- if ( stat == STAT_STAMINA )
- {
- if(owner)
- value += float(owner->GetStat(stat)) * 0.3f;
- }
- //warlock's and mage's pets gain 30% of owner's intellect
- else if ( stat == STAT_INTELLECT && getPetType() == SUMMON_PET )
- {
- if(owner && (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) )
- value += float(owner->GetStat(stat)) * 0.3f;
- }
-
SetStat(stat, int32(value));
switch(stat)
@@ -915,38 +892,16 @@ bool Pet::UpdateAllStats()
return true;
}
-void Pet::UpdateResistances(uint32 school)
-{
- if(school > SPELL_SCHOOL_NORMAL)
- {
- float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school));
-
- Unit *owner = GetOwner();
- // hunter and warlock pets gain 40% of owner's resistance
- if(owner && (getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)))
- value += float(owner->GetResistance(SpellSchools(school))) * 0.4f;
-
- SetResistance(SpellSchools(school), int32(value));
- }
- else
- UpdateArmor();
-}
-
void Pet::UpdateArmor()
{
float value = 0.0f;
float bonus_armor = 0.0f;
UnitMods unitMod = UNIT_MOD_ARMOR;
- Unit *owner = GetOwner();
- // hunter and warlock pets gain 35% of owner's armor value
- if(owner && (getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)))
- bonus_armor = 0.35f * float(owner->GetArmor());
-
+ // note that pets gain only 1 armor per agility
value = GetModifierValue(unitMod, BASE_VALUE);
value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetStat(STAT_AGILITY) * 2.0f;
- value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
+ value += GetModifierValue(unitMod, TOTAL_VALUE) + GetStat(STAT_AGILITY);
value *= GetModifierValue(unitMod, TOTAL_PCT);
SetArmor(int32(value));
@@ -985,44 +940,14 @@ void Pet::UpdateAttackPowerAndDamage(bool ranged)
return;
float val = 0.0f;
- float bonusAP = 0.0f;
UnitMods unitMod = UNIT_MOD_ATTACK_POWER;
- if(GetEntry() == 416) // imp's attack power
- val = GetStat(STAT_STRENGTH) - 10.0f;
+ if(GetEntry() == 416) // imp's attack power (probably this is correct for all "casters",
+ val = GetStat(STAT_STRENGTH) - 10.0f; // e.g. also mage's water elemental
else
val = 2 * GetStat(STAT_STRENGTH) - 20.0f;
- Unit* owner = GetOwner();
- if( owner && owner->GetTypeId()==TYPEID_PLAYER)
- {
- if(getPetType() == HUNTER_PET) //hunter pets benefit from owner's attack power
- {
- bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f;
- SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f));
- }
- //demons benefit from warlocks shadow or fire damage
- else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)
- {
- int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
- int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW);
- int32 maximum = (fire > shadow) ? fire : shadow;
- if(maximum < 0)
- maximum = 0;
- SetBonusDamage( int32(maximum * 0.15f));
- bonusAP = maximum * 0.57f;
- }
- //water elementals benefit from mage's frost damage
- else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_MAGE)
- {
- int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST);
- if(frost < 0)
- frost = 0;
- SetBonusDamage( int32(frost * 0.4f));
- }
- }
-
- SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP);
+ SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val);
//in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index ae03a34..e3aedb6 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -3957,6 +3957,10 @@ bool Unit::AddAura(Aura *Aur)
{
m_modAuras[aurName].push_back(Aur);
}
+ if (aurSpellInfo->AttributesEx4 & SPELL_ATTR_EX4_PET_SCALING_AURA && GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
+ {
+ ((Pet*)this)->m_scalingauras.push_back(Aur);
+ }
Aur->ApplyModifier(true,true);
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Aura %u now is in use", aurName);
@@ -4492,6 +4496,10 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
{
m_modAuras[Aur->GetModifier()->m_auraname].remove(Aur);
}
+ if (AurSpellInfo->AttributesEx4 & SPELL_ATTR_EX4_PET_SCALING_AURA && GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
+ {
+ ((Pet*)this)->m_scalingauras.remove(Aur);
+ }
// Set remove mode
Aur->SetRemoveMode(mode);
@@ -9368,6 +9376,19 @@ int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask)
return TakenAdvertisedBenefit;
}
+int32 Unit::GetMaxSpellBaseDamageBonusDone(SpellSchoolMask schoolMask)
+{
+ int32 bonus = 0;
+ for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
+ if (schoolMask & SpellSchoolMask(1 << i))
+ {
+ int32 current = SpellBaseDamageBonusDone(SpellSchoolMask(1 << i));
+ if (current > bonus)
+ bonus = current;
+ }
+ return bonus > 0 ? bonus : 0;
+}
+
bool Unit::IsSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType)
{
// not critting spell
@@ -9953,7 +9974,8 @@ uint32 Unit::MeleeDamageBonusDone(Unit *pVictim, uint32 pdamage,WeaponAttackType
AuraList const& mModDamageDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE);
for(AuraList::const_iterator i = mModDamageDone.begin(); i != mModDamageDone.end(); ++i)
{
- if ((*i)->GetModifier()->m_miscvalue & schoolMask && // schoolmask has to fit with the intrinsic spell school
+ if ((*i)->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_PET_SCALING_AURA || // completely schoolmask-independend: pet scaling auras, see note
+ (*i)->GetModifier()->m_miscvalue & schoolMask && // schoolmask has to fit with the intrinsic spell school
(*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask() && // AND schoolmask has to fit with weapon damage school (essential for non-physical spells)
((*i)->GetSpellProto()->EquippedItemClass == -1 || // general, weapon independent
pWeapon && pWeapon->IsFitToSpellRequirements((*i)->GetSpellProto()))) // OR used weapon fits aura requirements
@@ -9961,8 +9983,14 @@ uint32 Unit::MeleeDamageBonusDone(Unit *pVictim, uint32 pdamage,WeaponAttackType
DoneFlat += (*i)->GetModifier()->m_amount;
}
}
+ /* Additional note to pet scaling auras:
+ Those auras have SPELL_SCHOOL_MASK_MAGIC, but anyway should also
+ affect physical damage from non-weapon-damage-based spells (claw, swipe etc.).
+ Alternatively we could use pet::m_bonusdamage (that is currently still used for pet's
+ without dynamic scaling auras), but this would make the scaling aura idea inconsistent in some way :-/
+ */
- // Pets just add their bonus damage to their melee damage
+ // Pets (without scaling auras) just add their bonus damage to their melee damage
if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
DoneFlat += ((Pet*)this)->GetBonusDamage();
}
@@ -11426,6 +11454,10 @@ int32 Unit::CalculateSpellDamage(Unit const* target, SpellEntry const* spellProt
(spellProto->Effect[effect_index] != SPELL_EFFECT_APPLY_AURA || spellProto->EffectApplyAuraName[effect_index] != SPELL_AURA_MOD_DECREASE_SPEED))
value = int32(value*0.25f*exp(getLevel()*(70-spellProto->spellLevel)/1000.0f));
+ if(spellProto->AttributesEx4 & SPELL_ATTR_EX4_PET_SCALING_AURA && GetTypeId() == TYPEID_UNIT &&
+ ((Creature*)this)->isPet())
+ value += ((Pet*)this)->CalcScalingAuraBonus(spellProto, effect_index);
+
return value;
}
diff --git a/src/game/Unit.h b/src/game/Unit.h
index b4b4077..a5edd64 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1722,6 +1722,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
int32 SpellBonusWithCoeffs(SpellEntry const *spellProto, int32 total, int32 benefit, int32 ap_benefit, DamageEffectType damagetype, bool donePart, float defCoeffMod = 1.0f);
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask);
+ int32 GetMaxSpellBaseDamageBonusDone(SpellSchoolMask schoolMask);
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask);
uint32 SpellDamageBonusDone(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1);
uint32 SpellDamageBonusTaken(Unit *pCaster, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1);
--
1.6.5.1.1367.gcd48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment