diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/DataStores/GameTables.cpp | 34 | ||||
| -rw-r--r-- | src/server/game/DataStores/GameTables.h | 14 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 40 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 14 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.h | 2 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 27 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 20 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 8 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 22 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.h | 4 |
14 files changed, 127 insertions, 74 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index a54f6dd365f..7b65d86b9da 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -86,7 +86,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH); PrepareStatement(CHAR_SEL_CHARACTER_INSTANCE, "SELECT id, permanent, map, difficulty, extendState, resettime, entranceId FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemLevel FROM character_aura WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel FROM character_aura WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_AURA_EFFECTS, "SELECT casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount FROM character_aura_effect WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, timer FROM character_queststatus WHERE guid = ? AND status <> 0", CONNECTION_ASYNC); @@ -326,8 +326,8 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_TRANSMOG_OUTFIT, "DELETE FROM character_transmog_outfits WHERE setguid=?", CONNECTION_ASYNC); // Auras - PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemLevel) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_AURA_EFFECT, "INSERT INTO character_aura_effect (guid, casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); diff --git a/src/server/game/DataStores/GameTables.cpp b/src/server/game/DataStores/GameTables.cpp index 96924dd3406..c7c31b9871a 100644 --- a/src/server/game/DataStores/GameTables.cpp +++ b/src/server/game/DataStores/GameTables.cpp @@ -16,6 +16,7 @@ */ #include "GameTables.h" +#include "ItemTemplate.h" #include "Timer.h" #include "Log.h" #include "Util.h" @@ -35,6 +36,7 @@ GameTable<GtNpcDamageByClassEntry> sNpcDamageByClassGameTable[MAX_E GameTable<GtNpcManaCostScalerEntry> sNpcManaCostScalerGameTable; GameTable<GtNpcTotalHpEntry> sNpcTotalHpGameTable[MAX_EXPANSIONS]; GameTable<GtSpellScalingEntry> sSpellScalingGameTable; +GameTable<GtStaminaMultByILvl> sStaminaMultByILvlGameTable; GameTable<GtXpEntry> sXpGameTable; template<class T> @@ -136,6 +138,7 @@ void LoadGameTables(std::string const& dataPath) LOAD_GT(sNpcTotalHpGameTable[6], "NpcTotalHpExp6.txt"); LOAD_GT(sNpcTotalHpGameTable[7], "NpcTotalHpExp7.txt"); LOAD_GT(sSpellScalingGameTable, "SpellScaling.txt"); + LOAD_GT(sStaminaMultByILvlGameTable, "StaminaMultByILvl.txt"); LOAD_GT(sXpGameTable, "xp.txt"); #undef LOAD_GT @@ -152,3 +155,34 @@ void LoadGameTables(std::string const& dataPath) TC_LOG_INFO("server.loading", ">> Initialized %d GameTables in %u ms", gameTableCount, GetMSTimeDiffToNow(oldMSTime)); } + +template<class T> +float GetIlvlStatMultiplier(T const* row, InventoryType invType) +{ + switch (invType) + { + case INVTYPE_NECK: + case INVTYPE_FINGER: + return row->JewelryMultiplier; + break; + case INVTYPE_TRINKET: + return row->TrinketMultiplier; + break; + case INVTYPE_WEAPON: + case INVTYPE_SHIELD: + case INVTYPE_RANGED: + case INVTYPE_2HWEAPON: + case INVTYPE_WEAPONMAINHAND: + case INVTYPE_WEAPONOFFHAND: + case INVTYPE_HOLDABLE: + case INVTYPE_RANGEDRIGHT: + return row->WeaponMultiplier; + break; + default: + return row->ArmorMultiplier; + break; + } +} + +template float GetIlvlStatMultiplier(GtCombatRatingsMultByILvl const* row, InventoryType invType); +template float GetIlvlStatMultiplier(GtStaminaMultByILvl const* row, InventoryType invType); diff --git a/src/server/game/DataStores/GameTables.h b/src/server/game/DataStores/GameTables.h index 962f321496a..c82b11157c4 100644 --- a/src/server/game/DataStores/GameTables.h +++ b/src/server/game/DataStores/GameTables.h @@ -22,6 +22,8 @@ #include "Common.h" #include <vector> +enum InventoryType : uint8; + struct GtArmorMitigationByLvlEntry { float Mitigation = 0.0f; @@ -174,6 +176,14 @@ struct GtSpellScalingEntry float DamageSecondary = 0.0f; }; +struct GtStaminaMultByILvl +{ + float ArmorMultiplier = 0.0f; + float WeaponMultiplier = 0.0f; + float TrinketMultiplier = 0.0f; + float JewelryMultiplier = 0.0f; +}; + struct GtXpEntry { float Total = 0.0f; @@ -216,6 +226,7 @@ TC_GAME_API extern GameTable<GtNpcDamageByClassEntry> sNpcDamageBy TC_GAME_API extern GameTable<GtNpcManaCostScalerEntry> sNpcManaCostScalerGameTable; TC_GAME_API extern GameTable<GtNpcTotalHpEntry> sNpcTotalHpGameTable[MAX_EXPANSIONS]; TC_GAME_API extern GameTable<GtSpellScalingEntry> sSpellScalingGameTable; +TC_GAME_API extern GameTable<GtStaminaMultByILvl> sStaminaMultByILvlGameTable; TC_GAME_API extern GameTable<GtXpEntry> sXpGameTable; TC_GAME_API void LoadGameTables(std::string const& dataPath); @@ -308,4 +319,7 @@ inline float GetSpellScalingColumnForClass(GtSpellScalingEntry const* row, int32 return 0.0f; } +template<class T> +float GetIlvlStatMultiplier(T const* row, InventoryType invType); + #endif // GameTables_h__ diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b6c3384295e..e6aff9ca6eb 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7350,31 +7350,7 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) uint32 itemLevel = item->GetItemLevel(this); float combatRatingMultiplier = 1.0f; if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(itemLevel)) - { - switch (proto->GetInventoryType()) - { - case INVTYPE_WEAPON: - case INVTYPE_SHIELD: - case INVTYPE_RANGED: - case INVTYPE_2HWEAPON: - case INVTYPE_WEAPONMAINHAND: - case INVTYPE_WEAPONOFFHAND: - case INVTYPE_HOLDABLE: - case INVTYPE_RANGEDRIGHT: - combatRatingMultiplier = ratingMult->WeaponMultiplier; - break; - case INVTYPE_TRINKET: - combatRatingMultiplier = ratingMult->TrinketMultiplier; - break; - case INVTYPE_NECK: - case INVTYPE_FINGER: - combatRatingMultiplier = ratingMult->JewelryMultiplier; - break; - default: - combatRatingMultiplier = ratingMult->ArmorMultiplier; - break; - } - } + combatRatingMultiplier = GetIlvlStatMultiplier(ratingMult, proto->GetInventoryType()); // req. check at equip, but allow use for extended range if range limit max level, set proper level for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) @@ -7412,9 +7388,13 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) // ApplyStatBuffMod(STAT_SPIRIT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_SPIRIT, BASE_PCT_EXCLUDE_CREATE)), apply); // break; case ITEM_MOD_STAMINA: //modify stamina + { + if (GtStaminaMultByILvl const* staminaMult = sStaminaMultByILvlGameTable.GetRow(itemLevel)) + val = int32(val * GetIlvlStatMultiplier(staminaMult, proto->GetInventoryType())); HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply); ApplyStatBuffMod(STAT_STAMINA, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_PCT_EXCLUDE_CREATE)), apply); break; + } case ITEM_MOD_DEFENSE_SKILL_RATING: ApplyRatingMod(CR_DEFENSE_SKILL, int32(val * combatRatingMultiplier), apply); break; @@ -18621,8 +18601,8 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe } /* - 0 1 2 3 4 5 6 7 8 9 - SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemLevel FROM character_aura WHERE guid = ? + 0 1 2 3 4 5 6 7 8 9 10 + SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemId, castItemLevel FROM character_aura WHERE guid = ? */ if (auraResult) { @@ -18637,7 +18617,8 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe int32 maxDuration = fields[6].GetInt32(); int32 remainTime = fields[7].GetInt32(); uint8 remainCharges = fields[8].GetUInt8(); - int32 castItemLevel = fields[9].GetInt32(); + uint32 castItemId = fields[9].GetUInt32(); + int32 castItemLevel = fields[10].GetInt32(); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(key.SpellId); if (!spellInfo) @@ -18669,7 +18650,7 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe AuraLoadEffectInfo& info = effectInfo[key]; ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()); - if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, nullptr, info.BaseAmounts.data(), nullptr, casterGuid, itemGuid, castItemLevel)) + if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, nullptr, info.BaseAmounts.data(), nullptr, casterGuid, itemGuid, castItemId, castItemLevel)) { if (!aura->CanBeSaved()) { @@ -20574,6 +20555,7 @@ void Player::_SaveAuras(CharacterDatabaseTransaction& trans) stmt->setInt32(index++, aura->GetMaxDuration()); stmt->setInt32(index++, aura->GetDuration()); stmt->setUInt8(index++, aura->GetCharges()); + stmt->setUInt32(index++, aura->GetCastItemId()); stmt->setInt32(index++, aura->GetCastItemLevel()); trans->Append(stmt); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2a89e251b0e..2d6146da676 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3223,7 +3223,7 @@ void Unit::DeMorph() SetDisplayId(GetNativeDisplayId()); } -Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool resetPeriodicTimer /*= true*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, int32 castItemLevel /*= -1*/) +Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool resetPeriodicTimer /*= true*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/) { ASSERT(!casterGUID.IsEmpty() || caster); @@ -3239,9 +3239,15 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint3 { castItemGuid = castItem->GetGUID(); if (Player* owner = castItem->GetOwner()) + { + castItemId = castItem->GetEntry(); castItemLevel = int32(castItem->GetItemLevel(owner)); + } else if (castItem->GetOwnerGUID() == caster->GetGUID()) + { + castItemId = castItem->GetEntry(); castItemLevel = int32(castItem->GetItemLevel(caster->ToPlayer())); + } } // find current aura from spell and change it's stackamount, or refresh it's duration @@ -3278,6 +3284,8 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint3 { ObjectGuid* oldGUID = const_cast<ObjectGuid*>(&foundAura->m_castItemGuid); *oldGUID = castItemGuid; + uint32* oldItemId = const_cast<uint32*>(&foundAura->m_castItemId); + *oldItemId = castItemId; int32* oldItemLevel = const_cast<int32*>(&foundAura->m_castItemLevel); *oldItemLevel = castItemLevel; } @@ -8987,13 +8995,13 @@ float Unit::ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index } // function uses real base points (typically value - 1) -int32 Unit::CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints /*= nullptr*/, float* variance /*= nullptr*/, int32 itemLevel /*= -1*/) const +int32 Unit::CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints /*= nullptr*/, float* variance /*= nullptr*/, uint32 castItemId /*= 0*/, int32 itemLevel /*= -1*/) const { SpellEffectInfo const* effect = spellProto->GetEffect(GetMap()->GetDifficultyID(), effect_index); if (variance) *variance = 0.0f; - return effect ? effect->CalcValue(this, basePoints, target, variance, itemLevel) : 0; + return effect ? effect->CalcValue(this, basePoints, target, variance, castItemId, itemLevel) : 0; } int32 Unit::CalcSpellDuration(SpellInfo const* spellProto) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e4b5a803163..9b79a16a712 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1482,7 +1482,7 @@ class TC_GAME_API Unit : public WorldObject bool InitTamedPet(Pet* pet, uint8 level, uint32 spell_id); // aura apply/remove helpers - you should better not use these - Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = ObjectGuid::Empty, int32 castItemLevel = -1); + Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1); void _AddAura(UnitAura* aura, Unit* caster); AuraApplication * _CreateAuraApplication(Aura* aura, uint32 effMask); void _ApplyAuraEffect(Aura* aura, uint8 effIndex); @@ -1863,7 +1863,7 @@ class TC_GAME_API Unit : public WorldObject void SetSpeedRate(UnitMoveType mtype, float rate); float ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index, float value) const; - int32 CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints = nullptr, float* variance = nullptr, int32 itemLevel = -1) const; + int32 CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints = nullptr, float* variance = nullptr, uint32 castItemId = 0, int32 itemLevel = -1) const; int32 CalcSpellDuration(SpellInfo const* spellProto); int32 ModSpellDuration(SpellInfo const* spellProto, Unit const* target, int32 duration, bool positive, uint32 effectMask); void ModSpellCastTime(SpellInfo const* spellProto, int32& castTime, Spell* spell = NULL); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index acb6f0421c7..31edbd98bda 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -565,7 +565,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= AuraEffect::AuraEffect(Aura* base, uint32 effIndex, int32 *baseAmount, Unit* caster) : m_base(base), m_spellInfo(base->GetSpellInfo()), _effectInfo(base->GetSpellEffectInfo(effIndex)), -m_baseAmount(baseAmount ? *baseAmount : _effectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemLevel())), +m_baseAmount(baseAmount ? *baseAmount : _effectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())), m_damage(0), m_critChance(0.0f), m_donePct(1.0f), m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), m_canBeRecalculated(true), m_isPeriodic(false) @@ -611,7 +611,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster) int32 amount = 0; if (!m_spellInfo->HasAttribute(SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(GetSpellEffectInfo()->BonusCoefficient, 0.0f)) - amount = GetSpellEffectInfo()->CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit(), nullptr, GetBase()->GetCastItemLevel()); + amount = GetSpellEffectInfo()->CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit(), nullptr, GetBase()->GetCastItemId(), GetBase()->GetCastItemLevel()); else if (caster && caster->GetTypeId() == TYPEID_PLAYER) amount = int32(caster->ToPlayer()->m_activePlayerData->Mastery * GetSpellEffectInfo()->BonusCoefficient); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 829cfa4cd26..843466f61bb 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -30,7 +30,7 @@ typedef void(AuraEffect::*pAuraEffectHandler)(AuraApplication const* aurApp, uin class TC_GAME_API AuraEffect { friend void Aura::_InitEffects(uint32 effMask, Unit* caster, int32* baseAmount); - friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, bool resetPeriodicTimer, ObjectGuid castItemGuid, int32 castItemLevel); + friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, bool resetPeriodicTimer, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel); friend Aura::~Aura(); public: diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 9bb7a1eb444..a0f216b354c 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -256,7 +256,7 @@ uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availab return effMask & availableEffectMask; } -Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= nullptr*/, bool resetPeriodicTimer /*= true*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, int32 castItemLevel /*= -1*/) +Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= nullptr*/, bool resetPeriodicTimer /*= true*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/) { ASSERT(spellproto); ASSERT(owner); @@ -282,10 +282,10 @@ Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid cast return foundAura; } else - return Create(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemLevel); + return Create(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel); } -Aura* Aura::TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, int32 castItemLevel /*= -1*/) +Aura* Aura::TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/) { ASSERT(spellproto); ASSERT(owner); @@ -295,10 +295,10 @@ Aura* Aura::TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 try if (!effMask) return nullptr; - return Create(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemLevel); + return Create(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel); } -Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel) +Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel) { ASSERT(effMask); ASSERT(spellproto); @@ -328,10 +328,10 @@ Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMas { case TYPEID_UNIT: case TYPEID_PLAYER: - aura = new UnitAura(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemLevel); + aura = new UnitAura(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel); break; case TYPEID_DYNAMICOBJECT: - aura = new DynObjAura(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemLevel); + aura = new DynObjAura(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel); break; default: ABORT(); @@ -344,9 +344,10 @@ Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMas return aura; } -Aura::Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel) : +Aura::Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel) : m_spellInfo(spellproto), m_castGuid(castId), m_casterGuid(!casterGUID.IsEmpty() ? casterGUID : caster->GetGUID()), -m_castItemGuid(castItem ? castItem->GetGUID() : castItemGuid), m_castItemLevel(castItemLevel), m_spellXSpellVisualId(caster ? caster->GetCastSpellXSpellVisualId(spellproto) : spellproto->GetSpellXSpellVisualId()), +m_castItemGuid(castItem ? castItem->GetGUID() : castItemGuid), m_castItemId(castItem ? castItem->GetEntry() : castItemId), +m_castItemLevel(castItemLevel), m_spellXSpellVisualId(caster ? caster->GetCastSpellXSpellVisualId(spellproto) : spellproto->GetSpellXSpellVisualId()), m_applyTime(time(NULL)), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0), m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1), m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr), @@ -2253,8 +2254,8 @@ void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraAppli } } -UnitAura::UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel) - : Aura(spellproto, castId, owner, caster, castItem, casterGUID, castItemGuid, castItemLevel) +UnitAura::UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel) + : Aura(spellproto, castId, owner, caster, castItem, casterGUID, castItemGuid, castItemId, castItemLevel) { m_AuraDRGroup = DIMINISHING_NONE; LoadScripts(); @@ -2357,8 +2358,8 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c } } -DynObjAura::DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel) - : Aura(spellproto, castId, owner, caster, castItem, casterGUID, castItemGuid, castItemLevel) +DynObjAura::DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel) + : Aura(spellproto, castId, owner, caster, castItem, casterGUID, castItemGuid, castItemId, castItemLevel) { LoadScripts(); ASSERT(GetDynobjOwner()); diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 0be5e9d4afb..d9086a4753a 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -115,15 +115,15 @@ struct AuraLoadEffectInfo class TC_GAME_API Aura { - friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, bool resetPeriodicTimer, ObjectGuid castItemGuid, int32 castItemLevel); + friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, bool resetPeriodicTimer, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel); public: typedef std::map<ObjectGuid, AuraApplication*> ApplicationMap; static uint32 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availableEffectMask, WorldObject* owner); - static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = nullptr, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = ObjectGuid::Empty, int32 castItemLevel = -1); - static Aura* TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid castItemGuid = ObjectGuid::Empty, int32 castItemLevel = -1); - static Aura* Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel); - Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel); + static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = nullptr, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1); + static Aura* TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1); + static Aura* Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel); + Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel); void _InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount); virtual ~Aura(); @@ -133,6 +133,7 @@ class TC_GAME_API Aura ObjectGuid GetCastGUID() const { return m_castGuid; } ObjectGuid GetCasterGUID() const { return m_casterGuid; } ObjectGuid GetCastItemGUID() const { return m_castItemGuid; } + uint32 GetCastItemId() const { return m_castItemId; } int32 GetCastItemLevel() const { return m_castItemLevel; } uint32 GetSpellXSpellVisualId() const { return m_spellXSpellVisualId; } Unit* GetCaster() const; @@ -302,6 +303,7 @@ class TC_GAME_API Aura ObjectGuid const m_castGuid; ObjectGuid const m_casterGuid; ObjectGuid const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted + uint32 m_castItemId; int32 m_castItemLevel; uint32 const m_spellXSpellVisualId; time_t const m_applyTime; @@ -338,9 +340,9 @@ class TC_GAME_API Aura class TC_GAME_API UnitAura : public Aura { - friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel); + friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel); public: - UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel); + UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel); void _ApplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override; void _UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override; @@ -359,9 +361,9 @@ class TC_GAME_API UnitAura : public Aura class TC_GAME_API DynObjAura : public Aura { - friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel); + friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel); public: - DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, int32 castItemLevel); + DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel); void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index c6eeb3b6974..b29b6b7f2c2 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -500,7 +500,7 @@ SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto, Unit const* cast memset(EffectBasePoints, 0, sizeof(EffectBasePoints)); for (SpellEffectInfo const* effect : effects) if (effect) - EffectBasePoints[effect->EffectIndex] = effect->CalcBaseValue(caster, nullptr, -1); + EffectBasePoints[effect->EffectIndex] = effect->CalcBaseValue(caster, nullptr, 0, -1); CustomBasePointsMask = 0; MaxAffectedTargets = proto->MaxAffectedTargets; @@ -2602,13 +2602,13 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask) if (auraSpellEffect) basePoints[auraSpellEffect->EffectIndex] = (m_spellValue->CustomBasePointsMask & (1 << auraSpellEffect->EffectIndex)) ? m_spellValue->EffectBasePoints[auraSpellEffect->EffectIndex] : - auraSpellEffect->CalcBaseValue(m_originalCaster, unit, m_castItemLevel); + auraSpellEffect->CalcBaseValue(m_originalCaster, unit, m_castItemEntry, m_castItemLevel); bool refresh = false; bool const resetPeriodicTimer = !(_triggeredCastFlags & TRIGGERED_DONT_RESET_PERIODIC_TIMER); m_spellAura = Aura::TryRefreshStackOrCreate(m_spellInfo, m_castId, effectMask, unit, m_originalCaster, basePoints, - m_CastItem, ObjectGuid::Empty, &refresh, resetPeriodicTimer, ObjectGuid::Empty, m_castItemLevel); + m_CastItem, ObjectGuid::Empty, &refresh, resetPeriodicTimer, ObjectGuid::Empty, m_castItemEntry, m_castItemLevel); if (m_spellAura) { // Set aura stack amount to desired value @@ -6046,7 +6046,7 @@ SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules() int32 Spell::CalculateDamage(uint8 i, Unit const* target, float* var /*= nullptr*/) const { bool needRecalculateBasePoints = !(m_spellValue->CustomBasePointsMask & (1 << i)); - return m_caster->CalculateSpellDamage(target, m_spellInfo, i, needRecalculateBasePoints ? nullptr : &m_spellValue->EffectBasePoints[i], var, m_castItemLevel); + return m_caster->CalculateSpellDamage(target, m_spellInfo, i, needRecalculateBasePoints ? nullptr : &m_spellValue->EffectBasePoints[i], var, m_castItemEntry, m_castItemLevel); } bool Spell::CanAutoCast(Unit* target) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index cadab4b460d..4b6b0f504d1 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1510,7 +1510,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex) return; } - if (Aura* aura = Aura::TryCreate(m_spellInfo, m_castId, MAX_EFFECT_MASK, dynObj, caster, &m_spellValue->EffectBasePoints[0], nullptr, ObjectGuid::Empty, ObjectGuid::Empty, m_castItemLevel)) + if (Aura* aura = Aura::TryCreate(m_spellInfo, m_castId, MAX_EFFECT_MASK, dynObj, caster, &m_spellValue->EffectBasePoints[0], nullptr, ObjectGuid::Empty, ObjectGuid::Empty, m_castItemEntry, m_castItemLevel)) { m_spellAura = aura; m_spellAura->_RegisterForTargets(); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index b9d17622476..5662a1de538 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -457,11 +457,11 @@ bool SpellEffectInfo::IsUnitOwnedAuraEffect() const return IsAreaAuraEffect() || Effect == SPELL_EFFECT_APPLY_AURA; } -int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const* bp /*= nullptr*/, Unit const* target /*= nullptr*/, float* variance /*= nullptr*/, int32 itemLevel /*= -1*/) const +int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const* bp /*= nullptr*/, Unit const* target /*= nullptr*/, float* variance /*= nullptr*/, uint32 castItemId /*= 0*/, int32 itemLevel /*= -1*/) const { float basePointsPerLevel = RealPointsPerLevel; // TODO: this needs to be a float, not rounded - int32 basePoints = CalcBaseValue(caster, target, itemLevel); + int32 basePoints = CalcBaseValue(caster, target, castItemId, itemLevel); float value = bp ? *bp : basePoints; float comboDamage = PointsPerResource; @@ -509,7 +509,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const* return int32(round(value)); } -int32 SpellEffectInfo::CalcBaseValue(Unit const* caster, Unit const* target, int32 itemLevel) const +int32 SpellEffectInfo::CalcBaseValue(Unit const* caster, Unit const* target, uint32 itemId, int32 itemLevel) const { if (Scaling.Coefficient != 0.0f) { @@ -555,10 +555,21 @@ int32 SpellEffectInfo::CalcBaseValue(Unit const* caster, Unit const* target, int value = GetSpellScalingColumnForClass(sSpellScalingGameTable.GetRow(level), _spellInfo->Scaling.Class); if (_spellInfo->Scaling.Class == -7) + if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel)) + if (ItemSparseEntry const* itemSparse = sItemSparseStore.LookupEntry(itemId)) + value *= GetIlvlStatMultiplier(ratingMult, InventoryType(itemSparse->InventoryType)); + + if (IsAura(SPELL_AURA_MOD_RATING)) { - // todo: get inventorytype here if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel)) - value *= ratingMult->ArmorMultiplier; + if (ItemSparseEntry const* itemSparse = sItemSparseStore.LookupEntry(itemId)) + value *= GetIlvlStatMultiplier(ratingMult, InventoryType(itemSparse->InventoryType)); + } + else if (IsAura(SPELL_AURA_MOD_STAT) && MiscValue == STAT_STAMINA) + { + if (GtStaminaMultByILvl const* staminaMult = sStaminaMultByILvlGameTable.GetRow(effectiveItemLevel)) + if (ItemSparseEntry const* itemSparse = sItemSparseStore.LookupEntry(itemId)) + value *= GetIlvlStatMultiplier(staminaMult, InventoryType(itemSparse->InventoryType)); } } @@ -712,6 +723,7 @@ ExpectedStatType SpellEffectInfo::GetScalingExpectedStat() const case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: case SPELL_EFFECT_APPLY_AURA_ON_PET: case SPELL_EFFECT_202: + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM: switch (ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index aef724d4146..e3b0de52faf 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -376,8 +376,8 @@ public: bool IsFarDestTargetEffect() const; bool IsUnitOwnedAuraEffect() const; - int32 CalcValue(Unit const* caster = nullptr, int32 const* basePoints = nullptr, Unit const* target = nullptr, float* variance = nullptr, int32 itemLevel = -1) const; - int32 CalcBaseValue(Unit const* caster, Unit const* target, int32 itemLevel) const; + int32 CalcValue(Unit const* caster = nullptr, int32 const* basePoints = nullptr, Unit const* target = nullptr, float* variance = nullptr, uint32 castItemId = 0, int32 itemLevel = -1) const; + int32 CalcBaseValue(Unit const* caster, Unit const* target, uint32 itemId, int32 itemLevel) const; float CalcValueMultiplier(Unit* caster, Spell* spell = NULL) const; float CalcDamageMultiplier(Unit* caster, Spell* spell = NULL) const; |
