diff options
| author | Shauren <shauren.trinity@gmail.com> | 2018-12-09 14:45:03 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2018-12-09 14:45:03 +0100 |
| commit | f94deace764f0b8d99249760d2bc2e85c891c387 (patch) | |
| tree | 4c7c56f34768fc7aef05268061a12845c5bf67ce /src/server/game/Spells | |
| parent | 8725eec9c1c15f3e76bd9d524d4a5d8d0b3f0a44 (diff) | |
| parent | a70030ff252b266d12023ffada2a309409c1ccdb (diff) | |
Merge branch 'bfa'
Diffstat (limited to 'src/server/game/Spells')
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraDefines.h | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 101 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 125 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.h | 7 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 44 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 334 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.h | 6 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 12 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.h | 8 |
9 files changed, 328 insertions, 313 deletions
diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index c988199638e..75860abe402 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -562,7 +562,9 @@ enum AuraType : uint32 SPELL_AURA_489 = 489, SPELL_AURA_490 = 490, SPELL_AURA_491 = 491, - TOTAL_AURAS = 492 + SPELL_AURA_492 = 492, + SPELL_AURA_493 = 493, // 1 spell, 267116 - Animal Companion (modifies Call Pet) + TOTAL_AURAS }; enum AuraObjectType diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b639fe12d75..3ed8cc430de 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -563,7 +563,7 @@ 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 : base->GetSpellEffectInfo(effIndex)->BasePoints), +m_baseAmount(baseAmount ? *baseAmount : _effectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, 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) @@ -609,7 +609,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster) 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()); else if (caster && caster->GetTypeId() == TYPEID_PLAYER) - amount = int32(caster->GetFloatValue(PLAYER_MASTERY) * GetSpellEffectInfo()->BonusCoefficient); + amount = int32(caster->GetFloatValue(ACTIVE_PLAYER_FIELD_MASTERY) * GetSpellEffectInfo()->BonusCoefficient); // check item enchant aura cast if (!amount && caster) @@ -1483,7 +1483,7 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode { // apply glow vision if (target->GetTypeId() == TYPEID_PLAYER) - target->SetByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); + target->SetByteFlag(ACTIVE_PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); target->m_invisibility.AddFlag(type); target->m_invisibility.AddValue(type, GetAmount()); @@ -1495,7 +1495,7 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode // if not have different invisibility auras. // remove glow vision if (target->GetTypeId() == TYPEID_PLAYER) - target->RemoveByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); + target->RemoveByteFlag(ACTIVE_PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); target->m_invisibility.DelFlag(type); } @@ -1567,7 +1567,7 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo target->SetStandFlags(UNIT_STAND_FLAGS_CREEP); if (target->GetTypeId() == TYPEID_PLAYER) - target->SetByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_STEALTH); + target->SetByteFlag(ACTIVE_PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_STEALTH); } else { @@ -1579,7 +1579,7 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP); if (target->GetTypeId() == TYPEID_PLAYER) - target->RemoveByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_STEALTH); + target->RemoveByteFlag(ACTIVE_PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_STEALTH); } } @@ -2011,7 +2011,7 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode, uint32 model_id = 0; // choose a model, based on trigger flag - if (uint32 modelid = sObjectMgr->ChooseDisplayId(ci)) + if (uint32 modelid = ObjectMgr::ChooseDisplayId(ci)->CreatureDisplayID) model_id = modelid; target->SetDisplayId(model_id); @@ -2052,10 +2052,10 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode, uint32 cr_id = target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetMiscValue(); if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(cr_id)) { - uint32 displayID = ObjectMgr::ChooseDisplayId(ci); - sObjectMgr->GetCreatureModelRandomGender(&displayID); + CreatureModel model = *ObjectMgr::ChooseDisplayId(ci); + sObjectMgr->GetCreatureModelRandomGender(&model, ci); - target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, displayID); + target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, model.CreatureDisplayID); } } } @@ -2400,9 +2400,9 @@ void AuraEffect::HandleAuraTrackCreatures(AuraApplication const* aurApp, uint8 m return; if (apply) - target->SetFlag(PLAYER_TRACK_CREATURES, uint32(1) << (GetMiscValue() - 1)); + target->SetFlag(ACTIVE_PLAYER_FIELD_TRACK_CREATURES, uint32(1) << (GetMiscValue() - 1)); else - target->RemoveFlag(PLAYER_TRACK_CREATURES, uint32(1) << (GetMiscValue() - 1)); + target->RemoveFlag(ACTIVE_PLAYER_FIELD_TRACK_CREATURES, uint32(1) << (GetMiscValue() - 1)); } void AuraEffect::HandleAuraTrackResources(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -2416,9 +2416,9 @@ void AuraEffect::HandleAuraTrackResources(AuraApplication const* aurApp, uint8 m return; if (apply) - target->SetFlag(PLAYER_TRACK_RESOURCES, uint32(1) << (GetMiscValue() - 1)); + target->SetFlag(ACTIVE_PLAYER_FIELD_TRACK_RESOURCES, uint32(1) << (GetMiscValue() - 1)); else - target->RemoveFlag(PLAYER_TRACK_RESOURCES, uint32(1) << (GetMiscValue() - 1)); + target->RemoveFlag(ACTIVE_PLAYER_FIELD_TRACK_RESOURCES, uint32(1) << (GetMiscValue() - 1)); } void AuraEffect::HandleAuraTrackStealthed(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -2437,7 +2437,7 @@ void AuraEffect::HandleAuraTrackStealthed(AuraApplication const* aurApp, uint8 m if (target->HasAuraType(GetAuraType())) return; } - target->ApplyModFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_TRACK_STEALTHED, apply); + target->ApplyModFlag(ACTIVE_PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_TRACK_STEALTHED, apply); } void AuraEffect::HandleAuraModStalked(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -2553,8 +2553,9 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo if (!displayId) { - displayId = ObjectMgr::ChooseDisplayId(creatureInfo); - sObjectMgr->GetCreatureModelRandomGender(&displayId); + CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo); + sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo); + displayId = model.CreatureDisplayID; } //some spell has one aura of mount and one of vehicle @@ -3202,14 +3203,8 @@ void AuraEffect::HandleAuraModResistance(AuraApplication const* aurApp, uint8 mo Unit* target = aurApp->GetTarget(); for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) - { if (GetMiscValue() & int32(1<<x)) - { target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply); - if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) - target->ApplyResistanceBuffModsMod(SpellSchools(x), GetAmount() > 0, (float)GetAmount(), apply); - } - } } void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3251,20 +3246,9 @@ void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 if (GetMiscValue() & int32(1<<i)) { if (spellGroupVal) - { target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, (float)spellGroupVal, !apply); - if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) - { - target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)spellGroupVal, !apply); - target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)spellGroupVal, !apply); - } - } + target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply); - if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) - { - target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)GetAmount(), apply); - target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)GetAmount(), apply); - } } } } @@ -3302,11 +3286,11 @@ void AuraEffect::HandleModTargetResistance(AuraApplication const* aurApp, uint8 // show armor penetration if (target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) - target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE, GetAmount(), apply); + target->ApplyModInt32Value(ACTIVE_PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE, GetAmount(), apply); // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy if (target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_SPELL) == SPELL_SCHOOL_MASK_SPELL) - target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, GetAmount(), apply); + target->ApplyModInt32Value(ACTIVE_PLAYER_FIELD_MOD_TARGET_RESISTANCE, GetAmount(), apply); } /********************************/ @@ -3582,7 +3566,7 @@ void AuraEffect::HandleOverrideSpellPowerByAttackPower(AuraApplication const* au if (!target) return; - target->ApplyModSignedFloatValue(PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT, float(m_amount), apply); + target->ApplyModSignedFloatValue(ACTIVE_PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT, float(m_amount), apply); target->UpdateSpellDamageAndHealingBonus(); } @@ -3595,7 +3579,7 @@ void AuraEffect::HandleOverrideAttackPowerBySpellPower(AuraApplication const* au if (!target) return; - target->ApplyModSignedFloatValue(PLAYER_FIELD_OVERRIDE_AP_BY_SPELL_POWER_PERCENT, float(m_amount), apply); + target->ApplyModSignedFloatValue(ACTIVE_PLAYER_FIELD_OVERRIDE_AP_BY_SPELL_POWER_PERCENT, float(m_amount), apply); target->UpdateAttackPowerAndDamage(); target->UpdateAttackPowerAndDamage(true); } @@ -3607,7 +3591,7 @@ void AuraEffect::HandleModVersatilityByPct(AuraApplication const* aurApp, uint8 if (Player* target = aurApp->GetTarget()->ToPlayer()) { - target->SetStatFloatValue(PLAYER_VERSATILITY_BONUS, target->GetTotalAuraModifier(SPELL_AURA_MOD_VERSATILITY)); + target->SetStatFloatValue(ACTIVE_PLAYER_FIELD_VERSATILITY_BONUS, target->GetTotalAuraModifier(SPELL_AURA_MOD_VERSATILITY)); target->UpdateHealingDonePercentMod(); target->UpdateVersatilityDamageDone(); } @@ -4210,7 +4194,7 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode, // This information for client side use only if (target->GetTypeId() == TYPEID_PLAYER) { - uint16 baseField = GetAmount() >= 0 ? PLAYER_FIELD_MOD_DAMAGE_DONE_POS : PLAYER_FIELD_MOD_DAMAGE_DONE_NEG; + uint16 baseField = GetAmount() >= 0 ? ACTIVE_PLAYER_FIELD_MOD_DAMAGE_DONE_POS : ACTIVE_PLAYER_FIELD_MOD_DAMAGE_DONE_NEG; for (uint16 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) if (GetMiscValue() & (1 << i)) target->ApplyModInt32Value(baseField + i, GetAmount(), apply); @@ -4251,9 +4235,9 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 if (GetMiscValue() & (1 << i)) { if (spellGroupVal) - target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(spellGroupVal), !apply); + target->ApplyPercentModFloatValue(ACTIVE_PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(spellGroupVal), !apply); - target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(GetAmount()), apply); + target->ApplyPercentModFloatValue(ACTIVE_PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(GetAmount()), apply); } } } @@ -4341,10 +4325,10 @@ void AuraEffect::HandleNoReagentUseAura(AuraApplication const* aurApp, uint8 mod if (SpellEffectInfo const* effect = (*i)->GetSpellEffectInfo()) mask |= effect->SpellClassMask; - target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); - target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); - target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]); - target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+3, mask[3]); + target->SetUInt32Value(ACTIVE_PLAYER_FIELD_NO_REAGENT_COST , mask[0]); + target->SetUInt32Value(ACTIVE_PLAYER_FIELD_NO_REAGENT_COST+1, mask[1]); + target->SetUInt32Value(ACTIVE_PLAYER_FIELD_NO_REAGENT_COST+2, mask[2]); + target->SetUInt32Value(ACTIVE_PLAYER_FIELD_NO_REAGENT_COST+3, mask[3]); } void AuraEffect::HandleAuraRetainComboPoints(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4953,7 +4937,7 @@ void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 m if (apply) { - target->SetUInt16Value(PLAYER_FIELD_BYTES3, PLAYER_BYTES_3_OVERRIDE_SPELLS_UINT16_OFFSET, overrideId); + target->SetUInt16Value(ACTIVE_PLAYER_FIELD_BYTES3, PLAYER_BYTES_3_OVERRIDE_SPELLS_UINT16_OFFSET, overrideId); if (OverrideSpellDataEntry const* overrideSpells = sOverrideSpellDataStore.LookupEntry(overrideId)) for (uint8 i = 0; i < MAX_OVERRIDE_SPELL; ++i) if (uint32 spellId = overrideSpells->Spells[i]) @@ -4961,7 +4945,7 @@ void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 m } else { - target->SetUInt16Value(PLAYER_FIELD_BYTES3, PLAYER_BYTES_3_OVERRIDE_SPELLS_UINT16_OFFSET, 0); + target->SetUInt16Value(ACTIVE_PLAYER_FIELD_BYTES3, PLAYER_BYTES_3_OVERRIDE_SPELLS_UINT16_OFFSET, 0); if (OverrideSpellDataEntry const* overrideSpells = sOverrideSpellDataStore.LookupEntry(overrideId)) for (uint8 i = 0; i < MAX_OVERRIDE_SPELL; ++i) if (uint32 spellId = overrideSpells->Spells[i]) @@ -5005,9 +4989,9 @@ void AuraEffect::HandlePreventResurrection(AuraApplication const* aurApp, uint8 return; if (apply) - aurApp->GetTarget()->RemoveFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_RELEASE_TIMER); + aurApp->GetTarget()->RemoveFlag(ACTIVE_PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_RELEASE_TIMER); else if (!aurApp->GetTarget()->GetMap()->Instanceable()) - aurApp->GetTarget()->SetFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_RELEASE_TIMER); + aurApp->GetTarget()->SetFlag(ACTIVE_PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_RELEASE_TIMER); } void AuraEffect::HandleMastery(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const @@ -5584,7 +5568,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const if (overkill < 0) overkill = 0; - SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit); + SpellPeriodicAuraLogInfo pInfo(this, damage, dmg, overkill, absorb, resist, 0.0f, crit); caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); @@ -5674,6 +5658,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c // SendSpellNonMeleeDamageLog expects non-absorbed/non-resisted damage SpellNonMeleeDamage log(caster, target, GetId(), GetBase()->GetSpellXSpellVisualId(), GetSpellInfo()->GetSchoolMask(), GetBase()->GetCastGUID()); log.damage = damage; + log.originalDamage = dmg; log.absorb = absorb; log.resist = resist; log.periodicLog = true; @@ -5822,7 +5807,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const caster->CalcHealAbsorb(healInfo); caster->DealHeal(healInfo); - SpellPeriodicAuraLogInfo pInfo(this, heal, heal - healInfo.GetEffectiveHeal(), healInfo.GetAbsorb(), 0, 0.0f, crit); + SpellPeriodicAuraLogInfo pInfo(this, heal, damage, heal - healInfo.GetEffectiveHeal(), healInfo.GetAbsorb(), 0, 0.0f, crit); target->SendPeriodicAuraLog(&pInfo); target->getHostileRefManager().threatAssist(caster, float(healInfo.GetEffectiveHeal()) * 0.5f, GetSpellInfo()); @@ -5866,7 +5851,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); - SpellPeriodicAuraLogInfo pInfo(this, drainedAmount, 0, 0, 0, gainMultiplier, false); + SpellPeriodicAuraLogInfo pInfo(this, drainedAmount, drainAmount, 0, 0, 0, gainMultiplier, false); int32 gainAmount = int32(drainedAmount * gainMultiplier); int32 gainedAmount = 0; @@ -5920,7 +5905,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s energize %s for %u dmg inflicted by %u", GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), amount, GetId()); - SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false); + SpellPeriodicAuraLogInfo pInfo(this, amount, amount, 0, 0, 0, 0.0f, false); int32 gain = target->ModifyPower(powerType, amount); if (caster) @@ -5948,7 +5933,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons // ignore negative values (can be result apply spellmods to aura damage int32 amount = std::max(m_amount, 0); - SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false); + SpellPeriodicAuraLogInfo pInfo(this, amount, amount, 0, 0, 0, 0.0f, false); TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s energize %s for %u dmg inflicted by %u", GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), amount, GetId()); @@ -6156,9 +6141,9 @@ void AuraEffect::HandleAllowUsingGameobjectsWhileMounted(AuraApplication const* return; if (apply) - aurApp->GetTarget()->SetFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED); + aurApp->GetTarget()->SetFlag(ACTIVE_PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED); else if (!aurApp->GetTarget()->HasAuraType(SPELL_AURA_ALLOW_USING_GAMEOBJECTS_WHILE_MOUNTED)) - aurApp->GetTarget()->RemoveFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED); + aurApp->GetTarget()->RemoveFlag(ACTIVE_PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED); } void AuraEffect::HandlePlayScene(AuraApplication const* aurApp, uint8 mode, bool apply) const diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 8cc2a1b7f6d..d9b428c0598 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -491,7 +491,7 @@ void SpellCastTargets::OutDebug() const TC_LOG_DEBUG("spells", "pitch: %f", m_pitch); } -SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto) +SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto, Unit const* caster) { // todo 6.x SpellEffectInfoVector effects = proto->GetEffectsForDifficulty(diff); @@ -499,8 +499,9 @@ SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto) memset(EffectBasePoints, 0, sizeof(EffectBasePoints)); for (SpellEffectInfo const* effect : effects) if (effect) - EffectBasePoints[effect->EffectIndex] = effect->BasePoints; + EffectBasePoints[effect->EffectIndex] = effect->CalcBaseValue(caster, nullptr, -1); + CustomBasePointsMask = 0; MaxAffectedTargets = proto->MaxAffectedTargets; RadiusMod = 1.0f; AuraStackAmount = 1; @@ -521,7 +522,7 @@ protected: Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) : m_spellInfo(info), m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster), -m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)) +m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo, caster)) { _effects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID()); @@ -537,7 +538,6 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)) m_delayAtDamageCount = 0; m_applyMultiplierMask = 0; - m_auraScaleMask = 0; memset(m_damageMultipliers, 0, sizeof(m_damageMultipliers)); // Get data for type of attack @@ -791,31 +791,6 @@ void Spell::SelectSpellTargets() } } } - else if (m_auraScaleMask) - { - bool checkLvl = !m_UniqueTargetInfo.empty(); - for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();) - { - // remove targets which did not pass min level check - if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask) - { - // Do not check for selfcast - if (!ihit->scaleAura && ihit->targetGUID != m_caster->GetGUID()) - { - ihit = m_UniqueTargetInfo.erase(ihit); - continue; - } - } - - ++ihit; - } - - if (checkLvl && m_UniqueTargetInfo.empty()) - { - SendCastResult(SPELL_FAILED_LOWLEVEL); - finish(false); - } - } } if (m_targets.HasDst()) @@ -1489,6 +1464,9 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImpli if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsVehicle()) target = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0); break; + case TARGET_UNIT_OWN_CRITTER: + target = ObjectAccessor::GetCreatureOrPetOrVehicle(*m_caster, m_caster->GetCritterGUID()); + break; default: break; } @@ -2128,13 +2106,6 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= if (targetGUID == ihit->targetGUID) // Found in list { ihit->effectMask |= effectMask; // Immune effects removed from mask - ihit->scaleAura = false; - if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask && m_caster != target) - { - SpellInfo const* auraSpell = m_spellInfo->GetFirstRankSpell(); - if (uint32(target->GetLevelForTarget(m_caster) + 10) >= auraSpell->SpellLevel) - ihit->scaleAura = true; - } return; } } @@ -2149,13 +2120,6 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= targetInfo.alive = target->IsAlive(); targetInfo.damage = 0; targetInfo.crit = false; - targetInfo.scaleAura = false; - if (m_auraScaleMask && targetInfo.effectMask == m_auraScaleMask && m_caster != target) - { - SpellInfo const* auraSpell = m_spellInfo->GetFirstRankSpell(); - if (uint32(target->GetLevelForTarget(m_caster) + 10) >= auraSpell->SpellLevel) - targetInfo.scaleAura = true; - } // Calculate hit result if (m_originalCaster) @@ -2398,7 +2362,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER) enablePvP = true; // Decide on PvP flagging now, but act on it later. - SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura); + SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask); if (missInfo2 != SPELL_MISS_NONE) { @@ -2591,7 +2555,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } } -SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura) +SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask) { if (!unit || !effectMask) return SPELL_MISS_EVADE; @@ -2676,34 +2640,19 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA if (aura_effmask) { - // Select rank for aura with level requirements only in specific cases - // Unit has to be target only of aura effect, both caster and target have to be players, target has to be other than unit target - SpellInfo const* aurSpellInfo = m_spellInfo; - int32 basePoints[MAX_SPELL_EFFECTS]; - if (scaleAura) - { - aurSpellInfo = m_spellInfo->GetAuraRankForLevel(unitTarget->getLevel()); - ASSERT(aurSpellInfo); - for (SpellEffectInfo const* effect : aurSpellInfo->GetEffectsForDifficulty(0)) - { - basePoints[effect->EffectIndex] = effect->BasePoints; - if (SpellEffectInfo const* myEffect = GetEffect(effect->EffectIndex)) - { - if (myEffect->Effect != effect->Effect) - { - aurSpellInfo = m_spellInfo; - break; - } - } - } - } - if (m_originalCaster) { + int32 basePoints[MAX_SPELL_EFFECTS]; + for (SpellEffectInfo const* auraSpellEffect : GetEffects()) + if (auraSpellEffect) + basePoints[auraSpellEffect->EffectIndex] = (m_spellValue->CustomBasePointsMask & (1 << auraSpellEffect->EffectIndex)) ? + m_spellValue->EffectBasePoints[auraSpellEffect->EffectIndex] : + auraSpellEffect->CalcBaseValue(m_originalCaster, unit, m_castItemLevel); + bool refresh = false; bool const resetPeriodicTimer = !(_triggeredCastFlags & TRIGGERED_DONT_RESET_PERIODIC_TIMER); - m_spellAura = Aura::TryRefreshStackOrCreate(aurSpellInfo, m_castId, effectMask, unit, - m_originalCaster, (aurSpellInfo == m_spellInfo) ? m_spellValue->EffectBasePoints : basePoints, + m_spellAura = Aura::TryRefreshStackOrCreate(m_spellInfo, m_castId, effectMask, unit, + m_originalCaster, basePoints, m_CastItem, ObjectGuid::Empty, &refresh, resetPeriodicTimer, ObjectGuid::Empty, m_castItemLevel); if (m_spellAura) { @@ -2718,7 +2667,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA // Now Reduce spell duration using data received at spell hit int32 duration = m_spellAura->GetMaxDuration(); - float diminishMod = unit->ApplyDiminishingToDuration(aurSpellInfo, duration, m_originalCaster, diminishLevel); + float diminishMod = unit->ApplyDiminishingToDuration(m_spellInfo, duration, m_originalCaster, diminishLevel); // unit is immune to aura if it was diminished to 0 duration if (diminishMod == 0.0f) @@ -2739,13 +2688,13 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA if (AuraApplication* aurApp = m_spellAura->GetApplicationOfTarget(m_originalCaster->GetGUID())) positive = aurApp->IsPositive(); - duration = m_originalCaster->ModSpellDuration(aurSpellInfo, unit, duration, positive, effectMask); + duration = m_originalCaster->ModSpellDuration(m_spellInfo, unit, duration, positive, effectMask); if (duration > 0) { // Haste modifies duration of channeled spells if (m_spellInfo->IsChanneled()) - m_originalCaster->ModSpellDurationTime(aurSpellInfo, duration, this); + m_originalCaster->ModSpellDurationTime(m_spellInfo, duration, this); else if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION)) { int32 origDuration = duration; @@ -2953,27 +2902,6 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered InitExplicitTargets(*targets); - // Fill aura scaling information - if (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING)) - { - for (SpellEffectInfo const* effect : GetEffects()) - { - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) - { - // Change aura with ranks only if basepoints are taken from spellInfo and aura is positive - if (m_spellInfo->IsPositiveEffect(effect->EffectIndex)) - { - m_auraScaleMask |= (1 << effect->EffectIndex); - if (m_spellValue->EffectBasePoints[effect->EffectIndex] != effect->BasePoints) - { - m_auraScaleMask = 0; - break; - } - } - } - } - } - m_spellState = SPELL_STATE_PREPARING; if (triggeredByAura) @@ -6045,7 +5973,8 @@ SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules() int32 Spell::CalculateDamage(uint8 i, Unit const* target, float* var /*= nullptr*/) const { - return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_spellValue->EffectBasePoints[i], var, m_castItemLevel); + bool needRecalculateBasePoints = !(m_spellValue->CustomBasePointsMask & (1 << i)); + return m_caster->CalculateSpellDamage(target, m_spellInfo, i, needRecalculateBasePoints ? nullptr : &m_spellValue->EffectBasePoints[i], var, m_castItemLevel); } bool Spell::CanAutoCast(Unit* target) @@ -7295,7 +7224,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk skillId = SkillByLockType(LockType(lockInfo->Index[j])); - if (skillId != SKILL_NONE || lockInfo->Index[j] == LOCKTYPE_PICKLOCK) + if (skillId != SKILL_NONE || lockInfo->Index[j] == LOCKTYPE_LOCKPICKING) { reqSkillValue = lockInfo->Skill[j]; @@ -7303,7 +7232,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk skillValue = 0; if (!m_CastItem && m_caster->GetTypeId() == TYPEID_PLAYER) skillValue = m_caster->ToPlayer()->GetSkillValue(skillId); - else if (lockInfo->Index[j] == LOCKTYPE_PICKLOCK) + else if (lockInfo->Index[j] == LOCKTYPE_LOCKPICKING) skillValue = m_caster->getLevel() * 5; // skill bonus provided by casting spell (mostly item spells) @@ -7330,8 +7259,8 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value) { if (mod < SPELLVALUE_BASE_POINT_END) { - if (SpellEffectInfo const* effect = GetEffect(mod)) - m_spellValue->EffectBasePoints[mod] = effect->CalcBaseValue(value); + m_spellValue->EffectBasePoints[mod] = value; + m_spellValue->CustomBasePointsMask |= 1 << mod; return; } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 45b012a82e6..c0a9dff527b 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -296,8 +296,9 @@ class TC_GAME_API SpellCastTargets struct SpellValue { - explicit SpellValue(Difficulty diff, SpellInfo const* proto); + explicit SpellValue(Difficulty diff, SpellInfo const* proto, Unit const* caster); int32 EffectBasePoints[MAX_SPELL_EFFECTS]; + uint32 CustomBasePointsMask; uint32 MaxAffectedTargets; float RadiusMod; uint8 AuraStackAmount; @@ -788,7 +789,6 @@ class TC_GAME_API Spell bool processed; bool alive; bool crit; - bool scaleAura; }; std::vector<TargetInfo> m_UniqueTargetInfo; uint32 m_channelTargetEffectMask; // Mask req. alive targets @@ -817,7 +817,7 @@ class TC_GAME_API Spell void AddDestTarget(SpellDestination const& dest, uint32 effIndex); void DoAllEffectOnTarget(TargetInfo* target); - SpellMissInfo DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura); + SpellMissInfo DoSpellHitOnUnit(Unit* unit, uint32 effectMask); void DoTriggersOnSpellHit(Unit* unit, uint32 effMask); void DoAllEffectOnTarget(GOTargetInfo* target); void DoAllEffectOnTarget(ItemTargetInfo* target); @@ -884,7 +884,6 @@ class TC_GAME_API Spell SpellInfo const* m_triggeredByAuraSpell; bool m_skipCheck; - uint32 m_auraScaleMask; std::unique_ptr<PathGenerator> m_preGeneratedPath; std::vector<SpellLogEffectPowerDrainParams> _powerDrainTargets[MAX_SPELL_EFFECTS]; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index b6f009b971e..34743342da6 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -410,7 +410,8 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/) m_caster->CalcAbsorbResist(damageInfo); SpellNonMeleeDamage log(m_caster, unitTarget, m_spellInfo->Id, m_SpellVisual, m_spellInfo->GetSchoolMask(), m_castId); - log.damage = damage; + log.damage = damageInfo.GetDamage(); + log.originalDamage = damage; log.absorb = damageInfo.GetAbsorb(); log.resist = damageInfo.GetResist(); @@ -2365,7 +2366,7 @@ void Spell::EffectLearnSkill(SpellEffIndex /*effIndex*/) if (unitTarget->GetTypeId() != TYPEID_PLAYER) return; - if (damage < 0) + if (damage < 1) return; uint32 skillid = effectInfo->MiscValue; @@ -2378,7 +2379,7 @@ void Spell::EffectLearnSkill(SpellEffIndex /*effIndex*/) return; uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid); - unitTarget->ToPlayer()->SetSkill(skillid, effectInfo->CalcValue(), std::max<uint16>(skillval, 1), tier->Value[damage - 1]); + unitTarget->ToPlayer()->SetSkill(skillid, damage, std::max<uint16>(skillval, 1), tier->Value[damage - 1]); } void Spell::EffectPlayMovie(SpellEffIndex /*effIndex*/) @@ -4182,12 +4183,41 @@ void Spell::EffectSkinning(SpellEffIndex /*effIndex*/) creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); creature->SetFlag(OBJECT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5; + if (skill == SKILL_SKINNING) + { + int32 reqValue; + if (targetLevel <= 10) + reqValue = 1; + else if (targetLevel < 20) + reqValue = (targetLevel - 10) * 10; + else if (targetLevel <= 73) + reqValue = targetLevel * 5; + else if (targetLevel < 80) + reqValue = targetLevel * 10 - 365; + else if (targetLevel <= 84) + reqValue = targetLevel * 5 + 35; + else if (targetLevel <= 87) + reqValue = targetLevel * 15 - 805; + else if (targetLevel <= 92) + reqValue = (targetLevel - 62) * 20; + else if (targetLevel <= 104) + reqValue = targetLevel * 5 + 175; + else if (targetLevel <= 107) + reqValue = targetLevel * 15 - 905; + else if (targetLevel <= 112) + reqValue = (targetLevel - 72) * 20; + else if (targetLevel <= 122) + reqValue = (targetLevel - 32) * 10; + else + reqValue = 900; - int32 skillValue = m_caster->ToPlayer()->GetPureSkillValue(skill); + // TODO: Specialize skillid for each expansion + // new db field? + // tied to one of existing expansion fields in creature_template? - // Double chances for elites - m_caster->ToPlayer()->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1); + // Double chances for elites + m_caster->ToPlayer()->UpdateGatherSkill(skill, damage, reqValue, creature->isElite() ? 2 : 1); + } } void Spell::EffectCharge(SpellEffIndex /*effIndex*/) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index d1dfa32f7cb..d1ae93cd318 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -368,6 +368,7 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_ {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 147 {TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 148 {TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 149 + {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 150 }; SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* _effect) @@ -377,7 +378,6 @@ SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, uint8 effIndex, Spe Effect = _effect ? _effect->Effect : 0; ApplyAuraName = _effect ? _effect->EffectAura : 0; ApplyAuraPeriod = _effect ? _effect->EffectAuraPeriod : 0; - DieSides = _effect ? _effect->EffectDieSides : 0; RealPointsPerLevel = _effect ? _effect->EffectRealPointsPerLevel : 0.0f; BasePoints = _effect ? _effect->EffectBasePoints : 0; PointsPerResource = _effect ? _effect->EffectPointsPerResource : 0.0f; @@ -461,12 +461,59 @@ bool SpellEffectInfo::IsUnitOwnedAuraEffect() const int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const* bp /*= nullptr*/, Unit const* target /*= nullptr*/, float* variance /*= nullptr*/, int32 itemLevel /*= -1*/) const { float basePointsPerLevel = RealPointsPerLevel; - int32 basePoints = bp ? *bp : BasePoints; + // TODO: this needs to be a float, not rounded + int32 basePoints = CalcBaseValue(caster, target, itemLevel); + float value = bp ? *bp : basePoints; float comboDamage = PointsPerResource; + if (Scaling.Variance) + { + float delta = fabs(Scaling.Variance * 0.5f); + float valueVariance = frand(-delta, delta); + value += basePoints * valueVariance; + + if (variance) + *variance = valueVariance; + } + // base amount modification based on spell lvl vs caster lvl if (Scaling.Coefficient != 0.0f) { + if (Scaling.ResourceCoefficient) + comboDamage = Scaling.ResourceCoefficient * value; + } + else + { + if (GetScalingExpectedStat() == ExpectedStatType::None) + { + int32 level = caster ? int32(caster->getLevel()) : 0; + if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0) + level = int32(_spellInfo->MaxLevel); + level -= int32(_spellInfo->BaseLevel); + if (level < 0) + level = 0; + value += level * basePointsPerLevel; + } + } + + // random damage + if (caster) + { + // bonus amount from combo points + if (caster->m_playerMovingMe && comboDamage) + if (uint32 comboPoints = caster->m_playerMovingMe->GetComboPoints()) + value += comboDamage * comboPoints; + + value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value); + } + + return int32(round(value)); +} + +int32 SpellEffectInfo::CalcBaseValue(Unit const* caster, Unit const* target, int32 itemLevel) const +{ + if (Scaling.Coefficient != 0.0f) + { uint32 level = _spellInfo->SpellLevel; if (target && _spellInfo->IsPositiveEffect(EffectIndex) && (Effect == SPELL_EFFECT_APPLY_AURA)) level = target->getLevel(); @@ -488,148 +535,56 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const* if (!_spellInfo->Scaling.Class) return 0; - if (!_spellInfo->Scaling.ScalesFromItemLevel) + uint32 effectiveItemLevel = itemLevel != -1 ? uint32(itemLevel) : 1u; + if (_spellInfo->Scaling.ScalesFromItemLevel || _spellInfo->HasAttribute(SPELL_ATTR11_SCALES_WITH_ITEM_LEVEL)) { - if (!_spellInfo->HasAttribute(SPELL_ATTR11_SCALES_WITH_ITEM_LEVEL)) - value = GetSpellScalingColumnForClass(sSpellScalingGameTable.GetRow(level), _spellInfo->Scaling.Class); - else + if (_spellInfo->Scaling.ScalesFromItemLevel) + effectiveItemLevel = _spellInfo->Scaling.ScalesFromItemLevel; + + if (_spellInfo->Scaling.Class == -8) { - uint32 effectiveItemLevel = itemLevel != -1 ? uint32(itemLevel) : 1u; - value = GetRandomPropertyPoints(effectiveItemLevel, ITEM_QUALITY_RARE, INVTYPE_CHEST, 0); - if (IsAura() && ApplyAuraName == SPELL_AURA_MOD_RATING) - if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel)) - value *= ratingMult->ArmorMultiplier; + RandPropPointsEntry const* randPropPoints = sRandPropPointsStore.LookupEntry(effectiveItemLevel); + if (!randPropPoints) + randPropPoints = sRandPropPointsStore.AssertEntry(sRandPropPointsStore.GetNumRows() - 1); + + value = randPropPoints->DamageReplaceStat; } + else + value = GetRandomPropertyPoints(effectiveItemLevel, ITEM_QUALITY_RARE, INVTYPE_CHEST, 0); } else - value = GetRandomPropertyPoints(_spellInfo->Scaling.ScalesFromItemLevel, ITEM_QUALITY_RARE, INVTYPE_CHEST, 0); + value = GetSpellScalingColumnForClass(sSpellScalingGameTable.GetRow(level), _spellInfo->Scaling.Class); + + if (_spellInfo->Scaling.Class == -7) + { + // todo: get inventorytype here + if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel)) + value *= ratingMult->ArmorMultiplier; + } } value *= Scaling.Coefficient; if (value != 0.0f && value < 1.0f) value = 1.0f; - if (Scaling.Variance) - { - float delta = fabs(Scaling.Variance * 0.5f); - float valueVariance = frand(-delta, delta); - value += value * valueVariance; - - if (variance) - *variance = valueVariance; - } - - basePoints = int32(round(value)); - - if (Scaling.ResourceCoefficient) - comboDamage = Scaling.ResourceCoefficient * value; + return int32(round(value)); } else { - if (caster) - { - int32 level = int32(caster->getLevel()); - if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0) - level = int32(_spellInfo->MaxLevel); - else if (level < int32(_spellInfo->BaseLevel)) - level = int32(_spellInfo->BaseLevel); - level -= int32(_spellInfo->SpellLevel); - basePoints += int32(level * basePointsPerLevel); - } - - // roll in a range <1;EffectDieSides> as of patch 3.3.3 - int32 randomPoints = int32(DieSides); - switch (randomPoints) + float value = BasePoints; + ExpectedStatType stat = GetScalingExpectedStat(); + if (stat != ExpectedStatType::None) { - case 0: break; - case 1: basePoints += 1; break; // range 1..1 - default: - { - // range can have positive (1..rand) and negative (rand..1) values, so order its for irand - int32 randvalue = (randomPoints >= 1) - ? irand(1, randomPoints) - : irand(randomPoints, 1); + if (_spellInfo->HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION)) + stat = ExpectedStatType::CreatureAutoAttackDps; - basePoints += randvalue; - break; - } + // TODO - add expansion and content tuning id args? + int32 level = caster ? int32(caster->getLevel()) : 1; + value = sDB2Manager.EvaluateExpectedStat(stat, level, -2, 0, CLASS_NONE) * BasePoints / 100.0f; } - } - float value = float(basePoints); - - // random damage - if (caster) - { - // bonus amount from combo points - if (caster->m_playerMovingMe && comboDamage) - if (uint32 comboPoints = caster->m_playerMovingMe->GetComboPoints()) - value += comboDamage * comboPoints; - - value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value); - - // amount multiplication based on caster's level - if (!caster->IsControlledByPlayer() && - _spellInfo->SpellLevel && _spellInfo->SpellLevel != caster->getLevel() && - !basePointsPerLevel && (_spellInfo->HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))) - { - bool canEffectScale = false; - switch (Effect) - { - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_DUMMY: - case SPELL_EFFECT_POWER_DRAIN: - case SPELL_EFFECT_HEALTH_LEECH: - case SPELL_EFFECT_HEAL: - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_POWER_BURN: - case SPELL_EFFECT_SCRIPT_EFFECT: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - case SPELL_EFFECT_FORCE_CAST_WITH_VALUE: - case SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE: - case SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE: - canEffectScale = true; - break; - default: - break; - } - - switch (ApplyAuraName) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_DUMMY: - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_DAMAGE_SHIELD: - case SPELL_AURA_PROC_TRIGGER_DAMAGE: - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_PERIODIC_MANA_LEECH: - case SPELL_AURA_SCHOOL_ABSORB: - case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: - canEffectScale = true; - break; - default: - break; - } - - if (canEffectScale) - { - GtNpcManaCostScalerEntry const* spellScaler = sNpcManaCostScalerGameTable.GetRow(_spellInfo->SpellLevel); - GtNpcManaCostScalerEntry const* casterScaler = sNpcManaCostScalerGameTable.GetRow(caster->getLevel()); - if (spellScaler && casterScaler) - value *= casterScaler->Scaler / spellScaler->Scaler; - } - } + return int32(round(value)); } - - return int32(value); -} - -int32 SpellEffectInfo::CalcBaseValue(int32 value) const -{ - if (DieSides == 0) - return value; - else - return value - 1; } float SpellEffectInfo::CalcValueMultiplier(Unit* caster, Spell* spell) const @@ -723,6 +678,94 @@ SpellTargetObjectTypes SpellEffectInfo::GetUsedTargetObjectType() const return _data[Effect].UsedTargetObjectType; } +ExpectedStatType SpellEffectInfo::GetScalingExpectedStat() const +{ + switch (Effect) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_WEAPON_DAMAGE: + return ExpectedStatType::CreatureSpellDamage; + case SPELL_EFFECT_HEAL: + case SPELL_EFFECT_HEAL_MECHANICAL: + return ExpectedStatType::PlayerHealth; + case SPELL_EFFECT_ENERGIZE: + case SPELL_EFFECT_POWER_BURN: + if (!MiscValue) + return ExpectedStatType::PlayerMana; + return ExpectedStatType::None; + case SPELL_EFFECT_POWER_DRAIN: + return ExpectedStatType::PlayerMana; + case SPELL_EFFECT_APPLY_AURA: + case SPELL_EFFECT_PERSISTENT_AREA_AURA: + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + case SPELL_EFFECT_APPLY_AREA_AURA_PET: + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: + case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: + case SPELL_EFFECT_APPLY_AURA_ON_PET: + case SPELL_EFFECT_202: + switch (ApplyAuraName) + { + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_MOD_DAMAGE_DONE: + case SPELL_AURA_DAMAGE_SHIELD: + case SPELL_AURA_PROC_TRIGGER_DAMAGE: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_MOD_DAMAGE_DONE_CREATURE: + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: + case SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS: + case SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS: + case SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS: + return ExpectedStatType::CreatureSpellDamage; + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_MOD_DAMAGE_TAKEN: + case SPELL_AURA_MOD_INCREASE_HEALTH: + case SPELL_AURA_SCHOOL_ABSORB: + case SPELL_AURA_MOD_REGEN: + case SPELL_AURA_MANA_SHIELD: + case SPELL_AURA_MOD_HEALING: + case SPELL_AURA_MOD_HEALING_DONE: + case SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT: + case SPELL_AURA_MOD_MAX_HEALTH: + case SPELL_AURA_MOD_INCREASE_HEALTH_2: + case SPELL_AURA_SCHOOL_HEAL_ABSORB: + return ExpectedStatType::PlayerHealth; + case SPELL_AURA_PERIODIC_MANA_LEECH: + return ExpectedStatType::PlayerMana; + case SPELL_AURA_MOD_STAT: + case SPELL_AURA_MOD_ATTACK_POWER: + case SPELL_AURA_MOD_RANGED_ATTACK_POWER: + return ExpectedStatType::PlayerPrimaryStat; + case SPELL_AURA_MOD_RATING: + return ExpectedStatType::PlayerSecondaryStat; + case SPELL_AURA_MOD_RESISTANCE: + case SPELL_AURA_MOD_BASE_RESISTANCE: + case SPELL_AURA_MOD_TARGET_RESISTANCE: + case SPELL_AURA_MOD_BONUS_ARMOR: + return ExpectedStatType::ArmorConstant; + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_MOD_INCREASE_ENERGY: + case SPELL_AURA_MOD_POWER_COST_SCHOOL: + case SPELL_AURA_MOD_POWER_REGEN: + case SPELL_AURA_POWER_BURN: + case SPELL_AURA_MOD_MAX_POWER: + if (!MiscValue) + return ExpectedStatType::PlayerMana; + return ExpectedStatType::None; + default: + break; + } + default: + break; + } + + return ExpectedStatType::None; +} + SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = { // implicit target type used target object type @@ -982,6 +1025,12 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 253 SPELL_EFFECT_GIVE_HONOR {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 254 SPELL_EFFECT_254 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 255 SPELL_EFFECT_LEARN_TRANSMOG_SET + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 256 SPELL_EFFECT_256 + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 257 SPELL_EFFECT_257 + {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 258 SPELL_EFFECT_MODIFY_KEYSTONE + {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 259 SPELL_EFFECT_RESPEC_AZERITE_EMPOWERED_ITEM + {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 260 SPELL_EFFECT_SUMMON_STABLED_PET + {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 261 SPELL_EFFECT_SCRAP_ITEM }; SpellInfo::SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& effectsMap, SpellVisualMap&& visuals) @@ -1042,7 +1091,7 @@ SpellInfo::SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& // SpellAuraOptionsEntry SpellAuraOptionsEntry const* _options = data.AuraOptions; SpellProcsPerMinuteEntry const* _ppm = _options ? sSpellProcsPerMinuteStore.LookupEntry(_options->SpellProcsPerMinuteID) : nullptr; - ProcFlags = _options ? _options->ProcTypeMask : 0; + ProcFlags = _options ? _options->ProcTypeMask[0] : 0; ProcChance = _options ? _options->ProcChance : 0; ProcCharges = _options ? _options->ProcCharges : 0; ProcCooldown = _options ? _options->ProcCategoryRecovery : 0; @@ -1832,10 +1881,31 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a // continent limitation (virtual continent) if (HasAttribute(SPELL_ATTR4_CAST_ONLY_IN_OUTLAND)) { - uint32 v_map = sDB2Manager.GetVirtualMapForMapAndZone(map_id, zone_id); - MapEntry const* mapEntry = sMapStore.LookupEntry(v_map); - if (!mapEntry || mapEntry->ExpansionID < 1 || !mapEntry->IsContinent()) + uint32 mountFlags = 0; + if (player && player->HasAuraType(SPELL_AURA_MOUNT_RESTRICTIONS)) + { + for (AuraEffect const* auraEffect : player->GetAuraEffectsByType(SPELL_AURA_MOUNT_RESTRICTIONS)) + mountFlags |= auraEffect->GetMiscValue(); + } + else if (AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(area_id)) + mountFlags = areaTable->MountFlags; + + if (!(mountFlags & AREA_MOUNT_FLAG_FLYING_ALLOWED)) return SPELL_FAILED_INCORRECT_AREA; + + if (player) + { + uint32 mapToCheck = map_id; + if (MapEntry const* mapEntry = sMapStore.LookupEntry(map_id)) + mapToCheck = mapEntry->CosmeticParentMapID; + + if ((mapToCheck == 1116 || mapToCheck == 1464) && !player->HasSpell(191645)) // Draenor Pathfinder + return SPELL_FAILED_INCORRECT_AREA; + else if (mapToCheck == 1220 && !player->HasSpell(233368)) // Broken Isles Pathfinder + return SPELL_FAILED_INCORRECT_AREA; + else if ((mapToCheck == 1642 || mapToCheck == 1643) && !player->HasSpell(278833)) // Battle for Azeroth Pathfinder + return SPELL_FAILED_INCORRECT_AREA; + } } // raid instance limitation @@ -3851,9 +3921,9 @@ inline float CalcPPMCritMod(SpellProcsPerMinuteModEntry const* mod, Unit* caster if (caster->GetTypeId() != TYPEID_PLAYER) return 0.0f; - float crit = caster->GetFloatValue(PLAYER_CRIT_PERCENTAGE); - float rangedCrit = caster->GetFloatValue(PLAYER_RANGED_CRIT_PERCENTAGE); - float spellCrit = caster->GetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1); + float crit = caster->GetFloatValue(ACTIVE_PLAYER_FIELD_CRIT_PERCENTAGE); + float rangedCrit = caster->GetFloatValue(ACTIVE_PLAYER_FIELD_RANGED_CRIT_PERCENTAGE); + float spellCrit = caster->GetFloatValue(ACTIVE_PLAYER_FIELD_SPELL_CRIT_PERCENTAGE1); switch (mod->Param) { diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 2eb285b48ae..65aef5dca41 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -323,7 +323,6 @@ public: uint32 Effect; uint32 ApplyAuraName; uint32 ApplyAuraPeriod; - int32 DieSides; float RealPointsPerLevel; int32 BasePoints; float PointsPerResource; @@ -352,7 +351,7 @@ public: float ResourceCoefficient; } Scaling; - SpellEffectInfo() : _spellInfo(NULL), EffectIndex(0), Effect(0), ApplyAuraName(0), ApplyAuraPeriod(0), DieSides(0), + SpellEffectInfo() : _spellInfo(NULL), EffectIndex(0), Effect(0), ApplyAuraName(0), ApplyAuraPeriod(0), RealPointsPerLevel(0), BasePoints(0), PointsPerResource(0), Amplitude(0), ChainAmplitude(0), BonusCoefficient(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), PositionFacing(0), RadiusEntry(NULL), ChainTargets(0), ItemType(0), TriggerSpell(0), BonusCoefficientFromAP(0.0f), ImplicitTargetConditions(NULL) { } @@ -369,7 +368,7 @@ public: 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(int32 value) const; + int32 CalcBaseValue(Unit const* caster, Unit const* target, int32 itemLevel) const; float CalcValueMultiplier(Unit* caster, Spell* spell = NULL) const; float CalcDamageMultiplier(Unit* caster, Spell* spell = NULL) const; @@ -382,6 +381,7 @@ public: SpellEffectImplicitTargetTypes GetImplicitTargetType() const; SpellTargetObjectTypes GetUsedTargetObjectType() const; + ExpectedStatType GetScalingExpectedStat() const; ImmunityInfo const* GetImmunityInfo() const { return &_immunityInfo; } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 2532069e6c2..2bb498cf9af 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2068,7 +2068,7 @@ void SpellMgr::LoadSpellAreas() spellArea.questEndStatus = fields[4].GetUInt32(); spellArea.questEnd = fields[5].GetUInt32(); spellArea.auraSpell = fields[6].GetInt32(); - spellArea.raceMask = fields[7].GetUInt32(); + spellArea.raceMask = fields[7].GetUInt64(); spellArea.gender = Gender(fields[8].GetUInt8()); spellArea.flags = fields[9].GetUInt8(); @@ -2189,7 +2189,7 @@ void SpellMgr::LoadSpellAreas() if (spellArea.raceMask && (spellArea.raceMask & RACEMASK_ALL_PLAYABLE) == 0) { - TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_area` has wrong race mask (%u) requirement.", spell, spellArea.raceMask); + TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_area` has wrong race mask (" UI64FMTD ") requirement.", spell, spellArea.raceMask); continue; } @@ -2236,7 +2236,7 @@ void SpellMgr::LoadSpellInfoStore() uint32 oldMSTime = getMSTime(); UnloadSpellInfoStore(); - mSpellInfoMap.resize(sSpellStore.GetNumRows(), NULL); + mSpellInfoMap.resize(sSpellNameStore.GetNumRows(), NULL); std::unordered_map<uint32, SpellInfoLoadHelper> loadData; std::unordered_map<int32, SpellEffectEntryMap> effectsBySpell; @@ -2313,11 +2313,11 @@ void SpellMgr::LoadSpellInfoStore() for (SpellXSpellVisualEntry const* visual : sSpellXSpellVisualStore) visualsBySpell[visual->SpellID][visual->DifficultyID].push_back(visual); - for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) + for (uint32 i = 0; i < sSpellNameStore.GetNumRows(); ++i) { - if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(i)) + if (SpellNameEntry const* spellNameEntry = sSpellNameStore.LookupEntry(i)) { - loadData[i].Entry = spellEntry; + loadData[i].Entry = spellNameEntry; mSpellInfoMap[i] = new SpellInfo(loadData[i], effectsBySpell[i], std::move(visualsBySpell[i])); } } diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 1034f6b4333..690edb8f508 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -37,7 +37,6 @@ class Player; class Unit; class ProcEventInfo; struct SkillLineAbilityEntry; -struct SpellEntry; struct SpellAuraOptionsEntry; struct SpellAuraRestrictionsEntry; struct SpellCastingRequirementsEntry; @@ -48,6 +47,7 @@ struct SpellEquippedItemsEntry; struct SpellInterruptsEntry; struct SpellLevelsEntry; struct SpellMiscEntry; +struct SpellNameEntry; struct SpellReagentsEntry; struct SpellScalingEntry; struct SpellShapeshiftEntry; @@ -464,7 +464,7 @@ struct TC_GAME_API SpellArea uint32 questStart; // quest start (quest must be active or rewarded for spell apply) uint32 questEnd; // quest end (quest must not be rewarded for spell apply) int32 auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case - uint32 raceMask; // can be applied only to races + uint64 raceMask; // can be applied only to races Gender gender; // can be applied only to gender uint32 questStartStatus; // QuestStatus that quest_start must have in order to keep the spell uint32 questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped) @@ -561,7 +561,7 @@ bool IsWeaponSkill(uint32 skill); inline bool IsProfessionSkill(uint32 skill) { - return IsPrimaryProfessionSkill(skill) || skill == SKILL_FISHING || skill == SKILL_COOKING || skill == SKILL_FIRST_AID; + return IsPrimaryProfessionSkill(skill) || skill == SKILL_FISHING || skill == SKILL_COOKING; } inline bool IsProfessionOrRidingSkill(uint32 skill) @@ -575,7 +575,7 @@ TC_GAME_API extern PetFamilySpellsStore sPetFamilySpells struct SpellInfoLoadHelper { - SpellEntry const* Entry = nullptr; + SpellNameEntry const* Entry = nullptr; SpellAuraOptionsEntry const* AuraOptions = nullptr; SpellAuraRestrictionsEntry const* AuraRestrictions = nullptr; |
